mirror of
https://github.com/Graylog2/graylog2-server.git
synced 2026-03-13 09:32:21 +08:00
Use GiB on traffic charts. Mention UTC as time for calculation (#24983)
* Use GiB on traffic charts. Mention UTC as time for calculation * Add changelog * Adding further tests for unit conversion. * Rename `ram_size` to `binary_size` because it also used for network traffic. --------- Co-authored-by: Dennis Oelkers <dennis@graylog.com> Co-authored-by: Linus Pahl <linus.pahl@graylog.com>
This commit is contained in:
committed by
GitHub
parent
c33959ea1d
commit
464412a278
5
changelog/unreleased/issue-24982.toml
Normal file
5
changelog/unreleased/issue-24982.toml
Normal file
@@ -0,0 +1,5 @@
|
||||
type = "f"
|
||||
message = "Use GiB units for defining traffic limits in the chart. Add a label indicating that limits are calculated in UTC."
|
||||
|
||||
issues = ["24982"]
|
||||
pulls = ["24983"]
|
||||
@@ -63,7 +63,7 @@ const TrafficGraph = ({ width, traffic, trafficLimit = undefined }: Props) => {
|
||||
y: yValues,
|
||||
...getHoverTemplateSettings({
|
||||
convertedValues: yValues,
|
||||
unit: FieldUnit.fromJSON({ abbrev: 'b', unit_type: 'size' }),
|
||||
unit: FieldUnit.fromJSON({ abbrev: 'b', unit_type: 'binary_size' }),
|
||||
}),
|
||||
},
|
||||
],
|
||||
@@ -122,14 +122,14 @@ const TrafficGraph = ({ width, traffic, trafficLimit = undefined }: Props) => {
|
||||
const notZoomedLayout = useMemo<GeneratedLayout>(
|
||||
() => ({
|
||||
rangemode: 'tozero',
|
||||
...(getFormatSettingsByData('size', valuesToGetFormatSettings) as GeneratedLayout),
|
||||
...(getFormatSettingsByData('binary_size', valuesToGetFormatSettings) as GeneratedLayout),
|
||||
}),
|
||||
[valuesToGetFormatSettings],
|
||||
);
|
||||
const zoomedLayout = useMemo(
|
||||
() => ({
|
||||
rangemode: 'tozero',
|
||||
...(getFormatSettingsByData('size', yValues) as GeneratedLayout),
|
||||
...(getFormatSettingsByData('binary_size', yValues) as GeneratedLayout),
|
||||
}),
|
||||
[yValues],
|
||||
);
|
||||
@@ -143,7 +143,7 @@ const TrafficGraph = ({ width, traffic, trafficLimit = undefined }: Props) => {
|
||||
xaxis: {
|
||||
type: 'date',
|
||||
title: {
|
||||
text: 'Time',
|
||||
text: 'Time shown in UTC',
|
||||
},
|
||||
},
|
||||
hovermode: 'x',
|
||||
|
||||
@@ -89,7 +89,7 @@ const TrafficGraphWithDaySelect = ({ traffic, trafficLimit = undefined, title =
|
||||
const unixTraffic = useMemo(() => (traffic ? formatTrafficData(traffic) : null), [traffic]);
|
||||
|
||||
const formattedTotalTraffic = useMemo(() => {
|
||||
const prettified = getPrettifiedValue(bytesOut, { abbrev: 'b', unitType: 'size' });
|
||||
const prettified = getPrettifiedValue(bytesOut, { abbrev: 'b', unitType: 'binary_size' });
|
||||
|
||||
return formatValueWithUnitLabel(prettified?.value, prettified.unit.abbrev);
|
||||
}, [bytesOut]);
|
||||
|
||||
@@ -24,7 +24,7 @@ import Popover from 'components/common/Popover';
|
||||
import { HoverForHelp, ModalButtonToolbar } from 'components/common';
|
||||
import { Alert, Button, Input } from 'components/bootstrap';
|
||||
import type { Unit } from 'views/components/visualizations/utils/unitConverters';
|
||||
import { mappedUnitsFromJSON as units } from 'views/components/visualizations/utils/unitConverters';
|
||||
import { mappedUnitsFromJSONForAggregation as units } from 'views/components/visualizations/utils/unitConverters';
|
||||
import type { FieldUnitsFormValues } from 'views/types';
|
||||
import type FieldUnit from 'views/logic/aggregationbuilder/FieldUnit';
|
||||
import getUnitTextLabel from 'views/components/visualizations/utils/getUnitTextLabel';
|
||||
|
||||
@@ -71,6 +71,22 @@ describe('Unit converter functions', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('for binary_size should convert bigger unit to bytes', () => {
|
||||
const result = convertValueToBaseUnit(1, { abbrev: 'KiB', unitType: 'binary_size' });
|
||||
|
||||
expect(result).toEqual({
|
||||
value: 1024,
|
||||
unit: {
|
||||
type: 'base',
|
||||
abbrev: 'b',
|
||||
name: 'byte',
|
||||
unitType: 'binary_size',
|
||||
useInPrettier: true,
|
||||
conversion: undefined,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('for percent should convert bigger unit to decimal percent', () => {
|
||||
const result = convertValueToBaseUnit(50, { abbrev: '%', unitType: 'percent' });
|
||||
|
||||
@@ -201,6 +217,75 @@ describe('Unit converter functions', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('for binary_size should convert smaller unit (KiB) to bigger (GiB)', () => {
|
||||
const result = convertValueToUnit(
|
||||
1048576,
|
||||
{ abbrev: 'KiB', unitType: 'binary_size' },
|
||||
{ abbrev: 'GiB', unitType: 'binary_size' },
|
||||
);
|
||||
|
||||
expect(result).toEqual({
|
||||
value: 1,
|
||||
unit: {
|
||||
type: 'derived',
|
||||
abbrev: 'GiB',
|
||||
name: 'gibibyte',
|
||||
unitType: 'binary_size',
|
||||
useInPrettier: true,
|
||||
conversion: {
|
||||
value: 1073741824,
|
||||
action: 'MULTIPLY',
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('for binary_size should convert bytes to GiB', () => {
|
||||
const result = convertValueToUnit(
|
||||
3221225472,
|
||||
{ abbrev: 'b', unitType: 'binary_size' },
|
||||
{ abbrev: 'GiB', unitType: 'binary_size' },
|
||||
);
|
||||
|
||||
expect(result).toEqual({
|
||||
value: 3,
|
||||
unit: {
|
||||
type: 'derived',
|
||||
abbrev: 'GiB',
|
||||
name: 'gibibyte',
|
||||
unitType: 'binary_size',
|
||||
useInPrettier: true,
|
||||
conversion: {
|
||||
value: 1073741824,
|
||||
action: 'MULTIPLY',
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('for binary_size should convert bytes to MiB', () => {
|
||||
const result = convertValueToUnit(
|
||||
1572864,
|
||||
{ abbrev: 'b', unitType: 'binary_size' },
|
||||
{ abbrev: 'MiB', unitType: 'binary_size' },
|
||||
);
|
||||
|
||||
expect(result).toEqual({
|
||||
value: 1.5,
|
||||
unit: {
|
||||
type: 'derived',
|
||||
abbrev: 'MiB',
|
||||
name: 'mebibyte',
|
||||
unitType: 'binary_size',
|
||||
useInPrettier: true,
|
||||
conversion: {
|
||||
value: 1048576,
|
||||
action: 'MULTIPLY',
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('return nulls when some params where missed', () => {
|
||||
const result1 = convertValueToUnit(50, { abbrev: 'Gb', unitType: 'size' }, undefined);
|
||||
const result2 = convertValueToUnit(50, undefined, { abbrev: 'Gb', unitType: 'size' });
|
||||
@@ -301,6 +386,82 @@ describe('Unit converter functions', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('for binary_size should convert smaller then 1 value to the value with lower unit', () => {
|
||||
const result = getPrettifiedValue(0.5, { abbrev: 'GiB', unitType: 'binary_size' });
|
||||
|
||||
expect(result).toEqual({
|
||||
value: 512,
|
||||
unit: {
|
||||
type: 'derived',
|
||||
abbrev: 'MiB',
|
||||
name: 'mebibyte',
|
||||
unitType: 'binary_size',
|
||||
useInPrettier: true,
|
||||
conversion: {
|
||||
value: 1048576,
|
||||
action: 'MULTIPLY',
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('for binary_size should convert bigger then 1 value to the value with higher unit', () => {
|
||||
const result = getPrettifiedValue(2048, { abbrev: 'MiB', unitType: 'binary_size' });
|
||||
|
||||
expect(result).toEqual({
|
||||
value: 2,
|
||||
unit: {
|
||||
type: 'derived',
|
||||
abbrev: 'GiB',
|
||||
name: 'gibibyte',
|
||||
unitType: 'binary_size',
|
||||
useInPrettier: true,
|
||||
conversion: {
|
||||
value: 1073741824,
|
||||
action: 'MULTIPLY',
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('for binary_size should prettify larger bytes to GiB', () => {
|
||||
const result = getPrettifiedValue(3221225472, { abbrev: 'b', unitType: 'binary_size' });
|
||||
|
||||
expect(result).toEqual({
|
||||
value: 3,
|
||||
unit: {
|
||||
type: 'derived',
|
||||
abbrev: 'GiB',
|
||||
name: 'gibibyte',
|
||||
unitType: 'binary_size',
|
||||
useInPrettier: true,
|
||||
conversion: {
|
||||
value: 1073741824,
|
||||
action: 'MULTIPLY',
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('for binary_size should prettify larger bytes to MiB', () => {
|
||||
const result = getPrettifiedValue(1572864, { abbrev: 'b', unitType: 'binary_size' });
|
||||
|
||||
expect(result).toEqual({
|
||||
value: 1.5,
|
||||
unit: {
|
||||
type: 'derived',
|
||||
abbrev: 'MiB',
|
||||
name: 'mebibyte',
|
||||
unitType: 'binary_size',
|
||||
useInPrettier: true,
|
||||
conversion: {
|
||||
value: 1048576,
|
||||
action: 'MULTIPLY',
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('for percent should always convert to integer % unit', () => {
|
||||
const result1 = getPrettifiedValue(100, { abbrev: 'd%', unitType: 'percent' });
|
||||
const result2 = getPrettifiedValue(10000, { abbrev: '%', unitType: 'percent' });
|
||||
|
||||
@@ -117,6 +117,8 @@ export const getFormatSettingsByData = (unitTypeKey: FieldUnitType | DefaultAxis
|
||||
};
|
||||
case 'size':
|
||||
return getFormatSettingsWithCustomTickVals(values, 'size');
|
||||
case 'binary_size':
|
||||
return getFormatSettingsWithCustomTickVals(values, 'binary_size');
|
||||
case 'time':
|
||||
return getFormatSettingsWithCustomTickVals(values, 'time');
|
||||
default:
|
||||
@@ -311,7 +313,11 @@ export const getHoverTemplateSettings = ({
|
||||
unit: FieldUnit;
|
||||
name?: string;
|
||||
}): { text: Array<string>; hovertemplate: string; meta: string } | {} => {
|
||||
if (unit?.unitType === 'time' || unit?.unitType === 'size') {
|
||||
if (
|
||||
unit?.unitType === 'time' ||
|
||||
unit?.unitType === 'size' ||
|
||||
unit?.unitType === 'binary_size'
|
||||
) {
|
||||
return {
|
||||
text: getHoverTexts({ convertedValues, unit }),
|
||||
hovertemplate: `%{text}<br>${name ? '<extra>%{meta}</extra>' : '<extra></extra>'}`,
|
||||
|
||||
@@ -28,6 +28,45 @@ import supportedUnits from '../../../../../../graylog2-server/src/main/resources
|
||||
|
||||
type UnitConversionAction = 'MULTIPLY' | 'DIVIDE';
|
||||
|
||||
const binarySize = [
|
||||
{
|
||||
'type': 'base',
|
||||
'abbrev': 'b',
|
||||
'name': 'byte',
|
||||
'unit_type': 'binary_size',
|
||||
},
|
||||
{
|
||||
'type': 'derived',
|
||||
'abbrev': 'KiB',
|
||||
'name': 'kibibyte',
|
||||
'unit_type': 'binary_size',
|
||||
'conversion': {
|
||||
'value': 1024,
|
||||
'action': 'MULTIPLY',
|
||||
},
|
||||
},
|
||||
{
|
||||
'type': 'derived',
|
||||
'abbrev': 'MiB',
|
||||
'name': 'mebibyte',
|
||||
'unit_type': 'binary_size',
|
||||
'conversion': {
|
||||
'value': 1048576,
|
||||
'action': 'MULTIPLY',
|
||||
},
|
||||
},
|
||||
{
|
||||
'type': 'derived',
|
||||
'abbrev': 'GiB',
|
||||
'name': 'gibibyte',
|
||||
'unit_type': 'binary_size',
|
||||
'conversion': {
|
||||
'value': 1073741824,
|
||||
'action': 'MULTIPLY',
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const sourceUnits = supportedUnits.units as FieldUnitTypesJson;
|
||||
export type UnitJson = {
|
||||
type: 'base' | 'derived';
|
||||
@@ -70,13 +109,21 @@ const unitFromJson = (unitJson: UnitJson): Unit => ({
|
||||
conversion: unitJson.conversion,
|
||||
useInPrettier: isUnitUsableInPrettier(unitJson),
|
||||
});
|
||||
export const mappedUnitsFromJSON: FieldUnitTypes = <FieldUnitTypes>(
|
||||
|
||||
export const mappedUnitsFromJSONForAggregation: FieldUnitTypes = <FieldUnitTypes>(
|
||||
mapValues(
|
||||
sourceUnits,
|
||||
(unitsJson: Array<UnitJson>): Array<Unit> => unitsJson.map((unitJson: UnitJson): Unit => unitFromJson(unitJson)),
|
||||
)
|
||||
);
|
||||
|
||||
export const mappedUnitsFromJSON: FieldUnitTypes = <FieldUnitTypes>(
|
||||
mapValues(
|
||||
{ ...sourceUnits, binary_size: binarySize },
|
||||
(unitsJson: Array<UnitJson>): Array<Unit> => unitsJson.map((unitJson: UnitJson): Unit => unitFromJson(unitJson)),
|
||||
)
|
||||
);
|
||||
|
||||
export const _getBaseUnit = (units: FieldUnitTypes, unitType: FieldUnitType): Unit =>
|
||||
units[unitType].find(({ type }) => type === 'base');
|
||||
|
||||
|
||||
@@ -569,7 +569,7 @@ export interface WidgetCreator {
|
||||
icon: React.ComponentType<{}>;
|
||||
}
|
||||
|
||||
export type FieldUnitType = 'size' | 'time' | 'percent';
|
||||
export type FieldUnitType = 'size' | 'time' | 'percent' | 'binary_size';
|
||||
|
||||
export type DefaultAxisKey = typeof DEFAULT_AXIS_KEY;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user