[Exploratory view] Use index patterns for formatting (#96280)

This commit is contained in:
Shahzad 2021-04-08 07:16:23 +02:00 committed by GitHub
parent 93965343e5
commit 391e92ead3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
65 changed files with 470 additions and 123 deletions

1
.github/CODEOWNERS vendored
View file

@ -79,6 +79,7 @@
# Uptime # Uptime
/x-pack/plugins/uptime @elastic/uptime /x-pack/plugins/uptime @elastic/uptime
/x-pack/plugins/observability/public/components/shared/exploratory_view @elastic/uptime
/x-pack/test/functional_with_es_ssl/apps/uptime @elastic/uptime /x-pack/test/functional_with_es_ssl/apps/uptime @elastic/uptime
/x-pack/test/functional/apps/uptime @elastic/uptime /x-pack/test/functional/apps/uptime @elastic/uptime
/x-pack/test/api_integration/apis/uptime @elastic/uptime /x-pack/test/api_integration/apis/uptime @elastic/uptime

View file

@ -9,6 +9,7 @@
import sinon from 'sinon'; import sinon from 'sinon';
import { CoreSetup } from 'src/core/public'; import { CoreSetup } from 'src/core/public';
import { SerializedFieldFormat } from 'src/plugins/expressions/public';
import { IFieldType, FieldSpec } from '../../common/index_patterns'; import { IFieldType, FieldSpec } from '../../common/index_patterns';
import { IndexPattern, indexPatterns, KBN_FIELD_TYPES, fieldList } from '../'; import { IndexPattern, indexPatterns, KBN_FIELD_TYPES, fieldList } from '../';
import { getFieldFormatsRegistry } from '../test_utils'; import { getFieldFormatsRegistry } from '../test_utils';
@ -51,6 +52,7 @@ export class StubIndexPattern {
_reindexFields: Function; _reindexFields: Function;
stubSetFieldFormat: Function; stubSetFieldFormat: Function;
fields?: FieldSpec[]; fields?: FieldSpec[];
setFieldFormat: (fieldName: string, format: SerializedFieldFormat) => void;
constructor( constructor(
pattern: string, pattern: string,
@ -74,6 +76,10 @@ export class StubIndexPattern {
this.metaFields = ['_id', '_type', '_source']; this.metaFields = ['_id', '_type', '_source'];
this.fieldFormatMap = {}; this.fieldFormatMap = {};
this.setFieldFormat = (fieldName: string, format: SerializedFieldFormat) => {
this.fieldFormatMap[fieldName] = format;
};
this.getComputedFields = IndexPattern.prototype.getComputedFields.bind(this); this.getComputedFields = IndexPattern.prototype.getComputedFields.bind(this);
this.flattenHit = indexPatterns.flattenHitWrapper( this.flattenHit = indexPatterns.flattenHitWrapper(
(this as unknown) as IndexPattern, (this as unknown) as IndexPattern,

View file

@ -543,6 +543,7 @@ exports[`discover sidebar field details footer renders properly 1`] = `
"_source", "_source",
], ],
"popularizeField": [Function], "popularizeField": [Function],
"setFieldFormat": [Function],
"stubSetFieldFormat": [Function], "stubSetFieldFormat": [Function],
"timeFieldName": "time", "timeFieldName": "time",
"title": "logstash-*", "title": "logstash-*",

View file

@ -21,7 +21,7 @@ export type {
YAxisMode, YAxisMode,
XYCurveType, XYCurveType,
} from './xy_visualization/types'; } from './xy_visualization/types';
export type { DataType } from './types'; export type { DataType, OperationMetadata } from './types';
export type { export type {
PieVisualizationState, PieVisualizationState,
PieLayerState, PieLayerState,

View file

@ -18,7 +18,7 @@ const createStartContract = (): Start => {
}), }),
canUseEditor: jest.fn(() => true), canUseEditor: jest.fn(() => true),
navigateToPrefilledEditor: jest.fn(), navigateToPrefilledEditor: jest.fn(),
getXyVisTypes: jest.fn().mockReturnValue(new Promise(() => visualizationTypes)), getXyVisTypes: jest.fn().mockReturnValue(new Promise((resolve) => resolve(visualizationTypes))),
}; };
return startContract; return startContract;
}; };

View file

@ -5,10 +5,10 @@
* 2.0. * 2.0.
*/ */
import { ConfigProps, DataSeries } from '../types'; import { ConfigProps, DataSeries } from '../../types';
import { FieldLabels } from './constants'; import { FieldLabels } from '../constants';
import { buildPhraseFilter } from './utils'; import { buildPhraseFilter } from '../utils';
import { OperationType } from '../../../../../../lens/public'; import { OperationType } from '../../../../../../../lens/public';
export function getServiceLatencyLensConfig({ seriesId, indexPattern }: ConfigProps): DataSeries { export function getServiceLatencyLensConfig({ seriesId, indexPattern }: ConfigProps): DataSeries {
return { return {
@ -20,7 +20,7 @@ export function getServiceLatencyLensConfig({ seriesId, indexPattern }: ConfigPr
sourceField: '@timestamp', sourceField: '@timestamp',
}, },
yAxisColumn: { yAxisColumn: {
operationType: 'avg' as OperationType, operationType: 'average' as OperationType,
sourceField: 'transaction.duration.us', sourceField: 'transaction.duration.us',
label: 'Latency', label: 'Latency',
}, },

View file

@ -5,10 +5,10 @@
* 2.0. * 2.0.
*/ */
import { ConfigProps, DataSeries } from '../types'; import { ConfigProps, DataSeries } from '../../types';
import { FieldLabels } from './constants'; import { FieldLabels } from '../constants/constants';
import { buildPhraseFilter } from './utils'; import { buildPhraseFilter } from '../utils';
import { OperationType } from '../../../../../../lens/public'; import { OperationType } from '../../../../../../../lens/public';
export function getServiceThroughputLensConfig({ export function getServiceThroughputLensConfig({
seriesId, seriesId,
@ -23,7 +23,7 @@ export function getServiceThroughputLensConfig({
sourceField: '@timestamp', sourceField: '@timestamp',
}, },
yAxisColumn: { yAxisColumn: {
operationType: 'avg' as OperationType, operationType: 'average' as OperationType,
sourceField: 'transaction.duration.us', sourceField: 'transaction.duration.us',
label: 'Throughput', label: 'Throughput',
}, },

View file

@ -5,14 +5,8 @@
* 2.0. * 2.0.
*/ */
import { AppDataType, ReportViewTypeId } from '../types'; import { AppDataType, ReportViewTypeId } from '../../types';
import { import { CLS_FIELD, FCP_FIELD, FID_FIELD, LCP_FIELD, TBT_FIELD } from './elasticsearch_fieldnames';
CLS_FIELD,
FCP_FIELD,
FID_FIELD,
LCP_FIELD,
TBT_FIELD,
} from './data/elasticsearch_fieldnames';
export const FieldLabels: Record<string, string> = { export const FieldLabels: Record<string, string> = {
'user_agent.name': 'Browser family', 'user_agent.name': 'Browser family',
@ -24,10 +18,10 @@ export const FieldLabels: Record<string, string> = {
'service.name': 'Service Name', 'service.name': 'Service Name',
'service.environment': 'Environment', 'service.environment': 'Environment',
[LCP_FIELD]: 'Largest contentful paint', [LCP_FIELD]: 'Largest contentful paint (Seconds)',
[FCP_FIELD]: 'First contentful paint', [FCP_FIELD]: 'First contentful paint (Seconds)',
[TBT_FIELD]: 'Total blocking time', [TBT_FIELD]: 'Total blocking time (Seconds)',
[FID_FIELD]: 'First input delay', [FID_FIELD]: 'First input delay (Seconds)',
[CLS_FIELD]: 'Cumulative layout shift', [CLS_FIELD]: 'Cumulative layout shift',
'monitor.id': 'Monitor Id', 'monitor.id': 'Monitor Id',
@ -38,6 +32,7 @@ export const FieldLabels: Record<string, string> = {
'monitor.name': 'Monitor name', 'monitor.name': 'Monitor name',
'monitor.type': 'Monitor Type', 'monitor.type': 'Monitor Type',
'url.port': 'Port', 'url.port': 'Port',
'url.full': 'Url',
tags: 'Tags', tags: 'Tags',
// custom // custom

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 * from './constants';

View file

@ -6,16 +6,16 @@
*/ */
import { ReportViewTypes } from '../types'; import { ReportViewTypes } from '../types';
import { getPerformanceDistLensConfig } from './performance_dist_config'; import { getPerformanceDistLensConfig } from './rum/performance_dist_config';
import { getMonitorDurationConfig } from './monitor_duration_config'; import { getMonitorDurationConfig } from './synthetics/monitor_duration_config';
import { getServiceLatencyLensConfig } from './service_latency_config'; import { getServiceLatencyLensConfig } from './apm/service_latency_config';
import { getMonitorPingsConfig } from './monitor_pings_config'; import { getMonitorPingsConfig } from './synthetics/monitor_pings_config';
import { getServiceThroughputLensConfig } from './service_throughput_config'; import { getServiceThroughputLensConfig } from './apm/service_throughput_config';
import { getKPITrendsLensConfig } from './kpi_trends_config'; import { getKPITrendsLensConfig } from './rum/kpi_trends_config';
import { getCPUUsageLensConfig } from './cpu_usage_config'; import { getCPUUsageLensConfig } from './metrics/cpu_usage_config';
import { getMemoryUsageLensConfig } from './memory_usage_config'; import { getMemoryUsageLensConfig } from './metrics/memory_usage_config';
import { getNetworkActivityLensConfig } from './network_activity_config'; import { getNetworkActivityLensConfig } from './metrics/network_activity_config';
import { getLogsFrequencyLensConfig } from './logs_frequency_config'; import { getLogsFrequencyLensConfig } from './logs/logs_frequency_config';
import { IIndexPattern } from '../../../../../../../../src/plugins/data/common/index_patterns'; import { IIndexPattern } from '../../../../../../../../src/plugins/data/common/index_patterns';
interface Props { interface Props {

View file

@ -8,9 +8,8 @@
import { LensAttributes } from './lens_attributes'; import { LensAttributes } from './lens_attributes';
import { mockIndexPattern } from '../rtl_helpers'; import { mockIndexPattern } from '../rtl_helpers';
import { getDefaultConfigs } from './default_configs'; import { getDefaultConfigs } from './default_configs';
import { sampleAttribute } from './data/sample_attribute'; import { sampleAttribute } from './test_data/sample_attribute';
import { LCP_FIELD, SERVICE_NAME } from './data/elasticsearch_fieldnames'; import { LCP_FIELD, SERVICE_NAME, USER_AGENT_NAME } from './constants/elasticsearch_fieldnames';
import { USER_AGENT_NAME } from './data/elasticsearch_fieldnames';
describe('Lens Attribute', () => { describe('Lens Attribute', () => {
const reportViewConfig = getDefaultConfigs({ const reportViewConfig = getDefaultConfigs({
@ -93,7 +92,7 @@ describe('Lens Attribute', () => {
expect(lnsAttr.getNumberColumn('transaction.duration.us')).toEqual({ expect(lnsAttr.getNumberColumn('transaction.duration.us')).toEqual({
dataType: 'number', dataType: 'number',
isBucketed: true, isBucketed: true,
label: 'Page load time', label: 'Page load time (Seconds)',
operationType: 'range', operationType: 'range',
params: { params: {
maxBars: 'auto', maxBars: 'auto',
@ -129,7 +128,7 @@ describe('Lens Attribute', () => {
expect(lnsAttr.getXAxis()).toEqual({ expect(lnsAttr.getXAxis()).toEqual({
dataType: 'number', dataType: 'number',
isBucketed: true, isBucketed: true,
label: 'Page load time', label: 'Page load time (Seconds)',
operationType: 'range', operationType: 'range',
params: { params: {
maxBars: 'auto', maxBars: 'auto',
@ -154,7 +153,7 @@ describe('Lens Attribute', () => {
'x-axis-column': { 'x-axis-column': {
dataType: 'number', dataType: 'number',
isBucketed: true, isBucketed: true,
label: 'Page load time', label: 'Page load time (Seconds)',
operationType: 'range', operationType: 'range',
params: { params: {
maxBars: 'auto', maxBars: 'auto',
@ -318,7 +317,7 @@ describe('Lens Attribute', () => {
'x-axis-column': { 'x-axis-column': {
dataType: 'number', dataType: 'number',
isBucketed: true, isBucketed: true,
label: 'Page load time', label: 'Page load time (Seconds)',
operationType: 'range', operationType: 'range',
params: { params: {
maxBars: 'auto', maxBars: 'auto',
@ -363,7 +362,7 @@ describe('Lens Attribute', () => {
'x-axis-column': { 'x-axis-column': {
dataType: 'number', dataType: 'number',
isBucketed: true, isBucketed: true,
label: 'Page load time', label: 'Page load time (Seconds)',
operationType: 'range', operationType: 'range',
params: { params: {
maxBars: 'auto', maxBars: 'auto',

View file

@ -5,8 +5,8 @@
* 2.0. * 2.0.
*/ */
import { DataSeries } from '../types'; import { DataSeries } from '../../types';
import { FieldLabels } from './constants'; import { FieldLabels } from '../constants';
interface Props { interface Props {
seriesId: string; seriesId: string;

View file

@ -5,9 +5,9 @@
* 2.0. * 2.0.
*/ */
import { DataSeries } from '../types'; import { DataSeries } from '../../types';
import { FieldLabels } from './constants'; import { FieldLabels } from '../constants';
import { OperationType } from '../../../../../../lens/public'; import { OperationType } from '../../../../../../../lens/public';
interface Props { interface Props {
seriesId: string; seriesId: string;
@ -23,7 +23,7 @@ export function getCPUUsageLensConfig({ seriesId }: Props): DataSeries {
sourceField: '@timestamp', sourceField: '@timestamp',
}, },
yAxisColumn: { yAxisColumn: {
operationType: 'avg' as OperationType, operationType: 'average' as OperationType,
sourceField: 'system.cpu.user.pct', sourceField: 'system.cpu.user.pct',
label: 'CPU Usage %', label: 'CPU Usage %',
}, },

View file

@ -5,9 +5,9 @@
* 2.0. * 2.0.
*/ */
import { DataSeries } from '../types'; import { DataSeries } from '../../types';
import { FieldLabels } from './constants'; import { FieldLabels } from '../constants';
import { OperationType } from '../../../../../../lens/public'; import { OperationType } from '../../../../../../../lens/public';
interface Props { interface Props {
seriesId: string; seriesId: string;
@ -23,7 +23,7 @@ export function getMemoryUsageLensConfig({ seriesId }: Props): DataSeries {
sourceField: '@timestamp', sourceField: '@timestamp',
}, },
yAxisColumn: { yAxisColumn: {
operationType: 'avg' as OperationType, operationType: 'average' as OperationType,
sourceField: 'system.memory.used.pct', sourceField: 'system.memory.used.pct',
label: 'Memory Usage %', label: 'Memory Usage %',
}, },

View file

@ -5,9 +5,9 @@
* 2.0. * 2.0.
*/ */
import { DataSeries } from '../types'; import { DataSeries } from '../../types';
import { FieldLabels } from './constants'; import { FieldLabels } from '../constants';
import { OperationType } from '../../../../../../lens/public'; import { OperationType } from '../../../../../../../lens/public';
interface Props { interface Props {
seriesId: string; seriesId: string;
@ -23,7 +23,7 @@ export function getNetworkActivityLensConfig({ seriesId }: Props): DataSeries {
sourceField: '@timestamp', sourceField: '@timestamp',
}, },
yAxisColumn: { yAxisColumn: {
operationType: 'avg' as OperationType, operationType: 'average' as OperationType,
sourceField: 'system.memory.used.pct', sourceField: 'system.memory.used.pct',
}, },
hasMetricType: true, hasMetricType: true,

View file

@ -0,0 +1,74 @@
/*
* 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 { FieldFormat } from '../../types';
import {
FCP_FIELD,
FID_FIELD,
LCP_FIELD,
TBT_FIELD,
TRANSACTION_DURATION,
} from '../constants/elasticsearch_fieldnames';
export const rumFieldFormats: FieldFormat[] = [
{
field: TRANSACTION_DURATION,
format: {
id: 'duration',
params: {
inputFormat: 'microseconds',
outputFormat: 'asSeconds',
showSuffix: true,
outputPrecision: 1,
},
},
},
{
field: FCP_FIELD,
format: {
id: 'duration',
params: {
inputFormat: 'milliseconds',
outputFormat: 'asSeconds',
showSuffix: true,
},
},
},
{
field: LCP_FIELD,
format: {
id: 'duration',
params: {
inputFormat: 'milliseconds',
outputFormat: 'asSeconds',
showSuffix: true,
},
},
},
{
field: TBT_FIELD,
format: {
id: 'duration',
params: {
inputFormat: 'milliseconds',
outputFormat: 'asSeconds',
showSuffix: true,
},
},
},
{
field: FID_FIELD,
format: {
id: 'duration',
params: {
inputFormat: 'milliseconds',
outputFormat: 'asSeconds',
showSuffix: true,
},
},
},
];

View file

@ -5,9 +5,9 @@
* 2.0. * 2.0.
*/ */
import { ConfigProps, DataSeries } from '../types'; import { ConfigProps, DataSeries } from '../../types';
import { FieldLabels } from './constants'; import { FieldLabels } from '../constants';
import { buildPhraseFilter } from './utils'; import { buildPhraseFilter } from '../utils';
import { import {
CLIENT_GEO_COUNTRY_NAME, CLIENT_GEO_COUNTRY_NAME,
PROCESSOR_EVENT, PROCESSOR_EVENT,
@ -18,7 +18,7 @@ import {
USER_AGENT_NAME, USER_AGENT_NAME,
USER_AGENT_OS, USER_AGENT_OS,
USER_AGENT_VERSION, USER_AGENT_VERSION,
} from './data/elasticsearch_fieldnames'; } from '../constants/elasticsearch_fieldnames';
export function getKPITrendsLensConfig({ seriesId, indexPattern }: ConfigProps): DataSeries { export function getKPITrendsLensConfig({ seriesId, indexPattern }: ConfigProps): DataSeries {
return { return {

View file

@ -5,9 +5,9 @@
* 2.0. * 2.0.
*/ */
import { ConfigProps, DataSeries } from '../types'; import { ConfigProps, DataSeries } from '../../types';
import { FieldLabels } from './constants'; import { FieldLabels } from '../constants';
import { buildPhraseFilter } from './utils'; import { buildPhraseFilter } from '../utils';
import { import {
CLIENT_GEO_COUNTRY_NAME, CLIENT_GEO_COUNTRY_NAME,
CLS_FIELD, CLS_FIELD,
@ -24,7 +24,7 @@ import {
USER_AGENT_NAME, USER_AGENT_NAME,
USER_AGENT_OS, USER_AGENT_OS,
USER_AGENT_VERSION, USER_AGENT_VERSION,
} from './data/elasticsearch_fieldnames'; } from '../constants/elasticsearch_fieldnames';
export function getPerformanceDistLensConfig({ seriesId, indexPattern }: ConfigProps): DataSeries { export function getPerformanceDistLensConfig({ seriesId, indexPattern }: ConfigProps): DataSeries {
return { return {
@ -80,7 +80,7 @@ export function getPerformanceDistLensConfig({ seriesId, indexPattern }: ConfigP
labels: { labels: {
...FieldLabels, ...FieldLabels,
[SERVICE_NAME]: 'Web Application', [SERVICE_NAME]: 'Web Application',
[TRANSACTION_DURATION]: 'Page load time', [TRANSACTION_DURATION]: 'Page load time (Seconds)',
}, },
}; };
} }

View file

@ -0,0 +1,22 @@
/*
* 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 { FieldFormat } from '../../types';
export const syntheticsFieldFormats: FieldFormat[] = [
{
field: 'monitor.duration.us',
format: {
id: 'duration',
params: {
inputFormat: 'microseconds',
outputFormat: 'asMilliseconds',
outputPrecision: 0,
},
},
},
];

View file

@ -5,9 +5,9 @@
* 2.0. * 2.0.
*/ */
import { DataSeries } from '../types'; import { DataSeries } from '../../types';
import { FieldLabels } from './constants'; import { FieldLabels } from '../constants/constants';
import { OperationType } from '../../../../../../lens/public'; import { OperationType } from '../../../../../../../lens/public';
interface Props { interface Props {
seriesId: string; seriesId: string;
@ -23,7 +23,7 @@ export function getMonitorDurationConfig({ seriesId }: Props): DataSeries {
sourceField: '@timestamp', sourceField: '@timestamp',
}, },
yAxisColumn: { yAxisColumn: {
operationType: 'avg' as OperationType, operationType: 'average' as OperationType,
sourceField: 'monitor.duration.us', sourceField: 'monitor.duration.us',
label: 'Monitor duration (ms)', label: 'Monitor duration (ms)',
}, },

View file

@ -5,8 +5,8 @@
* 2.0. * 2.0.
*/ */
import { DataSeries } from '../types'; import { DataSeries } from '../../types';
import { FieldLabels } from './constants'; import { FieldLabels } from '../constants';
interface Props { interface Props {
seriesId: string; seriesId: string;

View file

@ -21,7 +21,7 @@ export const sampleAttribute = {
columns: { columns: {
'x-axis-column': { 'x-axis-column': {
sourceField: 'transaction.duration.us', sourceField: 'transaction.duration.us',
label: 'Page load time', label: 'Page load time (Seconds)',
dataType: 'number', dataType: 'number',
operationType: 'range', operationType: 'range',
isBucketed: true, isBucketed: true,

View file

@ -5,11 +5,11 @@
* 2.0. * 2.0.
*/ */
import rison, { RisonValue } from 'rison-node'; import rison, { RisonValue } from 'rison-node';
import type { AllSeries, AllShortSeries } from '../hooks/use_url_strorage'; import type { AllSeries, AllShortSeries } from '../hooks/use_url_storage';
import type { SeriesUrl } from '../types'; import type { SeriesUrl } from '../types';
import { IIndexPattern } from '../../../../../../../../src/plugins/data/common/index_patterns'; import { IIndexPattern } from '../../../../../../../../src/plugins/data/common/index_patterns';
import { esFilters } from '../../../../../../../../src/plugins/data/public'; import { esFilters } from '../../../../../../../../src/plugins/data/public';
import { URL_KEYS } from './url_constants'; import { URL_KEYS } from './constants/url_constants';
export function convertToShortUrl(series: SeriesUrl) { export function convertToShortUrl(series: SeriesUrl) {
const { const {

View file

@ -10,7 +10,7 @@ import { fireEvent, screen, waitFor } from '@testing-library/dom';
import { render, mockUrlStorage, mockCore } from './rtl_helpers'; import { render, mockUrlStorage, mockCore } from './rtl_helpers';
import { ExploratoryView } from './exploratory_view'; import { ExploratoryView } from './exploratory_view';
import { getStubIndexPattern } from '../../../../../../../src/plugins/data/public/test_utils'; import { getStubIndexPattern } from '../../../../../../../src/plugins/data/public/test_utils';
import * as obsvInd from '../../../utils/observability_index_patterns'; import * as obsvInd from './utils/observability_index_patterns';
describe('ExploratoryView', () => { describe('ExploratoryView', () => {
beforeEach(() => { beforeEach(() => {

View file

@ -12,7 +12,7 @@ import { useKibana } from '../../../../../../../src/plugins/kibana_react/public'
import { ObservabilityPublicPluginsStart } from '../../../plugin'; import { ObservabilityPublicPluginsStart } from '../../../plugin';
import { ExploratoryViewHeader } from './header/header'; import { ExploratoryViewHeader } from './header/header';
import { SeriesEditor } from './series_editor/series_editor'; import { SeriesEditor } from './series_editor/series_editor';
import { useUrlStorage } from './hooks/use_url_strorage'; import { useUrlStorage } from './hooks/use_url_storage';
import { useLensAttributes } from './hooks/use_lens_attributes'; import { useLensAttributes } from './hooks/use_lens_attributes';
import { EmptyView } from './components/empty_view'; import { EmptyView } from './components/empty_view';
import { useIndexPatternContext } from './hooks/use_default_index_pattern'; import { useIndexPatternContext } from './hooks/use_default_index_pattern';

View file

@ -12,7 +12,7 @@ import { TypedLensByValueInput } from '../../../../../../lens/public';
import { useKibana } from '../../../../../../../../src/plugins/kibana_react/public'; import { useKibana } from '../../../../../../../../src/plugins/kibana_react/public';
import { ObservabilityPublicPluginsStart } from '../../../../plugin'; import { ObservabilityPublicPluginsStart } from '../../../../plugin';
import { DataViewLabels } from '../configurations/constants'; import { DataViewLabels } from '../configurations/constants';
import { useUrlStorage } from '../hooks/use_url_strorage'; import { useUrlStorage } from '../hooks/use_url_storage';
interface Props { interface Props {
seriesId: string; seriesId: string;

View file

@ -10,7 +10,7 @@ import { IndexPattern } from '../../../../../../../../src/plugins/data/common';
import { AppDataType } from '../types'; import { AppDataType } from '../types';
import { useKibana } from '../../../../../../../../src/plugins/kibana_react/public'; import { useKibana } from '../../../../../../../../src/plugins/kibana_react/public';
import { ObservabilityPublicPluginsStart } from '../../../../plugin'; import { ObservabilityPublicPluginsStart } from '../../../../plugin';
import { ObservabilityIndexPatterns } from '../../../../utils/observability_index_patterns'; import { ObservabilityIndexPatterns } from '../utils/observability_index_patterns';
export interface IIndexPatternContext { export interface IIndexPatternContext {
indexPattern: IndexPattern; indexPattern: IndexPattern;

View file

@ -8,12 +8,9 @@ import { useFetcher } from '../../../..';
import { IKbnUrlStateStorage } from '../../../../../../../../src/plugins/kibana_utils/public'; import { IKbnUrlStateStorage } from '../../../../../../../../src/plugins/kibana_utils/public';
import { useKibana } from '../../../../../../../../src/plugins/kibana_react/public'; import { useKibana } from '../../../../../../../../src/plugins/kibana_react/public';
import { ObservabilityPublicPluginsStart } from '../../../../plugin'; import { ObservabilityPublicPluginsStart } from '../../../../plugin';
import { AllShortSeries } from './use_url_strorage'; import { AllShortSeries } from './use_url_storage';
import { ReportToDataTypeMap } from '../configurations/constants'; import { ReportToDataTypeMap } from '../configurations/constants';
import { import { DataType, ObservabilityIndexPatterns } from '../utils/observability_index_patterns';
DataType,
ObservabilityIndexPatterns,
} from '../../../../utils/observability_index_patterns';
export const useInitExploratoryView = (storage: IKbnUrlStateStorage) => { export const useInitExploratoryView = (storage: IKbnUrlStateStorage) => {
const { const {
@ -30,7 +27,7 @@ export const useInitExploratoryView = (storage: IKbnUrlStateStorage) => {
const firstSeries = allSeries[firstSeriesId]; const firstSeries = allSeries[firstSeriesId];
const { data: indexPattern } = useFetcher(() => { const { data: indexPattern, error } = useFetcher(() => {
const obsvIndexP = new ObservabilityIndexPatterns(data); const obsvIndexP = new ObservabilityIndexPatterns(data);
let reportType: DataType = 'apm'; let reportType: DataType = 'apm';
if (firstSeries?.rt) { if (firstSeries?.rt) {
@ -40,5 +37,9 @@ export const useInitExploratoryView = (storage: IKbnUrlStateStorage) => {
return obsvIndexP.getIndexPattern(reportType); return obsvIndexP.getIndexPattern(reportType);
}, [firstSeries?.rt, data]); }, [firstSeries?.rt, data]);
if (error) {
throw error;
}
return indexPattern; return indexPattern;
}; };

View file

@ -8,7 +8,7 @@
import { useMemo } from 'react'; import { useMemo } from 'react';
import { TypedLensByValueInput } from '../../../../../../lens/public'; import { TypedLensByValueInput } from '../../../../../../lens/public';
import { LensAttributes } from '../configurations/lens_attributes'; import { LensAttributes } from '../configurations/lens_attributes';
import { useUrlStorage } from './use_url_strorage'; import { useUrlStorage } from './use_url_storage';
import { getDefaultConfigs } from '../configurations/default_configs'; import { getDefaultConfigs } from '../configurations/default_configs';
import { IndexPattern } from '../../../../../../../../src/plugins/data/common'; import { IndexPattern } from '../../../../../../../../src/plugins/data/common';

View file

@ -5,7 +5,7 @@
* 2.0. * 2.0.
*/ */
import { useUrlStorage } from './use_url_strorage'; import { useUrlStorage } from './use_url_storage';
import { UrlFilter } from '../types'; import { UrlFilter } from '../types';
export interface UpdateFilter { export interface UpdateFilter {

View file

@ -10,7 +10,7 @@ import { IKbnUrlStateStorage } from '../../../../../../../../src/plugins/kibana_
import type { AppDataType, ReportViewTypeId, SeriesUrl, UrlFilter } from '../types'; import type { AppDataType, ReportViewTypeId, SeriesUrl, UrlFilter } from '../types';
import { convertToShortUrl } from '../configurations/utils'; import { convertToShortUrl } from '../configurations/utils';
import { OperationType, SeriesType } from '../../../../../../lens/public'; import { OperationType, SeriesType } from '../../../../../../lens/public';
import { URL_KEYS } from '../configurations/url_constants'; import { URL_KEYS } from '../configurations/constants/url_constants';
export const UrlStorageContext = createContext<IKbnUrlStateStorage | null>(null); export const UrlStorageContext = createContext<IKbnUrlStateStorage | null>(null);

View file

@ -18,7 +18,7 @@ import {
createKbnUrlStateStorage, createKbnUrlStateStorage,
withNotifyOnErrors, withNotifyOnErrors,
} from '../../../../../../../src/plugins/kibana_utils/public/'; } from '../../../../../../../src/plugins/kibana_utils/public/';
import { UrlStorageContextProvider } from './hooks/use_url_strorage'; import { UrlStorageContextProvider } from './hooks/use_url_storage';
import { useInitExploratoryView } from './hooks/use_init_exploratory_view'; import { useInitExploratoryView } from './hooks/use_init_exploratory_view';
import { WithHeaderLayout } from '../../app/layout/with_header'; import { WithHeaderLayout } from '../../app/layout/with_header';

View file

@ -23,20 +23,20 @@ import { ObservabilityPublicPluginsStart } from '../../../plugin';
import { EuiThemeProvider } from '../../../../../../../src/plugins/kibana_react/common'; import { EuiThemeProvider } from '../../../../../../../src/plugins/kibana_react/common';
import { lensPluginMock } from '../../../../../lens/public/mocks'; import { lensPluginMock } from '../../../../../lens/public/mocks';
import { IndexPatternContextProvider } from './hooks/use_default_index_pattern'; import { IndexPatternContextProvider } from './hooks/use_default_index_pattern';
import { AllSeries, UrlStorageContextProvider } from './hooks/use_url_strorage'; import { AllSeries, UrlStorageContextProvider } from './hooks/use_url_storage';
import { import {
withNotifyOnErrors, withNotifyOnErrors,
createKbnUrlStateStorage, createKbnUrlStateStorage,
} from '../../../../../../../src/plugins/kibana_utils/public'; } from '../../../../../../../src/plugins/kibana_utils/public';
import * as fetcherHook from '../../../hooks/use_fetcher'; import * as fetcherHook from '../../../hooks/use_fetcher';
import * as useUrlHook from './hooks/use_url_strorage'; import * as useUrlHook from './hooks/use_url_storage';
import * as useSeriesFilterHook from './hooks/use_series_filters'; import * as useSeriesFilterHook from './hooks/use_series_filters';
import * as useHasDataHook from '../../../hooks/use_has_data'; import * as useHasDataHook from '../../../hooks/use_has_data';
import * as useValuesListHook from '../../../hooks/use_values_list'; import * as useValuesListHook from '../../../hooks/use_values_list';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths // eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { getStubIndexPattern } from '../../../../../../../src/plugins/data/public/index_patterns/index_pattern.stub'; import { getStubIndexPattern } from '../../../../../../../src/plugins/data/public/index_patterns/index_pattern.stub';
import indexPatternData from './configurations/data/test_index_pattern.json'; import indexPatternData from './configurations/test_data/test_index_pattern.json';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths // eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { setIndexPatterns } from '../../../../../../../src/plugins/data/public/services'; import { setIndexPatterns } from '../../../../../../../src/plugins/data/public/services';

View file

@ -9,7 +9,7 @@ import React from 'react';
import { fireEvent, screen } from '@testing-library/react'; import { fireEvent, screen } from '@testing-library/react';
import { mockUrlStorage, render } from '../../rtl_helpers'; import { mockUrlStorage, render } from '../../rtl_helpers';
import { dataTypes, DataTypesCol } from './data_types_col'; import { dataTypes, DataTypesCol } from './data_types_col';
import { NEW_SERIES_KEY } from '../../hooks/use_url_strorage'; import { NEW_SERIES_KEY } from '../../hooks/use_url_storage';
describe('DataTypesCol', function () { describe('DataTypesCol', function () {
it('should render properly', function () { it('should render properly', function () {

View file

@ -9,7 +9,7 @@ import React from 'react';
import { EuiButton, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { EuiButton, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
import { AppDataType } from '../../types'; import { AppDataType } from '../../types';
import { useIndexPatternContext } from '../../hooks/use_default_index_pattern'; import { useIndexPatternContext } from '../../hooks/use_default_index_pattern';
import { NEW_SERIES_KEY, useUrlStorage } from '../../hooks/use_url_strorage'; import { NEW_SERIES_KEY, useUrlStorage } from '../../hooks/use_url_storage';
export const dataTypes: Array<{ id: AppDataType; label: string }> = [ export const dataTypes: Array<{ id: AppDataType; label: string }> = [
{ id: 'synthetics', label: 'Synthetic Monitoring' }, { id: 'synthetics', label: 'Synthetic Monitoring' },

View file

@ -10,9 +10,9 @@ import { fireEvent, screen } from '@testing-library/react';
import { render } from '../../../../../utils/test_helper'; import { render } from '../../../../../utils/test_helper';
import { getDefaultConfigs } from '../../configurations/default_configs'; import { getDefaultConfigs } from '../../configurations/default_configs';
import { mockIndexPattern, mockUrlStorage } from '../../rtl_helpers'; import { mockIndexPattern, mockUrlStorage } from '../../rtl_helpers';
import { NEW_SERIES_KEY } from '../../hooks/use_url_strorage'; import { NEW_SERIES_KEY } from '../../hooks/use_url_storage';
import { ReportBreakdowns } from './report_breakdowns'; import { ReportBreakdowns } from './report_breakdowns';
import { USER_AGENT_OS } from '../../configurations/data/elasticsearch_fieldnames'; import { USER_AGENT_OS } from '../../configurations/constants/elasticsearch_fieldnames';
describe('Series Builder ReportBreakdowns', function () { describe('Series Builder ReportBreakdowns', function () {
const dataViewSeries = getDefaultConfigs({ const dataViewSeries = getDefaultConfigs({

View file

@ -7,7 +7,7 @@
import React from 'react'; import React from 'react';
import { Breakdowns } from '../../series_editor/columns/breakdowns'; import { Breakdowns } from '../../series_editor/columns/breakdowns';
import { NEW_SERIES_KEY } from '../../hooks/use_url_strorage'; import { NEW_SERIES_KEY } from '../../hooks/use_url_storage';
import { DataSeries } from '../../types'; import { DataSeries } from '../../types';
export function ReportBreakdowns({ dataViewSeries }: { dataViewSeries: DataSeries }) { export function ReportBreakdowns({ dataViewSeries }: { dataViewSeries: DataSeries }) {

View file

@ -9,9 +9,9 @@ import React from 'react';
import { fireEvent, screen } from '@testing-library/react'; import { fireEvent, screen } from '@testing-library/react';
import { getDefaultConfigs } from '../../configurations/default_configs'; import { getDefaultConfigs } from '../../configurations/default_configs';
import { mockIndexPattern, mockUrlStorage, mockUseValuesList, render } from '../../rtl_helpers'; import { mockIndexPattern, mockUrlStorage, mockUseValuesList, render } from '../../rtl_helpers';
import { NEW_SERIES_KEY } from '../../hooks/use_url_strorage'; import { NEW_SERIES_KEY } from '../../hooks/use_url_storage';
import { ReportDefinitionCol } from './report_definition_col'; import { ReportDefinitionCol } from './report_definition_col';
import { SERVICE_NAME } from '../../configurations/data/elasticsearch_fieldnames'; import { SERVICE_NAME } from '../../configurations/constants/elasticsearch_fieldnames';
describe('Series Builder ReportDefinitionCol', function () { describe('Series Builder ReportDefinitionCol', function () {
const dataViewSeries = getDefaultConfigs({ const dataViewSeries = getDefaultConfigs({

View file

@ -8,7 +8,7 @@
import React from 'react'; import React from 'react';
import { EuiBadge, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { EuiBadge, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
import { useIndexPatternContext } from '../../hooks/use_default_index_pattern'; import { useIndexPatternContext } from '../../hooks/use_default_index_pattern';
import { NEW_SERIES_KEY, useUrlStorage } from '../../hooks/use_url_strorage'; import { NEW_SERIES_KEY, useUrlStorage } from '../../hooks/use_url_storage';
import { CustomReportField } from '../custom_report_field'; import { CustomReportField } from '../custom_report_field';
import FieldValueSuggestions from '../../../field_value_suggestions'; import FieldValueSuggestions from '../../../field_value_suggestions';
import { DataSeries } from '../../types'; import { DataSeries } from '../../types';
@ -67,6 +67,7 @@ export function ReportDefinitionCol({ dataViewSeries }: { dataViewSeries: DataSe
{rtd?.[field] && ( {rtd?.[field] && (
<EuiFlexItem grow={false}> <EuiFlexItem grow={false}>
<EuiBadge <EuiBadge
className="globalFilterItem"
iconSide="right" iconSide="right"
iconType="cross" iconType="cross"
color="hollow" color="hollow"

View file

@ -11,7 +11,7 @@ import { render } from '../../../../../utils/test_helper';
import { ReportFilters } from './report_filters'; import { ReportFilters } from './report_filters';
import { getDefaultConfigs } from '../../configurations/default_configs'; import { getDefaultConfigs } from '../../configurations/default_configs';
import { mockIndexPattern, mockUrlStorage } from '../../rtl_helpers'; import { mockIndexPattern, mockUrlStorage } from '../../rtl_helpers';
import { NEW_SERIES_KEY } from '../../hooks/use_url_strorage'; import { NEW_SERIES_KEY } from '../../hooks/use_url_storage';
describe('Series Builder ReportFilters', function () { describe('Series Builder ReportFilters', function () {
const dataViewSeries = getDefaultConfigs({ const dataViewSeries = getDefaultConfigs({

View file

@ -7,7 +7,7 @@
import React from 'react'; import React from 'react';
import { SeriesFilter } from '../../series_editor/columns/series_filter'; import { SeriesFilter } from '../../series_editor/columns/series_filter';
import { NEW_SERIES_KEY } from '../../hooks/use_url_strorage'; import { NEW_SERIES_KEY } from '../../hooks/use_url_storage';
import { DataSeries } from '../../types'; import { DataSeries } from '../../types';
export function ReportFilters({ dataViewSeries }: { dataViewSeries: DataSeries }) { export function ReportFilters({ dataViewSeries }: { dataViewSeries: DataSeries }) {

View file

@ -9,7 +9,7 @@ import React from 'react';
import { i18n } from '@kbn/i18n'; import { i18n } from '@kbn/i18n';
import { EuiButton, EuiFlexGroup, EuiFlexItem, EuiText } from '@elastic/eui'; import { EuiButton, EuiFlexGroup, EuiFlexItem, EuiText } from '@elastic/eui';
import { ReportViewTypeId, SeriesUrl } from '../../types'; import { ReportViewTypeId, SeriesUrl } from '../../types';
import { NEW_SERIES_KEY, useUrlStorage } from '../../hooks/use_url_strorage'; import { NEW_SERIES_KEY, useUrlStorage } from '../../hooks/use_url_storage';
interface Props { interface Props {
reportTypes: Array<{ id: ReportViewTypeId; label: string }>; reportTypes: Array<{ id: ReportViewTypeId; label: string }>;

View file

@ -7,7 +7,7 @@
import React from 'react'; import React from 'react';
import { EuiSuperSelect } from '@elastic/eui'; import { EuiSuperSelect } from '@elastic/eui';
import { useUrlStorage } from '../hooks/use_url_strorage'; import { useUrlStorage } from '../hooks/use_url_storage';
import { ReportDefinition } from '../types'; import { ReportDefinition } from '../types';
interface Props { interface Props {

View file

@ -16,7 +16,7 @@ import { ReportTypesCol } from './columns/report_types_col';
import { ReportDefinitionCol } from './columns/report_definition_col'; import { ReportDefinitionCol } from './columns/report_definition_col';
import { ReportFilters } from './columns/report_filters'; import { ReportFilters } from './columns/report_filters';
import { ReportBreakdowns } from './columns/report_breakdowns'; import { ReportBreakdowns } from './columns/report_breakdowns';
import { NEW_SERIES_KEY, useUrlStorage } from '../hooks/use_url_strorage'; import { NEW_SERIES_KEY, useUrlStorage } from '../hooks/use_url_storage';
import { useIndexPatternContext } from '../hooks/use_default_index_pattern'; import { useIndexPatternContext } from '../hooks/use_default_index_pattern';
import { getDefaultConfigs } from '../configurations/default_configs'; import { getDefaultConfigs } from '../configurations/default_configs';

View file

@ -8,7 +8,7 @@
import { EuiSuperDatePicker } from '@elastic/eui'; import { EuiSuperDatePicker } from '@elastic/eui';
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
import { useHasData } from '../../../../hooks/use_has_data'; import { useHasData } from '../../../../hooks/use_has_data';
import { useUrlStorage } from '../hooks/use_url_strorage'; import { useUrlStorage } from '../hooks/use_url_storage';
import { useQuickTimeRanges } from '../../../../hooks/use_quick_time_ranges'; import { useQuickTimeRanges } from '../../../../hooks/use_quick_time_ranges';
export interface TimePickerTime { export interface TimePickerTime {

View file

@ -9,9 +9,9 @@ import React from 'react';
import { fireEvent, screen } from '@testing-library/react'; import { fireEvent, screen } from '@testing-library/react';
import { Breakdowns } from './breakdowns'; import { Breakdowns } from './breakdowns';
import { mockIndexPattern, mockUrlStorage, render } from '../../rtl_helpers'; import { mockIndexPattern, mockUrlStorage, render } from '../../rtl_helpers';
import { NEW_SERIES_KEY } from '../../hooks/use_url_strorage'; import { NEW_SERIES_KEY } from '../../hooks/use_url_storage';
import { getDefaultConfigs } from '../../configurations/default_configs'; import { getDefaultConfigs } from '../../configurations/default_configs';
import { USER_AGENT_OS } from '../../configurations/data/elasticsearch_fieldnames'; import { USER_AGENT_OS } from '../../configurations/constants/elasticsearch_fieldnames';
describe('Breakdowns', function () { describe('Breakdowns', function () {
const dataViewSeries = getDefaultConfigs({ const dataViewSeries = getDefaultConfigs({

View file

@ -9,7 +9,7 @@ import React from 'react';
import { EuiSuperSelect } from '@elastic/eui'; import { EuiSuperSelect } from '@elastic/eui';
import { i18n } from '@kbn/i18n'; import { i18n } from '@kbn/i18n';
import { FieldLabels } from '../../configurations/constants'; import { FieldLabels } from '../../configurations/constants';
import { useUrlStorage } from '../../hooks/use_url_strorage'; import { useUrlStorage } from '../../hooks/use_url_storage';
interface Props { interface Props {
seriesId: string; seriesId: string;

View file

@ -19,7 +19,7 @@ import styled from 'styled-components';
import { useKibana } from '../../../../../../../../../src/plugins/kibana_react/public'; import { useKibana } from '../../../../../../../../../src/plugins/kibana_react/public';
import { ObservabilityPublicPluginsStart } from '../../../../../plugin'; import { ObservabilityPublicPluginsStart } from '../../../../../plugin';
import { useFetcher } from '../../../../..'; import { useFetcher } from '../../../../..';
import { useUrlStorage } from '../../hooks/use_url_strorage'; import { useUrlStorage } from '../../hooks/use_url_storage';
import { SeriesType } from '../../../../../../../lens/public'; import { SeriesType } from '../../../../../../../lens/public';
export function SeriesChartTypes({ export function SeriesChartTypes({

View file

@ -9,7 +9,7 @@ import React from 'react';
import { fireEvent, screen } from '@testing-library/react'; import { fireEvent, screen } from '@testing-library/react';
import { FilterExpanded } from './filter_expanded'; import { FilterExpanded } from './filter_expanded';
import { mockUrlStorage, mockUseValuesList, render } from '../../rtl_helpers'; import { mockUrlStorage, mockUseValuesList, render } from '../../rtl_helpers';
import { USER_AGENT_NAME } from '../../configurations/data/elasticsearch_fieldnames'; import { USER_AGENT_NAME } from '../../configurations/constants/elasticsearch_fieldnames';
describe('FilterExpanded', function () { describe('FilterExpanded', function () {
it('should render properly', async function () { it('should render properly', async function () {

View file

@ -14,7 +14,7 @@ import {
EuiFilterGroup, EuiFilterGroup,
} from '@elastic/eui'; } from '@elastic/eui';
import { useIndexPatternContext } from '../../hooks/use_default_index_pattern'; import { useIndexPatternContext } from '../../hooks/use_default_index_pattern';
import { useUrlStorage } from '../../hooks/use_url_strorage'; import { useUrlStorage } from '../../hooks/use_url_storage';
import { UrlFilter } from '../../types'; import { UrlFilter } from '../../types';
import { FilterValueButton } from './filter_value_btn'; import { FilterValueButton } from './filter_value_btn';
import { useValuesList } from '../../../../../hooks/use_values_list'; import { useValuesList } from '../../../../../hooks/use_values_list';

View file

@ -12,7 +12,7 @@ import { mockUrlStorage, mockUseSeriesFilter, mockUseValuesList, render } from '
import { import {
USER_AGENT_NAME, USER_AGENT_NAME,
USER_AGENT_VERSION, USER_AGENT_VERSION,
} from '../../configurations/data/elasticsearch_fieldnames'; } from '../../configurations/constants/elasticsearch_fieldnames';
describe('FilterValueButton', function () { describe('FilterValueButton', function () {
it('should render properly', async function () { it('should render properly', async function () {

View file

@ -8,7 +8,7 @@ import { i18n } from '@kbn/i18n';
import React, { useMemo } from 'react'; import React, { useMemo } from 'react';
import { EuiFilterButton, hexToRgb } from '@elastic/eui'; import { EuiFilterButton, hexToRgb } from '@elastic/eui';
import { useIndexPatternContext } from '../../hooks/use_default_index_pattern'; import { useIndexPatternContext } from '../../hooks/use_default_index_pattern';
import { useUrlStorage } from '../../hooks/use_url_strorage'; import { useUrlStorage } from '../../hooks/use_url_storage';
import { useSeriesFilters } from '../../hooks/use_series_filters'; import { useSeriesFilters } from '../../hooks/use_series_filters';
import { euiStyled } from '../../../../../../../../../src/plugins/kibana_react/common'; import { euiStyled } from '../../../../../../../../../src/plugins/kibana_react/common';
import FieldValueSuggestions from '../../../field_value_suggestions'; import FieldValueSuggestions from '../../../field_value_suggestions';

View file

@ -8,12 +8,12 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { i18n } from '@kbn/i18n'; import { i18n } from '@kbn/i18n';
import { EuiButton, EuiButtonGroup, EuiPopover } from '@elastic/eui'; import { EuiButton, EuiButtonGroup, EuiPopover } from '@elastic/eui';
import { useUrlStorage } from '../../hooks/use_url_strorage'; import { useUrlStorage } from '../../hooks/use_url_storage';
import { OperationType } from '../../../../../../../lens/public'; import { OperationType } from '../../../../../../../lens/public';
const toggleButtons = [ const toggleButtons = [
{ {
id: `avg`, id: `average`,
label: i18n.translate('xpack.observability.expView.metricsSelect.average', { label: i18n.translate('xpack.observability.expView.metricsSelect.average', {
defaultMessage: 'Average', defaultMessage: 'Average',
}), }),
@ -49,7 +49,7 @@ export function MetricSelection({
const [isOpen, setIsOpen] = useState(false); const [isOpen, setIsOpen] = useState(false);
const [toggleIdSelected, setToggleIdSelected] = useState(series?.metric ?? 'avg'); const [toggleIdSelected, setToggleIdSelected] = useState(series?.metric ?? 'average');
const onChange = (optionId: OperationType) => { const onChange = (optionId: OperationType) => {
setToggleIdSelected(optionId); setToggleIdSelected(optionId);

View file

@ -9,7 +9,7 @@ import { i18n } from '@kbn/i18n';
import React from 'react'; import React from 'react';
import { EuiButtonIcon } from '@elastic/eui'; import { EuiButtonIcon } from '@elastic/eui';
import { DataSeries } from '../../types'; import { DataSeries } from '../../types';
import { useUrlStorage } from '../../hooks/use_url_strorage'; import { useUrlStorage } from '../../hooks/use_url_storage';
interface Props { interface Props {
series: DataSeries; series: DataSeries;

View file

@ -17,9 +17,9 @@ import {
} from '@elastic/eui'; } from '@elastic/eui';
import { FilterExpanded } from './filter_expanded'; import { FilterExpanded } from './filter_expanded';
import { DataSeries } from '../../types'; import { DataSeries } from '../../types';
import { FieldLabels } from '../../configurations/constants'; import { FieldLabels } from '../../configurations/constants/constants';
import { SelectedFilters } from '../selected_filters'; import { SelectedFilters } from '../selected_filters';
import { NEW_SERIES_KEY, useUrlStorage } from '../../hooks/use_url_strorage'; import { NEW_SERIES_KEY, useUrlStorage } from '../../hooks/use_url_storage';
interface Props { interface Props {
seriesId: string; seriesId: string;

View file

@ -10,8 +10,8 @@ import { screen, waitFor } from '@testing-library/react';
import { mockIndexPattern, mockUrlStorage, render } from '../rtl_helpers'; import { mockIndexPattern, mockUrlStorage, render } from '../rtl_helpers';
import { SelectedFilters } from './selected_filters'; import { SelectedFilters } from './selected_filters';
import { getDefaultConfigs } from '../configurations/default_configs'; import { getDefaultConfigs } from '../configurations/default_configs';
import { NEW_SERIES_KEY } from '../hooks/use_url_strorage'; import { NEW_SERIES_KEY } from '../hooks/use_url_storage';
import { USER_AGENT_NAME } from '../configurations/data/elasticsearch_fieldnames'; import { USER_AGENT_NAME } from '../configurations/constants/elasticsearch_fieldnames';
describe('SelectedFilters', function () { describe('SelectedFilters', function () {
const dataViewSeries = getDefaultConfigs({ const dataViewSeries = getDefaultConfigs({

View file

@ -7,7 +7,7 @@
import React, { Fragment } from 'react'; import React, { Fragment } from 'react';
import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
import { NEW_SERIES_KEY, useUrlStorage } from '../hooks/use_url_strorage'; import { NEW_SERIES_KEY, useUrlStorage } from '../hooks/use_url_storage';
import { FilterLabel } from '../components/filter_label'; import { FilterLabel } from '../components/filter_label';
import { DataSeries, UrlFilter } from '../types'; import { DataSeries, UrlFilter } from '../types';
import { useIndexPatternContext } from '../hooks/use_default_index_pattern'; import { useIndexPatternContext } from '../hooks/use_default_index_pattern';

View file

@ -13,7 +13,7 @@ import { ActionsCol } from './columns/actions_col';
import { Breakdowns } from './columns/breakdowns'; import { Breakdowns } from './columns/breakdowns';
import { DataSeries } from '../types'; import { DataSeries } from '../types';
import { SeriesBuilder } from '../series_builder/series_builder'; import { SeriesBuilder } from '../series_builder/series_builder';
import { NEW_SERIES_KEY, useUrlStorage } from '../hooks/use_url_strorage'; import { NEW_SERIES_KEY, useUrlStorage } from '../hooks/use_url_storage';
import { getDefaultConfigs } from '../configurations/default_configs'; import { getDefaultConfigs } from '../configurations/default_configs';
import { DatePickerCol } from './columns/date_picker_col'; import { DatePickerCol } from './columns/date_picker_col';
import { RemoveSeries } from './columns/remove_series'; import { RemoveSeries } from './columns/remove_series';

View file

@ -87,3 +87,22 @@ export interface ConfigProps {
} }
export type AppDataType = 'synthetics' | 'rum' | 'logs' | 'metrics' | 'apm'; export type AppDataType = 'synthetics' | 'rum' | 'logs' | 'metrics' | 'apm';
type FormatType = 'duration' | 'number';
type InputFormat = 'microseconds' | 'milliseconds' | 'seconds';
type OutputFormat = 'asSeconds' | 'asMilliseconds' | 'humanize';
export interface FieldFormatParams {
inputFormat: InputFormat;
outputFormat: OutputFormat;
outputPrecision?: number;
showSuffix?: boolean;
}
export interface FieldFormat {
field: string;
format: {
id: FormatType;
params: FieldFormatParams;
};
}

View file

@ -0,0 +1,95 @@
/*
* 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 { indexPatternList, ObservabilityIndexPatterns } from './observability_index_patterns';
import { mockCore, mockIndexPattern } from '../rtl_helpers';
import { SavedObjectNotFound } from '../../../../../../../../src/plugins/kibana_utils/public';
const fieldFormats = {
'transaction.duration.us': {
id: 'duration',
params: {
inputFormat: 'microseconds',
outputFormat: 'asSeconds',
outputPrecision: 1,
showSuffix: true,
},
},
'transaction.experience.fid': {
id: 'duration',
params: { inputFormat: 'milliseconds', outputFormat: 'asSeconds', showSuffix: true },
},
'transaction.experience.tbt': {
id: 'duration',
params: { inputFormat: 'milliseconds', outputFormat: 'asSeconds', showSuffix: true },
},
'transaction.marks.agent.firstContentfulPaint': {
id: 'duration',
params: { inputFormat: 'milliseconds', outputFormat: 'asSeconds', showSuffix: true },
},
'transaction.marks.agent.largestContentfulPaint': {
id: 'duration',
params: { inputFormat: 'milliseconds', outputFormat: 'asSeconds', showSuffix: true },
},
};
describe('ObservabilityIndexPatterns', function () {
const { data } = mockCore();
data!.indexPatterns.get = jest.fn().mockReturnValue({ title: 'index-*' });
data!.indexPatterns.createAndSave = jest.fn().mockReturnValue({ id: indexPatternList.rum });
data!.indexPatterns.updateSavedObject = jest.fn();
it('should return index pattern for app', async function () {
const obsv = new ObservabilityIndexPatterns(data!);
const indexP = await obsv.getIndexPattern('rum');
expect(indexP).toEqual({ title: 'index-*' });
expect(data?.indexPatterns.get).toHaveBeenCalledWith(indexPatternList.rum);
expect(data?.indexPatterns.get).toHaveBeenCalledTimes(1);
});
it('should creates missing index pattern', async function () {
data!.indexPatterns.get = jest.fn().mockImplementation(() => {
throw new SavedObjectNotFound('index_pattern');
});
const obsv = new ObservabilityIndexPatterns(data!);
const indexP = await obsv.getIndexPattern('rum');
expect(indexP).toEqual({ id: indexPatternList.rum });
expect(data?.indexPatterns.createAndSave).toHaveBeenCalledWith({
fieldFormats,
id: 'rum_static_index_pattern_id',
timeFieldName: '@timestamp',
title: '(rum-data-view)*,apm-*',
});
expect(data?.indexPatterns.createAndSave).toHaveBeenCalledTimes(1);
});
it('should return getFieldFormats', function () {
const obsv = new ObservabilityIndexPatterns(data!);
expect(obsv.getFieldFormats('rum')).toEqual(fieldFormats);
});
it('should validate field formats', async function () {
mockIndexPattern.getFormatterForField = jest.fn().mockReturnValue({ params: () => {} });
const obsv = new ObservabilityIndexPatterns(data!);
await obsv.validateFieldFormats('rum', mockIndexPattern);
expect(data?.indexPatterns.updateSavedObject).toHaveBeenCalledTimes(1);
expect(data?.indexPatterns.updateSavedObject).toHaveBeenCalledWith(
expect.objectContaining({ fieldFormatMap: fieldFormats })
);
});
});

View file

@ -0,0 +1,124 @@
/*
* 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 { SavedObjectNotFound } from '../../../../../../../../src/plugins/kibana_utils/public';
import {
DataPublicPluginStart,
IndexPattern,
FieldFormat as IFieldFormat,
IndexPatternSpec,
} from '../../../../../../../../src/plugins/data/public';
import { rumFieldFormats } from '../configurations/rum/field_formats';
import { syntheticsFieldFormats } from '../configurations/synthetics/field_formats';
import { FieldFormat, FieldFormatParams } from '../types';
const appFieldFormats: Record<DataType, FieldFormat[] | null> = {
rum: rumFieldFormats,
apm: null,
logs: null,
metrics: null,
synthetics: syntheticsFieldFormats,
};
function getFieldFormatsForApp(app: DataType) {
return appFieldFormats[app];
}
export type DataType = 'synthetics' | 'apm' | 'logs' | 'metrics' | 'rum';
export const indexPatternList: Record<DataType, string> = {
synthetics: 'synthetics_static_index_pattern_id',
apm: 'apm_static_index_pattern_id',
rum: 'rum_static_index_pattern_id',
logs: 'logs_static_index_pattern_id',
metrics: 'metrics_static_index_pattern_id',
};
const appToPatternMap: Record<DataType, string> = {
synthetics: '(synthetics-data-view)*,heartbeat-*,synthetics-*',
apm: 'apm-*',
rum: '(rum-data-view)*,apm-*',
logs: 'logs-*,filebeat-*',
metrics: 'metrics-*,metricbeat-*',
};
export function isParamsSame(param1: IFieldFormat['_params'], param2: FieldFormatParams) {
return (
param1?.inputFormat === param2?.inputFormat &&
param1?.outputFormat === param2?.outputFormat &&
param1?.showSuffix === param2?.showSuffix &&
param2?.outputPrecision === param1?.outputPrecision
);
}
export class ObservabilityIndexPatterns {
data?: DataPublicPluginStart;
constructor(data: DataPublicPluginStart) {
this.data = data;
}
async createIndexPattern(app: DataType) {
if (!this.data) {
throw new Error('data is not defined');
}
const pattern = appToPatternMap[app];
return await this.data.indexPatterns.createAndSave({
title: pattern,
id: indexPatternList[app],
timeFieldName: '@timestamp',
fieldFormats: this.getFieldFormats(app),
});
}
// we want to make sure field formats remain same
async validateFieldFormats(app: DataType, indexPattern: IndexPattern) {
const defaultFieldFormats = getFieldFormatsForApp(app);
if (defaultFieldFormats && defaultFieldFormats.length > 0) {
let isParamsDifferent = false;
defaultFieldFormats.forEach(({ field, format }) => {
const fieldFormat = indexPattern.getFormatterForField(indexPattern.getFieldByName(field)!);
const params = fieldFormat.params();
if (!isParamsSame(params, format.params)) {
indexPattern.setFieldFormat(field, format);
isParamsDifferent = true;
}
});
if (isParamsDifferent) {
await this.data?.indexPatterns.updateSavedObject(indexPattern);
}
}
}
getFieldFormats(app: DataType) {
const fieldFormatMap: IndexPatternSpec['fieldFormats'] = {};
(appFieldFormats?.[app] ?? []).forEach(({ field, format }) => {
fieldFormatMap[field] = format;
});
return fieldFormatMap;
}
async getIndexPattern(app: DataType): Promise<IndexPattern | undefined> {
if (!this.data) {
throw new Error('data is not defined');
}
try {
const indexPattern = await this.data?.indexPatterns.get(indexPatternList[app]);
// this is intentional a non blocking call, so no await clause
this.validateFieldFormats(app, indexPattern);
return indexPattern;
} catch (e: unknown) {
if (e instanceof SavedObjectNotFound) {
return await this.createIndexPattern(app || 'apm');
}
}
}
}

View file

@ -76,6 +76,7 @@ export function FieldValueSelection({
<EuiButton <EuiButton
style={width ? { width } : {}} style={width ? { width } : {}}
size="s" size="s"
color="text"
iconType="arrowDown" iconType="arrowDown"
iconSide="right" iconSide="right"
onClick={onButtonClick} onClick={onButtonClick}