mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Decimals: Big Improvements to auto decimals and fixes to auto decimals bug found in 7.4-beta1 (#30519)
* Decimals: Nukes scaledDecimals from the earth it was an abomination * Moved move tests * Fixed test * Updated tests * Updated test
This commit is contained in:
parent
be8ba8ef46
commit
6bdc9fac45
@ -144,33 +144,6 @@ describe('Format value', () => {
|
||||
expect(result.text).toEqual('10.0');
|
||||
});
|
||||
|
||||
it('should set auto decimals, 1 significant', () => {
|
||||
const value = 3.23;
|
||||
const instance = getDisplayProcessorFromConfig({ decimals: null });
|
||||
expect(instance(value).text).toEqual('3.23');
|
||||
});
|
||||
|
||||
it('should set auto decimals, 2 significant', () => {
|
||||
const value = 0.0245;
|
||||
const instance = getDisplayProcessorFromConfig({ decimals: null });
|
||||
|
||||
expect(instance(value).text).toEqual('0.0245');
|
||||
});
|
||||
|
||||
it('should set auto decimals correctly for value 0.333333333333', () => {
|
||||
const value = 1 / 3;
|
||||
const instance = getDisplayProcessorFromConfig({ decimals: null });
|
||||
expect(instance(value).text).toEqual('0.333');
|
||||
});
|
||||
|
||||
it('should use override decimals', () => {
|
||||
const value = 100030303;
|
||||
const instance = getDisplayProcessorFromConfig({ decimals: 2, unit: 'bytes' });
|
||||
const disp = instance(value);
|
||||
expect(disp.text).toEqual('95.40');
|
||||
expect(disp.suffix).toEqual(' MiB');
|
||||
});
|
||||
|
||||
it('should return mapped value if there are matching value mappings', () => {
|
||||
const valueMappings: ValueMapping[] = [
|
||||
{ id: 0, text: '1-20', type: MappingType.RangeToText, from: '1', to: '20' },
|
||||
@ -211,7 +184,7 @@ describe('Format value', () => {
|
||||
const value = 1000;
|
||||
const instance = getDisplayProcessorFromConfig({ decimals: null, unit: 'short' });
|
||||
const disp = instance(value);
|
||||
expect(disp.text).toEqual('1.0');
|
||||
expect(disp.text).toEqual('1');
|
||||
expect(disp.suffix).toEqual(' K');
|
||||
});
|
||||
|
||||
@ -219,7 +192,7 @@ describe('Format value', () => {
|
||||
const value = 1200;
|
||||
const instance = getDisplayProcessorFromConfig({ decimals: null, unit: 'short' });
|
||||
const disp = instance(value);
|
||||
expect(disp.text).toEqual('1.2');
|
||||
expect(disp.text).toEqual('1.20');
|
||||
expect(disp.suffix).toEqual(' K');
|
||||
});
|
||||
|
||||
@ -235,7 +208,7 @@ describe('Format value', () => {
|
||||
const value = 1000000;
|
||||
const instance = getDisplayProcessorFromConfig({ decimals: null, unit: 'short' });
|
||||
const disp = instance(value);
|
||||
expect(disp.text).toEqual('1.0');
|
||||
expect(disp.text).toEqual('1');
|
||||
expect(disp.suffix).toEqual(' Mil');
|
||||
});
|
||||
|
||||
@ -243,9 +216,17 @@ describe('Format value', () => {
|
||||
const value = 1500000;
|
||||
const instance = getDisplayProcessorFromConfig({ decimals: null, unit: 'short' });
|
||||
const disp = instance(value);
|
||||
expect(disp.text).toEqual('1.5');
|
||||
expect(disp.text).toEqual('1.50');
|
||||
expect(disp.suffix).toEqual(' Mil');
|
||||
});
|
||||
|
||||
it('with value 128000000 and unit bytes', () => {
|
||||
const value = 1280000125;
|
||||
const instance = getDisplayProcessorFromConfig({ decimals: null, unit: 'bytes' });
|
||||
const disp = instance(value);
|
||||
expect(disp.text).toEqual('1.19');
|
||||
expect(disp.suffix).toEqual(' GiB');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Date display options', () => {
|
||||
|
@ -4,7 +4,7 @@ import _ from 'lodash';
|
||||
// Types
|
||||
import { Field, FieldType } from '../types/dataFrame';
|
||||
import { GrafanaTheme } from '../types/theme';
|
||||
import { DecimalCount, DecimalInfo, DisplayProcessor, DisplayValue } from '../types/displayValue';
|
||||
import { DisplayProcessor, DisplayValue } from '../types/displayValue';
|
||||
import { getValueFormat } from '../valueFormats/valueFormats';
|
||||
import { getMappedValue } from '../utils/valueMappings';
|
||||
import { dateTime } from '../datetime';
|
||||
@ -86,8 +86,7 @@ export function getDisplayProcessor(options?: DisplayProcessorOptions): DisplayP
|
||||
|
||||
if (!isNaN(numeric)) {
|
||||
if (shouldFormat && !_.isBoolean(value)) {
|
||||
const { decimals, scaledDecimals } = getDecimalsForValue(value, config.decimals);
|
||||
const v = formatFunc(numeric, decimals, scaledDecimals, options.timeZone);
|
||||
const v = formatFunc(numeric, config.decimals, null, options.timeZone);
|
||||
text = v.text;
|
||||
suffix = v.suffix;
|
||||
prefix = v.prefix;
|
||||
@ -137,53 +136,6 @@ function toStringProcessor(value: any): DisplayValue {
|
||||
return { text: _.toString(value), numeric: toNumber(value) };
|
||||
}
|
||||
|
||||
function getSignificantDigitCount(n: number) {
|
||||
//remove decimal and make positive
|
||||
n = Math.abs(+String(n).replace('.', ''));
|
||||
if (n === 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// kill the 0s at the end of n
|
||||
while (n !== 0 && n % 10 === 0) {
|
||||
n /= 10;
|
||||
}
|
||||
|
||||
// get number of digits
|
||||
return Math.floor(Math.log(n) / Math.LN10) + 1;
|
||||
}
|
||||
|
||||
export function getDecimalsForValue(value: number, decimalOverride?: DecimalCount): DecimalInfo {
|
||||
if (_.isNumber(decimalOverride)) {
|
||||
// It's important that scaledDecimals is null here
|
||||
return { decimals: decimalOverride, scaledDecimals: null };
|
||||
}
|
||||
|
||||
if (value === 0) {
|
||||
return { decimals: 0, scaledDecimals: 0 };
|
||||
}
|
||||
|
||||
const digits = getSignificantDigitCount(value);
|
||||
const log10 = Math.floor(Math.log(Math.abs(value)) / Math.LN10);
|
||||
let dec = -log10 + 1;
|
||||
const magn = Math.pow(10, -dec);
|
||||
const norm = value / magn; // norm is between 1.0 and 10.0
|
||||
|
||||
// special case for 2.5, requires an extra decimal
|
||||
if (norm > 2.25) {
|
||||
++dec;
|
||||
}
|
||||
|
||||
if (value % 1 === 0) {
|
||||
dec = 0;
|
||||
}
|
||||
|
||||
const decimals = Math.max(0, dec);
|
||||
const scaledDecimals = decimals - log10 + digits - 1;
|
||||
|
||||
return { decimals, scaledDecimals };
|
||||
}
|
||||
|
||||
export function getRawDisplayProcessor(): DisplayProcessor {
|
||||
return (value: any) => ({
|
||||
text: `${value}`,
|
||||
|
@ -31,7 +31,7 @@ const INTERVALS_IN_SECONDS: IntervalsInSeconds = {
|
||||
[Interval.Millisecond]: 0.001,
|
||||
};
|
||||
|
||||
export function toNanoSeconds(size: number, decimals?: DecimalCount, scaledDecimals?: DecimalCount): FormattedValue {
|
||||
export function toNanoSeconds(size: number, decimals?: DecimalCount): FormattedValue {
|
||||
if (size === null) {
|
||||
return { text: '' };
|
||||
}
|
||||
@ -39,21 +39,21 @@ export function toNanoSeconds(size: number, decimals?: DecimalCount, scaledDecim
|
||||
if (Math.abs(size) < 1000) {
|
||||
return { text: toFixed(size, decimals), suffix: ' ns' };
|
||||
} else if (Math.abs(size) < 1000000) {
|
||||
return toFixedScaled(size / 1000, decimals, scaledDecimals, 3, ' µs');
|
||||
return toFixedScaled(size / 1000, decimals, ' µs');
|
||||
} else if (Math.abs(size) < 1000000000) {
|
||||
return toFixedScaled(size / 1000000, decimals, scaledDecimals, 6, ' ms');
|
||||
return toFixedScaled(size / 1000000, decimals, ' ms');
|
||||
} else if (Math.abs(size) < 60000000000) {
|
||||
return toFixedScaled(size / 1000000000, decimals, scaledDecimals, 9, ' s');
|
||||
return toFixedScaled(size / 1000000000, decimals, ' s');
|
||||
} else if (Math.abs(size) < 3600000000000) {
|
||||
return toFixedScaled(size / 60000000000, decimals, scaledDecimals, 12, ' min');
|
||||
return toFixedScaled(size / 60000000000, decimals, ' min');
|
||||
} else if (Math.abs(size) < 86400000000000) {
|
||||
return toFixedScaled(size / 3600000000000, decimals, scaledDecimals, 13, ' hour');
|
||||
return toFixedScaled(size / 3600000000000, decimals, ' hour');
|
||||
} else {
|
||||
return toFixedScaled(size / 86400000000000, decimals, scaledDecimals, 14, ' day');
|
||||
return toFixedScaled(size / 86400000000000, decimals, ' day');
|
||||
}
|
||||
}
|
||||
|
||||
export function toMicroSeconds(size: number, decimals?: DecimalCount, scaledDecimals?: DecimalCount): FormattedValue {
|
||||
export function toMicroSeconds(size: number, decimals?: DecimalCount): FormattedValue {
|
||||
if (size === null) {
|
||||
return { text: '' };
|
||||
}
|
||||
@ -61,9 +61,9 @@ export function toMicroSeconds(size: number, decimals?: DecimalCount, scaledDeci
|
||||
if (Math.abs(size) < 1000) {
|
||||
return { text: toFixed(size, decimals), suffix: ' µs' };
|
||||
} else if (Math.abs(size) < 1000000) {
|
||||
return toFixedScaled(size / 1000, decimals, scaledDecimals, 3, ' ms');
|
||||
return toFixedScaled(size / 1000, decimals, ' ms');
|
||||
} else {
|
||||
return toFixedScaled(size / 1000000, decimals, scaledDecimals, 6, ' s');
|
||||
return toFixedScaled(size / 1000000, decimals, ' s');
|
||||
}
|
||||
}
|
||||
|
||||
@ -76,19 +76,19 @@ export function toMilliSeconds(size: number, decimals?: DecimalCount, scaledDeci
|
||||
return { text: toFixed(size, decimals), suffix: ' ms' };
|
||||
} else if (Math.abs(size) < 60000) {
|
||||
// Less than 1 min
|
||||
return toFixedScaled(size / 1000, decimals, scaledDecimals, 3, ' s');
|
||||
return toFixedScaled(size / 1000, decimals, ' s');
|
||||
} else if (Math.abs(size) < 3600000) {
|
||||
// Less than 1 hour, divide in minutes
|
||||
return toFixedScaled(size / 60000, decimals, scaledDecimals, 5, ' min');
|
||||
return toFixedScaled(size / 60000, decimals, ' min');
|
||||
} else if (Math.abs(size) < 86400000) {
|
||||
// Less than one day, divide in hours
|
||||
return toFixedScaled(size / 3600000, decimals, scaledDecimals, 7, ' hour');
|
||||
return toFixedScaled(size / 3600000, decimals, ' hour');
|
||||
} else if (Math.abs(size) < 31536000000) {
|
||||
// Less than one year, divide in days
|
||||
return toFixedScaled(size / 86400000, decimals, scaledDecimals, 8, ' day');
|
||||
return toFixedScaled(size / 86400000, decimals, ' day');
|
||||
}
|
||||
|
||||
return toFixedScaled(size / 31536000000, decimals, scaledDecimals, 10, ' year');
|
||||
return toFixedScaled(size / 31536000000, decimals, ' year');
|
||||
}
|
||||
|
||||
export function trySubstract(value1: DecimalCount, value2: DecimalCount): DecimalCount {
|
||||
@ -98,7 +98,7 @@ export function trySubstract(value1: DecimalCount, value2: DecimalCount): Decima
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function toSeconds(size: number, decimals?: DecimalCount, scaledDecimals?: DecimalCount): FormattedValue {
|
||||
export function toSeconds(size: number, decimals?: DecimalCount): FormattedValue {
|
||||
if (size === null) {
|
||||
return { text: '' };
|
||||
}
|
||||
@ -110,37 +110,37 @@ export function toSeconds(size: number, decimals?: DecimalCount, scaledDecimals?
|
||||
|
||||
// Less than 1 µs, divide in ns
|
||||
if (Math.abs(size) < 0.000001) {
|
||||
return toFixedScaled(size * 1e9, decimals, trySubstract(scaledDecimals, decimals), -9, ' ns');
|
||||
return toFixedScaled(size * 1e9, decimals, ' ns');
|
||||
}
|
||||
// Less than 1 ms, divide in µs
|
||||
if (Math.abs(size) < 0.001) {
|
||||
return toFixedScaled(size * 1e6, decimals, trySubstract(scaledDecimals, decimals), -6, ' µs');
|
||||
return toFixedScaled(size * 1e6, decimals, ' µs');
|
||||
}
|
||||
// Less than 1 second, divide in ms
|
||||
if (Math.abs(size) < 1) {
|
||||
return toFixedScaled(size * 1e3, decimals, trySubstract(scaledDecimals, decimals), -3, ' ms');
|
||||
return toFixedScaled(size * 1e3, decimals, ' ms');
|
||||
}
|
||||
|
||||
if (Math.abs(size) < 60) {
|
||||
return { text: toFixed(size, decimals), suffix: ' s' };
|
||||
} else if (Math.abs(size) < 3600) {
|
||||
// Less than 1 hour, divide in minutes
|
||||
return toFixedScaled(size / 60, decimals, scaledDecimals, 1, ' min');
|
||||
return toFixedScaled(size / 60, decimals, ' min');
|
||||
} else if (Math.abs(size) < 86400) {
|
||||
// Less than one day, divide in hours
|
||||
return toFixedScaled(size / 3600, decimals, scaledDecimals, 4, ' hour');
|
||||
return toFixedScaled(size / 3600, decimals, ' hour');
|
||||
} else if (Math.abs(size) < 604800) {
|
||||
// Less than one week, divide in days
|
||||
return toFixedScaled(size / 86400, decimals, scaledDecimals, 5, ' day');
|
||||
return toFixedScaled(size / 86400, decimals, ' day');
|
||||
} else if (Math.abs(size) < 31536000) {
|
||||
// Less than one year, divide in week
|
||||
return toFixedScaled(size / 604800, decimals, scaledDecimals, 6, ' week');
|
||||
return toFixedScaled(size / 604800, decimals, ' week');
|
||||
}
|
||||
|
||||
return toFixedScaled(size / 3.15569e7, decimals, scaledDecimals, 7, ' year');
|
||||
return toFixedScaled(size / 3.15569e7, decimals, ' year');
|
||||
}
|
||||
|
||||
export function toMinutes(size: number, decimals?: DecimalCount, scaledDecimals?: DecimalCount): FormattedValue {
|
||||
export function toMinutes(size: number, decimals?: DecimalCount): FormattedValue {
|
||||
if (size === null) {
|
||||
return { text: '' };
|
||||
}
|
||||
@ -148,17 +148,17 @@ export function toMinutes(size: number, decimals?: DecimalCount, scaledDecimals?
|
||||
if (Math.abs(size) < 60) {
|
||||
return { text: toFixed(size, decimals), suffix: ' min' };
|
||||
} else if (Math.abs(size) < 1440) {
|
||||
return toFixedScaled(size / 60, decimals, scaledDecimals, 2, ' hour');
|
||||
return toFixedScaled(size / 60, decimals, ' hour');
|
||||
} else if (Math.abs(size) < 10080) {
|
||||
return toFixedScaled(size / 1440, decimals, scaledDecimals, 3, ' day');
|
||||
return toFixedScaled(size / 1440, decimals, ' day');
|
||||
} else if (Math.abs(size) < 604800) {
|
||||
return toFixedScaled(size / 10080, decimals, scaledDecimals, 4, ' week');
|
||||
return toFixedScaled(size / 10080, decimals, ' week');
|
||||
} else {
|
||||
return toFixedScaled(size / 5.25948e5, decimals, scaledDecimals, 5, ' year');
|
||||
return toFixedScaled(size / 5.25948e5, decimals, ' year');
|
||||
}
|
||||
}
|
||||
|
||||
export function toHours(size: number, decimals?: DecimalCount, scaledDecimals?: DecimalCount): FormattedValue {
|
||||
export function toHours(size: number, decimals?: DecimalCount): FormattedValue {
|
||||
if (size === null) {
|
||||
return { text: '' };
|
||||
}
|
||||
@ -166,15 +166,15 @@ export function toHours(size: number, decimals?: DecimalCount, scaledDecimals?:
|
||||
if (Math.abs(size) < 24) {
|
||||
return { text: toFixed(size, decimals), suffix: ' hour' };
|
||||
} else if (Math.abs(size) < 168) {
|
||||
return toFixedScaled(size / 24, decimals, scaledDecimals, 2, ' day');
|
||||
return toFixedScaled(size / 24, decimals, ' day');
|
||||
} else if (Math.abs(size) < 8760) {
|
||||
return toFixedScaled(size / 168, decimals, scaledDecimals, 3, ' week');
|
||||
return toFixedScaled(size / 168, decimals, ' week');
|
||||
} else {
|
||||
return toFixedScaled(size / 8760, decimals, scaledDecimals, 4, ' year');
|
||||
return toFixedScaled(size / 8760, decimals, ' year');
|
||||
}
|
||||
}
|
||||
|
||||
export function toDays(size: number, decimals?: DecimalCount, scaledDecimals?: DecimalCount): FormattedValue {
|
||||
export function toDays(size: number, decimals?: DecimalCount): FormattedValue {
|
||||
if (size === null) {
|
||||
return { text: '' };
|
||||
}
|
||||
@ -182,9 +182,9 @@ export function toDays(size: number, decimals?: DecimalCount, scaledDecimals?: D
|
||||
if (Math.abs(size) < 7) {
|
||||
return { text: toFixed(size, decimals), suffix: ' day' };
|
||||
} else if (Math.abs(size) < 365) {
|
||||
return toFixedScaled(size / 7, decimals, scaledDecimals, 2, ' week');
|
||||
return toFixedScaled(size / 7, decimals, ' week');
|
||||
} else {
|
||||
return toFixedScaled(size / 365, decimals, scaledDecimals, 3, ' year');
|
||||
return toFixedScaled(size / 365, decimals, ' year');
|
||||
}
|
||||
}
|
||||
|
||||
@ -340,8 +340,8 @@ export function toDurationInDaysHoursMinutesSeconds(size: number): FormattedValu
|
||||
return { text: dayString + hmsString.text };
|
||||
}
|
||||
|
||||
export function toTimeTicks(size: number, decimals: DecimalCount, scaledDecimals: DecimalCount): FormattedValue {
|
||||
return toSeconds(size / 100, decimals, scaledDecimals);
|
||||
export function toTimeTicks(size: number, decimals: DecimalCount): FormattedValue {
|
||||
return toSeconds(size / 100, decimals);
|
||||
}
|
||||
|
||||
export function toClockMilliseconds(size: number, decimals: DecimalCount): FormattedValue {
|
||||
|
@ -17,6 +17,10 @@ const formatTests: ValueFormatTest[] = [
|
||||
{ id: 'currencyUSD', decimals: 2, value: 1532.82, result: '$1.53K' },
|
||||
{ id: 'currencyKRW', decimals: 2, value: 1532.82, result: '₩1.53K' },
|
||||
{ id: 'currencyIDR', decimals: 2, value: 1532.82, result: 'Rp1.53K' },
|
||||
// no unit
|
||||
{ id: 'none', decimals: null, value: 3.23, result: '3.23' },
|
||||
{ id: 'none', decimals: null, value: 0.0245, result: '0.0245' },
|
||||
{ id: 'none', decimals: null, value: 1 / 3, result: '0.333' },
|
||||
|
||||
// Standard
|
||||
{ id: 'ms', decimals: 4, value: 0.0024, result: '0.0024 ms' },
|
||||
@ -24,11 +28,17 @@ const formatTests: ValueFormatTest[] = [
|
||||
{ id: 'ms', decimals: 2, value: 1250, result: '1.25 s' },
|
||||
{ id: 'ms', decimals: 1, value: 10000086.123, result: '2.8 hour' },
|
||||
{ id: 'ms', decimals: 0, value: 1200, result: '1 s' },
|
||||
{ id: 'short', decimals: 0, scaledDecimals: -1, value: 98765, result: '98.77 K' },
|
||||
{ id: 'short', decimals: 0, scaledDecimals: 0, value: 9876543, result: '9.876543 Mil' },
|
||||
{ id: 'short', decimals: 2, scaledDecimals: null, value: 9876543, result: '9.88 Mil' },
|
||||
{ id: 'kbytes', decimals: 3, value: 10000000, result: '9.537 GiB' },
|
||||
{ id: 'deckbytes', decimals: 3, value: 10000000, result: '10.000 GB' },
|
||||
{ id: 'short', decimals: null, value: 1000, result: '1 K' },
|
||||
{ id: 'short', decimals: null, value: 1200, result: '1.20 K' },
|
||||
{ id: 'short', decimals: null, value: 1250, result: '1.25 K' },
|
||||
{ id: 'short', decimals: null, value: 1000000, result: '1 Mil' },
|
||||
{ id: 'short', decimals: null, value: 1500000, result: '1.50 Mil' },
|
||||
{ id: 'short', decimals: null, value: 1000120, result: '1.00 Mil' },
|
||||
{ id: 'short', decimals: null, value: 98765, result: '98.8 K' },
|
||||
{ id: 'short', decimals: null, value: 9876543, result: '9.88 Mil' },
|
||||
{ id: 'short', decimals: null, value: 9876543, result: '9.88 Mil' },
|
||||
{ id: 'kbytes', decimals: null, value: 10000000, result: '9.54 GiB' },
|
||||
{ id: 'deckbytes', decimals: null, value: 10000000, result: '10 GB' },
|
||||
{ id: 'megwatt', decimals: 3, value: 1000, result: '1.000 GW' },
|
||||
{ id: 'kohm', decimals: 3, value: 1000, result: '1.000 MΩ' },
|
||||
{ id: 'Mohm', decimals: 3, value: 1000, result: '1.000 GΩ' },
|
||||
|
@ -45,10 +45,15 @@ export function toFixed(value: number, decimals?: DecimalCount): string {
|
||||
if (value === null) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (value === Number.NEGATIVE_INFINITY || value === Number.POSITIVE_INFINITY) {
|
||||
return value.toLocaleString();
|
||||
}
|
||||
|
||||
if (decimals === null || decimals === undefined) {
|
||||
decimals = getDecimalsForValue(value);
|
||||
}
|
||||
|
||||
const factor = decimals ? Math.pow(10, Math.max(0, decimals)) : 1;
|
||||
const formatted = String(Math.round(value * factor) / factor);
|
||||
|
||||
@ -57,31 +62,37 @@ export function toFixed(value: number, decimals?: DecimalCount): string {
|
||||
return formatted;
|
||||
}
|
||||
|
||||
// If tickDecimals was specified, ensure that we have exactly that
|
||||
// much precision; otherwise default to the value's own precision.
|
||||
if (decimals != null) {
|
||||
const decimalPos = formatted.indexOf('.');
|
||||
const precision = decimalPos === -1 ? 0 : formatted.length - decimalPos - 1;
|
||||
if (precision < decimals) {
|
||||
return (precision ? formatted : formatted + '.') + String(factor).substr(1, decimals - precision);
|
||||
}
|
||||
const decimalPos = formatted.indexOf('.');
|
||||
const precision = decimalPos === -1 ? 0 : formatted.length - decimalPos - 1;
|
||||
if (precision < decimals) {
|
||||
return (precision ? formatted : formatted + '.') + String(factor).substr(1, decimals - precision);
|
||||
}
|
||||
|
||||
return formatted;
|
||||
}
|
||||
|
||||
export function toFixedScaled(
|
||||
value: number,
|
||||
decimals: DecimalCount,
|
||||
scaledDecimals: DecimalCount,
|
||||
additionalDecimals: number,
|
||||
ext?: string
|
||||
): FormattedValue {
|
||||
if (scaledDecimals === null || scaledDecimals === undefined) {
|
||||
return { text: toFixed(value, decimals), suffix: ext };
|
||||
function getDecimalsForValue(value: number): number {
|
||||
const log10 = Math.floor(Math.log(Math.abs(value)) / Math.LN10);
|
||||
let dec = -log10 + 1;
|
||||
const magn = Math.pow(10, -dec);
|
||||
const norm = value / magn; // norm is between 1.0 and 10.0
|
||||
|
||||
// special case for 2.5, requires an extra decimal
|
||||
if (norm > 2.25) {
|
||||
++dec;
|
||||
}
|
||||
|
||||
if (value % 1 === 0) {
|
||||
dec = 0;
|
||||
}
|
||||
|
||||
const decimals = Math.max(0, dec);
|
||||
return decimals;
|
||||
}
|
||||
|
||||
export function toFixedScaled(value: number, decimals: DecimalCount, ext?: string): FormattedValue {
|
||||
return {
|
||||
text: toFixed(value, scaledDecimals + additionalDecimals),
|
||||
text: toFixed(value, decimals),
|
||||
suffix: ext,
|
||||
};
|
||||
}
|
||||
@ -126,10 +137,6 @@ export function scaledUnits(factor: number, extArray: string[]): ValueFormatter
|
||||
}
|
||||
}
|
||||
|
||||
if (steps > 0 && scaledDecimals !== null && scaledDecimals !== undefined) {
|
||||
decimals = scaledDecimals + 3 * steps;
|
||||
}
|
||||
|
||||
return { text: toFixed(size, decimals), suffix: extArray[steps] };
|
||||
};
|
||||
}
|
||||
|
@ -599,7 +599,7 @@ describe('logSeriesToLogsModel', () => {
|
||||
hasUniqueLabels: false,
|
||||
meta: [
|
||||
{ label: 'Limit', value: '1000 (0 returned)', kind: 1 },
|
||||
{ label: 'Total bytes processed', value: '97 kB', kind: 1 },
|
||||
{ label: 'Total bytes processed', value: '97.0 kB', kind: 1 },
|
||||
],
|
||||
rows: [],
|
||||
};
|
||||
|
@ -4,7 +4,6 @@ import { DecimalCount, TimeZone } from '@grafana/data';
|
||||
interface ValueFormatTest {
|
||||
id: string;
|
||||
decimals?: DecimalCount;
|
||||
scaledDecimals?: DecimalCount;
|
||||
timeZone?: TimeZone;
|
||||
value: number;
|
||||
result: string;
|
||||
@ -22,8 +21,8 @@ const formatTests: ValueFormatTest[] = [
|
||||
{ id: 'ms', decimals: 2, value: 1250, result: '1.25 s' },
|
||||
{ id: 'ms', decimals: 1, value: 10000086.123, result: '2.8 hour' },
|
||||
{ id: 'ms', decimals: 0, value: 1200, result: '1 s' },
|
||||
{ id: 'short', decimals: 0, scaledDecimals: -1, value: 98765, result: '98.77 K' },
|
||||
{ id: 'short', decimals: 0, scaledDecimals: 0, value: 9876543, result: '9.876543 Mil' },
|
||||
{ id: 'short', decimals: 0, value: 98765, result: '99 K' },
|
||||
{ id: 'short', decimals: 0, value: 9876543, result: '10 Mil' },
|
||||
{ id: 'kbytes', decimals: 3, value: 10000000, result: '9.537 GiB' },
|
||||
{ id: 'deckbytes', decimals: 3, value: 10000000, result: '10.000 GB' },
|
||||
{ id: 'megwatt', decimals: 3, value: 1000, result: '1.000 GW' },
|
||||
@ -45,7 +44,7 @@ describe('Chcek KBN value formats', () => {
|
||||
for (const test of formatTests) {
|
||||
describe(`value format: ${test.id}`, () => {
|
||||
it(`should translate ${test.value} as ${test.result}`, () => {
|
||||
const result = kbn.valueFormats[test.id](test.value, test.decimals, test.scaledDecimals);
|
||||
const result = kbn.valueFormats[test.id](test.value, test.decimals);
|
||||
expect(result).toBe(test.result);
|
||||
});
|
||||
});
|
||||
|
@ -743,7 +743,7 @@ class GraphElement {
|
||||
};
|
||||
|
||||
// Use 'short' format for histogram values
|
||||
this.configureAxisMode(options.xaxis, 'short');
|
||||
this.configureAxisMode(options.xaxis, 'short', null);
|
||||
}
|
||||
|
||||
addXTableAxis(options: any) {
|
||||
@ -794,13 +794,15 @@ class GraphElement {
|
||||
this.applyLogScale(options.yaxes[1], data);
|
||||
this.configureAxisMode(
|
||||
options.yaxes[1],
|
||||
this.panel.percentage && this.panel.stack ? 'percent' : this.panel.yaxes[1].format
|
||||
this.panel.percentage && this.panel.stack ? 'percent' : this.panel.yaxes[1].format,
|
||||
this.panel.yaxes[1].decimals
|
||||
);
|
||||
}
|
||||
this.applyLogScale(options.yaxes[0], data);
|
||||
this.configureAxisMode(
|
||||
options.yaxes[0],
|
||||
this.panel.percentage && this.panel.stack ? 'percent' : this.panel.yaxes[0].format
|
||||
this.panel.percentage && this.panel.stack ? 'percent' : this.panel.yaxes[0].format,
|
||||
this.panel.yaxes[0].decimals
|
||||
);
|
||||
}
|
||||
|
||||
@ -915,14 +917,19 @@ class GraphElement {
|
||||
return ticks;
|
||||
}
|
||||
|
||||
configureAxisMode(axis: { tickFormatter: (val: any, axis: any) => string }, format: string) {
|
||||
configureAxisMode(
|
||||
axis: { tickFormatter: (val: any, axis: any) => string },
|
||||
format: string,
|
||||
decimals?: number | null
|
||||
) {
|
||||
axis.tickFormatter = (val, axis) => {
|
||||
const formatter = getValueFormat(format);
|
||||
|
||||
if (!formatter) {
|
||||
throw new Error(`Unit '${format}' is not supported`);
|
||||
}
|
||||
return formattedValueToString(formatter(val, axis.tickDecimals, axis.scaledDecimals));
|
||||
|
||||
return formattedValueToString(formatter(val, decimals));
|
||||
};
|
||||
}
|
||||
}
|
||||
|
5
public/vendor/flot/jquery.flot.js
vendored
5
public/vendor/flot/jquery.flot.js
vendored
@ -1783,11 +1783,6 @@ Licensed under the MIT license.
|
||||
axis.tickDecimals = Math.max(0, maxDec != null ? maxDec : dec);
|
||||
axis.tickSize = opts.tickSize || size;
|
||||
|
||||
// grafana addition
|
||||
if (opts.tickDecimals === null || opts.tickDecimals === undefined) {
|
||||
axis.scaledDecimals = axis.tickDecimals + dec;
|
||||
}
|
||||
|
||||
// Time mode was moved to a plug-in in 0.8, and since so many people use it
|
||||
// we'll add an especially friendly reminder to make sure they included it.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user