mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-12 11:49:03 +08:00
feat: added table column and row logic for the new api response structure for producer overview (#6433)
* feat: added table column and row logic for the new api response structure for prodcure overview * feat: fixed typo in function name * feat: consumed new 2 table merging logic for producer latency overview * feat: added 3 digit precision to 'ingestion_rate' and 'byte_rate'in consumer overview
This commit is contained in:
parent
0fbfb6b22b
commit
8c46de8eac
@ -1,10 +1,9 @@
|
|||||||
import axios from 'api';
|
import axios from 'api';
|
||||||
import { ErrorResponse, SuccessResponse } from 'types/api';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
MessagingQueueServicePayload,
|
MessagingQueueServicePayload,
|
||||||
MessagingQueuesPayloadProps,
|
MessagingQueuesPayloadProps,
|
||||||
} from './getConsumerLagDetails';
|
} from 'pages/MessagingQueues/MQDetails/MQTables/getConsumerLagDetails';
|
||||||
|
import { ErrorResponse, SuccessResponse } from 'types/api';
|
||||||
|
|
||||||
export const getTopicThroughputOverview = async (
|
export const getTopicThroughputOverview = async (
|
||||||
props: Omit<MessagingQueueServicePayload, 'variables'>,
|
props: Omit<MessagingQueueServicePayload, 'variables'>,
|
@ -108,13 +108,6 @@ const checkValidityOfDetailConfigs = (
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentTab === MessagingQueueServiceDetailType.ProducerDetails) {
|
|
||||||
return Boolean(
|
|
||||||
configDetails?.topic &&
|
|
||||||
configDetails?.partition &&
|
|
||||||
configDetails?.service_name,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return Boolean(configDetails?.topic && configDetails?.service_name);
|
return Boolean(configDetails?.topic && configDetails?.service_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,35 @@
|
|||||||
|
import { RowData } from 'pages/MessagingQueues/MessagingQueuesUtils';
|
||||||
|
|
||||||
|
import { MessagingQueuesPayloadProps } from './getConsumerLagDetails';
|
||||||
|
|
||||||
|
export function getTableDataForProducerLatencyOverview(
|
||||||
|
data: MessagingQueuesPayloadProps['payload'],
|
||||||
|
): RowData[] {
|
||||||
|
if (data?.result?.length === 0) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const firstTableData = data.result[0].table.rows || [];
|
||||||
|
const secondTableData = data.result[1]?.table.rows || [];
|
||||||
|
|
||||||
|
// Create a map for quick lookup of byte_rate using service_name and topic
|
||||||
|
const byteRateMap = new Map(
|
||||||
|
secondTableData.map((row) => [
|
||||||
|
`${row.data.service_name}--${row.data.topic}`,
|
||||||
|
row.data.byte_rate,
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Merge the data from both tables
|
||||||
|
const mergedTableData: RowData[] =
|
||||||
|
firstTableData.map(
|
||||||
|
(row, index): RowData => ({
|
||||||
|
...row.data,
|
||||||
|
byte_rate:
|
||||||
|
byteRateMap.get(`${row.data.service_name}--${row.data.topic}`) || 0,
|
||||||
|
key: index,
|
||||||
|
}),
|
||||||
|
) || [];
|
||||||
|
|
||||||
|
return mergedTableData;
|
||||||
|
}
|
@ -32,6 +32,7 @@ import {
|
|||||||
MessagingQueueServicePayload,
|
MessagingQueueServicePayload,
|
||||||
MessagingQueuesPayloadProps,
|
MessagingQueuesPayloadProps,
|
||||||
} from './getConsumerLagDetails';
|
} from './getConsumerLagDetails';
|
||||||
|
import { getTableDataForProducerLatencyOverview } from './MQTableUtils';
|
||||||
|
|
||||||
const INITIAL_PAGE_SIZE = 10;
|
const INITIAL_PAGE_SIZE = 10;
|
||||||
|
|
||||||
@ -39,16 +40,24 @@ const INITIAL_PAGE_SIZE = 10;
|
|||||||
export function getColumns(
|
export function getColumns(
|
||||||
data: MessagingQueuesPayloadProps['payload'],
|
data: MessagingQueuesPayloadProps['payload'],
|
||||||
history: History<unknown>,
|
history: History<unknown>,
|
||||||
|
isProducerOverview?: boolean,
|
||||||
): RowData[] {
|
): RowData[] {
|
||||||
if (data?.result?.length === 0) {
|
if (data?.result?.length === 0) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const mergedColumns = isProducerOverview
|
||||||
|
? [
|
||||||
|
...(data?.result?.[0]?.table?.columns || []),
|
||||||
|
{ name: 'byte_rate', queryName: 'byte_rate' },
|
||||||
|
]
|
||||||
|
: data?.result?.[0]?.table?.columns;
|
||||||
|
|
||||||
const columns: {
|
const columns: {
|
||||||
title: string;
|
title: string;
|
||||||
dataIndex: string;
|
dataIndex: string;
|
||||||
key: string;
|
key: string;
|
||||||
}[] = data?.result?.[0]?.table?.columns.map((column) => ({
|
}[] = mergedColumns.map((column) => ({
|
||||||
title: convertToTitleCase(column.name),
|
title: convertToTitleCase(column.name),
|
||||||
dataIndex: column.name,
|
dataIndex: column.name,
|
||||||
key: column.name,
|
key: column.name,
|
||||||
@ -58,6 +67,8 @@ export function getColumns(
|
|||||||
'throughput',
|
'throughput',
|
||||||
'avg_msg_size',
|
'avg_msg_size',
|
||||||
'error_percentage',
|
'error_percentage',
|
||||||
|
'ingestion_rate',
|
||||||
|
'byte_rate',
|
||||||
].includes(column.name)
|
].includes(column.name)
|
||||||
? (value: number | string): string => {
|
? (value: number | string): string => {
|
||||||
if (!isNumber(value)) return value.toString();
|
if (!isNumber(value)) return value.toString();
|
||||||
@ -172,13 +183,25 @@ function MessagingQueuesTable({
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const isProducerOverview = useMemo(
|
||||||
|
() =>
|
||||||
|
type === 'Overview' &&
|
||||||
|
selectedView === MessagingQueuesViewType.producerLatency.value &&
|
||||||
|
tableApiPayload?.detailType === 'producer',
|
||||||
|
[type, selectedView, tableApiPayload],
|
||||||
|
);
|
||||||
|
|
||||||
const { mutate: getViewDetails, isLoading, error, isError } = useMutation(
|
const { mutate: getViewDetails, isLoading, error, isError } = useMutation(
|
||||||
tableApi,
|
tableApi,
|
||||||
{
|
{
|
||||||
onSuccess: (data) => {
|
onSuccess: (data) => {
|
||||||
if (data.payload) {
|
if (data.payload) {
|
||||||
setColumns(getColumns(data?.payload, history));
|
setColumns(getColumns(data?.payload, history, isProducerOverview));
|
||||||
setTableData(getTableData(data?.payload));
|
setTableData(
|
||||||
|
isProducerOverview
|
||||||
|
? getTableDataForProducerLatencyOverview(data?.payload)
|
||||||
|
: getTableData(data?.payload),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onError: handleConsumerDetailsOnError,
|
onError: handleConsumerDetailsOnError,
|
||||||
@ -199,15 +222,29 @@ function MessagingQueuesTable({
|
|||||||
const [, setSelectedRows] = useState<any>();
|
const [, setSelectedRows] = useState<any>();
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
|
|
||||||
const onRowClick = (record: { [key: string]: string }): void => {
|
const selectedRowKeyGenerator = (record: {
|
||||||
const selectedKey = record.key;
|
[key: string]: string;
|
||||||
|
}): React.Key => {
|
||||||
|
if (!isEmpty(tableApiPayload?.detailType)) {
|
||||||
|
return `${record.key}_${selectedView}_${tableApiPayload?.detailType}`;
|
||||||
|
}
|
||||||
|
return `${record.key}_${selectedView}`;
|
||||||
|
};
|
||||||
|
|
||||||
if (`${selectedKey}_${selectedView}` === selectedRowKey) {
|
useEffect(() => {
|
||||||
|
if (isEmpty(configDetailQueryData)) {
|
||||||
|
setSelectedRowKey(undefined);
|
||||||
|
setSelectedRows({});
|
||||||
|
}
|
||||||
|
}, [configDetailQueryData]);
|
||||||
|
|
||||||
|
const onRowClick = (record: { [key: string]: string }): void => {
|
||||||
|
if (selectedRowKeyGenerator(record) === selectedRowKey) {
|
||||||
setSelectedRowKey(undefined);
|
setSelectedRowKey(undefined);
|
||||||
setSelectedRows({});
|
setSelectedRows({});
|
||||||
setConfigDetail(urlQuery, location, history, {});
|
setConfigDetail(urlQuery, location, history, {});
|
||||||
} else {
|
} else {
|
||||||
setSelectedRowKey(`${selectedKey}_${selectedView}`);
|
setSelectedRowKey(selectedRowKeyGenerator(record));
|
||||||
setSelectedRows(record);
|
setSelectedRows(record);
|
||||||
|
|
||||||
if (!isEmpty(record)) {
|
if (!isEmpty(record)) {
|
||||||
@ -267,7 +304,7 @@ function MessagingQueuesTable({
|
|||||||
: {}
|
: {}
|
||||||
}
|
}
|
||||||
rowClassName={(record): any =>
|
rowClassName={(record): any =>
|
||||||
`${record.key}_${selectedView}` === selectedRowKey
|
selectedRowKeyGenerator(record) === selectedRowKey
|
||||||
? 'ant-table-row-selected'
|
? 'ant-table-row-selected'
|
||||||
: ''
|
: ''
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
import './MQDetails.style.scss';
|
import './MQDetails.style.scss';
|
||||||
|
|
||||||
import { Radio } from 'antd';
|
import { Radio } from 'antd';
|
||||||
import { Dispatch, SetStateAction } from 'react';
|
import { getTopicThroughputOverview } from 'api/messagingQueues/getTopicThroughputOverview';
|
||||||
|
import useUrlQuery from 'hooks/useUrlQuery';
|
||||||
|
import { Dispatch, SetStateAction, useMemo } from 'react';
|
||||||
import { useSelector } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
|
import { useHistory, useLocation } from 'react-router-dom';
|
||||||
import { AppState } from 'store/reducers';
|
import { AppState } from 'store/reducers';
|
||||||
import { GlobalReducer } from 'types/reducer/globalTime';
|
import { GlobalReducer } from 'types/reducer/globalTime';
|
||||||
|
|
||||||
@ -10,25 +13,32 @@ import {
|
|||||||
MessagingQueuesViewType,
|
MessagingQueuesViewType,
|
||||||
MessagingQueuesViewTypeOptions,
|
MessagingQueuesViewTypeOptions,
|
||||||
ProducerLatencyOptions,
|
ProducerLatencyOptions,
|
||||||
|
setConfigDetail,
|
||||||
} from '../MessagingQueuesUtils';
|
} from '../MessagingQueuesUtils';
|
||||||
import { MessagingQueueServicePayload } from './MQTables/getConsumerLagDetails';
|
import { MessagingQueueServicePayload } from './MQTables/getConsumerLagDetails';
|
||||||
import { getKafkaSpanEval } from './MQTables/getKafkaSpanEval';
|
import { getKafkaSpanEval } from './MQTables/getKafkaSpanEval';
|
||||||
import { getPartitionLatencyOverview } from './MQTables/getPartitionLatencyOverview';
|
import { getPartitionLatencyOverview } from './MQTables/getPartitionLatencyOverview';
|
||||||
import { getTopicThroughputOverview } from './MQTables/getTopicThroughputOverview';
|
|
||||||
import MessagingQueuesTable from './MQTables/MQTables';
|
import MessagingQueuesTable from './MQTables/MQTables';
|
||||||
|
|
||||||
type SelectedViewType = keyof typeof MessagingQueuesViewType;
|
type SelectedViewType = keyof typeof MessagingQueuesViewType;
|
||||||
|
|
||||||
function PartitionLatencyTabs({
|
function ProducerLatencyTabs({
|
||||||
option,
|
option,
|
||||||
setOption,
|
setOption,
|
||||||
}: {
|
}: {
|
||||||
option: ProducerLatencyOptions;
|
option: ProducerLatencyOptions;
|
||||||
setOption: Dispatch<SetStateAction<ProducerLatencyOptions>>;
|
setOption: Dispatch<SetStateAction<ProducerLatencyOptions>>;
|
||||||
}): JSX.Element {
|
}): JSX.Element {
|
||||||
|
const urlQuery = useUrlQuery();
|
||||||
|
const location = useLocation();
|
||||||
|
const history = useHistory();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Radio.Group
|
<Radio.Group
|
||||||
onChange={(e): void => setOption(e.target.value)}
|
onChange={(e): void => {
|
||||||
|
setConfigDetail(urlQuery, location, history, {});
|
||||||
|
setOption(e.target.value);
|
||||||
|
}}
|
||||||
value={option}
|
value={option}
|
||||||
className="mq-details-options"
|
className="mq-details-options"
|
||||||
>
|
>
|
||||||
@ -71,27 +81,26 @@ function MessagingQueueOverview({
|
|||||||
(state) => state.globalTime,
|
(state) => state.globalTime,
|
||||||
);
|
);
|
||||||
|
|
||||||
const tableApiPayload: MessagingQueueServicePayload = {
|
const tableApiPayload: MessagingQueueServicePayload = useMemo(
|
||||||
variables: {},
|
() => ({
|
||||||
start: minTime,
|
variables: {},
|
||||||
end: maxTime,
|
start: minTime,
|
||||||
detailType:
|
end: maxTime,
|
||||||
// eslint-disable-next-line no-nested-ternary
|
detailType:
|
||||||
selectedView === MessagingQueuesViewType.producerLatency.value
|
// eslint-disable-next-line no-nested-ternary
|
||||||
? option === ProducerLatencyOptions.Producers
|
selectedView === MessagingQueuesViewType.producerLatency.value
|
||||||
? 'producer'
|
? option === ProducerLatencyOptions.Producers
|
||||||
: 'consumer'
|
? 'producer'
|
||||||
: undefined,
|
: 'consumer'
|
||||||
evalTime:
|
: undefined,
|
||||||
selectedView === MessagingQueuesViewType.dropRate.value
|
}),
|
||||||
? 2363404
|
[minTime, maxTime, selectedView, option],
|
||||||
: undefined,
|
);
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mq-overview-container">
|
<div className="mq-overview-container">
|
||||||
{selectedView === MessagingQueuesViewType.producerLatency.value ? (
|
{selectedView === MessagingQueuesViewType.producerLatency.value ? (
|
||||||
<PartitionLatencyTabs option={option} setOption={setOption} />
|
<ProducerLatencyTabs option={option} setOption={setOption} />
|
||||||
) : (
|
) : (
|
||||||
<div className="mq-overview-title">
|
<div className="mq-overview-title">
|
||||||
{MessagingQueuesViewType[selectedView as SelectedViewType].label}
|
{MessagingQueuesViewType[selectedView as SelectedViewType].label}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user