1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-09-24 17:51:14 +02:00

feat: histogram impact metric UI

This commit is contained in:
kwasniew 2025-09-24 10:36:11 +02:00
parent d33e57a05f
commit 63b072648a
No known key found for this signature in database
GPG Key ID: 43A7CBC24C119560
6 changed files with 59 additions and 20 deletions

View File

@ -5,7 +5,7 @@ import type { AggregationMode } from '../../../types.ts';
export type ModeSelectorProps = { export type ModeSelectorProps = {
value: AggregationMode; value: AggregationMode;
onChange: (mode: AggregationMode) => void; onChange: (mode: AggregationMode) => void;
seriesType: 'counter' | 'gauge' | 'unknown'; seriesType: 'counter' | 'gauge' | 'histogram' | 'unknown';
}; };
export const ModeSelector: FC<ModeSelectorProps> = ({ export const ModeSelector: FC<ModeSelectorProps> = ({
@ -32,14 +32,28 @@ export const ModeSelector: FC<ModeSelectorProps> = ({
Count Count
</MenuItem>, </MenuItem>,
] ]
: [ : seriesType === 'gauge'
<MenuItem key='avg' value='avg'> ? [
Average <MenuItem key='avg' value='avg'>
</MenuItem>, Average
<MenuItem key='sum' value='sum'> </MenuItem>,
Sum <MenuItem key='sum' value='sum'>
</MenuItem>, Sum
]} </MenuItem>,
]
: seriesType === 'histogram'
? [
<MenuItem key='p50' value='p50'>
50th percentile
</MenuItem>,
<MenuItem key='p95' value='p95'>
95th percentile
</MenuItem>,
<MenuItem key='p99' value='p99'>
99th percentile
</MenuItem>,
]
: []}
</Select> </Select>
</FormControl> </FormControl>
); );

View File

@ -2,7 +2,7 @@ import { useState, useEffect } from 'react';
import { useImpactMetricsData } from 'hooks/api/getters/useImpactMetricsData/useImpactMetricsData'; import { useImpactMetricsData } from 'hooks/api/getters/useImpactMetricsData/useImpactMetricsData';
import type { AggregationMode, ChartConfig } from '../types.ts'; import type { AggregationMode, ChartConfig } from '../types.ts';
import type { ImpactMetricsLabels } from 'hooks/api/getters/useImpactMetricsData/useImpactMetricsData'; import type { ImpactMetricsLabels } from 'hooks/api/getters/useImpactMetricsData/useImpactMetricsData';
import { getMetricType } from '../utils.ts'; import { getDefaultAggregation, getMetricType } from '../utils.ts';
type UseChartConfigParams = { type UseChartConfigParams = {
open: boolean; open: boolean;
@ -48,10 +48,12 @@ export const useChartFormState = ({
Record<string, string[]> Record<string, string[]>
>(initialConfig?.labelSelectors || {}); >(initialConfig?.labelSelectors || {});
const [aggregationMode, setAggregationMode] = useState<AggregationMode>( const [aggregationMode, setAggregationMode] = useState<AggregationMode>(
(initialConfig?.aggregationMode || getMetricType(metricName)) === initialConfig?.aggregationMode ||
'counter' (getMetricType(metricName) === 'counter'
? 'count' ? 'count'
: 'avg', : getMetricType(metricName) === 'histogram'
? 'p50'
: 'avg'),
); );
const { const {
@ -75,9 +77,7 @@ export const useChartFormState = ({
setLabelSelectors(initialConfig.labelSelectors); setLabelSelectors(initialConfig.labelSelectors);
setAggregationMode( setAggregationMode(
initialConfig.aggregationMode || initialConfig.aggregationMode ||
(getMetricType(initialConfig.metricName) === 'counter' getDefaultAggregation(initialConfig.metricName),
? 'count'
: 'avg'),
); );
} else if (open && !initialConfig) { } else if (open && !initialConfig) {
setTitle(''); setTitle('');
@ -97,6 +97,8 @@ export const useChartFormState = ({
setAggregationMode('count'); setAggregationMode('count');
} else if (metric === 'gauge') { } else if (metric === 'gauge') {
setAggregationMode('avg'); setAggregationMode('avg');
} else if (metric === 'histogram') {
setAggregationMode('p50');
} }
}; };

View File

@ -8,10 +8,17 @@ export type ChartConfig = {
title?: string; title?: string;
}; };
export type AggregationMode = 'rps' | 'count' | 'avg' | 'sum'; export type AggregationMode =
| 'rps'
| 'count'
| 'avg'
| 'sum'
| 'p50'
| 'p95'
| 'p99';
export type DisplayChartConfig = ChartConfig & { export type DisplayChartConfig = ChartConfig & {
type: 'counter' | 'gauge' | 'unknown'; type: 'counter' | 'gauge' | 'histogram' | 'unknown';
displayName: string; // e.g. my_metric with unleash_counter stripped displayName: string; // e.g. my_metric with unleash_counter stripped
}; };

View File

@ -64,5 +64,18 @@ export const formatLargeNumbers = (value: number): string => {
export const getMetricType = (seriesName: string) => { export const getMetricType = (seriesName: string) => {
if (seriesName.startsWith('unleash_counter_')) return 'counter'; if (seriesName.startsWith('unleash_counter_')) return 'counter';
if (seriesName.startsWith('unleash_gauge_')) return 'gauge'; if (seriesName.startsWith('unleash_gauge_')) return 'gauge';
if (seriesName.startsWith('unleash_histogram_')) return 'histogram';
return 'unknown'; return 'unknown';
}; };
export const getDefaultAggregation = (seriesName: string) => {
const metricType = getMetricType(seriesName);
if (metricType === 'counter') {
return 'count';
}
if (metricType === 'histogram') {
return 'p50';
}
return 'avg';
};

View File

@ -27,7 +27,7 @@ export type ImpactMetricsQuery = {
series: string; series: string;
range: 'hour' | 'day' | 'week' | 'month'; range: 'hour' | 'day' | 'week' | 'month';
labels?: Record<string, string[]>; labels?: Record<string, string[]>;
aggregationMode?: 'rps' | 'count' | 'avg' | 'sum'; aggregationMode?: 'rps' | 'count' | 'avg' | 'sum' | 'p50' | 'p95' | 'p99';
}; };
export const useImpactMetricsData = (query?: ImpactMetricsQuery) => { export const useImpactMetricsData = (query?: ImpactMetricsQuery) => {

View File

@ -16,4 +16,7 @@ export const CreateImpactMetricsConfigSchemaAggregationMode = {
count: 'count', count: 'count',
avg: 'avg', avg: 'avg',
sum: 'sum', sum: 'sum',
p50: 'p50',
p95: 'p95',
p99: 'p99',
} as const; } as const;