[Exploratory view] Update types names (#103214)
This commit is contained in:
parent
2ff2a6fa50
commit
4f45535c90
|
@ -1,53 +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 { ConfigProps, DataSeries } from '../../types';
|
||||
import { FieldLabels } from '../constants';
|
||||
import { buildPhraseFilter } from '../utils';
|
||||
import { TRANSACTION_DURATION } from '../constants/elasticsearch_fieldnames';
|
||||
|
||||
export function getServiceLatencyLensConfig({ indexPattern }: ConfigProps): DataSeries {
|
||||
return {
|
||||
reportType: 'kpi-over-time',
|
||||
defaultSeriesType: 'line',
|
||||
seriesTypes: ['line', 'bar'],
|
||||
xAxisColumn: {
|
||||
sourceField: '@timestamp',
|
||||
},
|
||||
yAxisColumns: [
|
||||
{
|
||||
operationType: 'average',
|
||||
sourceField: 'transaction.duration.us',
|
||||
label: 'Latency',
|
||||
},
|
||||
],
|
||||
hasOperationType: true,
|
||||
defaultFilters: [
|
||||
'user_agent.name',
|
||||
'user_agent.os.name',
|
||||
'client.geo.country_name',
|
||||
'user_agent.device.name',
|
||||
],
|
||||
breakdowns: [
|
||||
'user_agent.name',
|
||||
'user_agent.os.name',
|
||||
'client.geo.country_name',
|
||||
'user_agent.device.name',
|
||||
],
|
||||
filters: buildPhraseFilter('transaction.type', 'request', indexPattern),
|
||||
labels: { ...FieldLabels, [TRANSACTION_DURATION]: 'Latency' },
|
||||
reportDefinitions: [
|
||||
{
|
||||
field: 'service.name',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
field: 'service.environment',
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
|
@ -96,3 +96,5 @@ export const USE_BREAK_DOWN_COLUMN = 'USE_BREAK_DOWN_COLUMN';
|
|||
export const FILTER_RECORDS = 'FILTER_RECORDS';
|
||||
export const TERMS_COLUMN = 'TERMS_COLUMN';
|
||||
export const OPERATION_COLUMN = 'operation';
|
||||
|
||||
export const REPORT_METRIC_FIELD = 'REPORT_METRIC_FIELD';
|
||||
|
|
|
@ -13,4 +13,5 @@ export enum URL_KEYS {
|
|||
BREAK_DOWN = 'bd',
|
||||
FILTERS = 'ft',
|
||||
REPORT_DEFINITIONS = 'rdf',
|
||||
SELECTED_METRIC = 'mt',
|
||||
}
|
||||
|
|
|
@ -9,8 +9,14 @@ import { LayerConfig, LensAttributes } from './lens_attributes';
|
|||
import { mockAppIndexPattern, mockIndexPattern } from '../rtl_helpers';
|
||||
import { getDefaultConfigs } from './default_configs';
|
||||
import { sampleAttribute } from './test_data/sample_attribute';
|
||||
import { LCP_FIELD, USER_AGENT_NAME } from './constants/elasticsearch_fieldnames';
|
||||
import {
|
||||
LCP_FIELD,
|
||||
TRANSACTION_DURATION,
|
||||
USER_AGENT_NAME,
|
||||
} from './constants/elasticsearch_fieldnames';
|
||||
import { buildExistsFilter, buildPhrasesFilter } from './utils';
|
||||
import { sampleAttributeKpi } from './test_data/sample_attribute_kpi';
|
||||
import { REPORT_METRIC_FIELD } from './constants';
|
||||
|
||||
describe('Lens Attribute', () => {
|
||||
mockAppIndexPattern();
|
||||
|
@ -21,12 +27,12 @@ describe('Lens Attribute', () => {
|
|||
indexPattern: mockIndexPattern,
|
||||
});
|
||||
|
||||
reportViewConfig.filters?.push(...buildExistsFilter('transaction.type', mockIndexPattern));
|
||||
reportViewConfig.baseFilters?.push(...buildExistsFilter('transaction.type', mockIndexPattern));
|
||||
|
||||
let lnsAttr: LensAttributes;
|
||||
|
||||
const layerConfig: LayerConfig = {
|
||||
reportConfig: reportViewConfig,
|
||||
seriesConfig: reportViewConfig,
|
||||
seriesType: 'line',
|
||||
operationType: 'count',
|
||||
indexPattern: mockIndexPattern,
|
||||
|
@ -42,6 +48,27 @@ describe('Lens Attribute', () => {
|
|||
expect(lnsAttr.getJSON()).toEqual(sampleAttribute);
|
||||
});
|
||||
|
||||
it('should return expected json for kpi report type', function () {
|
||||
const seriesConfigKpi = getDefaultConfigs({
|
||||
reportType: 'kpi-over-time',
|
||||
dataType: 'ux',
|
||||
indexPattern: mockIndexPattern,
|
||||
});
|
||||
|
||||
const lnsAttrKpi = new LensAttributes([
|
||||
{
|
||||
seriesConfig: seriesConfigKpi,
|
||||
seriesType: 'line',
|
||||
operationType: 'count',
|
||||
indexPattern: mockIndexPattern,
|
||||
reportDefinitions: { 'service.name': ['elastic-co'] },
|
||||
time: { from: 'now-15m', to: 'now' },
|
||||
},
|
||||
]);
|
||||
|
||||
expect(lnsAttrKpi.getJSON()).toEqual(sampleAttributeKpi);
|
||||
});
|
||||
|
||||
it('should return main y axis', function () {
|
||||
expect(lnsAttr.getMainYAxis(layerConfig)).toEqual({
|
||||
dataType: 'number',
|
||||
|
@ -72,7 +99,7 @@ describe('Lens Attribute', () => {
|
|||
});
|
||||
|
||||
it('should return expected field type for custom field with default value', function () {
|
||||
expect(JSON.stringify(lnsAttr.getFieldMeta('performance.metric', layerConfig))).toEqual(
|
||||
expect(JSON.stringify(lnsAttr.getFieldMeta(REPORT_METRIC_FIELD, layerConfig))).toEqual(
|
||||
JSON.stringify({
|
||||
fieldMeta: {
|
||||
count: 0,
|
||||
|
@ -92,7 +119,7 @@ describe('Lens Attribute', () => {
|
|||
|
||||
it('should return expected field type for custom field with passed value', function () {
|
||||
const layerConfig1: LayerConfig = {
|
||||
reportConfig: reportViewConfig,
|
||||
seriesConfig: reportViewConfig,
|
||||
seriesType: 'line',
|
||||
operationType: 'count',
|
||||
indexPattern: mockIndexPattern,
|
||||
|
@ -102,20 +129,20 @@ describe('Lens Attribute', () => {
|
|||
|
||||
lnsAttr = new LensAttributes([layerConfig1]);
|
||||
|
||||
expect(JSON.stringify(lnsAttr.getFieldMeta('performance.metric', layerConfig1))).toEqual(
|
||||
expect(JSON.stringify(lnsAttr.getFieldMeta(REPORT_METRIC_FIELD, layerConfig1))).toEqual(
|
||||
JSON.stringify({
|
||||
fieldMeta: {
|
||||
count: 0,
|
||||
name: LCP_FIELD,
|
||||
name: TRANSACTION_DURATION,
|
||||
type: 'number',
|
||||
esTypes: ['scaled_float'],
|
||||
esTypes: ['long'],
|
||||
scripted: false,
|
||||
searchable: true,
|
||||
aggregatable: true,
|
||||
readFromDocValues: true,
|
||||
},
|
||||
fieldName: LCP_FIELD,
|
||||
columnLabel: 'Largest contentful paint',
|
||||
fieldName: TRANSACTION_DURATION,
|
||||
columnLabel: 'Page load time',
|
||||
})
|
||||
);
|
||||
});
|
||||
|
@ -269,7 +296,7 @@ describe('Lens Attribute', () => {
|
|||
describe('Layer breakdowns', function () {
|
||||
it('should return breakdown column', function () {
|
||||
const layerConfig1: LayerConfig = {
|
||||
reportConfig: reportViewConfig,
|
||||
seriesConfig: reportViewConfig,
|
||||
seriesType: 'line',
|
||||
operationType: 'count',
|
||||
indexPattern: mockIndexPattern,
|
||||
|
@ -322,7 +349,7 @@ describe('Lens Attribute', () => {
|
|||
'x-axis-column-layer0': {
|
||||
dataType: 'number',
|
||||
isBucketed: true,
|
||||
label: 'Largest contentful paint',
|
||||
label: 'Page load time',
|
||||
operationType: 'range',
|
||||
params: {
|
||||
maxBars: 'auto',
|
||||
|
@ -330,7 +357,7 @@ describe('Lens Attribute', () => {
|
|||
type: 'histogram',
|
||||
},
|
||||
scale: 'interval',
|
||||
sourceField: 'transaction.marks.agent.largestContentfulPaint',
|
||||
sourceField: 'transaction.duration.us',
|
||||
},
|
||||
'y-axis-column-layer0': {
|
||||
dataType: 'number',
|
||||
|
@ -353,12 +380,12 @@ describe('Lens Attribute', () => {
|
|||
|
||||
describe('Layer Filters', function () {
|
||||
it('should return expected filters', function () {
|
||||
reportViewConfig.filters?.push(
|
||||
reportViewConfig.baseFilters?.push(
|
||||
...buildPhrasesFilter('service.name', ['elastic', 'kibana'], mockIndexPattern)
|
||||
);
|
||||
|
||||
const layerConfig1: LayerConfig = {
|
||||
reportConfig: reportViewConfig,
|
||||
seriesConfig: reportViewConfig,
|
||||
seriesType: 'line',
|
||||
operationType: 'count',
|
||||
indexPattern: mockIndexPattern,
|
||||
|
|
|
@ -29,8 +29,14 @@ import {
|
|||
} from '../../../../../../lens/public';
|
||||
import { urlFiltersToKueryString } from '../utils/stringify_kueries';
|
||||
import { ExistsFilter, IndexPattern } from '../../../../../../../../src/plugins/data/common';
|
||||
import { FieldLabels, FILTER_RECORDS, USE_BREAK_DOWN_COLUMN, TERMS_COLUMN } from './constants';
|
||||
import { ColumnFilter, DataSeries, UrlFilter, URLReportDefinition } from '../types';
|
||||
import {
|
||||
FieldLabels,
|
||||
FILTER_RECORDS,
|
||||
USE_BREAK_DOWN_COLUMN,
|
||||
TERMS_COLUMN,
|
||||
REPORT_METRIC_FIELD,
|
||||
} from './constants';
|
||||
import { ColumnFilter, SeriesConfig, UrlFilter, URLReportDefinition } from '../types';
|
||||
import { PersistableFilter } from '../../../../../../lens/common';
|
||||
import { parseAbsoluteDate } from '../series_date_picker/date_range_picker';
|
||||
|
||||
|
@ -47,54 +53,47 @@ function buildNumberColumn(sourceField: string) {
|
|||
};
|
||||
}
|
||||
|
||||
export const parseCustomFieldName = (
|
||||
sourceField: string,
|
||||
reportViewConfig: DataSeries,
|
||||
selectedDefinitions: URLReportDefinition
|
||||
) => {
|
||||
let fieldName = sourceField;
|
||||
export const parseCustomFieldName = (seriesConfig: SeriesConfig, selectedMetricField?: string) => {
|
||||
let columnType;
|
||||
let columnFilters;
|
||||
let timeScale;
|
||||
let columnLabel;
|
||||
|
||||
const rdf = reportViewConfig.reportDefinitions ?? [];
|
||||
const metricOptions = seriesConfig.metricOptions ?? [];
|
||||
|
||||
const customField = rdf.find(({ field }) => field === fieldName);
|
||||
|
||||
if (customField) {
|
||||
if (selectedDefinitions[fieldName]) {
|
||||
fieldName = selectedDefinitions[fieldName][0];
|
||||
if (customField?.options) {
|
||||
const currField = customField?.options?.find(
|
||||
({ field, id }) => field === fieldName || id === fieldName
|
||||
);
|
||||
columnType = currField?.columnType;
|
||||
columnFilters = currField?.columnFilters;
|
||||
timeScale = currField?.timeScale;
|
||||
columnLabel = currField?.label;
|
||||
}
|
||||
} else if (customField.options?.[0].field || customField.options?.[0].id) {
|
||||
fieldName = customField.options?.[0].field || customField.options?.[0].id;
|
||||
columnType = customField.options?.[0].columnType;
|
||||
columnFilters = customField.options?.[0].columnFilters;
|
||||
timeScale = customField.options?.[0].timeScale;
|
||||
columnLabel = customField.options?.[0].label;
|
||||
if (selectedMetricField) {
|
||||
if (metricOptions) {
|
||||
const currField = metricOptions.find(
|
||||
({ field, id }) => field === selectedMetricField || id === selectedMetricField
|
||||
);
|
||||
columnType = currField?.columnType;
|
||||
columnFilters = currField?.columnFilters;
|
||||
timeScale = currField?.timeScale;
|
||||
columnLabel = currField?.label;
|
||||
}
|
||||
} else if (metricOptions?.[0].field || metricOptions?.[0].id) {
|
||||
const firstMetricOption = metricOptions?.[0];
|
||||
|
||||
selectedMetricField = firstMetricOption.field || firstMetricOption.id;
|
||||
columnType = firstMetricOption.columnType;
|
||||
columnFilters = firstMetricOption.columnFilters;
|
||||
timeScale = firstMetricOption.timeScale;
|
||||
columnLabel = firstMetricOption.label;
|
||||
}
|
||||
|
||||
return { fieldName, columnType, columnFilters, timeScale, columnLabel };
|
||||
return { fieldName: selectedMetricField!, columnType, columnFilters, timeScale, columnLabel };
|
||||
};
|
||||
|
||||
export interface LayerConfig {
|
||||
filters?: UrlFilter[];
|
||||
reportConfig: DataSeries;
|
||||
seriesConfig: SeriesConfig;
|
||||
breakdown?: string;
|
||||
seriesType?: SeriesType;
|
||||
operationType?: OperationType;
|
||||
reportDefinitions: URLReportDefinition;
|
||||
time: { to: string; from: string };
|
||||
indexPattern: IndexPattern;
|
||||
selectedMetricField?: string;
|
||||
}
|
||||
|
||||
export class LensAttributes {
|
||||
|
@ -105,9 +104,9 @@ export class LensAttributes {
|
|||
constructor(layerConfigs: LayerConfig[]) {
|
||||
this.layers = {};
|
||||
|
||||
layerConfigs.forEach(({ reportConfig, operationType }) => {
|
||||
layerConfigs.forEach(({ seriesConfig, operationType }) => {
|
||||
if (operationType) {
|
||||
reportConfig.yAxisColumns.forEach((yAxisColumn) => {
|
||||
seriesConfig.yAxisColumns.forEach((yAxisColumn) => {
|
||||
if (typeof yAxisColumn.operationType !== undefined) {
|
||||
yAxisColumn.operationType = operationType as FieldBasedIndexPatternColumn['operationType'];
|
||||
}
|
||||
|
@ -150,12 +149,12 @@ export class LensAttributes {
|
|||
|
||||
getNumberRangeColumn(
|
||||
sourceField: string,
|
||||
reportViewConfig: DataSeries,
|
||||
seriesConfig: SeriesConfig,
|
||||
label?: string
|
||||
): RangeIndexPatternColumn {
|
||||
return {
|
||||
sourceField,
|
||||
label: reportViewConfig.labels[sourceField] ?? label,
|
||||
label: seriesConfig.labels[sourceField] ?? label,
|
||||
dataType: 'number',
|
||||
operationType: 'range',
|
||||
isBucketed: true,
|
||||
|
@ -171,22 +170,22 @@ export class LensAttributes {
|
|||
getCardinalityColumn({
|
||||
sourceField,
|
||||
label,
|
||||
reportViewConfig,
|
||||
seriesConfig,
|
||||
}: {
|
||||
sourceField: string;
|
||||
label?: string;
|
||||
reportViewConfig: DataSeries;
|
||||
seriesConfig: SeriesConfig;
|
||||
}) {
|
||||
return this.getNumberOperationColumn({
|
||||
sourceField,
|
||||
operationType: 'unique_count',
|
||||
label,
|
||||
reportViewConfig,
|
||||
seriesConfig,
|
||||
});
|
||||
}
|
||||
|
||||
getNumberColumn({
|
||||
reportViewConfig,
|
||||
seriesConfig,
|
||||
label,
|
||||
sourceField,
|
||||
columnType,
|
||||
|
@ -196,7 +195,7 @@ export class LensAttributes {
|
|||
columnType?: string;
|
||||
operationType?: string;
|
||||
label?: string;
|
||||
reportViewConfig: DataSeries;
|
||||
seriesConfig: SeriesConfig;
|
||||
}) {
|
||||
if (columnType === 'operation' || operationType) {
|
||||
if (
|
||||
|
@ -209,26 +208,26 @@ export class LensAttributes {
|
|||
sourceField,
|
||||
operationType,
|
||||
label,
|
||||
reportViewConfig,
|
||||
seriesConfig,
|
||||
});
|
||||
}
|
||||
if (operationType?.includes('th')) {
|
||||
return this.getPercentileNumberColumn(sourceField, operationType, reportViewConfig!);
|
||||
return this.getPercentileNumberColumn(sourceField, operationType, seriesConfig!);
|
||||
}
|
||||
}
|
||||
return this.getNumberRangeColumn(sourceField, reportViewConfig!, label);
|
||||
return this.getNumberRangeColumn(sourceField, seriesConfig!, label);
|
||||
}
|
||||
|
||||
getNumberOperationColumn({
|
||||
sourceField,
|
||||
label,
|
||||
reportViewConfig,
|
||||
seriesConfig,
|
||||
operationType,
|
||||
}: {
|
||||
sourceField: string;
|
||||
operationType: 'average' | 'median' | 'sum' | 'unique_count';
|
||||
label?: string;
|
||||
reportViewConfig: DataSeries;
|
||||
seriesConfig: SeriesConfig;
|
||||
}):
|
||||
| AvgIndexPatternColumn
|
||||
| MedianIndexPatternColumn
|
||||
|
@ -239,7 +238,7 @@ export class LensAttributes {
|
|||
label: i18n.translate('xpack.observability.expView.columns.operation.label', {
|
||||
defaultMessage: '{operationType} of {sourceField}',
|
||||
values: {
|
||||
sourceField: label || reportViewConfig.labels[sourceField],
|
||||
sourceField: label || seriesConfig.labels[sourceField],
|
||||
operationType: capitalize(operationType),
|
||||
},
|
||||
}),
|
||||
|
@ -250,13 +249,13 @@ export class LensAttributes {
|
|||
getPercentileNumberColumn(
|
||||
sourceField: string,
|
||||
percentileValue: string,
|
||||
reportViewConfig: DataSeries
|
||||
seriesConfig: SeriesConfig
|
||||
): PercentileIndexPatternColumn {
|
||||
return {
|
||||
...buildNumberColumn(sourceField),
|
||||
label: i18n.translate('xpack.observability.expView.columns.label', {
|
||||
defaultMessage: '{percentileValue} percentile of {sourceField}',
|
||||
values: { sourceField: reportViewConfig.labels[sourceField], percentileValue },
|
||||
values: { sourceField: seriesConfig.labels[sourceField], percentileValue },
|
||||
}),
|
||||
operationType: 'percentile',
|
||||
params: { percentile: Number(percentileValue.split('th')[0]) },
|
||||
|
@ -295,13 +294,13 @@ export class LensAttributes {
|
|||
}
|
||||
|
||||
getXAxis(layerConfig: LayerConfig, layerId: string) {
|
||||
const { xAxisColumn } = layerConfig.reportConfig;
|
||||
const { xAxisColumn } = layerConfig.seriesConfig;
|
||||
|
||||
if (xAxisColumn?.sourceField === USE_BREAK_DOWN_COLUMN) {
|
||||
return this.getBreakdownColumn({
|
||||
layerId,
|
||||
indexPattern: layerConfig.indexPattern,
|
||||
sourceField: layerConfig.breakdown || layerConfig.reportConfig.breakdowns[0],
|
||||
sourceField: layerConfig.breakdown || layerConfig.seriesConfig.breakdownFields[0],
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -333,6 +332,7 @@ export class LensAttributes {
|
|||
timeScale,
|
||||
columnFilters,
|
||||
} = this.getFieldMeta(sourceField, layerConfig);
|
||||
|
||||
const { type: fieldType } = fieldMeta ?? {};
|
||||
|
||||
if (columnType === TERMS_COLUMN) {
|
||||
|
@ -356,14 +356,14 @@ export class LensAttributes {
|
|||
columnType,
|
||||
operationType,
|
||||
label: columnLabel || label,
|
||||
reportViewConfig: layerConfig.reportConfig,
|
||||
seriesConfig: layerConfig.seriesConfig,
|
||||
});
|
||||
}
|
||||
if (operationType === 'unique_count') {
|
||||
return this.getCardinalityColumn({
|
||||
sourceField: fieldName,
|
||||
label: columnLabel || label,
|
||||
reportViewConfig: layerConfig.reportConfig,
|
||||
seriesConfig: layerConfig.seriesConfig,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -378,32 +378,26 @@ export class LensAttributes {
|
|||
sourceField: string;
|
||||
layerConfig: LayerConfig;
|
||||
}) {
|
||||
return parseCustomFieldName(
|
||||
sourceField,
|
||||
layerConfig.reportConfig,
|
||||
layerConfig.reportDefinitions
|
||||
);
|
||||
return parseCustomFieldName(layerConfig.seriesConfig, sourceField);
|
||||
}
|
||||
|
||||
getFieldMeta(sourceField: string, layerConfig: LayerConfig) {
|
||||
const {
|
||||
fieldName,
|
||||
columnType,
|
||||
columnLabel,
|
||||
columnFilters,
|
||||
timeScale,
|
||||
} = this.getCustomFieldName({
|
||||
sourceField,
|
||||
layerConfig,
|
||||
});
|
||||
if (sourceField === REPORT_METRIC_FIELD) {
|
||||
const { fieldName, columnType, columnLabel, columnFilters, timeScale } = parseCustomFieldName(
|
||||
layerConfig.seriesConfig,
|
||||
layerConfig.selectedMetricField
|
||||
);
|
||||
const fieldMeta = layerConfig.indexPattern.getFieldByName(fieldName!);
|
||||
return { fieldMeta, fieldName, columnType, columnLabel, columnFilters, timeScale };
|
||||
} else {
|
||||
const fieldMeta = layerConfig.indexPattern.getFieldByName(sourceField);
|
||||
|
||||
const fieldMeta = layerConfig.indexPattern.getFieldByName(fieldName);
|
||||
|
||||
return { fieldMeta, fieldName, columnType, columnLabel, columnFilters, timeScale };
|
||||
return { fieldMeta, fieldName: sourceField };
|
||||
}
|
||||
}
|
||||
|
||||
getMainYAxis(layerConfig: LayerConfig) {
|
||||
const { sourceField, operationType, label } = layerConfig.reportConfig.yAxisColumns[0];
|
||||
const { sourceField, operationType, label } = layerConfig.seriesConfig.yAxisColumns[0];
|
||||
|
||||
if (sourceField === 'Records' || !sourceField) {
|
||||
return this.getRecordsColumn(label);
|
||||
|
@ -420,7 +414,7 @@ export class LensAttributes {
|
|||
|
||||
getChildYAxises(layerConfig: LayerConfig) {
|
||||
const lensColumns: Record<string, FieldBasedIndexPatternColumn | SumIndexPatternColumn> = {};
|
||||
const yAxisColumns = layerConfig.reportConfig.yAxisColumns;
|
||||
const yAxisColumns = layerConfig.seriesConfig.yAxisColumns;
|
||||
// 1 means there is only main y axis
|
||||
if (yAxisColumns.length === 1) {
|
||||
return lensColumns;
|
||||
|
@ -460,7 +454,7 @@ export class LensAttributes {
|
|||
const {
|
||||
filters,
|
||||
time: { from, to },
|
||||
reportConfig: { filters: layerFilters, reportType },
|
||||
seriesConfig: { baseFilters: layerFilters, reportType },
|
||||
} = layerConfig;
|
||||
let baseFilters = '';
|
||||
if (reportType !== 'kpi-over-time' && totalLayers > 1) {
|
||||
|
@ -522,7 +516,7 @@ export class LensAttributes {
|
|||
}
|
||||
|
||||
getTimeShift(mainLayerConfig: LayerConfig, layerConfig: LayerConfig, index: number) {
|
||||
if (index === 0 || mainLayerConfig.reportConfig.reportType !== 'kpi-over-time') {
|
||||
if (index === 0 || mainLayerConfig.seriesConfig.reportType !== 'kpi-over-time') {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -603,16 +597,16 @@ export class LensAttributes {
|
|||
...Object.keys(this.getChildYAxises(layerConfig)),
|
||||
],
|
||||
layerId: `layer${index}`,
|
||||
seriesType: layerConfig.seriesType || layerConfig.reportConfig.defaultSeriesType,
|
||||
palette: layerConfig.reportConfig.palette,
|
||||
yConfig: layerConfig.reportConfig.yConfig || [
|
||||
seriesType: layerConfig.seriesType || layerConfig.seriesConfig.defaultSeriesType,
|
||||
palette: layerConfig.seriesConfig.palette,
|
||||
yConfig: layerConfig.seriesConfig.yConfig || [
|
||||
{ forAccessor: `y-axis-column-layer${index}` },
|
||||
],
|
||||
xAccessor: `x-axis-column-layer${index}`,
|
||||
...(layerConfig.breakdown ? { splitAccessor: `breakdown-column-layer${index}` } : {}),
|
||||
})),
|
||||
...(this.layerConfigs[0].reportConfig.yTitle
|
||||
? { yTitle: this.layerConfigs[0].reportConfig.yTitle }
|
||||
...(this.layerConfigs[0].seriesConfig.yTitle
|
||||
? { yTitle: this.layerConfigs[0].seriesConfig.yTitle }
|
||||
: {}),
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,38 +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 { DataSeries, ConfigProps } from '../../types';
|
||||
import { FieldLabels } from '../constants';
|
||||
|
||||
export function getCPUUsageLensConfig({}: ConfigProps): DataSeries {
|
||||
return {
|
||||
reportType: 'kpi-over-time',
|
||||
defaultSeriesType: 'line',
|
||||
seriesTypes: ['line', 'bar'],
|
||||
xAxisColumn: {
|
||||
sourceField: '@timestamp',
|
||||
},
|
||||
yAxisColumns: [
|
||||
{
|
||||
operationType: 'average',
|
||||
sourceField: 'system.cpu.user.pct',
|
||||
label: 'CPU Usage %',
|
||||
},
|
||||
],
|
||||
hasOperationType: true,
|
||||
defaultFilters: [],
|
||||
breakdowns: ['host.hostname'],
|
||||
filters: [],
|
||||
labels: { ...FieldLabels, 'host.hostname': 'Host name' },
|
||||
reportDefinitions: [
|
||||
{
|
||||
field: 'agent.hostname',
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
|
@ -1,38 +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 { DataSeries, ConfigProps } from '../../types';
|
||||
import { FieldLabels } from '../constants';
|
||||
|
||||
export function getMemoryUsageLensConfig({}: ConfigProps): DataSeries {
|
||||
return {
|
||||
reportType: 'kpi-over-time',
|
||||
defaultSeriesType: 'line',
|
||||
seriesTypes: ['line', 'bar'],
|
||||
xAxisColumn: {
|
||||
sourceField: '@timestamp',
|
||||
},
|
||||
yAxisColumns: [
|
||||
{
|
||||
operationType: 'average',
|
||||
sourceField: 'system.memory.used.pct',
|
||||
label: 'Memory Usage %',
|
||||
},
|
||||
],
|
||||
hasOperationType: true,
|
||||
defaultFilters: [],
|
||||
breakdowns: ['host.hostname'],
|
||||
filters: [],
|
||||
labels: { ...FieldLabels, 'host.hostname': 'Host name' },
|
||||
reportDefinitions: [
|
||||
{
|
||||
field: 'host.hostname',
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
|
@ -1,37 +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 { DataSeries, ConfigProps } from '../../types';
|
||||
import { FieldLabels } from '../constants';
|
||||
|
||||
export function getNetworkActivityLensConfig({}: ConfigProps): DataSeries {
|
||||
return {
|
||||
reportType: 'kpi-over-time',
|
||||
defaultSeriesType: 'line',
|
||||
seriesTypes: ['line', 'bar'],
|
||||
xAxisColumn: {
|
||||
sourceField: '@timestamp',
|
||||
},
|
||||
yAxisColumns: [
|
||||
{
|
||||
operationType: 'average',
|
||||
sourceField: 'system.memory.used.pct',
|
||||
},
|
||||
],
|
||||
hasOperationType: true,
|
||||
defaultFilters: [],
|
||||
breakdowns: ['host.hostname'],
|
||||
filters: [],
|
||||
labels: { ...FieldLabels, 'host.hostname': 'Host name' },
|
||||
reportDefinitions: [
|
||||
{
|
||||
field: 'host.hostname',
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
|
@ -5,14 +5,14 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { ConfigProps, DataSeries } from '../../types';
|
||||
import { ConfigProps, SeriesConfig } from '../../types';
|
||||
import { FieldLabels, USE_BREAK_DOWN_COLUMN } from '../constants';
|
||||
import { buildPhraseFilter } from '../utils';
|
||||
import { SERVICE_NAME } from '../constants/elasticsearch_fieldnames';
|
||||
import { MOBILE_APP, NUMBER_OF_DEVICES } from '../constants/labels';
|
||||
import { MobileFields } from './mobile_fields';
|
||||
|
||||
export function getMobileDeviceDistributionConfig({ indexPattern }: ConfigProps): DataSeries {
|
||||
export function getMobileDeviceDistributionConfig({ indexPattern }: ConfigProps): SeriesConfig {
|
||||
return {
|
||||
reportType: 'device-data-distribution',
|
||||
defaultSeriesType: 'bar',
|
||||
|
@ -28,9 +28,9 @@ export function getMobileDeviceDistributionConfig({ indexPattern }: ConfigProps)
|
|||
},
|
||||
],
|
||||
hasOperationType: false,
|
||||
defaultFilters: Object.keys(MobileFields),
|
||||
breakdowns: Object.keys(MobileFields),
|
||||
filters: [
|
||||
filterFields: Object.keys(MobileFields),
|
||||
breakdownFields: Object.keys(MobileFields),
|
||||
baseFilters: [
|
||||
...buildPhraseFilter('agent.name', 'iOS/swift', indexPattern),
|
||||
...buildPhraseFilter('processor.event', 'transaction', indexPattern),
|
||||
],
|
||||
|
@ -39,11 +39,6 @@ export function getMobileDeviceDistributionConfig({ indexPattern }: ConfigProps)
|
|||
...MobileFields,
|
||||
[SERVICE_NAME]: MOBILE_APP,
|
||||
},
|
||||
reportDefinitions: [
|
||||
{
|
||||
field: SERVICE_NAME,
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
definitionFields: [SERVICE_NAME],
|
||||
};
|
||||
}
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { ConfigProps, DataSeries } from '../../types';
|
||||
import { FieldLabels, OPERATION_COLUMN, RECORDS_FIELD } from '../constants';
|
||||
import { ConfigProps, SeriesConfig } from '../../types';
|
||||
import { FieldLabels, OPERATION_COLUMN, RECORDS_FIELD, REPORT_METRIC_FIELD } from '../constants';
|
||||
import { buildPhrasesFilter } from '../utils';
|
||||
import {
|
||||
METRIC_SYSTEM_CPU_USAGE,
|
||||
|
@ -19,13 +19,13 @@ import {
|
|||
import { CPU_USAGE, MEMORY_USAGE, MOBILE_APP, RESPONSE_LATENCY } from '../constants/labels';
|
||||
import { MobileFields } from './mobile_fields';
|
||||
|
||||
export function getMobileKPIDistributionConfig({ indexPattern }: ConfigProps): DataSeries {
|
||||
export function getMobileKPIDistributionConfig({ indexPattern }: ConfigProps): SeriesConfig {
|
||||
return {
|
||||
reportType: 'data-distribution',
|
||||
defaultSeriesType: 'bar',
|
||||
seriesTypes: ['line', 'bar'],
|
||||
xAxisColumn: {
|
||||
sourceField: 'performance.metric',
|
||||
sourceField: REPORT_METRIC_FIELD,
|
||||
},
|
||||
yAxisColumns: [
|
||||
{
|
||||
|
@ -33,9 +33,9 @@ export function getMobileKPIDistributionConfig({ indexPattern }: ConfigProps): D
|
|||
},
|
||||
],
|
||||
hasOperationType: false,
|
||||
defaultFilters: Object.keys(MobileFields),
|
||||
breakdowns: Object.keys(MobileFields),
|
||||
filters: [
|
||||
filterFields: Object.keys(MobileFields),
|
||||
breakdownFields: Object.keys(MobileFields),
|
||||
baseFilters: [
|
||||
...buildPhrasesFilter('agent.name', ['iOS/swift', 'open-telemetry/swift'], indexPattern),
|
||||
],
|
||||
labels: {
|
||||
|
@ -43,38 +43,25 @@ export function getMobileKPIDistributionConfig({ indexPattern }: ConfigProps): D
|
|||
...MobileFields,
|
||||
[SERVICE_NAME]: MOBILE_APP,
|
||||
},
|
||||
reportDefinitions: [
|
||||
definitionFields: [SERVICE_NAME, SERVICE_ENVIRONMENT],
|
||||
metricOptions: [
|
||||
{
|
||||
field: SERVICE_NAME,
|
||||
required: true,
|
||||
label: RESPONSE_LATENCY,
|
||||
field: TRANSACTION_DURATION,
|
||||
id: TRANSACTION_DURATION,
|
||||
columnType: OPERATION_COLUMN,
|
||||
},
|
||||
{
|
||||
field: SERVICE_ENVIRONMENT,
|
||||
required: true,
|
||||
label: MEMORY_USAGE,
|
||||
field: METRIC_SYSTEM_MEMORY_USAGE,
|
||||
id: METRIC_SYSTEM_MEMORY_USAGE,
|
||||
columnType: OPERATION_COLUMN,
|
||||
},
|
||||
{
|
||||
field: 'performance.metric',
|
||||
custom: true,
|
||||
options: [
|
||||
{
|
||||
label: RESPONSE_LATENCY,
|
||||
field: TRANSACTION_DURATION,
|
||||
id: TRANSACTION_DURATION,
|
||||
columnType: OPERATION_COLUMN,
|
||||
},
|
||||
{
|
||||
label: MEMORY_USAGE,
|
||||
field: METRIC_SYSTEM_MEMORY_USAGE,
|
||||
id: METRIC_SYSTEM_MEMORY_USAGE,
|
||||
columnType: OPERATION_COLUMN,
|
||||
},
|
||||
{
|
||||
label: CPU_USAGE,
|
||||
field: METRIC_SYSTEM_CPU_USAGE,
|
||||
id: METRIC_SYSTEM_CPU_USAGE,
|
||||
columnType: OPERATION_COLUMN,
|
||||
},
|
||||
],
|
||||
label: CPU_USAGE,
|
||||
field: METRIC_SYSTEM_CPU_USAGE,
|
||||
id: METRIC_SYSTEM_CPU_USAGE,
|
||||
columnType: OPERATION_COLUMN,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { ConfigProps, DataSeries } from '../../types';
|
||||
import { FieldLabels, OPERATION_COLUMN, RECORDS_FIELD } from '../constants';
|
||||
import { ConfigProps, SeriesConfig } from '../../types';
|
||||
import { FieldLabels, OPERATION_COLUMN, RECORDS_FIELD, REPORT_METRIC_FIELD } from '../constants';
|
||||
import { buildPhrasesFilter } from '../utils';
|
||||
import {
|
||||
METRIC_SYSTEM_CPU_USAGE,
|
||||
|
@ -24,7 +24,7 @@ import {
|
|||
} from '../constants/labels';
|
||||
import { MobileFields } from './mobile_fields';
|
||||
|
||||
export function getMobileKPIConfig({ indexPattern }: ConfigProps): DataSeries {
|
||||
export function getMobileKPIConfig({ indexPattern }: ConfigProps): SeriesConfig {
|
||||
return {
|
||||
reportType: 'kpi-over-time',
|
||||
defaultSeriesType: 'line',
|
||||
|
@ -34,14 +34,14 @@ export function getMobileKPIConfig({ indexPattern }: ConfigProps): DataSeries {
|
|||
},
|
||||
yAxisColumns: [
|
||||
{
|
||||
sourceField: 'business.kpi',
|
||||
sourceField: REPORT_METRIC_FIELD,
|
||||
operationType: 'median',
|
||||
},
|
||||
],
|
||||
hasOperationType: true,
|
||||
defaultFilters: Object.keys(MobileFields),
|
||||
breakdowns: Object.keys(MobileFields),
|
||||
filters: [
|
||||
filterFields: Object.keys(MobileFields),
|
||||
breakdownFields: Object.keys(MobileFields),
|
||||
baseFilters: [
|
||||
...buildPhrasesFilter('agent.name', ['iOS/swift', 'open-telemetry/swift'], indexPattern),
|
||||
],
|
||||
labels: {
|
||||
|
@ -52,50 +52,37 @@ export function getMobileKPIConfig({ indexPattern }: ConfigProps): DataSeries {
|
|||
[METRIC_SYSTEM_MEMORY_USAGE]: MEMORY_USAGE,
|
||||
[METRIC_SYSTEM_CPU_USAGE]: CPU_USAGE,
|
||||
},
|
||||
reportDefinitions: [
|
||||
definitionFields: [SERVICE_NAME, SERVICE_ENVIRONMENT],
|
||||
metricOptions: [
|
||||
{
|
||||
field: SERVICE_NAME,
|
||||
required: true,
|
||||
label: RESPONSE_LATENCY,
|
||||
field: TRANSACTION_DURATION,
|
||||
id: TRANSACTION_DURATION,
|
||||
columnType: OPERATION_COLUMN,
|
||||
},
|
||||
{
|
||||
field: SERVICE_ENVIRONMENT,
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
field: 'business.kpi',
|
||||
custom: true,
|
||||
options: [
|
||||
field: RECORDS_FIELD,
|
||||
id: RECORDS_FIELD,
|
||||
label: TRANSACTIONS_PER_MINUTE,
|
||||
columnFilters: [
|
||||
{
|
||||
label: RESPONSE_LATENCY,
|
||||
field: TRANSACTION_DURATION,
|
||||
id: TRANSACTION_DURATION,
|
||||
columnType: OPERATION_COLUMN,
|
||||
},
|
||||
{
|
||||
field: RECORDS_FIELD,
|
||||
id: RECORDS_FIELD,
|
||||
label: TRANSACTIONS_PER_MINUTE,
|
||||
columnFilters: [
|
||||
{
|
||||
language: 'kuery',
|
||||
query: `processor.event: transaction`,
|
||||
},
|
||||
],
|
||||
timeScale: 'm',
|
||||
},
|
||||
{
|
||||
label: MEMORY_USAGE,
|
||||
field: METRIC_SYSTEM_MEMORY_USAGE,
|
||||
id: METRIC_SYSTEM_MEMORY_USAGE,
|
||||
columnType: OPERATION_COLUMN,
|
||||
},
|
||||
{
|
||||
label: CPU_USAGE,
|
||||
field: METRIC_SYSTEM_CPU_USAGE,
|
||||
id: METRIC_SYSTEM_CPU_USAGE,
|
||||
columnType: OPERATION_COLUMN,
|
||||
language: 'kuery',
|
||||
query: `processor.event: transaction`,
|
||||
},
|
||||
],
|
||||
timeScale: 'm',
|
||||
},
|
||||
{
|
||||
label: MEMORY_USAGE,
|
||||
field: METRIC_SYSTEM_MEMORY_USAGE,
|
||||
id: METRIC_SYSTEM_MEMORY_USAGE,
|
||||
columnType: OPERATION_COLUMN,
|
||||
},
|
||||
{
|
||||
label: CPU_USAGE,
|
||||
field: METRIC_SYSTEM_CPU_USAGE,
|
||||
id: METRIC_SYSTEM_CPU_USAGE,
|
||||
columnType: OPERATION_COLUMN,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
|
|
@ -6,8 +6,13 @@
|
|||
*/
|
||||
|
||||
import { euiPaletteForStatus } from '@elastic/eui';
|
||||
import { ConfigProps, DataSeries } from '../../types';
|
||||
import { FieldLabels, FILTER_RECORDS, USE_BREAK_DOWN_COLUMN } from '../constants';
|
||||
import { ConfigProps, SeriesConfig } from '../../types';
|
||||
import {
|
||||
FieldLabels,
|
||||
FILTER_RECORDS,
|
||||
REPORT_METRIC_FIELD,
|
||||
USE_BREAK_DOWN_COLUMN,
|
||||
} from '../constants';
|
||||
import { buildPhraseFilter } from '../utils';
|
||||
import {
|
||||
CLIENT_GEO_COUNTRY_NAME,
|
||||
|
@ -27,7 +32,7 @@ import {
|
|||
SERVICE_ENVIRONMENT,
|
||||
} from '../constants/elasticsearch_fieldnames';
|
||||
|
||||
export function getCoreWebVitalsConfig({ indexPattern }: ConfigProps): DataSeries {
|
||||
export function getCoreWebVitalsConfig({ indexPattern }: ConfigProps): SeriesConfig {
|
||||
const statusPallete = euiPaletteForStatus(3);
|
||||
|
||||
return {
|
||||
|
@ -39,20 +44,20 @@ export function getCoreWebVitalsConfig({ indexPattern }: ConfigProps): DataSerie
|
|||
},
|
||||
yAxisColumns: [
|
||||
{
|
||||
sourceField: 'core.web.vitals',
|
||||
sourceField: REPORT_METRIC_FIELD,
|
||||
label: 'Good',
|
||||
},
|
||||
{
|
||||
sourceField: 'core.web.vitals',
|
||||
sourceField: REPORT_METRIC_FIELD,
|
||||
label: 'Average',
|
||||
},
|
||||
{
|
||||
sourceField: 'core.web.vitals',
|
||||
sourceField: REPORT_METRIC_FIELD,
|
||||
label: 'Poor',
|
||||
},
|
||||
],
|
||||
hasOperationType: false,
|
||||
defaultFilters: [
|
||||
filterFields: [
|
||||
{
|
||||
field: TRANSACTION_URL,
|
||||
isNegated: false,
|
||||
|
@ -69,7 +74,7 @@ export function getCoreWebVitalsConfig({ indexPattern }: ConfigProps): DataSerie
|
|||
nested: USER_AGENT_VERSION,
|
||||
},
|
||||
],
|
||||
breakdowns: [
|
||||
breakdownFields: [
|
||||
SERVICE_NAME,
|
||||
USER_AGENT_NAME,
|
||||
USER_AGENT_OS,
|
||||
|
@ -77,79 +82,67 @@ export function getCoreWebVitalsConfig({ indexPattern }: ConfigProps): DataSerie
|
|||
USER_AGENT_DEVICE,
|
||||
URL_FULL,
|
||||
],
|
||||
filters: [
|
||||
baseFilters: [
|
||||
...buildPhraseFilter(TRANSACTION_TYPE, 'page-load', indexPattern),
|
||||
...buildPhraseFilter(PROCESSOR_EVENT, 'transaction', indexPattern),
|
||||
],
|
||||
labels: { ...FieldLabels, [SERVICE_NAME]: 'Web Application' },
|
||||
reportDefinitions: [
|
||||
definitionFields: [SERVICE_NAME, SERVICE_ENVIRONMENT],
|
||||
metricOptions: [
|
||||
{
|
||||
field: SERVICE_NAME,
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
field: SERVICE_ENVIRONMENT,
|
||||
},
|
||||
{
|
||||
field: 'core.web.vitals',
|
||||
custom: true,
|
||||
options: [
|
||||
id: LCP_FIELD,
|
||||
label: 'Largest contentful paint',
|
||||
columnType: FILTER_RECORDS,
|
||||
columnFilters: [
|
||||
{
|
||||
id: LCP_FIELD,
|
||||
label: 'Largest contentful paint',
|
||||
columnType: FILTER_RECORDS,
|
||||
columnFilters: [
|
||||
{
|
||||
language: 'kuery',
|
||||
query: `${LCP_FIELD} < 2500`,
|
||||
},
|
||||
{
|
||||
language: 'kuery',
|
||||
query: `${LCP_FIELD} > 2500 and ${LCP_FIELD} < 4000`,
|
||||
},
|
||||
{
|
||||
language: 'kuery',
|
||||
query: `${LCP_FIELD} > 4000`,
|
||||
},
|
||||
],
|
||||
language: 'kuery',
|
||||
query: `${LCP_FIELD} < 2500`,
|
||||
},
|
||||
{
|
||||
label: 'First input delay',
|
||||
id: FID_FIELD,
|
||||
columnType: FILTER_RECORDS,
|
||||
columnFilters: [
|
||||
{
|
||||
language: 'kuery',
|
||||
query: `${FID_FIELD} < 100`,
|
||||
},
|
||||
{
|
||||
language: 'kuery',
|
||||
query: `${FID_FIELD} > 100 and ${FID_FIELD} < 300`,
|
||||
},
|
||||
{
|
||||
language: 'kuery',
|
||||
query: `${FID_FIELD} > 300`,
|
||||
},
|
||||
],
|
||||
language: 'kuery',
|
||||
query: `${LCP_FIELD} > 2500 and ${LCP_FIELD} < 4000`,
|
||||
},
|
||||
{
|
||||
label: 'Cumulative layout shift',
|
||||
id: CLS_FIELD,
|
||||
columnType: FILTER_RECORDS,
|
||||
columnFilters: [
|
||||
{
|
||||
language: 'kuery',
|
||||
query: `${CLS_FIELD} < 0.1`,
|
||||
},
|
||||
{
|
||||
language: 'kuery',
|
||||
query: `${CLS_FIELD} > 0.1 and ${CLS_FIELD} < 0.25`,
|
||||
},
|
||||
{
|
||||
language: 'kuery',
|
||||
query: `${CLS_FIELD} > 0.25`,
|
||||
},
|
||||
],
|
||||
language: 'kuery',
|
||||
query: `${LCP_FIELD} > 4000`,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'First input delay',
|
||||
id: FID_FIELD,
|
||||
columnType: FILTER_RECORDS,
|
||||
columnFilters: [
|
||||
{
|
||||
language: 'kuery',
|
||||
query: `${FID_FIELD} < 100`,
|
||||
},
|
||||
{
|
||||
language: 'kuery',
|
||||
query: `${FID_FIELD} > 100 and ${FID_FIELD} < 300`,
|
||||
},
|
||||
{
|
||||
language: 'kuery',
|
||||
query: `${FID_FIELD} > 300`,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'Cumulative layout shift',
|
||||
id: CLS_FIELD,
|
||||
columnType: FILTER_RECORDS,
|
||||
columnFilters: [
|
||||
{
|
||||
language: 'kuery',
|
||||
query: `${CLS_FIELD} < 0.1`,
|
||||
},
|
||||
{
|
||||
language: 'kuery',
|
||||
query: `${CLS_FIELD} > 0.1 and ${CLS_FIELD} < 0.25`,
|
||||
},
|
||||
{
|
||||
language: 'kuery',
|
||||
query: `${CLS_FIELD} > 0.25`,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { ConfigProps, DataSeries } from '../../types';
|
||||
import { FieldLabels, RECORDS_FIELD } from '../constants';
|
||||
import { ConfigProps, SeriesConfig } from '../../types';
|
||||
import { FieldLabels, RECORDS_FIELD, REPORT_METRIC_FIELD } from '../constants';
|
||||
import { buildPhraseFilter } from '../utils';
|
||||
import {
|
||||
CLIENT_GEO_COUNTRY_NAME,
|
||||
|
@ -39,13 +39,13 @@ import {
|
|||
WEB_APPLICATION_LABEL,
|
||||
} from '../constants/labels';
|
||||
|
||||
export function getRumDistributionConfig({ indexPattern }: ConfigProps): DataSeries {
|
||||
export function getRumDistributionConfig({ indexPattern }: ConfigProps): SeriesConfig {
|
||||
return {
|
||||
reportType: 'data-distribution',
|
||||
defaultSeriesType: 'line',
|
||||
seriesTypes: [],
|
||||
xAxisColumn: {
|
||||
sourceField: 'performance.metric',
|
||||
sourceField: REPORT_METRIC_FIELD,
|
||||
},
|
||||
yAxisColumns: [
|
||||
{
|
||||
|
@ -54,7 +54,7 @@ export function getRumDistributionConfig({ indexPattern }: ConfigProps): DataSer
|
|||
},
|
||||
],
|
||||
hasOperationType: false,
|
||||
defaultFilters: [
|
||||
filterFields: [
|
||||
{
|
||||
field: TRANSACTION_URL,
|
||||
isNegated: false,
|
||||
|
@ -67,34 +67,22 @@ export function getRumDistributionConfig({ indexPattern }: ConfigProps): DataSer
|
|||
nested: USER_AGENT_VERSION,
|
||||
},
|
||||
],
|
||||
breakdowns: [USER_AGENT_NAME, USER_AGENT_OS, CLIENT_GEO_COUNTRY_NAME, USER_AGENT_DEVICE],
|
||||
reportDefinitions: [
|
||||
breakdownFields: [USER_AGENT_NAME, USER_AGENT_OS, CLIENT_GEO_COUNTRY_NAME, USER_AGENT_DEVICE],
|
||||
definitionFields: [SERVICE_NAME, SERVICE_ENVIRONMENT],
|
||||
metricOptions: [
|
||||
{ label: PAGE_LOAD_TIME_LABEL, id: TRANSACTION_DURATION, field: TRANSACTION_DURATION },
|
||||
{
|
||||
field: SERVICE_NAME,
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
field: SERVICE_ENVIRONMENT,
|
||||
},
|
||||
{
|
||||
field: 'performance.metric',
|
||||
custom: true,
|
||||
options: [
|
||||
{ label: PAGE_LOAD_TIME_LABEL, id: TRANSACTION_DURATION, field: TRANSACTION_DURATION },
|
||||
{
|
||||
label: BACKEND_TIME_LABEL,
|
||||
id: TRANSACTION_TIME_TO_FIRST_BYTE,
|
||||
field: TRANSACTION_TIME_TO_FIRST_BYTE,
|
||||
},
|
||||
{ label: FCP_LABEL, id: FCP_FIELD, field: FCP_FIELD },
|
||||
{ label: TBT_LABEL, id: TBT_FIELD, field: TBT_FIELD },
|
||||
{ label: LCP_LABEL, id: LCP_FIELD, field: LCP_FIELD },
|
||||
{ label: FID_LABEL, id: FID_FIELD, field: FID_FIELD },
|
||||
{ label: CLS_LABEL, id: CLS_FIELD, field: CLS_FIELD },
|
||||
],
|
||||
label: BACKEND_TIME_LABEL,
|
||||
id: TRANSACTION_TIME_TO_FIRST_BYTE,
|
||||
field: TRANSACTION_TIME_TO_FIRST_BYTE,
|
||||
},
|
||||
{ label: FCP_LABEL, id: FCP_FIELD, field: FCP_FIELD },
|
||||
{ label: TBT_LABEL, id: TBT_FIELD, field: TBT_FIELD },
|
||||
{ label: LCP_LABEL, id: LCP_FIELD, field: LCP_FIELD },
|
||||
{ label: FID_LABEL, id: FID_FIELD, field: FID_FIELD },
|
||||
{ label: CLS_LABEL, id: CLS_FIELD, field: CLS_FIELD },
|
||||
],
|
||||
filters: [
|
||||
baseFilters: [
|
||||
...buildPhraseFilter(TRANSACTION_TYPE, 'page-load', indexPattern),
|
||||
...buildPhraseFilter(PROCESSOR_EVENT, 'transaction', indexPattern),
|
||||
],
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { ConfigProps, DataSeries } from '../../types';
|
||||
import { FieldLabels, OPERATION_COLUMN, RECORDS_FIELD } from '../constants';
|
||||
import { ConfigProps, SeriesConfig } from '../../types';
|
||||
import { FieldLabels, OPERATION_COLUMN, RECORDS_FIELD, REPORT_METRIC_FIELD } from '../constants';
|
||||
import { buildPhraseFilter } from '../utils';
|
||||
import {
|
||||
CLIENT_GEO_COUNTRY_NAME,
|
||||
|
@ -39,7 +39,7 @@ import {
|
|||
WEB_APPLICATION_LABEL,
|
||||
} from '../constants/labels';
|
||||
|
||||
export function getKPITrendsLensConfig({ indexPattern }: ConfigProps): DataSeries {
|
||||
export function getKPITrendsLensConfig({ indexPattern }: ConfigProps): SeriesConfig {
|
||||
return {
|
||||
defaultSeriesType: 'bar_stacked',
|
||||
seriesTypes: [],
|
||||
|
@ -49,12 +49,12 @@ export function getKPITrendsLensConfig({ indexPattern }: ConfigProps): DataSerie
|
|||
},
|
||||
yAxisColumns: [
|
||||
{
|
||||
sourceField: 'business.kpi',
|
||||
sourceField: REPORT_METRIC_FIELD,
|
||||
operationType: 'median',
|
||||
},
|
||||
],
|
||||
hasOperationType: false,
|
||||
defaultFilters: [
|
||||
filterFields: [
|
||||
{
|
||||
field: TRANSACTION_URL,
|
||||
isNegated: false,
|
||||
|
@ -67,44 +67,32 @@ export function getKPITrendsLensConfig({ indexPattern }: ConfigProps): DataSerie
|
|||
nested: USER_AGENT_VERSION,
|
||||
},
|
||||
],
|
||||
breakdowns: [USER_AGENT_NAME, USER_AGENT_OS, CLIENT_GEO_COUNTRY_NAME, USER_AGENT_DEVICE],
|
||||
filters: [
|
||||
breakdownFields: [USER_AGENT_NAME, USER_AGENT_OS, CLIENT_GEO_COUNTRY_NAME, USER_AGENT_DEVICE],
|
||||
baseFilters: [
|
||||
...buildPhraseFilter(TRANSACTION_TYPE, 'page-load', indexPattern),
|
||||
...buildPhraseFilter(PROCESSOR_EVENT, 'transaction', indexPattern),
|
||||
],
|
||||
labels: { ...FieldLabels, [SERVICE_NAME]: WEB_APPLICATION_LABEL },
|
||||
reportDefinitions: [
|
||||
definitionFields: [SERVICE_NAME, SERVICE_ENVIRONMENT],
|
||||
metricOptions: [
|
||||
{ field: RECORDS_FIELD, id: RECORDS_FIELD, label: PAGE_VIEWS_LABEL },
|
||||
{
|
||||
field: SERVICE_NAME,
|
||||
required: true,
|
||||
label: PAGE_LOAD_TIME_LABEL,
|
||||
field: TRANSACTION_DURATION,
|
||||
id: TRANSACTION_DURATION,
|
||||
columnType: OPERATION_COLUMN,
|
||||
},
|
||||
{
|
||||
field: SERVICE_ENVIRONMENT,
|
||||
},
|
||||
{
|
||||
field: 'business.kpi',
|
||||
custom: true,
|
||||
options: [
|
||||
{ field: RECORDS_FIELD, id: RECORDS_FIELD, label: PAGE_VIEWS_LABEL },
|
||||
{
|
||||
label: PAGE_LOAD_TIME_LABEL,
|
||||
field: TRANSACTION_DURATION,
|
||||
id: TRANSACTION_DURATION,
|
||||
columnType: OPERATION_COLUMN,
|
||||
},
|
||||
{
|
||||
label: BACKEND_TIME_LABEL,
|
||||
field: TRANSACTION_TIME_TO_FIRST_BYTE,
|
||||
id: TRANSACTION_TIME_TO_FIRST_BYTE,
|
||||
columnType: OPERATION_COLUMN,
|
||||
},
|
||||
{ label: FCP_LABEL, field: FCP_FIELD, id: FCP_FIELD, columnType: OPERATION_COLUMN },
|
||||
{ label: TBT_LABEL, field: TBT_FIELD, id: TBT_FIELD, columnType: OPERATION_COLUMN },
|
||||
{ label: LCP_LABEL, field: LCP_FIELD, id: LCP_FIELD, columnType: OPERATION_COLUMN },
|
||||
{ label: FID_LABEL, field: FID_FIELD, id: FID_FIELD, columnType: OPERATION_COLUMN },
|
||||
{ label: CLS_LABEL, field: CLS_FIELD, id: CLS_FIELD, columnType: OPERATION_COLUMN },
|
||||
],
|
||||
label: BACKEND_TIME_LABEL,
|
||||
field: TRANSACTION_TIME_TO_FIRST_BYTE,
|
||||
id: TRANSACTION_TIME_TO_FIRST_BYTE,
|
||||
columnType: OPERATION_COLUMN,
|
||||
},
|
||||
{ label: FCP_LABEL, field: FCP_FIELD, id: FCP_FIELD, columnType: OPERATION_COLUMN },
|
||||
{ label: TBT_LABEL, field: TBT_FIELD, id: TBT_FIELD, columnType: OPERATION_COLUMN },
|
||||
{ label: LCP_LABEL, field: LCP_FIELD, id: LCP_FIELD, columnType: OPERATION_COLUMN },
|
||||
{ label: FID_LABEL, field: FID_FIELD, id: FID_FIELD, columnType: OPERATION_COLUMN },
|
||||
{ label: CLS_LABEL, field: CLS_FIELD, id: CLS_FIELD, columnType: OPERATION_COLUMN },
|
||||
],
|
||||
};
|
||||
}
|
||||
|
|
|
@ -5,18 +5,21 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { ConfigProps, DataSeries } from '../../types';
|
||||
import { FieldLabels, RECORDS_FIELD } from '../constants';
|
||||
import { ConfigProps, SeriesConfig } from '../../types';
|
||||
import { FieldLabels, RECORDS_FIELD, REPORT_METRIC_FIELD } from '../constants';
|
||||
import { buildExistsFilter } from '../utils';
|
||||
import { MONITORS_DURATION_LABEL, PINGS_LABEL } from '../constants/labels';
|
||||
|
||||
export function getSyntheticsDistributionConfig({ series, indexPattern }: ConfigProps): DataSeries {
|
||||
export function getSyntheticsDistributionConfig({
|
||||
series,
|
||||
indexPattern,
|
||||
}: ConfigProps): SeriesConfig {
|
||||
return {
|
||||
reportType: 'data-distribution',
|
||||
defaultSeriesType: series?.seriesType || 'line',
|
||||
seriesTypes: [],
|
||||
xAxisColumn: {
|
||||
sourceField: 'performance.metric',
|
||||
sourceField: REPORT_METRIC_FIELD,
|
||||
},
|
||||
yAxisColumns: [
|
||||
{
|
||||
|
@ -25,8 +28,8 @@ export function getSyntheticsDistributionConfig({ series, indexPattern }: Config
|
|||
},
|
||||
],
|
||||
hasOperationType: false,
|
||||
defaultFilters: ['monitor.type', 'observer.geo.name', 'tags'],
|
||||
breakdowns: [
|
||||
filterFields: ['monitor.type', 'observer.geo.name', 'tags'],
|
||||
breakdownFields: [
|
||||
'observer.geo.name',
|
||||
'monitor.name',
|
||||
'monitor.id',
|
||||
|
@ -34,21 +37,10 @@ export function getSyntheticsDistributionConfig({ series, indexPattern }: Config
|
|||
'tags',
|
||||
'url.port',
|
||||
],
|
||||
filters: [...buildExistsFilter('summary.up', indexPattern)],
|
||||
reportDefinitions: [
|
||||
{
|
||||
field: 'monitor.name',
|
||||
},
|
||||
{
|
||||
field: 'url.full',
|
||||
},
|
||||
{
|
||||
field: 'performance.metric',
|
||||
custom: true,
|
||||
options: [
|
||||
{ label: 'Monitor duration', id: 'monitor.duration.us', field: 'monitor.duration.us' },
|
||||
],
|
||||
},
|
||||
baseFilters: [...buildExistsFilter('summary.up', indexPattern)],
|
||||
definitionFields: ['monitor.name', 'url.full'],
|
||||
metricOptions: [
|
||||
{ label: 'Monitor duration', id: 'monitor.duration.us', field: 'monitor.duration.us' },
|
||||
],
|
||||
labels: { ...FieldLabels, 'monitor.duration.us': MONITORS_DURATION_LABEL },
|
||||
};
|
||||
|
|
|
@ -5,15 +5,15 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { ConfigProps, DataSeries } from '../../types';
|
||||
import { FieldLabels, OPERATION_COLUMN } from '../constants';
|
||||
import { ConfigProps, SeriesConfig } from '../../types';
|
||||
import { FieldLabels, OPERATION_COLUMN, REPORT_METRIC_FIELD } from '../constants';
|
||||
import { buildExistsFilter } from '../utils';
|
||||
import { DOWN_LABEL, MONITORS_DURATION_LABEL, UP_LABEL } from '../constants/labels';
|
||||
import { MONITOR_DURATION_US } from '../constants/field_names/synthetics';
|
||||
const SUMMARY_UP = 'summary.up';
|
||||
const SUMMARY_DOWN = 'summary.down';
|
||||
|
||||
export function getSyntheticsKPIConfig({ indexPattern }: ConfigProps): DataSeries {
|
||||
export function getSyntheticsKPIConfig({ indexPattern }: ConfigProps): SeriesConfig {
|
||||
return {
|
||||
reportType: 'kpi-over-time',
|
||||
defaultSeriesType: 'bar_stacked',
|
||||
|
@ -23,45 +23,34 @@ export function getSyntheticsKPIConfig({ indexPattern }: ConfigProps): DataSerie
|
|||
},
|
||||
yAxisColumns: [
|
||||
{
|
||||
sourceField: 'business.kpi',
|
||||
sourceField: REPORT_METRIC_FIELD,
|
||||
operationType: 'median',
|
||||
},
|
||||
],
|
||||
hasOperationType: false,
|
||||
defaultFilters: ['observer.geo.name', 'monitor.type', 'tags'],
|
||||
breakdowns: ['observer.geo.name', 'monitor.type'],
|
||||
filters: [...buildExistsFilter('summary.up', indexPattern)],
|
||||
filterFields: ['observer.geo.name', 'monitor.type', 'tags'],
|
||||
breakdownFields: ['observer.geo.name', 'monitor.type'],
|
||||
baseFilters: [...buildExistsFilter('summary.up', indexPattern)],
|
||||
palette: { type: 'palette', name: 'status' },
|
||||
reportDefinitions: [
|
||||
definitionFields: ['monitor.name', 'url.full'],
|
||||
metricOptions: [
|
||||
{
|
||||
field: 'monitor.name',
|
||||
label: MONITORS_DURATION_LABEL,
|
||||
field: MONITOR_DURATION_US,
|
||||
id: MONITOR_DURATION_US,
|
||||
columnType: OPERATION_COLUMN,
|
||||
},
|
||||
{
|
||||
field: 'url.full',
|
||||
field: SUMMARY_UP,
|
||||
id: SUMMARY_UP,
|
||||
label: UP_LABEL,
|
||||
columnType: OPERATION_COLUMN,
|
||||
},
|
||||
{
|
||||
field: 'business.kpi',
|
||||
custom: true,
|
||||
options: [
|
||||
{
|
||||
label: MONITORS_DURATION_LABEL,
|
||||
field: MONITOR_DURATION_US,
|
||||
id: MONITOR_DURATION_US,
|
||||
columnType: OPERATION_COLUMN,
|
||||
},
|
||||
{
|
||||
field: SUMMARY_UP,
|
||||
id: SUMMARY_UP,
|
||||
label: UP_LABEL,
|
||||
columnType: OPERATION_COLUMN,
|
||||
},
|
||||
{
|
||||
field: SUMMARY_DOWN,
|
||||
id: SUMMARY_DOWN,
|
||||
label: DOWN_LABEL,
|
||||
columnType: OPERATION_COLUMN,
|
||||
},
|
||||
],
|
||||
field: SUMMARY_DOWN,
|
||||
id: SUMMARY_DOWN,
|
||||
label: DOWN_LABEL,
|
||||
columnType: OPERATION_COLUMN,
|
||||
},
|
||||
],
|
||||
labels: { ...FieldLabels },
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
export const sampleAttributeKpi = {
|
||||
title: 'Prefilled from exploratory view app',
|
||||
description: '',
|
||||
visualizationType: 'lnsXY',
|
||||
references: [
|
||||
{ id: 'apm-*', name: 'indexpattern-datasource-current-indexpattern', type: 'index-pattern' },
|
||||
{ id: 'apm-*', name: 'indexpattern-datasource-layer-layer0', type: 'index-pattern' },
|
||||
],
|
||||
state: {
|
||||
datasourceStates: {
|
||||
indexpattern: {
|
||||
layers: {
|
||||
layer0: {
|
||||
columnOrder: ['x-axis-column-layer0', 'y-axis-column-layer0'],
|
||||
columns: {
|
||||
'x-axis-column-layer0': {
|
||||
sourceField: '@timestamp',
|
||||
dataType: 'date',
|
||||
isBucketed: true,
|
||||
label: '@timestamp',
|
||||
operationType: 'date_histogram',
|
||||
params: { interval: 'auto' },
|
||||
scale: 'interval',
|
||||
},
|
||||
'y-axis-column-layer0': {
|
||||
dataType: 'number',
|
||||
isBucketed: false,
|
||||
label: 'Page views',
|
||||
operationType: 'count',
|
||||
scale: 'ratio',
|
||||
sourceField: 'Records',
|
||||
filter: {
|
||||
query: 'transaction.type: page-load and processor.event: transaction',
|
||||
language: 'kuery',
|
||||
},
|
||||
},
|
||||
},
|
||||
incompleteColumns: {},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
visualization: {
|
||||
legend: { isVisible: true, position: 'right' },
|
||||
valueLabels: 'hide',
|
||||
fittingFunction: 'Linear',
|
||||
curveType: 'CURVE_MONOTONE_X',
|
||||
axisTitlesVisibilitySettings: { x: true, yLeft: true, yRight: true },
|
||||
tickLabelsVisibilitySettings: { x: true, yLeft: true, yRight: true },
|
||||
gridlinesVisibilitySettings: { x: true, yLeft: true, yRight: true },
|
||||
preferredSeriesType: 'line',
|
||||
layers: [
|
||||
{
|
||||
accessors: ['y-axis-column-layer0'],
|
||||
layerId: 'layer0',
|
||||
seriesType: 'line',
|
||||
yConfig: [{ forAccessor: 'y-axis-column-layer0' }],
|
||||
xAccessor: 'x-axis-column-layer0',
|
||||
},
|
||||
],
|
||||
},
|
||||
query: { query: '', language: 'kuery' },
|
||||
filters: [],
|
||||
},
|
||||
};
|
|
@ -21,6 +21,7 @@ export function convertToShortUrl(series: SeriesUrl) {
|
|||
filters,
|
||||
reportDefinitions,
|
||||
dataType,
|
||||
selectedMetricField,
|
||||
...restSeries
|
||||
} = series;
|
||||
|
||||
|
@ -32,6 +33,7 @@ export function convertToShortUrl(series: SeriesUrl) {
|
|||
[URL_KEYS.FILTERS]: filters,
|
||||
[URL_KEYS.REPORT_DEFINITIONS]: reportDefinitions,
|
||||
[URL_KEYS.DATA_TYPE]: dataType,
|
||||
[URL_KEYS.SELECTED_METRIC]: selectedMetricField,
|
||||
...restSeries,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -12,25 +12,16 @@ import { LayerConfig, LensAttributes } from '../configurations/lens_attributes';
|
|||
import { useSeriesStorage } from './use_series_storage';
|
||||
import { getDefaultConfigs } from '../configurations/default_configs';
|
||||
|
||||
import { DataSeries, SeriesUrl, UrlFilter } from '../types';
|
||||
import { SeriesUrl, UrlFilter } from '../types';
|
||||
import { useAppIndexPatternContext } from './use_app_index_pattern';
|
||||
|
||||
export const getFiltersFromDefs = (
|
||||
reportDefinitions: SeriesUrl['reportDefinitions'],
|
||||
dataViewConfig: DataSeries
|
||||
) => {
|
||||
const rdfFilters = Object.entries(reportDefinitions ?? {}).map(([field, value]) => {
|
||||
export const getFiltersFromDefs = (reportDefinitions: SeriesUrl['reportDefinitions']) => {
|
||||
return Object.entries(reportDefinitions ?? {}).map(([field, value]) => {
|
||||
return {
|
||||
field,
|
||||
values: value,
|
||||
};
|
||||
}) as UrlFilter[];
|
||||
|
||||
// let's filter out custom fields
|
||||
return rdfFilters.filter(({ field }) => {
|
||||
const rdf = dataViewConfig.reportDefinitions.find(({ field: fd }) => field === fd);
|
||||
return !rdf?.custom;
|
||||
});
|
||||
};
|
||||
|
||||
export const useLensAttributes = (): TypedLensByValueInput['attributes'] | null => {
|
||||
|
@ -49,25 +40,26 @@ export const useLensAttributes = (): TypedLensByValueInput['attributes'] | null
|
|||
const seriesT = allSeries[seriesIdT];
|
||||
const indexPattern = indexPatterns?.[seriesT?.dataType];
|
||||
if (indexPattern && seriesT.reportType && !isEmpty(seriesT.reportDefinitions)) {
|
||||
const reportViewConfig = getDefaultConfigs({
|
||||
const seriesConfig = getDefaultConfigs({
|
||||
reportType: seriesT.reportType,
|
||||
dataType: seriesT.dataType,
|
||||
indexPattern,
|
||||
});
|
||||
|
||||
const filters: UrlFilter[] = (seriesT.filters ?? []).concat(
|
||||
getFiltersFromDefs(seriesT.reportDefinitions, reportViewConfig)
|
||||
getFiltersFromDefs(seriesT.reportDefinitions)
|
||||
);
|
||||
|
||||
layerConfigs.push({
|
||||
filters,
|
||||
indexPattern,
|
||||
reportConfig: reportViewConfig,
|
||||
breakdown: seriesT.breakdown,
|
||||
operationType: seriesT.operationType,
|
||||
seriesType: seriesT.seriesType,
|
||||
reportDefinitions: seriesT.reportDefinitions ?? {},
|
||||
seriesConfig,
|
||||
time: seriesT.time,
|
||||
breakdown: seriesT.breakdown,
|
||||
seriesType: seriesT.seriesType,
|
||||
operationType: seriesT.operationType,
|
||||
reportDefinitions: seriesT.reportDefinitions ?? {},
|
||||
selectedMetricField: seriesT.selectedMetricField,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
@ -110,7 +110,7 @@ export function useSeriesStorage() {
|
|||
}
|
||||
|
||||
function convertFromShortUrl(newValue: ShortUrlSeries): SeriesUrl {
|
||||
const { dt, op, st, rt, bd, ft, time, rdf, ...restSeries } = newValue;
|
||||
const { dt, op, st, rt, bd, ft, time, rdf, mt, ...restSeries } = newValue;
|
||||
return {
|
||||
operationType: op,
|
||||
reportType: rt!,
|
||||
|
@ -120,6 +120,7 @@ function convertFromShortUrl(newValue: ShortUrlSeries): SeriesUrl {
|
|||
time: time!,
|
||||
reportDefinitions: rdf,
|
||||
dataType: dt!,
|
||||
selectedMetricField: mt,
|
||||
...restSeries,
|
||||
};
|
||||
}
|
||||
|
@ -132,6 +133,7 @@ interface ShortUrlSeries {
|
|||
[URL_KEYS.BREAK_DOWN]?: string;
|
||||
[URL_KEYS.FILTERS]?: UrlFilter[];
|
||||
[URL_KEYS.REPORT_DEFINITIONS]?: URLReportDefinition;
|
||||
[URL_KEYS.SELECTED_METRIC]?: string;
|
||||
time?: {
|
||||
to: string;
|
||||
from: string;
|
||||
|
|
|
@ -21,7 +21,7 @@ describe('Series Builder ReportBreakdowns', function () {
|
|||
});
|
||||
|
||||
it('should render properly', function () {
|
||||
render(<ReportBreakdowns dataViewSeries={dataViewSeries} seriesId={seriesId} />);
|
||||
render(<ReportBreakdowns seriesConfig={dataViewSeries} seriesId={seriesId} />);
|
||||
|
||||
screen.getByText('Select an option: , is selected');
|
||||
screen.getAllByText('Browser family');
|
||||
|
@ -29,7 +29,7 @@ describe('Series Builder ReportBreakdowns', function () {
|
|||
|
||||
it('should set new series breakdown on change', function () {
|
||||
const { setSeries } = render(
|
||||
<ReportBreakdowns dataViewSeries={dataViewSeries} seriesId={seriesId} />
|
||||
<ReportBreakdowns seriesConfig={dataViewSeries} seriesId={seriesId} />
|
||||
);
|
||||
|
||||
const btn = screen.getByRole('button', {
|
||||
|
@ -51,7 +51,7 @@ describe('Series Builder ReportBreakdowns', function () {
|
|||
});
|
||||
it('should set undefined on new series on no select breakdown', function () {
|
||||
const { setSeries } = render(
|
||||
<ReportBreakdowns dataViewSeries={dataViewSeries} seriesId={seriesId} />
|
||||
<ReportBreakdowns seriesConfig={dataViewSeries} seriesId={seriesId} />
|
||||
);
|
||||
|
||||
const btn = screen.getByRole('button', {
|
||||
|
|
|
@ -7,19 +7,19 @@
|
|||
|
||||
import React from 'react';
|
||||
import { Breakdowns } from '../../series_editor/columns/breakdowns';
|
||||
import { DataSeries } from '../../types';
|
||||
import { SeriesConfig } from '../../types';
|
||||
|
||||
export function ReportBreakdowns({
|
||||
seriesId,
|
||||
dataViewSeries,
|
||||
seriesConfig,
|
||||
}: {
|
||||
dataViewSeries: DataSeries;
|
||||
seriesConfig: SeriesConfig;
|
||||
seriesId: string;
|
||||
}) {
|
||||
return (
|
||||
<Breakdowns
|
||||
reportViewConfig={dataViewSeries}
|
||||
breakdowns={dataViewSeries.breakdowns ?? []}
|
||||
seriesConfig={seriesConfig}
|
||||
breakdowns={seriesConfig.breakdownFields ?? []}
|
||||
seriesId={seriesId}
|
||||
/>
|
||||
);
|
||||
|
|
|
@ -21,7 +21,7 @@ describe('Series Builder ReportDefinitionCol', function () {
|
|||
mockAppIndexPattern();
|
||||
const seriesId = 'test-series-id';
|
||||
|
||||
const dataViewSeries = getDefaultConfigs({
|
||||
const seriesConfig = getDefaultConfigs({
|
||||
reportType: 'data-distribution',
|
||||
indexPattern: mockIndexPattern,
|
||||
dataType: 'ux',
|
||||
|
@ -41,7 +41,7 @@ describe('Series Builder ReportDefinitionCol', function () {
|
|||
mockUseValuesList([{ label: 'elastic-co', count: 10 }]);
|
||||
|
||||
it('should render properly', async function () {
|
||||
render(<ReportDefinitionCol dataViewSeries={dataViewSeries} seriesId={seriesId} />, {
|
||||
render(<ReportDefinitionCol seriesConfig={seriesConfig} seriesId={seriesId} />, {
|
||||
initSeries,
|
||||
});
|
||||
|
||||
|
@ -52,7 +52,7 @@ describe('Series Builder ReportDefinitionCol', function () {
|
|||
});
|
||||
|
||||
it('should render selected report definitions', async function () {
|
||||
render(<ReportDefinitionCol dataViewSeries={dataViewSeries} seriesId={seriesId} />, {
|
||||
render(<ReportDefinitionCol seriesConfig={seriesConfig} seriesId={seriesId} />, {
|
||||
initSeries,
|
||||
});
|
||||
|
||||
|
@ -63,7 +63,7 @@ describe('Series Builder ReportDefinitionCol', function () {
|
|||
|
||||
it('should be able to remove selected definition', async function () {
|
||||
const { setSeries } = render(
|
||||
<ReportDefinitionCol dataViewSeries={dataViewSeries} seriesId={seriesId} />,
|
||||
<ReportDefinitionCol seriesConfig={seriesConfig} seriesId={seriesId} />,
|
||||
{ initSeries }
|
||||
);
|
||||
|
||||
|
|
|
@ -9,39 +9,40 @@ import React from 'react';
|
|||
import { EuiFlexGroup, EuiFlexItem, EuiHorizontalRule } from '@elastic/eui';
|
||||
import styled from 'styled-components';
|
||||
import { useSeriesStorage } from '../../hooks/use_series_storage';
|
||||
import { CustomReportField } from '../custom_report_field';
|
||||
import { DataSeries, URLReportDefinition } from '../../types';
|
||||
import { ReportMetricOptions } from '../report_metric_options';
|
||||
import { SeriesConfig } from '../../types';
|
||||
import { SeriesChartTypesSelect } from './chart_types';
|
||||
import { OperationTypeSelect } from './operation_type_select';
|
||||
import { DatePickerCol } from './date_picker_col';
|
||||
import { parseCustomFieldName } from '../../configurations/lens_attributes';
|
||||
import { ReportDefinitionField } from './report_definition_field';
|
||||
|
||||
function getColumnType(dataView: DataSeries, selectedDefinition: URLReportDefinition) {
|
||||
const { reportDefinitions } = dataView;
|
||||
const customColumn = reportDefinitions.find((item) => item.custom);
|
||||
if (customColumn?.field && selectedDefinition[customColumn?.field]) {
|
||||
const { columnType } = parseCustomFieldName(customColumn.field, dataView, selectedDefinition);
|
||||
function getColumnType(seriesConfig: SeriesConfig, selectedMetricField?: string) {
|
||||
const { columnType } = parseCustomFieldName(seriesConfig, selectedMetricField);
|
||||
|
||||
return columnType;
|
||||
}
|
||||
return null;
|
||||
return columnType;
|
||||
}
|
||||
|
||||
export function ReportDefinitionCol({
|
||||
dataViewSeries,
|
||||
seriesConfig,
|
||||
seriesId,
|
||||
}: {
|
||||
dataViewSeries: DataSeries;
|
||||
seriesConfig: SeriesConfig;
|
||||
seriesId: string;
|
||||
}) {
|
||||
const { getSeries, setSeries } = useSeriesStorage();
|
||||
|
||||
const series = getSeries(seriesId);
|
||||
|
||||
const { reportDefinitions: selectedReportDefinitions = {} } = series ?? {};
|
||||
const { reportDefinitions: selectedReportDefinitions = {}, selectedMetricField } = series ?? {};
|
||||
|
||||
const { reportDefinitions, defaultSeriesType, hasOperationType, yAxisColumns } = dataViewSeries;
|
||||
const {
|
||||
definitionFields,
|
||||
defaultSeriesType,
|
||||
hasOperationType,
|
||||
yAxisColumns,
|
||||
metricOptions,
|
||||
} = seriesConfig;
|
||||
|
||||
const onChange = (field: string, value?: string[]) => {
|
||||
if (!value?.[0]) {
|
||||
|
@ -58,7 +59,7 @@ export function ReportDefinitionCol({
|
|||
}
|
||||
};
|
||||
|
||||
const columnType = getColumnType(dataViewSeries, selectedReportDefinitions);
|
||||
const columnType = getColumnType(seriesConfig, selectedMetricField);
|
||||
|
||||
return (
|
||||
<FlexGroup direction="column" gutterSize="s">
|
||||
|
@ -66,20 +67,21 @@ export function ReportDefinitionCol({
|
|||
<DatePickerCol seriesId={seriesId} />
|
||||
</EuiFlexItem>
|
||||
<EuiHorizontalRule margin="xs" />
|
||||
{reportDefinitions.map(({ field, custom, options }) => (
|
||||
{definitionFields.map((field) => (
|
||||
<EuiFlexItem key={field}>
|
||||
{!custom ? (
|
||||
<ReportDefinitionField
|
||||
seriesId={seriesId}
|
||||
dataSeries={dataViewSeries}
|
||||
field={field}
|
||||
onChange={onChange}
|
||||
/>
|
||||
) : (
|
||||
<CustomReportField field={field} options={options} seriesId={seriesId} />
|
||||
)}
|
||||
<ReportDefinitionField
|
||||
seriesId={seriesId}
|
||||
seriesConfig={seriesConfig}
|
||||
field={field}
|
||||
onChange={onChange}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
))}
|
||||
{metricOptions && (
|
||||
<EuiFlexItem>
|
||||
<ReportMetricOptions options={metricOptions} seriesId={seriesId} />
|
||||
</EuiFlexItem>
|
||||
)}
|
||||
{(hasOperationType || columnType === 'operation') && (
|
||||
<EuiFlexItem>
|
||||
<OperationTypeSelect
|
||||
|
@ -92,7 +94,7 @@ export function ReportDefinitionCol({
|
|||
<SeriesChartTypesSelect
|
||||
seriesId={seriesId}
|
||||
defaultChartType={defaultSeriesType}
|
||||
seriesTypes={dataViewSeries.seriesTypes}
|
||||
seriesTypes={seriesConfig.seriesTypes}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</FlexGroup>
|
||||
|
|
|
@ -15,16 +15,16 @@ import { ESFilter } from '../../../../../../../../../src/core/types/elasticsearc
|
|||
import { PersistableFilter } from '../../../../../../../lens/common';
|
||||
import { ExistsFilter } from '../../../../../../../../../src/plugins/data/common/es_query/filters';
|
||||
import { buildPhrasesFilter } from '../../configurations/utils';
|
||||
import { DataSeries } from '../../types';
|
||||
import { SeriesConfig } from '../../types';
|
||||
|
||||
interface Props {
|
||||
seriesId: string;
|
||||
field: string;
|
||||
dataSeries: DataSeries;
|
||||
seriesConfig: SeriesConfig;
|
||||
onChange: (field: string, value?: string[]) => void;
|
||||
}
|
||||
|
||||
export function ReportDefinitionField({ seriesId, field, dataSeries, onChange }: Props) {
|
||||
export function ReportDefinitionField({ seriesId, field, seriesConfig, onChange }: Props) {
|
||||
const { getSeries } = useSeriesStorage();
|
||||
|
||||
const series = getSeries(seriesId);
|
||||
|
@ -33,11 +33,11 @@ export function ReportDefinitionField({ seriesId, field, dataSeries, onChange }:
|
|||
|
||||
const { reportDefinitions: selectedReportDefinitions = {} } = series;
|
||||
|
||||
const { labels, filters, reportDefinitions } = dataSeries;
|
||||
const { labels, baseFilters, definitionFields } = seriesConfig;
|
||||
|
||||
const queryFilters = useMemo(() => {
|
||||
const filtersN: ESFilter[] = [];
|
||||
(filters ?? []).forEach((qFilter: PersistableFilter | ExistsFilter) => {
|
||||
(baseFilters ?? []).forEach((qFilter: PersistableFilter | ExistsFilter) => {
|
||||
if (qFilter.query) {
|
||||
filtersN.push(qFilter.query);
|
||||
}
|
||||
|
@ -48,8 +48,8 @@ export function ReportDefinitionField({ seriesId, field, dataSeries, onChange }:
|
|||
});
|
||||
|
||||
if (!isEmpty(selectedReportDefinitions)) {
|
||||
reportDefinitions.forEach(({ field: fieldT, custom }) => {
|
||||
if (!custom && indexPattern && selectedReportDefinitions?.[fieldT] && fieldT !== field) {
|
||||
definitionFields.forEach((fieldT) => {
|
||||
if (indexPattern && selectedReportDefinitions?.[fieldT] && fieldT !== field) {
|
||||
const values = selectedReportDefinitions?.[fieldT];
|
||||
const valueFilter = buildPhrasesFilter(fieldT, values, indexPattern)[0];
|
||||
filtersN.push(valueFilter.query);
|
||||
|
@ -59,7 +59,7 @@ export function ReportDefinitionField({ seriesId, field, dataSeries, onChange }:
|
|||
|
||||
return filtersN;
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [JSON.stringify(selectedReportDefinitions), JSON.stringify(filters)]);
|
||||
}, [JSON.stringify(selectedReportDefinitions), JSON.stringify(baseFilters)]);
|
||||
|
||||
return (
|
||||
<EuiFlexGroup justifyContent="flexStart" gutterSize="s" alignItems="center" wrap>
|
||||
|
|
|
@ -21,7 +21,7 @@ describe('Series Builder ReportFilters', function () {
|
|||
});
|
||||
|
||||
it('should render properly', function () {
|
||||
render(<ReportFilters dataViewSeries={dataViewSeries} seriesId={seriesId} />);
|
||||
render(<ReportFilters seriesConfig={dataViewSeries} seriesId={seriesId} />);
|
||||
|
||||
screen.getByText('Add filter');
|
||||
});
|
||||
|
|
|
@ -7,23 +7,23 @@
|
|||
|
||||
import React from 'react';
|
||||
import { SeriesFilter } from '../../series_editor/columns/series_filter';
|
||||
import { DataSeries } from '../../types';
|
||||
import { SeriesConfig } from '../../types';
|
||||
|
||||
export function ReportFilters({
|
||||
dataViewSeries,
|
||||
seriesConfig,
|
||||
seriesId,
|
||||
}: {
|
||||
dataViewSeries: DataSeries;
|
||||
seriesConfig: SeriesConfig;
|
||||
seriesId: string;
|
||||
}) {
|
||||
return (
|
||||
<SeriesFilter
|
||||
series={dataViewSeries}
|
||||
defaultFilters={dataViewSeries.defaultFilters}
|
||||
filters={dataViewSeries.filters}
|
||||
seriesConfig={seriesConfig}
|
||||
filterFields={seriesConfig.filterFields}
|
||||
baseFilters={seriesConfig.baseFilters}
|
||||
seriesId={seriesId}
|
||||
isNew={true}
|
||||
labels={dataViewSeries.labels}
|
||||
labels={seriesConfig.labels}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ describe('ReportTypesCol', function () {
|
|||
expect(setSeries).toHaveBeenCalledWith(seriesId, {
|
||||
breakdown: 'user_agent.name',
|
||||
dataType: 'ux',
|
||||
reportDefinitions: {},
|
||||
selectedMetricField: undefined,
|
||||
reportType: 'kpi-over-time',
|
||||
time: { from: 'now-15m', to: 'now' },
|
||||
});
|
||||
|
|
|
@ -15,7 +15,7 @@ import { ReportViewType, SeriesUrl } from '../../types';
|
|||
import { useSeriesStorage } from '../../hooks/use_series_storage';
|
||||
import { DEFAULT_TIME } from '../../configurations/constants';
|
||||
import { useAppIndexPatternContext } from '../../hooks/use_app_index_pattern';
|
||||
import { ReportTypeItem, SELECT_DATA_TYPE } from '../series_builder';
|
||||
import { ReportTypeItem } from '../series_builder';
|
||||
|
||||
interface Props {
|
||||
seriesId: string;
|
||||
|
@ -30,7 +30,12 @@ export function ReportTypesCol({ seriesId, reportTypes }: Props) {
|
|||
const { loading, hasData } = useAppIndexPatternContext(restSeries.dataType);
|
||||
|
||||
if (!restSeries.dataType) {
|
||||
return <span>{SELECT_DATA_TYPE}</span>;
|
||||
return (
|
||||
<FormattedMessage
|
||||
id="xpack.observability.expView.seriesBuilder.selectDataType"
|
||||
defaultMessage="No data type selected"
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (!loading && !hasData) {
|
||||
|
@ -72,8 +77,7 @@ export function ReportTypesCol({ seriesId, reportTypes }: Props) {
|
|||
setSeries(seriesId, {
|
||||
...restSeries,
|
||||
reportType,
|
||||
operationType: undefined,
|
||||
reportDefinitions: {},
|
||||
selectedMetricField: undefined,
|
||||
time: restSeries?.time ?? DEFAULT_TIME,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -8,28 +8,26 @@
|
|||
import React from 'react';
|
||||
import { EuiSuperSelect } from '@elastic/eui';
|
||||
import { useSeriesStorage } from '../hooks/use_series_storage';
|
||||
import { ReportDefinition } from '../types';
|
||||
import { SeriesConfig } from '../types';
|
||||
|
||||
interface Props {
|
||||
field: string;
|
||||
seriesId: string;
|
||||
defaultValue?: string;
|
||||
options: ReportDefinition['options'];
|
||||
options: SeriesConfig['metricOptions'];
|
||||
}
|
||||
|
||||
export function CustomReportField({ field, seriesId, options: opts }: Props) {
|
||||
export function ReportMetricOptions({ seriesId, options: opts }: Props) {
|
||||
const { getSeries, setSeries } = useSeriesStorage();
|
||||
|
||||
const series = getSeries(seriesId);
|
||||
|
||||
const { reportDefinitions: rtd = {} } = series;
|
||||
|
||||
const onChange = (value: string) => {
|
||||
setSeries(seriesId, { ...series, reportDefinitions: { ...rtd, [field]: [value] } });
|
||||
setSeries(seriesId, {
|
||||
...series,
|
||||
selectedMetricField: value,
|
||||
});
|
||||
};
|
||||
|
||||
const { reportDefinitions } = series;
|
||||
|
||||
const options = opts ?? [];
|
||||
|
||||
return (
|
||||
|
@ -41,7 +39,7 @@ export function CustomReportField({ field, seriesId, options: opts }: Props) {
|
|||
value: fd || id,
|
||||
inputDisplay: label,
|
||||
}))}
|
||||
valueOfSelected={reportDefinitions?.[field]?.[0] || options?.[0].field || options?.[0].id}
|
||||
valueOfSelected={series.selectedMetricField || options?.[0].field || options?.[0].id}
|
||||
onChange={(value) => onChange(value)}
|
||||
/>
|
||||
);
|
|
@ -17,7 +17,7 @@ import {
|
|||
EuiSwitch,
|
||||
} from '@elastic/eui';
|
||||
import { rgba } from 'polished';
|
||||
import { AppDataType, DataSeries, ReportViewType, SeriesUrl } from '../types';
|
||||
import { AppDataType, SeriesConfig, ReportViewType, SeriesUrl } from '../types';
|
||||
import { DataTypesCol } from './columns/data_types_col';
|
||||
import { ReportTypesCol } from './columns/report_types_col';
|
||||
import { ReportDefinitionCol } from './columns/report_definition_col';
|
||||
|
@ -66,7 +66,7 @@ export const ReportTypes: Record<AppDataType, ReportTypeItem[]> = {
|
|||
interface BuilderItem {
|
||||
id: string;
|
||||
series: SeriesUrl;
|
||||
seriesConfig?: DataSeries;
|
||||
seriesConfig?: SeriesConfig;
|
||||
}
|
||||
|
||||
export function SeriesBuilder({
|
||||
|
@ -142,7 +142,7 @@ export function SeriesBuilder({
|
|||
return loading ? (
|
||||
LOADING_VIEW
|
||||
) : reportType ? (
|
||||
<ReportDefinitionCol seriesId={seriesId} dataViewSeries={seriesConfig} />
|
||||
<ReportDefinitionCol seriesId={seriesId} seriesConfig={seriesConfig} />
|
||||
) : (
|
||||
SELECT_REPORT_TYPE
|
||||
);
|
||||
|
@ -159,7 +159,7 @@ export function SeriesBuilder({
|
|||
field: 'id',
|
||||
render: (seriesId: string, { series: { reportType }, seriesConfig }: BuilderItem) =>
|
||||
reportType && seriesConfig ? (
|
||||
<ReportFilters seriesId={seriesId} dataViewSeries={seriesConfig} />
|
||||
<ReportFilters seriesId={seriesId} seriesConfig={seriesConfig} />
|
||||
) : null,
|
||||
},
|
||||
{
|
||||
|
@ -170,7 +170,7 @@ export function SeriesBuilder({
|
|||
field: 'id',
|
||||
render: (seriesId: string, { series: { reportType }, seriesConfig }: BuilderItem) =>
|
||||
reportType && seriesConfig ? (
|
||||
<ReportBreakdowns seriesId={seriesId} dataViewSeries={seriesConfig} />
|
||||
<ReportBreakdowns seriesId={seriesId} seriesConfig={seriesConfig} />
|
||||
) : null,
|
||||
},
|
||||
...(multiSeries
|
||||
|
@ -301,10 +301,3 @@ export const SELECT_REPORT_TYPE = i18n.translate(
|
|||
defaultMessage: 'No report type selected',
|
||||
}
|
||||
);
|
||||
|
||||
export const SELECT_DATA_TYPE = i18n.translate(
|
||||
'xpack.observability.expView.seriesBuilder.selectDataType',
|
||||
{
|
||||
defaultMessage: 'No data type selected',
|
||||
}
|
||||
);
|
||||
|
|
|
@ -8,22 +8,22 @@
|
|||
import React from 'react';
|
||||
import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
|
||||
import { Breakdowns } from './columns/breakdowns';
|
||||
import { DataSeries } from '../types';
|
||||
import { SeriesConfig } from '../types';
|
||||
import { ChartOptions } from './columns/chart_options';
|
||||
|
||||
interface Props {
|
||||
series: DataSeries;
|
||||
seriesConfig: SeriesConfig;
|
||||
seriesId: string;
|
||||
breakdowns: string[];
|
||||
breakdownFields: string[];
|
||||
}
|
||||
export function ChartEditOptions({ series, seriesId, breakdowns }: Props) {
|
||||
export function ChartEditOptions({ seriesConfig, seriesId, breakdownFields }: Props) {
|
||||
return (
|
||||
<EuiFlexGroup wrap>
|
||||
<EuiFlexItem>
|
||||
<Breakdowns seriesId={seriesId} breakdowns={breakdowns} reportViewConfig={series} />
|
||||
<Breakdowns seriesId={seriesId} breakdowns={breakdownFields} seriesConfig={seriesConfig} />
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<ChartOptions series={series} seriesId={seriesId} />
|
||||
<ChartOptions seriesConfig={seriesConfig} seriesId={seriesId} />
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
|
|
|
@ -23,8 +23,8 @@ describe('Breakdowns', function () {
|
|||
render(
|
||||
<Breakdowns
|
||||
seriesId={'series-id'}
|
||||
breakdowns={dataViewSeries.breakdowns}
|
||||
reportViewConfig={dataViewSeries}
|
||||
breakdowns={dataViewSeries.breakdownFields}
|
||||
seriesConfig={dataViewSeries}
|
||||
/>
|
||||
);
|
||||
|
||||
|
@ -37,8 +37,8 @@ describe('Breakdowns', function () {
|
|||
const { setSeries } = render(
|
||||
<Breakdowns
|
||||
seriesId={'series-id'}
|
||||
breakdowns={dataViewSeries.breakdowns}
|
||||
reportViewConfig={dataViewSeries}
|
||||
breakdowns={dataViewSeries.breakdownFields}
|
||||
seriesConfig={dataViewSeries}
|
||||
/>,
|
||||
{ initSeries }
|
||||
);
|
||||
|
|
|
@ -10,15 +10,15 @@ import { EuiSuperSelect } from '@elastic/eui';
|
|||
import { i18n } from '@kbn/i18n';
|
||||
import { useSeriesStorage } from '../../hooks/use_series_storage';
|
||||
import { USE_BREAK_DOWN_COLUMN } from '../../configurations/constants';
|
||||
import { DataSeries } from '../../types';
|
||||
import { SeriesConfig } from '../../types';
|
||||
|
||||
interface Props {
|
||||
seriesId: string;
|
||||
breakdowns: string[];
|
||||
reportViewConfig: DataSeries;
|
||||
seriesConfig: SeriesConfig;
|
||||
}
|
||||
|
||||
export function Breakdowns({ reportViewConfig, seriesId, breakdowns = [] }: Props) {
|
||||
export function Breakdowns({ seriesConfig, seriesId, breakdowns = [] }: Props) {
|
||||
const { setSeries, getSeries } = useSeriesStorage();
|
||||
|
||||
const series = getSeries(seriesId);
|
||||
|
@ -40,11 +40,11 @@ export function Breakdowns({ reportViewConfig, seriesId, breakdowns = [] }: Prop
|
|||
}
|
||||
};
|
||||
|
||||
const hasUseBreakdownColumn = reportViewConfig.xAxisColumn.sourceField === USE_BREAK_DOWN_COLUMN;
|
||||
const hasUseBreakdownColumn = seriesConfig.xAxisColumn.sourceField === USE_BREAK_DOWN_COLUMN;
|
||||
|
||||
const items = breakdowns.map((breakdown) => ({
|
||||
id: breakdown,
|
||||
label: reportViewConfig.labels[breakdown],
|
||||
label: seriesConfig.labels[breakdown],
|
||||
}));
|
||||
|
||||
if (!hasUseBreakdownColumn) {
|
||||
|
|
|
@ -7,22 +7,25 @@
|
|||
|
||||
import React from 'react';
|
||||
import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
|
||||
import { DataSeries } from '../../types';
|
||||
import { SeriesConfig } from '../../types';
|
||||
import { OperationTypeSelect } from '../../series_builder/columns/operation_type_select';
|
||||
import { SeriesChartTypesSelect } from '../../series_builder/columns/chart_types';
|
||||
|
||||
interface Props {
|
||||
series: DataSeries;
|
||||
seriesConfig: SeriesConfig;
|
||||
seriesId: string;
|
||||
}
|
||||
|
||||
export function ChartOptions({ series, seriesId }: Props) {
|
||||
export function ChartOptions({ seriesConfig, seriesId }: Props) {
|
||||
return (
|
||||
<EuiFlexGroup direction="column" gutterSize="s" justifyContent="center">
|
||||
<EuiFlexItem grow={false}>
|
||||
<SeriesChartTypesSelect seriesId={seriesId} defaultChartType={series.seriesTypes[0]} />
|
||||
<SeriesChartTypesSelect
|
||||
seriesId={seriesId}
|
||||
defaultChartType={seriesConfig.seriesTypes[0]}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
{series.hasOperationType && (
|
||||
{seriesConfig.hasOperationType && (
|
||||
<EuiFlexItem grow={false}>
|
||||
<OperationTypeSelect seriesId={seriesId} />
|
||||
</EuiFlexItem>
|
||||
|
|
|
@ -14,7 +14,7 @@ import { QueryDslQueryContainer } from '@elastic/elasticsearch/api/types';
|
|||
import { map } from 'lodash';
|
||||
import { useAppIndexPatternContext } from '../../hooks/use_app_index_pattern';
|
||||
import { useSeriesStorage } from '../../hooks/use_series_storage';
|
||||
import { DataSeries, UrlFilter } from '../../types';
|
||||
import { SeriesConfig, UrlFilter } from '../../types';
|
||||
import { FilterValueButton } from './filter_value_btn';
|
||||
import { useValuesList } from '../../../../../hooks/use_values_list';
|
||||
import { euiStyled } from '../../../../../../../../../src/plugins/kibana_react/common';
|
||||
|
@ -29,7 +29,7 @@ interface Props {
|
|||
isNegated?: boolean;
|
||||
goBack: () => void;
|
||||
nestedField?: string;
|
||||
filters: DataSeries['filters'];
|
||||
filters: SeriesConfig['baseFilters'];
|
||||
}
|
||||
|
||||
export function FilterExpanded({
|
||||
|
|
|
@ -16,16 +16,16 @@ import {
|
|||
EuiFlexGroup,
|
||||
} from '@elastic/eui';
|
||||
import { FilterExpanded } from './filter_expanded';
|
||||
import { DataSeries } from '../../types';
|
||||
import { SeriesConfig } from '../../types';
|
||||
import { FieldLabels } from '../../configurations/constants/constants';
|
||||
import { SelectedFilters } from '../selected_filters';
|
||||
import { useSeriesStorage } from '../../hooks/use_series_storage';
|
||||
|
||||
interface Props {
|
||||
seriesId: string;
|
||||
defaultFilters: DataSeries['defaultFilters'];
|
||||
filters: DataSeries['filters'];
|
||||
series: DataSeries;
|
||||
filterFields: SeriesConfig['filterFields'];
|
||||
baseFilters: SeriesConfig['baseFilters'];
|
||||
seriesConfig: SeriesConfig;
|
||||
isNew?: boolean;
|
||||
labels?: Record<string, string>;
|
||||
}
|
||||
|
@ -38,18 +38,18 @@ export interface Field {
|
|||
}
|
||||
|
||||
export function SeriesFilter({
|
||||
series,
|
||||
seriesConfig,
|
||||
isNew,
|
||||
seriesId,
|
||||
defaultFilters = [],
|
||||
filters,
|
||||
filterFields = [],
|
||||
baseFilters,
|
||||
labels,
|
||||
}: Props) {
|
||||
const [isPopoverVisible, setIsPopoverVisible] = useState(false);
|
||||
|
||||
const [selectedField, setSelectedField] = useState<Field | undefined>();
|
||||
|
||||
const options: Field[] = defaultFilters.map((field) => {
|
||||
const options: Field[] = filterFields.map((field) => {
|
||||
if (typeof field === 'string') {
|
||||
return { label: labels?.[field] ?? FieldLabels[field], field };
|
||||
}
|
||||
|
@ -111,7 +111,7 @@ export function SeriesFilter({
|
|||
goBack={() => {
|
||||
setSelectedField(undefined);
|
||||
}}
|
||||
filters={filters}
|
||||
filters={baseFilters}
|
||||
/>
|
||||
) : null;
|
||||
|
||||
|
@ -122,7 +122,7 @@ export function SeriesFilter({
|
|||
|
||||
return (
|
||||
<EuiFlexGroup wrap direction="column" gutterSize="xs" alignItems="flexStart">
|
||||
<SelectedFilters seriesId={seriesId} series={series} isNew={isNew} />
|
||||
<SelectedFilters seriesId={seriesId} seriesConfig={seriesConfig} isNew={isNew} />
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiPopover
|
||||
button={button}
|
||||
|
|
|
@ -24,7 +24,9 @@ describe('SelectedFilters', function () {
|
|||
it('should render properly', async function () {
|
||||
const initSeries = { filters: [{ field: USER_AGENT_NAME, values: ['Chrome'] }] };
|
||||
|
||||
render(<SelectedFilters seriesId={'series-id'} series={dataViewSeries} />, { initSeries });
|
||||
render(<SelectedFilters seriesId={'series-id'} seriesConfig={dataViewSeries} />, {
|
||||
initSeries,
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
screen.getByText('Chrome');
|
||||
|
|
|
@ -9,28 +9,28 @@ import React, { Fragment } from 'react';
|
|||
import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
|
||||
import { useSeriesStorage } from '../hooks/use_series_storage';
|
||||
import { FilterLabel } from '../components/filter_label';
|
||||
import { DataSeries, UrlFilter } from '../types';
|
||||
import { SeriesConfig, UrlFilter } from '../types';
|
||||
import { useAppIndexPatternContext } from '../hooks/use_app_index_pattern';
|
||||
import { useSeriesFilters } from '../hooks/use_series_filters';
|
||||
import { getFiltersFromDefs } from '../hooks/use_lens_attributes';
|
||||
|
||||
interface Props {
|
||||
seriesId: string;
|
||||
series: DataSeries;
|
||||
seriesConfig: SeriesConfig;
|
||||
isNew?: boolean;
|
||||
}
|
||||
export function SelectedFilters({ seriesId, isNew, series: dataSeries }: Props) {
|
||||
export function SelectedFilters({ seriesId, isNew, seriesConfig }: Props) {
|
||||
const { getSeries } = useSeriesStorage();
|
||||
|
||||
const series = getSeries(seriesId);
|
||||
|
||||
const { reportDefinitions = {} } = series;
|
||||
|
||||
const { labels } = dataSeries;
|
||||
const { labels } = seriesConfig;
|
||||
|
||||
const filters: UrlFilter[] = series.filters ?? [];
|
||||
|
||||
let definitionFilters: UrlFilter[] = getFiltersFromDefs(reportDefinitions, dataSeries);
|
||||
let definitionFilters: UrlFilter[] = getFiltersFromDefs(reportDefinitions);
|
||||
|
||||
// we don't want to display report definition filters in new series view
|
||||
if (isNew) {
|
||||
|
|
|
@ -10,7 +10,7 @@ import { i18n } from '@kbn/i18n';
|
|||
import { EuiBasicTable, EuiIcon, EuiSpacer, EuiText } from '@elastic/eui';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
import { SeriesFilter } from './columns/series_filter';
|
||||
import { DataSeries } from '../types';
|
||||
import { SeriesConfig } from '../types';
|
||||
import { NEW_SERIES_KEY, useSeriesStorage } from '../hooks/use_series_storage';
|
||||
import { getDefaultConfigs } from '../configurations/default_configs';
|
||||
import { DatePickerCol } from './columns/date_picker_col';
|
||||
|
@ -19,7 +19,7 @@ import { SeriesActions } from './columns/series_actions';
|
|||
import { ChartEditOptions } from './chart_edit_options';
|
||||
|
||||
interface EditItem {
|
||||
seriesConfig: DataSeries;
|
||||
seriesConfig: SeriesConfig;
|
||||
id: string;
|
||||
}
|
||||
|
||||
|
@ -48,10 +48,10 @@ export function SeriesEditor() {
|
|||
width: '15%',
|
||||
render: (seriesId: string, { seriesConfig, id }: EditItem) => (
|
||||
<SeriesFilter
|
||||
defaultFilters={seriesConfig.defaultFilters}
|
||||
filterFields={seriesConfig.filterFields}
|
||||
seriesId={id}
|
||||
series={seriesConfig}
|
||||
filters={seriesConfig.filters}
|
||||
seriesConfig={seriesConfig}
|
||||
baseFilters={seriesConfig.baseFilters}
|
||||
/>
|
||||
),
|
||||
},
|
||||
|
@ -64,8 +64,8 @@ export function SeriesEditor() {
|
|||
render: (seriesId: string, { seriesConfig, id }: EditItem) => (
|
||||
<ChartEditOptions
|
||||
seriesId={id}
|
||||
breakdowns={seriesConfig.breakdowns}
|
||||
series={seriesConfig}
|
||||
breakdownFields={seriesConfig.breakdownFields}
|
||||
seriesConfig={seriesConfig}
|
||||
/>
|
||||
),
|
||||
},
|
||||
|
@ -123,7 +123,7 @@ export function SeriesEditor() {
|
|||
rowHeader="firstName"
|
||||
columns={columns}
|
||||
noItemsMessage={i18n.translate('xpack.observability.expView.seriesEditor.seriesNotFound', {
|
||||
defaultMessage: 'No series found, please add a series.',
|
||||
defaultMessage: 'No series found. Please add a series.',
|
||||
})}
|
||||
cellProps={{
|
||||
style: {
|
||||
|
|
|
@ -37,31 +37,27 @@ export interface ColumnFilter {
|
|||
query: string;
|
||||
}
|
||||
|
||||
export interface ReportDefinition {
|
||||
field: string;
|
||||
required?: boolean;
|
||||
custom?: boolean;
|
||||
options?: Array<{
|
||||
id: string;
|
||||
field?: string;
|
||||
label: string;
|
||||
description?: string;
|
||||
columnType?: 'range' | 'operation' | 'FILTER_RECORDS' | 'TERMS_COLUMN';
|
||||
columnFilters?: ColumnFilter[];
|
||||
timeScale?: string;
|
||||
}>;
|
||||
export interface MetricOption {
|
||||
id: string;
|
||||
field?: string;
|
||||
label: string;
|
||||
description?: string;
|
||||
columnType?: 'range' | 'operation' | 'FILTER_RECORDS' | 'TERMS_COLUMN';
|
||||
columnFilters?: ColumnFilter[];
|
||||
timeScale?: string;
|
||||
}
|
||||
|
||||
export interface DataSeries {
|
||||
export interface SeriesConfig {
|
||||
reportType: ReportViewType;
|
||||
xAxisColumn: Partial<LastValueIndexPatternColumn> | Partial<DateHistogramIndexPatternColumn>;
|
||||
yAxisColumns: Array<Partial<FieldBasedIndexPatternColumn>>;
|
||||
breakdowns: string[];
|
||||
breakdownFields: string[];
|
||||
defaultSeriesType: SeriesType;
|
||||
defaultFilters: Array<string | { field: string; nested?: string; isNegated?: boolean }>;
|
||||
filterFields: Array<string | { field: string; nested?: string; isNegated?: boolean }>;
|
||||
seriesTypes: SeriesType[];
|
||||
filters?: PersistableFilter[] | ExistsFilter[];
|
||||
reportDefinitions: ReportDefinition[];
|
||||
baseFilters?: PersistableFilter[] | ExistsFilter[];
|
||||
definitionFields: string[];
|
||||
metricOptions?: MetricOption[];
|
||||
labels: Record<string, string>;
|
||||
hasOperationType: boolean;
|
||||
palette?: PaletteOutput;
|
||||
|
@ -83,6 +79,7 @@ export interface SeriesUrl {
|
|||
operationType?: OperationType;
|
||||
dataType: AppDataType;
|
||||
reportDefinitions?: URLReportDefinition;
|
||||
selectedMetricField?: string;
|
||||
isNew?: boolean;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue