chore: added kakfa analytics (#7127)

This commit is contained in:
SagarRajput-7 2025-02-17 15:04:57 +05:30 committed by GitHub
parent e86c7c970a
commit 1f52139ed3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 113 additions and 5 deletions

View File

@ -2,6 +2,7 @@
import '../MQDetails.style.scss'; import '../MQDetails.style.scss';
import { Table, Typography } from 'antd'; import { Table, Typography } from 'antd';
import logEvent from 'api/common/logEvent';
import { MessagingQueueServicePayload } from 'api/messagingQueues/getConsumerLagDetails'; import { MessagingQueueServicePayload } from 'api/messagingQueues/getConsumerLagDetails';
import { getKafkaSpanEval } from 'api/messagingQueues/getKafkaSpanEval'; import { getKafkaSpanEval } from 'api/messagingQueues/getKafkaSpanEval';
import axios from 'axios'; import axios from 'axios';
@ -15,7 +16,7 @@ import {
MessagingQueuesViewType, MessagingQueuesViewType,
RowData, RowData,
} from 'pages/MessagingQueues/MessagingQueuesUtils'; } from 'pages/MessagingQueues/MessagingQueuesUtils';
import { useEffect, useMemo, useState } from 'react'; import { useEffect, useMemo, useRef, useState } 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';
@ -93,6 +94,9 @@ export function getColumns(
className="traceid-text" className="traceid-text"
onClick={(): void => { onClick={(): void => {
window.open(`${ROUTES.TRACE}/${item}`, '_blank'); window.open(`${ROUTES.TRACE}/${item}`, '_blank');
logEvent(`MQ Kafka: Drop Rate - traceid navigation`, {
item,
});
}} }}
> >
{item} {item}
@ -227,6 +231,22 @@ function DropRateView(): JSX.Element {
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [minTime, maxTime, evaluationTime]); }, [minTime, maxTime, evaluationTime]);
const prevTableDataRef = useRef<string>();
useEffect(() => {
if (tableData.length > 0) {
const currentTableData = JSON.stringify(tableData);
if (currentTableData !== prevTableDataRef.current) {
logEvent(`MQ Kafka: Drop Rate View`, {
dataRender: tableData.length,
});
prevTableDataRef.current = currentTableData;
}
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [JSON.stringify(tableData)]);
return ( return (
<div className={cx('mq-overview-container', 'droprate-view')}> <div className={cx('mq-overview-container', 'droprate-view')}>
<div className="mq-overview-title"> <div className="mq-overview-title">

View File

@ -3,6 +3,7 @@
import './MQTables.styles.scss'; import './MQTables.styles.scss';
import { Skeleton, Table, Typography } from 'antd'; import { Skeleton, Table, Typography } from 'antd';
import logEvent from 'api/common/logEvent';
import { import {
MessagingQueueServicePayload, MessagingQueueServicePayload,
MessagingQueuesPayloadProps, MessagingQueuesPayloadProps,
@ -23,11 +24,12 @@ import {
MessagingQueueServiceDetailType, MessagingQueueServiceDetailType,
MessagingQueuesViewType, MessagingQueuesViewType,
MessagingQueuesViewTypeOptions, MessagingQueuesViewTypeOptions,
ProducerLatencyOptions,
RowData, RowData,
SelectedTimelineQuery, SelectedTimelineQuery,
setConfigDetail, setConfigDetail,
} from 'pages/MessagingQueues/MessagingQueuesUtils'; } from 'pages/MessagingQueues/MessagingQueuesUtils';
import { useEffect, useMemo, useState } from 'react'; import { useEffect, useMemo, useRef, useState } from 'react';
import { useMutation } from 'react-query'; import { useMutation } from 'react-query';
import { useHistory, useLocation } from 'react-router-dom'; import { useHistory, useLocation } from 'react-router-dom';
import { ErrorResponse, SuccessResponse } from 'types/api'; import { ErrorResponse, SuccessResponse } from 'types/api';
@ -130,6 +132,7 @@ function MessagingQueuesTable({
tableApi, tableApi,
validConfigPresent = false, validConfigPresent = false,
type = 'Detail', type = 'Detail',
option = ProducerLatencyOptions.Producers,
}: { }: {
currentTab?: MessagingQueueServiceDetailType; currentTab?: MessagingQueueServiceDetailType;
selectedView: MessagingQueuesViewTypeOptions; selectedView: MessagingQueuesViewTypeOptions;
@ -141,6 +144,7 @@ function MessagingQueuesTable({
>; >;
validConfigPresent?: boolean; validConfigPresent?: boolean;
type?: 'Detail' | 'Overview'; type?: 'Detail' | 'Overview';
option?: ProducerLatencyOptions;
}): JSX.Element { }): JSX.Element {
const [columns, setColumns] = useState<any[]>([]); const [columns, setColumns] = useState<any[]>([]);
const [tableData, setTableData] = useState<any[]>([]); const [tableData, setTableData] = useState<any[]>([]);
@ -262,6 +266,43 @@ function MessagingQueuesTable({
configDetailQueryData?.topic || '' configDetailQueryData?.topic || ''
} ${configDetailQueryData?.partition || ''}`; } ${configDetailQueryData?.partition || ''}`;
const prevTableDataRef = useRef<string>();
useEffect(() => {
if (tableData.length > 0 && type === 'Overview') {
const currentTableData = JSON.stringify(tableData);
if (currentTableData !== prevTableDataRef.current) {
logEvent(`MQ Kafka: ${MessagingQueuesViewType[selectedView].label}`, {
dataRender: tableData.length,
});
prevTableDataRef.current = currentTableData;
}
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [option, JSON.stringify(tableData), selectedView]);
useEffect(() => {
if (tableData.length > 0 && type === 'Detail') {
const currentTableData = JSON.stringify(tableData);
if (currentTableData !== prevTableDataRef.current) {
logEvent(
`MQ Kafka: ${MessagingQueuesViewType[selectedView].label} - details`,
{
dataRender: tableData.length,
activeTab: currentTab,
topic: configDetailQueryData?.topic,
partition: configDetailQueryData?.partition,
serviceName: configDetailQueryData?.service_name,
},
);
prevTableDataRef.current = currentTableData;
}
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [currentTab, JSON.stringify(tableData), selectedView]);
return ( return (
<div className="mq-tables-container"> <div className="mq-tables-container">
{!validConfigPresent ? ( {!validConfigPresent ? (

View File

@ -112,6 +112,7 @@ function MessagingQueueOverview({
tableApi={getTableApi(selectedView)} tableApi={getTableApi(selectedView)}
validConfigPresent validConfigPresent
type="Overview" type="Overview"
option={option}
/> />
</div> </div>
); );

View File

@ -26,12 +26,14 @@ interface MetricSectionProps {
title: string; title: string;
description: string; description: string;
graphCount: Widgets[]; graphCount: Widgets[];
checkIfDataExists?: (isDataAvailable: boolean) => void;
} }
function MetricSection({ function MetricSection({
title, title,
description, description,
graphCount, graphCount,
checkIfDataExists,
}: MetricSectionProps): JSX.Element { }: MetricSectionProps): JSX.Element {
const isDarkMode = useIsDarkMode(); const isDarkMode = useIsDarkMode();
@ -50,6 +52,7 @@ function MetricSection({
<MetricPageGridGraph <MetricPageGridGraph
key={`graph-${widgetData.id}`} key={`graph-${widgetData.id}`}
widgetData={widgetData} widgetData={widgetData}
checkIfDataExists={checkIfDataExists}
/> />
))} ))}
</div> </div>
@ -57,7 +60,15 @@ function MetricSection({
); );
} }
function MetricColumnGraphs(): JSX.Element { MetricSection.defaultProps = {
checkIfDataExists: (): void => {},
};
function MetricColumnGraphs({
checkIfDataExists,
}: {
checkIfDataExists: (isDataAvailable: boolean) => void;
}): JSX.Element {
const { t } = useTranslation('messagingQueues'); const { t } = useTranslation('messagingQueues');
const metricsData = [ const metricsData = [
@ -106,6 +117,7 @@ function MetricColumnGraphs(): JSX.Element {
title={metric.title} title={metric.title}
description={metric.description} description={metric.description}
graphCount={metric?.graphCount || []} graphCount={metric?.graphCount || []}
checkIfDataExists={checkIfDataExists}
/> />
))} ))}
</div> </div>

View File

@ -1,11 +1,12 @@
import './MetricPage.styles.scss'; import './MetricPage.styles.scss';
import { Typography } from 'antd'; import { Typography } from 'antd';
import logEvent from 'api/common/logEvent';
import cx from 'classnames'; import cx from 'classnames';
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';
import { useState } from 'react'; import { useRef, useState } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { Widgets } from 'types/api/dashboard/getAll'; import { Widgets } from 'types/api/dashboard/getAll';
@ -28,6 +29,7 @@ interface CollapsibleMetricSectionProps {
graphCount: Widgets[]; graphCount: Widgets[];
isCollapsed: boolean; isCollapsed: boolean;
onToggle: () => void; onToggle: () => void;
checkIfDataExists?: (isDataAvailable: boolean) => void;
} }
function CollapsibleMetricSection({ function CollapsibleMetricSection({
@ -36,6 +38,7 @@ function CollapsibleMetricSection({
graphCount, graphCount,
isCollapsed, isCollapsed,
onToggle, onToggle,
checkIfDataExists,
}: CollapsibleMetricSectionProps): JSX.Element { }: CollapsibleMetricSectionProps): JSX.Element {
const isDarkMode = useIsDarkMode(); const isDarkMode = useIsDarkMode();
@ -63,6 +66,7 @@ function CollapsibleMetricSection({
<MetricPageGridGraph <MetricPageGridGraph
key={`graph-${widgetData.id}`} key={`graph-${widgetData.id}`}
widgetData={widgetData} widgetData={widgetData}
checkIfDataExists={checkIfDataExists}
/> />
))} ))}
</div> </div>
@ -72,6 +76,10 @@ function CollapsibleMetricSection({
); );
} }
CollapsibleMetricSection.defaultProps = {
checkIfDataExists: undefined,
};
function MetricPage(): JSX.Element { function MetricPage(): JSX.Element {
const [collapsedSections, setCollapsedSections] = useState<{ const [collapsedSections, setCollapsedSections] = useState<{
[key: string]: boolean; [key: string]: boolean;
@ -114,9 +122,27 @@ function MetricPage(): JSX.Element {
}, },
]; ];
const [renderedGraphCount, setRenderedGraphCount] = useState(0);
const hasLoggedRef = useRef(false);
const checkIfDataExists = (isDataAvailable: boolean): void => {
if (isDataAvailable) {
const newCount = renderedGraphCount + 1;
setRenderedGraphCount(newCount);
// Only log when first graph has rendered and we haven't logged yet
if (newCount === 1 && !hasLoggedRef.current) {
logEvent('MQ Kafka: Metric view', {
graphRendered: true,
});
hasLoggedRef.current = true;
}
}
};
return ( return (
<div className="metric-page"> <div className="metric-page">
<MetricColumnGraphs /> <MetricColumnGraphs checkIfDataExists={checkIfDataExists} />
{metricSections.map(({ key, title, description, graphCount }) => ( {metricSections.map(({ key, title, description, graphCount }) => (
<CollapsibleMetricSection <CollapsibleMetricSection
key={key} key={key}
@ -125,6 +151,7 @@ function MetricPage(): JSX.Element {
graphCount={graphCount} graphCount={graphCount}
isCollapsed={collapsedSections[key]} isCollapsed={collapsedSections[key]}
onToggle={(): void => toggleCollapse(key)} onToggle={(): void => toggleCollapse(key)}
checkIfDataExists={checkIfDataExists}
/> />
))} ))}
</div> </div>

View File

@ -15,8 +15,10 @@ import { Widgets } from 'types/api/dashboard/getAll';
function MetricPageGridGraph({ function MetricPageGridGraph({
widgetData, widgetData,
checkIfDataExists,
}: { }: {
widgetData: Widgets; widgetData: Widgets;
checkIfDataExists?: (isDataAvailable: boolean) => void;
}): JSX.Element { }): JSX.Element {
const history = useHistory(); const history = useHistory();
const { pathname } = useLocation(); const { pathname } = useLocation();
@ -51,9 +53,14 @@ function MetricPageGridGraph({
widget={widgetData} widget={widgetData}
headerMenuList={[...ViewMenuAction]} headerMenuList={[...ViewMenuAction]}
onDragSelect={onDragSelect} onDragSelect={onDragSelect}
dataAvailable={checkIfDataExists}
/> />
</Card> </Card>
); );
} }
MetricPageGridGraph.defaultProps = {
checkIfDataExists: (): void => {},
};
export default MetricPageGridGraph; export default MetricPageGridGraph;