diff --git a/frontend/public/locales/en-GB/messagingQueues.json b/frontend/public/locales/en-GB/messagingQueues.json new file mode 100644 index 0000000000..5c446d98d8 --- /dev/null +++ b/frontend/public/locales/en-GB/messagingQueues.json @@ -0,0 +1,24 @@ +{ + "metricGraphCategory": { + "brokerMetrics": { + "title": "Broker Metrics", + "description": "The Kafka Broker metrics here inform you of data loss/delay through unclean leader elections and network throughputs, as well as request fails through request purgatories and timeouts metrics" + }, + "consumerMetrics": { + "title": "Consumer Metrics", + "description": "Kafka Consumer metrics provide insights into lag between message production and consumption, success rates and latency of message delivery, and the volume of data consumed." + }, + "producerMetrics": { + "title": "Producer Metrics", + "description": "Kafka Producers send messages to brokers for storage and distribution by topic. These metrics inform you of the volume and rate of data sent, and the success rate of message delivery." + }, + "brokerJVMMetrics": { + "title": "Broker JVM Metrics", + "description": "Kafka brokers are Java applications that expose JVM metrics to inform on the broker's system health. Garbage collection metrics like those below provide key insights into free memory, broker performance, and heap size. You need to enable new_gc_metrics for this section to populate." + }, + "partitionMetrics": { + "title": "Partition Metrics", + "description": "Kafka partitions are the unit of parallelism in Kafka. These metrics inform you of the number of partitions per topic, the current offset of each partition, the oldest offset, and the number of in-sync replicas." + } + } +} diff --git a/frontend/public/locales/en-GB/messagingQueuesKafkaOverview.json b/frontend/public/locales/en-GB/messagingQueuesKafkaOverview.json index 5061a5ddcb..f298f664d1 100644 --- a/frontend/public/locales/en-GB/messagingQueuesKafkaOverview.json +++ b/frontend/public/locales/en-GB/messagingQueuesKafkaOverview.json @@ -1,30 +1,54 @@ { - "breadcrumb": "Messaging Queues", - "header": "Kafka / Overview", - "overview": { - "title": "Start sending data in as little as 20 minutes", - "subtitle": "Connect and Monitor Your Data Streams" - }, - "configureConsumer": { - "title": "Configure Consumer", - "description": "Add consumer data sources to gain insights and enhance monitoring.", - "button": "Get Started" - }, - "configureProducer": { - "title": "Configure Producer", - "description": "Add producer data sources to gain insights and enhance monitoring.", - "button": "Get Started" - }, - "monitorKafka": { - "title": "Monitor kafka", - "description": "Add your Kafka source to gain insights and enhance activity tracking.", - "button": "Get Started" - }, - "summarySection": { - "viewDetailsButton": "View Details" - }, - "confirmModal": { - "content": "Before navigating to the details page, please make sure you have configured all the required setup to ensure correct data monitoring.", - "okText": "Proceed" - } -} \ No newline at end of file + "breadcrumb": "Messaging Queues", + "header": "Kafka / Overview", + "overview": { + "title": "Start sending data in as little as 20 minutes", + "subtitle": "Connect and Monitor Your Data Streams" + }, + "configureConsumer": { + "title": "Configure Consumer", + "description": "Add consumer data sources to gain insights and enhance monitoring.", + "button": "Get Started" + }, + "configureProducer": { + "title": "Configure Producer", + "description": "Add producer data sources to gain insights and enhance monitoring.", + "button": "Get Started" + }, + "monitorKafka": { + "title": "Monitor kafka", + "description": "Add your Kafka source to gain insights and enhance activity tracking.", + "button": "Get Started" + }, + "summarySection": { + "viewDetailsButton": "View Details", + "consumer": { + "title": "Consumer lag view", + "description": "Connect and Monitor Your Data Streams" + }, + "producer": { + "title": "Producer latency view", + "description": "Connect and Monitor Your Data Streams" + }, + "partition": { + "title": "Partition Latency view", + "description": "Connect and Monitor Your Data Streams" + }, + "dropRate": { + "title": "Drop Rate view", + "description": "Connect and Monitor Your Data Streams" + }, + "metricPage": { + "title": "Metric View", + "description": "Connect and Monitor Your Data Streams" + } + }, + "confirmModal": { + "content": "Before navigating to the details page, please make sure you have configured all the required setup to ensure correct data monitoring.", + "okText": "Proceed" + }, + "overviewSummarySection": { + "title": "Monitor Your Data Streams", + "subtitle": "Monitor key Kafka metrics like consumer lag and latency to ensure efficient data flow and troubleshoot in real time." + } +} diff --git a/frontend/public/locales/en/messagingQueues.json b/frontend/public/locales/en/messagingQueues.json new file mode 100644 index 0000000000..5c446d98d8 --- /dev/null +++ b/frontend/public/locales/en/messagingQueues.json @@ -0,0 +1,24 @@ +{ + "metricGraphCategory": { + "brokerMetrics": { + "title": "Broker Metrics", + "description": "The Kafka Broker metrics here inform you of data loss/delay through unclean leader elections and network throughputs, as well as request fails through request purgatories and timeouts metrics" + }, + "consumerMetrics": { + "title": "Consumer Metrics", + "description": "Kafka Consumer metrics provide insights into lag between message production and consumption, success rates and latency of message delivery, and the volume of data consumed." + }, + "producerMetrics": { + "title": "Producer Metrics", + "description": "Kafka Producers send messages to brokers for storage and distribution by topic. These metrics inform you of the volume and rate of data sent, and the success rate of message delivery." + }, + "brokerJVMMetrics": { + "title": "Broker JVM Metrics", + "description": "Kafka brokers are Java applications that expose JVM metrics to inform on the broker's system health. Garbage collection metrics like those below provide key insights into free memory, broker performance, and heap size. You need to enable new_gc_metrics for this section to populate." + }, + "partitionMetrics": { + "title": "Partition Metrics", + "description": "Kafka partitions are the unit of parallelism in Kafka. These metrics inform you of the number of partitions per topic, the current offset of each partition, the oldest offset, and the number of in-sync replicas." + } + } +} diff --git a/frontend/public/locales/en/messagingQueuesKafkaOverview.json b/frontend/public/locales/en/messagingQueuesKafkaOverview.json index de67d0b3e9..f298f664d1 100644 --- a/frontend/public/locales/en/messagingQueuesKafkaOverview.json +++ b/frontend/public/locales/en/messagingQueuesKafkaOverview.json @@ -37,6 +37,10 @@ "dropRate": { "title": "Drop Rate view", "description": "Connect and Monitor Your Data Streams" + }, + "metricPage": { + "title": "Metric View", + "description": "Connect and Monitor Your Data Streams" } }, "confirmModal": { diff --git a/frontend/src/pages/MessagingQueues/MQDetailPage/MQDetailPage.tsx b/frontend/src/pages/MessagingQueues/MQDetailPage/MQDetailPage.tsx index 5ee98249f6..5793d40b7b 100644 --- a/frontend/src/pages/MessagingQueues/MQDetailPage/MQDetailPage.tsx +++ b/frontend/src/pages/MessagingQueues/MQDetailPage/MQDetailPage.tsx @@ -18,6 +18,7 @@ import { } from '../MessagingQueuesUtils'; import DropRateView from '../MQDetails/DropRateView/DropRateView'; import MessagingQueueOverview from '../MQDetails/MessagingQueueOverview'; +import MetricPage from '../MQDetails/MetricPage/MetricPage'; import MessagingQueuesDetails from '../MQDetails/MQDetails'; import MessagingQueuesConfigOptions from '../MQGraph/MQConfigOptions'; import MessagingQueuesGraph from '../MQGraph/MQGraph'; @@ -60,6 +61,10 @@ function MQDetailPage(): JSX.Element { }); }; + const showMessagingQueueDetails = + selectedView !== MessagingQueuesViewType.dropRate.value && + selectedView !== MessagingQueuesViewType.metricPage.value; + return (
@@ -82,7 +87,7 @@ function MQDetailPage(): JSX.Element { setSelectedView(value); updateUrlQuery({ [QueryParams.mqServiceView]: value }); }} - value={mqServiceView} + value={selectedView} options={[ { label: MessagingQueuesViewType.consumerLag.label, @@ -100,6 +105,10 @@ function MQDetailPage(): JSX.Element { label: MessagingQueuesViewType.dropRate.label, value: MessagingQueuesViewType.dropRate.value, }, + { + label: MessagingQueuesViewType.metricPage.label, + value: MessagingQueuesViewType.metricPage.value, + }, ]} />
@@ -112,6 +121,8 @@ function MQDetailPage(): JSX.Element {
) : selectedView === MessagingQueuesViewType.dropRate.value ? ( + ) : selectedView === MessagingQueuesViewType.metricPage.value ? ( + ) : ( )} - {selectedView !== MessagingQueuesViewType.dropRate.value && ( + {showMessagingQueueDetails && (
-
- {MessagingQueuesViewType.dropRate.label} -
+ {MessagingQueuesViewType.dropRate.label}
( - + {ConsumerLagDetailTitle[detailType]} - {detailType === MessagingQueueServiceDetailType.PartitionHostMetrics && ( - - )} )); }; diff --git a/frontend/src/pages/MessagingQueues/MQDetails/MetricPage/MetricColumnGraphs.tsx b/frontend/src/pages/MessagingQueues/MQDetails/MetricPage/MetricColumnGraphs.tsx new file mode 100644 index 0000000000..a88db1efc7 --- /dev/null +++ b/frontend/src/pages/MessagingQueues/MQDetails/MetricPage/MetricColumnGraphs.tsx @@ -0,0 +1,115 @@ +import { Typography } from 'antd'; +import { CardContainer } from 'container/GridCardLayout/styles'; +import { useIsDarkMode } from 'hooks/useDarkMode'; +import { useTranslation } from 'react-i18next'; +import { Widgets } from 'types/api/dashboard/getAll'; + +import MetricPageGridGraph from './MetricPageGraph'; +import { + averageRequestLatencyWidgetData, + brokerCountWidgetData, + brokerNetworkThroughputWidgetData, + bytesConsumedWidgetData, + consumerFetchRateWidgetData, + consumerGroupMemberWidgetData, + consumerLagByGroupWidgetData, + consumerOffsetWidgetData, + ioWaitTimeWidgetData, + kafkaProducerByteRateWidgetData, + messagesConsumedWidgetData, + producerFetchRequestPurgatoryWidgetData, + requestResponseWidgetData, + requestTimesWidgetData, +} from './MetricPageUtil'; + +interface MetricSectionProps { + title: string; + description: string; + graphCount: Widgets[]; +} + +function MetricSection({ + title, + description, + graphCount, +}: MetricSectionProps): JSX.Element { + const isDarkMode = useIsDarkMode(); + + return ( +
+ +
+ {title} +
+
+ + {description} + +
+ {graphCount.map((widgetData) => ( + + ))} +
+
+ ); +} + +function MetricColumnGraphs(): JSX.Element { + const { t } = useTranslation('messagingQueues'); + + const metricsData = [ + { + title: t('metricGraphCategory.brokerMetrics.title'), + description: t('metricGraphCategory.brokerMetrics.description'), + graphCount: [ + brokerCountWidgetData, + requestTimesWidgetData, + producerFetchRequestPurgatoryWidgetData, + brokerNetworkThroughputWidgetData, + ], + id: 'broker-metrics', + }, + { + title: t('metricGraphCategory.producerMetrics.title'), + description: t('metricGraphCategory.producerMetrics.description'), + graphCount: [ + ioWaitTimeWidgetData, + requestResponseWidgetData, + averageRequestLatencyWidgetData, + kafkaProducerByteRateWidgetData, + bytesConsumedWidgetData, + ], + id: 'producer-metrics', + }, + { + title: t('metricGraphCategory.consumerMetrics.title'), + description: t('metricGraphCategory.consumerMetrics.description'), + graphCount: [ + consumerOffsetWidgetData, + consumerGroupMemberWidgetData, + consumerLagByGroupWidgetData, + consumerFetchRateWidgetData, + messagesConsumedWidgetData, + ], + id: 'consumer-metrics', + }, + ]; + + return ( +
+ {metricsData.map((metric) => ( + + ))} +
+ ); +} + +export default MetricColumnGraphs; diff --git a/frontend/src/pages/MessagingQueues/MQDetails/MetricPage/MetricPage.styles.scss b/frontend/src/pages/MessagingQueues/MQDetails/MetricPage/MetricPage.styles.scss new file mode 100644 index 0000000000..cc955c0739 --- /dev/null +++ b/frontend/src/pages/MessagingQueues/MQDetails/MetricPage/MetricPage.styles.scss @@ -0,0 +1,128 @@ +.metric-page { + padding: 20px; + display: flex; + flex-direction: column; + gap: 32px; + + .metric-page-container { + display: flex; + flex-direction: column; + + .row-panel { + padding-left: 10px; + } + + .metric-page-grid { + display: grid; + grid-template-columns: repeat(3, 1fr); + align-items: flex-start; + gap: 10px; + + .metric-graph { + height: 320px; + padding: 10px; + width: 100%; + box-sizing: border-box; + } + } + + @media (max-width: 768px) { + .metric-page-grid { + grid-template-columns: 1fr; + } + } + + .graph-description { + padding: 16px 10px 16px 10px; + } + } + + .row-panel { + border-radius: 4px; + background: rgba(18, 19, 23, 0.4); + padding: 8px; + display: flex; + gap: 6px; + align-items: center; + height: 48px !important; + + .ant-typography { + font-size: 14px; + font-weight: 500; + } + + .row-panel-section { + display: flex; + gap: 6px; + align-items: center; + + .row-icon { + color: var(--bg-vanilla-400); + cursor: pointer; + } + + .section-title { + color: var(--bg-vanilla-400); + font-family: Inter; + font-size: 14px; + font-style: normal; + font-weight: 400; + line-height: 20px; + letter-spacing: -0.07px; + } + } + } + + .metric-column-graph-container { + display: grid; + grid-template-columns: 1fr 1fr 1fr; + gap: 10px; + + .metric-column-graph { + display: flex; + flex-direction: column; + gap: 10px; + + .row-panel { + justify-content: center; + } + + .metric-page-grid { + display: flex; + flex-direction: column; + flex: 1; + min-width: 0; + gap: 10px; + + .metric-graph { + height: 320px; + padding: 10px; + width: 100%; + box-sizing: border-box; + } + } + } + } + + @media (max-width: 768px) { + .metric-column-graph-container { + grid-template-columns: 1fr; + } + } +} + +.lightMode { + .metric-page { + .row-panel { + .row-panel-section { + .row-icon { + color: var(--bg-ink-300); + } + + .section-title { + color: var(--bg-ink-300); + } + } + } + } +} diff --git a/frontend/src/pages/MessagingQueues/MQDetails/MetricPage/MetricPage.tsx b/frontend/src/pages/MessagingQueues/MQDetails/MetricPage/MetricPage.tsx new file mode 100644 index 0000000000..3c997da459 --- /dev/null +++ b/frontend/src/pages/MessagingQueues/MQDetails/MetricPage/MetricPage.tsx @@ -0,0 +1,134 @@ +import './MetricPage.styles.scss'; + +import { Typography } from 'antd'; +import cx from 'classnames'; +import { CardContainer } from 'container/GridCardLayout/styles'; +import { useIsDarkMode } from 'hooks/useDarkMode'; +import { ChevronDown, ChevronUp } from 'lucide-react'; +import { useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { Widgets } from 'types/api/dashboard/getAll'; + +import MetricColumnGraphs from './MetricColumnGraphs'; +import MetricPageGridGraph from './MetricPageGraph'; +import { + cpuRecentUtilizationWidgetData, + currentOffsetPartitionWidgetData, + insyncReplicasWidgetData, + jvmGcCollectionsElapsedWidgetData, + jvmGCCountWidgetData, + jvmMemoryHeapWidgetData, + oldestOffsetWidgetData, + partitionCountPerTopicWidgetData, +} from './MetricPageUtil'; + +interface CollapsibleMetricSectionProps { + title: string; + description: string; + graphCount: Widgets[]; + isCollapsed: boolean; + onToggle: () => void; +} + +function CollapsibleMetricSection({ + title, + description, + graphCount, + isCollapsed, + onToggle, +}: CollapsibleMetricSectionProps): JSX.Element { + const isDarkMode = useIsDarkMode(); + + return ( +
+ +
+
+ {title} + {isCollapsed ? ( + + ) : ( + + )} +
+
+
+ {!isCollapsed && ( + <> + + {description} + +
+ {graphCount.map((widgetData) => ( + + ))} +
+ + )} +
+ ); +} + +function MetricPage(): JSX.Element { + const [collapsedSections, setCollapsedSections] = useState<{ + [key: string]: boolean; + }>({ + producerMetrics: false, + consumerMetrics: false, + }); + + const toggleCollapse = (key: string): void => { + setCollapsedSections((prev) => ({ + ...prev, + [key]: !prev[key], + })); + }; + + const { t } = useTranslation('messagingQueues'); + + const metricSections = [ + { + key: 'bokerJVMMetrics', + title: t('metricGraphCategory.brokerJVMMetrics.title'), + description: t('metricGraphCategory.brokerJVMMetrics.description'), + graphCount: [ + jvmGCCountWidgetData, + jvmGcCollectionsElapsedWidgetData, + cpuRecentUtilizationWidgetData, + jvmMemoryHeapWidgetData, + ], + }, + { + key: 'partitionMetrics', + title: t('metricGraphCategory.partitionMetrics.title'), + description: t('metricGraphCategory.partitionMetrics.description'), + graphCount: [ + partitionCountPerTopicWidgetData, + currentOffsetPartitionWidgetData, + oldestOffsetWidgetData, + insyncReplicasWidgetData, + ], + }, + ]; + + return ( +
+ + {metricSections.map(({ key, title, description, graphCount }) => ( + toggleCollapse(key)} + /> + ))} +
+ ); +} + +export default MetricPage; diff --git a/frontend/src/pages/MessagingQueues/MQDetails/MetricPage/MetricPageGraph.tsx b/frontend/src/pages/MessagingQueues/MQDetails/MetricPage/MetricPageGraph.tsx new file mode 100644 index 0000000000..248dc35178 --- /dev/null +++ b/frontend/src/pages/MessagingQueues/MQDetails/MetricPage/MetricPageGraph.tsx @@ -0,0 +1,59 @@ +import './MetricPage.styles.scss'; + +import { QueryParams } from 'constants/query'; +import { PANEL_TYPES } from 'constants/queryBuilder'; +import { ViewMenuAction } from 'container/GridCardLayout/config'; +import GridCard from 'container/GridCardLayout/GridCard'; +import { Card } from 'container/GridCardLayout/styles'; +import { useIsDarkMode } from 'hooks/useDarkMode'; +import useUrlQuery from 'hooks/useUrlQuery'; +import { useCallback } from 'react'; +import { useDispatch } from 'react-redux'; +import { useHistory, useLocation } from 'react-router-dom'; +import { UpdateTimeInterval } from 'store/actions'; +import { Widgets } from 'types/api/dashboard/getAll'; + +function MetricPageGridGraph({ + widgetData, +}: { + widgetData: Widgets; +}): JSX.Element { + const history = useHistory(); + const { pathname } = useLocation(); + const dispatch = useDispatch(); + const urlQuery = useUrlQuery(); + const isDarkMode = useIsDarkMode(); + + 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, history, pathname, urlQuery], + ); + + return ( + + + + ); +} + +export default MetricPageGridGraph; diff --git a/frontend/src/pages/MessagingQueues/MQDetails/MetricPage/MetricPageUtil.ts b/frontend/src/pages/MessagingQueues/MQDetails/MetricPage/MetricPageUtil.ts new file mode 100644 index 0000000000..144b573c5f --- /dev/null +++ b/frontend/src/pages/MessagingQueues/MQDetails/MetricPage/MetricPageUtil.ts @@ -0,0 +1,1092 @@ +/* eslint-disable sonarjs/no-duplicate-string */ +import { PANEL_TYPES } from 'constants/queryBuilder'; +import { GetWidgetQueryBuilderProps } from 'container/MetricsApplication/types'; +import { Widgets } from 'types/api/dashboard/getAll'; +import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse'; +import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData'; +import { EQueryType } from 'types/common/dashboard'; +import { DataSource } from 'types/common/queryBuilder'; +import { v4 as uuid } from 'uuid'; + +interface GetWidgetQueryProps { + title: string; + description: string; + queryData: IBuilderQuery[]; +} + +interface GetWidgetQueryPropsReturn extends GetWidgetQueryBuilderProps { + description?: string; + nullZeroValues: string; +} + +export const getWidgetQueryBuilder = ({ + query, + title = '', + panelTypes, + yAxisUnit = '', + fillSpans = false, + id, + nullZeroValues, + description, +}: GetWidgetQueryPropsReturn): Widgets => ({ + description: description || '', + id: id || uuid(), + isStacked: false, + nullZeroValues: nullZeroValues || '', + opacity: '1', + panelTypes, + query, + timePreferance: 'GLOBAL_TIME', + title, + yAxisUnit, + softMax: null, + softMin: null, + selectedLogFields: [], + selectedTracesFields: [], + fillSpans, +}); + +export function getWidgetQuery( + props: GetWidgetQueryProps, +): GetWidgetQueryPropsReturn { + const { title, description } = props; + return { + title, + yAxisUnit: 'none', + panelTypes: PANEL_TYPES.TIME_SERIES, + fillSpans: false, + description, + nullZeroValues: 'zero', + query: { + queryType: EQueryType.QUERY_BUILDER, + promql: [], + builder: { + queryData: props.queryData, + queryFormulas: [], + }, + clickhouse_sql: [], + id: uuid(), + }, + }; +} + +export const requestTimesWidgetData = getWidgetQueryBuilder( + getWidgetQuery({ + queryData: [ + { + aggregateAttribute: { + dataType: DataTypes.Float64, + id: 'kafka_request_time_avg--float64--Gauge--true', + isColumn: true, + isJSON: false, + key: 'kafka_request_time_avg', + type: 'Gauge', + }, + aggregateOperator: 'avg', + dataSource: DataSource.METRICS, + disabled: false, + expression: 'A', + filters: { + items: [], + op: 'AND', + }, + functions: [], + groupBy: [], + having: [], + legend: 'Request Times', + limit: null, + orderBy: [], + queryName: 'A', + reduceTo: 'avg', + spaceAggregation: 'avg', + stepInterval: 60, + timeAggregation: 'avg', + }, + ], + title: 'Request Times', + description: + 'This metric is used to measure the average latency experienced by requests across the Kafka broker.', + }), +); + +export const brokerCountWidgetData = getWidgetQueryBuilder( + getWidgetQuery({ + queryData: [ + { + aggregateAttribute: { + dataType: DataTypes.Float64, + id: 'kafka_brokers--float64--Gauge--true', + isColumn: true, + isJSON: false, + key: 'kafka_brokers', + type: 'Gauge', + }, + aggregateOperator: 'sum', + dataSource: DataSource.METRICS, + disabled: false, + expression: 'A', + filters: { + items: [], + op: 'AND', + }, + functions: [], + groupBy: [], + having: [], + legend: 'Broker count', + limit: null, + orderBy: [], + queryName: 'A', + reduceTo: 'avg', + spaceAggregation: 'avg', + stepInterval: 60, + timeAggregation: 'sum', + }, + ], + title: 'Broker Count', + description: 'Total number of active brokers in the Kafka cluster.\n', + }), +); + +export const producerFetchRequestPurgatoryWidgetData = getWidgetQueryBuilder( + getWidgetQuery({ + queryData: [ + { + aggregateAttribute: { + dataType: DataTypes.Float64, + id: 'kafka_purgatory_size--float64--Gauge--true', + isColumn: true, + isJSON: false, + key: 'kafka_purgatory_size', + type: 'Gauge', + }, + aggregateOperator: 'avg', + dataSource: DataSource.METRICS, + disabled: false, + expression: 'A', + filters: { + items: [], + op: 'AND', + }, + functions: [], + groupBy: [], + having: [], + legend: 'Producer and Fetch Request Purgatory', + limit: null, + orderBy: [], + queryName: 'A', + reduceTo: 'avg', + spaceAggregation: 'avg', + stepInterval: 60, + timeAggregation: 'avg', + }, + ], + title: 'Producer and Fetch Request Purgatory', + description: + 'Measures the number of requests that Kafka brokers have received but cannot immediately fulfill', + }), +); + +export const brokerNetworkThroughputWidgetData = getWidgetQueryBuilder( + getWidgetQuery({ + queryData: [ + { + aggregateAttribute: { + dataType: DataTypes.Float64, + id: + 'kafka_server_brokertopicmetrics_bytesoutpersec_oneminuterate--float64--Gauge--true', + isColumn: true, + isJSON: false, + key: 'kafka_server_brokertopicmetrics_bytesoutpersec_oneminuterate', + type: 'Gauge', + }, + aggregateOperator: 'avg', + dataSource: DataSource.METRICS, + disabled: false, + expression: 'A', + filters: { + items: [], + op: 'AND', + }, + functions: [], + groupBy: [], + having: [], + legend: 'Broker Network Throughput', + limit: null, + orderBy: [], + queryName: 'A', + reduceTo: 'avg', + spaceAggregation: 'avg', + stepInterval: 60, + timeAggregation: 'avg', + }, + ], + title: 'Broker Network Throughput', + description: + 'Helps gauge the data throughput from the Kafka broker to consumer clients, focusing on the network usage associated with serving messages to consumers.', + }), +); + +export const ioWaitTimeWidgetData = getWidgetQueryBuilder( + getWidgetQuery({ + queryData: [ + { + aggregateAttribute: { + dataType: DataTypes.Float64, + id: 'kafka_producer_io_waittime_total--float64--Sum--true', + isColumn: true, + isJSON: false, + key: 'kafka_producer_io_waittime_total', + type: 'Sum', + }, + aggregateOperator: 'rate', + dataSource: DataSource.METRICS, + disabled: false, + expression: 'A', + filters: { + items: [], + op: 'AND', + }, + functions: [], + groupBy: [], + having: [], + legend: 'I/O Wait Time', + limit: null, + orderBy: [], + queryName: 'A', + reduceTo: 'avg', + spaceAggregation: 'sum', + stepInterval: 60, + timeAggregation: 'rate', + }, + ], + title: 'I/O Wait Time', + description: + 'This metric measures the total time that producers are in an I/O wait state, indicating potential bottlenecks in data transmission from producers to Kafka brokers.', + }), +); + +export const requestResponseWidgetData = getWidgetQueryBuilder( + getWidgetQuery({ + queryData: [ + { + aggregateAttribute: { + dataType: DataTypes.Float64, + id: 'kafka_producer_request_rate--float64--Gauge--true', + isColumn: true, + isJSON: false, + key: 'kafka_producer_request_rate', + type: 'Gauge', + }, + aggregateOperator: 'avg', + dataSource: DataSource.METRICS, + disabled: false, + expression: 'A', + filters: { + items: [], + op: 'AND', + }, + functions: [], + groupBy: [], + having: [], + legend: 'Request Rate', + limit: null, + orderBy: [], + queryName: 'A', + reduceTo: 'avg', + spaceAggregation: 'avg', + stepInterval: 60, + timeAggregation: 'avg', + }, + { + aggregateAttribute: { + dataType: DataTypes.Float64, + id: 'kafka_producer_response_rate--float64--Gauge--true', + isColumn: true, + isJSON: false, + key: 'kafka_producer_response_rate', + type: 'Gauge', + }, + aggregateOperator: 'avg', + dataSource: DataSource.METRICS, + disabled: false, + expression: 'B', + filters: { + items: [], + op: 'AND', + }, + functions: [], + groupBy: [], + having: [], + legend: 'Response Rate', + limit: null, + orderBy: [], + queryName: 'B', + reduceTo: 'avg', + spaceAggregation: 'avg', + stepInterval: 60, + timeAggregation: 'avg', + }, + ], + title: 'Request and Response Rate', + description: + "Indicates how many requests the producer is sending per second, reflecting the intensity of the producer's interaction with the Kafka cluster. Also, helps Kafka administrators gauge the responsiveness of brokers to producer requests.", + }), +); + +export const averageRequestLatencyWidgetData = getWidgetQueryBuilder( + getWidgetQuery({ + queryData: [ + { + aggregateAttribute: { + dataType: DataTypes.Float64, + id: 'kafka_producer_request_latency_avg--float64--Gauge--true', + isColumn: true, + isJSON: false, + key: 'kafka_producer_request_latency_avg', + type: 'Gauge', + }, + aggregateOperator: 'avg', + dataSource: DataSource.METRICS, + disabled: false, + expression: 'A', + filters: { + items: [], + op: 'AND', + }, + functions: [], + groupBy: [], + having: [], + legend: 'Average Request Latency', + limit: null, + orderBy: [], + queryName: 'A', + reduceTo: 'avg', + spaceAggregation: 'avg', + stepInterval: 60, + timeAggregation: 'avg', + }, + ], + title: 'Average Request Latency', + description: + 'Helps Kafka administrators and developers understand the average latency experienced by producer requests.', + }), +); + +export const kafkaProducerByteRateWidgetData = getWidgetQueryBuilder( + getWidgetQuery({ + queryData: [ + { + aggregateAttribute: { + dataType: DataTypes.Float64, + id: 'kafka_producer_byte_rate--float64--Gauge--true', + isColumn: true, + isJSON: false, + key: 'kafka_producer_byte_rate', + type: 'Gauge', + }, + aggregateOperator: 'avg', + dataSource: DataSource.METRICS, + disabled: false, + expression: 'A', + filters: { + items: [], + op: 'AND', + }, + functions: [], + groupBy: [ + { + dataType: DataTypes.String, + id: 'topic--string--tag--false', + isColumn: false, + isJSON: false, + key: 'topic', + type: 'tag', + }, + ], + having: [], + legend: '', + limit: null, + orderBy: [], + queryName: 'A', + reduceTo: 'avg', + spaceAggregation: 'avg', + stepInterval: 60, + timeAggregation: 'avg', + }, + ], + title: 'kafka_producer_byte_rate', + description: + 'Helps measure the data output rate from the producer, indicating the load a producer is placing on Kafka brokers.', + }), +); + +export const bytesConsumedWidgetData = getWidgetQueryBuilder( + getWidgetQuery({ + queryData: [ + { + aggregateAttribute: { + dataType: DataTypes.Float64, + id: 'kafka_consumer_bytes_consumed_rate--float64--Gauge--true', + isColumn: true, + isJSON: false, + key: 'kafka_consumer_bytes_consumed_rate', + type: 'Gauge', + }, + aggregateOperator: 'avg', + dataSource: DataSource.METRICS, + disabled: false, + expression: 'A', + filters: { + items: [], + op: 'AND', + }, + functions: [], + groupBy: [], + having: [], + legend: 'Bytes Consumed', + limit: null, + orderBy: [], + queryName: 'A', + reduceTo: 'avg', + spaceAggregation: 'avg', + stepInterval: 60, + timeAggregation: 'avg', + }, + ], + title: 'Bytes Consumed', + description: + 'Helps Kafka administrators monitor the data consumption rate of a consumer group, showing how much data (in bytes) is being read from the Kafka cluster over time.', + }), +); + +export const consumerOffsetWidgetData = getWidgetQueryBuilder( + getWidgetQuery({ + queryData: [ + { + aggregateAttribute: { + dataType: DataTypes.Float64, + id: 'kafka_consumer_group_offset--float64--Gauge--true', + isColumn: true, + isJSON: false, + key: 'kafka_consumer_group_offset', + type: 'Gauge', + }, + aggregateOperator: 'avg', + dataSource: DataSource.METRICS, + disabled: false, + expression: 'A', + filters: { + items: [], + op: 'AND', + }, + functions: [], + groupBy: [ + { + dataType: DataTypes.String, + id: 'group--string--tag--false', + isColumn: false, + isJSON: false, + key: 'group', + type: 'tag', + }, + { + dataType: DataTypes.String, + id: 'topic--string--tag--false', + isColumn: false, + isJSON: false, + key: 'topic', + type: 'tag', + }, + { + dataType: DataTypes.String, + id: 'partition--string--tag--false', + isColumn: false, + isJSON: false, + key: 'partition', + type: 'tag', + }, + ], + having: [], + legend: '', + limit: null, + orderBy: [], + queryName: 'A', + reduceTo: 'avg', + spaceAggregation: 'avg', + stepInterval: 60, + timeAggregation: 'avg', + }, + ], + title: 'Consumer Offest', + description: 'Current offset of each consumer group for each topic partition', + }), +); + +export const consumerGroupMemberWidgetData = getWidgetQueryBuilder( + getWidgetQuery({ + queryData: [ + { + aggregateAttribute: { + dataType: DataTypes.Float64, + id: 'kafka_consumer_group_members--float64--Gauge--true', + isColumn: true, + isJSON: false, + key: 'kafka_consumer_group_members', + type: 'Gauge', + }, + aggregateOperator: 'sum', + dataSource: DataSource.METRICS, + disabled: false, + expression: 'A', + filters: { + items: [], + op: 'AND', + }, + functions: [], + groupBy: [ + { + dataType: DataTypes.String, + id: 'group--string--tag--false', + isColumn: false, + isJSON: false, + key: 'group', + type: 'tag', + }, + ], + having: [], + legend: '', + limit: null, + orderBy: [], + queryName: 'A', + reduceTo: 'avg', + spaceAggregation: 'sum', + stepInterval: 60, + timeAggregation: 'sum', + }, + ], + title: 'Consumer Group Members', + description: 'Number of active users in each group', + }), +); + +export const consumerLagByGroupWidgetData = getWidgetQueryBuilder( + getWidgetQuery({ + queryData: [ + { + aggregateAttribute: { + dataType: DataTypes.Float64, + id: 'kafka_consumer_group_lag--float64--Gauge--true', + isColumn: true, + isJSON: false, + key: 'kafka_consumer_group_lag', + type: 'Gauge', + }, + aggregateOperator: 'avg', + dataSource: DataSource.METRICS, + disabled: false, + expression: 'A', + filters: { + items: [], + op: 'AND', + }, + functions: [], + groupBy: [ + { + dataType: DataTypes.String, + id: 'group--string--tag--false', + isColumn: false, + isJSON: false, + key: 'group', + type: 'tag', + }, + { + dataType: DataTypes.String, + id: 'topic--string--tag--false', + isColumn: false, + isJSON: false, + key: 'topic', + type: 'tag', + }, + { + dataType: DataTypes.String, + id: 'partition--string--tag--false', + isColumn: false, + isJSON: false, + key: 'partition', + type: 'tag', + }, + ], + having: [], + legend: '', + limit: null, + orderBy: [], + queryName: 'A', + reduceTo: 'avg', + spaceAggregation: 'avg', + stepInterval: 60, + timeAggregation: 'avg', + }, + ], + title: 'Consumer Lag by Group', + description: + 'Helps Kafka administrators assess whether consumer groups are keeping up with the incoming data stream or falling behind', + }), +); + +export const consumerFetchRateWidgetData = getWidgetQueryBuilder( + getWidgetQuery({ + queryData: [ + { + aggregateAttribute: { + dataType: DataTypes.Float64, + id: 'kafka_consumer_fetch_rate--float64--Gauge--true', + isColumn: true, + isJSON: false, + key: 'kafka_consumer_fetch_rate', + type: 'Gauge', + }, + aggregateOperator: 'avg', + dataSource: DataSource.METRICS, + disabled: false, + expression: 'A', + filters: { + items: [], + op: 'AND', + }, + functions: [], + groupBy: [ + { + dataType: DataTypes.String, + id: 'service_name--string--tag--false', + isColumn: false, + isJSON: false, + key: 'service_name', + type: 'tag', + }, + ], + having: [], + legend: '', + limit: null, + orderBy: [], + queryName: 'A', + reduceTo: 'avg', + spaceAggregation: 'avg', + stepInterval: 60, + timeAggregation: 'avg', + }, + ], + title: 'Consumer Fetch Rate', + description: + 'Metric measures the rate at which fetch requests are made by a Kafka consumer to the broker, typically in requests per second.', + }), +); + +export const messagesConsumedWidgetData = getWidgetQueryBuilder( + getWidgetQuery({ + queryData: [ + { + aggregateAttribute: { + dataType: DataTypes.Float64, + id: 'kafka_consumer_records_consumed_rate--float64--Gauge--true', + isColumn: true, + isJSON: false, + key: 'kafka_consumer_records_consumed_rate', + type: 'Gauge', + }, + aggregateOperator: 'avg', + dataSource: DataSource.METRICS, + disabled: false, + expression: 'A', + filters: { + items: [], + op: 'AND', + }, + functions: [], + groupBy: [], + having: [], + legend: 'Messages Consumed', + limit: null, + orderBy: [], + queryName: 'A', + reduceTo: 'avg', + spaceAggregation: 'avg', + stepInterval: 60, + timeAggregation: 'avg', + }, + ], + title: 'Messages Consumed', + description: + 'Measures the rate at which a Kafka consumer is consuming records (messages) per second from Kafka brokers.', + }), +); + +export const jvmGCCountWidgetData = getWidgetQueryBuilder( + getWidgetQuery({ + queryData: [ + { + aggregateAttribute: { + dataType: DataTypes.Float64, + id: 'jvm_gc_collections_count--float64--Sum--true', + isColumn: true, + isJSON: false, + key: 'jvm_gc_collections_count', + type: 'Sum', + }, + aggregateOperator: 'rate', + dataSource: DataSource.METRICS, + disabled: false, + expression: 'A', + filters: { + items: [], + op: 'AND', + }, + functions: [], + groupBy: [], + having: [], + legend: 'JVM GC Count', + limit: null, + orderBy: [], + queryName: 'A', + reduceTo: 'avg', + spaceAggregation: 'sum', + stepInterval: 60, + timeAggregation: 'rate', + }, + ], + title: 'JVM GC Count', + description: + 'Tracks the total number of garbage collection (GC) events that have occurred in the Java Virtual Machine (JVM).', + }), +); + +export const jvmGcCollectionsElapsedWidgetData = getWidgetQueryBuilder( + getWidgetQuery({ + queryData: [ + { + aggregateAttribute: { + dataType: DataTypes.Float64, + id: 'jvm_gc_collections_elapsed--float64--Sum--true', + isColumn: true, + isJSON: false, + key: 'jvm_gc_collections_elapsed', + type: 'Sum', + }, + aggregateOperator: 'rate', + dataSource: DataSource.METRICS, + disabled: false, + expression: 'A', + filters: { + items: [], + op: 'AND', + }, + functions: [], + groupBy: [], + having: [], + legend: 'garbagecollector', + limit: null, + orderBy: [], + queryName: 'A', + reduceTo: 'avg', + spaceAggregation: 'sum', + stepInterval: 60, + timeAggregation: 'rate', + }, + ], + title: 'jvm_gc_collections_elapsed', + description: + 'Measures the total time (usually in milliseconds) spent on garbage collection (GC) events in the Java Virtual Machine (JVM).', + }), +); + +export const cpuRecentUtilizationWidgetData = getWidgetQueryBuilder( + getWidgetQuery({ + queryData: [ + { + aggregateAttribute: { + dataType: DataTypes.Float64, + id: 'jvm_cpu_recent_utilization--float64--Gauge--true', + isColumn: true, + isJSON: false, + key: 'jvm_cpu_recent_utilization', + type: 'Gauge', + }, + aggregateOperator: 'avg', + dataSource: DataSource.METRICS, + disabled: false, + expression: 'A', + filters: { + items: [], + op: 'AND', + }, + functions: [], + groupBy: [], + having: [], + legend: 'CPU utilization', + limit: null, + orderBy: [], + queryName: 'A', + reduceTo: 'avg', + spaceAggregation: 'avg', + stepInterval: 60, + timeAggregation: 'avg', + }, + ], + title: 'CPU Recent Utilization', + description: + 'This metric measures the recent CPU usage by the Java Virtual Machine (JVM), typically expressed as a percentage.', + }), +); + +export const jvmMemoryHeapWidgetData = getWidgetQueryBuilder( + getWidgetQuery({ + queryData: [ + { + aggregateAttribute: { + dataType: DataTypes.Float64, + id: 'jvm_memory_heap_max--float64--Gauge--true', + isColumn: true, + isJSON: false, + key: 'jvm_memory_heap_max', + type: 'Gauge', + }, + aggregateOperator: 'avg', + dataSource: DataSource.METRICS, + disabled: false, + expression: 'A', + filters: { + items: [], + op: 'AND', + }, + functions: [], + groupBy: [], + having: [], + legend: 'JVM memory heap', + limit: null, + orderBy: [], + queryName: 'A', + reduceTo: 'avg', + spaceAggregation: 'avg', + stepInterval: 60, + timeAggregation: 'avg', + }, + ], + title: 'JVM memory heap', + description: + 'The metric represents the maximum amount of heap memory available to the Java Virtual Machine (JVM)', + }), +); + +export const partitionCountPerTopicWidgetData = getWidgetQueryBuilder( + getWidgetQuery({ + queryData: [ + { + aggregateAttribute: { + dataType: DataTypes.Float64, + id: 'kafka_topic_partitions--float64--Gauge--true', + isColumn: true, + isJSON: false, + key: 'kafka_topic_partitions', + type: 'Gauge', + }, + aggregateOperator: 'sum', + dataSource: DataSource.METRICS, + disabled: false, + expression: 'A', + filters: { + items: [], + op: 'AND', + }, + functions: [], + groupBy: [ + { + dataType: DataTypes.String, + id: 'topic--string--tag--false', + isColumn: false, + isJSON: false, + key: 'topic', + type: 'tag', + }, + ], + having: [], + legend: '', + limit: null, + orderBy: [], + queryName: 'A', + reduceTo: 'avg', + spaceAggregation: 'sum', + stepInterval: 60, + timeAggregation: 'sum', + }, + ], + title: 'Partition Count per Topic', + description: 'Number of partitions for each topic', + }), +); + +export const currentOffsetPartitionWidgetData = getWidgetQueryBuilder( + getWidgetQuery({ + queryData: [ + { + aggregateAttribute: { + dataType: DataTypes.Float64, + id: 'kafka_partition_current_offset--float64--Gauge--true', + isColumn: true, + isJSON: false, + key: 'kafka_partition_current_offset', + type: 'Gauge', + }, + aggregateOperator: 'avg', + dataSource: DataSource.METRICS, + disabled: false, + expression: 'A', + filters: { + items: [], + op: 'AND', + }, + functions: [], + groupBy: [ + { + dataType: DataTypes.String, + id: 'topic--string--tag--false', + isColumn: false, + isJSON: false, + key: 'topic', + type: 'tag', + }, + { + dataType: DataTypes.String, + id: 'partition--string--tag--false', + isColumn: false, + isJSON: false, + key: 'partition', + type: 'tag', + }, + ], + having: [], + legend: '', + limit: null, + orderBy: [], + queryName: 'A', + reduceTo: 'avg', + spaceAggregation: 'avg', + stepInterval: 60, + timeAggregation: 'avg', + }, + ], + title: 'Current Offset ( Partition )', + description: + 'Current offset of each partition, showing the latest position in each partition', + }), +); + +export const oldestOffsetWidgetData = getWidgetQueryBuilder( + getWidgetQuery({ + queryData: [ + { + aggregateAttribute: { + dataType: DataTypes.Float64, + id: 'kafka_partition_oldest_offset--float64--Gauge--true', + isColumn: true, + isJSON: false, + key: 'kafka_partition_oldest_offset', + type: 'Gauge', + }, + aggregateOperator: 'avg', + dataSource: DataSource.METRICS, + disabled: false, + expression: 'A', + filters: { + items: [], + op: 'AND', + }, + functions: [], + groupBy: [ + { + dataType: DataTypes.String, + id: 'topic--string--tag--false', + isColumn: false, + isJSON: false, + key: 'topic', + type: 'tag', + }, + { + dataType: DataTypes.String, + id: 'partition--string--tag--false', + isColumn: false, + isJSON: false, + key: 'partition', + type: 'tag', + }, + ], + having: [], + legend: '', + limit: null, + orderBy: [], + queryName: 'A', + reduceTo: 'avg', + spaceAggregation: 'avg', + stepInterval: 60, + timeAggregation: 'avg', + }, + ], + title: 'Oldest Offset (Partition)', + description: + 'Oldest offset of each partition to identify log retention and offset range.', + }), +); + +export const insyncReplicasWidgetData = getWidgetQueryBuilder( + getWidgetQuery({ + queryData: [ + { + aggregateAttribute: { + dataType: DataTypes.Float64, + id: 'kafka_partition_replicas_in_sync--float64--Gauge--true', + isColumn: true, + isJSON: false, + key: 'kafka_partition_replicas_in_sync', + type: 'Gauge', + }, + aggregateOperator: 'avg', + dataSource: DataSource.METRICS, + disabled: false, + expression: 'A', + filters: { + items: [], + op: 'AND', + }, + functions: [], + groupBy: [ + { + dataType: DataTypes.String, + id: 'topic--string--tag--false', + isColumn: false, + isJSON: false, + key: 'topic', + type: 'tag', + }, + { + dataType: DataTypes.String, + id: 'partition--string--tag--false', + isColumn: false, + isJSON: false, + key: 'partition', + type: 'tag', + }, + ], + having: [], + legend: '', + limit: null, + orderBy: [], + queryName: 'A', + reduceTo: 'avg', + spaceAggregation: 'avg', + stepInterval: 60, + timeAggregation: 'avg', + }, + ], + title: 'In-Sync Replicas (ISR)', + description: + 'Count of in-sync replicas for each partition to ensure data availability.', + }), +); diff --git a/frontend/src/pages/MessagingQueues/MessagingQueueHealthCheck/MessagingQueueHealthCheck.styles.scss b/frontend/src/pages/MessagingQueues/MessagingQueueHealthCheck/MessagingQueueHealthCheck.styles.scss index 22a1bed584..4e7bd9a64c 100644 --- a/frontend/src/pages/MessagingQueues/MessagingQueueHealthCheck/MessagingQueueHealthCheck.styles.scss +++ b/frontend/src/pages/MessagingQueues/MessagingQueueHealthCheck/MessagingQueueHealthCheck.styles.scss @@ -166,3 +166,77 @@ padding-right: 8px; } } + +.lightMode { + .mq-health-check-modal { + .ant-modal-content { + border: 1px solid var(--bg-vanilla-400); + background: var(--bg-vanilla-200); + + .ant-modal-header { + border-bottom: 1px solid var(--bg-vanilla-400); + background: var(--bg-vanilla-200); + + .ant-modal-title { + color: var(--bg-ink-300); + } + } + + .modal-content { + background: var(--bg-vanilla-100); + + .attribute-select { + .ant-select-selector { + border: 1px solid var(--bg-vanilla-300); + background: var(--bg-vanilla-200); + } + } + + .tree-text { + color: var(--bg-ink-300); + } + + .ant-tree { + .ant-tree-title { + .attribute-error-title { + color: var(--bg-amber-500); + + .tree-text { + color: var(--bg-amber-500); + } + } + + .attribute-success-title { + .success-attribute-icon { + color: var(--bg-ink-300); + } + } + } + } + } + + .loader-container { + background: var(--bg-ink-300); + } + } + } + + .config-btn { + background: var(--bg-vanilla-300); + + &.missing-config-btn { + background: var(--bg-amber-100); + color: var(--bg-amber-500); + + &:hover { + color: var(--bg-amber-600) !important; + } + } + + .missing-config-btn { + .config-btn-content { + border-right: 1px solid var(--bg-amber-600); + } + } + } +} diff --git a/frontend/src/pages/MessagingQueues/MessagingQueues.styles.scss b/frontend/src/pages/MessagingQueues/MessagingQueues.styles.scss index 9959bebe26..9edcd928a3 100644 --- a/frontend/src/pages/MessagingQueues/MessagingQueues.styles.scss +++ b/frontend/src/pages/MessagingQueues/MessagingQueues.styles.scss @@ -222,6 +222,12 @@ } } + :nth-child(2), + :nth-child(4) { + border-left: none !important; + border-right: none !important; + } + &.summary-section { .overview-info-card { min-height: 144px; @@ -331,6 +337,10 @@ .messaging-breadcrumb { color: var(--bg-ink-400); border-bottom: 1px solid var(--bg-vanilla-300); + + .message-queue-text { + color: var(--bg-ink-400); + } } .messaging-header { color: var(--bg-ink-400); diff --git a/frontend/src/pages/MessagingQueues/MessagingQueues.tsx b/frontend/src/pages/MessagingQueues/MessagingQueues.tsx index 34063fc3b8..74bc1f3796 100644 --- a/frontend/src/pages/MessagingQueues/MessagingQueues.tsx +++ b/frontend/src/pages/MessagingQueues/MessagingQueues.tsx @@ -156,7 +156,7 @@ function MessagingQueues(): JSX.Element { -
+

{t('summarySection.producer.title')}

@@ -174,7 +174,7 @@ function MessagingQueues(): JSX.Element {

-
+

{t('summarySection.partition.title')}

@@ -210,6 +210,24 @@ function MessagingQueues(): JSX.Element {

+
+
+

{t('summarySection.metricPage.title')}

+

+ {t('summarySection.metricPage.description')} +

+
+
+ +
+
diff --git a/frontend/src/pages/MessagingQueues/MessagingQueuesUtils.ts b/frontend/src/pages/MessagingQueues/MessagingQueuesUtils.ts index 024c2dfb1c..ec7fadcdce 100644 --- a/frontend/src/pages/MessagingQueues/MessagingQueuesUtils.ts +++ b/frontend/src/pages/MessagingQueues/MessagingQueuesUtils.ts @@ -222,7 +222,8 @@ export enum MessagingQueuesViewTypeOptions { ConsumerLag = 'consumerLag', PartitionLatency = 'partitionLatency', ProducerLatency = 'producerLatency', - ConsumerLatency = 'consumerLatency', + DropRate = 'dropRate', + MetricPage = 'metricPage', } export const MessagingQueuesViewType = { @@ -240,7 +241,11 @@ export const MessagingQueuesViewType = { }, dropRate: { label: 'Drop Rate view', - value: 'dropRate', + value: MessagingQueuesViewTypeOptions.DropRate, + }, + metricPage: { + label: 'Metric view', + value: MessagingQueuesViewTypeOptions.MetricPage, }, };