[Exploratory vie] Added synthetics metrics (#103482)

This commit is contained in:
Shahzad 2021-06-29 14:14:18 +02:00 committed by GitHub
parent 0c8d5e8f89
commit 5aa8305279
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 208 additions and 24 deletions

View file

@ -6,3 +6,8 @@
*/
export const MONITOR_DURATION_US = 'monitor.duration.us';
export const SYNTHETICS_CLS = 'browser.experience.cls';
export const SYNTHETICS_LCP = 'browser.experience.lcp.us';
export const SYNTHETICS_FCP = 'browser.experience.fcp.us';
export const SYNTHETICS_DOCUMENT_ONLOAD = 'browser.experience.load.us';
export const SYNTHETICS_DCL = 'browser.experience.dcl.us';

View file

@ -72,6 +72,17 @@ export const CLS_LABEL = i18n.translate('xpack.observability.expView.fieldLabels
defaultMessage: 'Cumulative layout shift',
});
export const DCL_LABEL = i18n.translate('xpack.observability.expView.fieldLabels.dcl', {
defaultMessage: 'DOM content loaded',
});
export const DOCUMENT_ONLOAD_LABEL = i18n.translate(
'xpack.observability.expView.fieldLabels.onload',
{
defaultMessage: 'Document complete (onLoad)',
}
);
export const BACKEND_TIME_LABEL = i18n.translate(
'xpack.observability.expView.fieldLabels.backend',
{

View file

@ -7,8 +7,23 @@
import { ConfigProps, SeriesConfig } from '../../types';
import { FieldLabels, REPORT_METRIC_FIELD, RECORDS_PERCENTAGE_FIELD } from '../constants';
import { buildExistsFilter } from '../utils';
import { MONITORS_DURATION_LABEL, PINGS_LABEL } from '../constants/labels';
import {
CLS_LABEL,
DCL_LABEL,
DOCUMENT_ONLOAD_LABEL,
FCP_LABEL,
LCP_LABEL,
MONITORS_DURATION_LABEL,
PINGS_LABEL,
} from '../constants/labels';
import {
MONITOR_DURATION_US,
SYNTHETICS_CLS,
SYNTHETICS_DCL,
SYNTHETICS_DOCUMENT_ONLOAD,
SYNTHETICS_FCP,
SYNTHETICS_LCP,
} from '../constants/field_names/synthetics';
export function getSyntheticsDistributionConfig({
series,
@ -37,10 +52,39 @@ export function getSyntheticsDistributionConfig({
'tags',
'url.port',
],
baseFilters: [...buildExistsFilter('summary.up', indexPattern)],
baseFilters: [],
definitionFields: ['monitor.name', 'url.full'],
metricOptions: [
{ label: 'Monitor duration', id: 'monitor.duration.us', field: 'monitor.duration.us' },
{
label: MONITORS_DURATION_LABEL,
id: MONITOR_DURATION_US,
field: MONITOR_DURATION_US,
},
{
label: LCP_LABEL,
field: SYNTHETICS_LCP,
id: SYNTHETICS_LCP,
},
{
label: FCP_LABEL,
field: SYNTHETICS_FCP,
id: SYNTHETICS_FCP,
},
{
label: DCL_LABEL,
field: SYNTHETICS_DCL,
id: SYNTHETICS_DCL,
},
{
label: DOCUMENT_ONLOAD_LABEL,
field: SYNTHETICS_DOCUMENT_ONLOAD,
id: SYNTHETICS_DOCUMENT_ONLOAD,
},
{
label: CLS_LABEL,
field: SYNTHETICS_CLS,
id: SYNTHETICS_CLS,
},
],
labels: { ...FieldLabels, 'monitor.duration.us': MONITORS_DURATION_LABEL },
};

View file

@ -6,6 +6,12 @@
*/
import { FieldFormat } from '../../types';
import {
SYNTHETICS_DCL,
SYNTHETICS_DOCUMENT_ONLOAD,
SYNTHETICS_FCP,
SYNTHETICS_LCP,
} from '../constants/field_names/synthetics';
export const syntheticsFieldFormats: FieldFormat[] = [
{
@ -21,4 +27,56 @@ export const syntheticsFieldFormats: FieldFormat[] = [
},
},
},
{
field: SYNTHETICS_LCP,
format: {
id: 'duration',
params: {
inputFormat: 'microseconds',
outputFormat: 'humanizePrecise',
outputPrecision: 1,
showSuffix: true,
useShortSuffix: true,
},
},
},
{
field: SYNTHETICS_FCP,
format: {
id: 'duration',
params: {
inputFormat: 'microseconds',
outputFormat: 'humanizePrecise',
outputPrecision: 1,
showSuffix: true,
useShortSuffix: true,
},
},
},
{
field: SYNTHETICS_DOCUMENT_ONLOAD,
format: {
id: 'duration',
params: {
inputFormat: 'microseconds',
outputFormat: 'humanizePrecise',
outputPrecision: 1,
showSuffix: true,
useShortSuffix: true,
},
},
},
{
field: SYNTHETICS_DCL,
format: {
id: 'duration',
params: {
inputFormat: 'microseconds',
outputFormat: 'humanizePrecise',
outputPrecision: 1,
showSuffix: true,
useShortSuffix: true,
},
},
},
];

View file

@ -7,9 +7,24 @@
import { ConfigProps, SeriesConfig } from '../../types';
import { FieldLabels, OPERATION_COLUMN, REPORT_METRIC_FIELD } from '../constants';
import { buildExistsFilter } from '../utils';
import { DOWN_LABEL, MONITORS_DURATION_LABEL, UP_LABEL } from '../constants/labels';
import { MONITOR_DURATION_US } from '../constants/field_names/synthetics';
import {
CLS_LABEL,
DCL_LABEL,
DOCUMENT_ONLOAD_LABEL,
DOWN_LABEL,
FCP_LABEL,
LCP_LABEL,
MONITORS_DURATION_LABEL,
UP_LABEL,
} from '../constants/labels';
import {
MONITOR_DURATION_US,
SYNTHETICS_CLS,
SYNTHETICS_DCL,
SYNTHETICS_DOCUMENT_ONLOAD,
SYNTHETICS_FCP,
SYNTHETICS_LCP,
} from '../constants/field_names/synthetics';
const SUMMARY_UP = 'summary.up';
const SUMMARY_DOWN = 'summary.down';
@ -29,8 +44,8 @@ export function getSyntheticsKPIConfig({ indexPattern }: ConfigProps): SeriesCon
],
hasOperationType: false,
filterFields: ['observer.geo.name', 'monitor.type', 'tags'],
breakdownFields: ['observer.geo.name', 'monitor.type'],
baseFilters: [...buildExistsFilter('summary.up', indexPattern)],
breakdownFields: ['observer.geo.name', 'monitor.type', 'monitor.name'],
baseFilters: [],
palette: { type: 'palette', name: 'status' },
definitionFields: ['monitor.name', 'url.full'],
metricOptions: [
@ -52,6 +67,36 @@ export function getSyntheticsKPIConfig({ indexPattern }: ConfigProps): SeriesCon
label: DOWN_LABEL,
columnType: OPERATION_COLUMN,
},
{
label: LCP_LABEL,
field: SYNTHETICS_LCP,
id: SYNTHETICS_LCP,
columnType: OPERATION_COLUMN,
},
{
label: FCP_LABEL,
field: SYNTHETICS_FCP,
id: SYNTHETICS_FCP,
columnType: OPERATION_COLUMN,
},
{
label: DCL_LABEL,
field: SYNTHETICS_DCL,
id: SYNTHETICS_DCL,
columnType: OPERATION_COLUMN,
},
{
label: DOCUMENT_ONLOAD_LABEL,
field: SYNTHETICS_DOCUMENT_ONLOAD,
id: SYNTHETICS_DOCUMENT_ONLOAD,
columnType: OPERATION_COLUMN,
},
{
label: CLS_LABEL,
field: SYNTHETICS_CLS,
id: SYNTHETICS_CLS,
columnType: OPERATION_COLUMN,
},
],
labels: { ...FieldLabels },
};

View file

@ -14,14 +14,17 @@ import { getDefaultConfigs } from '../configurations/default_configs';
import { SeriesUrl, UrlFilter } from '../types';
import { useAppIndexPatternContext } from './use_app_index_pattern';
import { ALL_VALUES_SELECTED } from '../../field_value_suggestions/field_value_combobox';
export const getFiltersFromDefs = (reportDefinitions: SeriesUrl['reportDefinitions']) => {
return Object.entries(reportDefinitions ?? {}).map(([field, value]) => {
return {
field,
values: value,
};
}) as UrlFilter[];
return Object.entries(reportDefinitions ?? {})
.map(([field, value]) => {
return {
field,
values: value,
};
})
.filter(({ values }) => !values.includes(ALL_VALUES_SELECTED)) as UrlFilter[];
};
export const useLensAttributes = (): TypedLensByValueInput['attributes'] | null => {

View file

@ -16,6 +16,7 @@ import { PersistableFilter } from '../../../../../../../lens/common';
import { ExistsFilter } from '../../../../../../../../../src/plugins/data/common/es_query/filters';
import { buildPhrasesFilter } from '../../configurations/utils';
import { SeriesConfig } from '../../types';
import { ALL_VALUES_SELECTED } from '../../../field_value_suggestions/field_value_combobox';
interface Props {
seriesId: string;
@ -51,8 +52,10 @@ export function ReportDefinitionField({ seriesId, field, seriesConfig, onChange
definitionFields.forEach((fieldT) => {
if (indexPattern && selectedReportDefinitions?.[fieldT] && fieldT !== field) {
const values = selectedReportDefinitions?.[fieldT];
const valueFilter = buildPhrasesFilter(fieldT, values, indexPattern)[0];
filtersN.push(valueFilter.query);
if (!values.includes(ALL_VALUES_SELECTED)) {
const valueFilter = buildPhrasesFilter(fieldT, values, indexPattern)[0];
filtersN.push(valueFilter.query);
}
}
});
}
@ -74,6 +77,7 @@ export function ReportDefinitionField({ seriesId, field, seriesConfig, onChange
filters={queryFilters}
time={series.time}
fullWidth={true}
allowAllValuesSelection={true}
/>
)}
</EuiFlexItem>

View file

@ -11,9 +11,11 @@ import { EuiComboBox, EuiFormControlLayout, EuiComboBoxOptionOption } from '@ela
import { i18n } from '@kbn/i18n';
import styled from 'styled-components';
import { FieldValueSelectionProps } from './types';
const formatOptions = (values?: string[]) => {
const uniqueValues = Array.from(new Set(values));
export const ALL_VALUES_SELECTED = 'ALL_VALUES';
const formatOptions = (values?: string[], allowAllValuesSelection?: boolean) => {
const uniqueValues = Array.from(
new Set(allowAllValuesSelection ? ['ALL_VALUES', ...(values ?? [])] : values)
);
return (uniqueValues ?? []).map((label) => ({
label,
@ -29,15 +31,24 @@ export function FieldValueCombobox({
values,
setQuery,
compressed = true,
allowAllValuesSelection,
onChange: onSelectionChange,
}: FieldValueSelectionProps) {
const [options, setOptions] = useState<ValueOption[]>(
formatOptions(union(values?.map(({ label: lb }) => lb) ?? [], selectedValue ?? []))
const [options, setOptions] = useState<ValueOption[]>(() =>
formatOptions(
union(values?.map(({ label: lb }) => lb) ?? [], selectedValue ?? []),
allowAllValuesSelection
)
);
useEffect(() => {
setOptions(formatOptions(union(values?.map(({ label: lb }) => lb) ?? [], selectedValue ?? [])));
}, [selectedValue, values]);
setOptions(
formatOptions(
union(values?.map(({ label: lb }) => lb) ?? [], selectedValue ?? []),
allowAllValuesSelection
)
);
}, [allowAllValuesSelection, selectedValue, values]);
const onChange = (selectedValuesN: ValueOption[]) => {
onSelectionChange(selectedValuesN.map(({ label: lbl }) => lbl));

View file

@ -30,6 +30,7 @@ export function FieldValueSuggestions({
singleSelection,
compressed,
asFilterButton,
allowAllValuesSelection,
asCombobox = true,
onChange: onSelectionChange,
}: FieldValueSuggestionsProps) {
@ -73,6 +74,7 @@ export function FieldValueSuggestions({
width={width}
compressed={compressed}
asFilterButton={asFilterButton}
allowAllValuesSelection={allowAllValuesSelection}
/>
);
}

View file

@ -23,6 +23,7 @@ interface CommonProps {
compressed?: boolean;
asFilterButton?: boolean;
showCount?: boolean;
allowAllValuesSelection?: boolean;
}
export type FieldValueSuggestionsProps = CommonProps & {