[Uptime] Align synthetics report types (#101855)

This commit is contained in:
Shahzad 2021-06-14 15:57:03 +02:00 committed by GitHub
parent 71a81f7cd6
commit e0a1a34fbc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
43 changed files with 247 additions and 419 deletions

View file

@ -89,7 +89,7 @@ export function PageLoadDistribution() {
{
[`${serviceName}-page-views`]: {
dataType: 'ux',
reportType: 'pld',
reportType: 'dist',
time: { from: rangeFrom!, to: rangeTo! },
reportDefinitions: {
'service.name': serviceName as string[],

View file

@ -26,7 +26,7 @@ describe('FilterLabel', function () {
value={'elastic-co'}
label={'Web Application'}
negate={false}
seriesId={'kpi-trends'}
seriesId={'kpi-over-time'}
removeFilter={jest.fn()}
/>
);
@ -49,7 +49,7 @@ describe('FilterLabel', function () {
value={'elastic-co'}
label={'Web Application'}
negate={false}
seriesId={'kpi-trends'}
seriesId={'kpi-over-time'}
removeFilter={removeFilter}
/>
);
@ -71,7 +71,7 @@ describe('FilterLabel', function () {
value={'elastic-co'}
label={'Web Application'}
negate={false}
seriesId={'kpi-trends'}
seriesId={'kpi-over-time'}
removeFilter={removeFilter}
/>
);
@ -96,7 +96,7 @@ describe('FilterLabel', function () {
value={'elastic-co'}
label={'Web Application'}
negate={true}
seriesId={'kpi-trends'}
seriesId={'kpi-over-time'}
removeFilter={jest.fn()}
/>
);

View file

@ -10,10 +10,9 @@ import { FieldLabels } from '../constants';
import { buildPhraseFilter } from '../utils';
import { TRANSACTION_DURATION } from '../constants/elasticsearch_fieldnames';
export function getServiceLatencyLensConfig({ seriesId, indexPattern }: ConfigProps): DataSeries {
export function getServiceLatencyLensConfig({ indexPattern }: ConfigProps): DataSeries {
return {
id: seriesId,
reportType: 'service-latency',
reportType: 'kpi-over-time',
defaultSeriesType: 'line',
seriesTypes: ['line', 'bar'],
xAxisColumn: {

View file

@ -1,57 +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/constants';
import { buildPhraseFilter } from '../utils';
import { TRANSACTION_DURATION } from '../constants/elasticsearch_fieldnames';
export function getServiceThroughputLensConfig({
seriesId,
indexPattern,
}: ConfigProps): DataSeries {
return {
id: seriesId,
reportType: 'service-throughput',
defaultSeriesType: 'line',
seriesTypes: ['line', 'bar'],
xAxisColumn: {
sourceField: '@timestamp',
},
yAxisColumns: [
{
operationType: 'average',
sourceField: 'transaction.duration.us',
label: 'Throughput',
},
],
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]: 'Throughput' },
reportDefinitions: [
{
field: 'service.name',
required: true,
},
{
field: 'service.environment',
},
],
};
}

View file

@ -5,7 +5,7 @@
* 2.0.
*/
import { AppDataType, ReportViewTypeId } from '../../types';
import { ReportViewTypeId } from '../../types';
import { CLS_FIELD, FCP_FIELD, FID_FIELD, LCP_FIELD, TBT_FIELD } from './elasticsearch_fieldnames';
import {
AGENT_HOST_LABEL,
@ -13,7 +13,6 @@ import {
BROWSER_VERSION_LABEL,
CLS_LABEL,
CORE_WEB_VITALS_LABEL,
CPU_USAGE_LABEL,
DEVICE_LABEL,
ENVIRONMENT_LABEL,
FCP_LABEL,
@ -23,25 +22,18 @@ import {
KPI_LABEL,
LCP_LABEL,
LOCATION_LABEL,
LOGS_FREQUENCY_LABEL,
MEMORY_USAGE_LABEL,
METRIC_LABEL,
MONITOR_DURATION_LABEL,
MONITOR_ID_LABEL,
MONITOR_NAME_LABEL,
MONITOR_STATUS_LABEL,
MONITOR_TYPE_LABEL,
NETWORK_ACTIVITY_LABEL,
OBSERVER_LOCATION_LABEL,
OS_LABEL,
PERF_DIST_LABEL,
PORT_LABEL,
SERVICE_LATENCY_LABEL,
SERVICE_NAME_LABEL,
SERVICE_THROUGHPUT_LABEL,
TAGS_LABEL,
TBT_LABEL,
UPTIME_PINGS_LABEL,
URL_LABEL,
} from './labels';
@ -83,33 +75,11 @@ export const FieldLabels: Record<string, string> = {
};
export const DataViewLabels: Record<ReportViewTypeId, string> = {
pld: PERF_DIST_LABEL,
upd: MONITOR_DURATION_LABEL,
upp: UPTIME_PINGS_LABEL,
svl: SERVICE_LATENCY_LABEL,
dist: PERF_DIST_LABEL,
kpi: KIP_OVER_TIME_LABEL,
tpt: SERVICE_THROUGHPUT_LABEL,
cpu: CPU_USAGE_LABEL,
logs: LOGS_FREQUENCY_LABEL,
mem: MEMORY_USAGE_LABEL,
nwk: NETWORK_ACTIVITY_LABEL,
cwv: CORE_WEB_VITALS_LABEL,
};
export const ReportToDataTypeMap: Record<ReportViewTypeId, AppDataType> = {
upd: 'synthetics',
upp: 'synthetics',
tpt: 'apm',
svl: 'apm',
kpi: 'ux',
pld: 'ux',
nwk: 'infra_metrics',
mem: 'infra_metrics',
logs: 'infra_logs',
cpu: 'infra_metrics',
cwv: 'ux',
};
export const USE_BREAK_DOWN_COLUMN = 'USE_BREAK_DOWN_COLUMN';
export const FILTER_RECORDS = 'FILTER_RECORDS';
export const OPERATION_COLUMN = 'operation';

View file

@ -0,0 +1,8 @@
/*
* 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 MONITOR_DURATION_US = 'monitor.duration.us';

View file

@ -100,6 +100,10 @@ export const PAGES_LOADED_LABEL = i18n.translate(
}
);
export const PINGS_LABEL = i18n.translate('xpack.observability.expView.fieldLabels.pings', {
defaultMessage: 'Pings',
});
export const MONITOR_ID_LABEL = i18n.translate(
'xpack.observability.expView.fieldLabels.monitorId',
{
@ -165,42 +169,6 @@ export const PERF_DIST_LABEL = i18n.translate(
}
);
export const MONITOR_DURATION_LABEL = i18n.translate(
'xpack.observability.expView.fieldLabels.monitorDuration',
{
defaultMessage: 'Uptime monitor duration',
}
);
export const UPTIME_PINGS_LABEL = i18n.translate('xpack.observability.expView.fieldLabels.pings', {
defaultMessage: 'Uptime pings',
});
export const SERVICE_LATENCY_LABEL = i18n.translate(
'xpack.observability.expView.fieldLabels.serviceLatency',
{
defaultMessage: 'APM Service latency',
}
);
export const SERVICE_THROUGHPUT_LABEL = i18n.translate(
'xpack.observability.expView.fieldLabels.serviceThroughput',
{
defaultMessage: 'APM Service throughput',
}
);
export const CPU_USAGE_LABEL = i18n.translate('xpack.observability.expView.fieldLabels.cpuUsage', {
defaultMessage: 'System CPU usage',
});
export const NETWORK_ACTIVITY_LABEL = i18n.translate(
'xpack.observability.expView.fieldLabels.networkActivity',
{
defaultMessage: 'Network activity',
}
);
export const CORE_WEB_VITALS_LABEL = i18n.translate(
'xpack.observability.expView.fieldLabels.coreWebVitals',
{
@ -215,13 +183,6 @@ export const MEMORY_USAGE_LABEL = i18n.translate(
}
);
export const LOGS_FREQUENCY_LABEL = i18n.translate(
'xpack.observability.expView.fieldLabels.logsFrequency',
{
defaultMessage: 'Logs frequency',
}
);
export const KIP_OVER_TIME_LABEL = i18n.translate(
'xpack.observability.expView.fieldLabels.kpiOverTime',
{
@ -243,10 +204,10 @@ export const WEB_APPLICATION_LABEL = i18n.translate(
}
);
export const UP_LABEL = i18n.translate('xpack.observability.expView.fieldLabels.up', {
defaultMessage: 'Up',
export const UP_LABEL = i18n.translate('xpack.observability.expView.fieldLabels.upPings', {
defaultMessage: 'Up Pings',
});
export const DOWN_LABEL = i18n.translate('xpack.observability.expView.fieldLabels.down', {
defaultMessage: 'Down',
export const DOWN_LABEL = i18n.translate('xpack.observability.expView.fieldLabels.downPings', {
defaultMessage: 'Down Pings',
});

View file

@ -5,51 +5,37 @@
* 2.0.
*/
import { ReportViewTypes } from '../types';
import { getPerformanceDistLensConfig } from './rum/performance_dist_config';
import { getMonitorDurationConfig } from './synthetics/monitor_duration_config';
import { getServiceLatencyLensConfig } from './apm/service_latency_config';
import { getMonitorPingsConfig } from './synthetics/monitor_pings_config';
import { getServiceThroughputLensConfig } from './apm/service_throughput_config';
import { getKPITrendsLensConfig } from './rum/kpi_trends_config';
import { getCPUUsageLensConfig } from './metrics/cpu_usage_config';
import { getMemoryUsageLensConfig } from './metrics/memory_usage_config';
import { getNetworkActivityLensConfig } from './metrics/network_activity_config';
import { getLogsFrequencyLensConfig } from './logs/logs_frequency_config';
import { IIndexPattern } from '../../../../../../../../src/plugins/data/common/index_patterns';
import { AppDataType, ReportViewTypes } from '../types';
import { getRumDistributionConfig } from './rum/data_distribution_config';
import { getSyntheticsDistributionConfig } from './synthetics/data_distribution_config';
import { getSyntheticsKPIConfig } from './synthetics/kpi_over_time_config';
import { getKPITrendsLensConfig } from './rum/kpi_over_time_config';
import { IndexPattern } from '../../../../../../../../src/plugins/data/common';
import { getCoreWebVitalsConfig } from './rum/core_web_vitals_config';
interface Props {
reportType: keyof typeof ReportViewTypes;
seriesId: string;
indexPattern: IIndexPattern;
indexPattern: IndexPattern;
dataType: AppDataType;
}
export const getDefaultConfigs = ({ reportType, seriesId, indexPattern }: Props) => {
switch (ReportViewTypes[reportType]) {
case 'page-load-dist':
return getPerformanceDistLensConfig({ seriesId, indexPattern });
case 'kpi-trends':
return getKPITrendsLensConfig({ seriesId, indexPattern });
case 'core-web-vitals':
return getCoreWebVitalsConfig({ seriesId, indexPattern });
case 'uptime-duration':
return getMonitorDurationConfig({ seriesId, indexPattern });
case 'uptime-pings':
return getMonitorPingsConfig({ seriesId, indexPattern });
case 'service-latency':
return getServiceLatencyLensConfig({ seriesId, indexPattern });
case 'service-throughput':
return getServiceThroughputLensConfig({ seriesId, indexPattern });
case 'cpu-usage':
return getCPUUsageLensConfig({ seriesId });
case 'memory-usage':
return getMemoryUsageLensConfig({ seriesId });
case 'network-activity':
return getNetworkActivityLensConfig({ seriesId });
case 'logs-frequency':
return getLogsFrequencyLensConfig({ seriesId });
export const getDefaultConfigs = ({ reportType, dataType, indexPattern }: Props) => {
switch (dataType) {
case 'ux':
if (reportType === 'dist') {
return getRumDistributionConfig({ indexPattern });
}
if (reportType === 'cwv') {
return getCoreWebVitalsConfig({ indexPattern });
}
return getKPITrendsLensConfig({ indexPattern });
case 'synthetics':
if (reportType === 'dist') {
return getSyntheticsDistributionConfig({ indexPattern });
}
return getSyntheticsKPIConfig({ indexPattern });
default:
return getKPITrendsLensConfig({ seriesId, indexPattern });
return getKPITrendsLensConfig({ indexPattern });
}
};

View file

@ -15,9 +15,9 @@ describe('Lens Attribute', () => {
mockAppIndexPattern();
const reportViewConfig = getDefaultConfigs({
reportType: 'pld',
reportType: 'dist',
dataType: 'ux',
indexPattern: mockIndexPattern,
seriesId: 'series-id',
});
let lnsAttr: LensAttributes;
@ -73,6 +73,7 @@ describe('Lens Attribute', () => {
readFromDocValues: true,
},
fieldName: 'transaction.duration.us',
columnLabel: 'Page load time',
})
);
});
@ -95,6 +96,7 @@ describe('Lens Attribute', () => {
readFromDocValues: true,
},
fieldName: LCP_FIELD,
columnLabel: 'Largest contentful paint',
})
);
});

View file

@ -55,6 +55,7 @@ export const parseCustomFieldName = (
let fieldName = sourceField;
let columnType;
let columnFilters;
let columnLabel;
const rdf = reportViewConfig.reportDefinitions ?? [];
@ -69,15 +70,17 @@ export const parseCustomFieldName = (
);
columnType = currField?.columnType;
columnFilters = currField?.columnFilters;
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;
columnLabel = customField.options?.[0].label;
}
}
return { fieldName, columnType, columnFilters };
return { fieldName, columnType, columnFilters, columnLabel };
};
export class LensAttributes {
@ -260,12 +263,14 @@ export class LensAttributes {
label?: string,
colIndex?: number
) {
const { fieldMeta, columnType, fieldName, columnFilters } = this.getFieldMeta(sourceField);
const { fieldMeta, columnType, fieldName, columnFilters, columnLabel } = this.getFieldMeta(
sourceField
);
const { type: fieldType } = fieldMeta ?? {};
if (fieldName === 'Records' || columnType === FILTER_RECORDS) {
return this.getRecordsColumn(
label,
columnLabel || label,
colIndex !== undefined ? columnFilters?.[colIndex] : undefined
);
}
@ -274,7 +279,7 @@ export class LensAttributes {
return this.getDateHistogramColumn(fieldName);
}
if (fieldType === 'number') {
return this.getNumberColumn(fieldName, columnType, operationType, label);
return this.getNumberColumn(fieldName, columnType, operationType, columnLabel || label);
}
// FIXME review my approach again
@ -286,11 +291,13 @@ export class LensAttributes {
}
getFieldMeta(sourceField: string) {
const { fieldName, columnType, columnFilters } = this.getCustomFieldName(sourceField);
const { fieldName, columnType, columnFilters, columnLabel } = this.getCustomFieldName(
sourceField
);
const fieldMeta = this.indexPattern.getFieldByName(fieldName);
return { fieldMeta, fieldName, columnType, columnFilters };
return { fieldMeta, fieldName, columnType, columnFilters, columnLabel };
}
getMainYAxis() {

View file

@ -1,41 +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 } from '../../types';
import { FieldLabels } from '../constants';
interface Props {
seriesId: string;
}
export function getLogsFrequencyLensConfig({ seriesId }: Props): DataSeries {
return {
id: seriesId,
reportType: 'logs-frequency',
defaultSeriesType: 'line',
seriesTypes: ['line', 'bar'],
xAxisColumn: {
sourceField: '@timestamp',
},
yAxisColumns: [
{
operationType: 'count',
},
],
hasOperationType: false,
defaultFilters: [],
breakdowns: ['agent.hostname'],
filters: [],
labels: { ...FieldLabels },
reportDefinitions: [
{
field: 'agent.hostname',
required: true,
},
],
};
}

View file

@ -5,17 +5,12 @@
* 2.0.
*/
import { DataSeries } from '../../types';
import { DataSeries, ConfigProps } from '../../types';
import { FieldLabels } from '../constants';
interface Props {
seriesId: string;
}
export function getCPUUsageLensConfig({ seriesId }: Props): DataSeries {
export function getCPUUsageLensConfig({}: ConfigProps): DataSeries {
return {
id: seriesId,
reportType: 'cpu-usage',
reportType: 'kpi-over-time',
defaultSeriesType: 'line',
seriesTypes: ['line', 'bar'],
xAxisColumn: {

View file

@ -5,17 +5,12 @@
* 2.0.
*/
import { DataSeries } from '../../types';
import { DataSeries, ConfigProps } from '../../types';
import { FieldLabels } from '../constants';
interface Props {
seriesId: string;
}
export function getMemoryUsageLensConfig({ seriesId }: Props): DataSeries {
export function getMemoryUsageLensConfig({}: ConfigProps): DataSeries {
return {
id: seriesId,
reportType: 'memory-usage',
reportType: 'kpi-over-time',
defaultSeriesType: 'line',
seriesTypes: ['line', 'bar'],
xAxisColumn: {

View file

@ -5,17 +5,12 @@
* 2.0.
*/
import { DataSeries } from '../../types';
import { DataSeries, ConfigProps } from '../../types';
import { FieldLabels } from '../constants';
interface Props {
seriesId: string;
}
export function getNetworkActivityLensConfig({ seriesId }: Props): DataSeries {
export function getNetworkActivityLensConfig({}: ConfigProps): DataSeries {
return {
id: seriesId,
reportType: 'network-activity',
reportType: 'kpi-over-time',
defaultSeriesType: 'line',
seriesTypes: ['line', 'bar'],
xAxisColumn: {

View file

@ -27,13 +27,12 @@ import {
SERVICE_ENVIRONMENT,
} from '../constants/elasticsearch_fieldnames';
export function getCoreWebVitalsConfig({ seriesId, indexPattern }: ConfigProps): DataSeries {
export function getCoreWebVitalsConfig({ indexPattern }: ConfigProps): DataSeries {
const statusPallete = euiPaletteForStatus(3);
return {
id: seriesId,
defaultSeriesType: 'bar_horizontal_percentage_stacked',
reportType: 'kpi-trends',
reportType: 'core-web-vitals',
seriesTypes: ['bar_horizontal_percentage_stacked'],
xAxisColumn: {
sourceField: USE_BREAK_DOWN_COLUMN,

View file

@ -39,10 +39,9 @@ import {
WEB_APPLICATION_LABEL,
} from '../constants/labels';
export function getPerformanceDistLensConfig({ seriesId, indexPattern }: ConfigProps): DataSeries {
export function getRumDistributionConfig({ indexPattern }: ConfigProps): DataSeries {
return {
id: seriesId ?? 'unique-key',
reportType: 'page-load-dist',
reportType: 'data-distribution',
defaultSeriesType: 'line',
seriesTypes: [],
xAxisColumn: {

View file

@ -39,12 +39,11 @@ import {
WEB_APPLICATION_LABEL,
} from '../constants/labels';
export function getKPITrendsLensConfig({ seriesId, indexPattern }: ConfigProps): DataSeries {
export function getKPITrendsLensConfig({ indexPattern }: ConfigProps): DataSeries {
return {
id: seriesId,
defaultSeriesType: 'bar_stacked',
reportType: 'kpi-trends',
seriesTypes: [],
reportType: 'kpi-over-time',
xAxisColumn: {
sourceField: '@timestamp',
},

View file

@ -6,27 +6,25 @@
*/
import { ConfigProps, DataSeries } from '../../types';
import { FieldLabels } from '../constants';
import { FieldLabels, RECORDS_FIELD } from '../constants';
import { buildExistsFilter } from '../utils';
import { MONITORS_DURATION_LABEL } from '../constants/labels';
import { MONITORS_DURATION_LABEL, PINGS_LABEL } from '../constants/labels';
export function getMonitorDurationConfig({ seriesId, indexPattern }: ConfigProps): DataSeries {
export function getSyntheticsDistributionConfig({ indexPattern }: ConfigProps): DataSeries {
return {
id: seriesId,
reportType: 'uptime-duration',
reportType: 'data-distribution',
defaultSeriesType: 'line',
seriesTypes: [],
xAxisColumn: {
sourceField: '@timestamp',
sourceField: 'performance.metric',
},
yAxisColumns: [
{
operationType: 'average',
sourceField: 'monitor.duration.us',
label: MONITORS_DURATION_LABEL,
sourceField: RECORDS_FIELD,
label: PINGS_LABEL,
},
],
hasOperationType: true,
hasOperationType: false,
defaultFilters: ['monitor.type', 'observer.geo.name', 'tags'],
breakdowns: [
'observer.geo.name',
@ -44,6 +42,13 @@ export function getMonitorDurationConfig({ seriesId, indexPattern }: ConfigProps
{
field: 'url.full',
},
{
field: 'performance.metric',
custom: true,
options: [
{ label: 'Monitor duration', id: 'monitor.duration.us', field: 'monitor.duration.us' },
],
},
],
labels: { ...FieldLabels, 'monitor.duration.us': MONITORS_DURATION_LABEL },
};

View file

@ -0,0 +1,69 @@
/*
* 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, OPERATION_COLUMN } 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 {
return {
reportType: 'kpi-over-time',
defaultSeriesType: 'bar_stacked',
seriesTypes: [],
xAxisColumn: {
sourceField: '@timestamp',
},
yAxisColumns: [
{
sourceField: 'business.kpi',
operationType: 'median',
},
],
hasOperationType: false,
defaultFilters: ['observer.geo.name', 'monitor.type', 'tags'],
breakdowns: ['observer.geo.name', 'monitor.type'],
filters: [...buildExistsFilter('summary.up', indexPattern)],
palette: { type: 'palette', name: 'status' },
reportDefinitions: [
{
field: 'monitor.name',
},
{
field: 'url.full',
},
{
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,
},
],
},
],
labels: { ...FieldLabels },
};
}

View file

@ -1,50 +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 { buildExistsFilter } from '../utils';
import { DOWN_LABEL, UP_LABEL } from '../constants/labels';
export function getMonitorPingsConfig({ seriesId, indexPattern }: ConfigProps): DataSeries {
return {
id: seriesId,
reportType: 'uptime-pings',
defaultSeriesType: 'bar_stacked',
seriesTypes: [],
xAxisColumn: {
sourceField: '@timestamp',
},
yAxisColumns: [
{
operationType: 'sum',
sourceField: 'summary.up',
label: UP_LABEL,
},
{
operationType: 'sum',
sourceField: 'summary.down',
label: DOWN_LABEL,
},
],
yTitle: 'Pings',
hasOperationType: false,
defaultFilters: ['observer.geo.name', 'monitor.type', 'tags'],
breakdowns: ['observer.geo.name', 'monitor.type'],
filters: [...buildExistsFilter('summary.up', indexPattern)],
palette: { type: 'palette', name: 'status' },
reportDefinitions: [
{
field: 'monitor.name',
},
{
field: 'url.full',
},
],
labels: { ...FieldLabels },
};
}

View file

@ -52,7 +52,7 @@ describe('ExploratoryView', () => {
data: {
'ux-series': {
dataType: 'ux' as const,
reportType: 'pld' as const,
reportType: 'dist' as const,
breakdown: 'user_agent .name',
reportDefinitions: { 'service.name': ['elastic-co'] },
time: { from: 'now-15m', to: 'now' },

View file

@ -16,7 +16,6 @@ import { useLensAttributes } from './hooks/use_lens_attributes';
import { EmptyView } from './components/empty_view';
import { TypedLensByValueInput } from '../../../../../lens/public';
import { useAppIndexPatternContext } from './hooks/use_app_index_pattern';
import { ReportToDataTypeMap } from './configurations/constants';
import { SeriesBuilder } from './series_builder/series_builder';
export function ExploratoryView({
@ -61,10 +60,10 @@ export function ExploratoryView({
};
useEffect(() => {
if (series?.reportType || series?.dataType) {
loadIndexPattern({ dataType: series?.dataType ?? ReportToDataTypeMap[series?.reportType] });
if (series?.dataType) {
loadIndexPattern({ dataType: series?.dataType });
}
}, [series?.reportType, series?.dataType, loadIndexPattern]);
}, [series?.dataType, loadIndexPattern]);
useEffect(() => {
setLensAttributes(lensAttributesT);
@ -91,7 +90,7 @@ export function ExploratoryView({
timeRange={series?.time}
attributes={lensAttributes}
onBrushEnd={({ range }) => {
if (series?.reportType !== 'pld') {
if (series?.reportType !== 'dist') {
setSeries(seriesId, {
...series,
time: {

View file

@ -26,7 +26,7 @@ describe('ExploratoryViewHeader', function () {
data: {
'uptime-pings-histogram': {
dataType: 'synthetics' as const,
reportType: 'upp' as const,
reportType: 'kpi' as const,
breakdown: 'monitor.status',
time: { from: 'now-15m', to: 'now' },
},

View file

@ -42,7 +42,8 @@ export const useLensAttributes = ({
}: Props): TypedLensByValueInput['attributes'] | null => {
const { getSeries } = useSeriesStorage();
const series = getSeries(seriesId);
const { breakdown, seriesType, operationType, reportType, reportDefinitions = {} } = series ?? {};
const { breakdown, seriesType, operationType, reportType, dataType, reportDefinitions = {} } =
series ?? {};
const { indexPattern } = useAppIndexPatternContext();
@ -52,8 +53,8 @@ export const useLensAttributes = ({
}
const dataViewConfig = getDefaultConfigs({
seriesId,
reportType,
dataType,
indexPattern,
});
@ -78,12 +79,12 @@ export const useLensAttributes = ({
return lensAttributes.getJSON();
}, [
indexPattern,
breakdown,
seriesType,
operationType,
reportType,
reportDefinitions,
seriesId,
dataType,
series.filters,
seriesType,
operationType,
breakdown,
]);
};

View file

@ -259,7 +259,7 @@ function mockSeriesStorageContext({
}) {
const mockDataSeries = data || {
'performance-distribution': {
reportType: 'pld',
reportType: 'dist',
dataType: 'ux',
breakdown: breakdown || 'user_agent.name',
time: { from: 'now-15m', to: 'now' },

View file

@ -37,7 +37,7 @@ describe('DataTypesCol', function () {
data: {
[seriesId]: {
dataType: 'synthetics' as const,
reportType: 'upp' as const,
reportType: 'kpi' as const,
breakdown: 'monitor.status',
time: { from: 'now-15m', to: 'now' },
},

View file

@ -11,7 +11,6 @@ import styled from 'styled-components';
import { AppDataType } from '../../types';
import { useAppIndexPatternContext } from '../../hooks/use_app_index_pattern';
import { useSeriesStorage } from '../../hooks/use_series_storage';
import { ReportToDataTypeMap } from '../../configurations/constants';
export const dataTypes: Array<{ id: AppDataType; label: string }> = [
{ id: 'synthetics', label: 'Synthetic Monitoring' },
@ -35,7 +34,7 @@ export function DataTypesCol({ seriesId }: { seriesId: string }) {
}
};
const selectedDataType = series.dataType ?? ReportToDataTypeMap[series.reportType];
const selectedDataType = series.dataType;
return (
<FlexGroup direction="column" gutterSize="xs">

View file

@ -48,6 +48,12 @@ export function OperationTypeSelect({
defaultMessage: 'Median',
}),
},
{
value: 'sum' as OperationType,
inputDisplay: i18n.translate('xpack.observability.expView.operationType.sum', {
defaultMessage: 'Sum',
}),
},
{
value: '75th' as OperationType,
inputDisplay: i18n.translate('xpack.observability.expView.operationType.75thPercentile', {

View file

@ -15,8 +15,8 @@ import { USER_AGENT_OS } from '../../configurations/constants/elasticsearch_fiel
describe('Series Builder ReportBreakdowns', function () {
const seriesId = 'test-series-id';
const dataViewSeries = getDefaultConfigs({
seriesId,
reportType: 'pld',
reportType: 'dist',
dataType: 'ux',
indexPattern: mockIndexPattern,
});
@ -45,7 +45,7 @@ describe('Series Builder ReportBreakdowns', function () {
expect(setSeries).toHaveBeenCalledWith(seriesId, {
breakdown: USER_AGENT_OS,
dataType: 'ux',
reportType: 'pld',
reportType: 'dist',
time: { from: 'now-15m', to: 'now' },
});
});
@ -67,7 +67,7 @@ describe('Series Builder ReportBreakdowns', function () {
expect(setSeries).toHaveBeenCalledWith(seriesId, {
breakdown: undefined,
dataType: 'ux',
reportType: 'pld',
reportType: 'dist',
time: { from: 'now-15m', to: 'now' },
});
});

View file

@ -22,16 +22,16 @@ describe('Series Builder ReportDefinitionCol', function () {
const seriesId = 'test-series-id';
const dataViewSeries = getDefaultConfigs({
seriesId,
reportType: 'pld',
reportType: 'dist',
indexPattern: mockIndexPattern,
dataType: 'ux',
});
const initSeries = {
data: {
[seriesId]: {
dataType: 'ux' as const,
reportType: 'pld' as const,
reportType: 'dist' as const,
time: { from: 'now-30d', to: 'now' },
reportDefinitions: { [SERVICE_NAME]: ['elastic-co'] },
},
@ -81,7 +81,7 @@ describe('Series Builder ReportDefinitionCol', function () {
expect(setSeries).toHaveBeenCalledWith(seriesId, {
dataType: 'ux',
reportDefinitions: {},
reportType: 'pld',
reportType: 'dist',
time: { from: 'now-30d', to: 'now' },
});
});

View file

@ -15,9 +15,9 @@ describe('Series Builder ReportFilters', function () {
const seriesId = 'test-series-id';
const dataViewSeries = getDefaultConfigs({
seriesId,
reportType: 'pld',
reportType: 'dist',
indexPattern: mockIndexPattern,
dataType: 'ux',
});
it('should render properly', function () {

View file

@ -34,13 +34,13 @@ describe('ReportTypesCol', function () {
<ReportTypesCol reportTypes={ReportTypes.synthetics} seriesId={seriesId} />
);
fireEvent.click(screen.getByText(/monitor duration/i));
fireEvent.click(screen.getByText(/KPI over time/i));
expect(setSeries).toHaveBeenCalledWith(seriesId, {
breakdown: 'user_agent.name',
dataType: 'ux',
reportDefinitions: {},
reportType: 'upd',
reportType: 'kpi',
time: { from: 'now-15m', to: 'now' },
});
expect(setSeries).toHaveBeenCalledTimes(1);
@ -51,7 +51,7 @@ describe('ReportTypesCol', function () {
data: {
[NEW_SERIES_KEY]: {
dataType: 'synthetics' as const,
reportType: 'upp' as const,
reportType: 'kpi' as const,
breakdown: 'monitor.status',
time: { from: 'now-15m', to: 'now' },
},
@ -64,7 +64,7 @@ describe('ReportTypesCol', function () {
);
const button = screen.getByRole('button', {
name: /pings histogram/i,
name: /KPI over time/i,
});
expect(button.classList).toContain('euiButton--fill');

View file

@ -21,29 +21,17 @@ import { getDefaultConfigs } from '../configurations/default_configs';
export const ReportTypes: Record<AppDataType, Array<{ id: ReportViewTypeId; label: string }>> = {
synthetics: [
{ id: 'upd', label: 'Monitor duration' },
{ id: 'upp', label: 'Pings histogram' },
{ id: 'kpi', label: 'KPI over time' },
{ id: 'dist', label: 'Performance distribution' },
],
ux: [
{ id: 'pld', label: 'Performance distribution' },
{ id: 'kpi', label: 'KPI over time' },
{ id: 'dist', label: 'Performance distribution' },
{ id: 'cwv', label: 'Core Web Vitals' },
],
apm: [
{ id: 'svl', label: 'Latency' },
{ id: 'tpt', label: 'Throughput' },
],
infra_logs: [
{
id: 'logs',
label: 'Logs Frequency',
},
],
infra_metrics: [
{ id: 'cpu', label: 'CPU usage' },
{ id: 'mem', label: 'Memory usage' },
{ id: 'nwk', label: 'Network activity' },
],
apm: [],
infra_logs: [],
infra_metrics: [],
};
export function SeriesBuilder({
@ -72,7 +60,7 @@ export function SeriesBuilder({
const getDataViewSeries = () => {
return getDefaultConfigs({
seriesId,
dataType,
indexPattern,
reportType: reportType!,
});

View file

@ -17,7 +17,7 @@ describe('SeriesDatePicker', function () {
data: {
'uptime-pings-histogram': {
dataType: 'synthetics' as const,
reportType: 'upp' as const,
reportType: 'dist' as const,
breakdown: 'monitor.status',
time: { from: 'now-30m', to: 'now' },
},
@ -32,7 +32,7 @@ describe('SeriesDatePicker', function () {
const initSeries = {
data: {
'uptime-pings-histogram': {
reportType: 'upp' as const,
reportType: 'kpi' as const,
dataType: 'synthetics' as const,
breakdown: 'monitor.status',
},
@ -46,7 +46,7 @@ describe('SeriesDatePicker', function () {
expect(setSeries1).toHaveBeenCalledWith('uptime-pings-histogram', {
breakdown: 'monitor.status',
dataType: 'synthetics' as const,
reportType: 'upp' as const,
reportType: 'kpi' as const,
time: DEFAULT_TIME,
});
});
@ -56,7 +56,7 @@ describe('SeriesDatePicker', function () {
data: {
'uptime-pings-histogram': {
dataType: 'synthetics' as const,
reportType: 'upp' as const,
reportType: 'kpi' as const,
breakdown: 'monitor.status',
time: { from: 'now-30m', to: 'now' },
},
@ -79,7 +79,7 @@ describe('SeriesDatePicker', function () {
expect(setSeries).toHaveBeenCalledWith('series-id', {
breakdown: 'monitor.status',
dataType: 'synthetics',
reportType: 'upp',
reportType: 'kpi',
time: { from: 'now/d', to: 'now/d' },
});
expect(setSeries).toHaveBeenCalledTimes(1);

View file

@ -23,7 +23,7 @@ export function ChartEditOptions({ series, seriesId, breakdowns }: Props) {
<Breakdowns seriesId={seriesId} breakdowns={breakdowns} reportViewConfig={series} />
</EuiFlexItem>
<EuiFlexItem>
<ChartOptions series={series} />
<ChartOptions series={series} seriesId={seriesId} />
</EuiFlexItem>
</EuiFlexGroup>
);

View file

@ -9,15 +9,14 @@ import React from 'react';
import { fireEvent, screen } from '@testing-library/react';
import { Breakdowns } from './breakdowns';
import { mockIndexPattern, render } from '../../rtl_helpers';
import { NEW_SERIES_KEY } from '../../hooks/use_series_storage';
import { getDefaultConfigs } from '../../configurations/default_configs';
import { USER_AGENT_OS } from '../../configurations/constants/elasticsearch_fieldnames';
describe('Breakdowns', function () {
const dataViewSeries = getDefaultConfigs({
reportType: 'pld',
reportType: 'dist',
indexPattern: mockIndexPattern,
seriesId: NEW_SERIES_KEY,
dataType: 'ux',
});
it('should render properly', async function () {
@ -53,7 +52,7 @@ describe('Breakdowns', function () {
expect(setSeries).toHaveBeenCalledWith('series-id', {
breakdown: 'user_agent.name',
dataType: 'ux',
reportType: 'pld',
reportType: 'dist',
time: { from: 'now-15m', to: 'now' },
});
expect(setSeries).toHaveBeenCalledTimes(1);

View file

@ -13,17 +13,18 @@ import { SeriesChartTypesSelect } from '../../series_builder/columns/chart_types
interface Props {
series: DataSeries;
seriesId: string;
}
export function ChartOptions({ series }: Props) {
export function ChartOptions({ series, seriesId }: Props) {
return (
<EuiFlexGroup direction="column" gutterSize="s" justifyContent="center">
<EuiFlexItem grow={false}>
<SeriesChartTypesSelect seriesId={series.id} defaultChartType={series.seriesTypes[0]} />
<SeriesChartTypesSelect seriesId={seriesId} defaultChartType={series.seriesTypes[0]} />
</EuiFlexItem>
{series.hasOperationType && (
<EuiFlexItem grow={false}>
<OperationTypeSelect seriesId={series.id} />
<OperationTypeSelect seriesId={seriesId} />
</EuiFlexItem>
)}
</EuiFlexGroup>

View file

@ -10,7 +10,6 @@ import { EuiButtonIcon, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { RemoveSeries } from './remove_series';
import { NEW_SERIES_KEY, useSeriesStorage } from '../../hooks/use_series_storage';
import { ReportToDataTypeMap } from '../../configurations/constants';
interface Props {
seriesId: string;
@ -21,7 +20,7 @@ export function SeriesActions({ seriesId }: Props) {
const onEdit = () => {
removeSeries(seriesId);
setSeries(NEW_SERIES_KEY, { ...series, dataType: ReportToDataTypeMap[series.reportType] });
setSeries(NEW_SERIES_KEY, { ...series });
};
return (

View file

@ -10,16 +10,15 @@ import { screen, waitFor } from '@testing-library/react';
import { mockAppIndexPattern, mockIndexPattern, render } from '../rtl_helpers';
import { SelectedFilters } from './selected_filters';
import { getDefaultConfigs } from '../configurations/default_configs';
import { NEW_SERIES_KEY } from '../hooks/use_series_storage';
import { USER_AGENT_NAME } from '../configurations/constants/elasticsearch_fieldnames';
describe('SelectedFilters', function () {
mockAppIndexPattern();
const dataViewSeries = getDefaultConfigs({
reportType: 'pld',
reportType: 'dist',
indexPattern: mockIndexPattern,
seriesId: NEW_SERIES_KEY,
dataType: 'ux',
});
it('should render properly', async function () {

View file

@ -18,6 +18,11 @@ import { useAppIndexPatternContext } from '../hooks/use_app_index_pattern';
import { SeriesActions } from './columns/series_actions';
import { ChartEditOptions } from './chart_edit_options';
interface EditItem {
seriesConfig: DataSeries;
id: string;
}
export function SeriesEditor() {
const { allSeries, firstSeriesId } = useSeriesStorage();
@ -43,8 +48,8 @@ export function SeriesEditor() {
}),
field: 'defaultFilters',
width: '15%',
render: (defaultFilters: string[], series: DataSeries) => (
<SeriesFilter defaultFilters={defaultFilters} seriesId={series.id} series={series} />
render: (defaultFilters: string[], { id, seriesConfig }: EditItem) => (
<SeriesFilter defaultFilters={defaultFilters} seriesId={id} series={seriesConfig} />
),
},
{
@ -53,8 +58,8 @@ export function SeriesEditor() {
}),
field: 'breakdowns',
width: '25%',
render: (val: string[], item: DataSeries) => (
<ChartEditOptions seriesId={item.id} breakdowns={val} series={item} />
render: (val: string[], item: EditItem) => (
<ChartEditOptions seriesId={item.id} breakdowns={val} series={item.seriesConfig} />
),
},
{
@ -69,7 +74,7 @@ export function SeriesEditor() {
width: '20%',
field: 'id',
align: 'right' as const,
render: (val: string, item: DataSeries) => <DatePickerCol seriesId={item.id} />,
render: (val: string, item: EditItem) => <DatePickerCol seriesId={item.id} />,
},
{
name: i18n.translate('xpack.observability.expView.seriesEditor.actions', {
@ -78,7 +83,7 @@ export function SeriesEditor() {
align: 'center' as const,
width: '10%',
field: 'id',
render: (val: string, item: DataSeries) => <SeriesActions seriesId={item.id} />,
render: (val: string, item: EditItem) => <SeriesActions seriesId={item.id} />,
},
]
: []),
@ -86,20 +91,21 @@ export function SeriesEditor() {
const allSeriesKeys = Object.keys(allSeries);
const items: DataSeries[] = [];
const items: EditItem[] = [];
const { indexPattern } = useAppIndexPatternContext();
allSeriesKeys.forEach((seriesKey) => {
const series = allSeries[seriesKey];
if (series.reportType && indexPattern) {
items.push(
getDefaultConfigs({
items.push({
id: seriesKey,
seriesConfig: getDefaultConfigs({
indexPattern,
reportType: series.reportType,
seriesId: seriesKey,
})
);
dataType: series.dataType,
}),
});
}
});

View file

@ -20,17 +20,9 @@ import { IIndexPattern } from '../../../../../../../src/plugins/data/common/inde
import { ExistsFilter } from '../../../../../../../src/plugins/data/common/es_query/filters';
export const ReportViewTypes = {
pld: 'page-load-dist',
kpi: 'kpi-trends',
dist: 'data-distribution',
kpi: 'kpi-over-time',
cwv: 'core-web-vitals',
upd: 'uptime-duration',
upp: 'uptime-pings',
svl: 'service-latency',
tpt: 'service-throughput',
logs: 'logs-frequency',
cpu: 'cpu-usage',
mem: 'memory-usage',
nwk: 'network-activity',
} as const;
type ValueOf<T> = T[keyof T];
@ -60,7 +52,6 @@ export interface ReportDefinition {
export interface DataSeries {
reportType: ReportViewType;
id: string;
xAxisColumn: Partial<LastValueIndexPatternColumn> | Partial<DateHistogramIndexPatternColumn>;
yAxisColumns: Array<Partial<FieldBasedIndexPatternColumn>>;
@ -100,7 +91,6 @@ export interface UrlFilter {
}
export interface ConfigProps {
seriesId: string;
indexPattern: IIndexPattern;
}

View file

@ -191,7 +191,7 @@ export const PingHistogramComponent: React.FC<PingHistogramComponentProps> = ({
{
'pings-over-time': {
dataType: 'synthetics',
reportType: 'upp',
reportType: 'kpi',
time: { from: dateRangeStart, to: dateRangeEnd },
...(monitorId ? { filters: [{ field: 'monitor.id', values: [monitorId] }] } : {}),
},

View file

@ -56,7 +56,7 @@ export const MonitorDuration: React.FC<MonitorIdParam> = ({ monitorId }) => {
const exploratoryViewLink = createExploratoryViewUrl(
{
[`monitor-duration`]: {
reportType: 'upd',
reportType: 'kpi',
time: { from: dateRangeStart, to: dateRangeEnd },
reportDefinitions: {
'monitor.id': [monitorId] as string[],