mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-12 00:38:59 +08:00
chore: added mq celery analytics (#7129)
This commit is contained in:
parent
a6cfb63036
commit
5a107f33f2
@ -2,6 +2,7 @@ import './CeleryTaskDetail.style.scss';
|
|||||||
|
|
||||||
import { Color, Spacing } from '@signozhq/design-tokens';
|
import { Color, Spacing } from '@signozhq/design-tokens';
|
||||||
import { Divider, Drawer, Typography } from 'antd';
|
import { Divider, Drawer, Typography } from 'antd';
|
||||||
|
import logEvent from 'api/common/logEvent';
|
||||||
import { PANEL_TYPES } from 'constants/queryBuilder';
|
import { PANEL_TYPES } from 'constants/queryBuilder';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import { useIsDarkMode } from 'hooks/useDarkMode';
|
import { useIsDarkMode } from 'hooks/useDarkMode';
|
||||||
@ -98,6 +99,12 @@ export default function CeleryTaskDetail({
|
|||||||
...rowData,
|
...rowData,
|
||||||
[taskData.entity]: taskData.value,
|
[taskData.entity]: taskData.value,
|
||||||
});
|
});
|
||||||
|
logEvent('MQ Celery: navigation to trace page', {
|
||||||
|
filters,
|
||||||
|
startTime,
|
||||||
|
endTime,
|
||||||
|
source: widgetData.title,
|
||||||
|
});
|
||||||
navigateToTrace(filters, startTime, endTime);
|
navigateToTrace(filters, startTime, endTime);
|
||||||
}}
|
}}
|
||||||
start={startTime}
|
start={startTime}
|
||||||
|
@ -42,10 +42,12 @@ import {
|
|||||||
function CeleryTaskBar({
|
function CeleryTaskBar({
|
||||||
onClick,
|
onClick,
|
||||||
queryEnabled,
|
queryEnabled,
|
||||||
|
checkIfDataExists,
|
||||||
}: {
|
}: {
|
||||||
onClick?: (task: CaptureDataProps) => void;
|
onClick?: (task: CaptureDataProps) => void;
|
||||||
|
|
||||||
queryEnabled: boolean;
|
queryEnabled: boolean;
|
||||||
|
checkIfDataExists?: (isDataAvailable: boolean) => void;
|
||||||
}): JSX.Element {
|
}): JSX.Element {
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
const { pathname } = useLocation();
|
const { pathname } = useLocation();
|
||||||
@ -187,6 +189,7 @@ function CeleryTaskBar({
|
|||||||
onGraphClick(celerySlowestTasksTableWidgetData, ...args)
|
onGraphClick(celerySlowestTasksTableWidgetData, ...args)
|
||||||
}
|
}
|
||||||
customSeries={getCustomSeries}
|
customSeries={getCustomSeries}
|
||||||
|
dataAvailable={checkIfDataExists}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{barState === CeleryTaskState.Failed && (
|
{barState === CeleryTaskState.Failed && (
|
||||||
@ -232,6 +235,7 @@ function CeleryTaskBar({
|
|||||||
|
|
||||||
CeleryTaskBar.defaultProps = {
|
CeleryTaskBar.defaultProps = {
|
||||||
onClick: (): void => {},
|
onClick: (): void => {},
|
||||||
|
checkIfDataExists: undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default CeleryTaskBar;
|
export default CeleryTaskBar;
|
||||||
|
@ -35,6 +35,8 @@ function CeleryTaskGraph({
|
|||||||
customErrorMessage,
|
customErrorMessage,
|
||||||
start,
|
start,
|
||||||
end,
|
end,
|
||||||
|
checkIfDataExists,
|
||||||
|
analyticsEvent,
|
||||||
}: {
|
}: {
|
||||||
widgetData: Widgets;
|
widgetData: Widgets;
|
||||||
onClick?: (task: CaptureDataProps) => void;
|
onClick?: (task: CaptureDataProps) => void;
|
||||||
@ -48,6 +50,8 @@ function CeleryTaskGraph({
|
|||||||
customErrorMessage?: string;
|
customErrorMessage?: string;
|
||||||
start?: number;
|
start?: number;
|
||||||
end?: number;
|
end?: number;
|
||||||
|
checkIfDataExists?: (isDataAvailable: boolean) => void;
|
||||||
|
analyticsEvent?: string;
|
||||||
}): JSX.Element {
|
}): JSX.Element {
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
const { pathname } = useLocation();
|
const { pathname } = useLocation();
|
||||||
@ -125,6 +129,8 @@ function CeleryTaskGraph({
|
|||||||
customErrorMessage={customErrorMessage}
|
customErrorMessage={customErrorMessage}
|
||||||
start={start}
|
start={start}
|
||||||
end={end}
|
end={end}
|
||||||
|
dataAvailable={checkIfDataExists}
|
||||||
|
analyticsEvent={analyticsEvent}
|
||||||
/>
|
/>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
@ -141,6 +147,8 @@ CeleryTaskGraph.defaultProps = {
|
|||||||
customErrorMessage: undefined,
|
customErrorMessage: undefined,
|
||||||
start: undefined,
|
start: undefined,
|
||||||
end: undefined,
|
end: undefined,
|
||||||
|
checkIfDataExists: undefined,
|
||||||
|
analyticsEvent: undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default CeleryTaskGraph;
|
export default CeleryTaskGraph;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import './CeleryTaskGraph.style.scss';
|
import './CeleryTaskGraph.style.scss';
|
||||||
|
|
||||||
import { Card, Typography } from 'antd';
|
import { Card, Typography } from 'antd';
|
||||||
|
import logEvent from 'api/common/logEvent';
|
||||||
import { CardContainer } from 'container/GridCardLayout/styles';
|
import { CardContainer } from 'container/GridCardLayout/styles';
|
||||||
import { useIsDarkMode } from 'hooks/useDarkMode';
|
import { useIsDarkMode } from 'hooks/useDarkMode';
|
||||||
import { ChevronDown, ChevronUp } from 'lucide-react';
|
import { ChevronDown, ChevronUp } from 'lucide-react';
|
||||||
@ -92,6 +93,15 @@ export default function CeleryTaskGraphGrid({
|
|||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const checkIfDataExists = (isDataAvailable: boolean, title: string): void => {
|
||||||
|
if (isDataAvailable) {
|
||||||
|
logEvent(`MQ Celery: ${title} data exists`, {
|
||||||
|
graph: title,
|
||||||
|
isDataAvailable,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="celery-task-graph-grid-container">
|
<div className="celery-task-graph-grid-container">
|
||||||
<div className="metric-based-graphs">
|
<div className="metric-based-graphs">
|
||||||
@ -124,6 +134,10 @@ export default function CeleryTaskGraphGrid({
|
|||||||
widgetData={celeryActiveTasksData}
|
widgetData={celeryActiveTasksData}
|
||||||
queryEnabled={queryEnabled}
|
queryEnabled={queryEnabled}
|
||||||
customErrorMessage="Enable Flower metrics to view this graph"
|
customErrorMessage="Enable Flower metrics to view this graph"
|
||||||
|
checkIfDataExists={(isDataAvailable): void =>
|
||||||
|
checkIfDataExists(isDataAvailable, 'Active Tasks by worker')
|
||||||
|
}
|
||||||
|
analyticsEvent="MQ Celery: Flower metric not enabled"
|
||||||
/>
|
/>
|
||||||
<Card className="celery-task-graph-worker-count">
|
<Card className="celery-task-graph-worker-count">
|
||||||
<div className="worker-count-header">
|
<div className="worker-count-header">
|
||||||
@ -173,8 +187,19 @@ export default function CeleryTaskGraphGrid({
|
|||||||
</div>
|
</div>
|
||||||
{!collapsedSections.traceBasedGraphs && (
|
{!collapsedSections.traceBasedGraphs && (
|
||||||
<>
|
<>
|
||||||
<CeleryTaskBar queryEnabled={queryEnabled} onClick={onClick} />
|
<CeleryTaskBar
|
||||||
<CeleryTaskLatencyGraph queryEnabled={queryEnabled} />
|
queryEnabled={queryEnabled}
|
||||||
|
onClick={onClick}
|
||||||
|
checkIfDataExists={(isDataAvailable): void =>
|
||||||
|
checkIfDataExists(isDataAvailable, 'State Graph')
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<CeleryTaskLatencyGraph
|
||||||
|
queryEnabled={queryEnabled}
|
||||||
|
checkIfDataExists={(isDataAvailable): void =>
|
||||||
|
checkIfDataExists(isDataAvailable, 'Task Latency')
|
||||||
|
}
|
||||||
|
/>
|
||||||
<div className="celery-task-graph-grid-bottom">
|
<div className="celery-task-graph-grid-bottom">
|
||||||
{bottomWidgetData.map((widgetData, index) => (
|
{bottomWidgetData.map((widgetData, index) => (
|
||||||
<CeleryTaskGraph
|
<CeleryTaskGraph
|
||||||
@ -184,6 +209,9 @@ export default function CeleryTaskGraphGrid({
|
|||||||
queryEnabled={queryEnabled}
|
queryEnabled={queryEnabled}
|
||||||
rightPanelTitle={rightPanelTitle[index]}
|
rightPanelTitle={rightPanelTitle[index]}
|
||||||
applyCeleryTaskFilter
|
applyCeleryTaskFilter
|
||||||
|
checkIfDataExists={(isDataAvailable): void =>
|
||||||
|
checkIfDataExists(isDataAvailable, rightPanelTitle[index])
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import './CeleryTaskGraph.style.scss';
|
import './CeleryTaskGraph.style.scss';
|
||||||
|
|
||||||
import { Col, Row } from 'antd';
|
import { Col, Row } from 'antd';
|
||||||
|
import logEvent from 'api/common/logEvent';
|
||||||
import { QueryParams } from 'constants/query';
|
import { QueryParams } from 'constants/query';
|
||||||
import { PANEL_TYPES } from 'constants/queryBuilder';
|
import { PANEL_TYPES } from 'constants/queryBuilder';
|
||||||
import { ViewMenuAction } from 'container/GridCardLayout/config';
|
import { ViewMenuAction } from 'container/GridCardLayout/config';
|
||||||
@ -40,8 +41,10 @@ export enum CeleryTaskGraphState {
|
|||||||
|
|
||||||
function CeleryTaskLatencyGraph({
|
function CeleryTaskLatencyGraph({
|
||||||
queryEnabled,
|
queryEnabled,
|
||||||
|
checkIfDataExists,
|
||||||
}: {
|
}: {
|
||||||
queryEnabled: boolean;
|
queryEnabled: boolean;
|
||||||
|
checkIfDataExists?: (isDataAvailable: boolean) => void;
|
||||||
}): JSX.Element {
|
}): JSX.Element {
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
const { pathname } = useLocation();
|
const { pathname } = useLocation();
|
||||||
@ -61,6 +64,10 @@ function CeleryTaskLatencyGraph({
|
|||||||
|
|
||||||
const handleTabClick = (key: CeleryTaskGraphState): void => {
|
const handleTabClick = (key: CeleryTaskGraphState): void => {
|
||||||
setGraphState(key as CeleryTaskGraphState);
|
setGraphState(key as CeleryTaskGraphState);
|
||||||
|
logEvent('MQ Celery: Task latency graph tab clicked', {
|
||||||
|
taskName: urlQuery.get(QueryParams.taskName),
|
||||||
|
graphState: key,
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const onDragSelect = useCallback(
|
const onDragSelect = useCallback(
|
||||||
@ -195,6 +202,7 @@ function CeleryTaskLatencyGraph({
|
|||||||
onDragSelect={onDragSelect}
|
onDragSelect={onDragSelect}
|
||||||
onClickHandler={onGraphClick('Celery_p99_latency')}
|
onClickHandler={onGraphClick('Celery_p99_latency')}
|
||||||
isQueryEnabled={queryEnabled}
|
isQueryEnabled={queryEnabled}
|
||||||
|
dataAvailable={checkIfDataExists}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
@ -215,6 +223,7 @@ function CeleryTaskLatencyGraph({
|
|||||||
onDragSelect={onDragSelect}
|
onDragSelect={onDragSelect}
|
||||||
onClickHandler={onGraphClick('Celery_p95_latency')}
|
onClickHandler={onGraphClick('Celery_p95_latency')}
|
||||||
isQueryEnabled={queryEnabled}
|
isQueryEnabled={queryEnabled}
|
||||||
|
dataAvailable={checkIfDataExists}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
@ -234,6 +243,7 @@ function CeleryTaskLatencyGraph({
|
|||||||
onDragSelect={onDragSelect}
|
onDragSelect={onDragSelect}
|
||||||
onClickHandler={onGraphClick('Celery_p90_latency')}
|
onClickHandler={onGraphClick('Celery_p90_latency')}
|
||||||
isQueryEnabled={queryEnabled}
|
isQueryEnabled={queryEnabled}
|
||||||
|
dataAvailable={checkIfDataExists}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
@ -243,3 +253,7 @@ function CeleryTaskLatencyGraph({
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default CeleryTaskLatencyGraph;
|
export default CeleryTaskLatencyGraph;
|
||||||
|
|
||||||
|
CeleryTaskLatencyGraph.defaultProps = {
|
||||||
|
checkIfDataExists: undefined,
|
||||||
|
};
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
import './CeleryTaskGraph.style.scss';
|
import './CeleryTaskGraph.style.scss';
|
||||||
|
|
||||||
import { Col, Row } from 'antd';
|
import { Col, Row } from 'antd';
|
||||||
|
import logEvent from 'api/common/logEvent';
|
||||||
import { QueryParams } from 'constants/query';
|
import { QueryParams } from 'constants/query';
|
||||||
import useUrlQuery from 'hooks/useUrlQuery';
|
import useUrlQuery from 'hooks/useUrlQuery';
|
||||||
import { Dispatch, SetStateAction, useMemo } from 'react';
|
import { Dispatch, SetStateAction, useMemo } from 'react';
|
||||||
@ -44,12 +45,16 @@ function CeleryTaskStateGraphConfig({
|
|||||||
{ label: 'Successful', key: CeleryTaskState.Successful },
|
{ label: 'Successful', key: CeleryTaskState.Successful },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const urlQuery = useUrlQuery();
|
||||||
|
|
||||||
const handleTabClick = (key: CeleryTaskState): void => {
|
const handleTabClick = (key: CeleryTaskState): void => {
|
||||||
setBarState(key as CeleryTaskState);
|
setBarState(key as CeleryTaskState);
|
||||||
|
logEvent('MQ Celery: State graph tab clicked', {
|
||||||
|
taskName: urlQuery.get(QueryParams.taskName),
|
||||||
|
graphState: key,
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const urlQuery = useUrlQuery();
|
|
||||||
|
|
||||||
const selectedFilters = useMemo(
|
const selectedFilters = useMemo(
|
||||||
() =>
|
() =>
|
||||||
getFiltersFromQueryParams(
|
getFiltersFromQueryParams(
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import logEvent from 'api/common/logEvent';
|
||||||
import { DEFAULT_ENTITY_VERSION } from 'constants/app';
|
import { DEFAULT_ENTITY_VERSION } from 'constants/app';
|
||||||
import { QueryParams } from 'constants/query';
|
import { QueryParams } from 'constants/query';
|
||||||
import { PANEL_TYPES } from 'constants/queryBuilder';
|
import { PANEL_TYPES } from 'constants/queryBuilder';
|
||||||
@ -44,6 +45,7 @@ function GridCardGraph({
|
|||||||
customErrorMessage,
|
customErrorMessage,
|
||||||
start,
|
start,
|
||||||
end,
|
end,
|
||||||
|
analyticsEvent,
|
||||||
}: GridCardGraphProps): JSX.Element {
|
}: GridCardGraphProps): JSX.Element {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const [errorMessage, setErrorMessage] = useState<string>();
|
const [errorMessage, setErrorMessage] = useState<string>();
|
||||||
@ -219,6 +221,11 @@ function GridCardGraph({
|
|||||||
setIsInternalServerError(
|
setIsInternalServerError(
|
||||||
String(error.message).includes('API responded with 500'),
|
String(error.message).includes('API responded with 500'),
|
||||||
);
|
);
|
||||||
|
if (analyticsEvent) {
|
||||||
|
logEvent(analyticsEvent, {
|
||||||
|
error: error.message,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
setDashboardQueryRangeCalled(true);
|
setDashboardQueryRangeCalled(true);
|
||||||
},
|
},
|
||||||
@ -283,6 +290,7 @@ GridCardGraph.defaultProps = {
|
|||||||
threshold: undefined,
|
threshold: undefined,
|
||||||
headerMenuList: [MenuItemKeys.View],
|
headerMenuList: [MenuItemKeys.View],
|
||||||
version: 'v3',
|
version: 'v3',
|
||||||
|
analyticsEvent: undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default memo(GridCardGraph);
|
export default memo(GridCardGraph);
|
||||||
|
@ -58,6 +58,7 @@ export interface GridCardGraphProps {
|
|||||||
customErrorMessage?: string;
|
customErrorMessage?: string;
|
||||||
start?: number;
|
start?: number;
|
||||||
end?: number;
|
end?: number;
|
||||||
|
analyticsEvent?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GetGraphVisibilityStateOnLegendClickProps {
|
export interface GetGraphVisibilityStateOnLegendClickProps {
|
||||||
|
@ -1,15 +1,30 @@
|
|||||||
import './CeleryTask.styles.scss';
|
import './CeleryTask.styles.scss';
|
||||||
|
|
||||||
|
import logEvent from 'api/common/logEvent';
|
||||||
import CeleryTaskConfigOptions from 'components/CeleryTask/CeleryTaskConfigOptions/CeleryTaskConfigOptions';
|
import CeleryTaskConfigOptions from 'components/CeleryTask/CeleryTaskConfigOptions/CeleryTaskConfigOptions';
|
||||||
import CeleryTaskDetail, {
|
import CeleryTaskDetail, {
|
||||||
CaptureDataProps,
|
CaptureDataProps,
|
||||||
} from 'components/CeleryTask/CeleryTaskDetail/CeleryTaskDetail';
|
} from 'components/CeleryTask/CeleryTaskDetail/CeleryTaskDetail';
|
||||||
import CeleryTaskGraphGrid from 'components/CeleryTask/CeleryTaskGraph/CeleryTaskGraphGrid';
|
import CeleryTaskGraphGrid from 'components/CeleryTask/CeleryTaskGraph/CeleryTaskGraphGrid';
|
||||||
|
import { QueryParams } from 'constants/query';
|
||||||
import DateTimeSelectionV2 from 'container/TopNav/DateTimeSelectionV2';
|
import DateTimeSelectionV2 from 'container/TopNav/DateTimeSelectionV2';
|
||||||
import { useState } from 'react';
|
import useUrlQuery from 'hooks/useUrlQuery';
|
||||||
|
import { useEffect, useRef, useState } from 'react';
|
||||||
|
|
||||||
export default function CeleryTask(): JSX.Element {
|
export default function CeleryTask(): JSX.Element {
|
||||||
const [task, setTask] = useState<CaptureDataProps | null>(null);
|
const [task, setTask] = useState<CaptureDataProps | null>(null);
|
||||||
|
const loggedRef = useRef(false);
|
||||||
|
|
||||||
|
const taskName = useUrlQuery().get(QueryParams.taskName);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (taskName && !loggedRef.current) {
|
||||||
|
logEvent('MQ Celery: Task name filter', {
|
||||||
|
taskName,
|
||||||
|
});
|
||||||
|
loggedRef.current = true;
|
||||||
|
}
|
||||||
|
}, [taskName]);
|
||||||
|
|
||||||
const onTaskClick = (captureData: CaptureDataProps): void => {
|
const onTaskClick = (captureData: CaptureDataProps): void => {
|
||||||
setTask(captureData);
|
setTask(captureData);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user