Skip to content

Commit e617d9b

Browse files
authored
fix(dashboards): Abbreviate LineChartWidget Y axis integers (#81937)
Converts numbers like "800,000" to "800k" in the Y Axis of `LineChartWidget` but _not_ in the tooltip! I split the `formatChartValue` function into two, one for formatting the value in the Y axis, and one for formatting the value for the tooltip. They're different! In the tooltip we expect to have more digits. I'll continue to tweak this as I find more cases.
1 parent d0bea1a commit e617d9b

File tree

5 files changed

+121
-14
lines changed

5 files changed

+121
-14
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import {formatTooltipValue} from './formatTooltipValue';
2+
3+
describe('formatTooltipValue', () => {
4+
describe('integer', () => {
5+
it.each([
6+
[0, '0'],
7+
[17, '17'],
8+
[171, '171'],
9+
[17111, '17,111'],
10+
[17_000_110, '17,000,110'],
11+
[1_000_110_000, '1,000,110,000'],
12+
])('Formats %s as %s', (value, formattedValue) => {
13+
expect(formatTooltipValue(value, 'integer')).toEqual(formattedValue);
14+
});
15+
});
16+
17+
describe('number', () => {
18+
it.each([
19+
[17.1238, '17.124'],
20+
[1772313.1, '1,772,313.1'],
21+
])('Formats %s as %s', (value, formattedValue) => {
22+
expect(formatTooltipValue(value, 'number')).toEqual(formattedValue);
23+
});
24+
});
25+
26+
describe('percentage', () => {
27+
it.each([
28+
[0, '0%'],
29+
[0.712, '71.2%'],
30+
[17.123, '1,712.3%'],
31+
[1, '100%'],
32+
])('Formats %s as %s', (value, formattedValue) => {
33+
expect(formatTooltipValue(value, 'percentage')).toEqual(formattedValue);
34+
});
35+
});
36+
37+
describe('duration', () => {
38+
it.each([
39+
[0, 'millisecond', '0.00ms'],
40+
[0.712, 'second', '712.00ms'],
41+
[1231, 'second', '20.52min'],
42+
])('Formats %s as %s', (value, unit, formattedValue) => {
43+
expect(formatTooltipValue(value, 'duration', unit)).toEqual(formattedValue);
44+
});
45+
});
46+
47+
describe('size', () => {
48+
it.each([
49+
[0, 'byte', '0.0 B'],
50+
[0.712, 'megabyte', '712 KB'],
51+
[1231, 'kibibyte', '1.2 MiB'],
52+
])('Formats %s as %s', (value, unit, formattedValue) => {
53+
expect(formatTooltipValue(value, 'size', unit)).toEqual(formattedValue);
54+
});
55+
});
56+
57+
describe('rate', () => {
58+
it.each([
59+
[0, '1/second', '0/s'],
60+
[0.712, '1/second', '0.712/s'],
61+
[12712, '1/second', '12.7K/s'],
62+
[1231, '1/minute', '1.23K/min'],
63+
])('Formats %s as %s', (value, unit, formattedValue) => {
64+
expect(formatTooltipValue(value, 'rate', unit)).toEqual(formattedValue);
65+
});
66+
});
67+
});

Diff for: static/app/views/dashboards/widgets/lineChartWidget/formatChartValue.tsx renamed to static/app/views/dashboards/widgets/lineChartWidget/formatTooltipValue.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import getDuration from 'sentry/utils/duration/getDuration';
1010
import {formatRate} from 'sentry/utils/formatters';
1111
import {formatPercentage} from 'sentry/utils/number/formatPercentage';
1212

13-
export function formatChartValue(value: number, type: string, unit?: string): string {
13+
export function formatTooltipValue(value: number, type: string, unit?: string): string {
1414
switch (type) {
1515
case 'integer':
1616
case 'number':
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,37 @@
1-
import {formatChartValue} from './formatChartValue';
1+
import {formatYAxisValue} from './formatYAxisValue';
22

3-
describe('formatChartValue', () => {
3+
describe('formatYAxisValue', () => {
44
describe('integer', () => {
55
it.each([
66
[0, '0'],
77
[17, '17'],
8-
[1772313, '1,772,313'],
8+
[171, '171'],
9+
[17111, '17k'],
10+
[17_000_110, '17m'],
11+
[1_000_110_000, '1b'],
912
])('Formats %s as %s', (value, formattedValue) => {
10-
expect(formatChartValue(value, 'integer')).toEqual(formattedValue);
13+
expect(formatYAxisValue(value, 'integer')).toEqual(formattedValue);
1114
});
1215
});
1316

1417
describe('number', () => {
1518
it.each([
16-
[0, '0'],
1719
[17.1238, '17.124'],
1820
[1772313.1, '1,772,313.1'],
1921
])('Formats %s as %s', (value, formattedValue) => {
20-
expect(formatChartValue(value, 'number')).toEqual(formattedValue);
22+
expect(formatYAxisValue(value, 'number')).toEqual(formattedValue);
2123
});
2224
});
2325

2426
describe('percentage', () => {
2527
it.each([
2628
[0, '0%'],
29+
[0.00005, '0.005%'],
2730
[0.712, '71.2%'],
2831
[17.123, '1,712.3%'],
2932
[1, '100%'],
3033
])('Formats %s as %s', (value, formattedValue) => {
31-
expect(formatChartValue(value, 'percentage')).toEqual(formattedValue);
34+
expect(formatYAxisValue(value, 'percentage')).toEqual(formattedValue);
3235
});
3336
});
3437

@@ -38,7 +41,7 @@ describe('formatChartValue', () => {
3841
[0.712, 'second', '712.00ms'],
3942
[1231, 'second', '20.52min'],
4043
])('Formats %s as %s', (value, unit, formattedValue) => {
41-
expect(formatChartValue(value, 'duration', unit)).toEqual(formattedValue);
44+
expect(formatYAxisValue(value, 'duration', unit)).toEqual(formattedValue);
4245
});
4346
});
4447

@@ -48,7 +51,7 @@ describe('formatChartValue', () => {
4851
[0.712, 'megabyte', '712 KB'],
4952
[1231, 'kibibyte', '1.2 MiB'],
5053
])('Formats %s as %s', (value, unit, formattedValue) => {
51-
expect(formatChartValue(value, 'size', unit)).toEqual(formattedValue);
54+
expect(formatYAxisValue(value, 'size', unit)).toEqual(formattedValue);
5255
});
5356
});
5457

@@ -59,7 +62,7 @@ describe('formatChartValue', () => {
5962
[12712, '1/second', '12.7K/s'],
6063
[1231, '1/minute', '1.23K/min'],
6164
])('Formats %s as %s', (value, unit, formattedValue) => {
62-
expect(formatChartValue(value, 'rate', unit)).toEqual(formattedValue);
65+
expect(formatYAxisValue(value, 'rate', unit)).toEqual(formattedValue);
6366
});
6467
});
6568
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import {formatBytesBase2} from 'sentry/utils/bytes/formatBytesBase2';
2+
import {formatBytesBase10} from 'sentry/utils/bytes/formatBytesBase10';
3+
import {
4+
ABYTE_UNITS,
5+
DURATION_UNITS,
6+
SIZE_UNITS,
7+
} from 'sentry/utils/discover/fieldRenderers';
8+
import type {RateUnit} from 'sentry/utils/discover/fields';
9+
import getDuration from 'sentry/utils/duration/getDuration';
10+
import {formatAbbreviatedNumber, formatRate} from 'sentry/utils/formatters';
11+
import {formatPercentage} from 'sentry/utils/number/formatPercentage';
12+
13+
export function formatYAxisValue(value: number, type: string, unit?: string): string {
14+
switch (type) {
15+
case 'integer':
16+
return formatAbbreviatedNumber(value);
17+
case 'number':
18+
return value.toLocaleString();
19+
case 'percentage':
20+
return formatPercentage(value, 3);
21+
case 'duration':
22+
return getDuration((value * (unit ? DURATION_UNITS[unit] : 1)) / 1000, 2, true);
23+
case 'size':
24+
const bytes = value * SIZE_UNITS[unit ?? 'byte'];
25+
26+
const formatter = ABYTE_UNITS.includes(unit ?? 'byte')
27+
? formatBytesBase10
28+
: formatBytesBase2;
29+
30+
return formatter(bytes);
31+
case 'rate':
32+
return formatRate(value, unit as RateUnit);
33+
default:
34+
return value.toString();
35+
}
36+
}

Diff for: static/app/views/dashboards/widgets/lineChartWidget/lineChartWidgetVisualization.tsx

+4-3
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ import {useWidgetSyncContext} from '../../contexts/widgetSyncContext';
2222
import {ReleaseSeries} from '../common/releaseSeries';
2323
import type {Meta, Release, TimeseriesData} from '../common/types';
2424

25-
import {formatChartValue} from './formatChartValue';
25+
import {formatTooltipValue} from './formatTooltipValue';
26+
import {formatYAxisValue} from './formatYAxisValue';
2627
import {splitSeriesIntoCompleteAndIncomplete} from './splitSeriesIntoCompleteAndIncomplete';
2728

2829
export interface LineChartWidgetVisualizationProps {
@@ -135,7 +136,7 @@ export function LineChartWidgetVisualization(props: LineChartWidgetVisualization
135136
isGroupedByDate: true,
136137
showTimeInTooltip: true,
137138
valueFormatter: value => {
138-
return formatChartValue(value, type, unit);
139+
return formatTooltipValue(value, type, unit);
139140
},
140141
truncate: true,
141142
utc: utc ?? false,
@@ -223,7 +224,7 @@ export function LineChartWidgetVisualization(props: LineChartWidgetVisualization
223224
yAxis={{
224225
axisLabel: {
225226
formatter(value: number) {
226-
return formatChartValue(value, type, unit);
227+
return formatYAxisValue(value, type, unit);
227228
},
228229
},
229230
axisPointer: {

0 commit comments

Comments
 (0)