mirror of
https://github.com/SigNoz/signoz.git
synced 2025-12-23 02:17:11 +00:00
* feat: custom hook to prevent redundant navigation and handle default params with URL comparison * feat: implement useSafeNavigation to QB, to ensure that the back navigation works properly * fix: handle syncing the relativeTime param with the time picker selected relative time * feat: add support for absolute and relative time sync with time picker component * refactor: integrate safeNavigate in LogsExplorerChart and deprecate the existing back navigation * feat: update pagination query params on pressing next/prev page * fix: fix the issue of NOOP getting converted to Count on coming back from alert creation page * refactor: replace history navigation with safeNavigate in DateTimeSelectionV2 component it also fixes the issue of relativeTime not being added to the url on mounting * feat: integrate useSafeNavigate across service details tabs * fix: fix duplicate redirections by converting the timestamp to milliseconds * fix: replace history navigation with useSafeNavigate in LogsExplorerViews and useUrlQueryData * fix: replace history navigation with useSafeNavigate across dashboard components * fix: use safeNavigate in alert components * fix: fix the issue of back navigation in alert table and sync the pagination with url param * fix: handle back navigation for resource filter and sync the state with url query * fix: fix the issue of double redirection from top operations to traces * fix: replace history.push with safeNavigate in TracesExplorer's updateDashboard * fix: prevent unnecessary query re-runs by checking stagedQuery before redirecting in NewWidget * chore: cleanup * fix: fix the failing tests * fix: fix the documentation redirection failing tests * test: mock useSafeNavigate hook in WidgetGraphComponent test * test: mock useSafeNavigate hook in ExplorerCard test
243 lines
6.4 KiB
TypeScript
243 lines
6.4 KiB
TypeScript
import { Col } from 'antd';
|
|
import logEvent from 'api/common/logEvent';
|
|
import { ENTITY_VERSION_V4 } from 'constants/app';
|
|
import { QueryParams } from 'constants/query';
|
|
import { PANEL_TYPES } from 'constants/queryBuilder';
|
|
import Graph from 'container/GridCardLayout/GridCard';
|
|
import {
|
|
databaseCallsAvgDuration,
|
|
databaseCallsRPS,
|
|
} from 'container/MetricsApplication/MetricsPageQueries/DBCallQueries';
|
|
import useResourceAttribute from 'hooks/useResourceAttribute';
|
|
import {
|
|
convertRawQueriesToTraceSelectedTags,
|
|
resourceAttributesToTagFilterItems,
|
|
} from 'hooks/useResourceAttribute/utils';
|
|
import { useSafeNavigate } from 'hooks/useSafeNavigate';
|
|
import useUrlQuery from 'hooks/useUrlQuery';
|
|
import getStep from 'lib/getStep';
|
|
import history from 'lib/history';
|
|
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
import { useDispatch } from 'react-redux';
|
|
import { useLocation, useParams } from 'react-router-dom';
|
|
import store from 'store';
|
|
import { UpdateTimeInterval } from 'store/actions';
|
|
import { TagFilterItem } from 'types/api/queryBuilder/queryBuilderData';
|
|
import { EQueryType } from 'types/common/dashboard';
|
|
import { v4 as uuid } from 'uuid';
|
|
|
|
import { GraphTitle, MENU_ITEMS, SERVICE_CHART_ID } from '../constant';
|
|
import { getWidgetQueryBuilder } from '../MetricsApplication.factory';
|
|
import { Card, GraphContainer, Row } from '../styles';
|
|
import { Button } from './styles';
|
|
import { IServiceName } from './types';
|
|
import {
|
|
dbSystemTags,
|
|
handleNonInQueryRange,
|
|
onGraphClickHandler,
|
|
onViewTracePopupClick,
|
|
useGetAPMToTracesQueries,
|
|
} from './util';
|
|
|
|
function DBCall(): JSX.Element {
|
|
const { servicename: encodedServiceName } = useParams<IServiceName>();
|
|
|
|
const servicename = decodeURIComponent(encodedServiceName);
|
|
const [selectedTimeStamp, setSelectedTimeStamp] = useState<number>(0);
|
|
const { queries } = useResourceAttribute();
|
|
const urlQuery = useUrlQuery();
|
|
const { pathname } = useLocation();
|
|
const dispatch = useDispatch();
|
|
|
|
const onDragSelect = useCallback(
|
|
(start: number, end: number) => {
|
|
const startTimestamp = Math.trunc(start);
|
|
const endTimestamp = Math.trunc(end);
|
|
|
|
urlQuery.set(QueryParams.startTime, startTimestamp.toString());
|
|
urlQuery.set(QueryParams.endTime, endTimestamp.toString());
|
|
const generatedUrl = `${pathname}?${urlQuery.toString()}`;
|
|
history.push(generatedUrl);
|
|
|
|
if (startTimestamp !== endTimestamp) {
|
|
dispatch(UpdateTimeInterval('custom', [startTimestamp, endTimestamp]));
|
|
}
|
|
},
|
|
[dispatch, pathname, urlQuery],
|
|
);
|
|
|
|
const tagFilterItems: TagFilterItem[] = useMemo(
|
|
() =>
|
|
handleNonInQueryRange(resourceAttributesToTagFilterItems(queries)) || [],
|
|
[queries],
|
|
);
|
|
|
|
const selectedTraceTags: string = useMemo(
|
|
() =>
|
|
JSON.stringify(
|
|
convertRawQueriesToTraceSelectedTags(queries).concat(...dbSystemTags) || [],
|
|
),
|
|
[queries],
|
|
);
|
|
|
|
const legend = '{{db_system}}';
|
|
|
|
const databaseCallsRPSWidget = useMemo(
|
|
() =>
|
|
getWidgetQueryBuilder({
|
|
query: {
|
|
queryType: EQueryType.QUERY_BUILDER,
|
|
promql: [],
|
|
builder: databaseCallsRPS({
|
|
servicename,
|
|
legend,
|
|
tagFilterItems,
|
|
}),
|
|
clickhouse_sql: [],
|
|
id: uuid(),
|
|
},
|
|
title: GraphTitle.DATABASE_CALLS_RPS,
|
|
panelTypes: PANEL_TYPES.TIME_SERIES,
|
|
yAxisUnit: 'reqps',
|
|
id: SERVICE_CHART_ID.dbCallsRPS,
|
|
fillSpans: false,
|
|
}),
|
|
[servicename, tagFilterItems],
|
|
);
|
|
const databaseCallsAverageDurationWidget = useMemo(
|
|
() =>
|
|
getWidgetQueryBuilder({
|
|
query: {
|
|
queryType: EQueryType.QUERY_BUILDER,
|
|
promql: [],
|
|
builder: databaseCallsAvgDuration({
|
|
servicename,
|
|
tagFilterItems,
|
|
}),
|
|
clickhouse_sql: [],
|
|
id: uuid(),
|
|
},
|
|
title: GraphTitle.DATABASE_CALLS_AVG_DURATION,
|
|
panelTypes: PANEL_TYPES.TIME_SERIES,
|
|
yAxisUnit: 'ms',
|
|
id: GraphTitle.DATABASE_CALLS_AVG_DURATION,
|
|
fillSpans: true,
|
|
}),
|
|
[servicename, tagFilterItems],
|
|
);
|
|
|
|
const stepInterval = useMemo(
|
|
() =>
|
|
getStep({
|
|
end: store.getState().globalTime.maxTime,
|
|
inputFormat: 'ns',
|
|
start: store.getState().globalTime.minTime,
|
|
}),
|
|
[],
|
|
);
|
|
|
|
const logEventCalledRef = useRef(false);
|
|
|
|
useEffect(() => {
|
|
if (!logEventCalledRef.current) {
|
|
const selectedEnvironments = queries.find(
|
|
(val) => val.tagKey === 'resource_deployment_environment',
|
|
)?.tagValue;
|
|
|
|
logEvent('APM: Service detail page visited', {
|
|
selectedEnvironments,
|
|
resourceAttributeUsed: !!queries?.length,
|
|
section: 'dbMetrics',
|
|
});
|
|
logEventCalledRef.current = true;
|
|
}
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
}, []);
|
|
|
|
const apmToTraceQuery = useGetAPMToTracesQueries({
|
|
servicename,
|
|
isDBCall: true,
|
|
});
|
|
const { safeNavigate } = useSafeNavigate();
|
|
|
|
return (
|
|
<Row gutter={24}>
|
|
<Col span={12}>
|
|
<Button
|
|
type="default"
|
|
size="small"
|
|
id="database_call_rps_button"
|
|
onClick={onViewTracePopupClick({
|
|
servicename,
|
|
selectedTraceTags,
|
|
timestamp: selectedTimeStamp,
|
|
apmToTraceQuery,
|
|
stepInterval,
|
|
safeNavigate,
|
|
})}
|
|
>
|
|
View Traces
|
|
</Button>
|
|
<Card data-testid="database_call_rps">
|
|
<GraphContainer>
|
|
<Graph
|
|
widget={databaseCallsRPSWidget}
|
|
onClickHandler={(xValue, yValue, mouseX, mouseY): void => {
|
|
onGraphClickHandler(setSelectedTimeStamp)(
|
|
xValue,
|
|
yValue,
|
|
mouseX,
|
|
mouseY,
|
|
'database_call_rps',
|
|
);
|
|
}}
|
|
onDragSelect={onDragSelect}
|
|
version={ENTITY_VERSION_V4}
|
|
/>
|
|
</GraphContainer>
|
|
</Card>
|
|
</Col>
|
|
|
|
<Col span={12}>
|
|
<Button
|
|
type="default"
|
|
size="small"
|
|
id="database_call_avg_duration_button"
|
|
onClick={onViewTracePopupClick({
|
|
servicename,
|
|
selectedTraceTags,
|
|
timestamp: selectedTimeStamp,
|
|
apmToTraceQuery,
|
|
stepInterval,
|
|
safeNavigate,
|
|
})}
|
|
>
|
|
View Traces
|
|
</Button>
|
|
|
|
<Card data-testid="database_call_avg_duration">
|
|
<GraphContainer>
|
|
<Graph
|
|
widget={databaseCallsAverageDurationWidget}
|
|
headerMenuList={MENU_ITEMS}
|
|
onClickHandler={(xValue, yValue, mouseX, mouseY): void => {
|
|
onGraphClickHandler(setSelectedTimeStamp)(
|
|
xValue,
|
|
yValue,
|
|
mouseX,
|
|
mouseY,
|
|
'database_call_avg_duration',
|
|
);
|
|
}}
|
|
onDragSelect={onDragSelect}
|
|
version={ENTITY_VERSION_V4}
|
|
/>
|
|
</GraphContainer>
|
|
</Card>
|
|
</Col>
|
|
</Row>
|
|
);
|
|
}
|
|
|
|
export default DBCall;
|