From d938c0e300ad3020e4d36b911b66321782067c7f Mon Sep 17 00:00:00 2001 From: nikkikapadia Date: Mon, 25 May 2026 13:58:30 -0400 Subject: [PATCH 1/7] fix(explore): y-axis formatting decimal truncation for heatmaps --- .../formatters/formatYAxisValue.spec.tsx | 4 ++-- .../timeSeriesWidget/formatters/formatYAxisValue.tsx | 11 ++++++++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/static/app/views/dashboards/widgets/timeSeriesWidget/formatters/formatYAxisValue.spec.tsx b/static/app/views/dashboards/widgets/timeSeriesWidget/formatters/formatYAxisValue.spec.tsx index 00420a7bbc2bfa..a88bdb072d7432 100644 --- a/static/app/views/dashboards/widgets/timeSeriesWidget/formatters/formatYAxisValue.spec.tsx +++ b/static/app/views/dashboards/widgets/timeSeriesWidget/formatters/formatYAxisValue.spec.tsx @@ -16,14 +16,14 @@ describe('formatYAxisValue', () => { describe('number', () => { it.each([ - [0.000033452, '0.000033452'], + [0.000033452, '0.00003345'], [0.00003, '0.00003'], [17.1238, '17.1238'], [170, '170'], [17111, '17K'], [17_000_110, '17M'], [1772313.1, '1,772,313.1'], - [1772313.11123, '1,772,313.11123'], + [1772313.11123, '1,772,313.1112'], ])('Formats %s as %s', (value, formattedValue) => { expect(formatYAxisValue(value, 'number')).toEqual(formattedValue); }); diff --git a/static/app/views/dashboards/widgets/timeSeriesWidget/formatters/formatYAxisValue.tsx b/static/app/views/dashboards/widgets/timeSeriesWidget/formatters/formatYAxisValue.tsx index 5af1d54f1169d3..46e9f50c4e1e5d 100644 --- a/static/app/views/dashboards/widgets/timeSeriesWidget/formatters/formatYAxisValue.tsx +++ b/static/app/views/dashboards/widgets/timeSeriesWidget/formatters/formatYAxisValue.tsx @@ -11,6 +11,10 @@ import {formatAbbreviatedNumber, formatDollars} from 'sentry/utils/formatters'; import {formatPercentage} from 'sentry/utils/number/formatPercentage'; import {convertDuration} from 'sentry/utils/unitConversion/convertDuration'; import {convertSize} from 'sentry/utils/unitConversion/convertSize'; +import { + NUMBER_MAX_FRACTION_DIGITS, + NUMBER_MIN_VALUE, +} from 'sentry/views/dashboards/widgets/common/settings'; import { isADurationUnit, isARateUnit, @@ -58,8 +62,13 @@ export function formatYAxisValue(value: number, type: string, unit?: string): st if (Number.isInteger(value)) { return formatAbbreviatedNumber(value); } + if (value > 0 && value < NUMBER_MIN_VALUE) { + return value.toLocaleString(undefined, { + maximumSignificantDigits: NUMBER_MAX_FRACTION_DIGITS, + }); + } return value.toLocaleString(undefined, { - maximumFractionDigits: 20, + maximumFractionDigits: NUMBER_MAX_FRACTION_DIGITS, }); case 'percentage': return formatPercentage(value, 3); From f37db701a987d8fe9a8168b86be933d43bab09b6 Mon Sep 17 00:00:00 2001 From: nikkikapadia Date: Tue, 26 May 2026 16:34:34 -0400 Subject: [PATCH 2/7] use number formatting recommendations --- static/app/utils/number/NUMBER_FORMATTING.md | 4 + .../formatters/formatYAxisValue.tsx | 94 +++++++++++++++++++ .../heatMapWidgetVisualization.tsx | 2 +- .../formatters/formatYAxisValue.tsx | 11 +-- 4 files changed, 100 insertions(+), 11 deletions(-) create mode 100644 static/app/views/dashboards/widgets/heatMapWidget/formatters/formatYAxisValue.tsx diff --git a/static/app/utils/number/NUMBER_FORMATTING.md b/static/app/utils/number/NUMBER_FORMATTING.md index 616260ee7e10cd..8a5c860bcbf18d 100644 --- a/static/app/utils/number/NUMBER_FORMATTING.md +++ b/static/app/utils/number/NUMBER_FORMATTING.md @@ -266,6 +266,10 @@ Each entry shows the function signature, the rounding/precision logic, and concr [formatYAxisValue.tsx](static/app/views/dashboards/widgets/timeSeriesWidget/formatters/formatYAxisValue.tsx) · Integers → `formatAbbreviatedNumber`. Non-integers → `toLocaleString({maximumFractionDigits: 20})` (full precision, trusts ECharts to provide round values). +### `formatYAxisValue(value, 'number'/'integer', ...)` + +[formatYAxisValue.tsx](static/app/views/dashboards/widgets/heatMapWidget/formatters/formatYAxisValue.tsx) · Integers → `formatAbbreviatedNumber`. Non-integers → `formatNumberWithDynamicDecimalPoints(value, 4)` (ECharts treats heat map y-axis as categories so it will not do a great job at formatting and providing round values. Hence we are rounding them off ourselves). + ### `formatTooltipValue(value, 'number'/'integer', ...)` [formatTooltipValue.tsx](static/app/views/dashboards/widgets/timeSeriesWidget/formatters/formatTooltipValue.tsx) · `toLocaleString({maximumFractionDigits: 4})`. If `0 < value < 0.0001`: switches to `{maximumSignificantDigits: 4}` to avoid `"0.0000"`. diff --git a/static/app/views/dashboards/widgets/heatMapWidget/formatters/formatYAxisValue.tsx b/static/app/views/dashboards/widgets/heatMapWidget/formatters/formatYAxisValue.tsx new file mode 100644 index 00000000000000..c2f6e300fee145 --- /dev/null +++ b/static/app/views/dashboards/widgets/heatMapWidget/formatters/formatYAxisValue.tsx @@ -0,0 +1,94 @@ +import {formatBytesBase2} from 'sentry/utils/bytes/formatBytesBase2'; +import {formatBytesBase10} from 'sentry/utils/bytes/formatBytesBase10'; +import { + ABYTE_UNITS, + DurationUnit, + RATE_UNIT_LABELS, + RateUnit, + SizeUnit, +} from 'sentry/utils/discover/fields'; +import {formatAbbreviatedNumber, formatDollars} from 'sentry/utils/formatters'; +import {formatNumberWithDynamicDecimalPoints} from 'sentry/utils/number/formatNumberWithDynamicDecimalPoints'; +import {formatPercentage} from 'sentry/utils/number/formatPercentage'; +import {convertDuration} from 'sentry/utils/unitConversion/convertDuration'; +import {convertSize} from 'sentry/utils/unitConversion/convertSize'; +import { + NUMBER_MIN_VALUE, + NUMBER_MAX_FRACTION_DIGITS, +} from 'sentry/views/dashboards/widgets/common/settings'; +import { + isADurationUnit, + isARateUnit, + isASizeUnit, +} from 'sentry/views/dashboards/widgets/common/typePredicates'; +import {formatYAxisDuration} from 'sentry/views/dashboards/widgets/timeSeriesWidget/formatters/formatYAxisDuration'; + +/** + * Format a value for the Y axis on an ECharts heat map graph. + * + * The values on the Y axis are chosen by ECharts. ECharts will automatically + * select, when possible, nice round values. With heat maps this is not the case. + * Since the Y axis in heat maps are considered categories to ECharts, + * We need to format the values ourselves to the precision we'd like to see, + * especially with floating point numbers. + * + * The rest of the logic is the same as the time series widget Y axis formatter + * (static/app/views/dashboards/widgets/timeSeriesWidget/formatters/formatYAxisValue.tsx). + */ +export function formatYAxisValue(value: number, type: string, unit?: string): string { + if (value === 0) { + return '0'; + } + + switch (type) { + case 'integer': + return formatAbbreviatedNumber(value); + case 'number': + if (Number.isInteger(value)) { + return formatAbbreviatedNumber(value); + } + if (value > 0 && value < NUMBER_MIN_VALUE) { + return value.toLocaleString(undefined, { + maximumFractionDigits: NUMBER_MAX_FRACTION_DIGITS, + }); + } + return formatNumberWithDynamicDecimalPoints(value, NUMBER_MAX_FRACTION_DIGITS); + case 'percentage': + return formatPercentage(value, 3); + case 'duration': { + const durationUnit = isADurationUnit(unit) ? unit : DurationUnit.MILLISECOND; + const durationInMilliseconds = convertDuration( + value, + durationUnit, + DurationUnit.MILLISECOND + ); + return formatYAxisDuration(durationInMilliseconds); + } + case 'size': { + const sizeUnit = isASizeUnit(unit) ? unit : SizeUnit.BYTE; + const sizeInBytes = convertSize(value, sizeUnit, SizeUnit.BYTE); + + const formatter = ABYTE_UNITS.includes(unit ?? 'byte') + ? formatBytesBase10 + : formatBytesBase2; + + return formatter(sizeInBytes); + } + case 'rate': { + // Always show rate in the original dataset's unit. If the unit is not + // appropriate, always convert the unit in the original dataset first. + // This way, named rate functions like `epm()` will be shows in per minute + // units + const rateUnit = isARateUnit(unit) ? unit : RateUnit.PER_SECOND; + return `${value.toLocaleString(undefined, { + notation: 'compact', + maximumSignificantDigits: 6, + })}${RATE_UNIT_LABELS[rateUnit]}`; + } + case 'currency': { + return formatDollars(value); + } + default: + return value.toString(); + } +} diff --git a/static/app/views/dashboards/widgets/heatMapWidget/heatMapWidgetVisualization.tsx b/static/app/views/dashboards/widgets/heatMapWidget/heatMapWidgetVisualization.tsx index 37ddc7aa4b24ca..a5a00be295d42d 100644 --- a/static/app/views/dashboards/widgets/heatMapWidget/heatMapWidgetVisualization.tsx +++ b/static/app/views/dashboards/widgets/heatMapWidget/heatMapWidgetVisualization.tsx @@ -21,10 +21,10 @@ import {formatAbbreviatedNumber} from 'sentry/utils/formatters'; import {ECHARTS_MISSING_DATA_VALUE} from 'sentry/utils/timeSeries/timeSeriesItemToEChartsDataPoint'; import {useOrganization} from 'sentry/utils/useOrganization'; import {NO_PLOTTABLE_VALUES} from 'sentry/views/dashboards/widgets/common/settings'; +import {formatYAxisValue} from 'sentry/views/dashboards/widgets/heatMapWidget/formatters/formatYAxisValue'; import {plottablesCanBeVisualized} from 'sentry/views/dashboards/widgets/plottablesCanBeVisualized'; import {formatTooltipValue} from 'sentry/views/dashboards/widgets/timeSeriesWidget/formatters/formatTooltipValue'; import {formatXAxisTimestamp} from 'sentry/views/dashboards/widgets/timeSeriesWidget/formatters/formatXAxisTimestamp'; -import {formatYAxisValue} from 'sentry/views/dashboards/widgets/timeSeriesWidget/formatters/formatYAxisValue'; import {FALLBACK_TYPE} from 'sentry/views/dashboards/widgets/timeSeriesWidget/settings'; import {getExploreUrl, type GetExploreUrlArgs} from 'sentry/views/explore/utils'; diff --git a/static/app/views/dashboards/widgets/timeSeriesWidget/formatters/formatYAxisValue.tsx b/static/app/views/dashboards/widgets/timeSeriesWidget/formatters/formatYAxisValue.tsx index 46e9f50c4e1e5d..5af1d54f1169d3 100644 --- a/static/app/views/dashboards/widgets/timeSeriesWidget/formatters/formatYAxisValue.tsx +++ b/static/app/views/dashboards/widgets/timeSeriesWidget/formatters/formatYAxisValue.tsx @@ -11,10 +11,6 @@ import {formatAbbreviatedNumber, formatDollars} from 'sentry/utils/formatters'; import {formatPercentage} from 'sentry/utils/number/formatPercentage'; import {convertDuration} from 'sentry/utils/unitConversion/convertDuration'; import {convertSize} from 'sentry/utils/unitConversion/convertSize'; -import { - NUMBER_MAX_FRACTION_DIGITS, - NUMBER_MIN_VALUE, -} from 'sentry/views/dashboards/widgets/common/settings'; import { isADurationUnit, isARateUnit, @@ -62,13 +58,8 @@ export function formatYAxisValue(value: number, type: string, unit?: string): st if (Number.isInteger(value)) { return formatAbbreviatedNumber(value); } - if (value > 0 && value < NUMBER_MIN_VALUE) { - return value.toLocaleString(undefined, { - maximumSignificantDigits: NUMBER_MAX_FRACTION_DIGITS, - }); - } return value.toLocaleString(undefined, { - maximumFractionDigits: NUMBER_MAX_FRACTION_DIGITS, + maximumFractionDigits: 20, }); case 'percentage': return formatPercentage(value, 3); From 7545445dbf8f5c23794cb8d0f66705aa67cc1bf5 Mon Sep 17 00:00:00 2001 From: nikkikapadia Date: Wed, 27 May 2026 10:28:40 -0400 Subject: [PATCH 3/7] fix tests and fix decimal issue --- .../formatters/formatYAxisValue.spec.tsx | 97 +++++++++++++++++++ .../formatters/formatYAxisValue.tsx | 2 +- .../formatters/formatYAxisValue.spec.tsx | 4 +- 3 files changed, 100 insertions(+), 3 deletions(-) create mode 100644 static/app/views/dashboards/widgets/heatMapWidget/formatters/formatYAxisValue.spec.tsx diff --git a/static/app/views/dashboards/widgets/heatMapWidget/formatters/formatYAxisValue.spec.tsx b/static/app/views/dashboards/widgets/heatMapWidget/formatters/formatYAxisValue.spec.tsx new file mode 100644 index 00000000000000..a88bdb072d7432 --- /dev/null +++ b/static/app/views/dashboards/widgets/heatMapWidget/formatters/formatYAxisValue.spec.tsx @@ -0,0 +1,97 @@ +import {formatYAxisValue} from './formatYAxisValue'; + +describe('formatYAxisValue', () => { + describe('integer', () => { + it.each([ + [0, '0'], + [17, '17'], + [171, '171'], + [17111, '17K'], + [17_000_110, '17M'], + [1_000_110_000, '1B'], + ])('Formats %s as %s', (value, formattedValue) => { + expect(formatYAxisValue(value, 'integer')).toEqual(formattedValue); + }); + }); + + describe('number', () => { + it.each([ + [0.000033452, '0.00003345'], + [0.00003, '0.00003'], + [17.1238, '17.1238'], + [170, '170'], + [17111, '17K'], + [17_000_110, '17M'], + [1772313.1, '1,772,313.1'], + [1772313.11123, '1,772,313.1112'], + ])('Formats %s as %s', (value, formattedValue) => { + expect(formatYAxisValue(value, 'number')).toEqual(formattedValue); + }); + }); + + describe('percentage', () => { + it.each([ + [0, '0'], + [0.00005, '0.005%'], + [0.712, '71.2%'], + [17.123, '1,712.3%'], + [1, '100%'], + ])('Formats %s as %s', (value, formattedValue) => { + expect(formatYAxisValue(value, 'percentage')).toEqual(formattedValue); + }); + }); + + describe('duration', () => { + it.each([ + [0, 'millisecond', '0'], + [0.712, 'second', '712ms'], + [1230, 'second', '20.5min'], + ])('Formats %s as %s', (value, unit, formattedValue) => { + expect(formatYAxisValue(value, 'duration', unit)).toEqual(formattedValue); + }); + }); + + describe('size', () => { + it.each([ + [0, 'byte', '0'], + [0.712, 'megabyte', '712 KB'], + [1231, 'kibibyte', '1.2 MiB'], + ])('Formats %s as %s', (value, unit, formattedValue) => { + expect(formatYAxisValue(value, 'size', unit)).toEqual(formattedValue); + }); + }); + + describe('rate', () => { + it.each([ + [0, '1/second', '0'], + [-3, '1/second', '-3/s'], + [0.712, '1/second', '0.712/s'], + [12700, '1/second', '12.7K/s'], + [0.0003, '1/second', '0.0003/s'], + [0.00000153, '1/second', '0.00000153/s'], + [0.35, '1/second', '0.35/s'], + [10, '1/second', '10/s'], + // eslint-disable-next-line unicorn/no-zero-fractions + [10.0, '1/second', '10/s'], + [1231, '1/minute', '1.231K/min'], + [110000, '1/second', '110K/s'], + [110001, '1/second', '110.001K/s'], + [123456789, '1/second', '123.457M/s'], + ])('Formats %s as %s', (value, unit, formattedValue) => { + expect(formatYAxisValue(value, 'rate', unit)).toEqual(formattedValue); + }); + }); + + describe('currency', () => { + it.each([ + [0, '0'], + [17, '$17'], + [171, '$171'], + [17111, '$17.11K'], + [17_000_110, '$17M'], + [1_000_110_000, '$1B'], + ])('Formats %s as %s', (value, formattedValue) => { + expect(formatYAxisValue(value, 'currency')).toEqual(formattedValue); + }); + }); +}); diff --git a/static/app/views/dashboards/widgets/heatMapWidget/formatters/formatYAxisValue.tsx b/static/app/views/dashboards/widgets/heatMapWidget/formatters/formatYAxisValue.tsx index c2f6e300fee145..5556de387094f4 100644 --- a/static/app/views/dashboards/widgets/heatMapWidget/formatters/formatYAxisValue.tsx +++ b/static/app/views/dashboards/widgets/heatMapWidget/formatters/formatYAxisValue.tsx @@ -49,7 +49,7 @@ export function formatYAxisValue(value: number, type: string, unit?: string): st } if (value > 0 && value < NUMBER_MIN_VALUE) { return value.toLocaleString(undefined, { - maximumFractionDigits: NUMBER_MAX_FRACTION_DIGITS, + maximumSignificantDigits: NUMBER_MAX_FRACTION_DIGITS, }); } return formatNumberWithDynamicDecimalPoints(value, NUMBER_MAX_FRACTION_DIGITS); diff --git a/static/app/views/dashboards/widgets/timeSeriesWidget/formatters/formatYAxisValue.spec.tsx b/static/app/views/dashboards/widgets/timeSeriesWidget/formatters/formatYAxisValue.spec.tsx index a88bdb072d7432..00420a7bbc2bfa 100644 --- a/static/app/views/dashboards/widgets/timeSeriesWidget/formatters/formatYAxisValue.spec.tsx +++ b/static/app/views/dashboards/widgets/timeSeriesWidget/formatters/formatYAxisValue.spec.tsx @@ -16,14 +16,14 @@ describe('formatYAxisValue', () => { describe('number', () => { it.each([ - [0.000033452, '0.00003345'], + [0.000033452, '0.000033452'], [0.00003, '0.00003'], [17.1238, '17.1238'], [170, '170'], [17111, '17K'], [17_000_110, '17M'], [1772313.1, '1,772,313.1'], - [1772313.11123, '1,772,313.1112'], + [1772313.11123, '1,772,313.11123'], ])('Formats %s as %s', (value, formattedValue) => { expect(formatYAxisValue(value, 'number')).toEqual(formattedValue); }); From b30133b05407f69283beb0946ffb1c0e8006d397 Mon Sep 17 00:00:00 2001 From: nikkikapadia Date: Wed, 27 May 2026 10:36:09 -0400 Subject: [PATCH 4/7] specify in md file --- static/app/utils/number/NUMBER_FORMATTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/static/app/utils/number/NUMBER_FORMATTING.md b/static/app/utils/number/NUMBER_FORMATTING.md index 8a5c860bcbf18d..c3033cc8e31bb2 100644 --- a/static/app/utils/number/NUMBER_FORMATTING.md +++ b/static/app/utils/number/NUMBER_FORMATTING.md @@ -268,7 +268,7 @@ Each entry shows the function signature, the rounding/precision logic, and concr ### `formatYAxisValue(value, 'number'/'integer', ...)` -[formatYAxisValue.tsx](static/app/views/dashboards/widgets/heatMapWidget/formatters/formatYAxisValue.tsx) · Integers → `formatAbbreviatedNumber`. Non-integers → `formatNumberWithDynamicDecimalPoints(value, 4)` (ECharts treats heat map y-axis as categories so it will not do a great job at formatting and providing round values. Hence we are rounding them off ourselves). +[formatYAxisValue.tsx](static/app/views/dashboards/widgets/heatMapWidget/formatters/formatYAxisValue.tsx) · NOTE: This function is ONLY for HEAT MAPS! Integers → `formatAbbreviatedNumber`. Non-integers → `formatNumberWithDynamicDecimalPoints(value, 4)` (ECharts treats heat map y-axis as categories so it will not do a great job at formatting and providing round values. Hence we are rounding them off ourselves). ### `formatTooltipValue(value, 'number'/'integer', ...)` From ed324e37d47ec8fb18e1a2b69a2e1f4052580827 Mon Sep 17 00:00:00 2001 From: nikkikapadia Date: Wed, 27 May 2026 12:53:57 -0400 Subject: [PATCH 5/7] use default decimal points --- .../widgets/heatMapWidget/formatters/formatYAxisValue.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/static/app/views/dashboards/widgets/heatMapWidget/formatters/formatYAxisValue.tsx b/static/app/views/dashboards/widgets/heatMapWidget/formatters/formatYAxisValue.tsx index 5556de387094f4..8b90133eb5c674 100644 --- a/static/app/views/dashboards/widgets/heatMapWidget/formatters/formatYAxisValue.tsx +++ b/static/app/views/dashboards/widgets/heatMapWidget/formatters/formatYAxisValue.tsx @@ -52,7 +52,7 @@ export function formatYAxisValue(value: number, type: string, unit?: string): st maximumSignificantDigits: NUMBER_MAX_FRACTION_DIGITS, }); } - return formatNumberWithDynamicDecimalPoints(value, NUMBER_MAX_FRACTION_DIGITS); + return formatNumberWithDynamicDecimalPoints(value); case 'percentage': return formatPercentage(value, 3); case 'duration': { From 6559024712ceed18f6fb11ea09342aa45ffce92b Mon Sep 17 00:00:00 2001 From: nikkikapadia Date: Wed, 27 May 2026 12:54:47 -0400 Subject: [PATCH 6/7] fix test --- .../heatMapWidget/formatters/formatYAxisValue.spec.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/static/app/views/dashboards/widgets/heatMapWidget/formatters/formatYAxisValue.spec.tsx b/static/app/views/dashboards/widgets/heatMapWidget/formatters/formatYAxisValue.spec.tsx index a88bdb072d7432..70d0261973257e 100644 --- a/static/app/views/dashboards/widgets/heatMapWidget/formatters/formatYAxisValue.spec.tsx +++ b/static/app/views/dashboards/widgets/heatMapWidget/formatters/formatYAxisValue.spec.tsx @@ -18,12 +18,12 @@ describe('formatYAxisValue', () => { it.each([ [0.000033452, '0.00003345'], [0.00003, '0.00003'], - [17.1238, '17.1238'], + [17.1238, '17.12'], [170, '170'], [17111, '17K'], [17_000_110, '17M'], [1772313.1, '1,772,313.1'], - [1772313.11123, '1,772,313.1112'], + [1772313.11123, '1,772,313.11'], ])('Formats %s as %s', (value, formattedValue) => { expect(formatYAxisValue(value, 'number')).toEqual(formattedValue); }); From 46d14deba1dbe44aff779255c19c0537055a201f Mon Sep 17 00:00:00 2001 From: nikkikapadia Date: Wed, 27 May 2026 12:55:18 -0400 Subject: [PATCH 7/7] update md --- static/app/utils/number/NUMBER_FORMATTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/static/app/utils/number/NUMBER_FORMATTING.md b/static/app/utils/number/NUMBER_FORMATTING.md index c3033cc8e31bb2..13bf6f13d87c8c 100644 --- a/static/app/utils/number/NUMBER_FORMATTING.md +++ b/static/app/utils/number/NUMBER_FORMATTING.md @@ -268,7 +268,7 @@ Each entry shows the function signature, the rounding/precision logic, and concr ### `formatYAxisValue(value, 'number'/'integer', ...)` -[formatYAxisValue.tsx](static/app/views/dashboards/widgets/heatMapWidget/formatters/formatYAxisValue.tsx) · NOTE: This function is ONLY for HEAT MAPS! Integers → `formatAbbreviatedNumber`. Non-integers → `formatNumberWithDynamicDecimalPoints(value, 4)` (ECharts treats heat map y-axis as categories so it will not do a great job at formatting and providing round values. Hence we are rounding them off ourselves). +[formatYAxisValue.tsx](static/app/views/dashboards/widgets/heatMapWidget/formatters/formatYAxisValue.tsx) · NOTE: This function is ONLY for HEAT MAPS! Integers → `formatAbbreviatedNumber`. Non-integers → `formatNumberWithDynamicDecimalPoints(value)` (ECharts treats heat map y-axis as categories so it will not do a great job at formatting and providing round values. Hence we are rounding them off ourselves). ### `formatTooltipValue(value, 'number'/'integer', ...)`