Skip to content

Commit 98471ee

Browse files
[Exploratory view] Core web vitals (#100320)
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
1 parent 4f07817 commit 98471ee

20 files changed

Lines changed: 354 additions & 74 deletions

x-pack/plugins/lens/public/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ export type {
2020
ValueLabelConfig,
2121
YAxisMode,
2222
XYCurveType,
23+
YConfig,
2324
} from './xy_visualization/types';
2425
export type { DataType, OperationMetadata } from './types';
2526
export type {

x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/constants/constants.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
BROWSER_FAMILY_LABEL,
1313
BROWSER_VERSION_LABEL,
1414
CLS_LABEL,
15+
CORE_WEB_VITALS_LABEL,
1516
CPU_USAGE_LABEL,
1617
DEVICE_LABEL,
1718
ENVIRONMENT_LABEL,
@@ -92,6 +93,7 @@ export const DataViewLabels: Record<ReportViewTypeId, string> = {
9293
logs: LOGS_FREQUENCY_LABEL,
9394
mem: MEMORY_USAGE_LABEL,
9495
nwk: NETWORK_ACTIVITY_LABEL,
96+
cwv: CORE_WEB_VITALS_LABEL,
9597
};
9698

9799
export const ReportToDataTypeMap: Record<ReportViewTypeId, AppDataType> = {
@@ -105,4 +107,9 @@ export const ReportToDataTypeMap: Record<ReportViewTypeId, AppDataType> = {
105107
mem: 'infra_metrics',
106108
logs: 'infra_logs',
107109
cpu: 'infra_metrics',
110+
cwv: 'ux',
108111
};
112+
113+
export const USE_BREAK_DOWN_COLUMN = 'USE_BREAK_DOWN_COLUMN';
114+
export const FILTER_RECORDS = 'FILTER_RECORDS';
115+
export const OPERATION_COLUMN = 'operation';

x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/constants/elasticsearch_fieldnames.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ export const TRANSACTION_URL = 'url.full';
119119
export const CLIENT_GEO = 'client.geo';
120120
export const USER_AGENT_DEVICE = 'user_agent.device.name';
121121
export const USER_AGENT_OS = 'user_agent.os.name';
122+
export const USER_AGENT_OS_VERSION = 'user_agent.os.version';
122123

123124
export const TRANSACTION_TIME_TO_FIRST_BYTE = 'transaction.marks.agent.timeToFirstByte';
124125
export const TRANSACTION_DOM_INTERACTIVE = 'transaction.marks.agent.domInteractive';

x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/constants/labels.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,14 @@ export const NETWORK_ACTIVITY_LABEL = i18n.translate(
200200
defaultMessage: 'Network activity',
201201
}
202202
);
203+
204+
export const CORE_WEB_VITALS_LABEL = i18n.translate(
205+
'xpack.observability.expView.fieldLabels.coreWebVitals',
206+
{
207+
defaultMessage: 'Core web vitals',
208+
}
209+
);
210+
203211
export const MEMORY_USAGE_LABEL = i18n.translate(
204212
'xpack.observability.expView.fieldLabels.memoryUsage',
205213
{

x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/default_configs.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { getMemoryUsageLensConfig } from './metrics/memory_usage_config';
1717
import { getNetworkActivityLensConfig } from './metrics/network_activity_config';
1818
import { getLogsFrequencyLensConfig } from './logs/logs_frequency_config';
1919
import { IIndexPattern } from '../../../../../../../../src/plugins/data/common/index_patterns';
20+
import { getCoreWebVitalsConfig } from './rum/core_web_vitals_config';
2021

2122
interface Props {
2223
reportType: keyof typeof ReportViewTypes;
@@ -30,6 +31,8 @@ export const getDefaultConfigs = ({ reportType, seriesId, indexPattern }: Props)
3031
return getPerformanceDistLensConfig({ seriesId, indexPattern });
3132
case 'kpi-trends':
3233
return getKPITrendsLensConfig({ seriesId, indexPattern });
34+
case 'core-web-vitals':
35+
return getCoreWebVitalsConfig({ seriesId, indexPattern });
3336
case 'uptime-duration':
3437
return getMonitorDurationConfig({ seriesId, indexPattern });
3538
case 'uptime-pings':

x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/lens_attributes.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,7 @@ describe('Lens Attribute', () => {
342342
orderBy: { columnId: 'y-axis-column', type: 'column' },
343343
orderDirection: 'desc',
344344
otherBucket: true,
345-
size: 3,
345+
size: 10,
346346
},
347347
scale: 'ordinal',
348348
sourceField: 'user_agent.name',

x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/lens_attributes.ts

Lines changed: 57 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,15 @@ import {
2424
OperationMetadata,
2525
FieldBasedIndexPatternColumn,
2626
SumIndexPatternColumn,
27+
TermsIndexPatternColumn,
2728
} from '../../../../../../lens/public';
2829
import {
2930
buildPhraseFilter,
3031
buildPhrasesFilter,
3132
IndexPattern,
3233
} from '../../../../../../../../src/plugins/data/common';
33-
import { FieldLabels } from './constants';
34-
import { DataSeries, UrlFilter, URLReportDefinition } from '../types';
34+
import { FieldLabels, FILTER_RECORDS, USE_BREAK_DOWN_COLUMN } from './constants';
35+
import { ColumnFilter, DataSeries, UrlFilter, URLReportDefinition } from '../types';
3536

3637
function getLayerReferenceName(layerId: string) {
3738
return `indexpattern-datasource-layer-${layerId}`;
@@ -53,6 +54,7 @@ export const parseCustomFieldName = (
5354
) => {
5455
let fieldName = sourceField;
5556
let columnType;
57+
let columnFilters;
5658

5759
const rdf = reportViewConfig.reportDefinitions ?? [];
5860

@@ -61,17 +63,21 @@ export const parseCustomFieldName = (
6163
if (customField) {
6264
if (selectedDefinitions[fieldName]) {
6365
fieldName = selectedDefinitions[fieldName][0];
64-
if (customField?.options)
65-
columnType = customField?.options?.find(({ field }) => field === fieldName)?.columnType;
66-
} else if (customField.defaultValue) {
67-
fieldName = customField.defaultValue;
68-
} else if (customField.options?.[0].field) {
69-
fieldName = customField.options?.[0].field;
66+
if (customField?.options) {
67+
const currField = customField?.options?.find(
68+
({ field, id }) => field === fieldName || id === fieldName
69+
);
70+
columnType = currField?.columnType;
71+
columnFilters = currField?.columnFilters;
72+
}
73+
} else if (customField.options?.[0].field || customField.options?.[0].id) {
74+
fieldName = customField.options?.[0].field || customField.options?.[0].id;
7075
columnType = customField.options?.[0].columnType;
76+
columnFilters = customField.options?.[0].columnFilters;
7177
}
7278
}
7379

74-
return { fieldName, columnType };
80+
return { fieldName, columnType, columnFilters };
7581
};
7682

7783
export class LensAttributes {
@@ -82,19 +88,22 @@ export class LensAttributes {
8288
seriesType: SeriesType;
8389
reportViewConfig: DataSeries;
8490
reportDefinitions: URLReportDefinition;
91+
breakdownSource?: string;
8592

8693
constructor(
8794
indexPattern: IndexPattern,
8895
reportViewConfig: DataSeries,
8996
seriesType?: SeriesType,
9097
filters?: UrlFilter[],
9198
operationType?: OperationType,
92-
reportDefinitions?: URLReportDefinition
99+
reportDefinitions?: URLReportDefinition,
100+
breakdownSource?: string
93101
) {
94102
this.indexPattern = indexPattern;
95103
this.layers = {};
96104
this.filters = filters ?? [];
97105
this.reportDefinitions = reportDefinitions ?? {};
106+
this.breakdownSource = breakdownSource;
98107

99108
if (operationType) {
100109
reportViewConfig.yAxisColumns.forEach((yAxisColumn) => {
@@ -109,24 +118,33 @@ export class LensAttributes {
109118
this.visualization = this.getXyState();
110119
}
111120

112-
addBreakdown(sourceField: string) {
121+
getBreakdownColumn(sourceField: string): TermsIndexPatternColumn {
113122
const fieldMeta = this.indexPattern.getFieldByName(sourceField);
114123

115-
this.layers.layer1.columns['break-down-column'] = {
124+
return {
116125
sourceField,
117126
label: `Top values of ${FieldLabels[sourceField]}`,
118127
dataType: fieldMeta?.type as DataType,
119128
operationType: 'terms',
120129
scale: 'ordinal',
121130
isBucketed: true,
122131
params: {
123-
size: 3,
132+
size: 10,
124133
orderBy: { type: 'column', columnId: 'y-axis-column' },
125134
orderDirection: 'desc',
126135
otherBucket: true,
127136
missingBucket: false,
128137
},
129138
};
139+
}
140+
141+
addBreakdown(sourceField: string) {
142+
const { xAxisColumn } = this.reportViewConfig;
143+
if (xAxisColumn?.sourceField === USE_BREAK_DOWN_COLUMN) {
144+
// do nothing since this will be used a x axis source
145+
return;
146+
}
147+
this.layers.layer1.columns['break-down-column'] = this.getBreakdownColumn(sourceField);
130148

131149
this.layers.layer1.columnOrder = [
132150
'x-axis-column',
@@ -229,15 +247,27 @@ export class LensAttributes {
229247
getXAxis() {
230248
const { xAxisColumn } = this.reportViewConfig;
231249

250+
if (xAxisColumn?.sourceField === USE_BREAK_DOWN_COLUMN) {
251+
return this.getBreakdownColumn(this.breakdownSource || this.reportViewConfig.breakdowns[0]);
252+
}
253+
232254
return this.getColumnBasedOnType(xAxisColumn.sourceField!, undefined, xAxisColumn.label);
233255
}
234256

235-
getColumnBasedOnType(sourceField: string, operationType?: OperationType, label?: string) {
236-
const { fieldMeta, columnType, fieldName } = this.getFieldMeta(sourceField);
257+
getColumnBasedOnType(
258+
sourceField: string,
259+
operationType?: OperationType,
260+
label?: string,
261+
colIndex?: number
262+
) {
263+
const { fieldMeta, columnType, fieldName, columnFilters } = this.getFieldMeta(sourceField);
237264
const { type: fieldType } = fieldMeta ?? {};
238265

239-
if (fieldName === 'Records') {
240-
return this.getRecordsColumn();
266+
if (fieldName === 'Records' || columnType === FILTER_RECORDS) {
267+
return this.getRecordsColumn(
268+
label,
269+
colIndex !== undefined ? columnFilters?.[colIndex] : undefined
270+
);
241271
}
242272

243273
if (fieldType === 'date') {
@@ -256,11 +286,11 @@ export class LensAttributes {
256286
}
257287

258288
getFieldMeta(sourceField: string) {
259-
const { fieldName, columnType } = this.getCustomFieldName(sourceField);
289+
const { fieldName, columnType, columnFilters } = this.getCustomFieldName(sourceField);
260290

261291
const fieldMeta = this.indexPattern.getFieldByName(fieldName);
262292

263-
return { fieldMeta, fieldName, columnType };
293+
return { fieldMeta, fieldName, columnType, columnFilters };
264294
}
265295

266296
getMainYAxis() {
@@ -270,7 +300,7 @@ export class LensAttributes {
270300
return this.getRecordsColumn(label);
271301
}
272302

273-
return this.getColumnBasedOnType(sourceField!, operationType, label);
303+
return this.getColumnBasedOnType(sourceField!, operationType, label, 0);
274304
}
275305

276306
getChildYAxises() {
@@ -286,20 +316,22 @@ export class LensAttributes {
286316
lensColumns[`y-axis-column-${i}`] = this.getColumnBasedOnType(
287317
sourceField!,
288318
operationType,
289-
label
319+
label,
320+
i
290321
);
291322
}
292323
return lensColumns;
293324
}
294325

295-
getRecordsColumn(label?: string): CountIndexPatternColumn {
326+
getRecordsColumn(label?: string, columnFilter?: ColumnFilter): CountIndexPatternColumn {
296327
return {
297328
dataType: 'number',
298329
isBucketed: false,
299330
label: label || 'Count of records',
300331
operationType: 'count',
301332
scale: 'ratio',
302333
sourceField: 'Records',
334+
filter: columnFilter,
303335
} as CountIndexPatternColumn;
304336
}
305337

@@ -331,7 +363,9 @@ export class LensAttributes {
331363
layerId: 'layer1',
332364
seriesType: this.seriesType ?? 'line',
333365
palette: this.reportViewConfig.palette,
334-
yConfig: [{ forAccessor: 'y-axis-column', color: 'green' }],
366+
yConfig: this.reportViewConfig.yConfig || [
367+
{ forAccessor: 'y-axis-column', color: 'green' },
368+
],
335369
xAccessor: 'x-axis-column',
336370
},
337371
],

0 commit comments

Comments
 (0)