feat(FE: Reducers): Combine Metrics reducers and refactor Metrics actions

This commit is contained in:
Nidhi Tandon 2021-05-30 19:07:37 +05:30
parent 007e2e7b78
commit af58d085a0
23 changed files with 466 additions and 526 deletions

View File

@ -4,7 +4,6 @@ import { Layout } from "antd";
import SideNav from "./Nav/SideNav"; import SideNav from "./Nav/SideNav";
import TopNav from "./Nav/TopNav"; import TopNav from "./Nav/TopNav";
import { useLocation } from "react-router-dom"; import { useLocation } from "react-router-dom";
import ROUTES from "Src/constants/routes";
import { useRoute } from "./RouteProvider"; import { useRoute } from "./RouteProvider";
const { Content, Footer } = Layout; const { Content, Footer } = Layout;
@ -18,7 +17,7 @@ const BaseLayout: React.FC<BaseLayoutProps> = ({ children }) => {
const { dispatch } = useRoute(); const { dispatch } = useRoute();
useEffect(() => { useEffect(() => {
dispatch({ type: "UPDATE_IS_LOADED", payload: location.pathname }); dispatch({ type: "ROUTE_IS_LOADED", payload: location.pathname });
}, [location]); }, [location]);
return ( return (

View File

@ -6,7 +6,7 @@ import { RouteComponentProps } from "react-router-dom";
import styled from "styled-components"; import styled from "styled-components";
import ROUTES from "Src/constants/routes"; import ROUTES from "Src/constants/routes";
import { metricItem } from "../../store/actions/metrics"; import { metricItem } from "../../store/actions/MetricsActions";
const ChartPopUpUnique = styled.div<{ const ChartPopUpUnique = styled.div<{
ycoordinate: number; ycoordinate: number;
@ -55,7 +55,7 @@ class ErrorRateChart extends React.Component<ErrorRateChartProps> {
xcoordinate: 0, xcoordinate: 0,
ycoordinate: 0, ycoordinate: 0,
showpopUp: false, showpopUp: false,
firstpoint_ts: 0 firstpoint_ts: 0,
// graphInfo:{} // graphInfo:{}
}; };

View File

@ -1,11 +1,9 @@
import React from "react"; import React from "react";
import { Line as ChartJSLine } from "react-chartjs-2"; import { Line as ChartJSLine } from "react-chartjs-2";
import { ChartOptions } from "chart.js";
import { withRouter } from "react-router"; import { withRouter } from "react-router";
import { RouteComponentProps } from "react-router-dom"; import { RouteComponentProps } from "react-router-dom";
import styled from "styled-components";
import { getOptions, borderColors } from "./graphConfig"; import { getOptions, borderColors } from "./graphConfig";
import { externalMetricsItem } from "../../store/actions/metrics"; import { externalMetricsItem } from "../../../store/actions/MetricsActions";
import { uniqBy, filter } from "lodash"; import { uniqBy, filter } from "lodash";
const theme = "dark"; const theme = "dark";

View File

@ -2,7 +2,7 @@ import React from "react";
import { Bar, Line as ChartJSLine } from "react-chartjs-2"; import { Bar, Line as ChartJSLine } from "react-chartjs-2";
import styled from "styled-components"; import styled from "styled-components";
import { customMetricsItem } from "../../store/actions/metrics"; import { customMetricsItem } from "../../store/actions/MetricsActions";
const GenVisualizationWrapper = styled.div` const GenVisualizationWrapper = styled.div`
height: 160px; height: 160px;

View File

@ -4,9 +4,7 @@ import { ChartOptions } from "chart.js";
import { withRouter } from "react-router"; import { withRouter } from "react-router";
import { RouteComponentProps } from "react-router-dom"; import { RouteComponentProps } from "react-router-dom";
import styled from "styled-components"; import styled from "styled-components";
import ROUTES from "Src/constants/routes"; import { metricItem } from "../../store/actions/MetricsActions";
import { metricItem } from "../../store/actions/metrics";
const ChartPopUpUnique = styled.div<{ const ChartPopUpUnique = styled.div<{
ycoordinate: number; ycoordinate: number;
@ -39,11 +37,8 @@ interface LatencyLineChartProps extends RouteComponentProps<any> {
popupClickHandler: Function; popupClickHandler: Function;
} }
interface LatencyLineChart {
chartRef: any;
}
class LatencyLineChart extends React.Component<LatencyLineChartProps> { class LatencyLineChart extends React.Component<LatencyLineChartProps> {
private chartRef: React.RefObject<HTMLElement>;
constructor(props: LatencyLineChartProps) { constructor(props: LatencyLineChartProps) {
super(props); super(props);
this.chartRef = React.createRef(); this.chartRef = React.createRef();
@ -54,7 +49,6 @@ class LatencyLineChart extends React.Component<LatencyLineChartProps> {
ycoordinate: 0, ycoordinate: 0,
showpopUp: false, showpopUp: false,
firstpoint_ts: 0, firstpoint_ts: 0,
// graphInfo:{}
}; };
onClickhandler = async (e: any, event: any) => { onClickhandler = async (e: any, event: any) => {
@ -69,7 +63,6 @@ class LatencyLineChart extends React.Component<LatencyLineChartProps> {
ycoordinate: e.offsetY, ycoordinate: e.offsetY,
showpopUp: true, showpopUp: true,
firstpoint_ts: this.props.data[firstPoint._index].timestamp, firstpoint_ts: this.props.data[firstPoint._index].timestamp,
// graphInfo:{...event}
}); });
} else { } else {
// if clicked outside of the graph line, then firstpoint is undefined -> close popup. // if clicked outside of the graph line, then firstpoint is undefined -> close popup.
@ -80,15 +73,6 @@ class LatencyLineChart extends React.Component<LatencyLineChartProps> {
} }
}; };
gotoTracesHandler = (xc: any) => {
this.props.history.push(ROUTES.TRACES);
};
gotoAlertsHandler = () => {
this.props.history.push(ROUTES.SERVICE_MAP);
// PNOTE - Keeping service map for now, will replace with alerts when alert page is made
};
options_charts: ChartOptions = { options_charts: ChartOptions = {
onClick: this.onClickhandler, onClick: this.onClickhandler,
@ -161,9 +145,6 @@ class LatencyLineChart extends React.Component<LatencyLineChartProps> {
xAxes: [ xAxes: [
{ {
type: "time", type: "time",
// time: {
// unit: 'second'
// },
distribution: "linear", distribution: "linear",
//'linear': data are spread according to their time (distances can vary) //'linear': data are spread according to their time (distances can vary)
// From https://www.chartjs.org/docs/latest/axes/cartesian/time.html // From https://www.chartjs.org/docs/latest/axes/cartesian/time.html
@ -193,7 +174,6 @@ class LatencyLineChart extends React.Component<LatencyLineChartProps> {
> >
View Traces View Traces
</PopUpElements> </PopUpElements>
{/* <PopUpElements onClick={this.gotoAlertsHandler}>Set Alerts</PopUpElements> */}
</ChartPopUpUnique> </ChartPopUpUnique>
); );
} else return null; } else return null;
@ -239,7 +219,7 @@ class LatencyLineChart extends React.Component<LatencyLineChartProps> {
<div> <div>
{this.GraphTracePopUp()} {this.GraphTracePopUp()}
<div> <div>
<div style={{textAlign: "center"}}>Application latency in ms</div> <div style={{ textAlign: "center" }}>Application latency in ms</div>
<ChartJSLine <ChartJSLine
ref={this.chartRef} ref={this.chartRef}
data={data_chartJS} data={data_chartJS}

View File

@ -5,7 +5,7 @@ import { withRouter } from "react-router";
import { RouteComponentProps } from "react-router-dom"; import { RouteComponentProps } from "react-router-dom";
import styled from "styled-components"; import styled from "styled-components";
import { metricItem } from "../../store/actions/metrics"; import { metricItem } from "../../store/actions/MetricsActions";
import ROUTES from "Src/constants/routes"; import ROUTES from "Src/constants/routes";
const ChartPopUpUnique = styled.div<{ const ChartPopUpUnique = styled.div<{

View File

@ -4,23 +4,24 @@ import { connect } from "react-redux";
import { useParams, RouteComponentProps } from "react-router-dom"; import { useParams, RouteComponentProps } from "react-router-dom";
import { withRouter } from "react-router"; import { withRouter } from "react-router";
import ROUTES from "Src/constants/routes"; import ROUTES from "Src/constants/routes";
import { GlobalTime, updateTimeInterval } from "Src/store/actions";
import { import {
getServicesMetrics,
metricItem, metricItem,
getTopEndpoints,
getDbOverViewMetrics,
getExternalMetrics,
externalMetricsAvgDurationItem, externalMetricsAvgDurationItem,
externalErrCodeMetricsItem, externalErrCodeMetricsItem,
externalMetricsItem, externalMetricsItem,
dbOverviewMetricsItem, dbOverviewMetricsItem,
topEndpointListItem,
} from "../../store/actions/MetricsActions";
import {
getServicesMetrics,
getTopEndpoints,
getDbOverViewMetrics,
getExternalMetrics,
getExternalAvgDurationMetrics, getExternalAvgDurationMetrics,
getExternalErrCodeMetrics, getExternalErrCodeMetrics,
topEndpointListItem, } from "../../store/actions/MetricsActions";
GlobalTime,
updateTimeInterval,
} from "Src/store/actions";
import { StoreState } from "../../store/reducers"; import { StoreState } from "../../store/reducers";
import LatencyLineChart from "./LatencyLineChart"; import LatencyLineChart from "./LatencyLineChart";
import RequestRateChart from "./RequestRateChart"; import RequestRateChart from "./RequestRateChart";
@ -223,13 +224,13 @@ const mapStateToProps = (
globalTime: GlobalTime; globalTime: GlobalTime;
} => { } => {
return { return {
externalErrCodeMetrics: state.externalErrCodeMetrics, externalErrCodeMetrics: state.metricsData.externalErrCodeMetricsItem,
serviceMetrics: state.serviceMetrics, serviceMetrics: state.metricsData.metricItems,
topEndpointsList: state.topEndpointsList, topEndpointsList: state.metricsData.topEndpointListItem,
externalMetrics: state.externalMetrics, externalMetrics: state.metricsData.externalMetricsItem,
globalTime: state.globalTime, globalTime: state.globalTime,
dbOverviewMetrics: state.dbOverviewMetrics, dbOverviewMetrics: state.metricsData.dbOverviewMetricsItem,
externalAvgDurationMetrics: state.externalAvgDurationMetrics, externalAvgDurationMetrics: state.metricsData.externalMetricsAvgDurationItem,
}; };
}; };

View File

@ -1,17 +1,12 @@
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import { useLocation } from "react-router-dom";
import { NavLink } from "react-router-dom"; import { NavLink } from "react-router-dom";
import { Button, Space, Spin, Table } from "antd"; import { Button, Space, Spin, Table } from "antd";
import styled from "styled-components"; import styled from "styled-components";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { SKIP_ONBOARDING } from "Src/constants/onboarding"; import { SKIP_ONBOARDING } from "Src/constants/onboarding";
import ROUTES from "Src/constants/routes"; import ROUTES from "Src/constants/routes";
import { getServicesList, GlobalTime } from "../../store/actions";
import { import { servicesListItem } from "../../store/actions/MetricsActions";
getServicesList,
GlobalTime,
servicesListItem,
} from "../../store/actions";
import { StoreState } from "../../store/reducers"; import { StoreState } from "../../store/reducers";
import { CustomModal } from "../../components/Modal"; import { CustomModal } from "../../components/Modal";
@ -75,7 +70,7 @@ const columns = [
key: "errorRate", key: "errorRate",
sorter: (a: any, b: any) => a.errorRate - b.errorRate, sorter: (a: any, b: any) => a.errorRate - b.errorRate,
// sortDirections: ['descend', 'ascend'], // sortDirections: ['descend', 'ascend'],
render: (value: number) => (value).toFixed(2), render: (value: number) => value.toFixed(2),
}, },
{ {
title: "Requests Per Second", title: "Requests Per Second",
@ -88,8 +83,6 @@ const columns = [
]; ];
const _ServicesTable = (props: ServicesTableProps) => { const _ServicesTable = (props: ServicesTableProps) => {
const search = useLocation().search;
const time_interval = new URLSearchParams(search).get("time");
const [initialDataFetch, setDataFetched] = useState(false); const [initialDataFetch, setDataFetched] = useState(false);
const [errorObject, setErrorObject] = useState({ const [errorObject, setErrorObject] = useState({
message: "", message: "",
@ -210,7 +203,10 @@ const _ServicesTable = (props: ServicesTableProps) => {
const mapStateToProps = ( const mapStateToProps = (
state: StoreState, state: StoreState,
): { servicesList: servicesListItem[]; globalTime: GlobalTime } => { ): { servicesList: servicesListItem[]; globalTime: GlobalTime } => {
return { servicesList: state.servicesList, globalTime: state.globalTime }; return {
servicesList: state.metricsData.serviceList,
globalTime: state.globalTime,
};
}; };
export const ServicesTable = connect(mapStateToProps, { export const ServicesTable = connect(mapStateToProps, {

View File

@ -3,7 +3,7 @@ import { Table, Button, Tooltip } from "antd";
import { connect } from "react-redux"; import { connect } from "react-redux";
import styled from "styled-components"; import styled from "styled-components";
import { useHistory, useParams } from "react-router-dom"; import { useHistory, useParams } from "react-router-dom";
import { topEndpointListItem } from "../../store/actions/metrics"; import { topEndpointListItem } from "../../store/actions/MetricsActions";
import { METRICS_PAGE_QUERY_PARAM } from "Src/constants/query"; import { METRICS_PAGE_QUERY_PARAM } from "Src/constants/query";
import { GlobalTime } from "Src/store/actions"; import { GlobalTime } from "Src/store/actions";
import { StoreState } from "Src/store/reducers"; import { StoreState } from "Src/store/reducers";

View File

@ -9,7 +9,7 @@ type State = {
}; };
enum ActionTypes { enum ActionTypes {
UPDATE_IS_LOADED = "UPDATE_IS_LOADED", UPDATE_IS_LOADED = "ROUTE_IS_LOADED",
} }
type Action = { type Action = {

View File

@ -1,4 +1,4 @@
import React, { useContext, useEffect, useRef } from "react"; import React, { useEffect, useRef } from "react";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { RouteComponentProps } from "react-router-dom"; import { RouteComponentProps } from "react-router-dom";
import { import {

View File

@ -2,16 +2,11 @@ import React, { useState, useEffect } from "react";
import GenericVisualizations from "../Metrics/GenericVisualization"; import GenericVisualizations from "../Metrics/GenericVisualization";
import { Select, Card, Space, Form } from "antd"; import { Select, Card, Space, Form } from "antd";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { StoreState } from "../../store/reducers"; import { StoreState } from "../../store/reducers";
import { import { GlobalTime, TraceFilters } from "../../store/actions";
customMetricsItem,
getFilteredTraceMetrics,
GlobalTime,
TraceFilters,
} from "../../store/actions";
import { useRoute } from "../RouteProvider"; import { useRoute } from "../RouteProvider";
import { getFilteredTraceMetrics } from "../../store/actions/MetricsActions";
import { customMetricsItem } from "../../store/actions/MetricsActions";
const { Option } = Select; const { Option } = Select;
const entity = [ const entity = [
@ -81,8 +76,9 @@ interface TraceCustomVisualizationsProps {
const _TraceCustomVisualizations = (props: TraceCustomVisualizationsProps) => { const _TraceCustomVisualizations = (props: TraceCustomVisualizationsProps) => {
const [selectedEntity, setSelectedEntity] = useState("calls"); const [selectedEntity, setSelectedEntity] = useState("calls");
const [selectedAggOption, setSelectedAggOption] = useState("count"); const [selectedAggOption, setSelectedAggOption] = useState("count");
const [selectedStep, setSelectedStep] = useState("60");
const { state } = useRoute(); const { state } = useRoute();
const [form] = Form.useForm();
const selectedStep = "60";
// Step should be multiples of 60, 60 -> 1 min // Step should be multiples of 60, 60 -> 1 min
@ -124,16 +120,6 @@ const _TraceCustomVisualizations = (props: TraceCustomVisualizationsProps) => {
//Custom metrics API called if time, tracefilters, selected entity or agg option changes //Custom metrics API called if time, tracefilters, selected entity or agg option changes
const [form] = Form.useForm();
function handleChange(value: string) {
// console.log(value);
}
function handleFinish(value: string) {
// console.log(value);
}
// PNOTE - Can also use 'coordinate' option in antd Select for implementing this - https://ant.design/components/select/ // PNOTE - Can also use 'coordinate' option in antd Select for implementing this - https://ant.design/components/select/
const handleFormValuesChange = (changedValues: any) => { const handleFormValuesChange = (changedValues: any) => {
const formFieldName = Object.keys(changedValues)[0]; const formFieldName = Object.keys(changedValues)[0];
@ -162,11 +148,9 @@ const _TraceCustomVisualizations = (props: TraceCustomVisualizationsProps) => {
return ( return (
<Card> <Card>
{/* <Space direction="vertical"> */}
<div>Custom Visualizations</div> <div>Custom Visualizations</div>
<Form <Form
form={form} form={form}
onFinish={handleFinish}
onValuesChange={handleFormValuesChange} onValuesChange={handleFormValuesChange}
initialValues={{ initialValues={{
agg_options: "Count", agg_options: "Count",
@ -199,7 +183,7 @@ const _TraceCustomVisualizations = (props: TraceCustomVisualizationsProps) => {
</Form.Item> </Form.Item>
<Form.Item name="chart_style"> <Form.Item name="chart_style">
<Select style={{ width: 120 }} onChange={handleChange} allowClear> <Select style={{ width: 120 }} allowClear>
<Option value="line">Line Chart</Option> <Option value="line">Line Chart</Option>
<Option value="bar">Bar Chart</Option> <Option value="bar">Bar Chart</Option>
<Option value="area">Area Chart</Option> <Option value="area">Area Chart</Option>
@ -207,7 +191,7 @@ const _TraceCustomVisualizations = (props: TraceCustomVisualizationsProps) => {
</Form.Item> </Form.Item>
<Form.Item name="interval"> <Form.Item name="interval">
<Select style={{ width: 120 }} onChange={handleChange} allowClear> <Select style={{ width: 120 }} allowClear>
<Option value="1m">1 min</Option> <Option value="1m">1 min</Option>
<Option value="5m">5 min</Option> <Option value="5m">5 min</Option>
<Option value="30m">30 min</Option> <Option value="30m">30 min</Option>
@ -216,7 +200,7 @@ const _TraceCustomVisualizations = (props: TraceCustomVisualizationsProps) => {
{/* Need heading for each option */} {/* Need heading for each option */}
<Form.Item name="group_by"> <Form.Item name="group_by">
<Select style={{ width: 120 }} onChange={handleChange} allowClear> <Select style={{ width: 120 }} allowClear>
<Option value="none">Group By</Option> <Option value="none">Group By</Option>
<Option value="status">Status Code</Option> <Option value="status">Status Code</Option>
<Option value="protocol">Protocol</Option> <Option value="protocol">Protocol</Option>
@ -239,7 +223,7 @@ const mapStateToProps = (
traceFilters: TraceFilters; traceFilters: TraceFilters;
} => { } => {
return { return {
filteredTraceMetrics: state.filteredTraceMetrics, filteredTraceMetrics: state.metricsData.customMetricsItem,
globalTime: state.globalTime, globalTime: state.globalTime,
traceFilters: state.traceFilters, traceFilters: state.traceFilters,
}; };

View File

@ -1,19 +1,19 @@
import React, { useEffect, useMemo, useState } from "react"; import React, { useEffect, useState } from "react";
import { Bar } from "react-chartjs-2"; import { Bar } from "react-chartjs-2";
import { Card, Form, Select, Space } from "antd"; import { Card, Select, Space } from "antd";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { import {
getServicesList, getServicesList,
getUsageData, getUsageData,
GlobalTime, GlobalTime,
servicesListItem,
usageDataItem, usageDataItem,
} from "../../store/actions"; } from "../../store/actions";
import { StoreState } from "../../store/reducers"; import { StoreState } from "../../store/reducers";
import moment from "moment"; import moment from "moment";
import { isOnboardingSkipped } from "../../utils/app"; import { isOnboardingSkipped } from "../../utils/app";
import { useRoute } from "../RouteProvider"; import { useRoute } from "../RouteProvider";
import { servicesListItem } from "../../store/actions/MetricsActions";
const { Option } = Select; const { Option } = Select;
interface UsageExplorerProps { interface UsageExplorerProps {
@ -212,7 +212,7 @@ const mapStateToProps = (
totalCount: totalCount, totalCount: totalCount,
usageData: state.usageDate, usageData: state.usageDate,
globalTime: state.globalTime, globalTime: state.globalTime,
servicesList: state.servicesList, servicesList: state.metricsData.serviceList,
}; };
}; };

View File

@ -0,0 +1,3 @@
export * from "./metricsInterfaces";
export * from "./metricsActionTypes";
export * from "./metricsActions";

View File

@ -0,0 +1,34 @@
import {
externalErrCodeMetricsActions,
externalMetricsAvgDurationAction,
getDbOverViewMetricsAction,
getExternalMetricsAction,
getFilteredTraceMetricsAction,
getServiceMetricsAction,
getServicesListAction,
getTopEndpointsAction,
} from "./metricsInterfaces";
export enum MetricsActionTypes {
updateInput = "UPDATE_INPUT",
fetchTraces = "FETCH_TRACES",
fetchTraceItem = "FETCH_TRACE_ITEM",
getServicesList = "GET_SERVICE_LIST",
getServiceMetrics = "GET_SERVICE_METRICS",
getAvgDurationMetrics = "GET_AVG_DURATION_METRICS",
getErrCodeMetrics = "GET_ERR_CODE_METRICS",
getDbOverviewMetrics = "GET_DB_OVERVIEW_METRICS",
getExternalMetrics = "GET_EXTERNAL_METRICS",
getTopEndpoints = "GET_TOP_ENDPOINTS",
getFilteredTraceMetrics = "GET_FILTERED_TRACE_METRICS",
}
export type MetricsActions =
| getServicesListAction
| getServiceMetricsAction
| getTopEndpointsAction
| getFilteredTraceMetricsAction
| getExternalMetricsAction
| externalErrCodeMetricsActions
| getDbOverViewMetricsAction
| externalMetricsAvgDurationAction;

View File

@ -0,0 +1,190 @@
import { Dispatch } from "redux";
import api, { apiV1 } from "../../../api";
import { GlobalTime } from "../global";
import { toUTCEpoch } from "../../../utils/timeUtils";
import { MetricsActionTypes } from "./metricsActionTypes";
import * as MetricsInterfaces from "./metricsInterfaces";
export const getServicesList = (globalTime: GlobalTime) => {
return async (dispatch: Dispatch) => {
let request_string =
"/services?start=" + globalTime.minTime + "&end=" + globalTime.maxTime;
const response = await api.get<MetricsInterfaces.servicesListItem[]>(
apiV1 + request_string,
);
dispatch<MetricsInterfaces.getServicesListAction>({
type: MetricsActionTypes.getServicesList,
payload: response.data,
//PNOTE - response.data in the axios response has the actual API response
});
};
};
export const getDbOverViewMetrics = (
serviceName: string,
globalTime: GlobalTime,
) => {
return async (dispatch: Dispatch) => {
let request_string =
"/service/dbOverview?service=" +
serviceName +
"&start=" +
globalTime.minTime +
"&end=" +
globalTime.maxTime +
"&step=60";
const response = await api.get<MetricsInterfaces.dbOverviewMetricsItem[]>(
apiV1 + request_string,
);
dispatch<MetricsInterfaces.getDbOverViewMetricsAction>({
type: MetricsActionTypes.getDbOverviewMetrics,
payload: response.data,
});
};
};
export const getExternalMetrics = (
serviceName: string,
globalTime: GlobalTime,
) => {
return async (dispatch: Dispatch) => {
let request_string =
"/service/external?service=" +
serviceName +
"&start=" +
globalTime.minTime +
"&end=" +
globalTime.maxTime +
"&step=60";
const response = await api.get<MetricsInterfaces.externalMetricsItem[]>(
apiV1 + request_string,
);
dispatch<MetricsInterfaces.getExternalMetricsAction>({
type: MetricsActionTypes.getExternalMetrics,
payload: response.data,
});
};
};
export const getExternalAvgDurationMetrics = (
serviceName: string,
globalTime: GlobalTime,
) => {
return async (dispatch: Dispatch) => {
let request_string =
"/service/externalAvgDuration?service=" +
serviceName +
"&start=" +
globalTime.minTime +
"&end=" +
globalTime.maxTime +
"&step=60";
const response = await api.get<
MetricsInterfaces.externalMetricsAvgDurationItem[]
>(apiV1 + request_string);
dispatch<MetricsInterfaces.externalMetricsAvgDurationAction>({
type: MetricsActionTypes.getAvgDurationMetrics,
payload: response.data,
});
};
};
export const getExternalErrCodeMetrics = (
serviceName: string,
globalTime: GlobalTime,
) => {
return async (dispatch: Dispatch) => {
let request_string =
"/service/externalErrors?service=" +
serviceName +
"&start=" +
globalTime.minTime +
"&end=" +
globalTime.maxTime +
"&step=60";
const response = await api.get<
MetricsInterfaces.externalErrCodeMetricsItem[]
>(apiV1 + request_string);
dispatch<MetricsInterfaces.externalErrCodeMetricsActions>({
type: MetricsActionTypes.getErrCodeMetrics,
payload: response.data,
});
};
};
export const getServicesMetrics = (
serviceName: string,
globalTime: GlobalTime,
) => {
return async (dispatch: Dispatch) => {
let request_string =
"/service/overview?service=" +
serviceName +
"&start=" +
globalTime.minTime +
"&end=" +
globalTime.maxTime +
"&step=60";
const response = await api.get<MetricsInterfaces.metricItem[]>(
apiV1 + request_string,
);
dispatch<MetricsInterfaces.getServiceMetricsAction>({
type: MetricsActionTypes.getServiceMetrics,
payload: response.data,
//PNOTE - response.data in the axios response has the actual API response
});
};
};
export const getTopEndpoints = (
serviceName: string,
globalTime: GlobalTime,
) => {
return async (dispatch: Dispatch) => {
let request_string =
"/service/top_endpoints?service=" +
serviceName +
"&start=" +
globalTime.minTime +
"&end=" +
globalTime.maxTime;
const response = await api.get<MetricsInterfaces.topEndpointListItem[]>(
apiV1 + request_string,
);
dispatch<MetricsInterfaces.getTopEndpointsAction>({
type: MetricsActionTypes.getTopEndpoints,
payload: response.data,
//PNOTE - response.data in the axios response has the actual API response
});
};
};
export const getFilteredTraceMetrics = (
filter_params: string,
globalTime: GlobalTime,
) => {
return async (dispatch: Dispatch) => {
let request_string =
"/spans/aggregates?start=" +
toUTCEpoch(globalTime.minTime) +
"&end=" +
toUTCEpoch(globalTime.maxTime) +
"&" +
filter_params;
const response = await api.get<MetricsInterfaces.customMetricsItem[]>(
apiV1 + request_string,
);
dispatch<MetricsInterfaces.getFilteredTraceMetricsAction>({
type: MetricsActionTypes.getFilteredTraceMetrics,
payload: response.data,
//PNOTE - response.data in the axios response has the actual API response
});
};
};

View File

@ -0,0 +1,98 @@
import { MetricsActionTypes } from "./metricsActionTypes";
export interface servicesListItem {
serviceName: string;
p99: number;
avgDuration: number;
numCalls: number;
callRate: number;
numErrors: number;
errorRate: number;
}
export interface metricItem {
timestamp: number;
p50: number;
p95: number;
p99: number;
numCalls: number;
callRate: number;
numErrors: number;
errorRate: number;
}
export interface externalMetricsAvgDurationItem {
avgDuration: number;
timestamp: number;
}
export interface externalErrCodeMetricsItem {
externalHttpUrl: string;
numCalls: number;
timestamp: number;
callRate: number;
}
export interface topEndpointListItem {
p50: number;
p90: number;
p99: number;
numCalls: number;
name: string;
}
export interface externalMetricsItem {
avgDuration: number;
callRate: number;
externalHttpUrl: string;
numCalls: number;
timestamp: number;
}
export interface dbOverviewMetricsItem {
avgDuration: number;
callRate: number;
dbSystem: string;
numCalls: number;
timestamp: number;
}
export interface customMetricsItem {
timestamp: number;
value: number;
}
export interface getServicesListAction {
type: MetricsActionTypes.getServicesList;
payload: servicesListItem[];
}
export interface externalErrCodeMetricsActions {
type: MetricsActionTypes.getErrCodeMetrics;
payload: externalErrCodeMetricsItem[];
}
export interface externalMetricsAvgDurationAction {
type: MetricsActionTypes.getAvgDurationMetrics;
payload: externalMetricsAvgDurationItem[];
}
export interface getServiceMetricsAction {
type: MetricsActionTypes.getServiceMetrics;
payload: metricItem[];
}
export interface getExternalMetricsAction {
type: MetricsActionTypes.getExternalMetrics;
payload: externalMetricsItem[];
}
export interface getDbOverViewMetricsAction {
type: MetricsActionTypes.getDbOverviewMetrics;
payload: dbOverviewMetricsItem[];
}
export interface getTopEndpointsAction {
type: MetricsActionTypes.getTopEndpoints;
payload: topEndpointListItem[];
}
export interface getFilteredTraceMetricsAction {
type: MetricsActionTypes.getFilteredTraceMetrics;
payload: customMetricsItem[];
}

View File

@ -2,6 +2,6 @@ export * from "./types";
export * from "./traceFilters"; export * from "./traceFilters";
export * from "./serviceMap"; export * from "./serviceMap";
export * from "./traces"; export * from "./traces";
export * from "./metrics"; export * from "./MetricsActions";
export * from "./usage"; export * from "./usage";
export * from "./global"; export * from "./global";

View File

@ -1,277 +0,0 @@
import { Dispatch } from "redux";
import api, { apiV1 } from "../../api";
import { GlobalTime } from "./global";
import { ActionTypes } from "./types";
import { Token } from "../../utils/token";
import { toUTCEpoch } from "../../utils/timeUtils";
export interface servicesListItem {
serviceName: string;
p99: number;
avgDuration: number;
numCalls: number;
callRate: number;
numErrors: number;
errorRate: number;
}
export interface metricItem {
timestamp: number;
p50: number;
p95: number;
p99: number;
numCalls: number;
callRate: number;
numErrors: number;
errorRate: number;
}
export interface externalMetricsAvgDurationItem {
avgDuration: number;
timestamp: number;
}
export interface externalErrCodeMetricsItem {
errorRate: number;
externalHttpUrl: string;
numErrors: number;
timestamp: number;
}
export interface topEndpointListItem {
p50: number;
p90: number;
p99: number;
numCalls: number;
name: string;
}
export interface externalMetricsItem {
avgDuration: number;
callRate: number;
externalHttpUrl: string;
numCalls: number;
timestamp: number;
}
export interface dbOverviewMetricsItem {
avgDuration: number;
callRate: number;
dbSystem: string;
numCalls: number;
timestamp: number;
}
export interface customMetricsItem {
timestamp: number;
value: number;
}
export interface getServicesListAction {
type: ActionTypes.getServicesList;
payload: servicesListItem[];
}
export interface externalErrCodeMetricsActions {
type: ActionTypes.getErrCodeMetrics;
payload: externalErrCodeMetricsItem[];
}
export interface externalMetricsAvgDurationAction {
type: ActionTypes.getAvgDurationMetrics;
payload: externalMetricsAvgDurationItem[];
}
export interface getServiceMetricsAction {
type: ActionTypes.getServiceMetrics;
payload: metricItem[];
}
export interface getExternalMetricsAction {
type: ActionTypes.getExternalMetrics;
payload: externalMetricsItem[];
}
export interface getDbOverViewMetricsAction {
type: ActionTypes.getDbOverviewMetrics;
payload: dbOverviewMetricsItem[];
}
export interface getTopEndpointsAction {
type: ActionTypes.getTopEndpoints;
payload: topEndpointListItem[];
}
export interface getFilteredTraceMetricsAction {
type: ActionTypes.getFilteredTraceMetrics;
payload: customMetricsItem[];
}
export const getServicesList = (globalTime: GlobalTime) => {
return async (dispatch: Dispatch) => {
let request_string =
"/services?start=" + globalTime.minTime + "&end=" + globalTime.maxTime;
const response = await api.get<servicesListItem[]>(apiV1 + request_string);
dispatch<getServicesListAction>({
type: ActionTypes.getServicesList,
payload: response.data,
//PNOTE - response.data in the axios response has the actual API response
});
};
};
export const getDbOverViewMetrics = (
serviceName: string,
globalTime: GlobalTime,
) => {
return async (dispatch: Dispatch) => {
let request_string =
"/service/dbOverview?service=" +
serviceName +
"&start=" +
globalTime.minTime +
"&end=" +
globalTime.maxTime +
"&step=60";
const response = await api.get<dbOverviewMetricsItem[]>(
apiV1 + request_string,
);
dispatch<getDbOverViewMetricsAction>({
type: ActionTypes.getDbOverviewMetrics,
payload: response.data,
});
};
};
export const getExternalMetrics = (
serviceName: string,
globalTime: GlobalTime,
) => {
return async (dispatch: Dispatch) => {
let request_string =
"/service/external?service=" +
serviceName +
"&start=" +
globalTime.minTime +
"&end=" +
globalTime.maxTime +
"&step=60";
const response = await api.get<externalMetricsItem[]>(apiV1 + request_string);
dispatch<getExternalMetricsAction>({
type: ActionTypes.getExternalMetrics,
payload: response.data,
});
};
};
export const getExternalAvgDurationMetrics = (
serviceName: string,
globalTime: GlobalTime,
) => {
return async (dispatch: Dispatch) => {
let request_string =
"/service/externalAvgDuration?service=" +
serviceName +
"&start=" +
globalTime.minTime +
"&end=" +
globalTime.maxTime +
"&step=60";
const response = await api.get<externalMetricsAvgDurationItem[]>(
apiV1 + request_string,
);
dispatch<externalMetricsAvgDurationAction>({
type: ActionTypes.getAvgDurationMetrics,
payload: response.data,
});
};
};
export const getExternalErrCodeMetrics = (
serviceName: string,
globalTime: GlobalTime,
) => {
return async (dispatch: Dispatch) => {
let request_string =
"/service/externalErrors?service=" +
serviceName +
"&start=" +
globalTime.minTime +
"&end=" +
globalTime.maxTime +
"&step=60";
const response = await api.get<externalErrCodeMetricsItem[]>(
apiV1 + request_string,
);
dispatch<externalErrCodeMetricsActions>({
type: ActionTypes.getErrCodeMetrics,
payload: response.data,
});
};
};
export const getServicesMetrics = (
serviceName: string,
globalTime: GlobalTime,
) => {
return async (dispatch: Dispatch) => {
let request_string =
"/service/overview?service=" +
serviceName +
"&start=" +
globalTime.minTime +
"&end=" +
globalTime.maxTime +
"&step=60";
const response = await api.get<metricItem[]>(apiV1 + request_string);
dispatch<getServiceMetricsAction>({
type: ActionTypes.getServiceMetrics,
payload: response.data,
//PNOTE - response.data in the axios response has the actual API response
});
};
};
export const getTopEndpoints = (
serviceName: string,
globalTime: GlobalTime,
) => {
return async (dispatch: Dispatch) => {
let request_string =
"/service/top_endpoints?service=" +
serviceName +
"&start=" +
globalTime.minTime +
"&end=" +
globalTime.maxTime;
const response = await api.get<topEndpointListItem[]>(apiV1 + request_string);
dispatch<getTopEndpointsAction>({
type: ActionTypes.getTopEndpoints,
payload: response.data,
//PNOTE - response.data in the axios response has the actual API response
});
};
};
export const getFilteredTraceMetrics = (
filter_params: string,
globalTime: GlobalTime,
) => {
return async (dispatch: Dispatch) => {
let request_string =
"/spans/aggregates?start=" +
toUTCEpoch(globalTime.minTime) +
"&end=" +
toUTCEpoch(globalTime.maxTime) +
"&" +
filter_params;
const response = await api.get<customMetricsItem[]>(apiV1 + request_string);
dispatch<getFilteredTraceMetricsAction>({
type: ActionTypes.getFilteredTraceMetrics,
payload: response.data,
//PNOTE - response.data in the axios response has the actual API response
});
};
};

View File

@ -1,36 +1,16 @@
import { FetchTracesAction, FetchTraceItemAction } from "./traces"; import { FetchTracesAction, FetchTraceItemAction } from "./traces";
import { updateTraceFiltersAction, updateInputTagAction } from "./traceFilters"; import { updateTraceFiltersAction, updateInputTagAction } from "./traceFilters";
import {
getServicesListAction,
getServiceMetricsAction,
externalErrCodeMetricsActions,
externalMetricsAvgDurationAction,
getExternalMetricsAction,
getTopEndpointsAction,
getFilteredTraceMetricsAction,
getDbOverViewMetricsAction,
} from "./metrics";
import { serviceMapItemAction, servicesAction } from "./serviceMap"; import { serviceMapItemAction, servicesAction } from "./serviceMap";
import { getUsageDataAction } from "./usage"; import { getUsageDataAction } from "./usage";
import { updateTimeIntervalAction } from "./global"; import { updateTimeIntervalAction } from "./global";
export enum ActionTypes { export enum ActionTypes {
updateTraceFilters = "UPDATE_TRACES_FILTER", updateTraceFilters = "UPDATE_TRACES_FILTER",
updateInput = "UPDATE_INPUT",
fetchTraces = "FETCH_TRACES",
fetchTraceItem = "FETCH_TRACE_ITEM",
getServicesList = "GET_SERVICE_LIST",
getServiceMetrics = "GET_SERVICE_METRICS",
getAvgDurationMetrics = "GET_AVG_DURATION_METRICS",
getErrCodeMetrics = "GET_ERR_CODE_METRICS",
getDbOverviewMetrics = "GET_DB_OVERVIEW_METRICS",
getExternalMetrics = "GET_EXTERNAL_METRICS",
getTopEndpoints = "GET_TOP_ENDPOINTS",
getUsageData = "GET_USAGE_DATE",
updateTimeInterval = "UPDATE_TIME_INTERVAL", updateTimeInterval = "UPDATE_TIME_INTERVAL",
getFilteredTraceMetrics = "GET_FILTERED_TRACE_METRICS",
getServiceMapItems = "GET_SERVICE_MAP_ITEMS", getServiceMapItems = "GET_SERVICE_MAP_ITEMS",
getServices = "GET_SERVICES", getServices = "GET_SERVICES",
getUsageData = "GET_USAGE_DATE",
} }
export type Action = export type Action =
@ -38,15 +18,7 @@ export type Action =
| FetchTracesAction | FetchTracesAction
| updateTraceFiltersAction | updateTraceFiltersAction
| updateInputTagAction | updateInputTagAction
| getServicesListAction
| getServiceMetricsAction
| getTopEndpointsAction
| getUsageDataAction | getUsageDataAction
| updateTimeIntervalAction | updateTimeIntervalAction
| getFilteredTraceMetricsAction
| getExternalMetricsAction
| externalErrCodeMetricsActions
| getDbOverViewMetricsAction
| servicesAction | servicesAction
| serviceMapItemAction | serviceMapItemAction;
| externalMetricsAvgDurationAction;

View File

@ -2,7 +2,6 @@ import { Dispatch } from "redux";
import api, { apiV1 } from "../../api"; import api, { apiV1 } from "../../api";
import { ActionTypes } from "./types"; import { ActionTypes } from "./types";
import { GlobalTime } from "./global";
import { toUTCEpoch } from "../../utils/timeUtils"; import { toUTCEpoch } from "../../utils/timeUtils";
export interface usageDataItem { export interface usageDataItem {

View File

@ -2,48 +2,25 @@ import { combineReducers } from "redux";
import { import {
traceResponseNew, traceResponseNew,
spansWSameTraceIDResponse, spansWSameTraceIDResponse,
servicesListItem,
metricItem,
topEndpointListItem,
externalMetricsItem,
externalMetricsAvgDurationItem,
usageDataItem, usageDataItem,
GlobalTime, GlobalTime,
externalErrCodeMetricsItem,
serviceMapStore, serviceMapStore,
customMetricsItem,
TraceFilters, TraceFilters,
} from "../actions"; } from "../actions";
import { updateGlobalTimeReducer } from "./global"; import { updateGlobalTimeReducer } from "./global";
import { import { MetricsInitialState, metricsReducer } from "./metrics";
filteredTraceMetricsReducer,
serviceMetricsReducer,
externalErrCodeMetricsReducer,
serviceTableReducer,
topEndpointsReducer,
dbOverviewMetricsReducer,
externalMetricsReducer,
externalAvgDurationMetricsReducer,
} from "./metrics";
import { traceFiltersReducer, inputsReducer } from "./traceFilters"; import { traceFiltersReducer, inputsReducer } from "./traceFilters";
import { traceItemReducer, tracesReducer } from "./traces"; import { traceItemReducer, tracesReducer } from "./traces";
import { usageDataReducer } from "./usage"; import { usageDataReducer } from "./usage";
import { ServiceMapReducer } from "./serviceMap"; import { ServiceMapReducer } from "./serviceMap";
export interface StoreState { export interface StoreState {
metricsData: MetricsInitialState;
traceFilters: TraceFilters; traceFilters: TraceFilters;
inputTag: string;
traces: traceResponseNew; traces: traceResponseNew;
traceItem: spansWSameTraceIDResponse; traceItem: spansWSameTraceIDResponse;
servicesList: servicesListItem[];
serviceMetrics: metricItem[];
topEndpointsList: topEndpointListItem[];
externalMetrics: externalMetricsItem[];
dbOverviewMetrics: externalMetricsItem[];
externalAvgDurationMetrics: externalMetricsAvgDurationItem[];
externalErrCodeMetrics: externalErrCodeMetricsItem[];
usageDate: usageDataItem[]; usageDate: usageDataItem[];
globalTime: GlobalTime; globalTime: GlobalTime;
filteredTraceMetrics: customMetricsItem[];
serviceMap: serviceMapStore; serviceMap: serviceMapStore;
} }
@ -52,16 +29,9 @@ const reducers = combineReducers<StoreState>({
inputTag: inputsReducer, inputTag: inputsReducer,
traces: tracesReducer, traces: tracesReducer,
traceItem: traceItemReducer, traceItem: traceItemReducer,
servicesList: serviceTableReducer,
serviceMetrics: serviceMetricsReducer,
dbOverviewMetrics: dbOverviewMetricsReducer,
topEndpointsList: topEndpointsReducer,
externalAvgDurationMetrics: externalAvgDurationMetricsReducer,
externalMetrics: externalMetricsReducer,
externalErrCodeMetrics: externalErrCodeMetricsReducer,
usageDate: usageDataReducer, usageDate: usageDataReducer,
globalTime: updateGlobalTimeReducer, globalTime: updateGlobalTimeReducer,
filteredTraceMetrics: filteredTraceMetricsReducer, metricsData: metricsReducer,
serviceMap: ServiceMapReducer, serviceMap: ServiceMapReducer,
}); });

View File

@ -1,6 +1,4 @@
import { import {
ActionTypes,
Action,
servicesListItem, servicesListItem,
metricItem, metricItem,
topEndpointListItem, topEndpointListItem,
@ -9,10 +7,21 @@ import {
externalMetricsItem, externalMetricsItem,
dbOverviewMetricsItem, dbOverviewMetricsItem,
externalMetricsAvgDurationItem, externalMetricsAvgDurationItem,
} from "../actions"; } from "../actions/MetricsActions";
import { MetricsActionTypes as ActionTypes } from "../actions/MetricsActions/metricsActionTypes";
export const serviceTableReducer = ( export type MetricsInitialState = {
state: servicesListItem[] = [ serviceList?: servicesListItem[];
metricItems?: metricItem[];
topEndpointListItem?: topEndpointListItem[];
externalMetricsAvgDurationItem?: externalMetricsAvgDurationItem[];
externalErrCodeMetricsItem?: externalErrCodeMetricsItem[];
externalMetricsItem?: externalMetricsItem[];
dbOverviewMetricsItem?: dbOverviewMetricsItem[];
customMetricsItem?: customMetricsItem[];
};
export const metricsInitialState: MetricsInitialState = {
serviceList: [
{ {
serviceName: "", serviceName: "",
p99: 0, p99: 0,
@ -23,22 +32,11 @@ export const serviceTableReducer = (
errorRate: 0, errorRate: 0,
}, },
], ],
action: Action, metricItems: [
) => {
switch (action.type) {
case ActionTypes.getServicesList:
return action.payload;
default:
return state;
}
};
export const serviceMetricsReducer = (
state: metricItem[] = [
{ {
timestamp: 0, timestamp: 0,
p50: 0, p50: 0,
p90: 0, p95: 0,
p99: 0, p99: 0,
numCalls: 0, numCalls: 0,
callRate: 0.0, callRate: 0.0,
@ -46,49 +44,22 @@ export const serviceMetricsReducer = (
errorRate: 0, errorRate: 0,
}, },
], ],
action: Action, topEndpointListItem: [
) => { {
switch (action.type) { p50: 0,
case ActionTypes.getServiceMetrics: p90: 0,
return action.payload; p99: 0,
default: numCalls: 0,
return state; name: "",
} },
};
export const topEndpointsReducer = (
state: topEndpointListItem[] = [
{ p50: 0, p90: 0, p99: 0, numCalls: 0, name: "" },
], ],
action: Action, externalMetricsAvgDurationItem: [
) => {
switch (action.type) {
case ActionTypes.getTopEndpoints:
return action.payload;
default:
return state;
}
};
export const externalAvgDurationMetricsReducer = (
state: externalMetricsAvgDurationItem[] = [
{ {
avgDuration: 0, avgDuration: 0,
timestamp: 0, timestamp: 0,
}, },
], ],
action: Action, externalErrCodeMetricsItem: [
) => {
switch (action.type) {
case ActionTypes.getAvgDurationMetrics:
return action.payload;
default:
return state;
}
};
export const externalErrCodeMetricsReducer = (
state: externalErrCodeMetricsItem[] = [
{ {
callRate: 0, callRate: 0,
externalHttpUrl: "", externalHttpUrl: "",
@ -96,18 +67,7 @@ export const externalErrCodeMetricsReducer = (
timestamp: 0, timestamp: 0,
}, },
], ],
action: Action, externalMetricsItem: [
) => {
switch (action.type) {
case ActionTypes.getErrCodeMetrics:
return action.payload;
default:
return state;
}
};
export const externalMetricsReducer = (
state: externalMetricsItem[] = [
{ {
avgDuration: 0, avgDuration: 0,
callRate: 0, callRate: 0,
@ -116,18 +76,7 @@ export const externalMetricsReducer = (
timestamp: 0, timestamp: 0,
}, },
], ],
action: Action, dbOverviewMetricsItem: [
) => {
switch (action.type) {
case ActionTypes.getExternalMetrics:
return action.payload;
default:
return state;
}
};
export const dbOverviewMetricsReducer = (
state: dbOverviewMetricsItem[] = [
{ {
avgDuration: 0, avgDuration: 0,
callRate: 0, callRate: 0,
@ -136,24 +85,68 @@ export const dbOverviewMetricsReducer = (
timestamp: 0, timestamp: 0,
}, },
], ],
action: Action, customMetricsItem: [
) => { {
switch (action.type) { timestamp: 0,
case ActionTypes.getDbOverviewMetrics: value: 0,
return action.payload; },
default: ],
return state;
}
}; };
export const filteredTraceMetricsReducer = ( type ActionType = {
state: customMetricsItem[] = [{ timestamp: 0, value: 0 }], type: string;
action: Action, payload: any;
};
export const metricsReducer = (
state: MetricsInitialState = metricsInitialState,
action: ActionType,
) => { ) => {
switch (action.type) { switch (action.type) {
case ActionTypes.getFilteredTraceMetrics: case ActionTypes.getFilteredTraceMetrics:
return action.payload; return {
...state,
customMetricsItem: action.payload,
};
case ActionTypes.getServiceMetrics:
return {
...state,
metricItems: action.payload,
};
case ActionTypes.getDbOverviewMetrics:
return {
...state,
dbOverviewMetricsItem: action.payload,
};
case ActionTypes.getExternalMetrics:
return {
...state,
externalMetricsItem: action.payload,
};
case ActionTypes.getTopEndpoints:
return {
...state,
topEndpointListItem: action.payload,
};
case ActionTypes.getErrCodeMetrics:
return {
...state,
externalErrCodeMetricsItem: action.payload,
};
case ActionTypes.getAvgDurationMetrics:
return {
...state,
externalMetricsAvgDurationItem: action.payload,
};
case ActionTypes.getServicesList:
return {
...state,
serviceList: action.payload,
};
default: default:
return state; return {
...state,
};
} }
}; };