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

View File

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

View File

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

View File

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

View File

@ -4,9 +4,7 @@ import { ChartOptions } from "chart.js";
import { withRouter } from "react-router";
import { RouteComponentProps } from "react-router-dom";
import styled from "styled-components";
import ROUTES from "Src/constants/routes";
import { metricItem } from "../../store/actions/metrics";
import { metricItem } from "../../store/actions/MetricsActions";
const ChartPopUpUnique = styled.div<{
ycoordinate: number;
@ -39,11 +37,8 @@ interface LatencyLineChartProps extends RouteComponentProps<any> {
popupClickHandler: Function;
}
interface LatencyLineChart {
chartRef: any;
}
class LatencyLineChart extends React.Component<LatencyLineChartProps> {
private chartRef: React.RefObject<HTMLElement>;
constructor(props: LatencyLineChartProps) {
super(props);
this.chartRef = React.createRef();
@ -54,7 +49,6 @@ class LatencyLineChart extends React.Component<LatencyLineChartProps> {
ycoordinate: 0,
showpopUp: false,
firstpoint_ts: 0,
// graphInfo:{}
};
onClickhandler = async (e: any, event: any) => {
@ -69,7 +63,6 @@ class LatencyLineChart extends React.Component<LatencyLineChartProps> {
ycoordinate: e.offsetY,
showpopUp: true,
firstpoint_ts: this.props.data[firstPoint._index].timestamp,
// graphInfo:{...event}
});
} else {
// 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 = {
onClick: this.onClickhandler,
@ -161,9 +145,6 @@ class LatencyLineChart extends React.Component<LatencyLineChartProps> {
xAxes: [
{
type: "time",
// time: {
// unit: 'second'
// },
distribution: "linear",
//'linear': data are spread according to their time (distances can vary)
// From https://www.chartjs.org/docs/latest/axes/cartesian/time.html
@ -193,7 +174,6 @@ class LatencyLineChart extends React.Component<LatencyLineChartProps> {
>
View Traces
</PopUpElements>
{/* <PopUpElements onClick={this.gotoAlertsHandler}>Set Alerts</PopUpElements> */}
</ChartPopUpUnique>
);
} else return null;

View File

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

View File

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

View File

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

View File

@ -3,7 +3,7 @@ import { Table, Button, Tooltip } from "antd";
import { connect } from "react-redux";
import styled from "styled-components";
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 { GlobalTime } from "Src/store/actions";
import { StoreState } from "Src/store/reducers";

View File

@ -9,7 +9,7 @@ type State = {
};
enum ActionTypes {
UPDATE_IS_LOADED = "UPDATE_IS_LOADED",
UPDATE_IS_LOADED = "ROUTE_IS_LOADED",
}
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 { RouteComponentProps } from "react-router-dom";
import {

View File

@ -2,16 +2,11 @@ import React, { useState, useEffect } from "react";
import GenericVisualizations from "../Metrics/GenericVisualization";
import { Select, Card, Space, Form } from "antd";
import { connect } from "react-redux";
import { StoreState } from "../../store/reducers";
import {
customMetricsItem,
getFilteredTraceMetrics,
GlobalTime,
TraceFilters,
} from "../../store/actions";
import { GlobalTime, TraceFilters } from "../../store/actions";
import { useRoute } from "../RouteProvider";
import { getFilteredTraceMetrics } from "../../store/actions/MetricsActions";
import { customMetricsItem } from "../../store/actions/MetricsActions";
const { Option } = Select;
const entity = [
@ -81,8 +76,9 @@ interface TraceCustomVisualizationsProps {
const _TraceCustomVisualizations = (props: TraceCustomVisualizationsProps) => {
const [selectedEntity, setSelectedEntity] = useState("calls");
const [selectedAggOption, setSelectedAggOption] = useState("count");
const [selectedStep, setSelectedStep] = useState("60");
const { state } = useRoute();
const [form] = Form.useForm();
const selectedStep = "60";
// 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
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/
const handleFormValuesChange = (changedValues: any) => {
const formFieldName = Object.keys(changedValues)[0];
@ -162,11 +148,9 @@ const _TraceCustomVisualizations = (props: TraceCustomVisualizationsProps) => {
return (
<Card>
{/* <Space direction="vertical"> */}
<div>Custom Visualizations</div>
<Form
form={form}
onFinish={handleFinish}
onValuesChange={handleFormValuesChange}
initialValues={{
agg_options: "Count",
@ -199,7 +183,7 @@ const _TraceCustomVisualizations = (props: TraceCustomVisualizationsProps) => {
</Form.Item>
<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="bar">Bar Chart</Option>
<Option value="area">Area Chart</Option>
@ -207,7 +191,7 @@ const _TraceCustomVisualizations = (props: TraceCustomVisualizationsProps) => {
</Form.Item>
<Form.Item name="interval">
<Select style={{ width: 120 }} onChange={handleChange} allowClear>
<Select style={{ width: 120 }} allowClear>
<Option value="1m">1 min</Option>
<Option value="5m">5 min</Option>
<Option value="30m">30 min</Option>
@ -216,7 +200,7 @@ const _TraceCustomVisualizations = (props: TraceCustomVisualizationsProps) => {
{/* Need heading for each option */}
<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="status">Status Code</Option>
<Option value="protocol">Protocol</Option>
@ -239,7 +223,7 @@ const mapStateToProps = (
traceFilters: TraceFilters;
} => {
return {
filteredTraceMetrics: state.filteredTraceMetrics,
filteredTraceMetrics: state.metricsData.customMetricsItem,
globalTime: state.globalTime,
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 { Card, Form, Select, Space } from "antd";
import { Card, Select, Space } from "antd";
import { connect } from "react-redux";
import {
getServicesList,
getUsageData,
GlobalTime,
servicesListItem,
usageDataItem,
} from "../../store/actions";
import { StoreState } from "../../store/reducers";
import moment from "moment";
import { isOnboardingSkipped } from "../../utils/app";
import { useRoute } from "../RouteProvider";
import { servicesListItem } from "../../store/actions/MetricsActions";
const { Option } = Select;
interface UsageExplorerProps {
@ -212,7 +212,7 @@ const mapStateToProps = (
totalCount: totalCount,
usageData: state.usageDate,
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 "./serviceMap";
export * from "./traces";
export * from "./metrics";
export * from "./MetricsActions";
export * from "./usage";
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 { updateTraceFiltersAction, updateInputTagAction } from "./traceFilters";
import {
getServicesListAction,
getServiceMetricsAction,
externalErrCodeMetricsActions,
externalMetricsAvgDurationAction,
getExternalMetricsAction,
getTopEndpointsAction,
getFilteredTraceMetricsAction,
getDbOverViewMetricsAction,
} from "./metrics";
import { serviceMapItemAction, servicesAction } from "./serviceMap";
import { getUsageDataAction } from "./usage";
import { updateTimeIntervalAction } from "./global";
export enum ActionTypes {
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",
getFilteredTraceMetrics = "GET_FILTERED_TRACE_METRICS",
getServiceMapItems = "GET_SERVICE_MAP_ITEMS",
getServices = "GET_SERVICES",
getUsageData = "GET_USAGE_DATE",
}
export type Action =
@ -38,15 +18,7 @@ export type Action =
| FetchTracesAction
| updateTraceFiltersAction
| updateInputTagAction
| getServicesListAction
| getServiceMetricsAction
| getTopEndpointsAction
| getUsageDataAction
| updateTimeIntervalAction
| getFilteredTraceMetricsAction
| getExternalMetricsAction
| externalErrCodeMetricsActions
| getDbOverViewMetricsAction
| servicesAction
| serviceMapItemAction
| externalMetricsAvgDurationAction;
| serviceMapItemAction;

View File

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

View File

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

View File

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