Skip to content

Commit

Permalink
Merge branch '7.17' into deprecations/os-packages
Browse files Browse the repository at this point in the history
  • Loading branch information
kibanamachine authored Dec 16, 2021
2 parents 011c802 + 3474216 commit ea192f5
Show file tree
Hide file tree
Showing 13 changed files with 303 additions and 85 deletions.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 17 additions & 0 deletions src/core/public/core_app/status/components/metric_tiles.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,18 @@ const timeMetric: Metric = {
value: 1234,
};

const metricWithMeta: Metric = {
name: 'Delay',
type: 'time',
value: 1,
meta: {
description: 'Percentiles',
title: '',
value: [1, 5, 10],
type: 'time',
},
};

describe('MetricTile', () => {
it('correct displays an untyped metric', () => {
const component = shallow(<MetricTile metric={untypedMetric} />);
Expand All @@ -55,4 +67,9 @@ describe('MetricTile', () => {
const component = shallow(<MetricTile metric={timeMetric} />);
expect(component).toMatchSnapshot();
});

it('correctly displays a metric with metadata', () => {
const component = shallow(<MetricTile metric={metricWithMeta} />);
expect(component).toMatchSnapshot();
});
});
106 changes: 98 additions & 8 deletions src/core/public/core_app/status/components/metric_tiles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,105 @@
*/

import React, { FunctionComponent } from 'react';
import { EuiFlexGrid, EuiFlexItem, EuiCard } from '@elastic/eui';
import { formatNumber, Metric } from '../lib';
import { EuiFlexGrid, EuiFlexItem, EuiCard, EuiStat } from '@elastic/eui';
import { DataType, formatNumber, Metric } from '../lib';

/*
* Displays a metric with the correct format.
* Displays metadata for a metric.
*/
export const MetricTile: FunctionComponent<{ metric: Metric }> = ({ metric }) => {
const { name } = metric;
const MetricCardFooter: FunctionComponent<{
title: string;
description: string;
}> = ({ title, description }) => {
return (
<EuiStat
data-test-subj="serverMetricMeta"
title={title}
titleSize="xxs"
description={description}
reverse
/>
);
};

const DelayMetricTile: FunctionComponent<{ metric: Metric }> = ({ metric }) => {
const { name, meta } = metric;
return (
<EuiCard
data-test-subj={`serverMetric-${formatMetricId(metric)}`}
layout="horizontal"
data-test-subj={`serverMetric-${formatMetricId(name)}`}
title={formatMetric(metric)}
textAlign="left"
description={`${name} avg`}
footer={
meta?.value && (
<MetricCardFooter
title={formatDelayFooterTitle(meta.value, meta.type)}
description={meta.description}
/>
)
}
/>
);
};

const LoadMetricTile: FunctionComponent<{ metric: Metric }> = ({ metric }) => {
const { name, meta } = metric;
return (
<EuiCard
data-test-subj={`serverMetric-${formatMetricId(name)}`}
title={formatMetric(metric)}
textAlign="left"
description={name}
footer={meta && <MetricCardFooter title={meta.title} description={meta.description} />}
/>
);
};

const ResponseTimeMetric: FunctionComponent<{ metric: Metric }> = ({ metric }) => {
const { name, meta } = metric;
return (
<EuiCard
data-test-subj={`serverMetric-${formatMetricId(name)}`}
title={formatMetric(metric)}
textAlign="left"
description={name}
footer={
meta?.value &&
Array.isArray(meta.value) && (
<MetricCardFooter
title={formatNumber(meta.value[0], meta.type)}
description={meta.description}
/>
)
}
/>
);
};

/*
* Displays a metric with the correct format.
*/
export const MetricTile: FunctionComponent<{ metric: Metric }> = ({ metric }) => {
const { name } = metric;
switch (name) {
case 'Delay':
return <DelayMetricTile metric={metric} />;
case 'Load':
return <LoadMetricTile metric={metric} />;
case 'Response time avg':
return <ResponseTimeMetric metric={metric} />;
default:
return (
<EuiCard
data-test-subj={`serverMetric-${formatMetricId(name)}`}
textAlign="left"
title={formatMetric(metric)}
description={name}
/>
);
}
};

/*
* Wrapper component that simply maps each metric to MetricTile inside a FlexGroup
*/
Expand All @@ -38,11 +119,20 @@ export const MetricTiles: FunctionComponent<{ metrics: Metric[] }> = ({ metrics
</EuiFlexGrid>
);

// formatting helper functions

const formatMetric = ({ value, type }: Metric) => {
const metrics = Array.isArray(value) ? value : [value];
return metrics.map((metric) => formatNumber(metric, type)).join(', ');
};

const formatMetricId = ({ name }: Metric) => {
const formatMetricId = (name: Metric['name']) => {
return name.toLowerCase().replace(/[ ]+/g, '-');
};

const formatDelayFooterTitle = (values: number[], type?: DataType) => {
return `
50: ${formatNumber(values[0], type)};
95: ${formatNumber(values[1], type)};
99: ${formatNumber(values[2], type)}`;
};
18 changes: 14 additions & 4 deletions src/core/public/core_app/status/lib/load_status.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,13 +218,23 @@ describe('response processing', () => {
expect(names).toEqual([
'Heap total',
'Heap used',
'Requests per second',
'Load',
'Delay',
'Response time avg',
'Response time max',
'Requests per second',
]);

const values = data.metrics.map((m) => m.value);
expect(values).toEqual([1000000, 100, [4.1, 2.1, 0.1], 4000, 8000, 400]);
expect(values).toEqual([1000000, 100, 400, [4.1, 2.1, 0.1], 1, 4000]);
});

test('adds meta details to Load, Delay and Response time', async () => {
const data = await loadStatus({ http, notifications });
const metricNames = data.metrics.filter((met) => met.meta);
expect(metricNames.map((item) => item.name)).toEqual(['Load', 'Delay', 'Response time avg']);
expect(metricNames.map((item) => item.meta!.description)).toEqual([
'Load interval',
'Percentiles',
'Response time max',
]);
});
});
62 changes: 49 additions & 13 deletions src/core/public/core_app/status/lib/load_status.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,17 @@ import type { HttpSetup } from '../../../http';
import type { NotificationsSetup } from '../../../notifications';
import type { DataType } from '../lib';

interface MetricMeta {
title: string;
description: string;
value?: number[];
type?: DataType;
}
export interface Metric {
name: string;
value: number | number[];
type?: DataType;
meta?: MetricMeta;
}

export interface FormattedStatus {
Expand Down Expand Up @@ -57,33 +64,62 @@ function formatMetrics({ metrics }: StatusResponse): Metric[] {
value: metrics.process.memory.heap.used_in_bytes,
type: 'byte',
},
{
name: i18n.translate('core.statusPage.metricsTiles.columns.requestsPerSecHeader', {
defaultMessage: 'Requests per second',
}),
value: (metrics.requests.total * 1000) / metrics.collection_interval_in_millis,
type: 'float',
},
{
name: i18n.translate('core.statusPage.metricsTiles.columns.loadHeader', {
defaultMessage: 'Load',
}),
value: [metrics.os.load['1m'], metrics.os.load['5m'], metrics.os.load['15m']],
type: 'float',
meta: {
description: i18n.translate('core.statusPage.metricsTiles.columns.load.metaHeader', {
defaultMessage: 'Load interval',
}),
title: Object.keys(metrics.os.load).join('; '),
},
},
{
name: i18n.translate('core.statusPage.metricsTiles.columns.resTimeAvgHeader', {
defaultMessage: 'Response time avg',
name: i18n.translate('core.statusPage.metricsTiles.columns.processDelayHeader', {
defaultMessage: 'Delay',
}),
value: metrics.response_times.avg_in_millis,
value: metrics.process.event_loop_delay,
type: 'time',
meta: {
description: i18n.translate(
'core.statusPage.metricsTiles.columns.processDelayDetailsHeader',
{
defaultMessage: 'Percentiles',
}
),
title: '',
value: [
metrics.process.event_loop_delay_histogram?.percentiles['50'],
metrics.process.event_loop_delay_histogram?.percentiles['95'],
metrics.process.event_loop_delay_histogram?.percentiles['99'],
],
type: 'time',
},
},
{
name: i18n.translate('core.statusPage.metricsTiles.columns.resTimeMaxHeader', {
defaultMessage: 'Response time max',
name: i18n.translate('core.statusPage.metricsTiles.columns.resTimeAvgHeader', {
defaultMessage: 'Response time avg',
}),
value: metrics.response_times.max_in_millis,
value: metrics.response_times.avg_in_millis,
type: 'time',
},
{
name: i18n.translate('core.statusPage.metricsTiles.columns.requestsPerSecHeader', {
defaultMessage: 'Requests per second',
}),
value: (metrics.requests.total * 1000) / metrics.collection_interval_in_millis,
type: 'float',
meta: {
description: i18n.translate('core.statusPage.metricsTiles.columns.resTimeMaxHeader', {
defaultMessage: 'Response time max',
}),
title: '',
value: [metrics.response_times.max_in_millis],
type: 'time',
},
},
];
}
Expand Down
Loading

0 comments on commit ea192f5

Please sign in to comment.