[8.14] [Lens] Fix telemetry for annotation layers (#187281) (#187588)

# Backport

This will backport the following commits from `main` to `8.14`:
- [[Lens] Fix telemetry for annotation layers
(#187281)](https://github.com/elastic/kibana/pull/187281)

<!--- Backport version: 9.4.3 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sqren/backport)

<!--BACKPORT [{"author":{"name":"Marco
Liberati","email":"dej611@users.noreply.github.com"},"sourceCommit":{"committedDate":"2024-07-03T10:05:06Z","message":"[Lens]
Fix telemetry for annotation layers (#187281)\n\n## Summary\r\n\r\nThis
PR fixes the telemetry code for annotation layers adding
some\r\ndedicated unit test for the event logic.\r\n\r\n\r\n###
Checklist\r\n\r\n- [x] [Unit or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common
scenarios","sha":"4359659729af670e9744a61b9000de7c8917fb23","branchLabelMapping":{"^v8.15.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["Team:Visualizations","release_note:skip","Feature:Lens","backport:prev-minor","v8.15.0"],"title":"[Lens]
Fix telemetry for annotation
layers","number":187281,"url":"https://github.com/elastic/kibana/pull/187281","mergeCommit":{"message":"[Lens]
Fix telemetry for annotation layers (#187281)\n\n## Summary\r\n\r\nThis
PR fixes the telemetry code for annotation layers adding
some\r\ndedicated unit test for the event logic.\r\n\r\n\r\n###
Checklist\r\n\r\n- [x] [Unit or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common
scenarios","sha":"4359659729af670e9744a61b9000de7c8917fb23"}},"sourceBranch":"main","suggestedTargetBranches":[],"targetPullRequestStates":[{"branch":"main","label":"v8.15.0","branchLabelMappingKey":"^v8.15.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/187281","number":187281,"mergeCommit":{"message":"[Lens]
Fix telemetry for annotation layers (#187281)\n\n## Summary\r\n\r\nThis
PR fixes the telemetry code for annotation layers adding
some\r\ndedicated unit test for the event logic.\r\n\r\n\r\n###
Checklist\r\n\r\n- [x] [Unit or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common
scenarios","sha":"4359659729af670e9744a61b9000de7c8917fb23"}}]}]
BACKPORT-->

Co-authored-by: Marco Liberati <dej611@users.noreply.github.com>
This commit is contained in:
Kibana Machine 2024-07-04 19:15:33 +02:00 committed by GitHub
parent 86899c64a0
commit 9e99d63513
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 232 additions and 5 deletions

View file

@ -10,7 +10,14 @@ import { Position } from '@elastic/charts';
import type { PaletteOutput } from '@kbn/coloring';
import { Datatable, DatatableRow } from '@kbn/expressions-plugin/common';
import { LayerTypes } from '../constants';
import { DataLayerConfig, ExtendedDataLayerConfig, XYProps } from '../types';
import {
AnnotationLayerConfig,
CommonXYLayerConfig,
DataLayerConfig,
ExtendedDataLayerConfig,
ReferenceLineLayerConfig,
XYProps,
} from '../types';
export const mockPaletteOutput: PaletteOutput = {
type: 'palette',
@ -46,6 +53,36 @@ export const createSampleDatatableWithRows = (rows: DatatableRow[]): Datatable =
rows,
});
export const sampleAnnotationLayer: AnnotationLayerConfig = {
layerId: 'first',
type: 'annotationLayer',
layerType: LayerTypes.ANNOTATIONS,
annotations: [
{
type: 'manual_point_event_annotation',
id: 'ann1',
time: '2021-01-01T00:00:00.000Z',
label: 'Manual annotation point',
},
{
type: 'query_point_event_annotation',
id: 'ann2',
filter: { type: 'kibana_query', language: 'kql', query: 'a: *' },
label: 'Query annotation point',
},
],
};
export const sampleReferenceLineLayer: ReferenceLineLayerConfig = {
layerId: 'first',
type: 'referenceLineLayer',
layerType: LayerTypes.REFERENCELINE,
accessors: ['b', 'c'],
columnToLabel: '{"b": "Label B", "c": "Label C"}',
decorations: [],
table: createSampleDatatableWithRows([]),
};
export const sampleLayer: DataLayerConfig = {
layerId: 'first',
type: 'dataLayer',
@ -84,7 +121,7 @@ export const sampleExtendedLayer: ExtendedDataLayerConfig = {
};
export const createArgsWithLayers = (
layers: DataLayerConfig | DataLayerConfig[] = sampleLayer
layers: CommonXYLayerConfig | CommonXYLayerConfig[] = sampleLayer
): XYProps => ({
showTooltip: true,
minBarHeight: 1,

View file

@ -0,0 +1,190 @@
/*
* 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 { CommonXYLayerConfig, LayerTypes } from '../../common';
import { AnnotationLayerConfig, DataLayerConfig, XYProps } from '../../common/types';
import {
createArgsWithLayers,
sampleAnnotationLayer,
sampleLayer,
sampleReferenceLineLayer,
} from '../../common/__mocks__';
import { getDataLayers } from '../helpers';
import { extractCounterEvents } from './xy_chart_renderer';
type PossibleLayerTypes =
| typeof LayerTypes.DATA
| typeof LayerTypes.ANNOTATIONS
| typeof LayerTypes.REFERENCELINE;
function createLayer(type: PossibleLayerTypes) {
switch (type) {
case LayerTypes.ANNOTATIONS: {
return { ...sampleAnnotationLayer };
}
case LayerTypes.REFERENCELINE: {
return { ...sampleReferenceLineLayer };
}
case LayerTypes.DATA:
default: {
return { ...sampleLayer };
}
}
}
function createLayers(
layerConfigs: Partial<Record<CommonXYLayerConfig['layerType'], { count: number }>>
): CommonXYLayerConfig[] {
const layers = [];
for (const [type, { count }] of Object.entries(layerConfigs)) {
layers.push(
...Array.from({ length: count }, () => createLayer(type as CommonXYLayerConfig['layerType']))
);
}
return layers;
}
function createAnnotations(count: number) {
return Array.from({ length: count }, () => createLayer('annotations') as AnnotationLayerConfig);
}
function getXYProps(
layersConfig: CommonXYLayerConfig[],
annotations?: AnnotationLayerConfig[]
): XYProps {
const args = createArgsWithLayers(layersConfig);
if (annotations?.length) {
if (!args.annotations) {
args.annotations = {
type: 'event_annotations_result',
layers: [],
datatable: {
type: 'datatable',
columns: [],
rows: [],
},
};
}
args.annotations!.layers = annotations;
}
return args;
}
describe('should emit the right telemetry events', () => {
it('should emit the telemetry event for a single data layer', () => {
expect(
extractCounterEvents('lens', getXYProps(createLayers({ data: { count: 1 } })), false, {
getDataLayers,
})
).toMatchInlineSnapshot(`
Array [
"render_lens_line",
]
`);
});
it('should emit the telemetry event for multiple data layers', () => {
expect(
extractCounterEvents('lens', getXYProps(createLayers({ data: { count: 2 } })), false, {
getDataLayers,
})
).toMatchInlineSnapshot(`
Array [
"render_lens_line",
"render_lens_multiple_data_layers",
]
`);
});
it('should emit the telemetry event for multiple data layers with mixed types', () => {
const layers = createLayers({ data: { count: 2 } });
// change layer 2 to be bar stacked
(layers[1] as DataLayerConfig).seriesType = 'bar';
(layers[1] as DataLayerConfig).isStacked = true;
expect(
extractCounterEvents('lens', getXYProps(layers), false, {
getDataLayers,
})
).toMatchInlineSnapshot(`
Array [
"render_lens_line",
"render_lens_multiple_data_layers",
"render_lens_mixed_xy",
]
`);
});
it('should emit the telemetry dedicated event for percentage charts', () => {
const layers = createLayers({ data: { count: 1 } });
// change layer 2 to be bar stacked
(layers[0] as DataLayerConfig).seriesType = 'bar';
(layers[0] as DataLayerConfig).isPercentage = true;
(layers[0] as DataLayerConfig).isStacked = true;
expect(
extractCounterEvents('lens', getXYProps(layers), false, {
getDataLayers,
})
).toMatchInlineSnapshot(`
Array [
"render_lens_vertical_bar_percentage_stacked",
]
`);
});
it('should emit the telemetry event for a data layer and an additonal reference line layer', () => {
expect(
extractCounterEvents(
'lens',
getXYProps(createLayers({ data: { count: 1 }, referenceLine: { count: 1 } })),
false,
{ getDataLayers }
)
).toMatchInlineSnapshot(`
Array [
"render_lens_line",
"render_lens_reference_layer",
]
`);
});
it('should emit the telemetry event for a data layer and an additional annotations layer', () => {
expect(
extractCounterEvents(
'lens',
getXYProps(createLayers({ data: { count: 1 } }), createAnnotations(1)),
false,
{ getDataLayers }
)
).toMatchInlineSnapshot(`
Array [
"render_lens_line",
"render_lens_annotation_layer",
]
`);
});
it('should emit the telemetry event for a scenario with the navigate to lens feature', () => {
expect(
extractCounterEvents(
'lens',
getXYProps(
createLayers({ data: { count: 1 }, referenceLine: { count: 1 } }),
createAnnotations(1)
),
true,
{ getDataLayers }
)
).toMatchInlineSnapshot(`
Array [
"render_lens_line",
"render_lens_reference_layer",
"render_lens_annotation_layer",
"render_lens_render_line_convertable",
]
`);
});
});

View file

@ -61,9 +61,9 @@ interface XyChartRendererDeps {
getStartDeps: GetStartDepsFn;
}
const extractCounterEvents = (
export const extractCounterEvents = (
originatingApp: string,
{ layers, yAxisConfigs }: XYChartProps['args'],
{ annotations, layers, yAxisConfigs }: XYChartProps['args'],
canNavigateToLens: boolean,
services: {
getDataLayers: typeof getDataLayers;
@ -78,7 +78,7 @@ const extractCounterEvents = (
? `${dataLayer.isHorizontal ? 'horizontal_bar' : 'vertical_bar'}`
: dataLayer.seriesType;
const byTypes = layers.reduce(
const byTypes = layers.concat(annotations?.layers || []).reduce(
(acc, item) => {
if (
!acc.mixedXY &&