diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 28b817c72abaf..aa0442041059b 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -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 diff --git a/package.json b/package.json index 4cdb0324c75d6..16f0ec705f349 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/x-pack/plugins/infra/public/common/visualizations/lens/README.md b/packages/kbn-lens-embeddable-utils/README.md similarity index 63% rename from x-pack/plugins/infra/public/common/visualizations/lens/README.md rename to packages/kbn-lens-embeddable-utils/README.md index c0fa8340f180e..662ba0c92e7cf 100644 --- a/x-pack/plugins/infra/public/common/visualizations/lens/README.md +++ b/packages/kbn-lens-embeddable-utils/README.md @@ -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: @@ -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: @@ -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: @@ -69,10 +137,13 @@ const xyChart = new XYChart({ }, }, }], - formulaAPI, + options: { + buckets: {type: 'date_histogram'}, + }, }), new XYReferenceLineLayer({ data: [{ + value: "1", format: { id: 'percent', @@ -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. @@ -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: @@ -150,10 +225,10 @@ const builder = new LensAttributesBuilder({ }, }, }, - formulaAPI, }), dataView, - }) + formulaAPI + }), }); const lensAttributes = builder.build(); @@ -163,4 +238,4 @@ const lensAttributes = builder.build(); viewMode={ViewMode.VIEW} ... /> -``` +``` \ No newline at end of file diff --git a/x-pack/plugins/infra/public/common/visualizations/lens/data_view_cache.ts b/packages/kbn-lens-embeddable-utils/attribute_builder/data_view_cache.ts similarity index 83% rename from x-pack/plugins/infra/public/common/visualizations/lens/data_view_cache.ts rename to packages/kbn-lens-embeddable-utils/attribute_builder/data_view_cache.ts index f079ddd417710..6eb76c9f5fec7 100644 --- a/x-pack/plugins/infra/public/common/visualizations/lens/data_view_cache.ts +++ b/packages/kbn-lens-embeddable-utils/attribute_builder/data_view_cache.ts @@ -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; diff --git a/x-pack/plugins/infra/public/common/visualizations/lens/lens_attributes_builder.test.ts b/packages/kbn-lens-embeddable-utils/attribute_builder/lens_attributes_builder.test.ts similarity index 92% rename from x-pack/plugins/infra/public/common/visualizations/lens/lens_attributes_builder.test.ts rename to packages/kbn-lens-embeddable-utils/attribute_builder/lens_attributes_builder.test.ts index 2b88909e462b3..199379e74eb9d 100644 --- a/x-pack/plugins/infra/public/common/visualizations/lens/lens_attributes_builder.test.ts +++ b/packages/kbn-lens-embeddable-utils/attribute_builder/lens_attributes_builder.test.ts @@ -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'; @@ -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', @@ -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', @@ -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 { @@ -148,10 +149,10 @@ describe('lens_attributes_builder', () => { options: { showTrendLine: true, }, - formulaAPI, }), dataView: mockDataView, + formulaAPI, }); const builder = new LensAttributesBuilder({ visualization: metriChart }); const { @@ -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 { @@ -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 { @@ -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 { diff --git a/x-pack/plugins/infra/public/common/visualizations/lens/lens_attributes_builder.ts b/packages/kbn-lens-embeddable-utils/attribute_builder/lens_attributes_builder.ts similarity index 61% rename from x-pack/plugins/infra/public/common/visualizations/lens/lens_attributes_builder.ts rename to packages/kbn-lens-embeddable-utils/attribute_builder/lens_attributes_builder.ts index d873f074ee346..e09d9cad8b0bd 100644 --- a/x-pack/plugins/infra/public/common/visualizations/lens/lens_attributes_builder.ts +++ b/packages/kbn-lens-embeddable-utils/attribute_builder/lens_attributes_builder.ts @@ -1,15 +1,17 @@ /* * 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'; @@ -17,12 +19,12 @@ export class LensAttributesBuilder> 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(), @@ -34,10 +36,17 @@ export class LensAttributesBuilder> }, }, 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) }), {}) + ), }, }; } diff --git a/packages/kbn-lens-embeddable-utils/attribute_builder/types.ts b/packages/kbn-lens-embeddable-utils/attribute_builder/types.ts new file mode 100644 index 0000000000000..6c9011b9782dc --- /dev/null +++ b/packages/kbn-lens-embeddable-utils/attribute_builder/types.ts @@ -0,0 +1,91 @@ +/* + * 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. + */ + +import type { SavedObjectReference } from '@kbn/core/server'; +import type { DataView } from '@kbn/data-views-plugin/common'; +import type { + FormBasedPersistedState, + MetricVisualizationState, + PersistedIndexPatternLayer, + TypedLensByValueInput, + XYState, + FormulaPublicApi, + XYLayerConfig, +} from '@kbn/lens-plugin/public'; +export type LensAttributes = TypedLensByValueInput['attributes']; + +// Attributes +export type LensVisualizationState = XYState | MetricVisualizationState; + +export interface VisualizationAttributesBuilder { + build(): LensAttributes; +} + +// Column +export interface BaseChartColumn { + getValueConfig(): TValueConfig; +} + +export interface ChartColumn extends BaseChartColumn { + getData( + id: string, + baseLayer: PersistedIndexPatternLayer, + dataView: DataView, + formulaAPI: FormulaPublicApi + ): PersistedIndexPatternLayer; +} + +export interface StaticChartColumn extends BaseChartColumn { + getData(id: string, baseLayer: PersistedIndexPatternLayer): PersistedIndexPatternLayer; +} + +// Layer +export type LensLayerConfig = XYLayerConfig | MetricVisualizationState; + +export interface ChartLayer { + getName(): string | undefined; + getLayer( + layerId: string, + accessorId: string, + dataView: DataView, + formulaAPI: FormulaPublicApi + ): FormBasedPersistedState['layers']; + getReference(layerId: string, dataView: DataView): SavedObjectReference[]; + getLayerConfig(layerId: string, acessorId: string): TLayerConfig; + getDataView(): DataView | undefined; +} + +// Chart +export interface Chart { + getTitle(): string; + getVisualizationType(): string; + getLayers(): FormBasedPersistedState['layers']; + getVisualizationState(): TVisualizationState; + getReferences(): SavedObjectReference[]; + getDataViews(): DataView[]; +} +export interface ChartConfig< + TLayer extends ChartLayer | Array> +> { + formulaAPI: FormulaPublicApi; + dataView: DataView; + layers: TLayer; + title?: string; +} + +// Formula +type LensFormula = Parameters[1]; +export type FormulaValueConfig = Omit & { + color?: string; + value: string; +}; + +export type StaticValueConfig = Omit & { + color?: string; + value: string; +}; diff --git a/x-pack/plugins/infra/public/common/visualizations/lens/utils.ts b/packages/kbn-lens-embeddable-utils/attribute_builder/utils.ts similarity index 68% rename from x-pack/plugins/infra/public/common/visualizations/lens/utils.ts rename to packages/kbn-lens-embeddable-utils/attribute_builder/utils.ts index 2a28e1ac659a9..ed75956cadbe1 100644 --- a/x-pack/plugins/infra/public/common/visualizations/lens/utils.ts +++ b/packages/kbn-lens-embeddable-utils/attribute_builder/utils.ts @@ -1,10 +1,12 @@ /* * 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 { + +import type { DateHistogramIndexPatternColumn, PersistedIndexPatternLayer, TermsIndexPatternColumn, @@ -17,12 +19,27 @@ export const DEFAULT_AD_HOC_DATA_VIEW_ID = 'infra_lens_ad_hoc_default'; const DEFAULT_BREAKDOWN_SIZE = 10; +export function nonNullable(v: T): v is NonNullable { + return v != null; +} + +export type DateHistogramColumnParams = DateHistogramIndexPatternColumn['params']; + +export type TopValuesColumnParams = Pick< + TermsIndexPatternColumn['params'], + 'size' | 'orderDirection' | 'orderBy' +>; + export const getHistogramColumn = ({ columnName, - overrides, + options, }: { columnName: string; - overrides?: Partial>; + options?: Partial< + Pick & { + params: DateHistogramColumnParams; + } + >; }) => { return { [columnName]: { @@ -32,32 +49,32 @@ export const getHistogramColumn = ({ operationType: 'date_histogram', scale: 'interval', sourceField: '@timestamp', - ...overrides, - params: { interval: 'auto', ...overrides?.params }, + ...options, + params: { interval: 'auto', ...options?.params }, } as DateHistogramIndexPatternColumn, }; }; export const getTopValuesColumn = ({ columnName, - overrides, + field, + options, }: { columnName: string; - overrides?: Partial> & { - breakdownSize?: number; - }; + field: string; + options?: Partial; }): PersistedIndexPatternLayer['columns'] => { - const { breakdownSize = DEFAULT_BREAKDOWN_SIZE, sourceField } = overrides ?? {}; + const { size = DEFAULT_BREAKDOWN_SIZE, ...params } = options ?? {}; return { [columnName]: { - label: `Top ${breakdownSize} values of ${sourceField}`, + label: `Top ${size} values of ${field}`, dataType: 'string', operationType: 'terms', scale: 'ordinal', - sourceField, + sourceField: field, isBucketed: true, params: { - size: breakdownSize, + size, orderBy: { type: 'alphabetical', fallback: false, @@ -72,6 +89,7 @@ export const getTopValuesColumn = ({ exclude: [], includeIsRegex: false, excludeIsRegex: false, + ...params, }, } as TermsIndexPatternColumn, }; diff --git a/x-pack/plugins/infra/public/common/visualizations/lens/visualization_types/index.ts b/packages/kbn-lens-embeddable-utils/attribute_builder/visualization_types/index.ts similarity index 61% rename from x-pack/plugins/infra/public/common/visualizations/lens/visualization_types/index.ts rename to packages/kbn-lens-embeddable-utils/attribute_builder/visualization_types/index.ts index 0bfbd11233b4d..7927ff37b2f16 100644 --- a/x-pack/plugins/infra/public/common/visualizations/lens/visualization_types/index.ts +++ b/packages/kbn-lens-embeddable-utils/attribute_builder/visualization_types/index.ts @@ -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. */ export { XYChart, type XYVisualOptions } from './xy_chart'; diff --git a/x-pack/plugins/infra/public/common/visualizations/lens/visualization_types/layers/column/formula.ts b/packages/kbn-lens-embeddable-utils/attribute_builder/visualization_types/layers/columns/formula.ts similarity index 55% rename from x-pack/plugins/infra/public/common/visualizations/lens/visualization_types/layers/column/formula.ts rename to packages/kbn-lens-embeddable-utils/attribute_builder/visualization_types/layers/columns/formula.ts index b1e30ce0bd225..9ca0f215bc2b2 100644 --- a/x-pack/plugins/infra/public/common/visualizations/lens/visualization_types/layers/column/formula.ts +++ b/packages/kbn-lens-embeddable-utils/attribute_builder/visualization_types/layers/columns/formula.ts @@ -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 { FormulaPublicApi, PersistedIndexPatternLayer } from '@kbn/lens-plugin/public'; import type { DataView } from '@kbn/data-views-plugin/public'; -import type { FormulaConfig, ChartColumn } from '../../../../types'; +import type { FormulaValueConfig, ChartColumn } from '../../../types'; export class FormulaColumn implements ChartColumn { - constructor(private formulaConfig: FormulaConfig, private formulaAPI: FormulaPublicApi) {} + constructor(private valueConfig: FormulaValueConfig) {} - getFormulaConfig(): FormulaConfig { - return this.formulaConfig; + getValueConfig(): FormulaValueConfig { + return this.valueConfig; } getData( id: string, baseLayer: PersistedIndexPatternLayer, - dataView: DataView + dataView: DataView, + formulaAPI: FormulaPublicApi ): PersistedIndexPatternLayer { - const { value, ...rest } = this.getFormulaConfig(); - const formulaLayer = this.formulaAPI.insertOrReplaceFormulaColumn( + const { value, ...rest } = this.getValueConfig(); + const formulaLayer = formulaAPI.insertOrReplaceFormulaColumn( id, { formula: value, ...rest }, baseLayer, diff --git a/x-pack/plugins/infra/public/common/visualizations/lens/visualization_types/layers/column/reference_line.ts b/packages/kbn-lens-embeddable-utils/attribute_builder/visualization_types/layers/columns/reference_line.ts similarity index 65% rename from x-pack/plugins/infra/public/common/visualizations/lens/visualization_types/layers/column/reference_line.ts rename to packages/kbn-lens-embeddable-utils/attribute_builder/visualization_types/layers/columns/reference_line.ts index d9f9c5f270997..f376ce40293f0 100644 --- a/x-pack/plugins/infra/public/common/visualizations/lens/visualization_types/layers/column/reference_line.ts +++ b/packages/kbn-lens-embeddable-utils/attribute_builder/visualization_types/layers/columns/reference_line.ts @@ -1,23 +1,24 @@ /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. + * 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 { PersistedIndexPatternLayer } from '@kbn/lens-plugin/public'; import type { ReferenceBasedIndexPatternColumn } from '@kbn/lens-plugin/public/datasources/form_based/operations/definitions/column_types'; -import type { FormulaConfig, ChartColumn } from '../../../../types'; +import type { StaticChartColumn, StaticValueConfig } from '../../../types'; -export class ReferenceLineColumn implements ChartColumn { - constructor(private formulaConfig: FormulaConfig) {} +export class ReferenceLineColumn implements StaticChartColumn { + constructor(private valueConfig: StaticValueConfig) {} - getFormulaConfig(): FormulaConfig { - return this.formulaConfig; + getValueConfig(): StaticValueConfig { + return this.valueConfig; } getData(id: string, baseLayer: PersistedIndexPatternLayer): PersistedIndexPatternLayer { - const { label, ...params } = this.getFormulaConfig(); + const { label, ...params } = this.getValueConfig(); return { linkToLayers: [], columnOrder: [...baseLayer.columnOrder, id], diff --git a/x-pack/plugins/infra/public/common/visualizations/lens/visualization_types/layers/index.ts b/packages/kbn-lens-embeddable-utils/attribute_builder/visualization_types/layers/index.ts similarity index 53% rename from x-pack/plugins/infra/public/common/visualizations/lens/visualization_types/layers/index.ts rename to packages/kbn-lens-embeddable-utils/attribute_builder/visualization_types/layers/index.ts index fb8300573b79a..e7bf72a214a5c 100644 --- a/x-pack/plugins/infra/public/common/visualizations/lens/visualization_types/layers/index.ts +++ b/packages/kbn-lens-embeddable-utils/attribute_builder/visualization_types/layers/index.ts @@ -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. */ export { MetricLayer, type MetricLayerOptions } from './metric_layer'; export { XYDataLayer, type XYLayerOptions } from './xy_data_layer'; export { XYReferenceLinesLayer } from './xy_reference_lines_layer'; -export { FormulaColumn as FormulaDataColumn } from './column/formula'; -export { ReferenceLineColumn } from './column/reference_line'; +export { FormulaColumn as FormulaDataColumn } from './columns/formula'; +export { ReferenceLineColumn } from './columns/reference_line'; diff --git a/x-pack/plugins/infra/public/common/visualizations/lens/visualization_types/layers/metric_layer.ts b/packages/kbn-lens-embeddable-utils/attribute_builder/visualization_types/layers/metric_layer.ts similarity index 63% rename from x-pack/plugins/infra/public/common/visualizations/lens/visualization_types/layers/metric_layer.ts rename to packages/kbn-lens-embeddable-utils/attribute_builder/visualization_types/layers/metric_layer.ts index c5f65c27640ad..dbfc4481cb3d5 100644 --- a/x-pack/plugins/infra/public/common/visualizations/lens/visualization_types/layers/metric_layer.ts +++ b/packages/kbn-lens-embeddable-utils/attribute_builder/visualization_types/layers/metric_layer.ts @@ -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 type { SavedObjectReference } from '@kbn/core/server'; @@ -13,9 +14,9 @@ import type { MetricVisualizationState, PersistedIndexPatternLayer, } from '@kbn/lens-plugin/public'; -import type { ChartColumn, ChartLayer, FormulaConfig } from '../../../types'; +import type { ChartColumn, ChartLayer, FormulaValueConfig } from '../../types'; import { getDefaultReferences, getHistogramColumn } from '../../utils'; -import { FormulaColumn } from './column/formula'; +import { FormulaColumn } from './columns/formula'; const HISTOGRAM_COLUMN_NAME = 'x_date_histogram'; @@ -27,28 +28,32 @@ export interface MetricLayerOptions { } interface MetricLayerConfig { - data: FormulaConfig; + data: FormulaValueConfig; options?: MetricLayerOptions; - formulaAPI: FormulaPublicApi; + /** + * It is possible to define a specific dataView for the layer. It will override the global chart one + **/ + dataView?: DataView; } export class MetricLayer implements ChartLayer { private column: ChartColumn; constructor(private layerConfig: MetricLayerConfig) { - this.column = new FormulaColumn(layerConfig.data, layerConfig.formulaAPI); + this.column = new FormulaColumn(layerConfig.data); } getLayer( layerId: string, accessorId: string, - dataView: DataView + chartDataView: DataView, + formulaAPI: FormulaPublicApi ): FormBasedPersistedState['layers'] { const baseLayer: PersistedIndexPatternLayer = { columnOrder: [HISTOGRAM_COLUMN_NAME], columns: getHistogramColumn({ columnName: HISTOGRAM_COLUMN_NAME, - overrides: { - sourceField: dataView.timeFieldName, + options: { + sourceField: (this.layerConfig.dataView ?? chartDataView).timeFieldName, params: { interval: 'auto', includeEmptyRows: true, @@ -66,23 +71,29 @@ export class MetricLayer implements ChartLayer { columnOrder: [], columns: {}, }, - dataView + this.layerConfig.dataView ?? chartDataView, + formulaAPI ), }, ...(this.layerConfig.options?.showTrendLine ? { [`${layerId}_trendline`]: { linkToLayers: [layerId], - ...this.column.getData(`${accessorId}_trendline`, baseLayer, dataView), + ...this.column.getData( + `${accessorId}_trendline`, + baseLayer, + this.layerConfig.dataView ?? chartDataView, + formulaAPI + ), }, } : {}), }; } - getReference(layerId: string, dataView: DataView): SavedObjectReference[] { + getReference(layerId: string, chartDataView: DataView): SavedObjectReference[] { return [ - ...getDefaultReferences(dataView, layerId), - ...getDefaultReferences(dataView, `${layerId}_trendline`), + ...getDefaultReferences(this.layerConfig.dataView ?? chartDataView, layerId), + ...getDefaultReferences(this.layerConfig.dataView ?? chartDataView, `${layerId}_trendline`), ]; } @@ -107,6 +118,10 @@ export class MetricLayer implements ChartLayer { }; } getName(): string | undefined { - return this.column.getFormulaConfig().label; + return this.column.getValueConfig().label; + } + + getDataView(): DataView | undefined { + return this.layerConfig.dataView; } } diff --git a/packages/kbn-lens-embeddable-utils/attribute_builder/visualization_types/layers/xy_data_layer.ts b/packages/kbn-lens-embeddable-utils/attribute_builder/visualization_types/layers/xy_data_layer.ts new file mode 100644 index 0000000000000..956fd5370a812 --- /dev/null +++ b/packages/kbn-lens-embeddable-utils/attribute_builder/visualization_types/layers/xy_data_layer.ts @@ -0,0 +1,177 @@ +/* + * 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. + */ + +import type { SavedObjectReference } from '@kbn/core/server'; +import type { DataView } from '@kbn/data-views-plugin/common'; +import type { + FormulaPublicApi, + FormBasedPersistedState, + PersistedIndexPatternLayer, + XYDataLayerConfig, + SeriesType, + TermsIndexPatternColumn, + DateHistogramIndexPatternColumn, +} from '@kbn/lens-plugin/public'; +import type { ChartColumn, ChartLayer, FormulaValueConfig } from '../../types'; +import { + getDefaultReferences, + getHistogramColumn, + getTopValuesColumn, + nonNullable, + type TopValuesColumnParams, + type DateHistogramColumnParams, +} from '../../utils'; +import { FormulaColumn } from './columns/formula'; + +const BREAKDOWN_COLUMN_NAME = 'aggs_breakdown'; +const HISTOGRAM_COLUMN_NAME = 'x_date_histogram'; + +interface TopValuesBucketedColumn { + type: 'top_values'; + field: TermsIndexPatternColumn['sourceField']; + params?: Partial; +} +interface DateHistogramBucketedColumn { + type: 'date_histogram'; + field?: DateHistogramIndexPatternColumn['sourceField']; + params?: Partial; +} + +export interface XYLayerOptions { + // Add more types as support for them is implemented + breakdown?: TopValuesBucketedColumn; + // Add more types as support for them is implemented + buckets?: DateHistogramBucketedColumn; + seriesType?: SeriesType; +} + +interface XYLayerConfig { + data: FormulaValueConfig[]; + options?: XYLayerOptions; + /** + * 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 { + private column: ChartColumn[]; + private layerConfig: XYLayerConfig; + constructor(layerConfig: XYLayerConfig) { + this.column = layerConfig.data.map((dataItem) => new FormulaColumn(dataItem)); + this.layerConfig = { + ...layerConfig, + options: { + ...layerConfig.options, + buckets: { + type: 'date_histogram', + ...layerConfig.options?.buckets, + }, + }, + }; + } + + getName(): string | undefined { + return this.column[0].getValueConfig().label; + } + + getBaseLayer(dataView: DataView, options: XYLayerOptions) { + return { + ...(options.buckets?.type === 'date_histogram' + ? getHistogramColumn({ + columnName: HISTOGRAM_COLUMN_NAME, + options: { + ...options.buckets.params, + sourceField: options.buckets.field ?? dataView.timeFieldName, + }, + }) + : {}), + ...(options.breakdown?.type === 'top_values' + ? { + ...getTopValuesColumn({ + columnName: BREAKDOWN_COLUMN_NAME, + field: options?.breakdown.field, + options: { + ...options.breakdown.params, + }, + }), + } + : {}), + }; + } + + getLayer( + layerId: string, + accessorId: string, + chartDataView: DataView, + formulaAPI: FormulaPublicApi + ): FormBasedPersistedState['layers'] { + const columnOrder: string[] = []; + if (this.layerConfig.options?.breakdown?.type === 'top_values') { + columnOrder.push(BREAKDOWN_COLUMN_NAME); + } + if (this.layerConfig.options?.buckets?.type === 'date_histogram') { + columnOrder.push(HISTOGRAM_COLUMN_NAME); + } + + const baseLayer: PersistedIndexPatternLayer = { + columnOrder, + columns: { + ...this.getBaseLayer( + this.layerConfig.dataView ?? chartDataView, + this.layerConfig.options ?? {} + ), + }, + }; + + return { + [layerId]: this.column.reduce( + (acc, curr, index) => ({ + ...acc, + ...curr.getData( + `${accessorId}_${index}`, + acc, + this.layerConfig.dataView ?? chartDataView, + formulaAPI + ), + }), + baseLayer + ), + }; + } + + getReference(layerId: string, chartDataView: DataView): SavedObjectReference[] { + return getDefaultReferences(this.layerConfig.dataView ?? chartDataView, layerId); + } + + getLayerConfig(layerId: string, accessorId: string): XYDataLayerConfig { + return { + layerId, + seriesType: this.layerConfig.options?.seriesType ?? 'line', + accessors: this.column.map((_, index) => `${accessorId}_${index}`), + yConfig: this.layerConfig.data + .map(({ color }, index) => + color ? { forAccessor: `${accessorId}_${index}`, color } : undefined + ) + .filter(nonNullable), + layerType: 'data', + xAccessor: + this.layerConfig.options?.buckets?.type === 'date_histogram' + ? HISTOGRAM_COLUMN_NAME + : undefined, + splitAccessor: + this.layerConfig.options?.breakdown?.type === 'top_values' + ? BREAKDOWN_COLUMN_NAME + : undefined, + }; + } + + getDataView(): DataView | undefined { + return this.layerConfig.dataView; + } +} diff --git a/x-pack/plugins/infra/public/common/visualizations/lens/visualization_types/layers/xy_reference_lines_layer.ts b/packages/kbn-lens-embeddable-utils/attribute_builder/visualization_types/layers/xy_reference_lines_layer.ts similarity index 58% rename from x-pack/plugins/infra/public/common/visualizations/lens/visualization_types/layers/xy_reference_lines_layer.ts rename to packages/kbn-lens-embeddable-utils/attribute_builder/visualization_types/layers/xy_reference_lines_layer.ts index c876473ee5f18..a91d1438f0daa 100644 --- a/x-pack/plugins/infra/public/common/visualizations/lens/visualization_types/layers/xy_reference_lines_layer.ts +++ b/packages/kbn-lens-embeddable-utils/attribute_builder/visualization_types/layers/xy_reference_lines_layer.ts @@ -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 type { SavedObjectReference } from '@kbn/core/server'; @@ -12,42 +13,42 @@ import type { PersistedIndexPatternLayer, XYReferenceLineLayerConfig, } from '@kbn/lens-plugin/public'; -import type { ChartColumn, ChartLayer, FormulaConfig } from '../../../types'; +import type { ChartLayer, StaticValueConfig, StaticChartColumn } from '../../types'; import { getDefaultReferences } from '../../utils'; -import { ReferenceLineColumn } from './column/reference_line'; +import { ReferenceLineColumn } from './columns/reference_line'; interface XYReferenceLinesLayerConfig { - data: FormulaConfig[]; + data: StaticValueConfig[]; + /** + * It is possible to define a specific dataView for the layer. It will override the global chart one + **/ + dataView?: DataView; } export class XYReferenceLinesLayer implements ChartLayer { - private column: ChartColumn[]; - constructor(layerConfig: XYReferenceLinesLayerConfig) { + private column: StaticChartColumn[]; + constructor(private layerConfig: XYReferenceLinesLayerConfig) { this.column = layerConfig.data.map((p) => new ReferenceLineColumn(p)); } getName(): string | undefined { - return this.column[0].getFormulaConfig().label; + return this.column[0].getValueConfig().label; } - getLayer( - layerId: string, - accessorId: string, - dataView: DataView - ): FormBasedPersistedState['layers'] { + getLayer(layerId: string, accessorId: string): FormBasedPersistedState['layers'] { const baseLayer = { columnOrder: [], columns: {} } as PersistedIndexPatternLayer; return { [`${layerId}_reference`]: this.column.reduce((acc, curr, index) => { return { ...acc, - ...curr.getData(`${accessorId}_${index}_reference_column`, acc, dataView), + ...curr.getData(`${accessorId}_${index}_reference_column`, acc), }; }, baseLayer), }; } - getReference(layerId: string, dataView: DataView): SavedObjectReference[] { - return getDefaultReferences(dataView, `${layerId}_reference`); + getReference(layerId: string, chartDataView: DataView): SavedObjectReference[] { + return getDefaultReferences(this.layerConfig.dataView ?? chartDataView, `${layerId}_reference`); } getLayerConfig(layerId: string, accessorId: string): XYReferenceLineLayerConfig { @@ -56,10 +57,14 @@ export class XYReferenceLinesLayer implements ChartLayer `${accessorId}_${index}_reference_column`), yConfig: this.column.map((layer, index) => ({ - color: layer.getFormulaConfig().color, + color: layer.getValueConfig().color, forAccessor: `${accessorId}_${index}_reference_column`, axisMode: 'left', })), }; } + + getDataView(): DataView | undefined { + return this.layerConfig.dataView; + } } diff --git a/x-pack/plugins/infra/public/common/visualizations/lens/visualization_types/metric_chart.ts b/packages/kbn-lens-embeddable-utils/attribute_builder/visualization_types/metric_chart.ts similarity index 66% rename from x-pack/plugins/infra/public/common/visualizations/lens/visualization_types/metric_chart.ts rename to packages/kbn-lens-embeddable-utils/attribute_builder/visualization_types/metric_chart.ts index 136545e4a61bd..9c3f5bf3afe98 100644 --- a/x-pack/plugins/infra/public/common/visualizations/lens/visualization_types/metric_chart.ts +++ b/packages/kbn-lens-embeddable-utils/attribute_builder/visualization_types/metric_chart.ts @@ -1,17 +1,17 @@ /* * 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 { FormBasedPersistedState, MetricVisualizationState } from '@kbn/lens-plugin/public'; 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 type { Chart, ChartConfig, ChartLayer } from '../../types'; - const ACCESSOR = 'metric_formula_accessor'; export class MetricChart implements Chart { @@ -22,7 +22,12 @@ export class MetricChart implements Chart { } getLayers(): FormBasedPersistedState['layers'] { - return this.chartConfig.layers.getLayer(DEFAULT_LAYER_ID, ACCESSOR, this.chartConfig.dataView); + return this.chartConfig.layers.getLayer( + DEFAULT_LAYER_ID, + ACCESSOR, + this.chartConfig.dataView, + this.chartConfig.formulaAPI + ); } getVisualizationState(): MetricVisualizationState { @@ -33,8 +38,10 @@ export class MetricChart implements Chart { return this.chartConfig.layers.getReference(DEFAULT_LAYER_ID, this.chartConfig.dataView); } - getDataView(): DataView { - return this.chartConfig.dataView; + getDataViews(): DataView[] { + return [this.chartConfig.dataView, this.chartConfig.layers.getDataView()].filter( + (x): x is DataView => !!x + ); } getTitle(): string { diff --git a/x-pack/plugins/infra/public/common/visualizations/lens/visualization_types/xy_chart.ts b/packages/kbn-lens-embeddable-utils/attribute_builder/visualization_types/xy_chart.ts similarity index 72% rename from x-pack/plugins/infra/public/common/visualizations/lens/visualization_types/xy_chart.ts rename to packages/kbn-lens-embeddable-utils/attribute_builder/visualization_types/xy_chart.ts index f891ebfe02a3c..cef612adc6b12 100644 --- a/x-pack/plugins/infra/public/common/visualizations/lens/visualization_types/xy_chart.ts +++ b/packages/kbn-lens-embeddable-utils/attribute_builder/visualization_types/xy_chart.ts @@ -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 type { @@ -13,8 +14,8 @@ import type { } from '@kbn/lens-plugin/public'; import type { DataView } from '@kbn/data-views-plugin/public'; import type { SavedObjectReference } from '@kbn/core/server'; +import type { Chart, ChartConfig, ChartLayer } from '../types'; import { DEFAULT_LAYER_ID } from '../utils'; -import type { Chart, ChartConfig, ChartLayer } from '../../types'; const ACCESSOR = 'formula_accessor'; @@ -27,6 +28,7 @@ export interface XYVisualOptions { } export class XYChart implements Chart { + private _layers: Array> | null = null; constructor( private chartConfig: ChartConfig>> & { visualOptions?: XYVisualOptions; @@ -37,13 +39,28 @@ export class XYChart implements Chart { return 'lnsXY'; } + private get layers() { + if (!this._layers) { + this._layers = Array.isArray(this.chartConfig.layers) + ? this.chartConfig.layers + : [this.chartConfig.layers]; + } + + return this._layers; + } + getLayers(): FormBasedPersistedState['layers'] { - return this.chartConfig.layers.reduce((acc, curr, index) => { + return this.layers.reduce((acc, curr, index) => { const layerId = `${DEFAULT_LAYER_ID}_${index}`; const accessorId = `${ACCESSOR}_${index}`; return { ...acc, - ...curr.getLayer(layerId, accessorId, this.chartConfig.dataView), + ...curr.getLayer( + layerId, + accessorId, + this.chartConfig.dataView, + this.chartConfig.formulaAPI + ), }; }, {}); } @@ -59,26 +76,29 @@ export class XYChart implements Chart { }), ], }), - fittingFunction: this.chartConfig.visualOptions?.missingValues ?? 'Zero', + fittingFunction: this.chartConfig.visualOptions?.missingValues ?? 'None', endValue: this.chartConfig.visualOptions?.endValues, - curveType: this.chartConfig.visualOptions?.lineInterpolation ?? 'LINEAR', + curveType: this.chartConfig.visualOptions?.lineInterpolation, emphasizeFitting: !this.chartConfig.visualOptions?.showDottedLine, }; } getReferences(): SavedObjectReference[] { - return this.chartConfig.layers.flatMap((p, index) => { + return this.layers.flatMap((p, index) => { const layerId = `${DEFAULT_LAYER_ID}_${index}`; return p.getReference(layerId, this.chartConfig.dataView); }); } - getDataView(): DataView { - return this.chartConfig.dataView; + getDataViews(): DataView[] { + return [ + this.chartConfig.dataView, + ...this.chartConfig.layers.map((p) => p.getDataView()).filter((x): x is DataView => !!x), + ]; } getTitle(): string { - return this.chartConfig.title ?? this.chartConfig.layers[0].getName() ?? ''; + return this.chartConfig.title ?? this.layers[0].getName() ?? ''; } } diff --git a/packages/kbn-lens-embeddable-utils/index.ts b/packages/kbn-lens-embeddable-utils/index.ts new file mode 100644 index 0000000000000..77259a91ae7f6 --- /dev/null +++ b/packages/kbn-lens-embeddable-utils/index.ts @@ -0,0 +1,27 @@ +/* + * 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 * from './attribute_builder/types'; + +export type { + MetricLayerOptions, + XYLayerOptions, + XYVisualOptions, +} from './attribute_builder/visualization_types'; + +export { + FormulaDataColumn, + MetricChart, + MetricLayer, + ReferenceLineColumn, + XYChart, + XYDataLayer, + XYReferenceLinesLayer, +} from './attribute_builder/visualization_types'; + +export { LensAttributesBuilder } from './attribute_builder/lens_attributes_builder'; diff --git a/packages/kbn-lens-embeddable-utils/jest.config.js b/packages/kbn-lens-embeddable-utils/jest.config.js new file mode 100644 index 0000000000000..cc0647cb2c626 --- /dev/null +++ b/packages/kbn-lens-embeddable-utils/jest.config.js @@ -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. + */ + +module.exports = { + preset: '@kbn/test', + rootDir: '../..', + roots: ['/packages/kbn-lens-embeddable-utils'], + setupFiles: ['jest-canvas-mock'], +}; diff --git a/packages/kbn-lens-embeddable-utils/kibana.jsonc b/packages/kbn-lens-embeddable-utils/kibana.jsonc new file mode 100644 index 0000000000000..d637ea2f24ccb --- /dev/null +++ b/packages/kbn-lens-embeddable-utils/kibana.jsonc @@ -0,0 +1,5 @@ +{ + "type": "shared-browser", + "id": "@kbn/lens-embeddable-utils", + "owner": "@elastic/infra-monitoring-ui" +} diff --git a/packages/kbn-lens-embeddable-utils/package.json b/packages/kbn-lens-embeddable-utils/package.json new file mode 100644 index 0000000000000..c70d63093593f --- /dev/null +++ b/packages/kbn-lens-embeddable-utils/package.json @@ -0,0 +1,6 @@ +{ + "name": "@kbn/lens-embeddable-utils", + "private": true, + "version": "1.0.0", + "license": "SSPL-1.0 OR Elastic License 2.0" +} \ No newline at end of file diff --git a/packages/kbn-lens-embeddable-utils/tsconfig.json b/packages/kbn-lens-embeddable-utils/tsconfig.json new file mode 100644 index 0000000000000..eca0b277bff1d --- /dev/null +++ b/packages/kbn-lens-embeddable-utils/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "target/types", + "types": ["jest", "node"] + }, + "include": ["**/*.ts"], + "exclude": ["target/**/*"], + "kbn_references": ["@kbn/core", "@kbn/data-plugin", "@kbn/data-views-plugin", "@kbn/lens-plugin"] +} diff --git a/tsconfig.base.json b/tsconfig.base.json index 4767ea254f353..cc2a1a7d3efb2 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -914,6 +914,8 @@ "@kbn/kubernetes-security-plugin/*": ["x-pack/plugins/kubernetes_security/*"], "@kbn/language-documentation-popover": ["packages/kbn-language-documentation-popover"], "@kbn/language-documentation-popover/*": ["packages/kbn-language-documentation-popover/*"], + "@kbn/lens-embeddable-utils": ["packages/kbn-lens-embeddable-utils"], + "@kbn/lens-embeddable-utils/*": ["packages/kbn-lens-embeddable-utils/*"], "@kbn/lens-plugin": ["x-pack/plugins/lens"], "@kbn/lens-plugin/*": ["x-pack/plugins/lens/*"], "@kbn/license-api-guard-plugin": ["x-pack/plugins/license_api_guard"], diff --git a/x-pack/plugins/infra/public/common/visualizations/index.ts b/x-pack/plugins/infra/public/common/visualizations/index.ts index 888bf3d8f8ad6..7bb1ba597dd79 100644 --- a/x-pack/plugins/infra/public/common/visualizations/index.ts +++ b/x-pack/plugins/infra/public/common/visualizations/index.ts @@ -9,14 +9,6 @@ export type { HostsLensFormulas, HostsLensMetricChartFormulas, HostsLensLineChartFormulas, - LensAttributes, - FormulaConfig, - Chart, - LensVisualizationState, } from './types'; export { hostLensFormulas } from './constants'; - -export * from './lens/visualization_types'; - -export { LensAttributesBuilder } from './lens/lens_attributes_builder'; diff --git a/x-pack/plugins/infra/public/common/visualizations/lens/dashboards/host/kpi_grid_config.ts b/x-pack/plugins/infra/public/common/visualizations/lens/dashboards/host/kpi_grid_config.ts index 9dde33f39cbdf..15efef082200f 100644 --- a/x-pack/plugins/infra/public/common/visualizations/lens/dashboards/host/kpi_grid_config.ts +++ b/x-pack/plugins/infra/public/common/visualizations/lens/dashboards/host/kpi_grid_config.ts @@ -7,13 +7,10 @@ import { i18n } from '@kbn/i18n'; import type { TypedLensByValueInput } from '@kbn/lens-plugin/public'; -import type { Layer } from '../../../../../hooks/use_lens_attributes'; +import { UseLensAttributesMetricLayerConfig } from '../../../../../hooks/use_lens_attributes'; import { hostLensFormulas } from '../../../constants'; import { TOOLTIP } from './translations'; -import type { FormulaConfig } from '../../../types'; -import type { MetricLayerOptions } from '../../visualization_types'; - export const KPI_CHART_HEIGHT = 150; export const AVERAGE_SUBTITLE = i18n.translate( 'xpack.infra.assetDetailsEmbeddable.overview.kpi.subtitle.average', @@ -23,7 +20,7 @@ export const AVERAGE_SUBTITLE = i18n.translate( ); export interface KPIChartProps extends Pick { - layers: Layer; + layers: UseLensAttributesMetricLayerConfig; toolTip: string; } @@ -36,12 +33,14 @@ export const KPI_CHARTS: KPIChartProps[] = [ layers: { data: { ...hostLensFormulas.cpuUsage, - format: { - ...hostLensFormulas.cpuUsage.format, - params: { - decimals: 1, - }, - }, + format: hostLensFormulas.cpuUsage.format + ? { + ...hostLensFormulas.cpuUsage.format, + params: { + decimals: 1, + }, + } + : undefined, }, layerType: 'data', options: { @@ -62,12 +61,14 @@ export const KPI_CHARTS: KPIChartProps[] = [ layers: { data: { ...hostLensFormulas.normalizedLoad1m, - format: { - ...hostLensFormulas.normalizedLoad1m.format, - params: { - decimals: 1, - }, - }, + format: hostLensFormulas.normalizedLoad1m.format + ? { + ...hostLensFormulas.normalizedLoad1m.format, + params: { + decimals: 1, + }, + } + : undefined, }, layerType: 'data', options: { @@ -85,12 +86,14 @@ export const KPI_CHARTS: KPIChartProps[] = [ layers: { data: { ...hostLensFormulas.memoryUsage, - format: { - ...hostLensFormulas.memoryUsage.format, - params: { - decimals: 1, - }, - }, + format: hostLensFormulas.memoryUsage.format + ? { + ...hostLensFormulas.memoryUsage.format, + params: { + decimals: 1, + }, + } + : undefined, }, layerType: 'data', options: { @@ -108,12 +111,14 @@ export const KPI_CHARTS: KPIChartProps[] = [ layers: { data: { ...hostLensFormulas.diskSpaceUsage, - format: { - ...hostLensFormulas.diskSpaceUsage.format, - params: { - decimals: 1, - }, - }, + format: hostLensFormulas.diskSpaceUsage.format + ? { + ...hostLensFormulas.diskSpaceUsage.format, + params: { + decimals: 1, + }, + } + : undefined, }, layerType: 'data', options: { diff --git a/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/cpu_usage.ts b/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/cpu_usage.ts index b3b40f585d7e0..1364d9a4bd83a 100644 --- a/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/cpu_usage.ts +++ b/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/cpu_usage.ts @@ -5,9 +5,9 @@ * 2.0. */ -import type { FormulaConfig } from '../../../types'; +import type { FormulaValueConfig } from '@kbn/lens-embeddable-utils'; -export const cpuUsage: FormulaConfig = { +export const cpuUsage: FormulaValueConfig = { label: 'CPU Usage', value: '(average(system.cpu.user.pct) + average(system.cpu.system.pct)) / max(system.cpu.cores)', format: { diff --git a/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/disk_read_iops.ts b/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/disk_read_iops.ts index 27b288f3a119e..9b3f22164aacc 100644 --- a/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/disk_read_iops.ts +++ b/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/disk_read_iops.ts @@ -5,9 +5,9 @@ * 2.0. */ -import type { FormulaConfig } from '../../../types'; +import type { FormulaValueConfig } from '@kbn/lens-embeddable-utils'; -export const diskIORead: FormulaConfig = { +export const diskIORead: FormulaValueConfig = { label: 'Disk Read IOPS', value: "counter_rate(max(system.diskio.read.count), kql='system.diskio.read.count: *')", format: { diff --git a/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/disk_read_throughput.ts b/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/disk_read_throughput.ts index 48fa795e9688a..5043fb7f94fe1 100644 --- a/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/disk_read_throughput.ts +++ b/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/disk_read_throughput.ts @@ -5,9 +5,9 @@ * 2.0. */ -import type { FormulaConfig } from '../../../types'; +import type { FormulaValueConfig } from '@kbn/lens-embeddable-utils'; -export const diskReadThroughput: FormulaConfig = { +export const diskReadThroughput: FormulaValueConfig = { label: 'Disk Read Throughput', value: "counter_rate(max(system.diskio.read.bytes), kql='system.diskio.read.bytes: *')", format: { diff --git a/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/disk_space_availability.ts b/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/disk_space_availability.ts index aadbd8ccea650..11d8346c06d28 100644 --- a/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/disk_space_availability.ts +++ b/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/disk_space_availability.ts @@ -5,9 +5,9 @@ * 2.0. */ -import type { FormulaConfig } from '../../../types'; +import type { FormulaValueConfig } from '@kbn/lens-embeddable-utils'; -export const diskSpaceAvailability: FormulaConfig = { +export const diskSpaceAvailability: FormulaValueConfig = { label: 'Disk Space Availability', value: '1 - average(system.filesystem.used.pct)', format: { diff --git a/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/disk_space_available.ts b/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/disk_space_available.ts index 088e28799ce03..2d55c085deb0b 100644 --- a/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/disk_space_available.ts +++ b/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/disk_space_available.ts @@ -5,9 +5,9 @@ * 2.0. */ -import type { FormulaConfig } from '../../../types'; +import type { FormulaValueConfig } from '@kbn/lens-embeddable-utils'; -export const diskSpaceAvailable: FormulaConfig = { +export const diskSpaceAvailable: FormulaValueConfig = { label: 'Disk Space Available', value: 'average(system.filesystem.free)', format: { diff --git a/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/disk_space_usage.ts b/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/disk_space_usage.ts index e4cb5851d5241..24143b58c81e6 100644 --- a/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/disk_space_usage.ts +++ b/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/disk_space_usage.ts @@ -5,9 +5,9 @@ * 2.0. */ -import type { FormulaConfig } from '../../../types'; +import type { FormulaValueConfig } from '@kbn/lens-embeddable-utils'; -export const diskSpaceUsage: FormulaConfig = { +export const diskSpaceUsage: FormulaValueConfig = { label: 'Disk Space Usage', value: 'average(system.filesystem.used.pct)', format: { diff --git a/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/disk_write_iops.ts b/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/disk_write_iops.ts index 04370c61903ce..2831957ccb230 100644 --- a/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/disk_write_iops.ts +++ b/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/disk_write_iops.ts @@ -5,9 +5,9 @@ * 2.0. */ -import type { FormulaConfig } from '../../../types'; +import type { FormulaValueConfig } from '@kbn/lens-embeddable-utils'; -export const diskIOWrite: FormulaConfig = { +export const diskIOWrite: FormulaValueConfig = { label: 'Disk Write IOPS', value: "counter_rate(max(system.diskio.write.count), kql='system.diskio.write.count: *')", format: { diff --git a/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/disk_write_throughput.ts b/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/disk_write_throughput.ts index aed685aa34d8c..9f0f0937bff37 100644 --- a/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/disk_write_throughput.ts +++ b/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/disk_write_throughput.ts @@ -5,9 +5,9 @@ * 2.0. */ -import type { FormulaConfig } from '../../../types'; +import type { FormulaValueConfig } from '@kbn/lens-embeddable-utils'; -export const diskWriteThroughput: FormulaConfig = { +export const diskWriteThroughput: FormulaValueConfig = { label: 'Disk Write Throughput', value: "counter_rate(max(system.diskio.write.bytes), kql='system.diskio.write.bytes: *')", format: { diff --git a/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/host_count.ts b/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/host_count.ts index e642a8cb629f1..f34a9d1913e49 100644 --- a/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/host_count.ts +++ b/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/host_count.ts @@ -5,9 +5,9 @@ * 2.0. */ -import type { FormulaConfig } from '../../../types'; +import type { FormulaValueConfig } from '@kbn/lens-embeddable-utils'; -export const hostCount: FormulaConfig = { +export const hostCount: FormulaValueConfig = { label: 'Hosts', value: 'unique_count(host.name)', format: { diff --git a/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/log_rate.ts b/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/log_rate.ts index f6b7ce3cdf0aa..3365efca35ebb 100644 --- a/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/log_rate.ts +++ b/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/log_rate.ts @@ -5,9 +5,9 @@ * 2.0. */ -import type { FormulaConfig } from '../../../types'; +import type { FormulaValueConfig } from '@kbn/lens-embeddable-utils'; -export const logRate: FormulaConfig = { +export const logRate: FormulaValueConfig = { label: 'Log Rate', value: 'differences(cumulative_sum(count()))', format: { diff --git a/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/memory_free.ts b/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/memory_free.ts index 4406ebd1e820c..5221faa86b3be 100644 --- a/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/memory_free.ts +++ b/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/memory_free.ts @@ -5,9 +5,9 @@ * 2.0. */ -import type { FormulaConfig } from '../../../types'; +import type { FormulaValueConfig } from '@kbn/lens-embeddable-utils'; -export const memoryFree: FormulaConfig = { +export const memoryFree: FormulaValueConfig = { label: 'Memory Free', value: 'max(system.memory.total) - average(system.memory.actual.used.bytes)', format: { diff --git a/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/memory_usage.ts b/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/memory_usage.ts index f95198756d61e..d7074968ce8b0 100644 --- a/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/memory_usage.ts +++ b/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/memory_usage.ts @@ -5,9 +5,9 @@ * 2.0. */ -import type { FormulaConfig } from '../../../types'; +import type { FormulaValueConfig } from '@kbn/lens-embeddable-utils'; -export const memoryUsage: FormulaConfig = { +export const memoryUsage: FormulaValueConfig = { label: 'Memory Usage', value: 'average(system.memory.actual.used.pct)', format: { diff --git a/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/normalized_load_1m.ts b/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/normalized_load_1m.ts index 32031d07fb858..3071804f3b5b4 100644 --- a/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/normalized_load_1m.ts +++ b/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/normalized_load_1m.ts @@ -5,9 +5,9 @@ * 2.0. */ -import type { FormulaConfig } from '../../../types'; +import type { FormulaValueConfig } from '@kbn/lens-embeddable-utils'; -export const normalizedLoad1m: FormulaConfig = { +export const normalizedLoad1m: FormulaValueConfig = { label: 'Normalized Load', value: 'average(system.load.1) / max(system.load.cores)', format: { diff --git a/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/rx.ts b/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/rx.ts index 2c5da5cb83988..92162fad6010f 100644 --- a/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/rx.ts +++ b/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/rx.ts @@ -5,9 +5,9 @@ * 2.0. */ -import type { FormulaConfig } from '../../../types'; +import type { FormulaValueConfig } from '@kbn/lens-embeddable-utils'; -export const rx: FormulaConfig = { +export const rx: FormulaValueConfig = { label: 'Network Inbound (RX)', value: "average(host.network.ingress.bytes) * 8 / (max(metricset.period, kql='host.network.ingress.bytes: *') / 1000)", diff --git a/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/tx.ts b/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/tx.ts index 70aa43a4efaf0..2b196103619a7 100644 --- a/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/tx.ts +++ b/x-pack/plugins/infra/public/common/visualizations/lens/formulas/host/tx.ts @@ -5,9 +5,9 @@ * 2.0. */ -import type { FormulaConfig } from '../../../types'; +import type { FormulaValueConfig } from '@kbn/lens-embeddable-utils'; -export const tx: FormulaConfig = { +export const tx: FormulaValueConfig = { label: 'Network Outbound (TX)', value: "average(host.network.egress.bytes) * 8 / (max(metricset.period, kql='host.network.egress.bytes: *') / 1000)", diff --git a/x-pack/plugins/infra/public/common/visualizations/lens/visualization_types/layers/xy_data_layer.ts b/x-pack/plugins/infra/public/common/visualizations/lens/visualization_types/layers/xy_data_layer.ts deleted file mode 100644 index 8da6598c77ae5..0000000000000 --- a/x-pack/plugins/infra/public/common/visualizations/lens/visualization_types/layers/xy_data_layer.ts +++ /dev/null @@ -1,108 +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 { SavedObjectReference } from '@kbn/core/server'; -import type { DataView } from '@kbn/data-views-plugin/common'; -import type { - FormulaPublicApi, - FormBasedPersistedState, - PersistedIndexPatternLayer, - XYDataLayerConfig, - SeriesType, -} from '@kbn/lens-plugin/public'; -import type { ChartColumn, ChartLayer, FormulaConfig } from '../../../types'; -import { getDefaultReferences, getHistogramColumn, getTopValuesColumn } from '../../utils'; -import { FormulaColumn } from './column/formula'; - -const BREAKDOWN_COLUMN_NAME = 'aggs_breakdown'; -const HISTOGRAM_COLUMN_NAME = 'x_date_histogram'; - -export interface XYLayerOptions { - breakdown?: { - size: number; - sourceField: string; - }; - seriesType?: SeriesType; -} - -interface XYLayerConfig { - data: FormulaConfig[]; - options?: XYLayerOptions; - formulaAPI: FormulaPublicApi; -} - -export class XYDataLayer implements ChartLayer { - private column: ChartColumn[]; - constructor(private layerConfig: XYLayerConfig) { - this.column = layerConfig.data.map((p) => new FormulaColumn(p, layerConfig.formulaAPI)); - } - - getName(): string | undefined { - return this.column[0].getFormulaConfig().label; - } - - getBaseLayer(dataView: DataView, options?: XYLayerOptions) { - return { - ...getHistogramColumn({ - columnName: HISTOGRAM_COLUMN_NAME, - overrides: { - sourceField: dataView.timeFieldName, - }, - }), - ...(options?.breakdown - ? { - ...getTopValuesColumn({ - columnName: BREAKDOWN_COLUMN_NAME, - overrides: { - sourceField: options?.breakdown.sourceField, - breakdownSize: options?.breakdown.size, - }, - }), - } - : {}), - }; - } - - getLayer( - layerId: string, - accessorId: string, - dataView: DataView - ): FormBasedPersistedState['layers'] { - const baseLayer: PersistedIndexPatternLayer = { - columnOrder: [BREAKDOWN_COLUMN_NAME, HISTOGRAM_COLUMN_NAME], - columns: { - ...this.getBaseLayer(dataView, this.layerConfig.options), - }, - }; - - return { - [layerId]: this.column.reduce( - (acc, curr, index) => ({ - ...acc, - ...curr.getData(`${accessorId}_${index}`, acc, dataView), - }), - baseLayer - ), - }; - } - - getReference(layerId: string, dataView: DataView): SavedObjectReference[] { - return getDefaultReferences(dataView, layerId); - } - - getLayerConfig(layerId: string, accessorId: string): XYDataLayerConfig { - return { - layerId, - seriesType: this.layerConfig.options?.seriesType ?? 'line', - accessors: this.column.map((_, index) => `${accessorId}_${index}`), - yConfig: [], - layerType: 'data', - xAccessor: HISTOGRAM_COLUMN_NAME, - splitAccessor: this.layerConfig.options?.breakdown ? BREAKDOWN_COLUMN_NAME : undefined, - }; - } -} diff --git a/x-pack/plugins/infra/public/common/visualizations/types.ts b/x-pack/plugins/infra/public/common/visualizations/types.ts index b9e04bf524477..b12343b0fd9c6 100644 --- a/x-pack/plugins/infra/public/common/visualizations/types.ts +++ b/x-pack/plugins/infra/public/common/visualizations/types.ts @@ -5,75 +5,7 @@ * 2.0. */ -import type { SavedObjectReference } from '@kbn/core/server'; -import type { DataView } from '@kbn/data-views-plugin/common'; -import type { - FormBasedPersistedState, - MetricVisualizationState, - PersistedIndexPatternLayer, - TypedLensByValueInput, - XYState, - FormulaPublicApi, - XYLayerConfig, -} from '@kbn/lens-plugin/public'; import { hostLensFormulas } from './constants'; -export type LensAttributes = TypedLensByValueInput['attributes']; - -// Attributes -export type LensVisualizationState = XYState | MetricVisualizationState; - -export interface VisualizationAttributesBuilder { - build(): LensAttributes; -} - -// Column -export interface ChartColumn { - getData( - id: string, - baseLayer: PersistedIndexPatternLayer, - dataView: DataView - ): PersistedIndexPatternLayer; - getFormulaConfig(): FormulaConfig; -} - -// Layer -export type LensLayerConfig = XYLayerConfig | MetricVisualizationState; - -export interface ChartLayer { - getName(): string | undefined; - getLayer( - layerId: string, - accessorId: string, - dataView: DataView - ): FormBasedPersistedState['layers']; - getReference(layerId: string, dataView: DataView): SavedObjectReference[]; - getLayerConfig(layerId: string, acessorId: string): TLayerConfig; -} - -// Chart -export interface Chart { - getTitle(): string; - getVisualizationType(): string; - getLayers(): FormBasedPersistedState['layers']; - getVisualizationState(): TVisualizationState; - getReferences(): SavedObjectReference[]; - getDataView(): DataView; -} -export interface ChartConfig< - TLayer extends ChartLayer | Array> -> { - dataView: DataView; - layers: TLayer; - title?: string; -} - -// Formula -type LensFormula = Parameters[1]; -export type FormulaConfig = Omit & { - color?: string; - format: NonNullable; - value: string; -}; export type HostsLensFormulas = keyof typeof hostLensFormulas; export type HostsLensMetricChartFormulas = Exclude; diff --git a/x-pack/plugins/infra/public/components/asset_details/tabs/overview/metrics/metrics_grid.tsx b/x-pack/plugins/infra/public/components/asset_details/tabs/overview/metrics/metrics_grid.tsx index 02fb533987d05..fcb76d2fa8ef9 100644 --- a/x-pack/plugins/infra/public/components/asset_details/tabs/overview/metrics/metrics_grid.tsx +++ b/x-pack/plugins/infra/public/components/asset_details/tabs/overview/metrics/metrics_grid.tsx @@ -11,22 +11,17 @@ import { i18n } from '@kbn/i18n'; import type { DataView } from '@kbn/data-views-plugin/public'; import type { TimeRange } from '@kbn/es-query'; import { FormattedMessage } from '@kbn/i18n-react'; -import { HostMetricsExplanationContent } from '../../../../lens/metric_explanation/host_metrics_explanation_content'; +import type { XYVisualOptions } from '@kbn/lens-embeddable-utils'; +import { UseLensAttributesXYLayerConfig } from '../../../../../hooks/use_lens_attributes'; import { buildCombinedHostsFilter } from '../../../../../utils/filters/build'; -import type { Layer } from '../../../../../hooks/use_lens_attributes'; -import { LensChart, type LensChartProps } from '../../../../lens'; -import { - type FormulaConfig, - hostLensFormulas, - type XYLayerOptions, - type XYVisualOptions, -} from '../../../../../common/visualizations'; +import { LensChart, type LensChartProps, HostMetricsExplanationContent } from '../../../../lens'; +import { hostLensFormulas } from '../../../../../common/visualizations'; import { METRIC_CHART_HEIGHT } from '../../../constants'; import { Popover } from '../../common/popover'; type DataViewOrigin = 'logs' | 'metrics'; interface MetricChartConfig extends Pick { - layers: Array>; + layers: UseLensAttributesXYLayerConfig; toolTip: string; } diff --git a/x-pack/plugins/infra/public/components/lens/lens_wrapper.tsx b/x-pack/plugins/infra/public/components/lens/lens_wrapper.tsx index f203c9c344797..043173113c5a5 100644 --- a/x-pack/plugins/infra/public/components/lens/lens_wrapper.tsx +++ b/x-pack/plugins/infra/public/components/lens/lens_wrapper.tsx @@ -11,10 +11,10 @@ import type { TimeRange } from '@kbn/es-query'; import { TypedLensByValueInput } from '@kbn/lens-plugin/public'; import { css } from '@emotion/react'; import { useEuiTheme } from '@elastic/eui'; +import { LensAttributes } from '@kbn/lens-embeddable-utils'; import { useKibanaContextForPlugin } from '../../hooks/use_kibana'; import { ChartLoadingProgress, ChartPlaceholder } from './chart_placeholder'; import { parseDateRange } from '../../utils/datemath'; -import { LensAttributes } from '../../common/visualizations'; export type LensWrapperProps = Omit< TypedLensByValueInput, diff --git a/x-pack/plugins/infra/public/hooks/use_lens_attributes.test.ts b/x-pack/plugins/infra/public/hooks/use_lens_attributes.test.ts index a3222210dec24..3058663f3a6fe 100644 --- a/x-pack/plugins/infra/public/hooks/use_lens_attributes.test.ts +++ b/x-pack/plugins/infra/public/hooks/use_lens_attributes.test.ts @@ -57,9 +57,15 @@ describe('useHostTable hook', () => { data: [normalizedLoad1m], layerType: 'data', options: { + buckets: { + type: 'date_histogram', + }, breakdown: { - size: 10, - sourceField: 'host.name', + field: 'host.name', + type: 'top_values', + params: { + size: 10, + }, }, }, }, diff --git a/x-pack/plugins/infra/public/hooks/use_lens_attributes.ts b/x-pack/plugins/infra/public/hooks/use_lens_attributes.ts index 5f562d2b8c5e1..373060c9452d8 100644 --- a/x-pack/plugins/infra/public/hooks/use_lens_attributes.ts +++ b/x-pack/plugins/infra/public/hooks/use_lens_attributes.ts @@ -12,13 +12,14 @@ import { useKibana } from '@kbn/kibana-react-plugin/public'; import type { Action, ActionExecutionContext } from '@kbn/ui-actions-plugin/public'; import { i18n } from '@kbn/i18n'; import useAsync from 'react-use/lib/useAsync'; -import { FormulaPublicApi, LayerType as LensLayerType } from '@kbn/lens-plugin/public'; -import { InfraClientSetupDeps } from '../types'; +import { FormulaPublicApi } from '@kbn/lens-plugin/public'; import { type XYLayerOptions, type MetricLayerOptions, - type FormulaConfig, + type FormulaValueConfig, type LensAttributes, + type StaticValueConfig, + type LensVisualizationState, type XYVisualOptions, type Chart, LensAttributesBuilder, @@ -27,48 +28,48 @@ import { XYChart, MetricChart, XYReferenceLinesLayer, - LensVisualizationState, -} from '../common/visualizations'; +} from '@kbn/lens-embeddable-utils'; + +import { InfraClientSetupDeps } from '../types'; import { useLazyRef } from './use_lazy_ref'; -type LayerOptions = XYLayerOptions | MetricLayerOptions; -type ChartType = 'lnsXY' | 'lnsMetric'; -type VisualOptions = XYVisualOptions; -export type LayerType = Exclude; +type Options = XYLayerOptions | MetricLayerOptions; -export interface Layer< - TLayerOptions extends LayerOptions, - TFormulaConfig extends FormulaConfig | FormulaConfig[], - TLayerType extends LayerType = LayerType -> { - layerType: TLayerType; - data: TFormulaConfig; - options?: TLayerOptions; +interface StaticValueLayer { + data: StaticValueConfig[]; + layerType: 'referenceLine'; } -interface UseLensAttributesBaseParams< - TOptions extends LayerOptions, - TLayers extends Array> | Layer +interface FormulaValueLayer< + TOptions extends Options, + TData extends FormulaValueConfig[] | FormulaValueConfig > { + options?: TOptions; + data: TData; + layerType: 'data'; +} + +type XYLayerConfig = StaticValueLayer | FormulaValueLayer; + +export type UseLensAttributesXYLayerConfig = XYLayerConfig | XYLayerConfig[]; +export type UseLensAttributesMetricLayerConfig = FormulaValueLayer< + MetricLayerOptions, + FormulaValueConfig +>; + +interface UseLensAttributesBaseParams { dataView?: DataView; - layers: TLayers; title?: string; } -interface UseLensAttributesXYChartParams - extends UseLensAttributesBaseParams< - XYLayerOptions, - Array> - > { +interface UseLensAttributesXYChartParams extends UseLensAttributesBaseParams { + layers: UseLensAttributesXYLayerConfig; visualizationType: 'lnsXY'; visualOptions?: XYVisualOptions; } -interface UseLensAttributesMetricChartParams - extends UseLensAttributesBaseParams< - MetricLayerOptions, - Layer - > { +interface UseLensAttributesMetricChartParams extends UseLensAttributesBaseParams { + layers: UseLensAttributesMetricLayerConfig; visualizationType: 'lnsMetric'; } @@ -76,13 +77,7 @@ export type UseLensAttributesParams = | UseLensAttributesXYChartParams | UseLensAttributesMetricChartParams; -export const useLensAttributes = ({ - dataView, - layers, - title, - visualizationType, - ...extraParams -}: UseLensAttributesParams) => { +export const useLensAttributes = ({ dataView, ...params }: UseLensAttributesParams) => { const { services: { lens }, } = useKibana(); @@ -99,10 +94,7 @@ export const useLensAttributes = ({ visualization: chartFactory({ dataView, formulaAPI, - layers, - title, - visualizationType, - ...extraParams, + ...params, }), }); @@ -163,9 +155,9 @@ export const useLensAttributes = ({ ); const getFormula = () => { - const firstDataLayer = [...(Array.isArray(layers) ? layers : [layers])].find( - (p) => p.layerType === 'data' - ); + const firstDataLayer = [ + ...(Array.isArray(params.layers) ? params.layers : [params.layers]), + ].find((p) => p.layerType === 'data'); if (!firstDataLayer) { return ''; @@ -181,80 +173,70 @@ export const useLensAttributes = ({ return { formula: getFormula(), attributes: attributes.current, getExtraActions, error }; }; -const chartFactory = < - TOptions, - TLayers extends Array> | Layer ->({ +const chartFactory = ({ dataView, formulaAPI, - layers, - title, - visualizationType, - visualOptions, + ...params }: { dataView: DataView; formulaAPI: FormulaPublicApi; - visualizationType: ChartType; - layers: TLayers; - title?: string; - visualOptions?: VisualOptions; -}): Chart => { - switch (visualizationType) { +} & UseLensAttributesParams): Chart => { + switch (params.visualizationType) { case 'lnsXY': - if (!Array.isArray(layers)) { + if (!Array.isArray(params.layers)) { throw new Error(`Invalid layers type. Expected an array of layers.`); } - const getLayerClass = (layerType: LayerType) => { - switch (layerType) { + const xyLayerFactory = (layer: XYLayerConfig) => { + switch (layer.layerType) { case 'data': { - return XYDataLayer; + return new XYDataLayer({ + data: layer.data, + options: layer.options, + }); } case 'referenceLine': { - return XYReferenceLinesLayer; + return new XYReferenceLinesLayer({ + data: layer.data, + }); } default: - throw new Error(`Invalid layerType: ${layerType}`); + throw new Error(`Invalid layerType`); } }; return new XYChart({ dataView, - layers: layers.map((layerItem) => { - const Layer = getLayerClass(layerItem.layerType); - return new Layer({ - data: layerItem.data, - formulaAPI, - options: layerItem.options, - }); + formulaAPI, + layers: params.layers.map((layerItem) => { + return xyLayerFactory(layerItem); }), - title, - visualOptions, + title: params.title, + visualOptions: params.visualOptions, }); case 'lnsMetric': - if (Array.isArray(layers)) { + if (Array.isArray(params.layers)) { throw new Error(`Invalid layers type. Expected a single layer object.`); } return new MetricChart({ dataView, + formulaAPI, layers: new MetricLayer({ - data: layers.data, - formulaAPI, - options: layers.options, + data: params.layers.data, + options: params.layers.options, }), - title, + title: params.title, }); default: - throw new Error(`Unsupported chart type: ${visualizationType}`); + throw new Error(`Unsupported chart type`); } }; const getOpenInLensAction = (onExecute: () => void): Action => { return { id: 'openInLens', - getDisplayName(_context: ActionExecutionContext): string { return i18n.translate('xpack.infra.hostsViewPage.tabs.metricsCharts.actions.openInLines', { defaultMessage: 'Open in Lens', diff --git a/x-pack/plugins/infra/public/pages/metrics/hosts/components/tabs/metrics/metric_chart.tsx b/x-pack/plugins/infra/public/pages/metrics/hosts/components/tabs/metrics/metric_chart.tsx index e15f212a23e18..2d77bdfbcecfc 100644 --- a/x-pack/plugins/infra/public/pages/metrics/hosts/components/tabs/metrics/metric_chart.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/hosts/components/tabs/metrics/metric_chart.tsx @@ -6,15 +6,11 @@ */ import React, { useMemo } from 'react'; import type { TypedLensByValueInput } from '@kbn/lens-plugin/public'; +import type { XYVisualOptions } from '@kbn/lens-embeddable-utils'; import { LensChart } from '../../../../../../components/lens'; -import type { Layer } from '../../../../../../hooks/use_lens_attributes'; +import type { UseLensAttributesXYLayerConfig } from '../../../../../../hooks/use_lens_attributes'; import { useMetricsDataViewContext } from '../../../hooks/use_data_view'; import { useUnifiedSearchContext } from '../../../hooks/use_unified_search'; -import type { - FormulaConfig, - XYLayerOptions, - XYVisualOptions, -} from '../../../../../../common/visualizations'; import { useHostsViewContext } from '../../../hooks/use_hosts_view'; import { buildCombinedHostsFilter } from '../../../../../../utils/filters/build'; import { useHostsTableContext } from '../../../hooks/use_hosts_table'; @@ -23,7 +19,7 @@ import { METRIC_CHART_HEIGHT } from '../../../constants'; export interface MetricChartProps extends Pick { title: string; - layers: Array>; + layers: UseLensAttributesXYLayerConfig; visualOptions?: XYVisualOptions; } diff --git a/x-pack/plugins/infra/public/pages/metrics/hosts/components/tabs/metrics/metrics_grid.tsx b/x-pack/plugins/infra/public/pages/metrics/hosts/components/tabs/metrics/metrics_grid.tsx index 30df5d6a66c62..07abe5fa98d09 100644 --- a/x-pack/plugins/infra/public/pages/metrics/hosts/components/tabs/metrics/metrics_grid.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/hosts/components/tabs/metrics/metrics_grid.tsx @@ -6,15 +6,10 @@ */ import React from 'react'; -import { EuiFlexGrid, EuiFlexItem, EuiText } from '@elastic/eui'; +import { EuiFlexGrid, EuiFlexItem, EuiText, EuiFlexGroup, EuiSpacer } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { EuiSpacer } from '@elastic/eui'; -import { EuiFlexGroup } from '@elastic/eui'; -import { - hostLensFormulas, - type XYVisualOptions, - type XYLayerOptions, -} from '../../../../../../common/visualizations'; +import type { XYLayerOptions, XYVisualOptions } from '@kbn/lens-embeddable-utils'; +import { hostLensFormulas } from '../../../../../../common/visualizations'; import { HostMetricsExplanationContent } from '../../../../../../components/lens'; import { MetricChart, MetricChartProps } from './metric_chart'; import { Popover } from '../../table/popover'; @@ -22,8 +17,11 @@ import { Popover } from '../../table/popover'; const DEFAULT_BREAKDOWN_SIZE = 20; const XY_LAYER_OPTIONS: XYLayerOptions = { breakdown: { - size: DEFAULT_BREAKDOWN_SIZE, - sourceField: 'host.name', + type: 'top_values', + field: 'host.name', + params: { + size: DEFAULT_BREAKDOWN_SIZE, + }, }, }; diff --git a/x-pack/plugins/infra/tsconfig.json b/x-pack/plugins/infra/tsconfig.json index c0cc1cbf1b3c9..519e2a8a1e941 100644 --- a/x-pack/plugins/infra/tsconfig.json +++ b/x-pack/plugins/infra/tsconfig.json @@ -69,6 +69,7 @@ "@kbn/logs-shared-plugin", "@kbn/licensing-plugin", "@kbn/aiops-utils", + "@kbn/lens-embeddable-utils" ], "exclude": ["target/**/*"] } diff --git a/yarn.lock b/yarn.lock index e306b12208f31..70cde31e803c4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5984,6 +5984,10 @@ version "0.0.0" uid "" +"@kbn/lens-embeddable-utils@link:packages/kbn-lens-embeddable-utils": + version "0.0.0" + uid "" + "@kbn/visualizations-plugin@link:src/plugins/visualizations": version "0.0.0" uid ""