[ObsUX] Move formulas and dashboard config to inventory models (#171872)

## Summary

This PR moves formulas and charts developed for the Hosts View and Asset
Details into the Inventory Models existing structure.

### `metrics_data_access` plugin

This is where the inventory models are found. All charts and formulas
have been moved from `infra` plugin into this plugin Most of the changes
are just about that. I've refactored a few things to help with the
reusability of these charts/dashboards

### `infra` plugin

Changes made here were a consequence of the refactors in the
charts/dashboards config.

### `@kbn/lens-embaddable-utils` package

Just added new types

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Carlos Crespo 2023-11-30 10:17:58 +01:00 committed by GitHub
parent df6e8ddaed
commit 092330c2a3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
125 changed files with 1772 additions and 1583 deletions

View file

@ -18,6 +18,7 @@ import type {
XYLayerConfig,
FillStyle,
} from '@kbn/lens-plugin/public';
export type LensAttributes = TypedLensByValueInput['attributes'];
// Attributes
@ -61,7 +62,6 @@ export interface ChartLayer<TLayerConfig extends LensLayerConfig> {
getDataView(): DataView | undefined;
}
// Chart
export interface Chart<TVisualizationState extends LensVisualizationState> {
getTitle(): string;
getVisualizationType(): string;
@ -70,6 +70,8 @@ export interface Chart<TVisualizationState extends LensVisualizationState> {
getReferences(): SavedObjectReference[];
getDataViews(): DataView[];
}
// Chart
export interface ChartConfig<
TLayer extends ChartLayer<LensLayerConfig> | Array<ChartLayer<LensLayerConfig>>
> {
@ -91,3 +93,5 @@ export type StaticValueConfig = Omit<LensFormula, 'formula'> & {
fill?: FillStyle;
value: string;
};
export type VisualizationTypes = 'lnsXY' | 'lnsMetric';

View file

@ -0,0 +1,14 @@
/*
* 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 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
export const XY_ID = 'lnsXY';
export const METRIC_ID = 'lnsMetric';
export const METRIC_TREND_LINE_ID = 'metricTrendline';
export const XY_REFERENCE_LINE_ID = 'referenceLine';
export const XY_DATA_ID = 'data';

View file

@ -5,8 +5,37 @@
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import type { DataView } from '@kbn/data-views-plugin/common';
import {
METRIC_ID,
XY_ID,
METRIC_TREND_LINE_ID,
XY_DATA_ID,
XY_REFERENCE_LINE_ID,
} from './constants';
import type { XYVisualOptions } from './xy_chart';
import type { MetricLayerConfig, XYDataLayerConfig, XYReferenceLinesLayerConfig } from './layers';
export { XYChart, type XYVisualOptions } from './xy_chart';
export { MetricChart } from './metric_chart';
export * from './layers';
export type XYLayerConfig = XYDataLayerConfig | XYReferenceLinesLayerConfig;
interface ChartModelBase {
id: string;
title?: string;
dataView?: DataView;
}
export interface XYChartModel extends ChartModelBase {
visualOptions?: XYVisualOptions;
visualizationType: typeof XY_ID;
layers: XYLayerConfig[];
}
export interface MetricChartModel extends ChartModelBase {
visualizationType: typeof METRIC_ID;
layers: MetricLayerConfig;
}
export type ChartModel = XYChartModel | MetricChartModel;
export type ChartTypes = typeof XY_ID | typeof METRIC_ID;
export { METRIC_ID, XY_ID, METRIC_TREND_LINE_ID, XY_DATA_ID, XY_REFERENCE_LINE_ID };

View file

@ -7,7 +7,7 @@
*/
export { MetricLayer, type MetricLayerOptions, type MetricLayerConfig } from './metric_layer';
export { XYDataLayer, type XYLayerOptions, type XYLayerConfig } from './xy_data_layer';
export { XYDataLayer, type XYLayerOptions, type XYDataLayerConfig } from './xy_data_layer';
export {
XYReferenceLinesLayer,
type XYReferenceLinesLayerConfig,

View file

@ -16,6 +16,7 @@ import type {
} from '@kbn/lens-plugin/public';
import type { ChartColumn, ChartLayer, FormulaValueConfig } from '../../types';
import { getDefaultReferences, getHistogramColumn } from '../../utils';
import { METRIC_TREND_LINE_ID } from '../constants';
import { FormulaColumn } from './columns/formula';
const HISTOGRAM_COLUMN_NAME = 'x_date_histogram';
@ -30,6 +31,7 @@ export interface MetricLayerOptions {
export interface MetricLayerConfig {
data: FormulaValueConfig;
options?: MetricLayerOptions;
layerType?: typeof METRIC_TREND_LINE_ID;
/**
* It is possible to define a specific dataView for the layer. It will override the global chart one
**/
@ -38,8 +40,13 @@ export interface MetricLayerConfig {
export class MetricLayer implements ChartLayer<MetricVisualizationState> {
private column: ChartColumn;
constructor(private layerConfig: MetricLayerConfig) {
private layerConfig: MetricLayerConfig;
constructor(layerConfig: MetricLayerConfig) {
this.column = new FormulaColumn(layerConfig.data);
this.layerConfig = {
...layerConfig,
layerType: layerConfig.layerType ?? 'metricTrendline',
};
}
getLayer(

View file

@ -12,7 +12,7 @@ import type {
FormulaPublicApi,
FormBasedPersistedState,
PersistedIndexPatternLayer,
XYDataLayerConfig,
XYDataLayerConfig as LensXYDataLayerConfig,
SeriesType,
TermsIndexPatternColumn,
DateHistogramIndexPatternColumn,
@ -26,6 +26,7 @@ import {
type TopValuesColumnParams,
type DateHistogramColumnParams,
} from '../../utils';
import { XY_DATA_ID } from '../constants';
import { FormulaColumn } from './columns/formula';
const BREAKDOWN_COLUMN_NAME = 'aggs_breakdown';
@ -50,22 +51,25 @@ export interface XYLayerOptions {
seriesType?: SeriesType;
}
export interface XYLayerConfig {
export interface XYDataLayerConfig {
data: FormulaValueConfig[];
options?: XYLayerOptions;
layerType?: typeof XY_DATA_ID;
/**
* It is possible to define a specific dataView for the layer. It will override the global chart one
**/
dataView?: DataView;
}
export class XYDataLayer implements ChartLayer<XYDataLayerConfig> {
export class XYDataLayer implements ChartLayer<LensXYDataLayerConfig> {
private column: ChartColumn[];
private layerConfig: XYLayerConfig;
constructor(layerConfig: XYLayerConfig) {
private layerConfig: XYDataLayerConfig;
constructor(layerConfig: XYDataLayerConfig) {
this.column = layerConfig.data.map((dataItem) => new FormulaColumn(dataItem));
this.layerConfig = {
...layerConfig,
layerType: layerConfig.layerType ?? 'data',
options: {
...layerConfig.options,
buckets: {
@ -151,7 +155,7 @@ export class XYDataLayer implements ChartLayer<XYDataLayerConfig> {
return getDefaultReferences(this.layerConfig.dataView ?? chartDataView, layerId);
}
getLayerConfig(layerId: string, accessorId: string): XYDataLayerConfig {
getLayerConfig(layerId: string, accessorId: string): LensXYDataLayerConfig {
return {
layerId,
seriesType: this.layerConfig.options?.seriesType ?? 'line',

View file

@ -15,10 +15,12 @@ import type {
} from '@kbn/lens-plugin/public';
import type { ChartLayer, StaticValueConfig, StaticChartColumn } from '../../types';
import { getDefaultReferences } from '../../utils';
import { XY_REFERENCE_LINE_ID } from '../constants';
import { StaticColumn } from './columns/static';
export interface XYReferenceLinesLayerConfig {
data: StaticValueConfig[];
layerType?: typeof XY_REFERENCE_LINE_ID;
/**
* It is possible to define a specific dataView for the layer. It will override the global chart one
**/
@ -27,8 +29,13 @@ export interface XYReferenceLinesLayerConfig {
export class XYReferenceLinesLayer implements ChartLayer<XYReferenceLineLayerConfig> {
private column: StaticChartColumn[];
constructor(private layerConfig: XYReferenceLinesLayerConfig) {
private layerConfig: XYReferenceLinesLayerConfig;
constructor(layerConfig: XYReferenceLinesLayerConfig) {
this.column = layerConfig.data.map((p) => new StaticColumn(p));
this.layerConfig = {
...layerConfig,
layerType: layerConfig.layerType ?? 'referenceLine',
};
}
getName(): string | undefined {

View file

@ -11,6 +11,7 @@ import type { SavedObjectReference } from '@kbn/core/server';
import type { DataView } from '@kbn/data-views-plugin/public';
import type { Chart, ChartConfig, ChartLayer } from '../types';
import { DEFAULT_LAYER_ID } from '../utils';
import { METRIC_ID } from './constants';
const ACCESSOR = 'metric_formula_accessor';
@ -18,7 +19,7 @@ export class MetricChart implements Chart<MetricVisualizationState> {
constructor(private chartConfig: ChartConfig<ChartLayer<MetricVisualizationState>>) {}
getVisualizationType(): string {
return 'lnsMetric';
return METRIC_ID;
}
getLayers(): FormBasedPersistedState['layers'] {

View file

@ -7,7 +7,9 @@
*/
import type {
AxisExtentConfig,
FormBasedPersistedState,
LegendConfig,
XYArgs,
XYLayerConfig,
XYState,
@ -17,6 +19,7 @@ import type { SavedObjectReference } from '@kbn/core/server';
import { AxesSettingsConfig } from '@kbn/visualizations-plugin/common';
import type { Chart, ChartConfig, ChartLayer } from '../types';
import { DEFAULT_LAYER_ID } from '../utils';
import { XY_ID } from './constants';
const ACCESSOR = 'formula_accessor';
@ -28,6 +31,8 @@ export interface XYVisualOptions {
showDottedLine?: boolean;
valueLabels?: XYArgs['valueLabels'];
axisTitlesVisibilitySettings?: AxesSettingsConfig;
legend?: LegendConfig;
yLeftExtent?: AxisExtentConfig;
}
export class XYChart implements Chart<XYState> {
@ -39,7 +44,7 @@ export class XYChart implements Chart<XYState> {
) {}
getVisualizationType(): string {
return 'lnsXY';
return XY_ID;
}
private get layers() {
@ -79,12 +84,23 @@ export class XYChart implements Chart<XYState> {
}),
],
}),
legend: this.chartConfig.visualOptions?.legend ?? {
isVisible: false,
position: 'right',
showSingleSeries: false,
},
fittingFunction: this.chartConfig.visualOptions?.missingValues ?? 'None',
endValue: this.chartConfig.visualOptions?.endValues,
curveType: this.chartConfig.visualOptions?.lineInterpolation,
emphasizeFitting: !this.chartConfig.visualOptions?.showDottedLine,
valueLabels: this.chartConfig.visualOptions?.valueLabels,
axisTitlesVisibilitySettings: this.chartConfig.visualOptions?.axisTitlesVisibilitySettings,
axisTitlesVisibilitySettings: this.chartConfig.visualOptions
?.axisTitlesVisibilitySettings ?? {
x: false,
yLeft: false,
yRight: true,
},
yLeftExtent: this.chartConfig.visualOptions?.yLeftExtent,
};
}
@ -117,11 +133,6 @@ export const getXYVisualizationState = (
},
valueLabels: 'show',
yLeftScale: 'linear',
axisTitlesVisibilitySettings: {
x: false,
yLeft: false,
yRight: true,
},
tickLabelsVisibilitySettings: {
x: true,
yLeft: true,

View file

@ -12,9 +12,14 @@ export type {
MetricLayerOptions,
MetricLayerConfig,
XYLayerOptions,
XYLayerConfig,
XYDataLayerConfig,
XYReferenceLinesLayerConfig,
XYVisualOptions,
XYLayerConfig,
ChartTypes,
ChartModel,
XYChartModel,
MetricChartModel,
} from './attribute_builder/visualization_types';
export {
@ -25,6 +30,11 @@ export {
XYChart,
XYDataLayer,
XYReferenceLinesLayer,
METRIC_ID,
METRIC_TREND_LINE_ID,
XY_ID,
XY_DATA_ID,
XY_REFERENCE_LINE_ID,
} from './attribute_builder/visualization_types';
export { LensAttributesBuilder } from './attribute_builder/lens_attributes_builder';

View file

@ -1,5 +1,5 @@
{
"type": "shared-browser",
"type": "shared-common",
"id": "@kbn/lens-embeddable-utils",
"owner": "@elastic/obs-ux-infra_services-team"
}

View file

@ -95,7 +95,7 @@ pageLoadAssetSize:
management: 46112
maps: 90000
mapsEms: 26072
metricsDataAccess: 60000
metricsDataAccess: 73287
ml: 82187
monitoring: 80000
navigation: 37269

View file

@ -7,3 +7,6 @@
export const HOST_METRICS_DOC_HREF = 'https://ela.st/docs-infra-host-metrics';
export const HOST_METRICS_DOTTED_LINES_DOC_HREF = 'https://ela.st/docs-infra-why-dotted';
export const KPI_CHART_HEIGHT = 150;
export const METRIC_CHART_HEIGHT = 300;

View file

@ -5,5 +5,9 @@
* 2.0.
*/
export * from './lens/dashboards';
export * from './lens/formulas';
export { METRICS_TOOLTIP } from './translations';
export {
HOST_METRICS_DOC_HREF,
HOST_METRICS_DOTTED_LINES_DOC_HREF,
KPI_CHART_HEIGHT,
} from './constants';

View file

@ -1,117 +0,0 @@
/*
* 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 { i18n } from '@kbn/i18n';
import { hostLensFormulas } from '../../../formulas';
import { METRICS_TOOLTIP } from '../../translations';
import type { KPIChartProps } from '../../types';
export const hostKPICharts = (backgroundColor: string): KPIChartProps[] => [
{
id: 'cpuUsage',
title: i18n.translate('xpack.infra.assetDetailsEmbeddable.overview.kpi.cpuUsage.title', {
defaultMessage: 'CPU Usage',
}),
layers: {
data: {
...hostLensFormulas.cpuUsage,
format: hostLensFormulas.cpuUsage.format
? {
...hostLensFormulas.cpuUsage.format,
params: {
decimals: 1,
},
}
: undefined,
},
options: {
backgroundColor,
showTrendLine: true,
},
type: 'visualization',
},
toolTip: METRICS_TOOLTIP.cpuUsage,
},
{
id: 'normalizedLoad1m',
title: i18n.translate(
'xpack.infra.assetDetailsEmbeddable.overview.kpi.normalizedLoad1m.title',
{
defaultMessage: 'Normalized Load',
}
),
layers: {
data: {
...hostLensFormulas.normalizedLoad1m,
format: hostLensFormulas.normalizedLoad1m.format
? {
...hostLensFormulas.normalizedLoad1m.format,
params: {
decimals: 1,
},
}
: undefined,
},
options: {
backgroundColor,
showTrendLine: true,
},
type: 'visualization',
},
toolTip: METRICS_TOOLTIP.normalizedLoad1m,
},
{
id: 'memoryUsage',
title: i18n.translate('xpack.infra.assetDetailsEmbeddable.overview.kpi.memoryUsage.title', {
defaultMessage: 'Memory Usage',
}),
layers: {
data: {
...hostLensFormulas.memoryUsage,
format: hostLensFormulas.memoryUsage.format
? {
...hostLensFormulas.memoryUsage.format,
params: {
decimals: 1,
},
}
: undefined,
},
options: {
backgroundColor,
showTrendLine: true,
},
type: 'visualization',
},
toolTip: METRICS_TOOLTIP.memoryUsage,
},
{
id: 'diskSpaceUsage',
title: i18n.translate('xpack.infra.assetDetailsEmbeddable.overview.kpi.diskUsage.title', {
defaultMessage: 'Disk Usage',
}),
layers: {
data: {
...hostLensFormulas.diskUsage,
format: hostLensFormulas.diskUsage.format
? {
...hostLensFormulas.diskUsage.format,
params: {
decimals: 1,
},
}
: undefined,
},
options: {
backgroundColor,
showTrendLine: true,
},
type: 'visualization',
},
toolTip: METRICS_TOOLTIP.diskSpaceUsage,
},
];

View file

@ -1,44 +0,0 @@
/*
* 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 { cpuUsage, normalizedLoad1m, cpuUsageBreakdown, loadBreakdown } from '../metric_charts/cpu';
import {
diskSpaceUsageAvailable,
diskThroughputReadWrite,
diskIOReadWrite,
diskUsageByMountPoint,
} from '../metric_charts/disk';
import { logRate } from '../metric_charts/log';
import { memoryUsage, memoryUsageBreakdown } from '../metric_charts/memory';
import { rxTx } from '../metric_charts/network';
import type { XYConfig } from '../../types';
export const hostMetricFlyoutCharts: XYConfig[] = [
cpuUsage,
memoryUsage,
normalizedLoad1m,
logRate,
diskSpaceUsageAvailable,
diskUsageByMountPoint,
diskThroughputReadWrite,
diskIOReadWrite,
rxTx,
];
export const hostMetricChartsFullPage: XYConfig[] = [
cpuUsage,
cpuUsageBreakdown,
memoryUsage,
memoryUsageBreakdown,
normalizedLoad1m,
loadBreakdown,
logRate,
diskSpaceUsageAvailable,
diskUsageByMountPoint,
diskThroughputReadWrite,
diskIOReadWrite,
rxTx,
];

View file

@ -1,94 +0,0 @@
/*
* 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 { i18n } from '@kbn/i18n';
import { kubernetesLensFormulas } from '../../../formulas';
import { XY_OVERRIDES } from '../../constants';
import type { XYConfig } from '../../types';
export const kubernetesCharts: XYConfig[] = [
{
id: 'nodeCpuCapacity',
title: i18n.translate('xpack.infra.assetDetails.metricsCharts.kubernetes.nodeCpuCapacity', {
defaultMessage: 'Node CPU Capacity',
}),
layers: [
{
data: [kubernetesLensFormulas.nodeCpuCapacity, kubernetesLensFormulas.nodeCpuUsed],
type: 'visualization',
options: {
seriesType: 'area',
},
},
],
dataViewOrigin: 'metrics',
overrides: {
settings: XY_OVERRIDES.settings,
},
},
{
id: 'nodeMemoryCapacity',
title: i18n.translate('xpack.infra.assetDetails.metricsCharts.nginx.nodeMemoryCapacity', {
defaultMessage: 'Node Memory Capacity',
}),
layers: [
{
data: [kubernetesLensFormulas.nodeMemoryCapacity, kubernetesLensFormulas.nodeMemoryUsed],
type: 'visualization',
options: {
seriesType: 'area',
},
},
],
dataViewOrigin: 'metrics',
overrides: {
settings: XY_OVERRIDES.settings,
},
},
{
id: 'nodeDiskCapacity',
title: i18n.translate('xpack.infra.assetDetails.metricsCharts.nginx.nodeDiskCapacity', {
defaultMessage: 'Node Disk Capacity',
}),
layers: [
{
data: [kubernetesLensFormulas.nodeDiskCapacity, kubernetesLensFormulas.nodeDiskUsed],
type: 'visualization',
options: {
seriesType: 'area',
},
},
],
dataViewOrigin: 'metrics',
overrides: {
settings: XY_OVERRIDES.settings,
},
},
{
id: 'nodePodCapacity',
title: i18n.translate('xpack.infra.assetDetails.metricsCharts.nginx.nodePodCapacity', {
defaultMessage: 'Node Pod Capacity',
}),
layers: [
{
data: [kubernetesLensFormulas.nodePodCapacity, kubernetesLensFormulas.nodePodUsed],
type: 'visualization',
options: {
seriesType: 'area',
},
},
],
dataViewOrigin: 'metrics',
overrides: {
settings: XY_OVERRIDES.settings,
},
},
];

View file

@ -1,19 +0,0 @@
/*
* 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 { hostMetricFlyoutCharts, hostMetricChartsFullPage } from './host/host_metric_charts';
import { hostKPICharts } from './host/host_kpi_charts';
import { kubernetesCharts } from './host/kubernetes_charts';
export const assetDetailsDashboards = {
host: { hostMetricFlyoutCharts, hostMetricChartsFullPage, hostKPICharts, keyField: 'host.name' },
kubernetes: {
kubernetesCharts,
keyField: 'kubernetes.node.name',
dependsOn: ['kubernetes.node'],
},
};

View file

@ -1,96 +0,0 @@
/*
* 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 { i18n } from '@kbn/i18n';
import { hostLensFormulas } from '../../../formulas';
import { REFERENCE_LINE, XY_OVERRIDES } from '../../constants';
import type { XYConfig } from '../../types';
export const cpuUsage: XYConfig = {
id: 'cpuUsage',
title: i18n.translate('xpack.infra.assetDetails.metricsCharts.cpuUsage', {
defaultMessage: 'CPU Usage',
}),
layers: [
{
data: [hostLensFormulas.cpuUsage],
type: 'visualization',
},
],
dataViewOrigin: 'metrics',
overrides: {
axisLeft: XY_OVERRIDES.axisLeft,
},
};
export const cpuUsageBreakdown: XYConfig = {
id: 'cpuUsageBreakdown',
title: i18n.translate('xpack.infra.assetDetails.metricsCharts.cpuUsage', {
defaultMessage: 'CPU Usage',
}),
layers: [
{
data: [
hostLensFormulas.cpuUsageIowait,
hostLensFormulas.cpuUsageIrq,
hostLensFormulas.cpuUsageNice,
hostLensFormulas.cpuUsageSoftirq,
hostLensFormulas.cpuUsageSteal,
hostLensFormulas.cpuUsageUser,
hostLensFormulas.cpuUsageSystem,
],
options: {
seriesType: 'area_stacked',
},
type: 'visualization',
},
],
overrides: {
axisLeft: XY_OVERRIDES.axisLeft,
settings: XY_OVERRIDES.settings,
},
dataViewOrigin: 'metrics',
};
export const normalizedLoad1m: XYConfig = {
id: 'normalizedLoad1m',
title: i18n.translate('xpack.infra.assetDetails.metricsCharts.normalizedLoad1m', {
defaultMessage: 'Normalized Load',
}),
layers: [
{
data: [hostLensFormulas.normalizedLoad1m],
type: 'visualization',
},
{
data: [REFERENCE_LINE],
type: 'referenceLines',
},
],
dataViewOrigin: 'metrics',
};
export const loadBreakdown: XYConfig = {
id: 'loadBreakdown',
title: i18n.translate('xpack.infra.assetDetails.metricsCharts.load', {
defaultMessage: 'Load',
}),
layers: [
{
data: [hostLensFormulas.load1m, hostLensFormulas.load5m, hostLensFormulas.load15m],
options: {
seriesType: 'area',
},
type: 'visualization',
},
],
overrides: {
settings: XY_OVERRIDES.settings,
},
dataViewOrigin: 'metrics',
};

View file

@ -1,150 +0,0 @@
/*
* 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 { i18n } from '@kbn/i18n';
import { hostLensFormulas } from '../../../formulas';
import { XY_OVERRIDES } from '../../constants';
import type { XYConfig } from '../../types';
const TOP_VALUES_SIZE = 5;
export const diskSpaceUsageAvailable: XYConfig = {
id: 'diskSpaceUsageAvailable',
title: i18n.translate('xpack.infra.assetDetails.metricsCharts.diskUsage', {
defaultMessage: 'Disk Usage',
}),
layers: [
{
data: [
{
...hostLensFormulas.diskUsage,
label: i18n.translate('xpack.infra.assetDetails.metricsCharts.diskUsage.label.used', {
defaultMessage: 'Used',
}),
},
{
...hostLensFormulas.diskSpaceAvailability,
label: i18n.translate(
'xpack.infra.assetDetails.metricsCharts.diskUsage.label.available',
{
defaultMessage: 'Available',
}
),
},
],
options: {
seriesType: 'area',
},
type: 'visualization',
},
],
overrides: {
axisLeft: XY_OVERRIDES.axisLeft,
settings: XY_OVERRIDES.settings,
},
dataViewOrigin: 'metrics',
};
export const diskUsageByMountPoint: XYConfig = {
id: 'DiskUsageByMountPoint',
title: i18n.translate('xpack.infra.assetDetails.metricsCharts.diskUsageByMountingPoint', {
defaultMessage: 'Disk Usage by Mount Point',
}),
layers: [
{
data: [
{
...hostLensFormulas.diskUsage,
label: i18n.translate('xpack.infra.assetDetails.metricsCharts.diskUsage.label.used', {
defaultMessage: 'Used',
}),
},
],
options: {
seriesType: 'area',
breakdown: {
type: 'top_values',
field: 'system.filesystem.mount_point',
params: {
size: TOP_VALUES_SIZE,
},
},
},
type: 'visualization',
},
],
overrides: {
axisLeft: XY_OVERRIDES.axisLeft,
},
dataViewOrigin: 'metrics',
};
export const diskThroughputReadWrite: XYConfig = {
id: 'diskThroughputReadWrite',
title: i18n.translate('xpack.infra.assetDetails.metricsCharts.diskIOPS', {
defaultMessage: 'Disk IOPS',
}),
layers: [
{
data: [
{
...hostLensFormulas.diskIORead,
label: i18n.translate('xpack.infra.assetDetails.metricsCharts.metric.label.read', {
defaultMessage: 'Read',
}),
},
{
...hostLensFormulas.diskIOWrite,
label: i18n.translate('xpack.infra.assetDetails.metricsCharts.metric.label.write', {
defaultMessage: 'Write',
}),
},
],
options: {
seriesType: 'area',
},
type: 'visualization',
},
],
overrides: {
settings: XY_OVERRIDES.settings,
},
dataViewOrigin: 'metrics',
};
export const diskIOReadWrite: XYConfig = {
id: 'diskIOReadWrite',
title: i18n.translate('xpack.infra.assetDetails.metricsCharts.diskThroughput', {
defaultMessage: 'Disk Throughput',
}),
layers: [
{
data: [
{
...hostLensFormulas.diskReadThroughput,
label: i18n.translate('xpack.infra.assetDetails.metricsCharts.metric.label.read', {
defaultMessage: 'Read',
}),
},
{
...hostLensFormulas.diskWriteThroughput,
label: i18n.translate('xpack.infra.assetDetails.metricsCharts.metric.label.write', {
defaultMessage: 'Write',
}),
},
],
options: {
seriesType: 'area',
},
type: 'visualization',
},
],
overrides: {
settings: XY_OVERRIDES.settings,
},
dataViewOrigin: 'metrics',
};

View file

@ -1,24 +0,0 @@
/*
* 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 { i18n } from '@kbn/i18n';
import { hostLensFormulas } from '../../../formulas';
import type { XYConfig } from '../../types';
export const logRate: XYConfig = {
id: 'logRate',
title: i18n.translate('xpack.infra.assetDetails.metricsCharts.logRate', {
defaultMessage: 'Log Rate',
}),
layers: [
{
data: [hostLensFormulas.logRate],
type: 'visualization',
},
],
dataViewOrigin: 'logs',
};

View file

@ -1,67 +0,0 @@
/*
* 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 { i18n } from '@kbn/i18n';
import { hostLensFormulas } from '../../../formulas';
import { XY_OVERRIDES } from '../../constants';
import type { XYConfig } from '../../types';
export const memoryUsage: XYConfig = {
id: 'memoryUsage',
title: i18n.translate('xpack.infra.assetDetails.metricsCharts.memoryUsage', {
defaultMessage: 'Memory Usage',
}),
layers: [
{
data: [hostLensFormulas.memoryUsage],
type: 'visualization',
},
],
dataViewOrigin: 'metrics',
overrides: {
axisLeft: XY_OVERRIDES.axisLeft,
},
};
export const memoryUsageBreakdown: XYConfig = {
id: 'memoryUsage',
title: i18n.translate('xpack.infra.assetDetails.metricsCharts.memoryUsage', {
defaultMessage: 'Memory Usage',
}),
layers: [
{
data: [
{
...hostLensFormulas.memoryCache,
label: i18n.translate('xpack.infra.assetDetails.metricsCharts.metric.label.cache', {
defaultMessage: 'Cache',
}),
},
{
...hostLensFormulas.memoryUsed,
label: i18n.translate('xpack.infra.assetDetails.metricsCharts.metric.label.used', {
defaultMessage: 'Used',
}),
},
{
...hostLensFormulas.memoryFreeExcludingCache,
label: i18n.translate('xpack.infra.assetDetails.metricsCharts.metric.label.free', {
defaultMessage: 'Free',
}),
},
],
options: {
seriesType: 'area_stacked',
},
type: 'visualization',
},
],
overrides: {
settings: XY_OVERRIDES.settings,
},
dataViewOrigin: 'metrics',
};

View file

@ -1,44 +0,0 @@
/*
* 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 { i18n } from '@kbn/i18n';
import { hostLensFormulas } from '../../../formulas';
import { XY_OVERRIDES } from '../../constants';
import type { XYConfig } from '../../types';
export const rxTx: XYConfig = {
id: 'rxTx',
title: i18n.translate('xpack.infra.assetDetails.metricsCharts.network', {
defaultMessage: 'Network',
}),
layers: [
{
data: [
{
...hostLensFormulas.rx,
label: i18n.translate('xpack.infra.assetDetails.metricsCharts.network.label.rx', {
defaultMessage: 'Inbound (RX)',
}),
},
{
...hostLensFormulas.tx,
label: i18n.translate('xpack.infra.assetDetails.metricsCharts.network.label.tx', {
defaultMessage: 'Outbound (TX)',
}),
},
],
options: {
seriesType: 'area',
},
type: 'visualization',
},
],
overrides: {
settings: XY_OVERRIDES.settings,
},
dataViewOrigin: 'metrics',
};

View file

@ -1,46 +0,0 @@
/*
* 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 { StaticValueConfig, XYVisualOptions } from '@kbn/lens-embeddable-utils';
import type { AllowedSettingsOverrides, AllowedXYOverrides } from '@kbn/lens-plugin/common/types';
interface XYOverrides {
axisLeft: AllowedXYOverrides['axisLeft'];
settings: AllowedSettingsOverrides['settings'];
}
export const REFERENCE_LINE: StaticValueConfig = {
value: '1',
format: {
id: 'percent',
params: {
decimals: 0,
},
},
color: '#6092c0',
};
export const XY_OVERRIDES: XYOverrides = {
axisLeft: {
domain: {
min: 0,
max: 1,
},
},
settings: {
showLegend: true,
legendPosition: 'bottom',
legendSize: 50,
},
};
export const XY_MISSING_VALUE_DOTTED_LINE_CONFIG: XYVisualOptions = {
showDottedLine: true,
missingValues: 'Linear',
};
export const KPI_CHART_HEIGHT = 150;

View file

@ -1,189 +0,0 @@
/*
* 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 { i18n } from '@kbn/i18n';
import type { XYLayerOptions } from '@kbn/lens-embeddable-utils';
import type { TypedLensByValueInput } from '@kbn/lens-plugin/public';
import { hostLensFormulas } from '../../formulas';
import type { XYChartLayerParams } from '../../../types';
import { REFERENCE_LINE, XY_OVERRIDES } from '../constants';
const XY_LAYER_OPTIONS: XYLayerOptions = {
breakdown: {
type: 'top_values',
field: 'host.name',
params: {
size: 20,
},
},
};
export const hostsMetricCharts: Array<
Pick<TypedLensByValueInput, 'id' | 'title' | 'overrides'> & {
layers: XYChartLayerParams[];
}
> = [
{
id: 'cpuUsage',
title: i18n.translate('xpack.infra.hostsViewPage.tabs.metricsCharts.cpuUsage', {
defaultMessage: 'CPU Usage',
}),
layers: [
{ data: [hostLensFormulas.cpuUsage], options: XY_LAYER_OPTIONS, type: 'visualization' },
],
overrides: { axisLeft: XY_OVERRIDES.axisLeft },
},
{
id: 'normalizedLoad1m',
title: i18n.translate('xpack.infra.hostsViewPage.tabs.metricsCharts.normalizedLoad1m', {
defaultMessage: 'Normalized Load',
}),
layers: [
{
data: [hostLensFormulas.normalizedLoad1m],
options: XY_LAYER_OPTIONS,
type: 'visualization',
},
{
data: [REFERENCE_LINE],
type: 'referenceLines',
},
],
},
{
id: 'memoryUsage',
title: i18n.translate('xpack.infra.hostsViewPage.tabs.metricsCharts.memoryUsage', {
defaultMessage: 'Memory Usage',
}),
layers: [
{
data: [hostLensFormulas.memoryUsage],
options: XY_LAYER_OPTIONS,
type: 'visualization',
},
],
overrides: { axisLeft: XY_OVERRIDES.axisLeft },
},
{
id: 'memoryFree',
title: i18n.translate('xpack.infra.hostsViewPage.tabs.metricsCharts.memoryFree', {
defaultMessage: 'Memory Free',
}),
layers: [
{
data: [hostLensFormulas.memoryFree],
options: XY_LAYER_OPTIONS,
type: 'visualization',
},
],
},
{
id: 'diskSpaceUsed',
title: i18n.translate('xpack.infra.hostsViewPage.tabs.metricsCharts.diskUsage', {
defaultMessage: 'Disk Usage',
}),
layers: [
{
data: [hostLensFormulas.diskUsage],
options: XY_LAYER_OPTIONS,
type: 'visualization',
},
],
overrides: { axisLeft: XY_OVERRIDES.axisLeft },
},
{
id: 'diskSpaceAvailable',
title: i18n.translate('xpack.infra.hostsViewPage.tabs.metricsCharts.diskSpaceAvailable', {
defaultMessage: 'Disk Space Available',
}),
layers: [
{
data: [hostLensFormulas.diskSpaceAvailable],
options: XY_LAYER_OPTIONS,
type: 'visualization',
},
],
},
{
id: 'diskIORead',
title: i18n.translate('xpack.infra.hostsViewPage.tabs.metricsCharts.diskIORead', {
defaultMessage: 'Disk Read IOPS',
}),
layers: [
{
data: [hostLensFormulas.diskIORead],
options: XY_LAYER_OPTIONS,
type: 'visualization',
},
],
},
{
id: 'diskIOWrite',
title: i18n.translate('xpack.infra.hostsViewPage.tabs.metricsCharts.diskIOWrite', {
defaultMessage: 'Disk Write IOPS',
}),
layers: [
{
data: [hostLensFormulas.diskIOWrite],
options: XY_LAYER_OPTIONS,
type: 'visualization',
},
],
},
{
id: 'diskReadThroughput',
title: i18n.translate('xpack.infra.hostsViewPage.tabs.metricsCharts.diskReadThroughput', {
defaultMessage: 'Disk Read Throughput',
}),
layers: [
{
data: [hostLensFormulas.diskReadThroughput],
options: XY_LAYER_OPTIONS,
type: 'visualization',
},
],
},
{
id: 'diskWriteThroughput',
title: i18n.translate('xpack.infra.hostsViewPage.tabs.metricsCharts.diskWriteThroughput', {
defaultMessage: 'Disk Write Throughput',
}),
layers: [
{
data: [hostLensFormulas.diskWriteThroughput],
options: XY_LAYER_OPTIONS,
type: 'visualization',
},
],
},
{
id: 'rx',
title: i18n.translate('xpack.infra.hostsViewPage.tabs.metricsCharts.rx', {
defaultMessage: 'Network Inbound (RX)',
}),
layers: [
{
data: [hostLensFormulas.rx],
options: XY_LAYER_OPTIONS,
type: 'visualization',
},
],
},
{
id: 'tx',
title: i18n.translate('xpack.infra.hostsViewPage.tabs.metricsCharts.tx', {
defaultMessage: 'Network Outbound (TX)',
}),
layers: [
{
data: [hostLensFormulas.tx],
options: XY_LAYER_OPTIONS,
type: 'visualization',
},
],
},
];

View file

@ -1,12 +0,0 @@
/*
* 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.
*/
export { assetDetailsDashboards } from './asset_details';
export { hostsViewDashboards } from './hosts_view';
export { AVERAGE_SUBTITLE, METRICS_TOOLTIP } from './translations';
export { XY_MISSING_VALUE_DOTTED_LINE_CONFIG, KPI_CHART_HEIGHT } from './constants';
export * from './types';

View file

@ -1,24 +0,0 @@
/*
* 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 { TypedLensByValueInput } from '@kbn/lens-plugin/public';
import type { DataViewOrigin } from '../../../../components/asset_details/types';
import type { MetricChartLayerParams, XYChartLayerParams } from '../../types';
type BaseProps = Pick<TypedLensByValueInput, 'id' | 'title' | 'overrides'>;
export interface AssetXYChartProps extends BaseProps {
layers: XYChartLayerParams[];
}
export interface XYConfig extends AssetXYChartProps {
dataViewOrigin: DataViewOrigin;
}
export interface KPIChartProps extends BaseProps {
layers: MetricChartLayerParams;
toolTip: string;
}

View file

@ -16,7 +16,7 @@ export const METRICS_TOOLTIP = {
defaultMessage:
'Percentage of CPU time spent in states other than Idle and IOWait, normalized by the number of CPU cores. This includes both time spent on user space and kernel space.',
}),
diskSpaceUsage: i18n.translate('xpack.infra.hostsViewPage.metrics.tooltip.diskSpaceUsage', {
diskUsage: i18n.translate('xpack.infra.hostsViewPage.metrics.tooltip.diskSpaceUsage', {
defaultMessage: 'Percentage of disk space used.',
}),
diskLatency: i18n.translate('xpack.infra.hostsViewPage.metrics.tooltip.diskLatency', {
@ -43,10 +43,3 @@ export const METRICS_TOOLTIP = {
'Number of bytes which have been sent per second on the public interfaces of the hosts.',
}),
};
export const AVERAGE_SUBTITLE = i18n.translate(
'xpack.infra.assetDetailsEmbeddable.overview.kpi.subtitle.average',
{
defaultMessage: 'Average',
}
);

View file

@ -1,18 +0,0 @@
/*
* 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 {
MetricLayerConfig,
XYLayerConfig,
XYReferenceLinesLayerConfig,
} from '@kbn/lens-embeddable-utils';
export type XYChartLayerParams =
| (XYLayerConfig & { type: 'visualization' })
| (XYReferenceLinesLayerConfig & { type: 'referenceLines' });
export type MetricChartLayerParams = MetricLayerConfig & { type: 'visualization' };

View file

@ -10,7 +10,6 @@ import { INTEGRATION_NAME } from './types';
export const ASSET_DETAILS_FLYOUT_COMPONENT_NAME = 'infraAssetDetailsFlyout';
export const ASSET_DETAILS_PAGE_COMPONENT_NAME = 'infraAssetDetailsPage';
export const METRIC_CHART_HEIGHT = 300;
export const APM_HOST_FILTER_FIELD = 'host.hostname';
export const ASSET_DETAILS_URL_STATE_KEY = 'assetDetails';

View file

@ -8,21 +8,20 @@ import React, { useMemo } from 'react';
import type { DataView } from '@kbn/data-views-plugin/public';
import { TimeRange } from '@kbn/es-query';
import { ChartModel } from '@kbn/lens-embeddable-utils';
import { METRICS_TOOLTIP } from '../../../../../common/visualizations';
import { LensChart, TooltipContent } from '../../../../lens';
import { AVERAGE_SUBTITLE, type KPIChartProps } from '../../../../../common/visualizations';
import { buildCombinedHostsFilter } from '../../../../../utils/filters/build';
import { useLoadingStateContext } from '../../../hooks/use_loading_state';
export const Kpi = ({
id,
title,
layers,
toolTip,
height,
dataView,
assetName,
dateRange,
}: KPIChartProps & {
dataView,
...chartProps
}: ChartModel & {
height: number;
dataView?: DataView;
assetName: string;
@ -39,20 +38,23 @@ export const Kpi = ({
];
}, [dataView, assetName]);
const tooltipContent = useMemo(() => <TooltipContent description={toolTip} />, [toolTip]);
const tooltipContent = useMemo(
() =>
id in METRICS_TOOLTIP ? (
<TooltipContent description={METRICS_TOOLTIP[id as keyof typeof METRICS_TOOLTIP]} />
) : undefined,
[id]
);
return (
<LensChart
{...chartProps}
id={`infraAssetDetailsKPI${id}`}
dataView={dataView}
dateRange={dateRange}
layers={layers}
height={height}
filters={filters}
title={title}
subtitle={AVERAGE_SUBTITLE}
toolTip={tooltipContent}
visualizationType="lnsMetric"
searchSessionId={searchSessionId}
disableTriggers
hidePanelTitles

View file

@ -5,12 +5,13 @@
* 2.0.
*/
import React from 'react';
import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
import React, { useMemo } from 'react';
import { EuiFlexGroup, EuiFlexItem, useEuiTheme } from '@elastic/eui';
import type { DataView } from '@kbn/data-views-plugin/public';
import type { TimeRange } from '@kbn/es-query';
import { useTheme } from '@kbn/observability-shared-plugin/public';
import { assetDetailsDashboards, KPI_CHART_HEIGHT } from '../../../../../common/visualizations';
import { findInventoryModel } from '@kbn/metrics-data-access-plugin/common';
import useAsync from 'react-use/lib/useAsync';
import { KPI_CHART_HEIGHT } from '../../../../../common/visualizations';
import { Kpi } from './kpi';
interface Props {
@ -20,23 +21,35 @@ interface Props {
}
export const KPIGrid = ({ assetName, dataView, dateRange }: Props) => {
const euiTheme = useTheme();
const model = findInventoryModel('host');
const { euiTheme } = useEuiTheme();
const { value: dashboards } = useAsync(() => {
return model.metrics.getDashboards();
});
const charts = useMemo(
() =>
dashboards?.kpi.get({
metricsDataView: dataView,
options: {
backgroundColor: euiTheme.colors.lightestShade,
},
}).charts ?? [],
[dataView, euiTheme.colors.lightestShade, dashboards?.kpi]
);
return (
<EuiFlexGroup direction="row" gutterSize="s" data-test-subj="infraAssetDetailsKPIGrid">
{assetDetailsDashboards.host
.hostKPICharts(euiTheme.eui.euiColorLightestShade)
.map((chartProps, index) => (
<EuiFlexItem key={index}>
<Kpi
{...chartProps}
dateRange={dateRange}
assetName={assetName}
dataView={dataView}
height={KPI_CHART_HEIGHT}
/>
</EuiFlexItem>
))}
{charts.map((chartProps, index) => (
<EuiFlexItem key={index}>
<Kpi
{...chartProps}
dateRange={dateRange}
assetName={assetName}
height={KPI_CHART_HEIGHT}
/>
</EuiFlexItem>
))}
</EuiFlexGroup>
);
};

View file

@ -5,47 +5,37 @@
* 2.0.
*/
import React, { useCallback, useMemo } from 'react';
import type { XYVisualOptions } from '@kbn/lens-embeddable-utils';
import type { DataView } from '@kbn/data-views-plugin/public';
import type { ChartModel } from '@kbn/lens-embeddable-utils';
import type { TimeRange } from '@kbn/es-query';
import { METRIC_CHART_HEIGHT } from '../../../../../common/visualizations/constants';
import { buildCombinedHostsFilter } from '../../../../../utils/filters/build';
import { type BrushEndArgs, LensChart, type OnFilterEvent } from '../../../../lens';
import { METRIC_CHART_HEIGHT } from '../../../constants';
import { type BrushEndArgs, LensChart, type OnFilterEvent, LensChartProps } from '../../../../lens';
import { useDatePickerContext } from '../../../hooks/use_date_picker';
import { extractRangeFromChartFilterEvent } from './chart_utils';
import type { XYConfig } from '../../../../../common/visualizations';
import { useLoadingStateContext } from '../../../hooks/use_loading_state';
export interface ChartProps extends XYConfig {
visualOptions?: XYVisualOptions;
metricsDataView?: DataView;
logsDataView?: DataView;
filterFieldName: string;
dateRange: TimeRange;
assetName: string;
['data-test-subj']: string;
}
export type ChartProps = ChartModel &
Pick<LensChartProps, 'overrides'> & {
filterFieldName: string;
dateRange: TimeRange;
assetName: string;
dataViewOrigin?: 'metrics' | 'logs';
['data-test-subj']: string;
};
export const Chart = ({
id,
title,
layers,
metricsDataView,
logsDataView,
filterFieldName,
visualOptions,
dataViewOrigin,
overrides,
dateRange,
assetName,
dataView,
...props
}: ChartProps) => {
const { setDateRange } = useDatePickerContext();
const { searchSessionId } = useLoadingStateContext();
const dataView = useMemo(() => {
return dataViewOrigin === 'metrics' ? metricsDataView : logsDataView;
}, [dataViewOrigin, logsDataView, metricsDataView]);
const { ['data-test-subj']: dataTestSubj, ...chartProps } = { ...props };
const filters = useMemo(() => {
return [
@ -85,18 +75,15 @@ export const Chart = ({
return (
<LensChart
id={`${props['data-test-subj']}${id}`}
{...chartProps}
id={`${dataTestSubj}${id}`}
borderRadius="m"
dataView={dataView}
dateRange={dateRange}
height={METRIC_CHART_HEIGHT}
visualOptions={visualOptions}
searchSessionId={searchSessionId}
layers={layers}
filters={filters}
title={title}
overrides={overrides}
visualizationType="lnsXY"
onBrushEnd={handleBrushEnd}
onFilter={handleFilter}
/>

View file

@ -4,61 +4,31 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import React, { useMemo } from 'react';
import type { DataView } from '@kbn/data-views-plugin/public';
import React from 'react';
import { EuiFlexItem, EuiFlexGrid } from '@elastic/eui';
import type { TimeRange } from '@kbn/es-query';
import {
type XYConfig,
XY_MISSING_VALUE_DOTTED_LINE_CONFIG,
} from '../../../../../common/visualizations';
import { useMetadataStateContext } from '../../../hooks/use_metadata_state';
import type { ChartModel } from '@kbn/lens-embeddable-utils';
import { Chart } from './chart';
interface Props {
assetName: string;
dateRange: TimeRange;
metricsDataView?: DataView;
logsDataView?: DataView;
filterFieldName: string;
charts: Array<XYConfig & { dependsOn?: string[] }>;
charts: ChartModel[];
['data-test-subj']: string;
}
export const MetricsGrid = ({
assetName,
metricsDataView,
logsDataView,
dateRange,
filterFieldName,
charts,
...props
}: Props) => {
const { metadata } = useMetadataStateContext();
const chartsToRender = useMemo(
() =>
charts.filter(
(c) =>
!c.dependsOn ||
c.dependsOn.every((d) => (metadata?.features ?? []).some((f) => d === f.name))
),
[charts, metadata?.features]
);
export const MetricsGrid = ({ assetName, dateRange, filterFieldName, charts, ...props }: Props) => {
return (
<EuiFlexGrid columns={2} gutterSize="s" data-test-subj={`${props['data-test-subj']}Grid`}>
{chartsToRender.map((chartProp, index) => (
{charts.map((chartProp, index) => (
<EuiFlexItem key={index} grow={false}>
<Chart
{...chartProp}
assetName={assetName}
dateRange={dateRange}
filterFieldName={filterFieldName}
logsDataView={logsDataView}
metricsDataView={metricsDataView}
data-test-subj={props['data-test-subj']}
visualOptions={XY_MISSING_VALUE_DOTTED_LINE_CONFIG}
/>
</EuiFlexItem>
))}

View file

@ -10,7 +10,8 @@ import { EuiFlexItem } from '@elastic/eui';
import type { DataView } from '@kbn/data-views-plugin/public';
import type { TimeRange } from '@kbn/es-query';
import { EuiFlexGroup } from '@elastic/eui';
import { assetDetailsDashboards } from '../../../../../common/visualizations';
import { findInventoryModel } from '@kbn/metrics-data-access-plugin/common';
import useAsync from 'react-use/lib/useAsync';
import {
MetricsSectionTitle,
KubernetesMetricsSectionTitle,
@ -25,31 +26,45 @@ interface Props {
logsDataView?: DataView;
}
const { host, kubernetes } = assetDetailsDashboards;
export const MetricsSection = ({ assetName, metricsDataView, logsDataView, dateRange }: Props) => {
const model = findInventoryModel('host');
const { value } = useAsync(() => {
return model.metrics.getDashboards();
});
const dashboards = useMemo(
() => ({
hosts: value?.assetDetails.get({
metricsDataView,
logsDataView,
}),
kubernetes: value?.assetDetailsKubernetesNode.get({
metricsDataView,
}),
}),
[logsDataView, metricsDataView, value?.assetDetails, value?.assetDetailsKubernetesNode]
);
return (
<EuiFlexGroup direction="column" gutterSize="s">
<Section title={MetricsSectionTitle}>
<MetricsGrid
assetName={assetName}
dateRange={dateRange}
charts={host.hostMetricChartsFullPage}
filterFieldName={host.keyField}
metricsDataView={metricsDataView}
logsDataView={logsDataView}
data-test-subj="infraAssetDetailsMetricsChart"
data-test-subj="infraAssetDetailsHostMetricsChart"
charts={dashboards.hosts?.charts ?? []}
filterFieldName={model.fields.name}
/>
</Section>
<Section dependsOn={kubernetes.dependsOn} title={KubernetesMetricsSectionTitle}>
<Section dependsOn={dashboards?.kubernetes?.dependsOn} title={KubernetesMetricsSectionTitle}>
<MetricsGrid
assetName={assetName}
dateRange={dateRange}
filterFieldName={kubernetes.keyField}
charts={kubernetes.kubernetesCharts}
metricsDataView={metricsDataView}
logsDataView={logsDataView}
data-test-subj="infraAssetDetailsKubernetesMetricsChart"
charts={dashboards.kubernetes?.charts ?? []}
filterFieldName={model.fields.name}
/>
</Section>
</EuiFlexGroup>
@ -61,19 +76,33 @@ export const MetricsSectionCompact = ({
metricsDataView,
logsDataView,
dateRange,
}: Props) => (
<Section title={MetricsSectionTitle}>
<MetricsGrid
assetName={assetName}
dateRange={dateRange}
filterFieldName={host.keyField}
charts={host.hostMetricFlyoutCharts}
metricsDataView={metricsDataView}
logsDataView={logsDataView}
data-test-subj="infraAssetDetailsMetricsChart"
/>
</Section>
);
}: Props) => {
const model = findInventoryModel('host');
const { value } = useAsync(() => {
return model.metrics.getDashboards();
});
const charts = useMemo(
() =>
value?.assetDetailsFlyout.get({
metricsDataView,
logsDataView,
}).charts ?? [],
[metricsDataView, logsDataView, value?.assetDetailsFlyout]
);
return (
<Section title={MetricsSectionTitle}>
<MetricsGrid
assetName={assetName}
dateRange={dateRange}
filterFieldName={model.fields.name}
charts={charts}
data-test-subj="infraAssetDetailsHostMetricsChart"
/>
</Section>
);
};
const Section = ({
title,

View file

@ -15,7 +15,6 @@ import { CoreStart } from '@kbn/core/public';
import type { InfraClientStartDeps } from '../types';
import { lensPluginMock } from '@kbn/lens-plugin/public/mocks';
import { FilterStateStore } from '@kbn/es-query';
import { hostLensFormulas } from '../common/visualizations';
jest.mock('@kbn/kibana-react-plugin/public');
const useKibanaMock = useKibana as jest.MockedFunction<typeof useKibana>;
@ -31,7 +30,16 @@ const mockDataView = {
metaFields: [],
} as unknown as jest.Mocked<DataView>;
const normalizedLoad1m = hostLensFormulas.normalizedLoad1m;
const normalizedLoad1m = {
label: 'Normalized Load',
value: 'average(system.load.1) / max(system.load.cores)',
format: {
id: 'percent',
params: {
decimals: 0,
},
},
};
const lensPluginMockStart = lensPluginMock.createStartContract();
const mockUseKibana = () => {
@ -55,7 +63,6 @@ describe('useHostTable hook', () => {
layers: [
{
data: [normalizedLoad1m],
type: 'visualization',
options: {
buckets: {
type: 'date_histogram',
@ -68,6 +75,7 @@ describe('useHostTable hook', () => {
},
},
},
layerType: 'data',
},
{
data: [
@ -81,7 +89,7 @@ describe('useHostTable hook', () => {
},
},
],
type: 'referenceLines',
layerType: 'referenceLine',
},
],
title: 'Injected Normalized Load',
@ -195,11 +203,12 @@ describe('useHostTable hook', () => {
it('should return extra actions', async () => {
const { result, waitForNextUpdate } = renderHook(() =>
useLensAttributes({
title: 'Chart',
visualizationType: 'lnsXY',
layers: [
{
data: [normalizedLoad1m],
type: 'visualization',
layerType: 'data',
},
],
dataView: mockDataView,

View file

@ -15,9 +15,10 @@ import useAsync from 'react-use/lib/useAsync';
import { FormulaPublicApi } from '@kbn/lens-plugin/public';
import {
type LensVisualizationState,
type XYVisualOptions,
type Chart,
type LensAttributes,
type ChartModel,
type XYLayerConfig,
LensAttributesBuilder,
XYChart,
MetricChart,
@ -26,35 +27,17 @@ import {
XYReferenceLinesLayer,
} from '@kbn/lens-embeddable-utils';
import { InfraClientSetupDeps } from '../types';
import type { MetricChartLayerParams, XYChartLayerParams } from '../common/visualizations/types';
interface UseLensAttributesBaseParams {
dataView?: DataView;
title?: string;
}
export interface UseLensAttributesXYChartParams extends UseLensAttributesBaseParams {
layers: XYChartLayerParams[];
visualizationType: 'lnsXY';
visualOptions?: XYVisualOptions;
}
export interface UseLensAttributesMetricChartParams extends UseLensAttributesBaseParams {
layers: MetricChartLayerParams;
visualizationType: 'lnsMetric';
subtitle?: string;
}
export type UseLensAttributesParams =
| UseLensAttributesXYChartParams
| UseLensAttributesMetricChartParams;
export type UseLensAttributesParams = Omit<ChartModel, 'id'>;
export const useLensAttributes = ({ dataView, ...params }: UseLensAttributesParams) => {
const {
services: { lens },
} = useKibana<InfraClientSetupDeps>();
const { navigateToPrefilledEditor } = lens;
const { value, error } = useAsync(lens.stateHelperApi, [lens]);
const { value, error } = useAsync(() => {
return lens.stateHelperApi();
}, [lens]);
const { formula: formulaAPI } = value ?? {};
const attributes = useMemo(() => {
@ -144,7 +127,7 @@ export const useLensAttributes = ({ dataView, ...params }: UseLensAttributesPara
const getFormula = () => {
const firstDataLayer = [
...(Array.isArray(params.layers) ? params.layers : [params.layers]),
].find((p) => p.type === 'visualization');
].find((p) => p.layerType === 'data');
if (!firstDataLayer) {
return '';
@ -174,32 +157,27 @@ const chartFactory = ({
throw new Error(`Invalid layers type. Expected an array of layers.`);
}
const xyLayerFactory = (layer: XYChartLayerParams) => {
switch (layer.type) {
case 'visualization': {
return new XYDataLayer({
data: layer.data,
options: layer.options,
});
const xyLayerFactory = (layer: XYLayerConfig) => {
switch (layer.layerType) {
case 'data': {
return new XYDataLayer(layer);
}
case 'referenceLines': {
return new XYReferenceLinesLayer({
data: layer.data,
});
case 'referenceLine': {
return new XYReferenceLinesLayer(layer);
}
default:
throw new Error(`Invalid layer type`);
}
};
const { layers, ...rest } = params;
return new XYChart({
dataView,
formulaAPI,
layers: params.layers.map((layerItem) => {
layers: layers.map((layerItem) => {
return xyLayerFactory(layerItem);
}),
title: params.title,
visualOptions: params.visualOptions,
...rest,
});
case 'lnsMetric':
@ -212,7 +190,8 @@ const chartFactory = ({
formulaAPI,
layers: new MetricLayer({
data: params.layers.data,
options: { ...params.layers.options, subtitle: params.subtitle },
options: { ...params.layers.options },
layerType: params.layers.layerType,
}),
title: params.title,
});

View file

@ -15,6 +15,7 @@ import { HostsViewProvider } from '../hooks/use_hosts_view';
import { HostsTableProvider } from '../hooks/use_hosts_table';
import { ErrorCallout } from './error_callout';
import { useUnifiedSearchContext } from '../hooks/use_unified_search';
import { HostCountProvider } from '../hooks/use_host_count';
export const HostsContent = () => {
const { error } = useUnifiedSearchContext();
@ -28,7 +29,9 @@ export const HostsContent = () => {
<HostsTableProvider>
<EuiFlexGroup direction="column" gutterSize="m">
<EuiFlexItem grow={false}>
<KPIGrid />
<HostCountProvider>
<KPIGrid />
</HostCountProvider>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<HostsTable />

View file

@ -7,18 +7,22 @@
import { i18n } from '@kbn/i18n';
import React from 'react';
import { useTheme } from '@kbn/observability-shared-plugin/public';
import { hostLensFormulas, METRICS_TOOLTIP } from '../../../../../common/visualizations';
import { findInventoryModel } from '@kbn/metrics-data-access-plugin/common';
import useAsync from 'react-use/lib/useAsync';
import { METRICS_TOOLTIP } from '../../../../../common/visualizations';
import { useHostCountContext } from '../../hooks/use_host_count';
import { useUnifiedSearchContext } from '../../hooks/use_unified_search';
import { type Props, MetricChartWrapper } from '../chart/metric_chart_wrapper';
import { TooltipContent } from '../../../../../components/lens';
export const HostCountKpi = ({ height }: { height: number }) => {
const inventoryModel = findInventoryModel('host');
const { data: hostCountData, isRequestRunning: hostCountLoading } = useHostCountContext();
const { searchCriteria } = useUnifiedSearchContext();
const euiTheme = useTheme();
const { value: formulas } = useAsync(() => inventoryModel.metrics.getFormulas());
const hostsCountChart: Omit<Props, 'loading' | 'value' | 'toolTip'> = {
id: 'hostsViewKPI-hostsCount',
color: euiTheme.eui.euiColorLightestShade,
@ -46,7 +50,7 @@ export const HostCountKpi = ({ height }: { height: number }) => {
subtitle={getSubtitle()}
toolTip={
<TooltipContent
formula={hostLensFormulas.hostCount.value}
formula={formulas?.hostCount.value}
description={METRICS_TOOLTIP.hostCount}
/>
}

View file

@ -5,21 +5,25 @@
* 2.0.
*/
import React, { useMemo } from 'react';
import { i18n } from '@kbn/i18n';
import { ChartModel } from '@kbn/lens-embeddable-utils';
import { METRICS_TOOLTIP } from '../../../../../common/visualizations';
import { LensChart, TooltipContent } from '../../../../../components/lens';
import { type KPIChartProps, AVERAGE_SUBTITLE } from '../../../../../common/visualizations';
import { buildCombinedHostsFilter } from '../../../../../utils/filters/build';
import { useMetricsDataViewContext } from '../../hooks/use_data_view';
import { useUnifiedSearchContext } from '../../hooks/use_unified_search';
import { useHostsViewContext } from '../../hooks/use_hosts_view';
import { useHostCountContext } from '../../hooks/use_host_count';
import { useAfterLoadedState } from '../../hooks/use_after_loaded_state';
export const Kpi = ({ id, title, layers, toolTip, height }: KPIChartProps & { height: number }) => {
export const Kpi = ({
id,
height,
visualizationType = 'lnsMetric',
dataView,
...chartProps
}: ChartModel & { height: number }) => {
const { searchCriteria } = useUnifiedSearchContext();
const { dataView } = useMetricsDataViewContext();
const { hostNodes, loading: hostsLoading, searchSessionId } = useHostsViewContext();
const { data: hostCountData, isRequestRunning: hostCountLoading } = useHostCountContext();
const { isRequestRunning: hostCountLoading } = useHostCountContext();
const shouldUseSearchCriteria = hostNodes.length === 0;
const loading = hostsLoading || hostCountLoading;
@ -34,16 +38,6 @@ export const Kpi = ({ id, title, layers, toolTip, height }: KPIChartProps & { he
}),
];
const subtitle =
searchCriteria.limit < (hostCountData?.count.value ?? 0)
? i18n.translate('xpack.infra.hostsViewPage.kpi.subtitle.average.limit', {
defaultMessage: 'Average (of {limit} hosts)',
values: {
limit: searchCriteria.limit,
},
})
: AVERAGE_SUBTITLE;
// prevents requestTs and searchCriteria state from reloading the chart
// we want it to reload only once the table has finished loading.
// attributes passed to useAfterLoadedState don't need to be memoized
@ -52,26 +46,29 @@ export const Kpi = ({ id, title, layers, toolTip, height }: KPIChartProps & { he
query: shouldUseSearchCriteria ? searchCriteria.query : undefined,
filters,
searchSessionId,
subtitle,
});
const tooltipComponent = useMemo(() => <TooltipContent description={toolTip} />, [toolTip]);
const tooltipContent = useMemo(
() =>
id in METRICS_TOOLTIP ? (
<TooltipContent description={METRICS_TOOLTIP[id as keyof typeof METRICS_TOOLTIP]} />
) : undefined,
[id]
);
return (
<LensChart
{...chartProps}
id={`hostsViewKPI-${id}`}
dataView={dataView}
dateRange={afterLoadedState.dateRange}
filters={afterLoadedState.filters}
layers={layers}
loading={loading}
height={height}
visualizationType={visualizationType}
query={afterLoadedState.query}
title={title}
searchSessionId={afterLoadedState.searchSessionId}
subtitle={afterLoadedState.subtitle}
toolTip={tooltipComponent}
visualizationType="lnsMetric"
toolTip={tooltipContent}
disableTriggers
hidePanelTitles
/>

View file

@ -4,36 +4,68 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import React from 'react';
import React, { useMemo } from 'react';
import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
import { EuiSpacer } from '@elastic/eui';
import { useTheme } from '@kbn/observability-shared-plugin/public';
import { findInventoryModel } from '@kbn/metrics-data-access-plugin/common';
import { useEuiTheme } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import useAsync from 'react-use/lib/useAsync';
import { KPI_CHART_HEIGHT } from '../../../../../common/visualizations';
import { HostMetricsDocsLink } from '../../../../../components/lens';
import { Kpi } from './kpi';
import { HostCountProvider } from '../../hooks/use_host_count';
import { useHostCountContext } from '../../hooks/use_host_count';
import { HostCountKpi } from './host_count_kpi';
import { assetDetailsDashboards, KPI_CHART_HEIGHT } from '../../../../../common/visualizations';
import { useMetricsDataViewContext } from '../../hooks/use_data_view';
import { useUnifiedSearchContext } from '../../hooks/use_unified_search';
export const KPIGrid = () => {
const euiTheme = useTheme();
const model = findInventoryModel('host');
const { searchCriteria } = useUnifiedSearchContext();
const { euiTheme } = useEuiTheme();
const { dataView } = useMetricsDataViewContext();
const { data: hostCountData } = useHostCountContext();
const { value: dashboards } = useAsync(() => {
return model.metrics.getDashboards();
});
const subtitle =
searchCriteria.limit < (hostCountData?.count.value ?? 0)
? i18n.translate('xpack.infra.hostsViewPage.kpi.subtitle.average.limit', {
defaultMessage: 'Average (of {limit} hosts)',
values: {
limit: searchCriteria.limit,
},
})
: undefined;
const charts = useMemo(
() =>
dashboards?.kpi.get({
metricsDataView: dataView,
options: {
backgroundColor: euiTheme.colors.lightestShade,
...(subtitle ? { subtitle } : {}),
},
}).charts ?? [],
[dashboards?.kpi, dataView, euiTheme.colors.lightestShade, subtitle]
);
return (
<HostCountProvider>
<>
<HostMetricsDocsLink type="metrics" />
<EuiSpacer size="s" />
<EuiFlexGroup direction="row" gutterSize="s" data-test-subj="hostsViewKPIGrid">
<EuiFlexItem>
<HostCountKpi height={KPI_CHART_HEIGHT} />
</EuiFlexItem>
{assetDetailsDashboards.host
.hostKPICharts(euiTheme.eui.euiColorLightestShade)
.map((chartProp, index) => (
<EuiFlexItem key={index}>
<Kpi {...chartProp} height={KPI_CHART_HEIGHT} />
</EuiFlexItem>
))}
{charts.map((chartProp, index) => (
<EuiFlexItem key={index}>
<Kpi {...chartProp} height={KPI_CHART_HEIGHT} />
</EuiFlexItem>
))}
</EuiFlexGroup>
</HostCountProvider>
</>
);
};

View file

@ -5,24 +5,21 @@
* 2.0.
*/
import React, { useMemo } from 'react';
import type { XYVisualOptions } from '@kbn/lens-embeddable-utils';
import type { AssetXYChartProps } from '../../../../../../common/visualizations';
import type { ChartModel, XYVisualOptions } from '@kbn/lens-embeddable-utils';
import { METRIC_CHART_HEIGHT } from '../../../../../../common/visualizations/constants';
import { LensChart } from '../../../../../../components/lens';
import { useMetricsDataViewContext } from '../../../hooks/use_data_view';
import { useUnifiedSearchContext } from '../../../hooks/use_unified_search';
import { useHostsViewContext } from '../../../hooks/use_hosts_view';
import { buildCombinedHostsFilter } from '../../../../../../utils/filters/build';
import { useHostsTableContext } from '../../../hooks/use_hosts_table';
import { useAfterLoadedState } from '../../../hooks/use_after_loaded_state';
import { METRIC_CHART_HEIGHT } from '../../../constants';
export interface ChartProps extends AssetXYChartProps {
export interface ChartProps extends Omit<ChartModel, 'visualOptions'> {
visualOptions?: XYVisualOptions;
}
export const Chart = ({ id, title, layers, visualOptions, overrides }: ChartProps) => {
export const Chart = ({ dataView, ...chartProps }: ChartProps) => {
const { searchCriteria } = useUnifiedSearchContext();
const { dataView } = useMetricsDataViewContext();
const { loading, searchSessionId } = useHostsViewContext();
const { currentPage } = useHostsTableContext();
@ -51,20 +48,16 @@ export const Chart = ({ id, title, layers, visualOptions, overrides }: ChartProp
return (
<LensChart
id={`hostsView-metricChart-${id}`}
{...chartProps}
id={`hostsView-metricChart-${chartProps.id}`}
borderRadius="m"
dataView={dataView}
dateRange={afterLoadedState.dateRange}
height={METRIC_CHART_HEIGHT}
layers={layers}
visualOptions={visualOptions}
loading={loading}
filters={filters}
query={afterLoadedState.query}
searchSessionId={afterLoadedState.searchSessionId}
title={title}
overrides={overrides}
visualizationType="lnsXY"
/>
);
};

View file

@ -4,22 +4,38 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import React from 'react';
import React, { useMemo } from 'react';
import { i18n } from '@kbn/i18n';
import { EuiFlexGrid, EuiFlexItem, EuiText, EuiFlexGroup, EuiSpacer } from '@elastic/eui';
import {
hostsViewDashboards,
XY_MISSING_VALUE_DOTTED_LINE_CONFIG,
} from '../../../../../../common/visualizations';
import { findInventoryModel } from '@kbn/metrics-data-access-plugin/common';
import useAsync from 'react-use/lib/useAsync';
import { HostMetricsExplanationContent } from '../../../../../../components/lens';
import { Chart } from './chart';
import { Popover } from '../../table/popover';
import { useMetricsDataViewContext } from '../../../hooks/use_data_view';
export const MetricsGrid = () => {
const model = findInventoryModel('host');
const { dataView } = useMetricsDataViewContext();
const { value: dashboards } = useAsync(() => {
return model.metrics.getDashboards();
});
const charts = useMemo(
() => dashboards?.hostsView.get({ metricsDataView: dataView }).charts ?? [],
[dataView, dashboards]
);
return (
<>
<EuiFlexGroup gutterSize="xs" alignItems="center">
<EuiFlexItem grow={false}>
<EuiText size="xs">Learn more about metrics</EuiText>
<EuiText size="xs">
{i18n.translate('xpack.infra.metricsGrid.learnMoreAboutMetricsTextLabel', {
defaultMessage: 'Learn more about metrics',
})}
</EuiText>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<Popover>
@ -30,9 +46,9 @@ export const MetricsGrid = () => {
<EuiSpacer size="s" />
<EuiFlexGrid columns={2} gutterSize="s" data-test-subj="hostsView-metricChart">
{hostsViewDashboards.hostsMetricCharts.map((chartProp, index) => (
{charts.map((chartProp, index) => (
<EuiFlexItem key={index} grow={false}>
<Chart {...chartProp} visualOptions={XY_MISSING_VALUE_DOTTED_LINE_CONFIG} />
<Chart {...chartProp} />
</EuiFlexItem>
))}
</EuiFlexGrid>

View file

@ -12,7 +12,5 @@ export const DEFAULT_PAGE_SIZE = 10;
export const LOCAL_STORAGE_HOST_LIMIT_KEY = 'hostsView:hostLimitSelection';
export const LOCAL_STORAGE_PAGE_SIZE_KEY = 'hostsView:pageSizeSelection';
export const METRIC_CHART_HEIGHT = 300;
export const HOST_LIMIT_OPTIONS = [50, 100, 500] as const;
export const HOST_METRICS_DOC_HREF = 'https://ela.st/docs-infra-host-metrics';

View file

@ -13,10 +13,11 @@ import {
type EuiBasicTable,
} from '@elastic/eui';
import createContainer from 'constate';
import useAsync from 'react-use/lib/useAsync';
import { isEqual } from 'lodash';
import { isNumber } from 'lodash/fp';
import { CloudProvider } from '@kbn/custom-icons';
import { hostLensFormulas } from '../../../../common/visualizations';
import { findInventoryModel } from '@kbn/metrics-data-access-plugin/common';
import { useKibanaContextForPlugin } from '../../../../hooks/use_kibana';
import { createInventoryMetricFormatter } from '../../inventory_view/lib/create_inventory_metric_formatter';
import { EntryTitle } from '../components/table/entry_title';
@ -124,9 +125,12 @@ const sortTableData =
* Build a table columns and items starting from the snapshot nodes.
*/
export const useHostsTable = () => {
const inventoryModel = findInventoryModel('host');
const [selectedItems, setSelectedItems] = useState<HostNodeRow[]>([]);
const { hostNodes } = useHostsViewContext();
const { value: formulas } = useAsync(() => inventoryModel.metrics.getFormulas());
const [{ detailsItemId, pagination, sorting }, setProperties] = useHostsTableUrlState();
const {
services: {
@ -241,7 +245,7 @@ export const useHostsTable = () => {
<ColumnHeader
label={TABLE_COLUMN_LABEL.cpuUsage}
toolTip={METRICS_TOOLTIP.cpuUsage}
formula={hostLensFormulas.cpuUsage.value}
formula={formulas?.cpuUsage.value}
/>
),
field: 'cpu',
@ -255,7 +259,7 @@ export const useHostsTable = () => {
<ColumnHeader
label={TABLE_COLUMN_LABEL.normalizedLoad1m}
toolTip={METRICS_TOOLTIP.normalizedLoad1m}
formula={hostLensFormulas.normalizedLoad1m.value}
formula={formulas?.normalizedLoad1m.value}
/>
),
field: 'normalizedLoad1m',
@ -269,7 +273,7 @@ export const useHostsTable = () => {
<ColumnHeader
label={TABLE_COLUMN_LABEL.memoryUsage}
toolTip={METRICS_TOOLTIP.memoryUsage}
formula={hostLensFormulas.memoryUsage.value}
formula={formulas?.memoryUsage.value}
/>
),
field: 'memory',
@ -283,7 +287,7 @@ export const useHostsTable = () => {
<ColumnHeader
label={TABLE_COLUMN_LABEL.memoryFree}
toolTip={METRICS_TOOLTIP.memoryFree}
formula={hostLensFormulas.memoryFree.value}
formula={formulas?.memoryFree.value}
/>
),
field: 'memoryFree',
@ -296,8 +300,8 @@ export const useHostsTable = () => {
name: (
<ColumnHeader
label={TABLE_COLUMN_LABEL.diskSpaceUsage}
toolTip={METRICS_TOOLTIP.diskSpaceUsage}
formula={hostLensFormulas.diskUsage.value}
toolTip={METRICS_TOOLTIP.diskUsage}
formula={formulas?.diskUsage.value}
/>
),
field: 'diskSpaceUsage',
@ -311,7 +315,7 @@ export const useHostsTable = () => {
<ColumnHeader
label={TABLE_COLUMN_LABEL.rx}
toolTip={METRICS_TOOLTIP.rx}
formula={hostLensFormulas.rx.value}
formula={formulas?.rx.value}
/>
),
field: 'rx',
@ -326,7 +330,7 @@ export const useHostsTable = () => {
<ColumnHeader
label={TABLE_COLUMN_LABEL.tx}
toolTip={METRICS_TOOLTIP.tx}
formula={hostLensFormulas.tx.value}
formula={formulas?.tx.value}
/>
),
field: 'tx',
@ -337,7 +341,18 @@ export const useHostsTable = () => {
width: '120px',
},
],
[detailsItemId, reportHostEntryClick, setProperties]
[
detailsItemId,
formulas?.cpuUsage.value,
formulas?.diskUsage.value,
formulas?.memoryFree.value,
formulas?.memoryUsage.value,
formulas?.normalizedLoad1m.value,
formulas?.rx.value,
formulas?.tx.value,
reportHostEntryClick,
setProperties,
]
);
const selection: EuiTableSelectionType<HostNodeRow> = {

View file

@ -19,6 +19,7 @@ export const getFilteredMetrics = (
.map((data) => data && data.name);
return requiredMetrics.filter((metric) => {
const metricModelCreator = metrics.tsvb[metric];
// We just need to get a dummy version of the model so we can filter
// using the `requires` attribute.
const metricModel = metricModelCreator(TIMESTAMP_FIELD, 'test', '>=1m');

View file

@ -13,7 +13,7 @@ export {
metrics,
} from './inventory_models';
export { podSnapshotMetricTypes } from './inventory_models/pod';
export { podSnapshotMetricTypes } from './inventory_models/kubernetes/pod';
export { containerSnapshotMetricTypes } from './inventory_models/container';
export { awsS3SnapshotMetricTypes } from './inventory_models/aws_s3';
export { hostSnapshotMetricTypes } from './inventory_models/host';

View file

@ -0,0 +1,18 @@
/*
* 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 { DashboardModel } from './types';
export const createDashboardModel = ({
charts,
dependsOn = [],
}: DashboardModel): DashboardModel => {
return {
dependsOn,
charts,
};
};

View file

@ -12,10 +12,9 @@ import {
aws as awsRequiredMetrics,
nginx as nginxRequireMetrics,
} from '../shared/metrics/required_metrics';
export { hostSnapshotMetricTypes } from './metrics';
export const host: InventoryModel = {
export const host: InventoryModel<typeof metrics> = {
id: 'host',
displayName: i18n.translate('xpack.metricsData.inventoryModel.host.displayName', {
defaultMessage: 'Hosts',

View file

@ -0,0 +1,85 @@
/*
* 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 { i18n } from '@kbn/i18n';
import type { StaticValueConfig, XYChartModel } from '@kbn/lens-embeddable-utils';
import { formulas } from '../formulas';
import type { ChartArgs } from './types';
export const REFERENCE_LINE: StaticValueConfig = {
value: '1',
format: {
id: 'percent',
params: {
decimals: 0,
},
},
color: '#6092c0',
};
export const cpuUsageBreakdown = {
get: ({ dataView }: ChartArgs): XYChartModel => ({
id: 'cpuUsageBreakdown',
title: i18n.translate('xpack.metricsData.assetDetails.metricsCharts.cpuUsage', {
defaultMessage: 'CPU Usage',
}),
layers: [
{
data: [
formulas.cpuUsageIowait,
formulas.cpuUsageIrq,
formulas.cpuUsageNice,
formulas.cpuUsageSoftirq,
formulas.cpuUsageSteal,
formulas.cpuUsageUser,
formulas.cpuUsageSystem,
],
options: {
seriesType: 'area_stacked',
},
layerType: 'data',
},
],
visualizationType: 'lnsXY',
dataView,
}),
};
export const normalizedLoad1m = {
get: ({ dataView }: ChartArgs): XYChartModel => ({
id: 'normalizedLoad1m',
title: i18n.translate('xpack.metricsData.assetDetails.metricsCharts.normalizedLoad1m', {
defaultMessage: 'Normalized Load',
}),
layers: [
{ data: [formulas.normalizedLoad1m], layerType: 'data' },
{ data: [REFERENCE_LINE], layerType: 'referenceLine' },
],
visualizationType: 'lnsXY',
dataView,
}),
};
export const loadBreakdown = {
get: ({ dataView }: ChartArgs): XYChartModel => ({
id: 'loadBreakdown',
title: i18n.translate('xpack.metricsData.assetDetails.metricsCharts.load', {
defaultMessage: 'Load',
}),
layers: [
{
data: [formulas.load1m, formulas.load5m, formulas.load15m],
options: {
seriesType: 'area',
},
layerType: 'data',
},
],
visualizationType: 'lnsXY',
dataView,
}),
};

View file

@ -0,0 +1,192 @@
/*
* 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 { i18n } from '@kbn/i18n';
import type { XYChartModel } from '@kbn/lens-embeddable-utils';
import { formulas } from '../formulas';
import type { ChartArgs } from './types';
const TOP_VALUES_SIZE = 5;
export const diskSpaceUsageAvailable = {
get: ({ dataView }: ChartArgs): XYChartModel => ({
id: 'diskSpaceUsageAvailable',
title: i18n.translate('xpack.metricsData.assetDetails.metricsCharts.diskUsage', {
defaultMessage: 'Disk Usage',
}),
layers: [
{
data: [
{
...formulas.diskUsage,
label: i18n.translate(
'xpack.metricsData.assetDetails.metricsCharts.diskUsage.label.used',
{
defaultMessage: 'Used',
}
),
},
{
...formulas.diskSpaceAvailability,
label: i18n.translate(
'xpack.metricsData.assetDetails.metricsCharts.diskUsage.label.available',
{
defaultMessage: 'Available',
}
),
},
],
options: {
seriesType: 'area',
},
layerType: 'data',
},
],
visualizationType: 'lnsXY',
dataView,
}),
};
export const diskUsageByMountPoint = {
get: ({ dataView }: ChartArgs): XYChartModel => ({
id: 'DiskUsageByMountPoint',
title: i18n.translate('xpack.metricsData.assetDetails.metricsCharts.diskUsageByMountingPoint', {
defaultMessage: 'Disk Usage by Mount Point',
}),
layers: [
{
data: [
{
...formulas.diskUsage,
label: i18n.translate(
'xpack.metricsData.assetDetails.metricsCharts.diskUsage.label.used',
{
defaultMessage: 'Used',
}
),
},
],
options: {
seriesType: 'area',
breakdown: {
type: 'top_values',
field: 'system.filesystem.mount_point',
params: {
size: TOP_VALUES_SIZE,
},
},
},
layerType: 'data',
},
],
visualOptions: {
legend: {
isVisible: true,
position: 'bottom',
legendSize: 50 as any,
},
yLeftExtent: {
mode: 'dataBounds',
lowerBound: 0,
upperBound: 1,
},
},
visualizationType: 'lnsXY',
dataView,
}),
};
export const diskThroughputReadWrite = {
get: ({ dataView }: ChartArgs): XYChartModel => ({
id: 'diskThroughputReadWrite',
title: i18n.translate('xpack.metricsData.assetDetails.metricsCharts.diskIOPS', {
defaultMessage: 'Disk IOPS',
}),
layers: [
{
data: [
{
...formulas.diskIORead,
label: i18n.translate(
'xpack.metricsData.assetDetails.metricsCharts.metric.label.read',
{
defaultMessage: 'Read',
}
),
},
{
...formulas.diskIOWrite,
label: i18n.translate(
'xpack.metricsData.assetDetails.metricsCharts.metric.label.write',
{
defaultMessage: 'Write',
}
),
},
],
options: {
seriesType: 'area',
},
layerType: 'data',
},
],
visualOptions: {
yLeftExtent: {
mode: 'dataBounds',
lowerBound: 0,
upperBound: 1,
},
},
visualizationType: 'lnsXY',
dataView,
}),
};
export const diskIOReadWrite = {
get: ({ dataView }: ChartArgs): XYChartModel => ({
id: 'diskIOReadWrite',
title: i18n.translate('xpack.metricsData.assetDetails.metricsCharts.diskThroughput', {
defaultMessage: 'Disk Throughput',
}),
layers: [
{
data: [
{
...formulas.diskReadThroughput,
label: i18n.translate(
'xpack.metricsData.assetDetails.metricsCharts.metric.label.read',
{
defaultMessage: 'Read',
}
),
},
{
...formulas.diskWriteThroughput,
label: i18n.translate(
'xpack.metricsData.assetDetails.metricsCharts.metric.label.write',
{
defaultMessage: 'Write',
}
),
},
],
options: {
seriesType: 'area',
},
layerType: 'data',
},
],
visualOptions: {
yLeftExtent: {
mode: 'dataBounds',
lowerBound: 0,
upperBound: 1,
},
},
visualizationType: 'lnsXY',
dataView,
}),
};

View file

@ -0,0 +1,72 @@
/*
* 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 ChartModel,
type XYChartModel,
type MetricChartModel,
type XYLayerOptions,
type MetricLayerOptions,
type ChartTypes,
type XYVisualOptions,
XY_ID,
} from '@kbn/lens-embeddable-utils';
import type { HostFormulaNames } from '../formulas';
import { formulas } from '../formulas';
type ChartByFormula<TType extends ChartTypes> = Record<
HostFormulaNames,
TType extends typeof XY_ID ? XYChartModel : MetricChartModel
>;
type BaseArgs<TType extends ChartTypes> = Pick<ChartModel, 'dataView'> & {
formulaIds: HostFormulaNames[];
visualizationType: TType;
layerOptions?: TType extends typeof XY_ID ? XYLayerOptions : MetricLayerOptions;
visualOptions?: TType extends typeof XY_ID ? XYVisualOptions : never;
};
export const createBasicCharts = <TType extends ChartTypes>({
formulaIds,
visualizationType,
dataView,
layerOptions,
...rest
}: BaseArgs<TType>): ChartByFormula<TType> => {
return formulaIds.reduce((acc, curr) => {
const layers = {
data: visualizationType === XY_ID ? [formulas[curr]] : formulas[curr],
layerType: visualizationType === XY_ID ? 'data' : 'metricTrendline',
options: layerOptions,
};
const chartModel = {
id: curr,
title: formulas[curr].label,
dataView,
visualizationType,
layers: visualizationType === XY_ID ? [layers] : layers,
...rest,
} as TType extends typeof XY_ID ? XYChartModel : MetricChartModel;
return {
...acc,
[curr]: chartModel,
};
}, {} as ChartByFormula<TType>);
};
// custom charts
export { cpuUsageBreakdown, normalizedLoad1m, loadBreakdown } from './cpu_charts';
export {
diskIOReadWrite,
diskSpaceUsageAvailable,
diskThroughputReadWrite,
diskUsageByMountPoint,
} from './disk_charts';
export { memoryUsageBreakdown } from './memory_charts';
export { rxTx } from './network_charts';

View file

@ -0,0 +1,71 @@
/*
* 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 { i18n } from '@kbn/i18n';
import type { XYChartModel } from '@kbn/lens-embeddable-utils';
import { formulas } from '../formulas';
import type { ChartArgs } from './types';
export const memoryUsageBreakdown = {
get: ({ dataView }: ChartArgs): XYChartModel => ({
id: 'memoryUsageBreakdown',
title: i18n.translate('xpack.metricsData.assetDetails.metricsCharts.memoryUsage', {
defaultMessage: 'Memory Usage',
}),
layers: [
{
data: [
{
...formulas.memoryCache,
label: i18n.translate(
'xpack.metricsData.assetDetails.metricsCharts.metric.label.cache',
{
defaultMessage: 'Cache',
}
),
},
{
...formulas.memoryUsed,
label: i18n.translate(
'xpack.metricsData.assetDetails.metricsCharts.metric.label.used',
{
defaultMessage: 'Used',
}
),
},
{
...formulas.memoryFreeExcludingCache,
label: i18n.translate(
'xpack.metricsData.assetDetails.metricsCharts.metric.label.free',
{
defaultMessage: 'Free',
}
),
},
],
options: {
seriesType: 'area_stacked',
},
layerType: 'data',
},
],
visualOptions: {
legend: {
isVisible: true,
position: 'bottom',
legendSize: 50 as any,
},
yLeftExtent: {
mode: 'dataBounds',
lowerBound: 0,
upperBound: 1,
},
},
visualizationType: 'lnsXY',
dataView,
}),
};

View file

@ -0,0 +1,52 @@
/*
* 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 { i18n } from '@kbn/i18n';
import type { XYChartModel } from '@kbn/lens-embeddable-utils';
import { formulas } from '../formulas';
import type { ChartArgs } from './types';
export const rxTx = {
get: ({ dataView }: ChartArgs): XYChartModel => ({
id: 'rxTx',
title: i18n.translate('xpack.metricsData.assetDetails.metricsCharts.network', {
defaultMessage: 'Network',
}),
layers: [
{
data: [
{
...formulas.rx,
label: i18n.translate('xpack.metricsData.assetDetails.metricsCharts.network.label.rx', {
defaultMessage: 'Inbound (RX)',
}),
},
{
...formulas.tx,
label: i18n.translate('xpack.metricsData.assetDetails.metricsCharts.network.label.tx', {
defaultMessage: 'Outbound (TX)',
}),
},
],
options: {
seriesType: 'area',
},
layerType: 'data',
},
],
visualOptions: {
yLeftExtent: {
mode: 'dataBounds',
lowerBound: 0,
upperBound: 1,
},
},
visualizationType: 'lnsXY',
dataView,
}),
};

View file

@ -5,8 +5,8 @@
* 2.0.
*/
import { hostsMetricCharts } from './hosts_metric_charts';
import { DataView } from '@kbn/data-views-plugin/common';
export const hostsViewDashboards = {
hostsMetricCharts,
};
export interface ChartArgs {
dataView?: DataView;
}

View file

@ -0,0 +1,97 @@
/*
* 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 { DataView } from '@kbn/data-views-plugin/common';
import type { XYVisualOptions } from '@kbn/lens-embeddable-utils';
import { createDashboardModel } from '../../../create_dashboard_model';
import {
createBasicCharts,
cpuUsageBreakdown,
diskSpaceUsageAvailable,
diskUsageByMountPoint,
diskIOReadWrite,
diskThroughputReadWrite,
memoryUsageBreakdown,
loadBreakdown,
rxTx,
} from '../charts';
export const assetDetails = {
get: ({
metricsDataView,
logsDataView,
}: {
metricsDataView?: DataView;
logsDataView?: DataView;
}) => {
const commonVisualOptions: XYVisualOptions = {
showDottedLine: true,
missingValues: 'Linear',
};
const legend: XYVisualOptions = {
legend: {
isVisible: true,
position: 'bottom',
},
};
const { cpuUsage, memoryUsage, normalizedLoad1m } = createBasicCharts({
visualizationType: 'lnsXY',
formulaIds: ['cpuUsage', 'memoryUsage', 'normalizedLoad1m'],
dataView: metricsDataView,
visualOptions: commonVisualOptions,
});
const { logRate } = createBasicCharts({
visualizationType: 'lnsXY',
formulaIds: ['logRate'],
dataView: logsDataView,
visualOptions: commonVisualOptions,
});
return createDashboardModel({
charts: [
cpuUsage,
{
...cpuUsageBreakdown.get({ dataView: metricsDataView }),
visualOptions: { ...commonVisualOptions, ...legend },
},
memoryUsage,
{
...memoryUsageBreakdown.get({ dataView: metricsDataView }),
visualOptions: { ...commonVisualOptions, ...legend },
},
normalizedLoad1m,
{
...loadBreakdown.get({ dataView: metricsDataView }),
visualOptions: { ...commonVisualOptions, ...legend },
},
logRate,
{
...diskSpaceUsageAvailable.get({ dataView: metricsDataView }),
visualOptions: { ...commonVisualOptions, ...legend },
},
{
...diskUsageByMountPoint.get({ dataView: metricsDataView }),
visualOptions: { ...commonVisualOptions, ...legend },
},
{
...diskThroughputReadWrite.get({ dataView: metricsDataView }),
visualOptions: { ...commonVisualOptions, ...legend },
},
{
...diskIOReadWrite.get({ dataView: metricsDataView }),
visualOptions: { ...commonVisualOptions, ...legend },
},
{
...rxTx.get({ dataView: metricsDataView }),
visualOptions: { ...commonVisualOptions, ...legend },
},
],
});
},
};

View file

@ -0,0 +1,82 @@
/*
* 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 { DataView } from '@kbn/data-views-plugin/common';
import type { XYVisualOptions } from '@kbn/lens-embeddable-utils';
import { createDashboardModel } from '../../../create_dashboard_model';
import {
createBasicCharts,
diskSpaceUsageAvailable,
diskUsageByMountPoint,
diskIOReadWrite,
diskThroughputReadWrite,
rxTx,
} from '../charts';
export const assetDetailsFlyout = {
get: ({
metricsDataView,
logsDataView,
}: {
metricsDataView?: DataView;
logsDataView?: DataView;
}) => {
const commonVisualOptions: XYVisualOptions = {
showDottedLine: true,
missingValues: 'Linear',
};
const legend: XYVisualOptions = {
legend: {
isVisible: true,
position: 'bottom',
},
};
const { cpuUsage, memoryUsage, normalizedLoad1m } = createBasicCharts({
visualizationType: 'lnsXY',
formulaIds: ['cpuUsage', 'memoryUsage', 'normalizedLoad1m'],
dataView: metricsDataView,
visualOptions: commonVisualOptions,
});
const { logRate } = createBasicCharts({
visualizationType: 'lnsXY',
formulaIds: ['logRate'],
dataView: logsDataView,
visualOptions: commonVisualOptions,
});
return createDashboardModel({
charts: [
cpuUsage,
memoryUsage,
normalizedLoad1m,
logRate,
{
...diskSpaceUsageAvailable.get({ dataView: metricsDataView }),
visualOptions: { ...commonVisualOptions, ...legend },
},
{
...diskUsageByMountPoint.get({ dataView: metricsDataView }),
visualOptions: { ...commonVisualOptions, ...legend },
},
{
...diskThroughputReadWrite.get({ dataView: metricsDataView }),
visualOptions: { ...commonVisualOptions, ...legend },
},
{
...diskIOReadWrite.get({ dataView: metricsDataView }),
visualOptions: { ...commonVisualOptions, ...legend },
},
{
...rxTx.get({ dataView: metricsDataView }),
visualOptions: { ...commonVisualOptions, ...legend },
},
],
});
},
};

View file

@ -0,0 +1,114 @@
/*
* 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 { DataView } from '@kbn/data-views-plugin/common';
import { i18n } from '@kbn/i18n';
import type { XYVisualOptions } from '@kbn/lens-embeddable-utils';
import { createDashboardModel } from '../../../create_dashboard_model';
import { formulas } from '../../../kubernetes/node/metrics';
export const assetDetailsKubernetesNode = {
get: ({ metricsDataView }: { metricsDataView?: DataView }) => {
const commonVisualOptions: XYVisualOptions = {
showDottedLine: true,
missingValues: 'Linear',
legend: {
isVisible: true,
position: 'bottom',
},
};
return createDashboardModel({
dependsOn: ['kubernetes.node'],
charts: [
{
id: 'nodeCpuCapacity',
title: i18n.translate(
'xpack.metricsData.assetDetails.metricsCharts.kubernetes.nodeCpuCapacity',
{
defaultMessage: 'Node CPU Capacity',
}
),
layers: [
{
data: [formulas.nodeCpuCapacity, formulas.nodeCpuUsed],
options: {
seriesType: 'area',
},
layerType: 'data',
},
],
dataView: metricsDataView,
visualizationType: 'lnsXY',
visualOptions: commonVisualOptions,
},
{
id: 'nodeMemoryCapacity',
title: i18n.translate(
'xpack.metricsData.assetDetails.metricsCharts.kubernetes.nodeMemoryCapacity',
{
defaultMessage: 'Node Memory Capacity',
}
),
layers: [
{
data: [formulas.nodeMemoryCapacity, formulas.nodeMemoryUsed],
options: {
seriesType: 'area',
},
layerType: 'data',
},
],
visualizationType: 'lnsXY',
dataView: metricsDataView,
visualOptions: commonVisualOptions,
},
{
id: 'nodeDiskCapacity',
title: i18n.translate(
'xpack.metricsData.assetDetails.metricsCharts.kubernetes.nodeDiskCapacity',
{
defaultMessage: 'Node Disk Capacity',
}
),
layers: [
{
data: [formulas.nodeDiskCapacity, formulas.nodeDiskUsed],
options: {
seriesType: 'area',
},
layerType: 'data',
},
],
visualizationType: 'lnsXY',
dataView: metricsDataView,
visualOptions: commonVisualOptions,
},
{
id: 'nodePodCapacity',
title: i18n.translate(
'xpack.metricsData.assetDetails.metricsCharts.kubernetes.nodePodCapacity',
{
defaultMessage: 'Node Pod Capacity',
}
),
layers: [
{
data: [formulas.nodePodCapacity, formulas.nodePodUsed],
options: {
seriesType: 'area',
},
layerType: 'data',
},
],
visualizationType: 'lnsXY',
dataView: metricsDataView,
visualOptions: commonVisualOptions,
},
],
});
},
};

View file

@ -0,0 +1,94 @@
/*
* 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 { DataView } from '@kbn/data-views-plugin/common';
import { XYChartModel, XYLayerOptions } from '@kbn/lens-embeddable-utils';
import { createDashboardModel } from '../../../create_dashboard_model';
import { createBasicCharts } from '../charts';
export const hostsView = {
get: ({ metricsDataView }: { metricsDataView?: DataView }) => {
const commonVisualOptions: XYChartModel['visualOptions'] = {
showDottedLine: true,
missingValues: 'Linear',
};
const layerOptions: XYLayerOptions = {
breakdown: {
type: 'top_values',
field: 'host.name',
params: {
size: 20,
},
},
};
const {
memoryUsage,
memoryFree,
diskUsage,
diskSpaceAvailable,
diskIORead,
diskIOWrite,
diskReadThroughput,
diskWriteThroughput,
rx,
tx,
} = createBasicCharts({
visualizationType: 'lnsXY',
formulaIds: [
'cpuUsage',
'memoryUsage',
'normalizedLoad1m',
'memoryFree',
'diskUsage',
'diskSpaceAvailable',
'diskIORead',
'diskIOWrite',
'diskReadThroughput',
'diskWriteThroughput',
'rx',
'tx',
],
dataView: metricsDataView,
layerOptions,
visualOptions: commonVisualOptions,
});
const { cpuUsage, normalizedLoad1m } = createBasicCharts({
visualizationType: 'lnsXY',
formulaIds: ['cpuUsage', 'normalizedLoad1m'],
layerOptions,
visualOptions: {
...commonVisualOptions,
yLeftExtent: {
mode: 'dataBounds',
lowerBound: 0,
upperBound: 1,
},
},
dataView: metricsDataView,
});
return createDashboardModel({
charts: [
cpuUsage,
normalizedLoad1m,
memoryUsage,
memoryFree,
diskUsage,
diskSpaceAvailable,
diskIORead,
diskIOWrite,
diskReadThroughput,
diskWriteThroughput,
rx,
tx,
],
});
},
};

View file

@ -0,0 +1,22 @@
/*
* 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 { assetDetails } from './asset_details';
import { assetDetailsFlyout } from './asset_details_flyout';
import { hostsView } from './hosts_view';
import { kpi } from './kpi';
import { assetDetailsKubernetesNode } from './asset_details_kubernetes_node';
export const dashboards = {
assetDetails,
assetDetailsFlyout,
hostsView,
kpi,
assetDetailsKubernetesNode,
};
export type HostDashboards = typeof dashboards;

View file

@ -0,0 +1,110 @@
/*
* 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 { DataView } from '@kbn/data-views-plugin/common';
import { i18n } from '@kbn/i18n';
import type { MetricLayerOptions } from '@kbn/lens-embeddable-utils';
import { createDashboardModel } from '../../../create_dashboard_model';
import { createBasicCharts } from '../charts';
const AVERAGE = i18n.translate('xpack.metricsData.assetDetails.overview.kpi.subtitle.average', {
defaultMessage: 'Average',
});
export const kpi = {
get: ({
metricsDataView,
options,
}: {
metricsDataView?: DataView;
options?: MetricLayerOptions;
}) => {
const { cpuUsage, diskUsage, memoryUsage, normalizedLoad1m } = createBasicCharts({
visualizationType: 'lnsMetric',
formulaIds: ['cpuUsage', 'diskUsage', 'memoryUsage', 'normalizedLoad1m'],
layerOptions: {
showTrendLine: true,
subtitle: AVERAGE,
...options,
},
dataView: metricsDataView,
});
return createDashboardModel({
charts: [
{
...cpuUsage,
layers: {
...cpuUsage.layers,
data: {
...cpuUsage.layers.data,
format: cpuUsage.layers.data.format
? {
...cpuUsage.layers.data.format,
params: {
decimals: 1,
},
}
: undefined,
},
},
},
{
...normalizedLoad1m,
layers: {
...normalizedLoad1m.layers,
data: {
...normalizedLoad1m.layers.data,
format: normalizedLoad1m.layers.data.format
? {
...normalizedLoad1m.layers.data.format,
params: {
decimals: 1,
},
}
: undefined,
},
},
},
{
...memoryUsage,
layers: {
...memoryUsage.layers,
data: {
...memoryUsage.layers.data,
format: memoryUsage.layers.data.format
? {
...memoryUsage.layers.data.format,
params: {
decimals: 1,
},
}
: undefined,
},
},
},
{
...diskUsage,
layers: {
...diskUsage.layers,
data: {
...diskUsage.layers.data,
format: diskUsage.layers.data.format
? {
...diskUsage.layers.data.format,
params: {
decimals: 1,
},
}
: undefined,
},
},
},
],
});
},
};

View file

@ -9,7 +9,7 @@ import { i18n } from '@kbn/i18n';
import type { FormulaValueConfig } from '@kbn/lens-embeddable-utils';
export const cpuUsage: FormulaValueConfig = {
label: i18n.translate('xpack.infra.assetDetails.formulas.cpuUsage', {
label: i18n.translate('xpack.metricsData.assetDetails.formulas.cpuUsage', {
defaultMessage: 'CPU Usage',
}),
value: '(average(system.cpu.user.pct) + average(system.cpu.system.pct)) / max(system.cpu.cores)',

View file

@ -9,7 +9,7 @@ import { i18n } from '@kbn/i18n';
import type { FormulaValueConfig } from '@kbn/lens-embeddable-utils';
export const cpuUsageIowait: FormulaValueConfig = {
label: i18n.translate('xpack.infra.assetDetails.formulas.cpuUsage.iowaitLabel', {
label: i18n.translate('xpack.metricsData.assetDetails.formulas.cpuUsage.iowaitLabel', {
defaultMessage: 'iowait',
}),
value: 'average(system.cpu.iowait.pct) / max(system.cpu.cores)',

View file

@ -9,7 +9,7 @@ import { i18n } from '@kbn/i18n';
import type { FormulaValueConfig } from '@kbn/lens-embeddable-utils';
export const cpuUsageIrq: FormulaValueConfig = {
label: i18n.translate('xpack.infra.assetDetails.formulas.cpuUsage.irqLabel', {
label: i18n.translate('xpack.metricsData.assetDetails.formulas.cpuUsage.irqLabel', {
defaultMessage: 'irq',
}),
value: 'average(system.cpu.irq.pct) / max(system.cpu.cores)',

View file

@ -9,7 +9,7 @@ import { i18n } from '@kbn/i18n';
import type { FormulaValueConfig } from '@kbn/lens-embeddable-utils';
export const cpuUsageNice: FormulaValueConfig = {
label: i18n.translate('xpack.infra.assetDetails.formulas.cpuUsage.niceLabel', {
label: i18n.translate('xpack.metricsData.assetDetails.formulas.cpuUsage.niceLabel', {
defaultMessage: 'nice',
}),
value: 'average(system.cpu.nice.norm.pct) / max(system.cpu.cores)',

View file

@ -9,7 +9,7 @@ import { i18n } from '@kbn/i18n';
import type { FormulaValueConfig } from '@kbn/lens-embeddable-utils';
export const cpuUsageSoftirq: FormulaValueConfig = {
label: i18n.translate('xpack.infra.assetDetails.formulas.cpuUsage.softirqLabel', {
label: i18n.translate('xpack.metricsData.assetDetails.formulas.cpuUsage.softirqLabel', {
defaultMessage: 'softirq',
}),
value: 'average(system.cpu.softirq.pct) / max(system.cpu.cores)',

View file

@ -9,7 +9,7 @@ import { i18n } from '@kbn/i18n';
import type { FormulaValueConfig } from '@kbn/lens-embeddable-utils';
export const cpuUsageSteal: FormulaValueConfig = {
label: i18n.translate('xpack.infra.assetDetails.formulas.cpuUsage.stealLabel', {
label: i18n.translate('xpack.metricsData.assetDetails.formulas.cpuUsage.stealLabel', {
defaultMessage: 'steal',
}),
value: 'average(system.cpu.steal.pct) / max(system.cpu.cores)',

View file

@ -9,7 +9,7 @@ import { i18n } from '@kbn/i18n';
import type { FormulaValueConfig } from '@kbn/lens-embeddable-utils';
export const cpuUsageSystem: FormulaValueConfig = {
label: i18n.translate('xpack.infra.assetDetails.formulas.cpuUsage.systemLabel', {
label: i18n.translate('xpack.metricsData.assetDetails.formulas.cpuUsage.systemLabel', {
defaultMessage: 'system',
}),
value: 'average(system.cpu.system.pct) / max(system.cpu.cores)',

View file

@ -9,7 +9,7 @@ import { i18n } from '@kbn/i18n';
import type { FormulaValueConfig } from '@kbn/lens-embeddable-utils';
export const cpuUsageUser: FormulaValueConfig = {
label: i18n.translate('xpack.infra.assetDetails.formulas.cpuUsage.userLabel', {
label: i18n.translate('xpack.metricsData.assetDetails.formulas.cpuUsage.userLabel', {
defaultMessage: 'user',
}),
value: 'average(system.cpu.user.pct) / max(system.cpu.cores)',

View file

@ -9,7 +9,7 @@ import { i18n } from '@kbn/i18n';
import type { FormulaValueConfig } from '@kbn/lens-embeddable-utils';
export const diskIORead: FormulaValueConfig = {
label: i18n.translate('xpack.infra.assetDetails.formulas.diskIORead', {
label: i18n.translate('xpack.metricsData.assetDetails.formulas.diskIORead', {
defaultMessage: 'Disk Read IOPS',
}),
value: "counter_rate(max(system.diskio.read.count), kql='system.diskio.read.count: *')",

View file

@ -9,7 +9,7 @@ import { i18n } from '@kbn/i18n';
import type { FormulaValueConfig } from '@kbn/lens-embeddable-utils';
export const diskReadThroughput: FormulaValueConfig = {
label: i18n.translate('xpack.infra.assetDetails.formulas.diskReadThroughput', {
label: i18n.translate('xpack.metricsData.assetDetails.formulas.diskReadThroughput', {
defaultMessage: 'Disk Read Throughput',
}),
value: "counter_rate(max(system.diskio.read.bytes), kql='system.diskio.read.bytes: *')",

View file

@ -9,7 +9,7 @@ import { i18n } from '@kbn/i18n';
import type { FormulaValueConfig } from '@kbn/lens-embeddable-utils';
export const diskSpaceAvailability: FormulaValueConfig = {
label: i18n.translate('xpack.infra.assetDetails.formulas.diskSpaceAvailability', {
label: i18n.translate('xpack.metricsData.assetDetails.formulas.diskSpaceAvailability', {
defaultMessage: 'Disk Space Availability',
}),
value: '1 - average(system.filesystem.used.pct)',

View file

@ -9,7 +9,7 @@ import { i18n } from '@kbn/i18n';
import type { FormulaValueConfig } from '@kbn/lens-embeddable-utils';
export const diskSpaceAvailable: FormulaValueConfig = {
label: i18n.translate('xpack.infra.assetDetails.formulas.diskSpaceAvailable', {
label: i18n.translate('xpack.metricsData.assetDetails.formulas.diskSpaceAvailable', {
defaultMessage: 'Disk Space Available',
}),
value: 'average(system.filesystem.free)',

View file

@ -9,7 +9,7 @@ import { i18n } from '@kbn/i18n';
import type { FormulaValueConfig } from '@kbn/lens-embeddable-utils';
export const diskUsage: FormulaValueConfig = {
label: i18n.translate('xpack.infra.assetDetails.formulas.diskUsage', {
label: i18n.translate('xpack.metricsData.assetDetails.formulas.diskUsage', {
defaultMessage: 'Disk Usage',
}),
value: 'average(system.filesystem.used.pct)',

View file

@ -9,7 +9,7 @@ import { i18n } from '@kbn/i18n';
import type { FormulaValueConfig } from '@kbn/lens-embeddable-utils';
export const diskIOWrite: FormulaValueConfig = {
label: i18n.translate('xpack.infra.assetDetails.formulas.diskIOWrite', {
label: i18n.translate('xpack.metricsData.assetDetails.formulas.diskIOWrite', {
defaultMessage: 'Disk Write IOPS',
}),
value: "counter_rate(max(system.diskio.write.count), kql='system.diskio.write.count: *')",

View file

@ -9,7 +9,7 @@ import { i18n } from '@kbn/i18n';
import type { FormulaValueConfig } from '@kbn/lens-embeddable-utils';
export const diskWriteThroughput: FormulaValueConfig = {
label: i18n.translate('xpack.infra.assetDetails.formulas.diskWriteThroughput', {
label: i18n.translate('xpack.metricsData.assetDetails.formulas.diskWriteThroughput', {
defaultMessage: 'Disk Write Throughput',
}),
value: "counter_rate(max(system.diskio.write.bytes), kql='system.diskio.write.bytes: *')",

View file

@ -9,7 +9,7 @@ import { i18n } from '@kbn/i18n';
import type { FormulaValueConfig } from '@kbn/lens-embeddable-utils';
export const hostCount: FormulaValueConfig = {
label: i18n.translate('xpack.infra.assetDetails.formulas.hostCount.hostsLabel', {
label: i18n.translate('xpack.metricsData.assetDetails.formulas.hostCount.hostsLabel', {
defaultMessage: 'Hosts',
}),
value: 'unique_count(host.name)',

View file

@ -34,7 +34,7 @@ import { memoryCache } from './memory_cache';
import { rx } from './rx';
import { tx } from './tx';
export const hostLensFormulas = {
export const formulas = {
cpuUsage,
cpuUsageIowait,
cpuUsageIrq,
@ -64,3 +64,6 @@ export const hostLensFormulas = {
rx,
tx,
};
export type HostFormulas = typeof formulas;
export type HostFormulaNames = keyof HostFormulas;

View file

@ -9,7 +9,7 @@ import { i18n } from '@kbn/i18n';
import type { FormulaValueConfig } from '@kbn/lens-embeddable-utils';
export const load15m: FormulaValueConfig = {
label: i18n.translate('xpack.infra.assetDetails.formulas.load15m', {
label: i18n.translate('xpack.metricsData.assetDetails.formulas.load15m', {
defaultMessage: 'Load (15m)',
}),
value: 'average(system.load.15)',

View file

@ -9,7 +9,7 @@ import { i18n } from '@kbn/i18n';
import type { FormulaValueConfig } from '@kbn/lens-embeddable-utils';
export const load1m: FormulaValueConfig = {
label: i18n.translate('xpack.infra.assetDetails.formulas.load1m', {
label: i18n.translate('xpack.metricsData.assetDetails.formulas.load1m', {
defaultMessage: 'Load (1m)',
}),
value: 'average(system.load.1)',

View file

@ -9,7 +9,7 @@ import { i18n } from '@kbn/i18n';
import type { FormulaValueConfig } from '@kbn/lens-embeddable-utils';
export const load5m: FormulaValueConfig = {
label: i18n.translate('xpack.infra.assetDetails.formulas.load5m', {
label: i18n.translate('xpack.metricsData.assetDetails.formulas.load5m', {
defaultMessage: 'Load (5m)',
}),
value: 'average(system.load.5)',

View file

@ -9,7 +9,7 @@ import { i18n } from '@kbn/i18n';
import type { FormulaValueConfig } from '@kbn/lens-embeddable-utils';
export const logRate: FormulaValueConfig = {
label: i18n.translate('xpack.infra.assetDetails.formulas.logRate', {
label: i18n.translate('xpack.metricsData.assetDetails.formulas.logRate', {
defaultMessage: 'Log Rate',
}),
value: 'differences(cumulative_sum(count()))',

View file

@ -9,7 +9,7 @@ import { i18n } from '@kbn/i18n';
import type { FormulaValueConfig } from '@kbn/lens-embeddable-utils';
export const memoryCache: FormulaValueConfig = {
label: i18n.translate('xpack.infra.assetDetails.formulas.metric.label.cache', {
label: i18n.translate('xpack.metricsData.assetDetails.formulas.metric.label.cache', {
defaultMessage: 'cache',
}),
value: 'average(system.memory.used.bytes) - average(system.memory.actual.used.bytes)',

View file

@ -9,7 +9,7 @@ import { i18n } from '@kbn/i18n';
import type { FormulaValueConfig } from '@kbn/lens-embeddable-utils';
export const memoryFree: FormulaValueConfig = {
label: i18n.translate('xpack.infra.assetDetails.formulas.memoryFree', {
label: i18n.translate('xpack.metricsData.assetDetails.formulas.memoryFree', {
defaultMessage: 'Memory Free',
}),
value: 'max(system.memory.total) - average(system.memory.actual.used.bytes)',

View file

@ -9,7 +9,7 @@ import { i18n } from '@kbn/i18n';
import type { FormulaValueConfig } from '@kbn/lens-embeddable-utils';
export const memoryFreeExcludingCache: FormulaValueConfig = {
label: i18n.translate('xpack.infra.assetDetails.formulas.metric.label.free', {
label: i18n.translate('xpack.metricsData.assetDetails.formulas.metric.label.free', {
defaultMessage: 'free',
}),
value: 'average(system.memory.free)',

View file

@ -9,7 +9,7 @@ import { i18n } from '@kbn/i18n';
import type { FormulaValueConfig } from '@kbn/lens-embeddable-utils';
export const memoryUsage: FormulaValueConfig = {
label: i18n.translate('xpack.infra.assetDetails.formulas.memoryUsage', {
label: i18n.translate('xpack.metricsData.assetDetails.formulas.memoryUsage', {
defaultMessage: 'Memory Usage',
}),
value: 'average(system.memory.actual.used.pct)',

View file

@ -9,7 +9,7 @@ import { i18n } from '@kbn/i18n';
import type { FormulaValueConfig } from '@kbn/lens-embeddable-utils';
export const memoryUsed: FormulaValueConfig = {
label: i18n.translate('xpack.infra.assetDetails.formulas.metric.label.used', {
label: i18n.translate('xpack.metricsData.assetDetails.formulas.metric.label.used', {
defaultMessage: 'used',
}),
value: 'average(system.memory.actual.used.bytes)',

View file

@ -9,7 +9,7 @@ import { i18n } from '@kbn/i18n';
import type { FormulaValueConfig } from '@kbn/lens-embeddable-utils';
export const normalizedLoad1m: FormulaValueConfig = {
label: i18n.translate('xpack.infra.assetDetails.formulas.normalizedLoad1m', {
label: i18n.translate('xpack.metricsData.assetDetails.formulas.normalizedLoad1m', {
defaultMessage: 'Normalized Load',
}),
value: 'average(system.load.1) / max(system.load.cores)',

View file

@ -9,7 +9,7 @@ import { i18n } from '@kbn/i18n';
import type { FormulaValueConfig } from '@kbn/lens-embeddable-utils';
export const rx: FormulaValueConfig = {
label: i18n.translate('xpack.infra.assetDetails.formulas.rx', {
label: i18n.translate('xpack.metricsData.assetDetails.formulas.rx', {
defaultMessage: 'Network Inbound (RX)',
}),
value:

View file

@ -9,7 +9,7 @@ import { i18n } from '@kbn/i18n';
import type { FormulaValueConfig } from '@kbn/lens-embeddable-utils';
export const tx: FormulaValueConfig = {
label: i18n.translate('xpack.infra.assetDetails.formulas.tx', {
label: i18n.translate('xpack.metricsData.assetDetails.formulas.tx', {
defaultMessage: 'Network Outbound (TX)',
}),
value:

View file

@ -4,79 +4,25 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { snapshot } from './snapshot';
import { tsvb } from './tsvb';
import { InventoryMetricsWithDashboards } from '../../types';
import { type HostFormulas } from './formulas';
import { type HostDashboards } from './dashboards';
import { cpu } from './snapshot/cpu';
import { diskLatency } from './snapshot/disk_latency';
import { diskSpaceUsage } from './snapshot/disk_space_usage';
import { count } from '../../shared/metrics/snapshot/count';
import { load } from './snapshot/load';
import { logRate } from './snapshot/log_rate';
import { memory } from './snapshot/memory';
import { memoryFree } from './snapshot/memory_free';
import { memoryTotal } from './snapshot/memory_total';
import { normalizedLoad1m } from './snapshot/normalized_load_1m';
import { rx } from './snapshot/rx';
import { tx } from './snapshot/tx';
import { hostSystemOverview } from './tsvb/host_system_overview';
import { hostCpuUsage } from './tsvb/host_cpu_usage';
import { hostLoad } from './tsvb/host_load';
import { hostMemoryUsage } from './tsvb/host_memory_usage';
import { hostNetworkTraffic } from './tsvb/host_network_traffic';
import { hostFilesystem } from './tsvb/host_filesystem';
import { hostK8sOverview } from './tsvb/host_k8s_overview';
import { hostK8sCpuCap } from './tsvb/host_k8s_cpu_cap';
import { hostK8sPodCap } from './tsvb/host_k8s_pod_cap';
import { hostK8sDiskCap } from './tsvb/host_k8s_disk_cap';
import { hostK8sMemoryCap } from './tsvb/host_k8s_memory_cap';
import { hostDockerTop5ByMemory } from './tsvb/host_docker_top_5_by_memory';
import { hostDockerTop5ByCpu } from './tsvb/host_docker_top_5_by_cpu';
import { hostDockerOverview } from './tsvb/host_docker_overview';
import { hostDockerInfo } from './tsvb/host_docker_info';
import { InventoryMetrics } from '../../types';
const exposedHostSnapshotMetrics = {
cpu,
diskLatency,
diskSpaceUsage,
load,
logRate,
memory,
memoryFree,
memoryTotal,
normalizedLoad1m,
rx,
tx,
};
// not sure why this is the only model with "count"
const hostSnapshotMetrics = { count, ...exposedHostSnapshotMetrics };
const { count, ...exposedHostSnapshotMetrics } = snapshot;
export const hostSnapshotMetricTypes = Object.keys(exposedHostSnapshotMetrics) as Array<
keyof typeof exposedHostSnapshotMetrics
>;
export const metrics: InventoryMetrics = {
tsvb: {
hostSystemOverview,
hostCpuUsage,
hostLoad,
hostMemoryUsage,
hostNetworkTraffic,
hostFilesystem,
hostK8sOverview,
hostK8sCpuCap,
hostK8sPodCap,
hostK8sDiskCap,
hostK8sMemoryCap,
hostDockerOverview,
hostDockerInfo,
hostDockerTop5ByMemory,
hostDockerTop5ByCpu,
},
snapshot: hostSnapshotMetrics,
export const metrics: InventoryMetricsWithDashboards<HostFormulas, HostDashboards> = {
tsvb,
snapshot,
getFormulas: async () => await import('./formulas').then(({ formulas }) => ({ ...formulas })),
getDashboards: async () =>
await import('./dashboards').then(({ dashboards }) => ({ ...dashboards })),
defaultSnapshot: 'cpu',
defaultTimeRangeInSeconds: 3600, // 1 hour
};

View file

@ -0,0 +1,34 @@
/*
* 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 { cpu } from './cpu';
import { diskLatency } from './disk_latency';
import { diskSpaceUsage } from './disk_space_usage';
import { count } from '../../../shared/metrics/snapshot/count';
import { load } from './load';
import { logRate } from './log_rate';
import { memory } from './memory';
import { memoryFree } from './memory_free';
import { memoryTotal } from './memory_total';
import { normalizedLoad1m } from './normalized_load_1m';
import { rx } from './rx';
import { tx } from './tx';
export const snapshot = {
cpu,
diskLatency,
diskSpaceUsage,
count,
load,
logRate,
memory,
memoryFree,
memoryTotal,
normalizedLoad1m,
rx,
tx,
};

View file

@ -0,0 +1,42 @@
/*
* 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 { hostSystemOverview } from './host_system_overview';
import { hostCpuUsage } from './host_cpu_usage';
import { hostLoad } from './host_load';
import { hostMemoryUsage } from './host_memory_usage';
import { hostNetworkTraffic } from './host_network_traffic';
import { hostFilesystem } from './host_filesystem';
import { hostK8sOverview } from './host_k8s_overview';
import { hostK8sCpuCap } from './host_k8s_cpu_cap';
import { hostK8sPodCap } from './host_k8s_pod_cap';
import { hostK8sDiskCap } from './host_k8s_disk_cap';
import { hostK8sMemoryCap } from './host_k8s_memory_cap';
import { hostDockerTop5ByMemory } from './host_docker_top_5_by_memory';
import { hostDockerTop5ByCpu } from './host_docker_top_5_by_cpu';
import { hostDockerOverview } from './host_docker_overview';
import { hostDockerInfo } from './host_docker_info';
export const tsvb = {
hostSystemOverview,
hostCpuUsage,
hostLoad,
hostMemoryUsage,
hostNetworkTraffic,
hostFilesystem,
hostK8sOverview,
hostK8sCpuCap,
hostK8sPodCap,
hostK8sDiskCap,
hostK8sMemoryCap,
hostDockerOverview,
hostDockerInfo,
hostDockerTop5ByMemory,
hostDockerTop5ByCpu,
};

View file

@ -8,7 +8,7 @@
import { i18n } from '@kbn/i18n';
import { POD_FIELD, HOST_FIELD, CONTAINER_FIELD } from '../constants';
import { host } from './host';
import { pod } from './pod';
import { pod } from './kubernetes/pod';
import { awsEC2 } from './aws_ec2';
import { awsS3 } from './aws_s3';
import { awsRDS } from './aws_rds';
@ -17,9 +17,21 @@ import { container } from './container';
import { InventoryItemType } from './types';
export { metrics } from './metrics';
export const inventoryModels = [host, pod, container, awsEC2, awsS3, awsRDS, awsSQS];
const catalog = {
host,
pod,
container,
awsEC2,
awsS3,
awsRDS,
awsSQS,
} as const;
export const findInventoryModel = (type: InventoryItemType) => {
export const inventoryModels = Object.values(catalog);
type InventoryModels<T extends InventoryItemType> = typeof catalog[T];
export const findInventoryModel = <T extends InventoryItemType>(type: T): InventoryModels<T> => {
const model = inventoryModels.find((m) => m.id === type);
if (!model) {
throw new Error(
@ -28,7 +40,8 @@ export const findInventoryModel = (type: InventoryItemType) => {
})
);
}
return model;
return model as InventoryModels<T>;
};
const LEGACY_TYPES = ['host', 'pod', 'container'];

View file

@ -14,7 +14,7 @@ import { nodeMemoryUsed } from './node_memory_used';
import { nodePodCapacity } from './node_pod_capacity';
import { nodePodUsed } from './node_pod_used';
export const kubernetesLensFormulas = {
export const formulas = {
nodeCpuCapacity,
nodeCpuUsed,
nodeDiskCapacity,

View file

@ -6,10 +6,10 @@
*/
import { i18n } from '@kbn/i18n';
import { FormulaValueConfig } from '@kbn/lens-embeddable-utils';
import type { FormulaValueConfig } from '@kbn/lens-embeddable-utils';
export const nodeCpuCapacity: FormulaValueConfig = {
label: i18n.translate('xpack.infra.assetDetails.formulas.kubernetes.capacity', {
label: i18n.translate('xpack.metricsData.assetDetails.formulas.kubernetes.capacity', {
defaultMessage: 'Capacity',
}),
value: 'max(kubernetes.node.cpu.allocatable.cores) * 1000000000',

View file

@ -6,10 +6,10 @@
*/
import { i18n } from '@kbn/i18n';
import { FormulaValueConfig } from '@kbn/lens-embeddable-utils';
import type { FormulaValueConfig } from '@kbn/lens-embeddable-utils';
export const nodeCpuUsed: FormulaValueConfig = {
label: i18n.translate('xpack.infra.assetDetails.formulas.kubernetes.used', {
label: i18n.translate('xpack.metricsData.assetDetails.formulas.kubernetes.used', {
defaultMessage: 'Used',
}),
value: 'average(kubernetes.node.cpu.usage.nanocores)',

View file

@ -6,10 +6,10 @@
*/
import { i18n } from '@kbn/i18n';
import { FormulaValueConfig } from '@kbn/lens-embeddable-utils';
import type { FormulaValueConfig } from '@kbn/lens-embeddable-utils';
export const nodeDiskCapacity: FormulaValueConfig = {
label: i18n.translate('xpack.infra.assetDetails.formulas.kubernetes.capacity', {
label: i18n.translate('xpack.metricsData.assetDetails.formulas.kubernetes.capacity', {
defaultMessage: 'Capacity',
}),
value: 'max(kubernetes.node.fs.capacity.bytes)',

View file

@ -6,10 +6,10 @@
*/
import { i18n } from '@kbn/i18n';
import { FormulaValueConfig } from '@kbn/lens-embeddable-utils';
import type { FormulaValueConfig } from '@kbn/lens-embeddable-utils';
export const nodeDiskUsed: FormulaValueConfig = {
label: i18n.translate('xpack.infra.assetDetails.formulas.kubernetes.used', {
label: i18n.translate('xpack.metricsData.assetDetails.formulas.kubernetes.used', {
defaultMessage: 'Used',
}),
value: 'average(kubernetes.node.fs.used.bytes)',

View file

@ -6,10 +6,10 @@
*/
import { i18n } from '@kbn/i18n';
import { FormulaValueConfig } from '@kbn/lens-embeddable-utils';
import type { FormulaValueConfig } from '@kbn/lens-embeddable-utils';
export const nodeMemoryCapacity: FormulaValueConfig = {
label: i18n.translate('xpack.infra.assetDetails.formulas.kubernetes.capacity', {
label: i18n.translate('xpack.metricsData.assetDetails.formulas.kubernetes.capacity', {
defaultMessage: 'Capacity',
}),
value: 'max(kubernetes.node.memory.allocatable.bytes)',

Some files were not shown because too many files have changed in this diff Show more