Merge branch 'main' into change-p90

# Conflicts:
#	frontend/src/store/actions/metrics.ts
#	frontend/src/store/reducers/metrics.ts
This commit is contained in:
Nidhi Tandon 2021-05-31 21:56:25 +05:30
commit 8a4f58e77b
29 changed files with 489 additions and 634 deletions

View File

@ -147,7 +147,6 @@
"prettier": "2.2.1",
"react-hot-loader": "^4.13.0",
"react-is": "^17.0.1",
"webpack-bundle-analyzer": "^4.4.2",
"webpack-cli": "^4.5.0"
}
}

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;
@ -239,7 +219,7 @@ class LatencyLineChart extends React.Component<LatencyLineChartProps> {
<div>
{this.GraphTracePopUp()}
<div>
<div style={{textAlign: "center"}}>Application latency in ms</div>
<div style={{ textAlign: "center" }}>Application latency in ms</div>
<ChartJSLine
ref={this.chartRef}
data={data_chartJS}

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,32 @@
import {
externalErrCodeMetricsActions,
externalMetricsAvgDurationAction,
getDbOverViewMetricsAction,
getExternalMetricsAction,
getFilteredTraceMetricsAction,
getServiceMetricsAction,
getServicesListAction,
getTopEndpointsAction,
} from "./metricsInterfaces";
export enum MetricsActionTypes {
updateInput = "UPDATE_INPUT",
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;
p95: 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

@ -32,16 +32,4 @@ export const updateTraceFilters = (traceFilters: TraceFilters) => {
};
};
export interface updateInputTagAction {
type: ActionTypes.updateInput;
payload: string;
}
export const updateInputTag = (Input: string) => {
return {
type: ActionTypes.updateInput,
payload: Input,
};
};
//named export when you want to export multiple functions from the same file

View File

@ -1,36 +1,18 @@
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",
fetchTraces = "FETCH_TRACES",
fetchTraceItem = "FETCH_TRACE_ITEM",
}
export type Action =
@ -38,15 +20,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,66 +2,35 @@ 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 { traceFiltersReducer, inputsReducer } from "./traceFilters";
import { MetricsInitialState, metricsReducer } from "./metrics";
import TraceFilterReducer 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;
}
const reducers = combineReducers<StoreState>({
traceFilters: traceFiltersReducer,
inputTag: inputsReducer,
traceFilters: TraceFilterReducer,
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,18 +32,7 @@ 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,
@ -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, p95: 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,
};
}
};

View File

@ -1,12 +1,11 @@
import { ActionTypes, Action, serviceMapStore } from "../actions";
export const ServiceMapReducer = (
state: serviceMapStore = {
items: [],
services: [],
},
action: Action,
) => {
const initialState: serviceMapStore = {
items: [],
services: [],
};
export const ServiceMapReducer = (state = initialState, action: Action) => {
switch (action.type) {
case ActionTypes.getServiceMapItems:
return {

View File

@ -1,19 +1,17 @@
import {
ActionTypes,
TraceFilters,
updateInputTagAction,
updateTraceFiltersAction,
} from "../actions";
import { ActionTypes, TraceFilters } from "../actions";
export const traceFiltersReducer = (
state: TraceFilters = {
service: "",
tags: [],
operation: "",
latency: { min: "", max: "" },
},
action: updateTraceFiltersAction,
) => {
type ACTION = {
type: ActionTypes;
payload: TraceFilters;
};
const initialState: TraceFilters = {
service: "",
tags: [],
operation: "",
latency: { min: "", max: "" },
};
const TraceFilterReducer = (state = initialState, action: ACTION) => {
switch (action.type) {
case ActionTypes.updateTraceFilters:
return action.payload;
@ -22,14 +20,4 @@ export const traceFiltersReducer = (
}
};
export const inputsReducer = (
state: string = "",
action: updateInputTagAction,
) => {
switch (action.type) {
case ActionTypes.updateInput:
return action.payload;
default:
return state;
}
};
export default TraceFilterReducer;

View File

@ -2,7 +2,6 @@
const { resolve } = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
console.log(resolve(__dirname, "./src/"));
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = {
mode: "development",
@ -57,7 +56,6 @@ module.exports = {
},
plugins: [
new HtmlWebpackPlugin({ template: "src/index.html.ejs" }),
new BundleAnalyzerPlugin()
],
performance: {
hints: false,

View File

@ -1574,11 +1574,6 @@
schema-utils "^2.6.5"
source-map "^0.7.3"
"@polka/url@^1.0.0-next.15":
version "1.0.0-next.15"
resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.15.tgz#6a9d143f7f4f49db2d782f9e1c8839a29b43ae23"
integrity sha512-15spi3V28QdevleWBNXE4pIls3nFZmBbUGrW9IVPwiQczuSb9n76TCB4bsk8TSel+I1OkHEdPhu5QKMfY6rQHA==
"@rollup/plugin-node-resolve@^7.1.1":
version "7.1.3"
resolved "https://registry.yarnpkg.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-7.1.3.tgz#80de384edfbd7bfc9101164910f86078151a3eca"
@ -2596,11 +2591,6 @@ acorn-walk@^7.1.1:
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc"
integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==
acorn-walk@^8.0.0:
version "8.1.0"
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.1.0.tgz#d3c6a9faf00987a5e2b9bdb506c2aa76cd707f83"
integrity sha512-mjmzmv12YIG/G8JQdQuz2MUDShEJ6teYpT5bmWA4q7iwoGen8xtt3twF3OvzIUl+Q06aWIjvnwQUKvQ6TtMRjg==
acorn@^7.1.0, acorn@^7.1.1, acorn@^7.4.0:
version "7.4.1"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa"
@ -5486,7 +5476,7 @@ dtype@^2.0.0:
resolved "https://registry.yarnpkg.com/dtype/-/dtype-2.0.0.tgz#cd052323ce061444ecd2e8f5748f69a29be28434"
integrity sha1-zQUjI84GFETs0uj1dI9popvihDQ=
duplexer@^0.1.1, duplexer@^0.1.2:
duplexer@^0.1.1:
version "0.1.2"
resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6"
integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==
@ -6946,13 +6936,6 @@ gzip-size@5.1.1:
duplexer "^0.1.1"
pify "^4.0.1"
gzip-size@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-6.0.0.tgz#065367fd50c239c0671cbcbad5be3e2eeb10e462"
integrity sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==
dependencies:
duplexer "^0.1.2"
handle-thing@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.1.tgz#857f79ce359580c340d43081cc648970d0bb234e"
@ -9035,7 +9018,7 @@ mime@1.6.0, mime@^1.3.4, mime@^1.4.1:
resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==
mime@^2.3.1, mime@^2.4.4:
mime@^2.4.4:
version "2.5.2"
resolved "https://registry.yarnpkg.com/mime/-/mime-2.5.2.tgz#6e3dc6cc2b9510643830e5f19d5cb753da5eeabe"
integrity sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==
@ -9601,11 +9584,6 @@ opencollective-postinstall@^2.0.2:
resolved "https://registry.yarnpkg.com/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz#7a0fff978f6dbfa4d006238fbac98ed4198c3259"
integrity sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==
opener@^1.5.2:
version "1.5.2"
resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.2.tgz#5d37e1f35077b9dcac4301372271afdeb2a13598"
integrity sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==
opn@^5.5.0:
version "5.5.0"
resolved "https://registry.yarnpkg.com/opn/-/opn-5.5.0.tgz#fc7164fab56d235904c51c3b27da6758ca3b9bfc"
@ -12236,15 +12214,6 @@ simple-get@^2.7.0:
once "^1.3.1"
simple-concat "^1.0.0"
sirv@^1.0.7:
version "1.0.12"
resolved "https://registry.yarnpkg.com/sirv/-/sirv-1.0.12.tgz#d816c882b35489b3c63290e2f455ae3eccd5f652"
integrity sha512-+jQoCxndz7L2tqQL4ZyzfDhky0W/4ZJip3XoOuxyQWnAwMxindLl3Xv1qT4x1YX/re0leShvTm8Uk0kQspGhBg==
dependencies:
"@polka/url" "^1.0.0-next.15"
mime "^2.3.1"
totalist "^1.0.0"
sisteransi@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed"
@ -13096,11 +13065,6 @@ toidentifier@1.0.0:
resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553"
integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==
totalist@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/totalist/-/totalist-1.1.0.tgz#a4d65a3e546517701e3e5c37a47a70ac97fe56df"
integrity sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g==
tough-cookie@^2.3.3, tough-cookie@~2.5.0:
version "2.5.0"
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2"
@ -13657,21 +13621,6 @@ webidl-conversions@^6.1.0:
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-6.1.0.tgz#9111b4d7ea80acd40f5270d666621afa78b69514"
integrity sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==
webpack-bundle-analyzer@^4.4.2:
version "4.4.2"
resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.4.2.tgz#39898cf6200178240910d629705f0f3493f7d666"
integrity sha512-PIagMYhlEzFfhMYOzs5gFT55DkUdkyrJi/SxJp8EF3YMWhS+T9vvs2EoTetpk5qb6VsCq02eXTlRDOydRhDFAQ==
dependencies:
acorn "^8.0.4"
acorn-walk "^8.0.0"
chalk "^4.1.0"
commander "^6.2.0"
gzip-size "^6.0.0"
lodash "^4.17.20"
opener "^1.5.2"
sirv "^1.0.7"
ws "^7.3.1"
webpack-cli@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-4.5.0.tgz#b5213b84adf6e1f5de6391334c9fa53a48850466"
@ -14146,11 +14095,6 @@ ws@^7.2.3:
resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.3.tgz#1f9643de34a543b8edb124bdcbc457ae55a6e5cd"
integrity sha512-hr6vCR76GsossIRsr8OLR9acVVm1jyfEWvhbNjtgPOrfvAlKzvyeg/P6r8RuDjRyrcQoPQT7K0DGEPc7Ae6jzA==
ws@^7.3.1:
version "7.4.6"
resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c"
integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==
xhr-request@^1.0.1:
version "1.1.0"
resolved "https://registry.yarnpkg.com/xhr-request/-/xhr-request-1.1.0.tgz#f4a7c1868b9f198723444d82dcae317643f2e2ed"