mirror of
https://github.com/SigNoz/signoz.git
synced 2026-03-16 18:02:09 +00:00
Compare commits
21 Commits
debug_time
...
perf/panel
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
18e856f62c | ||
|
|
c0bd545e26 | ||
|
|
346be7b7ba | ||
|
|
10176e3128 | ||
|
|
a6832d6ed0 | ||
|
|
5504e90620 | ||
|
|
19cffa0165 | ||
|
|
4dc4a0b95e | ||
|
|
2462f551be | ||
|
|
78ab80d294 | ||
|
|
d285b90f09 | ||
|
|
08e756cf5d | ||
|
|
42c1ddda39 | ||
|
|
efb85fc205 | ||
|
|
0e972257db | ||
|
|
f8144e3a1d | ||
|
|
02a8a11976 | ||
|
|
4a351e5280 | ||
|
|
311257a518 | ||
|
|
d5c665a72a | ||
|
|
0d6c8785d9 |
@@ -132,34 +132,117 @@ function CeleryTaskBar({
|
|||||||
[selectedFilters, celerySuccessStateData],
|
[selectedFilters, celerySuccessStateData],
|
||||||
);
|
);
|
||||||
|
|
||||||
const onGraphClick = (
|
const onGraphClick = useCallback(
|
||||||
widgetData: Widgets,
|
(
|
||||||
xValue: number,
|
widgetData: Widgets,
|
||||||
_yValue: number,
|
xValue: number,
|
||||||
_mouseX: number,
|
_yValue: number,
|
||||||
_mouseY: number,
|
_mouseX: number,
|
||||||
data?: {
|
_mouseY: number,
|
||||||
[key: string]: string;
|
data?: {
|
||||||
|
[key: string]: string;
|
||||||
|
},
|
||||||
|
): void => {
|
||||||
|
const { start, end } = getStartAndEndTimesInMilliseconds(xValue);
|
||||||
|
|
||||||
|
// Extract entity and value from data
|
||||||
|
const [firstDataPoint] = Object.entries(data || {});
|
||||||
|
const [entity, value] = (firstDataPoint || ([] as unknown)) as [
|
||||||
|
string,
|
||||||
|
string,
|
||||||
|
];
|
||||||
|
|
||||||
|
if (!isEmpty(entity) || !isEmpty(value)) {
|
||||||
|
onClick?.({
|
||||||
|
entity,
|
||||||
|
value,
|
||||||
|
timeRange: [start, end],
|
||||||
|
widgetData,
|
||||||
|
});
|
||||||
|
}
|
||||||
},
|
},
|
||||||
): void => {
|
[onClick],
|
||||||
const { start, end } = getStartAndEndTimesInMilliseconds(xValue);
|
);
|
||||||
|
|
||||||
// Extract entity and value from data
|
const onAllStateClick = useCallback(
|
||||||
const [firstDataPoint] = Object.entries(data || {});
|
(
|
||||||
const [entity, value] = (firstDataPoint || ([] as unknown)) as [
|
xValue: number,
|
||||||
string,
|
yValue: number,
|
||||||
string,
|
mouseX: number,
|
||||||
];
|
mouseY: number,
|
||||||
|
data?: any,
|
||||||
|
): void => {
|
||||||
|
onGraphClick(
|
||||||
|
celerySlowestTasksTableWidgetData,
|
||||||
|
xValue,
|
||||||
|
yValue,
|
||||||
|
mouseX,
|
||||||
|
mouseY,
|
||||||
|
data,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
[onGraphClick],
|
||||||
|
);
|
||||||
|
|
||||||
if (!isEmpty(entity) || !isEmpty(value)) {
|
const onFailedStateClick = useCallback(
|
||||||
onClick?.({
|
(
|
||||||
entity,
|
xValue: number,
|
||||||
value,
|
yValue: number,
|
||||||
timeRange: [start, end],
|
mouseX: number,
|
||||||
widgetData,
|
mouseY: number,
|
||||||
});
|
data?: any,
|
||||||
}
|
): void => {
|
||||||
};
|
onGraphClick(
|
||||||
|
celeryFailedTasksTableWidgetData,
|
||||||
|
xValue,
|
||||||
|
yValue,
|
||||||
|
mouseX,
|
||||||
|
mouseY,
|
||||||
|
data,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
[onGraphClick],
|
||||||
|
);
|
||||||
|
|
||||||
|
const onRetryStateClick = useCallback(
|
||||||
|
(
|
||||||
|
xValue: number,
|
||||||
|
yValue: number,
|
||||||
|
mouseX: number,
|
||||||
|
mouseY: number,
|
||||||
|
data?: any,
|
||||||
|
): void => {
|
||||||
|
onGraphClick(
|
||||||
|
celeryRetryTasksTableWidgetData,
|
||||||
|
xValue,
|
||||||
|
yValue,
|
||||||
|
mouseX,
|
||||||
|
mouseY,
|
||||||
|
data,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
[onGraphClick],
|
||||||
|
);
|
||||||
|
|
||||||
|
const onSuccessStateClick = useCallback(
|
||||||
|
(
|
||||||
|
xValue: number,
|
||||||
|
yValue: number,
|
||||||
|
mouseX: number,
|
||||||
|
mouseY: number,
|
||||||
|
data?: any,
|
||||||
|
): void => {
|
||||||
|
onGraphClick(
|
||||||
|
celerySuccessTasksTableWidgetData,
|
||||||
|
xValue,
|
||||||
|
yValue,
|
||||||
|
mouseX,
|
||||||
|
mouseY,
|
||||||
|
data,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
[onGraphClick],
|
||||||
|
);
|
||||||
|
|
||||||
const { getCustomSeries } = useGetGraphCustomSeries({
|
const { getCustomSeries } = useGetGraphCustomSeries({
|
||||||
isDarkMode,
|
isDarkMode,
|
||||||
@@ -185,16 +268,7 @@ function CeleryTaskBar({
|
|||||||
headerMenuList={[...ViewMenuAction]}
|
headerMenuList={[...ViewMenuAction]}
|
||||||
onDragSelect={onDragSelect}
|
onDragSelect={onDragSelect}
|
||||||
isQueryEnabled={queryEnabled}
|
isQueryEnabled={queryEnabled}
|
||||||
onClickHandler={(xValue, yValue, mouseX, mouseY, data): void =>
|
onClickHandler={onAllStateClick}
|
||||||
onGraphClick(
|
|
||||||
celerySlowestTasksTableWidgetData,
|
|
||||||
xValue,
|
|
||||||
yValue,
|
|
||||||
mouseX,
|
|
||||||
mouseY,
|
|
||||||
data,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
customSeries={getCustomSeries}
|
customSeries={getCustomSeries}
|
||||||
dataAvailable={checkIfDataExists}
|
dataAvailable={checkIfDataExists}
|
||||||
/>
|
/>
|
||||||
@@ -205,16 +279,7 @@ function CeleryTaskBar({
|
|||||||
headerMenuList={[...ViewMenuAction]}
|
headerMenuList={[...ViewMenuAction]}
|
||||||
onDragSelect={onDragSelect}
|
onDragSelect={onDragSelect}
|
||||||
isQueryEnabled={queryEnabled}
|
isQueryEnabled={queryEnabled}
|
||||||
onClickHandler={(xValue, yValue, mouseX, mouseY, data): void =>
|
onClickHandler={onFailedStateClick}
|
||||||
onGraphClick(
|
|
||||||
celeryFailedTasksTableWidgetData,
|
|
||||||
xValue,
|
|
||||||
yValue,
|
|
||||||
mouseX,
|
|
||||||
mouseY,
|
|
||||||
data,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
customSeries={getCustomSeries}
|
customSeries={getCustomSeries}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
@@ -224,16 +289,7 @@ function CeleryTaskBar({
|
|||||||
headerMenuList={[...ViewMenuAction]}
|
headerMenuList={[...ViewMenuAction]}
|
||||||
onDragSelect={onDragSelect}
|
onDragSelect={onDragSelect}
|
||||||
isQueryEnabled={queryEnabled}
|
isQueryEnabled={queryEnabled}
|
||||||
onClickHandler={(xValue, yValue, mouseX, mouseY, data): void =>
|
onClickHandler={onRetryStateClick}
|
||||||
onGraphClick(
|
|
||||||
celeryRetryTasksTableWidgetData,
|
|
||||||
xValue,
|
|
||||||
yValue,
|
|
||||||
mouseX,
|
|
||||||
mouseY,
|
|
||||||
data,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
customSeries={getCustomSeries}
|
customSeries={getCustomSeries}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
@@ -243,16 +299,7 @@ function CeleryTaskBar({
|
|||||||
headerMenuList={[...ViewMenuAction]}
|
headerMenuList={[...ViewMenuAction]}
|
||||||
onDragSelect={onDragSelect}
|
onDragSelect={onDragSelect}
|
||||||
isQueryEnabled={queryEnabled}
|
isQueryEnabled={queryEnabled}
|
||||||
onClickHandler={(xValue, yValue, mouseX, mouseY, data): void =>
|
onClickHandler={onSuccessStateClick}
|
||||||
onGraphClick(
|
|
||||||
celerySuccessTasksTableWidgetData,
|
|
||||||
xValue,
|
|
||||||
yValue,
|
|
||||||
mouseX,
|
|
||||||
mouseY,
|
|
||||||
data,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
customSeries={getCustomSeries}
|
customSeries={getCustomSeries}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import {
|
|||||||
SetStateAction,
|
SetStateAction,
|
||||||
useCallback,
|
useCallback,
|
||||||
useEffect,
|
useEffect,
|
||||||
|
useMemo,
|
||||||
useRef,
|
useRef,
|
||||||
useState,
|
useState,
|
||||||
} from 'react';
|
} from 'react';
|
||||||
@@ -76,6 +77,7 @@ function WidgetGraphComponent({
|
|||||||
const isFullViewOpen = params.get(QueryParams.expandedWidgetId) === widget.id;
|
const isFullViewOpen = params.get(QueryParams.expandedWidgetId) === widget.id;
|
||||||
|
|
||||||
const lineChartRef = useRef<ToggleGraphProps>();
|
const lineChartRef = useRef<ToggleGraphProps>();
|
||||||
|
|
||||||
const [graphVisibility, setGraphVisibility] = useState<boolean[]>(
|
const [graphVisibility, setGraphVisibility] = useState<boolean[]>(
|
||||||
Array(queryResponse.data?.payload?.data?.result?.length || 0).fill(true),
|
Array(queryResponse.data?.payload?.data?.result?.length || 0).fill(true),
|
||||||
);
|
);
|
||||||
@@ -110,7 +112,7 @@ function WidgetGraphComponent({
|
|||||||
|
|
||||||
const updateDashboardMutation = useUpdateDashboard();
|
const updateDashboardMutation = useUpdateDashboard();
|
||||||
|
|
||||||
const onDeleteHandler = (): void => {
|
const onDeleteHandler = useCallback((): void => {
|
||||||
if (!selectedDashboard) return;
|
if (!selectedDashboard) return;
|
||||||
|
|
||||||
const updatedWidgets = selectedDashboard?.data?.widgets?.filter(
|
const updatedWidgets = selectedDashboard?.data?.widgets?.filter(
|
||||||
@@ -138,9 +140,15 @@ function WidgetGraphComponent({
|
|||||||
setDeleteModal(false);
|
setDeleteModal(false);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
}, [
|
||||||
|
selectedDashboard,
|
||||||
|
widget.id,
|
||||||
|
updateDashboardMutation,
|
||||||
|
setLayouts,
|
||||||
|
setSelectedDashboard,
|
||||||
|
]);
|
||||||
|
|
||||||
const onCloneHandler = async (): Promise<void> => {
|
const onCloneHandler = useCallback(async (): Promise<void> => {
|
||||||
if (!selectedDashboard) return;
|
if (!selectedDashboard) return;
|
||||||
|
|
||||||
const uuid = v4();
|
const uuid = v4();
|
||||||
@@ -204,9 +212,18 @@ function WidgetGraphComponent({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
};
|
}, [
|
||||||
|
selectedDashboard,
|
||||||
|
widget,
|
||||||
|
updateDashboardMutation,
|
||||||
|
setLayouts,
|
||||||
|
setSelectedDashboard,
|
||||||
|
notifications,
|
||||||
|
safeNavigate,
|
||||||
|
pathname,
|
||||||
|
]);
|
||||||
|
|
||||||
const handleOnView = (): void => {
|
const handleOnView = useCallback((): void => {
|
||||||
const queryParams = {
|
const queryParams = {
|
||||||
[QueryParams.expandedWidgetId]: widget.id,
|
[QueryParams.expandedWidgetId]: widget.id,
|
||||||
};
|
};
|
||||||
@@ -225,17 +242,17 @@ function WidgetGraphComponent({
|
|||||||
pathname,
|
pathname,
|
||||||
search: newSearch,
|
search: newSearch,
|
||||||
});
|
});
|
||||||
};
|
}, [widget.id, search, pathname, safeNavigate]);
|
||||||
|
|
||||||
const handleOnDelete = (): void => {
|
const handleOnDelete = useCallback((): void => {
|
||||||
onToggleModal(setDeleteModal);
|
onToggleModal(setDeleteModal);
|
||||||
};
|
}, [onToggleModal]);
|
||||||
|
|
||||||
const onDeleteModelHandler = (): void => {
|
const onDeleteModelHandler = useCallback((): void => {
|
||||||
onToggleModal(setDeleteModal);
|
onToggleModal(setDeleteModal);
|
||||||
};
|
}, [onToggleModal]);
|
||||||
|
|
||||||
const onToggleModelHandler = (): void => {
|
const onToggleModelHandler = useCallback((): void => {
|
||||||
const existingSearchParams = new URLSearchParams(search);
|
const existingSearchParams = new URLSearchParams(search);
|
||||||
existingSearchParams.delete(QueryParams.expandedWidgetId);
|
existingSearchParams.delete(QueryParams.expandedWidgetId);
|
||||||
existingSearchParams.delete(QueryParams.compositeQuery);
|
existingSearchParams.delete(QueryParams.compositeQuery);
|
||||||
@@ -254,63 +271,84 @@ function WidgetGraphComponent({
|
|||||||
pathname,
|
pathname,
|
||||||
search: createQueryParams(updatedQueryParams),
|
search: createQueryParams(updatedQueryParams),
|
||||||
});
|
});
|
||||||
};
|
}, [search, queryResponse.data?.payload, widget.id, pathname, safeNavigate]);
|
||||||
|
|
||||||
const [searchTerm, setSearchTerm] = useState<string>('');
|
const [searchTerm, setSearchTerm] = useState<string>('');
|
||||||
|
|
||||||
|
// Memoize the isButtonEnabled value to prevent recalculation
|
||||||
|
const isGraphClickButtonEnabled = useMemo(
|
||||||
|
() =>
|
||||||
|
(widget?.query?.builder?.queryData &&
|
||||||
|
Array.isArray(widget.query.builder.queryData)
|
||||||
|
? widget.query.builder.queryData
|
||||||
|
: []
|
||||||
|
).some(
|
||||||
|
(q) =>
|
||||||
|
q.dataSource === DataSource.TRACES || q.dataSource === DataSource.LOGS,
|
||||||
|
),
|
||||||
|
[widget?.query?.builder?.queryData],
|
||||||
|
);
|
||||||
|
|
||||||
const graphClick = useGraphClickToShowButton({
|
const graphClick = useGraphClickToShowButton({
|
||||||
graphRef: currentGraphRef?.current ? currentGraphRef : graphRef,
|
graphRef: currentGraphRef?.current ? currentGraphRef : graphRef,
|
||||||
isButtonEnabled: (widget?.query?.builder?.queryData &&
|
isButtonEnabled: isGraphClickButtonEnabled,
|
||||||
Array.isArray(widget.query.builder.queryData)
|
|
||||||
? widget.query.builder.queryData
|
|
||||||
: []
|
|
||||||
).some(
|
|
||||||
(q) =>
|
|
||||||
q.dataSource === DataSource.TRACES || q.dataSource === DataSource.LOGS,
|
|
||||||
),
|
|
||||||
buttonClassName: 'view-onclick-show-button',
|
buttonClassName: 'view-onclick-show-button',
|
||||||
});
|
});
|
||||||
|
|
||||||
const navigateToExplorer = useNavigateToExplorer();
|
const navigateToExplorer = useNavigateToExplorer();
|
||||||
|
|
||||||
const graphClickHandler = (
|
const graphClickHandler = useCallback(
|
||||||
xValue: number,
|
(
|
||||||
yValue: number,
|
xValue: number,
|
||||||
mouseX: number,
|
yValue: number,
|
||||||
mouseY: number,
|
mouseX: number,
|
||||||
metric?: { [key: string]: string },
|
mouseY: number,
|
||||||
queryData?: { queryName: string; inFocusOrNot: boolean },
|
metric?: { [key: string]: string },
|
||||||
): void => {
|
queryData?: { queryName: string; inFocusOrNot: boolean },
|
||||||
const customTracesTimeRange = getCustomTimeRangeWindowSweepInMS(
|
): void => {
|
||||||
|
const customTracesTimeRange = getCustomTimeRangeWindowSweepInMS(
|
||||||
|
customTimeRangeWindowForCoRelation,
|
||||||
|
);
|
||||||
|
const { start, end } = getStartAndEndTimesInMilliseconds(
|
||||||
|
xValue,
|
||||||
|
customTracesTimeRange,
|
||||||
|
);
|
||||||
|
handleGraphClick({
|
||||||
|
xValue,
|
||||||
|
yValue,
|
||||||
|
mouseX,
|
||||||
|
mouseY,
|
||||||
|
metric,
|
||||||
|
queryData,
|
||||||
|
widget,
|
||||||
|
navigateToExplorerPages,
|
||||||
|
navigateToExplorer,
|
||||||
|
notifications,
|
||||||
|
graphClick,
|
||||||
|
...(customTimeRangeWindowForCoRelation
|
||||||
|
? { customTracesTimeRange: { start, end } }
|
||||||
|
: {}),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[
|
||||||
customTimeRangeWindowForCoRelation,
|
customTimeRangeWindowForCoRelation,
|
||||||
);
|
|
||||||
const { start, end } = getStartAndEndTimesInMilliseconds(
|
|
||||||
xValue,
|
|
||||||
customTracesTimeRange,
|
|
||||||
);
|
|
||||||
handleGraphClick({
|
|
||||||
xValue,
|
|
||||||
yValue,
|
|
||||||
mouseX,
|
|
||||||
mouseY,
|
|
||||||
metric,
|
|
||||||
queryData,
|
|
||||||
widget,
|
widget,
|
||||||
navigateToExplorerPages,
|
navigateToExplorerPages,
|
||||||
navigateToExplorer,
|
navigateToExplorer,
|
||||||
notifications,
|
notifications,
|
||||||
graphClick,
|
graphClick,
|
||||||
...(customTimeRangeWindowForCoRelation
|
],
|
||||||
? { customTracesTimeRange: { start, end } }
|
);
|
||||||
: {}),
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const { truncatedText, fullText } = useGetResolvedText({
|
const { truncatedText, fullText } = useGetResolvedText({
|
||||||
text: widget.title as string,
|
text: widget.title as string,
|
||||||
maxLength: 100,
|
maxLength: 100,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Use the provided onClickHandler if available, otherwise use the default graphClickHandler
|
||||||
|
// Both should be stable references due to useCallback
|
||||||
|
const clickHandler = onClickHandler ?? graphClickHandler;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
@@ -366,7 +404,7 @@ function WidgetGraphComponent({
|
|||||||
yAxisUnit={widget.yAxisUnit}
|
yAxisUnit={widget.yAxisUnit}
|
||||||
onToggleModelHandler={onToggleModelHandler}
|
onToggleModelHandler={onToggleModelHandler}
|
||||||
tableProcessedDataRef={tableProcessedDataRef}
|
tableProcessedDataRef={tableProcessedDataRef}
|
||||||
onClickHandler={onClickHandler ?? graphClickHandler}
|
onClickHandler={clickHandler}
|
||||||
customOnDragSelect={customOnDragSelect}
|
customOnDragSelect={customOnDragSelect}
|
||||||
setCurrentGraphRef={setCurrentGraphRef}
|
setCurrentGraphRef={setCurrentGraphRef}
|
||||||
enableDrillDown={
|
enableDrillDown={
|
||||||
@@ -416,7 +454,7 @@ function WidgetGraphComponent({
|
|||||||
setRequestData={setRequestData}
|
setRequestData={setRequestData}
|
||||||
setGraphVisibility={setGraphVisibility}
|
setGraphVisibility={setGraphVisibility}
|
||||||
graphVisibility={graphVisibility}
|
graphVisibility={graphVisibility}
|
||||||
onClickHandler={onClickHandler ?? graphClickHandler}
|
onClickHandler={clickHandler}
|
||||||
onDragSelect={onDragSelect}
|
onDragSelect={onDragSelect}
|
||||||
tableProcessedDataRef={tableProcessedDataRef}
|
tableProcessedDataRef={tableProcessedDataRef}
|
||||||
customTooltipElement={customTooltipElement}
|
customTooltipElement={customTooltipElement}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { timePreferenceType } from 'container/NewWidget/RightContainer/timeItems
|
|||||||
import { getDashboardVariables } from 'lib/dashbaordVariables/getDashboardVariables';
|
import { getDashboardVariables } from 'lib/dashbaordVariables/getDashboardVariables';
|
||||||
import { mapQueryDataFromApi } from 'lib/newQueryBuilder/queryBuilderMappers/mapQueryDataFromApi';
|
import { mapQueryDataFromApi } from 'lib/newQueryBuilder/queryBuilderMappers/mapQueryDataFromApi';
|
||||||
import { useDashboard } from 'providers/Dashboard/Dashboard';
|
import { useDashboard } from 'providers/Dashboard/Dashboard';
|
||||||
import { useCallback, useMemo } from 'react';
|
import { useCallback, useMemo, useRef } from 'react';
|
||||||
import { useMutation } from 'react-query';
|
import { useMutation } from 'react-query';
|
||||||
import { useSelector } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
import { AppState } from 'store/reducers';
|
import { AppState } from 'store/reducers';
|
||||||
@@ -46,6 +46,11 @@ function useUpdatedQuery(): UseUpdatedQueryResult {
|
|||||||
[selectedDashboard],
|
[selectedDashboard],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Use ref to access latest mutateAsync without recreating the callback
|
||||||
|
// queryRangeMutation object recreates on every render, but mutateAsync is stable
|
||||||
|
const mutateAsyncRef = useRef(queryRangeMutation.mutateAsync);
|
||||||
|
mutateAsyncRef.current = queryRangeMutation.mutateAsync;
|
||||||
|
|
||||||
const getUpdatedQuery = useCallback(
|
const getUpdatedQuery = useCallback(
|
||||||
async ({
|
async ({
|
||||||
widgetConfig,
|
widgetConfig,
|
||||||
@@ -63,12 +68,12 @@ function useUpdatedQuery(): UseUpdatedQueryResult {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Execute query and process results
|
// Execute query and process results
|
||||||
const queryResult = await queryRangeMutation.mutateAsync(queryPayload);
|
const queryResult = await mutateAsyncRef.current(queryPayload);
|
||||||
|
|
||||||
// Map query data from API response
|
// Map query data from API response
|
||||||
return mapQueryDataFromApi(queryResult.data.compositeQuery);
|
return mapQueryDataFromApi(queryResult.data.compositeQuery);
|
||||||
},
|
},
|
||||||
[dynamicVariables, globalSelectedInterval, queryRangeMutation],
|
[dynamicVariables, globalSelectedInterval],
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -238,6 +238,86 @@ function External(): JSX.Element {
|
|||||||
setSelectedData,
|
setSelectedData,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const onErrorPercentageClick = useCallback(
|
||||||
|
(
|
||||||
|
xValue: number,
|
||||||
|
yValue: number,
|
||||||
|
mouseX: number,
|
||||||
|
mouseY: number,
|
||||||
|
data: any,
|
||||||
|
): void => {
|
||||||
|
onGraphClickHandler(
|
||||||
|
xValue,
|
||||||
|
yValue,
|
||||||
|
mouseX,
|
||||||
|
mouseY,
|
||||||
|
'external_call_error_percentage',
|
||||||
|
data,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
[onGraphClickHandler],
|
||||||
|
);
|
||||||
|
|
||||||
|
const onDurationClick = useCallback(
|
||||||
|
(
|
||||||
|
xValue: number,
|
||||||
|
yValue: number,
|
||||||
|
mouseX: number,
|
||||||
|
mouseY: number,
|
||||||
|
data: any,
|
||||||
|
): void => {
|
||||||
|
onGraphClickHandler(
|
||||||
|
xValue,
|
||||||
|
yValue,
|
||||||
|
mouseX,
|
||||||
|
mouseY,
|
||||||
|
'external_call_duration',
|
||||||
|
data,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
[onGraphClickHandler],
|
||||||
|
);
|
||||||
|
|
||||||
|
const onRPSByAddressClick = useCallback(
|
||||||
|
(
|
||||||
|
xValue: number,
|
||||||
|
yValue: number,
|
||||||
|
mouseX: number,
|
||||||
|
mouseY: number,
|
||||||
|
data: any,
|
||||||
|
): void => {
|
||||||
|
onGraphClickHandler(
|
||||||
|
xValue,
|
||||||
|
yValue,
|
||||||
|
mouseX,
|
||||||
|
mouseY,
|
||||||
|
'external_call_rps_by_address',
|
||||||
|
data,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
[onGraphClickHandler],
|
||||||
|
);
|
||||||
|
|
||||||
|
const onDurationByAddressClick = useCallback(
|
||||||
|
(
|
||||||
|
xValue: number,
|
||||||
|
yValue: number,
|
||||||
|
mouseX: number,
|
||||||
|
mouseY: number,
|
||||||
|
data: any,
|
||||||
|
): void => {
|
||||||
|
onGraphClickHandler(
|
||||||
|
xValue,
|
||||||
|
yValue,
|
||||||
|
mouseX,
|
||||||
|
mouseY,
|
||||||
|
'external_call_duration_by_address',
|
||||||
|
data,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
[onGraphClickHandler],
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Row gutter={24}>
|
<Row gutter={24}>
|
||||||
@@ -266,16 +346,7 @@ function External(): JSX.Element {
|
|||||||
<Graph
|
<Graph
|
||||||
headerMenuList={MENU_ITEMS}
|
headerMenuList={MENU_ITEMS}
|
||||||
widget={externalCallErrorWidget}
|
widget={externalCallErrorWidget}
|
||||||
onClickHandler={(xValue, yValue, mouseX, mouseY, data): void => {
|
onClickHandler={onErrorPercentageClick}
|
||||||
onGraphClickHandler(
|
|
||||||
xValue,
|
|
||||||
yValue,
|
|
||||||
mouseX,
|
|
||||||
mouseY,
|
|
||||||
'external_call_error_percentage',
|
|
||||||
data,
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
onDragSelect={onDragSelect}
|
onDragSelect={onDragSelect}
|
||||||
version={ENTITY_VERSION_V4}
|
version={ENTITY_VERSION_V4}
|
||||||
/>
|
/>
|
||||||
@@ -309,16 +380,7 @@ function External(): JSX.Element {
|
|||||||
<Graph
|
<Graph
|
||||||
headerMenuList={MENU_ITEMS}
|
headerMenuList={MENU_ITEMS}
|
||||||
widget={externalCallDurationWidget}
|
widget={externalCallDurationWidget}
|
||||||
onClickHandler={(xValue, yValue, mouseX, mouseY, data): void => {
|
onClickHandler={onDurationClick}
|
||||||
onGraphClickHandler(
|
|
||||||
xValue,
|
|
||||||
yValue,
|
|
||||||
mouseX,
|
|
||||||
mouseY,
|
|
||||||
'external_call_duration',
|
|
||||||
data,
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
onDragSelect={onDragSelect}
|
onDragSelect={onDragSelect}
|
||||||
version={ENTITY_VERSION_V4}
|
version={ENTITY_VERSION_V4}
|
||||||
/>
|
/>
|
||||||
@@ -353,16 +415,7 @@ function External(): JSX.Element {
|
|||||||
<Graph
|
<Graph
|
||||||
widget={externalCallRPSWidget}
|
widget={externalCallRPSWidget}
|
||||||
headerMenuList={MENU_ITEMS}
|
headerMenuList={MENU_ITEMS}
|
||||||
onClickHandler={(xValue, yValue, mouseX, mouseY, data): Promise<void> =>
|
onClickHandler={onRPSByAddressClick}
|
||||||
onGraphClickHandler(
|
|
||||||
xValue,
|
|
||||||
yValue,
|
|
||||||
mouseX,
|
|
||||||
mouseY,
|
|
||||||
'external_call_rps_by_address',
|
|
||||||
data,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
onDragSelect={onDragSelect}
|
onDragSelect={onDragSelect}
|
||||||
version={ENTITY_VERSION_V4}
|
version={ENTITY_VERSION_V4}
|
||||||
/>
|
/>
|
||||||
@@ -396,16 +449,7 @@ function External(): JSX.Element {
|
|||||||
<Graph
|
<Graph
|
||||||
widget={externalCallDurationAddressWidget}
|
widget={externalCallDurationAddressWidget}
|
||||||
headerMenuList={MENU_ITEMS}
|
headerMenuList={MENU_ITEMS}
|
||||||
onClickHandler={(xValue, yValue, mouseX, mouseY, data): void => {
|
onClickHandler={onDurationByAddressClick}
|
||||||
onGraphClickHandler(
|
|
||||||
xValue,
|
|
||||||
yValue,
|
|
||||||
mouseX,
|
|
||||||
mouseY,
|
|
||||||
'external_call_duration_by_address',
|
|
||||||
data,
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
onDragSelect={onDragSelect}
|
onDragSelect={onDragSelect}
|
||||||
version={ENTITY_VERSION_V4}
|
version={ENTITY_VERSION_V4}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { FC } from 'react';
|
import isEqual from 'lodash-es/isEqual';
|
||||||
|
import { FC, memo } from 'react';
|
||||||
|
|
||||||
import { PanelTypeVsPanelWrapper } from './constants';
|
import { PanelTypeVsPanelWrapper } from './constants';
|
||||||
import { PanelWrapperProps } from './panelWrapper.types';
|
import { PanelWrapperProps } from './panelWrapper.types';
|
||||||
@@ -55,4 +56,36 @@ function PanelWrapper({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default PanelWrapper;
|
function arePropsEqual(
|
||||||
|
prevProps: PanelWrapperProps,
|
||||||
|
nextProps: PanelWrapperProps,
|
||||||
|
): boolean {
|
||||||
|
// Destructure to separate props that need deep comparison from the rest
|
||||||
|
const {
|
||||||
|
widget: prevWidget,
|
||||||
|
queryResponse: prevQueryResponse,
|
||||||
|
...prevRest
|
||||||
|
} = prevProps;
|
||||||
|
const {
|
||||||
|
widget: nextWidget,
|
||||||
|
queryResponse: nextQueryResponse,
|
||||||
|
...nextRest
|
||||||
|
} = nextProps;
|
||||||
|
|
||||||
|
// Shallow equality check for all other props (primitives, functions, refs, arrays)
|
||||||
|
const restKeys = Object.keys(prevRest) as Array<
|
||||||
|
keyof Omit<PanelWrapperProps, 'widget' | 'queryResponse'>
|
||||||
|
>;
|
||||||
|
|
||||||
|
if (restKeys.some((key) => prevRest[key] !== nextRest[key])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deep equality only for widget config and query response data payload
|
||||||
|
return (
|
||||||
|
isEqual(prevWidget, nextWidget) &&
|
||||||
|
isEqual(prevQueryResponse.data?.payload, nextQueryResponse.data?.payload)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default memo(PanelWrapper, arePropsEqual);
|
||||||
|
|||||||
@@ -132,11 +132,21 @@ function UplotPanelWrapper({
|
|||||||
[selectedGraph, widget?.panelTypes, widget?.stackedBarChart],
|
[selectedGraph, widget?.panelTypes, widget?.stackedBarChart],
|
||||||
);
|
);
|
||||||
|
|
||||||
const chartData = getUPlotChartData(
|
// Memoize chartData to prevent unnecessary recalculations
|
||||||
queryResponse?.data?.payload,
|
const chartData = useMemo(
|
||||||
widget.fillSpans,
|
() =>
|
||||||
stackedBarChart,
|
getUPlotChartData(
|
||||||
hiddenGraph,
|
queryResponse?.data?.payload,
|
||||||
|
widget.fillSpans,
|
||||||
|
stackedBarChart,
|
||||||
|
hiddenGraph,
|
||||||
|
),
|
||||||
|
[
|
||||||
|
queryResponse?.data?.payload,
|
||||||
|
widget.fillSpans,
|
||||||
|
stackedBarChart,
|
||||||
|
hiddenGraph,
|
||||||
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@@ -77,6 +77,20 @@ function MessagingQueuesGraph(): JSX.Element {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onClickHandler = useCallback(
|
||||||
|
(
|
||||||
|
xValue: number,
|
||||||
|
_yValue: number,
|
||||||
|
_mouseX: number,
|
||||||
|
_mouseY: number,
|
||||||
|
data?: any,
|
||||||
|
): void => {
|
||||||
|
setSelectedTimelineQuery(urlQuery, xValue, location, history, data);
|
||||||
|
},
|
||||||
|
[urlQuery, location, history],
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card
|
<Card
|
||||||
isDarkMode={isDarkMode}
|
isDarkMode={isDarkMode}
|
||||||
@@ -86,9 +100,7 @@ function MessagingQueuesGraph(): JSX.Element {
|
|||||||
<GridCard
|
<GridCard
|
||||||
widget={widgetData}
|
widget={widgetData}
|
||||||
headerMenuList={[...ViewMenuAction]}
|
headerMenuList={[...ViewMenuAction]}
|
||||||
onClickHandler={(xValue, _yValue, _mouseX, _mouseY, data): void => {
|
onClickHandler={onClickHandler}
|
||||||
setSelectedTimelineQuery(urlQuery, xValue, location, history, data);
|
|
||||||
}}
|
|
||||||
onDragSelect={onDragSelect}
|
onDragSelect={onDragSelect}
|
||||||
customTooltipElement={messagingQueueCustomTooltipText()}
|
customTooltipElement={messagingQueueCustomTooltipText()}
|
||||||
dataAvailable={checkIfDataExists}
|
dataAvailable={checkIfDataExists}
|
||||||
|
|||||||
Reference in New Issue
Block a user