[Infra] Fix metric table fields and calculations (#134341)

* [Infra] Fix metric table fields and calculations

Fixes 133119
Fixes 133122
Fixes 133124
This commit is contained in:
Milton Hultgren 2022-06-21 08:18:32 +01:00 committed by GitHub
parent 7410fbf4d8
commit d13d997d4c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 104 additions and 81 deletions

View file

@ -111,7 +111,7 @@ function createFetchMock(): NodeMetricsTableFetchMock {
function createContainer(
name: string,
uptimeMs: number,
startTime: number,
cpuUsagePct: number,
memoryUsageBytes: number
): Partial<MetricsExplorerSeries> {
@ -119,8 +119,8 @@ function createContainer(
id: name,
rows: [
{
[metricByField['kubernetes.container.start_time']]: uptimeMs,
[metricByField['kubernetes.container.cpu.usage.node.pct']]: cpuUsagePct,
[metricByField['kubernetes.container.start_time']]: startTime,
[metricByField['kubernetes.container.cpu.usage.limit.pct']]: cpuUsagePct,
[metricByField['kubernetes.container.memory.usage.bytes']]: memoryUsageBytes,
} as MetricsExplorerSeries['rows'][number],
],

View file

@ -12,14 +12,17 @@ import type {
} from '../../../../common/http_api/metrics_explorer';
import type { MetricsQueryOptions, SortState, UseNodeMetricsTableOptions } from '../shared';
import {
metricsToApiOptions,
useInfrastructureNodeMetrics,
averageOfValues,
createMetricByFieldLookup,
makeUnpackMetric,
metricsToApiOptions,
scaleUpPercentage,
useInfrastructureNodeMetrics,
} from '../shared';
type ContainerMetricsField =
| 'kubernetes.container.start_time'
| 'kubernetes.container.cpu.usage.node.pct'
| 'kubernetes.container.cpu.usage.limit.pct'
| 'kubernetes.container.memory.usage.bytes';
const containerMetricsQueryConfig: MetricsQueryOptions<ContainerMetricsField> = {
@ -34,9 +37,9 @@ const containerMetricsQueryConfig: MetricsQueryOptions<ContainerMetricsField> =
aggregation: 'max',
field: 'kubernetes.container.start_time',
},
'kubernetes.container.cpu.usage.node.pct': {
'kubernetes.container.cpu.usage.limit.pct': {
aggregation: 'avg',
field: 'kubernetes.container.cpu.usage.node.pct',
field: 'kubernetes.container.cpu.usage.limit.pct',
},
'kubernetes.container.memory.usage.bytes': {
aggregation: 'avg',
@ -46,6 +49,7 @@ const containerMetricsQueryConfig: MetricsQueryOptions<ContainerMetricsField> =
};
export const metricByField = createMetricByFieldLookup(containerMetricsQueryConfig.metricsMap);
const unpackMetric = makeUnpackMetric(metricByField);
export interface ContainerNodeMetricsRow {
name: string;
@ -114,17 +118,18 @@ function rowWithoutMetrics(name: string) {
}
function calculateMetricAverages(rows: MetricsExplorerRow[]) {
const { uptimeValues, averageCpuUsagePercentValues, averageMemoryUsageMegabytesValues } =
const { startTimeValues, averageCpuUsagePercentValues, averageMemoryUsageMegabytesValues } =
collectMetricValues(rows);
let uptime = null;
if (uptimeValues.length !== 0) {
uptime = averageOfValues(uptimeValues);
if (startTimeValues.length !== 0) {
const startTime = startTimeValues.at(-1);
uptime = Date.now() - startTime!;
}
let averageCpuUsagePercent = null;
if (averageCpuUsagePercentValues.length !== 0) {
averageCpuUsagePercent = averageOfValues(averageCpuUsagePercentValues);
averageCpuUsagePercent = scaleUpPercentage(averageOfValues(averageCpuUsagePercentValues));
}
let averageMemoryUsageMegabytes = null;
@ -142,15 +147,15 @@ function calculateMetricAverages(rows: MetricsExplorerRow[]) {
}
function collectMetricValues(rows: MetricsExplorerRow[]) {
const uptimeValues: number[] = [];
const startTimeValues: number[] = [];
const averageCpuUsagePercentValues: number[] = [];
const averageMemoryUsageMegabytesValues: number[] = [];
rows.forEach((row) => {
const { uptime, averageCpuUsagePercent, averageMemoryUsageMegabytes } = unpackMetrics(row);
const { startTime, averageCpuUsagePercent, averageMemoryUsageMegabytes } = unpackMetrics(row);
if (uptime !== null) {
uptimeValues.push(uptime);
if (startTime !== null) {
startTimeValues.push(startTime);
}
if (averageCpuUsagePercent !== null) {
@ -163,25 +168,18 @@ function collectMetricValues(rows: MetricsExplorerRow[]) {
});
return {
uptimeValues,
startTimeValues,
averageCpuUsagePercentValues,
averageMemoryUsageMegabytesValues,
};
}
function unpackMetrics(row: MetricsExplorerRow): Omit<ContainerNodeMetricsRow, 'name'> {
function unpackMetrics(
row: MetricsExplorerRow
): Omit<ContainerNodeMetricsRow, 'name' | 'uptime'> & { startTime: number | null } {
return {
uptime: row[metricByField['kubernetes.container.start_time']] as number | null,
averageCpuUsagePercent: row[metricByField['kubernetes.container.cpu.usage.node.pct']] as
| number
| null,
averageMemoryUsageMegabytes: row[metricByField['kubernetes.container.memory.usage.bytes']] as
| number
| null,
startTime: unpackMetric(row, 'kubernetes.container.start_time'),
averageCpuUsagePercent: unpackMetric(row, 'kubernetes.container.cpu.usage.limit.pct'),
averageMemoryUsageMegabytes: unpackMetric(row, 'kubernetes.container.memory.usage.bytes'),
};
}
function averageOfValues(values: number[]) {
const sum = values.reduce((acc, value) => acc + value, 0);
return sum / values.length;
}

View file

@ -129,7 +129,7 @@ function hostMetricsColumns(
),
},
{
name: 'Memory total (avg.)',
name: 'Memory total',
field: 'totalMemoryMegabytes',
align: 'right',
render: (totalMemoryMegabytes: number) => (

View file

@ -12,9 +12,12 @@ import type {
} from '../../../../common/http_api/metrics_explorer';
import type { MetricsQueryOptions, SortState, UseNodeMetricsTableOptions } from '../shared';
import {
metricsToApiOptions,
useInfrastructureNodeMetrics,
averageOfValues,
createMetricByFieldLookup,
makeUnpackMetric,
metricsToApiOptions,
scaleUpPercentage,
useInfrastructureNodeMetrics,
} from '../shared';
type HostMetricsField =
@ -45,6 +48,7 @@ const hostsMetricsQueryConfig: MetricsQueryOptions<HostMetricsField> = {
};
export const metricByField = createMetricByFieldLookup(hostsMetricsQueryConfig.metricsMap);
const unpackMetric = makeUnpackMetric(metricByField);
export interface HostNodeMetricsRow {
name: string;
@ -121,24 +125,24 @@ function calculateMetricAverages(rows: MetricsExplorerRow[]) {
let cpuCount = null;
if (cpuCountValues.length !== 0) {
cpuCount = averageOfValues(cpuCountValues);
cpuCount = cpuCountValues.at(-1)!;
}
let averageCpuUsagePercent = null;
if (averageCpuUsagePercentValues.length !== 0) {
averageCpuUsagePercent = averageOfValues(averageCpuUsagePercentValues);
averageCpuUsagePercent = scaleUpPercentage(averageOfValues(averageCpuUsagePercentValues));
}
let totalMemoryMegabytes = null;
if (totalMemoryMegabytesValues.length !== 0) {
const averageInBytes = averageOfValues(totalMemoryMegabytesValues);
const memoryInBytes = totalMemoryMegabytesValues.at(-1);
const bytesPerMegabyte = 1000000;
totalMemoryMegabytes = Math.floor(averageInBytes / bytesPerMegabyte);
totalMemoryMegabytes = Math.floor(memoryInBytes! / bytesPerMegabyte);
}
let averageMemoryUsagePercent = null;
if (averageMemoryUsagePercentValues.length !== 0) {
averageMemoryUsagePercent = averageOfValues(averageMemoryUsagePercentValues);
averageMemoryUsagePercent = scaleUpPercentage(averageOfValues(averageMemoryUsagePercentValues));
}
return {
@ -186,14 +190,9 @@ function collectMetricValues(rows: MetricsExplorerRow[]) {
function unpackMetrics(row: MetricsExplorerRow): Omit<HostNodeMetricsRow, 'name'> {
return {
cpuCount: row[metricByField['system.cpu.cores']] as number | null,
averageCpuUsagePercent: row[metricByField['system.cpu.total.norm.pct']] as number | null,
totalMemoryMegabytes: row[metricByField['system.memory.total']] as number | null,
averageMemoryUsagePercent: row[metricByField['system.memory.used.pct']] as number | null,
cpuCount: unpackMetric(row, 'system.cpu.cores'),
averageCpuUsagePercent: unpackMetric(row, 'system.cpu.total.norm.pct'),
totalMemoryMegabytes: unpackMetric(row, 'system.memory.total'),
averageMemoryUsagePercent: unpackMetric(row, 'system.memory.used.pct'),
};
}
function averageOfValues(values: number[]) {
const sum = values.reduce((acc, value) => acc + value, 0);
return sum / values.length;
}

View file

@ -112,7 +112,7 @@ function createFetchMock(): NodeMetricsTableFetchMock {
function createPod(
id: string,
name: string,
uptimeMs: number,
startTime: number,
cpuUsagePct: number,
memoryUsageBytes: number
): Partial<MetricsExplorerSeries> {
@ -121,8 +121,8 @@ function createPod(
keys: [id, name],
rows: [
{
[metricByField['kubernetes.pod.start_time']]: uptimeMs,
[metricByField['kubernetes.pod.cpu.usage.node.pct']]: cpuUsagePct,
[metricByField['kubernetes.pod.start_time']]: startTime,
[metricByField['kubernetes.pod.cpu.usage.limit.pct']]: cpuUsagePct,
[metricByField['kubernetes.pod.memory.usage.bytes']]: memoryUsageBytes,
} as MetricsExplorerSeries['rows'][number],
],

View file

@ -12,14 +12,17 @@ import type {
} from '../../../../common/http_api/metrics_explorer';
import type { MetricsQueryOptions, SortState, UseNodeMetricsTableOptions } from '../shared';
import {
metricsToApiOptions,
useInfrastructureNodeMetrics,
averageOfValues,
createMetricByFieldLookup,
makeUnpackMetric,
metricsToApiOptions,
scaleUpPercentage,
useInfrastructureNodeMetrics,
} from '../shared';
type PodMetricsField =
| 'kubernetes.pod.start_time'
| 'kubernetes.pod.cpu.usage.node.pct'
| 'kubernetes.pod.cpu.usage.limit.pct'
| 'kubernetes.pod.memory.usage.bytes';
const podMetricsQueryConfig: MetricsQueryOptions<PodMetricsField> = {
@ -34,9 +37,9 @@ const podMetricsQueryConfig: MetricsQueryOptions<PodMetricsField> = {
aggregation: 'max',
field: 'kubernetes.pod.start_time',
},
'kubernetes.pod.cpu.usage.node.pct': {
'kubernetes.pod.cpu.usage.limit.pct': {
aggregation: 'avg',
field: 'kubernetes.pod.cpu.usage.node.pct',
field: 'kubernetes.pod.cpu.usage.limit.pct',
},
'kubernetes.pod.memory.usage.bytes': {
aggregation: 'avg',
@ -46,6 +49,7 @@ const podMetricsQueryConfig: MetricsQueryOptions<PodMetricsField> = {
};
export const metricByField = createMetricByFieldLookup(podMetricsQueryConfig.metricsMap);
const unpackMetric = makeUnpackMetric(metricByField);
export interface PodNodeMetricsRow {
id: string;
@ -115,17 +119,18 @@ function rowWithoutMetrics(id: string, name: string) {
}
function calculateMetricAverages(rows: MetricsExplorerRow[]) {
const { uptimeValues, averageCpuUsagePercentValues, averageMemoryUsageMegabytesValues } =
const { startTimeValues, averageCpuUsagePercentValues, averageMemoryUsageMegabytesValues } =
collectMetricValues(rows);
let uptime = null;
if (uptimeValues.length !== 0) {
uptime = averageOfValues(uptimeValues);
if (startTimeValues.length !== 0) {
const startTime = startTimeValues.at(-1);
uptime = Date.now() - startTime!;
}
let averageCpuUsagePercent = null;
if (averageCpuUsagePercentValues.length !== 0) {
averageCpuUsagePercent = averageOfValues(averageCpuUsagePercentValues);
averageCpuUsagePercent = scaleUpPercentage(averageOfValues(averageCpuUsagePercentValues));
}
let averageMemoryUsageMegabytes = null;
@ -143,15 +148,15 @@ function calculateMetricAverages(rows: MetricsExplorerRow[]) {
}
function collectMetricValues(rows: MetricsExplorerRow[]) {
const uptimeValues: number[] = [];
const startTimeValues: number[] = [];
const averageCpuUsagePercentValues: number[] = [];
const averageMemoryUsageMegabytesValues: number[] = [];
rows.forEach((row) => {
const { uptime, averageCpuUsagePercent, averageMemoryUsageMegabytes } = unpackMetrics(row);
const { startTime, averageCpuUsagePercent, averageMemoryUsageMegabytes } = unpackMetrics(row);
if (uptime !== null) {
uptimeValues.push(uptime);
if (startTime !== null) {
startTimeValues.push(startTime);
}
if (averageCpuUsagePercent !== null) {
@ -164,25 +169,18 @@ function collectMetricValues(rows: MetricsExplorerRow[]) {
});
return {
uptimeValues,
startTimeValues,
averageCpuUsagePercentValues,
averageMemoryUsageMegabytesValues,
};
}
function unpackMetrics(row: MetricsExplorerRow): Omit<PodNodeMetricsRow, 'id' | 'name'> {
function unpackMetrics(
row: MetricsExplorerRow
): Omit<PodNodeMetricsRow, 'id' | 'name' | 'uptime'> & { startTime: number | null } {
return {
uptime: row[metricByField['kubernetes.pod.start_time']] as number | null,
averageCpuUsagePercent: row[metricByField['kubernetes.pod.cpu.usage.node.pct']] as
| number
| null,
averageMemoryUsageMegabytes: row[metricByField['kubernetes.pod.memory.usage.bytes']] as
| number
| null,
startTime: unpackMetric(row, 'kubernetes.pod.start_time'),
averageCpuUsagePercent: unpackMetric(row, 'kubernetes.pod.cpu.usage.limit.pct'),
averageMemoryUsageMegabytes: unpackMetric(row, 'kubernetes.pod.memory.usage.bytes'),
};
}
function averageOfValues(values: number[]) {
const sum = values.reduce((acc, value) => acc + value, 0);
return sum / values.length;
}

View file

@ -0,0 +1,24 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import type { MetricsExplorerRow } from '../../../../../common/http_api/metrics_explorer';
export function averageOfValues(values: number[]) {
const sum = values.reduce((acc, value) => acc + value, 0);
return sum / values.length;
}
export function makeUnpackMetric<T extends string>(metricByField: Record<T, string>) {
// Make sure metrics are accessed as row[metricByField['FIELD_NAME']]
// Not row['FIELD_NAME'] by accident
return (row: MetricsExplorerRow, field: T) => row[metricByField[field]] as number | null;
}
export function scaleUpPercentage(unscaled: number) {
// Scale e.g. 0.027 to 2.7
return unscaled * 100;
}

View file

@ -5,7 +5,8 @@
* 2.0.
*/
export { metricsToApiOptions, createMetricByFieldLookup } from './metrics_to_api_options';
export { averageOfValues, makeUnpackMetric, scaleUpPercentage } from './helpers';
export { createMetricByFieldLookup, metricsToApiOptions } from './metrics_to_api_options';
export type { MetricsMap, MetricsQueryOptions } from './metrics_to_api_options';
export { useInfrastructureNodeMetrics } from './use_infrastructure_node_metrics';
export type { SortState } from './use_infrastructure_node_metrics';

View file

@ -7,11 +7,14 @@
export { MetricsNodeDetailsLink, NumberCell, StepwisePagination, UptimeCell } from './components';
export {
metricsToApiOptions,
useInfrastructureNodeMetrics,
averageOfValues,
createMetricByFieldLookup,
makeUnpackMetric,
metricsToApiOptions,
scaleUpPercentage,
useInfrastructureNodeMetrics,
} from './hooks';
export type { MetricsMap, SortState, MetricsQueryOptions } from './hooks';
export type { MetricsMap, MetricsQueryOptions, SortState } from './hooks';
export type {
IntegratedNodeMetricsTableProps,
SourceProviderProps,