diff --git a/packages/kbn-optimizer/limits.yml b/packages/kbn-optimizer/limits.yml index 2e3a5b30bdd05f..56259881447db9 100644 --- a/packages/kbn-optimizer/limits.yml +++ b/packages/kbn-optimizer/limits.yml @@ -95,7 +95,7 @@ pageLoadAssetSize: newsfeed: 42228 observability: 95000 observabilityOnboarding: 19573 - observabilityShared: 21266 + observabilityShared: 36643 osquery: 107090 painlessLab: 179748 presentationUtil: 58834 diff --git a/x-pack/examples/exploratory_view_example/public/app.tsx b/x-pack/examples/exploratory_view_example/public/app.tsx index 268f070b40d167..b38c777eb400e5 100644 --- a/x-pack/examples/exploratory_view_example/public/app.tsx +++ b/x-pack/examples/exploratory_view_example/public/app.tsx @@ -20,7 +20,7 @@ import { } from '@elastic/eui'; import type { DataView } from '@kbn/data-views-plugin/public'; import { CoreStart } from '@kbn/core/public'; -import { AllSeries } from '@kbn/observability-plugin/public'; +import { AllSeries } from '@kbn/exploratory-view-plugin/public'; import { StartDependencies } from './plugin'; export const App = (props: { diff --git a/x-pack/plugins/exploratory_view/public/components/shared/exploratory_view/components/series_color_picker.tsx b/x-pack/plugins/exploratory_view/public/components/shared/exploratory_view/components/series_color_picker.tsx index 4324ff7a569bd7..6bdd250ead632b 100644 --- a/x-pack/plugins/exploratory_view/public/components/shared/exploratory_view/components/series_color_picker.tsx +++ b/x-pack/plugins/exploratory_view/public/components/shared/exploratory_view/components/series_color_picker.tsx @@ -55,16 +55,10 @@ export function SeriesColorPicker({ seriesId, series }: { seriesId: number; seri ); } -const PICK_A_COLOR_LABEL = i18n.translate( - 'xpack.exploratoryView.overview.exploratoryView.pickColor', - { - defaultMessage: 'Pick a color', - } -); +const PICK_A_COLOR_LABEL = i18n.translate('xpack.exploratoryView.pickColor', { + defaultMessage: 'Pick a color', +}); -const EDIT_SERIES_COLOR_LABEL = i18n.translate( - 'xpack.exploratoryView.overview.exploratoryView.editSeriesColor', - { - defaultMessage: 'Edit color for series', - } -); +const EDIT_SERIES_COLOR_LABEL = i18n.translate('xpack.exploratoryView.editSeriesColor', { + defaultMessage: 'Edit color for series', +}); diff --git a/x-pack/plugins/exploratory_view/public/components/shared/exploratory_view/configurations/alerts_configs/kpi_over_time_config.ts b/x-pack/plugins/exploratory_view/public/components/shared/exploratory_view/configurations/alerts_configs/kpi_over_time_config.ts index e6f8194f2663f5..233cdac7e0b299 100644 --- a/x-pack/plugins/exploratory_view/public/components/shared/exploratory_view/configurations/alerts_configs/kpi_over_time_config.ts +++ b/x-pack/plugins/exploratory_view/public/components/shared/exploratory_view/configurations/alerts_configs/kpi_over_time_config.ts @@ -21,7 +21,7 @@ export function getAlertsKPIConfig({ spaceId }: ConfigProps): SeriesConfig { defaultSeriesType: 'line', seriesTypes: [], xAxisColumn: { - label: i18n.translate('xpack.exploratoryView.exploratoryView.alerts.alertStarted', { + label: i18n.translate('xpack.exploratoryView.alerts.alertStarted', { defaultMessage: 'Timestamp', }), dataType: 'date', diff --git a/x-pack/plugins/exploratory_view/public/components/shared/exploratory_view/configurations/infra_logs/kpi_over_time_config.ts b/x-pack/plugins/exploratory_view/public/components/shared/exploratory_view/configurations/infra_logs/kpi_over_time_config.ts index aa367739d1d1b9..9629b3c8396f75 100644 --- a/x-pack/plugins/exploratory_view/public/components/shared/exploratory_view/configurations/infra_logs/kpi_over_time_config.ts +++ b/x-pack/plugins/exploratory_view/public/components/shared/exploratory_view/configurations/infra_logs/kpi_over_time_config.ts @@ -17,7 +17,7 @@ export function getLogsKPIConfig(configProps: ConfigProps): SeriesConfig { defaultSeriesType: 'bar', seriesTypes: [], xAxisColumn: { - label: i18n.translate('xpack.exploratoryView.exploratoryView.logs.logRateXAxisLabel', { + label: i18n.translate('xpack.exploratoryView.logs.logRateXAxisLabel', { defaultMessage: 'Timestamp', }), dataType: 'date', @@ -28,7 +28,7 @@ export function getLogsKPIConfig(configProps: ConfigProps): SeriesConfig { }, yAxisColumns: [ { - label: i18n.translate('xpack.exploratoryView.exploratoryView.logs.logRateYAxisLabel', { + label: i18n.translate('xpack.exploratoryView.logs.logRateYAxisLabel', { defaultMessage: 'Log rate per minute', }), dataType: 'number', diff --git a/x-pack/plugins/exploratory_view/public/components/shared/exploratory_view/embeddable/index.tsx b/x-pack/plugins/exploratory_view/public/components/shared/exploratory_view/embeddable/index.tsx index 98e9d61e512a66..85fb195d29d4fa 100644 --- a/x-pack/plugins/exploratory_view/public/components/shared/exploratory_view/embeddable/index.tsx +++ b/x-pack/plugins/exploratory_view/public/components/shared/exploratory_view/embeddable/index.tsx @@ -175,6 +175,6 @@ function EmptyState({ height }: { height?: string }) { ); } -const NO_DATA_LABEL = i18n.translate('xpack.exploratoryView.overview.exploratoryView.noData', { +const NO_DATA_LABEL = i18n.translate('xpack.exploratoryView.noData', { defaultMessage: 'No data', }); diff --git a/x-pack/plugins/exploratory_view/public/components/shared/exploratory_view/exploratory_view.tsx b/x-pack/plugins/exploratory_view/public/components/shared/exploratory_view/exploratory_view.tsx index cefe75c24b4ccf..a67618cf5f93cf 100644 --- a/x-pack/plugins/exploratory_view/public/components/shared/exploratory_view/exploratory_view.tsx +++ b/x-pack/plugins/exploratory_view/public/components/shared/exploratory_view/exploratory_view.tsx @@ -204,27 +204,18 @@ const ShowPreview = styled(EuiButtonEmpty)` bottom: 34px; `; -const PREVIEW_LABEL = i18n.translate('xpack.exploratoryView.overview.exploratoryView.preview', { +const PREVIEW_LABEL = i18n.translate('xpack.exploratoryView.preview', { defaultMessage: 'Preview', }); -const HIDE_CHART_LABEL = i18n.translate( - 'xpack.exploratoryView.overview.exploratoryView.hideChart', - { - defaultMessage: 'Hide chart', - } -); +const HIDE_CHART_LABEL = i18n.translate('xpack.exploratoryView.hideChart', { + defaultMessage: 'Hide chart', +}); -const SHOW_CHART_LABEL = i18n.translate( - 'xpack.exploratoryView.overview.exploratoryView.showChart', - { - defaultMessage: 'Show chart', - } -); +const SHOW_CHART_LABEL = i18n.translate('xpack.exploratoryView.showChart', { + defaultMessage: 'Show chart', +}); -const LENS_NOT_AVAILABLE = i18n.translate( - 'xpack.exploratoryView.overview.exploratoryView.lensDisabled', - { - defaultMessage: 'Lens app is not available, please enable Lens to use exploratory view.', - } -); +const LENS_NOT_AVAILABLE = i18n.translate('xpack.exploratoryView.lensDisabled', { + defaultMessage: 'Lens app is not available, please enable Lens to use exploratory view.', +}); diff --git a/x-pack/plugins/exploratory_view/public/components/shared/exploratory_view/header/refresh_button.tsx b/x-pack/plugins/exploratory_view/public/components/shared/exploratory_view/header/refresh_button.tsx index 7101cbceccb07d..de2828af096fd6 100644 --- a/x-pack/plugins/exploratory_view/public/components/shared/exploratory_view/header/refresh_button.tsx +++ b/x-pack/plugins/exploratory_view/public/components/shared/exploratory_view/header/refresh_button.tsx @@ -32,9 +32,6 @@ export function RefreshButton() { ); } -export const REFRESH_LABEL = i18n.translate( - 'xpack.exploratoryView.overview.exploratoryView.refresh', - { - defaultMessage: 'Refresh', - } -); +export const REFRESH_LABEL = i18n.translate('xpack.exploratoryView.refresh', { + defaultMessage: 'Refresh', +}); diff --git a/x-pack/plugins/exploratory_view/public/components/shared/exploratory_view/index.tsx b/x-pack/plugins/exploratory_view/public/components/shared/exploratory_view/index.tsx index fb333939722bbe..2c23044bb70598 100644 --- a/x-pack/plugins/exploratory_view/public/components/shared/exploratory_view/index.tsx +++ b/x-pack/plugins/exploratory_view/public/components/shared/exploratory_view/index.tsx @@ -56,7 +56,7 @@ export function ExploratoryViewPage({ useBreadcrumbs( [ { - text: i18n.translate('xpack.exploratoryView.overview.exploratoryView', { + text: i18n.translate('xpack.exploratoryView.overview', { defaultMessage: 'Explore data', }), }, diff --git a/x-pack/plugins/exploratory_view/public/components/shared/exploratory_view/labels.ts b/x-pack/plugins/exploratory_view/public/components/shared/exploratory_view/labels.ts index 935756c4965151..b46c4007f7b437 100644 --- a/x-pack/plugins/exploratory_view/public/components/shared/exploratory_view/labels.ts +++ b/x-pack/plugins/exploratory_view/public/components/shared/exploratory_view/labels.ts @@ -17,39 +17,30 @@ export enum DataTypes { } export const DataTypesLabels: Record = { - [DataTypes.UX]: i18n.translate('xpack.exploratoryView.overview.exploratoryView.uxLabel', { + [DataTypes.UX]: i18n.translate('xpack.exploratoryView.uxLabel', { defaultMessage: 'User experience (RUM)', }), - [DataTypes.SYNTHETICS]: i18n.translate( - 'xpack.exploratoryView.overview.exploratoryView.syntheticsLabel', - { - defaultMessage: 'Synthetics monitoring', - } - ), + [DataTypes.SYNTHETICS]: i18n.translate('xpack.exploratoryView.syntheticsLabel', { + defaultMessage: 'Synthetics monitoring', + }), - [DataTypes.UPTIME]: i18n.translate('xpack.exploratoryView.overview.exploratoryView.uptimeLabel', { + [DataTypes.UPTIME]: i18n.translate('xpack.exploratoryView.uptimeLabel', { defaultMessage: 'Uptime', }), - [DataTypes.METRICS]: i18n.translate( - 'xpack.exploratoryView.overview.exploratoryView.metricsLabel', - { - defaultMessage: 'Metrics', - } - ), + [DataTypes.METRICS]: i18n.translate('xpack.exploratoryView.metricsLabel', { + defaultMessage: 'Metrics', + }), - [DataTypes.LOGS]: i18n.translate('xpack.exploratoryView.overview.exploratoryView.logsLabel', { + [DataTypes.LOGS]: i18n.translate('xpack.exploratoryView.logsLabel', { defaultMessage: 'Logs', }), - [DataTypes.MOBILE]: i18n.translate( - 'xpack.exploratoryView.overview.exploratoryView.mobileExperienceLabel', - { - defaultMessage: 'Mobile experience', - } - ), - [DataTypes.ALERTS]: i18n.translate('xpack.exploratoryView.overview.exploratoryView.alertsLabel', { + [DataTypes.MOBILE]: i18n.translate('xpack.exploratoryView.mobileExperienceLabel', { + defaultMessage: 'Mobile experience', + }), + [DataTypes.ALERTS]: i18n.translate('xpack.exploratoryView.alertsLabel', { defaultMessage: 'Alerts', }), }; diff --git a/x-pack/plugins/exploratory_view/public/components/shared/exploratory_view/lens_embeddable.tsx b/x-pack/plugins/exploratory_view/public/components/shared/exploratory_view/lens_embeddable.tsx index bed9952b0ac13a..11f5328f0c0b4d 100644 --- a/x-pack/plugins/exploratory_view/public/components/shared/exploratory_view/lens_embeddable.tsx +++ b/x-pack/plugins/exploratory_view/public/components/shared/exploratory_view/lens_embeddable.tsx @@ -74,7 +74,7 @@ export function LensEmbeddable(props: Props) { }); } else { notifications?.toasts.add( - i18n.translate('xpack.exploratoryView.exploratoryView.noBrusing', { + i18n.translate('xpack.exploratoryView.noBrushing', { defaultMessage: 'Zoom by brush selection is only available on time series charts.', }) ); diff --git a/x-pack/plugins/exploratory_view/public/components/shared/exploratory_view/series_editor/breakdown/breakdowns.tsx b/x-pack/plugins/exploratory_view/public/components/shared/exploratory_view/series_editor/breakdown/breakdowns.tsx index 0d9d4827a83abe..f6548704997427 100644 --- a/x-pack/plugins/exploratory_view/public/components/shared/exploratory_view/series_editor/breakdown/breakdowns.tsx +++ b/x-pack/plugins/exploratory_view/public/components/shared/exploratory_view/series_editor/breakdown/breakdowns.tsx @@ -140,21 +140,18 @@ export function Breakdowns({ seriesConfig, seriesId, series }: Props) { } export const NO_BREAK_DOWN_LABEL = i18n.translate( - 'xpack.exploratoryView.exp.breakDownFilter.noBreakdown', + 'xpack.exploratoryView.breakDownFilter.noBreakdown', { defaultMessage: 'No breakdown', } ); -export const BREAKDOWN_WARNING = i18n.translate( - 'xpack.exploratoryView.exp.breakDownFilter.warning', - { - defaultMessage: 'Breakdowns can be applied to only one series at a time.', - } -); +export const BREAKDOWN_WARNING = i18n.translate('xpack.exploratoryView.breakDownFilter.warning', { + defaultMessage: 'Breakdowns can be applied to only one series at a time.', +}); export const BREAKDOWN_UNAVAILABLE = i18n.translate( - 'xpack.exploratoryView.exp.breakDownFilter.unavailable', + 'xpack.exploratoryView.breakDownFilter.unavailable', { defaultMessage: 'Step name breakdown is not available for monitor duration metric. Use step duration metric to breakdown by step name.', diff --git a/x-pack/plugins/exploratory_view/public/components/shared/exploratory_view/series_editor/columns/data_type_select.tsx b/x-pack/plugins/exploratory_view/public/components/shared/exploratory_view/series_editor/columns/data_type_select.tsx index 3ff9ec0fb4bb6a..e95520b870450d 100644 --- a/x-pack/plugins/exploratory_view/public/components/shared/exploratory_view/series_editor/columns/data_type_select.tsx +++ b/x-pack/plugins/exploratory_view/public/components/shared/exploratory_view/series_editor/columns/data_type_select.tsx @@ -98,16 +98,10 @@ export function DataTypesSelect({ seriesId, series }: Props) { ); } -const SELECT_DATA_TYPE_LABEL = i18n.translate( - 'xpack.exploratoryView.overview.exploratoryView.selectDataType', - { - defaultMessage: 'Select data type', - } -); +const SELECT_DATA_TYPE_LABEL = i18n.translate('xpack.exploratoryView.selectDataType', { + defaultMessage: 'Select data type', +}); -const SELECT_DATA_TYPE_TOOLTIP = i18n.translate( - 'xpack.exploratoryView.overview.exploratoryView.selectDataTypeTooltip', - { - defaultMessage: 'Data type cannot be edited.', - } -); +const SELECT_DATA_TYPE_TOOLTIP = i18n.translate('xpack.exploratoryView.selectDataTypeTooltip', { + defaultMessage: 'Data type cannot be edited.', +}); diff --git a/x-pack/plugins/exploratory_view/public/components/shared/exploratory_view/series_editor/columns/date_picker_col.tsx b/x-pack/plugins/exploratory_view/public/components/shared/exploratory_view/series_editor/columns/date_picker_col.tsx index d294d2a48b9634..ccf9d3bf0fd8e8 100644 --- a/x-pack/plugins/exploratory_view/public/components/shared/exploratory_view/series_editor/columns/date_picker_col.tsx +++ b/x-pack/plugins/exploratory_view/public/components/shared/exploratory_view/series_editor/columns/date_picker_col.tsx @@ -50,7 +50,7 @@ export function DatePickerCol({ seriesId, series }: Props) { - {i18n.translate('xpack.exploratoryView.overview.exploratoryView.noDataAvailable', { + {i18n.translate('xpack.exploratoryView.noDataAvailable', { defaultMessage: 'No {dataType} data available.', values: { dataType: series.dataType, diff --git a/x-pack/plugins/exploratory_view/public/components/shared/exploratory_view/series_editor/columns/incomplete_badge.tsx b/x-pack/plugins/exploratory_view/public/components/shared/exploratory_view/series_editor/columns/incomplete_badge.tsx index 456b74c0c19e84..36701f642a5c82 100644 --- a/x-pack/plugins/exploratory_view/public/components/shared/exploratory_view/series_editor/columns/incomplete_badge.tsx +++ b/x-pack/plugins/exploratory_view/public/components/shared/exploratory_view/series_editor/columns/incomplete_badge.tsx @@ -29,7 +29,7 @@ export function IncompleteBadge({ seriesConfig, series }: Props) { (!dataType || isEmpty(reportDefinitions) || !selectedMetricField) && !loading; const incompleteDefinition = isEmpty(reportDefinitions) - ? i18n.translate('xpack.exploratoryView.overview.exploratoryView.missingReportDefinition', { + ? i18n.translate('xpack.exploratoryView.missingReportDefinition', { defaultMessage: 'Missing {reportDefinition}', values: { reportDefinition: @@ -55,16 +55,10 @@ export function IncompleteBadge({ seriesConfig, series }: Props) { return {incompleteMessage}; } -const MISSING_REPORT_METRIC_LABEL = i18n.translate( - 'xpack.exploratoryView.overview.exploratoryView.missingReportMetric', - { - defaultMessage: 'Missing report metric', - } -); +const MISSING_REPORT_METRIC_LABEL = i18n.translate('xpack.exploratoryView.missingReportMetric', { + defaultMessage: 'Missing report metric', +}); -const MISSING_DATA_TYPE_LABEL = i18n.translate( - 'xpack.exploratoryView.overview.exploratoryView.missingDataType', - { - defaultMessage: 'Missing data type', - } -); +const MISSING_DATA_TYPE_LABEL = i18n.translate('xpack.exploratoryView.missingDataType', { + defaultMessage: 'Missing data type', +}); diff --git a/x-pack/plugins/observability/kibana.jsonc b/x-pack/plugins/observability/kibana.jsonc index 070638c42f1ce7..5284947ac2959d 100644 --- a/x-pack/plugins/observability/kibana.jsonc +++ b/x-pack/plugins/observability/kibana.jsonc @@ -14,6 +14,7 @@ "data", "dataViews", "embeddable", + "exploratoryView", "features", "files", "guidedOnboarding", diff --git a/x-pack/plugins/observability/public/components/app/section/ux/index.tsx b/x-pack/plugins/observability/public/components/app/section/ux/index.tsx index 9c59fb763bc1ea..35ead518c91521 100644 --- a/x-pack/plugins/observability/public/components/app/section/ux/index.tsx +++ b/x-pack/plugins/observability/public/components/app/section/ux/index.tsx @@ -8,7 +8,8 @@ import { i18n } from '@kbn/i18n'; import React from 'react'; import { useKibana } from '@kbn/kibana-react-plugin/public'; -import { CoreStart } from '@kbn/core/public'; +import { AllSeries } from '@kbn/exploratory-view-plugin/public'; +import { SERVICE_NAME, TRANSACTION_DURATION } from '@kbn/observability-shared-plugin/common'; import { UX_APP } from '../../../../context/constants'; import { ObservabilityPublicPluginsStart } from '../../../..'; import { SectionContainer } from '..'; @@ -17,12 +18,7 @@ import { FETCH_STATUS, useFetcher } from '../../../../hooks/use_fetcher'; import { useHasData } from '../../../../hooks/use_has_data'; import { useDatePickerContext } from '../../../../hooks/use_date_picker_context'; import CoreVitals from '../../../shared/core_web_vitals'; -import { getExploratoryViewEmbeddable } from '../../../shared/exploratory_view/embeddable'; -import { AllSeries } from '../../../shared/exploratory_view/hooks/use_series_storage'; -import { - SERVICE_NAME, - TRANSACTION_DURATION, -} from '../../../shared/exploratory_view/configurations/constants/elasticsearch_fieldnames'; + import type { BucketSize } from '../../../../pages/overview/helpers/calculate_bucket_size'; interface Props { bucketSize: BucketSize; @@ -31,15 +27,14 @@ interface Props { export function UXSection({ bucketSize }: Props) { const { forceUpdate, hasDataMap } = useHasData(); const { services } = useKibana(); + + const { ExploratoryViewEmbeddable } = services.exploratoryView; + const { relativeStart, relativeEnd, absoluteStart, absoluteEnd, lastUpdated } = useDatePickerContext(); const uxHasDataResponse = hasDataMap.ux; const serviceName = uxHasDataResponse?.serviceName as string; - const ExploratoryViewEmbeddable = getExploratoryViewEmbeddable( - services as ObservabilityPublicPluginsStart & CoreStart - ); - const seriesList: AllSeries = [ { name: PAGE_LOAD_DISTRIBUTION_TITLE, diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/README.md b/x-pack/plugins/observability/public/components/shared/exploratory_view/README.md deleted file mode 100644 index 6aea217a1aaa80..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/README.md +++ /dev/null @@ -1,161 +0,0 @@ -# Exploratory view component - -This component is used in observability plugin to show lens embeddable based observability visualizations. -The view is populated using configs stored as json within the view for each data type. - -This readme file contains few of the concepts being used in the component. - -Basic workflow for how exploratory view works, it looks like this - - -![Exploratory view workflow](https://i.imgur.com/Kgyfd29.png) - - -## Report Type - -The exploratory view report type controls how the data is visualized in the lens embeddable. The report type defines a set of constraints over the x and y axis. For example, the `kpi-over-time` report type is a time series chart type that plots key performance indicators over time, while the `data-distribution` chart plots the percentage of documents over key performance indicators. Current available data types can be found at `exploratory_view/configurations/constants`. - -Each report type has one or more available visualizations to plot data from one or more data types. - -## Data Types - -Each available visualization is backed by a data type. A data type consists of a set of configuration for displaying domain-specific visualizations for observability data. Some example data types include apm, metrics, and logs. - -For each respective data type, we fetch index pattern string from the app plugin contract, leveraging existing hasData API we have to return the index pattern string as well as a `hasData` boolean from each plugin. - -In most cases, there will be a 1-1 relation between apps and data types. - -### Observability `dataViews` - -Once we have index pattern string for each data type, a respective `dataView` is created. If there is an existing dataView for an index pattern, we will fetch and reuse it. - -After the dataView is created we also set field formats to promote human-readability. For example, we set format for monitor duration field, which is monitor.duration.us, from microseconds to seconds for browser monitors. - -### Visualization Configuration - -Each data type may have one or more visualization configurations. The data type to visualization configuration can be found in [`exploratory_view/obs_exploratory_view`](https://github.com/elastic/kibana/blob/main/x-pack/plugins/observability/public/components/shared/exploratory_view/obsv_exploratory_view.tsx#L86) - -Each visualization configuration is mapped to a single report type. - -Visualization configurations are used to define the UI we display for each report type and data type combination in the series builder. -Visualization configuration define UI options and display, including available `metrics`, available `filters`, available `breakdown` options, definitions for human-readable `labels`, and more. -The configuration also defines any custom base filters, which usually get pushed to a query, but are not displayed on the UI. You can also set more custom options on the configuration like colors which get used while rendering the chart. - -Visualization configuration can be found at [`exploratory_view/configurations`](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations), where each data type typically has a folder that holds one or more visualization configurations. - -The configuration defined ultimately influences the lens embeddable attributes which get pushed to lens embeddable, rendering the chart. - -Some options in configuration are: - -#### Definition fields -They are also filters, but usually main filters, around which usually app UI is based. -For apm, it could be service name and for uptime, monitor name. - -#### Filters -You can define base filters in kql form or data plugin filter format, filters are strongly typed. - -#### Breakdown fields -List of fields from an index pattern, UI will use this to populate breakdown option select. - -#### Labels -You can set key/value map for your field labels. UI will use these to set labels for data view fields. - -Sample config -``` -{ - reportType: ReportTypes.KPI, - defaultSeriesType: 'bar_stacked', - xAxisColumn: { - sourceField: '@timestamp', - }, - yAxisColumns: [ - { - sourceField: REPORT_METRIC_FIELD, - operationType: 'median', - }, - ], - hasOperationType: false, - filterFields: ['observer.geo.name', 'monitor.type', 'tags'], // these fields get's resolved from relevant dataView - breakdownFields: [ - 'observer.geo.name', - 'monitor.type', - 'monitor.name', - PERCENTILE, - ], // these fields get's resolved from relevant dataView - baseFilters: [], - palette: { type: 'palette', name: 'status' }, - definitionFields: [ - { field: 'monitor.name', nested: SYNTHETICS_STEP_NAME, singleSelection: true }, - { field: 'url.full', filters: buildExistsFilter('summary.up', dataView) }, - ], - metricOptions: [ - { - label: MONITORS_DURATION_LABEL, - field: 'monitor.duration.us', - columnType: OPERATION_COLUMN, - } - ], - labels: { ...FieldLabels, [SUMMARY_UP]: UP_LABEL, [SUMMARY_DOWN]: DOWN_LABEL }, - } -``` - - - -## Lens Embeddable - -Lens embeddable is what actually renders the chart in exploratory view. - -Exploratory view generates the lens embeddable attributes as json and pass it to the component. - -Based on configuration, exploratory view generates layers and columns. - -Add a link to lens embeddable readme - -#### Example -A simple usage of lens embeddable example and playground options -[embedded_lens_example](../../../../../../examples/embedded_lens_example) - -## Exploratory view Embeddable - -The primary purpose of the exploratory view is to embed it in observability solutions like uptime to replace -existing static visualizations, - -For that purpose, all the configuration options we define in the exploratory view can be used as an embeddable -via a component that is exposed using observability plugin contract, -usage looks like this - -`const ExploratoryViewComponent = props.plugins.observability.ExploratoryViewEmbeddable; -` - -``` - -``` - -there is an example in kibana example which you can view using -`yarn start --run-examples` and view the code at [Exploratory view embeddable](../../../../../../examples/exploratory_view_example) - -#### Example -A simple usage of lens embeddable example and playground options, run kibana with -`yarn start --run-example` to see this example in action -source code is defined at [embedded_lens_example](../../../../../../examples/embedded_lens_example) \ No newline at end of file diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/components/action_menu/action_menu.test.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/components/action_menu/action_menu.test.tsx deleted file mode 100644 index 566c271381125d..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/components/action_menu/action_menu.test.tsx +++ /dev/null @@ -1,70 +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 { render } from '../../rtl_helpers'; -import { fireEvent, screen } from '@testing-library/dom'; -import React from 'react'; -import { sampleAttribute } from '../../configurations/test_data/sample_attribute'; -import * as pluginHook from '../../../../../hooks/use_plugin_context'; -import { TypedLensByValueInput } from '@kbn/lens-plugin/public'; -import { ExpViewActionMenuContent } from './action_menu'; -import { noCasesPermissions as mockUseGetCasesPermissions } from '../../../../../utils/cases_permissions'; - -jest.spyOn(pluginHook, 'usePluginContext').mockReturnValue({ - appMountParameters: { - setHeaderActionMenu: jest.fn(), - }, -} as any); - -jest.mock('../../../../../hooks/use_get_user_cases_permissions', () => ({ - useGetUserCasesPermissions: jest.fn(() => mockUseGetCasesPermissions()), -})); - -describe('Action Menu', function () { - afterAll(() => { - jest.clearAllMocks(); - }); - - it('should be able to click open in lens', async function () { - const { findByText, core } = render( - - ); - - expect(await screen.findByText('Open in Lens')).toBeInTheDocument(); - - fireEvent.click(await findByText('Open in Lens')); - - expect(core.lens?.navigateToPrefilledEditor).toHaveBeenCalledTimes(1); - expect(core.lens?.navigateToPrefilledEditor).toHaveBeenCalledWith( - { - id: '', - attributes: sampleAttribute, - timeRange: { to: 'now', from: 'now-10m' }, - }, - { - openInNewTab: true, - } - ); - }); - - it('should be able to click save', async function () { - const { findByText } = render( - - ); - - expect(await screen.findByText('Save')).toBeInTheDocument(); - - fireEvent.click(await findByText('Save')); - - expect(await screen.findByText('Lens Save Modal Component')).toBeInTheDocument(); - }); -}); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/components/action_menu/action_menu.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/components/action_menu/action_menu.tsx deleted file mode 100644 index 2c52ea429ccaf7..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/components/action_menu/action_menu.tsx +++ /dev/null @@ -1,109 +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 React, { useState } from 'react'; -import { EuiButton, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; -import { LensEmbeddableInput, TypedLensByValueInput } from '@kbn/lens-plugin/public'; -import { useKibana } from '@kbn/kibana-react-plugin/public'; -import { EmbedAction } from '../../header/embed_action'; -import { ObservabilityAppServices } from '../../../../../application/types'; -import { AddToCaseAction } from '../../header/add_to_case_action'; - -export function ExpViewActionMenuContent({ - timeRange, - lensAttributes, -}: { - timeRange?: { from: string; to: string }; - lensAttributes: TypedLensByValueInput['attributes'] | null; -}) { - const kServices = useKibana().services; - - const { lens, isDev } = kServices; - - const [isSaveOpen, setIsSaveOpen] = useState(false); - - const LensSaveModalComponent = lens.SaveModalComponent; - - return ( - <> - - {isDev && ( - - - - )} - {timeRange && ( - - - - )} - - { - if (lensAttributes) { - lens.navigateToPrefilledEditor( - { - id: '', - timeRange, - attributes: lensAttributes, - }, - { - openInNewTab: true, - } - ); - } - }} - > - {i18n.translate('xpack.observability.expView.heading.openInLens', { - defaultMessage: 'Open in Lens', - })} - - - - { - if (lensAttributes) { - setIsSaveOpen(true); - } - }} - size="s" - > - {i18n.translate('xpack.observability.expView.heading.saveLensVisualization', { - defaultMessage: 'Save', - })} - - - - - {isSaveOpen && lensAttributes && ( - setIsSaveOpen(false)} - // if we want to do anything after the viz is saved - // right now there is no action, so an empty function - onSave={() => {}} - /> - )} - - ); -} diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/components/action_menu/index.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/components/action_menu/index.tsx deleted file mode 100644 index 63ce9162adefcc..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/components/action_menu/index.tsx +++ /dev/null @@ -1,26 +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 React from 'react'; -import { TypedLensByValueInput } from '@kbn/lens-plugin/public'; -import { ExpViewActionMenuContent } from './action_menu'; -import HeaderMenuPortal from '../../../header_menu_portal'; -import { useExploratoryView } from '../../contexts/exploratory_view_config'; - -interface Props { - timeRange?: { from: string; to: string }; - lensAttributes: TypedLensByValueInput['attributes'] | null; -} -export function ExpViewActionMenu(props: Props) { - const { setHeaderActionMenu, theme$ } = useExploratoryView(); - - return ( - - - - ); -} diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/components/date_range_picker.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/components/date_range_picker.tsx deleted file mode 100644 index 8589aeeeab14a1..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/components/date_range_picker.tsx +++ /dev/null @@ -1,119 +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 React from 'react'; -import { EuiDatePicker, EuiDatePickerRange } from '@elastic/eui'; -import { Moment } from 'moment'; -import DateMath from '@kbn/datemath'; -import { i18n } from '@kbn/i18n'; -import { useUiSetting } from '@kbn/kibana-react-plugin/public'; -import { useSeriesStorage } from '../hooks/use_series_storage'; -import { SeriesUrl } from '../types'; -import { ReportTypes } from '../configurations/constants'; - -export const parseRelativeDate = (date: string, options = {}): Moment | void => { - return DateMath.parse(date, options)!; -}; - -export function DateRangePicker({ seriesId, series }: { seriesId: number; series: SeriesUrl }) { - const { firstSeries, setSeries, reportType } = useSeriesStorage(); - const dateFormat = useUiSetting('dateFormat'); - - const seriesFrom = series.time?.from; - const seriesTo = series.time?.to; - - const { from: mainFrom, to: mainTo } = firstSeries!.time; - - const startDate = parseRelativeDate(seriesFrom ?? mainFrom)!; - const endDate = parseRelativeDate(seriesTo ?? mainTo, { roundUp: true })!; - - const getTotalDuration = () => { - const mainStartDate = parseRelativeDate(mainFrom)!; - const mainEndDate = parseRelativeDate(mainTo, { roundUp: true })!; - return mainEndDate.diff(mainStartDate, 'millisecond'); - }; - - const onStartChange = (newStartDate: Moment) => { - if (reportType === ReportTypes.KPI) { - const totalDuration = getTotalDuration(); - const newFrom = newStartDate.toISOString(); - const newTo = newStartDate.add(totalDuration, 'millisecond').toISOString(); - - setSeries(seriesId, { - ...series, - time: { from: newFrom, to: newTo }, - }); - } else { - const newFrom = newStartDate.toISOString(); - - setSeries(seriesId, { - ...series, - time: { from: newFrom, to: seriesTo }, - }); - } - }; - - const onEndChange = (newEndDate: Moment) => { - if (reportType === ReportTypes.KPI) { - const totalDuration = getTotalDuration(); - const newTo = newEndDate.toISOString(); - const newFrom = newEndDate.subtract(totalDuration, 'millisecond').toISOString(); - - setSeries(seriesId, { - ...series, - time: { from: newFrom, to: newTo }, - }); - } else { - const newTo = newEndDate.toISOString(); - - setSeries(seriesId, { - ...series, - time: { from: seriesFrom, to: newTo }, - }); - } - }; - - return ( - endDate} - aria-label={i18n.translate('xpack.observability.expView.dateRanger.startDate', { - defaultMessage: 'Start date', - })} - dateFormat={dateFormat.replace('ss.SSS', 'ss')} - showTimeSelect - popoverPlacement="rightCenter" - /> - } - endDateControl={ - endDate} - aria-label={i18n.translate('xpack.observability.expView.dateRanger.endDate', { - defaultMessage: 'End date', - })} - dateFormat={dateFormat.replace('ss.SSS', 'ss')} - showTimeSelect - popoverPlacement="rightCenter" - /> - } - /> - ); -} diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/components/empty_view.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/components/empty_view.tsx deleted file mode 100644 index d17e451ef702c8..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/components/empty_view.tsx +++ /dev/null @@ -1,99 +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 React from 'react'; -import { isEmpty } from 'lodash'; -import { EuiFlexGroup, EuiFlexItem, EuiProgress, EuiSpacer, EuiText } from '@elastic/eui'; -import styled from 'styled-components'; -import { i18n } from '@kbn/i18n'; -import { LOADING_VIEW } from '../series_editor/series_editor'; -import { ReportViewType, SeriesUrl } from '../types'; - -export function EmptyView({ - loading, - series, - reportType, -}: { - loading: boolean; - series?: SeriesUrl; - reportType: ReportViewType; -}) { - const { dataType, reportDefinitions } = series ?? {}; - - let emptyMessage = EMPTY_LABEL; - - if (dataType) { - if (reportType) { - if (isEmpty(reportDefinitions)) { - emptyMessage = CHOOSE_REPORT_DEFINITION; - } - } else { - emptyMessage = SELECT_REPORT_TYPE_BELOW; - } - } else { - emptyMessage = SELECTED_DATA_TYPE_FOR_REPORT; - } - - if (!series) { - emptyMessage = i18n.translate('xpack.observability.expView.seriesEditor.notFound', { - defaultMessage: 'No series found. Please add a series.', - }); - } - - return ( - - {loading && ( - - )} - - - - {loading ? LOADING_VIEW : emptyMessage} - - - - ); -} - -const Wrapper = styled.div` - text-align: center; - position: relative; -`; - -const FlexGroup = styled(EuiFlexGroup)` - height: 100%; -`; - -export const EMPTY_LABEL = i18n.translate('xpack.observability.expView.seriesBuilder.emptyview', { - defaultMessage: 'Nothing to display.', -}); - -export const CHOOSE_REPORT_DEFINITION = i18n.translate( - 'xpack.observability.expView.seriesBuilder.emptyReportDefinition', - { - defaultMessage: 'Select a report definition to create a visualization.', - } -); - -export const SELECT_REPORT_TYPE_BELOW = i18n.translate( - 'xpack.observability.expView.seriesBuilder.selectReportType.empty', - { - defaultMessage: 'Select a report type to create a visualization.', - } -); - -const SELECTED_DATA_TYPE_FOR_REPORT = i18n.translate( - 'xpack.observability.expView.reportType.selectDataType', - { defaultMessage: 'Select a data type to create a visualization.' } -); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/components/filter_label.test.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/components/filter_label.test.tsx deleted file mode 100644 index f5c65eee265977..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/components/filter_label.test.tsx +++ /dev/null @@ -1,146 +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 React from 'react'; -import { fireEvent, screen, waitFor } from '@testing-library/react'; -import { mockAppDataView, mockDataView, mockUxSeries, render } from '../rtl_helpers'; -import { FilterLabel } from './filter_label'; -import * as useSeriesHook from '../hooks/use_series_filters'; -import { buildFilterLabel } from '../../filter_value_label/filter_value_label'; -import 'jest-canvas-mock'; - -jest.setTimeout(10 * 1000); - -describe('FilterLabel', function () { - mockAppDataView(); - - const invertFilter = jest.fn(); - jest.spyOn(useSeriesHook, 'useSeriesFilters').mockReturnValue({ - invertFilter, - } as any); - - it('should render properly', async function () { - render( - - ); - - await waitFor(async () => { - expect(await screen.findByText('elastic-co')).toBeInTheDocument(); - expect(await screen.findByText('elastic-co')).toBeInTheDocument(); - expect(await screen.findByText(/web application:/i)).toBeInTheDocument(); - expect(await screen.findByTitle('Delete Web Application: elastic-co')).toBeInTheDocument(); - }); - }); - - it('should delete filter', async function () { - const removeFilter = jest.fn(); - render( - - ); - - fireEvent.click(await screen.findByLabelText('Filter actions')); - - fireEvent.click(await screen.findByTestId('deleteFilter')); - expect(removeFilter).toHaveBeenCalledTimes(1); - expect(removeFilter).toHaveBeenCalledWith('service.name', 'elastic-co', false); - }); - - it('should invert filter', async function () { - const removeFilter = jest.fn(); - render( - - ); - - fireEvent.click(await screen.findByLabelText('Filter actions')); - - fireEvent.click(await screen.findByTestId('negateFilter')); - expect(invertFilter).toHaveBeenCalledTimes(1); - expect(invertFilter).toHaveBeenCalledWith({ - field: 'service.name', - negate: false, - value: 'elastic-co', - }); - }); - - it('should display invert filter', async function () { - render( - - ); - - expect(await screen.findByText('elastic-co')).toBeInTheDocument(); - expect(await screen.findByText(/web application:/i)).toBeInTheDocument(); - expect(await screen.findByTitle('Delete NOT Web Application: elastic-co')).toBeInTheDocument(); - expect( - await screen.findByRole('button', { - name: /delete not web application: elastic-co/i, - }) - ).toBeInTheDocument(); - }); - - it('should build filter meta', function () { - expect( - buildFilterLabel({ - field: 'user_agent.name', - label: 'Browser family', - dataView: mockDataView, - value: 'Firefox', - negate: false, - }) - ).toEqual({ - meta: { - alias: null, - disabled: false, - index: 'apm-*', - key: 'Browser family', - negate: false, - type: 'phrase', - value: 'Firefox', - }, - query: { - match_phrase: { - 'user_agent.name': 'Firefox', - }, - }, - }); - }); -}); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/components/filter_label.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/components/filter_label.tsx deleted file mode 100644 index 8b6343119f121a..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/components/filter_label.tsx +++ /dev/null @@ -1,52 +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 React from 'react'; -import type { DataView } from '@kbn/data-views-plugin/common'; -import { useSeriesFilters } from '../hooks/use_series_filters'; -import { FilterValueLabel } from '../../filter_value_label/filter_value_label'; -import { SeriesUrl } from '../types'; - -interface Props { - field: string; - label: string; - value: string | Array; - seriesId: number; - series: SeriesUrl; - negate: boolean; - definitionFilter?: boolean; - dataView: DataView; - removeFilter: (field: string, value: string | Array, notVal: boolean) => void; -} - -export function FilterLabel({ - label, - seriesId, - series, - field, - value, - negate, - dataView, - removeFilter, - definitionFilter, -}: Props) { - const { invertFilter } = useSeriesFilters({ seriesId, series }); - - return dataView ? ( - { - if (!definitionFilter) invertFilter(val); - }} - field={field} - value={value} - negate={negate} - label={label} - /> - ) : null; -} diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/components/series_color_picker.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/components/series_color_picker.tsx deleted file mode 100644 index 28b96288f53348..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/components/series_color_picker.tsx +++ /dev/null @@ -1,70 +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 React, { useState } from 'react'; -import { - EuiColorPicker, - EuiFormRow, - EuiIcon, - EuiPopover, - EuiToolTip, - EuiButtonEmpty, -} from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; -import { useTheme } from '../../../../hooks/use_theme'; -import { useSeriesStorage } from '../hooks/use_series_storage'; -import { SeriesUrl } from '../types'; - -export function SeriesColorPicker({ seriesId, series }: { seriesId: number; series: SeriesUrl }) { - const theme = useTheme(); - - const { setSeries } = useSeriesStorage(); - - const [isOpen, setIsOpen] = useState(false); - - const onChange = (colorN: string) => { - setSeries(seriesId, { ...series, color: colorN }); - }; - - const color = - series.color ?? (theme.eui as unknown as Record)[`euiColorVis${seriesId}`]; - - const button = ( - - setIsOpen((prevState) => !prevState)} - flush="both" - > - - - - ); - - return ( - setIsOpen(false)}> - - - - - ); -} - -const PICK_A_COLOR_LABEL = i18n.translate( - 'xpack.observability.overview.exploratoryView.pickColor', - { - defaultMessage: 'Pick a color', - } -); - -const EDIT_SERIES_COLOR_LABEL = i18n.translate( - 'xpack.observability.overview.exploratoryView.editSeriesColor', - { - defaultMessage: 'Edit color for series', - } -); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/components/series_date_picker/index.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/components/series_date_picker/index.tsx deleted file mode 100644 index 0567f5cdaa1d58..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/components/series_date_picker/index.tsx +++ /dev/null @@ -1,59 +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 { EuiSuperDatePicker } from '@elastic/eui'; -import React from 'react'; - -import { useHasData } from '../../../../../hooks/use_has_data'; -import { useSeriesStorage } from '../../hooks/use_series_storage'; -import { useQuickTimeRanges } from '../../../../../hooks/use_quick_time_ranges'; -import { SeriesUrl } from '../../types'; -import { ReportTypes } from '../../configurations/constants'; - -export interface TimePickerTime { - from: string; - to: string; -} - -export interface TimePickerQuickRange extends TimePickerTime { - display: string; -} - -interface Props { - seriesId: number; - series: SeriesUrl; -} - -export function SeriesDatePicker({ series, seriesId }: Props) { - const { onRefreshTimeRange } = useHasData(); - - const commonlyUsedRanges = useQuickTimeRanges(); - - const { setSeries, reportType, allSeries } = useSeriesStorage(); - - function onTimeChange({ start, end }: { start: string; end: string }) { - onRefreshTimeRange?.(); - if (reportType === ReportTypes.KPI) { - allSeries.forEach((currSeries, seriesIndex) => { - setSeries(seriesIndex, { ...currSeries, time: { from: start, to: end } }); - }); - } else { - setSeries(seriesId, { ...series, time: { from: start, to: end } }); - } - } - - return ( - - ); -} diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/components/series_date_picker/series_date_picker.test.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/components/series_date_picker/series_date_picker.test.tsx deleted file mode 100644 index 4e6a02c3ddefbb..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/components/series_date_picker/series_date_picker.test.tsx +++ /dev/null @@ -1,68 +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 React from 'react'; -import { mockUseHasData, render } from '../../rtl_helpers'; -import { fireEvent, waitFor } from '@testing-library/react'; -import { SeriesDatePicker } from '.'; - -describe('SeriesDatePicker', function () { - it('should render properly', function () { - const initSeries = { - data: [ - { - name: 'uptime-pings-histogram', - dataType: 'synthetics' as const, - breakdown: 'monitor.status', - time: { from: 'now-30m', to: 'now' }, - }, - ], - }; - const { getByText } = render(, { - initSeries, - }); - - getByText('Last 30 minutes'); - }); - - it('should set series data', async function () { - const initSeries = { - data: [ - { - name: 'uptime-pings-histogram', - dataType: 'synthetics' as const, - breakdown: 'monitor.status', - time: { from: 'now-30m', to: 'now' }, - }, - ], - }; - - const { onRefreshTimeRange } = mockUseHasData(); - const { getByTestId, setSeries } = render( - , - { - initSeries, - } - ); - - await waitFor(function () { - fireEvent.click(getByTestId('superDatePickerToggleQuickMenuButton')); - }); - - fireEvent.click(getByTestId('superDatePickerCommonlyUsed_Today')); - - expect(onRefreshTimeRange).toHaveBeenCalledTimes(1); - - expect(setSeries).toHaveBeenCalledWith(0, { - name: 'uptime-pings-histogram', - breakdown: 'monitor.status', - dataType: 'synthetics', - time: { from: 'now/d', to: 'now/d' }, - }); - expect(setSeries).toHaveBeenCalledTimes(1); - }); -}); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/components/url_search/selectable_url_list.test.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/components/url_search/selectable_url_list.test.tsx deleted file mode 100644 index c93f985dd9f3fc..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/components/url_search/selectable_url_list.test.tsx +++ /dev/null @@ -1,111 +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 React, { useState } from 'react'; -import { fireEvent, waitFor, waitForElementToBeRemoved } from '@testing-library/react'; -import { createMemoryHistory } from 'history'; -import * as fetcherHook from '../../../../../hooks/use_fetcher'; -import { SelectableUrlList } from './selectable_url_list'; -import { I18LABELS } from './translations'; -import { render } from '../../rtl_helpers'; - -describe('SelectableUrlList', () => { - jest.spyOn(fetcherHook, 'useFetcher').mockReturnValue({ - data: {}, - status: fetcherHook.FETCH_STATUS.SUCCESS, - refetch: jest.fn(), - }); - - const customHistory = createMemoryHistory({ - initialEntries: ['/?searchTerm=blog'], - }); - - function WrappedComponent() { - const [isPopoverOpen, setIsPopoverOpen] = useState(false); - return ( - true} - /> - ); - } - - it('it uses search term value from url', () => { - const { getByDisplayValue } = render( - true} - />, - { history: customHistory } - ); - expect(getByDisplayValue('blog')).toBeInTheDocument(); - }); - - it('maintains focus on search input field', () => { - const { getByLabelText } = render( - true} - />, - { history: customHistory } - ); - - const input = getByLabelText(I18LABELS.filterByUrl); - fireEvent.click(input); - - expect(document.activeElement).toBe(input); - }); - - it('hides popover on escape', async () => { - const { getByText, getByLabelText, queryByText } = render(, { - history: customHistory, - }); - - const input = getByLabelText(I18LABELS.filterByUrl); - fireEvent.click(input); - - // wait for title of popover to be present - await waitFor(() => { - expect(getByText(I18LABELS.getSearchResultsLabel(0))).toBeInTheDocument(); - }); - - // escape key - fireEvent.keyDown(input, { - key: 'Escape', - code: 'Escape', - keyCode: 27, - charCode: 27, - }); - - // wait for title of popover to be removed - await waitForElementToBeRemoved(() => queryByText(I18LABELS.getSearchResultsLabel(0))); - }); -}); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/components/url_search/selectable_url_list.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/components/url_search/selectable_url_list.tsx deleted file mode 100644 index 06aa2c5d1c2a9e..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/components/url_search/selectable_url_list.tsx +++ /dev/null @@ -1,226 +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 React, { - SetStateAction, - useRef, - useState, - KeyboardEvent, - ReactNode, - FormEventHandler, -} from 'react'; -import { - EuiFlexGroup, - EuiFlexItem, - EuiLoadingSpinner, - EuiPopover, - EuiPopoverTitle, - EuiSelectable, - EuiSelectableMessage, - EuiPopoverFooter, - EuiButton, - EuiButtonIcon, - EuiSelectableOption, -} from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; -import useEvent from 'react-use/lib/useEvent'; -import classNames from 'classnames'; -import { I18LABELS } from './translations'; - -export type UrlOption = { - meta?: string[]; - isNewWildcard?: boolean; - isWildcard?: boolean; - title: string; -} & EuiSelectableOption; - -export interface SelectableUrlListProps { - data: { - items: UrlOption[]; - total?: number; - }; - loading: boolean; - rowHeight?: number; - onInputChange: (val: string) => void; - onSelectionApply: () => void; - onSelectionChange: (updatedOptions: UrlOption[]) => void; - searchValue: string; - popoverIsOpen: boolean; - initialValue?: string; - setPopoverIsOpen: React.Dispatch>; - renderOption?: (option: UrlOption, searchValue: string) => ReactNode; - hasChanged: () => boolean; -} -export const formatOptions = (options: EuiSelectableOption[]) => { - return options.map((item: EuiSelectableOption) => ({ - title: item.label, - ...item, - className: classNames('euiSelectableTemplateSitewide__listItem', item.className), - })); -}; -export function SelectableUrlList({ - data, - loading, - onInputChange, - onSelectionChange, - onSelectionApply, - searchValue, - popoverIsOpen, - setPopoverIsOpen, - initialValue, - renderOption, - rowHeight, - hasChanged, -}: SelectableUrlListProps) { - const [searchRef, setSearchRef] = useState(null); - - const titleRef = useRef(null); - - const formattedOptions = formatOptions(data.items ?? []); - - const onEnterKey = (evt: KeyboardEvent) => { - if (evt.key.toLowerCase() === 'enter') { - onSelectionApply(); - setPopoverIsOpen(false); - } - }; - - const onInputClick = (e: React.MouseEvent) => { - setPopoverIsOpen(true); - if (searchRef) { - searchRef.focus(); - } - }; - - const onSearchInput: FormEventHandler = (e) => { - onInputChange((e.target as HTMLInputElement).value); - setPopoverIsOpen(true); - }; - - const closePopover = () => { - setPopoverIsOpen(false); - }; - - // @ts-ignore - not sure, why it's not working - useEvent('keydown', onEnterKey, searchRef); - useEvent('escape', () => setPopoverIsOpen(false), searchRef); - - const loadingMessage = ( - - -
-

{I18LABELS.loadingResults}

-
- ); - - const emptyMessage = ( - -

{I18LABELS.noResults}

-
- ); - - const titleText = searchValue - ? I18LABELS.getSearchResultsLabel(data?.total ?? 0) - : I18LABELS.topPages; - - function PopOverTitle() { - return ( - - - - {loading ? : titleText} - - - closePopover()} - aria-label={i18n.translate('xpack.observability.search.url.close', { - defaultMessage: 'Close', - })} - iconType={'cross'} - /> - - - - ); - } - - return ( - - {(list, search) => ( - -
- - {list} - - - - { - onSelectionApply(); - closePopover(); - }} - isDisabled={!hasChanged()} - > - {i18n.translate('xpack.observability.apply.label', { - defaultMessage: 'Apply', - })} - - - - -
-
- )} -
- ); -} - -// eslint-disable-next-line import/no-default-export -export default SelectableUrlList; diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/components/url_search/translations.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/components/url_search/translations.ts deleted file mode 100644 index 7a827808366415..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/components/url_search/translations.ts +++ /dev/null @@ -1,34 +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 { i18n } from '@kbn/i18n'; - -export const I18LABELS = { - filterByUrl: i18n.translate('xpack.observability.filters.filterByUrl', { - defaultMessage: 'Filter by URL', - }), - getSearchResultsLabel: (total: number) => - i18n.translate('xpack.observability.filters.searchResults', { - defaultMessage: '{total} Search results', - values: { total }, - }), - topPages: i18n.translate('xpack.observability.filters.topPages', { - defaultMessage: 'Top pages', - }), - select: i18n.translate('xpack.observability.filters.select', { - defaultMessage: 'Select', - }), - url: i18n.translate('xpack.observability.filters.url', { - defaultMessage: 'Url', - }), - loadingResults: i18n.translate('xpack.observability.filters.url.loadingResults', { - defaultMessage: 'Loading results', - }), - noResults: i18n.translate('xpack.observability.filters.url.noResults', { - defaultMessage: 'No results available', - }), -}; diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/components/url_search/url_search.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/components/url_search/url_search.tsx deleted file mode 100644 index 00652bf50cf935..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/components/url_search/url_search.tsx +++ /dev/null @@ -1,231 +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 React, { useEffect, useState } from 'react'; -import { isEqual, map } from 'lodash'; -import { i18n } from '@kbn/i18n'; -import { SelectableUrlList, UrlOption } from './selectable_url_list'; -import { SeriesConfig, SeriesUrl, UrlFilter } from '../../types'; -import { useUrlSearch } from './use_url_search'; -import { useSeriesFilters } from '../../hooks/use_series_filters'; -import { TRANSACTION_URL } from '../../configurations/constants/elasticsearch_fieldnames'; - -interface Props { - seriesId: number; - seriesConfig: SeriesConfig; - series: SeriesUrl; -} - -const processSelectedItems = (items: UrlOption[]) => { - const urlItems = items.filter(({ isWildcard }) => !isWildcard); - - const wildcardItems = items.filter(({ isWildcard }) => isWildcard); - - const includedItems = map( - urlItems.filter((option) => option.checked === 'on'), - 'label' - ); - - const excludedItems = map( - urlItems.filter((option) => option.checked === 'off'), - 'label' - ); - - // for wild cards we use title since label contains extra information - const includedWildcards = map( - wildcardItems.filter((option) => option.checked === 'on'), - 'title' - ); - - // for wild cards we use title since label contains extra information - const excludedWildcards = map( - wildcardItems.filter((option) => option.checked === 'off'), - 'title' - ); - - return { includedItems, excludedItems, includedWildcards, excludedWildcards }; -}; - -const getWildcardLabel = (wildcard: string) => { - return i18n.translate('xpack.observability.urlFilter.wildcard', { - defaultMessage: 'Use wildcard *{wildcard}*', - values: { wildcard }, - }); -}; - -export function URLSearch({ series, seriesConfig, seriesId }: Props) { - const [popoverIsOpen, setPopoverIsOpen] = useState(false); - const [query, setQuery] = useState(''); - - const [items, setItems] = useState([]); - - const { values, loading } = useUrlSearch({ - query, - series, - seriesConfig, - seriesId, - }); - - useEffect(() => { - const queryLabel = getWildcardLabel(query); - const currFilter: UrlFilter | undefined = (series.filters ?? []).find( - ({ field }) => field === TRANSACTION_URL - ); - - const { - wildcards = [], - notWildcards = [], - values: currValues = [], - notValues: currNotValues = [], - } = currFilter ?? { field: TRANSACTION_URL }; - - setItems((prevItems) => { - const { includedItems, excludedItems } = processSelectedItems(prevItems); - - const newItems: UrlOption[] = (values ?? []).map((item) => { - if ( - includedItems.includes(item.label) || - wildcards.includes(item.label) || - currValues.includes(item.label) - ) { - return { ...item, checked: 'on', title: item.label }; - } - if ( - excludedItems.includes(item.label) || - notWildcards.includes(item.label) || - currNotValues.includes(item.label) - ) { - return { ...item, checked: 'off', title: item.label, ...item }; - } - return { ...item, title: item.label, checked: undefined }; - }); - - wildcards.forEach((wildcard) => { - newItems.unshift({ - title: wildcard, - label: getWildcardLabel(wildcard), - isWildcard: true, - checked: 'on', - }); - }); - - notWildcards.forEach((wildcard) => { - newItems.unshift({ - title: wildcard, - label: getWildcardLabel(wildcard), - isWildcard: true, - checked: 'off', - }); - }); - - let queryItem: UrlOption | undefined = prevItems.find(({ isNewWildcard }) => isNewWildcard); - if (query) { - if (!queryItem) { - queryItem = { - title: query, - label: queryLabel, - isNewWildcard: true, - isWildcard: true, - }; - newItems.unshift(queryItem); - } - - return [{ ...queryItem, label: queryLabel, title: query }, ...newItems]; - } - - return newItems; - }); - // we don't want to add series in the dependency, for that we have an extra side effect below - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [values, loading, query]); - - useEffect(() => { - const currFilter: UrlFilter | undefined = (series.filters ?? []).find( - ({ field }) => field === TRANSACTION_URL - ); - - const { - wildcards = [], - notWildcards = [], - values: currValues = [], - notValues: currNotValues = [], - } = currFilter ?? { field: TRANSACTION_URL }; - - setItems((prevItems) => { - const newItems: UrlOption[] = (prevItems ?? []).map((item) => { - if (currValues.includes(item.label) || wildcards.includes(item.title)) { - return { ...item, checked: 'on' }; - } - - if (currNotValues.includes(item.label) || notWildcards.includes(item.title)) { - return { ...item, checked: 'off' }; - } - return { ...item, checked: undefined }; - }); - - return newItems; - }); - }, [series]); - - const onSelectionChange = (updatedOptions: UrlOption[]) => { - setItems(updatedOptions); - }; - - const { replaceFilter } = useSeriesFilters({ seriesId, series }); - - const onSelectionApply = () => { - const { includedItems, excludedItems, includedWildcards, excludedWildcards } = - processSelectedItems(items); - - replaceFilter({ - field: TRANSACTION_URL, - values: includedItems, - notValues: excludedItems, - wildcards: includedWildcards, - notWildcards: excludedWildcards, - }); - - setQuery(''); - setPopoverIsOpen(false); - }; - - const hasChanged = () => { - const { includedItems, excludedItems, includedWildcards, excludedWildcards } = - processSelectedItems(items); - const currFilter: UrlFilter | undefined = (series.filters ?? []).find( - ({ field }) => field === TRANSACTION_URL - ); - - const { - wildcards = [], - notWildcards = [], - values: currValues = [], - notValues: currNotValues = [], - } = currFilter ?? { field: TRANSACTION_URL }; - - return ( - !isEqual(includedItems.sort(), currValues.sort()) || - !isEqual(excludedItems.sort(), currNotValues.sort()) || - !isEqual(wildcards.sort(), includedWildcards.sort()) || - !isEqual(notWildcards.sort(), excludedWildcards.sort()) - ); - }; - - return ( - setQuery(val)} - data={{ items, total: items.length }} - onSelectionChange={onSelectionChange} - searchValue={query} - popoverIsOpen={popoverIsOpen} - setPopoverIsOpen={setPopoverIsOpen} - onSelectionApply={onSelectionApply} - hasChanged={hasChanged} - /> - ); -} diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/components/url_search/use_url_search.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/components/url_search/use_url_search.ts deleted file mode 100644 index da99720fe94bbc..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/components/url_search/use_url_search.ts +++ /dev/null @@ -1,31 +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 { SeriesConfig, SeriesUrl } from '../../types'; -import { TRANSACTION_URL } from '../../configurations/constants/elasticsearch_fieldnames'; -import { useFilterValues } from '../../series_editor/use_filter_values'; - -interface Props { - query?: string; - seriesId: number; - series: SeriesUrl; - seriesConfig: SeriesConfig; -} -export const useUrlSearch = ({ series, query, seriesId, seriesConfig }: Props) => { - const { values, loading } = useFilterValues( - { - series, - seriesId, - field: TRANSACTION_URL, - baseFilters: seriesConfig.baseFilters, - label: seriesConfig.labels[TRANSACTION_URL], - }, - query - ); - - return { values, loading }; -}; diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/alerts_configs/kpi_over_time_config.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/alerts_configs/kpi_over_time_config.ts deleted file mode 100644 index ebe16faae4b500..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/alerts_configs/kpi_over_time_config.ts +++ /dev/null @@ -1,66 +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 { i18n } from '@kbn/i18n'; -import { ConfigProps, SeriesConfig } from '../../types'; -import { - FieldLabels, - RECORDS_FIELD, - REPORT_METRIC_FIELD, - REPORT_METRIC_TIMESTAMP, - ReportTypes, -} from '../constants'; - -export function getAlertsKPIConfig({ spaceId }: ConfigProps): SeriesConfig { - return { - reportType: ReportTypes.KPI, - defaultSeriesType: 'line', - seriesTypes: [], - xAxisColumn: { - label: i18n.translate('xpack.observability.exploratoryView.alerts.alertStarted', { - defaultMessage: 'Timestamp', - }), - dataType: 'date', - operationType: 'date_histogram', - isBucketed: true, - scale: 'interval', - sourceField: REPORT_METRIC_TIMESTAMP, - }, - yAxisColumns: [ - { - sourceField: REPORT_METRIC_FIELD, - operationType: 'count', - }, - ], - hasOperationType: false, - filterFields: ['kibana.alert.rule.name', 'kibana.alert.status'], - breakdownFields: ['kibana.alert.rule.category', 'kibana.alert.status'], - baseFilters: [], - definitionFields: ['kibana.alert.rule.category'], - metricOptions: [ - { - label: 'Total alerts', - field: RECORDS_FIELD, - id: 'Alerts', - columnType: 'unique_count', - timestampField: 'kibana.alert.start', - }, - { - label: 'Recovered alerts', - field: RECORDS_FIELD, - id: 'recovered_alerts', - columnType: 'unique_count', - timestampField: 'kibana.alert.end', - }, - ], - labels: { ...FieldLabels }, - query: { - language: 'kuery', - query: `kibana.space_ids: "${spaceId}"`, - }, - }; -} diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/alerts_configs/single_metric_config.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/alerts_configs/single_metric_config.ts deleted file mode 100644 index ce8b43d1768616..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/alerts_configs/single_metric_config.ts +++ /dev/null @@ -1,45 +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, SeriesConfig } from '../../types'; -import { FieldLabels, RECORDS_FIELD, ReportTypes } from '../constants'; - -export function getAlertsSingleMetricConfig({ spaceId }: ConfigProps): SeriesConfig { - return { - seriesTypes: [], - defaultSeriesType: 'line', - reportType: ReportTypes.SINGLE_METRIC, - xAxisColumn: {}, - yAxisColumns: [ - { - operationType: 'median', - }, - ], - hasOperationType: false, - filterFields: ['kibana.alert.rule.name', 'kibana.alert.status'], - breakdownFields: ['kibana.alert.rule.category', 'kibana.alert.status'], - baseFilters: [], - definitionFields: ['kibana.alert.rule.category'], - metricOptions: [ - { - label: 'Active', - field: RECORDS_FIELD, - id: 'Alerts', - columnType: 'unique_count', - metricStateOptions: { - titlePosition: 'bottom', - }, - emptyAsNull: false, - }, - ], - labels: { ...FieldLabels }, - query: { - language: 'kuery', - query: `kibana.space_ids: "${spaceId}"`, - }, - }; -} diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/apm/field_formats.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/apm/field_formats.ts deleted file mode 100644 index 5c1afbca2a7766..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/apm/field_formats.ts +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { FieldFormat } from '../../types'; -import { - METRIC_SYSTEM_CPU_USAGE, - METRIC_SYSTEM_MEMORY_USAGE, - TRANSACTION_DURATION, -} from '../constants/elasticsearch_fieldnames'; - -export const apmFieldFormats: FieldFormat[] = [ - { - field: TRANSACTION_DURATION, - format: { - id: 'duration', - params: { - inputFormat: 'microseconds', - outputFormat: 'asMilliseconds', - outputPrecision: 0, - showSuffix: true, - useShortSuffix: true, - }, - }, - }, - { - field: METRIC_SYSTEM_MEMORY_USAGE, - format: { id: 'bytes', params: {} }, - }, - { - field: METRIC_SYSTEM_CPU_USAGE, - format: { id: 'percent', params: {} }, - }, -]; diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/constants/constants.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/constants/constants.ts deleted file mode 100644 index 951cdfea966a4d..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/constants/constants.ts +++ /dev/null @@ -1,213 +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 { OperationType } from '@kbn/lens-plugin/public'; -import { DOCUMENT_FIELD_NAME } from '@kbn/lens-plugin/common/constants'; -import { i18n } from '@kbn/i18n'; -import { ReportViewType } from '../../types'; -import { - CLS_FIELD, - FCP_FIELD, - FID_FIELD, - LCP_FIELD, - TBT_FIELD, - TRANSACTION_DURATION, - TRANSACTION_TIME_TO_FIRST_BYTE, -} from './elasticsearch_fieldnames'; -import { - AGENT_HOST_LABEL, - AGENT_TYPE_LABEL, - BACKEND_TIME_LABEL, - BROWSER_FAMILY_LABEL, - BROWSER_VERSION_LABEL, - CLS_LABEL, - CORE_WEB_VITALS_LABEL, - DCL_LABEL, - DEVICE_DISTRIBUTION_LABEL, - DEVICE_LABEL, - ENVIRONMENT_LABEL, - EVENT_DATASET_LABEL, - FCP_LABEL, - FID_LABEL, - HEATMAP_LABEL, - HOST_NAME_LABEL, - KPI_LABEL, - KPI_OVER_TIME_LABEL, - LABELS_FIELD, - LCP_LABEL, - LOCATION_LABEL, - MESSAGE_LABEL, - METRIC_LABEL, - MONITOR_ID_LABEL, - MONITOR_NAME_LABEL, - MONITOR_STATUS_LABEL, - MONITOR_TYPE_LABEL, - MONITORS_DURATION_LABEL, - OBSERVER_LOCATION_LABEL, - OS_LABEL, - PAGE_LOAD_TIME_LABEL, - PERF_DIST_LABEL, - PORT_LABEL, - REQUEST_METHOD, - SERVICE_NAME_LABEL, - SERVICE_TYPE_LABEL, - SINGLE_METRIC_LABEL, - STEP_DURATION_LABEL, - STEP_NAME_LABEL, - TAGS_LABEL, - TBT_LABEL, - URL_LABEL, -} from './labels'; -import { - MONITOR_DURATION_US, - SYNTHETICS_BLOCKED_TIMINGS, - SYNTHETICS_CLS, - SYNTHETICS_CONNECT_TIMINGS, - SYNTHETICS_DCL, - SYNTHETICS_DNS_TIMINGS, - SYNTHETICS_DOCUMENT_ONLOAD, - SYNTHETICS_FCP, - SYNTHETICS_LCP, - SYNTHETICS_RECEIVE_TIMINGS, - SYNTHETICS_SEND_TIMINGS, - SYNTHETICS_SSL_TIMINGS, - SYNTHETICS_STEP_DURATION, - SYNTHETICS_STEP_NAME, - SYNTHETICS_TOTAL_TIMINGS, - SYNTHETICS_WAIT_TIMINGS, -} from './field_names/synthetics'; - -export const DEFAULT_TIME = { from: 'now-1h', to: 'now' }; - -export const RECORDS_FIELD = DOCUMENT_FIELD_NAME; -export const RECORDS_PERCENTAGE_FIELD = 'RecordsPercentage'; -export const FORMULA_COLUMN = 'FORMULA_COLUMN'; - -export const FieldLabels: Record = { - 'user_agent.name': BROWSER_FAMILY_LABEL, - 'user_agent.version': BROWSER_VERSION_LABEL, - 'user_agent.os.name': OS_LABEL, - 'client.geo.country_name': LOCATION_LABEL, - 'user_agent.device.name': DEVICE_LABEL, - 'observer.geo.name': OBSERVER_LOCATION_LABEL, - 'service.name': SERVICE_NAME_LABEL, - 'service.environment': ENVIRONMENT_LABEL, - 'service.type': SERVICE_TYPE_LABEL, - 'event.dataset': EVENT_DATASET_LABEL, - message: MESSAGE_LABEL, - - [LCP_FIELD]: LCP_LABEL, - [FCP_FIELD]: FCP_LABEL, - [TBT_FIELD]: TBT_LABEL, - [FID_FIELD]: FID_LABEL, - [CLS_FIELD]: CLS_LABEL, - - [SYNTHETICS_CLS]: CLS_LABEL, - [SYNTHETICS_DCL]: DCL_LABEL, - [SYNTHETICS_STEP_DURATION]: STEP_DURATION_LABEL, - [SYNTHETICS_LCP]: LCP_LABEL, - [SYNTHETICS_FCP]: FCP_LABEL, - [SYNTHETICS_DOCUMENT_ONLOAD]: PAGE_LOAD_TIME_LABEL, - [TRANSACTION_TIME_TO_FIRST_BYTE]: BACKEND_TIME_LABEL, - [TRANSACTION_DURATION]: PAGE_LOAD_TIME_LABEL, - [SYNTHETICS_CONNECT_TIMINGS]: i18n.translate('xpack.observability.expView.synthetics.connect', { - defaultMessage: 'Connect', - }), - [SYNTHETICS_DNS_TIMINGS]: i18n.translate('xpack.observability.expView.synthetics.dns', { - defaultMessage: 'DNS', - }), - [SYNTHETICS_WAIT_TIMINGS]: i18n.translate('xpack.observability.expView.synthetics.wait', { - defaultMessage: 'Wait', - }), - [SYNTHETICS_SSL_TIMINGS]: i18n.translate('xpack.observability.expView.synthetics.ssl', { - defaultMessage: 'SSL', - }), - [SYNTHETICS_BLOCKED_TIMINGS]: i18n.translate('xpack.observability.expView.synthetics.blocked', { - defaultMessage: 'Blocked', - }), - [SYNTHETICS_SEND_TIMINGS]: i18n.translate('xpack.observability.expView.synthetics.send', { - defaultMessage: 'Send', - }), - [SYNTHETICS_RECEIVE_TIMINGS]: i18n.translate('xpack.observability.expView.synthetics.receive', { - defaultMessage: 'Receive', - }), - [SYNTHETICS_TOTAL_TIMINGS]: i18n.translate('xpack.observability.expView.synthetics.total', { - defaultMessage: 'Total', - }), - - 'kibana.alert.rule.category': i18n.translate('xpack.observability.expView.alerts.category', { - defaultMessage: 'Rule category', - }), - 'kibana.alert.rule.name': i18n.translate('xpack.observability.expView.alerts.name', { - defaultMessage: 'Alert name', - }), - 'kibana.alert.status': i18n.translate('xpack.observability.expView.alerts.status', { - defaultMessage: 'Alert status', - }), - - 'monitor.id': MONITOR_ID_LABEL, - 'monitor.status': MONITOR_STATUS_LABEL, - [MONITOR_DURATION_US]: MONITORS_DURATION_LABEL, - [SYNTHETICS_STEP_NAME]: STEP_NAME_LABEL, - - 'agent.hostname': AGENT_HOST_LABEL, - 'agent.type': AGENT_TYPE_LABEL, - 'host.hostname': HOST_NAME_LABEL, - 'monitor.name': MONITOR_NAME_LABEL, - 'monitor.type': MONITOR_TYPE_LABEL, - 'url.port': PORT_LABEL, - 'url.full': URL_LABEL, - tags: TAGS_LABEL, - - // custom - - 'performance.metric': METRIC_LABEL, - 'Business.KPI': KPI_LABEL, - 'http.request.method': REQUEST_METHOD, - percentile: 'Percentile', - LABEL_FIELDS_FILTER: LABELS_FIELD, - LABEL_FIELDS_BREAKDOWN: 'Labels field', -}; - -export const DataViewLabels: Record = { - 'data-distribution': PERF_DIST_LABEL, - 'kpi-over-time': KPI_OVER_TIME_LABEL, - 'core-web-vitals': CORE_WEB_VITALS_LABEL, - 'device-data-distribution': DEVICE_DISTRIBUTION_LABEL, - 'single-metric': SINGLE_METRIC_LABEL, - heatmap: HEATMAP_LABEL, -}; - -export enum ReportTypes { - KPI = 'kpi-over-time', - DISTRIBUTION = 'data-distribution', - CORE_WEB_VITAL = 'core-web-vitals', - DEVICE_DISTRIBUTION = 'device-data-distribution', - SINGLE_METRIC = 'single-metric', - HEATMAP = 'heatmap', -} - -export const USE_BREAK_DOWN_COLUMN = 'USE_BREAK_DOWN_COLUMN'; -export const FILTER_RECORDS = 'FILTER_RECORDS'; -export const TERMS_COLUMN = 'TERMS_COLUMN'; -export const OPERATION_COLUMN = 'operation'; -export const PERCENTILE = 'percentile'; - -export const REPORT_METRIC_FIELD = 'REPORT_METRIC_FIELD'; -export const REPORT_METRIC_TIMESTAMP = 'REPORT_METRIC_FIELD_TIMESTAMP'; - -export const PERCENTILE_RANKS = [ - '99th' as OperationType, - '95th' as OperationType, - '90th' as OperationType, - '75th' as OperationType, - '50th' as OperationType, - '25th' as OperationType, -]; -export const LABEL_FIELDS_FILTER = 'LABEL_FIELDS_FILTER'; -export const LABEL_FIELDS_BREAKDOWN = 'LABEL_FIELDS_BREAKDOWN'; - -export const ENVIRONMENT_ALL = 'ENVIRONMENT_ALL'; diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/constants/field_names/infra_logs.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/constants/field_names/infra_logs.ts deleted file mode 100644 index b35c6ac2e42dd1..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/constants/field_names/infra_logs.ts +++ /dev/null @@ -1,10 +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 { RECORDS_FIELD } from '../constants'; - -export const LOG_RATE = RECORDS_FIELD; diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/constants/field_names/infra_metrics.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/constants/field_names/infra_metrics.ts deleted file mode 100644 index 26683dd2a206ee..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/constants/field_names/infra_metrics.ts +++ /dev/null @@ -1,11 +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. - */ - -export const SYSTEM_CPU_PERCENTAGE_FIELD = 'system.cpu.total.norm.pct'; -export const SYSTEM_MEMORY_PERCENTAGE_FIELD = 'system.memory.used.pct'; -export const DOCKER_CPU_PERCENTAGE_FIELD = 'docker.cpu.total.pct'; -export const K8S_POD_CPU_PERCENTAGE_FIELD = 'kubernetes.pod.cpu.usage.node.pct'; diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/constants/field_names/synthetics.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/constants/field_names/synthetics.ts deleted file mode 100644 index 003be106ffaaa1..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/constants/field_names/synthetics.ts +++ /dev/null @@ -1,35 +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. - */ - -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'; -export const SYNTHETICS_STEP_NAME = 'synthetics.step.name.keyword'; -export const SYNTHETICS_STEP_DURATION = 'synthetics.step.duration.us'; - -export const SYNTHETICS_DNS_TIMINGS = 'synthetics.payload.timings.dns'; -export const SYNTHETICS_SSL_TIMINGS = 'synthetics.payload.timings.ssl'; -export const SYNTHETICS_BLOCKED_TIMINGS = 'synthetics.payload.timings.blocked'; -export const SYNTHETICS_CONNECT_TIMINGS = 'synthetics.payload.timings.connect'; -export const SYNTHETICS_RECEIVE_TIMINGS = 'synthetics.payload.timings.receive'; -export const SYNTHETICS_SEND_TIMINGS = 'synthetics.payload.timings.send'; -export const SYNTHETICS_WAIT_TIMINGS = 'synthetics.payload.timings.wait'; -export const SYNTHETICS_TOTAL_TIMINGS = 'synthetics.payload.timings.total'; - -export const NETWORK_TIMINGS_FIELDS = [ - SYNTHETICS_DNS_TIMINGS, - SYNTHETICS_SSL_TIMINGS, - SYNTHETICS_BLOCKED_TIMINGS, - SYNTHETICS_CONNECT_TIMINGS, - SYNTHETICS_RECEIVE_TIMINGS, - SYNTHETICS_SEND_TIMINGS, - SYNTHETICS_WAIT_TIMINGS, - SYNTHETICS_TOTAL_TIMINGS, -]; diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/constants/index.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/constants/index.ts deleted file mode 100644 index 63661f0d5a9963..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/constants/index.ts +++ /dev/null @@ -1,8 +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. - */ - -export * from './constants'; diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/constants/labels.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/constants/labels.ts deleted file mode 100644 index c15880fb9e5d2d..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/constants/labels.ts +++ /dev/null @@ -1,408 +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 { i18n } from '@kbn/i18n'; - -export const BROWSER_FAMILY_LABEL = i18n.translate( - 'xpack.observability.expView.fieldLabels.browserFamily', - { - defaultMessage: 'Browser family', - } -); -export const BROWSER_VERSION_LABEL = i18n.translate( - 'xpack.observability.expView.fieldLabels.browserVersion', - { - defaultMessage: 'Browser version', - } -); - -export const OS_LABEL = i18n.translate('xpack.observability.expView.fieldLabels.os', { - defaultMessage: 'Operating system', -}); -export const LOCATION_LABEL = i18n.translate('xpack.observability.expView.fieldLabels.location', { - defaultMessage: 'Location', -}); - -export const DEVICE_LABEL = i18n.translate('xpack.observability.expView.fieldLabels.device', { - defaultMessage: 'Device', -}); - -export const OBSERVER_LOCATION_LABEL = i18n.translate( - 'xpack.observability.expView.fieldLabels.obsLocation', - { - defaultMessage: 'Observer location', - } -); - -export const SERVICE_NAME_LABEL = i18n.translate( - 'xpack.observability.expView.fieldLabels.serviceName', - { - defaultMessage: 'Service name', - } -); - -export const SERVICE_TYPE_LABEL = i18n.translate( - 'xpack.observability.expView.fieldLabels.serviceType', - { - defaultMessage: 'Service type', - } -); - -export const ENVIRONMENT_LABEL = i18n.translate( - 'xpack.observability.expView.fieldLabels.environment', - { - defaultMessage: 'Environment', - } -); - -export const EVENT_DATASET_LABEL = i18n.translate( - 'xpack.observability.expView.fieldLabels.eventDataset', - { - defaultMessage: 'Dataset', - } -); - -export const LCP_LABEL = i18n.translate('xpack.observability.expView.fieldLabels.lcp', { - defaultMessage: 'Largest contentful paint', -}); - -export const FCP_LABEL = i18n.translate('xpack.observability.expView.fieldLabels.fcp', { - defaultMessage: 'First contentful paint', -}); - -export const TBT_LABEL = i18n.translate('xpack.observability.expView.fieldLabels.tbt', { - defaultMessage: 'Total blocking time', -}); - -export const FID_LABEL = i18n.translate('xpack.observability.expView.fieldLabels.fid', { - defaultMessage: 'First input delay', -}); - -export const CLS_LABEL = i18n.translate('xpack.observability.expView.fieldLabels.cls', { - defaultMessage: 'Cumulative layout shift', -}); - -export const NETWORK_TIMINGS_LABEL = i18n.translate( - 'xpack.observability.expView.fieldLabels.networkTimings', - { - defaultMessage: 'Network timings', - } -); - -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', - { - defaultMessage: 'Backend time', - } -); - -export const PAGE_LOAD_TIME_LABEL = i18n.translate( - 'xpack.observability.expView.fieldLabels.pageLoadTime', - { - defaultMessage: 'Page load time', - } -); - -export const PAGE_VIEWS_LABEL = i18n.translate( - 'xpack.observability.expView.fieldLabels.pageViews', - { - defaultMessage: 'Page views', - } -); - -export const PAGES_LOADED_LABEL = i18n.translate( - 'xpack.observability.expView.fieldLabels.pagesLoaded', - { - defaultMessage: 'Pages loaded', - } -); - -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', - { - defaultMessage: 'Monitor Id', - } -); - -export const MONITOR_STATUS_LABEL = i18n.translate( - 'xpack.observability.expView.fieldLabels.monitorStatus', - { - defaultMessage: 'Monitor Status', - } -); - -export const AGENT_HOST_LABEL = i18n.translate( - 'xpack.observability.expView.fieldLabels.agentHost', - { - defaultMessage: 'Agent host', - } -); - -export const AGENT_TYPE_LABEL = i18n.translate( - 'xpack.observability.expView.fieldLabels.agentType', - { - defaultMessage: 'Agent type', - } -); - -export const MESSAGE_LABEL = i18n.translate('xpack.observability.expView.fieldLabels.message', { - defaultMessage: 'Message', -}); - -export const HOST_NAME_LABEL = i18n.translate('xpack.observability.expView.fieldLabels.hostName', { - defaultMessage: 'Host name', -}); - -export const MONITOR_NAME_LABEL = i18n.translate( - 'xpack.observability.expView.fieldLabels.monitorName', - { - defaultMessage: 'Monitor name', - } -); - -export const MONITOR_TYPE_LABEL = i18n.translate( - 'xpack.observability.expView.fieldLabels.monitorType', - { - defaultMessage: 'Monitor type', - } -); - -export const PORT_LABEL = i18n.translate('xpack.observability.expView.fieldLabels.port', { - defaultMessage: 'Port', -}); - -export const URL_LABEL = i18n.translate('xpack.observability.expView.fieldLabels.url', { - defaultMessage: 'URL', -}); - -export const TAGS_LABEL = i18n.translate('xpack.observability.expView.fieldLabels.tags', { - defaultMessage: 'Tags', -}); - -export const METRIC_LABEL = i18n.translate('xpack.observability.expView.fieldLabels.metric', { - defaultMessage: 'Metric', -}); -export const LABELS_FIELD = i18n.translate('xpack.observability.expView.fieldLabels.labels', { - defaultMessage: 'Labels', -}); -export const LABELS_BREAKDOWN = i18n.translate( - 'xpack.observability.expView.fieldLabels.chooseField', - { - defaultMessage: 'Labels field', - } -); -export const KPI_LABEL = i18n.translate('xpack.observability.expView.fieldLabels.kpi', { - defaultMessage: 'KPI', -}); - -export const PERF_DIST_LABEL = i18n.translate( - 'xpack.observability.expView.fieldLabels.performanceDistribution', - { - defaultMessage: 'Performance distribution', - } -); - -export const CORE_WEB_VITALS_LABEL = i18n.translate( - 'xpack.observability.expView.fieldLabels.coreWebVitals', - { - defaultMessage: 'Core web vitals', - } -); - -export const DEVICE_DISTRIBUTION_LABEL = i18n.translate( - 'xpack.observability.expView.fieldLabels.deviceDistribution', - { - defaultMessage: 'Device distribution', - } -); - -export const SINGLE_METRIC_LABEL = i18n.translate( - 'xpack.observability.expView.fieldLabels.singleMetric', - { - defaultMessage: 'Single metric', - } -); - -export const HEATMAP_LABEL = i18n.translate('xpack.observability.expView.fieldLabels.heatMap', { - defaultMessage: 'Heatmap', -}); - -export const MOBILE_RESPONSE_LABEL = i18n.translate( - 'xpack.observability.expView.fieldLabels.mobileResponse', - { - defaultMessage: 'Mobile response', - } -); - -export const MEMORY_USAGE_LABEL = i18n.translate( - 'xpack.observability.expView.fieldLabels.memoryUsage', - { - defaultMessage: 'System memory usage', - } -); - -export const KPI_OVER_TIME_LABEL = i18n.translate( - 'xpack.observability.expView.fieldLabels.kpiOverTime', - { - defaultMessage: 'KPI over time', - } -); - -export const MONITORS_DURATION_LABEL = i18n.translate( - 'xpack.observability.expView.fieldLabels.monitorDurationLabel', - { - defaultMessage: 'Monitor duration', - } -); - -export const STEP_DURATION_LABEL = i18n.translate( - 'xpack.observability.expView.fieldLabels.stepDurationLabel', - { - defaultMessage: 'Step duration', - } -); - -export const STEP_NAME_LABEL = i18n.translate( - 'xpack.observability.expView.fieldLabels.stepNameLabel', - { - defaultMessage: 'Step name', - } -); - -export const WEB_APPLICATION_LABEL = i18n.translate( - 'xpack.observability.expView.fieldLabels.webApplication', - { - defaultMessage: 'Web Application', - } -); - -export const UP_LABEL = i18n.translate('xpack.observability.expView.fieldLabels.upPings', { - defaultMessage: 'Up Pings', -}); - -export const DOWN_LABEL = i18n.translate('xpack.observability.expView.fieldLabels.downPings', { - defaultMessage: 'Down Pings', -}); - -export const CARRIER_NAME = i18n.translate('xpack.observability.expView.fieldLabels.carrierName', { - defaultMessage: 'Carrier Name', -}); - -export const REQUEST_METHOD = i18n.translate( - 'xpack.observability.expView.fieldLabels.requestMethod', - { - defaultMessage: 'Request Method', - } -); - -export const CONNECTION_TYPE = i18n.translate( - 'xpack.observability.expView.fieldLabels.connectionType', - { - defaultMessage: 'Connection Type', - } -); -export const HOST_OS = i18n.translate('xpack.observability.expView.fieldLabels.hostOS', { - defaultMessage: 'Host OS', -}); - -export const SERVICE_VERSION = i18n.translate( - 'xpack.observability.expView.fieldLabels.serviceVersion', - { - defaultMessage: 'Service Version', - } -); - -export const OS_PLATFORM = i18n.translate('xpack.observability.expView.fieldLabels.osPlatform', { - defaultMessage: 'OS Platform', -}); - -export const DEVICE_MODEL = i18n.translate('xpack.observability.expView.fieldLabels.deviceModel', { - defaultMessage: 'Device Model', -}); - -export const CARRIER_LOCATION = i18n.translate( - 'xpack.observability.expView.fieldLabels.carrierLocation', - { - defaultMessage: 'Carrier Location', - } -); - -export const RESPONSE_LATENCY = i18n.translate( - 'xpack.observability.expView.fieldLabels.responseLatency', - { - defaultMessage: 'Latency', - } -); - -export const MOBILE_APP = i18n.translate('xpack.observability.expView.fieldLabels.mobileApp', { - defaultMessage: 'Mobile App', -}); - -export const SYSTEM_MEMORY_USAGE = i18n.translate( - 'xpack.observability.expView.fieldLabels.mobile.memoryUsage', - { - defaultMessage: 'System memory usage', - } -); - -export const CPU_USAGE = i18n.translate('xpack.observability.expView.fieldLabels.cpuUsage', { - defaultMessage: 'CPU usage', -}); - -export const SYSTEM_CPU_USAGE = i18n.translate( - 'xpack.observability.expView.fieldLabels.cpuUsage.system', - { - defaultMessage: 'System CPU usage', - } -); - -export const DOCKER_CPU_USAGE = i18n.translate( - 'xpack.observability.expView.fieldLabels.cpuUsage.docker', - { - defaultMessage: 'Docker CPU usage', - } -); - -export const K8S_POD_CPU_USAGE = i18n.translate( - 'xpack.observability.expView.fieldLabels.cpuUsage.k8sDocker', - { - defaultMessage: 'K8s pod CPU usage', - } -); - -export const TRANSACTIONS_PER_MINUTE = i18n.translate( - 'xpack.observability.expView.fieldLabels.transactionPerMinute', - { - defaultMessage: 'Throughput', - } -); - -export const NUMBER_OF_DEVICES = i18n.translate( - 'xpack.observability.expView.fieldLabels.numberOfDevices', - { - defaultMessage: 'Number of Devices', - } -); - -export const LOG_RATE = i18n.translate('xpack.observability.expView.fieldLabels.logRate', { - defaultMessage: 'Log rate', -}); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/constants/url_constants.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/constants/url_constants.ts deleted file mode 100644 index df2f31481016de..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/constants/url_constants.ts +++ /dev/null @@ -1,22 +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. - */ - -export enum URL_KEYS { - DATA_TYPE = 'dt', - OPERATION_TYPE = 'op', - SERIES_TYPE = 'st', - BREAK_DOWN = 'bd', - FILTERS = 'ft', - REPORT_DEFINITIONS = 'rdf', - SELECTED_METRIC = 'mt', - HIDDEN = 'h', - NAME = 'n', - COLOR = 'c', - SHOW_PERCENTILE_ANNOTATIONS = 'spa', -} - -export const ALL_VALUES_SELECTED = 'ALL_VALUES'; diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/default_configs.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/default_configs.ts deleted file mode 100644 index a9c9a525835ce3..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/default_configs.ts +++ /dev/null @@ -1,45 +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 type { DataView } from '@kbn/data-views-plugin/common'; -import { AppDataType, ReportViewType, SeriesConfig } from '../types'; -import { ReportConfigMap } from '../contexts/exploratory_view_config'; - -interface Props { - reportType: ReportViewType; - dataView: DataView; - dataType: AppDataType; - reportConfigMap: ReportConfigMap; - spaceId?: string; -} - -export const getDefaultConfigs = ({ - reportType, - dataType, - spaceId, - dataView, - reportConfigMap, -}: Props): SeriesConfig => { - let configResult: SeriesConfig | undefined; - - reportConfigMap[dataType]?.some((fn) => { - const config = fn({ dataView, spaceId }); - if (config.reportType === reportType) { - configResult = config; - } - return config.reportType === reportType; - }); - - if (!configResult) { - // not a user facing error, more of a dev focused error - throw new Error( - `No report config provided for dataType: ${dataType} and reportType: ${reportType}` - ); - } - - return configResult; -}; diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/exploratory_view_url.test.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/exploratory_view_url.test.ts deleted file mode 100644 index 9be8b1adeda86e..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/exploratory_view_url.test.ts +++ /dev/null @@ -1,62 +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 { createExploratoryViewUrl } from './exploratory_view_url'; -import type { AllSeries } from '../../../..'; - -describe('createExploratoryViewUrl', () => { - const testAllSeries = [ - { - dataType: 'synthetics', - seriesType: 'area', - selectedMetricField: 'monitor.duration.us', - time: { - from: 'now-15m', - to: 'now', - }, - breakdown: 'monitor.type', - reportDefinitions: { - 'monitor.name': [], - 'url.full': ['ALL_VALUES'], - }, - name: 'All monitors response duration', - }, - ] as AllSeries; - - describe('handles URL reserved chars', () => { - const urlReservedRegex = /[;,\/?:@&=+$#]/; - - it('encodes &', () => { - const seriesWithAmpersand = [{ ...testAllSeries[0], name: 'Name with &' }]; - const url = createExploratoryViewUrl({ - reportType: 'kpi-over-time', - allSeries: seriesWithAmpersand, - }); - - expect(urlReservedRegex.test(grabRisonQueryFromUrl(url))).toEqual(false); - }); - - it('encodes other reserved chars', () => { - const seriesWithAmpersand = [ - { - ...testAllSeries[0], - name: 'Name with URL reserved chars ;,/?:@&=+$#', - }, - ]; - const url = createExploratoryViewUrl({ - reportType: 'kpi-over-time', - allSeries: seriesWithAmpersand, - }); - - expect(urlReservedRegex.test(grabRisonQueryFromUrl(url))).toEqual(false); - }); - }); -}); - -function grabRisonQueryFromUrl(url: string) { - return url.split('sr=')[1]; -} diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/exploratory_view_url.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/exploratory_view_url.ts deleted file mode 100644 index 57b2b8e71049c7..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/exploratory_view_url.ts +++ /dev/null @@ -1,75 +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 rison from '@kbn/rison'; -import { URL_KEYS } from './constants/url_constants'; -import type { ReportViewType, SeriesUrl } from '../types'; -import type { AllSeries } from '../../../..'; -import type { AllShortSeries } from '../hooks/use_series_storage'; - -export function convertToShortUrl(series: SeriesUrl) { - const { - operationType, - seriesType, - breakdown, - filters, - reportDefinitions, - dataType, - selectedMetricField, - hidden, - name, - color, - ...restSeries - } = series; - - return { - [URL_KEYS.OPERATION_TYPE]: operationType, - [URL_KEYS.SERIES_TYPE]: seriesType, - [URL_KEYS.BREAK_DOWN]: breakdown, - [URL_KEYS.FILTERS]: filters, - [URL_KEYS.REPORT_DEFINITIONS]: reportDefinitions, - [URL_KEYS.DATA_TYPE]: dataType, - [URL_KEYS.SELECTED_METRIC]: selectedMetricField, - [URL_KEYS.HIDDEN]: hidden, - [URL_KEYS.NAME]: name, - [URL_KEYS.COLOR]: color ? escape(color) : undefined, - ...restSeries, - }; -} - -export function createExploratoryViewUrl( - { reportType, allSeries }: { reportType: ReportViewType; allSeries: AllSeries }, - baseHref = '', - appId = 'observability' -) { - const allShortSeries: AllShortSeries = allSeries.map((series) => convertToShortUrl(series)); - - return ( - baseHref + - `/app/${appId}/exploratory-view/#?reportType=${reportType}&sr=${encodeUriIfNeeded( - rison.encode(allShortSeries) - )}` - ); -} - -/** - * Encodes the uri if it contains characters (`/?@&=+#`). - * It doesn't consider `,` and `:` as they are part of [Rison]{@link https://www.npmjs.com/package/rison-node} syntax. - * - * @param uri Non encoded URI - */ -export function encodeUriIfNeeded(uri: string) { - if (!uri) { - return uri; - } - - if (/[\/?@&=+#]/.test(uri)) { - return encodeURIComponent(uri); - } - - return uri; -} diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/infra_logs/kpi_over_time_config.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/infra_logs/kpi_over_time_config.ts deleted file mode 100644 index a5f8faeed10626..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/infra_logs/kpi_over_time_config.ts +++ /dev/null @@ -1,58 +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 { i18n } from '@kbn/i18n'; -import { ConfigProps, SeriesConfig } from '../../types'; -import { FieldLabels, RECORDS_FIELD, ReportTypes } from '../constants'; -import { LOG_RATE as LOG_RATE_FIELD } from '../constants/field_names/infra_logs'; -import { LOG_RATE as LOG_RATE_LABEL } from '../constants/labels'; - -export function getLogsKPIConfig(configProps: ConfigProps): SeriesConfig { - return { - reportType: ReportTypes.KPI, - defaultSeriesType: 'bar', - seriesTypes: [], - xAxisColumn: { - label: i18n.translate('xpack.observability.exploratoryView.logs.logRateXAxisLabel', { - defaultMessage: 'Timestamp', - }), - dataType: 'date', - operationType: 'date_histogram', - sourceField: '@timestamp', - isBucketed: true, - scale: 'interval', - }, - yAxisColumns: [ - { - label: i18n.translate('xpack.observability.exploratoryView.logs.logRateYAxisLabel', { - defaultMessage: 'Log rate per minute', - }), - dataType: 'number', - operationType: 'count', - isBucketed: false, - scale: 'ratio', - sourceField: RECORDS_FIELD, - timeScale: 'm', - }, - ], - hasOperationType: false, - filterFields: ['agent.type', 'service.type', 'event.dataset'], - breakdownFields: ['agent.hostname', 'service.type', 'event.dataset'], - baseFilters: [], - definitionFields: ['agent.hostname', 'service.type', 'event.dataset'], - textDefinitionFields: ['message'], - metricOptions: [ - { - label: LOG_RATE_LABEL, - field: RECORDS_FIELD, - id: LOG_RATE_FIELD, - columnType: 'unique_count', - }, - ], - labels: { ...FieldLabels }, - }; -} diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/infra_metrics/field_formats.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/infra_metrics/field_formats.ts deleted file mode 100644 index fe473e948e5747..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/infra_metrics/field_formats.ts +++ /dev/null @@ -1,45 +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 { FieldFormat } from '../../types'; -import { - SYSTEM_CPU_PERCENTAGE_FIELD, - DOCKER_CPU_PERCENTAGE_FIELD, - K8S_POD_CPU_PERCENTAGE_FIELD, - SYSTEM_MEMORY_PERCENTAGE_FIELD, -} from '../constants/field_names/infra_metrics'; - -export const infraMetricsFieldFormats: FieldFormat[] = [ - { - field: SYSTEM_CPU_PERCENTAGE_FIELD, - format: { - id: 'percent', - params: {}, - }, - }, - { - field: DOCKER_CPU_PERCENTAGE_FIELD, - format: { - id: 'percent', - params: {}, - }, - }, - { - field: K8S_POD_CPU_PERCENTAGE_FIELD, - format: { - id: 'percent', - params: {}, - }, - }, - { - field: SYSTEM_MEMORY_PERCENTAGE_FIELD, - format: { - id: 'percent', - params: {}, - }, - }, -]; diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/infra_metrics/kpi_over_time_config.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/infra_metrics/kpi_over_time_config.ts deleted file mode 100644 index 56538d252fe3c6..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/infra_metrics/kpi_over_time_config.ts +++ /dev/null @@ -1,70 +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, SeriesConfig } from '../../types'; -import { FieldLabels, OPERATION_COLUMN, REPORT_METRIC_FIELD, ReportTypes } from '../constants'; -import { - SYSTEM_CPU_PERCENTAGE_FIELD, - DOCKER_CPU_PERCENTAGE_FIELD, - K8S_POD_CPU_PERCENTAGE_FIELD, - SYSTEM_MEMORY_PERCENTAGE_FIELD, -} from '../constants/field_names/infra_metrics'; -import { - DOCKER_CPU_USAGE, - K8S_POD_CPU_USAGE, - SYSTEM_CPU_USAGE, - SYSTEM_MEMORY_USAGE, -} from '../constants/labels'; - -export function getMetricsKPIConfig({ dataView }: ConfigProps): SeriesConfig { - return { - reportType: ReportTypes.KPI, - defaultSeriesType: 'area', - seriesTypes: [], - xAxisColumn: { - sourceField: '@timestamp', - }, - yAxisColumns: [ - { - sourceField: REPORT_METRIC_FIELD, - operationType: 'median', - }, - ], - hasOperationType: false, - filterFields: ['agent.type', 'service.type'], - breakdownFields: ['agent.hostname', 'service.type'], - baseFilters: [], - definitionFields: ['agent.hostname', 'service.type'], - metricOptions: [ - { - label: SYSTEM_CPU_USAGE, - field: SYSTEM_CPU_PERCENTAGE_FIELD, - id: SYSTEM_CPU_PERCENTAGE_FIELD, - columnType: OPERATION_COLUMN, - }, - { - label: SYSTEM_MEMORY_USAGE, - field: SYSTEM_MEMORY_PERCENTAGE_FIELD, - id: SYSTEM_MEMORY_PERCENTAGE_FIELD, - columnType: OPERATION_COLUMN, - }, - { - label: DOCKER_CPU_USAGE, - field: DOCKER_CPU_PERCENTAGE_FIELD, - id: DOCKER_CPU_PERCENTAGE_FIELD, - columnType: OPERATION_COLUMN, - }, - { - label: K8S_POD_CPU_USAGE, - field: K8S_POD_CPU_PERCENTAGE_FIELD, - id: K8S_POD_CPU_PERCENTAGE_FIELD, - columnType: OPERATION_COLUMN, - }, - ], - labels: { ...FieldLabels }, - }; -} diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/lens_attributes.test.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/lens_attributes.test.ts deleted file mode 100644 index bb36de888b407c..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/lens_attributes.test.ts +++ /dev/null @@ -1,685 +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 { LayerConfig, LensAttributes } from './lens_attributes'; -import { mockAppDataView, mockDataView } from '../rtl_helpers'; -import { getDefaultConfigs } from './default_configs'; -import { sampleAttribute } from './test_data/sample_attribute'; - -import { - LCP_FIELD, - TRANSACTION_DURATION, - USER_AGENT_NAME, -} from './constants/elasticsearch_fieldnames'; -import { buildExistsFilter, buildPhrasesFilter } from './utils'; -import { sampleAttributeKpi } from './test_data/sample_attribute_kpi'; -import { RECORDS_FIELD, REPORT_METRIC_FIELD, PERCENTILE_RANKS, ReportTypes } from './constants'; -import { obsvReportConfigMap } from '../obsv_exploratory_view'; -import { sampleAttributeWithReferenceLines } from './test_data/sample_attribute_with_reference_lines'; -import { lensPluginMock } from '@kbn/lens-plugin/public/mocks'; -import { FormulaPublicApi, XYState } from '@kbn/lens-plugin/public'; - -describe('Lens Attribute', () => { - mockAppDataView(); - - const reportViewConfig = getDefaultConfigs({ - reportType: 'data-distribution', - dataType: 'ux', - dataView: mockDataView, - reportConfigMap: obsvReportConfigMap, - }); - - reportViewConfig.baseFilters?.push(...buildExistsFilter('transaction.type', mockDataView)); - - let lnsAttr: LensAttributes; - - const layerConfig: LayerConfig = { - seriesConfig: reportViewConfig, - seriesType: 'line', - operationType: 'count', - dataView: mockDataView, - reportDefinitions: {}, - time: { from: 'now-15m', to: 'now' }, - color: 'green', - name: 'test-series', - selectedMetricField: TRANSACTION_DURATION, - }; - - const lensPluginMockStart = lensPluginMock.createStartContract(); - - let formulaHelper: FormulaPublicApi; - - beforeEach(async () => { - formulaHelper = (await lensPluginMockStart.stateHelperApi()).formula; - lnsAttr = new LensAttributes([layerConfig], reportViewConfig.reportType, formulaHelper); - }); - - it('should return expected json', function () { - expect(lnsAttr.getJSON()).toEqual(sampleAttribute); - }); - - it('should return expected json for kpi report type', function () { - const seriesConfigKpi = getDefaultConfigs({ - reportType: ReportTypes.KPI, - dataType: 'ux', - dataView: mockDataView, - reportConfigMap: obsvReportConfigMap, - }); - - const lnsAttrKpi = new LensAttributes( - [ - { - seriesConfig: seriesConfigKpi, - seriesType: 'line', - operationType: 'count', - dataView: mockDataView, - reportDefinitions: { 'service.name': ['elastic-co'] }, - time: { from: 'now-15m', to: 'now' }, - color: 'green', - name: 'test-series', - selectedMetricField: RECORDS_FIELD, - }, - ], - ReportTypes.KPI - ); - - expect(lnsAttrKpi.getJSON()).toEqual(sampleAttributeKpi); - }); - - it('should return expected json for percentile breakdowns', function () { - const seriesConfigKpi = getDefaultConfigs({ - reportType: ReportTypes.KPI, - dataType: 'ux', - dataView: mockDataView, - reportConfigMap: obsvReportConfigMap, - }); - - const lnsAttrKpi = new LensAttributes( - [ - { - filters: [], - seriesConfig: seriesConfigKpi, - time: { - from: 'now-1h', - to: 'now', - }, - dataView: mockDataView, - name: 'Page load time', - breakdown: 'percentile', - reportDefinitions: {}, - selectedMetricField: 'transaction.duration.us', - color: '#54b399', - }, - ], - ReportTypes.KPI - ); - - expect(lnsAttrKpi.getJSON().state.datasourceStates.formBased.layers.layer0.columns).toEqual({ - 'x-axis-column-layer0': { - dataType: 'date', - isBucketed: true, - label: '@timestamp', - operationType: 'date_histogram', - params: { - interval: 'auto', - includeEmptyRows: true, - }, - scale: 'interval', - sourceField: '@timestamp', - }, - ...PERCENTILE_RANKS.reduce((acc: Record, rank, index) => { - acc[`y-axis-column-${index === 0 ? 'layer' + index + '-0' : index}`] = { - customLabel: true, - dataType: 'number', - filter: { - language: 'kuery', - query: 'transaction.type: page-load and processor.event: transaction', - }, - isBucketed: false, - label: 'Page load time', - operationType: 'percentile', - params: { - percentile: Number(rank.slice(0, 2)), - }, - scale: 'ratio', - sourceField: 'transaction.duration.us', - }; - return acc; - }, {}), - }); - }); - - it('should return main y axis', function () { - expect(lnsAttr.getMainYAxis(layerConfig, 'layer0', '')).toEqual([ - { - customLabel: true, - dataType: 'number', - isBucketed: false, - label: 'test-series', - operationType: 'formula', - params: { - format: { - id: 'percent', - params: { - decimals: 0, - }, - }, - formula: 'count() / overall_sum(count())', - isFormulaBroken: false, - }, - references: ['y-axis-column-layer0X3'], - }, - ]); - }); - - it('should return expected field type', function () { - expect(JSON.stringify(lnsAttr.getFieldMeta('transaction.type', layerConfig))).toEqual( - JSON.stringify({ - fieldMeta: { - count: 0, - name: 'transaction.type', - type: 'string', - esTypes: ['keyword'], - scripted: false, - searchable: true, - aggregatable: true, - readFromDocValues: true, - }, - fieldName: 'transaction.type', - }) - ); - }); - - it('should return expected field type for custom field with default value', function () { - expect(JSON.stringify(lnsAttr.getFieldMeta(REPORT_METRIC_FIELD, layerConfig))).toEqual( - JSON.stringify({ - fieldMeta: { - count: 0, - name: 'transaction.duration.us', - type: 'number', - esTypes: ['long'], - scripted: false, - searchable: true, - aggregatable: true, - readFromDocValues: true, - }, - fieldName: 'transaction.duration.us', - columnLabel: 'Page load time', - showPercentileAnnotations: true, - }) - ); - }); - - it('should return expected field type for custom field with passed value', function () { - const layerConfig1: LayerConfig = { - seriesConfig: reportViewConfig, - seriesType: 'line', - operationType: 'count', - dataView: mockDataView, - reportDefinitions: { 'performance.metric': [LCP_FIELD] }, - time: { from: 'now-15m', to: 'now' }, - color: 'green', - name: 'test-series', - selectedMetricField: TRANSACTION_DURATION, - }; - - lnsAttr = new LensAttributes([layerConfig1], reportViewConfig.reportType, formulaHelper); - - expect(JSON.stringify(lnsAttr.getFieldMeta(REPORT_METRIC_FIELD, layerConfig1))).toEqual( - JSON.stringify({ - fieldMeta: { - count: 0, - name: TRANSACTION_DURATION, - type: 'number', - esTypes: ['long'], - scripted: false, - searchable: true, - aggregatable: true, - readFromDocValues: true, - }, - fieldName: TRANSACTION_DURATION, - columnLabel: 'Page load time', - showPercentileAnnotations: true, - }) - ); - }); - - it('should return expected number range column', function () { - expect(lnsAttr.getNumberRangeColumn('transaction.duration.us', reportViewConfig)).toEqual({ - dataType: 'number', - isBucketed: true, - label: 'Page load time', - operationType: 'range', - params: { - maxBars: 'auto', - ranges: [ - { - from: 0, - label: '', - to: 1000, - }, - ], - type: 'histogram', - }, - scale: 'interval', - sourceField: 'transaction.duration.us', - }); - }); - - it('should return expected number operation column', function () { - expect(lnsAttr.getNumberRangeColumn('transaction.duration.us', reportViewConfig)).toEqual({ - dataType: 'number', - isBucketed: true, - label: 'Page load time', - operationType: 'range', - params: { - maxBars: 'auto', - ranges: [ - { - from: 0, - label: '', - to: 1000, - }, - ], - type: 'histogram', - }, - scale: 'interval', - sourceField: 'transaction.duration.us', - }); - }); - - it('should return expected date histogram column', function () { - expect(lnsAttr.getDateHistogramColumn('@timestamp')).toEqual({ - dataType: 'date', - isBucketed: true, - label: '@timestamp', - operationType: 'date_histogram', - params: { - interval: 'auto', - includeEmptyRows: true, - }, - scale: 'interval', - sourceField: '@timestamp', - }); - }); - - it('should return main x axis', function () { - expect(lnsAttr.getXAxis(layerConfig, 'layer0')).toEqual({ - dataType: 'number', - isBucketed: true, - label: 'Page load time', - operationType: 'range', - params: { - maxBars: 'auto', - ranges: [ - { - from: 0, - label: '', - to: 1000, - }, - ], - type: 'histogram', - }, - scale: 'interval', - sourceField: 'transaction.duration.us', - }); - }); - - it('should hide y axis when there are multiple series', function () { - const lensAttrWithMultiSeries = new LensAttributes( - [layerConfig, layerConfig], - reportViewConfig.reportType, - formulaHelper - ).getJSON() as any; - expect(lensAttrWithMultiSeries.state.visualization.axisTitlesVisibilitySettings).toEqual({ - x: false, - yLeft: false, - yRight: false, - }); - }); - - it('should show y axis when there is a single series', function () { - const lensAttrWithMultiSeries = new LensAttributes( - [layerConfig], - reportViewConfig.reportType, - formulaHelper - ).getJSON() as any; - expect(lensAttrWithMultiSeries.state.visualization.axisTitlesVisibilitySettings).toEqual({ - x: false, - yLeft: true, - yRight: true, - }); - }); - - it('should return first layer', function () { - expect(lnsAttr.getLayers()).toEqual(sampleAttribute.state.datasourceStates.formBased.layers); - }); - - it('should return expected XYState', function () { - expect(lnsAttr.getXyState()).toEqual({ - axisTitlesVisibilitySettings: { x: false, yLeft: true, yRight: true }, - curveType: 'CURVE_MONOTONE_X', - fittingFunction: 'Linear', - gridlinesVisibilitySettings: { x: false, yLeft: true, yRight: true }, - layers: [ - { - accessors: ['y-axis-column-layer0-0'], - layerId: 'layer0', - layerType: 'data', - palette: undefined, - seriesType: 'line', - xAccessor: 'x-axis-column-layer0', - yConfig: [{ color: 'green', forAccessor: 'y-axis-column-layer0-0', axisMode: 'left' }], - }, - { - accessors: [ - '50th-percentile-reference-line-layer0-reference-lines', - '75th-percentile-reference-line-layer0-reference-lines', - '90th-percentile-reference-line-layer0-reference-lines', - '95th-percentile-reference-line-layer0-reference-lines', - '99th-percentile-reference-line-layer0-reference-lines', - ], - layerId: 'layer0-reference-lines', - layerType: 'referenceLine', - yConfig: [ - { - axisMode: 'bottom', - color: '#6092C0', - forAccessor: '50th-percentile-reference-line-layer0-reference-lines', - lineStyle: 'solid', - lineWidth: 2, - textVisibility: true, - }, - { - axisMode: 'bottom', - color: '#6092C0', - forAccessor: '75th-percentile-reference-line-layer0-reference-lines', - lineStyle: 'solid', - lineWidth: 2, - textVisibility: true, - }, - { - axisMode: 'bottom', - color: '#6092C0', - forAccessor: '90th-percentile-reference-line-layer0-reference-lines', - lineStyle: 'solid', - lineWidth: 2, - textVisibility: true, - }, - { - axisMode: 'bottom', - color: '#6092C0', - forAccessor: '95th-percentile-reference-line-layer0-reference-lines', - lineStyle: 'solid', - lineWidth: 2, - textVisibility: true, - }, - { - axisMode: 'bottom', - color: '#6092C0', - forAccessor: '99th-percentile-reference-line-layer0-reference-lines', - lineStyle: 'solid', - lineWidth: 2, - textVisibility: true, - }, - ], - }, - ], - legend: { - isVisible: true, - showSingleSeries: true, - position: 'right', - legendSize: 'auto', - shouldTruncate: false, - }, - preferredSeriesType: 'line', - tickLabelsVisibilitySettings: { x: true, yLeft: true, yRight: true }, - valueLabels: 'hide', - }); - }); - - it('should not use global filters when there is more than one series', function () { - const multiSeriesLensAttr = new LensAttributes( - [layerConfig, layerConfig], - reportViewConfig.reportType, - formulaHelper - ).getJSON(); - expect(multiSeriesLensAttr.state.query.query).toEqual('transaction.duration.us < 60000000'); - }); - - describe('Layer breakdowns', function () { - it('should return breakdown column', function () { - const layerConfig1: LayerConfig = { - seriesConfig: reportViewConfig, - seriesType: 'line', - operationType: 'count', - dataView: mockDataView, - reportDefinitions: { 'performance.metric': [LCP_FIELD] }, - breakdown: USER_AGENT_NAME, - time: { from: 'now-15m', to: 'now' }, - color: 'green', - name: 'test-series', - selectedMetricField: LCP_FIELD, - }; - - lnsAttr = new LensAttributes([layerConfig1], reportViewConfig.reportType, formulaHelper); - - lnsAttr.getBreakdownColumn({ - layerConfig: layerConfig1, - sourceField: USER_AGENT_NAME, - layerId: 'layer0', - }); - - expect((lnsAttr.visualization as XYState)?.layers).toEqual([ - { - accessors: ['y-axis-column-layer0-0'], - layerId: 'layer0', - layerType: 'data', - palette: undefined, - seriesType: 'line', - splitAccessor: 'breakdown-column-layer0', - xAccessor: 'x-axis-column-layer0', - yConfig: [{ color: 'green', forAccessor: 'y-axis-column-layer0-0', axisMode: 'left' }], - }, - ]); - - expect(lnsAttr.layers.layer0).toEqual({ - columnOrder: [ - 'breakdown-column-layer0', - 'x-axis-column-layer0', - 'y-axis-column-layer0-0', - 'y-axis-column-layer0X0', - 'y-axis-column-layer0X1', - 'y-axis-column-layer0X2', - 'y-axis-column-layer0X3', - ], - columns: { - 'breakdown-column-layer0': { - dataType: 'string', - isBucketed: true, - label: 'Browser family', - operationType: 'terms', - params: { - missingBucket: false, - orderAgg: { - dataType: 'number', - isBucketed: false, - label: 'Count of records', - operationType: 'count', - scale: 'ratio', - sourceField: '___records___', - }, - orderBy: { - type: 'custom', - }, - orderDirection: 'desc', - otherBucket: true, - size: 10, - }, - scale: 'ordinal', - sourceField: 'user_agent.name', - }, - 'x-axis-column-layer0': { - dataType: 'number', - isBucketed: true, - label: 'Largest contentful paint', - operationType: 'range', - params: { - maxBars: 'auto', - ranges: [ - { - from: 0, - label: '', - to: 1000, - }, - ], - type: 'histogram', - }, - scale: 'interval', - sourceField: LCP_FIELD, - }, - 'y-axis-column-layer0-0': { - customLabel: true, - dataType: 'number', - filter: { - language: 'kuery', - query: - 'transaction.type: page-load and processor.event: transaction and transaction.type : *', - }, - isBucketed: false, - label: 'test-series', - operationType: 'formula', - params: { - format: { - id: 'percent', - params: { - decimals: 0, - }, - }, - formula: - "count(kql='transaction.type: page-load and processor.event: transaction and transaction.type : *') / overall_sum(count(kql='transaction.type: page-load and processor.event: transaction and transaction.type : *'))", - isFormulaBroken: false, - }, - references: ['y-axis-column-layer0X3'], - }, - 'y-axis-column-layer0X0': { - customLabel: true, - dataType: 'number', - filter: { - language: 'kuery', - query: - 'transaction.type: page-load and processor.event: transaction and transaction.type : *', - }, - isBucketed: false, - label: 'Part of Pages loaded', - operationType: 'count', - params: { - emptyAsNull: false, - }, - scale: 'ratio', - sourceField: RECORDS_FIELD, - }, - 'y-axis-column-layer0X1': { - customLabel: true, - dataType: 'number', - filter: { - language: 'kuery', - query: - 'transaction.type: page-load and processor.event: transaction and transaction.type : *', - }, - isBucketed: false, - label: 'Part of Pages loaded', - operationType: 'count', - params: { - emptyAsNull: false, - }, - scale: 'ratio', - sourceField: RECORDS_FIELD, - }, - 'y-axis-column-layer0X2': { - customLabel: true, - dataType: 'number', - isBucketed: false, - label: 'Part of Pages loaded', - operationType: 'overall_sum', - references: ['y-axis-column-layer0X1'], - scale: 'ratio', - }, - 'y-axis-column-layer0X3': { - customLabel: true, - dataType: 'number', - isBucketed: false, - label: 'Part of Pages loaded', - operationType: 'math', - params: { - tinymathAst: { - args: ['y-axis-column-layer0X0', 'y-axis-column-layer0X2'], - location: { - max: 212, - min: 0, - }, - name: 'divide', - text: "count(kql='transaction.type: page-load and processor.event: transaction and transaction.type : *') / overall_sum(count(kql='transaction.type: page-load and processor.event: transaction and transaction.type : *'))", - type: 'function', - }, - }, - references: ['y-axis-column-layer0X0', 'y-axis-column-layer0X2'], - scale: 'ratio', - }, - }, - incompleteColumns: {}, - }); - }); - }); - - describe('Layer Filters', function () { - it('should return expected filters', function () { - reportViewConfig.baseFilters?.push( - ...buildPhrasesFilter('service.name', ['elastic', 'kibana'], mockDataView) - ); - - const layerConfig1: LayerConfig = { - seriesConfig: reportViewConfig, - seriesType: 'line', - operationType: 'count', - dataView: mockDataView, - reportDefinitions: { 'performance.metric': [LCP_FIELD] }, - time: { from: 'now-15m', to: 'now' }, - color: 'green', - name: 'test-series', - selectedMetricField: TRANSACTION_DURATION, - }; - - const filters = lnsAttr.getLayerFilters(layerConfig1, 2); - - expect(filters).toEqual( - '@timestamp >= now-15m and @timestamp <= now and transaction.type: page-load and processor.event: transaction and transaction.type : * and service.name: (elastic or kibana)' - ); - }); - }); - - describe('Reference line layers', function () { - it('should return expected reference lines', function () { - const layerConfig1: LayerConfig = { - seriesConfig: reportViewConfig, - seriesType: 'line', - dataView: mockDataView, - reportDefinitions: {}, - time: { from: 'now-15m', to: 'now' }, - color: 'green', - name: 'test-series', - selectedMetricField: TRANSACTION_DURATION, - }; - - lnsAttr = new LensAttributes([layerConfig1], reportViewConfig.reportType, formulaHelper); - - const attributes = lnsAttr.getJSON(); - - expect(attributes).toEqual(sampleAttributeWithReferenceLines); - }); - }); -}); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/lens_attributes.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/lens_attributes.ts deleted file mode 100644 index 72039beb2d1fdc..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/lens_attributes.ts +++ /dev/null @@ -1,1295 +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 { i18n } from '@kbn/i18n'; -import { capitalize } from 'lodash'; -import { ExistsFilter, isExistsFilter } from '@kbn/es-query'; -import { - AvgIndexPatternColumn, - CardinalityIndexPatternColumn, - CountIndexPatternColumn, - DataType, - DateHistogramIndexPatternColumn, - FieldBasedIndexPatternColumn, - FiltersIndexPatternColumn, - FormulaIndexPatternColumn, - FormulaPublicApi, - LastValueIndexPatternColumn, - MaxIndexPatternColumn, - MedianIndexPatternColumn, - MinIndexPatternColumn, - OperationMetadata, - OperationType, - PercentileIndexPatternColumn, - PersistedIndexPatternLayer, - RangeIndexPatternColumn, - SeriesType, - SumIndexPatternColumn, - TermsIndexPatternColumn, - TypedLensByValueInput, - XYCurveType, - XYState, - YAxisMode, - HeatmapVisualizationState, - MetricState, -} from '@kbn/lens-plugin/public'; -import type { DataView } from '@kbn/data-views-plugin/common'; -import { PersistableFilter } from '@kbn/lens-plugin/common'; -import { DataViewSpec } from '@kbn/data-views-plugin/common'; -import { LegendSize } from '@kbn/visualizations-plugin/common/constants'; -import { urlFiltersToKueryString } from '../utils/stringify_kueries'; -import { - FILTER_RECORDS, - FORMULA_COLUMN, - PERCENTILE, - PERCENTILE_RANKS, - RECORDS_FIELD, - RECORDS_PERCENTAGE_FIELD, - REPORT_METRIC_FIELD, - REPORT_METRIC_TIMESTAMP, - ReportTypes, - TERMS_COLUMN, - USE_BREAK_DOWN_COLUMN, -} from './constants'; -import { - ColumnFilter, - MetricOption, - ParamFilter, - SeriesConfig, - SupportedOperations, - TermColumnParamsOrderBy, - UrlFilter, - URLReportDefinition, -} from '../types'; -import { parseRelativeDate } from '../components/date_range_picker'; -import { getDistributionInPercentageColumn } from './lens_columns/overall_column'; - -export function getLayerReferenceName(layerId: string) { - return `indexpattern-datasource-layer-${layerId}`; -} - -export function buildNumberColumn(sourceField: string) { - return { - sourceField, - dataType: 'number' as DataType, - isBucketed: false, - scale: 'ratio' as OperationMetadata['scale'], - }; -} - -export function getPercentileParam(operationType: string) { - return { - percentile: Number(operationType.split('th')[0]), - }; -} - -export const parseCustomFieldName = ( - seriesConfig: SeriesConfig, - selectedMetricField?: string -): - | (Partial & { fieldName: string; columnLabel?: string; columnField?: string }) - | MetricOption[] => { - const metricOptions = seriesConfig.metricOptions ?? []; - - if (selectedMetricField) { - if (metricOptions) { - const currField = metricOptions.find((opt) => { - if ('items' in opt) { - return opt.id === selectedMetricField; - } else { - return opt.field === selectedMetricField || opt.id === selectedMetricField; - } - }); - - if (currField && 'items' in currField) { - const currFieldItem = currField.items.find( - (item) => item.id === selectedMetricField || item.field === selectedMetricField - ); - - if (currFieldItem) { - return { - ...(currFieldItem ?? {}), - fieldName: selectedMetricField, - columnLabel: currFieldItem?.label, - columnField: currFieldItem?.field, - }; - } - - return currField.items; - } - - return { - ...(currField ?? {}), - fieldName: currField?.field ?? selectedMetricField, - columnLabel: currField?.label, - columnField: currField?.field, - }; - } - } - - return { - fieldName: selectedMetricField!, - }; -}; - -type MainYAxisColType = ReturnType; - -export interface LayerConfig { - filters?: UrlFilter[]; - seriesConfig: SeriesConfig; - breakdown?: string; - seriesType?: SeriesType; - operationType?: OperationType; - reportDefinitions: URLReportDefinition; - time: { to: string; from: string }; - dataView: DataView; - selectedMetricField: string; - color: string; - name: string; - showPercentileAnnotations?: boolean; -} - -export class LensAttributes { - layers: Record; - visualization?: XYState | HeatmapVisualizationState | MetricState; - layerConfigs: LayerConfig[] = []; - isMultiSeries?: boolean; - seriesReferenceLines: Record< - string, - { - layerData: PersistedIndexPatternLayer; - layerState: XYState['layers']; - dataView: DataView; - } - >; - globalFilter?: { query: string; language: string }; - reportType: string; - lensFormulaHelper?: FormulaPublicApi; - - constructor( - layerConfigs: LayerConfig[], - reportType: string, - lensFormulaHelper?: FormulaPublicApi - ) { - this.layers = {}; - this.seriesReferenceLines = {}; - this.reportType = reportType; - this.lensFormulaHelper = lensFormulaHelper; - this.isMultiSeries = layerConfigs.length > 1; - - layerConfigs.forEach(({ seriesConfig, operationType }) => { - if (operationType && reportType !== ReportTypes.SINGLE_METRIC) { - seriesConfig.yAxisColumns.forEach((yAxisColumn) => { - if (typeof yAxisColumn.operationType !== undefined) { - yAxisColumn.operationType = - operationType as FieldBasedIndexPatternColumn['operationType']; - } - }); - } - }); - this.layerConfigs = layerConfigs; - this.globalFilter = this.getGlobalFilter(this.isMultiSeries); - - if (reportType === ReportTypes.SINGLE_METRIC) { - return; - } - - this.layers = this.getLayers(); - this.visualization = this.getXyState(); - } - - getGlobalFilter(isMultiSeries: boolean) { - if (isMultiSeries) { - return undefined; - } - const defaultLayerFilter = this.layerConfigs[0].seriesConfig.query - ? ` and ${this.layerConfigs[0].seriesConfig.query.query}` - : ''; - return { - query: `${this.getLayerFilters( - this.layerConfigs[0], - this.layerConfigs.length - )}${defaultLayerFilter}`, - language: 'kuery', - }; - } - - getBreakdownColumn({ - sourceField, - layerId, - layerConfig, - alphabeticOrder, - size = 10, - }: { - sourceField: string; - layerId: string; - layerConfig: LayerConfig; - alphabeticOrder?: boolean; - size?: number; - }): TermsIndexPatternColumn { - const { dataView, seriesConfig, selectedMetricField } = layerConfig; - - const fieldMeta = dataView.getFieldByName(sourceField); - const { metricOptions } = seriesConfig; - const { sourceField: yAxisSourceField } = seriesConfig.yAxisColumns[0]; - - const labels = seriesConfig.labels ?? {}; - - const isFormulaColumn = - Boolean( - metricOptions && - (metricOptions.find((option) => option.id === selectedMetricField) as MetricOption) - ?.formula - ) || yAxisSourceField === RECORDS_PERCENTAGE_FIELD; - - let orderBy: TermColumnParamsOrderBy = { - type: 'column', - columnId: `y-axis-column-${layerId}-0`, - }; - - if (isFormulaColumn) { - orderBy = { type: 'custom' }; - } else if (alphabeticOrder) { - orderBy = { type: 'alphabetical', fallback: true }; - } - - return { - sourceField, - label: labels[sourceField], - dataType: fieldMeta?.type as DataType, - operationType: 'terms', - scale: 'ordinal', - isBucketed: true, - params: { - orderBy, - size, - orderDirection: 'desc', - otherBucket: true, - missingBucket: false, - ...(isFormulaColumn - ? { - orderAgg: { - label: 'Count of records', - dataType: 'number', - operationType: 'count', - isBucketed: false, - scale: 'ratio', - sourceField: '___records___', - }, - } - : {}), - }, - }; - } - - getNumberRangeColumn( - sourceField: string, - seriesConfig: SeriesConfig, - label?: string - ): RangeIndexPatternColumn { - return { - sourceField, - label: seriesConfig.labels[sourceField] ?? label, - dataType: 'number', - operationType: 'range', - isBucketed: true, - scale: 'interval', - params: { - type: 'histogram', - ranges: [{ from: 0, to: 1000, label: '' }], - maxBars: 'auto', - }, - }; - } - - getFiltersColumn({ - label, - paramFilters, - }: { - paramFilters: ParamFilter[]; - label?: string; - }): FiltersIndexPatternColumn { - return { - label: label ?? 'Filters', - dataType: 'string', - operationType: 'filters', - scale: 'ordinal', - isBucketed: true, - params: { - filters: paramFilters, - }, - }; - } - - getNumberColumn({ - seriesConfig, - label, - sourceField, - columnType, - columnFilter, - operationType, - }: { - sourceField: string; - columnType?: string; - columnFilter?: ColumnFilter; - operationType?: SupportedOperations | 'last_value'; - label?: string; - seriesConfig: SeriesConfig; - }) { - if (columnType === 'operation' || operationType) { - if ( - operationType && - ['median', 'average', 'sum', 'min', 'max', 'unique_count'].includes(operationType) - ) { - return this.getNumberOperationColumn({ - sourceField, - operationType: operationType as SupportedOperations, - label, - seriesConfig, - columnFilter, - }); - } - if (operationType === 'last_value') { - return this.getLastValueOperationColumn({ - sourceField, - operationType, - label, - seriesConfig, - columnFilter, - }); - } - if (operationType?.includes('th')) { - return this.getPercentileNumberColumn(sourceField, operationType, seriesConfig!, label); - } - } - return this.getNumberRangeColumn(sourceField, seriesConfig!, label); - } - - getLastValueOperationColumn({ - sourceField, - label, - seriesConfig, - operationType, - columnFilter, - }: { - sourceField: string; - operationType: 'last_value'; - label?: string; - seriesConfig: SeriesConfig; - columnFilter?: ColumnFilter; - }): LastValueIndexPatternColumn { - return { - ...buildNumberColumn(sourceField), - operationType, - label: label || seriesConfig.labels[sourceField], - filter: columnFilter, - params: { - sortField: '@timestamp', - showArrayValues: false, - }, - }; - } - - getNumberOperationColumn({ - sourceField, - label, - seriesConfig, - operationType, - columnFilter, - }: { - sourceField: string; - operationType: SupportedOperations; - label?: string; - seriesConfig: SeriesConfig; - columnFilter?: ColumnFilter; - }): - | MinIndexPatternColumn - | MaxIndexPatternColumn - | AvgIndexPatternColumn - | MedianIndexPatternColumn - | SumIndexPatternColumn - | CardinalityIndexPatternColumn { - return { - ...buildNumberColumn(sourceField), - label: - label ?? - i18n.translate('xpack.observability.expView.columns.operation.label', { - defaultMessage: '{operationType} of {sourceField}', - values: { - sourceField: seriesConfig.labels[sourceField], - operationType: capitalize(operationType), - }, - }), - filter: columnFilter, - operationType, - params: - operationType === 'unique_count' - ? { - emptyAsNull: true, - } - : {}, - }; - } - - getPercentileBreakdowns( - layerConfig: LayerConfig, - layerId: string, - columnFilter?: string - ): Record { - const yAxisColumns = layerConfig.seriesConfig.yAxisColumns; - const { sourceField: mainSourceField, label: mainLabel } = yAxisColumns[0]; - const lensColumns: Record = - {}; - - // start at 1, because main y axis will have the first percentile breakdown - for (let i = 1; i < PERCENTILE_RANKS.length; i++) { - lensColumns[`y-axis-column-${i}`] = { - ...this.getColumnBasedOnType({ - sourceField: mainSourceField!, - operationType: PERCENTILE_RANKS[i] as SupportedOperations, - label: mainLabel, - layerConfig, - layerId, - colIndex: i, - }), - filter: { query: columnFilter || '', language: 'kuery' }, - }; - } - return lensColumns; - } - - getPercentileNumberColumn( - sourceField: string, - percentileValue: string, - seriesConfig: SeriesConfig, - label?: string - ): PercentileIndexPatternColumn { - return { - ...buildNumberColumn(sourceField), - label: - label ?? - i18n.translate('xpack.observability.expView.columns.label', { - defaultMessage: '{percentileValue} percentile of {sourceField}', - values: { sourceField: seriesConfig.labels[sourceField]?.toLowerCase(), percentileValue }, - }), - operationType: 'percentile', - params: getPercentileParam(percentileValue), - customLabel: true, - }; - } - - getDateHistogramColumn(sourceField: string): DateHistogramIndexPatternColumn { - return { - sourceField, - dataType: 'date', - isBucketed: true, - label: '@timestamp', - operationType: 'date_histogram', - params: { interval: 'auto', includeEmptyRows: true }, - scale: 'interval', - }; - } - - getTermsColumn(sourceField: string, label?: string): TermsIndexPatternColumn { - return { - operationType: 'terms', - sourceField, - label: 'Top values of ' + label || sourceField, - dataType: 'string', - isBucketed: true, - scale: 'ordinal', - params: { - size: 10, - orderBy: { - type: 'alphabetical', - fallback: false, - }, - orderDirection: 'desc', - }, - }; - } - - getXAxis(layerConfig: LayerConfig, layerId: string) { - const { xAxisColumn } = layerConfig.seriesConfig; - - let xSourceFiled = xAxisColumn?.sourceField; - - if (!xSourceFiled) { - return [xAxisColumn as LastValueIndexPatternColumn]; - } - - if (xSourceFiled === USE_BREAK_DOWN_COLUMN) { - return this.getBreakdownColumn({ - layerId, - layerConfig, - sourceField: layerConfig.breakdown || layerConfig.seriesConfig.breakdownFields[0], - }); - } - - if (xSourceFiled === REPORT_METRIC_FIELD) { - const { paramFilters } = this.getFieldMeta(xSourceFiled, layerConfig); - if (paramFilters) { - return this.getFiltersColumn({ paramFilters }); - } - } - - if (xSourceFiled === REPORT_METRIC_TIMESTAMP) { - const metricOption = parseCustomFieldName( - layerConfig.seriesConfig, - layerConfig.selectedMetricField - ); - - if (!Array.isArray(metricOption)) { - const { timestampField = '@timestamp' } = metricOption; - xSourceFiled = timestampField; - } - } - - return this.getColumnBasedOnType({ - layerConfig, - layerId, - label: xAxisColumn.label, - sourceField: xSourceFiled, - }); - } - - getColumnBasedOnType({ - sourceField, - label, - layerConfig, - operationType, - colIndex, - layerId, - metricOption, - }: { - sourceField: string; - metricOption?: MetricOption; - operationType?: SupportedOperations; - label?: string; - layerId: string; - layerConfig: LayerConfig; - colIndex?: number; - }) { - const { breakdown, seriesConfig } = layerConfig; - const fieldMetaInfo = this.getFieldMeta(sourceField, layerConfig, metricOption); - - const { - format, - formula, - fieldMeta, - columnType, - fieldName, - columnLabel, - timeScale, - columnFilters, - showPercentileAnnotations, - } = fieldMetaInfo; - - if (columnType === FORMULA_COLUMN) { - return getDistributionInPercentageColumn({ - layerId, - formula, - format, - label: columnLabel ?? label, - dataView: layerConfig.dataView, - lensFormulaHelper: this.lensFormulaHelper!, - }).main; - } - - if (showPercentileAnnotations) { - this.addThresholdLayer(fieldName, layerId, layerConfig); - } - - const { type: fieldType } = fieldMeta ?? {}; - - if (columnType === TERMS_COLUMN) { - return this.getTermsColumn(fieldName, label || columnLabel); - } - - if (fieldName === RECORDS_FIELD || columnType === FILTER_RECORDS) { - return this.getRecordsColumn( - label || columnLabel, - colIndex !== undefined ? columnFilters?.[colIndex] : undefined, - timeScale - ); - } - - if (fieldType === 'date') { - return this.getDateHistogramColumn(fieldName); - } - - if (fieldType === 'number' && breakdown === PERCENTILE) { - return { - ...this.getPercentileNumberColumn( - fieldName, - operationType || PERCENTILE_RANKS[0], - seriesConfig!, - label || columnLabel - ), - filter: colIndex !== undefined ? columnFilters?.[colIndex] : undefined, - }; - } - - if (fieldType === 'number') { - return this.getNumberColumn({ - sourceField: fieldName, - columnType, - columnFilter: columnFilters?.[0], - operationType, - label: label || columnLabel, - seriesConfig: layerConfig.seriesConfig, - }); - } - if (operationType === 'unique_count' || fieldType === 'string') { - return this.getNumberOperationColumn({ - sourceField: fieldName, - operationType: 'unique_count', - label: label || columnLabel, - seriesConfig: layerConfig.seriesConfig, - columnFilter: columnFilters?.[0], - }); - } - - // FIXME review my approach again - return this.getDateHistogramColumn(fieldName); - } - - getCustomFieldName({ - sourceField, - layerConfig, - }: { - sourceField: string; - layerConfig: LayerConfig; - }) { - return parseCustomFieldName(layerConfig.seriesConfig, sourceField); - } - - getFieldMeta(sourceField: string, layerConfig: LayerConfig, metricOpt?: MetricOption) { - if (sourceField === REPORT_METRIC_FIELD) { - const metricOption = metricOpt - ? { - ...metricOpt, - columnLabel: metricOpt.label, - columnField: metricOpt.field, - fieldName: metricOpt.field!, - } - : parseCustomFieldName(layerConfig.seriesConfig, layerConfig.selectedMetricField); - - if (Array.isArray(metricOption)) { - return { - fieldName: sourceField, - items: metricOption, - }; - } - - const { - palette, - fieldName, - columnType, - columnLabel, - columnFilters, - timeScale, - paramFilters, - showPercentileAnnotations, - formula, - format, - } = metricOption; - const fieldMeta = layerConfig.dataView.getFieldByName(fieldName!); - return { - format, - formula, - palette, - fieldMeta, - fieldName, - columnType, - columnLabel, - columnFilters, - timeScale, - paramFilters, - showPercentileAnnotations: - layerConfig.showPercentileAnnotations ?? showPercentileAnnotations, - }; - } else { - const fieldMeta = layerConfig.dataView.getFieldByName(sourceField); - - return { fieldMeta, fieldName: sourceField }; - } - } - - getMainYAxis(layerConfig: LayerConfig, layerId: string, columnFilter: string) { - const { breakdown } = layerConfig; - const { - sourceField, - operationType, - label: colLabel, - timeScale, - } = layerConfig.seriesConfig.yAxisColumns[0]; - - let label = layerConfig.name || colLabel; - - if (layerConfig.seriesConfig.reportType === ReportTypes.CORE_WEB_VITAL) { - label = colLabel; - } - - if (sourceField === RECORDS_PERCENTAGE_FIELD) { - return [ - getDistributionInPercentageColumn({ - label, - layerId, - columnFilter, - dataView: layerConfig.dataView, - lensFormulaHelper: this.lensFormulaHelper!, - }).main, - ]; - } - - if (sourceField === RECORDS_FIELD || !sourceField) { - return [this.getRecordsColumn(label, undefined, timeScale)]; - } - - const fieldMetaInfo = this.getFieldMeta(sourceField, layerConfig); - - if (!fieldMetaInfo.fieldMeta && fieldMetaInfo.fieldName === RECORDS_FIELD) { - return [this.getRecordsColumn(label, fieldMetaInfo.columnFilters?.[0], timeScale)]; - } - - if ('items' in fieldMetaInfo) { - const { items } = fieldMetaInfo; - - return items?.map((item, index) => { - return this.getColumnBasedOnType({ - layerConfig, - layerId, - label: item.label, - sourceField: REPORT_METRIC_FIELD, - metricOption: item, - operationType: operationType as SupportedOperations, - }); - }); - } - - return [ - this.getColumnBasedOnType({ - sourceField, - label, - layerConfig, - colIndex: 0, - operationType: (breakdown === PERCENTILE - ? PERCENTILE_RANKS[0] - : operationType) as SupportedOperations, - layerId, - }), - ]; - } - - getChildYAxises( - layerConfig: LayerConfig, - layerId: string, - columnFilter?: string, - forAccessorsKeys?: boolean - ) { - const { breakdown } = layerConfig; - const lensColumns: Record< - string, - FieldBasedIndexPatternColumn | SumIndexPatternColumn | FormulaIndexPatternColumn - > = {}; - const yAxisColumns = layerConfig.seriesConfig.yAxisColumns; - const { sourceField: mainSourceField, label: mainLabel } = yAxisColumns[0]; - - if (mainSourceField === RECORDS_PERCENTAGE_FIELD && layerId && !forAccessorsKeys) { - return getDistributionInPercentageColumn({ - label: mainLabel, - layerId, - columnFilter, - dataView: layerConfig.dataView, - lensFormulaHelper: this.lensFormulaHelper!, - }).supportingColumns; - } - - if (mainSourceField && !forAccessorsKeys) { - const { columnLabel, formula, columnType } = this.getFieldMeta(mainSourceField, layerConfig); - - if (columnType === FORMULA_COLUMN) { - return getDistributionInPercentageColumn({ - label: columnLabel, - layerId, - formula, - dataView: layerConfig.dataView, - lensFormulaHelper: this.lensFormulaHelper!, - }).supportingColumns; - } - } - - if (yAxisColumns.length === 1 && breakdown === PERCENTILE) { - return this.getPercentileBreakdowns(layerConfig, layerId, columnFilter); - } - - if (yAxisColumns.length === 1) { - return lensColumns; - } - - // starting from 1 index since 0 column is used as main column - for (let i = 1; i < yAxisColumns.length; i++) { - const { sourceField, operationType, label } = yAxisColumns[i]; - - lensColumns[`y-axis-column-${i}`] = this.getColumnBasedOnType({ - sourceField: sourceField!, - operationType: operationType as SupportedOperations, - label, - layerConfig, - colIndex: i, - layerId, - }); - } - return lensColumns; - } - - getRecordsColumn( - label?: string, - columnFilter?: ColumnFilter, - timeScale?: string - ): CountIndexPatternColumn { - return { - dataType: 'number', - isBucketed: false, - label: label || 'Count of records', - operationType: 'count', - scale: 'ratio', - sourceField: RECORDS_FIELD, - filter: columnFilter, - ...(timeScale ? { timeScale } : {}), - } as CountIndexPatternColumn; - } - - getLayerFilters(layerConfig: LayerConfig, totalLayers: number) { - const { - filters, - time, - seriesConfig: { baseFilters: layerFilters, reportType }, - } = layerConfig; - let baseFilters = ''; - - if (reportType !== ReportTypes.KPI && totalLayers > 1 && time) { - // for kpi over time, we don't need to add time range filters - // since those are essentially plotted along the x-axis - baseFilters += `@timestamp >= ${time.from} and @timestamp <= ${time.to}`; - } - - layerFilters?.forEach((filter: PersistableFilter | ExistsFilter) => { - const qFilter = filter as PersistableFilter; - if (qFilter.query?.match_phrase) { - const fieldName = Object.keys(qFilter.query.match_phrase)[0]; - const kql = `${fieldName}: ${qFilter.query.match_phrase[fieldName]}`; - if (baseFilters.length > 0) { - baseFilters += ` and ${kql}`; - } else { - baseFilters += kql; - } - } - if (qFilter.query?.bool?.should) { - const values: string[] = []; - let fieldName = ''; - qFilter.query?.bool.should.forEach((ft: any) => { - if (ft.match_phrase) { - fieldName = Object.keys(ft.match_phrase)[0]; - values.push(ft.match_phrase[fieldName]); - } - }); - - const kueryString = `${fieldName}: (${values.join(' or ')})`; - - if (baseFilters.length > 0) { - baseFilters += ` and ${kueryString}`; - } else { - baseFilters += kueryString; - } - } - const existFilter = filter as ExistsFilter; - - if (isExistsFilter(existFilter)) { - const fieldName = existFilter.query.exists?.field; - const kql = `${fieldName} : *`; - if (baseFilters.length > 0) { - baseFilters += ` and ${kql}`; - } else { - baseFilters += kql; - } - } - }); - - const urlFilters = urlFiltersToKueryString(filters ?? []); - - if (!baseFilters) { - return urlFilters; - } - if (!urlFilters) { - return baseFilters; - } - return `${urlFilters} and ${baseFilters}`; - } - - getTimeShift(mainLayerConfig: LayerConfig, layerConfig: LayerConfig, index: number) { - if ( - index === 0 || - mainLayerConfig.seriesConfig.reportType !== ReportTypes.KPI || - !layerConfig.time - ) { - return null; - } - - const { - time: { from: mainFrom }, - } = mainLayerConfig; - - const { - time: { from }, - } = layerConfig; - - const parsedMainFrom = parseRelativeDate(mainFrom); - const parsedFrom = parseRelativeDate(from); - - const inDays = - parsedMainFrom && parsedFrom ? Math.abs(parsedMainFrom.diff(parsedFrom, 'days')) : 0; - if (inDays > 1) { - return inDays + 'd'; - } - - const inHours = - parsedMainFrom && parsedFrom ? Math.abs(parsedMainFrom?.diff(parsedFrom, 'hours')) : 0; - if (inHours === 0) { - return null; - } - return inHours + 'h'; - } - - getLayers() { - const layers: Record = {}; - const layerConfigs = this.layerConfigs; - - layerConfigs.forEach((layerConfig, index) => { - const { breakdown, seriesConfig } = layerConfig; - - const layerId = `layer${index}`; - const columnFilter = this.getLayerFilters(layerConfig, layerConfigs.length); - const timeShift = this.getTimeShift(this.layerConfigs[0], layerConfig, index); - const mainYAxises = this.getMainYAxis(layerConfig, layerId, columnFilter); - const { sourceField } = seriesConfig.xAxisColumn; - - const hasBreakdownColumn = - // do nothing since this will be used a x axis source - Boolean(breakdown && sourceField !== USE_BREAK_DOWN_COLUMN && breakdown !== PERCENTILE); - - layers[layerId] = this.getDataLayer({ - layerId, - layerConfig, - mainYAxises, - columnFilter, - timeShift, - hasBreakdownColumn, - }); - }); - - Object.entries(this.seriesReferenceLines).forEach(([id, { layerData }]) => { - layers[id] = layerData; - }); - - return layers; - } - - getDataLayer({ - hasBreakdownColumn, - layerId, - layerConfig, - columnFilter, - mainYAxises, - timeShift, - }: { - hasBreakdownColumn: boolean; - layerId: string; - timeShift: string | null; - layerConfig: LayerConfig; - columnFilter: string; - mainYAxises: MainYAxisColType; - }) { - const allYAxisColumns: Record = {}; - - mainYAxises?.forEach((mainYAxis, index) => { - let filterQuery = columnFilter || mainYAxis.filter?.query; - - if (columnFilter && mainYAxis.filter?.query) { - filterQuery = `${columnFilter} and ${mainYAxis.filter.query}`; - } - - const label = timeShift ? `${mainYAxis.label}(${timeShift})` : mainYAxis.label; - - allYAxisColumns[`y-axis-column-${layerId}-${index}`] = { - ...mainYAxis, - label, - filter: { - query: filterQuery ?? '', - language: 'kuery', - }, - ...(timeShift ? { timeShift } : {}), - }; - }); - - const { breakdown } = layerConfig; - - const breakDownColumn = hasBreakdownColumn - ? this.getBreakdownColumn({ - layerId, - sourceField: breakdown!, - layerConfig, - }) - : null; - - const xAxises = { - [`x-axis-column-${layerId}`]: this.getXAxis(layerConfig, layerId), - }; - - return { - columnOrder: [ - ...(hasBreakdownColumn ? [`breakdown-column-${layerId}`] : []), - ...Object.keys(xAxises), - ...Object.keys(allYAxisColumns), - ...Object.keys(this.getChildYAxises(layerConfig, layerId, columnFilter)), - ], - columns: { - ...xAxises, - ...allYAxisColumns, - ...(hasBreakdownColumn - ? { - [`breakdown-column-${layerId}`]: breakDownColumn!, - } - : {}), - ...this.getChildYAxises(layerConfig, layerId, columnFilter), - }, - incompleteColumns: {}, - }; - } - - getXyState(): XYState { - return { - legend: { - isVisible: true, - showSingleSeries: true, - position: 'right', - legendSize: LegendSize.AUTO, - shouldTruncate: false, - }, - valueLabels: 'hide', - fittingFunction: 'Linear', - curveType: 'CURVE_MONOTONE_X' as XYCurveType, - axisTitlesVisibilitySettings: { - x: false, - yLeft: !this.isMultiSeries, - yRight: !this.isMultiSeries, - }, - tickLabelsVisibilitySettings: { x: true, yLeft: true, yRight: true }, - gridlinesVisibilitySettings: { x: false, yLeft: true, yRight: true }, - preferredSeriesType: 'line', - layers: this.getDataLayers(), - ...(this.layerConfigs[0].seriesConfig.yTitle - ? { yTitle: this.layerConfigs[0].seriesConfig.yTitle } - : {}), - }; - } - - getDataLayers(): XYState['layers'] { - const dataLayers = this.layerConfigs.map((layerConfig, index) => { - const { sourceField } = layerConfig.seriesConfig.yAxisColumns[0]; - - let palette = layerConfig.seriesConfig.palette; - - if (sourceField) { - const fieldMeta = this.getFieldMeta(sourceField, layerConfig); - if (fieldMeta.palette) { - palette = fieldMeta.palette; - } - } - - const layerId = `layer${index}`; - - const columnFilter = this.getLayerFilters(layerConfig, this.layerConfigs.length); - - const mainYAxises = this.getMainYAxis(layerConfig, layerId, columnFilter) ?? []; - - return { - accessors: [ - ...mainYAxises.map((key, yIndex) => `y-axis-column-${layerId}-${yIndex}`), - ...Object.keys(this.getChildYAxises(layerConfig, `layer${index}`, undefined, true)), - ], - layerId: `layer${index}`, - layerType: 'data' as any, - seriesType: layerConfig.seriesType || layerConfig.seriesConfig.defaultSeriesType, - palette: palette ?? layerConfig.seriesConfig.palette, - yConfig: layerConfig.seriesConfig.yConfig || [ - { - forAccessor: `y-axis-column-layer${index}-0`, - color: layerConfig.color, - /* if the fields format matches the field format of the first layer, use the default y axis (right) - * if not, use the secondary y axis (left) */ - axisMode: - layerConfig.dataView.fieldFormatMap[layerConfig.selectedMetricField]?.id === - this.layerConfigs[0].dataView.fieldFormatMap[this.layerConfigs[0].selectedMetricField] - ?.id - ? ('left' as YAxisMode) - : ('right' as YAxisMode), - }, - ], - xAccessor: `x-axis-column-layer${index}`, - ...(layerConfig.breakdown && - layerConfig.breakdown !== PERCENTILE && - layerConfig.seriesConfig.xAxisColumn.sourceField !== USE_BREAK_DOWN_COLUMN - ? { splitAccessor: `breakdown-column-layer${index}` } - : {}), - ...(this.layerConfigs[0].seriesConfig.yTitle - ? { yTitle: this.layerConfigs[0].seriesConfig.yTitle } - : {}), - }; - }); - - const referenceLineLayers: XYState['layers'] = []; - - Object.entries(this.seriesReferenceLines).forEach(([_id, { layerState }]) => { - referenceLineLayers.push(layerState[0]); - }); - - return [...dataLayers, ...referenceLineLayers]; - } - - addThresholdLayer(fieldName: string, layerId: string, { seriesConfig, dataView }: LayerConfig) { - const referenceLineLayerId = `${layerId}-reference-lines`; - - const referenceLineColumns = this.getThresholdColumns( - fieldName, - referenceLineLayerId, - seriesConfig - ); - - const layerData = { - columnOrder: Object.keys(referenceLineColumns), - columns: referenceLineColumns, - incompleteColumns: {}, - }; - - const layerState = this.getThresholdLayer(fieldName, referenceLineLayerId, seriesConfig); - - this.seriesReferenceLines[referenceLineLayerId] = { layerData, layerState, dataView }; - } - - getThresholdLayer( - fieldName: string, - referenceLineLayerId: string, - seriesConfig: SeriesConfig - ): XYState['layers'] { - const columns = this.getThresholdColumns(fieldName, referenceLineLayerId, seriesConfig); - - return [ - { - layerId: referenceLineLayerId, - accessors: Object.keys(columns), - layerType: 'referenceLine', - yConfig: Object.keys(columns).map((columnId) => ({ - axisMode: 'bottom', - color: '#6092C0', - forAccessor: columnId, - lineStyle: 'solid', - lineWidth: 2, - textVisibility: true, - })), - }, - ]; - } - - getThresholdColumns(fieldName: string, layerId: string, seriesConfig: SeriesConfig) { - const referenceLines = ['50th', '75th', '90th', '95th', '99th']; - const columns: Record = {}; - - referenceLines.forEach((referenceLine) => { - columns[`${referenceLine}-percentile-reference-line-${layerId}`] = { - ...this.getPercentileNumberColumn(fieldName, referenceLine, seriesConfig), - label: referenceLine, - }; - }); - - return columns; - } - - getReferences() { - const uniqueIndexPatternsIds = Array.from( - new Set([...this.layerConfigs.map(({ dataView }) => dataView.id!)]) - ); - - const adHocDataViews: Record = {}; - - const referenceLineIndexReferences = Object.entries(this.seriesReferenceLines).map( - ([id, { dataView }]) => { - adHocDataViews[dataView.id!] = dataView.toSpec(false); - return { - id: dataView.id!, - name: getLayerReferenceName(id), - type: 'index-pattern', - }; - } - ); - - const internalReferences = [ - ...uniqueIndexPatternsIds.map((dataViewId) => ({ - id: dataViewId, - name: 'indexpattern-datasource-current-indexpattern', - type: 'index-pattern', - })), - ...this.layerConfigs.map(({ dataView }, index) => { - adHocDataViews[dataView.id!] = dataView.toSpec(false); - - return { - id: dataView.id!, - name: getLayerReferenceName(`layer${index}`), - type: 'index-pattern', - }; - }), - ...referenceLineIndexReferences, - ]; - - Object.entries(this.seriesReferenceLines).map(([id, { dataView }]) => ({ - id: dataView.id!, - name: getLayerReferenceName(id), - type: 'index-pattern', - })); - - return { internalReferences, adHocDataViews }; - } - - getJSON( - visualizationType: 'lnsXY' | 'lnsLegacyMetric' | 'lnsHeatmap' = 'lnsXY', - lastRefresh?: number - ): TypedLensByValueInput['attributes'] { - const query = this.globalFilter || this.layerConfigs[0].seriesConfig.query; - - const { internalReferences, adHocDataViews } = this.getReferences(); - - return { - title: 'Prefilled from exploratory view app', - description: lastRefresh ? `Last refreshed at ${new Date(lastRefresh).toISOString()}` : '', - visualizationType, - references: [], - state: { - internalReferences, - adHocDataViews, - datasourceStates: { - formBased: { - layers: this.layers, - }, - }, - visualization: this.visualization, - query: query || { query: '', language: 'kuery' }, - filters: [], - }, - }; - } -} diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/lens_attributes/heatmap_attributes.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/lens_attributes/heatmap_attributes.ts deleted file mode 100644 index d62bd8684b48cf..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/lens_attributes/heatmap_attributes.ts +++ /dev/null @@ -1,96 +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 { FormulaPublicApi, HeatmapVisualizationState } from '@kbn/lens-plugin/public'; - -import { euiPaletteNegative } from '@elastic/eui'; -import { ColorStop } from '@kbn/coloring'; -import { LayerConfig } from '../lens_attributes'; -import { SingleMetricLensAttributes } from './single_metric_attributes'; - -export class HeatMapLensAttributes extends SingleMetricLensAttributes { - xColumnId: string; - layerId: string; - breakDownColumnId: string; - - constructor( - layerConfigs: LayerConfig[], - reportType: string, - lensFormulaHelper: FormulaPublicApi - ) { - super(layerConfigs, reportType, lensFormulaHelper); - - this.xColumnId = 'layer-0-column-x-1'; - this.breakDownColumnId = 'layer-0-breakdown-column'; - this.layerId = 'layer0'; - const layer0 = this.getSingleMetricLayer()!; - - layer0.columns[this.xColumnId] = this.getDateHistogramColumn('@timestamp'); - - let columnOrder = [this.xColumnId]; - const layerConfig = layerConfigs[0]; - - if (layerConfig.breakdown) { - columnOrder = [this.breakDownColumnId, ...columnOrder]; - layer0.columns[this.breakDownColumnId] = this.getBreakdownColumn({ - layerConfig, - sourceField: layerConfig.breakdown, - layerId: this.layerId, - alphabeticOrder: true, - }); - } - - layer0.columnOrder = [...columnOrder, ...layer0.columnOrder]; - - this.layers = { layer0 }; - - this.visualization = this.getHeatmapState(); - } - - getHeatmapState() { - const negativePalette = euiPaletteNegative(5); - const layerConfig = this.layerConfigs[0]; - - return { - shape: 'heatmap', - layerId: this.layerId, - layerType: 'data', - legend: { - isVisible: true, - position: 'right', - type: 'heatmap_legend', - }, - gridConfig: { - type: 'heatmap_grid', - isCellLabelVisible: false, - isYAxisLabelVisible: true, - isXAxisLabelVisible: true, - isYAxisTitleVisible: false, - isXAxisTitleVisible: false, - xTitle: '', - }, - valueAccessor: this.columnId, - xAccessor: this.xColumnId, - yAccessor: layerConfig.breakdown ? this.breakDownColumnId : undefined, - palette: { - type: 'palette', - name: 'negative', - params: { - name: 'negative', - continuity: 'above', - reverse: false, - stops: negativePalette.map((nColor, ind) => ({ - color: nColor, - stop: ind === 0 ? 1 : ind * 20, - })) as ColorStop[], - rangeMin: 0, - }, - accessor: this.columnId, - }, - } as HeatmapVisualizationState; - } -} diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/lens_attributes/single_metric_attributes.test.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/lens_attributes/single_metric_attributes.test.ts deleted file mode 100644 index 16f35bab1f1c59..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/lens_attributes/single_metric_attributes.test.ts +++ /dev/null @@ -1,213 +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 { SingleMetricLensAttributes } from './single_metric_attributes'; -import { ReportTypes } from '../../../../..'; -import { mockAppDataView, mockDataView } from '../../rtl_helpers'; -import { getDefaultConfigs } from '../default_configs'; -import { obsvReportConfigMap } from '../../obsv_exploratory_view'; -import { buildExistsFilter } from '../utils'; -import { LensAttributes } from '../lens_attributes'; -import { TRANSACTION_DURATION } from '../constants/elasticsearch_fieldnames'; -import { lensPluginMock } from '@kbn/lens-plugin/public/mocks'; -import { FormulaPublicApi } from '@kbn/lens-plugin/public'; -import { sampleMetricFormulaAttribute } from '../test_data/test_formula_metric_attribute'; -import { DataTypes } from '../..'; - -describe('SingleMetricAttributes', () => { - mockAppDataView(); - - const reportViewConfig = getDefaultConfigs({ - reportType: ReportTypes.SINGLE_METRIC, - dataType: 'ux', - dataView: mockDataView, - reportConfigMap: obsvReportConfigMap, - }); - - reportViewConfig.baseFilters?.push(...buildExistsFilter('transaction.type', mockDataView)); - - let lnsAttr: LensAttributes; - - const layerConfig: any = { - seriesConfig: reportViewConfig, - operationType: 'median', - dataView: mockDataView, - reportDefinitions: {}, - time: { from: 'now-15m', to: 'now' }, - name: 'Page load time', - selectedMetricField: TRANSACTION_DURATION, - }; - - const lensPluginMockStart = lensPluginMock.createStartContract(); - - let formulaHelper: FormulaPublicApi; - - beforeEach(async () => { - formulaHelper = (await lensPluginMockStart.stateHelperApi()).formula; - lnsAttr = new SingleMetricLensAttributes( - [layerConfig], - ReportTypes.SINGLE_METRIC, - formulaHelper - ); - }); - - it('returns attributes as expected', () => { - const jsonAttr = lnsAttr.getJSON('lnsLegacyMetric'); - expect(jsonAttr).toEqual({ - description: '', - references: [], - state: { - adHocDataViews: { [mockDataView.title]: mockDataView.toSpec(false) }, - internalReferences: [ - { - id: 'apm-*', - name: 'indexpattern-datasource-current-indexpattern', - type: 'index-pattern', - }, - { - id: 'apm-*', - name: 'indexpattern-datasource-layer-layer0', - type: 'index-pattern', - }, - ], - datasourceStates: { - formBased: { - layers: { - layer0: { - columnOrder: ['layer-0-column-1'], - columns: { - 'layer-0-column-1': { - dataType: 'number', - isBucketed: false, - label: 'Page load time', - operationType: 'median', - scale: 'ratio', - sourceField: 'transaction.duration.us', - params: { - emptyAsNull: true, - }, - }, - }, - incompleteColumns: {}, - }, - }, - }, - }, - filters: [], - query: { - language: 'kuery', - query: - 'transaction.type: page-load and processor.event: transaction and transaction.type : *', - }, - visualization: { - accessor: 'layer-0-column-1', - layerId: 'layer0', - layerType: 'data', - size: 's', - }, - }, - title: 'Prefilled from exploratory view app', - visualizationType: 'lnsLegacyMetric', - }); - }); - - it('returns attributes as expected for percentile operation', () => { - layerConfig.operationType = '99th'; - lnsAttr = new SingleMetricLensAttributes( - [layerConfig], - ReportTypes.SINGLE_METRIC, - formulaHelper - ); - - const jsonAttr = lnsAttr.getJSON('lnsLegacyMetric'); - expect(jsonAttr).toEqual({ - description: '', - references: [], - state: { - adHocDataViews: { [mockDataView.title]: mockDataView.toSpec(false) }, - internalReferences: [ - { - id: 'apm-*', - name: 'indexpattern-datasource-current-indexpattern', - type: 'index-pattern', - }, - { - id: 'apm-*', - name: 'indexpattern-datasource-layer-layer0', - type: 'index-pattern', - }, - ], - datasourceStates: { - formBased: { - layers: { - layer0: { - columnOrder: ['layer-0-column-1'], - columns: { - 'layer-0-column-1': { - customLabel: true, - dataType: 'number', - isBucketed: false, - label: 'Page load time', - operationType: 'percentile', - params: { - percentile: 99, - }, - scale: 'ratio', - sourceField: 'transaction.duration.us', - }, - }, - incompleteColumns: {}, - }, - }, - }, - }, - filters: [], - query: { - language: 'kuery', - query: - 'transaction.type: page-load and processor.event: transaction and transaction.type : *', - }, - visualization: { - accessor: 'layer-0-column-1', - layerId: 'layer0', - layerType: 'data', - size: 's', - }, - }, - title: 'Prefilled from exploratory view app', - visualizationType: 'lnsLegacyMetric', - }); - }); - - it('returns attributes as expected for formula column', () => { - const reportViewConfigFormula = getDefaultConfigs({ - reportType: ReportTypes.SINGLE_METRIC, - dataType: DataTypes.SYNTHETICS, - dataView: mockDataView, - reportConfigMap: obsvReportConfigMap, - }); - - const layerConfigFormula: any = { - seriesConfig: reportViewConfigFormula, - operationType: 'median', - dataView: mockDataView, - reportDefinitions: {}, - time: { from: 'now-15m', to: 'now' }, - name: 'Availability', - selectedMetricField: 'monitor_availability', - }; - - lnsAttr = new SingleMetricLensAttributes( - [layerConfigFormula], - ReportTypes.SINGLE_METRIC, - formulaHelper - ); - - const jsonAttr = lnsAttr.getJSON('lnsLegacyMetric'); - expect(jsonAttr).toEqual(sampleMetricFormulaAttribute); - }); -}); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/lens_attributes/single_metric_attributes.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/lens_attributes/single_metric_attributes.ts deleted file mode 100644 index 79956df5f72d62..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/lens_attributes/single_metric_attributes.ts +++ /dev/null @@ -1,201 +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 { FormulaPublicApi, MetricState, OperationType } from '@kbn/lens-plugin/public'; - -import type { DataView } from '@kbn/data-views-plugin/common'; - -import { Query } from '@kbn/es-query'; -import { getColorPalette } from '../synthetics/single_metric_config'; -import { FORMULA_COLUMN, RECORDS_FIELD } from '../constants'; -import { ColumnFilter, MetricOption } from '../../types'; -import { SeriesConfig } from '../../../../..'; -import { - buildNumberColumn, - LayerConfig, - LensAttributes, - parseCustomFieldName, -} from '../lens_attributes'; - -export class SingleMetricLensAttributes extends LensAttributes { - columnId: string; - metricStateOptions?: MetricOption['metricStateOptions']; - - constructor( - layerConfigs: LayerConfig[], - reportType: string, - lensFormulaHelper: FormulaPublicApi - ) { - super(layerConfigs, reportType, lensFormulaHelper); - this.layers = {}; - this.reportType = reportType; - - this.layerConfigs = layerConfigs; - this.isMultiSeries = layerConfigs.length > 1; - - this.columnId = 'layer-0-column-1'; - - this.globalFilter = this.getGlobalFilter(this.isMultiSeries); - const layer0 = this.getSingleMetricLayer()!; - - this.layers = { - layer0, - }; - this.visualization = this.getMetricState(); - } - - getSingleMetricLayer() { - const { seriesConfig, selectedMetricField, operationType, dataView, name } = - this.layerConfigs[0]; - - const metricOption = parseCustomFieldName(seriesConfig, selectedMetricField); - - if (!Array.isArray(metricOption)) { - const { - columnFilter, - columnField, - columnLabel, - columnType, - formula, - metricStateOptions, - format, - emptyAsNull = true, - } = metricOption; - - this.metricStateOptions = metricStateOptions; - - if (columnType === FORMULA_COLUMN && formula) { - return this.getFormulaLayer({ - formula, - label: name ?? columnLabel, - dataView, - format, - filter: columnFilter, - }); - } - - const getSourceField = () => { - if ( - selectedMetricField.startsWith('Records') || - selectedMetricField.startsWith('records') - ) { - return 'Records'; - } - return columnField || selectedMetricField; - }; - - const sourceField = getSourceField(); - - const isPercentileColumn = operationType?.includes('th'); - - if (isPercentileColumn) { - return this.getPercentileLayer({ - sourceField, - operationType, - seriesConfig, - columnLabel, - columnFilter, - }); - } - - return { - columns: { - [this.columnId]: { - ...buildNumberColumn(sourceField), - label: name ?? columnLabel, - operationType: sourceField === RECORDS_FIELD ? 'count' : operationType || 'median', - filter: columnFilter, - params: { - emptyAsNull, - }, - }, - }, - columnOrder: [this.columnId], - incompleteColumns: {}, - }; - } - } - - getFormulaLayer({ - formula, - label, - dataView, - format, - filter, - }: { - formula: string; - label?: string; - format?: string; - filter?: Query; - dataView: DataView; - }) { - const layer = this.lensFormulaHelper?.insertOrReplaceFormulaColumn( - this.columnId, - { - formula, - label, - filter, - format: - format === 'percent' || !format - ? { - id: 'percent', - params: { - decimals: 1, - }, - } - : undefined, - }, - { columns: {}, columnOrder: [] }, - dataView - ); - - return layer!; - } - - getPercentileLayer({ - sourceField, - operationType, - seriesConfig, - columnLabel, - columnFilter, - }: { - sourceField: string; - operationType?: OperationType; - seriesConfig: SeriesConfig; - columnLabel?: string; - columnFilter?: ColumnFilter; - }) { - return { - columns: { - [this.columnId]: { - ...this.getPercentileNumberColumn(sourceField, operationType!, seriesConfig), - label: columnLabel ?? '', - filter: columnFilter, - }, - }, - columnOrder: [this.columnId], - incompleteColumns: {}, - }; - } - - getMetricState(): MetricState { - const { color } = this.layerConfigs[0]; - - const metricStateOptions: MetricOption['metricStateOptions'] = { - ...(this.metricStateOptions ?? {}), - ...(color ? { colorMode: 'Labels', palette: getColorPalette(color) } : {}), - }; - - return { - accessor: this.columnId, - layerId: 'layer0', - layerType: 'data', - ...metricStateOptions, - size: 's', - }; - } -} diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/lens_columns/overall_column.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/lens_columns/overall_column.ts deleted file mode 100644 index eeae6964318a28..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/lens_columns/overall_column.ts +++ /dev/null @@ -1,61 +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 { FormulaIndexPatternColumn, FormulaPublicApi } from '@kbn/lens-plugin/public'; -import type { DataView } from '@kbn/data-views-plugin/common'; - -export function getDistributionInPercentageColumn({ - label, - layerId, - dataView, - columnFilter, - lensFormulaHelper, - formula, - format, -}: { - label?: string; - columnFilter?: string; - layerId: string; - lensFormulaHelper: FormulaPublicApi; - dataView: DataView; - formula?: string; - format?: string; -}) { - const yAxisColId = `y-axis-column-${layerId}`; - - let lensFormula = formula ?? 'count() / overall_sum(count())'; - - if (columnFilter) { - lensFormula = - formula ?? `count(kql='${columnFilter}') / overall_sum(count(kql='${columnFilter}'))`; - } - - const { columns } = lensFormulaHelper?.insertOrReplaceFormulaColumn( - yAxisColId, - { - formula: lensFormula, - label, - format: - format === 'percent' || !format - ? { - id: 'percent', - params: { - decimals: 0, - }, - } - : undefined, - }, - { - columns: {}, - columnOrder: [], - }, - dataView - ) ?? { columns: {} }; - - const { [yAxisColId]: main, ...supportingColumns } = columns; - - return { main: columns[yAxisColId] as FormulaIndexPatternColumn, supportingColumns }; -} diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/mobile/device_distribution_config.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/mobile/device_distribution_config.ts deleted file mode 100644 index ae534704976e31..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/mobile/device_distribution_config.ts +++ /dev/null @@ -1,56 +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, SeriesConfig } from '../../types'; -import { - FieldLabels, - LABEL_FIELDS_FILTER, - REPORT_METRIC_FIELD, - ReportTypes, - USE_BREAK_DOWN_COLUMN, -} from '../constants'; -import { buildPhraseFilter } from '../utils'; -import { SERVICE_NAME } from '../constants/elasticsearch_fieldnames'; -import { MOBILE_APP, NUMBER_OF_DEVICES } from '../constants/labels'; -import { MobileFields } from './mobile_fields'; - -export function getMobileDeviceDistributionConfig({ dataView }: ConfigProps): SeriesConfig { - return { - reportType: ReportTypes.DEVICE_DISTRIBUTION, - defaultSeriesType: 'bar', - seriesTypes: ['bar', 'bar_horizontal'], - xAxisColumn: { - sourceField: USE_BREAK_DOWN_COLUMN, - }, - yAxisColumns: [ - { - sourceField: REPORT_METRIC_FIELD, - operationType: 'unique_count', - }, - ], - hasOperationType: false, - filterFields: [...Object.keys(MobileFields), LABEL_FIELDS_FILTER], - breakdownFields: Object.keys(MobileFields), - baseFilters: [ - ...buildPhraseFilter('agent.name', 'iOS/swift', dataView), - ...buildPhraseFilter('processor.event', 'transaction', dataView), - ], - labels: { - ...FieldLabels, - ...MobileFields, - [SERVICE_NAME]: MOBILE_APP, - }, - definitionFields: [SERVICE_NAME], - metricOptions: [ - { - field: 'labels.device_id', - id: 'labels.device_id', - label: NUMBER_OF_DEVICES, - }, - ], - }; -} diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/mobile/distribution_config.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/mobile/distribution_config.ts deleted file mode 100644 index cf3fd0f3d2aabe..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/mobile/distribution_config.ts +++ /dev/null @@ -1,90 +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, SeriesConfig } from '../../types'; -import { - FieldLabels, - LABEL_FIELDS_FILTER, - RECORDS_FIELD, - REPORT_METRIC_FIELD, - ReportTypes, -} from '../constants'; -import { buildPhrasesFilter } from '../utils'; -import { - METRIC_SYSTEM_CPU_USAGE, - METRIC_SYSTEM_MEMORY_USAGE, - PROCESSOR_EVENT, - SERVICE_ENVIRONMENT, - SERVICE_NAME, - TRANSACTION_DURATION, -} from '../constants/elasticsearch_fieldnames'; - -import { CPU_USAGE, SYSTEM_MEMORY_USAGE, MOBILE_APP, RESPONSE_LATENCY } from '../constants/labels'; -import { MobileFields } from './mobile_fields'; - -export function getMobileKPIDistributionConfig({ dataView }: ConfigProps): SeriesConfig { - return { - reportType: ReportTypes.DISTRIBUTION, - defaultSeriesType: 'bar', - seriesTypes: ['line', 'bar'], - xAxisColumn: { - sourceField: REPORT_METRIC_FIELD, - }, - yAxisColumns: [ - { - sourceField: RECORDS_FIELD, - }, - ], - hasOperationType: false, - filterFields: [...Object.keys(MobileFields), LABEL_FIELDS_FILTER], - breakdownFields: Object.keys(MobileFields), - baseFilters: [ - ...buildPhrasesFilter('agent.name', ['iOS/swift', 'open-telemetry/swift'], dataView), - ], - labels: { - ...FieldLabels, - ...MobileFields, - [SERVICE_NAME]: MOBILE_APP, - }, - definitionFields: [SERVICE_NAME, SERVICE_ENVIRONMENT], - metricOptions: [ - { - label: RESPONSE_LATENCY, - field: TRANSACTION_DURATION, - id: TRANSACTION_DURATION, - columnFilters: [ - { - language: 'kuery', - query: `${PROCESSOR_EVENT}: transaction`, - }, - ], - }, - { - label: SYSTEM_MEMORY_USAGE, - field: METRIC_SYSTEM_MEMORY_USAGE, - id: METRIC_SYSTEM_MEMORY_USAGE, - columnFilters: [ - { - language: 'kuery', - query: `${PROCESSOR_EVENT}: metric`, - }, - ], - }, - { - label: CPU_USAGE, - field: METRIC_SYSTEM_CPU_USAGE, - id: METRIC_SYSTEM_CPU_USAGE, - columnFilters: [ - { - language: 'kuery', - query: `${PROCESSOR_EVENT}: metric`, - }, - ], - }, - ], - }; -} diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/mobile/kpi_over_time_config.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/mobile/kpi_over_time_config.ts deleted file mode 100644 index 4d57ca45eae644..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/mobile/kpi_over_time_config.ts +++ /dev/null @@ -1,109 +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, SeriesConfig } from '../../types'; -import { - FieldLabels, - LABEL_FIELDS_FILTER, - OPERATION_COLUMN, - RECORDS_FIELD, - REPORT_METRIC_FIELD, - ReportTypes, -} from '../constants'; -import { buildPhrasesFilter } from '../utils'; -import { - METRIC_SYSTEM_CPU_USAGE, - METRIC_SYSTEM_MEMORY_USAGE, - PROCESSOR_EVENT, - SERVICE_ENVIRONMENT, - SERVICE_NAME, - TRANSACTION_DURATION, -} from '../constants/elasticsearch_fieldnames'; -import { - CPU_USAGE, - SYSTEM_MEMORY_USAGE, - MOBILE_APP, - RESPONSE_LATENCY, - TRANSACTIONS_PER_MINUTE, -} from '../constants/labels'; -import { MobileFields } from './mobile_fields'; - -export function getMobileKPIConfig({ dataView }: ConfigProps): SeriesConfig { - return { - reportType: ReportTypes.KPI, - defaultSeriesType: 'line', - seriesTypes: ['line', 'bar', 'area'], - xAxisColumn: { - sourceField: '@timestamp', - }, - yAxisColumns: [ - { - sourceField: REPORT_METRIC_FIELD, - operationType: 'median', - }, - ], - hasOperationType: true, - filterFields: [...Object.keys(MobileFields), LABEL_FIELDS_FILTER], - breakdownFields: Object.keys(MobileFields), - baseFilters: [ - ...buildPhrasesFilter('agent.name', ['iOS/swift', 'open-telemetry/swift'], dataView), - ], - labels: { - ...FieldLabels, - ...MobileFields, - [TRANSACTION_DURATION]: RESPONSE_LATENCY, - [SERVICE_NAME]: MOBILE_APP, - [METRIC_SYSTEM_MEMORY_USAGE]: SYSTEM_MEMORY_USAGE, - [METRIC_SYSTEM_CPU_USAGE]: CPU_USAGE, - }, - definitionFields: [SERVICE_NAME, SERVICE_ENVIRONMENT], - metricOptions: [ - { - label: RESPONSE_LATENCY, - field: TRANSACTION_DURATION, - id: TRANSACTION_DURATION, - columnType: OPERATION_COLUMN, - }, - { - field: RECORDS_FIELD, - id: RECORDS_FIELD, - label: TRANSACTIONS_PER_MINUTE, - columnFilters: [ - { - language: 'kuery', - query: `${PROCESSOR_EVENT}: transaction`, - }, - ], - timeScale: 'm', - }, - { - label: SYSTEM_MEMORY_USAGE, - field: METRIC_SYSTEM_MEMORY_USAGE, - id: METRIC_SYSTEM_MEMORY_USAGE, - columnType: OPERATION_COLUMN, - columnFilters: [ - { - language: 'kuery', - query: `${PROCESSOR_EVENT}: metric`, - }, - ], - }, - { - label: CPU_USAGE, - field: METRIC_SYSTEM_CPU_USAGE, - id: METRIC_SYSTEM_CPU_USAGE, - columnType: OPERATION_COLUMN, - columnFilters: [ - { - language: 'kuery', - query: `${PROCESSOR_EVENT}: metric`, - }, - ], - }, - ], - }; -} diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/mobile/mobile_fields.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/mobile/mobile_fields.ts deleted file mode 100644 index 46f9beba99e414..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/mobile/mobile_fields.ts +++ /dev/null @@ -1,28 +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 { - CARRIER_LOCATION, - CARRIER_NAME, - CONNECTION_TYPE, - DEVICE_MODEL, - HOST_OS, - OS_PLATFORM, - SERVICE_VERSION, - URL_LABEL, -} from '../constants/labels'; - -export const MobileFields: Record = { - 'host.os.platform': OS_PLATFORM, - 'host.os.full': HOST_OS, - 'service.version': SERVICE_VERSION, - 'network.carrier.icc': CARRIER_LOCATION, - 'network.carrier.name': CARRIER_NAME, - 'network.connection_type': CONNECTION_TYPE, - 'labels.device_model': DEVICE_MODEL, - 'url.full': URL_LABEL, -}; diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/mobile/mobile_kpi_config.test.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/mobile/mobile_kpi_config.test.ts deleted file mode 100644 index bd98f202b4be9d..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/mobile/mobile_kpi_config.test.ts +++ /dev/null @@ -1,45 +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 { mockAppDataView, mockDataView } from '../../rtl_helpers'; -import { LensAttributes } from '../lens_attributes'; -import { METRIC_SYSTEM_MEMORY_USAGE, SERVICE_NAME } from '../constants/elasticsearch_fieldnames'; -import { obsvReportConfigMap } from '../../obsv_exploratory_view'; -import { testMobileKPIAttr } from '../test_data/mobile_test_attribute'; -import { getLayerConfigs } from '../../hooks/use_lens_attributes'; -import { DataViewState } from '../../hooks/use_app_data_view'; -import { ReportTypes } from '../../../../..'; - -describe('Mobile kpi config test', function () { - mockAppDataView(); - - let lnsAttr: LensAttributes; - - const layerConfigs = getLayerConfigs( - [ - { - time: { from: 'now-15m', to: 'now' }, - reportDefinitions: { [SERVICE_NAME]: ['ios-integration-testing'] }, - selectedMetricField: METRIC_SYSTEM_MEMORY_USAGE, - color: 'green', - name: 'test-series', - dataType: 'mobile', - }, - ], - ReportTypes.KPI, - {} as any, - { mobile: mockDataView } as DataViewState, - obsvReportConfigMap - ); - - beforeEach(() => { - lnsAttr = new LensAttributes(layerConfigs, ReportTypes.KPI); - }); - it('should return expected json', function () { - expect(lnsAttr.getJSON()).toEqual(testMobileKPIAttr); - }); -}); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/rum/core_web_vitals_config.test.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/rum/core_web_vitals_config.test.ts deleted file mode 100644 index f7d415d05d551b..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/rum/core_web_vitals_config.test.ts +++ /dev/null @@ -1,45 +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 { mockAppDataView, mockDataView } from '../../rtl_helpers'; -import { getDefaultConfigs } from '../default_configs'; -import { LayerConfig, LensAttributes } from '../lens_attributes'; -import { sampleAttributeCoreWebVital } from '../test_data/sample_attribute_cwv'; -import { LCP_FIELD, SERVICE_NAME, USER_AGENT_OS } from '../constants/elasticsearch_fieldnames'; -import { obsvReportConfigMap } from '../../obsv_exploratory_view'; -import { ReportTypes } from '../../../../..'; - -describe('Core web vital config test', function () { - mockAppDataView(); - - const seriesConfig = getDefaultConfigs({ - reportType: ReportTypes.CORE_WEB_VITAL, - dataType: 'ux', - dataView: mockDataView, - reportConfigMap: obsvReportConfigMap, - }); - - let lnsAttr: LensAttributes; - - const layerConfig: LayerConfig = { - seriesConfig, - color: 'green', - name: 'test-series', - breakdown: USER_AGENT_OS, - dataView: mockDataView, - time: { from: 'now-15m', to: 'now' }, - reportDefinitions: { [SERVICE_NAME]: ['elastic-co'] }, - selectedMetricField: LCP_FIELD, - }; - - beforeEach(() => { - lnsAttr = new LensAttributes([layerConfig], ReportTypes.CORE_WEB_VITAL); - }); - it('should return expected json', function () { - expect(lnsAttr.getJSON()).toEqual(sampleAttributeCoreWebVital); - }); -}); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/rum/core_web_vitals_config.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/rum/core_web_vitals_config.ts deleted file mode 100644 index 0583ab390a0ef4..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/rum/core_web_vitals_config.ts +++ /dev/null @@ -1,161 +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 { euiPaletteForStatus } from '@elastic/eui'; -import { ConfigProps, SeriesConfig } from '../../types'; -import { - FieldLabels, - FILTER_RECORDS, - LABEL_FIELDS_FILTER, - REPORT_METRIC_FIELD, - ReportTypes, - USE_BREAK_DOWN_COLUMN, -} from '../constants'; -import { buildPhraseFilter } from '../utils'; -import { - CLIENT_GEO_COUNTRY_NAME, - CLS_FIELD, - FID_FIELD, - LCP_FIELD, - PROCESSOR_EVENT, - SERVICE_NAME, - TRANSACTION_TYPE, - USER_AGENT_DEVICE, - USER_AGENT_NAME, - USER_AGENT_OS, - USER_AGENT_VERSION, - TRANSACTION_URL, - USER_AGENT_OS_VERSION, - URL_FULL, - SERVICE_ENVIRONMENT, -} from '../constants/elasticsearch_fieldnames'; -import { CLS_LABEL, FID_LABEL, LCP_LABEL } from '../constants/labels'; - -export function getCoreWebVitalsConfig({ dataView }: ConfigProps): SeriesConfig { - const statusPallete = euiPaletteForStatus(3); - - return { - defaultSeriesType: 'bar_horizontal_percentage_stacked', - reportType: ReportTypes.CORE_WEB_VITAL, - seriesTypes: ['bar_horizontal_percentage_stacked'], - xAxisColumn: { - sourceField: USE_BREAK_DOWN_COLUMN, - }, - yAxisColumns: [ - { - sourceField: REPORT_METRIC_FIELD, - label: 'Good', - }, - { - sourceField: REPORT_METRIC_FIELD, - label: 'Average', - }, - { - sourceField: REPORT_METRIC_FIELD, - label: 'Poor', - }, - ], - hasOperationType: false, - filterFields: [ - { - field: TRANSACTION_URL, - isNegated: false, - }, - SERVICE_NAME, - { - field: USER_AGENT_OS, - nested: USER_AGENT_OS_VERSION, - }, - CLIENT_GEO_COUNTRY_NAME, - USER_AGENT_DEVICE, - { - field: USER_AGENT_NAME, - nested: USER_AGENT_VERSION, - }, - LABEL_FIELDS_FILTER, - ], - breakdownFields: [ - SERVICE_NAME, - USER_AGENT_NAME, - USER_AGENT_OS, - CLIENT_GEO_COUNTRY_NAME, - USER_AGENT_DEVICE, - URL_FULL, - ], - baseFilters: [ - ...buildPhraseFilter(TRANSACTION_TYPE, 'page-load', dataView), - ...buildPhraseFilter(PROCESSOR_EVENT, 'transaction', dataView), - ], - labels: { ...FieldLabels, [SERVICE_NAME]: 'Web Application' }, - definitionFields: [SERVICE_NAME, SERVICE_ENVIRONMENT], - metricOptions: [ - { - id: LCP_FIELD, - label: LCP_LABEL, - columnType: FILTER_RECORDS, - columnFilters: [ - { - language: 'kuery', - query: `${LCP_FIELD} < 2500`, - }, - { - language: 'kuery', - query: `${LCP_FIELD} > 2500 and ${LCP_FIELD} < 4000`, - }, - { - language: 'kuery', - query: `${LCP_FIELD} > 4000`, - }, - ], - }, - { - label: FID_LABEL, - id: FID_FIELD, - columnType: FILTER_RECORDS, - columnFilters: [ - { - language: 'kuery', - query: `${FID_FIELD} < 100`, - }, - { - language: 'kuery', - query: `${FID_FIELD} > 100 and ${FID_FIELD} < 300`, - }, - { - language: 'kuery', - query: `${FID_FIELD} > 300`, - }, - ], - }, - { - label: CLS_LABEL, - id: CLS_FIELD, - columnType: FILTER_RECORDS, - columnFilters: [ - { - language: 'kuery', - query: `${CLS_FIELD} < 0.1`, - }, - { - language: 'kuery', - query: `${CLS_FIELD} > 0.1 and ${CLS_FIELD} < 0.25`, - }, - { - language: 'kuery', - query: `${CLS_FIELD} > 0.25`, - }, - ], - }, - ], - yConfig: [ - { color: statusPallete[0], forAccessor: 'y-axis-column' }, - { color: statusPallete[1], forAccessor: 'y-axis-column-1' }, - { color: statusPallete[2], forAccessor: 'y-axis-column-2' }, - ], - query: { query: 'transaction.type: "page-load"', language: 'kuery' }, - }; -} diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/rum/data_distribution_config.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/rum/data_distribution_config.ts deleted file mode 100644 index 32099251f144ff..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/rum/data_distribution_config.ts +++ /dev/null @@ -1,115 +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, SeriesConfig } from '../../types'; -import { - FieldLabels, - REPORT_METRIC_FIELD, - RECORDS_PERCENTAGE_FIELD, - ReportTypes, - LABEL_FIELDS_FILTER, -} from '../constants'; -import { buildPhraseFilter } from '../utils'; -import { - CLIENT_GEO_COUNTRY_NAME, - CLS_FIELD, - FCP_FIELD, - FID_FIELD, - LCP_FIELD, - PROCESSOR_EVENT, - SERVICE_ENVIRONMENT, - SERVICE_NAME, - TBT_FIELD, - TRANSACTION_DURATION, - TRANSACTION_TIME_TO_FIRST_BYTE, - TRANSACTION_TYPE, - TRANSACTION_URL, - USER_AGENT_DEVICE, - USER_AGENT_NAME, - USER_AGENT_OS, - USER_AGENT_VERSION, -} from '../constants/elasticsearch_fieldnames'; -import { - BACKEND_TIME_LABEL, - CLS_LABEL, - FCP_LABEL, - FID_LABEL, - LCP_LABEL, - PAGE_LOAD_TIME_LABEL, - PAGES_LOADED_LABEL, - TBT_LABEL, - WEB_APPLICATION_LABEL, -} from '../constants/labels'; - -export function getRumDistributionConfig({ dataView }: ConfigProps): SeriesConfig { - return { - reportType: ReportTypes.DISTRIBUTION, - defaultSeriesType: 'line', - seriesTypes: [], - xAxisColumn: { - sourceField: REPORT_METRIC_FIELD, - }, - yAxisColumns: [ - { - sourceField: RECORDS_PERCENTAGE_FIELD, - label: PAGES_LOADED_LABEL, - }, - ], - hasOperationType: false, - filterFields: [ - { - field: TRANSACTION_URL, - isNegated: false, - }, - USER_AGENT_OS, - CLIENT_GEO_COUNTRY_NAME, - USER_AGENT_DEVICE, - { - field: USER_AGENT_NAME, - nested: USER_AGENT_VERSION, - }, - LABEL_FIELDS_FILTER, - ], - breakdownFields: [ - USER_AGENT_NAME, - USER_AGENT_OS, - CLIENT_GEO_COUNTRY_NAME, - USER_AGENT_DEVICE, - SERVICE_NAME, - ], - definitionFields: [SERVICE_NAME, SERVICE_ENVIRONMENT], - metricOptions: [ - { - label: PAGE_LOAD_TIME_LABEL, - id: TRANSACTION_DURATION, - field: TRANSACTION_DURATION, - showPercentileAnnotations: true, - }, - { - label: BACKEND_TIME_LABEL, - id: TRANSACTION_TIME_TO_FIRST_BYTE, - field: TRANSACTION_TIME_TO_FIRST_BYTE, - }, - { label: FCP_LABEL, id: FCP_FIELD, field: FCP_FIELD }, - { label: TBT_LABEL, id: TBT_FIELD, field: TBT_FIELD }, - { label: LCP_LABEL, id: LCP_FIELD, field: LCP_FIELD }, - { label: FID_LABEL, id: FID_FIELD, field: FID_FIELD }, - { label: CLS_LABEL, id: CLS_FIELD, field: CLS_FIELD }, - ], - baseFilters: [ - ...buildPhraseFilter(TRANSACTION_TYPE, 'page-load', dataView), - ...buildPhraseFilter(PROCESSOR_EVENT, 'transaction', dataView), - ], - labels: { - ...FieldLabels, - [SERVICE_NAME]: WEB_APPLICATION_LABEL, - [TRANSACTION_DURATION]: PAGE_LOAD_TIME_LABEL, - }, - // rum page load transactions are always less then 60 seconds - query: { query: 'transaction.duration.us < 60000000', language: 'kuery' }, - }; -} diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/rum/field_formats.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/rum/field_formats.ts deleted file mode 100644 index 25f258e17307dc..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/rum/field_formats.ts +++ /dev/null @@ -1,92 +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 { FieldFormat } from '../../types'; -import { - FCP_FIELD, - FID_FIELD, - LCP_FIELD, - TBT_FIELD, - TRANSACTION_DURATION, - TRANSACTION_TIME_TO_FIRST_BYTE, -} from '../constants/elasticsearch_fieldnames'; - -export const rumFieldFormats: FieldFormat[] = [ - { - field: TRANSACTION_DURATION, - format: { - id: 'duration', - params: { - inputFormat: 'microseconds', - outputFormat: 'asSeconds', - showSuffix: true, - outputPrecision: 1, - useShortSuffix: true, - }, - }, - }, - { - field: FCP_FIELD, - format: { - id: 'duration', - params: { - inputFormat: 'milliseconds', - outputFormat: 'humanizePrecise', - showSuffix: true, - useShortSuffix: true, - }, - }, - }, - { - field: LCP_FIELD, - format: { - id: 'duration', - params: { - inputFormat: 'milliseconds', - outputFormat: 'humanizePrecise', - showSuffix: true, - useShortSuffix: true, - }, - }, - }, - { - field: TBT_FIELD, - format: { - id: 'duration', - params: { - inputFormat: 'milliseconds', - outputFormat: 'humanizePrecise', - showSuffix: true, - useShortSuffix: true, - }, - }, - }, - { - field: FID_FIELD, - format: { - id: 'duration', - params: { - inputFormat: 'milliseconds', - outputFormat: 'humanizePrecise', - showSuffix: true, - useShortSuffix: true, - }, - }, - }, - { - field: TRANSACTION_TIME_TO_FIRST_BYTE, - format: { - id: 'duration', - params: { - inputFormat: 'milliseconds', - outputFormat: 'humanizePrecise', - showSuffix: true, - useShortSuffix: true, - }, - }, - }, -]; diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/rum/kpi_over_time_config.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/rum/kpi_over_time_config.ts deleted file mode 100644 index 4981c5c5315515..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/rum/kpi_over_time_config.ts +++ /dev/null @@ -1,112 +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, SeriesConfig } from '../../types'; -import { - FieldLabels, - LABEL_FIELDS_BREAKDOWN, - LABEL_FIELDS_FILTER, - OPERATION_COLUMN, - RECORDS_FIELD, - REPORT_METRIC_FIELD, - PERCENTILE, - ReportTypes, -} from '../constants'; -import { buildPhraseFilter } from '../utils'; -import { - CLIENT_GEO_COUNTRY_NAME, - CLS_FIELD, - FCP_FIELD, - FID_FIELD, - LCP_FIELD, - PROCESSOR_EVENT, - SERVICE_ENVIRONMENT, - SERVICE_NAME, - TBT_FIELD, - TRANSACTION_DURATION, - TRANSACTION_TYPE, - USER_AGENT_DEVICE, - USER_AGENT_NAME, - USER_AGENT_OS, - USER_AGENT_VERSION, - TRANSACTION_TIME_TO_FIRST_BYTE, - TRANSACTION_URL, -} from '../constants/elasticsearch_fieldnames'; -import { - BACKEND_TIME_LABEL, - CLS_LABEL, - FCP_LABEL, - FID_LABEL, - LCP_LABEL, - PAGE_LOAD_TIME_LABEL, - PAGE_VIEWS_LABEL, - TBT_LABEL, - WEB_APPLICATION_LABEL, -} from '../constants/labels'; - -export function getKPITrendsLensConfig({ dataView }: ConfigProps): SeriesConfig { - return { - defaultSeriesType: 'bar_stacked', - seriesTypes: [], - reportType: ReportTypes.KPI, - xAxisColumn: { - sourceField: '@timestamp', - }, - yAxisColumns: [ - { - sourceField: REPORT_METRIC_FIELD, - operationType: 'median', - }, - ], - hasOperationType: false, - filterFields: [ - TRANSACTION_URL, - USER_AGENT_OS, - CLIENT_GEO_COUNTRY_NAME, - USER_AGENT_DEVICE, - { - field: USER_AGENT_NAME, - nested: USER_AGENT_VERSION, - }, - LABEL_FIELDS_FILTER, - ], - breakdownFields: [ - USER_AGENT_NAME, - USER_AGENT_OS, - CLIENT_GEO_COUNTRY_NAME, - USER_AGENT_DEVICE, - PERCENTILE, - LABEL_FIELDS_BREAKDOWN, - ], - baseFilters: [ - ...buildPhraseFilter(TRANSACTION_TYPE, 'page-load', dataView), - ...buildPhraseFilter(PROCESSOR_EVENT, 'transaction', dataView), - ], - labels: { ...FieldLabels, [SERVICE_NAME]: WEB_APPLICATION_LABEL }, - definitionFields: [SERVICE_NAME, SERVICE_ENVIRONMENT], - metricOptions: [ - { field: RECORDS_FIELD, id: RECORDS_FIELD, label: PAGE_VIEWS_LABEL }, - { - label: PAGE_LOAD_TIME_LABEL, - field: TRANSACTION_DURATION, - id: TRANSACTION_DURATION, - columnType: OPERATION_COLUMN, - }, - { - label: BACKEND_TIME_LABEL, - field: TRANSACTION_TIME_TO_FIRST_BYTE, - id: TRANSACTION_TIME_TO_FIRST_BYTE, - columnType: OPERATION_COLUMN, - }, - { label: FCP_LABEL, field: FCP_FIELD, id: FCP_FIELD, columnType: OPERATION_COLUMN }, - { label: TBT_LABEL, field: TBT_FIELD, id: TBT_FIELD, columnType: OPERATION_COLUMN }, - { label: LCP_LABEL, field: LCP_FIELD, id: LCP_FIELD, columnType: OPERATION_COLUMN }, - { label: FID_LABEL, field: FID_FIELD, id: FID_FIELD, columnType: OPERATION_COLUMN }, - { label: CLS_LABEL, field: CLS_FIELD, id: CLS_FIELD, columnType: OPERATION_COLUMN }, - ], - }; -} diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/rum/single_metric_config.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/rum/single_metric_config.ts deleted file mode 100644 index 5358144672a844..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/rum/single_metric_config.ts +++ /dev/null @@ -1,56 +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, SeriesConfig } from '../../types'; -import { FieldLabels } from '../constants'; -import { buildPhraseFilter } from '../utils'; -import { PROCESSOR_EVENT, TRANSACTION_TYPE } from '../constants/elasticsearch_fieldnames'; - -export function getSingleMetricConfig({ dataView }: ConfigProps): SeriesConfig { - return { - defaultSeriesType: 'line', - xAxisColumn: {}, - yAxisColumns: [ - { - operationType: 'median', - }, - ], - breakdownFields: [], - filterFields: [], - seriesTypes: [], - hasOperationType: true, - definitionFields: ['service.name'], - reportType: 'single-metric', - baseFilters: [ - ...buildPhraseFilter(TRANSACTION_TYPE, 'page-load', dataView), - ...buildPhraseFilter(PROCESSOR_EVENT, 'transaction', dataView), - ], - metricOptions: [ - { - id: 'page_views', - field: 'Records', - label: 'Total page views', - }, - { - id: 'page_load_time', - field: 'transaction.duration.us', - label: 'Page load time', - }, - { - id: 'backend_time', - field: 'transaction.marks.agent.timeToFirstByte', - label: 'Backend time', - }, - { - id: 'frontend_time', - field: 'transaction.marks.agent.timeToFirstByte', - label: 'Frontend time', - }, - ], - labels: FieldLabels, - }; -} diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/synthetics/data_distribution_config.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/synthetics/data_distribution_config.ts deleted file mode 100644 index 412bf2ef87f6b5..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/synthetics/data_distribution_config.ts +++ /dev/null @@ -1,97 +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, SeriesConfig } from '../../types'; -import { - FieldLabels, - REPORT_METRIC_FIELD, - RECORDS_PERCENTAGE_FIELD, - ReportTypes, -} from '../constants'; -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'; -import { buildExistsFilter } from '../utils'; - -export function getSyntheticsDistributionConfig({ series, dataView }: ConfigProps): SeriesConfig { - return { - reportType: ReportTypes.DISTRIBUTION, - defaultSeriesType: series?.seriesType || 'line', - seriesTypes: [], - xAxisColumn: { - sourceField: REPORT_METRIC_FIELD, - }, - yAxisColumns: [ - { - sourceField: RECORDS_PERCENTAGE_FIELD, - label: PINGS_LABEL, - }, - ], - hasOperationType: false, - filterFields: ['monitor.type', 'observer.geo.name', 'tags', 'url.full'], - breakdownFields: [ - 'observer.geo.name', - 'monitor.name', - 'monitor.id', - 'monitor.type', - 'tags', - 'url.port', - ], - baseFilters: [], - definitionFields: [ - { field: 'monitor.name', nested: 'synthetics.step.name.keyword', singleSelection: true }, - { field: 'url.full', filters: buildExistsFilter('summary.up', dataView) }, - ], - metricOptions: [ - { - 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 }, - }; -} diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/synthetics/field_formats.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/synthetics/field_formats.ts deleted file mode 100644 index 9744a08c7ced96..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/synthetics/field_formats.ts +++ /dev/null @@ -1,104 +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 { FieldFormat } from '../../types'; -import { - SYNTHETICS_DCL, - SYNTHETICS_DOCUMENT_ONLOAD, - SYNTHETICS_FCP, - SYNTHETICS_LCP, - SYNTHETICS_STEP_DURATION, -} from '../constants/field_names/synthetics'; - -export const MS_TO_HUMANIZE_PRECISE = { - inputFormat: 'milliseconds' as const, - outputFormat: 'humanizePrecise' as const, - outputPrecision: 1, - showSuffix: true, - useShortSuffix: true, -}; - -export const syntheticsFieldFormats: FieldFormat[] = [ - { - field: 'monitor.duration.us', - format: { - id: 'duration', - params: { - inputFormat: 'microseconds', - outputFormat: 'humanizePrecise', - outputPrecision: 1, - showSuffix: true, - useShortSuffix: true, - }, - }, - }, - { - field: SYNTHETICS_STEP_DURATION, - format: { - id: 'duration', - params: { - inputFormat: 'microseconds', - outputFormat: 'humanizePrecise', - outputPrecision: 1, - showSuffix: true, - useShortSuffix: true, - }, - }, - }, - { - 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, - }, - }, - }, -]; diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/synthetics/heatmap_config.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/synthetics/heatmap_config.ts deleted file mode 100644 index 1c41aaa8d4db99..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/synthetics/heatmap_config.ts +++ /dev/null @@ -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, SeriesConfig } from '../../types'; -import { FieldLabels, RECORDS_FIELD, REPORT_METRIC_FIELD, ReportTypes } from '../constants'; -import { DOWN_LABEL, UP_LABEL } from '../constants/labels'; -import { SYNTHETICS_STEP_NAME } from '../constants/field_names/synthetics'; -import { buildExistsFilter } from '../utils'; - -const SUMMARY_UP = 'summary.up'; -const SUMMARY_DOWN = 'summary.down'; - -export function getSyntheticsHeatmapConfig({ dataView }: ConfigProps): SeriesConfig { - return { - reportType: ReportTypes.HEATMAP, - defaultSeriesType: 'bar_stacked', - seriesTypes: [], - xAxisColumn: { - sourceField: '@timestamp', - }, - yAxisColumns: [ - { - sourceField: REPORT_METRIC_FIELD, - operationType: 'median', - }, - ], - hasOperationType: false, - filterFields: ['observer.geo.name', 'monitor.type', 'tags', 'url.full'], - breakdownFields: ['observer.geo.name', 'monitor.type', 'monitor.name', SYNTHETICS_STEP_NAME], - baseFilters: [], - definitionFields: [ - { field: 'monitor.name' }, - { field: 'url.full', filters: buildExistsFilter('summary.up', dataView) }, - ], - metricOptions: [ - { - label: 'Failed tests', - id: 'failed_tests', - columnFilter: { language: 'kuery', query: 'summary.down > 0' }, - format: 'number', - field: RECORDS_FIELD, - }, - ], - labels: { ...FieldLabels, [SUMMARY_UP]: UP_LABEL, [SUMMARY_DOWN]: DOWN_LABEL }, - }; -} diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/synthetics/kpi_over_time_config.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/synthetics/kpi_over_time_config.ts deleted file mode 100644 index f6187e1117f993..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/synthetics/kpi_over_time_config.ts +++ /dev/null @@ -1,222 +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 { ColumnFilter, ConfigProps, SeriesConfig } from '../../types'; -import { - FieldLabels, - OPERATION_COLUMN, - REPORT_METRIC_FIELD, - PERCENTILE, - ReportTypes, - FORMULA_COLUMN, -} from '../constants'; -import { - CLS_LABEL, - DCL_LABEL, - DOWN_LABEL, - FCP_LABEL, - LCP_LABEL, - MONITORS_DURATION_LABEL, - STEP_DURATION_LABEL, - UP_LABEL, - PAGE_LOAD_TIME_LABEL, - NETWORK_TIMINGS_LABEL, -} from '../constants/labels'; -import { - MONITOR_DURATION_US, - NETWORK_TIMINGS_FIELDS, - SYNTHETICS_CLS, - SYNTHETICS_DCL, - SYNTHETICS_DOCUMENT_ONLOAD, - SYNTHETICS_FCP, - SYNTHETICS_LCP, - SYNTHETICS_STEP_DURATION, - SYNTHETICS_STEP_NAME, -} from '../constants/field_names/synthetics'; -import { buildExistsFilter } from '../utils'; -const SUMMARY_UP = 'summary.up'; -const SUMMARY_DOWN = 'summary.down'; - -export const isStepLevelMetric = (metric?: string) => { - if (!metric) { - return false; - } - return [ - SYNTHETICS_LCP, - SYNTHETICS_FCP, - SYNTHETICS_CLS, - SYNTHETICS_DCL, - SYNTHETICS_STEP_DURATION, - SYNTHETICS_DOCUMENT_ONLOAD, - ].includes(metric); -}; -export function getSyntheticsKPIConfig({ dataView }: ConfigProps): SeriesConfig { - return { - reportType: ReportTypes.KPI, - defaultSeriesType: 'bar_stacked', - seriesTypes: [], - xAxisColumn: { - sourceField: '@timestamp', - }, - yAxisColumns: [ - { - sourceField: REPORT_METRIC_FIELD, - operationType: 'median', - }, - ], - hasOperationType: true, - filterFields: ['observer.geo.name', 'monitor.type', 'tags', 'url.full'], - breakdownFields: [ - 'observer.geo.name', - 'monitor.type', - 'monitor.name', - SYNTHETICS_STEP_NAME, - PERCENTILE, - ], - baseFilters: [], - definitionFields: [ - { field: 'monitor.name', nested: SYNTHETICS_STEP_NAME, singleSelection: true }, - { field: 'url.full', filters: buildExistsFilter('summary.up', dataView) }, - ], - metricOptions: [ - { - label: MONITORS_DURATION_LABEL, - field: MONITOR_DURATION_US, - id: MONITOR_DURATION_US, - columnType: OPERATION_COLUMN, - }, - { - label: 'Monitor availability', - id: 'monitor_availability', - columnType: FORMULA_COLUMN, - formula: "1- (count(kql='summary.down > 0') / count(kql='summary: *'))", - }, - { - label: 'Monitor Errors', - id: 'monitor_errors', - columnType: OPERATION_COLUMN, - field: 'state.id', - columnFilters: [ - { - language: 'kuery', - query: `summary.down > 0`, - }, - ], - }, - { - label: 'Monitor Complete', - id: 'state.up', - field: 'state.up', - columnType: OPERATION_COLUMN, - columnFilters: [ - { - language: 'kuery', - query: `summary: * and summary.down: 0 and monitor.status: "up"`, - }, - ], - }, - { - label: 'Total runs', - id: 'monitor.check_group', - field: 'monitor.check_group', - columnType: OPERATION_COLUMN, - columnFilters: [ - { - language: 'kuery', - query: `summary: *`, - }, - ], - }, - { - field: SUMMARY_UP, - id: SUMMARY_UP, - label: UP_LABEL, - columnType: OPERATION_COLUMN, - palette: { type: 'palette', name: 'status' }, - }, - { - field: SUMMARY_DOWN, - id: SUMMARY_DOWN, - label: DOWN_LABEL, - columnType: OPERATION_COLUMN, - palette: { type: 'palette', name: 'status' }, - }, - { - label: STEP_DURATION_LABEL, - field: SYNTHETICS_STEP_DURATION, - id: SYNTHETICS_STEP_DURATION, - columnType: OPERATION_COLUMN, - columnFilters: [STEP_END_FILTER], - }, - { - label: LCP_LABEL, - field: SYNTHETICS_LCP, - id: SYNTHETICS_LCP, - columnType: OPERATION_COLUMN, - columnFilters: getStepMetricColumnFilter(SYNTHETICS_LCP), - }, - { - label: FCP_LABEL, - field: SYNTHETICS_FCP, - id: SYNTHETICS_FCP, - columnType: OPERATION_COLUMN, - columnFilters: getStepMetricColumnFilter(SYNTHETICS_FCP), - }, - { - label: DCL_LABEL, - field: SYNTHETICS_DCL, - id: SYNTHETICS_DCL, - columnType: OPERATION_COLUMN, - columnFilters: getStepMetricColumnFilter(SYNTHETICS_DCL), - }, - { - label: PAGE_LOAD_TIME_LABEL, - field: SYNTHETICS_DOCUMENT_ONLOAD, - id: SYNTHETICS_DOCUMENT_ONLOAD, - columnType: OPERATION_COLUMN, - columnFilters: getStepMetricColumnFilter(SYNTHETICS_DOCUMENT_ONLOAD), - }, - { - label: CLS_LABEL, - field: SYNTHETICS_CLS, - id: SYNTHETICS_CLS, - columnType: OPERATION_COLUMN, - columnFilters: getStepMetricColumnFilter(SYNTHETICS_CLS), - }, - { - label: NETWORK_TIMINGS_LABEL, - id: 'network_timings', - columnType: OPERATION_COLUMN, - items: NETWORK_TIMINGS_FIELDS.map((field) => ({ - label: FieldLabels[field] ?? field, - field, - id: field, - columnType: OPERATION_COLUMN, - columnFilters: getStepMetricColumnFilter(field, 'journey/network_info'), - })), - }, - ], - labels: { ...FieldLabels, [SUMMARY_UP]: UP_LABEL, [SUMMARY_DOWN]: DOWN_LABEL }, - }; -} - -const getStepMetricColumnFilter = ( - field: string, - stepType: 'step/metrics' | 'step/end' | 'journey/network_info' = 'step/metrics' -): ColumnFilter[] => { - return [ - { - language: 'kuery', - query: `synthetics.type: ${stepType} and ${field}: * and ${field} > 0`, - }, - ]; -}; - -const STEP_END_FILTER: ColumnFilter = { - language: 'kuery', - query: `synthetics.type: step/end`, -}; diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/synthetics/runtime_fields.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/synthetics/runtime_fields.ts deleted file mode 100644 index 16be09ed474bd6..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/synthetics/runtime_fields.ts +++ /dev/null @@ -1,62 +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 { RuntimeField } from '@kbn/data-views-plugin/public'; -import { MS_TO_HUMANIZE_PRECISE } from './field_formats'; -import { - SYNTHETICS_DNS_TIMINGS, - SYNTHETICS_BLOCKED_TIMINGS, - SYNTHETICS_CONNECT_TIMINGS, - SYNTHETICS_TOTAL_TIMINGS, - SYNTHETICS_RECEIVE_TIMINGS, - SYNTHETICS_SEND_TIMINGS, - SYNTHETICS_WAIT_TIMINGS, - SYNTHETICS_SSL_TIMINGS, -} from '../constants/field_names/synthetics'; - -const LONG_FIELD = { - type: 'long' as const, - format: { - id: 'duration', - params: MS_TO_HUMANIZE_PRECISE, - }, -}; - -export const syntheticsRuntimeFields: Array<{ name: string; field: RuntimeField }> = [ - { - name: SYNTHETICS_DNS_TIMINGS, - field: LONG_FIELD, - }, - { - name: SYNTHETICS_BLOCKED_TIMINGS, - field: LONG_FIELD, - }, - { - name: SYNTHETICS_CONNECT_TIMINGS, - field: LONG_FIELD, - }, - { - name: SYNTHETICS_TOTAL_TIMINGS, - field: LONG_FIELD, - }, - { - name: SYNTHETICS_RECEIVE_TIMINGS, - field: LONG_FIELD, - }, - { - name: SYNTHETICS_SEND_TIMINGS, - field: LONG_FIELD, - }, - { - name: SYNTHETICS_WAIT_TIMINGS, - field: LONG_FIELD, - }, - { - name: SYNTHETICS_SSL_TIMINGS, - field: LONG_FIELD, - }, -]; diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/synthetics/single_metric_config.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/synthetics/single_metric_config.ts deleted file mode 100644 index 7e19ae43b37bdb..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/synthetics/single_metric_config.ts +++ /dev/null @@ -1,178 +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 { i18n } from '@kbn/i18n'; -import { LegacyMetricState } from '@kbn/lens-plugin/common'; -import { euiPaletteForStatus } from '@elastic/eui'; -import { - SYNTHETICS_STEP_DURATION, - SYNTHETICS_STEP_NAME, -} from '../constants/field_names/synthetics'; -import { ConfigProps, SeriesConfig } from '../../types'; -import { FieldLabels, FORMULA_COLUMN, RECORDS_FIELD } from '../constants'; -import { buildExistsFilter } from '../utils'; - -export function getSyntheticsSingleMetricConfig({ dataView }: ConfigProps): SeriesConfig { - return { - defaultSeriesType: 'line', - xAxisColumn: {}, - yAxisColumns: [ - { - operationType: 'median', - }, - ], - breakdownFields: [], - filterFields: [], - seriesTypes: [], - hasOperationType: true, - definitionFields: [ - { field: 'monitor.name', nested: SYNTHETICS_STEP_NAME, singleSelection: true }, - { field: 'url.full', filters: buildExistsFilter('summary.up', dataView) }, - ], - reportType: 'single-metric', - baseFilters: [], - metricOptions: [ - { - id: 'monitor_availability', - columnType: FORMULA_COLUMN, - label: 'Availability', - formula: "1- (count(kql='summary.down > 0') / count())", - metricStateOptions: { - colorMode: 'Labels', - palette: { - name: 'custom', - type: 'palette', - params: { - steps: 3, - name: 'custom', - reverse: false, - rangeType: 'number', - rangeMin: 0, - rangeMax: 1, - progression: 'fixed', - stops: [ - { color: '#cc5642', stop: 0.9 }, - { color: '#d6bf57', stop: 0.95 }, - { color: '#209280', stop: 1.9903347477604902 }, - ], - colorStops: [ - { color: '#cc5642', stop: 0.8 }, - { color: '#d6bf57', stop: 0.9 }, - { color: '#209280', stop: 0.95 }, - ], - continuity: 'above', - maxSteps: 5, - }, - }, - titlePosition: 'bottom', - }, - columnFilter: { language: 'kuery', query: 'summary.up: *' }, - }, - { - id: 'monitor_duration', - field: 'monitor.duration.us', - label: i18n.translate('xpack.observability.expView.avgDuration', { - defaultMessage: 'Avg. Duration', - }), - metricStateOptions: { - titlePosition: 'bottom', - }, - columnFilter: { language: 'kuery', query: 'summary.up: *' }, - }, - { - id: 'step_duration', - field: SYNTHETICS_STEP_DURATION, - label: i18n.translate('xpack.observability.expView.stepDuration', { - defaultMessage: 'Total step duration', - }), - metricStateOptions: { - titlePosition: 'bottom', - textAlign: 'center', - }, - }, - { - id: 'monitor_total_runs', - label: i18n.translate('xpack.observability.expView.totalRuns', { - defaultMessage: 'Total Runs', - }), - metricStateOptions: { - titlePosition: 'bottom', - }, - columnType: FORMULA_COLUMN, - formula: "unique_count(monitor.check_group, kql='summary: *')", - format: 'number', - }, - { - id: 'monitor_complete', - label: i18n.translate('xpack.observability.expView.complete', { - defaultMessage: 'Complete', - }), - metricStateOptions: { - titlePosition: 'bottom', - }, - columnType: FORMULA_COLUMN, - formula: 'unique_count(monitor.check_group, kql=\'monitor.status: "up"\')', - format: 'number', - }, - { - id: 'monitor_errors', - label: i18n.translate('xpack.observability.expView.errors', { - defaultMessage: 'Errors', - }), - metricStateOptions: { - titlePosition: 'bottom', - colorMode: 'Labels', - palette: getColorPalette('danger'), - }, - columnType: FORMULA_COLUMN, - formula: 'unique_count(state.id, kql=\'monitor.status: "down"\')', - format: 'number', - }, - { - id: 'monitor_failed_tests', - label: i18n.translate('xpack.observability.expView.failedTests', { - defaultMessage: 'Failed tests', - }), - metricStateOptions: { - titlePosition: 'bottom', - }, - field: RECORDS_FIELD, - format: 'number', - columnFilter: { language: 'kuery', query: 'summary.down > 0' }, - }, - ], - labels: FieldLabels, - }; -} - -export const getColorPalette = ( - color: 'danger' | 'warning' | 'success' | string -): LegacyMetricState['palette'] => { - const statusPalette = euiPaletteForStatus(5); - - let valueColor = color ?? statusPalette[3]; - if (color === 'danger') { - valueColor = statusPalette[3]; - } - - return { - name: 'custom', - type: 'palette', - params: { - steps: 3, - name: 'custom', - reverse: false, - rangeType: 'number', - rangeMin: 0, - progression: 'fixed', - stops: [{ color: valueColor, stop: 100 }], - colorStops: [{ color: valueColor, stop: 0 }], - continuity: 'above', - maxSteps: 5, - }, - }; -}; diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/mobile_test_attribute.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/mobile_test_attribute.ts deleted file mode 100644 index c083962b0e21b2..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/mobile_test_attribute.ts +++ /dev/null @@ -1,98 +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 { mockDataView } from '../../rtl_helpers'; - -export const testMobileKPIAttr = { - title: 'Prefilled from exploratory view app', - description: '', - references: [], - visualizationType: 'lnsXY', - state: { - adHocDataViews: { [mockDataView.title]: mockDataView.toSpec(false) }, - internalReferences: [ - { - id: 'apm-*', - name: 'indexpattern-datasource-current-indexpattern', - type: 'index-pattern', - }, - { - id: 'apm-*', - name: 'indexpattern-datasource-layer-layer0', - type: 'index-pattern', - }, - ], - datasourceStates: { - formBased: { - layers: { - layer0: { - columnOrder: ['x-axis-column-layer0', 'y-axis-column-layer0-0'], - columns: { - 'x-axis-column-layer0': { - sourceField: '@timestamp', - dataType: 'date', - isBucketed: true, - label: '@timestamp', - operationType: 'date_histogram', - params: { interval: 'auto', includeEmptyRows: true }, - scale: 'interval', - }, - 'y-axis-column-layer0-0': { - isBucketed: false, - label: 'test-series', - operationType: 'median', - params: {}, - scale: 'ratio', - sourceField: 'system.memory.usage', - dataType: 'number', - filter: { - query: - 'service.name: "ios-integration-testing" and agent.name: (iOS/swift or open-telemetry/swift) and processor.event: metric', - language: 'kuery', - }, - }, - }, - incompleteColumns: {}, - }, - }, - }, - }, - visualization: { - legend: { - isVisible: true, - showSingleSeries: true, - position: 'right', - legendSize: 'auto', - shouldTruncate: false, - }, - valueLabels: 'hide', - fittingFunction: 'Linear', - curveType: 'CURVE_MONOTONE_X', - axisTitlesVisibilitySettings: { x: false, yLeft: true, yRight: true }, - tickLabelsVisibilitySettings: { x: true, yLeft: true, yRight: true }, - gridlinesVisibilitySettings: { x: false, yLeft: true, yRight: true }, - preferredSeriesType: 'line', - layers: [ - { - accessors: ['y-axis-column-layer0-0'], - layerId: 'layer0', - layerType: 'data', - palette: undefined, - seriesType: 'line', - yConfig: [{ forAccessor: 'y-axis-column-layer0-0', color: 'green', axisMode: 'left' }], - xAccessor: 'x-axis-column-layer0', - }, - ], - }, - query: { - query: - 'service.name: "ios-integration-testing" and agent.name: (iOS/swift or open-telemetry/swift)', - language: 'kuery', - }, - filters: [], - }, -}; diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/sample_attribute.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/sample_attribute.ts deleted file mode 100644 index 7c054a908ba3bd..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/sample_attribute.ts +++ /dev/null @@ -1,342 +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 { mockDataView } from '../../rtl_helpers'; -import { RECORDS_FIELD } from '../constants'; - -export const sampleAttribute = { - description: '', - references: [], - state: { - internalReferences: [ - { - id: 'apm-*', - name: 'indexpattern-datasource-current-indexpattern', - type: 'index-pattern', - }, - { - id: 'apm-*', - name: 'indexpattern-datasource-layer-layer0', - type: 'index-pattern', - }, - { - id: 'apm-*', - name: 'indexpattern-datasource-layer-layer0-reference-lines', - type: 'index-pattern', - }, - ], - adHocDataViews: { [mockDataView.title]: mockDataView.toSpec(false) }, - datasourceStates: { - formBased: { - layers: { - layer0: { - columnOrder: [ - 'x-axis-column-layer0', - 'y-axis-column-layer0-0', - 'y-axis-column-layer0X0', - 'y-axis-column-layer0X1', - 'y-axis-column-layer0X2', - 'y-axis-column-layer0X3', - ], - columns: { - 'x-axis-column-layer0': { - dataType: 'number', - isBucketed: true, - label: 'Page load time', - operationType: 'range', - params: { - maxBars: 'auto', - ranges: [ - { - from: 0, - label: '', - to: 1000, - }, - ], - type: 'histogram', - }, - scale: 'interval', - sourceField: 'transaction.duration.us', - }, - 'y-axis-column-layer0-0': { - customLabel: true, - dataType: 'number', - filter: { - language: 'kuery', - query: - 'transaction.type: page-load and processor.event: transaction and transaction.type : *', - }, - isBucketed: false, - label: 'test-series', - operationType: 'formula', - params: { - format: { - id: 'percent', - params: { - decimals: 0, - }, - }, - formula: - "count(kql='transaction.type: page-load and processor.event: transaction and transaction.type : *') / overall_sum(count(kql='transaction.type: page-load and processor.event: transaction and transaction.type : *'))", - isFormulaBroken: false, - }, - references: ['y-axis-column-layer0X3'], - }, - 'y-axis-column-layer0X0': { - customLabel: true, - dataType: 'number', - filter: { - language: 'kuery', - query: - 'transaction.type: page-load and processor.event: transaction and transaction.type : *', - }, - isBucketed: false, - label: 'Part of Pages loaded', - operationType: 'count', - params: { - emptyAsNull: false, - }, - scale: 'ratio', - sourceField: RECORDS_FIELD, - timeScale: undefined, - timeShift: undefined, - }, - 'y-axis-column-layer0X1': { - customLabel: true, - dataType: 'number', - filter: { - language: 'kuery', - query: - 'transaction.type: page-load and processor.event: transaction and transaction.type : *', - }, - isBucketed: false, - label: 'Part of Pages loaded', - operationType: 'count', - params: { - emptyAsNull: false, - }, - scale: 'ratio', - sourceField: RECORDS_FIELD, - timeScale: undefined, - timeShift: undefined, - }, - 'y-axis-column-layer0X2': { - customLabel: true, - dataType: 'number', - isBucketed: false, - label: 'Part of Pages loaded', - operationType: 'overall_sum', - params: undefined, - references: ['y-axis-column-layer0X1'], - scale: 'ratio', - }, - 'y-axis-column-layer0X3': { - customLabel: true, - dataType: 'number', - isBucketed: false, - label: 'Part of Pages loaded', - operationType: 'math', - params: { - tinymathAst: { - args: ['y-axis-column-layer0X0', 'y-axis-column-layer0X2'], - location: { - max: 212, - min: 0, - }, - name: 'divide', - text: "count(kql='transaction.type: page-load and processor.event: transaction and transaction.type : *') / overall_sum(count(kql='transaction.type: page-load and processor.event: transaction and transaction.type : *'))", - type: 'function', - }, - }, - references: ['y-axis-column-layer0X0', 'y-axis-column-layer0X2'], - scale: 'ratio', - }, - }, - incompleteColumns: {}, - }, - 'layer0-reference-lines': { - columnOrder: [ - '50th-percentile-reference-line-layer0-reference-lines', - '75th-percentile-reference-line-layer0-reference-lines', - '90th-percentile-reference-line-layer0-reference-lines', - '95th-percentile-reference-line-layer0-reference-lines', - '99th-percentile-reference-line-layer0-reference-lines', - ], - columns: { - '50th-percentile-reference-line-layer0-reference-lines': { - customLabel: true, - dataType: 'number', - isBucketed: false, - label: '50th', - operationType: 'percentile', - params: { - percentile: 50, - }, - scale: 'ratio', - sourceField: 'transaction.duration.us', - }, - '75th-percentile-reference-line-layer0-reference-lines': { - customLabel: true, - dataType: 'number', - isBucketed: false, - label: '75th', - operationType: 'percentile', - params: { - percentile: 75, - }, - scale: 'ratio', - sourceField: 'transaction.duration.us', - }, - '90th-percentile-reference-line-layer0-reference-lines': { - customLabel: true, - dataType: 'number', - isBucketed: false, - label: '90th', - operationType: 'percentile', - params: { - percentile: 90, - }, - scale: 'ratio', - sourceField: 'transaction.duration.us', - }, - '95th-percentile-reference-line-layer0-reference-lines': { - customLabel: true, - dataType: 'number', - isBucketed: false, - label: '95th', - operationType: 'percentile', - params: { - percentile: 95, - }, - scale: 'ratio', - sourceField: 'transaction.duration.us', - }, - '99th-percentile-reference-line-layer0-reference-lines': { - customLabel: true, - dataType: 'number', - isBucketed: false, - label: '99th', - operationType: 'percentile', - params: { - percentile: 99, - }, - scale: 'ratio', - sourceField: 'transaction.duration.us', - }, - }, - incompleteColumns: {}, - }, - }, - }, - }, - filters: [], - query: { - language: 'kuery', - query: - 'transaction.type: page-load and processor.event: transaction and transaction.type : * and transaction.duration.us < 60000000', - }, - visualization: { - axisTitlesVisibilitySettings: { - x: false, - yLeft: true, - yRight: true, - }, - curveType: 'CURVE_MONOTONE_X', - fittingFunction: 'Linear', - gridlinesVisibilitySettings: { - x: false, - yLeft: true, - yRight: true, - }, - layers: [ - { - accessors: ['y-axis-column-layer0-0'], - layerId: 'layer0', - layerType: 'data', - palette: undefined, - seriesType: 'line', - xAccessor: 'x-axis-column-layer0', - yConfig: [ - { - color: 'green', - forAccessor: 'y-axis-column-layer0-0', - axisMode: 'left', - }, - ], - }, - { - accessors: [ - '50th-percentile-reference-line-layer0-reference-lines', - '75th-percentile-reference-line-layer0-reference-lines', - '90th-percentile-reference-line-layer0-reference-lines', - '95th-percentile-reference-line-layer0-reference-lines', - '99th-percentile-reference-line-layer0-reference-lines', - ], - layerId: 'layer0-reference-lines', - layerType: 'referenceLine', - yConfig: [ - { - axisMode: 'bottom', - color: '#6092C0', - forAccessor: '50th-percentile-reference-line-layer0-reference-lines', - lineStyle: 'solid', - lineWidth: 2, - textVisibility: true, - }, - { - axisMode: 'bottom', - color: '#6092C0', - forAccessor: '75th-percentile-reference-line-layer0-reference-lines', - lineStyle: 'solid', - lineWidth: 2, - textVisibility: true, - }, - { - axisMode: 'bottom', - color: '#6092C0', - forAccessor: '90th-percentile-reference-line-layer0-reference-lines', - lineStyle: 'solid', - lineWidth: 2, - textVisibility: true, - }, - { - axisMode: 'bottom', - color: '#6092C0', - forAccessor: '95th-percentile-reference-line-layer0-reference-lines', - lineStyle: 'solid', - lineWidth: 2, - textVisibility: true, - }, - { - axisMode: 'bottom', - color: '#6092C0', - forAccessor: '99th-percentile-reference-line-layer0-reference-lines', - lineStyle: 'solid', - lineWidth: 2, - textVisibility: true, - }, - ], - }, - ], - legend: { - isVisible: true, - position: 'right', - showSingleSeries: true, - legendSize: 'auto', - shouldTruncate: false, - }, - preferredSeriesType: 'line', - tickLabelsVisibilitySettings: { - x: true, - yLeft: true, - yRight: true, - }, - valueLabels: 'hide', - }, - }, - title: 'Prefilled from exploratory view app', - visualizationType: 'lnsXY', -}; diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/sample_attribute_cwv.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/sample_attribute_cwv.ts deleted file mode 100644 index 5c09be23824259..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/sample_attribute_cwv.ts +++ /dev/null @@ -1,161 +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 { mockDataView } from '../../rtl_helpers'; -import { RECORDS_FIELD } from '../constants'; - -export const sampleAttributeCoreWebVital = { - description: '', - references: [], - state: { - internalReferences: [ - { - id: 'apm-*', - name: 'indexpattern-datasource-current-indexpattern', - type: 'index-pattern', - }, - { - id: 'apm-*', - name: 'indexpattern-datasource-layer-layer0', - type: 'index-pattern', - }, - ], - adHocDataViews: { [mockDataView.title]: mockDataView.toSpec(false) }, - datasourceStates: { - formBased: { - layers: { - layer0: { - columnOrder: [ - 'x-axis-column-layer0', - 'y-axis-column-layer0-0', - 'y-axis-column-1', - 'y-axis-column-2', - ], - columns: { - 'x-axis-column-layer0': { - dataType: 'string', - isBucketed: true, - label: 'Operating system', - operationType: 'terms', - params: { - missingBucket: false, - orderBy: { - columnId: 'y-axis-column-layer0-0', - type: 'column', - }, - orderDirection: 'desc', - otherBucket: true, - size: 10, - }, - scale: 'ordinal', - sourceField: 'user_agent.os.name', - }, - 'y-axis-column-1': { - dataType: 'number', - filter: { - language: 'kuery', - query: - 'transaction.marks.agent.largestContentfulPaint > 2500 and transaction.marks.agent.largestContentfulPaint < 4000', - }, - isBucketed: false, - label: 'Average', - operationType: 'count', - scale: 'ratio', - sourceField: RECORDS_FIELD, - }, - 'y-axis-column-2': { - dataType: 'number', - filter: { - language: 'kuery', - query: 'transaction.marks.agent.largestContentfulPaint > 4000', - }, - isBucketed: false, - label: 'Poor', - operationType: 'count', - scale: 'ratio', - sourceField: RECORDS_FIELD, - }, - 'y-axis-column-layer0-0': { - dataType: 'number', - filter: { - language: 'kuery', - query: - 'transaction.type: page-load and processor.event: transaction and transaction.marks.agent.largestContentfulPaint < 2500', - }, - isBucketed: false, - label: 'Good', - operationType: 'count', - scale: 'ratio', - sourceField: RECORDS_FIELD, - }, - }, - incompleteColumns: {}, - }, - }, - }, - }, - filters: [], - query: { - language: 'kuery', - query: - 'transaction.type: page-load and processor.event: transaction and transaction.type: "page-load"', - }, - visualization: { - axisTitlesVisibilitySettings: { - x: false, - yLeft: true, - yRight: true, - }, - curveType: 'CURVE_MONOTONE_X', - fittingFunction: 'Linear', - gridlinesVisibilitySettings: { - x: false, - yLeft: true, - yRight: true, - }, - layers: [ - { - accessors: ['y-axis-column-layer0-0', 'y-axis-column-1', 'y-axis-column-2'], - layerId: 'layer0', - layerType: 'data', - palette: undefined, - seriesType: 'bar_horizontal_percentage_stacked', - xAccessor: 'x-axis-column-layer0', - yConfig: [ - { - color: '#209280', - forAccessor: 'y-axis-column', - }, - { - color: '#d6bf57', - forAccessor: 'y-axis-column-1', - }, - { - color: '#cc5642', - forAccessor: 'y-axis-column-2', - }, - ], - }, - ], - legend: { - isVisible: true, - showSingleSeries: true, - position: 'right', - shouldTruncate: false, - legendSize: 'auto', - }, - preferredSeriesType: 'line', - tickLabelsVisibilitySettings: { - x: true, - yLeft: true, - yRight: true, - }, - valueLabels: 'hide', - }, - }, - title: 'Prefilled from exploratory view app', - visualizationType: 'lnsXY', -}; diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/sample_attribute_kpi.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/sample_attribute_kpi.ts deleted file mode 100644 index 49787f13048598..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/sample_attribute_kpi.ts +++ /dev/null @@ -1,116 +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 { mockDataView } from '../../rtl_helpers'; -import { RECORDS_FIELD } from '../constants'; - -export const sampleAttributeKpi = { - description: '', - references: [], - state: { - internalReferences: [ - { - id: 'apm-*', - name: 'indexpattern-datasource-current-indexpattern', - type: 'index-pattern', - }, - { - id: 'apm-*', - name: 'indexpattern-datasource-layer-layer0', - type: 'index-pattern', - }, - ], - adHocDataViews: { [mockDataView.title]: mockDataView.toSpec(false) }, - datasourceStates: { - formBased: { - layers: { - layer0: { - columnOrder: ['x-axis-column-layer0', 'y-axis-column-layer0-0'], - columns: { - 'x-axis-column-layer0': { - dataType: 'date', - isBucketed: true, - label: '@timestamp', - operationType: 'date_histogram', - params: { - interval: 'auto', - includeEmptyRows: true, - }, - scale: 'interval', - sourceField: '@timestamp', - }, - 'y-axis-column-layer0-0': { - dataType: 'number', - filter: { - language: 'kuery', - query: 'transaction.type: page-load and processor.event: transaction', - }, - isBucketed: false, - label: 'test-series', - operationType: 'count', - scale: 'ratio', - sourceField: RECORDS_FIELD, - }, - }, - incompleteColumns: {}, - }, - }, - }, - }, - filters: [], - query: { - language: 'kuery', - query: 'transaction.type: page-load and processor.event: transaction', - }, - visualization: { - axisTitlesVisibilitySettings: { - x: false, - yLeft: true, - yRight: true, - }, - curveType: 'CURVE_MONOTONE_X', - fittingFunction: 'Linear', - gridlinesVisibilitySettings: { - x: false, - yLeft: true, - yRight: true, - }, - layers: [ - { - accessors: ['y-axis-column-layer0-0'], - layerId: 'layer0', - layerType: 'data', - palette: undefined, - seriesType: 'line', - xAccessor: 'x-axis-column-layer0', - yConfig: [ - { - color: 'green', - forAccessor: 'y-axis-column-layer0-0', - axisMode: 'left', - }, - ], - }, - ], - legend: { - isVisible: true, - showSingleSeries: true, - position: 'right', - legendSize: 'auto', - shouldTruncate: false, - }, - preferredSeriesType: 'line', - tickLabelsVisibilitySettings: { - x: true, - yLeft: true, - yRight: true, - }, - valueLabels: 'hide', - }, - }, - title: 'Prefilled from exploratory view app', - visualizationType: 'lnsXY', -}; diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/sample_attribute_with_reference_lines.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/sample_attribute_with_reference_lines.ts deleted file mode 100644 index 66be0cf60083d7..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/sample_attribute_with_reference_lines.ts +++ /dev/null @@ -1,342 +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 { mockDataView } from '../../rtl_helpers'; -import { RECORDS_FIELD } from '../constants'; - -export const sampleAttributeWithReferenceLines = { - description: '', - references: [], - state: { - internalReferences: [ - { - id: 'apm-*', - name: 'indexpattern-datasource-current-indexpattern', - type: 'index-pattern', - }, - { - id: 'apm-*', - name: 'indexpattern-datasource-layer-layer0', - type: 'index-pattern', - }, - { - id: 'apm-*', - name: 'indexpattern-datasource-layer-layer0-reference-lines', - type: 'index-pattern', - }, - ], - adHocDataViews: { [mockDataView.title]: mockDataView.toSpec(false) }, - datasourceStates: { - formBased: { - layers: { - layer0: { - columnOrder: [ - 'x-axis-column-layer0', - 'y-axis-column-layer0-0', - 'y-axis-column-layer0X0', - 'y-axis-column-layer0X1', - 'y-axis-column-layer0X2', - 'y-axis-column-layer0X3', - ], - columns: { - 'x-axis-column-layer0': { - dataType: 'number', - isBucketed: true, - label: 'Page load time', - operationType: 'range', - params: { - maxBars: 'auto', - ranges: [ - { - from: 0, - label: '', - to: 1000, - }, - ], - type: 'histogram', - }, - scale: 'interval', - sourceField: 'transaction.duration.us', - }, - 'y-axis-column-layer0-0': { - customLabel: true, - dataType: 'number', - filter: { - language: 'kuery', - query: - 'transaction.type: page-load and processor.event: transaction and transaction.type : * and service.name: (elastic or kibana)', - }, - isBucketed: false, - label: 'test-series', - operationType: 'formula', - params: { - format: { - id: 'percent', - params: { - decimals: 0, - }, - }, - formula: - "count(kql='transaction.type: page-load and processor.event: transaction and transaction.type : * and service.name: (elastic or kibana)') / overall_sum(count(kql='transaction.type: page-load and processor.event: transaction and transaction.type : * and service.name: (elastic or kibana)'))", - isFormulaBroken: false, - }, - references: ['y-axis-column-layer0X3'], - }, - 'y-axis-column-layer0X0': { - customLabel: true, - dataType: 'number', - filter: { - language: 'kuery', - query: - 'transaction.type: page-load and processor.event: transaction and transaction.type : * and service.name: (elastic or kibana)', - }, - isBucketed: false, - label: 'Part of Pages loaded', - operationType: 'count', - params: { - emptyAsNull: false, - }, - scale: 'ratio', - sourceField: RECORDS_FIELD, - timeScale: undefined, - timeShift: undefined, - }, - 'y-axis-column-layer0X1': { - customLabel: true, - dataType: 'number', - filter: { - language: 'kuery', - query: - 'transaction.type: page-load and processor.event: transaction and transaction.type : * and service.name: (elastic or kibana)', - }, - isBucketed: false, - label: 'Part of Pages loaded', - operationType: 'count', - params: { - emptyAsNull: false, - }, - scale: 'ratio', - sourceField: RECORDS_FIELD, - timeScale: undefined, - timeShift: undefined, - }, - 'y-axis-column-layer0X2': { - customLabel: true, - dataType: 'number', - isBucketed: false, - label: 'Part of Pages loaded', - operationType: 'overall_sum', - params: undefined, - references: ['y-axis-column-layer0X1'], - scale: 'ratio', - }, - 'y-axis-column-layer0X3': { - customLabel: true, - dataType: 'number', - isBucketed: false, - label: 'Part of Pages loaded', - operationType: 'math', - params: { - tinymathAst: { - args: ['y-axis-column-layer0X0', 'y-axis-column-layer0X2'], - location: { - max: 288, - min: 0, - }, - name: 'divide', - text: "count(kql='transaction.type: page-load and processor.event: transaction and transaction.type : * and service.name: (elastic or kibana)') / overall_sum(count(kql='transaction.type: page-load and processor.event: transaction and transaction.type : * and service.name: (elastic or kibana)'))", - type: 'function', - }, - }, - references: ['y-axis-column-layer0X0', 'y-axis-column-layer0X2'], - scale: 'ratio', - }, - }, - incompleteColumns: {}, - }, - 'layer0-reference-lines': { - columnOrder: [ - '50th-percentile-reference-line-layer0-reference-lines', - '75th-percentile-reference-line-layer0-reference-lines', - '90th-percentile-reference-line-layer0-reference-lines', - '95th-percentile-reference-line-layer0-reference-lines', - '99th-percentile-reference-line-layer0-reference-lines', - ], - columns: { - '50th-percentile-reference-line-layer0-reference-lines': { - customLabel: true, - dataType: 'number', - isBucketed: false, - label: '50th', - operationType: 'percentile', - params: { - percentile: 50, - }, - scale: 'ratio', - sourceField: 'transaction.duration.us', - }, - '75th-percentile-reference-line-layer0-reference-lines': { - customLabel: true, - dataType: 'number', - isBucketed: false, - label: '75th', - operationType: 'percentile', - params: { - percentile: 75, - }, - scale: 'ratio', - sourceField: 'transaction.duration.us', - }, - '90th-percentile-reference-line-layer0-reference-lines': { - customLabel: true, - dataType: 'number', - isBucketed: false, - label: '90th', - operationType: 'percentile', - params: { - percentile: 90, - }, - scale: 'ratio', - sourceField: 'transaction.duration.us', - }, - '95th-percentile-reference-line-layer0-reference-lines': { - customLabel: true, - dataType: 'number', - isBucketed: false, - label: '95th', - operationType: 'percentile', - params: { - percentile: 95, - }, - scale: 'ratio', - sourceField: 'transaction.duration.us', - }, - '99th-percentile-reference-line-layer0-reference-lines': { - customLabel: true, - dataType: 'number', - isBucketed: false, - label: '99th', - operationType: 'percentile', - params: { - percentile: 99, - }, - scale: 'ratio', - sourceField: 'transaction.duration.us', - }, - }, - incompleteColumns: {}, - }, - }, - }, - }, - filters: [], - query: { - language: 'kuery', - query: - 'transaction.type: page-load and processor.event: transaction and transaction.type : * and service.name: (elastic or kibana) and transaction.duration.us < 60000000', - }, - visualization: { - axisTitlesVisibilitySettings: { - x: false, - yLeft: true, - yRight: true, - }, - curveType: 'CURVE_MONOTONE_X', - fittingFunction: 'Linear', - gridlinesVisibilitySettings: { - x: false, - yLeft: true, - yRight: true, - }, - layers: [ - { - accessors: ['y-axis-column-layer0-0'], - layerId: 'layer0', - layerType: 'data', - palette: undefined, - seriesType: 'line', - xAccessor: 'x-axis-column-layer0', - yConfig: [ - { - axisMode: 'left', - color: 'green', - forAccessor: 'y-axis-column-layer0-0', - }, - ], - }, - { - accessors: [ - '50th-percentile-reference-line-layer0-reference-lines', - '75th-percentile-reference-line-layer0-reference-lines', - '90th-percentile-reference-line-layer0-reference-lines', - '95th-percentile-reference-line-layer0-reference-lines', - '99th-percentile-reference-line-layer0-reference-lines', - ], - layerId: 'layer0-reference-lines', - layerType: 'referenceLine', - yConfig: [ - { - axisMode: 'bottom', - color: '#6092C0', - forAccessor: '50th-percentile-reference-line-layer0-reference-lines', - lineStyle: 'solid', - lineWidth: 2, - textVisibility: true, - }, - { - axisMode: 'bottom', - color: '#6092C0', - forAccessor: '75th-percentile-reference-line-layer0-reference-lines', - lineStyle: 'solid', - lineWidth: 2, - textVisibility: true, - }, - { - axisMode: 'bottom', - color: '#6092C0', - forAccessor: '90th-percentile-reference-line-layer0-reference-lines', - lineStyle: 'solid', - lineWidth: 2, - textVisibility: true, - }, - { - axisMode: 'bottom', - color: '#6092C0', - forAccessor: '95th-percentile-reference-line-layer0-reference-lines', - lineStyle: 'solid', - lineWidth: 2, - textVisibility: true, - }, - { - axisMode: 'bottom', - color: '#6092C0', - forAccessor: '99th-percentile-reference-line-layer0-reference-lines', - lineStyle: 'solid', - lineWidth: 2, - textVisibility: true, - }, - ], - }, - ], - legend: { - isVisible: true, - position: 'right', - showSingleSeries: true, - legendSize: 'auto', - shouldTruncate: false, - }, - preferredSeriesType: 'line', - tickLabelsVisibilitySettings: { - x: true, - yLeft: true, - yRight: true, - }, - valueLabels: 'hide', - }, - }, - title: 'Prefilled from exploratory view app', - visualizationType: 'lnsXY', -}; diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/test_data_view.json b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/test_data_view.json deleted file mode 100644 index 75020f5fd30be5..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/test_data_view.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "attributes": { - "fieldFormatMap": "{\"client.bytes\":{\"id\":\"bytes\"},\"client.nat.port\":{\"id\":\"string\"},\"client.port\":{\"id\":\"string\"},\"destination.bytes\":{\"id\":\"bytes\"},\"destination.nat.port\":{\"id\":\"string\"},\"destination.port\":{\"id\":\"string\"},\"event.duration\":{\"id\":\"duration\",\"params\":{\"inputFormat\":\"nanoseconds\",\"outputFormat\":\"asMilliseconds\",\"outputPrecision\":1}},\"event.sequence\":{\"id\":\"string\"},\"event.severity\":{\"id\":\"string\"},\"http.request.body.bytes\":{\"id\":\"bytes\"},\"http.request.bytes\":{\"id\":\"bytes\"},\"http.response.body.bytes\":{\"id\":\"bytes\"},\"http.response.bytes\":{\"id\":\"bytes\"},\"http.response.status_code\":{\"id\":\"string\"},\"log.syslog.facility.code\":{\"id\":\"string\"},\"log.syslog.priority\":{\"id\":\"string\"},\"network.bytes\":{\"id\":\"bytes\"},\"package.size\":{\"id\":\"string\"},\"process.parent.pgid\":{\"id\":\"string\"},\"process.parent.pid\":{\"id\":\"string\"},\"process.parent.ppid\":{\"id\":\"string\"},\"process.parent.thread.id\":{\"id\":\"string\"},\"process.pgid\":{\"id\":\"string\"},\"process.pid\":{\"id\":\"string\"},\"process.ppid\":{\"id\":\"string\"},\"process.thread.id\":{\"id\":\"string\"},\"server.bytes\":{\"id\":\"bytes\"},\"server.nat.port\":{\"id\":\"string\"},\"server.port\":{\"id\":\"string\"},\"source.bytes\":{\"id\":\"bytes\"},\"source.nat.port\":{\"id\":\"string\"},\"source.port\":{\"id\":\"string\"},\"system.cpu.total.norm.pct\":{\"id\":\"percent\"},\"system.memory.actual.free\":{\"id\":\"bytes\"},\"system.memory.total\":{\"id\":\"bytes\"},\"system.process.cgroup.memory.mem.limit.bytes\":{\"id\":\"bytes\"},\"system.process.cgroup.memory.mem.usage.bytes\":{\"id\":\"bytes\"},\"system.process.cpu.total.norm.pct\":{\"id\":\"percent\"},\"system.process.memory.rss.bytes\":{\"id\":\"bytes\"},\"system.process.memory.size\":{\"id\":\"bytes\"},\"url.port\":{\"id\":\"string\"}}", - "fields": "[{\"name\":\"system.memory.usage\",\"type\":\"number\",\"esTypes\":[\"float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"metadata_field\":false},{\"name\":\"@timestamp\",\"type\":\"date\",\"esTypes\":[\"date\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"_id\",\"type\":\"string\",\"esTypes\":[\"_id\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_index\",\"type\":\"string\",\"esTypes\":[\"_index\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_score\",\"type\":\"number\",\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_source\",\"type\":\"_source\",\"esTypes\":[\"_source\"],\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_type\",\"type\":\"string\",\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"agent.build.original\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"agent.ephemeral_id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"agent.hostname\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"agent.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"agent.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"agent.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"agent.version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"as.number\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"as.organization.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"as.organization.name.text\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false,\"subType\":{\"multi\":{\"parent\":\"as.organization.name\"}}},{\"name\":\"child.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.address\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.as.number\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.as.organization.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.as.organization.name.text\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false,\"subType\":{\"multi\":{\"parent\":\"client.as.organization.name\"}}},{\"name\":\"client.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.domain\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.geo.city_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.geo.continent_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.geo.country_iso_code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.geo.country_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.geo.location\",\"type\":\"geo_point\",\"esTypes\":[\"geo_point\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.geo.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.geo.region_iso_code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.geo.region_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.ip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.mac\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.nat.ip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.nat.port\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.packets\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.port\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.registered_domain\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.subdomain\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.top_level_domain\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.user.domain\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.user.email\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.user.full_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.user.full_name.text\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false,\"subType\":{\"multi\":{\"parent\":\"client.user.full_name\"}}},{\"name\":\"client.user.group.domain\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.user.group.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.user.group.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.user.hash\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.user.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.user.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"client.user.name.text\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false,\"subType\":{\"multi\":{\"parent\":\"client.user.name\"}}},{\"name\":\"client.user.roles\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"cloud.account.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"cloud.account.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"cloud.availability_zone\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"cloud.image.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"cloud.instance.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"cloud.instance.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"cloud.machine.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"cloud.project.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"cloud.project.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"cloud.provider\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"cloud.region\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"cloud.service.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"clr.gc.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"clr.gc.gen0size\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"clr.gc.gen1size\",\"type\":\"number\",\"esTypes\":[\"float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"clr.gc.gen2size\",\"type\":\"number\",\"esTypes\":[\"float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"clr.gc.gen3size\",\"type\":\"number\",\"esTypes\":[\"float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"code_signature.exists\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"code_signature.status\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"code_signature.subject_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"code_signature.trusted\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"code_signature.valid\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"container.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"container.image.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"container.image.tag\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"container.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"container.runtime\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.address\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.as.number\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.as.organization.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.as.organization.name.text\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false,\"subType\":{\"multi\":{\"parent\":\"destination.as.organization.name\"}}},{\"name\":\"destination.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.domain\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.geo.city_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.geo.continent_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.geo.country_iso_code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.geo.country_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.geo.location\",\"type\":\"geo_point\",\"esTypes\":[\"geo_point\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.geo.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.geo.region_iso_code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.geo.region_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.ip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.mac\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.nat.ip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.nat.port\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.packets\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.port\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.registered_domain\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.subdomain\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.top_level_domain\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.user.domain\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.user.email\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.user.full_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.user.full_name.text\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false,\"subType\":{\"multi\":{\"parent\":\"destination.user.full_name\"}}},{\"name\":\"destination.user.group.domain\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.user.group.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.user.group.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.user.hash\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.user.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.user.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.user.name.text\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false,\"subType\":{\"multi\":{\"parent\":\"destination.user.name\"}}},{\"name\":\"destination.user.roles\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dll.code_signature.exists\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dll.code_signature.status\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dll.code_signature.subject_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dll.code_signature.trusted\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dll.code_signature.valid\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dll.hash.md5\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dll.hash.sha1\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dll.hash.sha256\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dll.hash.sha512\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dll.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dll.path\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dll.pe.architecture\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dll.pe.company\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dll.pe.description\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dll.pe.file_version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dll.pe.imphash\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dll.pe.original_file_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dll.pe.product\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dns.answers.class\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dns.answers.data\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dns.answers.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dns.answers.ttl\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dns.answers.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dns.header_flags\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dns.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dns.op_code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dns.question.class\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dns.question.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dns.question.registered_domain\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dns.question.subdomain\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dns.question.top_level_domain\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dns.question.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dns.resolved_ip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dns.response_code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dns.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ecs.version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"error.code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"error.culprit\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"error.exception.code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"error.exception.handled\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"error.exception.message\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"error.exception.module\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"error.exception.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"error.grouping_key\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"error.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"error.log.level\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"error.log.logger_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"error.log.message\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"error.log.param_message\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"error.message\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"error.stack_trace\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":false,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"error.stack_trace.text\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false,\"subType\":{\"multi\":{\"parent\":\"error.stack_trace\"}}},{\"name\":\"error.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.action\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.category\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.created\",\"type\":\"date\",\"esTypes\":[\"date\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.dataset\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.duration\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.end\",\"type\":\"date\",\"esTypes\":[\"date\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.hash\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.ingested\",\"type\":\"date\",\"esTypes\":[\"date\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.kind\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.module\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.original\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":false,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.outcome\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.provider\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.reason\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.reference\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.risk_score\",\"type\":\"number\",\"esTypes\":[\"float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.risk_score_norm\",\"type\":\"number\",\"esTypes\":[\"float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.sequence\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.severity\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.start\",\"type\":\"date\",\"esTypes\":[\"date\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.timezone\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.url\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.accessed\",\"type\":\"date\",\"esTypes\":[\"date\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.attributes\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.code_signature.exists\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.code_signature.status\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.code_signature.subject_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.code_signature.trusted\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.code_signature.valid\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.created\",\"type\":\"date\",\"esTypes\":[\"date\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.ctime\",\"type\":\"date\",\"esTypes\":[\"date\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.device\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.directory\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.drive_letter\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.extension\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.gid\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.group\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.hash.md5\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.hash.sha1\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.hash.sha256\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.hash.sha512\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.inode\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.mime_type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.mode\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.mtime\",\"type\":\"date\",\"esTypes\":[\"date\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.owner\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.path\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.path.text\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false,\"subType\":{\"multi\":{\"parent\":\"file.path\"}}},{\"name\":\"file.pe.architecture\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.pe.company\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.pe.description\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.pe.file_version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.pe.imphash\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.pe.original_file_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.pe.product\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.size\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.target_path\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.target_path.text\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false,\"subType\":{\"multi\":{\"parent\":\"file.target_path\"}}},{\"name\":\"file.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.uid\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.x509.alternative_names\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.x509.issuer.common_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.x509.issuer.country\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.x509.issuer.distinguished_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.x509.issuer.locality\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.x509.issuer.organization\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.x509.issuer.organizational_unit\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.x509.issuer.state_or_province\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.x509.not_after\",\"type\":\"date\",\"esTypes\":[\"date\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.x509.not_before\",\"type\":\"date\",\"esTypes\":[\"date\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.x509.public_key_algorithm\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.x509.public_key_curve\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.x509.public_key_exponent\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":false,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.x509.public_key_size\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.x509.serial_number\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.x509.signature_algorithm\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.x509.subject.common_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.x509.subject.country\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.x509.subject.distinguished_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.x509.subject.locality\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.x509.subject.organization\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.x509.subject.organizational_unit\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.x509.subject.state_or_province\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.x509.version_number\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.city_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.continent_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.country_iso_code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.country_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.location\",\"type\":\"geo_point\",\"esTypes\":[\"geo_point\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.region_iso_code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.region_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"golang.goroutines\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"golang.heap.allocations.active\",\"type\":\"number\",\"esTypes\":[\"float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"golang.heap.allocations.allocated\",\"type\":\"number\",\"esTypes\":[\"float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"golang.heap.allocations.frees\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"golang.heap.allocations.idle\",\"type\":\"number\",\"esTypes\":[\"float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"golang.heap.allocations.mallocs\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"golang.heap.allocations.objects\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"golang.heap.allocations.total\",\"type\":\"number\",\"esTypes\":[\"float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"golang.heap.gc.cpu_fraction\",\"type\":\"number\",\"esTypes\":[\"float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"golang.heap.gc.next_gc_limit\",\"type\":\"number\",\"esTypes\":[\"float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"golang.heap.gc.total_count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"golang.heap.gc.total_pause.ns\",\"type\":\"number\",\"esTypes\":[\"float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"golang.heap.system.obtained\",\"type\":\"number\",\"esTypes\":[\"float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"golang.heap.system.released\",\"type\":\"number\",\"esTypes\":[\"float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"golang.heap.system.stack\",\"type\":\"number\",\"esTypes\":[\"float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"golang.heap.system.total\",\"type\":\"number\",\"esTypes\":[\"float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"group.domain\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"group.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"group.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"hash.md5\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"hash.sha1\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"hash.sha256\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"hash.sha512\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.architecture\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.containerized\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.domain\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.geo.city_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.geo.continent_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.geo.country_iso_code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.geo.country_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.geo.location\",\"type\":\"geo_point\",\"esTypes\":[\"geo_point\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.geo.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.geo.region_iso_code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.geo.region_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.hostname\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.ip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.mac\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.os.build\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.os.codename\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.os.family\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.os.full\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.os.full.text\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false,\"subType\":{\"multi\":{\"parent\":\"host.os.full\"}}},{\"name\":\"host.os.kernel\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.os.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.os.name.text\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false,\"subType\":{\"multi\":{\"parent\":\"host.os.name\"}}},{\"name\":\"host.os.platform\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.os.version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.uptime\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.user.domain\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.user.email\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.user.full_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.user.full_name.text\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false,\"subType\":{\"multi\":{\"parent\":\"host.user.full_name\"}}},{\"name\":\"host.user.group.domain\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.user.group.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.user.group.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.user.hash\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.user.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.user.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.user.name.text\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false,\"subType\":{\"multi\":{\"parent\":\"host.user.name\"}}},{\"name\":\"host.user.roles\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"http.request.body.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"http.request.body.content\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"http.request.body.content.text\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false,\"subType\":{\"multi\":{\"parent\":\"http.request.body.content\"}}},{\"name\":\"http.request.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"http.request.method\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"http.request.mime_type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"http.request.referrer\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"http.response.body.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"http.response.body.content\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"http.response.body.content.text\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false,\"subType\":{\"multi\":{\"parent\":\"http.response.body.content\"}}},{\"name\":\"http.response.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"http.response.finished\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"http.response.mime_type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"http.response.status_code\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"http.version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"interface.alias\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"interface.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"interface.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"jvm.gc.alloc\",\"type\":\"number\",\"esTypes\":[\"float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"jvm.gc.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"jvm.gc.time\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"jvm.memory.heap.committed\",\"type\":\"number\",\"esTypes\":[\"float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"jvm.memory.heap.max\",\"type\":\"number\",\"esTypes\":[\"float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"jvm.memory.heap.pool.committed\",\"type\":\"number\",\"esTypes\":[\"float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"jvm.memory.heap.pool.max\",\"type\":\"number\",\"esTypes\":[\"float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"jvm.memory.heap.pool.used\",\"type\":\"number\",\"esTypes\":[\"float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"jvm.memory.heap.used\",\"type\":\"number\",\"esTypes\":[\"float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"jvm.memory.non_heap.committed\",\"type\":\"number\",\"esTypes\":[\"float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"jvm.memory.non_heap.max\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"jvm.memory.non_heap.used\",\"type\":\"number\",\"esTypes\":[\"float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"jvm.thread.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.image\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.container.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.deployment.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.namespace\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.node.hostname\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.node.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.pod.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.pod.uid\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.replicaset.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"kubernetes.statefulset.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"labels.city\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"labels.company\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"labels.country_code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"labels.customer_email\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"labels.customer_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"labels.customer_tier\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"labels.env\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"labels.events_encoded\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"labels.events_failed\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"labels.events_original\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"labels.events_published\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"labels.foo\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"labels.git_rev\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"labels.hostname\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"labels.in_eu\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"labels.ip\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"labels.kibana_uuid\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"labels.lang\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"labels.lorem\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"labels.multi-line\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"labels.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"labels.plugin\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"labels.productId\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"labels.request_id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"labels.served_from_cache\",\"type\":\"conflict\",\"esTypes\":[\"boolean\",\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false,\"conflictDescriptions\":{\"boolean\":[\"apm-8.0.0-transaction-000001\"],\"keyword\":[\"apm-8.0.0-transaction-000002\"]}},{\"name\":\"labels.taskType\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"labels.this-is-a-very-long-tag-name-without-any-spaces\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"labels.u\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"labels.worker\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"log.file.path\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"log.level\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"log.logger\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"log.origin.file.line\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"log.origin.file.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"log.origin.function\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"log.original\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":false,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"log.syslog.facility.code\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"log.syslog.facility.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"log.syslog.priority\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"log.syslog.severity.code\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"log.syslog.severity.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"message\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"metricset.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"metricset.period\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"network.application\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"network.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"network.community_id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"network.direction\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"network.forwarded_ip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"network.iana_number\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"network.inner.vlan.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"network.inner.vlan.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"network.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"network.packets\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"network.protocol\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"network.transport\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"network.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"network.vlan.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"network.vlan.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nodejs.eventloop.delay.avg.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nodejs.eventloop.delay.ns\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nodejs.handles.active\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nodejs.memory.arrayBuffers.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nodejs.memory.external.bytes\",\"type\":\"number\",\"esTypes\":[\"float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nodejs.memory.heap.allocated.bytes\",\"type\":\"number\",\"esTypes\":[\"float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nodejs.memory.heap.used.bytes\",\"type\":\"number\",\"esTypes\":[\"float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nodejs.requests.active\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.egress.interface.alias\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.egress.interface.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.egress.interface.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.egress.vlan.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.egress.vlan.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.egress.zone\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.geo.city_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.geo.continent_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.geo.country_iso_code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.geo.country_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.geo.location\",\"type\":\"geo_point\",\"esTypes\":[\"geo_point\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.geo.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.geo.region_iso_code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.geo.region_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.hostname\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.ingress.interface.alias\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.ingress.interface.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.ingress.interface.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.ingress.vlan.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.ingress.vlan.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.ingress.zone\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.ip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.listening\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.mac\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.os.family\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.os.full\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.os.full.text\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false,\"subType\":{\"multi\":{\"parent\":\"observer.os.full\"}}},{\"name\":\"observer.os.kernel\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.os.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.os.name.text\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false,\"subType\":{\"multi\":{\"parent\":\"observer.os.name\"}}},{\"name\":\"observer.os.platform\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.os.version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.product\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.serial_number\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.vendor\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"observer.version_major\",\"type\":\"number\",\"esTypes\":[\"byte\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"organization.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"organization.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"organization.name.text\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false,\"subType\":{\"multi\":{\"parent\":\"organization.name\"}}},{\"name\":\"os.family\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"os.full\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"os.full.text\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false,\"subType\":{\"multi\":{\"parent\":\"os.full\"}}},{\"name\":\"os.kernel\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"os.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"os.name.text\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false,\"subType\":{\"multi\":{\"parent\":\"os.name\"}}},{\"name\":\"os.platform\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"os.version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"package.architecture\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"package.build_version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"package.checksum\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"package.description\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"package.install_scope\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"package.installed\",\"type\":\"date\",\"esTypes\":[\"date\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"package.license\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"package.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"package.path\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"package.reference\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"package.size\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"package.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"package.version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"parent.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"pe.architecture\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"pe.company\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"pe.description\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"pe.file_version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"pe.imphash\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"pe.original_file_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"pe.product\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.args\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.args_count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.code_signature.exists\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.code_signature.status\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.code_signature.subject_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.code_signature.trusted\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.code_signature.valid\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.command_line\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.command_line.text\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false,\"subType\":{\"multi\":{\"parent\":\"process.command_line\"}}},{\"name\":\"process.entity_id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.executable\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.executable.text\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false,\"subType\":{\"multi\":{\"parent\":\"process.executable\"}}},{\"name\":\"process.exit_code\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.hash.md5\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.hash.sha1\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.hash.sha256\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.hash.sha512\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.name.text\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false,\"subType\":{\"multi\":{\"parent\":\"process.name\"}}},{\"name\":\"process.parent.args\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.args_count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.code_signature.exists\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.code_signature.status\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.code_signature.subject_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.code_signature.trusted\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.code_signature.valid\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.command_line\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.command_line.text\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false,\"subType\":{\"multi\":{\"parent\":\"process.parent.command_line\"}}},{\"name\":\"process.parent.entity_id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.executable\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.executable.text\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false,\"subType\":{\"multi\":{\"parent\":\"process.parent.executable\"}}},{\"name\":\"process.parent.exit_code\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.hash.md5\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.hash.sha1\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.hash.sha256\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.hash.sha512\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.name.text\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false,\"subType\":{\"multi\":{\"parent\":\"process.parent.name\"}}},{\"name\":\"process.parent.pe.architecture\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.pe.company\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.pe.description\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.pe.file_version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.pe.imphash\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.pe.original_file_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.pe.product\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.pgid\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.pid\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.ppid\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.start\",\"type\":\"date\",\"esTypes\":[\"date\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.thread.id\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.thread.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.title\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.title.text\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false,\"subType\":{\"multi\":{\"parent\":\"process.parent.title\"}}},{\"name\":\"process.parent.uptime\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.working_directory\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.working_directory.text\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false,\"subType\":{\"multi\":{\"parent\":\"process.parent.working_directory\"}}},{\"name\":\"process.pe.architecture\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.pe.company\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.pe.description\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.pe.file_version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.pe.imphash\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.pe.original_file_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.pe.product\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.pgid\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.pid\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.ppid\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.start\",\"type\":\"date\",\"esTypes\":[\"date\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.id\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.title\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.uptime\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.working_directory\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.working_directory.text\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false,\"subType\":{\"multi\":{\"parent\":\"process.working_directory\"}}},{\"name\":\"processor.event\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"processor.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"profile.alloc_objects.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"profile.alloc_space.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"profile.cpu.ns\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"profile.duration\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"profile.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"profile.inuse_objects.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"profile.inuse_space.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"profile.samples.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"profile.stack.filename\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"profile.stack.function\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"profile.stack.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"profile.stack.line\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"profile.top.filename\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"profile.top.function\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"profile.top.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"profile.top.line\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"registry.data.bytes\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"registry.data.strings\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"registry.data.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"registry.hive\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"registry.key\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"registry.path\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"registry.value\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"related.hash\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"related.hosts\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"related.ip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"related.user\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ruby.gc.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ruby.heap.allocations.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ruby.heap.slots.free\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ruby.heap.slots.live\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ruby.threads\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rule.author\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rule.category\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rule.description\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rule.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rule.license\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rule.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rule.reference\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rule.ruleset\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rule.uuid\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rule.version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.address\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.as.number\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.as.organization.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.as.organization.name.text\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false,\"subType\":{\"multi\":{\"parent\":\"server.as.organization.name\"}}},{\"name\":\"server.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.domain\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.geo.city_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.geo.continent_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.geo.country_iso_code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.geo.country_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.geo.location\",\"type\":\"geo_point\",\"esTypes\":[\"geo_point\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.geo.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.geo.region_iso_code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.geo.region_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.ip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.mac\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.nat.ip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.nat.port\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.packets\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.port\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.registered_domain\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.subdomain\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.top_level_domain\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.user.domain\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.user.email\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.user.full_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.user.full_name.text\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false,\"subType\":{\"multi\":{\"parent\":\"server.user.full_name\"}}},{\"name\":\"server.user.group.domain\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.user.group.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.user.group.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.user.hash\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.user.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.user.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"server.user.name.text\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false,\"subType\":{\"multi\":{\"parent\":\"server.user.name\"}}},{\"name\":\"server.user.roles\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"service.environment\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"service.ephemeral_id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"service.framework.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"service.framework.version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"service.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"service.language.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"service.language.version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"service.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"service.node.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"service.runtime.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"service.runtime.version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"service.state\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"service.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"service.version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.address\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.as.number\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.as.organization.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.as.organization.name.text\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false,\"subType\":{\"multi\":{\"parent\":\"source.as.organization.name\"}}},{\"name\":\"source.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.domain\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.geo.city_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.geo.continent_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.geo.country_iso_code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.geo.country_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.geo.location\",\"type\":\"geo_point\",\"esTypes\":[\"geo_point\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.geo.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.geo.region_iso_code\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.geo.region_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.ip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.mac\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.nat.ip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.nat.port\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.packets\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.port\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.registered_domain\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.subdomain\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.top_level_domain\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.user.domain\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.user.email\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.user.full_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.user.full_name.text\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false,\"subType\":{\"multi\":{\"parent\":\"source.user.full_name\"}}},{\"name\":\"source.user.group.domain\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.user.group.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.user.group.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.user.hash\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.user.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.user.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.user.name.text\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false,\"subType\":{\"multi\":{\"parent\":\"source.user.name\"}}},{\"name\":\"source.user.roles\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"sourcemap.bundle_filepath\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"sourcemap.service.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"sourcemap.service.version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"span.action\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"span.db.link\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"span.db.rows_affected\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"span.destination.service.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"span.destination.service.resource\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"span.destination.service.response_time.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"span.destination.service.response_time.sum.us\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"span.destination.service.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"span.duration.us\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"span.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"span.message.age.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"span.message.queue.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"span.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"span.self_time.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"span.self_time.sum.us\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"span.start.us\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"span.subtype\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"span.sync\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"span.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.cpu.total.norm.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.memory.actual.free\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.memory.total\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.mem.limit.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.mem.usage.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cgroup.memory.stats.inactive_file.bytes\",\"type\":\"number\",\"esTypes\":[\"float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cpu.system.norm.pct\",\"type\":\"number\",\"esTypes\":[\"float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cpu.total.norm.pct\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.cpu.user.norm.pct\",\"type\":\"number\",\"esTypes\":[\"float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.memory.rss.bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"system.process.memory.size\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tags\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"threat.framework\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"threat.tactic.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"threat.tactic.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"threat.tactic.reference\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"threat.technique.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"threat.technique.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"threat.technique.name.text\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false,\"subType\":{\"multi\":{\"parent\":\"threat.technique.name\"}}},{\"name\":\"threat.technique.reference\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"threat.technique.subtechnique.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"threat.technique.subtechnique.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"threat.technique.subtechnique.name.text\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false,\"subType\":{\"multi\":{\"parent\":\"threat.technique.subtechnique.name\"}}},{\"name\":\"threat.technique.subtechnique.reference\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"timeseries.instance\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"timestamp.us\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.cipher\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.client.certificate\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.client.certificate_chain\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.client.hash.md5\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.client.hash.sha1\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.client.hash.sha256\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.client.issuer\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.client.ja3\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.client.not_after\",\"type\":\"date\",\"esTypes\":[\"date\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.client.not_before\",\"type\":\"date\",\"esTypes\":[\"date\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.client.server_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.client.subject\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.client.supported_ciphers\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.client.x509.alternative_names\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.client.x509.issuer.common_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.client.x509.issuer.country\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.client.x509.issuer.distinguished_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.client.x509.issuer.locality\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.client.x509.issuer.organization\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.client.x509.issuer.organizational_unit\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.client.x509.issuer.state_or_province\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.client.x509.not_after\",\"type\":\"date\",\"esTypes\":[\"date\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.client.x509.not_before\",\"type\":\"date\",\"esTypes\":[\"date\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.client.x509.public_key_algorithm\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.client.x509.public_key_curve\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.client.x509.public_key_exponent\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":false,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.client.x509.public_key_size\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.client.x509.serial_number\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.client.x509.signature_algorithm\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.client.x509.subject.common_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.client.x509.subject.country\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.client.x509.subject.distinguished_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.client.x509.subject.locality\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.client.x509.subject.organization\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.client.x509.subject.organizational_unit\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.client.x509.subject.state_or_province\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.client.x509.version_number\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.curve\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.established\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.next_protocol\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.resumed\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.server.certificate\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.server.certificate_chain\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.server.hash.md5\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.server.hash.sha1\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.server.hash.sha256\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.server.issuer\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.server.ja3s\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.server.not_after\",\"type\":\"date\",\"esTypes\":[\"date\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.server.not_before\",\"type\":\"date\",\"esTypes\":[\"date\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.server.subject\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.server.x509.alternative_names\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.server.x509.issuer.common_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.server.x509.issuer.country\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.server.x509.issuer.distinguished_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.server.x509.issuer.locality\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.server.x509.issuer.organization\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.server.x509.issuer.organizational_unit\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.server.x509.issuer.state_or_province\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.server.x509.not_after\",\"type\":\"date\",\"esTypes\":[\"date\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.server.x509.not_before\",\"type\":\"date\",\"esTypes\":[\"date\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.server.x509.public_key_algorithm\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.server.x509.public_key_curve\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.server.x509.public_key_exponent\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":false,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.server.x509.public_key_size\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.server.x509.serial_number\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.server.x509.signature_algorithm\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.server.x509.subject.common_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.server.x509.subject.country\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.server.x509.subject.distinguished_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.server.x509.subject.locality\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.server.x509.subject.organization\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.server.x509.subject.organizational_unit\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.server.x509.subject.state_or_province\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.server.x509.version_number\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"tls.version_protocol\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"trace.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"transaction.breakdown.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"transaction.duration.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"transaction.duration.histogram\",\"type\":\"histogram\",\"esTypes\":[\"histogram\"],\"searchable\":false,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"transaction.duration.sum.us\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"transaction.duration.us\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"transaction.experience.cls\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"transaction.experience.fid\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"transaction.experience.longtask.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"transaction.experience.longtask.max\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"transaction.experience.longtask.sum\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"transaction.experience.tbt\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"transaction.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"transaction.marks.agent.domComplete\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"transaction.marks.agent.domInteractive\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"transaction.marks.agent.firstContentfulPaint\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"transaction.marks.agent.largestContentfulPaint\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"transaction.marks.agent.timeToFirstByte\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"transaction.marks.navigationTiming.connectEnd\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"transaction.marks.navigationTiming.connectStart\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"transaction.marks.navigationTiming.domComplete\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"transaction.marks.navigationTiming.domContentLoadedEventEnd\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"transaction.marks.navigationTiming.domContentLoadedEventStart\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"transaction.marks.navigationTiming.domInteractive\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"transaction.marks.navigationTiming.domLoading\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"transaction.marks.navigationTiming.domainLookupEnd\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"transaction.marks.navigationTiming.domainLookupStart\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"transaction.marks.navigationTiming.fetchStart\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"transaction.marks.navigationTiming.loadEventEnd\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"transaction.marks.navigationTiming.loadEventStart\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"transaction.marks.navigationTiming.requestStart\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"transaction.marks.navigationTiming.responseEnd\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"transaction.marks.navigationTiming.responseStart\",\"type\":\"number\",\"esTypes\":[\"scaled_float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"transaction.message.age.ms\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"transaction.message.queue.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"transaction.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"transaction.name.text\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false,\"subType\":{\"multi\":{\"parent\":\"transaction.name\"}}},{\"name\":\"transaction.result\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"transaction.root\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"transaction.sampled\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"transaction.self_time.count\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"transaction.self_time.sum.us\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"transaction.span_count.dropped\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"transaction.type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"url.domain\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"url.extension\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"url.fragment\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"url.full\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"url.original\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"url.original.text\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false,\"subType\":{\"multi\":{\"parent\":\"url.original\"}}},{\"name\":\"url.password\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"url.path\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"url.port\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"url.query\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"url.registered_domain\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"url.scheme\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"url.subdomain\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"url.top_level_domain\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"url.username\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user.domain\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user.email\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user.full_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user.full_name.text\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false,\"subType\":{\"multi\":{\"parent\":\"user.full_name\"}}},{\"name\":\"user.group.domain\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user.group.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user.group.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user.hash\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user.roles\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user_agent.device.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user_agent.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user_agent.original\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user_agent.original.text\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false,\"subType\":{\"multi\":{\"parent\":\"user_agent.original\"}}},{\"name\":\"user_agent.os.family\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user_agent.os.full\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user_agent.os.kernel\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user_agent.os.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user_agent.os.platform\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user_agent.os.version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user_agent.version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"vlan.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"vlan.name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"vulnerability.category\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"vulnerability.classification\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"vulnerability.description\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"vulnerability.description.text\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false,\"subType\":{\"multi\":{\"parent\":\"vulnerability.description\"}}},{\"name\":\"vulnerability.enumeration\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"vulnerability.id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"vulnerability.reference\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"vulnerability.report_id\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"vulnerability.scanner.vendor\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"vulnerability.score.base\",\"type\":\"number\",\"esTypes\":[\"float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"vulnerability.score.environmental\",\"type\":\"number\",\"esTypes\":[\"float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"vulnerability.score.temporal\",\"type\":\"number\",\"esTypes\":[\"float\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"vulnerability.score.version\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"vulnerability.severity\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"x509.alternative_names\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"x509.issuer.common_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"x509.issuer.country\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"x509.issuer.distinguished_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"x509.issuer.locality\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"x509.issuer.organization\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"x509.issuer.organizational_unit\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"x509.issuer.state_or_province\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"x509.not_after\",\"type\":\"date\",\"esTypes\":[\"date\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"x509.not_before\",\"type\":\"date\",\"esTypes\":[\"date\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"x509.public_key_algorithm\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"x509.public_key_curve\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"x509.public_key_exponent\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":false,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"x509.public_key_size\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"x509.serial_number\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"x509.signature_algorithm\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"x509.subject.common_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"x509.subject.country\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"x509.subject.distinguished_name\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"x509.subject.locality\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"x509.subject.organization\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"x509.subject.organizational_unit\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"x509.subject.state_or_province\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"x509.version_number\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true}]", - "sourceFilters": "[{\"value\":\"sourcemap.sourcemap\"}]", - "timeFieldName": "@timestamp" - }, - "id": "apm-*", - "type": "index-pattern", - "version": "1" -} diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/test_formula_metric_attribute.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/test_formula_metric_attribute.ts deleted file mode 100644 index d1f63100ecbe85..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/test_formula_metric_attribute.ts +++ /dev/null @@ -1,190 +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 { mockDataView } from '../../rtl_helpers'; - -export const sampleMetricFormulaAttribute = { - description: '', - references: [], - state: { - adHocDataViews: { [mockDataView.title]: mockDataView.toSpec(false) }, - internalReferences: [ - { - id: 'apm-*', - name: 'indexpattern-datasource-current-indexpattern', - type: 'index-pattern', - }, - { - id: 'apm-*', - name: 'indexpattern-datasource-layer-layer0', - type: 'index-pattern', - }, - ], - datasourceStates: { - formBased: { - layers: { - layer0: { - columnOrder: [ - 'layer-0-column-1X0', - 'layer-0-column-1X1', - 'layer-0-column-1X2', - 'layer-0-column-1', - ], - columns: { - 'layer-0-column-1': { - customLabel: true, - dataType: 'number', - filter: { - language: 'kuery', - query: 'summary.up: *', - }, - isBucketed: false, - label: 'Availability', - operationType: 'formula', - params: { - format: { - id: 'percent', - params: { - decimals: 1, - }, - }, - formula: "1- (count(kql='summary.down > 0') / count())", - isFormulaBroken: false, - }, - references: ['layer-0-column-1X2'], - }, - 'layer-0-column-1X0': { - customLabel: true, - dataType: 'number', - filter: { - language: 'kuery', - query: '(summary.up: *) AND (summary.down > 0)', - }, - isBucketed: false, - label: 'Part of Availability', - operationType: 'count', - params: { - emptyAsNull: false, - }, - scale: 'ratio', - sourceField: '___records___', - }, - 'layer-0-column-1X1': { - customLabel: true, - dataType: 'number', - filter: { - language: 'kuery', - query: 'summary.up: *', - }, - isBucketed: false, - label: 'Part of Availability', - operationType: 'count', - params: { - emptyAsNull: false, - }, - scale: 'ratio', - sourceField: '___records___', - }, - 'layer-0-column-1X2': { - customLabel: true, - dataType: 'number', - isBucketed: false, - label: 'Part of Availability', - operationType: 'math', - params: { - tinymathAst: { - args: [ - 1, - { - args: ['layer-0-column-1X0', 'layer-0-column-1X1'], - location: { - max: 44, - min: 2, - }, - name: 'divide', - text: " (count(kql='summary.down > 0') / count())", - type: 'function', - }, - ], - location: { - max: 44, - min: 0, - }, - name: 'subtract', - text: "1- (count(kql='summary.down > 0') / count())", - type: 'function', - }, - }, - references: ['layer-0-column-1X0', 'layer-0-column-1X1'], - scale: 'ratio', - }, - }, - indexPatternId: 'apm-*', - }, - }, - }, - }, - filters: [], - query: { - language: 'kuery', - query: '', - }, - visualization: { - accessor: 'layer-0-column-1', - colorMode: 'Labels', - layerId: 'layer0', - layerType: 'data', - palette: { - name: 'custom', - params: { - colorStops: [ - { - color: '#cc5642', - stop: 0.8, - }, - { - color: '#d6bf57', - stop: 0.9, - }, - { - color: '#209280', - stop: 0.95, - }, - ], - continuity: 'above', - maxSteps: 5, - name: 'custom', - progression: 'fixed', - rangeMax: 1, - rangeMin: 0, - rangeType: 'number', - reverse: false, - steps: 3, - stops: [ - { - color: '#cc5642', - stop: 0.9, - }, - { - color: '#d6bf57', - stop: 0.95, - }, - { - color: '#209280', - stop: 1.9903347477604902, - }, - ], - }, - type: 'palette', - }, - size: 's', - titlePosition: 'bottom', - }, - }, - title: 'Prefilled from exploratory view app', - visualizationType: 'lnsLegacyMetric', -}; diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/utils.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/utils.ts deleted file mode 100644 index c8848e50f917f3..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/utils.ts +++ /dev/null @@ -1,127 +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 rison from '@kbn/rison'; -import { - buildQueryFilter, - PhraseFilter, - ExistsFilter, - buildPhraseFilter as esBuildPhraseFilter, - buildPhrasesFilter as esBuildPhrasesFilter, - buildExistsFilter as esBuildExistsFilter, -} from '@kbn/es-query'; -import type { DataView } from '@kbn/data-views-plugin/common'; -import { PersistableFilter } from '@kbn/lens-plugin/common'; -import type { ReportViewType, UrlFilter } from '../types'; -import type { AllSeries, AllShortSeries } from '../hooks/use_series_storage'; -import { convertToShortUrl, encodeUriIfNeeded } from './exploratory_view_url'; - -export function createExploratoryViewRoutePath({ - reportType, - allSeries, -}: { - reportType: ReportViewType; - allSeries: AllSeries; -}) { - const allShortSeries: AllShortSeries = allSeries.map((series) => convertToShortUrl(series)); - - return `/exploratory-view/#?reportType=${reportType}&sr=${encodeUriIfNeeded( - rison.encode(allShortSeries) - )}`; -} - -export function buildPhraseFilter(field: string, value: string, dataView?: DataView) { - const fieldMeta = dataView?.fields.find((fieldT) => fieldT.name === field); - if (fieldMeta && dataView) { - return [esBuildPhraseFilter(fieldMeta, value, dataView)]; - } - return []; -} - -export function getQueryFilter(field: string, value: string[], dataView?: DataView) { - const fieldMeta = dataView?.fields.find((fieldT) => fieldT.name === field); - if (fieldMeta && dataView) { - return value.map((val) => - buildQueryFilter( - { - query_string: { - fields: [field], - query: `*${val}*`, - }, - }, - dataView.id!, - '' - ) - ); - } - - return []; -} - -export function buildPhrasesFilter( - field: string, - value: Array, - dataView?: DataView -) { - const fieldMeta = dataView?.fields.find((fieldT) => fieldT.name === field); - if (fieldMeta && dataView) { - if (value.length === 1) { - return [esBuildPhraseFilter(fieldMeta, value[0], dataView)]; - } - return [esBuildPhrasesFilter(fieldMeta, value, dataView)]; - } - return []; -} - -export function buildExistsFilter(field: string, dataView?: DataView) { - const fieldMeta = dataView?.fields.find((fieldT) => fieldT.name === field); - if (fieldMeta && dataView) { - return [esBuildExistsFilter(fieldMeta, dataView)]; - } - return []; -} - -type FiltersType = Array; - -export function urlFilterToPersistedFilter({ - urlFilters, - initFilters, - dataView, -}: { - urlFilters: UrlFilter[]; - initFilters?: FiltersType; - dataView: DataView; -}) { - const parsedFilters: FiltersType = initFilters ? [...initFilters] : []; - - urlFilters.forEach( - ({ field, values = [], notValues = [], wildcards = [], notWildcards = ([] = []) }) => { - if (values.length > 0) { - const filter = buildPhrasesFilter(field, values, dataView); - parsedFilters.push(...filter); - } - - if (notValues.length > 0) { - const filter = buildPhrasesFilter(field, notValues, dataView)[0]; - filter.meta.negate = true; - parsedFilters.push(filter); - } - - if (wildcards.length > 0) { - const filter = getQueryFilter(field, wildcards, dataView); - parsedFilters.push(...filter); - } - - if (notWildcards.length > 0) { - const filter = getQueryFilter(field, notWildcards, dataView)[0]; - filter.meta.negate = true; - parsedFilters.push(filter); - } - } - ); - - return parsedFilters; -} diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/contexts/exploratory_view_config.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/contexts/exploratory_view_config.tsx deleted file mode 100644 index c0249711985101..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/contexts/exploratory_view_config.tsx +++ /dev/null @@ -1,74 +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 React, { createContext, useContext, useState } from 'react'; -import { AppMountParameters } from '@kbn/core/public'; -import { i18n } from '@kbn/i18n'; -import type { AppDataType, ConfigProps, ReportViewType, SeriesConfig } from '../types'; - -export type ReportConfigMap = Record SeriesConfig>>; - -interface ExploratoryViewContextValue { - dataTypes: Array<{ id: AppDataType; label: string }>; - reportTypes: Array<{ - reportType: ReportViewType | typeof SELECT_REPORT_TYPE; - label: string; - }>; - reportConfigMap: ReportConfigMap; - asPanel?: boolean; - setHeaderActionMenu: AppMountParameters['setHeaderActionMenu']; - theme$: AppMountParameters['theme$']; - isEditMode?: boolean; - setIsEditMode?: React.Dispatch>; -} - -export const ExploratoryViewContext = createContext( - {} as ExploratoryViewContextValue -); - -export function ExploratoryViewContextProvider({ - children, - reportTypes, - dataTypes, - reportConfigMap, - setHeaderActionMenu, - asPanel = true, - theme$, -}: { children: JSX.Element } & ExploratoryViewContextValue) { - const [isEditMode, setIsEditMode] = useState(false); - - const value = { - asPanel, - reportTypes, - dataTypes, - reportConfigMap, - setHeaderActionMenu, - theme$, - isEditMode, - setIsEditMode, - }; - - return ( - {children} - ); -} - -export function useExploratoryView() { - const context = useContext(ExploratoryViewContext); - - if (context === undefined) { - throw new Error('useExploratoryView must be used within a ExploratoryViewContextProvider'); - } - return context; -} - -export const SELECT_REPORT_TYPE = i18n.translate( - 'xpack.observability.expView.seriesBuilder.selectReportType', - { - defaultMessage: 'No report type selected', - } -); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/embeddable/embeddable.test.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/embeddable/embeddable.test.tsx deleted file mode 100644 index f10d188c6b566f..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/embeddable/embeddable.test.tsx +++ /dev/null @@ -1,197 +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 React from 'react'; -import Embeddable from './embeddable'; -import { LensPublicStart } from '@kbn/lens-plugin/public'; -import { DataViewState } from '../hooks/use_app_data_view'; -import { render } from '../rtl_helpers'; -import { AddToCaseAction } from '../header/add_to_case_action'; -import { ActionTypes } from './use_actions'; - -jest.mock('../header/add_to_case_action', () => ({ - AddToCaseAction: jest.fn(() =>
mockAddToCaseAction
), -})); - -const mockLensAttrs = { - hidePanelTitles: true, - description: '', - visualizationType: 'lnsMetric', - state: { - visualization: { - accessor: 'b00c65ea-32be-4163-bfc8-f795b1ef9d06', - layerId: '416b6fad-1923-4f6a-a2df-b223bb287e30', - layerType: 'data', - }, - query: { - language: 'kuery', - query: '', - }, - filters: [], - datasourceStates: { - formBased: { - layers: { - '416b6fad-1923-4f6a-a2df-b223bb287e30': { - columnOrder: ['b00c65ea-32be-4163-bfc8-f795b1ef9d06'], - columns: { - 'b00c65ea-32be-4163-bfc8-f795b1ef9d06': { - customLabel: true, - dataType: 'number', - isBucketed: false, - label: ' ', - operationType: 'unique_count', - scale: 'ratio', - sourceField: 'host.name', - }, - }, - incompleteColumns: {}, - }, - }, - }, - }, - }, - references: [ - { - type: 'index-pattern', - id: 'security-solution-default', - name: 'indexpattern-datasource-current-indexpattern', - }, - { - type: 'index-pattern', - id: 'security-solution-default', - name: 'indexpattern-datasource-layer-416b6fad-1923-4f6a-a2df-b223bb287e30', - }, - { - type: 'tag', - id: 'security-solution-default', - name: 'tag-ref-security-solution-default', - }, - ], -}; -const mockTimeRange = { - from: '2022-02-15T16:00:00.000Z', - to: '2022-02-16T15:59:59.999Z', -}; -const mockOwner = 'securitySolution'; -const mockAppId = 'securitySolutionUI'; -const mockDataViews = {} as DataViewState; -const mockReportType = 'kpi-over-time'; -const mockTitle = 'mockTitle'; -const mockLens = { - EmbeddableComponent: jest.fn((props) => { - return ( -
- mockEmbeddableComponent -
- ); - }), - SaveModalComponent: jest.fn(() =>
mockSaveModalComponent
), -} as unknown as LensPublicStart; -const mockActions: ActionTypes[] = ['addToCase', 'openInLens']; - -describe('Embeddable', () => { - beforeEach(() => { - jest.clearAllMocks(); - }); - - it('renders title', async () => { - const { container, getByText } = render( - - ); - expect(container.querySelector(`[data-test-subj="exploratoryView-title"]`)).toBeInTheDocument(); - expect(getByText(mockTitle)).toBeInTheDocument(); - }); - - it('renders no title if it is not given', async () => { - const { container } = render( - - ); - expect( - container.querySelector(`[data-test-subj="exploratoryView-title"]`) - ).not.toBeInTheDocument(); - }); - - it('renders lens component', () => { - const { container } = render( - - ); - - expect( - container.querySelector(`[data-test-subj="exploratoryView-singleMetric"]`) - ).not.toBeInTheDocument(); - expect(container.querySelector(`[data-test-subj="exploratoryView"]`)).toBeInTheDocument(); - expect((mockLens.EmbeddableComponent as jest.Mock).mock.calls[0][0].id).toEqual( - 'exploratoryView' - ); - expect((mockLens.EmbeddableComponent as jest.Mock).mock.calls[0][0].attributes).toEqual( - mockLensAttrs - ); - expect((mockLens.EmbeddableComponent as jest.Mock).mock.calls[0][0].timeRange).toEqual( - mockTimeRange - ); - expect((mockLens.EmbeddableComponent as jest.Mock).mock.calls[0][0].timeRange).toEqual( - mockTimeRange - ); - expect((mockLens.EmbeddableComponent as jest.Mock).mock.calls[0][0].withDefaultActions).toEqual( - true - ); - }); - - it('renders AddToCaseAction', () => { - render( - - ); - - expect((AddToCaseAction as jest.Mock).mock.calls[0][0].timeRange).toEqual(mockTimeRange); - expect((AddToCaseAction as jest.Mock).mock.calls[0][0].appId).toEqual(mockAppId); - expect((AddToCaseAction as jest.Mock).mock.calls[0][0].lensAttributes).toEqual(mockLensAttrs); - expect((AddToCaseAction as jest.Mock).mock.calls[0][0].owner).toEqual(mockOwner); - }); -}); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/embeddable/embeddable.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/embeddable/embeddable.tsx deleted file mode 100644 index be9a04e05e73bf..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/embeddable/embeddable.tsx +++ /dev/null @@ -1,317 +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 { Position } from '@elastic/charts'; -import React, { useState } from 'react'; -import { EuiFlexGroup, EuiFlexItem, EuiText, EuiTitle } from '@elastic/eui'; -import { - FormulaPublicApi, - LensEmbeddableInput, - LensPublicStart, - XYState, -} from '@kbn/lens-plugin/public'; -import { ViewMode } from '@kbn/embeddable-plugin/common'; -import styled from 'styled-components'; -import { useKibanaSpace } from '../../../../hooks/use_kibana_space'; -import { HeatMapLensAttributes } from '../configurations/lens_attributes/heatmap_attributes'; -import { SingleMetricLensAttributes } from '../configurations/lens_attributes/single_metric_attributes'; -import { AllSeries, ReportTypes, useTheme } from '../../../..'; -import { LayerConfig, LensAttributes } from '../configurations/lens_attributes'; -import { AppDataType, ReportViewType } from '../types'; -import { getLayerConfigs } from '../hooks/use_lens_attributes'; -import { OperationTypeComponent } from '../series_editor/columns/operation_type_select'; -import { DataViewState } from '../hooks/use_app_data_view'; -import { ReportConfigMap } from '../contexts/exploratory_view_config'; -import { obsvReportConfigMap } from '../obsv_exploratory_view'; -import { ActionTypes, useActions } from './use_actions'; -import { AddToCaseAction } from '../header/add_to_case_action'; -import { observabilityFeatureId } from '../../../../../common'; - -export interface ExploratoryEmbeddableProps { - id?: string; - appId?: 'securitySolutionUI' | 'observability'; - appendTitle?: JSX.Element; - attributes?: AllSeries; - axisTitlesVisibility?: XYState['axisTitlesVisibilitySettings']; - gridlinesVisibilitySettings?: XYState['gridlinesVisibilitySettings']; - customHeight?: string; - customLensAttrs?: any; // Takes LensAttributes - customTimeRange?: { from: string; to: string }; // required if rendered with LensAttributes - dataTypesIndexPatterns?: Partial>; - isSingleMetric?: boolean; - legendIsVisible?: boolean; - legendPosition?: Position; - hideTicks?: boolean; - onBrushEnd?: (param: { range: number[] }) => void; - onLoad?: (loading: boolean) => void; - caseOwner?: string; - reportConfigMap?: ReportConfigMap; - reportType: ReportViewType; - showCalculationMethod?: boolean; - title?: string | JSX.Element; - withActions?: boolean | ActionTypes[]; - align?: 'left' | 'right' | 'center'; - sparklineMode?: boolean; - noLabel?: boolean; - fontSize?: number; - lineHeight?: number; - dataTestSubj?: string; - searchSessionId?: string; -} - -export interface ExploratoryEmbeddableComponentProps extends ExploratoryEmbeddableProps { - lens: LensPublicStart; - dataViewState: DataViewState; - lensFormulaHelper?: FormulaPublicApi; -} - -// eslint-disable-next-line import/no-default-export -export default function Embeddable({ - appId, - appendTitle, - attributes = [], - axisTitlesVisibility, - gridlinesVisibilitySettings, - customHeight, - customLensAttrs, - customTimeRange, - dataViewState, - legendIsVisible, - legendPosition, - lens, - onBrushEnd, - caseOwner = observabilityFeatureId, - reportConfigMap = {}, - reportType, - showCalculationMethod = false, - title, - withActions = true, - lensFormulaHelper, - hideTicks, - align, - noLabel, - fontSize = 27, - lineHeight = 32, - searchSessionId, - onLoad, -}: ExploratoryEmbeddableComponentProps) { - const LensComponent = lens?.EmbeddableComponent; - const LensSaveModalComponent = lens?.SaveModalComponent; - - const [isSaveOpen, setIsSaveOpen] = useState(false); - const [isAddToCaseOpen, setAddToCaseOpen] = useState(false); - - const spaceId = useKibanaSpace(); - - const series = Object.entries(attributes)[0]?.[1]; - - const [operationType, setOperationType] = useState(series?.operationType); - const theme = useTheme(); - - const layerConfigs: LayerConfig[] = getLayerConfigs( - attributes, - reportType, - theme, - dataViewState, - { ...reportConfigMap, ...obsvReportConfigMap }, - spaceId.space?.id - ); - - let lensAttributes; - let attributesJSON = customLensAttrs; - if (!customLensAttrs) { - try { - if (reportType === ReportTypes.SINGLE_METRIC) { - lensAttributes = new SingleMetricLensAttributes( - layerConfigs, - reportType, - lensFormulaHelper! - ); - attributesJSON = lensAttributes?.getJSON('lnsLegacyMetric'); - } else if (reportType === ReportTypes.HEATMAP) { - lensAttributes = new HeatMapLensAttributes(layerConfigs, reportType, lensFormulaHelper!); - attributesJSON = lensAttributes?.getJSON('lnsHeatmap'); - } else { - lensAttributes = new LensAttributes(layerConfigs, reportType, lensFormulaHelper); - attributesJSON = lensAttributes?.getJSON(); - } - // eslint-disable-next-line no-empty - } catch (error) {} - } - - const timeRange = customTimeRange ?? series?.time; - - const actions = useActions({ - withActions, - attributes, - reportType, - appId, - setIsSaveOpen, - setAddToCaseOpen, - lensAttributes: attributesJSON, - timeRange, - }); - - if (!attributesJSON) { - return null; - } - - if (typeof axisTitlesVisibility !== 'undefined') { - (attributesJSON.state.visualization as XYState).axisTitlesVisibilitySettings = - axisTitlesVisibility; - } - - if (typeof gridlinesVisibilitySettings !== 'undefined') { - (attributesJSON.state.visualization as XYState).gridlinesVisibilitySettings = - gridlinesVisibilitySettings; - } - - if (typeof legendIsVisible !== 'undefined') { - (attributesJSON.state.visualization as XYState).legend.isVisible = legendIsVisible; - } - if (typeof legendPosition !== 'undefined') { - (attributesJSON.state.visualization as XYState).legend.position = legendPosition; - } - - if (hideTicks) { - (attributesJSON.state.visualization as XYState).tickLabelsVisibilitySettings = { - x: false, - yRight: false, - yLeft: false, - }; - } - - if (!attributesJSON && layerConfigs.length < 1) { - return null; - } - - if (!LensComponent) { - return No lens component; - } - - attributesJSON.state.searchSessionId = searchSessionId; - attributesJSON.searchSessionId = searchSessionId; - - return ( - - {(title || showCalculationMethod || appendTitle) && ( - - {title && ( - - -

{title}

-
-
- )} - {showCalculationMethod && ( - - { - setOperationType(val); - }} - /> - - )} - {appendTitle && appendTitle} -
- )} - - - {isSaveOpen && attributesJSON && ( - setIsSaveOpen(false)} - // if we want to do anything after the viz is saved - // right now there is no action, so an empty function - onSave={() => {}} - /> - )} - -
- ); -} - -const Wrapper = styled.div<{ - $customHeight?: string | number; - align?: 'left' | 'right' | 'center'; - noLabel?: boolean; - fontSize?: number; - lineHeight?: number; -}>` - height: ${(props) => (props.$customHeight ? `${props.$customHeight};` : `100%;`)}; - position: relative; - &&& { - > :nth-child(2) { - height: ${(props) => - props.$customHeight ? `${props.$customHeight};` : `calc(100% - 32px);`}; - } - .expExpressionRenderer__expression { - padding: 0 !important; - } - - .legacyMtrVis { - > :first-child { - justify-content: ${(props) => - props.align === 'left' - ? `flex-start;` - : props.align === 'right' - ? `flex-end;` - : 'center;'}; - } - justify-content: flex-end; - .legacyMtrVis__container { - padding: 0; - > :nth-child(2) { - ${({ noLabel }) => - noLabel && - ` display: none; - `} - } - } - .legacyMtrVis__value { - line-height: ${({ lineHeight }) => lineHeight}px !important; - font-size: ${({ fontSize }) => fontSize}px !important; - } - > :first-child { - transform: none !important; - } - } - - .euiLoadingChart { - position: absolute; - top: 50%; - right: 50%; - transform: translate(50%, -50%); - } - } -`; diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/embeddable/index.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/embeddable/index.tsx deleted file mode 100644 index 48747afe53305e..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/embeddable/index.tsx +++ /dev/null @@ -1,179 +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 React, { useCallback, useMemo, useState, useEffect } from 'react'; -import { EuiFlexGroup, EuiFlexItem, EuiLoadingSpinner } from '@elastic/eui'; -import { EuiThemeProvider } from '@kbn/kibana-react-plugin/common'; -import type { CoreStart } from '@kbn/core/public'; -import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; -import { EuiErrorBoundary } from '@elastic/eui'; -import styled from 'styled-components'; -import { DataView } from '@kbn/data-views-plugin/common'; -import { FormulaPublicApi } from '@kbn/lens-plugin/public'; -import { i18n } from '@kbn/i18n'; -import { useAppDataView } from './use_app_data_view'; -import { ObservabilityPublicPluginsStart, useFetcher } from '../../../..'; -import type { ExploratoryEmbeddableProps, ExploratoryEmbeddableComponentProps } from './embeddable'; - -const Embeddable = React.lazy(() => import('./embeddable')); - -function ExploratoryViewEmbeddable(props: ExploratoryEmbeddableComponentProps) { - return ( - }> - - - ); -} - -export function getExploratoryViewEmbeddable( - services: CoreStart & ObservabilityPublicPluginsStart -) { - const { lens, dataViews: dataViewsService, uiSettings } = services; - - const dataViewCache: Record = {}; - - const lenStateHelperPromise: Promise<{ formula: FormulaPublicApi }> | null = null; - - const lastRefreshed: Record = {}; - - const hasSameTimeRange = (props: ExploratoryEmbeddableProps) => { - const { attributes } = props; - if (!attributes || attributes?.length === 0) { - return false; - } - const series = attributes[0]; - const { time } = series; - const { from, to } = time; - return attributes.every((seriesT) => { - const { time: timeT } = seriesT; - return timeT.from === from && timeT.to === to; - }); - }; - - return (props: ExploratoryEmbeddableProps) => { - useEffect(() => { - if (!services.data.search.session.getSessionId()) { - services.data.search.session.start(); - } - }, []); - - const { dataTypesIndexPatterns, attributes, customHeight } = props; - - if (!dataViewsService || !lens || !attributes || attributes?.length === 0) { - return null; - } - - const series = attributes[0]; - - const isDarkMode = uiSettings?.get('theme:darkMode'); - - const { data: lensHelper, loading: lensLoading } = useFetcher(async () => { - if (lenStateHelperPromise) { - return lenStateHelperPromise; - } - return lens.stateHelperApi(); - }, []); - - const [loadCount, setLoadCount] = useState(0); - - const onLensLoaded = useCallback( - (lensLoaded: boolean) => { - if (lensLoaded && props.id && hasSameTimeRange(props) && !lastRefreshed[props.id]) { - lastRefreshed[props.id] = series.time; - } - setLoadCount((prev) => prev + 1); - }, - [props, series.time] - ); - - const { dataViews, loading } = useAppDataView({ - series, - dataViewCache, - dataViewsService, - dataTypesIndexPatterns, - seriesDataType: series?.dataType, - }); - - const embedProps = useMemo(() => { - const newProps = { ...props }; - if (props.sparklineMode) { - newProps.axisTitlesVisibility = { x: false, yRight: false, yLeft: false }; - newProps.legendIsVisible = false; - newProps.hideTicks = true; - } - if (props.id && lastRefreshed[props.id] && loadCount < 2) { - newProps.attributes = props.attributes?.map((seriesT) => ({ - ...seriesT, - time: lastRefreshed[props.id!], - })); - } else if (props.id) { - lastRefreshed[props.id] = series.time; - } - return newProps; - }, [loadCount, props, series.time]); - - if (Object.keys(dataViews).length === 0 || loading || !lensHelper || lensLoading) { - return ( - - - - ); - } - - if (!dataViews[series?.dataType]) { - return ; - } - - return ( - - - - - - - - - - ); - }; -} - -const Wrapper = styled.div<{ - customHeight?: string; -}>` - height: ${(props) => (props.customHeight ? `${props.customHeight};` : `100%;`)}; -`; - -const LoadingWrapper = styled.div<{ - customHeight?: string; -}>` - height: ${(props) => (props.customHeight ? `${props.customHeight};` : `100%;`)}; - display: flex; - align-items: center; - justify-content: center; -`; - -function EmptyState({ height }: { height?: string }) { - return ( - - - {NO_DATA_LABEL} - - - ); -} - -const NO_DATA_LABEL = i18n.translate('xpack.observability.overview.exploratoryView.noData', { - defaultMessage: 'No data', -}); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/embeddable/use_actions.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/embeddable/use_actions.ts deleted file mode 100644 index 5fd8b2938eb01b..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/embeddable/use_actions.ts +++ /dev/null @@ -1,197 +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 { useCallback, useEffect, useState } from 'react'; -import { i18n } from '@kbn/i18n'; -import { useKibana } from '@kbn/kibana-react-plugin/public'; -import { Action, ActionExecutionContext } from '@kbn/ui-actions-plugin/public'; -import { createExploratoryViewRoutePath } from '../configurations/utils'; -import { createExploratoryViewUrl } from '../configurations/exploratory_view_url'; -import { ReportViewType } from '../types'; -import { AllSeries } from '../hooks/use_series_storage'; -import { ObservabilityAppServices } from '../../../../application/types'; - -export type ActionTypes = 'explore' | 'save' | 'addToCase' | 'openInLens'; - -export function useActions({ - withActions, - attributes, - reportType, - setIsSaveOpen, - setAddToCaseOpen, - appId = 'observability', - timeRange, - lensAttributes, -}: { - withActions?: boolean | ActionTypes[]; - reportType: ReportViewType; - attributes: AllSeries; - appId?: 'securitySolutionUI' | 'observability'; - setIsSaveOpen: (val: boolean) => void; - setAddToCaseOpen: (val: boolean) => void; - timeRange: { from: string; to: string }; - lensAttributes: any; -}) { - const kServices = useKibana().services; - - const { lens } = kServices; - - const [defaultActions, setDefaultActions] = useState(['explore', 'save', 'addToCase']); - - useEffect(() => { - if (withActions === false) { - setDefaultActions([]); - } - if (Array.isArray(withActions)) { - setDefaultActions(withActions); - } - }, [withActions]); - - const { http, application } = useKibana().services; - - const href = createExploratoryViewUrl( - { reportType, allSeries: attributes }, - http?.basePath.get(), - appId - ); - - const routePath = createExploratoryViewRoutePath({ reportType, allSeries: attributes }); - - const openInLensCallback = useCallback(() => { - if (lensAttributes) { - lens.navigateToPrefilledEditor( - { - id: '', - timeRange, - attributes: lensAttributes, - }, - { - openInNewTab: true, - } - ); - } - }, [lens, lensAttributes, timeRange]); - - const exploreCallback = useCallback(() => { - application?.navigateToApp(appId, { path: routePath }); - }, [appId, application, routePath]); - - const saveCallback = useCallback(() => { - setIsSaveOpen(true); - }, [setIsSaveOpen]); - - const addToCaseCallback = useCallback(() => { - setAddToCaseOpen(true); - }, [setAddToCaseOpen]); - - return defaultActions.map((action) => { - if (action === 'save') { - return getSaveAction({ callback: saveCallback }); - } - if (action === 'addToCase') { - return getAddToCaseAction({ callback: addToCaseCallback }); - } - if (action === 'openInLens') { - return getOpenInLensAction({ callback: openInLensCallback }); - } - return getExploreAction({ href, callback: exploreCallback }); - }); -} - -const getOpenInLensAction = ({ callback }: { callback: () => void }): Action => { - return { - id: 'expViewOpenInLens', - getDisplayName(context: ActionExecutionContext): string { - return i18n.translate('xpack.observability.expView.openInLens', { - defaultMessage: 'Open in Lens', - }); - }, - getIconType(context: ActionExecutionContext): string | undefined { - return 'visArea'; - }, - type: 'link', - async isCompatible(context: ActionExecutionContext): Promise { - return true; - }, - async execute(context: ActionExecutionContext): Promise { - callback(); - return; - }, - }; -}; - -const getExploreAction = ({ href, callback }: { href: string; callback: () => void }): Action => { - return { - id: 'expViewExplore', - getDisplayName(context: ActionExecutionContext): string { - return i18n.translate('xpack.observability.expView.explore', { - defaultMessage: 'Explore', - }); - }, - getIconType(context: ActionExecutionContext): string | undefined { - return 'visArea'; - }, - type: 'link', - async isCompatible(context: ActionExecutionContext): Promise { - return true; - }, - async getHref(context: ActionExecutionContext): Promise { - return href; - }, - async execute(context: ActionExecutionContext): Promise { - callback(); - return; - }, - order: 50, - }; -}; - -const getSaveAction = ({ callback }: { callback: () => void }): Action => { - return { - id: 'expViewSave', - getDisplayName(context: ActionExecutionContext): string { - return i18n.translate('xpack.observability.expView.save', { - defaultMessage: 'Save visualization', - }); - }, - getIconType(context: ActionExecutionContext): string | undefined { - return 'save'; - }, - type: 'actionButton', - async isCompatible(context: ActionExecutionContext): Promise { - return true; - }, - async execute(context: ActionExecutionContext): Promise { - callback(); - return; - }, - order: 49, - }; -}; - -const getAddToCaseAction = ({ callback }: { callback: () => void }): Action => { - return { - id: 'expViewAddToCase', - getDisplayName(context: ActionExecutionContext): string { - return i18n.translate('xpack.observability.expView.addToCase', { - defaultMessage: 'Add to case', - }); - }, - getIconType(context: ActionExecutionContext): string | undefined { - return 'link'; - }, - type: 'actionButton', - async isCompatible(context: ActionExecutionContext): Promise { - return true; - }, - async execute(context: ActionExecutionContext): Promise { - callback(); - return; - }, - order: 48, - }; -}; diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/embeddable/use_app_data_view.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/embeddable/use_app_data_view.ts deleted file mode 100644 index 0d6a9066ca0ae9..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/embeddable/use_app_data_view.ts +++ /dev/null @@ -1,55 +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 { useState } from 'react'; -import { DataView } from '@kbn/data-views-plugin/common'; -import { useLocalDataView } from './use_local_data_view'; -import { - ExploratoryEmbeddableProps, - ObservabilityPublicPluginsStart, - useFetcher, -} from '../../../..'; -import type { DataViewState } from '../hooks/use_app_data_view'; -import type { AppDataType } from '../types'; -import { ObservabilityDataViews } from '../../../../utils/observability_data_views/observability_data_views'; -import { SeriesUrl } from '../../../..'; - -export const useAppDataView = ({ - series, - dataViewCache, - seriesDataType, - dataViewsService, - dataTypesIndexPatterns, -}: { - series: SeriesUrl; - seriesDataType: AppDataType; - dataViewCache: Record; - dataViewsService: ObservabilityPublicPluginsStart['dataViews']; - dataTypesIndexPatterns: ExploratoryEmbeddableProps['dataTypesIndexPatterns']; -}) => { - const [dataViews, setDataViews] = useState({} as DataViewState); - const { dataViewTitle } = useLocalDataView(seriesDataType, dataTypesIndexPatterns); - - const { loading } = useFetcher(async () => { - if (dataViewTitle && !dataViews[seriesDataType]) { - if (dataViewCache[dataViewTitle]) { - setDataViews((prevState) => ({ - ...(prevState ?? {}), - [seriesDataType]: dataViewCache[dataViewTitle], - })); - } else { - const obsvIndexP = new ObservabilityDataViews(dataViewsService, true); - const indPattern = await obsvIndexP.getDataView(seriesDataType, dataViewTitle); - dataViewCache[dataViewTitle] = indPattern!; - setDataViews((prevState) => ({ ...(prevState ?? {}), [seriesDataType]: indPattern })); - } - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [dataViewTitle, seriesDataType, JSON.stringify(series)]); - - return { dataViews, loading }; -}; diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/embeddable/use_local_data_view.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/embeddable/use_local_data_view.ts deleted file mode 100644 index 7b73a0b4ba3a72..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/embeddable/use_local_data_view.ts +++ /dev/null @@ -1,39 +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 { useEffect } from 'react'; -import useLocalStorage from 'react-use/lib/useLocalStorage'; -import { getDataTypeIndices } from '../../../../utils/observability_data_views'; -import { AppDataType } from '../types'; -import { ExploratoryEmbeddableProps, useFetcher } from '../../../..'; - -export function useLocalDataView( - seriesDataType: AppDataType, - dataTypesIndexPatterns: ExploratoryEmbeddableProps['dataTypesIndexPatterns'] -) { - const [dataViewTitle, setDataViewTitle] = useLocalStorage( - `${seriesDataType}AppDataViewTitle`, - '' - ); - - const initDatViewTitle = dataTypesIndexPatterns?.[seriesDataType]; - - const { data: updatedDataViewTitle } = useFetcher(async () => { - if (initDatViewTitle) { - return initDatViewTitle; - } - return (await getDataTypeIndices(seriesDataType)).indices; - }, [initDatViewTitle, seriesDataType]); - - useEffect(() => { - if (updatedDataViewTitle) { - setDataViewTitle(updatedDataViewTitle); - } - }, [setDataViewTitle, updatedDataViewTitle]); - - return { dataViewTitle: dataViewTitle || initDatViewTitle }; -} diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/exploratory_view.test.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/exploratory_view.test.tsx deleted file mode 100644 index 9f50b22dc9f76a..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/exploratory_view.test.tsx +++ /dev/null @@ -1,81 +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 React from 'react'; -import { screen } from '@testing-library/dom'; -import { render, mockAppDataView } from './rtl_helpers'; -import { ExploratoryView } from './exploratory_view'; -import * as obsvDataViews from '../../../utils/observability_data_views/observability_data_views'; -import * as pluginHook from '../../../hooks/use_plugin_context'; -import { createStubIndexPattern } from '@kbn/data-plugin/common/stubs'; -import { noCasesPermissions as mockUseGetCasesPermissions } from '../../../utils/cases_permissions'; - -jest.spyOn(pluginHook, 'usePluginContext').mockReturnValue({ - appMountParameters: { - setHeaderActionMenu: jest.fn(), - }, -} as any); - -jest.mock('../../../hooks/use_get_user_cases_permissions', () => ({ - useGetUserCasesPermissions: jest.fn(() => mockUseGetCasesPermissions()), -})); - -describe('ExploratoryView', () => { - mockAppDataView(); - - beforeEach(() => { - const indexPattern = createStubIndexPattern({ - spec: { - id: 'apm-*', - title: 'apm-*', - timeFieldName: '@timestamp', - fields: { - '@timestamp': { - name: '@timestamp', - type: 'date', - esTypes: ['date'], - searchable: true, - aggregatable: true, - readFromDocValues: true, - }, - }, - }, - }); - - jest.spyOn(obsvDataViews, 'ObservabilityDataViews').mockReturnValue({ - getDataView: jest.fn().mockReturnValue(indexPattern), - } as any); - }); - - it('renders exploratory view', async () => { - render(, { initSeries: { data: [] } }); - - expect(await screen.findByText(/No series found. Please add a series./i)).toBeInTheDocument(); - expect(await screen.findByText(/Hide chart/i)).toBeInTheDocument(); - }); - - it('renders lens component when there is series', async () => { - render(); - - expect((await screen.findAllByText('Performance distribution'))[0]).toBeInTheDocument(); - expect(await screen.findByText(/Lens Embeddable Component/i)).toBeInTheDocument(); - - expect(screen.getByTestId('exploratoryViewSeriesPanel0')).toBeInTheDocument(); - }); - - it('shows/hides the chart', async () => { - render(); - - const toggleButton = await screen.findByText('Hide chart'); - expect(toggleButton).toBeInTheDocument(); - - toggleButton.click(); - - expect(toggleButton.textContent).toBe('Show chart'); - expect(screen.queryByText('Refresh')).toBeNull(); - }); -}); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/exploratory_view.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/exploratory_view.tsx deleted file mode 100644 index 8b885a29c97176..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/exploratory_view.tsx +++ /dev/null @@ -1,225 +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 { i18n } from '@kbn/i18n'; -import React, { useEffect, useRef, useState } from 'react'; -import styled from 'styled-components'; -import { - EuiButtonEmpty, - EuiResizableContainer, - EuiTitle, - EuiFlexGroup, - EuiFlexItem, -} from '@elastic/eui'; -import { PanelDirection } from '@elastic/eui/src/components/resizable_container/types'; -import { useKibana } from '@kbn/kibana-react-plugin/public'; -import { TypedLensByValueInput } from '@kbn/lens-plugin/public'; -import { ObservabilityPublicPluginsStart } from '../../../plugin'; -import { useSeriesStorage } from './hooks/use_series_storage'; -import { useLensAttributes } from './hooks/use_lens_attributes'; -import { useAppDataViewContext } from './hooks/use_app_data_view'; -import { SeriesViews } from './views/series_views'; -import { LensEmbeddable } from './lens_embeddable'; -import { EmptyView } from './components/empty_view'; -import { useExpViewTimeRange } from './hooks/use_time_range'; -import { ExpViewActionMenu } from './components/action_menu'; -import { useExploratoryView } from './contexts/exploratory_view_config'; - -export type PanelId = 'seriesPanel' | 'chartPanel'; - -export function ExploratoryView({ - saveAttributes, -}: { - saveAttributes?: (attr: TypedLensByValueInput['attributes'] | null) => void; -}) { - const { - services: { lens }, - } = useKibana(); - - const seriesBuilderRef = useRef(null); - const wrapperRef = useRef(null); - - const [height, setHeight] = useState('100vh'); - - const { isEditMode } = useExploratoryView(); - - const [lensAttributes, setLensAttributes] = useState( - null - ); - - const { loadDataView, loading } = useAppDataViewContext(); - - const { firstSeries, allSeries, lastRefresh, reportType, setChartTimeRangeContext } = - useSeriesStorage(); - - const lensAttributesT = useLensAttributes(); - const timeRange = useExpViewTimeRange(); - - const setHeightOffset = () => { - if (seriesBuilderRef?.current && wrapperRef.current) { - const headerOffset = wrapperRef.current.getBoundingClientRect().top; - setHeight(`calc(100vh - ${headerOffset + 40}px)`); - } - }; - - useEffect(() => { - allSeries.forEach((seriesT) => { - loadDataView({ - dataType: seriesT.dataType, - }); - }); - }, [allSeries, loadDataView]); - - useEffect(() => { - setLensAttributes(lensAttributesT); - if (saveAttributes) { - saveAttributes(lensAttributesT); - } - - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [JSON.stringify(lensAttributesT ?? {}), lastRefresh]); - - useEffect(() => { - setHeightOffset(); - }); - - const collapseFn = useRef<(id: PanelId, direction: PanelDirection) => void>(); - - const [hiddenPanel, setHiddenPanel] = useState(''); - - const onCollapse = (panelId: string) => { - setHiddenPanel((prevState) => (panelId === prevState ? '' : panelId)); - }; - - const onChange = (panelId: PanelId) => { - onCollapse(panelId); - if (collapseFn.current) { - collapseFn.current(panelId, panelId === 'seriesPanel' ? 'right' : 'left'); - } - }; - - return lens ? ( - <> - - - - {(EuiResizablePanel, _EuiResizableButton, { togglePanel }) => { - collapseFn.current = (id, direction) => togglePanel?.(id, { direction }); - - return ( - <> - - - onChange('chartPanel')} - > - {hiddenPanel === 'chartPanel' ? SHOW_CHART_LABEL : HIDE_CHART_LABEL} - - - - - - {lensAttributes ? ( - - ) : ( - - )} - - - - - - - ); - }} - - {hiddenPanel === 'seriesPanel' && ( - onChange('seriesPanel')} iconType="arrowUp"> - {PREVIEW_LABEL} - - )} - - - ) : ( - -

{LENS_NOT_AVAILABLE}

-
- ); -} -const LensWrapper = styled.div<{ height: string }>` - min-height: 400px; - height: ${(props) => props.height}; - - &&& > div { - height: 100%; - } -`; - -const ResizableContainer = styled(EuiResizableContainer)` - height: 100%; - &&& .paddingTopSmall { - padding-top: 8px; - } - #chartPanel { - > .euiPanel { - padding-bottom: 0; - padding-top: 0; - } - .expExpressionRenderer__expression { - padding-bottom: 0 !important; - padding-top: 0 !important; - } - } -`; - -const ShowPreview = styled(EuiButtonEmpty)` - position: absolute; - bottom: 34px; -`; - -const PREVIEW_LABEL = i18n.translate('xpack.observability.overview.exploratoryView.preview', { - defaultMessage: 'Preview', -}); - -const HIDE_CHART_LABEL = i18n.translate('xpack.observability.overview.exploratoryView.hideChart', { - defaultMessage: 'Hide chart', -}); - -const SHOW_CHART_LABEL = i18n.translate('xpack.observability.overview.exploratoryView.showChart', { - defaultMessage: 'Show chart', -}); - -const LENS_NOT_AVAILABLE = i18n.translate( - 'xpack.observability.overview.exploratoryView.lensDisabled', - { - defaultMessage: 'Lens app is not available, please enable Lens to use exploratory view.', - } -); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/header/add_to_case_action.test.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/header/add_to_case_action.test.tsx deleted file mode 100644 index e6f432f4f30cba..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/header/add_to_case_action.test.tsx +++ /dev/null @@ -1,125 +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 React from 'react'; -import { render, forNearestButton } from '../rtl_helpers'; -import { fireEvent } from '@testing-library/dom'; -import { AddToCaseAction } from './add_to_case_action'; -import * as useCaseHook from '../hooks/use_add_to_case'; -import * as datePicker from '../components/date_range_picker'; -import moment from 'moment'; -import { noCasesPermissions as mockUseGetCasesPermissions } from '../../../../utils/cases_permissions'; - -jest.mock('../../../../hooks/use_get_user_cases_permissions', () => ({ - useGetUserCasesPermissions: jest.fn(() => mockUseGetCasesPermissions()), -})); - -describe('AddToCaseAction', function () { - beforeEach(() => { - jest.spyOn(datePicker, 'parseRelativeDate').mockRestore(); - }); - - it('should render properly', async function () { - const { findByText } = render( - - ); - expect(await findByText('Add to case')).toBeInTheDocument(); - }); - - it('should parse relative data to the useAddToCase hook', async function () { - const useAddToCaseHook = jest.spyOn(useCaseHook, 'useAddToCase'); - jest.spyOn(datePicker, 'parseRelativeDate').mockReturnValue(moment('2021-11-10T10:52:06.091Z')); - - const { findByText } = render( - - ); - expect(await findByText('Add to case')).toBeInTheDocument(); - - expect(useAddToCaseHook).toHaveBeenCalledWith( - expect.objectContaining({ - lensAttributes: { - title: 'Performance distribution', - }, - timeRange: { - from: '2021-11-10T10:52:06.091Z', - to: '2021-11-10T10:52:06.091Z', - }, - }) - ); - }); - - it('should use an empty time-range when timeRanges are empty', async function () { - const useAddToCaseHook = jest.spyOn(useCaseHook, 'useAddToCase'); - - const { getByText } = render( - - ); - - expect(await forNearestButton(getByText)('Add to case')).toBeDisabled(); - - expect(useAddToCaseHook).toHaveBeenCalledWith( - expect.objectContaining({ - lensAttributes: null, - timeRange: { - from: '', - to: '', - }, - appId: 'securitySolutionUI', - owner: 'security', - }) - ); - }); - - it('should be able to click add to case button', async function () { - const initSeries = { - data: [ - { - name: 'test-series', - dataType: 'synthetics' as const, - reportType: 'kpi-over-time' as const, - breakdown: 'monitor.status', - time: { from: 'now-15m', to: 'now' }, - }, - ], - }; - - const { findByText, core } = render( - , - { initSeries } - ); - fireEvent.click(await findByText('Add to case')); - - expect(core?.cases?.ui.getAllCasesSelectorModal).toHaveBeenCalledTimes(1); - expect(core?.cases?.ui.getAllCasesSelectorModal).toHaveBeenCalledWith( - expect.objectContaining({ - owner: ['observability'], - permissions: { - all: false, - create: false, - read: false, - update: false, - delete: false, - push: false, - }, - }) - ); - }); -}); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/header/add_to_case_action.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/header/add_to_case_action.tsx deleted file mode 100644 index 7a7fb603bb8b68..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/header/add_to_case_action.tsx +++ /dev/null @@ -1,137 +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 { EuiButtonEmpty, EuiFlexGroup, EuiFlexItem, EuiLink } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; -import React, { useCallback, useEffect } from 'react'; -import { toMountPoint, useKibana } from '@kbn/kibana-react-plugin/public'; -import { - CasesDeepLinkId, - generateCaseViewPath, - GetAllCasesSelectorModalProps, -} from '@kbn/cases-plugin/public'; -import { TypedLensByValueInput } from '@kbn/lens-plugin/public'; -import { useGetUserCasesPermissions } from '../../../../hooks/use_get_user_cases_permissions'; -import { ObservabilityAppServices } from '../../../../application/types'; -import { useAddToCase } from '../hooks/use_add_to_case'; -import { observabilityFeatureId, observabilityAppId } from '../../../../../common'; -import { parseRelativeDate } from '../components/date_range_picker'; - -export interface AddToCaseProps { - appId?: 'securitySolutionUI' | 'observability'; - autoOpen?: boolean; - lensAttributes: TypedLensByValueInput['attributes'] | null; - owner?: string; - setAutoOpen?: (val: boolean) => void; - timeRange: { from: string; to: string }; -} - -export function AddToCaseAction({ - appId, - autoOpen, - lensAttributes, - owner = observabilityFeatureId, - setAutoOpen, - timeRange, -}: AddToCaseProps) { - const kServices = useKibana().services; - const userCasesPermissions = useGetUserCasesPermissions(); - - const { - cases, - application: { getUrlForApp }, - theme, - } = kServices; - - const getToastText = useCallback( - (theCase) => - toMountPoint( - , - { theme$: theme?.theme$ } - ), - [appId, getUrlForApp, theme?.theme$] - ); - - const absoluteFromDate = parseRelativeDate(timeRange.from); - const absoluteToDate = parseRelativeDate(timeRange.to, { roundUp: true }); - - const { onCaseClicked, isCasesOpen, setIsCasesOpen, isSaving } = useAddToCase({ - lensAttributes, - getToastText, - timeRange: { - from: absoluteFromDate?.toISOString() ?? '', - to: absoluteToDate?.toISOString() ?? '', - }, - appId, - owner, - }); - - const getAllCasesSelectorModalProps: GetAllCasesSelectorModalProps = { - permissions: userCasesPermissions, - onRowClick: onCaseClicked, - owner: [owner], - onClose: () => { - setIsCasesOpen(false); - }, - }; - - useEffect(() => { - if (autoOpen) { - setIsCasesOpen(true); - } - }, [autoOpen, setIsCasesOpen]); - - useEffect(() => { - if (!isCasesOpen) { - setAutoOpen?.(false); - } - }, [isCasesOpen, setAutoOpen]); - - return ( - <> - {typeof autoOpen === 'undefined' && ( - { - if (lensAttributes) { - setIsCasesOpen(true); - } - }} - > - {i18n.translate('xpack.observability.expView.heading.addToCase', { - defaultMessage: 'Add to case', - })} - - )} - {isCasesOpen && - lensAttributes && - cases.ui.getAllCasesSelectorModal(getAllCasesSelectorModalProps)} - - ); -} - -export function CaseToastText({ linkUrl }: { linkUrl: string }) { - return ( - - - - {i18n.translate('xpack.observability.expView.heading.addToCase.notification.viewCase', { - defaultMessage: 'View case', - })} - - - - ); -} diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/header/chart_creation_info.test.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/header/chart_creation_info.test.tsx deleted file mode 100644 index 570362a63c33f3..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/header/chart_creation_info.test.tsx +++ /dev/null @@ -1,35 +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 React from 'react'; -import { screen } from '@testing-library/dom'; -import { render } from '../rtl_helpers'; -import { ChartCreationInfo } from './chart_creation_info'; - -const info = { - to: 1634071132571, - from: 1633406400000, - lastUpdated: 1634071140788, -}; - -describe('ChartCreationInfo', () => { - it('renders chart creation info', async () => { - render(); - - expect(screen.getByText('Chart created')).toBeInTheDocument(); - expect(screen.getByText('Oct 12, 2021 4:39 PM')).toBeInTheDocument(); - expect(screen.getByText('Displaying from')).toBeInTheDocument(); - expect(screen.getByText('Oct 5, 2021 12:00 AM → Oct 12, 2021 4:38 PM')).toBeInTheDocument(); - }); - - it('does not display info when props are falsey', async () => { - render(); - - expect(screen.queryByText('Chart created')).not.toBeInTheDocument(); - expect(screen.queryByText('Displaying from')).not.toBeInTheDocument(); - }); -}); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/header/chart_creation_info.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/header/chart_creation_info.tsx deleted file mode 100644 index 2cd2edbe8f2fd8..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/header/chart_creation_info.tsx +++ /dev/null @@ -1,61 +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 React from 'react'; -import moment from 'moment'; -import { FormattedMessage } from '@kbn/i18n-react'; -import { EuiFlexGroup, EuiFlexItem, EuiText, EuiSpacer } from '@elastic/eui'; -import type { ChartTimeRange } from './last_updated'; - -export function ChartCreationInfo(props: Partial) { - const dateFormat = 'lll'; - const from = moment(props.from).format(dateFormat); - const to = moment(props.to).format(dateFormat); - const created = moment(props.lastUpdated).format(dateFormat); - - return ( - <> - {props.lastUpdated && ( - <> - - - - - - - - {created} - - - - - )} - {props.to && props.from && ( - <> - - - - - - - - - {from} → {to} - - - - - )} - - ); -} diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/header/embed_action.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/header/embed_action.tsx deleted file mode 100644 index f181ff81899d3a..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/header/embed_action.tsx +++ /dev/null @@ -1,67 +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 { EuiButtonEmpty, EuiPopover, EuiCodeBlock, EuiPopoverTitle } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; -import React, { useState } from 'react'; -import { TypedLensByValueInput } from '@kbn/lens-plugin/public'; -import { useSeriesStorage } from '../hooks/use_series_storage'; - -export function EmbedAction({ - lensAttributes, -}: { - lensAttributes: TypedLensByValueInput['attributes'] | null; -}) { - const [isOpen, setIsOpen] = useState(false); - - const { reportType, allSeries } = useSeriesStorage(); - - const button = ( - { - setIsOpen(!isOpen); - }} - > - {EMBED_LABEL} - - ); - - return ( - setIsOpen(false)}> - {EMBED_TITLE_LABEL} - - {`const { observability } = useKibana<>().services; - -const { ExploratoryViewEmbeddable } = observability; - - - `} - - - ); -} - -const EMBED_TITLE_LABEL = i18n.translate('xpack.observability.expView.heading.embedTitle', { - defaultMessage: 'Embed Exploratory view (Dev only feature)', -}); - -const EMBED_LABEL = i18n.translate('xpack.observability.expView.heading.embed', { - defaultMessage: 'Embed <>', -}); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/header/last_updated.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/header/last_updated.tsx deleted file mode 100644 index a2340281a90b97..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/header/last_updated.tsx +++ /dev/null @@ -1,72 +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 React, { useEffect, useState } from 'react'; -import moment from 'moment'; -import styled from 'styled-components'; -import { EuiIcon, EuiText, EuiToolTip } from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n-react'; -import { ChartCreationInfo } from './chart_creation_info'; - -export interface ChartTimeRange { - lastUpdated: number; - to?: number; - from?: number; -} - -interface Props { - chartTimeRange?: ChartTimeRange; -} - -export function LastUpdated({ chartTimeRange }: Props) { - const { lastUpdated } = chartTimeRange || {}; - const [refresh, setRefresh] = useState(() => Date.now()); - - useEffect(() => { - const interVal = setInterval(() => { - setRefresh(Date.now()); - }, 5000); - - return () => { - clearInterval(interVal); - }; - }, []); - - useEffect(() => { - setRefresh(Date.now()); - }, [lastUpdated]); - - if (!lastUpdated) { - return null; - } - - const isWarning = moment().diff(moment(lastUpdated), 'minute') > 5; - const isDanger = moment().diff(moment(lastUpdated), 'minute') > 10; - - return ( - - } - > - - {' '} - - - ); -} - -export const StyledToolTipWrapper = styled.div` - min-width: 30vw; -`; diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/header/refresh_button.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/header/refresh_button.tsx deleted file mode 100644 index 9ceda4962cc5c0..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/header/refresh_button.tsx +++ /dev/null @@ -1,40 +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 React from 'react'; -import { i18n } from '@kbn/i18n'; -import { EuiButton, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; -import { LastUpdated } from './last_updated'; -import { useSeriesStorage } from '../hooks/use_series_storage'; - -export function RefreshButton() { - const { setLastRefresh, chartTimeRangeContext } = useSeriesStorage(); - - return ( - - - - - - setLastRefresh(Date.now())} - > - {REFRESH_LABEL} - - - - ); -} - -export const REFRESH_LABEL = i18n.translate( - 'xpack.observability.overview.exploratoryView.refresh', - { - defaultMessage: 'Refresh', - } -); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_add_to_case.test.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_add_to_case.test.tsx deleted file mode 100644 index f1b81483c9b3eb..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_add_to_case.test.tsx +++ /dev/null @@ -1,81 +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 { useAddToCase } from './use_add_to_case'; -import React, { useEffect } from 'react'; -import { render } from '../rtl_helpers'; -import { EuiButton } from '@elastic/eui'; -import { fireEvent } from '@testing-library/dom'; -import { act } from '@testing-library/react'; - -describe('useAddToCase', function () { - function setupTestComponent() { - const setData = jest.fn(); - function TestComponent() { - const getToastText = jest.fn(); - - const result = useAddToCase({ - lensAttributes: { title: 'Test lens attributes' } as any, - timeRange: { to: 'now', from: 'now-5m' }, - getToastText, - }); - useEffect(() => { - setData(result); - }, [result]); - - return ( - - result.onCaseClicked()} - > - Add new case - - result.onCaseClicked({ id: 'test' } as any)} - > - On case click - - - ); - } - - const renderSetup = render(); - - return { setData, ...renderSetup }; - } - it('should return expected result', async function () { - const { setData, core, findByText } = setupTestComponent(); - - expect(setData).toHaveBeenLastCalledWith({ - isCasesOpen: false, - isSaving: false, - onCaseClicked: expect.any(Function), - setIsCasesOpen: expect.any(Function), - }); - - await act(async () => { - fireEvent.click(await findByText('Add new case')); - }); - - expect(core.application?.navigateToApp).toHaveBeenCalledTimes(1); - expect(core.application?.navigateToApp).toHaveBeenCalledWith('observability', { - deepLinkId: 'cases_create', - openInNewTab: true, - }); - - await act(async () => { - fireEvent.click(await findByText('On case click')); - }); - - expect(core.http?.post).toHaveBeenCalledTimes(1); - expect(core.http?.post).toHaveBeenCalledWith('/api/cases/test/comments', { - body: '{"comment":"!{lens{\\"attributes\\":{\\"title\\":\\"Test lens attributes\\"},\\"timeRange\\":{\\"to\\":\\"now\\",\\"from\\":\\"now-5m\\"}}}","type":"user","owner":"observability"}', - }); - }); -}); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_add_to_case.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_add_to_case.ts deleted file mode 100644 index 9534f66a38cfd4..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_add_to_case.ts +++ /dev/null @@ -1,125 +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 { useCallback, useState } from 'react'; -import { i18n } from '@kbn/i18n'; -import { HttpSetup, MountPoint } from '@kbn/core/public'; -import { Case } from '@kbn/cases-plugin/common'; -import { TypedLensByValueInput } from '@kbn/lens-plugin/public'; -import { CasesDeepLinkId, DRAFT_COMMENT_STORAGE_ID } from '@kbn/cases-plugin/public'; -import { useKibana } from '../../../../utils/kibana_react'; -import { AddToCaseProps } from '../header/add_to_case_action'; -import { observabilityFeatureId } from '../../../../../common'; - -async function addToCase( - http: HttpSetup, - theCase: Case, - attributes: TypedLensByValueInput['attributes'], - timeRange?: { from: string; to: string }, - owner?: string -) { - const apiPath = `/api/cases/${theCase?.id}/comments`; - - const vizPayload = { - attributes, - timeRange, - }; - - const payload = { - comment: `!{lens${JSON.stringify(vizPayload)}}`, - type: 'user', - owner: owner ?? observabilityFeatureId, - }; - - return http.post(apiPath, { body: JSON.stringify(payload) }); -} - -export const useAddToCase = ({ - lensAttributes, - getToastText, - timeRange, - appId, - owner = observabilityFeatureId, -}: AddToCaseProps & { - appId?: 'securitySolutionUI' | 'observability'; - getToastText: (thaCase: Case) => MountPoint; -}) => { - const [isSaving, setIsSaving] = useState(false); - const [isCasesOpen, setIsCasesOpen] = useState(false); - - const { - http, - application: { navigateToApp }, - notifications: { toasts }, - storage, - } = useKibana().services; - - const onCaseClicked = useCallback( - (theCase?: Case) => { - if (theCase && lensAttributes) { - setIsCasesOpen(false); - setIsSaving(true); - addToCase(http, theCase, lensAttributes, timeRange, owner).then( - () => { - setIsSaving(false); - toasts.addSuccess( - { - title: i18n.translate( - 'xpack.observability.expView.heading.addToCase.notification', - { - defaultMessage: 'Successfully added visualization to the case: {caseTitle}', - values: { caseTitle: theCase.title }, - } - ), - text: getToastText(theCase), - }, - { - toastLifeTimeMs: 10000, - } - ); - }, - (error) => { - toasts.addError(error, { - title: i18n.translate( - 'xpack.observability.expView.heading.addToCase.notification.error', - { - defaultMessage: 'Failed to add visualization to the selected case.', - } - ), - }); - } - ); - } else { - /* save lens attributes and timerange to local storage, - ** so the description field will be automatically filled on case creation page. - */ - storage?.set(DRAFT_COMMENT_STORAGE_ID, { - commentId: 'description', - comment: `!{lens${JSON.stringify({ - timeRange, - attributes: lensAttributes, - })}}`, - position: '', - caseTitle: '', - caseTags: '', - }); - navigateToApp(appId ?? observabilityFeatureId, { - deepLinkId: CasesDeepLinkId.casesCreate, - openInNewTab: true, - }); - } - }, - [appId, getToastText, http, lensAttributes, navigateToApp, owner, storage, timeRange, toasts] - ); - - return { - onCaseClicked, - isSaving, - isCasesOpen, - setIsCasesOpen, - }; -}; diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_app_data_view.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_app_data_view.tsx deleted file mode 100644 index d5092aa67d8466..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_app_data_view.tsx +++ /dev/null @@ -1,115 +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 React, { createContext, useContext, Context, useState, useCallback, useMemo } from 'react'; -import type { IHttpFetchError } from '@kbn/core-http-browser'; -import type { DataView } from '@kbn/data-views-plugin/common'; -import { useKibana } from '@kbn/kibana-react-plugin/public'; -import { DataViewInsufficientAccessError } from '@kbn/data-views-plugin/common'; -import { AppDataType } from '../types'; -import { ObservabilityPublicPluginsStart } from '../../../../plugin'; -import { - getDataTypeIndices, - ObservabilityDataViews, -} from '../../../../utils/observability_data_views'; - -export interface DataViewContext { - loading: boolean; - dataViews: DataViewState; - dataViewErrors: DataViewErrors; - hasAppData: HasAppDataState; - loadDataView: (params: { dataType: AppDataType }) => void; -} - -export const DataViewContext = createContext>({}); - -interface ProviderProps { - children: JSX.Element; -} - -type HasAppDataState = Record; -export type DataViewState = Record; -export type DataViewErrors = Record>; -type LoadingState = Record; - -export function DataViewContextProvider({ children }: ProviderProps) { - const [loading, setLoading] = useState({} as LoadingState); - const [dataViews, setDataViews] = useState({} as DataViewState); - const [dataViewErrors, setDataViewErrors] = useState({} as DataViewErrors); - const [hasAppData, setHasAppData] = useState({} as HasAppDataState); - - const { - services: { dataViews: dataViewsService }, - } = useKibana(); - - const loadDataView: DataViewContext['loadDataView'] = useCallback( - async ({ dataType }) => { - if (typeof hasAppData[dataType] === 'undefined' && !loading[dataType]) { - setLoading((prevState) => ({ ...prevState, [dataType]: true })); - - try { - const { indices, hasData } = await getDataTypeIndices(dataType); - - setHasAppData((prevState) => ({ ...prevState, [dataType]: hasData })); - - if (hasData && indices) { - const obsvDataV = new ObservabilityDataViews(dataViewsService, true); - const dataV = await obsvDataV.getDataView(dataType, indices); - - setDataViews((prevState) => ({ ...prevState, [dataType]: dataV })); - } - setLoading((prevState) => ({ ...prevState, [dataType]: false })); - } catch (e) { - if ( - e instanceof DataViewInsufficientAccessError || - (e as IHttpFetchError).body === 'Forbidden' - ) { - setDataViewErrors((prevState) => ({ ...prevState, [dataType]: e })); - } - setLoading((prevState) => ({ ...prevState, [dataType]: false })); - } - } - }, - [dataViewsService, hasAppData, loading] - ); - - return ( - loadingT), - }} - > - {children} - - ); -} - -export const useAppDataViewContext = (dataType?: AppDataType) => { - const { loading, hasAppData, loadDataView, dataViews, dataViewErrors } = useContext( - DataViewContext as unknown as Context - ); - - if (dataType && !dataViews?.[dataType] && !loading) { - loadDataView({ dataType }); - } - - return useMemo(() => { - return { - hasAppData, - loading, - dataViews, - dataViewErrors, - dataView: dataType ? dataViews?.[dataType] : undefined, - hasData: dataType ? hasAppData?.[dataType] : undefined, - loadDataView, - }; - }, [dataType, hasAppData, dataViewErrors, dataViews, loadDataView, loading]); -}; diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_discover_link.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_discover_link.tsx deleted file mode 100644 index d3a9d16be8c0f3..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_discover_link.tsx +++ /dev/null @@ -1,93 +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 { useCallback, useEffect, useState } from 'react'; -import { Filter } from '@kbn/es-query'; -import { useKibana } from '../../../../utils/kibana_react'; -import { SeriesConfig, SeriesUrl } from '../types'; -import { useAppDataViewContext } from './use_app_data_view'; -import { buildExistsFilter, urlFilterToPersistedFilter } from '../configurations/utils'; -import { getFiltersFromDefs } from './use_lens_attributes'; -import { RECORDS_FIELD, RECORDS_PERCENTAGE_FIELD } from '../configurations/constants'; - -interface UseDiscoverLink { - seriesConfig?: SeriesConfig; - series: SeriesUrl; -} - -export const useDiscoverLink = ({ series, seriesConfig }: UseDiscoverLink) => { - const kServices = useKibana().services; - const { - application: { navigateToUrl }, - } = kServices; - - const { dataViews } = useAppDataViewContext(); - - const locator = kServices.discover?.locator; - const [discoverUrl, setDiscoverUrl] = useState(''); - - useEffect(() => { - const dataView = dataViews?.[series.dataType]; - - if (dataView) { - const definitions = series.reportDefinitions ?? {}; - - const urlFilters = (series.filters ?? []).concat(getFiltersFromDefs(definitions)); - - const filters = urlFilterToPersistedFilter({ - dataView, - urlFilters, - initFilters: seriesConfig?.baseFilters, - }) as Filter[]; - - const selectedMetricField = series.selectedMetricField; - - if ( - selectedMetricField && - selectedMetricField !== RECORDS_FIELD && - selectedMetricField !== RECORDS_PERCENTAGE_FIELD - ) { - filters.push(buildExistsFilter(selectedMetricField, dataView)[0]); - } - - const getDiscoverUrl = async () => { - if (!locator) return; - - const newUrl = await locator.getUrl({ - filters, - indexPatternId: dataView?.id, - }); - setDiscoverUrl(newUrl); - }; - getDiscoverUrl(); - } - }, [ - dataViews, - series.dataType, - series.filters, - series.reportDefinitions, - series.selectedMetricField, - seriesConfig?.baseFilters, - locator, - ]); - - const onClick = useCallback( - (event: React.MouseEvent) => { - if (discoverUrl) { - event.preventDefault(); - - return navigateToUrl(discoverUrl); - } - }, - [discoverUrl, navigateToUrl] - ); - - return { - href: discoverUrl, - onClick, - }; -}; diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_lens_attributes.test.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_lens_attributes.test.tsx deleted file mode 100644 index d98a8a8260cbd5..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_lens_attributes.test.tsx +++ /dev/null @@ -1,103 +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 React from 'react'; - -import { allSeriesKey, reportTypeKey, UrlStorageContextProvider } from './use_series_storage'; -import { renderHook } from '@testing-library/react-hooks'; -import { useLensAttributes } from './use_lens_attributes'; -import { ReportTypes } from '../configurations/constants'; -import { mockDataView } from '../rtl_helpers'; -import { createKbnUrlStateStorage } from '@kbn/kibana-utils-plugin/public'; -import { TRANSACTION_DURATION } from '../configurations/constants/elasticsearch_fieldnames'; -import * as lensAttributes from '../configurations/lens_attributes'; -import * as useAppDataViewHook from './use_app_data_view'; -import * as theme from '../../../../hooks/use_theme'; -import { dataTypes, obsvReportConfigMap, reportTypesList } from '../obsv_exploratory_view'; -import { ExploratoryViewContextProvider } from '../contexts/exploratory_view_config'; -import { themeServiceMock } from '@kbn/core/public/mocks'; -import * as lensHook from './use_lens_formula_helper'; -import { lensPluginMock } from '@kbn/lens-plugin/public/mocks'; -import { FormulaPublicApi } from '@kbn/lens-plugin/public'; - -const mockSingleSeries = [ - { - name: 'performance-distribution', - dataType: 'ux', - breakdown: 'user_agent.name', - time: { from: 'now-15m', to: 'now' }, - selectedMetricField: TRANSACTION_DURATION, - reportDefinitions: { 'service.name': ['elastic-co'] }, - }, -]; - -describe('useExpViewTimeRange', function () { - const storage = createKbnUrlStateStorage({ useHash: false }); - // @ts-ignore - jest.spyOn(useAppDataViewHook, 'useAppDataViewContext').mockReturnValue({ - dataViews: { - ux: mockDataView, - apm: mockDataView, - mobile: mockDataView, - infra_logs: mockDataView, - infra_metrics: mockDataView, - synthetics: mockDataView, - uptime: mockDataView, - alerts: mockDataView, - }, - }); - jest.spyOn(theme, 'useTheme').mockReturnValue({ - // @ts-ignore - eui: { - euiColorVis1: '#111111', - }, - }); - - let formulaHelper: FormulaPublicApi; - - beforeAll(async () => { - const lensPluginMockStart = lensPluginMock.createStartContract(); - formulaHelper = (await lensPluginMockStart.stateHelperApi()).formula; - - jest.spyOn(lensHook, 'useLensFormulaHelper').mockReturnValue(formulaHelper); - }); - - const lensAttributesSpy = jest.spyOn(lensAttributes, 'LensAttributes'); - - function Wrapper({ children }: { children: JSX.Element }) { - return ( - - {children} - - ); - } - - it('updates lens attributes with report type from storage', async function () { - await storage.set(allSeriesKey, mockSingleSeries); - await storage.set(reportTypeKey, ReportTypes.KPI); - - renderHook(() => useLensAttributes(), { - wrapper: Wrapper, - }); - - expect(lensAttributesSpy).toBeCalledWith( - expect.arrayContaining([ - expect.objectContaining({ - seriesConfig: expect.objectContaining({ reportType: ReportTypes.KPI }), - }), - ]), - 'kpi-over-time', - formulaHelper - ); - }); -}); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_lens_attributes.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_lens_attributes.ts deleted file mode 100644 index 690da3d98704a8..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_lens_attributes.ts +++ /dev/null @@ -1,163 +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 { useMemo } from 'react'; -import { isEmpty } from 'lodash'; -import { TypedLensByValueInput } from '@kbn/lens-plugin/public'; -import { EuiTheme } from '@kbn/kibana-react-plugin/common'; -import { useKibanaSpace } from '../../../../hooks/use_kibana_space'; -import { HeatMapLensAttributes } from '../configurations/lens_attributes/heatmap_attributes'; -import { useLensFormulaHelper } from './use_lens_formula_helper'; -import { ALL_VALUES_SELECTED } from '../configurations/constants/url_constants'; -import { LayerConfig, LensAttributes } from '../configurations/lens_attributes'; -import { - AllSeries, - allSeriesKey, - convertAllShortSeries, - reportTypeKey, - useSeriesStorage, -} from './use_series_storage'; -import { getDefaultConfigs } from '../configurations/default_configs'; -import { ReportViewType, SeriesUrl, UrlFilter } from '../types'; -import { DataViewState, useAppDataViewContext } from './use_app_data_view'; -import { useTheme } from '../../../../hooks/use_theme'; -import { LABEL_FIELDS_BREAKDOWN } from '../configurations/constants'; -import { ReportConfigMap, useExploratoryView } from '../contexts/exploratory_view_config'; -import { SingleMetricLensAttributes } from '../configurations/lens_attributes/single_metric_attributes'; - -export const getFiltersFromDefs = ( - reportDefinitions: SeriesUrl['reportDefinitions'] | SeriesUrl['textReportDefinitions'] -) => { - return Object.entries(reportDefinitions ?? {}) - .map(([field, value]) => { - return { - field, - values: Array.isArray(value) ? value : [value], - }; - }) - .filter(({ values }) => !values.includes(ALL_VALUES_SELECTED)) as UrlFilter[]; -}; - -export function getLayerConfigs( - allSeries: AllSeries, - reportType: ReportViewType, - theme: EuiTheme, - dataViews: DataViewState, - reportConfigMap: ReportConfigMap, - spaceId?: string -) { - const layerConfigs: LayerConfig[] = []; - - allSeries.forEach((series, seriesIndex) => { - const dataView = dataViews?.[series?.dataType]; - - if ( - dataView && - !isEmpty(series.reportDefinitions) && - !series.hidden && - series.selectedMetricField - ) { - const seriesConfig = getDefaultConfigs({ - reportType, - dataView, - dataType: series.dataType, - reportConfigMap, - spaceId, - }); - - const filters: UrlFilter[] = (series.filters ?? []).concat( - getFiltersFromDefs(series.reportDefinitions), - getFiltersFromDefs(series.textReportDefinitions) - ); - - const color = (theme.eui as unknown as Record)?.[`euiColorVis${seriesIndex}`]; - let seriesColor = series.color!; - if (reportType !== 'single-metric') { - seriesColor = series.color ?? color; - } - - layerConfigs.push({ - filters, - dataView, - seriesConfig, - time: series.time, - name: series.name, - color: seriesColor, - breakdown: series.breakdown === LABEL_FIELDS_BREAKDOWN ? undefined : series.breakdown, - seriesType: series.seriesType, - operationType: series.operationType, - reportDefinitions: series.reportDefinitions ?? {}, - selectedMetricField: series.selectedMetricField, - showPercentileAnnotations: series.showPercentileAnnotations, - }); - } - }); - - return layerConfigs; -} - -export const useLensAttributes = (): TypedLensByValueInput['attributes'] | null => { - const { storage, allSeries, lastRefresh, reportType } = useSeriesStorage(); - - const { dataViews } = useAppDataViewContext(); - - const spaceId = useKibanaSpace(); - - const { reportConfigMap } = useExploratoryView(); - - const theme = useTheme(); - - const lensFormulaHelper = useLensFormulaHelper(); - - return useMemo(() => { - // we only use the data from url to apply, since that gets updated to apply changes - const allSeriesT: AllSeries = convertAllShortSeries(storage.get(allSeriesKey) ?? []); - const reportTypeT: ReportViewType = storage.get(reportTypeKey) as ReportViewType; - - if (isEmpty(dataViews) || isEmpty(allSeriesT) || !reportTypeT || !lensFormulaHelper) { - return null; - } - const layerConfigs = getLayerConfigs( - allSeriesT, - reportTypeT, - theme, - dataViews, - reportConfigMap, - spaceId.space?.id - ); - - if (layerConfigs.length < 1) { - return null; - } - - if (reportTypeT === 'single-metric') { - const lensAttributes = new SingleMetricLensAttributes( - layerConfigs, - reportTypeT, - lensFormulaHelper - ); - - return lensAttributes.getJSON('lnsLegacyMetric', lastRefresh); - } - - if (reportTypeT === 'heatmap') { - const lensAttributes = new HeatMapLensAttributes( - layerConfigs, - reportTypeT, - lensFormulaHelper - ); - - return lensAttributes.getJSON('lnsHeatmap', lastRefresh); - } - - const lensAttributes = new LensAttributes(layerConfigs, reportTypeT, lensFormulaHelper); - - return lensAttributes.getJSON('lnsXY', lastRefresh); - // we also want to check the state on allSeries changes - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [dataViews, reportType, storage, theme, lastRefresh, allSeries, lensFormulaHelper]); -}; diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_lens_formula_helper.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_lens_formula_helper.ts deleted file mode 100644 index 6e1bfe4a9eb83b..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_lens_formula_helper.ts +++ /dev/null @@ -1,26 +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 { useMemo } from 'react'; -import { useKibana } from '@kbn/kibana-react-plugin/public'; -import { ObservabilityPublicPluginsStart, useFetcher } from '../../../..'; - -export const useLensFormulaHelper = () => { - const { - services: { lens }, - } = useKibana(); - - const { data: lensHelper } = useFetcher(async () => { - return lens.stateHelperApi(); - }, [lens]); - - return useMemo(() => { - if (lensHelper) { - return lensHelper.formula; - } - }, [lensHelper]); -}; diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_series_filters.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_series_filters.ts deleted file mode 100644 index 253db8a42dd7ca..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_series_filters.ts +++ /dev/null @@ -1,188 +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 { concat } from 'lodash'; -import { useSeriesStorage } from './use_series_storage'; -import { SeriesUrl, UrlFilter } from '../types'; - -export interface UpdateFilter { - field: string; - value: string | Array; - negate?: boolean; - wildcards?: string[]; - isWildcard?: boolean; -} - -export const useSeriesFilters = ({ seriesId, series }: { seriesId: number; series: SeriesUrl }) => { - const { setSeries } = useSeriesStorage(); - - const filters = series.filters ?? []; - - const replaceFilter = ({ - field, - values, - notValues, - wildcards, - notWildcards, - }: { - field: string; - values: Array; - notValues: Array; - wildcards?: string[]; - notWildcards?: string[]; - }) => { - const currFilter: UrlFilter | undefined = filters.find(({ field: fd }) => field === fd) ?? { - field, - }; - - currFilter.notValues = notValues.length > 0 ? notValues : undefined; - currFilter.values = values.length > 0 ? values : undefined; - - currFilter.wildcards = wildcards; - currFilter.notWildcards = notWildcards; - - const otherFilters = filters.filter(({ field: fd }) => fd !== field); - - if (concat(values, notValues, wildcards, notWildcards).length > 0) { - setSeries(seriesId, { ...series, filters: [...otherFilters, currFilter] }); - } else { - setSeries(seriesId, { ...series, filters: otherFilters }); - } - }; - - const removeFilter = ({ field, value, negate, isWildcard }: UpdateFilter) => { - const filtersN = filters - .map((filter) => { - if (filter.field === field) { - if (negate) { - if (isWildcard) { - const notWildcardsN = filter.notWildcards?.filter((val) => - value instanceof Array ? !value.includes(val) : val !== value - ); - return { ...filter, notWildcards: notWildcardsN }; - } - const notValuesN = filter.notValues?.filter((val) => - value instanceof Array ? !value.includes(val) : val !== value - ); - return { ...filter, notValues: notValuesN }; - } else { - if (isWildcard) { - const wildcardsN = filter.wildcards?.filter((val) => - value instanceof Array ? !value.includes(val) : val !== value - ); - return { ...filter, wildcards: wildcardsN }; - } - const valuesN = filter.values?.filter((val) => - value instanceof Array ? !value.includes(val) : val !== value - ); - return { ...filter, values: valuesN }; - } - } - - return filter; - }) - .filter( - ({ values = [], notValues = [], wildcards = [], notWildcards = [] }) => - values.length > 0 || - notValues.length > 0 || - wildcards.length > 0 || - notWildcards.length > 0 - ); - setSeries(seriesId, { ...series, filters: filtersN }); - }; - - const addFilter = ({ field, value, negate }: UpdateFilter) => { - const currFilter: UrlFilter = { field }; - if (negate) { - currFilter.notValues = value instanceof Array ? value : [value]; - } else { - currFilter.values = value instanceof Array ? value : [value]; - } - - if (filters.length === 0) { - setSeries(seriesId, { ...series, filters: [currFilter] }); - } else { - setSeries(seriesId, { - ...series, - filters: [currFilter, ...filters.filter((ft) => ft.field !== field)], - }); - } - }; - - const updateFilter = ({ field, value, negate, wildcards }: UpdateFilter) => { - const currFilter: UrlFilter | undefined = filters.find(({ field: fd }) => field === fd) ?? { - field, - }; - - const currNotValues = currFilter.notValues ?? []; - const currValues = currFilter.values ?? []; - - const notValues = currNotValues.filter((val) => - value instanceof Array ? !value.includes(val) : val !== value - ); - - const values = currValues.filter((val) => - value instanceof Array ? !value.includes(val) : val !== value - ); - - if (negate) { - if (value instanceof Array) { - notValues.push(...value); - } else { - notValues.push(value); - } - } else { - if (value instanceof Array) { - values.push(...value); - } else { - values.push(value); - } - } - - replaceFilter({ field, values, notValues, wildcards }); - }; - - const setFilter = ({ field, value, negate, wildcards }: UpdateFilter) => { - const currFilter: UrlFilter | undefined = filters.find(({ field: fd }) => field === fd); - - if (!currFilter) { - addFilter({ field, value, negate, wildcards }); - } else { - updateFilter({ field, value, negate, wildcards }); - } - }; - - const setFiltersWildcard = ({ field, wildcards }: { field: string; wildcards: string[] }) => { - let currFilter: UrlFilter | undefined = filters.find(({ field: fd }) => field === fd); - - if (!currFilter) { - currFilter = { field, wildcards }; - - if (filters.length === 0) { - setSeries(seriesId, { ...series, filters: [currFilter] }); - } else { - setSeries(seriesId, { - ...series, - filters: [currFilter, ...filters.filter((ft) => ft.field !== field)], - }); - } - } else { - replaceFilter({ - field, - values: currFilter.values ?? [], - notValues: currFilter.notValues ?? [], - wildcards, - }); - } - }; - - const invertFilter = ({ field, value, negate }: UpdateFilter) => { - updateFilter({ field, value, negate: !negate }); - }; - - return { invertFilter, setFilter, removeFilter, replaceFilter, setFiltersWildcard }; -}; diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_series_storage.test.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_series_storage.test.tsx deleted file mode 100644 index 023d3d96288c8a..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_series_storage.test.tsx +++ /dev/null @@ -1,291 +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 React, { useEffect } from 'react'; -import { act, renderHook } from '@testing-library/react-hooks'; -import { Router } from 'react-router-dom'; -import { Route } from '@kbn/shared-ux-router'; -import { render } from '@testing-library/react'; -import { UrlStorageContextProvider, useSeriesStorage, reportTypeKey } from './use_series_storage'; -import { getHistoryFromUrl } from '../rtl_helpers'; -import type { AppDataType } from '../types'; -import { ReportTypes } from '../configurations/constants'; -import * as useTrackMetric from '../../../../hooks/use_track_metric'; - -const mockSingleSeries = [ - { - name: 'performance-distribution', - dataType: 'ux' as AppDataType, - breakdown: 'user_agent.name', - time: { from: 'now-15m', to: 'now' }, - }, -]; - -const mockMultipleSeries = [ - { - name: 'performance-distribution', - dataType: 'ux' as AppDataType, - breakdown: 'user_agent.name', - time: { from: 'now-15m', to: 'now' }, - filters: [ - { - field: 'url.full', - value: 'https://elastic.co', - }, - ], - selectedMetricField: 'transaction.duration.us', - }, - { - name: 'kpi-over-time', - dataType: 'synthetics' as AppDataType, - breakdown: 'user_agent.name', - time: { from: 'now-15m', to: 'now' }, - filters: [ - { - field: 'monitor.type', - value: 'browser', - }, - ], - selectedMetricField: 'monitor.duration.us', - }, -]; - -describe('userSeriesStorage', function () { - function setupTestComponent(seriesData: any) { - const setData = jest.fn(); - - function TestComponent() { - const data = useSeriesStorage(); - - useEffect(() => { - setData(data); - }, [data]); - - return Test; - } - - render( - - - (key === 'sr' ? seriesData : null)), - set: jest.fn(), - }} - > - - - - - ); - - return setData; - } - it('should return expected result when there is one series', function () { - const setData = setupTestComponent(mockSingleSeries); - - expect(setData).toHaveBeenCalledTimes(2); - expect(setData).toHaveBeenLastCalledWith( - expect.objectContaining({ - allSeries: [ - { - name: 'performance-distribution', - dataType: 'ux', - breakdown: 'user_agent.name', - time: { from: 'now-15m', to: 'now' }, - }, - ], - firstSeries: { - name: 'performance-distribution', - dataType: 'ux', - breakdown: 'user_agent.name', - time: { from: 'now-15m', to: 'now' }, - }, - }) - ); - }); - - it('should return expected result when there are multiple series', function () { - const setData = setupTestComponent(mockMultipleSeries); - - expect(setData).toHaveBeenCalledTimes(2); - expect(setData).toHaveBeenLastCalledWith( - expect.objectContaining({ - allSeries: mockMultipleSeries, - firstSeries: mockMultipleSeries[0], - }) - ); - }); - - it('should return expected result when there are no series', function () { - const setData = setupTestComponent([]); - - expect(setData).toHaveBeenCalledTimes(1); - expect(setData).toHaveBeenLastCalledWith( - expect.objectContaining({ - allSeries: [], - firstSeries: undefined, - }) - ); - }); - - it('ensures that only one series has a breakdown', () => { - function wrapper({ children }: { children: React.ReactElement }) { - return ( - (key === 'sr' ? mockMultipleSeries : null)), - set: jest.fn(), - }} - > - {children} - - ); - } - const { result } = renderHook(() => useSeriesStorage(), { wrapper }); - - act(() => { - result.current.setSeries(1, mockMultipleSeries[1]); - }); - - expect(result.current.allSeries).toEqual([ - mockMultipleSeries[0], - { - ...mockMultipleSeries[1], - breakdown: undefined, - }, - ]); - }); - - it('sets reportType when calling applyChanges', () => { - const setStorage = jest.fn(); - function wrapper({ children }: { children: React.ReactElement }) { - return ( - - key === 'sr' ? mockMultipleSeries : 'kpi-over-time' - ), - set: setStorage, - }} - > - {children} - - ); - } - const { result } = renderHook(() => useSeriesStorage(), { wrapper }); - - act(() => { - result.current.setReportType(ReportTypes.DISTRIBUTION); - }); - - act(() => { - result.current.applyChanges(); - }); - - expect(setStorage).toBeCalledWith(reportTypeKey, ReportTypes.DISTRIBUTION); - }); - - it('returns reportType in state, not url storage, from hook', () => { - const setStorage = jest.fn(); - function wrapper({ children }: { children: React.ReactElement }) { - return ( - - key === 'sr' ? mockMultipleSeries : 'kpi-over-time' - ), - set: setStorage, - }} - > - {children} - - ); - } - const { result } = renderHook(() => useSeriesStorage(), { wrapper }); - - act(() => { - result.current.setReportType(ReportTypes.DISTRIBUTION); - }); - - expect(result.current.reportType).toEqual(ReportTypes.DISTRIBUTION); - }); - - it('ensures that telemetry is called', () => { - const trackEvent = jest.fn(); - jest.spyOn(useTrackMetric, 'useUiTracker').mockReturnValue(trackEvent); - function wrapper({ children }: { children: React.ReactElement }) { - return ( - - key === 'sr' ? mockMultipleSeries : 'kpi-over-time' - ), - set: jest.fn(), - }} - > - {children} - - ); - } - const { result } = renderHook(() => useSeriesStorage(), { wrapper }); - - act(() => { - result.current.applyChanges(); - }); - - expect(trackEvent).toBeCalledTimes(7); - expect(trackEvent).toBeCalledWith({ - app: 'observability-overview', - metric: 'exploratory_view__filters__filter_url.full', - metricType: 'count', - }); - expect(trackEvent).toBeCalledWith({ - app: 'observability-overview', - metric: 'exploratory_view__filters__filter_monitor.type', - metricType: 'count', - }); - expect(trackEvent).toBeCalledWith({ - app: 'observability-overview', - metric: 'exploratory_view__filters__report_type_kpi-over-time__data_type_ux__filter_url.full', - metricType: 'count', - }); - expect(trackEvent).toBeCalledWith({ - app: 'observability-overview', - metric: - 'exploratory_view__filters__report_type_kpi-over-time__data_type_synthetics__filter_monitor.type', - metricType: 'count', - }); - expect(trackEvent).toBeCalledWith({ - app: 'observability-overview', - metric: - 'exploratory_view__report_type_kpi-over-time__data_type_synthetics__metric_type_monitor.duration.us', - metricType: 'count', - }); - expect(trackEvent).toBeCalledWith({ - app: 'observability-overview', - metric: - 'exploratory_view__report_type_kpi-over-time__data_type_ux__metric_type_transaction.duration.us', - metricType: 'count', - }); - expect(trackEvent).toBeCalledWith({ - app: 'observability-overview', - metric: 'exploratory_view_apply_changes', - metricType: 'count', - }); - }); -}); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_series_storage.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_series_storage.tsx deleted file mode 100644 index 9cbddbbde9965c..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_series_storage.tsx +++ /dev/null @@ -1,194 +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 React, { createContext, useContext, useState, useEffect, useCallback } from 'react'; -import { IKbnUrlStateStorage, ISessionStorageStateStorage } from '@kbn/kibana-utils-plugin/public'; -import { OperationType, SeriesType } from '@kbn/lens-plugin/public'; -import { ChartTimeRange } from '../header/last_updated'; -import { useUiTracker } from '../../../../hooks/use_track_metric'; -import type { - AppDataType, - ReportViewType, - SeriesUrl, - UrlFilter, - URLReportDefinition, -} from '../types'; -import { convertToShortUrl } from '../configurations/exploratory_view_url'; -import { URL_KEYS } from '../configurations/constants/url_constants'; -import { trackTelemetryOnApply } from '../utils/telemetry'; - -export interface SeriesContextValue { - firstSeries?: SeriesUrl; - lastRefresh: number; - setLastRefresh: (val: number) => void; - applyChanges: (onApply?: () => void) => void; - allSeries: AllSeries; - setSeries: (seriesIndex: number, newValue: SeriesUrl) => void; - getSeries: (seriesIndex: number) => SeriesUrl | undefined; - removeSeries: (seriesIndex: number) => void; - setReportType: (reportType: ReportViewType) => void; - storage: IKbnUrlStateStorage | ISessionStorageStateStorage; - reportType: ReportViewType; - chartTimeRangeContext?: ChartTimeRange; - setChartTimeRangeContext: React.Dispatch>; -} -export const UrlStorageContext = createContext({} as SeriesContextValue); - -interface ProviderProps { - storage: IKbnUrlStateStorage | ISessionStorageStateStorage; -} - -export function convertAllShortSeries(allShortSeries: AllShortSeries) { - return (allShortSeries ?? []).map((shortSeries) => convertFromShortUrl(shortSeries)); -} - -export const allSeriesKey = 'sr'; -export const reportTypeKey = 'reportType'; - -export function UrlStorageContextProvider({ - children, - storage, -}: ProviderProps & { children: JSX.Element }) { - const [allSeries, setAllSeries] = useState(() => - convertAllShortSeries(storage.get(allSeriesKey) ?? []) - ); - - const [lastRefresh, setLastRefresh] = useState(() => Date.now()); - - const [chartTimeRangeContext, setChartTimeRangeContext] = useState(); - - const [reportType, setReportType] = useState( - () => ((storage as IKbnUrlStateStorage).get(reportTypeKey) ?? '') as ReportViewType - ); - - const [firstSeries, setFirstSeries] = useState(); - - const trackEvent = useUiTracker(); - - useEffect(() => { - const firstSeriesT = allSeries?.[0]; - - setFirstSeries(firstSeriesT); - }, [allSeries, storage]); - - const setSeries = useCallback((seriesIndex: number, newValue: SeriesUrl) => { - setAllSeries((prevAllSeries) => { - const seriesWithCurrentBreakdown = prevAllSeries.findIndex((series) => series.breakdown); - const newStateRest = prevAllSeries.map((series, index) => { - if (index === seriesIndex) { - return { - ...newValue, - breakdown: - seriesWithCurrentBreakdown === seriesIndex || seriesWithCurrentBreakdown === -1 - ? newValue.breakdown - : undefined, - }; - } - return series; - }); - - if (prevAllSeries.length === seriesIndex) { - return [...newStateRest, newValue]; - } - - return [...newStateRest]; - }); - }, []); - - const removeSeries = useCallback((seriesIndex: number) => { - setAllSeries((prevAllSeries) => - prevAllSeries.filter((seriesT, index) => index !== seriesIndex) - ); - }, []); - - const getSeries = useCallback( - (seriesIndex: number) => { - return allSeries[seriesIndex]; - }, - [allSeries] - ); - - const applyChanges = useCallback( - (onApply?: () => void) => { - const allShortSeries = allSeries.map((series) => convertToShortUrl(series)); - (storage as IKbnUrlStateStorage).set(reportTypeKey, reportType); - - (storage as IKbnUrlStateStorage).set(allSeriesKey, allShortSeries); - setLastRefresh(Date.now()); - - trackTelemetryOnApply(trackEvent, allSeries, reportType); - - if (onApply) { - onApply(); - } - }, - [allSeries, storage, trackEvent, reportType] - ); - - const value = { - applyChanges, - storage, - getSeries, - setSeries, - removeSeries, - allSeries, - lastRefresh, - setLastRefresh, - setReportType, - reportType, - chartTimeRangeContext, - setChartTimeRangeContext, - firstSeries: firstSeries!, - }; - return {children}; -} - -export function useSeriesStorage() { - return useContext(UrlStorageContext); -} - -function convertFromShortUrl(newValue: ShortUrlSeries): SeriesUrl { - const { dt, op, st, bd, ft, time, rdf, mt, h, n, c, spa, ...restSeries } = newValue; - return { - operationType: op, - seriesType: st, - breakdown: bd, - filters: ft!, - time: time!, - reportDefinitions: rdf, - dataType: dt!, - selectedMetricField: mt, - hidden: h, - name: n, - color: c, - showPercentileAnnotations: spa, - ...restSeries, - }; -} - -interface ShortUrlSeries { - [URL_KEYS.OPERATION_TYPE]?: OperationType; - [URL_KEYS.DATA_TYPE]?: AppDataType; - [URL_KEYS.SERIES_TYPE]?: SeriesType; - [URL_KEYS.BREAK_DOWN]?: string; - [URL_KEYS.FILTERS]?: UrlFilter[]; - [URL_KEYS.REPORT_DEFINITIONS]?: URLReportDefinition; - [URL_KEYS.SELECTED_METRIC]?: string; - [URL_KEYS.HIDDEN]?: boolean; - [URL_KEYS.NAME]: string; - [URL_KEYS.COLOR]?: string; - [URL_KEYS.SHOW_PERCENTILE_ANNOTATIONS]?: boolean; - time?: { - to: string; - from: string; - }; -} - -export type AllShortSeries = ShortUrlSeries[]; -export type AllSeries = SeriesUrl[]; - -export const NEW_SERIES_KEY = 'new-series'; diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_time_range.test.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_time_range.test.tsx deleted file mode 100644 index b97e3cc3c69237..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_time_range.test.tsx +++ /dev/null @@ -1,136 +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 React from 'react'; - -import { allSeriesKey, reportTypeKey, UrlStorageContextProvider } from './use_series_storage'; -import { renderHook } from '@testing-library/react-hooks'; -import { useExpViewTimeRange } from './use_time_range'; -import { ReportTypes } from '../configurations/constants'; -import { createKbnUrlStateStorage } from '@kbn/kibana-utils-plugin/public'; -import { - TRANSACTION_DURATION, - METRIC_SYSTEM_MEMORY_USAGE, -} from '../configurations/constants/elasticsearch_fieldnames'; - -const mockSingleSeries = [ - { - name: 'performance-distribution', - dataType: 'ux', - breakdown: 'user_agent.name', - time: { from: 'now-15m', to: 'now' }, - selectedMetricField: TRANSACTION_DURATION, - reportDefinitions: { 'service.name': ['elastic-co'] }, - }, -]; - -const mockMultipleSeries = [ - ...mockSingleSeries, - { - name: 'kpi-over-time', - dataType: 'synthetics', - breakdown: 'user_agent.name', - time: { from: 'now-30m', to: 'now' }, - selectedMetricField: TRANSACTION_DURATION, - reportDefinitions: { 'service.name': ['elastic-co'] }, - }, -]; - -describe('useExpViewTimeRange', function () { - const storage = createKbnUrlStateStorage({ useHash: false }); - - function Wrapper({ children }: { children: JSX.Element }) { - return {children}; - } - it('should return expected result when there is one series', async function () { - await storage.set(allSeriesKey, mockSingleSeries); - await storage.set(reportTypeKey, ReportTypes.KPI); - - const { result } = renderHook(() => useExpViewTimeRange(), { - wrapper: Wrapper, - }); - - expect(result.current).toEqual({ - from: 'now-15m', - to: 'now', - }); - }); - - it('should return expected result when there are multiple KPI series', async function () { - await storage.set(allSeriesKey, mockMultipleSeries); - await storage.set(reportTypeKey, ReportTypes.KPI); - - const { result } = renderHook(() => useExpViewTimeRange(), { - wrapper: Wrapper, - }); - - expect(result.current).toEqual({ - from: 'now-15m', - to: 'now', - }); - }); - - it('should return expected result when there are multiple distribution series with relative dates', async function () { - await storage.set(allSeriesKey, mockMultipleSeries); - await storage.set(reportTypeKey, ReportTypes.DISTRIBUTION); - - const { result } = renderHook(() => useExpViewTimeRange(), { - wrapper: Wrapper, - }); - - expect(result.current).toEqual({ - from: 'now-30m', - to: 'now', - }); - }); - - it("should correctly parse dates when last series doesn't have a report definition", async function () { - const mockSeriesWithoutDefinitions = [ - ...mockSingleSeries, - { - dataType: 'mobile', - name: 'mobile-series-1', - reportDefinitions: undefined, - selectedMetricField: METRIC_SYSTEM_MEMORY_USAGE, - time: { from: 'now-30m', to: 'now' }, - }, - ]; - - await storage.set(allSeriesKey, mockSeriesWithoutDefinitions); - await storage.set(reportTypeKey, ReportTypes.DISTRIBUTION); - - const { result } = renderHook(() => useExpViewTimeRange(), { - wrapper: Wrapper, - }); - - expect(result.current).toEqual({ - from: 'now-30m', - to: 'now', - }); - }); - - it('should return expected result when there are multiple distribution series with absolute dates', async function () { - // from:'2021-10-11T09:55:39.551Z',to:'2021-10-11T10:55:41.516Z'))) - mockMultipleSeries[0].time.from = '2021-10-11T09:55:39.551Z'; - mockMultipleSeries[0].time.to = '2021-10-11T11:55:41.516Z'; - - mockMultipleSeries[1].time.from = '2021-01-11T09:55:39.551Z'; - mockMultipleSeries[1].time.to = '2021-10-11T10:55:41.516Z'; - - await storage.set(allSeriesKey, mockMultipleSeries); - await storage.set(reportTypeKey, ReportTypes.DISTRIBUTION); - - const { result } = renderHook(() => useExpViewTimeRange(), { - wrapper: Wrapper, - }); - - expect(result.current).toEqual({ - from: '2021-01-11T09:55:39.551Z', - to: '2021-10-11T11:55:41.516Z', - }); - }); -}); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_time_range.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_time_range.ts deleted file mode 100644 index 7d6203bef2df8f..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_time_range.ts +++ /dev/null @@ -1,60 +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 { useMemo } from 'react'; -import { - AllSeries, - allSeriesKey, - convertAllShortSeries, - useSeriesStorage, -} from './use_series_storage'; - -import { ReportViewType, SeriesUrl } from '../types'; -import { ReportTypes } from '../configurations/constants'; -import { parseRelativeDate } from '../components/date_range_picker'; - -export const combineTimeRanges = ( - reportType: ReportViewType, - allSeries: SeriesUrl[], - firstSeries?: SeriesUrl -) => { - let to: string = ''; - let from: string = ''; - - if (reportType === ReportTypes.KPI) { - return firstSeries?.time; - } - - allSeries.forEach((series) => { - if (series.dataType && series.selectedMetricField && series.time) { - const seriesFrom = parseRelativeDate(series.time.from)!; - const seriesTo = parseRelativeDate(series.time.to, { roundUp: true })!; - - if (!to || seriesTo > parseRelativeDate(to, { roundUp: true })) { - to = series.time.to; - } - if (!from || seriesFrom < parseRelativeDate(from)) { - from = series.time.from; - } - } - }); - - return { to, from }; -}; -export const useExpViewTimeRange = () => { - const { storage, reportType, lastRefresh, firstSeries } = useSeriesStorage(); - - return useMemo(() => { - // we only use the data from url to apply, since that get updated to apply changes - const allSeriesFromUrl: AllSeries = convertAllShortSeries(storage.get(allSeriesKey) ?? []); - const firstSeriesT = allSeriesFromUrl?.[0]; - - return firstSeriesT ? combineTimeRanges(reportType, allSeriesFromUrl, firstSeriesT) : undefined; - // we want to keep last refresh in dependencies to force refresh - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [reportType, storage, lastRefresh, firstSeries]); -}; diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/index.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/index.tsx deleted file mode 100644 index ec7fc1e542af08..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/index.tsx +++ /dev/null @@ -1,93 +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 React from 'react'; -import { i18n } from '@kbn/i18n'; -import { useHistory } from 'react-router-dom'; -import { useKibana } from '@kbn/kibana-react-plugin/public'; -import { - createKbnUrlStateStorage, - withNotifyOnErrors, - createSessionStorageStateStorage, -} from '@kbn/kibana-utils-plugin/public'; -import { TypedLensByValueInput } from '@kbn/lens-plugin/public'; -import { ExploratoryView } from './exploratory_view'; -import { ObservabilityPublicPluginsStart } from '../../../plugin'; -import { useBreadcrumbs } from '../../../hooks/use_breadcrumbs'; -import { DataViewContextProvider } from './hooks/use_app_data_view'; -import { UrlStorageContextProvider } from './hooks/use_series_storage'; -import { useTrackPageview } from '../../..'; -import { usePluginContext } from '../../../hooks/use_plugin_context'; -import { RefreshButton } from './header/refresh_button'; - -const PAGE_TITLE = i18n.translate('xpack.observability.expView.heading.label', { - defaultMessage: 'Explore data', -}); - -export interface ExploratoryViewPageProps { - useSessionStorage?: boolean; - saveAttributes?: (attr: TypedLensByValueInput['attributes'] | null) => void; - app?: { id: string; label: string }; -} - -export function ExploratoryViewPage({ - app, - saveAttributes, - useSessionStorage = false, -}: ExploratoryViewPageProps) { - useTrackPageview({ app: 'observability-overview', path: 'exploratory-view' }); - useTrackPageview({ - app: 'observability-overview', - path: 'exploratory-view', - delay: 15000, - }); - - useBreadcrumbs( - [ - { - text: i18n.translate('xpack.observability.overview.exploratoryView', { - defaultMessage: 'Explore data', - }), - }, - ], - app - ); - - const { ObservabilityPageTemplate } = usePluginContext(); - const { - services: { uiSettings, notifications }, - } = useKibana(); - - const history = useHistory(); - - const kbnUrlStateStorage = useSessionStorage - ? createSessionStorageStateStorage() - : createKbnUrlStateStorage({ - history, - useHash: uiSettings!.get('state:storeInSessionStorage'), - ...withNotifyOnErrors(notifications!.toasts), - }); - - return ( - - ], - }} - > - - - - - - ); -} - -// eslint-disable-next-line import/no-default-export -export default ExploratoryViewPage; -export { DataTypes } from './labels'; diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/labels.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/labels.ts deleted file mode 100644 index add254e327d180..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/labels.ts +++ /dev/null @@ -1,52 +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 { i18n } from '@kbn/i18n'; - -export enum DataTypes { - SYNTHETICS = 'synthetics', - UPTIME = 'uptime', - UX = 'ux', - MOBILE = 'mobile', - METRICS = 'infra_metrics', - LOGS = 'infra_logs', - ALERTS = 'alerts', -} - -export const DataTypesLabels: Record = { - [DataTypes.UX]: i18n.translate('xpack.observability.overview.exploratoryView.uxLabel', { - defaultMessage: 'User experience (RUM)', - }), - - [DataTypes.SYNTHETICS]: i18n.translate( - 'xpack.observability.overview.exploratoryView.syntheticsLabel', - { - defaultMessage: 'Synthetics monitoring', - } - ), - - [DataTypes.UPTIME]: i18n.translate('xpack.observability.overview.exploratoryView.uptimeLabel', { - defaultMessage: 'Uptime', - }), - - [DataTypes.METRICS]: i18n.translate('xpack.observability.overview.exploratoryView.metricsLabel', { - defaultMessage: 'Metrics', - }), - - [DataTypes.LOGS]: i18n.translate('xpack.observability.overview.exploratoryView.logsLabel', { - defaultMessage: 'Logs', - }), - - [DataTypes.MOBILE]: i18n.translate( - 'xpack.observability.overview.exploratoryView.mobileExperienceLabel', - { - defaultMessage: 'Mobile experience', - } - ), - [DataTypes.ALERTS]: i18n.translate('xpack.observability.overview.exploratoryView.alertsLabel', { - defaultMessage: 'Alerts', - }), -}; diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/lens_embeddable.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/lens_embeddable.tsx deleted file mode 100644 index 833085e314a9d4..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/lens_embeddable.tsx +++ /dev/null @@ -1,139 +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 { i18n } from '@kbn/i18n'; -import React, { Dispatch, SetStateAction, useCallback, useState } from 'react'; -import styled from 'styled-components'; -import { LensEmbeddableInput, TypedLensByValueInput } from '@kbn/lens-plugin/public'; -import { useKibana } from '@kbn/kibana-react-plugin/public'; -import { useUiTracker } from '../../../hooks/use_track_metric'; -import { useSeriesStorage } from './hooks/use_series_storage'; -import { ObservabilityPublicPluginsStart } from '../../../plugin'; -import { useExpViewTimeRange } from './hooks/use_time_range'; -import { parseRelativeDate } from './components/date_range_picker'; -import { trackTelemetryOnLoad } from './utils/telemetry'; -import type { ChartTimeRange } from './header/last_updated'; - -interface Props { - lensAttributes: TypedLensByValueInput['attributes']; - setChartTimeRangeContext: Dispatch>; -} -const EXECUTION_CONTEXT = { - type: 'observability_exploratory_view', -}; - -export function LensEmbeddable(props: Props) { - const { lensAttributes, setChartTimeRangeContext } = props; - const { - services: { lens, notifications }, - } = useKibana(); - - const LensComponent = lens?.EmbeddableComponent; - const LensSaveModalComponent = lens?.SaveModalComponent; - - const { firstSeries, setSeries, reportType, lastRefresh } = useSeriesStorage(); - - const [isSaveOpen, setIsSaveOpen] = useState(false); - - const firstSeriesId = 0; - - const timeRange = useExpViewTimeRange(); - - const trackEvent = useUiTracker(); - - const onLensLoad = useCallback( - (isLoading) => { - const timeLoaded = Date.now(); - - setChartTimeRangeContext?.({ - lastUpdated: timeLoaded, - to: parseRelativeDate(timeRange?.to || '')?.valueOf(), - from: parseRelativeDate(timeRange?.from || '')?.valueOf(), - }); - - if (!isLoading) { - trackTelemetryOnLoad(trackEvent, lastRefresh, timeLoaded); - } - }, - [setChartTimeRangeContext, timeRange, lastRefresh, trackEvent] - ); - - const onBrushEnd = useCallback( - ({ range }: { range: number[] }) => { - if (reportType !== 'data-distribution' && firstSeries) { - setSeries(firstSeriesId, { - ...firstSeries, - time: { - from: new Date(range[0]).toISOString(), - to: new Date(range[1]).toISOString(), - }, - }); - } else { - notifications?.toasts.add( - i18n.translate('xpack.observability.exploratoryView.noBrusing', { - defaultMessage: 'Zoom by brush selection is only available on time series charts.', - }) - ); - } - }, - [reportType, setSeries, firstSeries, notifications?.toasts] - ); - - if (!timeRange || !lensAttributes) { - return null; - } - - return ( - - - {isSaveOpen && lensAttributes && ( - setIsSaveOpen(false)} - // if we want to do anything after the viz is saved - // right now there is no action, so an empty function - onSave={() => {}} - /> - )} - - ); -} - -const LensWrapper = styled.div` - height: 100%; - - .embPanel__optionsMenuPopover { - visibility: collapse; - } - - &&&:hover { - .embPanel__optionsMenuPopover { - visibility: visible; - } - } - - && .embPanel--editing { - border-style: initial !important; - :hover { - box-shadow: none; - } - } - .embPanel__title { - display: none; - } - - &&& > div { - height: 100%; - } -`; diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/obsv_exploratory_view.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/obsv_exploratory_view.tsx deleted file mode 100644 index 9b3f7b470dd321..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/obsv_exploratory_view.tsx +++ /dev/null @@ -1,122 +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 * as React from 'react'; -import { EuiErrorBoundary } from '@elastic/eui'; -import { getAlertsSingleMetricConfig } from './configurations/alerts_configs/single_metric_config'; -import { getAlertsKPIConfig } from './configurations/alerts_configs/kpi_over_time_config'; -import { DataTypes, DataTypesLabels } from './labels'; -import { getSyntheticsHeatmapConfig } from './configurations/synthetics/heatmap_config'; -import { getSyntheticsSingleMetricConfig } from './configurations/synthetics/single_metric_config'; -import { ExploratoryViewPage } from '.'; -import { ExploratoryViewContextProvider } from './contexts/exploratory_view_config'; -import { AppDataType, ReportViewType } from './types'; - -import { - CORE_WEB_VITALS_LABEL, - DEVICE_DISTRIBUTION_LABEL, - HEATMAP_LABEL, - KPI_OVER_TIME_LABEL, - PERF_DIST_LABEL, - SINGLE_METRIC_LABEL, -} from './configurations/constants/labels'; -import { SELECT_REPORT_TYPE } from './series_editor/series_editor'; -import { getRumDistributionConfig } from './configurations/rum/data_distribution_config'; -import { getKPITrendsLensConfig } from './configurations/rum/kpi_over_time_config'; -import { getCoreWebVitalsConfig } from './configurations/rum/core_web_vitals_config'; -import { getSyntheticsKPIConfig } from './configurations/synthetics/kpi_over_time_config'; -import { getSyntheticsDistributionConfig } from './configurations/synthetics/data_distribution_config'; -import { getMobileKPIDistributionConfig } from './configurations/mobile/distribution_config'; -import { getMobileKPIConfig } from './configurations/mobile/kpi_over_time_config'; -import { getMobileDeviceDistributionConfig } from './configurations/mobile/device_distribution_config'; -import { usePluginContext } from '../../../hooks/use_plugin_context'; -import { getLogsKPIConfig } from './configurations/infra_logs/kpi_over_time_config'; -import { getSingleMetricConfig } from './configurations/rum/single_metric_config'; - -export const dataTypes: Array<{ id: AppDataType; label: string }> = [ - { - id: DataTypes.UPTIME, - label: DataTypesLabels[DataTypes.UPTIME], - }, - { - id: DataTypes.SYNTHETICS, - label: DataTypesLabels[DataTypes.SYNTHETICS], - }, - { - id: DataTypes.UX, - label: DataTypesLabels[DataTypes.UX], - }, - { - id: DataTypes.LOGS, - label: DataTypesLabels[DataTypes.LOGS], - }, - { - id: DataTypes.MOBILE, - label: DataTypesLabels[DataTypes.MOBILE], - }, - { - id: DataTypes.ALERTS, - label: DataTypesLabels[DataTypes.ALERTS], - }, -]; - -export const reportTypesList: Array<{ - reportType: ReportViewType | typeof SELECT_REPORT_TYPE; - label: string; -}> = [ - { reportType: 'kpi-over-time', label: KPI_OVER_TIME_LABEL }, - { reportType: 'data-distribution', label: PERF_DIST_LABEL }, - { reportType: 'core-web-vitals', label: CORE_WEB_VITALS_LABEL }, - { reportType: 'device-data-distribution', label: DEVICE_DISTRIBUTION_LABEL }, - { reportType: 'single-metric', label: SINGLE_METRIC_LABEL }, - { reportType: 'heatmap', label: HEATMAP_LABEL }, -]; - -export const obsvReportConfigMap = { - [DataTypes.UX]: [ - getKPITrendsLensConfig, - getRumDistributionConfig, - getCoreWebVitalsConfig, - getSingleMetricConfig, - ], - [DataTypes.SYNTHETICS]: [ - getSyntheticsKPIConfig, - getSyntheticsDistributionConfig, - getSyntheticsSingleMetricConfig, - getSyntheticsHeatmapConfig, - ], - [DataTypes.UPTIME]: [ - getSyntheticsKPIConfig, - getSyntheticsDistributionConfig, - getSyntheticsSingleMetricConfig, - getSyntheticsHeatmapConfig, - ], - [DataTypes.MOBILE]: [ - getMobileKPIConfig, - getMobileKPIDistributionConfig, - getMobileDeviceDistributionConfig, - ], - [DataTypes.LOGS]: [getLogsKPIConfig], - [DataTypes.ALERTS]: [getAlertsKPIConfig, getAlertsSingleMetricConfig], -}; - -export function ObservabilityExploratoryView() { - const { appMountParameters } = usePluginContext(); - return ( - - - - - - ); -} diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/rtl_helpers.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/rtl_helpers.tsx deleted file mode 100644 index 9c0c1817d48936..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/rtl_helpers.tsx +++ /dev/null @@ -1,398 +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 { of } from 'rxjs'; -import React, { ReactElement } from 'react'; -import { stringify } from 'query-string'; -// eslint-disable-next-line import/no-extraneous-dependencies -import { - render as reactTestLibRender, - RenderOptions, - MatcherFunction, -} from '@testing-library/react'; -import { Router } from 'react-router-dom'; -import { Route } from '@kbn/shared-ux-router'; -import { createMemoryHistory, History } from 'history'; -import { CoreStart } from '@kbn/core/public'; -import { I18nProvider } from '@kbn/i18n-react'; -import { coreMock, themeServiceMock } from '@kbn/core/public/mocks'; -import { KibanaContextProvider, KibanaServices } from '@kbn/kibana-react-plugin/public'; -import { EuiThemeProvider } from '@kbn/kibana-react-plugin/common'; -import { lensPluginMock } from '@kbn/lens-plugin/public/mocks'; -import { setIndexPatterns } from '@kbn/unified-search-plugin/public/services'; -import type { DataView, DataViewsContract } from '@kbn/data-views-plugin/public'; -import { createStubDataView } from '@kbn/data-views-plugin/common/stubs'; -import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; -import { dataViewPluginMocks } from '@kbn/data-views-plugin/public/mocks'; -import { casesPluginMock } from '@kbn/cases-plugin/public/mocks'; -import { DataViewSpec } from '@kbn/data-views-plugin/public'; -import { rumFieldFormats } from './configurations/rum/field_formats'; -import { ObservabilityPublicPluginsStart } from '../../../plugin'; -import * as useAppDataViewHook from './hooks/use_app_data_view'; -import { DataViewContext, DataViewContextProvider } from './hooks/use_app_data_view'; -import { - AllSeries, - reportTypeKey, - SeriesContextValue, - UrlStorageContext, -} from './hooks/use_series_storage'; - -import * as fetcherHook from '../../../hooks/use_fetcher'; -import * as useSeriesFilterHook from './hooks/use_series_filters'; -import * as useHasDataHook from '../../../hooks/use_has_data'; -import * as useValuesListHook from '../../../hooks/use_values_list'; - -import dataViewData from './configurations/test_data/test_data_view.json'; - -import { AppDataType, SeriesUrl, UrlFilter } from './types'; -import { ListItem } from '../../../hooks/use_values_list'; -import { TRANSACTION_DURATION } from './configurations/constants/elasticsearch_fieldnames'; -import { dataTypes, obsvReportConfigMap, reportTypesList } from './obsv_exploratory_view'; -import { ExploratoryViewContextProvider } from './contexts/exploratory_view_config'; - -interface KibanaProps { - services?: KibanaServices; -} - -export interface KibanaProviderOptions { - core?: ExtraCore & Partial; - kibanaProps?: KibanaProps; -} - -interface MockKibanaProviderProps> - extends KibanaProviderOptions { - children: ReactElement; - history: History; -} - -type MockRouterProps> = MockKibanaProviderProps; - -type Url = - | string - | { - path: string; - queryParams: Record; - }; - -interface RenderRouterOptions extends KibanaProviderOptions { - history?: History; - renderOptions?: Omit; - url?: Url; - initSeries?: { - data?: AllSeries; - filters?: UrlFilter[]; - breakdown?: string; - }; -} - -function getSetting(key: string): T { - if (key === 'timepicker:quickRanges') { - return [ - { - display: 'Today', - from: 'now/d', - to: 'now/d', - }, - ] as unknown as T; - } - return 'MMM D, YYYY @ HH:mm:ss.SSS' as unknown as T; -} - -function setSetting$(key: string): T { - return of('MMM D, YYYY @ HH:mm:ss.SSS') as unknown as T; -} - -/* default mock core */ -const defaultCore = coreMock.createStart(); -export const mockCore: () => Partial = () => { - const core: Partial = { - ...defaultCore, - application: { - ...defaultCore.application, - getUrlForApp: () => '/app/observability', - navigateToUrl: jest.fn(), - capabilities: { - ...defaultCore.application.capabilities, - observability: { - 'alerting:save': true, - configureSettings: true, - save: true, - show: true, - }, - }, - }, - uiSettings: { - ...defaultCore.uiSettings, - get: getSetting, - get$: setSetting$, - }, - lens: lensPluginMock.createStartContract(), - data: dataPluginMock.createStartContract(), - dataViews: dataViewPluginMocks.createStartContract(), - cases: casesPluginMock.createStartContract(), - }; - - return core; -}; - -/* Mock Provider Components */ -export function MockKibanaProvider>({ - children, - core, - kibanaProps, -}: MockKibanaProviderProps) { - const dataView = mockDataView; - setIndexPatterns({ - ...[dataView], - get: async () => dataView, - } as unknown as DataViewsContract); - - return ( - - - - {children} - - - - ); -} - -export function MockRouter>({ - children, - core, - history = createMemoryHistory(), - kibanaProps, -}: MockRouterProps) { - return ( - - - - {children} - - - - ); -} - -/* Custom react testing library render */ -export function render( - ui: ReactElement, - { - history = createMemoryHistory(), - core: customCore, - kibanaProps, - renderOptions, - url = '/app/observability/exploratory-view/', - initSeries = {}, - }: RenderRouterOptions = {} -): any { - if (url) { - history = getHistoryFromUrl(url); - } - - const core = { - ...mockCore(), - ...customCore, - }; - - const seriesContextValue = mockSeriesStorageContext(initSeries); - - return { - ...reactTestLibRender( - - - - {ui} - - - , - renderOptions - ), - history, - core, - ...seriesContextValue, - }; -} - -export const getHistoryFromUrl = (url: Url) => { - if (typeof url === 'string') { - return createMemoryHistory({ - initialEntries: [url], - }); - } - - return createMemoryHistory({ - initialEntries: [url.path + stringify(url.queryParams)], - }); -}; - -export const mockFetcher = (data: any) => { - return jest.spyOn(fetcherHook, 'useFetcher').mockReturnValue({ - data, - status: fetcherHook.FETCH_STATUS.SUCCESS, - refetch: jest.fn(), - }); -}; - -export const mockUseHasData = () => { - const onRefreshTimeRange = jest.fn(); - const spy = jest.spyOn(useHasDataHook, 'useHasData').mockReturnValue({ - onRefreshTimeRange, - } as any); - return { spy, onRefreshTimeRange }; -}; - -export const mockAppDataView = (props?: Partial) => { - const loadDataView = jest.fn(); - const spy = jest.spyOn(useAppDataViewHook, 'useAppDataViewContext').mockReturnValue({ - dataView: mockDataView, - hasData: true, - loading: false, - hasAppData: { ux: true } as any, - loadDataView, - dataViews: { ux: mockDataView } as unknown as Record, - dataViewErrors: {} as any, - ...(props || {}), - }); - return { spy, loadDataView }; -}; - -export const mockUseValuesList = (values?: ListItem[]) => { - const onRefreshTimeRange = jest.fn(); - const spy = jest.spyOn(useValuesListHook, 'useValuesList').mockReturnValue({ - values: values ?? [], - } as any); - return { spy, onRefreshTimeRange }; -}; - -export const mockUxSeries = { - name: 'performance-distribution', - dataType: 'ux', - breakdown: 'user_agent.name', - time: { from: 'now-15m', to: 'now' }, - reportDefinitions: { 'service.name': ['elastic-co'] }, - selectedMetricField: TRANSACTION_DURATION, -} as SeriesUrl; - -function mockSeriesStorageContext({ - data, - filters, - breakdown, -}: { - data?: AllSeries; - filters?: UrlFilter[]; - breakdown?: string; -}) { - const testSeries = { - ...mockUxSeries, - breakdown: breakdown || 'user_agent.name', - ...(filters ? { filters } : {}), - }; - - const mockDataSeries = data || [testSeries]; - - const removeSeries = jest.fn(); - const setSeries = jest.fn(); - - const getSeries = jest.fn().mockReturnValue(testSeries); - - return { - removeSeries, - setSeries, - getSeries, - autoApply: true, - reportType: 'data-distribution', - lastRefresh: Date.now(), - setLastRefresh: jest.fn(), - setAutoApply: jest.fn(), - applyChanges: jest.fn(), - firstSeries: mockDataSeries[0], - allSeries: mockDataSeries, - setReportType: jest.fn(), - setChartTimeRangeContext: jest.fn(), - storage: { - get: jest - .fn() - .mockImplementation((key: string) => - key === reportTypeKey ? 'data-distribution' : mockDataSeries - ), - } as any, - } as SeriesContextValue; -} - -export function mockUseSeriesFilter() { - const removeFilter = jest.fn(); - const invertFilter = jest.fn(); - const setFilter = jest.fn(); - const replaceFilter = jest.fn(); - const setFiltersWildcard = jest.fn(); - const spy = jest.spyOn(useSeriesFilterHook, 'useSeriesFilters').mockReturnValue({ - removeFilter, - invertFilter, - setFilter, - replaceFilter, - setFiltersWildcard, - }); - - return { - spy, - removeFilter, - invertFilter, - setFilter, - replaceFilter, - setFiltersWildcard, - }; -} - -const hist = createMemoryHistory(); -export const mockHistory = { - ...hist, - createHref: jest.fn(({ pathname }) => `/observability${pathname}`), - push: jest.fn(), - location: { - ...hist.location, - pathname: '/current-path', - }, -}; - -const fieldFormatMap: DataViewSpec['fieldFormats'] = {}; - -rumFieldFormats.forEach(({ field, format }) => { - fieldFormatMap[field] = format; -}); - -export const mockDataView = createStubDataView({ - spec: { - id: 'apm-*', - title: 'apm-*', - timeFieldName: '@timestamp', - fields: JSON.parse(dataViewData.attributes.fields), - fieldFormats: fieldFormatMap, - }, -}); - -// This function allows us to query for the nearest button with test -// no matter whether it has nested tags or not (as EuiButton elements do). -export const forNearestButton = - (getByText: (f: MatcherFunction) => HTMLElement | null) => - (text: string): HTMLElement | null => - getByText((_content: string, node: Element | null) => { - if (!node) return false; - const noOtherButtonHasText = Array.from(node.children).every( - (child) => child && (child.textContent !== text || child.tagName.toLowerCase() !== 'button') - ); - return ( - noOtherButtonHasText && node.textContent === text && node.tagName.toLowerCase() === 'button' - ); - }); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/breakdown/breakdowns.test.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/breakdown/breakdowns.test.tsx deleted file mode 100644 index 37a554ba334d14..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/breakdown/breakdowns.test.tsx +++ /dev/null @@ -1,102 +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 React from 'react'; -import { fireEvent, screen } from '@testing-library/react'; -import { Breakdowns } from './breakdowns'; -import { mockDataView, mockUxSeries, render } from '../../rtl_helpers'; -import { getDefaultConfigs } from '../../configurations/default_configs'; -import { RECORDS_FIELD } from '../../configurations/constants'; -import { USER_AGENT_OS } from '../../configurations/constants/elasticsearch_fieldnames'; -import { obsvReportConfigMap } from '../../obsv_exploratory_view'; - -describe('Breakdowns', function () { - const dataViewSeries = getDefaultConfigs({ - reportType: 'data-distribution', - dataView: mockDataView, - dataType: 'ux', - reportConfigMap: obsvReportConfigMap, - }); - - it('should render properly', async function () { - render(); - - screen.getAllByText('Browser family'); - }); - - it('should call set series on change', function () { - const initSeries = { breakdown: USER_AGENT_OS }; - - const { setSeries } = render( - , - { initSeries } - ); - - screen.getAllByText('Operating system'); - - fireEvent.click(screen.getByTestId('seriesBreakdown')); - - fireEvent.click(screen.getByText('Browser family')); - - expect(setSeries).toHaveBeenCalledWith(0, { - breakdown: 'user_agent.name', - dataType: 'ux', - name: 'performance-distribution', - reportDefinitions: { - 'service.name': ['elastic-co'], - }, - selectedMetricField: 'transaction.duration.us', - time: { from: 'now-15m', to: 'now' }, - }); - expect(setSeries).toHaveBeenCalledTimes(1); - }); - - it('does not show percentile breakdown for records metrics', function () { - const kpiConfig = getDefaultConfigs({ - reportType: 'kpi-over-time', - dataView: mockDataView, - dataType: 'ux', - reportConfigMap: obsvReportConfigMap, - }); - - render( - - ); - - fireEvent.click(screen.getByTestId('seriesBreakdown')); - - expect(screen.queryByText('Percentile')).not.toBeInTheDocument(); - }); - - it('should disable breakdowns when a different series has a breakdown', function () { - const initSeries = { - data: [mockUxSeries, { ...mockUxSeries, breakdown: undefined }], - breakdown: USER_AGENT_OS, - }; - - render( - , - { initSeries } - ); - - const button = screen.getByText('No breakdown'); - - expect(button).toHaveAttribute('disabled'); - }); -}); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/breakdown/breakdowns.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/breakdown/breakdowns.tsx deleted file mode 100644 index 8a3bd549274b8e..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/breakdown/breakdowns.tsx +++ /dev/null @@ -1,165 +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 React, { useEffect } from 'react'; -import styled from 'styled-components'; -import { EuiSuperSelect, EuiToolTip } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; -import { useSeriesStorage } from '../../hooks/use_series_storage'; -import { - LABEL_FIELDS_BREAKDOWN, - USE_BREAK_DOWN_COLUMN, - RECORDS_FIELD, - PERCENTILE, -} from '../../configurations/constants'; -import { SeriesConfig, SeriesUrl } from '../../types'; -import { SYNTHETICS_STEP_NAME } from '../../configurations/constants/field_names/synthetics'; -import { isStepLevelMetric } from '../../configurations/synthetics/kpi_over_time_config'; - -interface Props { - seriesId: number; - series: SeriesUrl; - seriesConfig?: SeriesConfig; -} - -export function Breakdowns({ seriesConfig, seriesId, series }: Props) { - const { setSeries, allSeries } = useSeriesStorage(); - - const indexOfSeriesWithBreakdown = allSeries.findIndex((seriesT) => { - return Boolean(seriesT.breakdown); - }); - const currentSeriesHasBreakdown = indexOfSeriesWithBreakdown === seriesId; - const anySeriesHasBreakdown = indexOfSeriesWithBreakdown !== -1; - const differentSeriesHasBreakdown = anySeriesHasBreakdown && !currentSeriesHasBreakdown; - - const selectedBreakdown = series.breakdown; - const NO_BREAKDOWN = 'no_breakdown'; - - const onOptionChange = (optionId: string) => { - if (optionId === NO_BREAKDOWN) { - setSeries(seriesId, { - ...series, - breakdown: undefined, - }); - } else { - setSeries(seriesId, { - ...series, - breakdown: selectedBreakdown === optionId ? undefined : optionId, - }); - } - }; - - useEffect(() => { - if ( - !isStepLevelMetric(series.selectedMetricField) && - selectedBreakdown === SYNTHETICS_STEP_NAME - ) { - setSeries(seriesId, { - ...series, - breakdown: undefined, - }); - } - }); - - if (!seriesConfig) { - return null; - } - - const hasUseBreakdownColumn = seriesConfig.xAxisColumn.sourceField === USE_BREAK_DOWN_COLUMN; - const isRecordsMetric = series.selectedMetricField === RECORDS_FIELD; - - const items = seriesConfig.breakdownFields.map((breakdown) => ({ - id: breakdown, - label: seriesConfig.labels[breakdown] ?? breakdown, - })); - - if (!hasUseBreakdownColumn) { - items.push({ - id: NO_BREAKDOWN, - label: NO_BREAK_DOWN_LABEL, - }); - } - - const options = items - .map(({ id, label }) => { - if (id === SYNTHETICS_STEP_NAME && !isStepLevelMetric(series.selectedMetricField)) { - return { - inputDisplay: label, - value: id, - dropdownDisplay: ( - - <>{label} - - ), - disabled: true, - }; - } else { - return { - inputDisplay: label, - value: id, - dropdownDisplay: label, - }; - } - }) - .filter(({ value }) => !(value === PERCENTILE && isRecordsMetric)); - - let valueOfSelected = - selectedBreakdown || (hasUseBreakdownColumn ? options[0].value : NO_BREAKDOWN); - - if (selectedBreakdown?.startsWith('labels.')) { - valueOfSelected = LABEL_FIELDS_BREAKDOWN; - } - - function Select() { - return ( - onOptionChange(value)} - data-test-subj={'seriesBreakdown'} - disabled={differentSeriesHasBreakdown} - /> - ); - } - - return ( - - {differentSeriesHasBreakdown ? ( - - - )} - - ); -} - -export const NO_BREAK_DOWN_LABEL = i18n.translate( - 'xpack.observability.exp.breakDownFilter.noBreakdown', - { - defaultMessage: 'No breakdown', - } -); - -export const BREAKDOWN_WARNING = i18n.translate('xpack.observability.exp.breakDownFilter.warning', { - defaultMessage: 'Breakdowns can be applied to only one series at a time.', -}); - -export const BREAKDOWN_UNAVAILABLE = i18n.translate( - 'xpack.observability.exp.breakDownFilter.unavailable', - { - defaultMessage: - 'Step name breakdown is not available for monitor duration metric. Use step duration metric to breakdown by step name.', - } -); - -const Wrapper = styled.span` - .euiToolTipAnchor { - width: 100%; - } -`; diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/breakdown/label_breakdown.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/breakdown/label_breakdown.tsx deleted file mode 100644 index d85c7fcaad7214..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/breakdown/label_breakdown.tsx +++ /dev/null @@ -1,68 +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 { EuiComboBox, EuiFlexItem } from '@elastic/eui'; -import React from 'react'; -import { i18n } from '@kbn/i18n'; -import { SeriesConfig, SeriesUrl } from '../../types'; -import { useAppDataViewContext } from '../../hooks/use_app_data_view'; -import { useSeriesStorage } from '../../hooks/use_series_storage'; -import { LABEL_FIELDS_BREAKDOWN } from '../../configurations/constants'; - -interface Props { - seriesId: number; - series: SeriesUrl; - seriesConfig?: SeriesConfig; -} -export function LabelsBreakdown({ series, seriesId }: Props) { - const { dataView } = useAppDataViewContext(series.dataType); - - const labelFields = dataView?.fields.filter((field) => field.name.startsWith('labels.')); - - const { setSeries } = useSeriesStorage(); - - const { breakdown } = series; - - const hasLabelBreakdown = - breakdown === LABEL_FIELDS_BREAKDOWN || breakdown?.startsWith('labels.'); - - if (!hasLabelBreakdown) { - return null; - } - - const labelFieldOptions = labelFields?.map((field) => { - return { - label: field.name, - value: field.name, - }; - }); - - return ( - - labelField.label === breakdown)} - options={labelFieldOptions} - placeholder={CHOOSE_BREAKDOWN_FIELD} - onChange={(value) => { - setSeries(seriesId, { - ...series, - breakdown: value?.[0]?.label ?? LABEL_FIELDS_BREAKDOWN, - }); - }} - singleSelection={{ asPlainText: true }} - isInvalid={series.breakdown === LABEL_FIELDS_BREAKDOWN} - /> - - ); -} - -export const CHOOSE_BREAKDOWN_FIELD = i18n.translate( - 'xpack.observability.expView.seriesBuilder.labelField', - { - defaultMessage: 'Choose label field', - } -); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/chart_type_select.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/chart_type_select.tsx deleted file mode 100644 index 29f6bcb38cdceb..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/chart_type_select.tsx +++ /dev/null @@ -1,74 +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 React, { useState } from 'react'; -import { EuiPopover, EuiToolTip, EuiButtonEmpty, EuiIcon } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; -import { useKibana } from '@kbn/kibana-react-plugin/public'; -import { ObservabilityPublicPluginsStart } from '../../../../../plugin'; -import { SeriesUrl, useFetcher } from '../../../../..'; -import { SeriesConfig } from '../../types'; -import { SeriesChartTypesSelect } from './chart_types'; - -interface Props { - seriesId: number; - series: SeriesUrl; - seriesConfig: SeriesConfig; -} - -export function SeriesChartTypes({ seriesId, series, seriesConfig }: Props) { - const seriesType = series?.seriesType ?? seriesConfig.defaultSeriesType; - - const { - services: { lens }, - } = useKibana(); - - const { data = [] } = useFetcher(() => lens.getXyVisTypes(), [lens]); - - const icon = (data ?? []).find(({ id }) => id === seriesType)?.icon; - - const [isPopoverOpen, setIsPopoverOpen] = useState(false); - - return ( - setIsPopoverOpen(false)} - button={ - - setIsPopoverOpen((prevState) => !prevState)} - flush="both" - > - {icon && ( - id === seriesType)?.icon!} size="l" /> - )} - - - } - > - - - ); -} - -const EDIT_CHART_TYPE_LABEL = i18n.translate( - 'xpack.observability.expView.seriesEditor.editChartSeriesLabel', - { - defaultMessage: 'Edit chart type for series', - } -); - -const CHART_TYPE_LABEL = i18n.translate('xpack.observability.expView.chartTypes.label', { - defaultMessage: 'Chart type', -}); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/chart_types.test.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/chart_types.test.tsx deleted file mode 100644 index 8f196b8a05dda3..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/chart_types.test.tsx +++ /dev/null @@ -1,52 +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 React from 'react'; -import { fireEvent, screen, waitFor } from '@testing-library/react'; -import { mockUxSeries, render } from '../../rtl_helpers'; -import { SeriesChartTypesSelect, XYChartTypesSelect } from './chart_types'; - -describe.skip('SeriesChartTypesSelect', function () { - it('should render properly', async function () { - render(); - - await waitFor(() => { - screen.getByText(/chart type/i); - }); - }); - - it('should call set series on change', async function () { - const { setSeries } = render( - - ); - - await waitFor(() => { - screen.getByText(/chart type/i); - }); - - fireEvent.click(screen.getByText(/chart type/i)); - fireEvent.click(screen.getByTestId('lnsXY_seriesType-bar_stacked')); - - expect(setSeries).toHaveBeenNthCalledWith(1, 'performance-distribution', { - breakdown: 'user_agent.name', - reportType: 'pld', - seriesType: 'bar_stacked', - time: { from: 'now-15m', to: 'now' }, - }); - expect(setSeries).toHaveBeenCalledTimes(3); - }); - - describe('XYChartTypesSelect', function () { - it('should render properly', async function () { - render(); - - await waitFor(() => { - screen.getByText(/chart type/i); - }); - }); - }); -}); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/chart_types.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/chart_types.tsx deleted file mode 100644 index b75a3adcc8ae0a..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/chart_types.tsx +++ /dev/null @@ -1,114 +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 React from 'react'; -import { EuiFlexGroup, EuiFlexItem, EuiFormRow, EuiIcon, EuiSuperSelect } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; -import { useKibana } from '@kbn/kibana-react-plugin/public'; -import { SeriesType } from '@kbn/lens-plugin/public'; -import { ObservabilityPublicPluginsStart } from '../../../../../plugin'; -import { SeriesUrl, useFetcher } from '../../../../..'; -import { useSeriesStorage } from '../../hooks/use_series_storage'; - -const CHART_TYPE_LABEL = i18n.translate('xpack.observability.expView.chartTypes.label', { - defaultMessage: 'Chart type', -}); - -export function SeriesChartTypesSelect({ - seriesId, - series, - defaultChartType, -}: { - seriesId: number; - series: SeriesUrl; - defaultChartType: SeriesType; -}) { - const { setSeries } = useSeriesStorage(); - - const seriesType = series?.seriesType ?? defaultChartType; - - const onChange = (value: SeriesType) => { - setSeries(seriesId, { ...series, seriesType: value }); - }; - - return ( - - ); -} - -export interface XYChartTypesProps { - label?: string; - value: SeriesType; - includeChartTypes?: SeriesType[]; - excludeChartTypes?: SeriesType[]; - onChange: (value: SeriesType) => void; -} - -export function XYChartTypesSelect({ - onChange, - value, - includeChartTypes, - excludeChartTypes, -}: XYChartTypesProps) { - const { - services: { lens }, - } = useKibana(); - - const { data = [], loading } = useFetcher(() => lens.getXyVisTypes(), [lens]); - - let vizTypes = data; - - if ((excludeChartTypes ?? []).length > 0) { - vizTypes = vizTypes.filter(({ id }) => !excludeChartTypes?.includes(id as SeriesType)); - } - - if ((includeChartTypes ?? []).length > 0) { - vizTypes = vizTypes.filter(({ id }) => includeChartTypes?.includes(id as SeriesType)); - } - - const options = (vizTypes ?? []).map(({ id, fullLabel, label, icon }) => { - const LabelWithIcon = ( - - - - - {fullLabel || label} - - ); - return { - value: id as SeriesType, - inputDisplay: LabelWithIcon, - dropdownDisplay: LabelWithIcon, - }; - }); - - return ( - - - - ); -} diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/data_type_select.test.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/data_type_select.test.tsx deleted file mode 100644 index c3457c29386308..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/data_type_select.test.tsx +++ /dev/null @@ -1,45 +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 React from 'react'; -import { fireEvent, screen } from '@testing-library/react'; -import { mockAppDataView, mockUxSeries, render } from '../../rtl_helpers'; -import { DataTypesSelect } from './data_type_select'; -import { DataTypes, DataTypesLabels } from '../../labels'; - -describe('DataTypeSelect', function () { - const seriesId = 0; - - mockAppDataView(); - - it('should render properly', function () { - render(); - }); - - it('should set series on change', async function () { - const seriesWithoutDataType = { - ...mockUxSeries, - dataType: undefined, - }; - const { setSeries } = render( - - ); - - fireEvent.click(await screen.findByText('Select data type')); - fireEvent.click(await screen.findByText(DataTypesLabels[DataTypes.SYNTHETICS])); - - expect(setSeries).toHaveBeenCalledTimes(1); - expect(setSeries).toHaveBeenCalledWith(seriesId, { - dataType: 'synthetics', - name: 'synthetics-series-1', - time: { - from: 'now-15m', - to: 'now', - }, - }); - }); -}); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/data_type_select.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/data_type_select.tsx deleted file mode 100644 index a8ffcc5fd0bdea..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/data_type_select.tsx +++ /dev/null @@ -1,113 +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 React, { useState, useCallback } from 'react'; -import { - EuiButton, - EuiPopover, - EuiListGroup, - EuiListGroupItem, - EuiBadge, - EuiToolTip, -} from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; -import { useSeriesStorage } from '../../hooks/use_series_storage'; -import { AppDataType, SeriesUrl } from '../../types'; -import { useExploratoryView } from '../../contexts/exploratory_view_config'; - -interface Props { - seriesId: number; - series: Omit & { - dataType?: SeriesUrl['dataType']; - }; -} - -const SELECT_DATA_TYPE = 'SELECT_DATA_TYPE'; - -export function DataTypesSelect({ seriesId, series }: Props) { - const { setSeries, reportType } = useSeriesStorage(); - const [showOptions, setShowOptions] = useState(false); - - const focusButton = useCallback((ref: HTMLButtonElement) => { - ref?.focus(); - }, []); - - const onDataTypeChange = (dataType: AppDataType) => { - if (String(dataType) !== SELECT_DATA_TYPE) { - setSeries(seriesId, { - dataType, - time: series.time, - name: `${dataType}-series-${seriesId + 1}`, - }); - } - }; - - const { dataTypes, reportConfigMap } = useExploratoryView(); - - const options = dataTypes - .filter(({ id }) => { - return reportConfigMap[id]?.find((config) => config({}).reportType === reportType); - }) - .map(({ id, label }) => ({ - value: id, - inputDisplay: label, - })); - - const currDataType = dataTypes.find((dt) => dt.id === series.dataType); - - return ( - <> - {!series.dataType && ( - setShowOptions((prevState) => !prevState)} - fill - size="s" - buttonRef={focusButton} - > - {SELECT_DATA_TYPE_LABEL} - - } - isOpen={showOptions} - closePopover={() => setShowOptions((prevState) => !prevState)} - > - - {options.map((option) => ( - onDataTypeChange(option.value)} - label={option.inputDisplay} - /> - ))} - - - )} - {series.dataType && ( - - {currDataType?.label} - - )} - - ); -} - -const SELECT_DATA_TYPE_LABEL = i18n.translate( - 'xpack.observability.overview.exploratoryView.selectDataType', - { - defaultMessage: 'Select data type', - } -); - -const SELECT_DATA_TYPE_TOOLTIP = i18n.translate( - 'xpack.observability.overview.exploratoryView.selectDataTypeTooltip', - { - defaultMessage: 'Data type cannot be edited.', - } -); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/date_picker_col.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/date_picker_col.tsx deleted file mode 100644 index cc6c76755689b0..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/date_picker_col.tsx +++ /dev/null @@ -1,87 +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 React from 'react'; -import styled from 'styled-components'; -import { i18n } from '@kbn/i18n'; -import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; -import { useSeriesStorage } from '../../hooks/use_series_storage'; -import { DateRangePicker } from '../../components/date_range_picker'; -import { SeriesDatePicker } from '../../components/series_date_picker'; -import { AppDataType, SeriesUrl } from '../../types'; -import { ReportTypes } from '../../configurations/constants'; -import { useAppDataViewContext } from '../../hooks/use_app_data_view'; -import { SyntheticsAddData } from '../../../add_data_buttons/synthetics_add_data'; -import { MobileAddData } from '../../../add_data_buttons/mobile_add_data'; -import { UXAddData } from '../../../add_data_buttons/ux_add_data'; - -interface Props { - seriesId: number; - series: SeriesUrl; -} - -const AddDataComponents: Record = { - mobile: MobileAddData, - ux: UXAddData, - uptime: SyntheticsAddData, - synthetics: null, - apm: null, - infra_logs: null, - infra_metrics: null, - alerts: null, -}; - -export function DatePickerCol({ seriesId, series }: Props) { - const { reportType } = useSeriesStorage(); - - const { hasAppData } = useAppDataViewContext(); - - if (!series.dataType) { - return null; - } - - const AddDataButton = AddDataComponents[series.dataType]; - if (hasAppData[series.dataType] === false && AddDataButton !== null) { - return ( - - - - {i18n.translate('xpack.observability.overview.exploratoryView.noDataAvailable', { - defaultMessage: 'No {dataType} data available.', - values: { - dataType: series.dataType, - }, - })} - - - - - - - ); - } - - return ( - - {seriesId === 0 || reportType !== ReportTypes.KPI ? ( - - ) : ( - - )} - - ); -} - -const Wrapper = styled.div` - width: 100%; - .euiSuperDatePicker__flexWrapper { - width: 100%; - > .euiFlexItem { - margin-right: 0; - } - } -`; diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/filter_expanded.test.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/filter_expanded.test.tsx deleted file mode 100644 index d821e65afae04f..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/filter_expanded.test.tsx +++ /dev/null @@ -1,118 +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 React from 'react'; -import { fireEvent, screen, waitFor } from '@testing-library/react'; -import { FilterExpanded } from './filter_expanded'; -import { mockUxSeries, mockAppDataView, mockUseValuesList, render } from '../../rtl_helpers'; -import { USER_AGENT_NAME } from '../../configurations/constants/elasticsearch_fieldnames'; - -describe('FilterExpanded', function () { - const filters = [{ field: USER_AGENT_NAME, values: ['Chrome'] }]; - - const mockSeries = { ...mockUxSeries, filters }; - - it('render', async () => { - const initSeries = { filters }; - mockAppDataView(); - - render( - , - { initSeries } - ); - - await waitFor(() => { - screen.getByText('Browser Family'); - }); - }); - - it('should call go back on click', async function () { - const initSeries = { filters }; - - render( - , - { initSeries } - ); - - await waitFor(() => { - fireEvent.click(screen.getByText('Browser Family')); - }); - }); - - it('calls useValuesList on load', async () => { - const initSeries = { filters }; - - const { spy } = mockUseValuesList([ - { label: 'Chrome', count: 10 }, - { label: 'Firefox', count: 5 }, - ]); - - render( - , - { initSeries } - ); - - await waitFor(() => { - expect(spy).toHaveBeenCalledTimes(1); - expect(spy).toBeCalledWith( - expect.objectContaining({ - time: { from: 'now-15m', to: 'now' }, - sourceField: USER_AGENT_NAME, - }) - ); - }); - }); - - it('filters display values', async () => { - const initSeries = { filters }; - - mockUseValuesList([ - { label: 'Chrome', count: 10 }, - { label: 'Firefox', count: 5 }, - ]); - - render( - , - { initSeries } - ); - - await waitFor(() => { - fireEvent.click(screen.getByText('Browser Family')); - - expect(screen.queryByText('Firefox')).toBeTruthy(); - - fireEvent.input(screen.getByRole('searchbox'), { target: { value: 'ch' } }); - - expect(screen.queryByText('Firefox')).toBeFalsy(); - expect(screen.getByText('Chrome')).toBeTruthy(); - }); - }); -}); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/filter_expanded.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/filter_expanded.tsx deleted file mode 100644 index 09b9f443389ce2..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/filter_expanded.tsx +++ /dev/null @@ -1,56 +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 React, { useState } from 'react'; - -import { EuiFilterButton, EuiPopover } from '@elastic/eui'; -import { SeriesConfig, SeriesUrl } from '../../types'; -import { useFilterValues } from '../use_filter_values'; -import { FilterValuesList } from '../components/filter_values_list'; - -export interface FilterProps { - seriesId: number; - series: SeriesUrl; - label: string; - field: string; - isNegated?: boolean; - nestedField?: string; - baseFilters: SeriesConfig['baseFilters']; -} - -export interface NestedFilterOpen { - value: string; - negate: boolean; -} - -export function FilterExpanded(props: FilterProps) { - const [isOpen, setIsOpen] = useState(false); - - const [query, setQuery] = useState(''); - - const { values, loading } = useFilterValues(props, query); - - return ( - setIsOpen((prevState) => !prevState)} iconType="arrowDown"> - {props.label} - - } - isOpen={isOpen} - closePopover={() => setIsOpen(false)} - > - - - ); -} diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/filter_value_btn.test.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/filter_value_btn.test.tsx deleted file mode 100644 index 66f52875cfc74b..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/filter_value_btn.test.tsx +++ /dev/null @@ -1,267 +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 React from 'react'; -import { fireEvent, screen, waitFor } from '@testing-library/react'; -import { FilterValueButton } from './filter_value_btn'; -import { mockUxSeries, mockUseSeriesFilter, mockUseValuesList, render } from '../../rtl_helpers'; -import { - USER_AGENT_NAME, - USER_AGENT_VERSION, -} from '../../configurations/constants/elasticsearch_fieldnames'; - -describe('FilterValueButton', function () { - it('renders', async () => { - render( - - ); - - await waitFor(() => { - expect(screen.getByText('Chrome')).toBeInTheDocument(); - }); - }); - - describe('when negate is true', () => { - it('displays negate stats', async () => { - render( - - ); - - await waitFor(() => { - expect(screen.getByText('Not Chrome')).toBeInTheDocument(); - expect(screen.getByTitle('Not Chrome')).toBeInTheDocument(); - const btn = screen.getByRole('button'); - expect(btn.classList[4]).toContain('empty-danger'); - }); - }); - - it('calls setFilter on click', async () => { - const { setFilter, removeFilter } = mockUseSeriesFilter(); - - render( - - ); - - fireEvent.click(screen.getByText('Not Chrome')); - - await waitFor(() => { - expect(removeFilter).toHaveBeenCalledTimes(0); - expect(setFilter).toHaveBeenCalledTimes(1); - - expect(setFilter).toHaveBeenCalledWith({ - field: 'user_agent.name', - negate: true, - value: 'Chrome', - }); - }); - }); - }); - - describe('when selected', () => { - it('removes the filter on click', async () => { - const { removeFilter } = mockUseSeriesFilter(); - - render( - - ); - - fireEvent.click(screen.getByText('Chrome')); - - await waitFor(() => { - expect(removeFilter).toHaveBeenCalledWith({ - field: 'user_agent.name', - negate: false, - value: 'Chrome', - }); - }); - }); - }); - - it('should change filter on negated one', async function () { - const { removeFilter } = mockUseSeriesFilter(); - - render( - - ); - - fireEvent.click(screen.getByText('Not Chrome')); - - await waitFor(() => { - expect(removeFilter).toHaveBeenCalledWith({ - field: 'user_agent.name', - negate: true, - value: 'Chrome', - }); - }); - }); - - it('should force open nested', async function () { - mockUseSeriesFilter(); - const { spy } = mockUseValuesList(); - - render( - - ); - - await waitFor(() => { - expect(spy).toHaveBeenCalledTimes(2); - expect(spy).toBeCalledWith( - expect.objectContaining({ - filters: [ - { - term: { - [USER_AGENT_NAME]: 'Chrome', - }, - }, - ], - sourceField: 'user_agent.version', - }) - ); - }); - }); - it('should set isNestedOpen on click', async function () { - mockUseSeriesFilter(); - const { spy } = mockUseValuesList(); - - render( - - ); - - await waitFor(() => { - expect(spy).toHaveBeenCalledTimes(6); - expect(spy).toBeCalledWith( - expect.objectContaining({ - filters: [ - { - term: { - [USER_AGENT_NAME]: 'Chrome', - }, - }, - ], - sourceField: USER_AGENT_VERSION, - }) - ); - }); - }); - - it('should set call setIsNestedOpen on click selected', async function () { - mockUseSeriesFilter(); - mockUseValuesList(); - - const setIsNestedOpen = jest.fn(); - - render( - - ); - - fireEvent.click(screen.getByText('Chrome')); - await waitFor(() => { - expect(setIsNestedOpen).toHaveBeenCalledTimes(1); - expect(setIsNestedOpen).toHaveBeenCalledWith({ negate: false, value: '' }); - }); - }); - - it('should set call setIsNestedOpen on click not selected', async function () { - mockUseSeriesFilter(); - mockUseValuesList(); - - const setIsNestedOpen = jest.fn(); - - render( - - ); - - fireEvent.click(screen.getByText('Not Chrome')); - await waitFor(() => { - expect(setIsNestedOpen).toHaveBeenCalledTimes(1); - expect(setIsNestedOpen).toHaveBeenCalledWith({ negate: true, value: 'Chrome' }); - }); - }); -}); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/filter_value_btn.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/filter_value_btn.tsx deleted file mode 100644 index 4b4387d57acc6c..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/filter_value_btn.tsx +++ /dev/null @@ -1,122 +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 { i18n } from '@kbn/i18n'; - -import React, { useMemo } from 'react'; -import { EuiFilterButton, hexToRgb } from '@elastic/eui'; -import { euiStyled } from '@kbn/kibana-react-plugin/common'; -import { useAppDataViewContext } from '../../hooks/use_app_data_view'; -import { useSeriesFilters } from '../../hooks/use_series_filters'; -import FieldValueSuggestions from '../../../field_value_suggestions'; -import { SeriesUrl } from '../../types'; -import { NestedFilterOpen } from './filter_expanded'; - -interface Props { - value: string; - field: string; - allSelectedValues?: Array; - negate: boolean; - nestedField?: string; - seriesId: number; - series: SeriesUrl; - isNestedOpen: { - value: string; - negate: boolean; - }; - setIsNestedOpen: (val: NestedFilterOpen) => void; -} - -export function FilterValueButton({ - isNestedOpen, - setIsNestedOpen, - value, - field, - negate, - seriesId, - series, - nestedField, - allSelectedValues, -}: Props) { - const { dataViews } = useAppDataViewContext(series.dataType); - - const { setFilter, removeFilter } = useSeriesFilters({ seriesId, series }); - - const hasActiveFilters = (allSelectedValues ?? []).includes(value); - - const button = ( - { - if (hasActiveFilters) { - removeFilter({ field, value, negate }); - } else { - setFilter({ field, value, negate }); - } - if (!hasActiveFilters) { - setIsNestedOpen({ value, negate }); - } else { - setIsNestedOpen({ value: '', negate }); - } - }} - > - {negate - ? i18n.translate('xpack.observability.expView.filterValueButton.negate', { - defaultMessage: 'Not {value}', - values: { value }, - }) - : value} - - ); - - const onNestedChange = (valuesN?: string[]) => { - (valuesN ?? []).forEach((valN) => { - setFilter({ field: nestedField!, value: valN! }); - }); - setIsNestedOpen({ value: '', negate }); - }; - - const forceOpenNested = isNestedOpen?.value === value && isNestedOpen.negate === negate; - - const filters = useMemo(() => { - return [ - { - term: { - [field]: value, - }, - }, - ]; - }, [field, value]); - - return nestedField && forceOpenNested ? ( - - ) : ( - button - ); -} - -const FilterButton = euiStyled(EuiFilterButton)` - background-color: rgba(${(props) => { - const color = props.hasActiveFilters - ? props.color === 'danger' - ? hexToRgb(props.theme.eui.euiColorDanger) - : hexToRgb(props.theme.eui.euiColorPrimary) - : 'initial'; - return `${color[0]}, ${color[1]}, ${color[2]}, 0.1`; - }}); -`; diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/incomplete_badge.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/incomplete_badge.tsx deleted file mode 100644 index eedcce11616ef5..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/incomplete_badge.tsx +++ /dev/null @@ -1,70 +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 React from 'react'; -import { isEmpty } from 'lodash'; -import { i18n } from '@kbn/i18n'; -import { EuiBadge } from '@elastic/eui'; -import { useAppDataViewContext } from '../../hooks/use_app_data_view'; -import { SeriesConfig, SeriesUrl } from '../../types'; - -interface Props { - series: SeriesUrl; - seriesConfig?: SeriesConfig; -} - -export function IncompleteBadge({ seriesConfig, series }: Props) { - const { loading } = useAppDataViewContext(); - - if (!seriesConfig) { - return null; - } - const { dataType, reportDefinitions, selectedMetricField } = series; - const { definitionFields, labels } = seriesConfig; - const isIncomplete = - (!dataType || isEmpty(reportDefinitions) || !selectedMetricField) && !loading; - - const incompleteDefinition = isEmpty(reportDefinitions) - ? i18n.translate('xpack.observability.overview.exploratoryView.missingReportDefinition', { - defaultMessage: 'Missing {reportDefinition}', - values: { - reportDefinition: - labels?.[ - typeof definitionFields[0] === 'string' - ? definitionFields[0] - : definitionFields[0]?.field - ], - }, - }) - : ''; - - let incompleteMessage = !selectedMetricField ? MISSING_REPORT_METRIC_LABEL : incompleteDefinition; - - if (!dataType) { - incompleteMessage = MISSING_DATA_TYPE_LABEL; - } - - if (!isIncomplete) { - return null; - } - - return {incompleteMessage}; -} - -const MISSING_REPORT_METRIC_LABEL = i18n.translate( - 'xpack.observability.overview.exploratoryView.missingReportMetric', - { - defaultMessage: 'Missing report metric', - } -); - -const MISSING_DATA_TYPE_LABEL = i18n.translate( - 'xpack.observability.overview.exploratoryView.missingDataType', - { - defaultMessage: 'Missing data type', - } -); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/operation_type_select.test.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/operation_type_select.test.tsx deleted file mode 100644 index 94761f36118697..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/operation_type_select.test.tsx +++ /dev/null @@ -1,67 +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 React from 'react'; -import { fireEvent, screen } from '@testing-library/react'; -import { mockUxSeries, render } from '../../rtl_helpers'; -import { OperationTypeSelect } from './operation_type_select'; - -describe('OperationTypeSelect', function () { - it('should render properly', function () { - render(); - - // SR-only text 'Select an option: , is selected' - // was removed here: https://github.com/elastic/eui/pull/6630#discussion_r1123655995 - screen.getByRole('button'); - }); - - it('should display selected value', function () { - const initSeries = { - data: [ - { - name: 'performance-distribution', - dataType: 'ux' as const, - operationType: 'median' as const, - time: { from: 'now-15m', to: 'now' }, - }, - ], - }; - - render(, { - initSeries, - }); - - screen.getByText('Median'); - }); - - it('should call set series on change', function () { - const initSeries = { - data: [ - { - name: 'performance-distribution', - dataType: 'ux' as const, - operationType: 'median' as const, - time: { from: 'now-15m', to: 'now' }, - }, - ], - }; - - const { setSeries } = render(, { - initSeries, - }); - - fireEvent.click(screen.getByTestId('operationTypeSelect')); - - fireEvent.click(screen.getByText('95th Percentile')); - expect(setSeries).toHaveBeenCalledWith(0, { - operationType: '95th', - dataType: 'ux', - time: { from: 'now-15m', to: 'now' }, - name: 'performance-distribution', - }); - }); -}); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/operation_type_select.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/operation_type_select.tsx deleted file mode 100644 index f67f348ec101d7..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/operation_type_select.tsx +++ /dev/null @@ -1,132 +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 React from 'react'; -import { i18n } from '@kbn/i18n'; -import { EuiSuperSelect } from '@elastic/eui'; - -import { OperationType } from '@kbn/lens-plugin/public'; -import { useSeriesStorage } from '../../hooks/use_series_storage'; -import { SeriesUrl } from '../../types'; - -export function OperationTypeSelect({ - seriesId, - series, - defaultOperationType, -}: { - seriesId: number; - series: SeriesUrl; - defaultOperationType?: OperationType; -}) { - const { setSeries } = useSeriesStorage(); - - const operationType = series?.operationType; - - const onChange = (value: OperationType) => { - setSeries(seriesId, { ...series, operationType: value }); - }; - - return ( - - ); -} - -export function OperationTypeComponent({ - operationType, - onChange, -}: { - operationType?: OperationType; - onChange: (value: OperationType) => void; -}) { - const options = [ - { - value: 'min' as OperationType, - inputDisplay: i18n.translate('xpack.observability.expView.operationType.min', { - defaultMessage: 'Min', - }), - }, - { - value: 'max' as OperationType, - inputDisplay: i18n.translate('xpack.observability.expView.operationType.max', { - defaultMessage: 'Max', - }), - }, - { - value: 'average' as OperationType, - inputDisplay: i18n.translate('xpack.observability.expView.operationType.average', { - defaultMessage: 'Average', - }), - }, - { - value: 'median' as OperationType, - inputDisplay: i18n.translate('xpack.observability.expView.operationType.median', { - defaultMessage: 'Median', - }), - }, - { - value: 'sum' as OperationType, - inputDisplay: i18n.translate('xpack.observability.expView.operationType.sum', { - defaultMessage: 'Sum', - }), - }, - { - value: 'last_value' as OperationType, - inputDisplay: i18n.translate('xpack.observability.expView.operationType.lastValue', { - defaultMessage: 'Last value', - }), - }, - { - value: 'unique_count' as OperationType, - inputDisplay: i18n.translate('xpack.observability.expView.operationType.uniqueCount', { - defaultMessage: 'Unique count', - }), - }, - { - value: '25th' as OperationType, - inputDisplay: i18n.translate('xpack.observability.expView.operationType.25thPercentile', { - defaultMessage: '25th Percentile', - }), - }, - { - value: '75th' as OperationType, - inputDisplay: i18n.translate('xpack.observability.expView.operationType.75thPercentile', { - defaultMessage: '75th Percentile', - }), - }, - { - value: '90th' as OperationType, - inputDisplay: i18n.translate('xpack.observability.expView.operationType.90thPercentile', { - defaultMessage: '90th Percentile', - }), - }, - { - value: '95th' as OperationType, - inputDisplay: i18n.translate('xpack.observability.expView.operationType.95thPercentile', { - defaultMessage: '95th Percentile', - }), - }, - { - value: '99th' as OperationType, - inputDisplay: i18n.translate('xpack.observability.expView.operationType.99thPercentile', { - defaultMessage: '99th Percentile', - }), - }, - ]; - - return ( - - ); -} diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/report_definition_col.test.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/report_definition_col.test.tsx deleted file mode 100644 index 980c02a0ab1531..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/report_definition_col.test.tsx +++ /dev/null @@ -1,82 +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 { fireEvent, screen, waitFor } from '@testing-library/react'; -import React from 'react'; -import { getDefaultConfigs } from '../../configurations/default_configs'; -import { - mockAppDataView, - mockDataView, - mockUseValuesList, - mockUxSeries, - render, -} from '../../rtl_helpers'; -import { ReportDefinitionCol } from './report_definition_col'; -import { obsvReportConfigMap } from '../../obsv_exploratory_view'; - -describe('Series Builder ReportDefinitionCol', function () { - mockAppDataView(); - const seriesId = 0; - - const seriesConfig = getDefaultConfigs({ - reportType: 'data-distribution', - dataView: mockDataView, - dataType: 'ux', - reportConfigMap: obsvReportConfigMap, - }); - - mockUseValuesList([{ label: 'elastic-co', count: 10 }]); - - it('renders', async () => { - render( - - ); - - await waitFor(() => { - expect(screen.getByText('Web Application')).toBeInTheDocument(); - expect(screen.getByText('Environment')).toBeInTheDocument(); - expect(screen.getByText('Search Environment')).toBeInTheDocument(); - }); - }); - - it('should render selected report definitions', async function () { - render( - - ); - - expect(await screen.findByText('elastic-co')).toBeInTheDocument(); - - expect(screen.getAllByTestId('comboBoxToggleListButton')[0]).toBeInTheDocument(); - }); - - it('should be able to remove selected definition', async function () { - const { setSeries } = render( - - ); - - expect( - await screen.findByLabelText('Remove elastic-co from selection in this group') - ).toBeInTheDocument(); - - fireEvent.click(screen.getAllByTestId('comboBoxToggleListButton')[0]); - - const removeBtn = await screen.findByTitle(/Remove elastic-co from selection in this group/i); - - fireEvent.click(removeBtn); - - expect(setSeries).toHaveBeenCalledTimes(1); - - expect(setSeries).toHaveBeenCalledWith(seriesId, { - dataType: 'ux', - name: 'performance-distribution', - breakdown: 'user_agent.name', - reportDefinitions: {}, - selectedMetricField: 'transaction.duration.us', - time: { from: 'now-15m', to: 'now' }, - }); - }); -}); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/report_definition_col.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/report_definition_col.tsx deleted file mode 100644 index ccb439549c6193..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/report_definition_col.tsx +++ /dev/null @@ -1,140 +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 React from 'react'; -import { isEmpty } from 'lodash'; -import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; -import { useSeriesStorage } from '../../hooks/use_series_storage'; -import { SeriesConfig, SeriesUrl } from '../../types'; -import { ReportDefinitionField } from './report_definition_field'; -import { TextReportDefinitionField } from './text_report_definition_field'; -import { isStepLevelMetric } from '../../configurations/synthetics/kpi_over_time_config'; -import { SYNTHETICS_STEP_NAME } from '../../configurations/constants/field_names/synthetics'; - -export function ReportDefinitionCol({ - seriesId, - series, - seriesConfig, -}: { - seriesId: number; - series: SeriesUrl; - seriesConfig: SeriesConfig; -}) { - const { setSeries } = useSeriesStorage(); - - const { - reportDefinitions: selectedReportDefinitions = {}, - textReportDefinitions: selectedTextReportDefinitions = {}, - } = series; - - const { definitionFields, textDefinitionFields } = seriesConfig; - - const onChange = (field: string, value?: string[]) => { - if (!value?.[0]) { - delete selectedReportDefinitions[field]; - setSeries(seriesId, { - ...series, - reportDefinitions: { ...selectedReportDefinitions }, - }); - } else { - setSeries(seriesId, { - ...series, - reportDefinitions: { ...selectedReportDefinitions, [field]: value }, - }); - } - }; - - const onChangeTextDefinitionField = (field: string, value: string) => { - if (isEmpty(value)) { - delete selectedTextReportDefinitions[field]; - setSeries(seriesId, { - ...series, - textReportDefinitions: { ...selectedTextReportDefinitions }, - }); - } else { - setSeries(seriesId, { - ...series, - textReportDefinitions: { ...selectedTextReportDefinitions, [field]: value }, - }); - } - }; - - const hasFieldDataSelected = (field: string) => { - return !isEmpty(series.reportDefinitions?.[field]); - }; - - return ( - - {definitionFields.map((field) => { - const fieldStr = typeof field === 'string' ? field : field.field; - const singleSelection = typeof field !== 'string' && field.singleSelection; - const nestedField = typeof field !== 'string' && field.nested; - const filters = typeof field !== 'string' ? field.filters : undefined; - - const isNonStepMetric = !isStepLevelMetric(series.selectedMetricField); - - const hideNestedStep = nestedField === SYNTHETICS_STEP_NAME && isNonStepMetric; - - if (hideNestedStep && nestedField && selectedReportDefinitions[nestedField]?.length > 0) { - setSeries(seriesId, { - ...series, - reportDefinitions: { ...selectedReportDefinitions, [nestedField]: [] }, - }); - } - - let nestedFieldElement; - - if (nestedField && hasFieldDataSelected(fieldStr) && !hideNestedStep) { - nestedFieldElement = ( - - - - ); - } - - return ( - <> - - - - {nestedFieldElement} - - ); - })} - - {textDefinitionFields?.map((field) => { - return ( - - - - ); - })} - - ); -} diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/report_definition_field.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/report_definition_field.tsx deleted file mode 100644 index 7ccebcd84282d8..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/report_definition_field.tsx +++ /dev/null @@ -1,105 +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 React, { useMemo } from 'react'; -import { isEmpty } from 'lodash'; -import { ExistsFilter, PhraseFilter } from '@kbn/es-query'; -import type { ESFilter } from '@kbn/es-types'; -import { PersistableFilter } from '@kbn/lens-plugin/common'; -import { ALL_VALUES_SELECTED } from '../../configurations/constants/url_constants'; -import FieldValueSuggestions from '../../../field_value_suggestions'; -import { useAppDataViewContext } from '../../hooks/use_app_data_view'; -import { buildPhrasesFilter } from '../../configurations/utils'; -import { SeriesConfig, SeriesUrl } from '../../types'; - -interface Props { - seriesId: number; - series: SeriesUrl; - singleSelection?: boolean; - keepHistory?: boolean; - field: string | { field: string; nested: string }; - seriesConfig: SeriesConfig; - onChange: (field: string, value?: string[]) => void; - filters?: Array; -} - -export function ReportDefinitionField({ - singleSelection, - keepHistory, - series, - field: fieldProp, - seriesConfig, - onChange, - filters, -}: Props) { - const { dataView } = useAppDataViewContext(series.dataType); - - const field = typeof fieldProp === 'string' ? fieldProp : fieldProp.field; - - const { reportDefinitions: selectedReportDefinitions = {} } = series; - - const { labels, baseFilters, definitionFields } = seriesConfig; - - const queryFilters = useMemo(() => { - const filtersN: ESFilter[] = []; - (baseFilters ?? []) - .concat(filters ?? []) - .forEach((qFilter: PersistableFilter | ExistsFilter) => { - if (qFilter.query) { - filtersN.push(qFilter.query); - } - const existFilter = qFilter as ExistsFilter; - if (existFilter.query.exists) { - filtersN.push({ exists: existFilter.query.exists }); - } - }); - - if (!isEmpty(selectedReportDefinitions)) { - definitionFields.forEach((fieldObj) => { - const fieldT = typeof fieldObj === 'string' ? fieldObj : fieldObj.field; - - if (dataView && selectedReportDefinitions?.[fieldT] && fieldT !== field) { - const values = selectedReportDefinitions?.[fieldT]; - if (!values.includes(ALL_VALUES_SELECTED)) { - const valueFilter = buildPhrasesFilter(fieldT, values, dataView)[0]; - if (valueFilter.query) { - filtersN.push(valueFilter.query); - } - } - } - }); - } - - return filtersN; - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [JSON.stringify(selectedReportDefinitions), JSON.stringify(baseFilters)]); - - if (!dataView) { - return null; - } - - return ( - onChange(field, val)} - filters={queryFilters} - time={series.time} - fullWidth={true} - asCombobox={true} - allowExclusions={false} - allowAllValuesSelection={true} - usePrependLabel={false} - compressed={false} - required={isEmpty(selectedReportDefinitions)} - singleSelection={singleSelection} - keepHistory={keepHistory} - /> - ); -} diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/report_type_select.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/report_type_select.tsx deleted file mode 100644 index 3e91f8140ce0ee..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/report_type_select.tsx +++ /dev/null @@ -1,58 +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 React from 'react'; -import { EuiSuperSelect } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; -import { useSeriesStorage } from '../../hooks/use_series_storage'; -import { ReportViewType } from '../../types'; - -import { useExploratoryView } from '../../contexts/exploratory_view_config'; - -const SELECT_REPORT_TYPE = 'SELECT_REPORT_TYPE'; - -interface Props { - prepend: string; -} - -const SELECT_REPORT = { - reportType: SELECT_REPORT_TYPE, - label: i18n.translate('xpack.observability.expView.reportType.selectLabel', { - defaultMessage: 'Select report type', - }), -}; - -export function ReportTypesSelect({ prepend }: Props) { - const { setReportType, reportType: selectedReportType, allSeries } = useSeriesStorage(); - - const { reportTypes } = useExploratoryView(); - - const onReportTypeChange = (reportType: ReportViewType) => { - setReportType(reportType); - }; - - const options = [SELECT_REPORT, ...reportTypes] - .filter(({ reportType }) => (selectedReportType ? reportType !== SELECT_REPORT_TYPE : true)) - .map(({ reportType, label }) => ({ - value: reportType, - inputDisplay: reportType === SELECT_REPORT_TYPE ? label : {label}, - dropdownDisplay: label, - })); - - return ( - onReportTypeChange(value as ReportViewType)} - style={{ minWidth: 200 }} - isInvalid={!selectedReportType && allSeries.length > 0} - disabled={allSeries.length > 0} - prepend={prepend} - /> - ); -} diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/selected_filters.test.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/selected_filters.test.tsx deleted file mode 100644 index ef0f7c47d3f675..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/selected_filters.test.tsx +++ /dev/null @@ -1,46 +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 React from 'react'; -import { screen, waitFor } from '@testing-library/react'; -import { mockAppDataView, mockDataView, mockUxSeries, render } from '../../rtl_helpers'; -import { SelectedFilters } from './selected_filters'; -import { getDefaultConfigs } from '../../configurations/default_configs'; -import { USER_AGENT_NAME } from '../../configurations/constants/elasticsearch_fieldnames'; -import { obsvReportConfigMap } from '../../obsv_exploratory_view'; - -describe('SelectedFilters', function () { - mockAppDataView(); - - const dataViewSeries = getDefaultConfigs({ - reportType: 'data-distribution', - dataView: mockDataView, - dataType: 'ux', - reportConfigMap: obsvReportConfigMap, - }); - - it('should render properly', async function () { - const filters = [{ field: USER_AGENT_NAME, values: ['Chrome'] }]; - const initSeries = { filters }; - - render( - , - { - initSeries, - } - ); - - await waitFor(() => { - screen.getByText('Chrome'); - screen.getByTitle('Filter: Browser family: Chrome. Select for more filter actions.'); - }); - }); -}); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/selected_filters.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/selected_filters.tsx deleted file mode 100644 index f1dfbfcf23e26e..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/selected_filters.tsx +++ /dev/null @@ -1,152 +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 React, { Fragment } from 'react'; -import { EuiButtonEmpty, EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; -import { FilterLabel } from '../../components/filter_label'; -import { SeriesConfig, SeriesUrl, UrlFilter } from '../../types'; -import { useAppDataViewContext } from '../../hooks/use_app_data_view'; -import { useSeriesFilters } from '../../hooks/use_series_filters'; -import { useSeriesStorage } from '../../hooks/use_series_storage'; - -interface Props { - seriesId: number; - series: SeriesUrl; - seriesConfig: SeriesConfig; -} -export function SelectedFilters({ seriesId, series, seriesConfig }: Props) { - const { setSeries } = useSeriesStorage(); - - const { labels } = seriesConfig; - - const filters: UrlFilter[] = series.filters ?? []; - - const { removeFilter, replaceFilter } = useSeriesFilters({ seriesId, series }); - - const { dataView } = useAppDataViewContext(series.dataType); - - if (filters.length === 0 || !dataView) { - return null; - } - - const btnProps = { - seriesId, - series, - dataView, - }; - - return ( - <> - - {filters.map( - ({ field, values = [], notValues = [], wildcards = [], notWildcards = [] }) => ( - - {values.length > 0 && ( - - { - replaceFilter({ - field, - values: [], - notValues, - wildcards, - notWildcards, - }); - }} - negate={false} - {...btnProps} - /> - - )} - {notValues.length > 0 && ( - - { - replaceFilter({ - field, - notValues: [], - values, - wildcards, - notWildcards, - }); - }} - {...btnProps} - /> - - )} - {wildcards.length > 0 && ( - - { - wildcards?.forEach((val) => { - removeFilter({ field, value: val, negate: false, isWildcard: true }); - }); - }} - {...btnProps} - /> - - )} - {notWildcards.length > 0 && ( - - { - notWildcards?.forEach((val) => { - removeFilter({ field, value: val, negate: true, isWildcard: true }); - }); - }} - {...btnProps} - /> - - )} - - ) - )} - - {(series.filters ?? []).length > 0 && ( - - { - setSeries(seriesId, { ...series, filters: undefined }); - }} - size="xs" - > - {i18n.translate('xpack.observability.expView.seriesEditor.clearFilter', { - defaultMessage: 'Clear filters', - })} - - - )} - - - - ); -} diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/series_actions.test.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/series_actions.test.tsx deleted file mode 100644 index ec5c3b3c4eca0b..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/series_actions.test.tsx +++ /dev/null @@ -1,56 +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 React from 'react'; -import userEvent from '@testing-library/user-event'; -import { screen } from '@testing-library/react'; -import { waitForEuiPopoverOpen } from '@elastic/eui/lib/test/rtl'; -import { SeriesActions } from './series_actions'; -import { mockUxSeries, render } from '../../rtl_helpers'; - -describe('SeriesActions', function () { - it('should contain an edit button', function () { - const { getByLabelText } = render(); - - expect(getByLabelText('Edit series')).toBeInTheDocument(); - }); - - it('should contain an actions button', function () { - const { getByLabelText } = render(); - - expect(getByLabelText('View series actions')).toBeInTheDocument(); - }); - - describe('action context menu', function () { - beforeEach(async () => { - render(); - - const actionsButton = screen.getByLabelText('View series actions'); - userEvent.click(actionsButton); - await waitForEuiPopoverOpen(); - }); - - it('should display the action list when the actions button is clicked', function () { - expect(screen.getByLabelText('Series actions list')).toBeVisible(); - }); - - it('should display a view transaction link', function () { - expect(screen.getByLabelText('View transaction in Discover')).toBeVisible(); - }); - - it('should display a hide series link', function () { - expect(screen.getByLabelText('Hide series')).toBeVisible(); - }); - - it('should display a duplicates series link', function () { - expect(screen.getByLabelText('Duplicate series')).toBeVisible(); - }); - - it('should display a remove series link', function () { - expect(screen.getByLabelText('Remove series')).toBeVisible(); - }); - }); -}); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/series_actions.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/series_actions.tsx deleted file mode 100644 index aab83cc511d9c0..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/series_actions.tsx +++ /dev/null @@ -1,199 +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 React, { useState, useCallback } from 'react'; -import { - EuiButtonIcon, - EuiFlexGroup, - EuiFlexItem, - EuiToolTip, - EuiContextMenuPanel, - EuiContextMenuItem, - EuiPopover, -} from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; -import { useSeriesStorage } from '../../hooks/use_series_storage'; -import { SeriesConfig, SeriesUrl } from '../../types'; -import { useDiscoverLink } from '../../hooks/use_discover_link'; -import { useAppDataViewContext } from '../../hooks/use_app_data_view'; - -interface Props { - seriesId: number; - series: SeriesUrl; - seriesConfig?: SeriesConfig; - onEditClick?: () => void; -} - -export function SeriesActions({ seriesId, series, seriesConfig, onEditClick }: Props) { - const { setSeries, removeSeries, allSeries } = useSeriesStorage(); - const [isPopoverOpen, setPopover] = useState(false); - - const { href: discoverHref } = useDiscoverLink({ series, seriesConfig }); - - const { dataViews } = useAppDataViewContext(); - - const dataView = dataViews?.[series.dataType]; - const deleteDisabled = seriesId === 0 && allSeries.length > 1; - - const copySeries = () => { - let copySeriesId: string = `${series.name}-copy`; - if (allSeries.find(({ name }) => name === copySeriesId)) { - copySeriesId = copySeriesId + allSeries.length; - } - setSeries(allSeries.length, { ...series, name: copySeriesId, breakdown: undefined }); - closePopover(); - }; - - const toggleSeries = () => { - if (series.hidden) { - setSeries(seriesId, { ...series, hidden: undefined }); - } else { - setSeries(seriesId, { ...series, hidden: true }); - } - closePopover(); - }; - - const closePopover = useCallback(() => { - setPopover(false); - }, [setPopover]); - - const onRemoveSeriesClick = useCallback(() => { - removeSeries(seriesId); - closePopover(); - }, [removeSeries, seriesId, closePopover]); - - const changePopoverVisibility = useCallback(() => { - setPopover(!isPopoverOpen); - }, [setPopover, isPopoverOpen]); - - const popoverButton = ( - - ); - - return ( - - - - - - - - - - - {VIEW_SAMPLE_DOCUMENTS_LABEL} - , - - {series.hidden ? SHOW_SERIES_LABEL : HIDE_SERIES_LABEL} - , - - {COPY_SERIES_LABEL} - , - - {DELETE_SERIES_LABEL} - , - ]} - /> - - - - ); -} - -const EDIT_SERIES_LABEL = i18n.translate('xpack.observability.seriesEditor.edit', { - defaultMessage: 'Edit series', -}); - -const HIDE_SERIES_LABEL = i18n.translate('xpack.observability.seriesEditor.hide', { - defaultMessage: 'Hide series', -}); - -const SHOW_SERIES_LABEL = i18n.translate('xpack.observability.seriesEditor.show', { - defaultMessage: 'Show series', -}); - -const COPY_SERIES_LABEL = i18n.translate('xpack.observability.seriesEditor.clone', { - defaultMessage: 'Duplicate series', -}); - -const DELETE_SERIES_LABEL = i18n.translate( - 'xpack.observability.expView.seriesEditor.removeSeries', - { - defaultMessage: 'Remove series', - } -); - -const DELETE_SERIES_TOOLTIP_LABEL = i18n.translate( - 'xpack.observability.expView.seriesEditor.removeSeriesDisabled', - { - defaultMessage: - 'Main series cannot be removed. Please remove all series below before you can remove this.', - } -); - -const VIEW_SAMPLE_DOCUMENTS_LABEL = i18n.translate( - 'xpack.observability.seriesEditor.sampleDocuments', - { - defaultMessage: 'View transaction in Discover', - } -); - -const POPOVER_BUTTON_LABEL = i18n.translate('xpack.observability.seriesEditor.popoverButtonLabel', { - defaultMessage: 'View series actions', -}); - -const ACTIONS_CONTEXT_MENU_LABEL = i18n.translate( - 'xpack.observability.seriesEditor.actionsAriaContextLabel', - { - defaultMessage: 'Series actions list', - } -); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/series_filter.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/series_filter.tsx deleted file mode 100644 index cc84f64c2c7f05..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/series_filter.tsx +++ /dev/null @@ -1,96 +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 React, { useMemo } from 'react'; -import { EuiFilterGroup, EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui'; -import { FilterExpanded } from './filter_expanded'; -import { SeriesConfig, SeriesUrl } from '../../types'; -import { FieldLabels, LABEL_FIELDS_FILTER } from '../../configurations/constants/constants'; -import { SelectedFilters } from './selected_filters'; -import { LabelsFieldFilter } from '../components/labels_filter'; -import { URLSearch } from '../../components/url_search/url_search'; -import { TRANSACTION_URL } from '../../configurations/constants/elasticsearch_fieldnames'; - -interface Props { - seriesId: number; - seriesConfig: SeriesConfig; - series: SeriesUrl; -} - -export interface Field { - label: string; - field: string; - nestedField?: string; - isNegated?: boolean; -} - -export function SeriesFilter({ series, seriesConfig, seriesId }: Props) { - const options: Field[] = seriesConfig.filterFields - .filter((field) => field !== TRANSACTION_URL) - .map((field) => { - if (typeof field === 'string') { - return { label: seriesConfig.labels?.[field] ?? FieldLabels[field] ?? field, field }; - } - - return { - field: field.field, - nestedField: field.nested, - isNegated: field.isNegated, - label: (seriesConfig.labels?.[field.field] ?? FieldLabels[field.field]) || field.field, - }; - }); - - const hasUrlFilter = useMemo(() => { - return seriesConfig.filterFields.some((field) => { - if (typeof field === 'string') { - return field === TRANSACTION_URL; - } else if (field.field !== undefined) { - return field.field === TRANSACTION_URL; - } else { - return false; - } - }); - }, [seriesConfig]); - - return ( - <> - - {hasUrlFilter ? ( - - - - ) : null} - - - {options.map((opt) => - opt.field === LABEL_FIELDS_FILTER ? ( - - ) : ( - - ) - )} - - - - - - - - ); -} diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/series_info.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/series_info.tsx deleted file mode 100644 index 4c2e57e7805508..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/series_info.tsx +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; -import { SeriesConfig, SeriesUrl } from '../../types'; -import { SeriesColorPicker } from '../../components/series_color_picker'; -import { SeriesChartTypes } from './chart_type_select'; - -interface Props { - seriesId: number; - series: SeriesUrl; - seriesConfig?: SeriesConfig; -} - -export function SeriesInfo({ seriesId, series, seriesConfig }: Props) { - if (!seriesConfig) { - return null; - } - - return ( - - - - - - - - - ); - - return null; -} diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/series_name.test.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/series_name.test.tsx deleted file mode 100644 index cbd7efc42d964f..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/series_name.test.tsx +++ /dev/null @@ -1,89 +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 React from 'react'; -import { fireEvent, screen, waitFor } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; -import { mockUxSeries, render } from '../../rtl_helpers'; -import { SeriesName } from './series_name'; - -// ensures that fields appropriately match to their label -jest.mock('@elastic/eui/lib/services/accessibility/html_id_generator', () => ({ - ...jest.requireActual('@elastic/eui/lib/services/accessibility/html_id_generator'), - htmlIdGenerator: () => () => `id-${Math.random()}`, -})); - -describe('SeriesName', function () { - it('should render properly', async function () { - render(); - - expect(screen.getByText(mockUxSeries.name)).toBeInTheDocument(); - }); - - it('should display input when editing name', async function () { - render(); - - let input = screen.queryByTestId('exploratoryViewSeriesNameInput') as HTMLInputElement; - - // read only - expect(input).not.toBeInTheDocument(); - - const editButton = screen.getByRole('button'); - // toggle editing - fireEvent.click(editButton); - - await waitFor(() => { - input = screen.getByTestId('exploratoryViewSeriesNameInput') as HTMLInputElement; - - expect(input).toBeInTheDocument(); - expect(input.value).toBe(mockUxSeries.name); - }); - - // toggle readonly - fireEvent.click(editButton); - - await waitFor(() => { - input = screen.queryByTestId('exploratoryViewSeriesNameInput') as HTMLInputElement; - - expect(screen.getByText(mockUxSeries.name)).toBeInTheDocument(); - expect(input).not.toBeInTheDocument(); - }); - }); - - it('should save name on enter key', async function () { - const newName = '-test-new-name'; - render(); - - let input = screen.queryByTestId('exploratoryViewSeriesNameInput') as HTMLInputElement; - - // read only - expect(input).not.toBeInTheDocument(); - - const editButton = screen.getByRole('button'); - // toggle editing - userEvent.click(editButton); - - await waitFor(() => { - input = screen.getByTestId('exploratoryViewSeriesNameInput') as HTMLInputElement; - - expect(input).toBeInTheDocument(); - }); - - userEvent.click(input); - userEvent.type(input, newName); - - // submit - userEvent.keyboard('{enter}'); - - await waitFor(() => { - input = screen.queryByTestId('exploratoryViewSeriesNameInput') as HTMLInputElement; - - expect(screen.getByText(`${mockUxSeries.name}${newName}`)).toBeInTheDocument(); - expect(input).not.toBeInTheDocument(); - }); - }); -}); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/series_name.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/series_name.tsx deleted file mode 100644 index a8d0338e9eb7ea..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/series_name.tsx +++ /dev/null @@ -1,115 +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 React, { useState, ChangeEvent, useEffect, useRef, KeyboardEventHandler } from 'react'; -import styled from 'styled-components'; -import { i18n } from '@kbn/i18n'; -import { - EuiFieldText, - EuiText, - EuiButtonIcon, - EuiFlexGroup, - EuiFlexItem, - EuiOutsideClickDetector, -} from '@elastic/eui'; -import { useSeriesStorage } from '../../hooks/use_series_storage'; -import { SeriesUrl } from '../../types'; - -interface Props { - seriesId: number; - series: SeriesUrl; -} - -export const StyledText = styled(EuiText)` - &.euiText.euiText--constrainedWidth { - max-width: 200px; - text-overflow: ellipsis; - white-space: nowrap; - overflow: hidden; - } -`; - -export function SeriesName({ series, seriesId }: Props) { - const { setSeries } = useSeriesStorage(); - - const [value, setValue] = useState(series.name); - const [isEditingEnabled, setIsEditingEnabled] = useState(false); - const inputRef = useRef(null); - const buttonRef = useRef(null); - - const onChange = (e: ChangeEvent) => { - setValue(e.target.value); - }; - - const onSave = () => { - if (value !== series.name) { - setSeries(seriesId, { ...series, name: value }); - } - }; - - const onOutsideClick = (event: Event) => { - if (event.target !== buttonRef.current) { - setIsEditingEnabled(false); - onSave(); - } - }; - - const onKeyDown: KeyboardEventHandler = (event) => { - if (event.key === 'Enter') { - setIsEditingEnabled(false); - onSave(); - } - }; - - useEffect(() => { - setValue(series.name); - }, [series.name]); - - useEffect(() => { - if (isEditingEnabled && inputRef.current) { - inputRef.current.focus(); - } - }, [isEditingEnabled, inputRef]); - - return ( - - {isEditingEnabled ? ( - - - - - - ) : ( - - {value} - - )} - - setIsEditingEnabled(!isEditingEnabled)} - iconType="pencil" - aria-label={i18n.translate('xpack.observability.expView.seriesEditor.editName', { - defaultMessage: 'Edit name', - })} - color="text" - buttonRef={buttonRef} - /> - - - ); -} diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/text_report_definition_field.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/text_report_definition_field.tsx deleted file mode 100644 index 98012a42a58948..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/text_report_definition_field.tsx +++ /dev/null @@ -1,40 +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 React from 'react'; -import { EuiFieldText, EuiFormRow } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; -import { SeriesConfig, SeriesUrl } from '../../types'; - -interface Props { - seriesId: number; - series: SeriesUrl; - field: string; - seriesConfig: SeriesConfig; - onChange: (field: string, value: string) => void; -} - -export function TextReportDefinitionField({ series, field, seriesConfig, onChange }: Props) { - const { textReportDefinitions: selectedTextReportDefinitions = {} } = series; - const { labels } = seriesConfig; - const label = labels[field] ?? field; - - return ( - - onChange(field, e.target.value)} - compressed={false} - /> - - ); -} diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/components/filter_values_list.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/components/filter_values_list.tsx deleted file mode 100644 index a0601e81a6c358..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/components/filter_values_list.tsx +++ /dev/null @@ -1,144 +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 { EuiFieldSearch, EuiFilterGroup, EuiProgress, EuiSpacer, EuiText } from '@elastic/eui'; -import React, { Fragment, useState } from 'react'; -import { rgba } from 'polished'; -import styled from 'styled-components'; -import { map } from 'lodash'; -import { i18n } from '@kbn/i18n'; -import { euiStyled } from '@kbn/kibana-react-plugin/common'; -import { FilterValueButton } from '../columns/filter_value_btn'; -import { FilterProps, NestedFilterOpen } from '../columns/filter_expanded'; -import { UrlFilter } from '../../types'; -import { ListItem } from '../../../../../hooks/use_values_list'; - -interface Props extends FilterProps { - values: ListItem[]; - field: string; - query: string; - loading?: boolean; - setQuery: (q: string) => void; -} - -export function FilterValuesList({ - field, - values, - query, - setQuery, - label, - loading, - isNegated, - nestedField, - series, - seriesId, -}: Props) { - const [isNestedOpen, setIsNestedOpen] = useState({ value: '', negate: false }); - - const displayValues = map(values, 'label').filter((opt) => - opt.toLowerCase().includes(query.toLowerCase()) - ); - - const filters = series?.filters ?? []; - - const currFilter: UrlFilter | undefined = filters.find(({ field: fd }) => field === fd); - - const btnProps = { - field, - nestedField, - seriesId, - series, - isNestedOpen, - setIsNestedOpen, - }; - - return ( - - { - setQuery(evt.target.value); - }} - placeholder={getSearchLabel(label)} - /> - - - {loading && ( -
- -
- )} - {displayValues.length === 0 && !loading && ( - {NO_RESULT_FOUND} - )} - {displayValues.map((opt) => ( - - - {isNegated !== false && ( - - )} - - - - - ))} -
-
- ); -} - -const NO_RESULT_FOUND = i18n.translate('xpack.observability.filters.expanded.noFilter', { - defaultMessage: 'No filters found.', -}); - -const getSearchLabel = (label: string) => - i18n.translate('xpack.observability.filters.expanded.search', { - defaultMessage: 'Search for {label}', - values: { label }, - }); - -const ListWrapper = euiStyled.div` - height: 370px; - overflow-y: auto; - &::-webkit-scrollbar { - height: ${({ theme }) => theme.eui.euiScrollBar}; - width: ${({ theme }) => theme.eui.euiScrollBar}; - } - &::-webkit-scrollbar-thumb { - background-clip: content-box; - background-color: ${({ theme }) => rgba(theme.eui.euiColorDarkShade, 0.5)}; - border: ${({ theme }) => theme.eui.euiScrollBarCorner} solid transparent; - } - &::-webkit-scrollbar-corner, - &::-webkit-scrollbar-track { - background-color: transparent; - } -`; - -const Wrapper = styled.div` - width: 400px; -`; diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/components/labels_filter.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/components/labels_filter.tsx deleted file mode 100644 index 1a7cf1e22165e8..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/components/labels_filter.tsx +++ /dev/null @@ -1,129 +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 React, { useState } from 'react'; -import { - EuiPopoverTitle, - EuiFilterButton, - EuiPopover, - EuiIcon, - EuiButtonEmpty, - EuiSelectableOption, -} from '@elastic/eui'; - -import { EuiSelectable } from '@elastic/eui'; - -import { i18n } from '@kbn/i18n'; -import { FilterProps } from '../columns/filter_expanded'; -import { useAppDataViewContext } from '../../hooks/use_app_data_view'; -import { FilterValuesList } from './filter_values_list'; -import { useFilterValues } from '../use_filter_values'; - -export function LabelsFieldFilter(props: FilterProps) { - const { series } = props; - - const [query, setQuery] = useState(''); - - const { dataView } = useAppDataViewContext(series.dataType); - - const labelFields = dataView?.fields.filter((field) => field.name.startsWith('labels.')); - - const [isPopoverOpen, setPopover] = useState(false); - - const onButtonClick = () => { - setPopover(!isPopoverOpen); - }; - - const button = ( - - {LABELS_LABEL} - - ); - - const [selectedLabel, setSelectedLabel] = useState(''); - - const { values, loading } = useFilterValues({ ...props, field: selectedLabel }, query); - - const labelFieldOptions: EuiSelectableOption[] = (labelFields ?? []).map((field) => { - return { - label: field.name, - searchableLabel: field.name, - append: , - showIcons: false, - }; - }); - - labelFieldOptions.unshift({ - label: LABELS_FIELDS_LABEL, - isGroupLabel: true, - }); - - const closePopover = () => { - setPopover(false); - setSelectedLabel(''); - }; - - return ( - - {selectedLabel ? ( - <> - - setSelectedLabel('')} - > - {BACK_TO_LABEL} - - - - - ) : ( - { - const checked = optionsChange.find((option) => option.checked === 'on'); - setSelectedLabel(checked?.label ?? ''); - }} - listProps={{ - onFocusBadge: false, - }} - height={450} - > - {(list, search) => ( -
- {search} - {list} -
- )} -
- )} -
- ); -} - -const LABELS_LABEL = i18n.translate('xpack.observability.filters.expanded.labels.label', { - defaultMessage: 'Labels', -}); - -const LABELS_FIELDS_LABEL = i18n.translate('xpack.observability.filters.expanded.labels.fields', { - defaultMessage: 'Label fields', -}); - -const BACK_TO_LABEL = i18n.translate('xpack.observability.filters.expanded.labels.backTo', { - defaultMessage: 'Back to labels', -}); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/expanded_series_row.test.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/expanded_series_row.test.tsx deleted file mode 100644 index 5d70e42808ea99..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/expanded_series_row.test.tsx +++ /dev/null @@ -1,42 +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 React from 'react'; -import { screen } from '@testing-library/react'; -import { ExpandedSeriesRow } from './expanded_series_row'; -import { mockDataView, mockUxSeries, render } from '../rtl_helpers'; -import { getDefaultConfigs } from '../configurations/default_configs'; -import { PERCENTILE } from '../configurations/constants'; -import { obsvReportConfigMap } from '../obsv_exploratory_view'; - -describe('ExpandedSeriesRow', function () { - const dataViewSeries = getDefaultConfigs({ - reportConfigMap: obsvReportConfigMap, - reportType: 'kpi-over-time', - dataView: mockDataView, - dataType: 'ux', - }); - - it('should render properly', async function () { - render(); - - expect(screen.getByText('Breakdown by')).toBeInTheDocument(); - expect(screen.getByText('Operation')).toBeInTheDocument(); - }); - - it('should not display operation field when percentile breakdowns are applied', async function () { - render( - - ); - - expect(screen.queryByText('Operation')).toBeInTheDocument(); - }); -}); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/expanded_series_row.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/expanded_series_row.tsx deleted file mode 100644 index 9c910879a1716d..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/expanded_series_row.tsx +++ /dev/null @@ -1,107 +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 React from 'react'; -import { i18n } from '@kbn/i18n'; - -import { EuiFlexGroup, EuiFlexItem, EuiFormRow, EuiHorizontalRule } from '@elastic/eui'; -import { SeriesConfig, SeriesUrl } from '../types'; -import { PERCENTILE } from '../configurations/constants'; -import { ReportDefinitionCol } from './columns/report_definition_col'; -import { OperationTypeSelect } from './columns/operation_type_select'; -import { parseCustomFieldName } from '../configurations/lens_attributes'; -import { SeriesFilter } from './columns/series_filter'; -import { DatePickerCol } from './columns/date_picker_col'; -import { Breakdowns } from './breakdown/breakdowns'; -import { LabelsBreakdown } from './breakdown/label_breakdown'; - -function getColumnType(seriesConfig: SeriesConfig, selectedMetricField?: string) { - const metricOption = parseCustomFieldName(seriesConfig, selectedMetricField); - - if (!Array.isArray(metricOption)) { - return metricOption?.columnType; - } -} - -interface Props { - seriesId: number; - series: SeriesUrl; - seriesConfig?: SeriesConfig; -} -export function ExpandedSeriesRow(seriesProps: Props) { - const { seriesConfig, series, seriesId } = seriesProps; - - if (!seriesConfig) { - return null; - } - - const { selectedMetricField } = series ?? {}; - - const { hasOperationType, yAxisColumns } = seriesConfig; - - const columnType = getColumnType(seriesConfig, selectedMetricField); - - // if the breakdown field is percentiles, we can't apply further operations - const hasPercentileBreakdown = series.breakdown === PERCENTILE; - - return ( -
- - - - - - - - - - - - - - - - - - - - - - - - - - {(hasOperationType || (columnType === 'operation' && !hasPercentileBreakdown)) && ( - - - - - - )} - -
- ); -} - -const BREAKDOWN_BY_LABEL = i18n.translate('xpack.observability.expView.seriesBuilder.breakdownBy', { - defaultMessage: 'Breakdown by', -}); - -const FILTERS_LABEL = i18n.translate('xpack.observability.expView.seriesBuilder.selectFilters', { - defaultMessage: 'Filters', -}); - -const OPERATION_LABEL = i18n.translate('xpack.observability.expView.seriesBuilder.operation', { - defaultMessage: 'Operation', -}); - -const DATE_LABEL = i18n.translate('xpack.observability.expView.seriesBuilder.date', { - defaultMessage: 'Date', -}); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/report_metric_options.test.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/report_metric_options.test.tsx deleted file mode 100644 index 63725346ba18b2..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/report_metric_options.test.tsx +++ /dev/null @@ -1,75 +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 React from 'react'; -import { screen } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; -import { mockAppDataView, mockDataView, mockUxSeries, render } from '../rtl_helpers'; -import { getDefaultConfigs } from '../configurations/default_configs'; -import { PERCENTILE } from '../configurations/constants'; -import { ReportMetricOptions } from './report_metric_options'; -import { obsvReportConfigMap } from '../obsv_exploratory_view'; - -describe('ReportMetricOptions', function () { - const dataViewSeries = getDefaultConfigs({ - dataType: 'ux', - reportType: 'kpi-over-time', - dataView: mockDataView, - reportConfigMap: obsvReportConfigMap, - }); - - it('should render properly', async function () { - render( - - ); - - expect(await screen.findByText('No data available')).toBeInTheDocument(); - }); - - it('should display loading if index pattern is not available and is loading', async function () { - mockAppDataView({ loading: true, dataViews: undefined }); - const { container } = render( - - ); - - expect(container.getElementsByClassName('euiLoadingSpinner').length).toBe(1); - }); - - it('should not display loading if index pattern is already loaded', async function () { - mockAppDataView({ loading: true }); - render( - - ); - - expect(await screen.findByText('Page load time')).toBeInTheDocument(); - }); - - it('should include a tooltip for the report metric', async function () { - mockAppDataView({ loading: false }); - const { getByText, findByText } = render( - - ); - - userEvent.hover(getByText('Page load time')); - - // The tooltip from EUI takes 250ms to appear, so we must - // use a `find*` query to asynchronously poll for it. - expect(await findByText('Report metric')).toBeInTheDocument(); - }); -}); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/report_metric_options.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/report_metric_options.tsx deleted file mode 100644 index 68eb718ce28906..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/report_metric_options.tsx +++ /dev/null @@ -1,187 +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 React, { useState, useCallback } from 'react'; -import { - EuiToolTip, - EuiPopover, - EuiButton, - EuiListGroup, - EuiListGroupItem, - EuiBadge, - EuiText, - EuiLoadingSpinner, -} from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; -import { FormattedMessage } from '@kbn/i18n-react'; -import { useSeriesStorage } from '../hooks/use_series_storage'; -import { SeriesConfig, SeriesUrl } from '../types'; -import { useAppDataViewContext } from '../hooks/use_app_data_view'; -import { RECORDS_FIELD, RECORDS_PERCENTAGE_FIELD } from '../configurations/constants'; - -interface Props { - seriesId: number; - series: SeriesUrl; - defaultValue?: string; - seriesConfig?: SeriesConfig; -} - -export function ReportMetricOptions({ seriesId, series, seriesConfig }: Props) { - const { setSeries } = useSeriesStorage(); - const [showOptions, setShowOptions] = useState(false); - const metricOptions = seriesConfig?.metricOptions; - - const { dataViews, dataViewErrors, loading } = useAppDataViewContext(); - - const onChange = (value?: string) => { - setSeries(seriesId, { - ...series, - selectedMetricField: value, - }); - }; - - const focusButton = useCallback((ref: HTMLButtonElement) => { - ref?.focus(); - }, []); - - if (!series.dataType) { - return null; - } - - const dataView = dataViews?.[series.dataType]; - const dataViewError = dataViewErrors?.[series.dataType]; - - const options = (metricOptions ?? []).map(({ label, field, id }) => { - let disabled = false; - - if (field !== RECORDS_FIELD && field !== RECORDS_PERCENTAGE_FIELD && field) { - disabled = !Boolean(dataView?.getFieldByName(field)); - } - return { - disabled, - value: field || id, - dropdownDisplay: disabled ? ( - {field}, - }} - /> - } - > - {label} - - ) : ( - label - ), - inputDisplay: label, - }; - }); - - if (dataViewError && !dataView && !loading) { - // TODO: Add a link to docs to explain how to add index patterns - return ( - - {dataViewError.body?.error === 'Forbidden' || - dataViewError.name === 'DataViewInsufficientAccessError' - ? NO_PERMISSIONS - : dataViewError.body?.message} - - ); - } - - if (!dataView && !loading) { - return {NO_DATA_AVAILABLE}; - } - - return ( - <> - {!series.selectedMetricField && ( - setShowOptions((prevState) => !prevState)} - fill - size="s" - isLoading={!dataView && loading} - buttonRef={focusButton} - > - {SELECT_REPORT_METRIC_LABEL} - - } - isOpen={showOptions} - closePopover={() => setShowOptions((prevState) => !prevState)} - > - - {options.map((option) => ( - onChange(option.value)} - label={option.dropdownDisplay} - isDisabled={option.disabled} - /> - ))} - - - )} - {series.selectedMetricField && - (dataView ? ( - - onChange(undefined)} - iconOnClickAriaLabel={REMOVE_REPORT_METRIC_LABEL} - > - {seriesConfig?.metricOptions?.find( - (option) => - option.id === series.selectedMetricField || - option.field === series.selectedMetricField - )?.label ?? series.selectedMetricField} - - - ) : ( - - ))} - - ); -} - -const SELECT_REPORT_METRIC_LABEL = i18n.translate( - 'xpack.observability.expView.seriesEditor.selectReportMetric', - { - defaultMessage: 'Select report metric', - } -); - -const REMOVE_REPORT_METRIC_LABEL = i18n.translate( - 'xpack.observability.expView.seriesEditor.removeReportMetric', - { - defaultMessage: 'Remove report metric', - } -); - -const NO_DATA_AVAILABLE = i18n.translate('xpack.observability.expView.seriesEditor.noData', { - defaultMessage: 'No data available', -}); - -const NO_PERMISSIONS = i18n.translate('xpack.observability.expView.seriesEditor.noPermissions', { - defaultMessage: - "Unable to create Data View. You don't have the required permission, please contact your admin.", -}); - -const REPORT_METRIC_TOOLTIP = i18n.translate( - 'xpack.observability.expView.seriesEditor.reportMetricTooltip', - { - defaultMessage: 'Report metric', - } -); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/series.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/series.tsx deleted file mode 100644 index 33fc5ef541b68d..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/series.tsx +++ /dev/null @@ -1,114 +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 React, { useEffect, useState } from 'react'; -import styled from 'styled-components'; -import { i18n } from '@kbn/i18n'; -import { EuiFlexItem, EuiFlexGroup, EuiPanel, EuiAccordion, EuiSpacer } from '@elastic/eui'; -import { BuilderItem } from '../types'; -import { SeriesActions } from './columns/series_actions'; -import { SeriesInfo } from './columns/series_info'; -import { DataTypesSelect } from './columns/data_type_select'; -import { IncompleteBadge } from './columns/incomplete_badge'; -import { ExpandedSeriesRow } from './expanded_series_row'; -import { SeriesName } from './columns/series_name'; -import { ReportMetricOptions } from './report_metric_options'; - -const StyledAccordion = styled(EuiAccordion)` - .euiAccordion__button { - width: auto; - flex-grow: 0; - } - - .euiAccordion__optionalAction { - flex-grow: 1; - flex-shrink: 1; - } - - .euiAccordion__childWrapper { - overflow: visible; - } -`; - -interface Props { - item: BuilderItem; - isExpanded: boolean; - toggleExpanded: () => void; -} - -export function Series({ item, isExpanded, toggleExpanded }: Props) { - const { id } = item; - const seriesProps = { - ...item, - seriesId: id, - }; - - const [isExpandedOnce, setIsExpandedOnce] = useState(false); - - useEffect(() => { - if (isExpanded) { - setIsExpandedOnce(true); - } - }, [isExpanded]); - - return ( - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - } - > - - - {isExpandedOnce && } - - - - ); -} - -export const ACCORDION_LABEL = i18n.translate( - 'xpack.observability.expView.seriesBuilder.accordion.label', - { - defaultMessage: 'Toggle series information', - } -); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/series_editor.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/series_editor.tsx deleted file mode 100644 index 0a5a57e95efccf..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/series_editor.tsx +++ /dev/null @@ -1,248 +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 React, { useEffect, useState } from 'react'; -import { i18n } from '@kbn/i18n'; -import { EuiSpacer, EuiFormRow, EuiFlexItem, EuiFlexGroup } from '@elastic/eui'; -import { rgba } from 'polished'; -import { euiStyled } from '@kbn/kibana-react-plugin/common'; -import { AppDataType, ReportViewType, BuilderItem } from '../types'; -import { SeriesContextValue, useSeriesStorage } from '../hooks/use_series_storage'; -import { DataViewState, useAppDataViewContext } from '../hooks/use_app_data_view'; -import { getDefaultConfigs } from '../configurations/default_configs'; -import { ReportTypesSelect } from './columns/report_type_select'; -import { ViewActions } from '../views/view_actions'; -import { Series } from './series'; -import { ReportConfigMap, useExploratoryView } from '../contexts/exploratory_view_config'; - -export interface ReportTypeItem { - id: string; - reportType: ReportViewType; - label: string; -} - -type ExpandedRowMap = Record; - -export const getSeriesToEdit = ({ - dataViews, - allSeries, - reportType, - reportConfigMap, -}: { - allSeries: SeriesContextValue['allSeries']; - dataViews: DataViewState; - reportType: ReportViewType; - reportConfigMap: ReportConfigMap; -}): BuilderItem[] => { - const getDataViewSeries = (dataType: AppDataType) => { - if (dataViews?.[dataType]) { - return getDefaultConfigs({ - dataType, - reportType, - reportConfigMap, - dataView: dataViews[dataType], - }); - } - }; - - return allSeries.map((series, seriesIndex) => { - const seriesConfig = getDataViewSeries(series.dataType); - - return { id: seriesIndex, series, seriesConfig }; - }); -}; - -export const SeriesEditor = React.memo(function () { - const [editorItems, setEditorItems] = useState([]); - - const { getSeries, allSeries, reportType } = useSeriesStorage(); - - const { loading, dataViews } = useAppDataViewContext(); - - const { reportConfigMap, setIsEditMode } = useExploratoryView(); - - const [itemIdToExpandedRowMap, setItemIdToExpandedRowMap] = useState>({}); - - const [{ prevCount, curCount }, setSeriesCount] = useState<{ - prevCount?: number; - curCount: number; - }>({ - curCount: allSeries.length, - }); - - useEffect(() => { - setIsEditMode?.(Object.keys(itemIdToExpandedRowMap).length > 0); - }, [itemIdToExpandedRowMap, setIsEditMode]); - - useEffect(() => { - setSeriesCount((oldParams) => ({ prevCount: oldParams.curCount, curCount: allSeries.length })); - if (typeof prevCount !== 'undefined' && !isNaN(prevCount) && prevCount < curCount) { - setItemIdToExpandedRowMap({}); - } - }, [allSeries.length, curCount, prevCount]); - - useEffect(() => { - const newExpandRows: ExpandedRowMap = {}; - - setEditorItems((prevState) => { - const newEditorItems = getSeriesToEdit({ - reportType, - allSeries, - dataViews, - reportConfigMap, - }); - - newEditorItems.forEach(({ series, id }) => { - const prevSeriesItem = prevState.find(({ id: prevId }) => prevId === id); - if ( - prevSeriesItem && - series.selectedMetricField && - prevSeriesItem.series.selectedMetricField !== series.selectedMetricField - ) { - newExpandRows[id] = true; - } - }); - return [...newEditorItems]; - }); - - setItemIdToExpandedRowMap((prevState) => { - return { ...prevState, ...newExpandRows }; - }); - }, [allSeries, getSeries, dataViews, loading, reportConfigMap, reportType]); - - const toggleDetails = (item: BuilderItem) => { - const itemIdToExpandedRowMapValues = { ...itemIdToExpandedRowMap }; - if (itemIdToExpandedRowMapValues[item.id]) { - delete itemIdToExpandedRowMapValues[item.id]; - } else { - itemIdToExpandedRowMapValues[item.id] = true; - } - setItemIdToExpandedRowMap(itemIdToExpandedRowMapValues); - }; - - return ( - - - - - - - - - - - setItemIdToExpandedRowMap({})} /> - - - - - {editorItems.map((item, index) => ( -
- toggleDetails(item)} - isExpanded={itemIdToExpandedRowMap[item.id]} - /> - {index + 1 !== editorItems.length && } -
- ))} -
-
- ); -}); - -const Wrapper = euiStyled.div` - &::-webkit-scrollbar { - height: ${({ theme }) => theme.eui.euiScrollBar}; - width: ${({ theme }) => theme.eui.euiScrollBar}; - } - &::-webkit-scrollbar-thumb { - background-clip: content-box; - background-color: ${({ theme }) => rgba(theme.eui.euiColorDarkShade, 0.5)}; - border: ${({ theme }) => theme.eui.euiScrollBarCorner} solid transparent; - } - &::-webkit-scrollbar-corner, - &::-webkit-scrollbar-track { - background-color: transparent; - } - - &&& { - .euiTableRow-isExpandedRow .euiTableRowCell { - border-top: none; - background-color: #FFFFFF; - border-bottom: 2px solid #d3dae6; - border-right: 2px solid rgb(211, 218, 230); - border-left: 2px solid rgb(211, 218, 230); - } - - .isExpanded { - border-right: 2px solid rgb(211, 218, 230); - border-left: 2px solid rgb(211, 218, 230); - .euiTableRowCell { - border-bottom: none; - } - } - .isIncomplete .euiTableRowCell { - background-color: rgba(254, 197, 20, 0.1); - } - } -`; - -const SectionHeaderBackground = euiStyled.div` - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 56px; - background-color: ${({ theme }) => theme.eui.euiPageBackgroundColor}; - border-bottom: 1px solid ${({ theme }) => theme.eui.euiColorLightShade}; - z-index: 90; -`; - -const StickyFlexGroup = euiStyled(EuiFlexGroup)` - position: sticky; - top: 0; - z-index: 100; - padding: 0; -`; - -const EditorRowsWrapper = euiStyled.div` - margin: ${({ theme }) => theme.eui.euiSizeM} 0; -`; - -export const LOADING_VIEW = i18n.translate( - 'xpack.observability.expView.seriesBuilder.loadingView', - { - defaultMessage: 'Loading view ...', - } -); - -export const SELECT_REPORT_TYPE = i18n.translate( - 'xpack.observability.expView.seriesBuilder.selectReportType', - { - defaultMessage: 'No report type selected', - } -); - -export const REPORT_TYPE_LABEL = i18n.translate( - 'xpack.observability.expView.seriesBuilder.reportType', - { - defaultMessage: 'Report type', - } -); - -export const REPORT_TYPE_ARIA_LABEL = i18n.translate( - 'xpack.observability.expView.seriesBuilder.reportType.aria', - { - defaultMessage: 'This select allows you to choose the type of report you wish to create', - } -); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/use_filter_values.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/use_filter_values.ts deleted file mode 100644 index 8a6653dd62c1b9..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/use_filter_values.ts +++ /dev/null @@ -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 { ExistsFilter, isExistsFilter } from '@kbn/es-query'; -import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; -import type { ESFilter } from '@kbn/es-types'; -import { PersistableFilter } from '@kbn/lens-plugin/common'; -import { useValuesList } from '../../../../hooks/use_values_list'; -import { FilterProps } from './columns/filter_expanded'; -import { useAppDataViewContext } from '../hooks/use_app_data_view'; - -export function useFilterValues( - { field, series, baseFilters, label }: FilterProps, - query?: string -) { - const { dataViews } = useAppDataViewContext(series.dataType); - - const queryFilters: ESFilter[] = []; - - baseFilters?.forEach((qFilter: PersistableFilter | ExistsFilter) => { - if (qFilter.query) { - queryFilters.push(qFilter.query); - } - if (isExistsFilter(qFilter)) { - queryFilters.push({ exists: qFilter.query.exists } as estypes.QueryDslQueryContainer); - } - }); - - return useValuesList({ - query, - label: label ?? field, - sourceField: field, - time: series.time, - keepHistory: true, - filters: queryFilters, - dataViewTitle: dataViews[series.dataType]?.title, - }); -} diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/types.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/types.ts deleted file mode 100644 index 690f00e19fec15..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/types.ts +++ /dev/null @@ -1,186 +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 type { PaletteOutput } from '@kbn/coloring'; -import type { ExistsFilter, PhraseFilter } from '@kbn/es-query'; -import type { - LastValueIndexPatternColumn, - DateHistogramIndexPatternColumn, - FieldBasedIndexPatternColumn, - SeriesType, - OperationType, - YConfig, - MetricState, -} from '@kbn/lens-plugin/public'; - -import type { PersistableFilter } from '@kbn/lens-plugin/common'; -import type { DataView } from '@kbn/data-views-plugin/common'; -import { - FieldFormatParams as BaseFieldFormatParams, - SerializedFieldFormat, -} from '@kbn/field-formats-plugin/common'; -import { TermsIndexPatternColumn } from '@kbn/lens-plugin/public'; -import { FORMULA_COLUMN } from './configurations/constants'; - -export const ReportViewTypes = { - dist: 'data-distribution', - kpi: 'kpi-over-time', - cwv: 'core-web-vitals', - mdd: 'device-data-distribution', - smt: 'single-metric', - htm: 'heatmap', -} as const; - -type ValueOf = T[keyof T]; - -export type ReportViewTypeId = keyof typeof ReportViewTypes; - -export type ReportViewType = ValueOf; - -export interface ColumnFilter { - language: 'kuery'; - query: string; -} - -export interface ParamFilter { - label: string; - input: ColumnFilter; -} - -export interface MetricOption { - id: string; - field?: string; - label: string; - description?: string; - columnType?: - | 'range' - | 'operation' - | 'FILTER_RECORDS' - | 'TERMS_COLUMN' - | 'unique_count' - | typeof FORMULA_COLUMN; - columnFilters?: ColumnFilter[]; - columnFilter?: ColumnFilter; - paramFilters?: ParamFilter[]; - timeScale?: string; - showPercentileAnnotations?: boolean; - formula?: string; - metricStateOptions?: Pick; - palette?: PaletteOutput; - format?: 'percent' | 'number'; - emptyAsNull?: boolean; - timestampField?: string; -} - -export interface SeriesConfig { - reportType: ReportViewType | string; - xAxisColumn: Partial | Partial; - yAxisColumns: Array>; - breakdownFields: string[]; - defaultSeriesType: SeriesType; - filterFields: Array; - seriesTypes: SeriesType[]; - baseFilters?: Array; - definitionFields: Array< - | string - | { - field: string; - nested?: string; - singleSelection?: boolean; - filters?: Array; - } - >; - textDefinitionFields?: string[]; - metricOptions?: Array< - | MetricOption - | { id: string; field?: string; label: string; items: MetricOption[]; columnType?: string } - >; - labels: Record; - hasOperationType: boolean; - palette?: PaletteOutput; - yTitle?: string; - yConfig?: YConfig[]; - query?: { query: string; language: 'kuery' }; -} - -export type URLReportDefinition = Record; -export type URLTextReportDefinition = Record; - -export interface SeriesUrl { - name: string; - time: { - to: string; - from: string; - }; - breakdown?: string; - filters?: UrlFilter[]; - seriesType?: SeriesType; - operationType?: OperationType; - dataType: AppDataType; - reportDefinitions?: URLReportDefinition; - textReportDefinitions?: URLTextReportDefinition; - selectedMetricField?: string; - hidden?: boolean; - showPercentileAnnotations?: boolean; - color?: string; -} - -export interface UrlFilter { - field: string; - values?: Array; - notValues?: Array; - wildcards?: string[]; - notWildcards?: string[]; -} - -export interface ConfigProps { - dataView?: DataView; - series?: SeriesUrl; - spaceId?: string; -} - -interface FormatType extends SerializedFieldFormat { - id: 'duration' | 'number' | 'bytes' | 'percent'; -} - -export type AppDataType = - | 'synthetics' - | 'uptime' - | 'ux' - | 'infra_logs' - | 'infra_metrics' - | 'apm' - | 'mobile' - | 'alerts'; - -type InputFormat = 'microseconds' | 'milliseconds' | 'seconds'; -type OutputFormat = 'asSeconds' | 'asMilliseconds' | 'humanize' | 'humanizePrecise'; - -export interface FieldFormatParams extends BaseFieldFormatParams { - inputFormat?: InputFormat; - outputFormat?: OutputFormat; - outputPrecision?: number; - showSuffix?: boolean; - useShortSuffix?: boolean; -} - -export interface FieldFormat { - field: string; - format: FormatType; -} - -export interface BuilderItem { - id: number; - series: SeriesUrl; - seriesConfig?: SeriesConfig; -} - -export type SupportedOperations = 'average' | 'median' | 'sum' | 'unique_count' | 'min' | 'max'; - -type TermColumnParams = TermsIndexPatternColumn['params']; - -export type TermColumnParamsOrderBy = TermColumnParams['orderBy']; diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/utils/stringify_kueries.test.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/utils/stringify_kueries.test.ts deleted file mode 100644 index c278483f87b08e..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/utils/stringify_kueries.test.ts +++ /dev/null @@ -1,148 +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 { urlFiltersToKueryString } from './stringify_kueries'; -import { UrlFilter } from '../types'; -import { USER_AGENT_NAME } from '../configurations/constants/elasticsearch_fieldnames'; - -describe('stringifyKueries', () => { - let filters: UrlFilter[]; - beforeEach(() => { - filters = [ - { - field: USER_AGENT_NAME, - values: ['Chrome', 'Firefox'], - notValues: [], - }, - ]; - }); - - it('stringifies the current values', () => { - expect(urlFiltersToKueryString(filters)).toMatchInlineSnapshot( - `"user_agent.name: (\\"Chrome\\" or \\"Firefox\\")"` - ); - }); - - it('correctly stringifies a single value', () => { - filters = [ - { - field: USER_AGENT_NAME, - values: ['Chrome'], - notValues: [], - }, - ]; - expect(urlFiltersToKueryString(filters)).toMatchInlineSnapshot( - `"user_agent.name: \\"Chrome\\""` - ); - }); - - it('returns an empty string for an empty array', () => { - expect(urlFiltersToKueryString([])).toMatchInlineSnapshot(`""`); - }); - - it('returns an empty string for an empty value', () => { - filters = [ - { - field: USER_AGENT_NAME, - values: [], - notValues: [], - }, - ]; - expect(urlFiltersToKueryString(filters)).toMatchInlineSnapshot(`""`); - }); - - it('adds quotations if the value contains a space', () => { - filters = [ - { - field: USER_AGENT_NAME, - values: ['Google Chrome'], - notValues: [], - }, - ]; - expect(urlFiltersToKueryString(filters)).toMatchInlineSnapshot( - `"user_agent.name: \\"Google Chrome\\""` - ); - }); - - it('adds quotations inside parens if there are values containing spaces', () => { - filters = [ - { - field: USER_AGENT_NAME, - values: ['Google Chrome'], - notValues: ['Apple Safari'], - }, - ]; - expect(urlFiltersToKueryString(filters)).toMatchInlineSnapshot( - `"user_agent.name: \\"Google Chrome\\" and not (user_agent.name: \\"Apple Safari\\")"` - ); - }); - - it('handles parens for values with greater than 2 items', () => { - filters = [ - { - field: USER_AGENT_NAME, - values: ['Chrome', 'Firefox', 'Safari', 'Opera'], - notValues: ['Safari'], - }, - ]; - expect(urlFiltersToKueryString(filters)).toMatchInlineSnapshot( - `"user_agent.name: (\\"Chrome\\" or \\"Firefox\\" or \\"Safari\\" or \\"Opera\\") and not (user_agent.name: \\"Safari\\")"` - ); - }); - - it('handles colon characters in values', () => { - filters = [ - { - field: 'url', - values: ['https://elastic.co', 'https://example.com'], - notValues: [], - }, - ]; - expect(urlFiltersToKueryString(filters)).toMatchInlineSnapshot( - `"url: (\\"https://elastic.co\\" or \\"https://example.com\\")"` - ); - }); - - it('handles precending empty array', () => { - filters = [ - { - field: 'url', - values: ['https://elastic.co', 'https://example.com'], - notValues: [], - }, - { - field: USER_AGENT_NAME, - values: [], - }, - ]; - expect(urlFiltersToKueryString(filters)).toMatchInlineSnapshot( - `"url: (\\"https://elastic.co\\" or \\"https://example.com\\")"` - ); - }); - - it('handles skipped empty arrays', () => { - filters = [ - { - field: 'url', - values: ['https://elastic.co', 'https://example.com'], - notValues: [], - }, - { - field: USER_AGENT_NAME, - values: [], - }, - { - field: 'url', - values: ['https://elastic.co', 'https://example.com'], - notValues: [], - }, - ]; - expect(urlFiltersToKueryString(filters)).toMatchInlineSnapshot( - `"url: (\\"https://elastic.co\\" or \\"https://example.com\\") and url: (\\"https://elastic.co\\" or \\"https://example.com\\")"` - ); - }); -}); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/utils/stringify_kueries.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/utils/stringify_kueries.ts deleted file mode 100644 index aee60118bc7e41..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/utils/stringify_kueries.ts +++ /dev/null @@ -1,64 +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 { UrlFilter } from '../types'; - -/** - * Extract a map's keys to an array, then map those keys to a string per key. - * The strings contain all of the values chosen for the given field (which is also the key value). - * Reduce the list of query strings to a singular string, with AND operators between. - */ - -const buildOrCondition = (values: string[]) => { - if (values.length === 1) { - return `${values.join(' or ')}`; - } - return `(${values.join(' or ')})`; -}; - -function addSlashes(str: string | number) { - return (str + '').replace(/[\\"']/g, '\\$&').replace(/\u0000/g, '\\0'); -} - -export const urlFiltersToKueryString = (urlFilters: UrlFilter[]): string => { - let kueryString = ''; - - urlFilters.forEach(({ field, values, notValues, wildcards, notWildcards }) => { - const valuesT = values?.map((val) => `"${addSlashes(val)}"`); - const notValuesT = notValues?.map((val) => `"${addSlashes(val)}"`); - const wildcardsT = wildcards?.map((val) => `*${val}*`); - const notWildcardsT = notWildcards?.map((val) => `*${val}*`); - - if (valuesT && valuesT?.length > 0) { - if (kueryString.length > 0) { - kueryString += ' and '; - } - kueryString += `${field}: ${buildOrCondition(valuesT)}`; - } - - if (notValuesT && notValuesT?.length > 0) { - if (kueryString.length > 0) { - kueryString += ' and '; - } - kueryString += `not (${field}: ${buildOrCondition(notValuesT)})`; - } - if (wildcardsT && wildcardsT?.length > 0) { - if (kueryString.length > 0) { - kueryString += ' and '; - } - kueryString += `(${field}: ${buildOrCondition(wildcardsT)})`; - } - if (notWildcardsT && notWildcardsT?.length > 0) { - if (kueryString.length > 0) { - kueryString += ' and '; - } - kueryString += `(${field}: ${buildOrCondition(notWildcardsT)})`; - } - }); - - return kueryString; -}; diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/utils/telemetry.test.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/utils/telemetry.test.tsx deleted file mode 100644 index cf24cd47d9d10b..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/utils/telemetry.test.tsx +++ /dev/null @@ -1,120 +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 type { AppDataType } from '../types'; -import { trackTelemetryOnApply, trackTelemetryOnLoad } from './telemetry'; - -const mockMultipleSeries = [ - { - name: 'performance-distribution', - dataType: 'ux' as AppDataType, - breakdown: 'user_agent.name', - time: { from: 'now-15m', to: 'now' }, - filters: [ - { - field: 'url.full', - value: 'https://elastic.co', - }, - ], - selectedMetricField: 'transaction.duration.us', - }, - { - name: 'kpi-over-time', - dataType: 'synthetics' as AppDataType, - breakdown: 'user_agent.name', - time: { from: 'now-15m', to: 'now' }, - filters: [ - { - field: 'monitor.type', - value: 'browser', - }, - ], - selectedMetricField: 'monitor.duration.us', - }, -]; - -describe('telemetry', function () { - it('ensures that appropriate telemetry is called when settings are applied', () => { - const trackEvent = jest.fn(); - trackTelemetryOnApply(trackEvent, mockMultipleSeries, 'kpi-over-time'); - - expect(trackEvent).toBeCalledTimes(7); - expect(trackEvent).toBeCalledWith({ - app: 'observability-overview', - metric: 'exploratory_view__filters__filter_url.full', - metricType: 'count', - }); - expect(trackEvent).toBeCalledWith({ - app: 'observability-overview', - metric: 'exploratory_view__filters__filter_monitor.type', - metricType: 'count', - }); - expect(trackEvent).toBeCalledWith({ - app: 'observability-overview', - metric: 'exploratory_view__filters__report_type_kpi-over-time__data_type_ux__filter_url.full', - metricType: 'count', - }); - expect(trackEvent).toBeCalledWith({ - app: 'observability-overview', - metric: - 'exploratory_view__filters__report_type_kpi-over-time__data_type_synthetics__filter_monitor.type', - metricType: 'count', - }); - expect(trackEvent).toBeCalledWith({ - app: 'observability-overview', - metric: - 'exploratory_view__report_type_kpi-over-time__data_type_synthetics__metric_type_monitor.duration.us', - metricType: 'count', - }); - expect(trackEvent).toBeCalledWith({ - app: 'observability-overview', - metric: - 'exploratory_view__report_type_kpi-over-time__data_type_ux__metric_type_transaction.duration.us', - metricType: 'count', - }); - expect(trackEvent).toBeCalledWith({ - app: 'observability-overview', - metric: 'exploratory_view_apply_changes', - metricType: 'count', - }); - }); - - it('does not call track event for report type/data type/metric type config unless all values are truthy', () => { - const trackEvent = jest.fn(); - const series = { - ...mockMultipleSeries[1], - filters: undefined, - selectedMetricField: undefined, - }; - - trackTelemetryOnApply(trackEvent, [series], 'kpi-over-time'); - - expect(trackEvent).toBeCalledTimes(1); - expect(trackEvent).toBeCalledWith({ - app: 'observability-overview', - metric: 'exploratory_view_apply_changes', - metricType: 'count', - }); - }); - - it.each([ - [1635784025000, '5-10'], - [1635784030000, '10-20'], - [1635784040000, '20-30'], - [1635784050000, '30-60'], - [1635784080000, '60+'], - ])('ensures that appropriate telemetry is called when chart is loaded', (endTime, range) => { - const trackEvent = jest.fn(); - trackTelemetryOnLoad(trackEvent, 1635784020000, endTime); - - expect(trackEvent).toBeCalledTimes(1); - expect(trackEvent).toBeCalledWith({ - app: 'observability-overview', - metric: `exploratory_view__chart_loading_in_seconds_${range}`, - metricType: 'count', - }); - }); -}); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/utils/telemetry.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/utils/telemetry.ts deleted file mode 100644 index 76d99824c26f03..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/utils/telemetry.ts +++ /dev/null @@ -1,110 +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 { TrackEvent, METRIC_TYPE } from '../../../../hooks/use_track_metric'; -import type { SeriesUrl } from '../types'; - -export const trackTelemetryOnApply = ( - trackEvent: TrackEvent, - allSeries: SeriesUrl[], - reportType: string -) => { - trackFilters(trackEvent, allSeries, reportType); - trackDataType(trackEvent, allSeries, reportType); - trackApplyChanges(trackEvent); -}; - -export const trackTelemetryOnLoad = (trackEvent: TrackEvent, start: number, end: number) => { - trackChartLoadingTime(trackEvent, start, end); -}; - -const getAppliedFilters = (allSeries: SeriesUrl[]) => { - const filtersByDataType = new Map(); - allSeries.forEach((series) => { - const seriesFilters = filtersByDataType.get(series.dataType); - const filterFields = (series.filters || []).map((filter) => filter.field); - - if (seriesFilters) { - seriesFilters.push(...filterFields); - } else { - filtersByDataType.set(series.dataType, [...filterFields]); - } - }); - return filtersByDataType; -}; - -const trackFilters = (trackEvent: TrackEvent, allSeries: SeriesUrl[], reportType: string) => { - const filtersByDataType = getAppliedFilters(allSeries); - [...filtersByDataType.keys()].forEach((dataType) => { - const filtersForDataType = filtersByDataType.get(dataType); - - (filtersForDataType || []).forEach((filter) => { - trackEvent({ - app: 'observability-overview', - metricType: METRIC_TYPE.COUNT, - metric: `exploratory_view__filters__filter_${filter}`, - }); - trackEvent({ - app: 'observability-overview', - metricType: METRIC_TYPE.COUNT, - metric: `exploratory_view__filters__report_type_${reportType}__data_type_${dataType}__filter_${filter}`, - }); - }); - }); -}; - -const trackApplyChanges = (trackEvent: TrackEvent) => { - trackEvent({ - app: 'observability-overview', - metricType: METRIC_TYPE.COUNT, - metric: 'exploratory_view_apply_changes', - }); -}; - -const trackDataType = (trackEvent: TrackEvent, allSeries: SeriesUrl[], reportType: string) => { - const metrics = allSeries.map((series) => ({ - dataType: series.dataType, - metricType: series.selectedMetricField, - })); - - metrics.forEach(({ dataType, metricType }) => { - if (reportType && dataType && metricType) { - trackEvent({ - app: 'observability-overview', - metricType: METRIC_TYPE.COUNT, - metric: `exploratory_view__report_type_${reportType}__data_type_${dataType}__metric_type_${metricType}`, - }); - } - }); -}; - -export const trackChartLoadingTime = (trackEvent: TrackEvent, start: number, end: number) => { - const secondsLoading = (end - start) / 1000; - const rangeStr = toRangeStr(secondsLoading); - - if (rangeStr) { - trackChartLoadingMetric(trackEvent, rangeStr); - } -}; - -function toRangeStr(n: number) { - if (n < 0 || isNaN(n)) return null; - if (n >= 60) return '60+'; - else if (n >= 30) return '30-60'; - else if (n >= 20) return '20-30'; - else if (n >= 10) return '10-20'; - else if (n >= 5) return '5-10'; - return '0-5'; -} - -const trackChartLoadingMetric = (trackEvent: TrackEvent, range: string) => { - trackEvent({ - app: 'observability-overview', - metricType: METRIC_TYPE.COUNT, - metric: `exploratory_view__chart_loading_in_seconds_${range}`, - }); -}; diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/utils/utils.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/utils/utils.ts deleted file mode 100644 index 0edf6ff0c19e47..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/utils/utils.ts +++ /dev/null @@ -1,16 +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 { uniq } from 'lodash'; -import { ApmIndicesConfig } from '../../../../../common/typings'; - -export function getApmDataViewTitle(apmIndicesConfig?: ApmIndicesConfig) { - if (!apmIndicesConfig) { - return; - } - return uniq([apmIndicesConfig.transaction, apmIndicesConfig.metric]).join(','); -} diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/views/add_series_button.test.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/views/add_series_button.test.tsx deleted file mode 100644 index 978296a295efc3..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/views/add_series_button.test.tsx +++ /dev/null @@ -1,106 +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 React from 'react'; -import { screen, waitFor, fireEvent } from '@testing-library/dom'; -import { render } from '../rtl_helpers'; -import { AddSeriesButton } from './add_series_button'; -import { DEFAULT_TIME, ReportTypes } from '../configurations/constants'; -import * as hooks from '../hooks/use_series_storage'; - -const setSeries = jest.fn(); - -describe('AddSeriesButton', () => { - beforeEach(() => { - jest.spyOn(hooks, 'useSeriesStorage').mockReturnValue({ - ...jest.requireActual('../hooks/use_series_storage'), - allSeries: [], - setSeries, - reportType: ReportTypes.KPI, - }); - setSeries.mockClear(); - }); - - it('renders AddSeriesButton', async () => { - render(); - - expect(screen.getByText(/Add series/i)).toBeInTheDocument(); - }); - - it('calls setSeries when AddSeries Button is clicked', async () => { - const { rerender } = render(); - let addSeriesButton = screen.getByText(/Add series/i); - - fireEvent.click(addSeriesButton); - - await waitFor(() => { - expect(setSeries).toBeCalledTimes(1); - expect(setSeries).toBeCalledWith(0, { name: 'new-series-1', time: DEFAULT_TIME }); - }); - - jest.clearAllMocks(); - jest.spyOn(hooks, 'useSeriesStorage').mockReturnValue({ - ...jest.requireActual('../hooks/use_series_storage'), - allSeries: new Array(1), - setSeries, - reportType: ReportTypes.KPI, - }); - - rerender(); - - addSeriesButton = screen.getByText(/Add series/i); - - fireEvent.click(addSeriesButton); - - await waitFor(() => { - expect(setSeries).toBeCalledTimes(1); - expect(setSeries).toBeCalledWith(1, { name: 'new-series-2', time: DEFAULT_TIME }); - }); - }); - - it.each([ReportTypes.DEVICE_DISTRIBUTION, ReportTypes.CORE_WEB_VITAL])( - 'does not allow adding more than 1 series for core web vitals or device distribution', - async (reportType) => { - jest.clearAllMocks(); - jest.spyOn(hooks, 'useSeriesStorage').mockReturnValue({ - ...jest.requireActual('../hooks/use_series_storage'), - allSeries: new Array(1), // mock array of length 1 - setSeries, - reportType, - }); - - render(); - const addSeriesButton = screen.getByText(/Add series/i); - expect(addSeriesButton.closest('button')).toBeDisabled(); - - fireEvent.click(addSeriesButton); - - await waitFor(() => { - expect(setSeries).toBeCalledTimes(0); - }); - } - ); - - it('does not allow adding a series when the report type is undefined', async () => { - jest.clearAllMocks(); - jest.spyOn(hooks, 'useSeriesStorage').mockReturnValue({ - ...jest.requireActual('../hooks/use_series_storage'), - allSeries: [], - setSeries, - }); - - render(); - const addSeriesButton = screen.getByText(/Add series/i); - expect(addSeriesButton.closest('button')).toBeDisabled(); - - fireEvent.click(addSeriesButton); - - await waitFor(() => { - expect(setSeries).toBeCalledTimes(0); - }); - }); -}); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/views/add_series_button.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/views/add_series_button.tsx deleted file mode 100644 index 7dada383a729d2..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/views/add_series_button.tsx +++ /dev/null @@ -1,90 +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 React, { useEffect, useState, useRef } from 'react'; - -import { EuiToolTip, EuiButton } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; -import { SeriesUrl, BuilderItem } from '../types'; -import { getSeriesToEdit } from '../series_editor/series_editor'; -import { NEW_SERIES_KEY, useSeriesStorage } from '../hooks/use_series_storage'; -import { useAppDataViewContext } from '../hooks/use_app_data_view'; -import { DEFAULT_TIME, ReportTypes } from '../configurations/constants'; -import { useExploratoryView } from '../contexts/exploratory_view_config'; - -export function AddSeriesButton() { - const [editorItems, setEditorItems] = useState([]); - const addSeriesButtonRef = useRef(null); - const { getSeries, allSeries, setSeries, reportType } = useSeriesStorage(); - - const { loading, dataViews } = useAppDataViewContext(); - - const { reportConfigMap } = useExploratoryView(); - - useEffect(() => { - setEditorItems(getSeriesToEdit({ allSeries, dataViews, reportType, reportConfigMap })); - }, [allSeries, getSeries, dataViews, loading, reportConfigMap, reportType]); - - const addSeries = () => { - const prevSeries = allSeries?.[0]; - const name = `${NEW_SERIES_KEY}-${editorItems.length + 1}`; - const nextSeries = { name } as SeriesUrl; - if (addSeriesButtonRef?.current) { - addSeriesButtonRef.current.blur(); - } - - const nextSeriesId = allSeries.length; - - if (reportType === 'data-distribution') { - setSeries(nextSeriesId, { - ...nextSeries, - time: prevSeries?.time || DEFAULT_TIME, - } as SeriesUrl); - } else { - setSeries( - nextSeriesId, - prevSeries ? nextSeries : ({ ...nextSeries, time: DEFAULT_TIME } as SeriesUrl) - ); - } - }; - - const isAddDisabled = - !reportType || - ((reportType === ReportTypes.CORE_WEB_VITAL || - reportType === ReportTypes.DEVICE_DISTRIBUTION || - reportType === ReportTypes.SINGLE_METRIC) && - allSeries.length > 0); - - return ( - - addSeries()} - isDisabled={isAddDisabled} - iconType="plusInCircle" - size="s" - buttonRef={addSeriesButtonRef} - > - {i18n.translate('xpack.observability.expView.seriesBuilder.addSeries', { - defaultMessage: 'Add series', - })} - - - ); -} diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/views/series_views.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/views/series_views.tsx deleted file mode 100644 index 00fbc8c0e522f7..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/views/series_views.tsx +++ /dev/null @@ -1,26 +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 React, { RefObject } from 'react'; - -import { SeriesEditor } from '../series_editor/series_editor'; -import { AddSeriesButton } from './add_series_button'; -import { PanelId } from '../exploratory_view'; - -export function SeriesViews({ - seriesBuilderRef, -}: { - seriesBuilderRef: RefObject; - onSeriesPanelCollapse: (panel: PanelId) => void; -}) { - return ( -
- - -
- ); -} diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/views/view_actions.test.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/views/view_actions.test.tsx deleted file mode 100644 index df709c94abcde2..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/views/view_actions.test.tsx +++ /dev/null @@ -1,151 +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 React from 'react'; -import { screen, waitFor, fireEvent } from '@testing-library/dom'; -import { render } from '../rtl_helpers'; -import * as hooks from '../hooks/use_series_storage'; -import { ViewActions } from './view_actions'; -import { AllSeries, reportTypeKey } from '../hooks/use_series_storage'; -import { ReportTypes } from '../../../..'; - -describe('ViewActions', () => { - const applyChanges = jest.fn(); - - const mockSeriesStorage = (allSeries: AllSeries, urlAllSeries: AllSeries) => { - jest.clearAllMocks(); - jest.spyOn(hooks, 'useSeriesStorage').mockReturnValue({ - ...jest.requireActual('../hooks/use_series_storage'), - allSeries, - applyChanges, - storage: { - get: (key: string) => { - if (key === reportTypeKey) { - return ReportTypes.KPI; - } - return urlAllSeries; - }, - } as any, - reportType: ReportTypes.KPI, - }); - }; - - const assertApplyIsEnabled = async () => { - render(); - - const applyBtn = screen.getByText(/Apply changes/i); - - const btnComponent = screen.getByTestId('seriesChangesApplyButton'); - - expect(btnComponent.classList).not.toContain('euiButton-isDisabled'); - - fireEvent.click(applyBtn); - - await waitFor(() => { - expect(applyChanges).toBeCalledTimes(1); - }); - }; - - it('renders ViewActions', async () => { - mockSeriesStorage([], []); - render(); - - expect(screen.getByText(/Apply changes/i)).toBeInTheDocument(); - }); - - it('apply button is disabled when no changes', async () => { - mockSeriesStorage([], []); - - render(); - const applyBtn = screen.getByText(/Apply changes/i); - - const btnComponent = screen.getByTestId('seriesChangesApplyButton'); - - expect(btnComponent.classList[1]).toContain('disabled'); - - fireEvent.click(applyBtn); - - await waitFor(() => { - expect(applyChanges).toBeCalledTimes(0); - }); - }); - - it('should call apply changes when series length is different', async function () { - mockSeriesStorage([], [{ name: 'testSeries' } as any]); - - await assertApplyIsEnabled(); - }); - - it('should call apply changes when series content is different', async function () { - mockSeriesStorage([{ name: 'testSeriesChange' } as any], [{ name: 'testSeries' } as any]); - - await assertApplyIsEnabled(); - }); - - it('should call apply changes when series content is different as in undefined', async function () { - mockSeriesStorage( - [{ name: undefined } as any], - [{ name: 'testSeries', operationType: undefined } as any] - ); - - await assertApplyIsEnabled(); - }); - it('apply button is disabled when no filter changes but different orders', async () => { - const allSeries: AllSeries = [ - { - seriesType: 'area', - breakdown: 'monitor.type', - filters: [ - { - values: ['spa-heartbeat', 'nyc-heartbeat', 'au-heartbeat'], - field: 'observer.geo.name', - }, - ], - time: { from: 'now-15m', to: 'now' }, - dataType: 'synthetics', - reportDefinitions: { 'monitor.name': [], 'url.full': ['ALL_VALUES'] }, - selectedMetricField: 'monitor.duration.us', - name: 'All monitors response duration', - }, - ]; - - const urlSeries: AllSeries = [ - { - seriesType: 'area', - breakdown: 'monitor.type', - filters: [ - { - field: 'observer.geo.name', - values: ['spa-heartbeat', 'nyc-heartbeat', 'au-heartbeat'], - notValues: undefined, - notWildcards: undefined, - }, - ], - time: { from: 'now-15m', to: 'now' }, - reportDefinitions: { 'monitor.name': [], 'url.full': ['ALL_VALUES'] }, - dataType: 'synthetics', - selectedMetricField: 'monitor.duration.us', - name: 'All monitors response duration', - }, - ]; - - mockSeriesStorage(allSeries, urlSeries); - - render(); - const applyBtn = screen.getByText(/Apply changes/i); - - const btnComponent = screen.getByTestId('seriesChangesApplyButton'); - - expect(btnComponent.classList[1]).toContain('disabled'); - - fireEvent.click(applyBtn); - - await waitFor(() => { - expect(applyChanges).toBeCalledTimes(0); - }); - }); -}); diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/views/view_actions.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/views/view_actions.tsx deleted file mode 100644 index c8e38e4ffb124d..00000000000000 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/views/view_actions.tsx +++ /dev/null @@ -1,73 +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 React from 'react'; -import { EuiButton, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; -import { isEqual, pickBy } from 'lodash'; -import { - allSeriesKey, - convertAllShortSeries, - reportTypeKey, - useSeriesStorage, -} from '../hooks/use_series_storage'; -import { SeriesUrl } from '../types'; - -interface Props { - onApply?: () => void; -} - -export function removeUndefinedEmptyValues(series: SeriesUrl) { - const resultSeries = removeUndefinedProps(series) as SeriesUrl; - Object.entries(resultSeries).forEach(([prop, value]) => { - if (typeof value === 'object') { - // @ts-expect-error - resultSeries[prop] = removeUndefinedEmptyValues(value); - } - }); - return resultSeries; -} - -export function removeUndefinedProps(obj: T): Partial { - return pickBy(obj, (value) => value !== undefined); -} - -export function ViewActions({ onApply }: Props) { - const { allSeries, storage, applyChanges, reportType } = useSeriesStorage(); - - const urlAllSeries = convertAllShortSeries(storage.get(allSeriesKey) ?? []); - const urlReportType = storage.get(reportTypeKey) ?? ''; - - let noChanges = allSeries.length === urlAllSeries.length && reportType === urlReportType; - - if (noChanges) { - noChanges = !allSeries.some( - (series, index) => - !isEqual( - removeUndefinedEmptyValues(series), - removeUndefinedEmptyValues(urlAllSeries[index]) - ) - ); - } - - return ( - - - applyChanges(onApply)} - isDisabled={noChanges} - fill - data-test-subj={'seriesChangesApplyButton'} - > - {i18n.translate('xpack.observability.expView.seriesBuilder.apply', { - defaultMessage: 'Apply changes', - })} - - - - ); -} diff --git a/x-pack/plugins/observability/public/components/shared/index.tsx b/x-pack/plugins/observability/public/components/shared/index.tsx index 5c3dbc083e285d..04138a22425b1e 100644 --- a/x-pack/plugins/observability/public/components/shared/index.tsx +++ b/x-pack/plugins/observability/public/components/shared/index.tsx @@ -16,8 +16,6 @@ import type { } from './field_value_suggestions/types'; import type { DatePickerProps } from './date_picker'; import type { FilterValueLabelProps } from './filter_value_label/filter_value_label'; -import type { SelectableUrlListProps } from './exploratory_view/components/url_search/selectable_url_list'; -import type { ExploratoryViewPageProps } from './exploratory_view'; export { createLazyObservabilityPageTemplate } from './page_template'; export type { LazyObservabilityPageTemplateProps } from './page_template'; @@ -73,28 +71,6 @@ export function FilterValueLabel(props: FilterValueLabelProps) { ); } -const SelectableUrlListLazy = lazy( - () => import('./exploratory_view/components/url_search/selectable_url_list') -); - -export function SelectableUrlList(props: SelectableUrlListProps) { - return ( - - - - ); -} - -const ExploratoryViewLazy = lazy(() => import('./exploratory_view')); - -export function ExploratoryView(props: ExploratoryViewPageProps) { - return ( - - - - ); -} - const DatePickerLazy = lazy(() => import('./date_picker')); export function DatePicker(props: DatePickerProps) { diff --git a/x-pack/plugins/observability/public/hooks/use_quick_time_ranges.tsx b/x-pack/plugins/observability/public/hooks/use_quick_time_ranges.tsx index a6b4e78d86b890..81ed31065095b1 100644 --- a/x-pack/plugins/observability/public/hooks/use_quick_time_ranges.tsx +++ b/x-pack/plugins/observability/public/hooks/use_quick_time_ranges.tsx @@ -7,7 +7,12 @@ import { useUiSetting } from '@kbn/kibana-react-plugin/public'; import { UI_SETTINGS } from '@kbn/data-plugin/common'; -import { TimePickerQuickRange } from '../components/shared/exploratory_view/components/series_date_picker'; + +export interface TimePickerQuickRange { + from: string; + to: string; + display: string; +} export function useQuickTimeRanges() { const timePickerQuickRanges = useUiSetting( diff --git a/x-pack/plugins/observability/public/hooks/use_values_list.ts b/x-pack/plugins/observability/public/hooks/use_values_list.ts index 0b980021ec95a8..d1b9162f01bf92 100644 --- a/x-pack/plugins/observability/public/hooks/use_values_list.ts +++ b/x-pack/plugins/observability/public/hooks/use_values_list.ts @@ -10,8 +10,8 @@ import { useEffect, useState } from 'react'; import useDebounce from 'react-use/lib/useDebounce'; import type { ESFilter } from '@kbn/es-types'; import { IInspectorInfo } from '@kbn/data-plugin/common'; +import { TRANSACTION_URL } from '@kbn/observability-shared-plugin/common'; import { createEsParams, useEsSearch } from './use_es_search'; -import { TRANSACTION_URL } from '../components/shared/exploratory_view/configurations/constants/elasticsearch_fieldnames'; export interface Props { sourceField: string; diff --git a/x-pack/plugins/observability/public/index.ts b/x-pack/plugins/observability/public/index.ts index c55e2f8f658caf..d9f6368a13bdeb 100644 --- a/x-pack/plugins/observability/public/index.ts +++ b/x-pack/plugins/observability/public/index.ts @@ -17,7 +17,6 @@ import { ObservabilityPublicStart, ObservabilityPublicSetup, } from './plugin'; -export { ALL_VALUES_SELECTED } from './components/shared/exploratory_view/configurations/constants/url_constants'; export type { ObservabilityPublicSetup, ObservabilityPublicStart, @@ -53,8 +52,6 @@ export { FieldValueSuggestions, FieldValueSelection, FilterValueLabel, - SelectableUrlList, - ExploratoryView, DatePicker, LoadWhenInView, ObservabilityAlertSearchBar, @@ -93,9 +90,6 @@ export type { LinkDescriptor } from './hooks/use_link_props'; export { NavigationWarningPromptProvider, Prompt } from './utils/navigation_warning_prompt'; export { getApmTraceUrl } from './utils/get_apm_trace_url'; -export { createExploratoryViewUrl } from './components/shared/exploratory_view/configurations/exploratory_view_url'; -export type { AllSeries } from './components/shared/exploratory_view/hooks/use_series_storage'; -export type { SeriesUrl, UrlFilter } from './components/shared/exploratory_view/types'; export type { ObservabilityRuleTypeFormatter, @@ -103,25 +97,11 @@ export type { ObservabilityRuleTypeRegistry, } from './rules/create_observability_rule_type_registry'; export { createObservabilityRuleTypeRegistryMock } from './rules/observability_rule_type_registry_mock'; -export type { ExploratoryEmbeddableProps } from './components/shared/exploratory_view/embeddable/embeddable'; export type { AddInspectorRequest } from './context/inspector/inspector_context'; export { InspectorContextProvider } from './context/inspector/inspector_context'; export { useInspectorContext } from './context/inspector/use_inspector_context'; -export type { SeriesConfig, ConfigProps } from './components/shared/exploratory_view/types'; -export { - ReportTypes, - FILTER_RECORDS, - ENVIRONMENT_ALL, - REPORT_METRIC_FIELD, - USE_BREAK_DOWN_COLUMN, - RECORDS_FIELD, - OPERATION_COLUMN, - TERMS_COLUMN, - RECORDS_PERCENTAGE_FIELD, -} from './components/shared/exploratory_view/configurations/constants'; -export { ExploratoryViewContextProvider } from './components/shared/exploratory_view/contexts/exploratory_view_config'; export { fromQuery, toQuery } from './utils/url'; export { getAlertSummaryTimeRange } from './utils/alert_summary_widget'; export { calculateTimeRangeBucketSize } from './pages/overview/helpers/calculate_bucket_size'; diff --git a/x-pack/plugins/observability/public/plugin.ts b/x-pack/plugins/observability/public/plugin.ts index 6c2874f39b6d8c..190c646bebbcc0 100644 --- a/x-pack/plugins/observability/public/plugin.ts +++ b/x-pack/plugins/observability/public/plugin.ts @@ -24,7 +24,6 @@ import type { DataPublicPluginSetup, DataPublicPluginStart } from '@kbn/data-plu import type { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public'; import type { DiscoverStart } from '@kbn/discover-plugin/public'; import type { EmbeddableStart } from '@kbn/embeddable-plugin/public'; -import type { ExploratoryViewPublicPluginsStart } from '@kbn/exploratory-view-plugin/public'; import type { HomePublicPluginSetup, HomePublicPluginStart } from '@kbn/home-plugin/public'; import type { ChartsPluginStart } from '@kbn/charts-plugin/public'; import type { @@ -49,6 +48,7 @@ import { GuidedOnboardingPluginStart } from '@kbn/guided-onboarding-plugin/publi import { SpacesPluginStart } from '@kbn/spaces-plugin/public'; import { LicensingPluginStart } from '@kbn/licensing-plugin/public'; import { UnifiedSearchPublicPluginStart } from '@kbn/unified-search-plugin/public'; +import { ExploratoryViewPublicStart } from '@kbn/exploratory-view-plugin/public'; import { RuleDetailsLocatorDefinition } from './locators/rule_details'; import { observabilityAppId, observabilityFeatureId, casesPath } from '../common'; import { registerDataHandler } from './data_handler'; @@ -94,7 +94,7 @@ export interface ObservabilityPublicPluginsStart { dataViews: DataViewsPublicPluginStart; discover: DiscoverStart; embeddable: EmbeddableStart; - exploratoryView: ExploratoryViewPublicPluginsStart; + exploratoryView: ExploratoryViewPublicStart; guidedOnboarding: GuidedOnboardingPluginStart; lens: LensPublicStart; licensing: LicensingPluginStart; diff --git a/x-pack/plugins/observability/public/utils/observability_data_views/get_app_data_view.ts b/x-pack/plugins/observability/public/utils/observability_data_views/get_app_data_view.ts deleted file mode 100644 index 4b3af576f6d0de..00000000000000 --- a/x-pack/plugins/observability/public/utils/observability_data_views/get_app_data_view.ts +++ /dev/null @@ -1,25 +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 type { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public'; -import type { AppDataType } from '../../components/shared/exploratory_view/types'; - -const getAppDataView = (data: DataViewsPublicPluginStart) => { - return async (appId: AppDataType, indexPattern?: string) => { - try { - const { ObservabilityDataViews } = await import('./observability_data_views'); - - const obsvIndexP = new ObservabilityDataViews(data); - return await obsvIndexP.getDataView(appId, indexPattern); - } catch (e) { - return null; - } - }; -}; - -// eslint-disable-next-line import/no-default-export -export default getAppDataView; diff --git a/x-pack/plugins/observability/public/utils/observability_data_views/index.ts b/x-pack/plugins/observability/public/utils/observability_data_views/index.ts deleted file mode 100644 index 571f5ea4c11a25..00000000000000 --- a/x-pack/plugins/observability/public/utils/observability_data_views/index.ts +++ /dev/null @@ -1,8 +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. - */ - -export * from './observability_data_views'; diff --git a/x-pack/plugins/observability/public/utils/observability_data_views/observability_data_views.test.ts b/x-pack/plugins/observability/public/utils/observability_data_views/observability_data_views.test.ts deleted file mode 100644 index 26ceafb80cf5c6..00000000000000 --- a/x-pack/plugins/observability/public/utils/observability_data_views/observability_data_views.test.ts +++ /dev/null @@ -1,133 +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 { dataViewList, ObservabilityDataViews } from './observability_data_views'; -import { mockCore, mockDataView } from '../../components/shared/exploratory_view/rtl_helpers'; -import { SavedObjectNotFound } from '@kbn/kibana-utils-plugin/public'; - -const fieldFormats = { - 'transaction.duration.us': { - id: 'duration', - params: { - inputFormat: 'microseconds', - outputFormat: 'asSeconds', - outputPrecision: 1, - showSuffix: true, - useShortSuffix: true, - }, - }, - 'transaction.experience.fid': { - id: 'duration', - params: { - inputFormat: 'milliseconds', - outputFormat: 'humanizePrecise', - showSuffix: true, - useShortSuffix: true, - }, - }, - 'transaction.experience.tbt': { - id: 'duration', - params: { - inputFormat: 'milliseconds', - outputFormat: 'humanizePrecise', - showSuffix: true, - useShortSuffix: true, - }, - }, - 'transaction.marks.agent.firstContentfulPaint': { - id: 'duration', - params: { - inputFormat: 'milliseconds', - outputFormat: 'humanizePrecise', - showSuffix: true, - useShortSuffix: true, - }, - }, - 'transaction.marks.agent.largestContentfulPaint': { - id: 'duration', - params: { - inputFormat: 'milliseconds', - outputFormat: 'humanizePrecise', - showSuffix: true, - useShortSuffix: true, - }, - }, - 'transaction.marks.agent.timeToFirstByte': { - id: 'duration', - params: { - inputFormat: 'milliseconds', - outputFormat: 'humanizePrecise', - showSuffix: true, - useShortSuffix: true, - }, - }, -}; - -describe('ObservabilityDataViews', function () { - const { dataViews } = mockCore(); - dataViews!.get = jest.fn().mockReturnValue({ title: 'index-*' }); - dataViews!.createAndSave = jest.fn().mockReturnValue({ id: dataViewList.ux }); - dataViews!.create = jest.fn().mockReturnValue({ id: dataViewList.ux }); - dataViews!.updateSavedObject = jest.fn(); - - it('should return index pattern for app', async function () { - const obsv = new ObservabilityDataViews(dataViews!); - - const indexP = await obsv.getDataView('ux', 'heartbeat-8*,synthetics-*'); - - expect(indexP).toEqual({ id: 'rum_static_index_pattern_id' }); - - expect(dataViews?.get).toHaveBeenCalledWith( - 'rum_static_index_pattern_id_heartbeat_8_synthetics_' - ); - expect(dataViews?.get).toHaveBeenCalledTimes(1); - }); - - it('should creates missing index pattern', async function () { - dataViews!.get = jest.fn().mockImplementation(() => { - throw new SavedObjectNotFound('index_pattern'); - }); - - dataViews!.createAndSave = jest.fn().mockReturnValue({ id: dataViewList.ux }); - - const obsv = new ObservabilityDataViews(dataViews!); - - const indexP = await obsv.getDataView('ux', 'trace-*,apm-*'); - - expect(indexP).toEqual({ id: dataViewList.ux }); - - expect(dataViews?.createAndSave).toHaveBeenCalledWith({ - fieldFormats, - id: 'rum_static_index_pattern_id_trace_apm_', - timeFieldName: '@timestamp', - title: 'trace-*,apm-*', - name: 'User experience (RUM)', - allowNoIndex: true, - }); - - expect(dataViews?.createAndSave).toHaveBeenCalledTimes(1); - }); - - it('should return getFieldFormats', function () { - const obsv = new ObservabilityDataViews(dataViews!); - - expect(obsv.getFieldFormats('ux')).toEqual(fieldFormats); - }); - - it('should validate field formats', async function () { - mockDataView.getFormatterForField = jest.fn().mockReturnValue({ params: () => {} }); - - const obsv = new ObservabilityDataViews(dataViews!); - - await obsv.validateFieldFormats('ux', mockDataView); - - expect(dataViews?.updateSavedObject).toHaveBeenCalledTimes(1); - expect(dataViews?.updateSavedObject).toHaveBeenCalledWith( - expect.objectContaining({ fieldFormatMap: fieldFormats }) - ); - }); -}); diff --git a/x-pack/plugins/observability/public/utils/observability_data_views/observability_data_views.ts b/x-pack/plugins/observability/public/utils/observability_data_views/observability_data_views.ts deleted file mode 100644 index f5e8893ce1b284..00000000000000 --- a/x-pack/plugins/observability/public/utils/observability_data_views/observability_data_views.ts +++ /dev/null @@ -1,262 +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 type { FieldFormat as IFieldFormat } from '@kbn/field-formats-plugin/common'; -import { SavedObjectNotFound } from '@kbn/kibana-utils-plugin/public'; -import type { - DataViewsPublicPluginStart, - DataView, - DataViewSpec, -} from '@kbn/data-views-plugin/public'; -import { RuntimeField } from '@kbn/data-views-plugin/public'; -import { DataViewMissingIndices } from '@kbn/data-views-plugin/common'; -import { DataTypesLabels } from '../../components/shared/exploratory_view/labels'; -import { syntheticsRuntimeFields } from '../../components/shared/exploratory_view/configurations/synthetics/runtime_fields'; -import { getApmDataViewTitle } from '../../components/shared/exploratory_view/utils/utils'; -import { rumFieldFormats } from '../../components/shared/exploratory_view/configurations/rum/field_formats'; -import { syntheticsFieldFormats } from '../../components/shared/exploratory_view/configurations/synthetics/field_formats'; -import { - AppDataType, - FieldFormat, - FieldFormatParams, -} from '../../components/shared/exploratory_view/types'; -import { apmFieldFormats } from '../../components/shared/exploratory_view/configurations/apm/field_formats'; -import { getDataHandler } from '../../data_handler'; -import { infraMetricsFieldFormats } from '../../components/shared/exploratory_view/configurations/infra_metrics/field_formats'; - -const appFieldFormats: Record = { - infra_logs: null, - infra_metrics: infraMetricsFieldFormats, - ux: rumFieldFormats, - apm: apmFieldFormats, - uptime: syntheticsFieldFormats, - synthetics: syntheticsFieldFormats, - mobile: apmFieldFormats, - alerts: null, -}; - -const appRuntimeFields: Record | null> = { - infra_logs: null, - infra_metrics: null, - ux: null, - apm: null, - uptime: syntheticsRuntimeFields, - synthetics: syntheticsRuntimeFields, - mobile: null, - alerts: null, -}; - -function getFieldFormatsForApp(app: AppDataType) { - return { runtimeFields: appRuntimeFields[app], formats: appFieldFormats[app] }; -} - -export const dataViewList: Record = { - synthetics: 'synthetics_static_index_pattern_id', - uptime: 'uptime_static_index_pattern_id', - apm: 'apm_static_index_pattern_id', - ux: 'rum_static_index_pattern_id', - infra_logs: 'infra_logs_static_index_pattern_id', - infra_metrics: 'infra_metrics_static_index_pattern_id', - mobile: 'mobile_static_index_pattern_id', - alerts: 'alerts_static_index_pattern_id', -}; - -const getAppIndicesWithPattern = (app: AppDataType, indices: string) => { - return `${indices}`; -}; - -const getAppDataViewId = (app: AppDataType, indices: string) => { - // Replace characters / ? , " < > | * with _ - const postfix = indices.replace(/[^A-Z0-9]+/gi, '_').toLowerCase(); - - return `${dataViewList?.[app] ?? app}_${postfix}`; -}; - -export async function getDataTypeIndices(dataType: AppDataType) { - switch (dataType) { - case 'synthetics': - return { - hasData: true, - indices: 'synthetics-*', - }; - case 'mobile': - case 'ux': - case 'apm': - const resultApm = await getDataHandler('apm')?.hasData(); - return { - hasData: Boolean(resultApm?.hasData), - indices: getApmDataViewTitle(resultApm?.indices), - }; - case 'alerts': - return { - hasData: true, - indices: '.alerts-observability*', - }; - default: - const resultUx = await getDataHandler(dataType)?.hasData(); - return { hasData: Boolean(resultUx?.hasData), indices: resultUx?.indices as string }; - } -} - -export function isParamsSame(param1: IFieldFormat['_params'], param2?: FieldFormatParams) { - const isSame = - param1?.inputFormat === param2?.inputFormat && - param1?.outputFormat === param2?.outputFormat && - param1?.useShortSuffix === param2?.useShortSuffix && - param1?.showSuffix === param2?.showSuffix; - - if (param2?.outputPrecision !== undefined) { - return param2.outputPrecision === param1?.outputPrecision && isSame; - } - - return isSame; -} - -export class ObservabilityDataViews { - dataViews: DataViewsPublicPluginStart; - adHocDataViews: boolean = false; - - constructor(dataViews: DataViewsPublicPluginStart, adHocDataViews?: boolean) { - this.dataViews = dataViews; - this.adHocDataViews = adHocDataViews ?? false; - } - - async createDataView(app: AppDataType, indices: string) { - const appIndicesPattern = getAppIndicesWithPattern(app, indices); - - const { runtimeFields } = getFieldFormatsForApp(app); - - const id = getAppDataViewId(app, indices); - - try { - const dataView = await this.dataViews.create( - { - id, - title: appIndicesPattern, - timeFieldName: '@timestamp', - fieldFormats: this.getFieldFormats(app), - name: DataTypesLabels[app], - allowNoIndex: true, - }, - false, - false - ); - - if (dataView.matchedIndices.length === 0) { - return; - } - - if (runtimeFields !== null) { - runtimeFields.forEach(({ name, field }) => { - dataView.addRuntimeField(name, field); - }); - } - - return dataView; - } catch (e) { - if (e instanceof DataViewMissingIndices) { - this.dataViews.clearInstanceCache(id); - } - } - } - - async createAndSavedDataView(app: AppDataType, indices: string) { - const appIndicesPattern = getAppIndicesWithPattern(app, indices); - - const dataViewId = getAppDataViewId(app, indices); - - return await this.dataViews.createAndSave({ - title: appIndicesPattern, - id: dataViewId, - timeFieldName: '@timestamp', - fieldFormats: this.getFieldFormats(app), - name: DataTypesLabels[app], - allowNoIndex: true, - }); - } - // we want to make sure field formats remain same - async validateFieldFormats(app: AppDataType, dataView: DataView) { - const { formats: defaultFieldFormats, runtimeFields } = getFieldFormatsForApp(app); - if (defaultFieldFormats && defaultFieldFormats.length > 0) { - let isParamsDifferent = false; - defaultFieldFormats.forEach(({ field, format }) => { - const fieldByName = dataView.getFieldByName(field); - if (fieldByName) { - const fieldFormat = dataView.getFormatterForField(fieldByName); - const params = fieldFormat.params(); - if (!isParamsSame(params, format.params) || format.id !== fieldFormat.type.id) { - dataView.setFieldFormat(field, format); - isParamsDifferent = true; - } - } - }); - let hasNewRuntimeField = false; - if (runtimeFields !== null) { - const allRunTimeFields = dataView.getAllRuntimeFields(); - runtimeFields.forEach(({ name, field }) => { - if (!allRunTimeFields[name]) { - hasNewRuntimeField = true; - dataView.addRuntimeField(name, field); - } - }); - } - if (isParamsDifferent || hasNewRuntimeField) { - await this.dataViews?.updateSavedObject(dataView); - } - } - } - - getFieldFormats(app: AppDataType) { - const fieldFormatMap: DataViewSpec['fieldFormats'] = {}; - - (appFieldFormats?.[app] ?? []).forEach(({ field, format }) => { - fieldFormatMap[field] = format; - }); - - return fieldFormatMap; - } - - async getDataView(app: AppDataType, indices?: string): Promise { - let appIndices = indices; - let hasData = false; - if (!appIndices) { - const { indices: indicesT, hasData: hData } = await getDataTypeIndices(app); - hasData = hData; - appIndices = indicesT; - } - - if (appIndices && (hasData || indices)) { - try { - const dataViewId = getAppDataViewId(app, appIndices); - const dataViewTitle = getAppIndicesWithPattern(app, appIndices); - // we will get the data view by id - - if (this.adHocDataViews) { - return await this.createDataView(app, appIndices); - } - - const dataView = await this.dataViews?.get(dataViewId); - - // and make sure title matches, otherwise, we will need to create it - if (dataView.title !== dataViewTitle) { - return await this.createAndSavedDataView(app, appIndices); - } - - // this is intentional a non blocking call, so no await clause - this.validateFieldFormats(app, dataView); - return dataView; - } catch (e: unknown) { - if (e instanceof SavedObjectNotFound) { - return await this.createAndSavedDataView(app, appIndices); - } - } - } - } -} - -// eslint-disable-next-line import/no-default-export -export default ObservabilityDataViews; diff --git a/x-pack/plugins/observability/public/utils/test_helper.tsx b/x-pack/plugins/observability/public/utils/test_helper.tsx index b3d8864a5cec6c..9d92b057d50816 100644 --- a/x-pack/plugins/observability/public/utils/test_helper.tsx +++ b/x-pack/plugins/observability/public/utils/test_helper.tsx @@ -55,7 +55,17 @@ const queryClient = new QueryClient({ export const render = (component: React.ReactNode, config: Subset = {}) => { return testLibRender( - +
Embeddable exploratory view
, + }, + }} + > ) => void; diff --git a/x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/user_details_content.stories.tsx b/x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/user_details_content.stories.tsx index db17ada4a3b10d..685315c66cf9df 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/user_details_content.stories.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/user_details_content.stories.tsx @@ -6,21 +6,20 @@ */ import React from 'react'; -import { storiesOf, addDecorator } from '@storybook/react'; +import { storiesOf } from '@storybook/react'; import { EuiFlyout, EuiFlyoutBody } from '@elastic/eui'; import { UserDetailsContentComponent } from './user_details_content'; import { StorybookProviders } from '../../../../common/mock/storybook_providers'; import { mockManagedUser, mockObservedUser, mockRiskScoreState } from './__mocks__'; -addDecorator((storyFn) => ( - - {}}> - {storyFn()} - - -)); - storiesOf('UserDetailsContent', module) + .addDecorator((storyFn) => ( + + {}}> + {storyFn()} + + + )) .add('default', () => ( { const [isMouseOver, setIsMouseOver] = useState(false); const [isPopoverOpen, setIsPopoverOpen] = useState(false); + const isErrorPopoverOpen = useSelector(selectErrorPopoverState); const locationName = useLocationName({ locationId: monitor.location?.id })?.label || monitor.location?.id; const { status, timestamp, ping, configIdByLocation } = useStatusByLocationOverview( @@ -86,6 +87,9 @@ export const MetricItem = ({ } }} onMouseLeave={() => { + if (isErrorPopoverOpen) { + dispatch(toggleErrorPopoverOpen(null)); + } if (isMouseOver) { setIsMouseOver(false); } diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/metric_item_icon.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/metric_item_icon.tsx index c3a91461e85ceb..a1fdf1e734d5cf 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/metric_item_icon.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/metric_item_icon.tsx @@ -103,8 +103,7 @@ export const MetricItemIcon = ({ onMouseLeave={() => { if (isPopoverOpen) { return; - } - if (timer.current) { + } else if (timer.current) { clearTimeout(timer.current); } }} diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/overview_alerts.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/overview_alerts.tsx index 68fe35fefeb628..693cd0d9ed85b6 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/overview_alerts.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/overview_alerts.tsx @@ -15,9 +15,10 @@ import { EuiTitle, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { RECORDS_FIELD, useTheme } from '@kbn/observability-plugin/public'; +import { useTheme } from '@kbn/observability-plugin/public'; import { useKibana } from '@kbn/kibana-react-plugin/public'; import { useSelector } from 'react-redux'; +import { RECORDS_FIELD } from '@kbn/exploratory-view-plugin/public'; import { selectOverviewStatus } from '../../../../state/overview_status'; import { AlertsLink } from '../../../common/links/view_alerts'; import { useRefreshedRange, useGetUrlParams } from '../../../../hooks'; diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index e3e66f3ee33134..2feb5667303890 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -25330,22 +25330,11 @@ "xpack.observability.enableAwsLambdaMetricsDescription": "{technicalPreviewLabel} Affichez les indicateurs Amazon Lambda dans l'onglet d'indicateurs de service. {feedbackLink}", "xpack.observability.enableCriticalPathDescription": "{technicalPreviewLabel} Affichez de façon optionnelle le chemin critique d'une trace.", "xpack.observability.enableInfrastructureHostsViewDescription": "{technicalPreviewLabel} Activez la vue Hôtes dans l'application Infrastructure. {feedbackLink}.", - "xpack.observability.expView.columns.label": "{percentileValue} centile de {sourceField}", - "xpack.observability.expView.columns.operation.label": "{operationType} sur {sourceField}", - "xpack.observability.expView.filterValueButton.negate": "Pas {value}", - "xpack.observability.expView.heading.addToCase.notification": "Visualisation correctement ajoutée au cas : {caseTitle}", - "xpack.observability.expView.lastUpdated.label": "Dernière mise à jour : {updatedDate}", - "xpack.observability.expView.seriesEditor.selectReportMetric.noFieldData": "Aucune donnée disponible pour le champ {field}.", "xpack.observability.fieldValueSelection.apply.label": "Appliquer les filtres sélectionnés pour {label}", "xpack.observability.fieldValueSelection.placeholder": "Filtrer {label}", "xpack.observability.fieldValueSelection.placeholder.search": "Rechercher {label}", "xpack.observability.filterButton.label": "développe le groupe de filtres pour le filtre {label}", - "xpack.observability.filters.expanded.search": "Rechercher {label}", - "xpack.observability.filters.label.wildcard": "Caractère générique {label}", - "xpack.observability.filters.searchResults": "{total} résultats de recherche", "xpack.observability.inspector.stats.queryTimeValue": "{queryTime} ms", - "xpack.observability.overview.exploratoryView.missingReportDefinition": "{reportDefinition} manquante", - "xpack.observability.overview.exploratoryView.noDataAvailable": "Aucune donnée {dataType} disponible.", "xpack.observability.profilingElasticsearchPluginDescription": "{technicalPreviewLabel} Si les traces d'appel doivent être chargées à l'aide du plug-in de profilage Elasticsearch.", "xpack.observability.ruleDetails.executionLogError": "Impossible de charger le log d'exécution de la règle. Raison : {message}", "xpack.observability.ruleDetails.ruleLoadError": "Impossible de charger la règle. Raison : {message}", @@ -25357,9 +25346,7 @@ "xpack.observability.slo.rules.burnRate.errors.invalidThresholdValue": "Le seuil du taux d'avancement doit être compris entre 1 et {maxBurnRate}.", "xpack.observability.slo.rules.errorBudgetExhaustion.text": "À ce niveau, le bilan d'erreurs de SLO sera épuisé après {formatedHours} heures.", "xpack.observability.slo.rules.longWindowDuration.tooltip": "Période historique sur laquelle le taux d'avancement est calculé. Une période historique plus courte de {shortWindowDuration} minutes (1/12 de la période historique) sera utilisée pour une récupération plus rapide", - "xpack.observability.textDefinitionField.placeholder.search": "Rechercher {label}", "xpack.observability.transactionRateLabel": "{value} tpm", - "xpack.observability.urlFilter.wildcard": "Utiliser le caractère générique *{wildcard}*", "xpack.observability.ux.coreVitals.averageMessage": " et inférieur à {bad}", "xpack.observability.ux.coreVitals.paletteLegend.rankPercentage": "{labelsInd} ({ranksInd} %)", "xpack.observability.ux.dashboard.webCoreVitals.traffic": "{trafficPerc} du trafic représenté", @@ -25429,7 +25416,6 @@ "xpack.observability.apmProgressiveLoadingQualityOff": "Désactivé", "xpack.observability.apmServiceInventoryOptimizedSorting": "Optimiser les performances de chargement des listes de services dans APM", "xpack.observability.apmTraceExplorerTab": "Explorateur de traces APM", - "xpack.observability.apply.label": "Appliquer", "xpack.observability.breadcrumbs.alertsLinkText": "Alertes", "xpack.observability.breadcrumbs.observabilityLinkText": "Observabilité", "xpack.observability.breadcrumbs.overviewLinkText": "Aperçu", @@ -25468,162 +25454,8 @@ "xpack.observability.enableInfrastructureHostsView": "Vue des hôtes de l'infrastructure", "xpack.observability.enableInspectEsQueriesExperimentDescription": "Inspectez les recherches Elasticsearch dans les réponses API.", "xpack.observability.enableInspectEsQueriesExperimentName": "Inspecter les recherches ES", - "xpack.observability.exp.breakDownFilter.noBreakdown": "Pas de répartition", - "xpack.observability.exp.breakDownFilter.unavailable": "La répartition par nom d'étape n'est pas disponible pour l'indicateur de durée de monitoring. Utilisez l'indicateur de durée d'étape pour répartir par nom d'étape.", - "xpack.observability.exp.breakDownFilter.warning": "Les répartitions ne peuvent être appliquées qu’à une seule série à la fois.", "xpack.observability.experimentalBadgeDescription": "Cette fonctionnalité est en version d'évaluation technique et pourra être modifiée ou retirée complètement dans une future version. Elastic s'efforcera au maximum de corriger tout problème, mais les fonctionnalités en version d'évaluation technique ne sont pas soumises aux accords de niveau de service d'assistance des fonctionnalités officielles en disponibilité générale.", "xpack.observability.experimentalBadgeLabel": "Version d'évaluation technique", - "xpack.observability.exploratoryView.alerts.alertStarted": "Horodatage", - "xpack.observability.exploratoryView.logs.logRateXAxisLabel": "Horodatage", - "xpack.observability.exploratoryView.logs.logRateYAxisLabel": "Taux de log par minute", - "xpack.observability.exploratoryView.noBrusing": "Zoomer sur une sélection par brossage est une fonctionnalité disponible uniquement dans les graphiques de séries temporelles.", - "xpack.observability.expView.addToCase": "Ajouter au cas", - "xpack.observability.expView.alerts.category": "Catégorie de règle", - "xpack.observability.expView.alerts.name": "Nom de l'alerte", - "xpack.observability.expView.alerts.status": "Statut de l'alerte", - "xpack.observability.expView.avgDuration": "Moy. Durée", - "xpack.observability.expView.chartTypes.label": "Type de graphique", - "xpack.observability.expView.complete": "Terminé", - "xpack.observability.expView.dateRanger.endDate": "Date de fin", - "xpack.observability.expView.dateRanger.startDate": "Date de début", - "xpack.observability.expView.errors": "Erreurs", - "xpack.observability.expView.explore": "Explorer", - "xpack.observability.expView.failedTests": "Tests ayant échoué", - "xpack.observability.expView.fieldLabels.agentHost": "Hôte de l'agent", - "xpack.observability.expView.fieldLabels.agentType": "Type d'agent", - "xpack.observability.expView.fieldLabels.backend": "Heure de backend", - "xpack.observability.expView.fieldLabels.browserFamily": "Famille de navigateurs", - "xpack.observability.expView.fieldLabels.browserVersion": "Version de navigateur", - "xpack.observability.expView.fieldLabels.carrierLocation": "Emplacement de l'opérateur", - "xpack.observability.expView.fieldLabels.carrierName": "Nom de l'opérateur", - "xpack.observability.expView.fieldLabels.chooseField": "Champ d'étiquettes", - "xpack.observability.expView.fieldLabels.cls": "Cumulative Layout Shift", - "xpack.observability.expView.fieldLabels.connectionType": "Type de connexion", - "xpack.observability.expView.fieldLabels.coreWebVitals": "Core Web Vitals", - "xpack.observability.expView.fieldLabels.cpuUsage": "Utilisation CPU", - "xpack.observability.expView.fieldLabels.cpuUsage.docker": "Utilisation CPU Docker", - "xpack.observability.expView.fieldLabels.cpuUsage.k8sDocker": "Utilisation CPU pod K8s", - "xpack.observability.expView.fieldLabels.cpuUsage.system": "Utilisation CPU système", - "xpack.observability.expView.fieldLabels.dcl": "Contenu DOM chargé", - "xpack.observability.expView.fieldLabels.device": "Appareil", - "xpack.observability.expView.fieldLabels.deviceDistribution": "Distribution de l'appareil", - "xpack.observability.expView.fieldLabels.deviceModel": "Modèle de l'appareil", - "xpack.observability.expView.fieldLabels.downPings": "Pings arrêtés", - "xpack.observability.expView.fieldLabels.environment": "Environnement", - "xpack.observability.expView.fieldLabels.eventDataset": "Ensemble de données", - "xpack.observability.expView.fieldLabels.fcp": "First Contentful Paint", - "xpack.observability.expView.fieldLabels.fid": "First Input Delay", - "xpack.observability.expView.fieldLabels.heatMap": "Carte thermique", - "xpack.observability.expView.fieldLabels.hostName": "Nom d'hôte", - "xpack.observability.expView.fieldLabels.hostOS": "Système d'exploitation de l'hôte", - "xpack.observability.expView.fieldLabels.kpi": "KPI", - "xpack.observability.expView.fieldLabels.kpiOverTime": "KPI sur la durée", - "xpack.observability.expView.fieldLabels.labels": "Étiquettes", - "xpack.observability.expView.fieldLabels.lcp": "Largest Contentful Paint", - "xpack.observability.expView.fieldLabels.location": "Emplacement", - "xpack.observability.expView.fieldLabels.logRate": "Taux du log", - "xpack.observability.expView.fieldLabels.memoryUsage": "Utilisation mémoire système", - "xpack.observability.expView.fieldLabels.message": "Message", - "xpack.observability.expView.fieldLabels.metric": "Indicateur", - "xpack.observability.expView.fieldLabels.mobile.memoryUsage": "Utilisation mémoire système", - "xpack.observability.expView.fieldLabels.mobileApp": "Application mobile", - "xpack.observability.expView.fieldLabels.mobileResponse": "Réponse mobile", - "xpack.observability.expView.fieldLabels.monitorDurationLabel": "Durée du moniteur", - "xpack.observability.expView.fieldLabels.monitorId": "ID de moniteur", - "xpack.observability.expView.fieldLabels.monitorName": "Nom de moniteur", - "xpack.observability.expView.fieldLabels.monitorStatus": "Statut du moniteur", - "xpack.observability.expView.fieldLabels.monitorType": "Type de moniteur", - "xpack.observability.expView.fieldLabels.networkTimings": "Délais réseau", - "xpack.observability.expView.fieldLabels.numberOfDevices": "Nombre d'appareils", - "xpack.observability.expView.fieldLabels.obsLocation": "Emplacement de l'observateur", - "xpack.observability.expView.fieldLabels.onload": "Document complet (onLoad)", - "xpack.observability.expView.fieldLabels.os": "Système d'exploitation", - "xpack.observability.expView.fieldLabels.osPlatform": "Plateforme du système d'exploitation", - "xpack.observability.expView.fieldLabels.pageLoadTime": "Temps de chargement de la page", - "xpack.observability.expView.fieldLabels.pagesLoaded": "Pages chargées", - "xpack.observability.expView.fieldLabels.pageViews": "Vues de la page", - "xpack.observability.expView.fieldLabels.performanceDistribution": "Distribution des performances", - "xpack.observability.expView.fieldLabels.pings": "Pings", - "xpack.observability.expView.fieldLabels.port": "Port", - "xpack.observability.expView.fieldLabels.requestMethod": "Méthode de requête", - "xpack.observability.expView.fieldLabels.responseLatency": "Latence", - "xpack.observability.expView.fieldLabels.serviceName": "Nom de service", - "xpack.observability.expView.fieldLabels.serviceType": "Type de service", - "xpack.observability.expView.fieldLabels.serviceVersion": "Version du service", - "xpack.observability.expView.fieldLabels.singleMetric": "Indicateur unique", - "xpack.observability.expView.fieldLabels.stepDurationLabel": "Durée de l’étape", - "xpack.observability.expView.fieldLabels.stepNameLabel": "Nom de l'étape", - "xpack.observability.expView.fieldLabels.tags": "Balises", - "xpack.observability.expView.fieldLabels.tbt": "Temps de blocage total", - "xpack.observability.expView.fieldLabels.transactionPerMinute": "Rendement", - "xpack.observability.expView.fieldLabels.upPings": "Pings opérationnels", - "xpack.observability.expView.fieldLabels.url": "URL", - "xpack.observability.expView.fieldLabels.webApplication": "Application Web", - "xpack.observability.expView.heading.addToCase": "Ajouter au cas", - "xpack.observability.expView.heading.addToCase.notification.error": "Impossible d'ajouter la visualisation au cas sélectionné.", - "xpack.observability.expView.heading.addToCase.notification.viewCase": "Afficher le cas", - "xpack.observability.expView.heading.embed": "Incorporer <></>", - "xpack.observability.expView.heading.embedTitle": "Incorporer la vue d’exploration (fonctionnalité Dev uniquement)", - "xpack.observability.expView.heading.label": "Explorer les données", - "xpack.observability.expView.heading.openInLens": "Ouvrir dans Lens", - "xpack.observability.expView.heading.saveLensVisualization": "Enregistrer", - "xpack.observability.expView.openInLens": "Ouvrir dans Lens", - "xpack.observability.expView.operationType.25thPercentile": "25e centile", - "xpack.observability.expView.operationType.75thPercentile": "75e centile", - "xpack.observability.expView.operationType.90thPercentile": "90e centile", - "xpack.observability.expView.operationType.95thPercentile": "95e centile", - "xpack.observability.expView.operationType.99thPercentile": "99e centile", - "xpack.observability.expView.operationType.average": "Moyenne", - "xpack.observability.expView.operationType.lastValue": "Dernière valeur", - "xpack.observability.expView.operationType.max": "Max.", - "xpack.observability.expView.operationType.median": "Médiane", - "xpack.observability.expView.operationType.min": "Min.", - "xpack.observability.expView.operationType.sum": "Somme", - "xpack.observability.expView.operationType.uniqueCount": "Compte unique", - "xpack.observability.expView.reportType.selectDataType": "Sélectionnez un type de données pour créer une visualisation.", - "xpack.observability.expView.reportType.selectLabel": "Sélectionner le type de rapport", - "xpack.observability.expView.save": "Enregistrer la visualisation", - "xpack.observability.expView.seriesBuilder.accordion.label": "Afficher/Masquer les informations de série", - "xpack.observability.expView.seriesBuilder.addSeries": "Ajouter une série", - "xpack.observability.expView.seriesBuilder.addSeries.limitation": "Vous ne pouvez ajouter qu’une seule série à ce type de rapport.", - "xpack.observability.expView.seriesBuilder.addSeries.selectReportType": "Vous devez sélectionner un type de rapport pour pouvoir ajouter des séries.", - "xpack.observability.expView.seriesBuilder.apply": "Appliquer les modifications", - "xpack.observability.expView.seriesBuilder.breakdownBy": "Répartir par", - "xpack.observability.expView.seriesBuilder.creationContext": "Afficher à partir de", - "xpack.observability.expView.seriesBuilder.creationTime": "Graphique créé", - "xpack.observability.expView.seriesBuilder.date": "Date", - "xpack.observability.expView.seriesBuilder.emptyReportDefinition": "Sélectionnez une définition de rapport pour créer une visualisation.", - "xpack.observability.expView.seriesBuilder.emptyview": "Rien à afficher.", - "xpack.observability.expView.seriesBuilder.labelField": "Sélectionner le champ d'étiquette", - "xpack.observability.expView.seriesBuilder.loadingView": "Chargement de la vue...", - "xpack.observability.expView.seriesBuilder.operation": "Opération", - "xpack.observability.expView.seriesBuilder.reportType": "Type de rapport", - "xpack.observability.expView.seriesBuilder.reportType.aria": "Sélectionnez le type de rapport à créer.", - "xpack.observability.expView.seriesBuilder.selectFilters": "Filtres", - "xpack.observability.expView.seriesBuilder.selectReportType": "Aucun type de rapport sélectionné", - "xpack.observability.expView.seriesBuilder.selectReportType.empty": "Sélectionnez un type de rapport pour créer une visualisation.", - "xpack.observability.expView.seriesEditor.clearFilter": "Effacer les filtres", - "xpack.observability.expView.seriesEditor.editChartSeriesLabel": "Modifier le type de graphique pour les séries", - "xpack.observability.expView.seriesEditor.editName": "Modifier le nom", - "xpack.observability.expView.seriesEditor.noData": "Aucune donnée disponible", - "xpack.observability.expView.seriesEditor.noPermissions": "Impossible de créer la vue de données. Vous ne disposez pas des autorisations requises. Veuillez contacter votre administrateur.", - "xpack.observability.expView.seriesEditor.notFound": "Aucune série trouvée. Veuillez ajouter une série.", - "xpack.observability.expView.seriesEditor.removeReportMetric": "Supprimer l’indicateur de rapport", - "xpack.observability.expView.seriesEditor.removeSeries": "Supprimer la série", - "xpack.observability.expView.seriesEditor.removeSeriesDisabled": "Les séries principales ne peuvent pas être supprimées. Veuillez supprimer toutes les séries ci-dessous avant de supprimer celle-ci.", - "xpack.observability.expView.seriesEditor.reportMetricTooltip": "Indicateur de rapport", - "xpack.observability.expView.seriesEditor.selectReportMetric": "Sélectionner l’indicateur de rapport", - "xpack.observability.expView.seriesEditor.seriesName": "Nom de la série", - "xpack.observability.expView.stepDuration": "Durée totale de l'étape", - "xpack.observability.expView.synthetics.blocked": "Bloqué", - "xpack.observability.expView.synthetics.connect": "Connecter", - "xpack.observability.expView.synthetics.dns": "DNS", - "xpack.observability.expView.synthetics.receive": "Recevoir", - "xpack.observability.expView.synthetics.send": "Envoyer", - "xpack.observability.expView.synthetics.ssl": "SSL", - "xpack.observability.expView.synthetics.total": "Total", - "xpack.observability.expView.synthetics.wait": "Attendre", - "xpack.observability.expView.totalRuns": "Total d'exécutions", "xpack.observability.featureCatalogueDescription": "Consolidez vos logs, indicateurs, traces d'application et disponibilités système avec les interfaces utilisateur spécialement conçues.", "xpack.observability.featureCatalogueTitle": "Observabilité", "xpack.observability.featureRegistry.deleteSubFeatureDetails": "Supprimer les cas et les commentaires", @@ -25633,16 +25465,6 @@ "xpack.observability.fieldValueSelection.apply": "Appliquer", "xpack.observability.fieldValueSelection.loading": "Chargement", "xpack.observability.fieldValueSelection.logicalAnd": "Utiliser AND logique", - "xpack.observability.filters.expanded.labels.backTo": "Retour aux étiquettes", - "xpack.observability.filters.expanded.labels.fields": "Champs d'étiquette", - "xpack.observability.filters.expanded.labels.label": "Étiquettes", - "xpack.observability.filters.expanded.noFilter": "Aucun filtre trouvé.", - "xpack.observability.filters.filterByUrl": "Filtrer par URL", - "xpack.observability.filters.select": "Sélectionner", - "xpack.observability.filters.topPages": "Premières pages", - "xpack.observability.filters.url": "Url", - "xpack.observability.filters.url.loadingResults": "Chargement des résultats", - "xpack.observability.filters.url.noResults": "Aucun résultat disponible", "xpack.observability.formatters.hoursTimeUnitLabel": "h", "xpack.observability.formatters.hoursTimeUnitLabelExtended": "heures", "xpack.observability.formatters.microsTimeUnitLabel": "μs", @@ -25699,25 +25521,6 @@ "xpack.observability.overview.apm.throughput": "Rendement", "xpack.observability.overview.apm.throughputTip": "Les valeurs sont calculées pour les transactions de type \"requête\" ou \"chargement de page\". Si aucune transaction de ce type n’est disponible, les valeurs reflètent le premier type de transaction.", "xpack.observability.overview.apm.title": "Services", - "xpack.observability.overview.exploratoryView": "Explorer les données", - "xpack.observability.overview.exploratoryView.alertsLabel": "Alertes", - "xpack.observability.overview.exploratoryView.editSeriesColor": "Modifier la couleur de la série", - "xpack.observability.overview.exploratoryView.hideChart": "Masquer le graphique", - "xpack.observability.overview.exploratoryView.lensDisabled": "L'application Lens n'est pas disponible, veuillez activer Lens pour utiliser la vue d'exploration.", - "xpack.observability.overview.exploratoryView.logsLabel": "Logs", - "xpack.observability.overview.exploratoryView.metricsLabel": "Indicateurs", - "xpack.observability.overview.exploratoryView.missingDataType": "Type de données manquant", - "xpack.observability.overview.exploratoryView.missingReportMetric": "Indicateur de rapport manquant", - "xpack.observability.overview.exploratoryView.mobileExperienceLabel": "Expérience mobile", - "xpack.observability.overview.exploratoryView.noData": "Aucune donnée", - "xpack.observability.overview.exploratoryView.pickColor": "Sélectionner une couleur", - "xpack.observability.overview.exploratoryView.preview": "Aperçu", - "xpack.observability.overview.exploratoryView.refresh": "Actualiser", - "xpack.observability.overview.exploratoryView.selectDataType": "Sélectionner le type de données", - "xpack.observability.overview.exploratoryView.selectDataTypeTooltip": "Impossible de modifier le type de données.", - "xpack.observability.overview.exploratoryView.showChart": "Afficher le graphique", - "xpack.observability.overview.exploratoryView.syntheticsLabel": "Monitoring synthétique", - "xpack.observability.overview.exploratoryView.uxLabel": "Expérience utilisateur (RUM)", "xpack.observability.overview.guidedSetupButton": "Assistant de données", "xpack.observability.overview.guidedSetupTourContent": "Si vous avez un doute, vous pouvez toujours accéder à l'assistant de données et visualiser les prochaines étapes en cliquant ici.", "xpack.observability.overview.guidedSetupTourDismissButton": "Rejeter", @@ -25780,15 +25583,7 @@ "xpack.observability.rules.docsLinkText": "Documentation", "xpack.observability.rulesLinkTitle": "Règles", "xpack.observability.rulesTitle": "Règles", - "xpack.observability.search.url.close": "Fermer", "xpack.observability.section.errorPanel": "Une erreur est survenue lors de la tentative de récupération des données. Réessayez plus tard", - "xpack.observability.seriesEditor.actionsAriaContextLabel": "Liste des actions de la série", - "xpack.observability.seriesEditor.clone": "Dupliquer la série", - "xpack.observability.seriesEditor.edit": "Modifier la série", - "xpack.observability.seriesEditor.hide": "Masquer la série", - "xpack.observability.seriesEditor.popoverButtonLabel": "Afficher les actions de la série", - "xpack.observability.seriesEditor.sampleDocuments": "Afficher la transaction dans Discover", - "xpack.observability.seriesEditor.show": "Afficher la série", "xpack.observability.serviceGroupMaxServicesUiSettingDescription": "Limiter le nombre de services dans un groupe de services donné", "xpack.observability.serviceGroupMaxServicesUiSettingName": "Nombre maximum de services dans un groupe de services", "xpack.observability.slo.alerting.reasonDescription": "Une description concise de la raison du signalement", @@ -25891,6 +25686,211 @@ "xpack.observability.ux.dashboard.webCoreVitals.help": "Découvrez", "xpack.observability.ux.dashboard.webCoreVitals.helpAriaLabel": "aide", "xpack.observability.ux.service.help": "Le service RUM comportant le plus de trafic est sélectionné", + "xpack.exploratoryView.expView.columns.label": "{percentileValue} centile de {sourceField}", + "xpack.exploratoryView.expView.columns.operation.label": "{operationType} sur {sourceField}", + "xpack.exploratoryView.expView.filterValueButton.negate": "Pas {value}", + "xpack.exploratoryView.expView.heading.addToCase.notification": "Visualisation correctement ajoutée au cas : {caseTitle}", + "xpack.exploratoryView.expView.lastUpdated.label": "Dernière mise à jour : {updatedDate}", + "xpack.exploratoryView.expView.seriesEditor.selectReportMetric.noFieldData": "Aucune donnée disponible pour le champ {field}.", + "xpack.exploratoryView.filters.expanded.search": "Rechercher {label}", + "xpack.exploratoryView.filters.label.wildcard": "Caractère générique {label}", + "xpack.exploratoryView.filters.searchResults": "{total} résultats de recherche", + "xpack.exploratoryView.missingReportDefinition": "{reportDefinition} manquante", + "xpack.exploratoryView.noDataAvailable": "Aucune donnée {dataType} disponible.", + "xpack.exploratoryView.textDefinitionField.placeholder.search": "Rechercher {label}", + "xpack.exploratoryView.urlFilter.wildcard": "Utiliser le caractère générique *{wildcard}*", + "xpack.exploratoryView.apply.label": "Appliquer", + "xpack.exploratoryView.breakDownFilter.noBreakdown": "Pas de répartition", + "xpack.exploratoryView.breakDownFilter.unavailable": "La répartition par nom d'étape n'est pas disponible pour l'indicateur de durée de monitoring. Utilisez l'indicateur de durée d'étape pour répartir par nom d'étape.", + "xpack.exploratoryView.breakDownFilter.warning": "Les répartitions ne peuvent être appliquées qu’à une seule série à la fois.", + "xpack.exploratoryView.alerts.alertStarted": "Horodatage", + "xpack.exploratoryView.logs.logRateXAxisLabel": "Horodatage", + "xpack.exploratoryView.logs.logRateYAxisLabel": "Taux de log par minute", + "xpack.exploratoryView.noBrushing": "Zoomer sur une sélection par brossage est une fonctionnalité disponible uniquement dans les graphiques de séries temporelles.", + "xpack.exploratoryView.expView.addToCase": "Ajouter au cas", + "xpack.exploratoryView.expView.alerts.category": "Catégorie de règle", + "xpack.exploratoryView.expView.alerts.name": "Nom de l'alerte", + "xpack.exploratoryView.expView.alerts.status": "Statut de l'alerte", + "xpack.exploratoryView.expView.avgDuration": "Moy. Durée", + "xpack.exploratoryView.expView.chartTypes.label": "Type de graphique", + "xpack.exploratoryView.expView.complete": "Terminé", + "xpack.exploratoryView.expView.dateRanger.endDate": "Date de fin", + "xpack.exploratoryView.expView.dateRanger.startDate": "Date de début", + "xpack.exploratoryView.expView.errors": "Erreurs", + "xpack.exploratoryView.expView.explore": "Explorer", + "xpack.exploratoryView.expView.failedTests": "Tests ayant échoué", + "xpack.exploratoryView.expView.fieldLabels.agentHost": "Hôte de l'agent", + "xpack.exploratoryView.expView.fieldLabels.agentType": "Type d'agent", + "xpack.exploratoryView.expView.fieldLabels.backend": "Heure de backend", + "xpack.exploratoryView.expView.fieldLabels.browserFamily": "Famille de navigateurs", + "xpack.exploratoryView.expView.fieldLabels.browserVersion": "Version de navigateur", + "xpack.exploratoryView.expView.fieldLabels.carrierLocation": "Emplacement de l'opérateur", + "xpack.exploratoryView.expView.fieldLabels.carrierName": "Nom de l'opérateur", + "xpack.exploratoryView.expView.fieldLabels.chooseField": "Champ d'étiquettes", + "xpack.exploratoryView.expView.fieldLabels.cls": "Cumulative Layout Shift", + "xpack.exploratoryView.expView.fieldLabels.connectionType": "Type de connexion", + "xpack.exploratoryView.expView.fieldLabels.coreWebVitals": "Core Web Vitals", + "xpack.exploratoryView.expView.fieldLabels.cpuUsage": "Utilisation CPU", + "xpack.exploratoryView.expView.fieldLabels.cpuUsage.docker": "Utilisation CPU Docker", + "xpack.exploratoryView.expView.fieldLabels.cpuUsage.k8sDocker": "Utilisation CPU pod K8s", + "xpack.exploratoryView.expView.fieldLabels.cpuUsage.system": "Utilisation CPU système", + "xpack.exploratoryView.expView.fieldLabels.dcl": "Contenu DOM chargé", + "xpack.exploratoryView.expView.fieldLabels.device": "Appareil", + "xpack.exploratoryView.expView.fieldLabels.deviceDistribution": "Distribution de l'appareil", + "xpack.exploratoryView.expView.fieldLabels.deviceModel": "Modèle de l'appareil", + "xpack.exploratoryView.expView.fieldLabels.downPings": "Pings arrêtés", + "xpack.exploratoryView.expView.fieldLabels.environment": "Environnement", + "xpack.exploratoryView.expView.fieldLabels.eventDataset": "Ensemble de données", + "xpack.exploratoryView.expView.fieldLabels.fcp": "First Contentful Paint", + "xpack.exploratoryView.expView.fieldLabels.fid": "First Input Delay", + "xpack.exploratoryView.expView.fieldLabels.heatMap": "Carte thermique", + "xpack.exploratoryView.expView.fieldLabels.hostName": "Nom d'hôte", + "xpack.exploratoryView.expView.fieldLabels.hostOS": "Système d'exploitation de l'hôte", + "xpack.exploratoryView.expView.fieldLabels.kpi": "KPI", + "xpack.exploratoryView.expView.fieldLabels.kpiOverTime": "KPI sur la durée", + "xpack.exploratoryView.expView.fieldLabels.labels": "Étiquettes", + "xpack.exploratoryView.expView.fieldLabels.lcp": "Largest Contentful Paint", + "xpack.exploratoryView.expView.fieldLabels.location": "Emplacement", + "xpack.exploratoryView.expView.fieldLabels.logRate": "Taux du log", + "xpack.exploratoryView.expView.fieldLabels.memoryUsage": "Utilisation mémoire système", + "xpack.exploratoryView.expView.fieldLabels.message": "Message", + "xpack.exploratoryView.expView.fieldLabels.metric": "Indicateur", + "xpack.exploratoryView.expView.fieldLabels.mobile.memoryUsage": "Utilisation mémoire système", + "xpack.exploratoryView.expView.fieldLabels.mobileApp": "Application mobile", + "xpack.exploratoryView.expView.fieldLabels.mobileResponse": "Réponse mobile", + "xpack.exploratoryView.expView.fieldLabels.monitorDurationLabel": "Durée du moniteur", + "xpack.exploratoryView.expView.fieldLabels.monitorId": "ID de moniteur", + "xpack.exploratoryView.expView.fieldLabels.monitorName": "Nom de moniteur", + "xpack.exploratoryView.expView.fieldLabels.monitorStatus": "Statut du moniteur", + "xpack.exploratoryView.expView.fieldLabels.monitorType": "Type de moniteur", + "xpack.exploratoryView.expView.fieldLabels.networkTimings": "Délais réseau", + "xpack.exploratoryView.expView.fieldLabels.numberOfDevices": "Nombre d'appareils", + "xpack.exploratoryView.expView.fieldLabels.obsLocation": "Emplacement de l'observateur", + "xpack.exploratoryView.expView.fieldLabels.onload": "Document complet (onLoad)", + "xpack.exploratoryView.expView.fieldLabels.os": "Système d'exploitation", + "xpack.exploratoryView.expView.fieldLabels.osPlatform": "Plateforme du système d'exploitation", + "xpack.exploratoryView.expView.fieldLabels.pageLoadTime": "Temps de chargement de la page", + "xpack.exploratoryView.expView.fieldLabels.pagesLoaded": "Pages chargées", + "xpack.exploratoryView.expView.fieldLabels.pageViews": "Vues de la page", + "xpack.exploratoryView.expView.fieldLabels.performanceDistribution": "Distribution des performances", + "xpack.exploratoryView.expView.fieldLabels.pings": "Pings", + "xpack.exploratoryView.expView.fieldLabels.port": "Port", + "xpack.exploratoryView.expView.fieldLabels.requestMethod": "Méthode de requête", + "xpack.exploratoryView.expView.fieldLabels.responseLatency": "Latence", + "xpack.exploratoryView.expView.fieldLabels.serviceName": "Nom de service", + "xpack.exploratoryView.expView.fieldLabels.serviceType": "Type de service", + "xpack.exploratoryView.expView.fieldLabels.serviceVersion": "Version du service", + "xpack.exploratoryView.expView.fieldLabels.singleMetric": "Indicateur unique", + "xpack.exploratoryView.expView.fieldLabels.stepDurationLabel": "Durée de l’étape", + "xpack.exploratoryView.expView.fieldLabels.stepNameLabel": "Nom de l'étape", + "xpack.exploratoryView.expView.fieldLabels.tags": "Balises", + "xpack.exploratoryView.expView.fieldLabels.tbt": "Temps de blocage total", + "xpack.exploratoryView.expView.fieldLabels.transactionPerMinute": "Rendement", + "xpack.exploratoryView.expView.fieldLabels.upPings": "Pings opérationnels", + "xpack.exploratoryView.expView.fieldLabels.url": "URL", + "xpack.exploratoryView.expView.fieldLabels.webApplication": "Application Web", + "xpack.exploratoryView.expView.heading.addToCase": "Ajouter au cas", + "xpack.exploratoryView.expView.heading.addToCase.notification.error": "Impossible d'ajouter la visualisation au cas sélectionné.", + "xpack.exploratoryView.expView.heading.addToCase.notification.viewCase": "Afficher le cas", + "xpack.exploratoryView.expView.heading.embed": "Incorporer <></>", + "xpack.exploratoryView.expView.heading.embedTitle": "Incorporer la vue d’exploration (fonctionnalité Dev uniquement)", + "xpack.exploratoryView.expView.heading.label": "Explorer les données", + "xpack.exploratoryView.expView.heading.openInLens": "Ouvrir dans Lens", + "xpack.exploratoryView.expView.heading.saveLensVisualization": "Enregistrer", + "xpack.exploratoryView.expView.openInLens": "Ouvrir dans Lens", + "xpack.exploratoryView.expView.operationType.25thPercentile": "25e centile", + "xpack.exploratoryView.expView.operationType.75thPercentile": "75e centile", + "xpack.exploratoryView.expView.operationType.90thPercentile": "90e centile", + "xpack.exploratoryView.expView.operationType.95thPercentile": "95e centile", + "xpack.exploratoryView.expView.operationType.99thPercentile": "99e centile", + "xpack.exploratoryView.expView.operationType.average": "Moyenne", + "xpack.exploratoryView.expView.operationType.lastValue": "Dernière valeur", + "xpack.exploratoryView.expView.operationType.max": "Max.", + "xpack.exploratoryView.expView.operationType.median": "Médiane", + "xpack.exploratoryView.expView.operationType.min": "Min.", + "xpack.exploratoryView.expView.operationType.sum": "Somme", + "xpack.exploratoryView.expView.operationType.uniqueCount": "Compte unique", + "xpack.exploratoryView.expView.reportType.selectDataType": "Sélectionnez un type de données pour créer une visualisation.", + "xpack.exploratoryView.expView.reportType.selectLabel": "Sélectionner le type de rapport", + "xpack.exploratoryView.expView.save": "Enregistrer la visualisation", + "xpack.exploratoryView.expView.seriesBuilder.accordion.label": "Afficher/Masquer les informations de série", + "xpack.exploratoryView.expView.seriesBuilder.addSeries": "Ajouter une série", + "xpack.exploratoryView.expView.seriesBuilder.addSeries.limitation": "Vous ne pouvez ajouter qu’une seule série à ce type de rapport.", + "xpack.exploratoryView.expView.seriesBuilder.addSeries.selectReportType": "Vous devez sélectionner un type de rapport pour pouvoir ajouter des séries.", + "xpack.exploratoryView.expView.seriesBuilder.apply": "Appliquer les modifications", + "xpack.exploratoryView.expView.seriesBuilder.breakdownBy": "Répartir par", + "xpack.exploratoryView.expView.seriesBuilder.creationContext": "Afficher à partir de", + "xpack.exploratoryView.expView.seriesBuilder.creationTime": "Graphique créé", + "xpack.exploratoryView.expView.seriesBuilder.date": "Date", + "xpack.exploratoryView.expView.seriesBuilder.emptyReportDefinition": "Sélectionnez une définition de rapport pour créer une visualisation.", + "xpack.exploratoryView.expView.seriesBuilder.emptyview": "Rien à afficher.", + "xpack.exploratoryView.expView.seriesBuilder.labelField": "Sélectionner le champ d'étiquette", + "xpack.exploratoryView.expView.seriesBuilder.loadingView": "Chargement de la vue...", + "xpack.exploratoryView.expView.seriesBuilder.operation": "Opération", + "xpack.exploratoryView.expView.seriesBuilder.reportType": "Type de rapport", + "xpack.exploratoryView.expView.seriesBuilder.reportType.aria": "Sélectionnez le type de rapport à créer.", + "xpack.exploratoryView.expView.seriesBuilder.selectFilters": "Filtres", + "xpack.exploratoryView.expView.seriesBuilder.selectReportType": "Aucun type de rapport sélectionné", + "xpack.exploratoryView.expView.seriesBuilder.selectReportType.empty": "Sélectionnez un type de rapport pour créer une visualisation.", + "xpack.exploratoryView.expView.seriesEditor.clearFilter": "Effacer les filtres", + "xpack.exploratoryView.expView.seriesEditor.editChartSeriesLabel": "Modifier le type de graphique pour les séries", + "xpack.exploratoryView.expView.seriesEditor.editName": "Modifier le nom", + "xpack.exploratoryView.expView.seriesEditor.noData": "Aucune donnée disponible", + "xpack.exploratoryView.expView.seriesEditor.noPermissions": "Impossible de créer la vue de données. Vous ne disposez pas des autorisations requises. Veuillez contacter votre administrateur.", + "xpack.exploratoryView.expView.seriesEditor.notFound": "Aucune série trouvée. Veuillez ajouter une série.", + "xpack.exploratoryView.expView.seriesEditor.removeReportMetric": "Supprimer l’indicateur de rapport", + "xpack.exploratoryView.expView.seriesEditor.removeSeries": "Supprimer la série", + "xpack.exploratoryView.expView.seriesEditor.removeSeriesDisabled": "Les séries principales ne peuvent pas être supprimées. Veuillez supprimer toutes les séries ci-dessous avant de supprimer celle-ci.", + "xpack.exploratoryView.expView.seriesEditor.reportMetricTooltip": "Indicateur de rapport", + "xpack.exploratoryView.expView.seriesEditor.selectReportMetric": "Sélectionner l’indicateur de rapport", + "xpack.exploratoryView.expView.seriesEditor.seriesName": "Nom de la série", + "xpack.exploratoryView.expView.stepDuration": "Durée totale de l'étape", + "xpack.exploratoryView.expView.synthetics.blocked": "Bloqué", + "xpack.exploratoryView.expView.synthetics.connect": "Connecter", + "xpack.exploratoryView.expView.synthetics.dns": "DNS", + "xpack.exploratoryView.expView.synthetics.receive": "Recevoir", + "xpack.exploratoryView.expView.synthetics.send": "Envoyer", + "xpack.exploratoryView.expView.synthetics.ssl": "SSL", + "xpack.exploratoryView.expView.synthetics.total": "Total", + "xpack.exploratoryView.expView.synthetics.wait": "Attendre", + "xpack.exploratoryView.expView.totalRuns": "Total d'exécutions", + "xpack.exploratoryView.filters.expanded.labels.backTo": "Retour aux étiquettes", + "xpack.exploratoryView.filters.expanded.labels.fields": "Champs d'étiquette", + "xpack.exploratoryView.filters.expanded.labels.label": "Étiquettes", + "xpack.exploratoryView.filters.expanded.noFilter": "Aucun filtre trouvé.", + "xpack.exploratoryView.filters.filterByUrl": "Filtrer par URL", + "xpack.exploratoryView.filters.select": "Sélectionner", + "xpack.exploratoryView.filters.topPages": "Premières pages", + "xpack.exploratoryView.filters.url": "Url", + "xpack.exploratoryView.filters.url.loadingResults": "Chargement des résultats", + "xpack.exploratoryView.filters.url.noResults": "Aucun résultat disponible", + "xpack.exploratoryView.overview": "Explorer les données", + "xpack.exploratoryView.alertsLabel": "Alertes", + "xpack.exploratoryView.editSeriesColor": "Modifier la couleur de la série", + "xpack.exploratoryView.hideChart": "Masquer le graphique", + "xpack.exploratoryView.lensDisabled": "L'application Lens n'est pas disponible, veuillez activer Lens pour utiliser la vue d'exploration.", + "xpack.exploratoryView.logsLabel": "Logs", + "xpack.exploratoryView.metricsLabel": "Indicateurs", + "xpack.exploratoryView.missingDataType": "Type de données manquant", + "xpack.exploratoryView.missingReportMetric": "Indicateur de rapport manquant", + "xpack.exploratoryView.mobileExperienceLabel": "Expérience mobile", + "xpack.exploratoryView.noData": "Aucune donnée", + "xpack.exploratoryView.pickColor": "Sélectionner une couleur", + "xpack.exploratoryView.preview": "Aperçu", + "xpack.exploratoryView.refresh": "Actualiser", + "xpack.exploratoryView.selectDataType": "Sélectionner le type de données", + "xpack.exploratoryView.selectDataTypeTooltip": "Impossible de modifier le type de données.", + "xpack.exploratoryView.showChart": "Afficher le graphique", + "xpack.exploratoryView.syntheticsLabel": "Monitoring synthétique", + "xpack.exploratoryView.uxLabel": "Expérience utilisateur (RUM)", + "xpack.exploratoryView.search.url.close": "Fermer", + "xpack.exploratoryView.seriesEditor.actionsAriaContextLabel": "Liste des actions de la série", + "xpack.exploratoryView.seriesEditor.clone": "Dupliquer la série", + "xpack.exploratoryView.seriesEditor.edit": "Modifier la série", + "xpack.exploratoryView.seriesEditor.hide": "Masquer la série", + "xpack.exploratoryView.seriesEditor.popoverButtonLabel": "Afficher les actions de la série", + "xpack.exploratoryView.seriesEditor.sampleDocuments": "Afficher la transaction dans Discover", + "xpack.exploratoryView.seriesEditor.show": "Afficher la série", "xpack.osquery.action.missingPrivileges": "Pour accéder à cette page, demandez à votre administrateur vos privilèges Kibana pour {osquery}.", "xpack.osquery.agentPolicy.confirmModalCalloutDescription": "Fleet a détecté que certains de vos agents utilisaient déjà {agentPolicyCount, plural, one {la politique d'agent sélectionnée} other {les politiques d'agent sélectionnées}}. Suite à cette action, Fleet déploie les mises à jour de tous les agents qui utilisent {agentPolicyCount, plural, one {cette politique d'agent} other {ces politiques d'agent}}.", "xpack.osquery.agentPolicy.confirmModalCalloutTitle": "Cette action mettra à jour {agentCount, plural, one {# agent} other {# agents}}", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index fd315db4df1af2..9caebf91e4f74c 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -25315,22 +25315,11 @@ "xpack.observability.enableAwsLambdaMetricsDescription": "{technicalPreviewLabel} [サービスメトリック]タブにAmazon Lambdaメトリックを表示します。{feedbackLink}", "xpack.observability.enableCriticalPathDescription": "{technicalPreviewLabel} 任意で、トレースのクリティカルパスを表示します。", "xpack.observability.enableInfrastructureHostsViewDescription": "{technicalPreviewLabel}インフラアプリでホストビューを有効にします。{feedbackLink}。", - "xpack.observability.expView.columns.label": "{sourceField}の{percentileValue}パーセンタイル", - "xpack.observability.expView.columns.operation.label": "{operationType} / {sourceField}", - "xpack.observability.expView.filterValueButton.negate": "{value}以外", - "xpack.observability.expView.heading.addToCase.notification": "ビジュアライゼーションが正常にケースに追加されました:{caseTitle}", - "xpack.observability.expView.lastUpdated.label": "最終更新:{updatedDate}", - "xpack.observability.expView.seriesEditor.selectReportMetric.noFieldData": "フィールド{field}のデータがありません。", "xpack.observability.fieldValueSelection.apply.label": "{label}に選択したフィルターを適用", "xpack.observability.fieldValueSelection.placeholder": "フィルター{label}", "xpack.observability.fieldValueSelection.placeholder.search": "{label}を検索", "xpack.observability.filterButton.label": "{label}フィルターのフィルターグループを展開", - "xpack.observability.filters.expanded.search": "{label}を検索", - "xpack.observability.filters.label.wildcard": "{label}ワイルドカード", - "xpack.observability.filters.searchResults": "{total}件の検索結果", "xpack.observability.inspector.stats.queryTimeValue": "{queryTime}ms", - "xpack.observability.overview.exploratoryView.missingReportDefinition": "{reportDefinition}が見つかりません", - "xpack.observability.overview.exploratoryView.noDataAvailable": "利用可能な{dataType}データがありません。", "xpack.observability.profilingElasticsearchPluginDescription": "{technicalPreviewLabel} Elasticsearchプロファイラープラグインを使用してスタックトレースを読み込むかどうか。", "xpack.observability.ruleDetails.executionLogError": "ルール実行ログを読み込めません。理由:{message}", "xpack.observability.ruleDetails.ruleLoadError": "ルールを読み込めません。理由:{message}", @@ -25338,9 +25327,7 @@ "xpack.observability.slo.rules.burnRate.errors.invalidThresholdValue": "バーンレートしきい値は1以上{maxBurnRate}以下でなければなりません。", "xpack.observability.slo.rules.errorBudgetExhaustion.text": "このレートでは、SLOのエラー予算が{formatedHours}時間後に枯渇してしまいます。", "xpack.observability.slo.rules.longWindowDuration.tooltip": "バーンレートが計算されるルックバック期間。ルックバック期間を{shortWindowDuration}分(ルックバック期間の1/12)と短くすることで、より高速な復帰が可能になります", - "xpack.observability.textDefinitionField.placeholder.search": "{label}を検索", "xpack.observability.transactionRateLabel": "{value} tpm", - "xpack.observability.urlFilter.wildcard": "ワイルドカード*{wildcard}*を使用", "xpack.observability.ux.coreVitals.averageMessage": " {bad}未満", "xpack.observability.ux.coreVitals.paletteLegend.rankPercentage": "{labelsInd}({ranksInd}%)", "xpack.observability.ux.dashboard.webCoreVitals.traffic": "トラフィックの{trafficPerc}が表示されました", @@ -25410,7 +25397,6 @@ "xpack.observability.apmProgressiveLoadingQualityOff": "オフ", "xpack.observability.apmServiceInventoryOptimizedSorting": "APMでサービスリストの読み込みパフォーマンスを最適化", "xpack.observability.apmTraceExplorerTab": "APMトレースエクスプローラー", - "xpack.observability.apply.label": "適用", "xpack.observability.breadcrumbs.alertsLinkText": "アラート", "xpack.observability.breadcrumbs.observabilityLinkText": "Observability", "xpack.observability.breadcrumbs.overviewLinkText": "概要", @@ -25449,162 +25435,8 @@ "xpack.observability.enableInfrastructureHostsView": "インフラストラクチャーホストビュー", "xpack.observability.enableInspectEsQueriesExperimentDescription": "API応答でElasticsearchクエリを調査します。", "xpack.observability.enableInspectEsQueriesExperimentName": "ESクエリを調査", - "xpack.observability.exp.breakDownFilter.noBreakdown": "内訳なし", - "xpack.observability.exp.breakDownFilter.unavailable": "モニター期間メトリックでは、ステップ名内訳を使用できません。ステップ期間メトリックを使用して、ステップ名で分解します。", - "xpack.observability.exp.breakDownFilter.warning": "内訳は一度に1つの系列にのみ適用できます。", "xpack.observability.experimentalBadgeDescription": "この機能はテクニカルプレビュー中であり、将来のリリースでは変更されたり完全に削除されたりする場合があります。Elasticは最善の努力を講じてすべての問題の修正に努めますが、テクニカルプレビュー中の機能には正式なGA機能のサポートSLAが適用されません。", "xpack.observability.experimentalBadgeLabel": "テクニカルプレビュー", - "xpack.observability.exploratoryView.alerts.alertStarted": "タイムスタンプ", - "xpack.observability.exploratoryView.logs.logRateXAxisLabel": "タイムスタンプ", - "xpack.observability.exploratoryView.logs.logRateYAxisLabel": "毎分のログレート", - "xpack.observability.exploratoryView.noBrusing": "ブラシ選択によるズームは時系列グラフでのみ使用できます。", - "xpack.observability.expView.addToCase": "ケースに追加", - "xpack.observability.expView.alerts.category": "ルールカテゴリー", - "xpack.observability.expView.alerts.name": "アラート名", - "xpack.observability.expView.alerts.status": "アラートステータス", - "xpack.observability.expView.avgDuration": "平均期間", - "xpack.observability.expView.chartTypes.label": "チャートタイプ", - "xpack.observability.expView.complete": "完了", - "xpack.observability.expView.dateRanger.endDate": "終了日", - "xpack.observability.expView.dateRanger.startDate": "開始日", - "xpack.observability.expView.errors": "エラー", - "xpack.observability.expView.explore": "探索", - "xpack.observability.expView.failedTests": "失敗したテスト", - "xpack.observability.expView.fieldLabels.agentHost": "エージェントホスト", - "xpack.observability.expView.fieldLabels.agentType": "エージェントタイプ", - "xpack.observability.expView.fieldLabels.backend": "バックエンド時刻", - "xpack.observability.expView.fieldLabels.browserFamily": "ブラウザーファミリー", - "xpack.observability.expView.fieldLabels.browserVersion": "ブラウザーバージョン", - "xpack.observability.expView.fieldLabels.carrierLocation": "キャリアの位置情報", - "xpack.observability.expView.fieldLabels.carrierName": "キャリア名", - "xpack.observability.expView.fieldLabels.chooseField": "ラベルフィールド", - "xpack.observability.expView.fieldLabels.cls": "累積レイアウト変更", - "xpack.observability.expView.fieldLabels.connectionType": "接続タイプ", - "xpack.observability.expView.fieldLabels.coreWebVitals": "コア Web バイタル", - "xpack.observability.expView.fieldLabels.cpuUsage": "CPU 使用状況", - "xpack.observability.expView.fieldLabels.cpuUsage.docker": "Docker CPU使用状況", - "xpack.observability.expView.fieldLabels.cpuUsage.k8sDocker": "K8s pod CPU使用状況", - "xpack.observability.expView.fieldLabels.cpuUsage.system": "システムCPU使用状況", - "xpack.observability.expView.fieldLabels.dcl": "DOMコンテンツが読み込まれました", - "xpack.observability.expView.fieldLabels.device": "デバイス", - "xpack.observability.expView.fieldLabels.deviceDistribution": "デバイス分布", - "xpack.observability.expView.fieldLabels.deviceModel": "デバイスモデル", - "xpack.observability.expView.fieldLabels.downPings": "Down Ping", - "xpack.observability.expView.fieldLabels.environment": "環境", - "xpack.observability.expView.fieldLabels.eventDataset": "データセット", - "xpack.observability.expView.fieldLabels.fcp": "初回コンテンツの描画", - "xpack.observability.expView.fieldLabels.fid": "初回入力遅延", - "xpack.observability.expView.fieldLabels.heatMap": "ヒートマップ", - "xpack.observability.expView.fieldLabels.hostName": "ホスト名", - "xpack.observability.expView.fieldLabels.hostOS": "ホストOS", - "xpack.observability.expView.fieldLabels.kpi": "KPI", - "xpack.observability.expView.fieldLabels.kpiOverTime": "一定期間のKPI", - "xpack.observability.expView.fieldLabels.labels": "ラベル", - "xpack.observability.expView.fieldLabels.lcp": "最大コンテンツの描画", - "xpack.observability.expView.fieldLabels.location": "場所", - "xpack.observability.expView.fieldLabels.logRate": "ログレート", - "xpack.observability.expView.fieldLabels.memoryUsage": "システムメモリー使用状況", - "xpack.observability.expView.fieldLabels.message": "メッセージ", - "xpack.observability.expView.fieldLabels.metric": "メトリック", - "xpack.observability.expView.fieldLabels.mobile.memoryUsage": "システムメモリー使用状況", - "xpack.observability.expView.fieldLabels.mobileApp": "モバイルアプリ", - "xpack.observability.expView.fieldLabels.mobileResponse": "モバイル応答", - "xpack.observability.expView.fieldLabels.monitorDurationLabel": "監視期間", - "xpack.observability.expView.fieldLabels.monitorId": "モニターID", - "xpack.observability.expView.fieldLabels.monitorName": "モニター名", - "xpack.observability.expView.fieldLabels.monitorStatus": "監視ステータス", - "xpack.observability.expView.fieldLabels.monitorType": "モニタータイプ", - "xpack.observability.expView.fieldLabels.networkTimings": "ネットワークタイミング", - "xpack.observability.expView.fieldLabels.numberOfDevices": "デバイス数", - "xpack.observability.expView.fieldLabels.obsLocation": "Observerの位置情報", - "xpack.observability.expView.fieldLabels.onload": "ドキュメント完了(読み込み時)", - "xpack.observability.expView.fieldLabels.os": "オペレーティングシステム", - "xpack.observability.expView.fieldLabels.osPlatform": "OSプラットフォーム", - "xpack.observability.expView.fieldLabels.pageLoadTime": "ページ読み込み時間", - "xpack.observability.expView.fieldLabels.pagesLoaded": "ページが読み込まれました", - "xpack.observability.expView.fieldLabels.pageViews": "ページビュー", - "xpack.observability.expView.fieldLabels.performanceDistribution": "パフォーマンス分布", - "xpack.observability.expView.fieldLabels.pings": "ピング", - "xpack.observability.expView.fieldLabels.port": "ポート", - "xpack.observability.expView.fieldLabels.requestMethod": "リクエストメソッド", - "xpack.observability.expView.fieldLabels.responseLatency": "レイテンシ", - "xpack.observability.expView.fieldLabels.serviceName": "サービス名", - "xpack.observability.expView.fieldLabels.serviceType": "サービスタイプ", - "xpack.observability.expView.fieldLabels.serviceVersion": "サービスバージョン", - "xpack.observability.expView.fieldLabels.singleMetric": "シングルメトリック", - "xpack.observability.expView.fieldLabels.stepDurationLabel": "ステップ期間", - "xpack.observability.expView.fieldLabels.stepNameLabel": "ステップ名", - "xpack.observability.expView.fieldLabels.tags": "タグ", - "xpack.observability.expView.fieldLabels.tbt": "合計ブロック時間", - "xpack.observability.expView.fieldLabels.transactionPerMinute": "スループット", - "xpack.observability.expView.fieldLabels.upPings": "Up Ping", - "xpack.observability.expView.fieldLabels.url": "URL", - "xpack.observability.expView.fieldLabels.webApplication": "Webアプリケーション", - "xpack.observability.expView.heading.addToCase": "ケースに追加", - "xpack.observability.expView.heading.addToCase.notification.error": "選択したケースにビジュアライゼーションを追加できませんでした。", - "xpack.observability.expView.heading.addToCase.notification.viewCase": "ケースの表示", - "xpack.observability.expView.heading.embed": "埋め込み <></>", - "xpack.observability.expView.heading.embedTitle": "調査ビューを埋め込み(開発者専用機能)", - "xpack.observability.expView.heading.label": "データの探索", - "xpack.observability.expView.heading.openInLens": "Lensで開く", - "xpack.observability.expView.heading.saveLensVisualization": "保存", - "xpack.observability.expView.openInLens": "Lensで開く", - "xpack.observability.expView.operationType.25thPercentile": "25パーセンタイル", - "xpack.observability.expView.operationType.75thPercentile": "75パーセンタイル", - "xpack.observability.expView.operationType.90thPercentile": "90パーセンタイル", - "xpack.observability.expView.operationType.95thPercentile": "95パーセンタイル", - "xpack.observability.expView.operationType.99thPercentile": "99パーセンタイル", - "xpack.observability.expView.operationType.average": "平均", - "xpack.observability.expView.operationType.lastValue": "最終値", - "xpack.observability.expView.operationType.max": "最高", - "xpack.observability.expView.operationType.median": "中央", - "xpack.observability.expView.operationType.min": "最低", - "xpack.observability.expView.operationType.sum": "合計", - "xpack.observability.expView.operationType.uniqueCount": "ユニークカウント", - "xpack.observability.expView.reportType.selectDataType": "ビジュアライゼーションを作成するデータ型を選択します。", - "xpack.observability.expView.reportType.selectLabel": "レポートタイプを選択", - "xpack.observability.expView.save": "ビジュアライゼーションを保存", - "xpack.observability.expView.seriesBuilder.accordion.label": "系列情報を切り替える", - "xpack.observability.expView.seriesBuilder.addSeries": "数列を追加", - "xpack.observability.expView.seriesBuilder.addSeries.limitation": "このレポートタイプには1つの系列のみを追加できます。", - "xpack.observability.expView.seriesBuilder.addSeries.selectReportType": "系列を追加する前にレポートタイプを選択してください。", - "xpack.observability.expView.seriesBuilder.apply": "変更を適用", - "xpack.observability.expView.seriesBuilder.breakdownBy": "内訳基準", - "xpack.observability.expView.seriesBuilder.creationContext": "表示開始", - "xpack.observability.expView.seriesBuilder.creationTime": "グラフが作成されました", - "xpack.observability.expView.seriesBuilder.date": "日付", - "xpack.observability.expView.seriesBuilder.emptyReportDefinition": "ビジュアライゼーションを作成するレポート定義を選択します。", - "xpack.observability.expView.seriesBuilder.emptyview": "表示する情報がありません。", - "xpack.observability.expView.seriesBuilder.labelField": "ラベルフィールドを選択", - "xpack.observability.expView.seriesBuilder.loadingView": "ビューを読み込んでいます...", - "xpack.observability.expView.seriesBuilder.operation": "演算", - "xpack.observability.expView.seriesBuilder.reportType": "レポートタイプ", - "xpack.observability.expView.seriesBuilder.reportType.aria": "この選択により、作成するレポートのタイプを選択できます", - "xpack.observability.expView.seriesBuilder.selectFilters": "フィルター", - "xpack.observability.expView.seriesBuilder.selectReportType": "レポートタイプが選択されていません", - "xpack.observability.expView.seriesBuilder.selectReportType.empty": "レポートタイプを選択すると、ビジュアライゼーションを作成します。", - "xpack.observability.expView.seriesEditor.clearFilter": "フィルターを消去", - "xpack.observability.expView.seriesEditor.editChartSeriesLabel": "系列のグラフタイプを編集", - "xpack.observability.expView.seriesEditor.editName": "名前を編集", - "xpack.observability.expView.seriesEditor.noData": "利用可能なデータがありません", - "xpack.observability.expView.seriesEditor.noPermissions": "データビューを作成できません。必要な権限がありません。管理者に連絡してください。", - "xpack.observability.expView.seriesEditor.notFound": "系列が見つかりません。系列を追加してください。", - "xpack.observability.expView.seriesEditor.removeReportMetric": "レポートメトリックの削除", - "xpack.observability.expView.seriesEditor.removeSeries": "系列の削除", - "xpack.observability.expView.seriesEditor.removeSeriesDisabled": "主系列は削除できません。これを削除する前に、以下のすべての系列を削除してください。", - "xpack.observability.expView.seriesEditor.reportMetricTooltip": "レポートメトリック", - "xpack.observability.expView.seriesEditor.selectReportMetric": "レポートメトリックを選択", - "xpack.observability.expView.seriesEditor.seriesName": "系列名", - "xpack.observability.expView.stepDuration": "合計ステップ期間", - "xpack.observability.expView.synthetics.blocked": "ブロック", - "xpack.observability.expView.synthetics.connect": "接続", - "xpack.observability.expView.synthetics.dns": "DNS", - "xpack.observability.expView.synthetics.receive": "受信", - "xpack.observability.expView.synthetics.send": "送信", - "xpack.observability.expView.synthetics.ssl": "SSL", - "xpack.observability.expView.synthetics.total": "合計", - "xpack.observability.expView.synthetics.wait": "待機", - "xpack.observability.expView.totalRuns": "合計実行回数", "xpack.observability.featureCatalogueDescription": "専用UIで、ログ、メトリック、アプリケーショントレース、システム可用性を連結します。", "xpack.observability.featureCatalogueTitle": "Observability", "xpack.observability.featureRegistry.deleteSubFeatureDetails": "ケースとコメントを削除", @@ -25614,16 +25446,6 @@ "xpack.observability.fieldValueSelection.apply": "適用", "xpack.observability.fieldValueSelection.loading": "読み込み中", "xpack.observability.fieldValueSelection.logicalAnd": "論理ANDを使用", - "xpack.observability.filters.expanded.labels.backTo": "ラベルに戻る", - "xpack.observability.filters.expanded.labels.fields": "ラベルフィールド", - "xpack.observability.filters.expanded.labels.label": "ラベル", - "xpack.observability.filters.expanded.noFilter": "フィルターが見つかりません。", - "xpack.observability.filters.filterByUrl": "IDでフィルタリング", - "xpack.observability.filters.select": "選択してください", - "xpack.observability.filters.topPages": "上位のページ", - "xpack.observability.filters.url": "Url", - "xpack.observability.filters.url.loadingResults": "結果を読み込み中", - "xpack.observability.filters.url.noResults": "結果がありません", "xpack.observability.formatters.hoursTimeUnitLabel": "h", "xpack.observability.formatters.hoursTimeUnitLabelExtended": "時間", "xpack.observability.formatters.microsTimeUnitLabel": "μs", @@ -25680,25 +25502,6 @@ "xpack.observability.overview.apm.throughput": "スループット", "xpack.observability.overview.apm.throughputTip": "タイプ「リクエスト」または「ペイロード」のトランザクションの値が計算されます。いずれも使用できない場合は、値は上位のトランザクションタイプになります。", "xpack.observability.overview.apm.title": "サービス", - "xpack.observability.overview.exploratoryView": "データの探索", - "xpack.observability.overview.exploratoryView.alertsLabel": "アラート", - "xpack.observability.overview.exploratoryView.editSeriesColor": "系列の色を編集", - "xpack.observability.overview.exploratoryView.hideChart": "グラフを非表示", - "xpack.observability.overview.exploratoryView.lensDisabled": "Lensアプリを使用できません。調査ビューを使用するには、Lensを有効にしてください。", - "xpack.observability.overview.exploratoryView.logsLabel": "ログ", - "xpack.observability.overview.exploratoryView.metricsLabel": "メトリック", - "xpack.observability.overview.exploratoryView.missingDataType": "データ型が見つかりません", - "xpack.observability.overview.exploratoryView.missingReportMetric": "レポートメトリックが見つかりません", - "xpack.observability.overview.exploratoryView.mobileExperienceLabel": "モバイルエクスペリエンス", - "xpack.observability.overview.exploratoryView.noData": "データなし", - "xpack.observability.overview.exploratoryView.pickColor": "色を選択", - "xpack.observability.overview.exploratoryView.preview": "プレビュー", - "xpack.observability.overview.exploratoryView.refresh": "更新", - "xpack.observability.overview.exploratoryView.selectDataType": "データ型を選択", - "xpack.observability.overview.exploratoryView.selectDataTypeTooltip": "データ型は編集できません。", - "xpack.observability.overview.exploratoryView.showChart": "グラフを表示", - "xpack.observability.overview.exploratoryView.syntheticsLabel": "Synthetics監視", - "xpack.observability.overview.exploratoryView.uxLabel": "ユーザーエクスペリエンス(RUM)", "xpack.observability.overview.guidedSetupButton": "データアシスタント", "xpack.observability.overview.guidedSetupTourContent": "疑問がある場合は、ここをクリックすると、常にデータアシスタントにアクセスし、次のステップを確認できます。", "xpack.observability.overview.guidedSetupTourDismissButton": "閉じる", @@ -25761,15 +25564,7 @@ "xpack.observability.rules.docsLinkText": "ドキュメント", "xpack.observability.rulesLinkTitle": "ルール", "xpack.observability.rulesTitle": "ルール", - "xpack.observability.search.url.close": "閉じる", "xpack.observability.section.errorPanel": "データの取得時にエラーが発生しました。再試行してください", - "xpack.observability.seriesEditor.actionsAriaContextLabel": "系列アクションリスト", - "xpack.observability.seriesEditor.clone": "系列の複製", - "xpack.observability.seriesEditor.edit": "系列を編集", - "xpack.observability.seriesEditor.hide": "系列を非表示", - "xpack.observability.seriesEditor.popoverButtonLabel": "系列アクションを表示", - "xpack.observability.seriesEditor.sampleDocuments": "Discoverでトランザクションを表示", - "xpack.observability.seriesEditor.show": "系列を表示", "xpack.observability.serviceGroupMaxServicesUiSettingDescription": "特定のサービスグループのサービス数を制限", "xpack.observability.serviceGroupMaxServicesUiSettingName": "サービスグループの最大サービス", "xpack.observability.slo.alerting.reasonDescription": "アラートの理由の簡潔な説明", @@ -25872,6 +25667,211 @@ "xpack.observability.ux.dashboard.webCoreVitals.help": "詳細", "xpack.observability.ux.dashboard.webCoreVitals.helpAriaLabel": "ヘルプ", "xpack.observability.ux.service.help": "最大トラフィックのRUMサービスが選択されています", + "xpack.exploratoryView.expView.columns.label": "{sourceField}の{percentileValue}パーセンタイル", + "xpack.exploratoryView.expView.columns.operation.label": "{operationType} / {sourceField}", + "xpack.exploratoryView.expView.filterValueButton.negate": "{value}以外", + "xpack.exploratoryView.expView.heading.addToCase.notification": "ビジュアライゼーションが正常にケースに追加されました:{caseTitle}", + "xpack.exploratoryView.expView.lastUpdated.label": "最終更新:{updatedDate}", + "xpack.exploratoryView.expView.seriesEditor.selectReportMetric.noFieldData": "フィールド{field}のデータがありません。", + "xpack.exploratoryView.filters.expanded.search": "{label}を検索", + "xpack.exploratoryView.filters.label.wildcard": "{label}ワイルドカード", + "xpack.exploratoryView.filters.searchResults": "{total}件の検索結果", + "xpack.exploratoryView.missingReportDefinition": "{reportDefinition}が見つかりません", + "xpack.exploratoryView.noDataAvailable": "利用可能な{dataType}データがありません。", + "xpack.exploratoryView.textDefinitionField.placeholder.search": "{label}を検索", + "xpack.exploratoryView.urlFilter.wildcard": "ワイルドカード*{wildcard}*を使用", + "xpack.exploratoryView.apply.label": "適用", + "xpack.exploratoryView.breakDownFilter.noBreakdown": "内訳なし", + "xpack.exploratoryView.breakDownFilter.unavailable": "モニター期間メトリックでは、ステップ名内訳を使用できません。ステップ期間メトリックを使用して、ステップ名で分解します。", + "xpack.exploratoryView.breakDownFilter.warning": "内訳は一度に1つの系列にのみ適用できます。", + "xpack.exploratoryView.alerts.alertStarted": "タイムスタンプ", + "xpack.exploratoryView.logs.logRateXAxisLabel": "タイムスタンプ", + "xpack.exploratoryView.logs.logRateYAxisLabel": "毎分のログレート", + "xpack.exploratoryView.noBrushing": "ブラシ選択によるズームは時系列グラフでのみ使用できます。", + "xpack.exploratoryView.expView.addToCase": "ケースに追加", + "xpack.exploratoryView.expView.alerts.category": "ルールカテゴリー", + "xpack.exploratoryView.expView.alerts.name": "アラート名", + "xpack.exploratoryView.expView.alerts.status": "アラートステータス", + "xpack.exploratoryView.expView.avgDuration": "平均期間", + "xpack.exploratoryView.expView.chartTypes.label": "チャートタイプ", + "xpack.exploratoryView.expView.complete": "完了", + "xpack.exploratoryView.expView.dateRanger.endDate": "終了日", + "xpack.exploratoryView.expView.dateRanger.startDate": "開始日", + "xpack.exploratoryView.expView.errors": "エラー", + "xpack.exploratoryView.expView.explore": "探索", + "xpack.exploratoryView.expView.failedTests": "失敗したテスト", + "xpack.exploratoryView.expView.fieldLabels.agentHost": "エージェントホスト", + "xpack.exploratoryView.expView.fieldLabels.agentType": "エージェントタイプ", + "xpack.exploratoryView.expView.fieldLabels.backend": "バックエンド時刻", + "xpack.exploratoryView.expView.fieldLabels.browserFamily": "ブラウザーファミリー", + "xpack.exploratoryView.expView.fieldLabels.browserVersion": "ブラウザーバージョン", + "xpack.exploratoryView.expView.fieldLabels.carrierLocation": "キャリアの位置情報", + "xpack.exploratoryView.expView.fieldLabels.carrierName": "キャリア名", + "xpack.exploratoryView.expView.fieldLabels.chooseField": "ラベルフィールド", + "xpack.exploratoryView.expView.fieldLabels.cls": "累積レイアウト変更", + "xpack.exploratoryView.expView.fieldLabels.connectionType": "接続タイプ", + "xpack.exploratoryView.expView.fieldLabels.coreWebVitals": "コア Web バイタル", + "xpack.exploratoryView.expView.fieldLabels.cpuUsage": "CPU 使用状況", + "xpack.exploratoryView.expView.fieldLabels.cpuUsage.docker": "Docker CPU使用状況", + "xpack.exploratoryView.expView.fieldLabels.cpuUsage.k8sDocker": "K8s pod CPU使用状況", + "xpack.exploratoryView.expView.fieldLabels.cpuUsage.system": "システムCPU使用状況", + "xpack.exploratoryView.expView.fieldLabels.dcl": "DOMコンテンツが読み込まれました", + "xpack.exploratoryView.expView.fieldLabels.device": "デバイス", + "xpack.exploratoryView.expView.fieldLabels.deviceDistribution": "デバイス分布", + "xpack.exploratoryView.expView.fieldLabels.deviceModel": "デバイスモデル", + "xpack.exploratoryView.expView.fieldLabels.downPings": "Down Ping", + "xpack.exploratoryView.expView.fieldLabels.environment": "環境", + "xpack.exploratoryView.expView.fieldLabels.eventDataset": "データセット", + "xpack.exploratoryView.expView.fieldLabels.fcp": "初回コンテンツの描画", + "xpack.exploratoryView.expView.fieldLabels.fid": "初回入力遅延", + "xpack.exploratoryView.expView.fieldLabels.heatMap": "ヒートマップ", + "xpack.exploratoryView.expView.fieldLabels.hostName": "ホスト名", + "xpack.exploratoryView.expView.fieldLabels.hostOS": "ホストOS", + "xpack.exploratoryView.expView.fieldLabels.kpi": "KPI", + "xpack.exploratoryView.expView.fieldLabels.kpiOverTime": "一定期間のKPI", + "xpack.exploratoryView.expView.fieldLabels.labels": "ラベル", + "xpack.exploratoryView.expView.fieldLabels.lcp": "最大コンテンツの描画", + "xpack.exploratoryView.expView.fieldLabels.location": "場所", + "xpack.exploratoryView.expView.fieldLabels.logRate": "ログレート", + "xpack.exploratoryView.expView.fieldLabels.memoryUsage": "システムメモリー使用状況", + "xpack.exploratoryView.expView.fieldLabels.message": "メッセージ", + "xpack.exploratoryView.expView.fieldLabels.metric": "メトリック", + "xpack.exploratoryView.expView.fieldLabels.mobile.memoryUsage": "システムメモリー使用状況", + "xpack.exploratoryView.expView.fieldLabels.mobileApp": "モバイルアプリ", + "xpack.exploratoryView.expView.fieldLabels.mobileResponse": "モバイル応答", + "xpack.exploratoryView.expView.fieldLabels.monitorDurationLabel": "監視期間", + "xpack.exploratoryView.expView.fieldLabels.monitorId": "モニターID", + "xpack.exploratoryView.expView.fieldLabels.monitorName": "モニター名", + "xpack.exploratoryView.expView.fieldLabels.monitorStatus": "監視ステータス", + "xpack.exploratoryView.expView.fieldLabels.monitorType": "モニタータイプ", + "xpack.exploratoryView.expView.fieldLabels.networkTimings": "ネットワークタイミング", + "xpack.exploratoryView.expView.fieldLabels.numberOfDevices": "デバイス数", + "xpack.exploratoryView.expView.fieldLabels.obsLocation": "Observerの位置情報", + "xpack.exploratoryView.expView.fieldLabels.onload": "ドキュメント完了(読み込み時)", + "xpack.exploratoryView.expView.fieldLabels.os": "オペレーティングシステム", + "xpack.exploratoryView.expView.fieldLabels.osPlatform": "OSプラットフォーム", + "xpack.exploratoryView.expView.fieldLabels.pageLoadTime": "ページ読み込み時間", + "xpack.exploratoryView.expView.fieldLabels.pagesLoaded": "ページが読み込まれました", + "xpack.exploratoryView.expView.fieldLabels.pageViews": "ページビュー", + "xpack.exploratoryView.expView.fieldLabels.performanceDistribution": "パフォーマンス分布", + "xpack.exploratoryView.expView.fieldLabels.pings": "ピング", + "xpack.exploratoryView.expView.fieldLabels.port": "ポート", + "xpack.exploratoryView.expView.fieldLabels.requestMethod": "リクエストメソッド", + "xpack.exploratoryView.expView.fieldLabels.responseLatency": "レイテンシ", + "xpack.exploratoryView.expView.fieldLabels.serviceName": "サービス名", + "xpack.exploratoryView.expView.fieldLabels.serviceType": "サービスタイプ", + "xpack.exploratoryView.expView.fieldLabels.serviceVersion": "サービスバージョン", + "xpack.exploratoryView.expView.fieldLabels.singleMetric": "シングルメトリック", + "xpack.exploratoryView.expView.fieldLabels.stepDurationLabel": "ステップ期間", + "xpack.exploratoryView.expView.fieldLabels.stepNameLabel": "ステップ名", + "xpack.exploratoryView.expView.fieldLabels.tags": "タグ", + "xpack.exploratoryView.expView.fieldLabels.tbt": "合計ブロック時間", + "xpack.exploratoryView.expView.fieldLabels.transactionPerMinute": "スループット", + "xpack.exploratoryView.expView.fieldLabels.upPings": "Up Ping", + "xpack.exploratoryView.expView.fieldLabels.url": "URL", + "xpack.exploratoryView.expView.fieldLabels.webApplication": "Webアプリケーション", + "xpack.exploratoryView.expView.heading.addToCase": "ケースに追加", + "xpack.exploratoryView.expView.heading.addToCase.notification.error": "選択したケースにビジュアライゼーションを追加できませんでした。", + "xpack.exploratoryView.expView.heading.addToCase.notification.viewCase": "ケースの表示", + "xpack.exploratoryView.expView.heading.embed": "埋め込み <></>", + "xpack.exploratoryView.expView.heading.embedTitle": "調査ビューを埋め込み(開発者専用機能)", + "xpack.exploratoryView.expView.heading.label": "データの探索", + "xpack.exploratoryView.expView.heading.openInLens": "Lensで開く", + "xpack.exploratoryView.expView.heading.saveLensVisualization": "保存", + "xpack.exploratoryView.expView.openInLens": "Lensで開く", + "xpack.exploratoryView.expView.operationType.25thPercentile": "25パーセンタイル", + "xpack.exploratoryView.expView.operationType.75thPercentile": "75パーセンタイル", + "xpack.exploratoryView.expView.operationType.90thPercentile": "90パーセンタイル", + "xpack.exploratoryView.expView.operationType.95thPercentile": "95パーセンタイル", + "xpack.exploratoryView.expView.operationType.99thPercentile": "99パーセンタイル", + "xpack.exploratoryView.expView.operationType.average": "平均", + "xpack.exploratoryView.expView.operationType.lastValue": "最終値", + "xpack.exploratoryView.expView.operationType.max": "最高", + "xpack.exploratoryView.expView.operationType.median": "中央", + "xpack.exploratoryView.expView.operationType.min": "最低", + "xpack.exploratoryView.expView.operationType.sum": "合計", + "xpack.exploratoryView.expView.operationType.uniqueCount": "ユニークカウント", + "xpack.exploratoryView.expView.reportType.selectDataType": "ビジュアライゼーションを作成するデータ型を選択します。", + "xpack.exploratoryView.expView.reportType.selectLabel": "レポートタイプを選択", + "xpack.exploratoryView.expView.save": "ビジュアライゼーションを保存", + "xpack.exploratoryView.expView.seriesBuilder.accordion.label": "系列情報を切り替える", + "xpack.exploratoryView.expView.seriesBuilder.addSeries": "数列を追加", + "xpack.exploratoryView.expView.seriesBuilder.addSeries.limitation": "このレポートタイプには1つの系列のみを追加できます。", + "xpack.exploratoryView.expView.seriesBuilder.addSeries.selectReportType": "系列を追加する前にレポートタイプを選択してください。", + "xpack.exploratoryView.expView.seriesBuilder.apply": "変更を適用", + "xpack.exploratoryView.expView.seriesBuilder.breakdownBy": "内訳基準", + "xpack.exploratoryView.expView.seriesBuilder.creationContext": "表示開始", + "xpack.exploratoryView.expView.seriesBuilder.creationTime": "グラフが作成されました", + "xpack.exploratoryView.expView.seriesBuilder.date": "日付", + "xpack.exploratoryView.expView.seriesBuilder.emptyReportDefinition": "ビジュアライゼーションを作成するレポート定義を選択します。", + "xpack.exploratoryView.expView.seriesBuilder.emptyview": "表示する情報がありません。", + "xpack.exploratoryView.expView.seriesBuilder.labelField": "ラベルフィールドを選択", + "xpack.exploratoryView.expView.seriesBuilder.loadingView": "ビューを読み込んでいます...", + "xpack.exploratoryView.expView.seriesBuilder.operation": "演算", + "xpack.exploratoryView.expView.seriesBuilder.reportType": "レポートタイプ", + "xpack.exploratoryView.expView.seriesBuilder.reportType.aria": "この選択により、作成するレポートのタイプを選択できます", + "xpack.exploratoryView.expView.seriesBuilder.selectFilters": "フィルター", + "xpack.exploratoryView.expView.seriesBuilder.selectReportType": "レポートタイプが選択されていません", + "xpack.exploratoryView.expView.seriesBuilder.selectReportType.empty": "レポートタイプを選択すると、ビジュアライゼーションを作成します。", + "xpack.exploratoryView.expView.seriesEditor.clearFilter": "フィルターを消去", + "xpack.exploratoryView.expView.seriesEditor.editChartSeriesLabel": "系列のグラフタイプを編集", + "xpack.exploratoryView.expView.seriesEditor.editName": "名前を編集", + "xpack.exploratoryView.expView.seriesEditor.noData": "利用可能なデータがありません", + "xpack.exploratoryView.expView.seriesEditor.noPermissions": "データビューを作成できません。必要な権限がありません。管理者に連絡してください。", + "xpack.exploratoryView.expView.seriesEditor.notFound": "系列が見つかりません。系列を追加してください。", + "xpack.exploratoryView.expView.seriesEditor.removeReportMetric": "レポートメトリックの削除", + "xpack.exploratoryView.expView.seriesEditor.removeSeries": "系列の削除", + "xpack.exploratoryView.expView.seriesEditor.removeSeriesDisabled": "主系列は削除できません。これを削除する前に、以下のすべての系列を削除してください。", + "xpack.exploratoryView.expView.seriesEditor.reportMetricTooltip": "レポートメトリック", + "xpack.exploratoryView.expView.seriesEditor.selectReportMetric": "レポートメトリックを選択", + "xpack.exploratoryView.expView.seriesEditor.seriesName": "系列名", + "xpack.exploratoryView.expView.stepDuration": "合計ステップ期間", + "xpack.exploratoryView.expView.synthetics.blocked": "ブロック", + "xpack.exploratoryView.expView.synthetics.connect": "接続", + "xpack.exploratoryView.expView.synthetics.dns": "DNS", + "xpack.exploratoryView.expView.synthetics.receive": "受信", + "xpack.exploratoryView.expView.synthetics.send": "送信", + "xpack.exploratoryView.expView.synthetics.ssl": "SSL", + "xpack.exploratoryView.expView.synthetics.total": "合計", + "xpack.exploratoryView.expView.synthetics.wait": "待機", + "xpack.exploratoryView.expView.totalRuns": "合計実行回数", + "xpack.exploratoryView.filters.expanded.labels.backTo": "ラベルに戻る", + "xpack.exploratoryView.filters.expanded.labels.fields": "ラベルフィールド", + "xpack.exploratoryView.filters.expanded.labels.label": "ラベル", + "xpack.exploratoryView.filters.expanded.noFilter": "フィルターが見つかりません。", + "xpack.exploratoryView.filters.filterByUrl": "IDでフィルタリング", + "xpack.exploratoryView.filters.select": "選択してください", + "xpack.exploratoryView.filters.topPages": "上位のページ", + "xpack.exploratoryView.filters.url": "Url", + "xpack.exploratoryView.filters.url.loadingResults": "結果を読み込み中", + "xpack.exploratoryView.filters.url.noResults": "結果がありません", + "xpack.exploratoryView.overview": "データの探索", + "xpack.exploratoryView.alertsLabel": "アラート", + "xpack.exploratoryView.editSeriesColor": "系列の色を編集", + "xpack.exploratoryView.hideChart": "グラフを非表示", + "xpack.exploratoryView.lensDisabled": "Lensアプリを使用できません。調査ビューを使用するには、Lensを有効にしてください。", + "xpack.exploratoryView.logsLabel": "ログ", + "xpack.exploratoryView.metricsLabel": "メトリック", + "xpack.exploratoryView.missingDataType": "データ型が見つかりません", + "xpack.exploratoryView.missingReportMetric": "レポートメトリックが見つかりません", + "xpack.exploratoryView.mobileExperienceLabel": "モバイルエクスペリエンス", + "xpack.exploratoryView.noData": "データなし", + "xpack.exploratoryView.pickColor": "色を選択", + "xpack.exploratoryView.preview": "プレビュー", + "xpack.exploratoryView.refresh": "更新", + "xpack.exploratoryView.selectDataType": "データ型を選択", + "xpack.exploratoryView.selectDataTypeTooltip": "データ型は編集できません。", + "xpack.exploratoryView.showChart": "グラフを表示", + "xpack.exploratoryView.syntheticsLabel": "Synthetics監視", + "xpack.exploratoryView.uxLabel": "ユーザーエクスペリエンス(RUM)", + "xpack.exploratoryView.search.url.close": "閉じる", + "xpack.exploratoryView.seriesEditor.actionsAriaContextLabel": "系列アクションリスト", + "xpack.exploratoryView.seriesEditor.clone": "系列の複製", + "xpack.exploratoryView.seriesEditor.edit": "系列を編集", + "xpack.exploratoryView.seriesEditor.hide": "系列を非表示", + "xpack.exploratoryView.seriesEditor.popoverButtonLabel": "系列アクションを表示", + "xpack.exploratoryView.seriesEditor.sampleDocuments": "Discoverでトランザクションを表示", + "xpack.exploratoryView.seriesEditor.show": "系列を表示", "xpack.osquery.action.missingPrivileges": "このページにアクセスするには、{osquery} Kibana権限について管理者に確認してください。", "xpack.osquery.agentPolicy.confirmModalCalloutDescription": "選択した{agentPolicyCount, plural, other {エージェントポリシー}}が一部のエージェントですでに使用されていることをFleetが検出しました。このアクションの結果として、Fleetはこの{agentPolicyCount, plural, other {エージェントポリシー}}を使用しているすべてのエージェントに更新をデプロイします。", "xpack.osquery.agentPolicy.confirmModalCalloutTitle": "{agentCount, plural, other {#個のエージェント}}が更新されます", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 1a65bd04e2be15..75901fdc42c3cf 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -25328,22 +25328,11 @@ "xpack.observability.enableAwsLambdaMetricsDescription": "{technicalPreviewLabel} 在服务指标选项卡中显示 Amazon Lambda 指标。{feedbackLink}", "xpack.observability.enableCriticalPathDescription": "{technicalPreviewLabel}(可选)显示跟踪的关键路径。", "xpack.observability.enableInfrastructureHostsViewDescription": "{technicalPreviewLabel} 在 Infrastructure 应用中启用主机视图。{feedbackLink}。", - "xpack.observability.expView.columns.label": "{sourceField} 的第 {percentileValue} 百分位", - "xpack.observability.expView.columns.operation.label": "{sourceField} 的 {operationType}", - "xpack.observability.expView.filterValueButton.negate": "不是 {value}", - "xpack.observability.expView.heading.addToCase.notification": "已成功将可视化添加到案例:{caseTitle}", - "xpack.observability.expView.lastUpdated.label": "上次更新时间:{updatedDate}", - "xpack.observability.expView.seriesEditor.selectReportMetric.noFieldData": "字段 {field} 无可用数据。", "xpack.observability.fieldValueSelection.apply.label": "为 {label} 应用选定筛选", "xpack.observability.fieldValueSelection.placeholder": "筛选 {label}", "xpack.observability.fieldValueSelection.placeholder.search": "搜索 {label}", "xpack.observability.filterButton.label": "展开筛选 {label} 的筛选组", - "xpack.observability.filters.expanded.search": "搜索 {label}", - "xpack.observability.filters.label.wildcard": "{label} 通配符", - "xpack.observability.filters.searchResults": "{total} 项搜索结果", "xpack.observability.inspector.stats.queryTimeValue": "{queryTime}ms", - "xpack.observability.overview.exploratoryView.missingReportDefinition": "缺少 {reportDefinition}", - "xpack.observability.overview.exploratoryView.noDataAvailable": "没有可用的 {dataType} 数据。", "xpack.observability.profilingElasticsearchPluginDescription": "{technicalPreviewLabel} 是否使用 Elasticsearch 分析器插件加载堆栈跟踪。", "xpack.observability.ruleDetails.executionLogError": "无法加载规则执行日志。原因:{message}", "xpack.observability.ruleDetails.ruleLoadError": "无法加载规则。原因:{message}", @@ -25355,9 +25344,7 @@ "xpack.observability.slo.rules.burnRate.errors.invalidThresholdValue": "消耗速度阈值必须介于 1 和 {maxBurnRate} 之间。", "xpack.observability.slo.rules.errorBudgetExhaustion.text": "在此速度下,SLO 的错误预算将在 {formatedHours} 小时后耗尽。", "xpack.observability.slo.rules.longWindowDuration.tooltip": "在其间计算消耗速度的回顾期。将使用 {shortWindowDuration} 分钟的较短回顾期(1/12 的回顾期)以便更快恢复", - "xpack.observability.textDefinitionField.placeholder.search": "搜索 {label}", "xpack.observability.transactionRateLabel": "{value} tpm", - "xpack.observability.urlFilter.wildcard": "使用通配符 *{wildcard}*", "xpack.observability.ux.coreVitals.averageMessage": " 且小于 {bad}", "xpack.observability.ux.coreVitals.paletteLegend.rankPercentage": "{labelsInd} ({ranksInd}%)", "xpack.observability.ux.dashboard.webCoreVitals.traffic": "已占 {trafficPerc} 的流量", @@ -25427,7 +25414,6 @@ "xpack.observability.apmProgressiveLoadingQualityOff": "关闭", "xpack.observability.apmServiceInventoryOptimizedSorting": "优化 APM 中的服务列表加载性能", "xpack.observability.apmTraceExplorerTab": "APM Trace Explorer", - "xpack.observability.apply.label": "应用", "xpack.observability.breadcrumbs.alertsLinkText": "告警", "xpack.observability.breadcrumbs.observabilityLinkText": "Observability", "xpack.observability.breadcrumbs.overviewLinkText": "概览", @@ -25466,162 +25452,8 @@ "xpack.observability.enableInfrastructureHostsView": "基础架构主机视图", "xpack.observability.enableInspectEsQueriesExperimentDescription": "检查 API 响应中的 Elasticsearch 查询。", "xpack.observability.enableInspectEsQueriesExperimentName": "检查 ES 查询", - "xpack.observability.exp.breakDownFilter.noBreakdown": "无细目", - "xpack.observability.exp.breakDownFilter.unavailable": "步骤名称细目不可用于监测持续时间指标。使用步骤持续时间指标以按步骤名称细分。", - "xpack.observability.exp.breakDownFilter.warning": "一次只能将细目应用于一个序列。", "xpack.observability.experimentalBadgeDescription": "此功能处于技术预览状态,在未来版本中可能会更改或完全移除。Elastic 将尽最大努力来修复任何问题,但处于技术预览状态的功能不受正式 GA 功能支持 SLA 的约束。", "xpack.observability.experimentalBadgeLabel": "技术预览", - "xpack.observability.exploratoryView.alerts.alertStarted": "时间戳", - "xpack.observability.exploratoryView.logs.logRateXAxisLabel": "时间戳", - "xpack.observability.exploratoryView.logs.logRateYAxisLabel": "每分钟日志速率", - "xpack.observability.exploratoryView.noBrusing": "按画笔选择缩放仅适用于时间序列图表。", - "xpack.observability.expView.addToCase": "添加到案例", - "xpack.observability.expView.alerts.category": "规则类别", - "xpack.observability.expView.alerts.name": "告警名称", - "xpack.observability.expView.alerts.status": "告警状态", - "xpack.observability.expView.avgDuration": "平均持续时间", - "xpack.observability.expView.chartTypes.label": "图表类型", - "xpack.observability.expView.complete": "已完成", - "xpack.observability.expView.dateRanger.endDate": "结束日期", - "xpack.observability.expView.dateRanger.startDate": "开始日期", - "xpack.observability.expView.errors": "错误", - "xpack.observability.expView.explore": "浏览", - "xpack.observability.expView.failedTests": "失败的测试", - "xpack.observability.expView.fieldLabels.agentHost": "代理主机", - "xpack.observability.expView.fieldLabels.agentType": "代理类型", - "xpack.observability.expView.fieldLabels.backend": "后端时间", - "xpack.observability.expView.fieldLabels.browserFamily": "浏览器系列", - "xpack.observability.expView.fieldLabels.browserVersion": "浏览器版本", - "xpack.observability.expView.fieldLabels.carrierLocation": "运营商位置", - "xpack.observability.expView.fieldLabels.carrierName": "运营商名称", - "xpack.observability.expView.fieldLabels.chooseField": "标签字段", - "xpack.observability.expView.fieldLabels.cls": "累计布局偏移", - "xpack.observability.expView.fieldLabels.connectionType": "连接类型", - "xpack.observability.expView.fieldLabels.coreWebVitals": "网站体验核心指标", - "xpack.observability.expView.fieldLabels.cpuUsage": "CPU 使用", - "xpack.observability.expView.fieldLabels.cpuUsage.docker": "Docker CPU 使用", - "xpack.observability.expView.fieldLabels.cpuUsage.k8sDocker": "K8s pod CPU 使用", - "xpack.observability.expView.fieldLabels.cpuUsage.system": "系统 CPU 使用", - "xpack.observability.expView.fieldLabels.dcl": "DOM 内容已加载", - "xpack.observability.expView.fieldLabels.device": "设备", - "xpack.observability.expView.fieldLabels.deviceDistribution": "设备分布", - "xpack.observability.expView.fieldLabels.deviceModel": "设备型号", - "xpack.observability.expView.fieldLabels.downPings": "关闭 Ping", - "xpack.observability.expView.fieldLabels.environment": "环境", - "xpack.observability.expView.fieldLabels.eventDataset": "数据集", - "xpack.observability.expView.fieldLabels.fcp": "首次内容绘制", - "xpack.observability.expView.fieldLabels.fid": "首次输入延迟", - "xpack.observability.expView.fieldLabels.heatMap": "热图", - "xpack.observability.expView.fieldLabels.hostName": "主机名", - "xpack.observability.expView.fieldLabels.hostOS": "主机 OS", - "xpack.observability.expView.fieldLabels.kpi": "KPI", - "xpack.observability.expView.fieldLabels.kpiOverTime": "时移 KPI", - "xpack.observability.expView.fieldLabels.labels": "标签", - "xpack.observability.expView.fieldLabels.lcp": "最大内容绘制", - "xpack.observability.expView.fieldLabels.location": "位置", - "xpack.observability.expView.fieldLabels.logRate": "日志速率", - "xpack.observability.expView.fieldLabels.memoryUsage": "系统内存使用", - "xpack.observability.expView.fieldLabels.message": "消息", - "xpack.observability.expView.fieldLabels.metric": "指标", - "xpack.observability.expView.fieldLabels.mobile.memoryUsage": "系统内存使用", - "xpack.observability.expView.fieldLabels.mobileApp": "移动应用", - "xpack.observability.expView.fieldLabels.mobileResponse": "移动响应", - "xpack.observability.expView.fieldLabels.monitorDurationLabel": "监测持续时间", - "xpack.observability.expView.fieldLabels.monitorId": "监测 ID", - "xpack.observability.expView.fieldLabels.monitorName": "监测名称", - "xpack.observability.expView.fieldLabels.monitorStatus": "监测状态", - "xpack.observability.expView.fieldLabels.monitorType": "监测类型", - "xpack.observability.expView.fieldLabels.networkTimings": "网络计时", - "xpack.observability.expView.fieldLabels.numberOfDevices": "设备数量", - "xpack.observability.expView.fieldLabels.obsLocation": "观察者位置", - "xpack.observability.expView.fieldLabels.onload": "文档完成 (onLoad)", - "xpack.observability.expView.fieldLabels.os": "操作系统", - "xpack.observability.expView.fieldLabels.osPlatform": "OS 平台", - "xpack.observability.expView.fieldLabels.pageLoadTime": "页面加载时间", - "xpack.observability.expView.fieldLabels.pagesLoaded": "已加载页面", - "xpack.observability.expView.fieldLabels.pageViews": "页面查看次数", - "xpack.observability.expView.fieldLabels.performanceDistribution": "性能分布", - "xpack.observability.expView.fieldLabels.pings": "Ping", - "xpack.observability.expView.fieldLabels.port": "端口", - "xpack.observability.expView.fieldLabels.requestMethod": "请求方法", - "xpack.observability.expView.fieldLabels.responseLatency": "延迟", - "xpack.observability.expView.fieldLabels.serviceName": "服务名称", - "xpack.observability.expView.fieldLabels.serviceType": "服务类型", - "xpack.observability.expView.fieldLabels.serviceVersion": "服务版本", - "xpack.observability.expView.fieldLabels.singleMetric": "单一指标", - "xpack.observability.expView.fieldLabels.stepDurationLabel": "步骤持续时间", - "xpack.observability.expView.fieldLabels.stepNameLabel": "步骤名称", - "xpack.observability.expView.fieldLabels.tags": "标签", - "xpack.observability.expView.fieldLabels.tbt": "阻止总时间", - "xpack.observability.expView.fieldLabels.transactionPerMinute": "吞吐量", - "xpack.observability.expView.fieldLabels.upPings": "运行 Ping", - "xpack.observability.expView.fieldLabels.url": "URL", - "xpack.observability.expView.fieldLabels.webApplication": "Web 应用程序", - "xpack.observability.expView.heading.addToCase": "添加到案例", - "xpack.observability.expView.heading.addToCase.notification.error": "未能将可视化添加到所选案例。", - "xpack.observability.expView.heading.addToCase.notification.viewCase": "查看案例", - "xpack.observability.expView.heading.embed": "嵌入 <></>", - "xpack.observability.expView.heading.embedTitle": "嵌入浏览视图(仅用于开发的功能)", - "xpack.observability.expView.heading.label": "浏览数据", - "xpack.observability.expView.heading.openInLens": "在 Lens 中打开", - "xpack.observability.expView.heading.saveLensVisualization": "保存", - "xpack.observability.expView.openInLens": "在 Lens 中打开", - "xpack.observability.expView.operationType.25thPercentile": "第 25 个百分位", - "xpack.observability.expView.operationType.75thPercentile": "第 75 个百分位", - "xpack.observability.expView.operationType.90thPercentile": "第 90 个百分位", - "xpack.observability.expView.operationType.95thPercentile": "第 95 个百分位", - "xpack.observability.expView.operationType.99thPercentile": "第 99 个百分位", - "xpack.observability.expView.operationType.average": "平均值", - "xpack.observability.expView.operationType.lastValue": "最后值", - "xpack.observability.expView.operationType.max": "最大值", - "xpack.observability.expView.operationType.median": "中值", - "xpack.observability.expView.operationType.min": "最小值", - "xpack.observability.expView.operationType.sum": "求和", - "xpack.observability.expView.operationType.uniqueCount": "唯一计数", - "xpack.observability.expView.reportType.selectDataType": "选择数据类型以创建可视化。", - "xpack.observability.expView.reportType.selectLabel": "选择报告类型", - "xpack.observability.expView.save": "保存可视化", - "xpack.observability.expView.seriesBuilder.accordion.label": "切换序列信息", - "xpack.observability.expView.seriesBuilder.addSeries": "添加序列", - "xpack.observability.expView.seriesBuilder.addSeries.limitation": "只能添加一个此报告类型的序列。", - "xpack.observability.expView.seriesBuilder.addSeries.selectReportType": "请先选择报告类型,然后再添加序列。", - "xpack.observability.expView.seriesBuilder.apply": "应用更改", - "xpack.observability.expView.seriesBuilder.breakdownBy": "细分依据", - "xpack.observability.expView.seriesBuilder.creationContext": "显示自", - "xpack.observability.expView.seriesBuilder.creationTime": "已创建图表", - "xpack.observability.expView.seriesBuilder.date": "日期", - "xpack.observability.expView.seriesBuilder.emptyReportDefinition": "选择报告定义以创建可视化。", - "xpack.observability.expView.seriesBuilder.emptyview": "没有可显示的内容。", - "xpack.observability.expView.seriesBuilder.labelField": "选择标签字段", - "xpack.observability.expView.seriesBuilder.loadingView": "正在加载视图......", - "xpack.observability.expView.seriesBuilder.operation": "操作", - "xpack.observability.expView.seriesBuilder.reportType": "报告类型", - "xpack.observability.expView.seriesBuilder.reportType.aria": "此选择允许您选择希望创建的报告类型", - "xpack.observability.expView.seriesBuilder.selectFilters": "筛选", - "xpack.observability.expView.seriesBuilder.selectReportType": "未选择任何报告类型", - "xpack.observability.expView.seriesBuilder.selectReportType.empty": "选择报告类型以创建可视化。", - "xpack.observability.expView.seriesEditor.clearFilter": "清除筛选", - "xpack.observability.expView.seriesEditor.editChartSeriesLabel": "编辑序列的图表类型", - "xpack.observability.expView.seriesEditor.editName": "编辑名称", - "xpack.observability.expView.seriesEditor.noData": "没有可用数据", - "xpack.observability.expView.seriesEditor.noPermissions": "无法创建数据视图。您没有所需权限,请与管理员联系。", - "xpack.observability.expView.seriesEditor.notFound": "未找到任何序列。请添加序列。", - "xpack.observability.expView.seriesEditor.removeReportMetric": "移除报告指标", - "xpack.observability.expView.seriesEditor.removeSeries": "移除序列", - "xpack.observability.expView.seriesEditor.removeSeriesDisabled": "无法移除主要序列。请先移除下面的所有序列,然后才能移除此项。", - "xpack.observability.expView.seriesEditor.reportMetricTooltip": "报告指标", - "xpack.observability.expView.seriesEditor.selectReportMetric": "选择报告指标", - "xpack.observability.expView.seriesEditor.seriesName": "序列名称", - "xpack.observability.expView.stepDuration": "步骤总持续时间", - "xpack.observability.expView.synthetics.blocked": "已阻止", - "xpack.observability.expView.synthetics.connect": "连接", - "xpack.observability.expView.synthetics.dns": "DNS", - "xpack.observability.expView.synthetics.receive": "接收", - "xpack.observability.expView.synthetics.send": "发送", - "xpack.observability.expView.synthetics.ssl": "SSL", - "xpack.observability.expView.synthetics.total": "合计", - "xpack.observability.expView.synthetics.wait": "等待", - "xpack.observability.expView.totalRuns": "总运行次数", "xpack.observability.featureCatalogueDescription": "通过专用 UI 整合您的日志、指标、应用程序跟踪和系统可用性。", "xpack.observability.featureCatalogueTitle": "Observability", "xpack.observability.featureRegistry.deleteSubFeatureDetails": "删除案例和注释", @@ -25631,16 +25463,6 @@ "xpack.observability.fieldValueSelection.apply": "应用", "xpack.observability.fieldValueSelection.loading": "正在加载", "xpack.observability.fieldValueSelection.logicalAnd": "使用逻辑 AND", - "xpack.observability.filters.expanded.labels.backTo": "返回到标签", - "xpack.observability.filters.expanded.labels.fields": "标签字段", - "xpack.observability.filters.expanded.labels.label": "标签", - "xpack.observability.filters.expanded.noFilter": "未找到任何筛选。", - "xpack.observability.filters.filterByUrl": "按 URL 筛选", - "xpack.observability.filters.select": "选择", - "xpack.observability.filters.topPages": "排名靠前页面", - "xpack.observability.filters.url": "URL", - "xpack.observability.filters.url.loadingResults": "正在加载结果", - "xpack.observability.filters.url.noResults": "没有可用结果", "xpack.observability.formatters.hoursTimeUnitLabel": "h", "xpack.observability.formatters.hoursTimeUnitLabelExtended": "小时", "xpack.observability.formatters.microsTimeUnitLabel": "μs", @@ -25697,25 +25519,6 @@ "xpack.observability.overview.apm.throughput": "吞吐量", "xpack.observability.overview.apm.throughputTip": "将为类型为“request”或“page-load”的事务计算值。如果两者都不可用,值将反映排名靠前事务类型。", "xpack.observability.overview.apm.title": "服务", - "xpack.observability.overview.exploratoryView": "浏览数据", - "xpack.observability.overview.exploratoryView.alertsLabel": "告警", - "xpack.observability.overview.exploratoryView.editSeriesColor": "编辑序列的颜色", - "xpack.observability.overview.exploratoryView.hideChart": "隐藏图表", - "xpack.observability.overview.exploratoryView.lensDisabled": "Lens 应用不可用,请启用 Lens 以使用浏览视图。", - "xpack.observability.overview.exploratoryView.logsLabel": "日志", - "xpack.observability.overview.exploratoryView.metricsLabel": "指标", - "xpack.observability.overview.exploratoryView.missingDataType": "缺少数据类型", - "xpack.observability.overview.exploratoryView.missingReportMetric": "缺少报告指标", - "xpack.observability.overview.exploratoryView.mobileExperienceLabel": "移动体验", - "xpack.observability.overview.exploratoryView.noData": "无数据", - "xpack.observability.overview.exploratoryView.pickColor": "选取颜色", - "xpack.observability.overview.exploratoryView.preview": "预览", - "xpack.observability.overview.exploratoryView.refresh": "刷新", - "xpack.observability.overview.exploratoryView.selectDataType": "选择数据类型", - "xpack.observability.overview.exploratoryView.selectDataTypeTooltip": "无法编辑数据类型。", - "xpack.observability.overview.exploratoryView.showChart": "显示图表", - "xpack.observability.overview.exploratoryView.syntheticsLabel": "Synthetics 监测", - "xpack.observability.overview.exploratoryView.uxLabel": "用户体验 (RUM)", "xpack.observability.overview.guidedSetupButton": "数据助手", "xpack.observability.overview.guidedSetupTourContent": "如果您存在疑问,您始终可以通过单击此处来访问数据助手并查看后续步骤。", "xpack.observability.overview.guidedSetupTourDismissButton": "关闭", @@ -25778,15 +25581,7 @@ "xpack.observability.rules.docsLinkText": "文档", "xpack.observability.rulesLinkTitle": "规则", "xpack.observability.rulesTitle": "规则", - "xpack.observability.search.url.close": "关闭", "xpack.observability.section.errorPanel": "尝试提取数据时发生错误。请重试", - "xpack.observability.seriesEditor.actionsAriaContextLabel": "序列操作列表", - "xpack.observability.seriesEditor.clone": "序列重复", - "xpack.observability.seriesEditor.edit": "编辑序列", - "xpack.observability.seriesEditor.hide": "隐藏序列", - "xpack.observability.seriesEditor.popoverButtonLabel": "查看序列操作", - "xpack.observability.seriesEditor.sampleDocuments": "在 Discover 中查看事务", - "xpack.observability.seriesEditor.show": "显示序列", "xpack.observability.serviceGroupMaxServicesUiSettingDescription": "限制给定服务组中服务的数量", "xpack.observability.serviceGroupMaxServicesUiSettingName": "服务组中的最大服务数", "xpack.observability.slo.alerting.reasonDescription": "告警原因的简洁描述", @@ -25889,6 +25684,211 @@ "xpack.observability.ux.dashboard.webCoreVitals.help": "详细了解", "xpack.observability.ux.dashboard.webCoreVitals.helpAriaLabel": "帮助", "xpack.observability.ux.service.help": "选择流量最高的 RUM 服务", + "xpack.exploratoryView.expView.columns.label": "{sourceField} 的第 {percentileValue} 百分位", + "xpack.exploratoryView.expView.columns.operation.label": "{sourceField} 的 {operationType}", + "xpack.exploratoryView.expView.filterValueButton.negate": "不是 {value}", + "xpack.exploratoryView.expView.heading.addToCase.notification": "已成功将可视化添加到案例:{caseTitle}", + "xpack.exploratoryView.expView.lastUpdated.label": "上次更新时间:{updatedDate}", + "xpack.exploratoryView.expView.seriesEditor.selectReportMetric.noFieldData": "字段 {field} 无可用数据。", + "xpack.exploratoryView.filters.expanded.search": "搜索 {label}", + "xpack.exploratoryView.filters.label.wildcard": "{label} 通配符", + "xpack.exploratoryView.filters.searchResults": "{total} 项搜索结果", + "xpack.exploratoryView.missingReportDefinition": "缺少 {reportDefinition}", + "xpack.exploratoryView.noDataAvailable": "没有可用的 {dataType} 数据。", + "xpack.exploratoryView.textDefinitionField.placeholder.search": "搜索 {label}", + "xpack.exploratoryView.urlFilter.wildcard": "使用通配符 *{wildcard}*", + "xpack.exploratoryView.apply.label": "应用", + "xpack.exploratoryView.breakDownFilter.noBreakdown": "无细目", + "xpack.exploratoryView.breakDownFilter.unavailable": "步骤名称细目不可用于监测持续时间指标。使用步骤持续时间指标以按步骤名称细分。", + "xpack.exploratoryView.breakDownFilter.warning": "一次只能将细目应用于一个序列。", + "xpack.exploratoryView.alerts.alertStarted": "时间戳", + "xpack.exploratoryView.logs.logRateXAxisLabel": "时间戳", + "xpack.exploratoryView.logs.logRateYAxisLabel": "每分钟日志速率", + "xpack.exploratoryView.noBrushing": "按画笔选择缩放仅适用于时间序列图表。", + "xpack.exploratoryView.expView.addToCase": "添加到案例", + "xpack.exploratoryView.expView.alerts.category": "规则类别", + "xpack.exploratoryView.expView.alerts.name": "告警名称", + "xpack.exploratoryView.expView.alerts.status": "告警状态", + "xpack.exploratoryView.expView.avgDuration": "平均持续时间", + "xpack.exploratoryView.expView.chartTypes.label": "图表类型", + "xpack.exploratoryView.expView.complete": "已完成", + "xpack.exploratoryView.expView.dateRanger.endDate": "结束日期", + "xpack.exploratoryView.expView.dateRanger.startDate": "开始日期", + "xpack.exploratoryView.expView.errors": "错误", + "xpack.exploratoryView.expView.explore": "浏览", + "xpack.exploratoryView.expView.failedTests": "失败的测试", + "xpack.exploratoryView.expView.fieldLabels.agentHost": "代理主机", + "xpack.exploratoryView.expView.fieldLabels.agentType": "代理类型", + "xpack.exploratoryView.expView.fieldLabels.backend": "后端时间", + "xpack.exploratoryView.expView.fieldLabels.browserFamily": "浏览器系列", + "xpack.exploratoryView.expView.fieldLabels.browserVersion": "浏览器版本", + "xpack.exploratoryView.expView.fieldLabels.carrierLocation": "运营商位置", + "xpack.exploratoryView.expView.fieldLabels.carrierName": "运营商名称", + "xpack.exploratoryView.expView.fieldLabels.chooseField": "标签字段", + "xpack.exploratoryView.expView.fieldLabels.cls": "累计布局偏移", + "xpack.exploratoryView.expView.fieldLabels.connectionType": "连接类型", + "xpack.exploratoryView.expView.fieldLabels.coreWebVitals": "网站体验核心指标", + "xpack.exploratoryView.expView.fieldLabels.cpuUsage": "CPU 使用", + "xpack.exploratoryView.expView.fieldLabels.cpuUsage.docker": "Docker CPU 使用", + "xpack.exploratoryView.expView.fieldLabels.cpuUsage.k8sDocker": "K8s pod CPU 使用", + "xpack.exploratoryView.expView.fieldLabels.cpuUsage.system": "系统 CPU 使用", + "xpack.exploratoryView.expView.fieldLabels.dcl": "DOM 内容已加载", + "xpack.exploratoryView.expView.fieldLabels.device": "设备", + "xpack.exploratoryView.expView.fieldLabels.deviceDistribution": "设备分布", + "xpack.exploratoryView.expView.fieldLabels.deviceModel": "设备型号", + "xpack.exploratoryView.expView.fieldLabels.downPings": "关闭 Ping", + "xpack.exploratoryView.expView.fieldLabels.environment": "环境", + "xpack.exploratoryView.expView.fieldLabels.eventDataset": "数据集", + "xpack.exploratoryView.expView.fieldLabels.fcp": "首次内容绘制", + "xpack.exploratoryView.expView.fieldLabels.fid": "首次输入延迟", + "xpack.exploratoryView.expView.fieldLabels.heatMap": "热图", + "xpack.exploratoryView.expView.fieldLabels.hostName": "主机名", + "xpack.exploratoryView.expView.fieldLabels.hostOS": "主机 OS", + "xpack.exploratoryView.expView.fieldLabels.kpi": "KPI", + "xpack.exploratoryView.expView.fieldLabels.kpiOverTime": "时移 KPI", + "xpack.exploratoryView.expView.fieldLabels.labels": "标签", + "xpack.exploratoryView.expView.fieldLabels.lcp": "最大内容绘制", + "xpack.exploratoryView.expView.fieldLabels.location": "位置", + "xpack.exploratoryView.expView.fieldLabels.logRate": "日志速率", + "xpack.exploratoryView.expView.fieldLabels.memoryUsage": "系统内存使用", + "xpack.exploratoryView.expView.fieldLabels.message": "消息", + "xpack.exploratoryView.expView.fieldLabels.metric": "指标", + "xpack.exploratoryView.expView.fieldLabels.mobile.memoryUsage": "系统内存使用", + "xpack.exploratoryView.expView.fieldLabels.mobileApp": "移动应用", + "xpack.exploratoryView.expView.fieldLabels.mobileResponse": "移动响应", + "xpack.exploratoryView.expView.fieldLabels.monitorDurationLabel": "监测持续时间", + "xpack.exploratoryView.expView.fieldLabels.monitorId": "监测 ID", + "xpack.exploratoryView.expView.fieldLabels.monitorName": "监测名称", + "xpack.exploratoryView.expView.fieldLabels.monitorStatus": "监测状态", + "xpack.exploratoryView.expView.fieldLabels.monitorType": "监测类型", + "xpack.exploratoryView.expView.fieldLabels.networkTimings": "网络计时", + "xpack.exploratoryView.expView.fieldLabels.numberOfDevices": "设备数量", + "xpack.exploratoryView.expView.fieldLabels.obsLocation": "观察者位置", + "xpack.exploratoryView.expView.fieldLabels.onload": "文档完成 (onLoad)", + "xpack.exploratoryView.expView.fieldLabels.os": "操作系统", + "xpack.exploratoryView.expView.fieldLabels.osPlatform": "OS 平台", + "xpack.exploratoryView.expView.fieldLabels.pageLoadTime": "页面加载时间", + "xpack.exploratoryView.expView.fieldLabels.pagesLoaded": "已加载页面", + "xpack.exploratoryView.expView.fieldLabels.pageViews": "页面查看次数", + "xpack.exploratoryView.expView.fieldLabels.performanceDistribution": "性能分布", + "xpack.exploratoryView.expView.fieldLabels.pings": "Ping", + "xpack.exploratoryView.expView.fieldLabels.port": "端口", + "xpack.exploratoryView.expView.fieldLabels.requestMethod": "请求方法", + "xpack.exploratoryView.expView.fieldLabels.responseLatency": "延迟", + "xpack.exploratoryView.expView.fieldLabels.serviceName": "服务名称", + "xpack.exploratoryView.expView.fieldLabels.serviceType": "服务类型", + "xpack.exploratoryView.expView.fieldLabels.serviceVersion": "服务版本", + "xpack.exploratoryView.expView.fieldLabels.singleMetric": "单一指标", + "xpack.exploratoryView.expView.fieldLabels.stepDurationLabel": "步骤持续时间", + "xpack.exploratoryView.expView.fieldLabels.stepNameLabel": "步骤名称", + "xpack.exploratoryView.expView.fieldLabels.tags": "标签", + "xpack.exploratoryView.expView.fieldLabels.tbt": "阻止总时间", + "xpack.exploratoryView.expView.fieldLabels.transactionPerMinute": "吞吐量", + "xpack.exploratoryView.expView.fieldLabels.upPings": "运行 Ping", + "xpack.exploratoryView.expView.fieldLabels.url": "URL", + "xpack.exploratoryView.expView.fieldLabels.webApplication": "Web 应用程序", + "xpack.exploratoryView.expView.heading.addToCase": "添加到案例", + "xpack.exploratoryView.expView.heading.addToCase.notification.error": "未能将可视化添加到所选案例。", + "xpack.exploratoryView.expView.heading.addToCase.notification.viewCase": "查看案例", + "xpack.exploratoryView.expView.heading.embed": "嵌入 <></>", + "xpack.exploratoryView.expView.heading.embedTitle": "嵌入浏览视图(仅用于开发的功能)", + "xpack.exploratoryView.expView.heading.label": "浏览数据", + "xpack.exploratoryView.expView.heading.openInLens": "在 Lens 中打开", + "xpack.exploratoryView.expView.heading.saveLensVisualization": "保存", + "xpack.exploratoryView.expView.openInLens": "在 Lens 中打开", + "xpack.exploratoryView.expView.operationType.25thPercentile": "第 25 个百分位", + "xpack.exploratoryView.expView.operationType.75thPercentile": "第 75 个百分位", + "xpack.exploratoryView.expView.operationType.90thPercentile": "第 90 个百分位", + "xpack.exploratoryView.expView.operationType.95thPercentile": "第 95 个百分位", + "xpack.exploratoryView.expView.operationType.99thPercentile": "第 99 个百分位", + "xpack.exploratoryView.expView.operationType.average": "平均值", + "xpack.exploratoryView.expView.operationType.lastValue": "最后值", + "xpack.exploratoryView.expView.operationType.max": "最大值", + "xpack.exploratoryView.expView.operationType.median": "中值", + "xpack.exploratoryView.expView.operationType.min": "最小值", + "xpack.exploratoryView.expView.operationType.sum": "求和", + "xpack.exploratoryView.expView.operationType.uniqueCount": "唯一计数", + "xpack.exploratoryView.expView.reportType.selectDataType": "选择数据类型以创建可视化。", + "xpack.exploratoryView.expView.reportType.selectLabel": "选择报告类型", + "xpack.exploratoryView.expView.save": "保存可视化", + "xpack.exploratoryView.expView.seriesBuilder.accordion.label": "切换序列信息", + "xpack.exploratoryView.expView.seriesBuilder.addSeries": "添加序列", + "xpack.exploratoryView.expView.seriesBuilder.addSeries.limitation": "只能添加一个此报告类型的序列。", + "xpack.exploratoryView.expView.seriesBuilder.addSeries.selectReportType": "请先选择报告类型,然后再添加序列。", + "xpack.exploratoryView.expView.seriesBuilder.apply": "应用更改", + "xpack.exploratoryView.expView.seriesBuilder.breakdownBy": "细分依据", + "xpack.exploratoryView.expView.seriesBuilder.creationContext": "显示自", + "xpack.exploratoryView.expView.seriesBuilder.creationTime": "已创建图表", + "xpack.exploratoryView.expView.seriesBuilder.date": "日期", + "xpack.exploratoryView.expView.seriesBuilder.emptyReportDefinition": "选择报告定义以创建可视化。", + "xpack.exploratoryView.expView.seriesBuilder.emptyview": "没有可显示的内容。", + "xpack.exploratoryView.expView.seriesBuilder.labelField": "选择标签字段", + "xpack.exploratoryView.expView.seriesBuilder.loadingView": "正在加载视图......", + "xpack.exploratoryView.expView.seriesBuilder.operation": "操作", + "xpack.exploratoryView.expView.seriesBuilder.reportType": "报告类型", + "xpack.exploratoryView.expView.seriesBuilder.reportType.aria": "此选择允许您选择希望创建的报告类型", + "xpack.exploratoryView.expView.seriesBuilder.selectFilters": "筛选", + "xpack.exploratoryView.expView.seriesBuilder.selectReportType": "未选择任何报告类型", + "xpack.exploratoryView.expView.seriesBuilder.selectReportType.empty": "选择报告类型以创建可视化。", + "xpack.exploratoryView.expView.seriesEditor.clearFilter": "清除筛选", + "xpack.exploratoryView.expView.seriesEditor.editChartSeriesLabel": "编辑序列的图表类型", + "xpack.exploratoryView.expView.seriesEditor.editName": "编辑名称", + "xpack.exploratoryView.expView.seriesEditor.noData": "没有可用数据", + "xpack.exploratoryView.expView.seriesEditor.noPermissions": "无法创建数据视图。您没有所需权限,请与管理员联系。", + "xpack.exploratoryView.expView.seriesEditor.notFound": "未找到任何序列。请添加序列。", + "xpack.exploratoryView.expView.seriesEditor.removeReportMetric": "移除报告指标", + "xpack.exploratoryView.expView.seriesEditor.removeSeries": "移除序列", + "xpack.exploratoryView.expView.seriesEditor.removeSeriesDisabled": "无法移除主要序列。请先移除下面的所有序列,然后才能移除此项。", + "xpack.exploratoryView.expView.seriesEditor.reportMetricTooltip": "报告指标", + "xpack.exploratoryView.expView.seriesEditor.selectReportMetric": "选择报告指标", + "xpack.exploratoryView.expView.seriesEditor.seriesName": "序列名称", + "xpack.exploratoryView.expView.stepDuration": "步骤总持续时间", + "xpack.exploratoryView.expView.synthetics.blocked": "已阻止", + "xpack.exploratoryView.expView.synthetics.connect": "连接", + "xpack.exploratoryView.expView.synthetics.dns": "DNS", + "xpack.exploratoryView.expView.synthetics.receive": "接收", + "xpack.exploratoryView.expView.synthetics.send": "发送", + "xpack.exploratoryView.expView.synthetics.ssl": "SSL", + "xpack.exploratoryView.expView.synthetics.total": "合计", + "xpack.exploratoryView.expView.synthetics.wait": "等待", + "xpack.exploratoryView.expView.totalRuns": "总运行次数", + "xpack.exploratoryView.filters.expanded.labels.backTo": "返回到标签", + "xpack.exploratoryView.filters.expanded.labels.fields": "标签字段", + "xpack.exploratoryView.filters.expanded.labels.label": "标签", + "xpack.exploratoryView.filters.expanded.noFilter": "未找到任何筛选。", + "xpack.exploratoryView.filters.filterByUrl": "按 URL 筛选", + "xpack.exploratoryView.filters.select": "选择", + "xpack.exploratoryView.filters.topPages": "排名靠前页面", + "xpack.exploratoryView.filters.url": "URL", + "xpack.exploratoryView.filters.url.loadingResults": "正在加载结果", + "xpack.exploratoryView.filters.url.noResults": "没有可用结果", + "xpack.exploratoryView.overview": "浏览数据", + "xpack.exploratoryView.alertsLabel": "告警", + "xpack.exploratoryView.editSeriesColor": "编辑序列的颜色", + "xpack.exploratoryView.hideChart": "隐藏图表", + "xpack.exploratoryView.lensDisabled": "Lens 应用不可用,请启用 Lens 以使用浏览视图。", + "xpack.exploratoryView.logsLabel": "日志", + "xpack.exploratoryView.metricsLabel": "指标", + "xpack.exploratoryView.missingDataType": "缺少数据类型", + "xpack.exploratoryView.missingReportMetric": "缺少报告指标", + "xpack.exploratoryView.mobileExperienceLabel": "移动体验", + "xpack.exploratoryView.noData": "无数据", + "xpack.exploratoryView.pickColor": "选取颜色", + "xpack.exploratoryView.preview": "预览", + "xpack.exploratoryView.refresh": "刷新", + "xpack.exploratoryView.selectDataType": "选择数据类型", + "xpack.exploratoryView.selectDataTypeTooltip": "无法编辑数据类型。", + "xpack.exploratoryView.showChart": "显示图表", + "xpack.exploratoryView.syntheticsLabel": "Synthetics 监测", + "xpack.exploratoryView.uxLabel": "用户体验 (RUM)", + "xpack.exploratoryView.search.url.close": "关闭", + "xpack.exploratoryView.seriesEditor.actionsAriaContextLabel": "序列操作列表", + "xpack.exploratoryView.seriesEditor.clone": "序列重复", + "xpack.exploratoryView.seriesEditor.edit": "编辑序列", + "xpack.exploratoryView.seriesEditor.hide": "隐藏序列", + "xpack.exploratoryView.seriesEditor.popoverButtonLabel": "查看序列操作", + "xpack.exploratoryView.seriesEditor.sampleDocuments": "在 Discover 中查看事务", + "xpack.exploratoryView.seriesEditor.show": "显示序列", "xpack.osquery.action.missingPrivileges": "要访问此页面,请联系管理员获取 {osquery} Kibana 权限。", "xpack.osquery.agentPolicy.confirmModalCalloutDescription": "Fleet 检测到您的部分代理已在使用选定{agentPolicyCount, plural, other {代理策略}}。由于此操作,Fleet 会将更新部署到所有使用此{agentPolicyCount, plural, other {代理策略}}的代理。", "xpack.osquery.agentPolicy.confirmModalCalloutTitle": "此操作将更新 {agentCount, plural, other {# 个代理}}",