Skip to content

Commit 4baeafe

Browse files
[Infrastructure UI] Lens Embeddable attributes builder refactor (#161281)
relates to [#160381](#160381) closes [#161432](#161432) ## Summary This pull request aims to enhance the usage of Lens Embeddable by introducing abstractions that simplify the creation of the necessary data structures for rendering charts. The goal is to improve the DX by providing clearer and more intuitive interfaces. More details in the [README.md](https://github.com/elastic/kibana/blob/62a9ef70e6bbbb6798bd78083dac097d84b85ec5/x-pack/plugins/infra/public/common/visualizations/lens/README.md) ### For reviewers - The majority of the changes are concentrated in the `common/visualizations` directory. The `formulas/host` files have been modified to only contain the formula itself. The formulas are now designed to be independent of specific chart styles. - The `use_lens_attributes` hook has been modified to receive the essential information. Previously, it had knowledge of host formulas, but now it accepts an abstracted chart representation and returns the JSON object accordingly. - Chart-specific style configurations have been moved to the chart usage component in the `tile` and `metric_chart` components. ### How to test - Start a local Kibana instance - Navigate to `Infrastructure` > `Hosts` - Check all charts and navigate to Lens. --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
1 parent 9f2a75b commit 4baeafe

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+1731
-855
lines changed

x-pack/plugins/infra/public/common/visualizations/constants.ts

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ import {
2020
tx,
2121
hostCount,
2222
} from './lens/formulas/host';
23-
import { LineChart, MetricChart } from './lens/visualization_types';
2423

2524
export const hostLensFormulas = {
2625
cpuUsage,
@@ -38,9 +37,4 @@ export const hostLensFormulas = {
3837
tx,
3938
};
4039

41-
export const visualizationTypes = {
42-
lineChart: LineChart,
43-
metricChart: MetricChart,
44-
};
45-
4640
export const HOST_METRICS_DOC_HREF = 'https://ela.st/docs-infra-host-metrics';

x-pack/plugins/infra/public/common/visualizations/index.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,16 @@
77

88
export type {
99
HostsLensFormulas,
10-
LineChartOptions,
11-
LensChartConfig,
12-
LensLineChartConfig,
13-
MetricChartOptions,
1410
HostsLensMetricChartFormulas,
1511
HostsLensLineChartFormulas,
16-
LensOptions,
1712
LensAttributes,
13+
FormulaConfig,
14+
Chart,
15+
LensVisualizationState,
1816
} from './types';
1917

20-
export { hostLensFormulas, visualizationTypes } from './constants';
18+
export { hostLensFormulas } from './constants';
19+
20+
export * from './lens/visualization_types';
2121

2222
export { LensAttributesBuilder } from './lens/lens_attributes_builder';
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
2+
# Lens Attributes Builder
3+
4+
The Lens Attributes Builder is a utility for creating JSON objects used to render charts with Lens. It simplifies the process of configuring and building the necessary attributes for different chart types.
5+
6+
## Usage
7+
8+
### Creating a Metric Chart
9+
10+
To create a metric chart, use the `MetricChart` class and provide the required configuration. Here's an example:
11+
12+
```ts
13+
const metricChart = new MetricChart({
14+
layers: new MetricLayer({
15+
data: {
16+
label: 'Disk Read Throughput',
17+
value: "counter_rate(max(system.diskio.read.count), kql='system.diskio.read.count: *')",
18+
format: {
19+
id: 'bytes',
20+
params: {
21+
decimals: 1,
22+
},
23+
},
24+
},
25+
formulaAPI,
26+
}),
27+
dataView,
28+
});
29+
```
30+
31+
### Creating an XY Chart
32+
33+
To create an XY chart, use the `XYChart` class and provide the required configuration. Here's an example:
34+
35+
```ts
36+
const xyChart = new XYChart({
37+
layers: [new XYDataLayer({
38+
data: [{
39+
label: 'Normalized Load',
40+
value: "average(system.load.1) / max(system.load.cores)",
41+
format: {
42+
id: 'percent',
43+
params: {
44+
decimals: 1,
45+
},
46+
},
47+
}],
48+
formulaAPI,
49+
})],
50+
dataView,
51+
});
52+
```
53+
54+
### Adding Multiple Layers to an XY Chart
55+
56+
An XY chart can have multiple layers. Here's an example of containing a Reference Line Layer:
57+
58+
```ts
59+
const xyChart = new XYChart({
60+
layers: [
61+
new XYDataLayer({
62+
data: [{
63+
label: 'Disk Read Throughput',
64+
value: "average(system.load.1) / max(system.load.cores)",
65+
format: {
66+
id: 'percent',
67+
params: {
68+
decimals: 1,
69+
},
70+
},
71+
}],
72+
formulaAPI,
73+
}),
74+
new XYReferenceLineLayer({
75+
data: [{
76+
value: "1",
77+
format: {
78+
id: 'percent',
79+
params: {
80+
decimals: 1,
81+
},
82+
},
83+
}],
84+
}),
85+
],
86+
dataView,
87+
});
88+
```
89+
90+
### Adding Multiple Data Sources in the Same Layer
91+
92+
In an XY chart, it's possible to define multiple data sources within the same layer.
93+
94+
To configure multiple data sources in an XY data layer, simply provide an array of data to the same YXDataLayer class:
95+
96+
```ts
97+
const xyChart = new XYChart({
98+
layers: new YXDataLayer({
99+
data: [{
100+
label: 'RX',
101+
value: "average(host.network.ingress.bytes) * 8 / (max(metricset.period, kql='host.network.ingress.bytes: *') / 1000)",
102+
format: {
103+
id: 'bits',
104+
params: {
105+
decimals: 1,
106+
},
107+
},
108+
},{
109+
label: 'TX',
110+
value: "(average(host.network.egresss.bytes) * 8 / (max(metricset.period, kql='host.network.egresss.bytes: *') / 1000)",
111+
format: {
112+
id: 'bits',
113+
params: {
114+
decimals: 1,
115+
},
116+
},
117+
}],
118+
formulaAPI,
119+
}),
120+
dataView,
121+
});
122+
```
123+
124+
### Building Lens Chart Attributes
125+
126+
The `LensAttributesBuilder` is responsible for creating the full JSON object that combines the attributes returned by the chart classes. Here's an example:
127+
128+
```ts
129+
const builder = new LensAttributesBuilder({ visualization: xyChart });
130+
const attributes = builder.build();
131+
```
132+
133+
The `attributes` object contains the final JSON representation of the chart configuration and can be used to render the chart with Lens.
134+
135+
### Usage with Lens EmbeddableComponent
136+
137+
To display the charts rendered with the Lens Attributes Builder, it's recommended to use the Lens `EmbeddableComponent`. The `EmbeddableComponent` abstracts some of the chart styling and other details that would be challenging to handle directly with the Lens Attributes Builder.
138+
139+
```tsx
140+
const builder = new LensAttributesBuilder({
141+
visualization: new MetricChart({
142+
layers: new MetricLayer({
143+
data: {
144+
label: 'Disk Read Throughput',
145+
value: "counter_rate(max(system.diskio.read.count), kql='system.diskio.read.count: *')",
146+
format: {
147+
id: 'bytes',
148+
params: {
149+
decimals: 1,
150+
},
151+
},
152+
},
153+
formulaAPI,
154+
}),
155+
dataView,
156+
})
157+
});
158+
159+
const lensAttributes = builder.build();
160+
161+
<EmbeddableComponent
162+
attributes={lensAttributes}
163+
viewMode={ViewMode.VIEW}
164+
...
165+
/>
166+
```
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0; you may not use this file except in compliance with the Elastic License
5+
* 2.0.
6+
*/
7+
8+
import { TypedLensByValueInput } from '@kbn/lens-plugin/public';
9+
import { i18n } from '@kbn/i18n';
10+
import { Layer } from '../../../../../hooks/use_lens_attributes';
11+
import { hostLensFormulas } from '../../../constants';
12+
import { FormulaConfig } from '../../../types';
13+
import { TOOLTIP } from './translations';
14+
import { MetricLayerOptions } from '../../visualization_types/layers';
15+
16+
export interface KPIChartProps
17+
extends Pick<TypedLensByValueInput, 'id' | 'title' | 'overrides' | 'style'> {
18+
layers: Layer<MetricLayerOptions, FormulaConfig, 'data'>;
19+
toolTip: string;
20+
}
21+
22+
export const KPI_CHARTS: KPIChartProps[] = [
23+
{
24+
id: 'cpuUsage',
25+
title: i18n.translate('xpack.infra.hostsViewPage.metricTrend.cpuUsage.title', {
26+
defaultMessage: 'CPU Usage',
27+
}),
28+
layers: {
29+
data: {
30+
...hostLensFormulas.cpuUsage,
31+
format: {
32+
...hostLensFormulas.cpuUsage.format,
33+
params: {
34+
decimals: 1,
35+
},
36+
},
37+
},
38+
layerType: 'data',
39+
options: {
40+
backgroundColor: '#F1D86F',
41+
showTrendLine: true,
42+
},
43+
},
44+
toolTip: TOOLTIP.cpuUsage,
45+
},
46+
{
47+
id: 'normalizedLoad1m',
48+
title: i18n.translate('xpack.infra.hostsViewPage.metricTrend.normalizedLoad1m.title', {
49+
defaultMessage: 'CPU Usage',
50+
}),
51+
layers: {
52+
data: {
53+
...hostLensFormulas.normalizedLoad1m,
54+
format: {
55+
...hostLensFormulas.normalizedLoad1m.format,
56+
params: {
57+
decimals: 1,
58+
},
59+
},
60+
},
61+
layerType: 'data',
62+
options: {
63+
backgroundColor: '#79AAD9',
64+
showTrendLine: true,
65+
},
66+
},
67+
toolTip: TOOLTIP.normalizedLoad1m,
68+
},
69+
{
70+
id: 'memoryUsage',
71+
title: i18n.translate('xpack.infra.hostsViewPage.metricTrend.memoryUsage.title', {
72+
defaultMessage: 'CPU Usage',
73+
}),
74+
layers: {
75+
data: {
76+
...hostLensFormulas.memoryUsage,
77+
format: {
78+
...hostLensFormulas.memoryUsage.format,
79+
params: {
80+
decimals: 1,
81+
},
82+
},
83+
},
84+
layerType: 'data',
85+
options: {
86+
backgroundColor: '#A987D1',
87+
showTrendLine: true,
88+
},
89+
},
90+
toolTip: TOOLTIP.memoryUsage,
91+
},
92+
{
93+
id: 'diskSpaceUsage',
94+
title: i18n.translate('xpack.infra.hostsViewPage.metricTrend.diskSpaceUsage.title', {
95+
defaultMessage: 'CPU Usage',
96+
}),
97+
layers: {
98+
data: {
99+
...hostLensFormulas.diskSpaceUsage,
100+
format: {
101+
...hostLensFormulas.diskSpaceUsage.format,
102+
params: {
103+
decimals: 1,
104+
},
105+
},
106+
},
107+
layerType: 'data',
108+
options: {
109+
backgroundColor: '#F5A35C',
110+
showTrendLine: true,
111+
},
112+
},
113+
toolTip: TOOLTIP.diskSpaceUsage,
114+
},
115+
];

x-pack/plugins/infra/public/common/visualizations/lens/translations.ts renamed to x-pack/plugins/infra/public/common/visualizations/lens/dashboards/host/translations.ts

File renamed without changes.

x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/cpu_usage.ts

Lines changed: 8 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,32 +5,15 @@
55
* 2.0.
66
*/
77

8-
import type { LensChartConfig, LensLineChartConfig } from '../../../types';
9-
import { getFilters } from './utils';
8+
import type { FormulaConfig } from '../../../types';
109

11-
export const cpuLineChart: LensLineChartConfig = {
12-
extraVisualizationState: {
13-
yLeftExtent: {
14-
mode: 'custom',
15-
lowerBound: 0,
16-
upperBound: 1,
10+
export const cpuUsage: FormulaConfig = {
11+
label: 'CPU Usage',
12+
value: '(average(system.cpu.user.pct) + average(system.cpu.system.pct)) / max(system.cpu.cores)',
13+
format: {
14+
id: 'percent',
15+
params: {
16+
decimals: 0,
1717
},
1818
},
1919
};
20-
21-
export const cpuUsage: LensChartConfig = {
22-
title: 'CPU Usage',
23-
formula: {
24-
formula:
25-
'(average(system.cpu.user.pct) + average(system.cpu.system.pct)) / max(system.cpu.cores)',
26-
format: {
27-
id: 'percent',
28-
params: {
29-
decimals: 0,
30-
},
31-
},
32-
},
33-
getFilters,
34-
35-
lineChartConfig: cpuLineChart,
36-
};

x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/disk_read_iops.ts

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,15 @@
55
* 2.0.
66
*/
77

8-
import type { LensChartConfig } from '../../../types';
9-
import { getFilters } from './utils';
8+
import type { FormulaConfig } from '../../../types';
109

11-
export const diskIORead: LensChartConfig = {
12-
title: 'Disk Read IOPS',
13-
formula: {
14-
formula: "counter_rate(max(system.diskio.read.count), kql='system.diskio.read.count: *')",
15-
format: {
16-
id: 'number',
17-
params: {
18-
decimals: 0,
19-
},
10+
export const diskIORead: FormulaConfig = {
11+
label: 'Disk Read IOPS',
12+
value: "counter_rate(max(system.diskio.read.count), kql='system.diskio.read.count: *')",
13+
format: {
14+
id: 'number',
15+
params: {
16+
decimals: 0,
2017
},
2118
},
22-
getFilters,
2319
};

0 commit comments

Comments
 (0)