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

feat: histogram impact metric UI (#10684)

This commit is contained in:
Mateusz Kwasniewski 2025-09-24 10:53:58 +02:00 committed by GitHub
parent b4ad9c964f
commit efdfb67c9f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 58 additions and 24 deletions

View File

@ -58,7 +58,7 @@ export const ImpactMetricsControls: FC<ImpactMetricsControlsProps> = ({
<ModeSelector
value={formData.aggregationMode}
onChange={actions.setAggregationMode}
seriesType={getMetricType(formData.metricName)!}
metricType={getMetricType(formData.metricName)!}
/>
</>
) : null}

View File

@ -5,15 +5,15 @@ import type { AggregationMode } from '../../../types.ts';
export type ModeSelectorProps = {
value: AggregationMode;
onChange: (mode: AggregationMode) => void;
seriesType: 'counter' | 'gauge' | 'unknown';
metricType: 'counter' | 'gauge' | 'histogram' | 'unknown';
};
export const ModeSelector: FC<ModeSelectorProps> = ({
value,
onChange,
seriesType,
metricType,
}) => {
if (seriesType === 'unknown') return null;
if (metricType === 'unknown') return null;
return (
<FormControl variant='outlined' size='small' sx={{ minWidth: 200 }}>
<InputLabel id='mode-select-label'>Mode</InputLabel>
@ -23,7 +23,7 @@ export const ModeSelector: FC<ModeSelectorProps> = ({
onChange={(e) => onChange(e.target.value as AggregationMode)}
label='Mode'
>
{seriesType === 'counter'
{metricType === 'counter'
? [
<MenuItem key='rps' value='rps'>
Rate per second
@ -32,14 +32,28 @@ export const ModeSelector: FC<ModeSelectorProps> = ({
Count
</MenuItem>,
]
: [
<MenuItem key='avg' value='avg'>
Average
</MenuItem>,
<MenuItem key='sum' value='sum'>
Sum
</MenuItem>,
]}
: metricType === 'gauge'
? [
<MenuItem key='avg' value='avg'>
Average
</MenuItem>,
<MenuItem key='sum' value='sum'>
Sum
</MenuItem>,
]
: metricType === '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>
</FormControl>
);

View File

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

View File

@ -8,10 +8,17 @@ export type ChartConfig = {
title?: string;
};
export type AggregationMode = 'rps' | 'count' | 'avg' | 'sum';
export type AggregationMode =
| 'rps'
| 'count'
| 'avg'
| 'sum'
| 'p50'
| 'p95'
| 'p99';
export type DisplayChartConfig = ChartConfig & {
type: 'counter' | 'gauge' | 'unknown';
type: 'counter' | 'gauge' | 'histogram' | 'unknown';
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) => {
if (seriesName.startsWith('unleash_counter_')) return 'counter';
if (seriesName.startsWith('unleash_gauge_')) return 'gauge';
if (seriesName.startsWith('unleash_histogram_')) return 'histogram';
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;
range: 'hour' | 'day' | 'week' | 'month';
labels?: Record<string, string[]>;
aggregationMode?: 'rps' | 'count' | 'avg' | 'sum';
aggregationMode?: 'rps' | 'count' | 'avg' | 'sum' | 'p50' | 'p95' | 'p99';
};
export const useImpactMetricsData = (query?: ImpactMetricsQuery) => {

View File

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