From 1b3471a4606a16f530f004583cde8aab4a8577e1 Mon Sep 17 00:00:00 2001 From: Akila-I Date: Fri, 21 Nov 2025 15:10:29 +0530 Subject: [PATCH 1/3] Update observer openAPI spec and generated types --- .../openapi/openchoreo-observability-api.yaml | 109 +++++++++++++ .../src/generated/observability/types.ts | 154 +++++++++++++++++- 2 files changed, 262 insertions(+), 1 deletion(-) diff --git a/packages/openchoreo-client-node/openapi/openchoreo-observability-api.yaml b/packages/openchoreo-client-node/openapi/openchoreo-observability-api.yaml index 4a35b2fb..cb333ee8 100644 --- a/packages/openchoreo-client-node/openapi/openchoreo-observability-api.yaml +++ b/packages/openchoreo-client-node/openapi/openchoreo-observability-api.yaml @@ -244,6 +244,39 @@ paths: schema: $ref: '#/components/schemas/ErrorResponse' + /api/metrics/component/http: + post: + tags: + - Metrics + summary: Get component HTTP metrics + description: Retrieve HTTP request metrics (request counts, latency percentiles) for a component as time series data + operationId: getComponentHTTPMetrics + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/MetricsRequest' + responses: + '200': + description: Successfully retrieved HTTP metrics + content: + application/json: + schema: + $ref: '#/components/schemas/HTTPMetricsTimeSeries' + '400': + description: Bad request - invalid parameters + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + /api/metrics/component/usage: post: tags: @@ -476,6 +509,7 @@ components: MetricsRequest: type: object required: + - componentId - environmentId - projectId properties: @@ -623,6 +657,81 @@ components: - time: '2025-01-10T12:05:00Z' value: 2147483648 + HTTPMetricsTimeSeries: + type: object + properties: + requestCount: + type: array + items: + $ref: '#/components/schemas/TimeValuePoint' + description: Total HTTP request count time series (requests per second) + successfulRequestCount: + type: array + items: + $ref: '#/components/schemas/TimeValuePoint' + description: Successful HTTP request count time series (status 200, requests per second) + unsuccessfulRequestCount: + type: array + items: + $ref: '#/components/schemas/TimeValuePoint' + description: Unsuccessful HTTP request count time series (status != 200, requests per second) + meanLatency: + type: array + items: + $ref: '#/components/schemas/TimeValuePoint' + description: Mean HTTP request latency time series (in seconds) + latencyPercentile50th: + type: array + items: + $ref: '#/components/schemas/TimeValuePoint' + description: 50th percentile (median) HTTP request latency time series (in seconds) + latencyPercentile90th: + type: array + items: + $ref: '#/components/schemas/TimeValuePoint' + description: 90th percentile HTTP request latency time series (in seconds) + latencyPercentile99th: + type: array + items: + $ref: '#/components/schemas/TimeValuePoint' + description: 99th percentile HTTP request latency time series (in seconds) + example: + requestCount: + - time: '2025-01-10T12:00:00Z' + value: 125.5 + - time: '2025-01-10T12:05:00Z' + value: 143.2 + successfulRequestCount: + - time: '2025-01-10T12:00:00Z' + value: 120.0 + - time: '2025-01-10T12:05:00Z' + value: 138.5 + unsuccessfulRequestCount: + - time: '2025-01-10T12:00:00Z' + value: 5.5 + - time: '2025-01-10T12:05:00Z' + value: 4.7 + meanLatency: + - time: '2025-01-10T12:00:00Z' + value: 0.125 + - time: '2025-01-10T12:05:00Z' + value: 0.132 + latencyPercentile50th: + - time: '2025-01-10T12:00:00Z' + value: 0.095 + - time: '2025-01-10T12:05:00Z' + value: 0.102 + latencyPercentile90th: + - time: '2025-01-10T12:00:00Z' + value: 0.250 + - time: '2025-01-10T12:05:00Z' + value: 0.265 + latencyPercentile99th: + - time: '2025-01-10T12:00:00Z' + value: 0.500 + - time: '2025-01-10T12:05:00Z' + value: 0.520 + ErrorResponse: type: object required: diff --git a/packages/openchoreo-client-node/src/generated/observability/types.ts b/packages/openchoreo-client-node/src/generated/observability/types.ts index b6d3a130..d062f78a 100644 --- a/packages/openchoreo-client-node/src/generated/observability/types.ts +++ b/packages/openchoreo-client-node/src/generated/observability/types.ts @@ -124,6 +124,26 @@ export interface paths { patch?: never; trace?: never; }; + '/api/metrics/component/http': { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * Get component HTTP metrics + * @description Retrieve HTTP request metrics (request counts, latency percentiles) for a component as time series data + */ + post: operations['getComponentHTTPMetrics']; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; '/api/metrics/component/usage': { parameters: { query?: never; @@ -350,7 +370,7 @@ export interface components { * @description Component identifier * @example comp-123 */ - componentId?: string; + componentId: string; /** * @description Environment identifier * @example env-dev @@ -507,6 +527,96 @@ export interface components { /** @description Memory limits time series (in bytes) */ memoryLimits?: components['schemas']['TimeValuePoint'][]; }; + /** + * @example { + * "requestCount": [ + * { + * "time": "2025-01-10T12:00:00Z", + * "value": 125.5 + * }, + * { + * "time": "2025-01-10T12:05:00Z", + * "value": 143.2 + * } + * ], + * "successfulRequestCount": [ + * { + * "time": "2025-01-10T12:00:00Z", + * "value": 120 + * }, + * { + * "time": "2025-01-10T12:05:00Z", + * "value": 138.5 + * } + * ], + * "unsuccessfulRequestCount": [ + * { + * "time": "2025-01-10T12:00:00Z", + * "value": 5.5 + * }, + * { + * "time": "2025-01-10T12:05:00Z", + * "value": 4.7 + * } + * ], + * "meanLatency": [ + * { + * "time": "2025-01-10T12:00:00Z", + * "value": 0.125 + * }, + * { + * "time": "2025-01-10T12:05:00Z", + * "value": 0.132 + * } + * ], + * "latencyPercentile50th": [ + * { + * "time": "2025-01-10T12:00:00Z", + * "value": 0.095 + * }, + * { + * "time": "2025-01-10T12:05:00Z", + * "value": 0.102 + * } + * ], + * "latencyPercentile90th": [ + * { + * "time": "2025-01-10T12:00:00Z", + * "value": 0.25 + * }, + * { + * "time": "2025-01-10T12:05:00Z", + * "value": 0.265 + * } + * ], + * "latencyPercentile99th": [ + * { + * "time": "2025-01-10T12:00:00Z", + * "value": 0.5 + * }, + * { + * "time": "2025-01-10T12:05:00Z", + * "value": 0.52 + * } + * ] + * } + */ + HTTPMetricsTimeSeries: { + /** @description Total HTTP request count time series (requests per second) */ + requestCount?: components['schemas']['TimeValuePoint'][]; + /** @description Successful HTTP request count time series (status 200, requests per second) */ + successfulRequestCount?: components['schemas']['TimeValuePoint'][]; + /** @description Unsuccessful HTTP request count time series (status != 200, requests per second) */ + unsuccessfulRequestCount?: components['schemas']['TimeValuePoint'][]; + /** @description Mean HTTP request latency time series (in seconds) */ + meanLatency?: components['schemas']['TimeValuePoint'][]; + /** @description 50th percentile (median) HTTP request latency time series (in seconds) */ + latencyPercentile50th?: components['schemas']['TimeValuePoint'][]; + /** @description 90th percentile HTTP request latency time series (in seconds) */ + latencyPercentile90th?: components['schemas']['TimeValuePoint'][]; + /** @description 99th percentile HTTP request latency time series (in seconds) */ + latencyPercentile99th?: components['schemas']['TimeValuePoint'][]; + }; ErrorResponse: { /** * @description Error type @@ -790,6 +900,48 @@ export interface operations { }; }; }; + getComponentHTTPMetrics: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + 'application/json': components['schemas']['MetricsRequest']; + }; + }; + responses: { + /** @description Successfully retrieved HTTP metrics */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['HTTPMetricsTimeSeries']; + }; + }; + /** @description Bad request - invalid parameters */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['ErrorResponse']; + }; + }; + /** @description Internal server error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['ErrorResponse']; + }; + }; + }; + }; getComponentResourceMetrics: { parameters: { query?: never; From 4b8d7ca9efda27fa01261525cea210f1d328e2a6 Mon Sep 17 00:00:00 2001 From: Akila-I Date: Fri, 21 Nov 2025 15:27:41 +0530 Subject: [PATCH 2/3] Add network metrics support to observability plugin - Introduced new types for NetworkThroughputMetrics and NetworkLatencyMetrics in types.ts. - Updated ObservabilityApi to return comprehensive Metrics including network data. - Enhanced MetricGraphByComponent to visualize network throughput and latency metrics. - Added new components for displaying network metrics in ObservabilityMetricsPage. - Improved utility functions to handle formatting and transformation of network metrics data. --- .../src/services/ObservabilityService.ts | 38 ++++- .../src/types.ts | 4 + .../src/api/ObservabilityApi.ts | 17 ++- .../Metrics/MetricGraphByComponent.tsx | 29 +++- .../Metrics/ObservabilityMetricsPage.tsx | 43 +++++- .../src/components/Metrics/styles.ts | 21 ++- .../src/components/Metrics/utils.ts | 134 ++++++++++++++---- .../src/hooks/useMetrics.ts | 4 +- plugins/openchoreo-observability/src/types.ts | 17 ++- 9 files changed, 267 insertions(+), 40 deletions(-) diff --git a/plugins/openchoreo-observability-backend/src/services/ObservabilityService.ts b/plugins/openchoreo-observability-backend/src/services/ObservabilityService.ts index ab10be7e..9ed57f5f 100644 --- a/plugins/openchoreo-observability-backend/src/services/ObservabilityService.ts +++ b/plugins/openchoreo-observability-backend/src/services/ObservabilityService.ts @@ -9,7 +9,7 @@ import { createOpenChoreoApiClient, createObservabilityClientWithUrl, } from '@openchoreo/openchoreo-client-node'; -import { Environment, ResourceMetricsTimeSeries } from '../types'; +import { ComponentMetricsTimeSeries, Environment } from '../types'; /** * Error thrown when observability is not configured for a component @@ -132,7 +132,7 @@ export class ObservabilityService { startTime?: string; endTime?: string; }, - ): Promise { + ): Promise { const startTime = Date.now(); try { this.logger.debug( @@ -203,6 +203,22 @@ export class ObservabilityService { }, ); + const { + data: httpData, + error: httpError, + response: httpResponse, + } = await obsClient.POST('/api/metrics/component/http', { + body: { + componentId, + environmentId, + projectId, + limit: options?.limit || 100, + offset: options?.offset || 0, + startTime: options?.startTime, + endTime: options?.endTime, + }, + }); + if (error || !response.ok) { const errorText = await response.text(); this.logger.error( @@ -214,6 +230,17 @@ export class ObservabilityService { ); } + if (httpError || !httpResponse.ok) { + const errorText = await httpResponse.text(); + this.logger.error( + `Failed to fetch HTTP metrics for component ${componentId}: ${httpResponse.status} ${httpResponse.statusText}`, + { error: errorText }, + ); + throw new Error( + `Failed to fetch HTTP metrics: ${httpResponse.status} ${httpResponse.statusText}`, + ); + } + this.logger.debug( `Successfully fetched metrics for component ${componentId}: ${JSON.stringify( data, @@ -234,6 +261,13 @@ export class ObservabilityService { memory: data.memory ?? [], memoryRequests: data.memoryRequests ?? [], memoryLimits: data.memoryLimits ?? [], + requestCount: httpData.requestCount ?? [], + successfulRequestCount: httpData.successfulRequestCount ?? [], + unsuccessfulRequestCount: httpData.unsuccessfulRequestCount ?? [], + meanLatency: httpData.meanLatency ?? [], + latencyPercentile50th: httpData.latencyPercentile50th ?? [], + latencyPercentile90th: httpData.latencyPercentile90th ?? [], + latencyPercentile99th: httpData.latencyPercentile99th ?? [], }; } catch (error: unknown) { if (error instanceof ObservabilityNotConfiguredError) { diff --git a/plugins/openchoreo-observability-backend/src/types.ts b/plugins/openchoreo-observability-backend/src/types.ts index 8bfc08d2..8d0170c4 100644 --- a/plugins/openchoreo-observability-backend/src/types.ts +++ b/plugins/openchoreo-observability-backend/src/types.ts @@ -8,3 +8,7 @@ export type Environment = OpenChoreoComponents['schemas']['EnvironmentResponse']; export type ResourceMetricsTimeSeries = ObservabilityComponents['schemas']['ResourceMetricsTimeSeries']; + +export type ComponentMetricsTimeSeries = + ObservabilityComponents['schemas']['ResourceMetricsTimeSeries'] & + ObservabilityComponents['schemas']['HTTPMetricsTimeSeries']; diff --git a/plugins/openchoreo-observability/src/api/ObservabilityApi.ts b/plugins/openchoreo-observability/src/api/ObservabilityApi.ts index 93c56217..63939569 100644 --- a/plugins/openchoreo-observability/src/api/ObservabilityApi.ts +++ b/plugins/openchoreo-observability/src/api/ObservabilityApi.ts @@ -3,7 +3,7 @@ import { DiscoveryApi, FetchApi, } from '@backstage/core-plugin-api'; -import { UsageMetrics } from '../types'; +import { Metrics } from '../types'; export interface ObservabilityApi { getMetrics( @@ -20,7 +20,7 @@ export interface ObservabilityApi { startTime?: string; endTime?: string; }, - ): Promise; + ): Promise; } export const observabilityApiRef = createApiRef({ @@ -50,7 +50,7 @@ export class ObservabilityClient implements ObservabilityApi { startTime?: string; endTime?: string; }, - ): Promise { + ): Promise { const baseUrl = await this.discoveryApi.getBaseUrl( 'openchoreo-observability-backend', ); @@ -93,6 +93,17 @@ export class ObservabilityClient implements ObservabilityApi { memoryRequests: data.memoryRequests, memoryLimits: data.memoryLimits, }, + networkThroughput: { + requestCount: data.requestCount, + successfulRequestCount: data.successfulRequestCount, + unsuccessfulRequestCount: data.unsuccessfulRequestCount, + }, + networkLatency: { + meanLatency: data.meanLatency, + latencyPercentile50th: data.latencyPercentile50th, + latencyPercentile90th: data.latencyPercentile90th, + latencyPercentile99th: data.latencyPercentile99th, + }, }; } } diff --git a/plugins/openchoreo-observability/src/components/Metrics/MetricGraphByComponent.tsx b/plugins/openchoreo-observability/src/components/Metrics/MetricGraphByComponent.tsx index fbab3055..26cfcdf6 100644 --- a/plugins/openchoreo-observability/src/components/Metrics/MetricGraphByComponent.tsx +++ b/plugins/openchoreo-observability/src/components/Metrics/MetricGraphByComponent.tsx @@ -10,7 +10,12 @@ import { LegendPayload, } from 'recharts'; import { DataKey } from 'recharts/types/util/types'; -import { CpuUsageMetrics, MemoryUsageMetrics } from '../../types'; +import { + CpuUsageMetrics, + MemoryUsageMetrics, + NetworkLatencyMetrics, + NetworkThroughputMetrics, +} from '../../types'; import { formatAxisTime, formatTooltipTime, @@ -28,8 +33,12 @@ export const MetricGraphByComponent = ({ usageType, timeRange, }: { - usageData: CpuUsageMetrics | MemoryUsageMetrics; - usageType: 'cpu' | 'memory'; + usageData: + | CpuUsageMetrics + | MemoryUsageMetrics + | NetworkThroughputMetrics + | NetworkLatencyMetrics; + usageType: 'cpu' | 'memory' | 'networkThroughput' | 'networkLatency'; timeRange?: string; }) => { const classes = useMetricGraphStyles(); @@ -54,6 +63,20 @@ export const MetricGraphByComponent = ({ const handleMouseLeave = () => setHoveringDataKey(undefined); + if (transformedData.length === 0) { + return ( +
+
No data available
+ {(usageType === 'networkThroughput' || + usageType === 'networkLatency') && ( +

+ Network metrics are available in OpenChoreo Cilium Edition only. +

+ )} +
+ ); + } + return (
{ > {isObservabilityDisabled - ? 'Observability is not enabled for this component. Please enable observability to view metrics.' + ? 'Observability is not enabled for this component. Please enable observability to view runtime logs.' : error} {!isObservabilityDisabled && ( @@ -141,7 +147,7 @@ export const ObservabilityMetricsPage = () => { }; return ( - + {isLoading && } {!isLoading && ( @@ -183,6 +189,37 @@ export const ObservabilityMetricsPage = () => { + + + + + + + + + + + + + + + + + + )} diff --git a/plugins/openchoreo-observability/src/components/Metrics/styles.ts b/plugins/openchoreo-observability/src/components/Metrics/styles.ts index bef65a9d..7c8d8095 100644 --- a/plugins/openchoreo-observability/src/components/Metrics/styles.ts +++ b/plugins/openchoreo-observability/src/components/Metrics/styles.ts @@ -14,7 +14,7 @@ export const useMetricsActionsStyles = makeStyles((theme: Theme) => ({ }, })); -export const useMetricGraphStyles = makeStyles(() => ({ +export const useMetricGraphStyles = makeStyles((theme: Theme) => ({ chartContainer: { width: '100%', }, @@ -24,6 +24,25 @@ export const useMetricGraphStyles = makeStyles(() => ({ maxHeight: '70vh', aspectRatio: 1.618, }, + emptyChart: { + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + height: '100%', + fontSize: '1.2rem', + color: theme.palette.text.secondary, + }, + emptyChartText: { + alignItems: 'center', + justifyContent: 'center', + display: 'flex', + flexDirection: 'column', + width: '100%', + textAlign: 'center', + fontSize: '0.875rem', + color: theme.palette.text.secondary, + marginTop: theme.spacing(1), + }, })); export const useObservabilityMetricsPageStyles = makeStyles((theme: Theme) => ({ diff --git a/plugins/openchoreo-observability/src/components/Metrics/utils.ts b/plugins/openchoreo-observability/src/components/Metrics/utils.ts index 76e49339..a2bc5c58 100644 --- a/plugins/openchoreo-observability/src/components/Metrics/utils.ts +++ b/plugins/openchoreo-observability/src/components/Metrics/utils.ts @@ -1,5 +1,10 @@ import { DataKey } from 'recharts/types/util/types'; -import { CpuUsageMetrics, MemoryUsageMetrics } from '../../types'; +import { + CpuUsageMetrics, + MemoryUsageMetrics, + NetworkLatencyMetrics, + NetworkThroughputMetrics, +} from '../../types'; /** * Format timestamp for axis display based on the time range @@ -45,7 +50,7 @@ export const formatTooltipTime = (timestamp: number): string => { */ export const formatMetricValue = ( value: number, - usageType: 'cpu' | 'memory', + usageType: 'cpu' | 'memory' | 'networkThroughput' | 'networkLatency', ): string => { if (value === 0) return '0'; @@ -55,11 +60,22 @@ export const formatMetricValue = ( if (value > 0.001) return `${(value * 1000).toFixed(2)} mCPU`; return `${(value * 1000000).toFixed(2)} uCPU`; } - - // value is in Bytes - if (value > 1000000) return `${(value / 1000000).toFixed(2)} MB`; - if (value > 1000) return `${(value / 1000).toFixed(2)} KB`; - return `${value.toFixed(2)} B`; + if (usageType === 'memory') { + // value is in Bytes + if (value > 1000000) return `${(value / 1000000).toFixed(2)} MB`; + if (value > 1000) return `${(value / 1000).toFixed(2)} KB`; + return `${value.toFixed(2)} B`; + } + if (usageType === 'networkThroughput') { + return `${value.toFixed(2)} req/s`; + } + if (usageType === 'networkLatency') { + // value is in seconds + if (value > 1) return `${value.toFixed(2)} s`; + if (value > 0.001) return `${(value * 1000).toFixed(2)} ms`; + return `${(value * 1000000).toFixed(2)} us`; + } + return value.toFixed(2); }; /** @@ -129,7 +145,11 @@ export const calculateTimeDomain = ( * Transform metrics data structure to be compatible with Recharts */ export const transformMetricsData = ( - usageData: CpuUsageMetrics | MemoryUsageMetrics, + usageData: + | CpuUsageMetrics + | MemoryUsageMetrics + | NetworkThroughputMetrics + | NetworkLatencyMetrics, ) => { const timeMap = new Map(); @@ -158,21 +178,78 @@ export interface MetricConfig { } export const getMetricConfigs = ( - usageType: 'cpu' | 'memory', -): Record => ({ - usage: { - key: usageType === 'cpu' ? 'cpuUsage' : 'memoryUsage', - color: '#8884d8', - }, - requests: { - key: usageType === 'cpu' ? 'cpuRequests' : 'memoryRequests', - color: '#82ca9d', - }, - limits: { - key: usageType === 'cpu' ? 'cpuLimits' : 'memoryLimits', - color: '#ffc658', - }, -}); + usageType: 'cpu' | 'memory' | 'networkThroughput' | 'networkLatency', +): Record => { + if (usageType === 'networkThroughput') { + return { + totalRequests: { + key: 'requestCount', + color: '#8884d8', + }, + successfulRequests: { + key: 'successfulRequestCount', + color: '#82ca9d', + }, + unsuccessfulRequests: { + key: 'unsuccessfulRequestCount', + color: '#ff7f7f', + }, + }; + } + + if (usageType === 'networkLatency') { + return { + meanLatency: { + key: 'meanLatency', + color: '#8884d8', + }, + p50Latency: { + key: 'latencyPercentile50th', + color: '#82ca9d', + }, + p90Latency: { + key: 'latencyPercentile90th', + color: '#ffc658', + }, + p99Latency: { + key: 'latencyPercentile99th', + color: '#ff7300', + }, + }; + } + + if (usageType === 'cpu') { + return { + usage: { + key: 'cpuUsage', + color: '#8884d8', + }, + requests: { + key: 'cpuRequests', + color: '#82ca9d', + }, + limits: { + key: 'cpuLimits', + color: '#ffc658', + }, + }; + } + + return { + usage: { + key: 'memoryUsage', + color: '#8884d8', + }, + requests: { + key: 'memoryRequests', + color: '#82ca9d', + }, + limits: { + key: 'memoryLimits', + color: '#ffc658', + }, + }; +}; /** * Calculate opacity for metric lines based on hover state @@ -185,8 +262,15 @@ export const getLineOpacity = ( }; /** - * Format metric key to display name (e.g., 'cpuUsage' -> 'Cpu Usage') + * Format metric key to display name (e.g., 'cpuUsage' -> 'CPU Usage') */ export const formatMetricName = (key: string): string => { - return key.replace(/([A-Z])/g, ' $1').replace(/^./, str => str.toUpperCase()); + const name = key + .replace(/([A-Z])/g, ' $1') + .replace(/^./, str => str.toUpperCase()); + if (name.includes('Cpu')) { + // Capitalize to CPU + return name.replace('Cpu', 'CPU'); + } + return name; }; diff --git a/plugins/openchoreo-observability/src/hooks/useMetrics.ts b/plugins/openchoreo-observability/src/hooks/useMetrics.ts index 33291241..d3a5e31c 100644 --- a/plugins/openchoreo-observability/src/hooks/useMetrics.ts +++ b/plugins/openchoreo-observability/src/hooks/useMetrics.ts @@ -8,7 +8,7 @@ import { import { observabilityApiRef } from '../api/ObservabilityApi'; import { Filters } from '../types'; import { Entity } from '@backstage/catalog-model'; -import { UsageMetrics } from '../types'; +import { Metrics } from '../types'; import { CHOREO_ANNOTATIONS } from '@openchoreo/backstage-plugin-common'; async function getComponentDetails( @@ -111,7 +111,7 @@ export function useMetrics( const discovery = useApi(discoveryApiRef); const identity = useApi(identityApiRef); const fetchApi = useApi(fetchApiRef); - const [metrics, setMetrics] = useState(null); + const [metrics, setMetrics] = useState(null); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const [componentId, setComponentId] = useState(null); diff --git a/plugins/openchoreo-observability/src/types.ts b/plugins/openchoreo-observability/src/types.ts index b1cf4a6f..39478946 100644 --- a/plugins/openchoreo-observability/src/types.ts +++ b/plugins/openchoreo-observability/src/types.ts @@ -15,9 +15,24 @@ export type MemoryUsageMetrics = { memoryLimits: TimeValuePoint[]; }; -export type UsageMetrics = { +export type NetworkThroughputMetrics = { + requestCount: TimeValuePoint[]; + successfulRequestCount: TimeValuePoint[]; + unsuccessfulRequestCount: TimeValuePoint[]; +}; + +export type NetworkLatencyMetrics = { + meanLatency: TimeValuePoint[]; + latencyPercentile50th: TimeValuePoint[]; + latencyPercentile90th: TimeValuePoint[]; + latencyPercentile99th: TimeValuePoint[]; +}; + +export type Metrics = { cpuUsage: CpuUsageMetrics; memoryUsage: MemoryUsageMetrics; + networkThroughput: NetworkThroughputMetrics; + networkLatency: NetworkLatencyMetrics; }; export interface TimeRangeOption { From f26239cfcb04b7effa3f740af4a441a73881b15e Mon Sep 17 00:00:00 2001 From: Akila-I Date: Fri, 21 Nov 2025 10:39:03 +0530 Subject: [PATCH 3/3] Enhance Logs and Metrics Filters Labels - Updated InputLabel components in LogsFilter and MetricsFilters to include id attributes for improved accessibility. - Added label properties to Select components to ensure proper association with their corresponding labels. - Ensured consistent labeling across filter components for better user experience. --- .../src/components/Metrics/MetricsFilters.tsx | 13 +++++++++--- .../src/components/RuntimeLogs/LogsFilter.tsx | 21 ++++++++++++++----- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/plugins/openchoreo-observability/src/components/Metrics/MetricsFilters.tsx b/plugins/openchoreo-observability/src/components/Metrics/MetricsFilters.tsx index c1f47113..e301151f 100644 --- a/plugins/openchoreo-observability/src/components/Metrics/MetricsFilters.tsx +++ b/plugins/openchoreo-observability/src/components/Metrics/MetricsFilters.tsx @@ -54,10 +54,12 @@ export const MetricsFilters = ({ - Environment + Environment + Time Range + (selected as string[]).join(', ')} > {LOG_LEVELS.map(level => ( @@ -86,11 +88,13 @@ export const LogsFilter: FC = ({ - Selected Fields + Selected Fields {environments.map(env => ( @@ -132,8 +138,13 @@ export const LogsFilter: FC = ({ - Time Range - {TIME_RANGE_OPTIONS.map(option => ( {option.label}