mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-14 02:35:56 +08:00
feat: navigate to trace from metrics (#2191)
* feat: navigate to trace from metrics * chore: add sonar back * chore: refactor
This commit is contained in:
parent
47a41473df
commit
d779b83715
@ -47,7 +47,7 @@ export const databaseCallsAvgDuration = ({
|
|||||||
const metricNameA = 'signoz_db_latency_sum';
|
const metricNameA = 'signoz_db_latency_sum';
|
||||||
const metricNameB = 'signoz_db_latency_count';
|
const metricNameB = 'signoz_db_latency_count';
|
||||||
const expression = 'A/B';
|
const expression = 'A/B';
|
||||||
const legendFormula = '';
|
const legendFormula = 'Average Duration';
|
||||||
const legend = '';
|
const legend = '';
|
||||||
const disabled = true;
|
const disabled = true;
|
||||||
const additionalItemsA = [
|
const additionalItemsA = [
|
||||||
|
@ -4,8 +4,11 @@ import {
|
|||||||
databaseCallsAvgDuration,
|
databaseCallsAvgDuration,
|
||||||
databaseCallsRPS,
|
databaseCallsRPS,
|
||||||
} from 'container/MetricsApplication/MetricsPageQueries/DBCallQueries';
|
} from 'container/MetricsApplication/MetricsPageQueries/DBCallQueries';
|
||||||
import { resourceAttributesToTagFilterItems } from 'lib/resourceAttributes';
|
import {
|
||||||
import React, { useMemo } from 'react';
|
convertRawQueriesToTraceSelectedTags,
|
||||||
|
resourceAttributesToTagFilterItems,
|
||||||
|
} from 'lib/resourceAttributes';
|
||||||
|
import React, { useMemo, useState } from 'react';
|
||||||
import { useSelector } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
import { useParams } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
import { AppState } from 'store/reducers';
|
import { AppState } from 'store/reducers';
|
||||||
@ -13,9 +16,16 @@ import { Widgets } from 'types/api/dashboard/getAll';
|
|||||||
import MetricReducer from 'types/reducer/metrics';
|
import MetricReducer from 'types/reducer/metrics';
|
||||||
|
|
||||||
import { Card, GraphContainer, GraphTitle, Row } from '../styles';
|
import { Card, GraphContainer, GraphTitle, Row } from '../styles';
|
||||||
|
import { Button } from './styles';
|
||||||
|
import {
|
||||||
|
dbSystemTags,
|
||||||
|
onGraphClickHandler,
|
||||||
|
onViewTracePopupClick,
|
||||||
|
} from './util';
|
||||||
|
|
||||||
function DBCall({ getWidgetQueryBuilder }: DBCallProps): JSX.Element {
|
function DBCall({ getWidgetQueryBuilder }: DBCallProps): JSX.Element {
|
||||||
const { servicename } = useParams<{ servicename?: string }>();
|
const { servicename } = useParams<{ servicename?: string }>();
|
||||||
|
const [selectedTimeStamp, setSelectedTimeStamp] = useState<number>(0);
|
||||||
const { resourceAttributeQueries } = useSelector<AppState, MetricReducer>(
|
const { resourceAttributeQueries } = useSelector<AppState, MetricReducer>(
|
||||||
(state) => state.metrics,
|
(state) => state.metrics,
|
||||||
);
|
);
|
||||||
@ -23,6 +33,15 @@ function DBCall({ getWidgetQueryBuilder }: DBCallProps): JSX.Element {
|
|||||||
() => resourceAttributesToTagFilterItems(resourceAttributeQueries) || [],
|
() => resourceAttributesToTagFilterItems(resourceAttributeQueries) || [],
|
||||||
[resourceAttributeQueries],
|
[resourceAttributeQueries],
|
||||||
);
|
);
|
||||||
|
const selectedTraceTags: string = useMemo(
|
||||||
|
() =>
|
||||||
|
JSON.stringify(
|
||||||
|
convertRawQueriesToTraceSelectedTags(resourceAttributeQueries).concat(
|
||||||
|
...dbSystemTags,
|
||||||
|
) || [],
|
||||||
|
),
|
||||||
|
[resourceAttributeQueries],
|
||||||
|
);
|
||||||
const legend = '{{db_system}}';
|
const legend = '{{db_system}}';
|
||||||
|
|
||||||
const databaseCallsRPSWidget = useMemo(
|
const databaseCallsRPSWidget = useMemo(
|
||||||
@ -39,7 +58,6 @@ function DBCall({ getWidgetQueryBuilder }: DBCallProps): JSX.Element {
|
|||||||
}),
|
}),
|
||||||
[getWidgetQueryBuilder, servicename, tagFilterItems],
|
[getWidgetQueryBuilder, servicename, tagFilterItems],
|
||||||
);
|
);
|
||||||
|
|
||||||
const databaseCallsAverageDurationWidget = useMemo(
|
const databaseCallsAverageDurationWidget = useMemo(
|
||||||
() =>
|
() =>
|
||||||
getWidgetQueryBuilder({
|
getWidgetQueryBuilder({
|
||||||
@ -57,6 +75,18 @@ function DBCall({ getWidgetQueryBuilder }: DBCallProps): JSX.Element {
|
|||||||
return (
|
return (
|
||||||
<Row gutter={24}>
|
<Row gutter={24}>
|
||||||
<Col span={12}>
|
<Col span={12}>
|
||||||
|
<Button
|
||||||
|
type="default"
|
||||||
|
size="small"
|
||||||
|
id="database_call_rps_button"
|
||||||
|
onClick={onViewTracePopupClick(
|
||||||
|
servicename,
|
||||||
|
selectedTraceTags,
|
||||||
|
selectedTimeStamp,
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
View Traces
|
||||||
|
</Button>
|
||||||
<Card>
|
<Card>
|
||||||
<GraphTitle>Database Calls RPS</GraphTitle>
|
<GraphTitle>Database Calls RPS</GraphTitle>
|
||||||
<GraphContainer>
|
<GraphContainer>
|
||||||
@ -65,12 +95,33 @@ function DBCall({ getWidgetQueryBuilder }: DBCallProps): JSX.Element {
|
|||||||
fullViewOptions={false}
|
fullViewOptions={false}
|
||||||
widget={databaseCallsRPSWidget}
|
widget={databaseCallsRPSWidget}
|
||||||
yAxisUnit="reqps"
|
yAxisUnit="reqps"
|
||||||
|
onClickHandler={(ChartEvent, activeElements, chart, data): void => {
|
||||||
|
onGraphClickHandler(setSelectedTimeStamp)(
|
||||||
|
ChartEvent,
|
||||||
|
activeElements,
|
||||||
|
chart,
|
||||||
|
data,
|
||||||
|
'database_call_rps',
|
||||||
|
);
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</GraphContainer>
|
</GraphContainer>
|
||||||
</Card>
|
</Card>
|
||||||
</Col>
|
</Col>
|
||||||
|
|
||||||
<Col span={12}>
|
<Col span={12}>
|
||||||
|
<Button
|
||||||
|
type="default"
|
||||||
|
size="small"
|
||||||
|
id="database_call_avg_duration_button"
|
||||||
|
onClick={onViewTracePopupClick(
|
||||||
|
servicename,
|
||||||
|
selectedTraceTags,
|
||||||
|
selectedTimeStamp,
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
View Traces
|
||||||
|
</Button>
|
||||||
<Card>
|
<Card>
|
||||||
<GraphTitle>Database Calls Avg Duration</GraphTitle>
|
<GraphTitle>Database Calls Avg Duration</GraphTitle>
|
||||||
<GraphContainer>
|
<GraphContainer>
|
||||||
@ -79,6 +130,15 @@ function DBCall({ getWidgetQueryBuilder }: DBCallProps): JSX.Element {
|
|||||||
fullViewOptions={false}
|
fullViewOptions={false}
|
||||||
widget={databaseCallsAverageDurationWidget}
|
widget={databaseCallsAverageDurationWidget}
|
||||||
yAxisUnit="ms"
|
yAxisUnit="ms"
|
||||||
|
onClickHandler={(ChartEvent, activeElements, chart, data): void => {
|
||||||
|
onGraphClickHandler(setSelectedTimeStamp)(
|
||||||
|
ChartEvent,
|
||||||
|
activeElements,
|
||||||
|
chart,
|
||||||
|
data,
|
||||||
|
'database_call_avg_duration',
|
||||||
|
);
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</GraphContainer>
|
</GraphContainer>
|
||||||
</Card>
|
</Card>
|
||||||
|
@ -6,8 +6,11 @@ import {
|
|||||||
externalCallErrorPercent,
|
externalCallErrorPercent,
|
||||||
externalCallRpsByAddress,
|
externalCallRpsByAddress,
|
||||||
} from 'container/MetricsApplication/MetricsPageQueries/ExternalQueries';
|
} from 'container/MetricsApplication/MetricsPageQueries/ExternalQueries';
|
||||||
import { resourceAttributesToTagFilterItems } from 'lib/resourceAttributes';
|
import {
|
||||||
import React, { useMemo } from 'react';
|
convertRawQueriesToTraceSelectedTags,
|
||||||
|
resourceAttributesToTagFilterItems,
|
||||||
|
} from 'lib/resourceAttributes';
|
||||||
|
import React, { useMemo, useState } from 'react';
|
||||||
import { useSelector } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
import { useParams } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
import { AppState } from 'store/reducers';
|
import { AppState } from 'store/reducers';
|
||||||
@ -15,18 +18,25 @@ import { Widgets } from 'types/api/dashboard/getAll';
|
|||||||
import MetricReducer from 'types/reducer/metrics';
|
import MetricReducer from 'types/reducer/metrics';
|
||||||
|
|
||||||
import { Card, GraphContainer, GraphTitle, Row } from '../styles';
|
import { Card, GraphContainer, GraphTitle, Row } from '../styles';
|
||||||
|
import { Button } from './styles';
|
||||||
|
import { onGraphClickHandler, onViewTracePopupClick } from './util';
|
||||||
|
|
||||||
function External({ getWidgetQueryBuilder }: ExternalProps): JSX.Element {
|
function External({ getWidgetQueryBuilder }: ExternalProps): JSX.Element {
|
||||||
const { servicename } = useParams<{ servicename?: string }>();
|
const { servicename } = useParams<{ servicename?: string }>();
|
||||||
const { resourceAttributeQueries } = useSelector<AppState, MetricReducer>(
|
const { resourceAttributeQueries } = useSelector<AppState, MetricReducer>(
|
||||||
(state) => state.metrics,
|
(state) => state.metrics,
|
||||||
);
|
);
|
||||||
|
const [selectedTimeStamp, setSelectedTimeStamp] = useState<number>(0);
|
||||||
|
|
||||||
const tagFilterItems = useMemo(
|
const tagFilterItems = useMemo(
|
||||||
() => resourceAttributesToTagFilterItems(resourceAttributeQueries) || [],
|
() => resourceAttributesToTagFilterItems(resourceAttributeQueries) || [],
|
||||||
[resourceAttributeQueries],
|
[resourceAttributeQueries],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const selectedTraceTags: string = JSON.stringify(
|
||||||
|
convertRawQueriesToTraceSelectedTags(resourceAttributeQueries) || [],
|
||||||
|
);
|
||||||
|
|
||||||
const legend = '{{address}}';
|
const legend = '{{address}}';
|
||||||
|
|
||||||
const externalCallErrorWidget = useMemo(
|
const externalCallErrorWidget = useMemo(
|
||||||
@ -92,6 +102,18 @@ function External({ getWidgetQueryBuilder }: ExternalProps): JSX.Element {
|
|||||||
<>
|
<>
|
||||||
<Row gutter={24}>
|
<Row gutter={24}>
|
||||||
<Col span={12}>
|
<Col span={12}>
|
||||||
|
<Button
|
||||||
|
type="default"
|
||||||
|
size="small"
|
||||||
|
id="external_call_error_percentage_button"
|
||||||
|
onClick={onViewTracePopupClick(
|
||||||
|
servicename,
|
||||||
|
selectedTraceTags,
|
||||||
|
selectedTimeStamp,
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
View Traces
|
||||||
|
</Button>
|
||||||
<Card>
|
<Card>
|
||||||
<GraphTitle>External Call Error Percentage</GraphTitle>
|
<GraphTitle>External Call Error Percentage</GraphTitle>
|
||||||
<GraphContainer>
|
<GraphContainer>
|
||||||
@ -100,12 +122,33 @@ function External({ getWidgetQueryBuilder }: ExternalProps): JSX.Element {
|
|||||||
fullViewOptions={false}
|
fullViewOptions={false}
|
||||||
widget={externalCallErrorWidget}
|
widget={externalCallErrorWidget}
|
||||||
yAxisUnit="%"
|
yAxisUnit="%"
|
||||||
|
onClickHandler={(ChartEvent, activeElements, chart, data): void => {
|
||||||
|
onGraphClickHandler(setSelectedTimeStamp)(
|
||||||
|
ChartEvent,
|
||||||
|
activeElements,
|
||||||
|
chart,
|
||||||
|
data,
|
||||||
|
'external_call_error_percentage',
|
||||||
|
);
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</GraphContainer>
|
</GraphContainer>
|
||||||
</Card>
|
</Card>
|
||||||
</Col>
|
</Col>
|
||||||
|
|
||||||
<Col span={12}>
|
<Col span={12}>
|
||||||
|
<Button
|
||||||
|
type="default"
|
||||||
|
size="small"
|
||||||
|
id="external_call_duration_button"
|
||||||
|
onClick={onViewTracePopupClick(
|
||||||
|
servicename,
|
||||||
|
selectedTraceTags,
|
||||||
|
selectedTimeStamp,
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
View Traces
|
||||||
|
</Button>
|
||||||
<Card>
|
<Card>
|
||||||
<GraphTitle>External Call duration</GraphTitle>
|
<GraphTitle>External Call duration</GraphTitle>
|
||||||
<GraphContainer>
|
<GraphContainer>
|
||||||
@ -114,6 +157,15 @@ function External({ getWidgetQueryBuilder }: ExternalProps): JSX.Element {
|
|||||||
fullViewOptions={false}
|
fullViewOptions={false}
|
||||||
widget={externalCallDurationWidget}
|
widget={externalCallDurationWidget}
|
||||||
yAxisUnit="ms"
|
yAxisUnit="ms"
|
||||||
|
onClickHandler={(ChartEvent, activeElements, chart, data): void => {
|
||||||
|
onGraphClickHandler(setSelectedTimeStamp)(
|
||||||
|
ChartEvent,
|
||||||
|
activeElements,
|
||||||
|
chart,
|
||||||
|
data,
|
||||||
|
'external_call_duration',
|
||||||
|
);
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</GraphContainer>
|
</GraphContainer>
|
||||||
</Card>
|
</Card>
|
||||||
@ -122,6 +174,18 @@ function External({ getWidgetQueryBuilder }: ExternalProps): JSX.Element {
|
|||||||
|
|
||||||
<Row gutter={24}>
|
<Row gutter={24}>
|
||||||
<Col span={12}>
|
<Col span={12}>
|
||||||
|
<Button
|
||||||
|
type="default"
|
||||||
|
size="small"
|
||||||
|
id="external_call_rps_by_address_button"
|
||||||
|
onClick={onViewTracePopupClick(
|
||||||
|
servicename,
|
||||||
|
selectedTraceTags,
|
||||||
|
selectedTimeStamp,
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
View Traces
|
||||||
|
</Button>
|
||||||
<Card>
|
<Card>
|
||||||
<GraphTitle>External Call RPS(by Address)</GraphTitle>
|
<GraphTitle>External Call RPS(by Address)</GraphTitle>
|
||||||
<GraphContainer>
|
<GraphContainer>
|
||||||
@ -130,12 +194,33 @@ function External({ getWidgetQueryBuilder }: ExternalProps): JSX.Element {
|
|||||||
fullViewOptions={false}
|
fullViewOptions={false}
|
||||||
widget={externalCallRPSWidget}
|
widget={externalCallRPSWidget}
|
||||||
yAxisUnit="reqps"
|
yAxisUnit="reqps"
|
||||||
|
onClickHandler={(ChartEvent, activeElements, chart, data): void => {
|
||||||
|
onGraphClickHandler(setSelectedTimeStamp)(
|
||||||
|
ChartEvent,
|
||||||
|
activeElements,
|
||||||
|
chart,
|
||||||
|
data,
|
||||||
|
'external_call_rps_by_address',
|
||||||
|
);
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</GraphContainer>
|
</GraphContainer>
|
||||||
</Card>
|
</Card>
|
||||||
</Col>
|
</Col>
|
||||||
|
|
||||||
<Col span={12}>
|
<Col span={12}>
|
||||||
|
<Button
|
||||||
|
type="default"
|
||||||
|
size="small"
|
||||||
|
id="external_call_duration_by_address_button"
|
||||||
|
onClick={onViewTracePopupClick(
|
||||||
|
servicename,
|
||||||
|
selectedTraceTags,
|
||||||
|
selectedTimeStamp,
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
View Traces
|
||||||
|
</Button>
|
||||||
<Card>
|
<Card>
|
||||||
<GraphTitle>External Call duration(by Address)</GraphTitle>
|
<GraphTitle>External Call duration(by Address)</GraphTitle>
|
||||||
<GraphContainer>
|
<GraphContainer>
|
||||||
@ -144,6 +229,15 @@ function External({ getWidgetQueryBuilder }: ExternalProps): JSX.Element {
|
|||||||
fullViewOptions={false}
|
fullViewOptions={false}
|
||||||
widget={externalCallDurationAddressWidget}
|
widget={externalCallDurationAddressWidget}
|
||||||
yAxisUnit="ms"
|
yAxisUnit="ms"
|
||||||
|
onClickHandler={(ChartEvent, activeElements, chart, data): void => {
|
||||||
|
onGraphClickHandler(setSelectedTimeStamp)(
|
||||||
|
ChartEvent,
|
||||||
|
activeElements,
|
||||||
|
chart,
|
||||||
|
data,
|
||||||
|
'external_call_duration_by_address',
|
||||||
|
);
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</GraphContainer>
|
</GraphContainer>
|
||||||
</Card>
|
</Card>
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import { ActiveElement, Chart, ChartData, ChartEvent } from 'chart.js';
|
|
||||||
import Graph from 'components/Graph';
|
import Graph from 'components/Graph';
|
||||||
import { METRICS_PAGE_QUERY_PARAM } from 'constants/query';
|
import { METRICS_PAGE_QUERY_PARAM } from 'constants/query';
|
||||||
import ROUTES from 'constants/routes';
|
import ROUTES from 'constants/routes';
|
||||||
@ -10,7 +9,7 @@ import {
|
|||||||
convertRawQueriesToTraceSelectedTags,
|
convertRawQueriesToTraceSelectedTags,
|
||||||
resourceAttributesToTagFilterItems,
|
resourceAttributesToTagFilterItems,
|
||||||
} from 'lib/resourceAttributes';
|
} from 'lib/resourceAttributes';
|
||||||
import React, { useCallback, useMemo, useRef } from 'react';
|
import React, { useCallback, useMemo, useState } from 'react';
|
||||||
import { useDispatch, useSelector } from 'react-redux';
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
import { useParams } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
import { UpdateTimeInterval } from 'store/actions';
|
import { UpdateTimeInterval } from 'store/actions';
|
||||||
@ -25,10 +24,11 @@ import {
|
|||||||
import { Card, Col, GraphContainer, GraphTitle, Row } from '../styles';
|
import { Card, Col, GraphContainer, GraphTitle, Row } from '../styles';
|
||||||
import TopOperationsTable from '../TopOperationsTable';
|
import TopOperationsTable from '../TopOperationsTable';
|
||||||
import { Button } from './styles';
|
import { Button } from './styles';
|
||||||
|
import { onGraphClickHandler, onViewTracePopupClick } from './util';
|
||||||
|
|
||||||
function Application({ getWidgetQueryBuilder }: DashboardProps): JSX.Element {
|
function Application({ getWidgetQueryBuilder }: DashboardProps): JSX.Element {
|
||||||
const { servicename } = useParams<{ servicename?: string }>();
|
const { servicename } = useParams<{ servicename?: string }>();
|
||||||
const selectedTimeStamp = useRef(0);
|
const [selectedTimeStamp, setSelectedTimeStamp] = useState<number>(0);
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@ -39,7 +39,7 @@ function Application({ getWidgetQueryBuilder }: DashboardProps): JSX.Element {
|
|||||||
} = useSelector<AppState, MetricReducer>((state) => state.metrics);
|
} = useSelector<AppState, MetricReducer>((state) => state.metrics);
|
||||||
|
|
||||||
const selectedTraceTags: string = JSON.stringify(
|
const selectedTraceTags: string = JSON.stringify(
|
||||||
convertRawQueriesToTraceSelectedTags(resourceAttributeQueries, 'array') || [],
|
convertRawQueriesToTraceSelectedTags(resourceAttributeQueries) || [],
|
||||||
);
|
);
|
||||||
|
|
||||||
const tagFilterItems = useMemo(
|
const tagFilterItems = useMemo(
|
||||||
@ -77,58 +77,6 @@ function Application({ getWidgetQueryBuilder }: DashboardProps): JSX.Element {
|
|||||||
[servicename, topLevelOperations, tagFilterItems, getWidgetQueryBuilder],
|
[servicename, topLevelOperations, tagFilterItems, getWidgetQueryBuilder],
|
||||||
);
|
);
|
||||||
|
|
||||||
const onTracePopupClick = (timestamp: number): void => {
|
|
||||||
const currentTime = timestamp;
|
|
||||||
const tPlusOne = timestamp + 1 * 60 * 1000;
|
|
||||||
|
|
||||||
const urlParams = new URLSearchParams();
|
|
||||||
urlParams.set(METRICS_PAGE_QUERY_PARAM.startTime, currentTime.toString());
|
|
||||||
urlParams.set(METRICS_PAGE_QUERY_PARAM.endTime, tPlusOne.toString());
|
|
||||||
|
|
||||||
history.replace(
|
|
||||||
`${
|
|
||||||
ROUTES.TRACE
|
|
||||||
}?${urlParams.toString()}&selected={"serviceName":["${servicename}"]}&filterToFetchData=["duration","status","serviceName"]&spanAggregateCurrentPage=1&selectedTags=${selectedTraceTags}&&isFilterExclude={"serviceName":false}&userSelectedFilter={"status":["error","ok"],"serviceName":["${servicename}"]}&spanAggregateCurrentPage=1`,
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const onClickHandler = async (
|
|
||||||
event: ChartEvent,
|
|
||||||
elements: ActiveElement[],
|
|
||||||
chart: Chart,
|
|
||||||
data: ChartData,
|
|
||||||
from: string,
|
|
||||||
): Promise<void> => {
|
|
||||||
if (event.native) {
|
|
||||||
const points = chart.getElementsAtEventForMode(
|
|
||||||
event.native,
|
|
||||||
'nearest',
|
|
||||||
{ intersect: true },
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
|
|
||||||
const id = `${from}_button`;
|
|
||||||
const buttonElement = document.getElementById(id);
|
|
||||||
|
|
||||||
if (points.length !== 0) {
|
|
||||||
const firstPoint = points[0];
|
|
||||||
|
|
||||||
if (data.labels) {
|
|
||||||
const time = data?.labels[firstPoint.index] as Date;
|
|
||||||
|
|
||||||
if (buttonElement) {
|
|
||||||
buttonElement.style.display = 'block';
|
|
||||||
buttonElement.style.left = `${firstPoint.element.x}px`;
|
|
||||||
buttonElement.style.top = `${firstPoint.element.y}px`;
|
|
||||||
selectedTimeStamp.current = time.getTime();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (buttonElement && buttonElement.style.display === 'block') {
|
|
||||||
buttonElement.style.display = 'none';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const onDragSelect = useCallback(
|
const onDragSelect = useCallback(
|
||||||
(start: number, end: number) => {
|
(start: number, end: number) => {
|
||||||
const startTimestamp = Math.trunc(start);
|
const startTimestamp = Math.trunc(start);
|
||||||
@ -162,9 +110,11 @@ function Application({ getWidgetQueryBuilder }: DashboardProps): JSX.Element {
|
|||||||
type="default"
|
type="default"
|
||||||
size="small"
|
size="small"
|
||||||
id="Service_button"
|
id="Service_button"
|
||||||
onClick={(): void => {
|
onClick={onViewTracePopupClick(
|
||||||
onTracePopupClick(selectedTimeStamp.current);
|
servicename,
|
||||||
}}
|
selectedTraceTags,
|
||||||
|
selectedTimeStamp,
|
||||||
|
)}
|
||||||
>
|
>
|
||||||
View Traces
|
View Traces
|
||||||
</Button>
|
</Button>
|
||||||
@ -173,7 +123,13 @@ function Application({ getWidgetQueryBuilder }: DashboardProps): JSX.Element {
|
|||||||
<GraphContainer>
|
<GraphContainer>
|
||||||
<Graph
|
<Graph
|
||||||
onClickHandler={(ChartEvent, activeElements, chart, data): void => {
|
onClickHandler={(ChartEvent, activeElements, chart, data): void => {
|
||||||
onClickHandler(ChartEvent, activeElements, chart, data, 'Service');
|
onGraphClickHandler(setSelectedTimeStamp)(
|
||||||
|
ChartEvent,
|
||||||
|
activeElements,
|
||||||
|
chart,
|
||||||
|
data,
|
||||||
|
'Service',
|
||||||
|
);
|
||||||
}}
|
}}
|
||||||
name="service_latency"
|
name="service_latency"
|
||||||
type="line"
|
type="line"
|
||||||
@ -230,9 +186,11 @@ function Application({ getWidgetQueryBuilder }: DashboardProps): JSX.Element {
|
|||||||
type="default"
|
type="default"
|
||||||
size="small"
|
size="small"
|
||||||
id="Rate_button"
|
id="Rate_button"
|
||||||
onClick={(): void => {
|
onClick={onViewTracePopupClick(
|
||||||
onTracePopupClick(selectedTimeStamp.current);
|
servicename,
|
||||||
}}
|
selectedTraceTags,
|
||||||
|
selectedTimeStamp,
|
||||||
|
)}
|
||||||
>
|
>
|
||||||
View Traces
|
View Traces
|
||||||
</Button>
|
</Button>
|
||||||
@ -243,7 +201,13 @@ function Application({ getWidgetQueryBuilder }: DashboardProps): JSX.Element {
|
|||||||
name="operations_per_sec"
|
name="operations_per_sec"
|
||||||
fullViewOptions={false}
|
fullViewOptions={false}
|
||||||
onClickHandler={(event, element, chart, data): void => {
|
onClickHandler={(event, element, chart, data): void => {
|
||||||
onClickHandler(event, element, chart, data, 'Rate');
|
onGraphClickHandler(setSelectedTimeStamp)(
|
||||||
|
event,
|
||||||
|
element,
|
||||||
|
chart,
|
||||||
|
data,
|
||||||
|
'Rate',
|
||||||
|
);
|
||||||
}}
|
}}
|
||||||
widget={operationPerSecWidget}
|
widget={operationPerSecWidget}
|
||||||
yAxisUnit="ops"
|
yAxisUnit="ops"
|
||||||
@ -260,7 +224,7 @@ function Application({ getWidgetQueryBuilder }: DashboardProps): JSX.Element {
|
|||||||
size="small"
|
size="small"
|
||||||
id="Error_button"
|
id="Error_button"
|
||||||
onClick={(): void => {
|
onClick={(): void => {
|
||||||
onErrorTrackHandler(selectedTimeStamp.current);
|
onErrorTrackHandler(selectedTimeStamp);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
View Traces
|
View Traces
|
||||||
@ -273,7 +237,13 @@ function Application({ getWidgetQueryBuilder }: DashboardProps): JSX.Element {
|
|||||||
name="error_percentage_%"
|
name="error_percentage_%"
|
||||||
fullViewOptions={false}
|
fullViewOptions={false}
|
||||||
onClickHandler={(ChartEvent, activeElements, chart, data): void => {
|
onClickHandler={(ChartEvent, activeElements, chart, data): void => {
|
||||||
onClickHandler(ChartEvent, activeElements, chart, data, 'Error');
|
onGraphClickHandler(setSelectedTimeStamp)(
|
||||||
|
ChartEvent,
|
||||||
|
activeElements,
|
||||||
|
chart,
|
||||||
|
data,
|
||||||
|
'Error',
|
||||||
|
);
|
||||||
}}
|
}}
|
||||||
widget={errorPercentageWidget}
|
widget={errorPercentageWidget}
|
||||||
yAxisUnit="%"
|
yAxisUnit="%"
|
||||||
|
75
frontend/src/container/MetricsApplication/Tabs/util.ts
Normal file
75
frontend/src/container/MetricsApplication/Tabs/util.ts
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
import { ActiveElement, Chart, ChartData, ChartEvent } from 'chart.js';
|
||||||
|
import { METRICS_PAGE_QUERY_PARAM } from 'constants/query';
|
||||||
|
import ROUTES from 'constants/routes';
|
||||||
|
import history from 'lib/history';
|
||||||
|
import { Tags } from 'types/reducer/trace';
|
||||||
|
|
||||||
|
export const dbSystemTags: Tags[] = [
|
||||||
|
{
|
||||||
|
Key: ['db.system.(string)'],
|
||||||
|
StringValues: [''],
|
||||||
|
NumberValues: [],
|
||||||
|
BoolValues: [],
|
||||||
|
Operator: 'Exists',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export function onViewTracePopupClick(
|
||||||
|
servicename: string | undefined,
|
||||||
|
selectedTraceTags: string,
|
||||||
|
timestamp: number,
|
||||||
|
): VoidFunction {
|
||||||
|
return (): void => {
|
||||||
|
const currentTime = timestamp;
|
||||||
|
const tPlusOne = timestamp + 1 * 60 * 1000;
|
||||||
|
|
||||||
|
const urlParams = new URLSearchParams();
|
||||||
|
urlParams.set(METRICS_PAGE_QUERY_PARAM.startTime, currentTime.toString());
|
||||||
|
urlParams.set(METRICS_PAGE_QUERY_PARAM.endTime, tPlusOne.toString());
|
||||||
|
|
||||||
|
history.replace(
|
||||||
|
`${
|
||||||
|
ROUTES.TRACE
|
||||||
|
}?${urlParams.toString()}&selected={"serviceName":["${servicename}"]}&filterToFetchData=["duration","status","serviceName"]&spanAggregateCurrentPage=1&selectedTags=${selectedTraceTags}&&isFilterExclude={"serviceName":false}&userSelectedFilter={"status":["error","ok"],"serviceName":["${servicename}"]}&spanAggregateCurrentPage=1`,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function onGraphClickHandler(
|
||||||
|
setSelectedTimeStamp: React.Dispatch<React.SetStateAction<number>>,
|
||||||
|
) {
|
||||||
|
return async (
|
||||||
|
event: ChartEvent,
|
||||||
|
elements: ActiveElement[],
|
||||||
|
chart: Chart,
|
||||||
|
data: ChartData,
|
||||||
|
from: string,
|
||||||
|
): Promise<void> => {
|
||||||
|
if (event.native) {
|
||||||
|
const points = chart.getElementsAtEventForMode(
|
||||||
|
event.native,
|
||||||
|
'nearest',
|
||||||
|
{ intersect: true },
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
const id = `${from}_button`;
|
||||||
|
const buttonElement = document.getElementById(id);
|
||||||
|
|
||||||
|
if (points.length !== 0) {
|
||||||
|
const firstPoint = points[0];
|
||||||
|
|
||||||
|
if (data.labels) {
|
||||||
|
const time = data?.labels[firstPoint.index] as Date;
|
||||||
|
if (buttonElement) {
|
||||||
|
buttonElement.style.display = 'block';
|
||||||
|
buttonElement.style.left = `${firstPoint.element.x}px`;
|
||||||
|
buttonElement.style.top = `${firstPoint.element.y}px`;
|
||||||
|
setSelectedTimeStamp(time.getTime());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (buttonElement && buttonElement.style.display === 'block') {
|
||||||
|
buttonElement.style.display = 'none';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
import { OperatorConversions } from 'constants/resourceAttributes';
|
import { OperatorConversions } from 'constants/resourceAttributes';
|
||||||
import { IResourceAttributeQuery } from 'container/MetricsApplication/ResourceAttributesFilter/types';
|
import { IResourceAttributeQuery } from 'container/MetricsApplication/ResourceAttributesFilter/types';
|
||||||
import { IQueryBuilderTagFilterItems } from 'types/api/dashboard/getAll';
|
import { IQueryBuilderTagFilterItems } from 'types/api/dashboard/getAll';
|
||||||
import { OperatorValues, Tags, TagsAPI } from 'types/reducer/trace';
|
import { OperatorValues, Tags } from 'types/reducer/trace';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* resource_x_y -> x.y
|
* resource_x_y -> x.y
|
||||||
@ -35,13 +35,9 @@ export const convertOperatorLabelToTraceOperator = (
|
|||||||
|
|
||||||
export const convertRawQueriesToTraceSelectedTags = (
|
export const convertRawQueriesToTraceSelectedTags = (
|
||||||
queries: IResourceAttributeQuery[],
|
queries: IResourceAttributeQuery[],
|
||||||
keyType: 'string' | 'array' = 'string',
|
): Tags[] =>
|
||||||
): Tags[] | TagsAPI[] =>
|
|
||||||
queries.map((query) => ({
|
queries.map((query) => ({
|
||||||
Key:
|
Key: [convertMetricKeyToTrace(query.tagKey)],
|
||||||
keyType === 'array'
|
|
||||||
? [convertMetricKeyToTrace(query.tagKey)]
|
|
||||||
: (convertMetricKeyToTrace(query.tagKey) as never),
|
|
||||||
Operator: convertOperatorLabelToTraceOperator(query.operator),
|
Operator: convertOperatorLabelToTraceOperator(query.operator),
|
||||||
StringValues: query.tagValue,
|
StringValues: query.tagValue,
|
||||||
NumberValues: [],
|
NumberValues: [],
|
||||||
|
@ -54,13 +54,6 @@ export interface Tags {
|
|||||||
BoolValues: boolean[];
|
BoolValues: boolean[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TagsAPI {
|
|
||||||
Key: string;
|
|
||||||
Operator: OperatorValues;
|
|
||||||
StringValues: string[];
|
|
||||||
NumberValues: number[];
|
|
||||||
BoolValues: boolean[];
|
|
||||||
}
|
|
||||||
export type OperatorValues =
|
export type OperatorValues =
|
||||||
| 'NotIn'
|
| 'NotIn'
|
||||||
| 'In'
|
| 'In'
|
||||||
|
Loading…
x
Reference in New Issue
Block a user