Skip to content

Commit

Permalink
StatsHouse UI: add unit (#741)
Browse files Browse the repository at this point in the history
  • Loading branch information
vauweb authored Sep 11, 2023
1 parent fb50699 commit 4963519
Show file tree
Hide file tree
Showing 13 changed files with 524 additions and 34 deletions.
1 change: 1 addition & 0 deletions statshouse-ui/src/admin/api/saveMetric.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export function saveMetric(metric: IMetric) {
skip_min_host: !!metric.skip_min_host,
skip_sum_square: !!metric.skip_sum_square,
pre_key_only: !!metric.pre_key_only,
metric_type: metric.metric_type,
version: metric.version,
group_id: metric.group_id,
};
Expand Down
2 changes: 2 additions & 0 deletions statshouse-ui/src/admin/models/metric.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ export interface IMetric extends IShortMetric {
readonly skip_min_host?: boolean;
readonly skip_sum_square?: boolean;
readonly pre_key_only?: boolean;
readonly metric_type?: string;
readonly version?: number;
readonly group_id?: number;
}
Expand All @@ -68,6 +69,7 @@ export interface IBackendMetric {
readonly skip_min_host?: boolean;
readonly skip_sum_square?: boolean;
readonly pre_key_only?: boolean;
readonly metric_type?: string;
readonly version?: number;
readonly group_id?: number;
}
31 changes: 30 additions & 1 deletion statshouse-ui/src/admin/pages/FormPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,12 @@ import { IActions } from '../storages/MetricFormValues/reducer';
import { selectorListMetricsGroup, selectorLoadListMetricsGroup, useStore } from '../../store';
import { RawValueKind } from '../../view/api';
import { freeKeyPrefix } from '../../url/queryParams';
import { METRIC_TYPE, METRIC_TYPE_DESCRIPTION, MetricType } from '../../api/enum';

const { clearMetricsMeta } = useStore.getState();

const METRIC_TYPE_KEYS: MetricType[] = Object.values(METRIC_TYPE) as MetricType[];

export function FormPage(props: { yAxisSize: number; adminMode: boolean }) {
const { yAxisSize, adminMode } = props;
const { metricName } = useParams();
Expand Down Expand Up @@ -53,11 +56,12 @@ export function FormPage(props: { yAxisSize: number; adminMode: boolean }) {
tagsSize: String(metric.tags.length),
pre_key_tag_id: metric.pre_key_tag_id && freeKeyPrefix(metric.pre_key_tag_id),
pre_key_from: metric.pre_key_from,
metric_type: metric.metric_type,
version: metric.version,
group_id: metric.group_id,
})
);
}, [metricName, setInitMetric]);
}, [metricName]);

// update document title
React.useEffect(() => {
Expand Down Expand Up @@ -226,6 +230,31 @@ export function EditForm(props: { isReadonly: boolean; adminMode: boolean }) {
resolution might render with surprises in UI.
</div>
</div>
{adminMode && (
<div className="row mb-3">
<label htmlFor="unit" className="col-sm-2 col-form-label">
Unit
</label>
<div className="col-sm-auto">
<select
id="unit"
className="form-select"
value={values.metric_type}
onChange={(e) => dispatch({ metric_type: e.target.value })}
disabled={isReadonly}
>
{METRIC_TYPE_KEYS.map((unit_type) => (
<option key={unit_type} value={unit_type}>
{METRIC_TYPE_DESCRIPTION[unit_type]}
</option>
))}
</select>
</div>
<div id="unitHelpBlock" className="form-text">
The unit in which the metric is written
</div>
</div>
)}
<div className="row mb-3">
<label htmlFor="weight" className="col-sm-2 col-form-label">
Weight
Expand Down
27 changes: 26 additions & 1 deletion statshouse-ui/src/api/enum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

import { isEnum } from '../common/helpers';
import { isEnum, toEnum } from '../common/helpers';

export type Enum<T> = T[keyof T];

Expand Down Expand Up @@ -196,3 +196,28 @@ export type ApiFetchOptMethods = Enum<typeof API_FETCH_OPT_METHODS>;

export const isQueryWhat = isEnum<QueryWhat>(QUERY_WHAT);
export const isTagKey = isEnum<TagKey>(TAG_KEY);

/**
* metric unit type
*/
export const METRIC_TYPE = {
none: '',
// time
second: 'second',
millisecond: 'millisecond',
microsecond: 'microsecond',
nanosecond: 'nanosecond',
// data size
byte: 'byte',
} as const;
export type MetricType = Enum<typeof METRIC_TYPE>;
export const isMetricType = isEnum<MetricType>(METRIC_TYPE);
export const toMetricType = toEnum(isMetricType);
export const METRIC_TYPE_DESCRIPTION: Record<MetricType, string> = {
[METRIC_TYPE.none]: 'no unit',
[METRIC_TYPE.second]: 'second',
[METRIC_TYPE.millisecond]: 'millisecond',
[METRIC_TYPE.microsecond]: 'microsecond',
[METRIC_TYPE.nanosecond]: 'nanosecond',
[METRIC_TYPE.byte]: 'byte',
};
1 change: 1 addition & 0 deletions statshouse-ui/src/api/metric.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ export type MetricMetaValue = {
skip_min_host?: boolean;
skip_sum_square?: boolean;
pre_key_only?: boolean;
metric_type?: string;
};

export type MetricMetaTag = {
Expand Down
210 changes: 210 additions & 0 deletions statshouse-ui/src/common/formatByMetricType.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
import { formatByMetricType } from './formatByMetricType';
import { METRIC_TYPE } from '../api/enum';

describe('formatByMetricType', () => {
test('none', () => {
const formatter = formatByMetricType(METRIC_TYPE.none);
expect(formatter(0)).toEqual('0');
expect(formatter(0.01111)).toEqual('0.011');
expect(formatter(0.001111)).toEqual('1.111m');
expect(formatter(0.000001111)).toEqual('1.111μ');
expect(formatter(0.000000001111)).toEqual('1.111n');
expect(formatter(0.000000000001111)).toEqual('1.111p');
expect(formatter(0.000000000000001111)).toEqual('1.111f');
expect(formatter(0.000000000000000001111)).toEqual('1.111a');
expect(formatter(0.000000000000000000001111)).toEqual('1.111z');
expect(formatter(0.000000000000000000000001111)).toEqual('1.111y');
expect(formatter(0.000000000000000000000000001111)).toEqual('0.001y');
expect(formatter(1111)).toEqual('1.111k');
expect(formatter(1111100)).toEqual('1.111M');
expect(formatter(1111100000)).toEqual('1.111G');
expect(formatter(1111100000000)).toEqual('1.111T');
expect(formatter(1111100000000000)).toEqual('1.111P');
expect(formatter(1111100000000000000)).toEqual('1.111E');
expect(formatter(1111100000000000000000)).toEqual('1.111Z');
expect(formatter(1111100000000000000000000)).toEqual('1.111Y');
expect(formatter(1111100000000000000000000000)).toEqual('1111.1Y');
});
test('byte', () => {
const formatter = formatByMetricType(METRIC_TYPE.byte);
expect(formatter(0)).toEqual('0');
expect(formatter(0.1111)).toEqual('0.1b');
expect(formatter(0.01111)).toEqual('0b');
expect(formatter(1)).toEqual('1b');
expect(formatter(11)).toEqual('11b');
expect(formatter(111)).toEqual('111b');
expect(formatter(256)).toEqual('256b');
expect(formatter(512)).toEqual('512b');
expect(formatter(970)).toEqual('970b');
let p = 1024;
expect(formatter(p)).toEqual('1kb');
expect(formatter(1.11 * p)).toEqual('1.1kb');
expect(formatter(1.5 * p)).toEqual('1.5kb');
expect(formatter(1.9 * p)).toEqual('1.9kb');
expect(formatter(1.99 * p)).toEqual('2kb');
expect(formatter(10 * p)).toEqual('10kb');
expect(formatter(100 * p)).toEqual('100kb');
expect(formatter(100 * p)).toEqual('100kb');
expect(formatter(1000 * p)).toEqual('1000kb');
p *= 1024;
expect(formatter(p)).toEqual('1Mb');
expect(formatter(10 * p)).toEqual('10Mb');
expect(formatter(100 * p)).toEqual('100Mb');
expect(formatter(1000 * p)).toEqual('1000Mb');
p *= 1024;
expect(formatter(p)).toEqual('1Gb');
expect(formatter(10 * p)).toEqual('10Gb');
expect(formatter(100 * p)).toEqual('100Gb');
expect(formatter(1000 * p)).toEqual('1000Gb');
p *= 1024;
expect(formatter(p)).toEqual('1Tb');
expect(formatter(10 * p)).toEqual('10Tb');
expect(formatter(100 * p)).toEqual('100Tb');
expect(formatter(1000 * p)).toEqual('1000Tb');
p *= 1024;
expect(formatter(p)).toEqual('1Pb');
expect(formatter(10 * p)).toEqual('10Pb');
expect(formatter(100 * p)).toEqual('100Pb');
expect(formatter(1000 * p)).toEqual('1000Pb');
p *= 1024;
expect(formatter(p)).toEqual('1Eb');
expect(formatter(10 * p)).toEqual('10Eb');
expect(formatter(100 * p)).toEqual('100Eb');
expect(formatter(1000 * p)).toEqual('1000Eb');
p *= 1024;
expect(formatter(p)).toEqual('1Zb');
expect(formatter(10 * p)).toEqual('10Zb');
expect(formatter(100 * p)).toEqual('100Zb');
expect(formatter(1000 * p)).toEqual('1000Zb');
p *= 1024;
expect(formatter(p)).toEqual('1Yb');
expect(formatter(10 * p)).toEqual('10Yb');
expect(formatter(100 * p)).toEqual('100Yb');
expect(formatter(1000 * p)).toEqual('1000Yb');
p *= 1024;
expect(formatter(p)).toEqual('1024Yb');
expect(formatter(10 * p)).toEqual('10240Yb');
expect(formatter(100 * p)).toEqual('102400Yb');
expect(formatter(1000 * p)).toEqual('1024000Yb');
});
test('second', () => {
const formatter = formatByMetricType(METRIC_TYPE.second);
expect(formatter(0)).toEqual('0');
expect(formatter(1)).toEqual('1s');
expect(formatter(0.1)).toEqual('100ms');
expect(formatter(0.1111)).toEqual('111.1ms');
expect(formatter(0.01111)).toEqual('11.11ms');
expect(formatter(0.0011111)).toEqual('1.111ms');
expect(formatter(0.00011111)).toEqual('111.11μs');
expect(formatter(0.000011111)).toEqual('11.111μs');
expect(formatter(0.0000011111)).toEqual('1.111μs');
expect(formatter(0.00000011111)).toEqual('111.11ns');
expect(formatter(0.000000011111)).toEqual('11.111ns');
expect(formatter(0.0000000011111)).toEqual('1.111ns');
expect(formatter(0.0000000000011111)).toEqual('0.001ns');
expect(formatter(0.00000000000011111)).toEqual('0ns');
expect(formatter(11)).toEqual('11s');
expect(formatter(111)).toEqual('111s');
expect(formatter(119)).toEqual('119s');
expect(formatter(120)).toEqual('2m');
expect(formatter(1111)).toEqual('18.5m');
expect(formatter(7196)).toEqual('119.9m');
expect(formatter(7200)).toEqual('2h');
expect(formatter(11110)).toEqual('3.1h');
expect(formatter(111100)).toEqual('30.9h');
expect(formatter(172619)).toEqual('47.9h');
expect(formatter(172799)).toEqual('48h');
expect(formatter(172800)).toEqual('2d');
expect(formatter(1111000)).toEqual('12.9d');
});
test('millisecond', () => {
const formatter = formatByMetricType(METRIC_TYPE.millisecond);
expect(formatter(0)).toEqual('0');
expect(formatter(1)).toEqual('1ms');
expect(formatter(0.1)).toEqual('100μs');
expect(formatter(0.1111)).toEqual('111.1μs');
expect(formatter(0.01111)).toEqual('11.11μs');
expect(formatter(0.0011111)).toEqual('1.111μs');
expect(formatter(0.00011111)).toEqual('111.11ns');
expect(formatter(0.000011111)).toEqual('11.111ns');
expect(formatter(0.0000011111)).toEqual('1.111ns');
expect(formatter(0.00000011111)).toEqual('0.111ns');
expect(formatter(0.000000011111)).toEqual('0.011ns');
expect(formatter(0.0000000011111)).toEqual('0.001ns');
expect(formatter(0.0000000000011111)).toEqual('0ns');
expect(formatter(0.00000000000011111)).toEqual('0ns');
expect(formatter(11)).toEqual('11ms');
expect(formatter(111)).toEqual('111ms');
expect(formatter(119000)).toEqual('119s');
expect(formatter(120000)).toEqual('2m');
expect(formatter(1111000)).toEqual('18.5m');
expect(formatter(7196000)).toEqual('119.9m');
expect(formatter(7200000)).toEqual('2h');
expect(formatter(11110000)).toEqual('3.1h');
expect(formatter(111100000)).toEqual('30.9h');
expect(formatter(172619000)).toEqual('47.9h');
expect(formatter(172799000)).toEqual('48h');
expect(formatter(172800000)).toEqual('2d');
expect(formatter(1111000000)).toEqual('12.9d');
});
test('microsecond', () => {
const formatter = formatByMetricType(METRIC_TYPE.microsecond);
expect(formatter(0)).toEqual('0');
expect(formatter(1)).toEqual('1μs');
expect(formatter(0.1)).toEqual('100ns');
expect(formatter(0.1111)).toEqual('111.1ns');
expect(formatter(0.01111)).toEqual('11.11ns');
expect(formatter(0.0011111)).toEqual('1.111ns');
expect(formatter(0.00011111)).toEqual('0.111ns');
expect(formatter(0.000011111)).toEqual('0.011ns');
expect(formatter(0.0000011111)).toEqual('0.001ns');
expect(formatter(0.00000011111)).toEqual('0ns');
expect(formatter(0.000000011111)).toEqual('0ns');
expect(formatter(0.0000000011111)).toEqual('0ns');
expect(formatter(0.0000000000011111)).toEqual('0ns');
expect(formatter(0.00000000000011111)).toEqual('0ns');
expect(formatter(11)).toEqual('11μs');
expect(formatter(111)).toEqual('111μs');
expect(formatter(111000)).toEqual('111ms');
expect(formatter(111000000)).toEqual('111s');
expect(formatter(119000000)).toEqual('119s');
expect(formatter(120000000)).toEqual('2m');
expect(formatter(1111000000)).toEqual('18.5m');
expect(formatter(7196000000)).toEqual('119.9m');
expect(formatter(7200000000)).toEqual('2h');
expect(formatter(11110000000)).toEqual('3.1h');
expect(formatter(111100000000)).toEqual('30.9h');
expect(formatter(172619000000)).toEqual('47.9h');
expect(formatter(172799000000)).toEqual('48h');
expect(formatter(172800000000)).toEqual('2d');
expect(formatter(1111000000000)).toEqual('12.9d');
});
test('nanosecond', () => {
const formatter = formatByMetricType(METRIC_TYPE.nanosecond);
expect(formatter(0)).toEqual('0');
expect(formatter(1)).toEqual('1ns');
expect(formatter(0.1)).toEqual('0.1ns');
expect(formatter(0.1111)).toEqual('0.111ns');
expect(formatter(0.01111)).toEqual('0.011ns');
expect(formatter(0.0011111)).toEqual('0.001ns');
expect(formatter(0.00011111)).toEqual('0ns');
expect(formatter(0.000011111)).toEqual('0ns');
expect(formatter(11)).toEqual('11ns');
expect(formatter(111)).toEqual('111ns');
expect(formatter(111100)).toEqual('111.1μs');
expect(formatter(111100000)).toEqual('111.1ms');
expect(formatter(111100000000)).toEqual('111.1s');
expect(formatter(111000000000)).toEqual('111s');
expect(formatter(119000000000)).toEqual('119s');
expect(formatter(120000000000)).toEqual('2m');
expect(formatter(1111000000000)).toEqual('18.5m');
expect(formatter(7196000000000)).toEqual('119.9m');
expect(formatter(7200000000000)).toEqual('2h');
expect(formatter(11110000000000)).toEqual('3.1h');
expect(formatter(111100000000000)).toEqual('30.9h');
expect(formatter(172619000000000)).toEqual('47.9h');
expect(formatter(172799000000000)).toEqual('48h');
expect(formatter(172800000000000)).toEqual('2d');
expect(formatter(1111000000000000)).toEqual('12.9d');
});
});
Loading

0 comments on commit 4963519

Please sign in to comment.