Alerting: Improve displaying small numbers in query preview (#103439)
* Improve rendering of small numbers in the query preview * Use getSeriesValue in Expression component
This commit is contained in:
@@ -35,7 +35,7 @@ import { Spacer } from '../Spacer';
|
||||
import { AlertStateTag } from '../rules/AlertStateTag';
|
||||
|
||||
import { ExpressionStatusIndicator } from './ExpressionStatusIndicator';
|
||||
import { formatLabels, getSeriesLabels, getSeriesName, getSeriesValue, isEmptySeries } from './util';
|
||||
import { formatLabels, formatSeriesValue, getSeriesLabels, getSeriesName, getSeriesValue, isEmptySeries } from './util';
|
||||
|
||||
interface ExpressionProps {
|
||||
isAlertCondition?: boolean;
|
||||
@@ -438,7 +438,7 @@ function FrameRow({ frame, index, isAlertCondition, isRecordingRule }: FrameProp
|
||||
)}
|
||||
</Text>
|
||||
</div>
|
||||
<div className={styles.expression.resultValue}>{value}</div>
|
||||
<div className={styles.expression.resultValue}>{formatSeriesValue(value)}</div>
|
||||
{shouldRenderSumary && (
|
||||
<>
|
||||
{showFiring && <AlertStateTag state={PromAlertingRuleState.Firing} size="sm" />}
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
decodeGrafanaNamespace,
|
||||
encodeGrafanaNamespace,
|
||||
formatLabels,
|
||||
formatSeriesValue,
|
||||
getSeriesLabels,
|
||||
getSeriesName,
|
||||
getSeriesValue,
|
||||
@@ -24,10 +25,6 @@ const DATA_FRAME: DataFrame = toDataFrame({
|
||||
fields: [{ name: 'value', type: FieldType.number, values: [1, 2, 3] }],
|
||||
});
|
||||
|
||||
const DATA_FRAME_LARGE_DECIMAL: DataFrame = toDataFrame({
|
||||
fields: [{ name: 'value', type: FieldType.number, values: [1.23456789] }],
|
||||
});
|
||||
|
||||
const DATA_FRAME_WITH_LABELS: DataFrame = toDataFrame({
|
||||
fields: [{ name: 'value', type: FieldType.number, values: [1, 2, 3], labels: { __name__: 'my-series', foo: 'bar' } }],
|
||||
});
|
||||
@@ -222,10 +219,6 @@ describe('getSeriesValue', () => {
|
||||
const name = getSeriesValue(DATA_FRAME);
|
||||
expect(name).toBe(1);
|
||||
});
|
||||
|
||||
it('should round values', () => {
|
||||
expect(getSeriesValue(DATA_FRAME_LARGE_DECIMAL)).toBe(1.23457);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getSeriesLabels', () => {
|
||||
@@ -237,3 +230,35 @@ describe('getSeriesLabels', () => {
|
||||
expect(getSeriesLabels(EMPTY_FRAME)).toStrictEqual({});
|
||||
});
|
||||
});
|
||||
|
||||
describe('formatSeriesValue', () => {
|
||||
it('should convert non-numeric values to strings', () => {
|
||||
expect(formatSeriesValue('string value')).toBe('string value');
|
||||
expect(formatSeriesValue(null)).toBe('null');
|
||||
expect(formatSeriesValue(undefined)).toBe('undefined');
|
||||
expect(formatSeriesValue({})).toBe('[object Object]');
|
||||
});
|
||||
|
||||
it('should return 5 significant digits in absolutely smaller than 1', () => {
|
||||
expect(formatSeriesValue(0.00005123)).toBe('0.00005123');
|
||||
expect(formatSeriesValue(0.7894)).toBe('0.7894');
|
||||
expect(formatSeriesValue(-0.000051237676767)).toBe('-0.000051238');
|
||||
expect(formatSeriesValue(-0.25)).toBe('-0.25');
|
||||
});
|
||||
|
||||
it('should use standard notation for numbers absolutely larger than 1', () => {
|
||||
expect(formatSeriesValue(1.0001)).toBe('1.0001');
|
||||
expect(formatSeriesValue(1.234)).toBe('1.234');
|
||||
expect(formatSeriesValue(76767345.9876)).toBe('76767345.9876');
|
||||
});
|
||||
|
||||
it('should round regular numbers to 5 decimal places', () => {
|
||||
expect(formatSeriesValue(1.23456789)).toBe('1.23457');
|
||||
expect(formatSeriesValue(0.10000001)).toBe('0.1');
|
||||
expect(formatSeriesValue(-42.98765432)).toBe('-42.98765');
|
||||
});
|
||||
|
||||
it('should handle zero correctly', () => {
|
||||
expect(formatSeriesValue(0)).toBe('0');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -15,20 +15,29 @@ import { isCloudRulesSource } from '../../utils/datasource';
|
||||
*/
|
||||
|
||||
const getSeriesName = (frame: DataFrame): string | undefined => {
|
||||
const firstField = frame.fields[0];
|
||||
const firstField = frame.fields.at(0);
|
||||
|
||||
const displayNameFromDS = firstField?.config?.displayNameFromDS;
|
||||
return displayNameFromDS ?? frame.name ?? firstField?.labels?.__name__;
|
||||
};
|
||||
|
||||
const getSeriesValue = (frame: DataFrame) => {
|
||||
const value = frame.fields[0]?.values[0];
|
||||
return frame.fields.at(0)?.values.at(0);
|
||||
};
|
||||
|
||||
if (Number.isFinite(value)) {
|
||||
return roundDecimals(value, 5);
|
||||
const smallNumberFormatter = new Intl.NumberFormat(undefined, {
|
||||
maximumSignificantDigits: 5,
|
||||
});
|
||||
|
||||
const formatSeriesValue = (value: unknown): string => {
|
||||
if (Number.isFinite(value) && typeof value === 'number') {
|
||||
const absValue = Math.abs(value);
|
||||
if (absValue < 1) {
|
||||
return smallNumberFormatter.format(value);
|
||||
}
|
||||
return roundDecimals(value, 5).toString(10);
|
||||
}
|
||||
|
||||
return value;
|
||||
return String(value);
|
||||
};
|
||||
|
||||
const getSeriesLabels = (frame: DataFrame): Record<string, string> => {
|
||||
@@ -103,5 +112,6 @@ export {
|
||||
getSeriesLabels,
|
||||
getSeriesName,
|
||||
getSeriesValue,
|
||||
formatSeriesValue,
|
||||
isEmptySeries,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user