Skip to content

Commit

Permalink
Move Lens attribute builder to a package (#163422)
Browse files Browse the repository at this point in the history
closes [#163491](#163491)

## Summary

This PR creates a new package that contains a utility API that helps to
generate the JSON with the attributes required to render a Lens chart
with the `EmbeddableComponent`.

---------

Co-authored-by: kibanamachine <[email protected]>
  • Loading branch information
crespocarlos and kibanamachine authored Aug 14, 2023
1 parent 6e241a8 commit 281cc22
Show file tree
Hide file tree
Showing 50 changed files with 786 additions and 477 deletions.
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,7 @@ src/plugins/kibana_usage_collection @elastic/kibana-core
src/plugins/kibana_utils @elastic/kibana-app-services
x-pack/plugins/kubernetes_security @elastic/sec-cloudnative-integrations
packages/kbn-language-documentation-popover @elastic/kibana-visualizations
packages/kbn-lens-embeddable-utils @elastic/infra-monitoring-ui
x-pack/plugins/lens @elastic/kibana-visualizations
x-pack/plugins/license_api_guard @elastic/platform-deployment-management
x-pack/plugins/license_management @elastic/platform-deployment-management
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,7 @@
"@kbn/kibana-utils-plugin": "link:src/plugins/kibana_utils",
"@kbn/kubernetes-security-plugin": "link:x-pack/plugins/kubernetes_security",
"@kbn/language-documentation-popover": "link:packages/kbn-language-documentation-popover",
"@kbn/lens-embeddable-utils": "link:packages/kbn-lens-embeddable-utils",
"@kbn/lens-plugin": "link:x-pack/plugins/lens",
"@kbn/license-api-guard-plugin": "link:x-pack/plugins/license_api_guard",
"@kbn/license-management-plugin": "link:x-pack/plugins/license_management",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@

# Lens Attributes Builder
# @kbn/lens-embeddable-utils

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.
## Lens Attributes Builder

## Usage
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.

### Creating a Metric Chart
**Notes**:

This utililty is primarily used by Infra Observability UI and not meant to be used as an official solution provided by the Lens team.

- The tool has partial support of Lens charts, currently limited to XY and Metric charts.
- XY Bucket and Breakdown dimensions are limited respectively to Date Histogram and Top values.

### Usage

#### Creating a Metric Chart

To create a metric chart, use the `MetricChart` class and provide the required configuration. Here's an example:

Expand All @@ -22,13 +31,13 @@ const metricChart = new MetricChart({
},
},
},
formulaAPI,
}),
dataView,
formulaAPI
});
```

### Creating an XY Chart
#### Creating an XY Chart

To create an XY chart, use the `XYChart` class and provide the required configuration. Here's an example:

Expand All @@ -45,13 +54,72 @@ const xyChart = new XYChart({
},
},
}],
formulaAPI,
options: {
buckets: {type: 'date_histogram'},
},
})],
dataView,
formulaAPI
});
```

#### Variations of the XY Chart

XYChart has different series type variations. Here is an example of how to build a line (default) and area charts

#### Line chart

```ts
const xyChart = new XYChart({
layers: [new XYDataLayer({
data: [{
label: 'Inbound (RX)',
value: "average(system.load.1) / max(system.load.cores)",
format: {
id: 'percent',
params: {
decimals: 1,
},
},

}],
options: {
buckets: {type: 'date_histogram'},
seriesType: 'line' // default. it doesn't need to be informed.
}
})],
dataView,
formulaAPI
});
```

#### Area chart

```ts
const xyChart = new XYChart({
layers: [new XYDataLayer({
data: [{
label: 'Inbound (RX)',
value: "average(system.load.1) / max(system.load.cores)",
format: {
id: 'percent',
params: {
decimals: 1,
},
},

}],
options: {
buckets: {type: 'date_histogram'},
seriesType: 'area'
}
})],
dataView,
formulaAPI
});
```

### Adding Multiple Layers to an XY Chart
#### Adding Multiple Layers to an XY Chart

An XY chart can have multiple layers. Here's an example of containing a Reference Line Layer:

Expand All @@ -69,10 +137,13 @@ const xyChart = new XYChart({
},
},
}],
formulaAPI,
options: {
buckets: {type: 'date_histogram'},
},
}),
new XYReferenceLineLayer({
data: [{

value: "1",
format: {
id: 'percent',
Expand All @@ -84,10 +155,11 @@ const xyChart = new XYChart({
}),
],
dataView,
formulaAPI
});
```

### Adding Multiple Data Sources in the Same Layer
#### Adding Multiple Data Sources in the Same Layer

In an XY chart, it's possible to define multiple data sources within the same layer.

Expand Down Expand Up @@ -115,13 +187,16 @@ const xyChart = new XYChart({
},
},
}],
formulaAPI,
options: {
buckets: {type: 'date_histogram'},
},
}),
dataView,
formulaAPI
});
```

### Building Lens Chart Attributes
#### Building Lens Chart Attributes

The `LensAttributesBuilder` is responsible for creating the full JSON object that combines the attributes returned by the chart classes. Here's an example:

Expand Down Expand Up @@ -150,10 +225,10 @@ const builder = new LensAttributesBuilder({
},
},
},
formulaAPI,
}),
dataView,
})
formulaAPI
}),
});

const lensAttributes = builder.build();
Expand All @@ -163,4 +238,4 @@ const lensAttributes = builder.build();
viewMode={ViewMode.VIEW}
...
/>
```
```
Original file line number Diff line number Diff line change
@@ -1,13 +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; you may not use this file except in compliance with the Elastic License
* 2.0.
* 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.
*/

import { DataViewSpec, DataView } from '@kbn/data-plugin/common';

export const DEFAULT_AD_HOC_DATA_VIEW_ID = 'infra_lens_ad_hoc_default';
export const DEFAULT_AD_HOC_DATA_VIEW_ID = 'lens_ad_hoc_default';

export class DataViewCache {
private static instance: DataViewCache;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
/*
* 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.
* 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.
*/

import 'jest-canvas-mock';
Expand All @@ -19,7 +20,7 @@ import {
} from './visualization_types';
import type { FormulaPublicApi, GenericIndexPatternColumn } from '@kbn/lens-plugin/public';
import { ReferenceBasedIndexPatternColumn } from '@kbn/lens-plugin/public/datasources/form_based/operations/definitions/column_types';
import type { FormulaConfig } from '../types';
import type { FormulaValueConfig } from './types';

const mockDataView = {
id: 'mock-id',
Expand Down Expand Up @@ -85,7 +86,7 @@ const REFERENCE_LINE_LAYER: ReferenceBasedIndexPatternColumn = {
scale: 'ratio',
};

const getFormula = (value: string): FormulaConfig => ({
const getFormula = (value: string): FormulaValueConfig => ({
value,
format: {
id: 'percent',
Expand All @@ -106,10 +107,10 @@ describe('lens_attributes_builder', () => {
const metriChart = new MetricChart({
layers: new MetricLayer({
data: getFormula(AVERAGE_CPU_USER_FORMULA),
formulaAPI,
}),

dataView: mockDataView,
formulaAPI,
});
const builder = new LensAttributesBuilder({ visualization: metriChart });
const {
Expand Down Expand Up @@ -148,10 +149,10 @@ describe('lens_attributes_builder', () => {
options: {
showTrendLine: true,
},
formulaAPI,
}),

dataView: mockDataView,
formulaAPI,
});
const builder = new LensAttributesBuilder({ visualization: metriChart });
const {
Expand Down Expand Up @@ -204,10 +205,13 @@ describe('lens_attributes_builder', () => {
layers: [
new XYDataLayer({
data: [getFormula(AVERAGE_CPU_USER_FORMULA)],
formulaAPI,
options: {
buckets: { type: 'date_histogram' },
},
}),
],
dataView: mockDataView,
formulaAPI,
});
const builder = new LensAttributesBuilder({ visualization: xyChart });
const {
Expand Down Expand Up @@ -248,13 +252,23 @@ describe('lens_attributes_builder', () => {
layers: [
new XYDataLayer({
data: [getFormula(AVERAGE_CPU_USER_FORMULA)],
formulaAPI,
options: {
buckets: { type: 'date_histogram' },
},
}),
new XYReferenceLinesLayer({
data: [getFormula('1')],
data: [
{
value: '1',
format: {
id: 'percent',
},
},
],
}),
],
dataView: mockDataView,
formulaAPI,
});
const builder = new LensAttributesBuilder({ visualization: xyChart });
const {
Expand Down Expand Up @@ -316,10 +330,13 @@ describe('lens_attributes_builder', () => {
layers: [
new XYDataLayer({
data: [getFormula(AVERAGE_CPU_USER_FORMULA), getFormula(AVERAGE_CPU_SYSTEM_FORMULA)],
formulaAPI,
options: {
buckets: { type: 'date_histogram' },
},
}),
],
dataView: mockDataView,
formulaAPI,
});
const builder = new LensAttributesBuilder({ visualization: xyChart });
const {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,28 +1,30 @@
/*
* 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.
* 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.
*/

import type {
LensAttributes,
LensVisualizationState,
Chart,
VisualizationAttributesBuilder,
} from '../types';
} from './types';
import { DataViewCache } from './data_view_cache';
import { getAdhocDataView } from './utils';

export class LensAttributesBuilder<T extends Chart<LensVisualizationState>>
implements VisualizationAttributesBuilder
{
private dataViewCache: DataViewCache;
constructor(private state: { visualization: T }) {
constructor(private lens: { visualization: T }) {
this.dataViewCache = DataViewCache.getInstance();
}

build(): LensAttributes {
const { visualization } = this.state;
const { visualization } = this.lens;
return {
title: visualization.getTitle(),
visualizationType: visualization.getVisualizationType(),
Expand All @@ -34,10 +36,17 @@ export class LensAttributesBuilder<T extends Chart<LensVisualizationState>>
},
},
internalReferences: visualization.getReferences(),
// EmbeddableComponent receive filters.
filters: [],
// EmbeddableComponent receive query.
query: { language: 'kuery', query: '' },
visualization: visualization.getVisualizationState(),
adHocDataViews: getAdhocDataView(this.dataViewCache.getSpec(visualization.getDataView())),
// Getting the spec from a data view is a heavy operation, that's why the result is cached.
adHocDataViews: getAdhocDataView(
visualization
.getDataViews()
.reduce((acc, curr) => ({ ...acc, ...this.dataViewCache.getSpec(curr) }), {})
),
},
};
}
Expand Down
Loading

0 comments on commit 281cc22

Please sign in to comment.