From ba6335473fcf2f4bb80167ceed87b9e1a57a537e Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Tue, 16 Nov 2021 10:20:01 +0100 Subject: [PATCH 001/148] [Reporting] Add log level to config (#118319) * added critical log level to unused reporting config * use warning instead of critical Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- x-pack/plugins/reporting/server/config/index.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/reporting/server/config/index.ts b/x-pack/plugins/reporting/server/config/index.ts index fa836fd47cde3..711e930484e01 100644 --- a/x-pack/plugins/reporting/server/config/index.ts +++ b/x-pack/plugins/reporting/server/config/index.ts @@ -18,10 +18,10 @@ export const config: PluginConfigDescriptor = { exposeToBrowser: { poll: true, roles: true }, schema: ConfigSchema, deprecations: ({ unused }) => [ - unused('capture.browser.chromium.maxScreenshotDimension'), // unused since 7.8 - unused('poll.jobCompletionNotifier.intervalErrorMultiplier'), // unused since 7.10 - unused('poll.jobsRefresh.intervalErrorMultiplier'), // unused since 7.10 - unused('capture.viewport'), // deprecated as unused since 7.16 + unused('capture.browser.chromium.maxScreenshotDimension', { level: 'warning' }), // unused since 7.8 + unused('poll.jobCompletionNotifier.intervalErrorMultiplier', { level: 'warning' }), // unused since 7.10 + unused('poll.jobsRefresh.intervalErrorMultiplier', { level: 'warning' }), // unused since 7.10 + unused('capture.viewport', { level: 'warning' }), // deprecated as unused since 7.16 (settings, fromPath, addDeprecation) => { const reporting = get(settings, fromPath); if (reporting?.roles?.enabled !== false) { From aeafd037df529417067f7f087af3c0d7672be08c Mon Sep 17 00:00:00 2001 From: Marco Vettorello Date: Tue, 16 Nov 2021 11:04:23 +0100 Subject: [PATCH 002/148] [charts] Disable Lens/Visualize axis label orientation with multilayer time axis (#117828) --- .../category_axis_panel.test.tsx.snap | 1 + .../__snapshots__/index.test.tsx.snap | 1 + .../__snapshots__/label_options.test.tsx.snap | 65 +++++++++++-------- .../metrics_axes/category_axis_panel.test.tsx | 14 ++++ .../metrics_axes/category_axis_panel.tsx | 9 ++- .../options/metrics_axes/index.test.tsx | 5 ++ .../components/options/metrics_axes/index.tsx | 20 +++++- .../options/metrics_axes/label_options.tsx | 57 ++++++++++------ .../lens/public/xy_visualization/index.ts | 6 +- .../xy_visualization/to_expression.test.ts | 1 + .../xy_visualization/visualization.test.ts | 1 + .../public/xy_visualization/visualization.tsx | 4 +- .../xy_config_panel/axis_settings_popover.tsx | 59 +++++++++++------ .../xy_config_panel/index.tsx | 31 ++++++++- .../xy_visualization/xy_suggestions.test.ts | 1 + 15 files changed, 199 insertions(+), 76 deletions(-) diff --git a/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/__snapshots__/category_axis_panel.test.tsx.snap b/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/__snapshots__/category_axis_panel.test.tsx.snap index bc66c1940ac72..0f3b0e8ef5576 100644 --- a/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/__snapshots__/category_axis_panel.test.tsx.snap +++ b/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/__snapshots__/category_axis_panel.test.tsx.snap @@ -61,6 +61,7 @@ exports[`CategoryAxisPanel component should init with the default set of props 1 "truncate": 0, } } + disableSingleLayerAxisControls={false} setAxisLabel={[Function]} /> diff --git a/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/__snapshots__/index.test.tsx.snap b/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/__snapshots__/index.test.tsx.snap index 05e2532073eaf..620e361946443 100644 --- a/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/__snapshots__/index.test.tsx.snap +++ b/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/__snapshots__/index.test.tsx.snap @@ -154,6 +154,7 @@ exports[`MetricsAxisOptions component should init with the default set of props } onPositionChanged={[Function]} setCategoryAxis={[Function]} + useMultiLayerAxis={false} /> `; diff --git a/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/__snapshots__/label_options.test.tsx.snap b/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/__snapshots__/label_options.test.tsx.snap index 175ec043cdbea..d6e95dfdb87b9 100644 --- a/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/__snapshots__/label_options.test.tsx.snap +++ b/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/__snapshots__/label_options.test.tsx.snap @@ -27,7 +27,6 @@ exports[`LabelOptions component should init with the default set of props 1`] = /> - + + + - + + + diff --git a/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/category_axis_panel.test.tsx b/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/category_axis_panel.test.tsx index 066f053d4e186..9d18200ae7eb9 100644 --- a/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/category_axis_panel.test.tsx +++ b/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/category_axis_panel.test.tsx @@ -11,6 +11,7 @@ import { shallow } from 'enzyme'; import { CategoryAxisPanel, CategoryAxisPanelProps } from './category_axis_panel'; import { CategoryAxis } from '../../../../types'; import { LabelOptions } from './label_options'; +import { TruncateLabelsOption } from '../../common'; import { categoryAxis } from './mocks'; import { Position } from '@elastic/charts'; @@ -29,6 +30,7 @@ describe('CategoryAxisPanel component', () => { axis, onPositionChanged, setCategoryAxis, + useMultiLayerAxis: false, }; }); @@ -55,4 +57,16 @@ describe('CategoryAxisPanel component', () => { expect(setCategoryAxis).toHaveBeenLastCalledWith({ ...axis, position: value }); expect(onPositionChanged).toBeCalledWith(value); }); + + it('should disable label options with multilayer axis', () => { + const comp = shallow(); + const labelOptions = comp.find(LabelOptions).dive(); + const rotateLabelsOption = labelOptions.find({ paramName: 'rotate' }); + const filterLabelOption = labelOptions.find({ paramName: 'filter' }); + const truncateLabelOption = labelOptions.find(TruncateLabelsOption); + + expect(rotateLabelsOption.prop('disabled')).toBe(true); + expect(filterLabelOption.prop('disabled')).toBe(true); + expect(truncateLabelOption.prop('disabled')).toBe(true); + }); }); diff --git a/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/category_axis_panel.tsx b/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/category_axis_panel.tsx index ee5cc950ff66b..c3d1d2dcfee4d 100644 --- a/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/category_axis_panel.tsx +++ b/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/category_axis_panel.tsx @@ -25,9 +25,15 @@ export interface CategoryAxisPanelProps { axis: CategoryAxis; onPositionChanged: (position: Position) => void; setCategoryAxis: (value: CategoryAxis) => void; + useMultiLayerAxis: boolean; } -function CategoryAxisPanel({ axis, onPositionChanged, setCategoryAxis }: CategoryAxisPanelProps) { +function CategoryAxisPanel({ + axis, + onPositionChanged, + setCategoryAxis, + useMultiLayerAxis, +}: CategoryAxisPanelProps) { const setAxis = useCallback( (paramName: T, value: CategoryAxis[T]) => { const updatedAxis = { @@ -95,6 +101,7 @@ function CategoryAxisPanel({ axis, onPositionChanged, setCategoryAxis }: Categor axisLabels={axis.labels} axisFilterCheckboxName={`xAxisFilterLabelsCheckbox${axis.id}`} setAxisLabel={setAxisLabel} + disableSingleLayerAxisControls={useMultiLayerAxis} /> )} diff --git a/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/index.test.tsx b/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/index.test.tsx index 4996018d21120..6a32b1f75016b 100644 --- a/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/index.test.tsx +++ b/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/index.test.tsx @@ -31,6 +31,11 @@ jest.mock('./category_axis_panel', () => ({ jest.mock('./value_axes_panel', () => ({ ValueAxesPanel: () => 'ValueAxesPanel', })); +jest.mock('../../../../services', () => ({ + getUISettings: jest.fn(() => ({ + get: jest.fn((key: string, defaultOverride?: unknown) => defaultOverride), + })), +})); const SERIES_PARAMS = 'seriesParams'; const VALUE_AXES = 'valueAxes'; diff --git a/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/index.tsx b/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/index.tsx index dc7e13634d6d6..0397eec7b2c73 100644 --- a/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/index.tsx +++ b/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/index.tsx @@ -10,8 +10,10 @@ import React, { useState, useEffect, useCallback } from 'react'; import { cloneDeep, get } from 'lodash'; import { EuiSpacer } from '@elastic/eui'; +import { Position } from '@elastic/charts'; -import { IAggConfig } from '../../../../../../../data/public'; +import { BUCKET_TYPES, IAggConfig } from '../../../../../../../data/public'; +import { getUISettings } from '../../../../services'; import { VisParams, ValueAxis, SeriesParam, CategoryAxis } from '../../../../types'; import { ValidationVisOptionsProps } from '../../common'; @@ -27,6 +29,7 @@ import { mapPositionOpposingOpposite, } from './utils'; import { getSeriesParams } from '../../../../utils/get_series_params'; +import { LEGACY_TIME_AXIS } from '../../../../../../../charts/common'; export type SetParamByIndex =

( axesName: 'valueAxes' | 'seriesParams', @@ -287,6 +290,20 @@ function MetricsAxisOptions(props: ValidationVisOptionsProps) { updateAxisTitle(updatedSeries); }, [firstValueAxesId, setValue, stateParams.seriesParams, updateAxisTitle, aggs, schemaName]); + const isTimeViz = aggs.aggs.some( + (agg) => + agg.schema === 'segment' && agg.enabled && agg.type?.name === BUCKET_TYPES.DATE_HISTOGRAM + ); + const xAxisIsHorizontal = + stateParams.categoryAxes[0].position === Position.Bottom || + stateParams.categoryAxes[0].position === Position.Top; + const useLegacyTimeAxis = getUISettings().get(LEGACY_TIME_AXIS, false); + const linearOrStackedBars = stateParams.seriesParams.every( + ({ mode, type }) => type !== 'histogram' || (type === 'histogram' && mode === 'stacked') + ); + const useMultiLayerAxis = + xAxisIsHorizontal && isTimeViz && !useLegacyTimeAxis && linearOrStackedBars; + return isTabSelected ? ( <> ) { axis={stateParams.categoryAxes[0]} onPositionChanged={onCategoryAxisPositionChanged} setCategoryAxis={setCategoryAxis} + useMultiLayerAxis={useMultiLayerAxis} /> ) : null; diff --git a/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/label_options.tsx b/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/label_options.tsx index ef48d8b6d7880..ed7ac178d3d8b 100644 --- a/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/label_options.tsx +++ b/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/label_options.tsx @@ -8,7 +8,7 @@ import React, { useCallback, useMemo } from 'react'; -import { EuiTitle, EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui'; +import { EuiTitle, EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiToolTip } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; @@ -23,9 +23,15 @@ export interface LabelOptionsProps { axisLabels: Labels; axisFilterCheckboxName: string; setAxisLabel: SetAxisLabel; + disableSingleLayerAxisControls?: boolean; } -function LabelOptions({ axisLabels, axisFilterCheckboxName, setAxisLabel }: LabelOptionsProps) { +function LabelOptions({ + axisLabels, + axisFilterCheckboxName, + setAxisLabel, + disableSingleLayerAxisControls, +}: LabelOptionsProps) { const setAxisLabelRotate = useCallback( (paramName: 'rotate', value: Labels['rotate']) => { setAxisLabel(paramName, Number(value)); @@ -34,6 +40,15 @@ function LabelOptions({ axisLabels, axisFilterCheckboxName, setAxisLabel }: Labe ); const rotateOptions = useMemo(getRotateOptions, []); + const multilayerAxisTooltipText = disableSingleLayerAxisControls + ? i18n.translate( + 'visTypeXy.controls.pointSeries.categoryAxis.axisLabelsOptionsMultilayer.disabled', + { + defaultMessage: 'This option can be configured only with non-time-based axes', + } + ) + : undefined; + const axisLabelControlDisabled = !axisLabels.show || disableSingleLayerAxisControls; return ( <> @@ -56,39 +71,43 @@ function LabelOptions({ axisLabels, axisFilterCheckboxName, setAxisLabel }: Labe value={axisLabels.show} setValue={setAxisLabel} /> - - + + + - + + + diff --git a/x-pack/plugins/lens/public/xy_visualization/index.ts b/x-pack/plugins/lens/public/xy_visualization/index.ts index d3d461e8f8741..8ac9076919dd9 100644 --- a/x-pack/plugins/lens/public/xy_visualization/index.ts +++ b/x-pack/plugins/lens/public/xy_visualization/index.ts @@ -30,7 +30,7 @@ export class XyVisualization { const { getXyChartRenderer, getXyVisualization } = await import('../async_services'); const [, { charts, fieldFormats }] = await core.getStartServices(); const palettes = await charts.palettes.getPalettes(); - + const useLegacyTimeAxis = core.uiSettings.get(LEGACY_TIME_AXIS); expressions.registerRenderer( getXyChartRenderer({ formatFactory, @@ -38,10 +38,10 @@ export class XyVisualization { chartsActiveCursorService: charts.activeCursor, paletteService: palettes, timeZone: getTimeZone(core.uiSettings), - useLegacyTimeAxis: core.uiSettings.get(LEGACY_TIME_AXIS), + useLegacyTimeAxis, }) ); - return getXyVisualization({ paletteService: palettes, fieldFormats }); + return getXyVisualization({ paletteService: palettes, fieldFormats, useLegacyTimeAxis }); }); } } diff --git a/x-pack/plugins/lens/public/xy_visualization/to_expression.test.ts b/x-pack/plugins/lens/public/xy_visualization/to_expression.test.ts index 7d1bd64abe906..033e324a5d02d 100644 --- a/x-pack/plugins/lens/public/xy_visualization/to_expression.test.ts +++ b/x-pack/plugins/lens/public/xy_visualization/to_expression.test.ts @@ -19,6 +19,7 @@ describe('#toExpression', () => { const xyVisualization = getXyVisualization({ paletteService: chartPluginMock.createPaletteRegistry(), fieldFormats: fieldFormatsServiceMock.createStartContract(), + useLegacyTimeAxis: false, }); let mockDatasource: ReturnType; let frame: ReturnType; diff --git a/x-pack/plugins/lens/public/xy_visualization/visualization.test.ts b/x-pack/plugins/lens/public/xy_visualization/visualization.test.ts index 0c3fa21708263..029cfe8ecbe40 100644 --- a/x-pack/plugins/lens/public/xy_visualization/visualization.test.ts +++ b/x-pack/plugins/lens/public/xy_visualization/visualization.test.ts @@ -40,6 +40,7 @@ const fieldFormatsMock = fieldFormatsServiceMock.createStartContract(); const xyVisualization = getXyVisualization({ paletteService: paletteServiceMock, fieldFormats: fieldFormatsMock, + useLegacyTimeAxis: false, }); describe('xy_visualization', () => { diff --git a/x-pack/plugins/lens/public/xy_visualization/visualization.tsx b/x-pack/plugins/lens/public/xy_visualization/visualization.tsx index 2f3ec7e2723d4..0ba74f4b8bb3a 100644 --- a/x-pack/plugins/lens/public/xy_visualization/visualization.tsx +++ b/x-pack/plugins/lens/public/xy_visualization/visualization.tsx @@ -98,9 +98,11 @@ function getDescription(state?: State) { export const getXyVisualization = ({ paletteService, fieldFormats, + useLegacyTimeAxis, }: { paletteService: PaletteRegistry; fieldFormats: FieldFormatsStart; + useLegacyTimeAxis: boolean; }): Visualization => ({ id: 'lnsXY', @@ -573,7 +575,7 @@ export const getXyVisualization = ({ renderToolbar(domElement, props) { render( - + , domElement ); diff --git a/x-pack/plugins/lens/public/xy_visualization/xy_config_panel/axis_settings_popover.tsx b/x-pack/plugins/lens/public/xy_visualization/xy_config_panel/axis_settings_popover.tsx index e0a30bdb2c511..4ce1667ee1008 100644 --- a/x-pack/plugins/lens/public/xy_visualization/xy_config_panel/axis_settings_popover.tsx +++ b/x-pack/plugins/lens/public/xy_visualization/xy_config_panel/axis_settings_popover.tsx @@ -21,7 +21,7 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { XYLayerConfig, AxesSettingsConfig, AxisExtentConfig } from '../../../common/expressions'; -import { ToolbarPopover, useDebouncedValue } from '../../shared_components'; +import { ToolbarPopover, useDebouncedValue, TooltipWrapper } from '../../shared_components'; import { isHorizontalChart } from '../state_helpers'; import { EuiIconAxisBottom } from '../../assets/axis_bottom'; import { EuiIconAxisLeft } from '../../assets/axis_left'; @@ -104,6 +104,11 @@ export interface AxisSettingsPopoverProps { hasBarOrAreaOnAxis: boolean; hasPercentageAxis: boolean; dataBounds?: { min: number; max: number }; + + /** + * Toggle the visibility of legacy axis settings when using the new multilayer time axis + */ + useMultilayerTimeAxis?: boolean; } const popoverConfig = ( @@ -210,6 +215,7 @@ export const AxisSettingsPopover: React.FunctionComponent { const isHorizontal = layers?.length ? isHorizontalChart(layers) : false; const config = popoverConfig(axis, isHorizontal); @@ -314,30 +320,41 @@ export const AxisSettingsPopover: React.FunctionComponent - - value === orientation)!.id} - onChange={(optionId) => { - const newOrientation = axisOrientationOptions.find(({ id }) => id === optionId)!.value; - setOrientation(axis, newOrientation); - }} - /> - + > + value === orientation)!.id} + onChange={(optionId) => { + const newOrientation = axisOrientationOptions.find( + ({ id }) => id === optionId + )!.value; + setOrientation(axis, newOrientation); + }} + /> + + {setEndzoneVisibility && ( <> diff --git a/x-pack/plugins/lens/public/xy_visualization/xy_config_panel/index.tsx b/x-pack/plugins/lens/public/xy_visualization/xy_config_panel/index.tsx index cef4a5f01ce8a..6a43be64ec1d4 100644 --- a/x-pack/plugins/lens/public/xy_visualization/xy_config_panel/index.tsx +++ b/x-pack/plugins/lens/public/xy_visualization/xy_config_panel/index.tsx @@ -176,8 +176,10 @@ function hasPercentageAxis(axisGroups: GroupsConfiguration, groupId: string, sta ); } -export const XyToolbar = memo(function XyToolbar(props: VisualizationToolbarProps) { - const { state, setState, frame } = props; +export const XyToolbar = memo(function XyToolbar( + props: VisualizationToolbarProps & { useLegacyTimeAxis?: boolean } +) { + const { state, setState, frame, useLegacyTimeAxis } = props; const shouldRotate = state?.layers.length ? isHorizontalChart(state.layers) : false; const axisGroups = getAxesConfiguration(state?.layers, shouldRotate, frame.activeData); @@ -327,6 +329,28 @@ export const XyToolbar = memo(function XyToolbar(props: VisualizationToolbarProp [setState, state] ); + const filteredBarLayers = state?.layers.filter((layer) => layer.seriesType.includes('bar')); + const chartHasMoreThanOneBarSeries = + filteredBarLayers.length > 1 || + filteredBarLayers.some((layer) => layer.accessors.length > 1 || layer.splitAccessor); + + const isTimeHistogramModeEnabled = state?.layers.some( + ({ xAccessor, layerId, seriesType, splitAccessor }) => { + if (!xAccessor) { + return false; + } + const xAccessorOp = props.frame.datasourceLayers[layerId].getOperationForColumnId(xAccessor); + return ( + getScaleType(xAccessorOp, ScaleType.Linear) === ScaleType.Time && + xAccessorOp?.isBucketed && + (seriesType.includes('stacked') || !splitAccessor) && + (seriesType.includes('stacked') || + !seriesType.includes('bar') || + !chartHasMoreThanOneBarSeries) + ); + } + ); + return ( @@ -487,6 +511,9 @@ export const XyToolbar = memo(function XyToolbar(props: VisualizationToolbarProp setEndzoneVisibility={onChangeEndzoneVisiblity} hasBarOrAreaOnAxis={false} hasPercentageAxis={false} + useMultilayerTimeAxis={ + isTimeHistogramModeEnabled && !useLegacyTimeAxis && !shouldRotate + } /> { From 8873a48277b6971aec8b930b53fd8f2b79e7c02a Mon Sep 17 00:00:00 2001 From: Maja Grubic Date: Tue, 16 Nov 2021 11:06:43 +0100 Subject: [PATCH 003/148] [Discover] Add EuiErrorBoundary to catch errors in the functionals (#117976) * [Discover] Add error boundary to cath errors in functionals * Fix invalid import * Move to router Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../public/application/discover_router.tsx | 49 ++++++++++--------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/src/plugins/discover/public/application/discover_router.tsx b/src/plugins/discover/public/application/discover_router.tsx index 6f88c28b52bf9..66ad0cccd03c7 100644 --- a/src/plugins/discover/public/application/discover_router.tsx +++ b/src/plugins/discover/public/application/discover_router.tsx @@ -9,6 +9,7 @@ import { Redirect, Route, Router, Switch } from 'react-router-dom'; import React from 'react'; import { History } from 'history'; +import { EuiErrorBoundary } from '@elastic/eui'; import { KibanaContextProvider } from '../../../kibana_react/public'; import { ContextAppRoute } from './context'; import { SingleDocRoute } from './doc'; @@ -25,29 +26,31 @@ export const discoverRouter = (services: DiscoverServices, history: History) => return ( - - - } - /> - ( - - )} - /> - } - /> - } /> - } /> - - - + + + + } + /> + ( + + )} + /> + } + /> + } /> + } /> + + + + ); }; From 809bdad9e8b5bc570f4cd4911350cf171433fc6b Mon Sep 17 00:00:00 2001 From: Oliver Gupte Date: Tue, 16 Nov 2021 05:12:45 -0500 Subject: [PATCH 004/148] [APM] Fixes isntructions for the APM integration tutorial (#118256) (#118645) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../home/common/instruction_variant.ts | 4 +- .../tutorial_fleet_instructions/index.tsx | 56 ++++++++++++------- .../apm/server/tutorial/envs/on_prem.ts | 48 ++++++++-------- 3 files changed, 63 insertions(+), 45 deletions(-) diff --git a/src/plugins/home/common/instruction_variant.ts b/src/plugins/home/common/instruction_variant.ts index 66c841cdc8b56..f19aa7849586b 100644 --- a/src/plugins/home/common/instruction_variant.ts +++ b/src/plugins/home/common/instruction_variant.ts @@ -32,8 +32,8 @@ export const INSTRUCTION_VARIANT = { const DISPLAY_MAP = { [INSTRUCTION_VARIANT.ESC]: 'Elastic Cloud', [INSTRUCTION_VARIANT.OSX]: 'macOS', - [INSTRUCTION_VARIANT.DEB]: 'DEB', - [INSTRUCTION_VARIANT.RPM]: 'RPM', + [INSTRUCTION_VARIANT.DEB]: 'Linux DEB', + [INSTRUCTION_VARIANT.RPM]: 'Linux RPM', [INSTRUCTION_VARIANT.DOCKER]: 'Docker', [INSTRUCTION_VARIANT.WINDOWS]: 'Windows', [INSTRUCTION_VARIANT.NODE]: 'Node.js', diff --git a/x-pack/plugins/apm/public/tutorial/tutorial_fleet_instructions/index.tsx b/x-pack/plugins/apm/public/tutorial/tutorial_fleet_instructions/index.tsx index f0d6dc72b72a5..7df52b20376b0 100644 --- a/x-pack/plugins/apm/public/tutorial/tutorial_fleet_instructions/index.tsx +++ b/x-pack/plugins/apm/public/tutorial/tutorial_fleet_instructions/index.tsx @@ -4,13 +4,17 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { EuiButton } from '@elastic/eui'; -import { EuiFlexItem } from '@elastic/eui'; -import { EuiFlexGroup } from '@elastic/eui'; -import { EuiPanel } from '@elastic/eui'; -import { EuiCard } from '@elastic/eui'; -import { EuiImage } from '@elastic/eui'; -import { EuiLoadingSpinner } from '@elastic/eui'; +import { + EuiButton, + EuiFlexItem, + EuiFlexGroup, + EuiPanel, + EuiCard, + EuiImage, + EuiLoadingSpinner, + EuiText, + EuiSpacer, +} from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { HttpStart } from 'kibana/public'; import React, { useEffect, useState } from 'react'; @@ -90,18 +94,32 @@ function TutorialFleetInstructions({ http, basePath, isDarkTheme }: Props) { } )} footer={ - - {i18n.translate( - 'xpack.apm.tutorial.apmServer.fleet.apmIntegration.button', - { - defaultMessage: 'APM integration', - } - )} - + <> + + {i18n.translate( + 'xpack.apm.tutorial.apmServer.fleet.apmIntegration.button', + { + defaultMessage: 'APM integration', + } + )} + + + +

+ {i18n.translate( + 'xpack.apm.tutorial.apmServer.fleet.apmIntegration.description', + { + defaultMessage: + 'Fleet allows you to centrally manage Elastic Agents running the APM integration. The default option is to install a Fleet Server on a dedicated host. For setups without a dedicated host, we recommend following the instructions to install the standalone APM Server for your operating system by selecting the respective tab above.', + } + )} +

+ + } /> diff --git a/x-pack/plugins/apm/server/tutorial/envs/on_prem.ts b/x-pack/plugins/apm/server/tutorial/envs/on_prem.ts index ba99b0624c441..8051ef2a72b6a 100644 --- a/x-pack/plugins/apm/server/tutorial/envs/on_prem.ts +++ b/x-pack/plugins/apm/server/tutorial/envs/on_prem.ts @@ -64,30 +64,6 @@ export function onPremInstructions({ iconType: 'alert', }, instructionVariants: [ - // hides fleet section when plugin is disabled - ...(isFleetPluginEnabled - ? [ - { - id: INSTRUCTION_VARIANT.FLEET, - instructions: [ - { - title: i18n.translate('xpack.apm.tutorial.fleet.title', { - defaultMessage: 'Fleet', - }), - customComponentName: 'TutorialFleetInstructions', - }, - ], - }, - ] - : []), - { - id: INSTRUCTION_VARIANT.OSX, - instructions: [ - createDownloadServerOsx(), - EDIT_CONFIG, - START_SERVER_UNIX, - ], - }, { id: INSTRUCTION_VARIANT.DEB, instructions: [ @@ -104,10 +80,34 @@ export function onPremInstructions({ START_SERVER_UNIX_SYSV, ], }, + { + id: INSTRUCTION_VARIANT.OSX, + instructions: [ + createDownloadServerOsx(), + EDIT_CONFIG, + START_SERVER_UNIX, + ], + }, { id: INSTRUCTION_VARIANT.WINDOWS, instructions: createWindowsServerInstructions(), }, + // hides fleet section when plugin is disabled + ...(isFleetPluginEnabled + ? [ + { + id: INSTRUCTION_VARIANT.FLEET, + instructions: [ + { + title: i18n.translate('xpack.apm.tutorial.fleet.title', { + defaultMessage: 'Fleet', + }), + customComponentName: 'TutorialFleetInstructions', + }, + ], + }, + ] + : []), ], statusCheck: { title: i18n.translate( From f69ff00f4485ca676ca7d02cfe33d27b959a1ff3 Mon Sep 17 00:00:00 2001 From: Ashokaditya <1849116+ashokaditya@users.noreply.github.com> Date: Tue, 16 Nov 2021 12:01:15 +0100 Subject: [PATCH 005/148] [Security Solution][Endpoint] Consistent pending actions agent status label (#117875) * pull more than default 10 records!! refs elastic/kibana/pull/115691 Co-Authored-By: Ashokaditya <1849116+ashokaditya@users.noreply.github.com> * commit using ashokaditya@elastic.co * show correct isolation status badge when pending actions data is updated fixes elastic/security-team/issues/2105 Co-Authored-By: Ashokaditya <1849116+ashokaditya@users.noreply.github.com> * fix typo Co-Authored-By: Ashokaditya <1849116+ashokaditya@users.noreply.github.com> * remove redundant dependencies review changes Co-Authored-By: Ashokaditya <1849116+ashokaditya@users.noreply.github.com> * show `isolated` right after pending state is refreshed fixes elastic/security-team/issues/2105 Co-Authored-By: Ashokaditya <1849116+ashokaditya@users.noreply.github.com> * recompute only on prop change Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../endpoint_host_isolation_status.tsx | 48 +++++++++++-------- .../server/endpoint/services/actions.ts | 1 + 2 files changed, 30 insertions(+), 19 deletions(-) diff --git a/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/endpoint_host_isolation_status.tsx b/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/endpoint_host_isolation_status.tsx index 6795557f17f1a..ad86b0f362234 100644 --- a/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/endpoint_host_isolation_status.tsx +++ b/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/endpoint_host_isolation_status.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import React, { memo, useMemo } from 'react'; +import React, { memo, useMemo, useRef, useEffect } from 'react'; import { EuiBadge, EuiFlexGroup, EuiFlexItem, EuiTextColor, EuiToolTip } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { useTestIdGenerator } from '../../../../management/components/hooks/use_test_id_generator'; @@ -28,12 +28,20 @@ export interface EndpointHostIsolationStatusProps { export const EndpointHostIsolationStatus = memo( ({ isIsolated, pendingIsolate = 0, pendingUnIsolate = 0, 'data-test-subj': dataTestSubj }) => { const getTestId = useTestIdGenerator(dataTestSubj); - const isPendingStatuseDisabled = useIsExperimentalFeatureEnabled( + const isPendingStatusDisabled = useIsExperimentalFeatureEnabled( 'disableIsolationUIPendingStatuses' ); + const wasReleasing = useRef(false); + const wasIsolating = useRef(false); + + useEffect(() => { + wasReleasing.current = pendingIsolate === 0 && pendingUnIsolate > 0; + wasIsolating.current = pendingIsolate > 0 && pendingUnIsolate === 0; + }, [pendingIsolate, pendingUnIsolate]); + return useMemo(() => { - if (isPendingStatuseDisabled) { + if (isPendingStatusDisabled) { // If nothing is pending and host is not currently isolated, then render nothing if (!isIsolated) { return null; @@ -49,21 +57,23 @@ export const EndpointHostIsolationStatus = memo - - - ); + // If nothing is pending + if (!(pendingIsolate || pendingUnIsolate)) { + // and host is either releasing and or currently released, then render nothing + if ((!wasIsolating.current && wasReleasing.current) || !isIsolated) { + return null; + } + // else host was isolating or is isolated, then show isolation badge + else if ((!isIsolated && wasIsolating.current && !wasReleasing.current) || isIsolated) { + return ( + + + + ); + } } // If there are multiple types of pending isolation actions, then show count of actions with tooltip that displays breakdown @@ -136,7 +146,7 @@ export const EndpointHostIsolationStatus = memo( { index: ENDPOINT_ACTION_RESPONSES_INDEX, + size: 10000, body: { query: { bool: { From 42957d954f3fb015cf84eac673de0a14ec1c5175 Mon Sep 17 00:00:00 2001 From: Pierre Gayvallet Date: Tue, 16 Nov 2021 12:16:50 +0100 Subject: [PATCH 006/148] [SOM] Fix UI and export when handling more than 10k objects (#118335) * delete the unused `scroll/export` endpoint * adapt the scroll/counts endpoint to use PIT search * improve export error message * only display 10k first items * fix findAll unit tests * fix FTR test * remove unused comment Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../objects_table/components/table.tsx | 19 +- .../objects_table/saved_objects_table.tsx | 14 +- .../server/lib/find_all.test.ts | 61 +++--- .../server/lib/find_all.ts | 32 ++-- .../server/routes/index.test.ts | 8 +- .../server/routes/index.ts | 2 - .../server/routes/scroll_count.ts | 4 +- .../server/routes/scroll_export.ts | 56 ------ .../saved_objects_management/scroll_count.ts | 181 ++++++++++++------ .../translations/translations/ja-JP.json | 1 - .../translations/translations/zh-CN.json | 1 - 11 files changed, 197 insertions(+), 182 deletions(-) delete mode 100644 src/plugins/saved_objects_management/server/routes/scroll_export.ts diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.tsx index 75f36e20eb084..ed79135f1f09f 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/components/table.tsx @@ -74,6 +74,8 @@ interface TableState { activeAction?: SavedObjectsManagementAction; } +const MAX_PAGINATED_ITEM = 10000; + export class Table extends PureComponent { state: TableState = { isSearchTextValid: true, @@ -150,10 +152,12 @@ export class Table extends PureComponent { allowedTypes, } = this.props; + const cappedTotalItemCount = Math.min(totalItemCount, MAX_PAGINATED_ITEM); + const pagination = { pageIndex, pageSize, - totalItemCount, + totalItemCount: cappedTotalItemCount, pageSizeOptions: [5, 10, 20, 50], }; @@ -321,6 +325,7 @@ export class Table extends PureComponent { ); const activeActionContents = this.state.activeAction?.render() ?? null; + const exceededResultCount = totalItemCount > MAX_PAGINATED_ITEM; return ( @@ -392,6 +397,18 @@ export class Table extends PureComponent { /> {queryParseError} + {exceededResultCount && ( + <> + + + + + + )}
{ savedObjectsClient = savedObjectsClientMock.create(); }); - it('calls the saved object client with the correct parameters', async () => { + it('calls `client.createPointInTimeFinder` with the correct parameters', async () => { + const query: SavedObjectsFindOptions = { + type: ['some-type', 'another-type'], + }; + + savedObjectsClient.find.mockResolvedValue({ + saved_objects: [], + total: 1, + per_page: 20, + page: 1, + }); + + await findAll(savedObjectsClient, query); + + expect(savedObjectsClient.createPointInTimeFinder).toHaveBeenCalledTimes(1); + expect(savedObjectsClient.createPointInTimeFinder).toHaveBeenCalledWith(query); + }); + + it('returns the results from the PIT search', async () => { const query: SavedObjectsFindOptions = { type: ['some-type', 'another-type'], }; @@ -41,45 +59,40 @@ describe('findAll', () => { const results = await findAll(savedObjectsClient, query); expect(savedObjectsClient.find).toHaveBeenCalledTimes(1); - expect(savedObjectsClient.find).toHaveBeenCalledWith({ - ...query, - page: 1, - }); + expect(savedObjectsClient.find).toHaveBeenCalledWith( + expect.objectContaining({ + ...query, + }) + ); expect(results).toEqual([createObj(1), createObj(2)]); }); - it('recursively call find until all objects are fetched', async () => { + it('works when the PIT search returns multiple batches', async () => { const query: SavedObjectsFindOptions = { type: ['some-type', 'another-type'], + perPage: 2, }; const objPerPage = 2; - savedObjectsClient.find.mockImplementation(({ page }) => { - const firstInPage = (page! - 1) * objPerPage + 1; + let callCount = 0; + savedObjectsClient.find.mockImplementation(({}) => { + callCount++; + const firstInPage = (callCount - 1) * objPerPage + 1; return Promise.resolve({ - saved_objects: [createObj(firstInPage), createObj(firstInPage + 1)], + saved_objects: + callCount > 3 + ? [createObj(firstInPage)] + : [createObj(firstInPage), createObj(firstInPage + 1)], total: objPerPage * 3, per_page: objPerPage, - page: page!, + page: callCount!, }); }); const results = await findAll(savedObjectsClient, query); - expect(savedObjectsClient.find).toHaveBeenCalledTimes(3); - expect(savedObjectsClient.find).toHaveBeenCalledWith({ - ...query, - page: 1, - }); - expect(savedObjectsClient.find).toHaveBeenCalledWith({ - ...query, - page: 2, - }); - expect(savedObjectsClient.find).toHaveBeenCalledWith({ - ...query, - page: 3, - }); - expect(results).toEqual(times(6, (num) => createObj(num + 1))); + expect(savedObjectsClient.find).toHaveBeenCalledTimes(4); + expect(results).toEqual(times(7, (num) => createObj(num + 1))); }); }); diff --git a/src/plugins/saved_objects_management/server/lib/find_all.ts b/src/plugins/saved_objects_management/server/lib/find_all.ts index 08681758752be..8d908234c6961 100644 --- a/src/plugins/saved_objects_management/server/lib/find_all.ts +++ b/src/plugins/saved_objects_management/server/lib/find_all.ts @@ -6,30 +6,20 @@ * Side Public License, v 1. */ -import { SavedObjectsClientContract, SavedObject, SavedObjectsFindOptions } from 'src/core/server'; +import { + SavedObjectsClientContract, + SavedObject, + SavedObjectsCreatePointInTimeFinderOptions, +} from 'src/core/server'; export const findAll = async ( client: SavedObjectsClientContract, - findOptions: SavedObjectsFindOptions + findOptions: SavedObjectsCreatePointInTimeFinderOptions ): Promise => { - return recursiveFind(client, findOptions, 1, []); -}; - -const recursiveFind = async ( - client: SavedObjectsClientContract, - findOptions: SavedObjectsFindOptions, - page: number, - allObjects: SavedObject[] -): Promise => { - const objects = await client.find({ - ...findOptions, - page, - }); - - allObjects.push(...objects.saved_objects); - if (allObjects.length < objects.total) { - return recursiveFind(client, findOptions, page + 1, allObjects); + const finder = client.createPointInTimeFinder(findOptions); + const results: SavedObject[] = []; + for await (const result of finder.find()) { + results.push(...result.saved_objects); } - - return allObjects; + return results; }; diff --git a/src/plugins/saved_objects_management/server/routes/index.test.ts b/src/plugins/saved_objects_management/server/routes/index.test.ts index 3ec6afe1c0bbc..9c3d235a83e36 100644 --- a/src/plugins/saved_objects_management/server/routes/index.test.ts +++ b/src/plugins/saved_objects_management/server/routes/index.test.ts @@ -24,7 +24,7 @@ describe('registerRoutes', () => { expect(httpSetup.createRouter).toHaveBeenCalledTimes(1); expect(router.get).toHaveBeenCalledTimes(3); - expect(router.post).toHaveBeenCalledTimes(3); + expect(router.post).toHaveBeenCalledTimes(2); expect(router.get).toHaveBeenCalledWith( expect.objectContaining({ @@ -56,11 +56,5 @@ describe('registerRoutes', () => { }), expect.any(Function) ); - expect(router.post).toHaveBeenCalledWith( - expect.objectContaining({ - path: '/api/kibana/management/saved_objects/scroll/export', - }), - expect.any(Function) - ); }); }); diff --git a/src/plugins/saved_objects_management/server/routes/index.ts b/src/plugins/saved_objects_management/server/routes/index.ts index b5b461575604d..5370088d27977 100644 --- a/src/plugins/saved_objects_management/server/routes/index.ts +++ b/src/plugins/saved_objects_management/server/routes/index.ts @@ -11,7 +11,6 @@ import { ISavedObjectsManagement } from '../services'; import { registerFindRoute } from './find'; import { registerBulkGetRoute } from './bulk_get'; import { registerScrollForCountRoute } from './scroll_count'; -import { registerScrollForExportRoute } from './scroll_export'; import { registerRelationshipsRoute } from './relationships'; import { registerGetAllowedTypesRoute } from './get_allowed_types'; @@ -25,7 +24,6 @@ export function registerRoutes({ http, managementServicePromise }: RegisterRoute registerFindRoute(router, managementServicePromise); registerBulkGetRoute(router, managementServicePromise); registerScrollForCountRoute(router); - registerScrollForExportRoute(router); registerRelationshipsRoute(router, managementServicePromise); registerGetAllowedTypesRoute(router); } diff --git a/src/plugins/saved_objects_management/server/routes/scroll_count.ts b/src/plugins/saved_objects_management/server/routes/scroll_count.ts index 89a895adf6008..9a021be4c0cde 100644 --- a/src/plugins/saved_objects_management/server/routes/scroll_count.ts +++ b/src/plugins/saved_objects_management/server/routes/scroll_count.ts @@ -7,7 +7,7 @@ */ import { schema } from '@kbn/config-schema'; -import { IRouter, SavedObjectsFindOptions } from 'src/core/server'; +import { IRouter, SavedObjectsCreatePointInTimeFinderOptions } from 'src/core/server'; import { chain } from 'lodash'; import { findAll } from '../lib'; @@ -42,7 +42,7 @@ export const registerScrollForCountRoute = (router: IRouter) => { .value(); const client = getClient({ includedHiddenTypes }); - const findOptions: SavedObjectsFindOptions = { + const findOptions: SavedObjectsCreatePointInTimeFinderOptions = { type: typesToInclude, perPage: 1000, }; diff --git a/src/plugins/saved_objects_management/server/routes/scroll_export.ts b/src/plugins/saved_objects_management/server/routes/scroll_export.ts deleted file mode 100644 index 8d11437af661b..0000000000000 --- a/src/plugins/saved_objects_management/server/routes/scroll_export.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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { schema } from '@kbn/config-schema'; -import { IRouter } from 'src/core/server'; -import { chain } from 'lodash'; -import { findAll } from '../lib'; - -export const registerScrollForExportRoute = (router: IRouter) => { - router.post( - { - path: '/api/kibana/management/saved_objects/scroll/export', - validate: { - body: schema.object({ - typesToInclude: schema.arrayOf(schema.string()), - }), - }, - }, - router.handleLegacyErrors(async (context, req, res) => { - const { typesToInclude } = req.body; - const { getClient, typeRegistry } = context.core.savedObjects; - const includedHiddenTypes = chain(typesToInclude) - .uniq() - .filter( - (type) => typeRegistry.isHidden(type) && typeRegistry.isImportableAndExportable(type) - ) - .value(); - - const client = getClient({ includedHiddenTypes }); - - const objects = await findAll(client, { - perPage: 1000, - type: typesToInclude, - }); - - return res.ok({ - body: objects.map((hit) => { - return { - _id: hit.id, - _source: hit.attributes, - _meta: { - savedObjectVersion: 2, - }, - _migrationVersion: hit.migrationVersion, - _references: hit.references || [], - }; - }), - }); - }) - ); -}; diff --git a/test/api_integration/apis/saved_objects_management/scroll_count.ts b/test/api_integration/apis/saved_objects_management/scroll_count.ts index 088b26d8205da..ffb275e8656f0 100644 --- a/test/api_integration/apis/saved_objects_management/scroll_count.ts +++ b/test/api_integration/apis/saved_objects_management/scroll_count.ts @@ -18,77 +18,132 @@ export default function ({ getService }: FtrProviderContext) { const esArchiver = getService('esArchiver'); describe('scroll_count', () => { - before(async () => { - await esArchiver.load( - 'test/api_integration/fixtures/es_archiver/management/saved_objects/scroll_count' - ); - }); - after(async () => { - await esArchiver.unload( - 'test/api_integration/fixtures/es_archiver/management/saved_objects/scroll_count' - ); - }); + describe('with less than 10k objects', () => { + before(async () => { + await esArchiver.load( + 'test/api_integration/fixtures/es_archiver/management/saved_objects/scroll_count' + ); + }); + after(async () => { + await esArchiver.unload( + 'test/api_integration/fixtures/es_archiver/management/saved_objects/scroll_count' + ); + }); + + it('returns the count for each included types', async () => { + const res = await supertest + .post(apiUrl) + .send({ + typesToInclude: defaultTypes, + }) + .expect(200); - it('returns the count for each included types', async () => { - const res = await supertest - .post(apiUrl) - .send({ - typesToInclude: defaultTypes, - }) - .expect(200); - - expect(res.body).to.eql({ - dashboard: 2, - 'index-pattern': 1, - search: 1, - visualization: 2, + expect(res.body).to.eql({ + dashboard: 2, + 'index-pattern': 1, + search: 1, + visualization: 2, + }); }); - }); - it('only returns count for types to include', async () => { - const res = await supertest - .post(apiUrl) - .send({ - typesToInclude: ['dashboard', 'search'], - }) - .expect(200); - - expect(res.body).to.eql({ - dashboard: 2, - search: 1, + it('only returns count for types to include', async () => { + const res = await supertest + .post(apiUrl) + .send({ + typesToInclude: ['dashboard', 'search'], + }) + .expect(200); + + expect(res.body).to.eql({ + dashboard: 2, + search: 1, + }); }); - }); - it('filters on title when `searchString` is provided', async () => { - const res = await supertest - .post(apiUrl) - .send({ - typesToInclude: defaultTypes, - searchString: 'Amazing', - }) - .expect(200); - - expect(res.body).to.eql({ - dashboard: 1, - visualization: 1, - 'index-pattern': 0, - search: 0, + it('filters on title when `searchString` is provided', async () => { + const res = await supertest + .post(apiUrl) + .send({ + typesToInclude: defaultTypes, + searchString: 'Amazing', + }) + .expect(200); + + expect(res.body).to.eql({ + dashboard: 1, + visualization: 1, + 'index-pattern': 0, + search: 0, + }); + }); + + it('includes all requested types even when none match the search', async () => { + const res = await supertest + .post(apiUrl) + .send({ + typesToInclude: ['dashboard', 'search', 'visualization'], + searchString: 'nothing-will-match', + }) + .expect(200); + + expect(res.body).to.eql({ + dashboard: 0, + visualization: 0, + search: 0, + }); }); }); - it('includes all requested types even when none match the search', async () => { - const res = await supertest - .post(apiUrl) - .send({ - typesToInclude: ['dashboard', 'search', 'visualization'], - searchString: 'nothing-will-match', - }) - .expect(200); - - expect(res.body).to.eql({ - dashboard: 0, - visualization: 0, - search: 0, + describe('scroll_count with more than 10k objects', () => { + const importVisualizations = async ({ + startIdx = 1, + endIdx, + }: { + startIdx?: number; + endIdx: number; + }) => { + const fileChunks: string[] = []; + for (let i = startIdx; i <= endIdx; i++) { + const id = `test-vis-${i}`; + fileChunks.push( + JSON.stringify({ + type: 'visualization', + id, + attributes: { + title: `My visualization (${i})`, + uiStateJSON: '{}', + visState: '{}', + }, + references: [], + }) + ); + } + + await supertest + .post(`/api/saved_objects/_import`) + .attach('file', Buffer.from(fileChunks.join('\n'), 'utf8'), 'export.ndjson') + .expect(200); + }; + + before(async () => { + await importVisualizations({ startIdx: 1, endIdx: 6000 }); + await importVisualizations({ startIdx: 6001, endIdx: 12000 }); + }); + after(async () => { + await esArchiver.emptyKibanaIndex(); + }); + + it('returns the correct count for each included types', async () => { + const res = await supertest + .post(apiUrl) + .send({ + typesToInclude: ['visualization'], + }) + .expect(200); + + expect(res.body).to.eql({ + visualization: 12000, + }); }); }); }); diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index eee055e75eb8f..45b6828e25fe6 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -4279,7 +4279,6 @@ "savedObjectsManagement.objectsTable.deleteSavedObjectsConfirmModal.titleColumnName": "タイトル", "savedObjectsManagement.objectsTable.deleteSavedObjectsConfirmModal.typeColumnName": "型", "savedObjectsManagement.objectsTable.deleteSavedObjectsConfirmModalTitle": "保存されたオブジェクトの削除", - "savedObjectsManagement.objectsTable.export.dangerNotification": "エクスポートを生成できません", "savedObjectsManagement.objectsTable.export.successNotification": "ファイルはバックグラウンドでダウンロード中です", "savedObjectsManagement.objectsTable.export.successWithExcludedObjectsNotification": "ファイルはバックグラウンドでダウンロード中です。一部のオブジェクトはエクスポートから除外されました。除外されたオブジェクトの一覧は、エクスポートされたファイルの最後の行をご覧ください。", "savedObjectsManagement.objectsTable.export.successWithMissingRefsNotification": "ファイルはバックグラウンドでダウンロード中です。一部の関連オブジェクトが見つかりませんでした。足りないオブジェクトの一覧は、エクスポートされたファイルの最後の行をご覧ください。", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 3a5d909e12049..ccdc7f1d7bccb 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -4320,7 +4320,6 @@ "savedObjectsManagement.objectsTable.deleteSavedObjectsConfirmModal.titleColumnName": "标题", "savedObjectsManagement.objectsTable.deleteSavedObjectsConfirmModal.typeColumnName": "类型", "savedObjectsManagement.objectsTable.deleteSavedObjectsConfirmModalTitle": "删除已保存对象", - "savedObjectsManagement.objectsTable.export.dangerNotification": "无法生成导出", "savedObjectsManagement.objectsTable.export.successNotification": "您的文件正在后台下载", "savedObjectsManagement.objectsTable.export.successWithExcludedObjectsNotification": "您的文件正在后台下载。一些对象已从导出中排除。有关已排除对象列表,请查看导出文件的最后一行。", "savedObjectsManagement.objectsTable.export.successWithMissingRefsNotification": "您的文件正在后台下载。找不到某些相关对象。有关缺失对象列表,请查看导出文件的最后一行。", From b48268dd0c42c9dc1fe310f7c0b3327117d066a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Louv-Jansen?= Date: Tue, 16 Nov 2021 12:44:55 +0100 Subject: [PATCH 007/148] [APM] Remove projections (#118327) * Delete errors projection * Remove `getMetricsProjection` * Remove `getServiceNodesProjection` * Fix tests Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../apm/common/utils/environment_query.ts | 20 ++- .../shared/charts/metrics_chart/index.tsx | 11 +- .../use_service_metric_charts_fetcher.ts | 8 +- .../apm/server/lib/errors/get_error_groups.ts | 49 +++---- .../server/lib/metrics/by_agent/default.ts | 6 +- .../java/gc/fetch_and_transform_gc_metrics.ts | 35 +++-- .../server/lib/metrics/by_agent/java/index.ts | 6 +- .../metrics/fetch_and_transform_metrics.ts | 120 ++++++++++------ .../get_metrics_chart_data_by_agent.ts | 8 +- .../metrics/transform_metrics_chart.test.ts | 132 ------------------ .../lib/metrics/transform_metrics_chart.ts | 55 -------- .../server/lib/service_map/get_service_map.ts | 1 - .../__snapshots__/queries.test.ts.snap | 29 ++-- .../apm/server/lib/service_nodes/index.ts | 39 ++++-- .../lib/services/get_service_node_metadata.ts | 73 ++++++---- .../get_environments/index.ts | 5 - .../agent_configuration/get_service_names.ts | 5 - .../plugins/apm/server/projections/errors.ts | 53 ------- .../plugins/apm/server/projections/metrics.ts | 65 --------- .../apm/server/projections/service_nodes.ts | 48 ------- x-pack/plugins/apm/server/routes/metrics.ts | 5 +- .../metrics_charts/metrics_charts.spec.ts | 72 ++++++---- 22 files changed, 292 insertions(+), 553 deletions(-) delete mode 100644 x-pack/plugins/apm/server/lib/metrics/transform_metrics_chart.test.ts delete mode 100644 x-pack/plugins/apm/server/lib/metrics/transform_metrics_chart.ts delete mode 100644 x-pack/plugins/apm/server/projections/errors.ts delete mode 100644 x-pack/plugins/apm/server/projections/metrics.ts delete mode 100644 x-pack/plugins/apm/server/projections/service_nodes.ts diff --git a/x-pack/plugins/apm/common/utils/environment_query.ts b/x-pack/plugins/apm/common/utils/environment_query.ts index e2f9a722e3de2..bc02e4cd2518b 100644 --- a/x-pack/plugins/apm/common/utils/environment_query.ts +++ b/x-pack/plugins/apm/common/utils/environment_query.ts @@ -6,11 +6,15 @@ */ import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; -import { SERVICE_ENVIRONMENT } from '../elasticsearch_fieldnames'; +import { + SERVICE_ENVIRONMENT, + SERVICE_NODE_NAME, +} from '../elasticsearch_fieldnames'; import { ENVIRONMENT_ALL, ENVIRONMENT_NOT_DEFINED, } from '../environment_filter_values'; +import { SERVICE_NODE_NAME_MISSING } from '../service_nodes'; export function environmentQuery( environment: string @@ -25,3 +29,17 @@ export function environmentQuery( return [{ term: { [SERVICE_ENVIRONMENT]: environment } }]; } + +export function serviceNodeNameQuery( + serviceNodeName?: string +): QueryDslQueryContainer[] { + if (!serviceNodeName) { + return []; + } + + if (serviceNodeName === SERVICE_NODE_NAME_MISSING) { + return [{ bool: { must_not: [{ exists: { field: SERVICE_NODE_NAME } }] } }]; + } + + return [{ term: { [SERVICE_NODE_NAME]: serviceNodeName } }]; +} diff --git a/x-pack/plugins/apm/public/components/shared/charts/metrics_chart/index.tsx b/x-pack/plugins/apm/public/components/shared/charts/metrics_chart/index.tsx index 9f437a95e7dd9..1c2b7fdeb7714 100644 --- a/x-pack/plugins/apm/public/components/shared/charts/metrics_chart/index.tsx +++ b/x-pack/plugins/apm/public/components/shared/charts/metrics_chart/index.tsx @@ -7,6 +7,7 @@ import { EuiTitle } from '@elastic/eui'; import React from 'react'; +import { APIReturnType } from '../../../../services/rest/createCallApmApi'; import { asDecimal, asInteger, @@ -14,8 +15,6 @@ import { getDurationFormatter, getFixedByteFormatter, } from '../../../../../common/utils/formatters'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { GenericMetricsChart } from '../../../../../server/lib/metrics/transform_metrics_chart'; import { Maybe } from '../../../../../typings/common'; import { FETCH_STATUS } from '../../../../hooks/use_fetcher'; import { TimeseriesChart } from '../timeseries_chart'; @@ -24,7 +23,11 @@ import { getResponseTimeTickFormatter, } from '../transaction_charts/helper'; -function getYTickFormatter(chart: GenericMetricsChart) { +type MetricChartApiResponse = + APIReturnType<'GET /internal/apm/services/{serviceName}/metrics/charts'>; +type MetricChart = MetricChartApiResponse['charts'][0]; + +function getYTickFormatter(chart: MetricChart) { const max = getMaxY(chart.series); switch (chart.yUnit) { @@ -50,7 +53,7 @@ function getYTickFormatter(chart: GenericMetricsChart) { interface Props { start: Maybe; end: Maybe; - chart: GenericMetricsChart; + chart: MetricChart; fetchStatus: FETCH_STATUS; } diff --git a/x-pack/plugins/apm/public/hooks/use_service_metric_charts_fetcher.ts b/x-pack/plugins/apm/public/hooks/use_service_metric_charts_fetcher.ts index ef360698192e1..15037ecf6adb8 100644 --- a/x-pack/plugins/apm/public/hooks/use_service_metric_charts_fetcher.ts +++ b/x-pack/plugins/apm/public/hooks/use_service_metric_charts_fetcher.ts @@ -5,14 +5,16 @@ * 2.0. */ -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { MetricsChartsByAgentAPIResponse } from '../../server/lib/metrics/get_metrics_chart_data_by_agent'; +import type { APIReturnType } from '../services/rest/createCallApmApi'; import { useApmServiceContext } from '../context/apm_service/use_apm_service_context'; import { useFetcher } from './use_fetcher'; import { useTimeRange } from './use_time_range'; import { useApmParams } from './use_apm_params'; -const INITIAL_DATA: MetricsChartsByAgentAPIResponse = { +type MetricChartApiResponse = + APIReturnType<'GET /internal/apm/services/{serviceName}/metrics/charts'>; + +const INITIAL_DATA: MetricChartApiResponse = { charts: [], }; diff --git a/x-pack/plugins/apm/server/lib/errors/get_error_groups.ts b/x-pack/plugins/apm/server/lib/errors/get_error_groups.ts index 2c8d0f6998bf8..4d4c935d20e76 100644 --- a/x-pack/plugins/apm/server/lib/errors/get_error_groups.ts +++ b/x-pack/plugins/apm/server/lib/errors/get_error_groups.ts @@ -5,6 +5,10 @@ * 2.0. */ +import { AggregationsTermsAggregationOrder } from '@elastic/elasticsearch/lib/api/types'; +import { ProcessorEvent } from '../../../common/processor_event'; +import { environmentQuery } from '../../../common/utils/environment_query'; +import { kqlQuery, rangeQuery } from '../../../../observability/server'; import { ERROR_CULPRIT, ERROR_EXC_HANDLED, @@ -12,9 +16,8 @@ import { ERROR_EXC_TYPE, ERROR_GROUP_ID, ERROR_LOG_MESSAGE, + SERVICE_NAME, } from '../../../common/elasticsearch_fieldnames'; -import { getErrorGroupsProjection } from '../../projections/errors'; -import { mergeProjection } from '../../projections/util/merge_projection'; import { getErrorName } from '../helpers/get_error_name'; import { Setup } from '../helpers/setup_request'; @@ -42,27 +45,31 @@ export async function getErrorGroups({ // sort buckets by last occurrence of error const sortByLatestOccurrence = sortField === 'latestOccurrenceAt'; - const projection = getErrorGroupsProjection({ - environment, - kuery, - serviceName, - start, - end, - }); - - const order = sortByLatestOccurrence - ? { - max_timestamp: sortDirection, - } + const maxTimestampAggKey = 'max_timestamp'; + const order: AggregationsTermsAggregationOrder = sortByLatestOccurrence + ? { [maxTimestampAggKey]: sortDirection } : { _count: sortDirection }; - const params = mergeProjection(projection, { + const params = { + apm: { + events: [ProcessorEvent.error as const], + }, body: { size: 0, + query: { + bool: { + filter: [ + { term: { [SERVICE_NAME]: serviceName } }, + ...rangeQuery(start, end), + ...environmentQuery(environment), + ...kqlQuery(kuery), + ], + }, + }, aggs: { error_groups: { terms: { - ...projection.body.aggs.error_groups.terms, + field: ERROR_GROUP_ID, size: 500, order, }, @@ -83,19 +90,13 @@ export async function getErrorGroups({ }, }, ...(sortByLatestOccurrence - ? { - max_timestamp: { - max: { - field: '@timestamp', - }, - }, - } + ? { [maxTimestampAggKey]: { max: { field: '@timestamp' } } } : {}), }, }, }, }, - }); + }; const resp = await apmEventClient.search('get_error_groups', params); diff --git a/x-pack/plugins/apm/server/lib/metrics/by_agent/default.ts b/x-pack/plugins/apm/server/lib/metrics/by_agent/default.ts index 62e23d19b00bd..54e10bd8adde0 100644 --- a/x-pack/plugins/apm/server/lib/metrics/by_agent/default.ts +++ b/x-pack/plugins/apm/server/lib/metrics/by_agent/default.ts @@ -9,7 +9,7 @@ import { Setup } from '../../helpers/setup_request'; import { getCPUChartData } from './shared/cpu'; import { getMemoryChartData } from './shared/memory'; -export async function getDefaultMetricsCharts({ +export function getDefaultMetricsCharts({ environment, kuery, serviceName, @@ -24,10 +24,8 @@ export async function getDefaultMetricsCharts({ start: number; end: number; }) { - const charts = await Promise.all([ + return Promise.all([ getCPUChartData({ environment, kuery, setup, serviceName, start, end }), getMemoryChartData({ environment, kuery, setup, serviceName, start, end }), ]); - - return { charts }; } diff --git a/x-pack/plugins/apm/server/lib/metrics/by_agent/java/gc/fetch_and_transform_gc_metrics.ts b/x-pack/plugins/apm/server/lib/metrics/by_agent/java/gc/fetch_and_transform_gc_metrics.ts index 117b372d445d2..2d4cf2f70ab5f 100644 --- a/x-pack/plugins/apm/server/lib/metrics/by_agent/java/gc/fetch_and_transform_gc_metrics.ts +++ b/x-pack/plugins/apm/server/lib/metrics/by_agent/java/gc/fetch_and_transform_gc_metrics.ts @@ -11,17 +11,26 @@ import { isFiniteNumber } from '../../../../../../common/utils/is_finite_number' import { Setup } from '../../../../helpers/setup_request'; import { getMetricsDateHistogramParams } from '../../../../helpers/metrics'; import { ChartBase } from '../../../types'; -import { getMetricsProjection } from '../../../../../projections/metrics'; -import { mergeProjection } from '../../../../../projections/util/merge_projection'; + import { AGENT_NAME, LABEL_NAME, METRIC_JAVA_GC_COUNT, METRIC_JAVA_GC_TIME, + SERVICE_NAME, } from '../../../../../../common/elasticsearch_fieldnames'; import { getBucketSize } from '../../../../helpers/get_bucket_size'; import { getVizColorForIndex } from '../../../../../../common/viz_colors'; import { JAVA_AGENT_NAMES } from '../../../../../../common/agent_name'; +import { + environmentQuery, + serviceNodeNameQuery, +} from '../../../../../../common/utils/environment_query'; +import { + kqlQuery, + rangeQuery, +} from '../../../../../../../observability/server'; +import { ProcessorEvent } from '../../../../../../common/processor_event'; export async function fetchAndTransformGcMetrics({ environment, @@ -50,26 +59,24 @@ export async function fetchAndTransformGcMetrics({ const { bucketSize } = getBucketSize({ start, end }); - const projection = getMetricsProjection({ - environment, - kuery, - serviceName, - serviceNodeName, - start, - end, - }); - // GC rate and time are reported by the agents as monotonically // increasing counters, which means that we have to calculate // the delta in an es query. In the future agent might start // reporting deltas. - const params = mergeProjection(projection, { + const params = { + apm: { + events: [ProcessorEvent.metric], + }, body: { size: 0, query: { bool: { filter: [ - ...projection.body.query.bool.filter, + { term: { [SERVICE_NAME]: serviceName } }, + ...serviceNodeNameQuery(serviceNodeName), + ...rangeQuery(start, end), + ...environmentQuery(environment), + ...kqlQuery(kuery), { exists: { field: fieldName } }, { terms: { [AGENT_NAME]: JAVA_AGENT_NAMES } }, ], @@ -114,7 +121,7 @@ export async function fetchAndTransformGcMetrics({ }, }, }, - }); + }; const response = await apmEventClient.search(operationName, params); diff --git a/x-pack/plugins/apm/server/lib/metrics/by_agent/java/index.ts b/x-pack/plugins/apm/server/lib/metrics/by_agent/java/index.ts index 164777539c9d5..9039bb19ebb78 100644 --- a/x-pack/plugins/apm/server/lib/metrics/by_agent/java/index.ts +++ b/x-pack/plugins/apm/server/lib/metrics/by_agent/java/index.ts @@ -32,7 +32,7 @@ export function getJavaMetricsCharts({ start: number; end: number; }) { - return withApmSpan('get_java_system_metric_charts', async () => { + return withApmSpan('get_java_system_metric_charts', () => { const options = { environment, kuery, @@ -43,7 +43,7 @@ export function getJavaMetricsCharts({ end, }; - const charts = await Promise.all([ + return Promise.all([ getCPUChartData(options), getMemoryChartData(options), getHeapMemoryChart(options), @@ -52,7 +52,5 @@ export function getJavaMetricsCharts({ getGcRateChart(options), getGcTimeChart(options), ]); - - return { charts }; }); } diff --git a/x-pack/plugins/apm/server/lib/metrics/fetch_and_transform_metrics.ts b/x-pack/plugins/apm/server/lib/metrics/fetch_and_transform_metrics.ts index 581a0782e4d72..0a24179ed9fc6 100644 --- a/x-pack/plugins/apm/server/lib/metrics/fetch_and_transform_metrics.ts +++ b/x-pack/plugins/apm/server/lib/metrics/fetch_and_transform_metrics.ts @@ -5,15 +5,23 @@ * 2.0. */ -import { Overwrite, Unionize } from 'utility-types'; +import { Unionize } from 'utility-types'; +import { euiLightVars as theme } from '@kbn/ui-shared-deps-src/theme'; +import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/types'; +import { getVizColorForIndex } from '../../../common/viz_colors'; import { AggregationOptionsByType } from '../../../../../../src/core/types/elasticsearch'; -import { getMetricsProjection } from '../../projections/metrics'; -import { mergeProjection } from '../../projections/util/merge_projection'; -import { APMEventESSearchRequest } from '../helpers/create_es_client/create_apm_event_client'; import { getMetricsDateHistogramParams } from '../helpers/metrics'; import { Setup } from '../helpers/setup_request'; -import { transformDataToMetricsChart } from './transform_metrics_chart'; import { ChartBase } from './types'; +import { + environmentQuery, + serviceNodeNameQuery, +} from '../../../common/utils/environment_query'; +import { kqlQuery, rangeQuery } from '../../../../observability/server'; +import { ProcessorEvent } from '../../../common/processor_event'; +import { SERVICE_NAME } from '../../../common/elasticsearch_fieldnames'; +import { APMEventESSearchRequest } from '../helpers/create_es_client/create_apm_event_client'; +import { PromiseReturnType } from '../../../../observability/typings/common'; type MetricsAggregationMap = Unionize<{ min: AggregationOptionsByType['min']; @@ -24,31 +32,20 @@ type MetricsAggregationMap = Unionize<{ type MetricAggs = Record; -export type GenericMetricsRequest = Overwrite< - APMEventESSearchRequest, - { - body: { - aggs: { - timeseriesData: { - date_histogram: AggregationOptionsByType['date_histogram']; - aggs: MetricAggs; - }; - } & MetricAggs; - }; - } ->; - -interface Filter { - exists?: { - field: string; - }; - term?: { - [key: string]: string; - }; - terms?: { - [key: string]: string[]; +export type GenericMetricsRequest = APMEventESSearchRequest & { + body: { + aggs: { + timeseriesData: { + date_histogram: AggregationOptionsByType['date_histogram']; + aggs: MetricAggs; + }; + } & MetricAggs; }; -} +}; + +export type GenericMetricsChart = PromiseReturnType< + typeof fetchAndTransformMetrics +>; export async function fetchAndTransformMetrics({ environment, @@ -72,26 +69,27 @@ export async function fetchAndTransformMetrics({ end: number; chartBase: ChartBase; aggs: T; - additionalFilters?: Filter[]; + additionalFilters?: QueryDslQueryContainer[]; operationName: string; }) { const { apmEventClient, config } = setup; - const projection = getMetricsProjection({ - environment, - kuery, - serviceName, - serviceNodeName, - start, - end, - }); - - const params: GenericMetricsRequest = mergeProjection(projection, { + const params: GenericMetricsRequest = { + apm: { + events: [ProcessorEvent.metric], + }, body: { size: 0, query: { bool: { - filter: [...projection.body.query.bool.filter, ...additionalFilters], + filter: [ + { term: { [SERVICE_NAME]: serviceName } }, + ...serviceNodeNameQuery(serviceNodeName), + ...rangeQuery(start, end), + ...environmentQuery(environment), + ...kqlQuery(kuery), + ...additionalFilters, + ], }, }, aggs: { @@ -106,9 +104,43 @@ export async function fetchAndTransformMetrics({ ...aggs, }, }, - }); + }; + + const { hits, aggregations } = await apmEventClient.search( + operationName, + params + ); + const timeseriesData = aggregations?.timeseriesData; - const response = await apmEventClient.search(operationName, params); + return { + title: chartBase.title, + key: chartBase.key, + yUnit: chartBase.yUnit, + series: + hits.total.value === 0 + ? [] + : Object.keys(chartBase.series).map((seriesKey, i) => { + // @ts-ignore + const overallValue = aggregations?.[seriesKey]?.value as number; - return transformDataToMetricsChart(response, chartBase); + return { + title: chartBase.series[seriesKey].title, + key: seriesKey, + type: chartBase.type, + color: + chartBase.series[seriesKey].color || + getVizColorForIndex(i, theme), + overallValue, + data: + timeseriesData?.buckets.map((bucket) => { + const { value } = bucket[seriesKey]; + const y = value === null || isNaN(value) ? null : value; + return { + x: bucket.key, + y, + }; + }) || [], + }; + }), + }; } diff --git a/x-pack/plugins/apm/server/lib/metrics/get_metrics_chart_data_by_agent.ts b/x-pack/plugins/apm/server/lib/metrics/get_metrics_chart_data_by_agent.ts index 29991034f7c5e..611bb8196032c 100644 --- a/x-pack/plugins/apm/server/lib/metrics/get_metrics_chart_data_by_agent.ts +++ b/x-pack/plugins/apm/server/lib/metrics/get_metrics_chart_data_by_agent.ts @@ -8,12 +8,8 @@ import { Setup } from '../helpers/setup_request'; import { getJavaMetricsCharts } from './by_agent/java'; import { getDefaultMetricsCharts } from './by_agent/default'; -import { GenericMetricsChart } from './transform_metrics_chart'; import { isJavaAgentName } from '../../../common/agent_name'; - -export interface MetricsChartsByAgentAPIResponse { - charts: GenericMetricsChart[]; -} +import { GenericMetricsChart } from './fetch_and_transform_metrics'; export async function getMetricsChartDataByAgent({ environment, @@ -33,7 +29,7 @@ export async function getMetricsChartDataByAgent({ agentName: string; start: number; end: number; -}): Promise { +}): Promise { if (isJavaAgentName(agentName)) { return getJavaMetricsCharts({ environment, diff --git a/x-pack/plugins/apm/server/lib/metrics/transform_metrics_chart.test.ts b/x-pack/plugins/apm/server/lib/metrics/transform_metrics_chart.test.ts deleted file mode 100644 index 107e2d5774816..0000000000000 --- a/x-pack/plugins/apm/server/lib/metrics/transform_metrics_chart.test.ts +++ /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 { transformDataToMetricsChart } from './transform_metrics_chart'; -import { ChartType, YUnit } from '../../../typings/timeseries'; - -test('transformDataToMetricsChart should transform an ES result into a chart object', () => { - const response = { - hits: { total: { value: 5000 } }, - aggregations: { - a: { value: 1000 }, - b: { value: 1000 }, - c: { value: 1000 }, - timeseriesData: { - buckets: [ - { - a: { value: 10 }, - b: { value: 10 }, - c: { value: 10 }, - key: 1, - doc_count: 0, - }, - { - a: { value: 20 }, - b: { value: 20 }, - c: { value: 20 }, - key: 2, - doc_count: 0, - }, - { - a: { value: 30 }, - b: { value: 30 }, - c: { value: 30 }, - key: 3, - doc_count: 0, - }, - ], - }, - }, - } as any; - - const chartBase = { - title: 'Test Chart Title', - type: 'linemark' as ChartType, - key: 'test_chart_key', - yUnit: 'number' as YUnit, - series: { - a: { title: 'Series A', color: 'red' }, - b: { title: 'Series B', color: 'blue' }, - c: { title: 'Series C', color: 'green' }, - }, - }; - - const chart = transformDataToMetricsChart(response, chartBase); - - expect(chart).toMatchInlineSnapshot(` -Object { - "key": "test_chart_key", - "series": Array [ - Object { - "color": "red", - "data": Array [ - Object { - "x": 1, - "y": 10, - }, - Object { - "x": 2, - "y": 20, - }, - Object { - "x": 3, - "y": 30, - }, - ], - "key": "a", - "overallValue": 1000, - "title": "Series A", - "type": "linemark", - }, - Object { - "color": "blue", - "data": Array [ - Object { - "x": 1, - "y": 10, - }, - Object { - "x": 2, - "y": 20, - }, - Object { - "x": 3, - "y": 30, - }, - ], - "key": "b", - "overallValue": 1000, - "title": "Series B", - "type": "linemark", - }, - Object { - "color": "green", - "data": Array [ - Object { - "x": 1, - "y": 10, - }, - Object { - "x": 2, - "y": 20, - }, - Object { - "x": 3, - "y": 30, - }, - ], - "key": "c", - "overallValue": 1000, - "title": "Series C", - "type": "linemark", - }, - ], - "title": "Test Chart Title", - "yUnit": "number", -} -`); -}); diff --git a/x-pack/plugins/apm/server/lib/metrics/transform_metrics_chart.ts b/x-pack/plugins/apm/server/lib/metrics/transform_metrics_chart.ts deleted file mode 100644 index fea853af93b84..0000000000000 --- a/x-pack/plugins/apm/server/lib/metrics/transform_metrics_chart.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 { euiLightVars as theme } from '@kbn/ui-shared-deps-src/theme'; -import { ESSearchResponse } from '../../../../../../src/core/types/elasticsearch'; -import { getVizColorForIndex } from '../../../common/viz_colors'; -import { GenericMetricsRequest } from './fetch_and_transform_metrics'; -import { ChartBase } from './types'; - -export type GenericMetricsChart = ReturnType< - typeof transformDataToMetricsChart ->; - -export function transformDataToMetricsChart( - result: ESSearchResponse, - chartBase: ChartBase -) { - const { aggregations } = result; - const timeseriesData = aggregations?.timeseriesData; - - return { - title: chartBase.title, - key: chartBase.key, - yUnit: chartBase.yUnit, - series: - result.hits.total.value > 0 - ? Object.keys(chartBase.series).map((seriesKey, i) => { - const overallValue = aggregations?.[seriesKey]?.value; - - return { - title: chartBase.series[seriesKey].title, - key: seriesKey, - type: chartBase.type, - color: - chartBase.series[seriesKey].color || - getVizColorForIndex(i, theme), - overallValue, - data: - timeseriesData?.buckets.map((bucket) => { - const { value } = bucket[seriesKey]; - const y = value === null || isNaN(value) ? null : value; - return { - x: bucket.key, - y, - }; - }) || [], - }; - }) - : [], - }; -} diff --git a/x-pack/plugins/apm/server/lib/service_map/get_service_map.ts b/x-pack/plugins/apm/server/lib/service_map/get_service_map.ts index aaf55413d9774..9f94bdd9275c0 100644 --- a/x-pack/plugins/apm/server/lib/service_map/get_service_map.ts +++ b/x-pack/plugins/apm/server/lib/service_map/get_service_map.ts @@ -156,7 +156,6 @@ async function getServicesData(options: IEnvOptions) { export type ConnectionsResponse = PromiseReturnType; export type ServicesResponse = PromiseReturnType; -export type ServiceMapAPIResponse = PromiseReturnType; export function getServiceMap(options: IEnvOptions) { return withApmSpan('get_service_map', async () => { diff --git a/x-pack/plugins/apm/server/lib/service_nodes/__snapshots__/queries.test.ts.snap b/x-pack/plugins/apm/server/lib/service_nodes/__snapshots__/queries.test.ts.snap index 1b72fc8867570..e0591a90b1c19 100644 --- a/x-pack/plugins/apm/server/lib/service_nodes/__snapshots__/queries.test.ts.snap +++ b/x-pack/plugins/apm/server/lib/service_nodes/__snapshots__/queries.test.ts.snap @@ -35,11 +35,6 @@ Object { "service.name": "foo", }, }, - Object { - "term": Object { - "service.node.name": "bar", - }, - }, Object { "range": Object { "@timestamp": Object { @@ -49,6 +44,11 @@ Object { }, }, }, + Object { + "term": Object { + "service.node.name": "bar", + }, + }, ], }, }, @@ -92,6 +92,15 @@ Object { "service.name": "foo", }, }, + Object { + "range": Object { + "@timestamp": Object { + "format": "epoch_millis", + "gte": 0, + "lte": 50000, + }, + }, + }, Object { "bool": Object { "must_not": Array [ @@ -103,15 +112,6 @@ Object { ], }, }, - Object { - "range": Object { - "@timestamp": Object { - "format": "epoch_millis", - "gte": 0, - "lte": 50000, - }, - }, - }, ], }, }, @@ -191,6 +191,7 @@ Object { ], }, }, + "size": 0, }, } `; diff --git a/x-pack/plugins/apm/server/lib/service_nodes/index.ts b/x-pack/plugins/apm/server/lib/service_nodes/index.ts index 0ae7274c3b33f..541fbb79c9e50 100644 --- a/x-pack/plugins/apm/server/lib/service_nodes/index.ts +++ b/x-pack/plugins/apm/server/lib/service_nodes/index.ts @@ -14,8 +14,13 @@ import { } from '../../../common/elasticsearch_fieldnames'; import { SERVICE_NODE_NAME_MISSING } from '../../../common/service_nodes'; import { asMutableArray } from '../../../common/utils/as_mutable_array'; -import { getServiceNodesProjection } from '../../projections/service_nodes'; -import { mergeProjection } from '../../projections/util/merge_projection'; +import { + SERVICE_NAME, + SERVICE_NODE_NAME, +} from '../../../common/elasticsearch_fieldnames'; +import { ProcessorEvent } from '../../../common/processor_event'; +import { kqlQuery, rangeQuery } from '../../../../observability/server'; +import { environmentQuery } from '../../../common/utils/environment_query'; import { Setup } from '../helpers/setup_request'; const getServiceNodes = async ({ @@ -35,20 +40,26 @@ const getServiceNodes = async ({ }) => { const { apmEventClient } = setup; - const projection = getServiceNodesProjection({ - kuery, - serviceName, - environment, - start, - end, - }); - - const params = mergeProjection(projection, { + const params = { + apm: { + events: [ProcessorEvent.metric], + }, body: { + size: 0, + query: { + bool: { + filter: [ + { term: { [SERVICE_NAME]: serviceName } }, + ...rangeQuery(start, end), + ...environmentQuery(environment), + ...kqlQuery(kuery), + ], + }, + }, aggs: { nodes: { terms: { - ...projection.body.aggs.nodes.terms, + field: SERVICE_NODE_NAME, size: 10000, missing: SERVICE_NODE_NAME_MISSING, }, @@ -57,7 +68,7 @@ const getServiceNodes = async ({ top_metrics: { metrics: asMutableArray([{ field: HOST_NAME }] as const), sort: { - '@timestamp': 'desc', + '@timestamp': 'desc' as const, }, }, }, @@ -85,7 +96,7 @@ const getServiceNodes = async ({ }, }, }, - }); + }; const response = await apmEventClient.search('get_service_nodes', params); diff --git a/x-pack/plugins/apm/server/lib/services/get_service_node_metadata.ts b/x-pack/plugins/apm/server/lib/services/get_service_node_metadata.ts index ef52c4b0f4927..ab0fa91529917 100644 --- a/x-pack/plugins/apm/server/lib/services/get_service_node_metadata.ts +++ b/x-pack/plugins/apm/server/lib/services/get_service_node_metadata.ts @@ -11,8 +11,16 @@ import { CONTAINER_ID, } from '../../../common/elasticsearch_fieldnames'; import { NOT_AVAILABLE_LABEL } from '../../../common/i18n'; -import { mergeProjection } from '../../projections/util/merge_projection'; -import { getServiceNodesProjection } from '../../projections/service_nodes'; +import { + SERVICE_NAME, + SERVICE_NODE_NAME, +} from '../../../common/elasticsearch_fieldnames'; +import { ProcessorEvent } from '../../../common/processor_event'; +import { kqlQuery, rangeQuery } from '../../../../observability/server'; +import { + environmentQuery, + serviceNodeNameQuery, +} from '../../../common/utils/environment_query'; import { ENVIRONMENT_ALL } from '../../../common/environment_filter_values'; export async function getServiceNodeMetadata({ @@ -32,39 +40,48 @@ export async function getServiceNodeMetadata({ }) { const { apmEventClient } = setup; - const query = mergeProjection( - getServiceNodesProjection({ - kuery, - serviceName, - serviceNodeName, - environment: ENVIRONMENT_ALL.value, - start, - end, - }), - { - body: { - size: 0, - aggs: { - host: { - terms: { - field: HOST_NAME, - size: 1, - }, + const params = { + apm: { + events: [ProcessorEvent.metric], + }, + body: { + size: 0, + query: { + bool: { + filter: [ + { term: { [SERVICE_NAME]: serviceName } }, + ...rangeQuery(start, end), + ...environmentQuery(ENVIRONMENT_ALL.value), + ...kqlQuery(kuery), + ...serviceNodeNameQuery(serviceNodeName), + ], + }, + }, + aggs: { + nodes: { + terms: { + field: SERVICE_NODE_NAME, }, - containerId: { - terms: { - field: CONTAINER_ID, - size: 1, - }, + }, + host: { + terms: { + field: HOST_NAME, + size: 1, + }, + }, + containerId: { + terms: { + field: CONTAINER_ID, + size: 1, }, }, }, - } - ); + }, + }; const response = await apmEventClient.search( 'get_service_node_metadata', - query + params ); return { diff --git a/x-pack/plugins/apm/server/lib/settings/agent_configuration/get_environments/index.ts b/x-pack/plugins/apm/server/lib/settings/agent_configuration/get_environments/index.ts index dadb29d156e0b..a22c1d35dc663 100644 --- a/x-pack/plugins/apm/server/lib/settings/agent_configuration/get_environments/index.ts +++ b/x-pack/plugins/apm/server/lib/settings/agent_configuration/get_environments/index.ts @@ -8,14 +8,9 @@ import { withApmSpan } from '../../../../utils/with_apm_span'; import { getAllEnvironments } from '../../../environments/get_all_environments'; import { Setup } from '../../../helpers/setup_request'; -import { PromiseReturnType } from '../../../../../../observability/typings/common'; import { getExistingEnvironmentsForService } from './get_existing_environments_for_service'; import { ALL_OPTION_VALUE } from '../../../../../common/agent_configuration/all_option'; -export type AgentConfigurationEnvironmentsAPIResponse = PromiseReturnType< - typeof getEnvironments ->; - export async function getEnvironments({ serviceName, setup, diff --git a/x-pack/plugins/apm/server/lib/settings/agent_configuration/get_service_names.ts b/x-pack/plugins/apm/server/lib/settings/agent_configuration/get_service_names.ts index 06bd900872a20..fc5167159b98d 100644 --- a/x-pack/plugins/apm/server/lib/settings/agent_configuration/get_service_names.ts +++ b/x-pack/plugins/apm/server/lib/settings/agent_configuration/get_service_names.ts @@ -7,15 +7,10 @@ import { ProcessorEvent } from '../../../../common/processor_event'; import { Setup } from '../../helpers/setup_request'; -import { PromiseReturnType } from '../../../../../observability/typings/common'; import { SERVICE_NAME } from '../../../../common/elasticsearch_fieldnames'; import { ALL_OPTION_VALUE } from '../../../../common/agent_configuration/all_option'; import { getProcessorEventForTransactions } from '../../helpers/transactions'; -export type AgentConfigurationServicesAPIResponse = PromiseReturnType< - typeof getServiceNames ->; - export async function getServiceNames({ setup, searchAggregatedTransactions, diff --git a/x-pack/plugins/apm/server/projections/errors.ts b/x-pack/plugins/apm/server/projections/errors.ts deleted file mode 100644 index b256428143400..0000000000000 --- a/x-pack/plugins/apm/server/projections/errors.ts +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { - SERVICE_NAME, - ERROR_GROUP_ID, -} from '../../common/elasticsearch_fieldnames'; -import { rangeQuery, kqlQuery } from '../../../observability/server'; -import { environmentQuery } from '../../common/utils/environment_query'; -import { ProcessorEvent } from '../../common/processor_event'; - -export function getErrorGroupsProjection({ - environment, - kuery, - serviceName, - start, - end, -}: { - environment: string; - kuery: string; - serviceName: string; - start: number; - end: number; -}) { - return { - apm: { - events: [ProcessorEvent.error as const], - }, - body: { - query: { - bool: { - filter: [ - { term: { [SERVICE_NAME]: serviceName } }, - ...rangeQuery(start, end), - ...environmentQuery(environment), - ...kqlQuery(kuery), - ], - }, - }, - aggs: { - error_groups: { - terms: { - field: ERROR_GROUP_ID, - }, - }, - }, - }, - }; -} diff --git a/x-pack/plugins/apm/server/projections/metrics.ts b/x-pack/plugins/apm/server/projections/metrics.ts deleted file mode 100644 index 417281f2de487..0000000000000 --- a/x-pack/plugins/apm/server/projections/metrics.ts +++ /dev/null @@ -1,65 +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 { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; -import { - SERVICE_NAME, - SERVICE_NODE_NAME, -} from '../../common/elasticsearch_fieldnames'; -import { rangeQuery, kqlQuery } from '../../../observability/server'; -import { environmentQuery } from '../../common/utils/environment_query'; -import { SERVICE_NODE_NAME_MISSING } from '../../common/service_nodes'; -import { ProcessorEvent } from '../../common/processor_event'; - -function getServiceNodeNameFilters(serviceNodeName?: string) { - if (!serviceNodeName) { - return []; - } - - if (serviceNodeName === SERVICE_NODE_NAME_MISSING) { - return [{ bool: { must_not: [{ exists: { field: SERVICE_NODE_NAME } }] } }]; - } - - return [{ term: { [SERVICE_NODE_NAME]: serviceNodeName } }]; -} - -export function getMetricsProjection({ - environment, - kuery, - serviceName, - serviceNodeName, - start, - end, -}: { - environment: string; - kuery: string; - serviceName: string; - serviceNodeName?: string; - start: number; - end: number; -}) { - const filter = [ - { term: { [SERVICE_NAME]: serviceName } }, - ...getServiceNodeNameFilters(serviceNodeName), - ...rangeQuery(start, end), - ...environmentQuery(environment), - ...kqlQuery(kuery), - ] as QueryDslQueryContainer[]; - - return { - apm: { - events: [ProcessorEvent.metric], - }, - body: { - query: { - bool: { - filter, - }, - }, - }, - }; -} diff --git a/x-pack/plugins/apm/server/projections/service_nodes.ts b/x-pack/plugins/apm/server/projections/service_nodes.ts deleted file mode 100644 index 5d97af0ad9860..0000000000000 --- a/x-pack/plugins/apm/server/projections/service_nodes.ts +++ /dev/null @@ -1,48 +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 { SERVICE_NODE_NAME } from '../../common/elasticsearch_fieldnames'; -import { mergeProjection } from './util/merge_projection'; -import { getMetricsProjection } from './metrics'; - -export function getServiceNodesProjection({ - serviceName, - serviceNodeName, - environment, - kuery, - start, - end, -}: { - serviceName: string; - serviceNodeName?: string; - environment: string; - kuery: string; - start: number; - end: number; -}) { - return mergeProjection( - getMetricsProjection({ - serviceName, - serviceNodeName, - environment, - kuery, - start, - end, - }), - { - body: { - aggs: { - nodes: { - terms: { - field: SERVICE_NODE_NAME, - }, - }, - }, - }, - } - ); -} diff --git a/x-pack/plugins/apm/server/routes/metrics.ts b/x-pack/plugins/apm/server/routes/metrics.ts index 1817c3e1546bd..36a504859797a 100644 --- a/x-pack/plugins/apm/server/routes/metrics.ts +++ b/x-pack/plugins/apm/server/routes/metrics.ts @@ -37,7 +37,8 @@ const metricsChartsRoute = createApmServerRoute({ const { serviceName } = params.path; const { agentName, environment, kuery, serviceNodeName, start, end } = params.query; - return await getMetricsChartDataByAgent({ + + const charts = await getMetricsChartDataByAgent({ environment, kuery, setup, @@ -47,6 +48,8 @@ const metricsChartsRoute = createApmServerRoute({ start, end, }); + + return { charts }; }, }); diff --git a/x-pack/test/apm_api_integration/tests/metrics_charts/metrics_charts.spec.ts b/x-pack/test/apm_api_integration/tests/metrics_charts/metrics_charts.spec.ts index 74af2c2dba008..d70ee347d4c2d 100644 --- a/x-pack/test/apm_api_integration/tests/metrics_charts/metrics_charts.spec.ts +++ b/x-pack/test/apm_api_integration/tests/metrics_charts/metrics_charts.spec.ts @@ -7,35 +7,39 @@ import expect from '@kbn/expect'; import { first } from 'lodash'; -import { MetricsChartsByAgentAPIResponse } from '../../../../plugins/apm/server/lib/metrics/get_metrics_chart_data_by_agent'; -import { GenericMetricsChart } from '../../../../plugins/apm/server/lib/metrics/transform_metrics_chart'; +import { GenericMetricsChart } from '../../../../plugins/apm/server/lib/metrics/fetch_and_transform_metrics'; +import { SupertestReturnType } from '../../common/apm_api_supertest'; import { FtrProviderContext } from '../../common/ftr_provider_context'; -interface ChartResponse { - body: MetricsChartsByAgentAPIResponse; - status: number; -} +type ChartResponse = SupertestReturnType<'GET /internal/apm/services/{serviceName}/metrics/charts'>; export default function ApiTest({ getService }: FtrProviderContext) { const registry = getService('registry'); - const supertest = getService('legacySupertestAsApmReadUser'); + const apmApiClient = getService('apmApiClient'); registry.when( 'Metrics charts when data is loaded', { config: 'basic', archives: ['metrics_8.0.0'] }, () => { describe('for opbeans-node', () => { - const start = encodeURIComponent('2020-09-08T14:50:00.000Z'); - const end = encodeURIComponent('2020-09-08T14:55:00.000Z'); - const agentName = 'nodejs'; - describe('returns metrics data', () => { let chartsResponse: ChartResponse; before(async () => { - chartsResponse = await supertest.get( - `/internal/apm/services/opbeans-node/metrics/charts?start=${start}&end=${end}&agentName=${agentName}&kuery=&environment=ENVIRONMENT_ALL` - ); + chartsResponse = await apmApiClient.readUser({ + endpoint: 'GET /internal/apm/services/{serviceName}/metrics/charts', + params: { + path: { serviceName: 'opbeans-node' }, + query: { + start: '2020-09-08T14:50:00.000Z', + end: '2020-09-08T14:55:00.000Z', + agentName: 'nodejs', + environment: 'ENVIRONMENT_ALL', + kuery: ``, + }, + }, + }); }); + it('contains CPU usage and System memory usage chart data', async () => { expect(chartsResponse.status).to.be(200); expectSnapshot(chartsResponse.body.charts.map((chart) => chart.title)).toMatchInline(` @@ -112,17 +116,22 @@ export default function ApiTest({ getService }: FtrProviderContext) { }); describe('for opbeans-java', () => { - const agentName = 'java'; - describe('returns metrics data', () => { - const start = encodeURIComponent('2020-09-08T14:55:30.000Z'); - const end = encodeURIComponent('2020-09-08T15:00:00.000Z'); - let chartsResponse: ChartResponse; before(async () => { - chartsResponse = await supertest.get( - `/internal/apm/services/opbeans-java/metrics/charts?start=${start}&end=${end}&agentName=${agentName}&environment=ENVIRONMENT_ALL&kuery=` - ); + chartsResponse = await apmApiClient.readUser({ + endpoint: 'GET /internal/apm/services/{serviceName}/metrics/charts', + params: { + path: { serviceName: 'opbeans-java' }, + query: { + start: '2020-09-08T14:55:30.000Z', + end: '2020-09-08T15:00:00.000Z', + agentName: 'java', + environment: 'ENVIRONMENT_ALL', + kuery: ``, + }, + }, + }); }); it('has correct chart data', async () => { @@ -406,12 +415,19 @@ export default function ApiTest({ getService }: FtrProviderContext) { // 9223372036854771712 = memory limit for a c-group when no memory limit is specified it('calculates system memory usage using system total field when cgroup limit is equal to 9223372036854771712', async () => { - const start = encodeURIComponent('2020-09-08T15:00:30.000Z'); - const end = encodeURIComponent('2020-09-08T15:05:00.000Z'); - - const chartsResponse: ChartResponse = await supertest.get( - `/internal/apm/services/opbeans-java/metrics/charts?start=${start}&end=${end}&agentName=${agentName}&environment=ENVIRONMENT_ALL&kuery=` - ); + const chartsResponse = await apmApiClient.readUser({ + endpoint: 'GET /internal/apm/services/{serviceName}/metrics/charts', + params: { + path: { serviceName: 'opbeans-java' }, + query: { + start: '2020-09-08T15:00:30.000Z', + end: '2020-09-08T15:05:00.000Z', + agentName: 'java', + environment: 'ENVIRONMENT_ALL', + kuery: ``, + }, + }, + }); const systemMemoryUsageChart = chartsResponse.body.charts.find( ({ key }) => key === 'memory_usage_chart' From a247508c82fd689b92abaaa6498f8e852c4cfd61 Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Tue, 16 Nov 2021 13:46:22 +0200 Subject: [PATCH 008/148] [Cases] Fixes configuration page flaky tests (#118521) --- .../components/configure_cases/index.test.tsx | 58 ++++++++++++------- 1 file changed, 36 insertions(+), 22 deletions(-) diff --git a/x-pack/plugins/cases/public/components/configure_cases/index.test.tsx b/x-pack/plugins/cases/public/components/configure_cases/index.test.tsx index 990d44584cf05..8843bed9a2b43 100644 --- a/x-pack/plugins/cases/public/components/configure_cases/index.test.tsx +++ b/x-pack/plugins/cases/public/components/configure_cases/index.test.tsx @@ -39,6 +39,8 @@ const useConnectorsMock = useConnectors as jest.Mock; const useCaseConfigureMock = useCaseConfigure as jest.Mock; const useGetUrlSearchMock = jest.fn(); const useActionTypesMock = useActionTypes as jest.Mock; +const getAddConnectorFlyoutMock = jest.fn(); +const getEditConnectorFlyoutMock = jest.fn(); describe('ConfigureCases', () => { beforeAll(() => { @@ -46,6 +48,12 @@ describe('ConfigureCases', () => { actionTypeTitle: '.servicenow', iconClass: 'logoSecurity', }); + + useKibanaMock().services.triggersActionsUi.getAddConnectorFlyout = + getAddConnectorFlyoutMock.mockReturnValue(
); + + useKibanaMock().services.triggersActionsUi.getEditConnectorFlyout = + getEditConnectorFlyoutMock.mockReturnValue(
); }); beforeEach(() => { @@ -72,12 +80,12 @@ describe('ConfigureCases', () => { expect(wrapper.find('[data-test-subj="closure-options-radio-group"]').exists()).toBeTruthy(); }); - test('it does NOT render the ConnectorAddFlyout', () => { - expect(wrapper.find('ConnectorAddFlyout').exists()).toBeFalsy(); + test('it does NOT render the add connector flyout', () => { + expect(wrapper.find('[data-test-subj="add-connector-flyout"]').exists()).toBeFalsy(); }); - test('it does NOT render the ConnectorEditFlyout', () => { - expect(wrapper.find('ConnectorEditFlyout').exists()).toBeFalsy(); + test('it does NOT render the edit connector flyout"]', () => { + expect(wrapper.find('[data-test-subj="edit-connector-flyout"]').exists()).toBeFalsy(); }); test('it does NOT render the EuiCallOut', () => { @@ -176,8 +184,8 @@ describe('ConfigureCases', () => { expect(wrapper.find(ClosureOptions).prop('closureTypeSelected')).toBe('close-by-user'); // Flyouts - expect(wrapper.find('ConnectorAddFlyout').exists()).toBe(false); - expect(wrapper.find('ConnectorEditFlyout').exists()).toBe(false); + expect(wrapper.find('[data-test-subj="add-connector-flyout"]').exists()).toBe(false); + expect(wrapper.find('[data-test-subj="edit-connector-flyout"]').exists()).toBe(false); }); test('it disables correctly when the user cannot crud', () => { @@ -541,21 +549,25 @@ describe('ConfigureCases', () => { await waitFor(() => { wrapper.update(); - expect(wrapper.find('ConnectorAddFlyout').exists()).toBe(true); - expect(wrapper.find('ConnectorAddFlyout').prop('actionTypes')).toEqual([ - expect.objectContaining({ - id: '.servicenow', - }), - expect.objectContaining({ - id: '.jira', - }), - expect.objectContaining({ - id: '.resilient', - }), + expect(wrapper.find('[data-test-subj="add-connector-flyout"]').exists()).toBe(true); + expect(getAddConnectorFlyoutMock).toHaveBeenCalledWith( expect.objectContaining({ - id: '.servicenow-sir', - }), - ]); + actionTypes: [ + expect.objectContaining({ + id: '.servicenow', + }), + expect.objectContaining({ + id: '.jira', + }), + expect.objectContaining({ + id: '.resilient', + }), + expect.objectContaining({ + id: '.servicenow-sir', + }), + ], + }) + ); }); }); @@ -588,8 +600,10 @@ describe('ConfigureCases', () => { await waitFor(() => { wrapper.update(); - expect(wrapper.find('ConnectorEditFlyout').exists()).toBe(true); - expect(wrapper.find('ConnectorEditFlyout').prop('initialConnector')).toEqual(connectors[1]); + expect(wrapper.find('[data-test-subj="edit-connector-flyout"]').exists()).toBe(true); + expect(getEditConnectorFlyoutMock).toHaveBeenCalledWith( + expect.objectContaining({ initialConnector: connectors[1] }) + ); }); expect( From f7344efedc08cbc35400612f905a55dce518f664 Mon Sep 17 00:00:00 2001 From: Yaroslav Kuznietsov Date: Tue, 16 Nov 2021 13:57:39 +0200 Subject: [PATCH 009/148] [Expressions] `columns`. Fixes Bugs caused by using name instead of ID. (#118470) * Fixed behavior of the columns function. * updated tests to check for `id` matching in addition to the `name`. Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../common/__fixtures__/test_tables.ts | 14 ++++++ .../functions/common/columns.test.js | 30 ++++++++---- .../functions/common/columns.ts | 48 +++++++++++++------ 3 files changed, 68 insertions(+), 24 deletions(-) diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__fixtures__/test_tables.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__fixtures__/test_tables.ts index 18aa70534b0ba..22c4d16d9810a 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__fixtures__/test_tables.ts +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__fixtures__/test_tables.ts @@ -21,6 +21,11 @@ const testTable: Datatable = { name: 'name', meta: { type: 'string' }, }, + { + id: 'title_id', + name: 'title', + meta: { type: 'string' }, + }, { id: 'time', name: 'time', @@ -49,6 +54,7 @@ const testTable: Datatable = { price: 605, quantity: 100, in_stock: true, + title_id: 'title1', }, { name: 'product1', @@ -56,6 +62,7 @@ const testTable: Datatable = { price: 583, quantity: 200, in_stock: true, + title_id: 'title2', }, { name: 'product1', @@ -63,6 +70,7 @@ const testTable: Datatable = { price: 420, quantity: 300, in_stock: true, + title_id: 'title3', }, { name: 'product2', @@ -70,6 +78,7 @@ const testTable: Datatable = { price: 216, quantity: 350, in_stock: false, + title_id: 'title4', }, { name: 'product2', @@ -77,6 +86,7 @@ const testTable: Datatable = { price: 200, quantity: 256, in_stock: false, + title_id: 'title5', }, { name: 'product2', @@ -84,6 +94,7 @@ const testTable: Datatable = { price: 190, quantity: 231, in_stock: false, + title_id: 'title6', }, { name: 'product3', @@ -91,6 +102,7 @@ const testTable: Datatable = { price: 67, quantity: 240, in_stock: true, + title_id: 'title7', }, { name: 'product4', @@ -98,6 +110,7 @@ const testTable: Datatable = { price: 311, quantity: 447, in_stock: false, + title_id: 'title8', }, { name: 'product5', @@ -105,6 +118,7 @@ const testTable: Datatable = { price: 288, quantity: 384, in_stock: true, + title_id: 'title9', }, ], }; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/columns.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/columns.test.js index d7f28559ee0ef..0184920285a6d 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/columns.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/columns.test.js @@ -20,15 +20,20 @@ describe('columns', () => { it('returns a datatable with included columns and without excluded columns', () => { const arbitraryRowIndex = 7; const result = fn(testTable, { - include: 'name, price, quantity, foo, bar', + include: 'name, title_id, price, quantity, foo, bar', exclude: 'price, quantity, fizz, buzz', }); expect(result.columns[0]).toHaveProperty('name', 'name'); + expect(result.columns[1]).toHaveProperty('id', 'title_id'); expect(result.rows[arbitraryRowIndex]).toHaveProperty( 'name', testTable.rows[arbitraryRowIndex].name ); + expect(result.rows[arbitraryRowIndex]).toHaveProperty( + 'title_id', + testTable.rows[arbitraryRowIndex].title_id + ); expect(result.rows[arbitraryRowIndex]).not.toHaveProperty('price'); expect(result.rows[arbitraryRowIndex]).not.toHaveProperty('quantity'); expect(result.rows[arbitraryRowIndex]).not.toHaveProperty('foo'); @@ -46,8 +51,8 @@ describe('columns', () => { expect( fn(testTable, { - include: 'price, quantity, in_stock', - exclude: 'price, quantity, in_stock', + include: 'price, quantity, in_stock, title_id', + exclude: 'price, quantity, in_stock, title_id', }) ).toEqual(emptyTable); }); @@ -56,15 +61,17 @@ describe('columns', () => { it('returns a datatable with included columns only', () => { const arbitraryRowIndex = 3; const result = fn(testTable, { - include: 'name, time, in_stock', + include: 'name, time, in_stock, title_id', }); - expect(result.columns).toHaveLength(3); - expect(Object.keys(result.rows[0])).toHaveLength(3); + expect(result.columns).toHaveLength(4); + expect(Object.keys(result.rows[0])).toHaveLength(4); expect(result.columns[0]).toHaveProperty('name', 'name'); expect(result.columns[1]).toHaveProperty('name', 'time'); expect(result.columns[2]).toHaveProperty('name', 'in_stock'); + expect(result.columns[3]).toHaveProperty('id', 'title_id'); + expect(result.rows[arbitraryRowIndex]).toHaveProperty( 'name', testTable.rows[arbitraryRowIndex].name @@ -77,6 +84,10 @@ describe('columns', () => { 'in_stock', testTable.rows[arbitraryRowIndex].in_stock ); + expect(result.rows[arbitraryRowIndex]).toHaveProperty( + 'title_id', + testTable.rows[arbitraryRowIndex].title_id + ); }); it('ignores invalid columns', () => { @@ -102,14 +113,15 @@ describe('columns', () => { describe('exclude', () => { it('returns a datatable without excluded columns', () => { const arbitraryRowIndex = 5; - const result = fn(testTable, { exclude: 'price, quantity, foo, bar' }); + const result = fn(testTable, { exclude: 'price, quantity, foo, bar, title_id' }); - expect(result.columns.length).toEqual(testTable.columns.length - 2); - expect(Object.keys(result.rows[0])).toHaveLength(testTable.columns.length - 2); + expect(result.columns.length).toEqual(testTable.columns.length - 3); + expect(Object.keys(result.rows[0])).toHaveLength(testTable.columns.length - 3); expect(result.rows[arbitraryRowIndex]).not.toHaveProperty('price'); expect(result.rows[arbitraryRowIndex]).not.toHaveProperty('quantity'); expect(result.rows[arbitraryRowIndex]).not.toHaveProperty('foo'); expect(result.rows[arbitraryRowIndex]).not.toHaveProperty('bar'); + expect(result.rows[arbitraryRowIndex]).not.toHaveProperty('title_id'); }); it('ignores invalid columns', () => { diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/columns.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/columns.ts index a81368e23a477..e627086d70d9d 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/columns.ts +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/columns.ts @@ -14,6 +14,26 @@ interface Arguments { exclude: string; } +const prepareFields = (fields: string) => fields.split(',').map((field) => field.trim()); + +const getFieldsIds = (cols: DatatableColumn[]) => cols.map((col) => col.id ?? col.name); + +const splitColumnsByFields = ( + cols: DatatableColumn[], + fields: string[], + saveOther: boolean = false +) => + cols.reduce<{ matched: DatatableColumn[]; other: DatatableColumn[] }>( + (splitColumns, col) => { + if (fields.includes(col.id) || fields.includes(col.name)) { + return { ...splitColumns, matched: [...splitColumns.matched, col] }; + } + + return saveOther ? { ...splitColumns, other: [...splitColumns.other, col] } : splitColumns; + }, + { matched: [], other: [] } + ); + export function columns(): ExpressionFunctionDefinition< 'columns', Datatable, @@ -44,27 +64,25 @@ export function columns(): ExpressionFunctionDefinition< let result = { ...input }; if (exclude) { - const fields = exclude.split(',').map((field) => field.trim()); - const cols = contextColumns.filter((col) => !fields.includes(col.name)); - const rows = cols.length > 0 ? contextRows.map((row) => omit(row, fields)) : []; - - result = { rows, columns: cols, ...rest }; + const fields = prepareFields(exclude); + const { matched: excluded, other } = splitColumnsByFields(result.columns, fields, true); + const fieldsIds = getFieldsIds(excluded); + const rows = excluded.length ? result.rows.map((row) => omit(row, fieldsIds)) : result.rows; + result = { rows, columns: other, ...rest }; } if (include) { - const fields = include.split(',').map((field) => field.trim()); - // const columns = result.columns.filter(col => fields.includes(col.name)); + const fields = prepareFields(include); + const { matched: included } = splitColumnsByFields(result.columns, fields); + const fieldsIds = getFieldsIds(included); // Include columns in the order the user specified - const cols: DatatableColumn[] = []; + const cols = fields.reduce((includedCols, field) => { + const column = find(included, (col) => col.id === field || col.name === field); + return column ? [...includedCols, column] : includedCols; + }, []); - fields.forEach((field) => { - const column = find(result.columns, { name: field }); - if (column) { - cols.push(column); - } - }); - const rows = cols.length > 0 ? result.rows.map((row) => pick(row, fields)) : []; + const rows = cols.length ? result.rows.map((row) => pick(row, fieldsIds)) : []; result = { rows, columns: cols, ...rest }; } From 8087bc2d5122468aa888afe2007f8a9e9209c6da Mon Sep 17 00:00:00 2001 From: Mikhail Shustov Date: Tue, 16 Nov 2021 13:46:39 +0100 Subject: [PATCH 010/148] do not re-export apm agent from fleet (#118586) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- x-pack/plugins/fleet/server/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/x-pack/plugins/fleet/server/index.ts b/x-pack/plugins/fleet/server/index.ts index c3dd408925cf0..17425050a4e10 100644 --- a/x-pack/plugins/fleet/server/index.ts +++ b/x-pack/plugins/fleet/server/index.ts @@ -17,7 +17,6 @@ import { import { FleetPlugin } from './plugin'; -export { default as apm } from 'elastic-apm-node'; export type { AgentService, ESIndexPatternService, From 6f8ca2e79290aa8dccc8ec7e8e1d490b0e728d75 Mon Sep 17 00:00:00 2001 From: Phillip Burch Date: Tue, 16 Nov 2021 06:52:19 -0600 Subject: [PATCH 011/148] Fix bug with manage views button (#118547) --- .../infra/public/components/saved_views/toolbar_control.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/infra/public/components/saved_views/toolbar_control.tsx b/x-pack/plugins/infra/public/components/saved_views/toolbar_control.tsx index 9ed4047e45bd3..bb9e7ced40c53 100644 --- a/x-pack/plugins/infra/public/components/saved_views/toolbar_control.tsx +++ b/x-pack/plugins/infra/public/components/saved_views/toolbar_control.tsx @@ -75,8 +75,12 @@ export function SavedViewsToolbarControls(props: Props) { setModalOpen(true); }, [find, hideSavedViewMenu]); const showSavedViewMenu = useCallback(() => { + if (isSavedViewMenuOpen) { + setIsSavedViewMenuOpen(false); + return; + } setIsSavedViewMenuOpen(true); - }, [setIsSavedViewMenuOpen]); + }, [setIsSavedViewMenuOpen, isSavedViewMenuOpen]); const save = useCallback( (name: string, hasTime: boolean = false) => { const currentState = { From e08c633156ed865010e12349ee767fbea8f72474 Mon Sep 17 00:00:00 2001 From: Pierre Gayvallet Date: Tue, 16 Nov 2021 13:53:53 +0100 Subject: [PATCH 012/148] [SO migration] fail the migration if unknown types are encountered (#118300) * manually revert #105213 * enabled xpack to register types for some IT tests * fiz doc size Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../actions/check_for_unknown_docs.test.ts | 16 +- .../actions/check_for_unknown_docs.ts | 17 +- .../saved_objects/migrations/actions/index.ts | 2 + .../migrations/core/migrate_raw_docs.test.ts | 43 ---- .../migrations/core/migrate_raw_docs.ts | 10 +- .../7_13_0_unknown_types.test.ts | 214 ++++-------------- .../batch_size_bytes.test.ts | 6 +- .../collects_corrupt_docs.test.ts | 2 +- .../migrations/kibana_migrator.ts | 1 - .../migrations/model/extract_errors.test.ts | 2 +- .../migrations/model/extract_errors.ts | 9 +- .../migrations/model/model.test.ts | 49 +--- .../saved_objects/migrations/model/model.ts | 26 +-- 13 files changed, 96 insertions(+), 301 deletions(-) diff --git a/src/core/server/saved_objects/migrations/actions/check_for_unknown_docs.test.ts b/src/core/server/saved_objects/migrations/actions/check_for_unknown_docs.test.ts index 8a99d28b40de1..0ddb858f91bc0 100644 --- a/src/core/server/saved_objects/migrations/actions/check_for_unknown_docs.test.ts +++ b/src/core/server/saved_objects/migrations/actions/check_for_unknown_docs.test.ts @@ -98,12 +98,10 @@ describe('checkForUnknownDocs', () => { const result = await task(); expect(Either.isRight(result)).toBe(true); - expect((result as Either.Right).right).toEqual({ - unknownDocs: [], - }); + expect((result as Either.Right).right).toEqual({}); }); - it('resolves with `Either.right` when unknown docs are found', async () => { + it('resolves with `Either.left` when unknown docs are found', async () => { const client = elasticsearchClientMock.createInternalClient( elasticsearchClientMock.createSuccessTransportRequestPromise({ hits: { @@ -124,8 +122,9 @@ describe('checkForUnknownDocs', () => { const result = await task(); - expect(Either.isRight(result)).toBe(true); - expect((result as Either.Right).right).toEqual({ + expect(Either.isLeft(result)).toBe(true); + expect((result as Either.Left).left).toEqual({ + type: 'unknown_docs_found', unknownDocs: [ { id: '12', type: 'foo' }, { id: '14', type: 'bar' }, @@ -151,8 +150,9 @@ describe('checkForUnknownDocs', () => { const result = await task(); - expect(Either.isRight(result)).toBe(true); - expect((result as Either.Right).right).toEqual({ + expect(Either.isLeft(result)).toBe(true); + expect((result as Either.Left).left).toEqual({ + type: 'unknown_docs_found', unknownDocs: [{ id: '12', type: 'unknown' }], }); }); diff --git a/src/core/server/saved_objects/migrations/actions/check_for_unknown_docs.ts b/src/core/server/saved_objects/migrations/actions/check_for_unknown_docs.ts index cfeda0548b16a..6dd8fbda73c95 100644 --- a/src/core/server/saved_objects/migrations/actions/check_for_unknown_docs.ts +++ b/src/core/server/saved_objects/migrations/actions/check_for_unknown_docs.ts @@ -32,6 +32,7 @@ export interface CheckForUnknownDocsFoundDoc { /** @internal */ export interface UnknownDocsFound { + type: 'unknown_docs_found'; unknownDocs: CheckForUnknownDocsFoundDoc[]; } @@ -41,7 +42,10 @@ export const checkForUnknownDocs = indexName, unusedTypesQuery, knownTypes, - }: CheckForUnknownDocsParams): TaskEither.TaskEither => + }: CheckForUnknownDocsParams): TaskEither.TaskEither< + RetryableEsClientError | UnknownDocsFound, + {} + > => () => { const query = createUnknownDocQuery(unusedTypesQuery, knownTypes); @@ -54,9 +58,14 @@ export const checkForUnknownDocs = }) .then((response) => { const { hits } = response.body.hits; - return Either.right({ - unknownDocs: hits.map((hit) => ({ id: hit._id, type: hit._source?.type ?? 'unknown' })), - }); + if (hits.length) { + return Either.left({ + type: 'unknown_docs_found' as const, + unknownDocs: hits.map((hit) => ({ id: hit._id, type: hit._source?.type ?? 'unknown' })), + }); + } else { + return Either.right({}); + } }) .catch(catchRetryableEsClientErrors); }; diff --git a/src/core/server/saved_objects/migrations/actions/index.ts b/src/core/server/saved_objects/migrations/actions/index.ts index 158d97f3b7c27..4e88e9c448d40 100644 --- a/src/core/server/saved_objects/migrations/actions/index.ts +++ b/src/core/server/saved_objects/migrations/actions/index.ts @@ -80,6 +80,7 @@ export type { } from './update_and_pickup_mappings'; export { updateAndPickupMappings } from './update_and_pickup_mappings'; +import type { UnknownDocsFound } from './check_for_unknown_docs'; export type { CheckForUnknownDocsParams, UnknownDocsFound, @@ -141,6 +142,7 @@ export interface ActionErrorTypeMap { remove_index_not_a_concrete_index: RemoveIndexNotAConcreteIndex; documents_transform_failed: DocumentsTransformFailed; request_entity_too_large_exception: RequestEntityTooLargeException; + unknown_docs_found: UnknownDocsFound; } /** diff --git a/src/core/server/saved_objects/migrations/core/migrate_raw_docs.test.ts b/src/core/server/saved_objects/migrations/core/migrate_raw_docs.test.ts index c8ff79351aadb..1effabe7bfc96 100644 --- a/src/core/server/saved_objects/migrations/core/migrate_raw_docs.test.ts +++ b/src/core/server/saved_objects/migrations/core/migrate_raw_docs.test.ts @@ -139,7 +139,6 @@ describe('migrateRawDocsSafely', () => { ]); const task = migrateRawDocsSafely({ serializer: new SavedObjectsSerializer(new SavedObjectTypeRegistry()), - knownTypes: new Set(['a', 'c']), migrateDoc: transform, rawDocs: [ { _id: 'a:b', _source: { type: 'a', a: { name: 'AAA' } } }, @@ -184,7 +183,6 @@ describe('migrateRawDocsSafely', () => { ]); const task = migrateRawDocsSafely({ serializer: new SavedObjectsSerializer(new SavedObjectTypeRegistry()), - knownTypes: new Set(['a', 'c']), migrateDoc: transform, rawDocs: [ { _id: 'foo:b', _source: { type: 'a', a: { name: 'AAA' } } }, @@ -206,7 +204,6 @@ describe('migrateRawDocsSafely', () => { ]); const task = migrateRawDocsSafely({ serializer: new SavedObjectsSerializer(new SavedObjectTypeRegistry()), - knownTypes: new Set(['a', 'c']), migrateDoc: transform, rawDocs: [{ _id: 'a:b', _source: { type: 'a', a: { name: 'AAA' } } }], }); @@ -240,7 +237,6 @@ describe('migrateRawDocsSafely', () => { }); const task = migrateRawDocsSafely({ serializer: new SavedObjectsSerializer(new SavedObjectTypeRegistry()), - knownTypes: new Set(['a', 'c']), migrateDoc: transform, rawDocs: [{ _id: 'a:b', _source: { type: 'a', a: { name: 'AAA' } } }], // this is the raw doc }); @@ -256,43 +252,4 @@ describe('migrateRawDocsSafely', () => { } `); }); - - test('skips documents of unknown types', async () => { - const transform = jest.fn((doc: any) => [ - set(_.cloneDeep(doc), 'attributes.name', 'HOI!'), - ]); - const task = migrateRawDocsSafely({ - serializer: new SavedObjectsSerializer(new SavedObjectTypeRegistry()), - knownTypes: new Set(['a']), - migrateDoc: transform, - rawDocs: [ - { _id: 'a:b', _source: { type: 'a', a: { name: 'AAA' } } }, - { _id: 'c:d', _source: { type: 'c', c: { name: 'DDD' } } }, - ], - }); - - const result = (await task()) as Either.Right; - expect(result._tag).toEqual('Right'); - expect(result.right.processedDocs).toEqual([ - { - _id: 'a:b', - _source: { type: 'a', a: { name: 'HOI!' }, migrationVersion: {}, references: [] }, - }, - { - _id: 'c:d', - // name field is not migrated on unknown type - _source: { type: 'c', c: { name: 'DDD' } }, - }, - ]); - - const obj1 = { - id: 'b', - type: 'a', - attributes: { name: 'AAA' }, - migrationVersion: {}, - references: [], - }; - expect(transform).toHaveBeenCalledTimes(1); - expect(transform).toHaveBeenNthCalledWith(1, obj1); - }); }); diff --git a/src/core/server/saved_objects/migrations/core/migrate_raw_docs.ts b/src/core/server/saved_objects/migrations/core/migrate_raw_docs.ts index 65ea21a6778d5..fb9176d111c8e 100644 --- a/src/core/server/saved_objects/migrations/core/migrate_raw_docs.ts +++ b/src/core/server/saved_objects/migrations/core/migrate_raw_docs.ts @@ -25,13 +25,16 @@ export interface DocumentsTransformFailed { readonly corruptDocumentIds: string[]; readonly transformErrors: TransformErrorObjects[]; } + export interface DocumentsTransformSuccess { readonly processedDocs: SavedObjectsRawDoc[]; } + export interface TransformErrorObjects { readonly rawId: string; readonly err: TransformSavedObjectDocumentError | Error; } + type MigrateFn = ( doc: SavedObjectUnsanitizedDoc ) => Promise>>; @@ -83,7 +86,6 @@ export async function migrateRawDocs( interface MigrateRawDocsSafelyDeps { serializer: SavedObjectsSerializer; - knownTypes: ReadonlySet; migrateDoc: MigrateAndConvertFn; rawDocs: SavedObjectsRawDoc[]; } @@ -97,7 +99,6 @@ interface MigrateRawDocsSafelyDeps { */ export function migrateRawDocsSafely({ serializer, - knownTypes, migrateDoc, rawDocs, }: MigrateRawDocsSafelyDeps): TaskEither.TaskEither< @@ -111,10 +112,7 @@ export function migrateRawDocsSafely({ const corruptSavedObjectIds: string[] = []; const options = { namespaceTreatment: 'lax' as const }; for (const raw of rawDocs) { - // Do not transform documents of unknown types - if (raw?._source?.type && !knownTypes.has(raw._source.type)) { - processedDocs.push(raw); - } else if (serializer.isRawSavedObject(raw, options)) { + if (serializer.isRawSavedObject(raw, options)) { try { const savedObject = convertToRawAddMigrationVersion(raw, options, serializer); processedDocs.push( diff --git a/src/core/server/saved_objects/migrations/integration_tests/7_13_0_unknown_types.test.ts b/src/core/server/saved_objects/migrations/integration_tests/7_13_0_unknown_types.test.ts index aea84cea22862..0791b0db30c93 100644 --- a/src/core/server/saved_objects/migrations/integration_tests/7_13_0_unknown_types.test.ts +++ b/src/core/server/saved_objects/migrations/integration_tests/7_13_0_unknown_types.test.ts @@ -11,16 +11,7 @@ import fs from 'fs/promises'; import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import * as kbnTestServer from '../../../../test_helpers/kbn_server'; import { Root } from '../../../root'; -import JSON5 from 'json5'; -import { ElasticsearchClient } from '../../../elasticsearch'; -import { Env } from '@kbn/config'; -import { REPO_ROOT } from '@kbn/utils'; -import { getEnvOptions } from '../../../config/mocks'; -import { retryAsync } from '../test_helpers/retry_async'; -import { LogRecord } from '@kbn/logging'; -const kibanaVersion = Env.createDefault(REPO_ROOT, getEnvOptions()).packageInfo.version; -const targetIndex = `.kibana_${kibanaVersion}_001`; const logFilePath = Path.join(__dirname, '7_13_unknown_types.log'); async function removeLogFile() { @@ -63,152 +54,54 @@ describe('migration v2', () => { await new Promise((resolve) => setTimeout(resolve, 10000)); }); - it('logs a warning and completes the migration with unknown docs retained', async () => { - root = createRoot(); - esServer = await startES(); - await root.preboot(); - await root.setup(); - await root.start(); - - let unknownDocsWarningLog: LogRecord; - - await retryAsync( - async () => { - const logFileContent = await fs.readFile(logFilePath, 'utf-8'); - const records = logFileContent - .split('\n') - .filter(Boolean) - .map((str) => JSON5.parse(str)); - - unknownDocsWarningLog = records.find((rec) => - rec.message.startsWith(`[.kibana] CHECK_UNKNOWN_DOCUMENTS`) - ); - - expect( - unknownDocsWarningLog.message.startsWith( - '[.kibana] CHECK_UNKNOWN_DOCUMENTS Upgrades will fail for 8.0+ because documents were found for unknown saved ' + - 'object types. To ensure that upgrades will succeed in the future, either re-enable plugins or delete ' + - `these documents from the "${targetIndex}" index after the current upgrade completes.` - ) - ).toBeTruthy(); - }, - { retryAttempts: 10, retryDelayMs: 200 } - ); - - const unknownDocs = [ - { type: 'space', id: 'space:default' }, - { type: 'space', id: 'space:first' }, - { type: 'space', id: 'space:second' }, - { type: 'space', id: 'space:third' }, - { type: 'space', id: 'space:forth' }, - { type: 'space', id: 'space:fifth' }, - { type: 'space', id: 'space:sixth' }, - { type: 'foo', id: 'P2SQfHkBs3dBRGh--No5' }, - { type: 'foo', id: 'QGSZfHkBs3dBRGh-ANoD' }, - { type: 'foo', id: 'QWSZfHkBs3dBRGh-hNob' }, - ]; - - unknownDocs.forEach(({ id, type }) => { - expect(unknownDocsWarningLog.message).toEqual( - expect.stringContaining(`- "${id}" (type: "${type}")`) - ); - }); - - const client: ElasticsearchClient = esServer.es.getKibanaEsClient(); - const { body: response } = await client.indices.getSettings({ - index: targetIndex, - }); - const settings = response[targetIndex].settings as estypes.IndicesIndexStatePrefixedSettings; - expect(settings.index).not.toBeUndefined(); - expect(settings.index!.blocks?.write).not.toEqual('true'); - - // Ensure that documents for unknown types were preserved in target index in an unmigrated state - const spaceDocs = await fetchDocs(client, targetIndex, 'space'); - expect(spaceDocs.map((s) => s.id)).toEqual( - expect.arrayContaining([ - 'space:default', - 'space:first', - 'space:second', - 'space:third', - 'space:forth', - 'space:fifth', - 'space:sixth', - ]) - ); - spaceDocs.forEach((d) => { - expect(d.migrationVersion.space).toEqual('6.6.0'); - expect(d.coreMigrationVersion).toEqual('7.13.0'); - }); - const fooDocs = await fetchDocs(client, targetIndex, 'foo'); - expect(fooDocs.map((f) => f.id)).toEqual( - expect.arrayContaining([ - 'P2SQfHkBs3dBRGh--No5', - 'QGSZfHkBs3dBRGh-ANoD', - 'QWSZfHkBs3dBRGh-hNob', - ]) - ); - fooDocs.forEach((d) => { - expect(d.migrationVersion.foo).toEqual('7.13.0'); - expect(d.coreMigrationVersion).toEqual('7.13.0'); - }); - }); - - it('migrates outdated documents when types are re-enabled', async () => { + it('fails the migration if unknown types are found in the source index', async () => { // Start kibana with foo and space types disabled root = createRoot(); esServer = await startES(); await root.preboot(); await root.setup(); - await root.start(); - // Shutdown and start Kibana again with space type registered to ensure space docs get migrated - await root.shutdown(); - root = createRoot(); - await root.preboot(); - const coreSetup = await root.setup(); - coreSetup.savedObjects.registerType({ - name: 'space', - hidden: false, - mappings: { properties: {} }, - namespaceType: 'agnostic', - migrations: { - '6.6.0': (d) => d, - [kibanaVersion]: (d) => d, - }, - }); - await root.start(); - - const client: ElasticsearchClient = esServer.es.getKibanaEsClient(); - const spacesDocsMigrated = await fetchDocs(client, targetIndex, 'space'); - expect(spacesDocsMigrated.map((s) => s.id)).toEqual( - expect.arrayContaining([ - 'space:default', - 'space:first', - 'space:second', - 'space:third', - 'space:forth', - 'space:fifth', - 'space:sixth', - ]) - ); - spacesDocsMigrated.forEach((d) => { - expect(d.migrationVersion.space).toEqual(kibanaVersion); // should be migrated - expect(d.coreMigrationVersion).toEqual(kibanaVersion); - }); - - // Make sure unmigrated foo docs are also still there in an unmigrated state - const fooDocsUnmigrated = await fetchDocs(client, targetIndex, 'foo'); - expect(fooDocsUnmigrated.map((f) => f.id)).toEqual( - expect.arrayContaining([ - 'P2SQfHkBs3dBRGh--No5', - 'QGSZfHkBs3dBRGh-ANoD', - 'QWSZfHkBs3dBRGh-hNob', - ]) - ); - fooDocsUnmigrated.forEach((d) => { - expect(d.migrationVersion.foo).toEqual('7.13.0'); // should still not be migrated - expect(d.coreMigrationVersion).toEqual('7.13.0'); - }); + try { + await root.start(); + expect('should have thrown').toEqual('but it did not'); + } catch (err) { + const errorMessage = err.message; + + expect( + errorMessage.startsWith( + 'Unable to complete saved object migrations for the [.kibana] index: Migration failed because documents ' + + 'were found for unknown saved object types. To proceed with the migration, please delete these documents from the ' + + '".kibana_7.13.0_001" index.' + ) + ).toBeTruthy(); + + const unknownDocs = [ + { type: 'space', id: 'space:default' }, + { type: 'space', id: 'space:first' }, + { type: 'space', id: 'space:second' }, + { type: 'space', id: 'space:third' }, + { type: 'space', id: 'space:forth' }, + { type: 'space', id: 'space:fifth' }, + { type: 'space', id: 'space:sixth' }, + { type: 'foo', id: 'P2SQfHkBs3dBRGh--No5' }, + { type: 'foo', id: 'QGSZfHkBs3dBRGh-ANoD' }, + { type: 'foo', id: 'QWSZfHkBs3dBRGh-hNob' }, + ]; + + unknownDocs.forEach(({ id, type }) => { + expect(errorMessage).toEqual(expect.stringContaining(`- "${id}" (type: "${type}")`)); + }); + + const client = esServer.es.getClient(); + const { body: response } = await client.indices.getSettings( + { index: '.kibana_7.13.0_001' }, + { meta: true } + ); + const settings = response['.kibana_7.13.0_001'] + .settings as estypes.IndicesIndexStatePrefixedSettings; + expect(settings.index).not.toBeUndefined(); + expect(settings.index!.blocks?.write).not.toEqual('true'); + } }); }); @@ -242,26 +135,3 @@ function createRoot() { } ); } - -async function fetchDocs(esClient: ElasticsearchClient, index: string, type: string) { - const { body } = await esClient.search({ - index, - size: 10000, - body: { - query: { - bool: { - should: [ - { - term: { type }, - }, - ], - }, - }, - }, - }); - - return body.hits.hits.map((h) => ({ - ...h._source, - id: h._id, - })); -} diff --git a/src/core/server/saved_objects/migrations/integration_tests/batch_size_bytes.test.ts b/src/core/server/saved_objects/migrations/integration_tests/batch_size_bytes.test.ts index e444a3b1a8bdb..3d8dcad08149c 100644 --- a/src/core/server/saved_objects/migrations/integration_tests/batch_size_bytes.test.ts +++ b/src/core/server/saved_objects/migrations/integration_tests/batch_size_bytes.test.ts @@ -109,7 +109,7 @@ describe('migration v2', () => { await root.preboot(); await root.setup(); await expect(root.start()).rejects.toMatchInlineSnapshot( - `[Error: Unable to complete saved object migrations for the [.kibana] index: The document with _id "canvas-workpad-template:workpad-template-061d7868-2b4e-4dc8-8bf7-3772b52926e5" is 1715275 bytes which exceeds the configured maximum batch size of 1015275 bytes. To proceed, please increase the 'migrations.maxBatchSizeBytes' Kibana configuration option and ensure that the Elasticsearch 'http.max_content_length' configuration option is set to an equal or larger value.]` + `[Error: Unable to complete saved object migrations for the [.kibana] index: The document with _id "canvas-workpad-template:workpad-template-061d7868-2b4e-4dc8-8bf7-3772b52926e5" is 1715274 bytes which exceeds the configured maximum batch size of 1015275 bytes. To proceed, please increase the 'migrations.maxBatchSizeBytes' Kibana configuration option and ensure that the Elasticsearch 'http.max_content_length' configuration option is set to an equal or larger value.]` ); await retryAsync( @@ -122,7 +122,7 @@ describe('migration v2', () => { expect( records.find((rec) => rec.message.startsWith( - `Unable to complete saved object migrations for the [.kibana] index: The document with _id "canvas-workpad-template:workpad-template-061d7868-2b4e-4dc8-8bf7-3772b52926e5" is 1715275 bytes which exceeds the configured maximum batch size of 1015275 bytes. To proceed, please increase the 'migrations.maxBatchSizeBytes' Kibana configuration option and ensure that the Elasticsearch 'http.max_content_length' configuration option is set to an equal or larger value.` + `Unable to complete saved object migrations for the [.kibana] index: The document with _id "canvas-workpad-template:workpad-template-061d7868-2b4e-4dc8-8bf7-3772b52926e5" is 1715274 bytes which exceeds the configured maximum batch size of 1015275 bytes. To proceed, please increase the 'migrations.maxBatchSizeBytes' Kibana configuration option and ensure that the Elasticsearch 'http.max_content_length' configuration option is set to an equal or larger value.` ) ) ).toBeDefined(); @@ -159,7 +159,7 @@ function createRoot(options: { maxBatchSizeBytes?: number }) { }, }, { - oss: true, + oss: false, } ); } diff --git a/src/core/server/saved_objects/migrations/integration_tests/collects_corrupt_docs.test.ts b/src/core/server/saved_objects/migrations/integration_tests/collects_corrupt_docs.test.ts index e330653089c6e..e5f0206b091fd 100644 --- a/src/core/server/saved_objects/migrations/integration_tests/collects_corrupt_docs.test.ts +++ b/src/core/server/saved_objects/migrations/integration_tests/collects_corrupt_docs.test.ts @@ -170,7 +170,7 @@ function createRoot() { }, }, { - oss: true, + oss: false, } ); } diff --git a/src/core/server/saved_objects/migrations/kibana_migrator.ts b/src/core/server/saved_objects/migrations/kibana_migrator.ts index fa1172c0684a7..2e2c4e2c63c04 100644 --- a/src/core/server/saved_objects/migrations/kibana_migrator.ts +++ b/src/core/server/saved_objects/migrations/kibana_migrator.ts @@ -170,7 +170,6 @@ export class KibanaMigrator { transformRawDocs: (rawDocs: SavedObjectsRawDoc[]) => migrateRawDocsSafely({ serializer: this.serializer, - knownTypes: new Set(this.typeRegistry.getAllTypes().map((t) => t.name)), migrateDoc: this.documentMigrator.migrateAndConvert, rawDocs, }), diff --git a/src/core/server/saved_objects/migrations/model/extract_errors.test.ts b/src/core/server/saved_objects/migrations/model/extract_errors.test.ts index c2daadcd342ac..a028c40ca6597 100644 --- a/src/core/server/saved_objects/migrations/model/extract_errors.test.ts +++ b/src/core/server/saved_objects/migrations/model/extract_errors.test.ts @@ -25,7 +25,7 @@ describe('extractUnknownDocFailureReason', () => { '.kibana_15' ) ).toMatchInlineSnapshot(` - "Upgrades will fail for 8.0+ because documents were found for unknown saved object types. To ensure that upgrades will succeed in the future, either re-enable plugins or delete these documents from the \\".kibana_15\\" index after the current upgrade completes. + "Migration failed because documents were found for unknown saved object types. To proceed with the migration, please delete these documents from the \\".kibana_15\\" index. The documents with unknown types are: - \\"unknownType:12\\" (type: \\"unknownType\\") - \\"anotherUnknownType:42\\" (type: \\"anotherUnknownType\\") diff --git a/src/core/server/saved_objects/migrations/model/extract_errors.ts b/src/core/server/saved_objects/migrations/model/extract_errors.ts index 3dabb09043376..95d10603caa80 100644 --- a/src/core/server/saved_objects/migrations/model/extract_errors.ts +++ b/src/core/server/saved_objects/migrations/model/extract_errors.ts @@ -38,16 +38,15 @@ export function extractTransformFailuresReason( export function extractUnknownDocFailureReason( unknownDocs: CheckForUnknownDocsFoundDoc[], - targetIndex: string + sourceIndex: string ): string { return ( - `Upgrades will fail for 8.0+ because documents were found for unknown saved object types. ` + - `To ensure that upgrades will succeed in the future, either re-enable plugins or delete these documents from the ` + - `"${targetIndex}" index after the current upgrade completes.\n` + + `Migration failed because documents were found for unknown saved object types. ` + + `To proceed with the migration, please delete these documents from the "${sourceIndex}" index.\n` + `The documents with unknown types are:\n` + unknownDocs.map((doc) => `- "${doc.id}" (type: "${doc.type}")\n`).join('') + `You can delete them using the following command:\n` + - `curl -X POST "{elasticsearch}/${targetIndex}/_bulk?pretty" -H 'Content-Type: application/json' -d'\n` + + `curl -X POST "{elasticsearch}/${sourceIndex}/_bulk?pretty" -H 'Content-Type: application/json' -d'\n` + unknownDocs.map((doc) => `{ "delete" : { "_id" : "${doc.id}" } }\n`).join('') + `'` ); diff --git a/src/core/server/saved_objects/migrations/model/model.test.ts b/src/core/server/saved_objects/migrations/model/model.test.ts index 7cd5f63640d1d..5ca6713ca163f 100644 --- a/src/core/server/saved_objects/migrations/model/model.test.ts +++ b/src/core/server/saved_objects/migrations/model/model.test.ts @@ -717,7 +717,7 @@ describe('migrations v2 model', () => { }, } as const; - test('CHECK_UNKNOWN_DOCUMENTS -> SET_SOURCE_WRITE_BLOCK if action succeeds and no unknown docs are found', () => { + test('CHECK_UNKNOWN_DOCUMENTS -> SET_SOURCE_WRITE_BLOCK if action succeeds', () => { const checkUnknownDocumentsSourceState: CheckUnknownDocumentsState = { ...baseState, controlState: 'CHECK_UNKNOWN_DOCUMENTS', @@ -725,7 +725,7 @@ describe('migrations v2 model', () => { sourceIndexMappings: mappingsWithUnknownType, }; - const res: ResponseType<'CHECK_UNKNOWN_DOCUMENTS'> = Either.right({ unknownDocs: [] }); + const res: ResponseType<'CHECK_UNKNOWN_DOCUMENTS'> = Either.right({}); const newState = model(checkUnknownDocumentsSourceState, res); expect(newState.controlState).toEqual('SET_SOURCE_WRITE_BLOCK'); @@ -765,7 +765,7 @@ describe('migrations v2 model', () => { expect(newState.logs).toEqual([]); }); - test('CHECK_UNKNOWN_DOCUMENTS -> SET_SOURCE_WRITE_BLOCK and adds log if action succeeds and unknown docs were found', () => { + test('CHECK_UNKNOWN_DOCUMENTS -> FATAL if action fails and unknown docs were found', () => { const checkUnknownDocumentsSourceState: CheckUnknownDocumentsState = { ...baseState, controlState: 'CHECK_UNKNOWN_DOCUMENTS', @@ -773,51 +773,20 @@ describe('migrations v2 model', () => { sourceIndexMappings: mappingsWithUnknownType, }; - const res: ResponseType<'CHECK_UNKNOWN_DOCUMENTS'> = Either.right({ + const res: ResponseType<'CHECK_UNKNOWN_DOCUMENTS'> = Either.left({ + type: 'unknown_docs_found', unknownDocs: [ { id: 'dashboard:12', type: 'dashboard' }, { id: 'foo:17', type: 'foo' }, ], }); const newState = model(checkUnknownDocumentsSourceState, res); - expect(newState.controlState).toEqual('SET_SOURCE_WRITE_BLOCK'); + expect(newState.controlState).toEqual('FATAL'); expect(newState).toMatchObject({ - controlState: 'SET_SOURCE_WRITE_BLOCK', - sourceIndex: Option.some('.kibana_3'), - targetIndex: '.kibana_7.11.0_001', - }); - - // This snapshot asserts that we disable the unknown saved object - // type. Because it's mappings are disabled, we also don't copy the - // `_meta.migrationMappingPropertyHashes` for the disabled type. - expect(newState.targetIndexMappings).toMatchInlineSnapshot(` - Object { - "_meta": Object { - "migrationMappingPropertyHashes": Object { - "new_saved_object_type": "4a11183eee21e6fbad864f7a30b39ad0", - }, - }, - "properties": Object { - "disabled_saved_object_type": Object { - "dynamic": false, - "properties": Object {}, - }, - "new_saved_object_type": Object { - "properties": Object { - "value": Object { - "type": "text", - }, - }, - }, - }, - } - `); - - expect(newState.logs[0]).toMatchObject({ - level: 'warning', - message: expect.stringContaining( - 'Upgrades will fail for 8.0+ because documents were found for unknown saved object types' + controlState: 'FATAL', + reason: expect.stringContaining( + 'Migration failed because documents were found for unknown saved object types' ), }); }); diff --git a/src/core/server/saved_objects/migrations/model/model.ts b/src/core/server/saved_objects/migrations/model/model.ts index 522a43a737cb7..e9efb72bca6f5 100644 --- a/src/core/server/saved_objects/migrations/model/model.ts +++ b/src/core/server/saved_objects/migrations/model/model.ts @@ -11,7 +11,6 @@ import * as Option from 'fp-ts/lib/Option'; import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { AliasAction, isLeftTypeof } from '../actions'; -import { MigrationLog } from '../types'; import { AllActionStates, State } from '../state'; import type { ResponseType } from '../next'; import { disableUnknownTypeMappingFields } from '../core'; @@ -352,24 +351,17 @@ export const model = (currentState: State, resW: ResponseType): { add: { index: target, alias: stateP.versionAlias } }, { remove_index: { index: stateP.tempIndex } }, ]), - - logs: [ - ...stateP.logs, - ...(res.right.unknownDocs.length > 0 - ? ([ - { - level: 'warning', - message: `CHECK_UNKNOWN_DOCUMENTS ${extractUnknownDocFailureReason( - res.right.unknownDocs, - target - )}`, - }, - ] as MigrationLog[]) - : []), - ], }; } else { - return throwBadResponse(stateP, res); + if (isLeftTypeof(res.left, 'unknown_docs_found')) { + return { + ...stateP, + controlState: 'FATAL', + reason: extractUnknownDocFailureReason(res.left.unknownDocs, stateP.sourceIndex.value), + }; + } else { + return throwBadResponse(stateP, res.left); + } } } else if (stateP.controlState === 'SET_SOURCE_WRITE_BLOCK') { const res = resW as ExcludeRetryableEsError>; From 6742a2d1fb66b04e7ebca2104fa984558566cba8 Mon Sep 17 00:00:00 2001 From: Gloria Hornero Date: Tue, 16 Nov 2021 14:27:29 +0100 Subject: [PATCH 013/148] adds threshold test for upgrade (#118086) --- .../cypress/screens/alerts.ts | 38 ++++-- .../cypress/screens/alerts_details.ts | 22 +++ .../cypress/screens/timelines.ts | 4 +- .../cypress/tasks/alerts_detection_rules.ts | 4 + .../cypress/tasks/timelines.ts | 3 +- .../custom_query_rule.spec.ts | 83 ++++-------- .../import_timeline.spec.ts | 2 +- .../threshold_rule.spec.ts | 126 ++++++++++++++++++ 8 files changed, 210 insertions(+), 72 deletions(-) create mode 100644 x-pack/plugins/security_solution/cypress/upgrade_integration/threshold_rule.spec.ts diff --git a/x-pack/plugins/security_solution/cypress/screens/alerts.ts b/x-pack/plugins/security_solution/cypress/screens/alerts.ts index 0d2eab221b49a..6177234575ec3 100644 --- a/x-pack/plugins/security_solution/cypress/screens/alerts.ts +++ b/x-pack/plugins/security_solution/cypress/screens/alerts.ts @@ -7,10 +7,8 @@ export const ADD_EXCEPTION_BTN = '[data-test-subj="add-exception-menu-item"]'; -export const ALERTS = '[data-test-subj="events-viewer-panel"] [data-test-subj="event"]'; - -export const ALERTS_COUNT = - '[data-test-subj="events-viewer-panel"] [data-test-subj="server-side-event-count"]'; +export const ALERT_COUNT_TABLE_FIRST_ROW_COUNT = + '[data-test-subj="alertsCountTable"] tr:nth-child(1) td:nth-child(2) .euiTableCellContent__text'; export const ALERT_CHECKBOX = '[data-test-subj~="select-event"].euiCheckbox__input'; @@ -28,16 +26,28 @@ export const ALERT_RULE_SEVERITY = '[data-test-subj="formatted-field-kibana.aler export const ALERT_DATA_GRID = '[data-test-subj="dataGridWrapper"]'; +export const ALERTS = '[data-test-subj="events-viewer-panel"][data-test-subj="event"]'; + +export const ALERTS_COUNT = + '[data-test-subj="events-viewer-panel"] [data-test-subj="server-side-event-count"]'; + +export const ALERTS_TREND_SIGNAL_RULE_NAME_PANEL = + '[data-test-subj="render-content-kibana.alert.rule.name"]'; + export const CLOSE_ALERT_BTN = '[data-test-subj="close-alert-status"]'; export const CLOSE_SELECTED_ALERTS_BTN = '[data-test-subj="close-alert-status"]'; export const CLOSED_ALERTS_FILTER_BTN = '[data-test-subj="closedAlerts"]'; +export const DESTINATION_IP = '[data-test-subj^=formatted-field][data-test-subj$=destination\\.ip]'; + export const EMPTY_ALERT_TABLE = '[data-test-subj="tGridEmptyState"]'; export const EXPAND_ALERT_BTN = '[data-test-subj="expand-event"]'; +export const HOST_NAME = '[data-test-subj^=formatted-field][data-test-subj$=host\\.name]'; + export const ACKNOWLEDGED_ALERTS_FILTER_BTN = '[data-test-subj="acknowledgedAlerts"]'; export const LOADING_ALERTS_PANEL = '[data-test-subj="loading-alerts-panel"]'; @@ -53,18 +63,26 @@ export const OPEN_ALERT_BTN = '[data-test-subj="open-alert-status"]'; export const OPENED_ALERTS_FILTER_BTN = '[data-test-subj="openAlerts"]'; +export const PROCESS_NAME = '[data-test-subj="formatted-field-process.name"]'; + +export const REASON = '[data-test-subj^=formatted-field][data-test-subj$=reason]'; + +export const RISK_SCORE = '[data-test-subj^=formatted-field][data-test-subj$=risk_score]'; + +export const RULE_NAME = '[data-test-subj^=formatted-field][data-test-subj$=rule\\.name]'; + export const SELECTED_ALERTS = '[data-test-subj="selectedShowBulkActionsButton"]'; export const SEND_ALERT_TO_TIMELINE_BTN = '[data-test-subj="send-alert-to-timeline-button"]'; +export const SEVERITY = '[data-test-subj^=formatted-field][data-test-subj$=severity]'; + +export const SOURCE_IP = '[data-test-subj^=formatted-field][data-test-subj$=source\\.ip]'; + export const TAKE_ACTION_POPOVER_BTN = '[data-test-subj="selectedShowBulkActionsButton"]'; export const TIMELINE_CONTEXT_MENU_BTN = '[data-test-subj="timeline-context-menu-button"]'; -export const ATTACH_ALERT_TO_CASE_BUTTON = '[data-test-subj="add-existing-case-menu-item"]'; +export const USER_NAME = '[data-test-subj^=formatted-field][data-test-subj$=user\\.name]'; -export const ALERT_COUNT_TABLE_FIRST_ROW_COUNT = - '[data-test-subj="alertsCountTable"] tr:nth-child(1) td:nth-child(2) .euiTableCellContent__text'; - -export const ALERTS_TREND_SIGNAL_RULE_NAME_PANEL = - '[data-test-subj="render-content-kibana.alert.rule.name"]'; +export const ATTACH_ALERT_TO_CASE_BUTTON = '[data-test-subj="add-existing-case-menu-item"]'; diff --git a/x-pack/plugins/security_solution/cypress/screens/alerts_details.ts b/x-pack/plugins/security_solution/cypress/screens/alerts_details.ts index 85a4fa257a957..70ccfcea7ba2c 100644 --- a/x-pack/plugins/security_solution/cypress/screens/alerts_details.ts +++ b/x-pack/plugins/security_solution/cypress/screens/alerts_details.ts @@ -30,6 +30,28 @@ export const JSON_VIEW_TAB = '[data-test-subj="jsonViewTab"]'; export const JSON_TEXT = '[data-test-subj="jsonView"]'; +export const OVERVIEW_HOST_NAME = + '[data-test-subj="eventDetails"] [data-test-subj="host-details-button"]'; + +export const OVERVIEW_RISK_SCORE = + '[data-test-subj="eventDetails"] [data-test-subj^=formatted][data-test-subj$=risk_score]'; + +export const OVERVIEW_RULE = + '[data-test-subj="eventDetails"] [data-test-subj^=formatted][data-test-subj$=rule\\.name]'; + +export const OVERVIEW_SEVERITY = + '[data-test-subj="eventDetails"] [data-test-subj^=formatted][data-test-subj$=rule\\.severity]'; + +export const OVERVIEW_STATUS = '[data-test-subj="eventDetails"] [data-test-subj$=status]'; + +export const OVERVIEW_THRESHOLD_COUNT = + '[data-test-subj="eventDetails"] [data-test-subj^=formatted][data-test-subj$=threshold_result\\.count]'; + +export const OVERVIEW_THRESHOLD_VALUE = + '[data-test-subj="eventDetails"] [data-test-subj$=threshold_result\\.terms]'; + +export const SUMMARY_VIEW = '[data-test-subj="summary-view"]'; + export const TABLE_CELL = '.euiTableRowCell'; export const TABLE_TAB = '[data-test-subj="tableTab"]'; diff --git a/x-pack/plugins/security_solution/cypress/screens/timelines.ts b/x-pack/plugins/security_solution/cypress/screens/timelines.ts index 5e64e4fbb5ece..21febda41d062 100644 --- a/x-pack/plugins/security_solution/cypress/screens/timelines.ts +++ b/x-pack/plugins/security_solution/cypress/screens/timelines.ts @@ -11,9 +11,7 @@ export const EXPAND_NOTES_BTN = '[data-test-subj="expand-notes"]'; export const EXPORT_TIMELINE_ACTION = '[data-test-subj="export-timeline-action"]'; -export const IMPORT_BTN = '.euiButton__text'; - -export const IMPORT_BTN_POSITION = 8; +export const IMPORT_BTN = '.euiButton.euiButton--primary.euiButton--fill'; export const IMPORT_TIMELINE_BTN = '[data-test-subj="open-import-data-modal-btn"]'; diff --git a/x-pack/plugins/security_solution/cypress/tasks/alerts_detection_rules.ts b/x-pack/plugins/security_solution/cypress/tasks/alerts_detection_rules.ts index 84b81108f8be3..e304d08f4c68f 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/alerts_detection_rules.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/alerts_detection_rules.ts @@ -149,6 +149,10 @@ export const goToRuleDetails = () => { cy.get(RULE_NAME).first().click({ force: true }); }; +export const goToTheRuleDetailsOf = (ruleName: string) => { + cy.get(RULE_NAME).contains(ruleName).click(); +}; + export const loadPrebuiltDetectionRules = () => { cy.get(LOAD_PREBUILT_RULES_BTN).should('exist').click({ force: true }); }; diff --git a/x-pack/plugins/security_solution/cypress/tasks/timelines.ts b/x-pack/plugins/security_solution/cypress/tasks/timelines.ts index 07c752a191968..d7f69638d0c55 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/timelines.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/timelines.ts @@ -12,7 +12,6 @@ import { EXPAND_NOTES_BTN, EXPORT_TIMELINE_ACTION, IMPORT_BTN, - IMPORT_BTN_POSITION, IMPORT_TIMELINE_BTN, INPUT_FILE, TIMELINES_TABLE, @@ -34,7 +33,7 @@ export const importTimeline = (timeline: string) => { cy.get(IMPORT_TIMELINE_BTN).click(); cy.get(INPUT_FILE).should('exist'); cy.get(INPUT_FILE).trigger('click', { force: true }).attachFile(timeline).trigger('change'); - cy.get(IMPORT_BTN).eq(IMPORT_BTN_POSITION).click({ force: true }); + cy.get(IMPORT_BTN).last().click({ force: true }); cy.get(INPUT_FILE).should('not.exist'); }; diff --git a/x-pack/plugins/security_solution/cypress/upgrade_integration/custom_query_rule.spec.ts b/x-pack/plugins/security_solution/cypress/upgrade_integration/custom_query_rule.spec.ts index 1af7a3f9bed03..e4464ae43dd62 100644 --- a/x-pack/plugins/security_solution/cypress/upgrade_integration/custom_query_rule.spec.ts +++ b/x-pack/plugins/security_solution/cypress/upgrade_integration/custom_query_rule.spec.ts @@ -4,8 +4,18 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - -import { ALERT_DETAILS_CELLS, SERVER_SIDE_EVENT_COUNT } from '../screens/alerts_detection_rules'; +import { + DESTINATION_IP, + HOST_NAME, + PROCESS_NAME, + REASON, + RISK_SCORE, + RULE_NAME, + SEVERITY, + SOURCE_IP, + USER_NAME, +} from '../screens/alerts'; +import { SERVER_SIDE_EVENT_COUNT } from '../screens/alerts_detection_rules'; import { ADDITIONAL_LOOK_BACK_DETAILS, ABOUT_DETAILS, @@ -24,7 +34,7 @@ import { } from '../screens/rule_details'; import { waitForPageToBeLoaded } from '../tasks/common'; -import { waitForRulesTableToBeLoaded, goToRuleDetails } from '../tasks/alerts_detection_rules'; +import { waitForRulesTableToBeLoaded, goToTheRuleDetailsOf } from '../tasks/alerts_detection_rules'; import { loginAndWaitForPage } from '../tasks/login'; import { DETECTIONS_RULE_MANAGEMENT_URL } from '../urls/navigation'; @@ -38,8 +48,8 @@ const alert = { reason: 'file event with process test, file The file to test, by Security Solution on security-solution.local created low alert Custom query rule for upgrade.', hostName: 'security-solution.local', - username: 'test', - processName: 'The file to test', + username: 'Security Solution', + processName: 'test', fileName: 'The file to test', sourceIp: '127.0.0.1', destinationIp: '127.0.0.2', @@ -49,7 +59,7 @@ const rule = { customQuery: '*:*', name: 'Custom query rule for upgrade', description: 'My description', - index: ['auditbeat-*'], + index: ['auditbeat-custom*'], severity: 'Low', riskScore: '7', timelineTemplate: 'none', @@ -62,7 +72,7 @@ describe('After an upgrade, the custom query rule', () => { before(() => { loginAndWaitForPage(DETECTIONS_RULE_MANAGEMENT_URL); waitForRulesTableToBeLoaded(); - goToRuleDetails(); + goToTheRuleDetailsOf(rule.name); waitForPageToBeLoaded(); }); @@ -89,54 +99,15 @@ describe('After an upgrade, the custom query rule', () => { }); }); - it('Displays the alert details', () => { - cy.get(ALERT_DETAILS_CELLS).first().focus(); - cy.get(ALERT_DETAILS_CELLS).first().type('{rightarrow}'); - cy.get(ALERT_DETAILS_CELLS) - .contains(alert.rule) - .then(($el) => { - cy.wrap($el).type('{rightarrow}'); - }); - cy.get(ALERT_DETAILS_CELLS) - .contains(alert.severity) - .then(($el) => { - cy.wrap($el).type('{rightarrow}'); - }); - cy.get(ALERT_DETAILS_CELLS) - .contains(alert.riskScore) - .then(($el) => { - cy.wrap($el).type('{rightarrow}'); - }); - cy.get(ALERT_DETAILS_CELLS) - .contains(alert.reason) - .then(($el) => { - cy.wrap($el).type('{rightarrow}'); - }); - cy.get(ALERT_DETAILS_CELLS) - .contains(alert.hostName) - .then(($el) => { - cy.wrap($el).type('{rightarrow}'); - }); - cy.get(ALERT_DETAILS_CELLS) - .contains(alert.username) - .then(($el) => { - cy.wrap($el).type('{rightarrow}'); - }); - cy.get(ALERT_DETAILS_CELLS) - .contains(alert.processName) - .then(($el) => { - cy.wrap($el).type('{rightarrow}'); - }); - cy.get(ALERT_DETAILS_CELLS) - .contains(alert.fileName) - .then(($el) => { - cy.wrap($el).type('{rightarrow}'); - }); - cy.get(ALERT_DETAILS_CELLS) - .contains(alert.sourceIp) - .then(($el) => { - cy.wrap($el).type('{rightarrow}'); - }); - cy.get(ALERT_DETAILS_CELLS).contains(alert.destinationIp); + it('Displays the alert details at the tgrid', () => { + cy.get(RULE_NAME).should('have.text', alert.rule); + cy.get(SEVERITY).should('have.text', alert.severity); + cy.get(RISK_SCORE).should('have.text', alert.riskScore); + cy.get(REASON).should('have.text', alert.reason).type('{rightarrow}'); + cy.get(HOST_NAME).should('have.text', alert.hostName); + cy.get(USER_NAME).should('have.text', alert.username); + cy.get(PROCESS_NAME).should('have.text', alert.processName); + cy.get(SOURCE_IP).should('have.text', alert.sourceIp); + cy.get(DESTINATION_IP).should('have.text', alert.destinationIp); }); }); diff --git a/x-pack/plugins/security_solution/cypress/upgrade_integration/import_timeline.spec.ts b/x-pack/plugins/security_solution/cypress/upgrade_integration/import_timeline.spec.ts index 3ce3937b3e4b2..464c42d9fc220 100644 --- a/x-pack/plugins/security_solution/cypress/upgrade_integration/import_timeline.spec.ts +++ b/x-pack/plugins/security_solution/cypress/upgrade_integration/import_timeline.spec.ts @@ -54,7 +54,7 @@ const username = 'elastic'; const timelineDetails = { dateStart: 'Oct 11, 2020 @ 00:00:00.000', dateEnd: 'Oct 11, 2030 @ 17:13:15.851', - queryTab: 'Query2', + queryTab: 'Query4', correlationTab: 'Correlation', analyzerTab: 'Analyzer', notesTab: 'Notes2', diff --git a/x-pack/plugins/security_solution/cypress/upgrade_integration/threshold_rule.spec.ts b/x-pack/plugins/security_solution/cypress/upgrade_integration/threshold_rule.spec.ts new file mode 100644 index 0000000000000..b6dbcd0e3232c --- /dev/null +++ b/x-pack/plugins/security_solution/cypress/upgrade_integration/threshold_rule.spec.ts @@ -0,0 +1,126 @@ +/* + * 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 { HOST_NAME, REASON, RISK_SCORE, RULE_NAME, SEVERITY } from '../screens/alerts'; +import { SERVER_SIDE_EVENT_COUNT } from '../screens/alerts_detection_rules'; +import { + ADDITIONAL_LOOK_BACK_DETAILS, + ABOUT_DETAILS, + ABOUT_RULE_DESCRIPTION, + CUSTOM_QUERY_DETAILS, + DEFINITION_DETAILS, + getDetails, + INDEX_PATTERNS_DETAILS, + RISK_SCORE_DETAILS, + RULE_NAME_HEADER, + RULE_TYPE_DETAILS, + RUNS_EVERY_DETAILS, + SCHEDULE_DETAILS, + SEVERITY_DETAILS, + THRESHOLD_DETAILS, + TIMELINE_TEMPLATE_DETAILS, +} from '../screens/rule_details'; + +import { expandFirstAlert } from '../tasks/alerts'; +import { waitForPageToBeLoaded } from '../tasks/common'; +import { waitForRulesTableToBeLoaded, goToRuleDetails } from '../tasks/alerts_detection_rules'; +import { loginAndWaitForPage } from '../tasks/login'; + +import { DETECTIONS_RULE_MANAGEMENT_URL } from '../urls/navigation'; +import { + OVERVIEW_HOST_NAME, + OVERVIEW_RISK_SCORE, + OVERVIEW_RULE, + OVERVIEW_SEVERITY, + OVERVIEW_STATUS, + OVERVIEW_THRESHOLD_COUNT, + OVERVIEW_THRESHOLD_VALUE, + SUMMARY_VIEW, +} from '../screens/alerts_details'; + +const EXPECTED_NUMBER_OF_ALERTS = '1'; + +const alert = { + rule: 'Threshold rule', + severity: 'medium', + riskScore: '17', + reason: 'event created medium alert Threshold rule.', + hostName: 'security-solution.local', + thresholdCount: '2', +}; + +const rule = { + customQuery: '*:*', + name: 'Threshold rule', + description: 'Threshold rule for testing upgrade', + index: ['auditbeat-threshold*'], + severity: 'Medium', + riskScore: '17', + timelineTemplate: 'none', + runsEvery: '60s', + lookBack: '2999999m', + timeline: 'None', + thresholdField: 'host.name', + threholdValue: '1', +}; + +describe('After an upgrade, the threshold rule', () => { + before(() => { + loginAndWaitForPage(DETECTIONS_RULE_MANAGEMENT_URL); + waitForRulesTableToBeLoaded(); + goToRuleDetails(); + waitForPageToBeLoaded(); + }); + + it('Has the expected alerts number', () => { + cy.get(SERVER_SIDE_EVENT_COUNT).contains(EXPECTED_NUMBER_OF_ALERTS); + }); + + it('Displays the rule details', () => { + cy.get(RULE_NAME_HEADER).should('contain', rule.name); + cy.get(ABOUT_RULE_DESCRIPTION).should('have.text', rule.description); + cy.get(ABOUT_DETAILS).within(() => { + getDetails(SEVERITY_DETAILS).should('have.text', rule.severity); + getDetails(RISK_SCORE_DETAILS).should('have.text', rule.riskScore); + }); + cy.get(DEFINITION_DETAILS).within(() => { + getDetails(INDEX_PATTERNS_DETAILS).should('have.text', rule.index.join('')); + getDetails(CUSTOM_QUERY_DETAILS).should('have.text', rule.customQuery); + getDetails(RULE_TYPE_DETAILS).should('have.text', 'Threshold'); + getDetails(TIMELINE_TEMPLATE_DETAILS).should('have.text', rule.timeline); + getDetails(THRESHOLD_DETAILS).should( + 'have.text', + `Results aggregated by ${rule.thresholdField} >= ${rule.threholdValue}` + ); + }); + cy.get(SCHEDULE_DETAILS).within(() => { + getDetails(RUNS_EVERY_DETAILS).should('have.text', rule.runsEvery); + getDetails(ADDITIONAL_LOOK_BACK_DETAILS).should('have.text', rule.lookBack); + }); + }); + + it('Displays the alert details in the TGrid', () => { + cy.get(RULE_NAME).should('have.text', alert.rule); + cy.get(SEVERITY).should('have.text', alert.severity); + cy.get(RISK_SCORE).should('have.text', alert.riskScore); + cy.get(REASON).should('have.text', alert.reason); + cy.get(HOST_NAME).should('have.text', alert.hostName); + }); + + it('Displays the Overview alert details in the alert flyout', () => { + expandFirstAlert(); + + cy.get(OVERVIEW_STATUS).should('have.text', 'open'); + cy.get(OVERVIEW_RULE).should('have.text', alert.rule); + cy.get(OVERVIEW_SEVERITY).should('have.text', alert.severity); + cy.get(OVERVIEW_RISK_SCORE).should('have.text', alert.riskScore); + cy.get(OVERVIEW_HOST_NAME).should('have.text', alert.hostName); + cy.get(OVERVIEW_THRESHOLD_COUNT).should('have.text', alert.thresholdCount); + cy.get(OVERVIEW_THRESHOLD_VALUE).should('have.text', alert.hostName); + cy.get(SUMMARY_VIEW).should('contain', `${rule.thresholdField} [threshold]`); + }); +}); From 72d37289b8a31accbb2657b6ddc2291d82569ceb Mon Sep 17 00:00:00 2001 From: Thomas Watson Date: Tue, 16 Nov 2021 14:45:20 +0100 Subject: [PATCH 014/148] Create missing directories in file logging appenders (#117666) --- logs/.empty | 0 .../appenders/file/file_appender.test.mocks.ts | 3 ++- .../logging/appenders/file/file_appender.test.ts | 11 ++++++++++- .../server/logging/appenders/file/file_appender.ts | 8 +++++++- .../appenders/rolling_file/rolling_file_manager.ts | 8 +++++++- 5 files changed, 26 insertions(+), 4 deletions(-) delete mode 100644 logs/.empty diff --git a/logs/.empty b/logs/.empty deleted file mode 100644 index e69de29bb2d1d..0000000000000 diff --git a/src/core/server/logging/appenders/file/file_appender.test.mocks.ts b/src/core/server/logging/appenders/file/file_appender.test.mocks.ts index 2c2a2015b6fd3..48173d683e9a4 100644 --- a/src/core/server/logging/appenders/file/file_appender.test.mocks.ts +++ b/src/core/server/logging/appenders/file/file_appender.test.mocks.ts @@ -19,4 +19,5 @@ jest.mock('../../layouts/layouts', () => { }); export const mockCreateWriteStream = jest.fn(); -jest.mock('fs', () => ({ createWriteStream: mockCreateWriteStream })); +export const mockMkdirSync = jest.fn(); +jest.mock('fs', () => ({ createWriteStream: mockCreateWriteStream, mkdirSync: mockMkdirSync })); diff --git a/src/core/server/logging/appenders/file/file_appender.test.ts b/src/core/server/logging/appenders/file/file_appender.test.ts index 081cb16afd2ff..f3a5d483d5a7b 100644 --- a/src/core/server/logging/appenders/file/file_appender.test.ts +++ b/src/core/server/logging/appenders/file/file_appender.test.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { mockCreateWriteStream } from './file_appender.test.mocks'; +import { mockCreateWriteStream, mockMkdirSync } from './file_appender.test.mocks'; import { LogRecord, LogLevel } from '@kbn/logging'; import { FileAppender } from './file_appender'; @@ -15,6 +15,7 @@ const tickMs = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)) beforeEach(() => { mockCreateWriteStream.mockReset(); + mockMkdirSync.mockReset(); }); test('`createConfigSchema()` creates correct schema.', () => { @@ -49,8 +50,10 @@ test('file stream is created only once and only after first `append()` is called }); const mockPath = 'mock://path/file.log'; + const mockDir = 'mock://path'; const appender = new FileAppender({ format: () => '' }, mockPath); + expect(mockMkdirSync).not.toHaveBeenCalled(); expect(mockCreateWriteStream).not.toHaveBeenCalled(); appender.append({ @@ -61,12 +64,17 @@ test('file stream is created only once and only after first `append()` is called pid: 5355, }); + expect(mockMkdirSync).toHaveBeenCalledTimes(1); + expect(mockMkdirSync).toHaveBeenCalledWith(mockDir, { + recursive: true, + }); expect(mockCreateWriteStream).toHaveBeenCalledTimes(1); expect(mockCreateWriteStream).toHaveBeenCalledWith(mockPath, { encoding: 'utf8', flags: 'a', }); + mockMkdirSync.mockClear(); mockCreateWriteStream.mockClear(); appender.append({ context: 'context-2', @@ -76,6 +84,7 @@ test('file stream is created only once and only after first `append()` is called pid: 5355, }); + expect(mockMkdirSync).not.toHaveBeenCalled(); expect(mockCreateWriteStream).not.toHaveBeenCalled(); }); diff --git a/src/core/server/logging/appenders/file/file_appender.ts b/src/core/server/logging/appenders/file/file_appender.ts index 3c22a37038bcc..1c0f842f6c630 100644 --- a/src/core/server/logging/appenders/file/file_appender.ts +++ b/src/core/server/logging/appenders/file/file_appender.ts @@ -8,7 +8,8 @@ import { schema } from '@kbn/config-schema'; import { LogRecord, Layout, DisposableAppender } from '@kbn/logging'; -import { createWriteStream, WriteStream } from 'fs'; +import { createWriteStream, WriteStream, mkdirSync } from 'fs'; +import { dirname } from 'path'; import { Layouts, LayoutConfigType } from '../../layouts/layouts'; @@ -47,6 +48,7 @@ export class FileAppender implements DisposableAppender { */ public append(record: LogRecord) { if (this.outputStream === undefined) { + this.ensureDirectory(this.path); this.outputStream = createWriteStream(this.path, { encoding: 'utf8', flags: 'a', @@ -73,4 +75,8 @@ export class FileAppender implements DisposableAppender { }); }); } + + private ensureDirectory(path: string) { + mkdirSync(dirname(path), { recursive: true }); + } } diff --git a/src/core/server/logging/appenders/rolling_file/rolling_file_manager.ts b/src/core/server/logging/appenders/rolling_file/rolling_file_manager.ts index e96c57578f908..df9c531fa2e7f 100644 --- a/src/core/server/logging/appenders/rolling_file/rolling_file_manager.ts +++ b/src/core/server/logging/appenders/rolling_file/rolling_file_manager.ts @@ -6,7 +6,8 @@ * Side Public License, v 1. */ -import { createWriteStream, WriteStream } from 'fs'; +import { createWriteStream, WriteStream, mkdirSync } from 'fs'; +import { dirname } from 'path'; import { RollingFileContext } from './rolling_file_context'; /** @@ -40,6 +41,7 @@ export class RollingFileManager { private ensureStreamOpen() { if (this.outputStream === undefined) { + this.ensureDirectory(this.filePath); this.outputStream = createWriteStream(this.filePath, { encoding: 'utf8', flags: 'a', @@ -49,4 +51,8 @@ export class RollingFileManager { } return this.outputStream!; } + + private ensureDirectory(path: string) { + mkdirSync(dirname(path), { recursive: true }); + } } From e66072de1765ff7bcd7c64f3054d678fb1474b73 Mon Sep 17 00:00:00 2001 From: Marta Bondyra Date: Tue, 16 Nov 2021 14:50:14 +0100 Subject: [PATCH 015/148] [Lens] add optional labels to dimensions (#118580) * [Lens] add optional labels to dimensions * CR feedback * fix failing test * Update x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.test.tsx --- .../editor_frame/config_panel/layer_panel.test.tsx | 5 ++++- .../editor_frame/config_panel/layer_panel.tsx | 12 +++++++++++- .../dimension_panel/dimensions_editor_helpers.tsx | 7 ++++++- .../public/metric_visualization/visualization.tsx | 1 + 4 files changed, 22 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.test.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.test.tsx index 5b432f85efde2..92633d5e7305b 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.test.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.test.tsx @@ -157,7 +157,7 @@ describe('LayerPanel', () => { }); describe('single group', () => { - it('should render the non-editable state', async () => { + it('should render the non-editable state and optional label', async () => { mockVisualization.getConfiguration.mockReturnValue({ groups: [ { @@ -172,8 +172,11 @@ describe('LayerPanel', () => { }); const { instance } = await mountWithProvider(); + const group = instance.find('.lnsLayerPanel__dimensionContainer[data-test-subj="lnsGroup"]'); expect(group).toHaveLength(1); + const optionalLabel = instance.find('[data-test-subj="lnsGroup_optional"]').first(); + expect(optionalLabel.text()).toEqual('Optional'); }); it('should render the group with a way to add a new column', async () => { diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.tsx index 51d880e8f7c1c..6af3d88b17d41 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.tsx @@ -14,6 +14,7 @@ import { EuiFlexGroup, EuiFlexItem, EuiFormRow, + EuiText, EuiIconTip, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; @@ -385,7 +386,7 @@ export function LayerPanel( {groups.map((group, groupIndex) => { const isMissing = !isEmptyLayer && group.required && group.accessors.length === 0; - + const isOptional = !group.required; return ( } + labelAppend={ + isOptional ? ( + + {i18n.translate('xpack.lens.editorFrame.optionalDimensionLabel', { + defaultMessage: 'Optional', + })} + + ) : null + } labelType="legend" key={group.groupId} isInvalid={isMissing} diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimensions_editor_helpers.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimensions_editor_helpers.tsx index 876711c5d6aaf..ce8c7d61bfc16 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimensions_editor_helpers.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimensions_editor_helpers.tsx @@ -161,7 +161,12 @@ export const DimensionEditorTabs = ({ tabs }: { tabs: DimensionEditorTab[] }) => > {tabs.map(({ id, enabled, state, onClick, label }) => { return enabled ? ( - + {label} ) : null; diff --git a/x-pack/plugins/lens/public/metric_visualization/visualization.tsx b/x-pack/plugins/lens/public/metric_visualization/visualization.tsx index 1b30e6c7fd932..5693d67546f99 100644 --- a/x-pack/plugins/lens/public/metric_visualization/visualization.tsx +++ b/x-pack/plugins/lens/public/metric_visualization/visualization.tsx @@ -106,6 +106,7 @@ export const metricVisualization: Visualization = { accessors: props.state.accessor ? [{ columnId: props.state.accessor }] : [], supportsMoreColumns: !props.state.accessor, filterOperations: (op: OperationMetadata) => !op.isBucketed && op.dataType === 'number', + required: true, }, ], }; From 349434ed040bb558552acbfe2b7686f65a81c77f Mon Sep 17 00:00:00 2001 From: Joe Portner <5295965+jportner@users.noreply.github.com> Date: Tue, 16 Nov 2021 08:51:22 -0500 Subject: [PATCH 016/148] Fix cluster call responses that are missing source fields (#118642) Change usage from `_source: 'true'` to `_source: true`. --- .../src/lib/docs/generate_doc_records_stream.test.ts | 4 ++-- .../src/lib/docs/generate_doc_records_stream.ts | 2 +- src/core/server/saved_objects/service/lib/repository.ts | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/kbn-es-archiver/src/lib/docs/generate_doc_records_stream.test.ts b/packages/kbn-es-archiver/src/lib/docs/generate_doc_records_stream.test.ts index 3b5f1f777b0e3..ae21649690a99 100644 --- a/packages/kbn-es-archiver/src/lib/docs/generate_doc_records_stream.test.ts +++ b/packages/kbn-es-archiver/src/lib/docs/generate_doc_records_stream.test.ts @@ -121,7 +121,7 @@ describe('esArchiver: createGenerateDocRecordsStream()', () => { "calls": Array [ Array [ Object { - "_source": "true", + "_source": true, "index": "bar", "query": undefined, "rest_total_hits_as_int": true, @@ -136,7 +136,7 @@ describe('esArchiver: createGenerateDocRecordsStream()', () => { ], Array [ Object { - "_source": "true", + "_source": true, "index": "foo", "query": undefined, "rest_total_hits_as_int": true, diff --git a/packages/kbn-es-archiver/src/lib/docs/generate_doc_records_stream.ts b/packages/kbn-es-archiver/src/lib/docs/generate_doc_records_stream.ts index 4bd44b649afd2..b1b713f6f3cbf 100644 --- a/packages/kbn-es-archiver/src/lib/docs/generate_doc_records_stream.ts +++ b/packages/kbn-es-archiver/src/lib/docs/generate_doc_records_stream.ts @@ -38,7 +38,7 @@ export function createGenerateDocRecordsStream({ index, scroll: SCROLL_TIMEOUT, size: SCROLL_SIZE, - _source: 'true', + _source: true, query, rest_total_hits_as_int: true, }, diff --git a/src/core/server/saved_objects/service/lib/repository.ts b/src/core/server/saved_objects/service/lib/repository.ts index d538690fb1920..9be58f1b71861 100644 --- a/src/core/server/saved_objects/service/lib/repository.ts +++ b/src/core/server/saved_objects/service/lib/repository.ts @@ -1825,7 +1825,7 @@ export class SavedObjectsRepository { index: this.getIndexForType(type), refresh, require_alias: true, - _source: 'true', + _source: true, body: { script: { source: ` From 42916a2233ff6736c3d08eba50cf4a818b67bdf4 Mon Sep 17 00:00:00 2001 From: Miriam <31922082+MiriamAparicio@users.noreply.github.com> Date: Tue, 16 Nov 2021 14:07:19 +0000 Subject: [PATCH 017/148] [APM] Remove usage of ignore_throttled unless targeting frozen indices (#118371) * [APM] Remove usage of ignore_throttled unless targeting frozen indices * changes after review * test just target ignore_throttled property --- .../queries/get_request_base.test.ts | 18 +++++------------- .../correlations/queries/get_request_base.ts | 2 +- .../queries/query_field_candidates.test.ts | 2 +- .../queries/query_histogram.test.ts | 2 +- .../query_histogram_range_steps.test.ts | 2 +- .../queries/query_percentiles.test.ts | 2 +- .../correlations/queries/query_ranges.test.ts | 2 +- .../create_apm_event_client/index.ts | 2 +- .../server/lib/helpers/setup_request.test.ts | 5 ++--- 9 files changed, 14 insertions(+), 23 deletions(-) diff --git a/x-pack/plugins/apm/server/lib/correlations/queries/get_request_base.test.ts b/x-pack/plugins/apm/server/lib/correlations/queries/get_request_base.test.ts index eb771e1e1aaf4..9df412b65b8d3 100644 --- a/x-pack/plugins/apm/server/lib/correlations/queries/get_request_base.test.ts +++ b/x-pack/plugins/apm/server/lib/correlations/queries/get_request_base.test.ts @@ -10,35 +10,27 @@ import { getRequestBase } from './get_request_base'; describe('correlations', () => { describe('getRequestBase', () => { - it('returns the request base parameters', () => { + it('defaults to not setting `ignore_throttled`', () => { const requestBase = getRequestBase({ index: 'apm-*', - includeFrozen: true, environment: ENVIRONMENT_ALL.value, kuery: '', start: 1577836800000, end: 1609459200000, }); - expect(requestBase).toEqual({ - index: 'apm-*', - ignore_throttled: false, - ignore_unavailable: true, - }); + expect(requestBase.ignore_throttled).toEqual(undefined); }); - it('defaults ignore_throttled to true', () => { + it('adds `ignore_throttled=false` when `includeFrozen=true`', () => { const requestBase = getRequestBase({ index: 'apm-*', + includeFrozen: true, environment: ENVIRONMENT_ALL.value, kuery: '', start: 1577836800000, end: 1609459200000, }); - expect(requestBase).toEqual({ - index: 'apm-*', - ignore_throttled: true, - ignore_unavailable: true, - }); + expect(requestBase.ignore_throttled).toEqual(false); }); }); }); diff --git a/x-pack/plugins/apm/server/lib/correlations/queries/get_request_base.ts b/x-pack/plugins/apm/server/lib/correlations/queries/get_request_base.ts index 5ab4e3b26122d..02719ee3929ce 100644 --- a/x-pack/plugins/apm/server/lib/correlations/queries/get_request_base.ts +++ b/x-pack/plugins/apm/server/lib/correlations/queries/get_request_base.ts @@ -13,6 +13,6 @@ export const getRequestBase = ({ }: CorrelationsParams) => ({ index, // matches APM's event client settings - ignore_throttled: includeFrozen === undefined ? true : !includeFrozen, + ...(includeFrozen ? { ignore_throttled: false } : {}), ignore_unavailable: true, }); diff --git a/x-pack/plugins/apm/server/lib/correlations/queries/query_field_candidates.test.ts b/x-pack/plugins/apm/server/lib/correlations/queries/query_field_candidates.test.ts index 02af6637e5bb3..957e2393558ed 100644 --- a/x-pack/plugins/apm/server/lib/correlations/queries/query_field_candidates.test.ts +++ b/x-pack/plugins/apm/server/lib/correlations/queries/query_field_candidates.test.ts @@ -88,7 +88,7 @@ describe('query_field_candidates', () => { size: 1000, }, index: params.index, - ignore_throttled: !params.includeFrozen, + ignore_throttled: params.includeFrozen ? false : undefined, ignore_unavailable: true, }); }); diff --git a/x-pack/plugins/apm/server/lib/correlations/queries/query_histogram.test.ts b/x-pack/plugins/apm/server/lib/correlations/queries/query_histogram.test.ts index 3c5726ee586da..c9ea70452bdb0 100644 --- a/x-pack/plugins/apm/server/lib/correlations/queries/query_histogram.test.ts +++ b/x-pack/plugins/apm/server/lib/correlations/queries/query_histogram.test.ts @@ -63,7 +63,7 @@ describe('query_histogram', () => { size: 0, }, index: params.index, - ignore_throttled: !params.includeFrozen, + ignore_throttled: params.includeFrozen ? false : undefined, ignore_unavailable: true, }); }); diff --git a/x-pack/plugins/apm/server/lib/correlations/queries/query_histogram_range_steps.test.ts b/x-pack/plugins/apm/server/lib/correlations/queries/query_histogram_range_steps.test.ts index 3a79b4375e4a5..526207beaabce 100644 --- a/x-pack/plugins/apm/server/lib/correlations/queries/query_histogram_range_steps.test.ts +++ b/x-pack/plugins/apm/server/lib/correlations/queries/query_histogram_range_steps.test.ts @@ -66,7 +66,7 @@ describe('query_histogram_range_steps', () => { size: 0, }, index: params.index, - ignore_throttled: !params.includeFrozen, + ignore_throttled: params.includeFrozen ? false : undefined, ignore_unavailable: true, }); }); diff --git a/x-pack/plugins/apm/server/lib/correlations/queries/query_percentiles.test.ts b/x-pack/plugins/apm/server/lib/correlations/queries/query_percentiles.test.ts index 67b2f580e3f4d..4e637d1ca6f4a 100644 --- a/x-pack/plugins/apm/server/lib/correlations/queries/query_percentiles.test.ts +++ b/x-pack/plugins/apm/server/lib/correlations/queries/query_percentiles.test.ts @@ -65,7 +65,7 @@ describe('query_percentiles', () => { track_total_hits: true, }, index: params.index, - ignore_throttled: !params.includeFrozen, + ignore_throttled: params.includeFrozen ? false : undefined, ignore_unavailable: true, }); }); diff --git a/x-pack/plugins/apm/server/lib/correlations/queries/query_ranges.test.ts b/x-pack/plugins/apm/server/lib/correlations/queries/query_ranges.test.ts index 3cafc17e2681b..5c43b771f69ee 100644 --- a/x-pack/plugins/apm/server/lib/correlations/queries/query_ranges.test.ts +++ b/x-pack/plugins/apm/server/lib/correlations/queries/query_ranges.test.ts @@ -82,7 +82,7 @@ describe('query_ranges', () => { size: 0, }, index: params.index, - ignore_throttled: !params.includeFrozen, + ignore_throttled: params.includeFrozen ? false : undefined, ignore_unavailable: true, }); }); diff --git a/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_apm_event_client/index.ts b/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_apm_event_client/index.ts index 26b00b075a5c8..a45d314c33719 100644 --- a/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_apm_event_client/index.ts +++ b/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_apm_event_client/index.ts @@ -100,7 +100,7 @@ export function createApmEventClient({ const searchParams = { ...withPossibleLegacyDataFilter, - ignore_throttled: !includeFrozen, + ...(includeFrozen ? { ignore_throttled: false } : {}), ignore_unavailable: true, preference: 'any', }; diff --git a/x-pack/plugins/apm/server/lib/helpers/setup_request.test.ts b/x-pack/plugins/apm/server/lib/helpers/setup_request.test.ts index 52e9e5a8ea74a..7b3201095106e 100644 --- a/x-pack/plugins/apm/server/lib/helpers/setup_request.test.ts +++ b/x-pack/plugins/apm/server/lib/helpers/setup_request.test.ts @@ -132,7 +132,6 @@ describe('setupRequest', () => { }, }, ignore_unavailable: true, - ignore_throttled: true, preference: 'any', }, { @@ -251,7 +250,7 @@ describe('without a bool filter', () => { }); describe('with includeFrozen=false', () => { - it('sets `ignore_throttled=true`', async () => { + it('should NOT send "ignore_throttled:true" in the request', async () => { const mockResources = getMockResources(); // mock includeFrozen to return false @@ -268,7 +267,7 @@ describe('with includeFrozen=false', () => { const params = mockResources.context.core.elasticsearch.client.asCurrentUser.search.mock .calls[0][0]; - expect(params.ignore_throttled).toBe(true); + expect(params.ignore_throttled).toBe(undefined); }); }); From f9488f41f711841d40623c486bfd4002069aace1 Mon Sep 17 00:00:00 2001 From: Sandra G Date: Tue, 16 Nov 2021 09:08:51 -0500 Subject: [PATCH 018/148] [Stack Monitoring] remove usage of fields being removed in ES segments, update tests (#118106) * remove usage of fields being removed in es, update tests * add Lucene to title of fixed_bit_set_memory_in_bytes instead of generic IndexMemoryMetric class * update fixtures for integration tests * remove index segment count * update translations * remove usage of fields being removed in es, update tests * add Lucene to title of fixed_bit_set_memory_in_bytes instead of generic IndexMemoryMetric class * update fixtures for integration tests * remove index segment count * update translations * Revert "remove index segment count" This reverts commit d56ce6e746efba6d82253f4eea66c64be41aab84. * Revert "remove index segment count" This reverts commit d56ce6e746efba6d82253f4eea66c64be41aab84. Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../elasticsearch/index/advanced.js | 2 - .../components/elasticsearch/index/index.js | 1 - .../components/elasticsearch/node/advanced.js | 2 - .../components/elasticsearch/node/node.js | 1 - .../lib/cluster/__fixtures__/clusters.json | 14 - .../__snapshots__/get_metrics.test.js.snap | 754 +----------------- .../server/lib/details/get_metrics.test.js | 9 +- .../get_nodes/__fixtures__/cluster_data.json | 7 - .../shards/__fixtures__/cluster.json | 7 - .../__snapshots__/metrics.test.js.snap | 284 +------ .../lib/metrics/elasticsearch/metrics.js | 236 +----- .../elasticsearch/metric_set_index_detail.js | 24 +- .../elasticsearch/metric_set_node_detail.js | 24 +- .../translations/translations/ja-JP.json | 51 -- .../translations/translations/zh-CN.json | 51 -- .../elasticsearch/fixtures/index_detail.json | 293 ------- .../fixtures/index_detail_advanced.json | 355 +-------- .../elasticsearch/fixtures/node_detail.json | 293 ------- .../fixtures/node_detail_advanced.json | 366 +-------- 19 files changed, 22 insertions(+), 2752 deletions(-) diff --git a/x-pack/plugins/monitoring/public/components/elasticsearch/index/advanced.js b/x-pack/plugins/monitoring/public/components/elasticsearch/index/advanced.js index 2f76e9b5cc8bb..ed86a4bb58048 100644 --- a/x-pack/plugins/monitoring/public/components/elasticsearch/index/advanced.js +++ b/x-pack/plugins/monitoring/public/components/elasticsearch/index/advanced.js @@ -23,8 +23,6 @@ import { AlertsCallout } from '../../../alerts/callout'; export const AdvancedIndex = ({ indexSummary, metrics, alerts, ...props }) => { const metricsToShow = [ - metrics.index_1, - metrics.index_2, metrics.index_3, metrics.index_4, metrics.index_total, diff --git a/x-pack/plugins/monitoring/public/components/elasticsearch/index/index.js b/x-pack/plugins/monitoring/public/components/elasticsearch/index/index.js index 9bdaa513998b5..15a297f3cac73 100644 --- a/x-pack/plugins/monitoring/public/components/elasticsearch/index/index.js +++ b/x-pack/plugins/monitoring/public/components/elasticsearch/index/index.js @@ -31,7 +31,6 @@ export const Index = ({ ...props }) => { const metricsToShow = [ - metrics.index_mem, metrics.index_size, metrics.index_search_request_rate, metrics.index_request_rate, diff --git a/x-pack/plugins/monitoring/public/components/elasticsearch/node/advanced.js b/x-pack/plugins/monitoring/public/components/elasticsearch/node/advanced.js index 5d95aa8bec676..30ddcf09ede26 100644 --- a/x-pack/plugins/monitoring/public/components/elasticsearch/node/advanced.js +++ b/x-pack/plugins/monitoring/public/components/elasticsearch/node/advanced.js @@ -27,8 +27,6 @@ export const AdvancedNode = ({ nodeSummary, metrics, alerts, ...props }) => { metrics.node_gc_time, metrics.node_jvm_mem, metrics.node_cpu_utilization, - metrics.node_index_1, - metrics.node_index_2, metrics.node_index_3, metrics.node_index_4, metrics.node_index_time, diff --git a/x-pack/plugins/monitoring/public/components/elasticsearch/node/node.js b/x-pack/plugins/monitoring/public/components/elasticsearch/node/node.js index 0b03f1077f9cb..0f545de7960d5 100644 --- a/x-pack/plugins/monitoring/public/components/elasticsearch/node/node.js +++ b/x-pack/plugins/monitoring/public/components/elasticsearch/node/node.js @@ -43,7 +43,6 @@ export const Node = ({ nodeSummary, metrics, logs, alerts, nodeId, clusterUuid, */ const metricsToShow = [ metrics.node_jvm_mem, - metrics.node_mem, metrics.node_total_io, metrics.node_cpu_metric, metrics.node_load_average, diff --git a/x-pack/plugins/monitoring/server/lib/cluster/__fixtures__/clusters.json b/x-pack/plugins/monitoring/server/lib/cluster/__fixtures__/clusters.json index 49a82492a2301..71e27d81ef9b6 100644 --- a/x-pack/plugins/monitoring/server/lib/cluster/__fixtures__/clusters.json +++ b/x-pack/plugins/monitoring/server/lib/cluster/__fixtures__/clusters.json @@ -69,13 +69,6 @@ }, "segments": { "count": 9, - "memory_in_bytes": 14272, - "terms_memory_in_bytes": 10251, - "stored_fields_memory_in_bytes": 2808, - "term_vectors_memory_in_bytes": 0, - "norms_memory_in_bytes": 320, - "points_memory_in_bytes": 9, - "doc_values_memory_in_bytes": 884, "index_writer_memory_in_bytes": 0, "version_map_memory_in_bytes": 0, "fixed_bit_set_memory_in_bytes": 0, @@ -417,13 +410,6 @@ }, "segments": { "count": 27, - "memory_in_bytes": 120198, - "terms_memory_in_bytes": 85510, - "stored_fields_memory_in_bytes": 8480, - "term_vectors_memory_in_bytes": 0, - "norms_memory_in_bytes": 4928, - "points_memory_in_bytes": 1020, - "doc_values_memory_in_bytes": 20260, "index_writer_memory_in_bytes": 174805, "version_map_memory_in_bytes": 16836, "fixed_bit_set_memory_in_bytes": 104, diff --git a/x-pack/plugins/monitoring/server/lib/details/__snapshots__/get_metrics.test.js.snap b/x-pack/plugins/monitoring/server/lib/details/__snapshots__/get_metrics.test.js.snap index 842372f633086..f6c5079091a5d 100644 --- a/x-pack/plugins/monitoring/server/lib/details/__snapshots__/get_metrics.test.js.snap +++ b/x-pack/plugins/monitoring/server/lib/details/__snapshots__/get_metrics.test.js.snap @@ -1516,7 +1516,7 @@ Object { exports[`getMetrics and getSeries should return metrics with object structure for metric 1`] = ` Object { - "index_1": Array [ + "index_3": Array [ Object { "bucket_size": "10 mins", "data": Array [ @@ -1871,14 +1871,14 @@ Object { ], "metric": Object { "app": "elasticsearch", - "description": "Total heap memory used by Lucene for current index. This is the sum of other fields for primary and replica shards.", - "field": "index_stats.total.segments.memory_in_bytes", + "description": "Heap memory used by Fixed Bit Sets (e.g., deeply nested documents). This is a part of Lucene Total.", + "field": "index_stats.total.segments.fixed_bit_set_memory_in_bytes", "format": "0.0 b", "hasCalculation": false, "isDerivative": false, - "label": "Lucene Total", + "label": "Fixed Bitsets", "metricAgg": "max", - "title": "Index Memory - Lucene 1", + "title": "Index Memory - Lucene", "units": "B", }, "timeRange": Object { @@ -2240,750 +2240,12 @@ Object { ], "metric": Object { "app": "elasticsearch", - "description": "Heap memory used by Stored Fields (e.g., _source). This is a part of Lucene Total.", - "field": "index_stats.total.segments.stored_fields_memory_in_bytes", + "description": "Heap memory used by Versioning (e.g., updates and deletes). This is NOT a part of Lucene Total.", + "field": "index_stats.total.segments.version_map_memory_in_bytes", "format": "0.0 b", "hasCalculation": false, "isDerivative": false, - "label": "Stored Fields", - "metricAgg": "max", - "title": "Index Memory", - "units": "B", - }, - "timeRange": Object { - "max": 1499054399999, - "min": 1498968000000, - }, - }, - Object { - "bucket_size": "10 mins", - "data": Array [ - Array [ - 1498968000000, - 2.1666666666667, - ], - Array [ - 1498968600000, - 2.3166666666667, - ], - Array [ - 1498969200000, - 2.3666666666667, - ], - Array [ - 1498969800000, - 2.5, - ], - Array [ - 1498970400000, - 2.6166666666667, - ], - Array [ - 1498971000000, - 2.85, - ], - Array [ - 1498971600000, - 2.8666666666667, - ], - Array [ - 1498972200000, - 3.0833333333333, - ], - Array [ - 1498972800000, - 1.6666666666667, - ], - Array [ - 1498973400000, - 0.11666666666667, - ], - Array [ - 1498974000000, - 0.13333333333333, - ], - Array [ - 1498974600000, - 0.43333333333333, - ], - Array [ - 1498975200000, - 1.15, - ], - Array [ - 1498975800000, - 1.1333333333333, - ], - Array [ - 1498976400000, - 1.15, - ], - Array [ - 1498977000000, - 1.05, - ], - Array [ - 1498977600000, - 1.1833333333333, - ], - Array [ - 1498978200000, - 0.91666666666667, - ], - Array [ - 1498978800000, - 0.95, - ], - Array [ - 1498979400000, - 1.0166666666667, - ], - Array [ - 1498980000000, - 1.0333333333333, - ], - Array [ - 1498980600000, - 1.05, - ], - Array [ - 1498981200000, - 1.0333333333333, - ], - Array [ - 1498981800000, - 1.0833333333333, - ], - Array [ - 1498982400000, - 1, - ], - Array [ - 1498983000000, - 1.1333333333333, - ], - Array [ - 1498983600000, - 1.3666666666667, - ], - Array [ - 1498984200000, - 1.9833333333333, - ], - Array [ - 1498984800000, - 2, - ], - Array [ - 1498985400000, - 2.1833333333333, - ], - Array [ - 1498986000000, - 2.2, - ], - Array [ - 1498986600000, - 2.3666666666667, - ], - Array [ - 1498987200000, - 2.4166666666667, - ], - Array [ - 1498987800000, - 2.55, - ], - Array [ - 1498988400000, - 2.7, - ], - Array [ - 1498989000000, - 2.8166666666667, - ], - Array [ - 1498989600000, - 2.9333333333333, - ], - Array [ - 1498990200000, - 3.0833333333333, - ], - Array [ - 1498990800000, - 3.1166666666667, - ], - Array [ - 1498991400000, - 3.3833333333333, - ], - Array [ - 1498992000000, - 3.4666666666667, - ], - Array [ - 1498992600000, - 1.0666666666667, - ], - Array [ - 1498993200000, - 1, - ], - Array [ - 1498993800000, - 1.0833333333333, - ], - Array [ - 1498994400000, - 1.1, - ], - Array [ - 1498995000000, - 1.05, - ], - Array [ - 1498995600000, - 1.0333333333333, - ], - Array [ - 1498996200000, - 1.1166666666667, - ], - Array [ - 1498996800000, - 1.0333333333333, - ], - Array [ - 1498997400000, - 1.0833333333333, - ], - Array [ - 1498998000000, - 1.0666666666667, - ], - Array [ - 1498998600000, - 1.0166666666667, - ], - Array [ - 1498999200000, - 1, - ], - Array [ - 1498999800000, - 1.05, - ], - Array [ - 1499000400000, - 1.0333333333333, - ], - Array [ - 1499001000000, - 1.8166666666667, - ], - Array [ - 1499001600000, - 2.0166666666667, - ], - Array [ - 1499002200000, - 2.0833333333333, - ], - Array [ - 1499002800000, - 2.2, - ], - Array [ - 1499003400000, - 2.3, - ], - Array [ - 1499004000000, - 2.3666666666667, - ], - Array [ - 1499004600000, - 2.5593220338983, - ], - Array [ - 1499005200000, - 2.7166666666667, - ], - Array [ - 1499005800000, - 2.8833333333333, - ], - Array [ - 1499006400000, - 3, - ], - Array [ - 1499007000000, - 3.0833333333333, - ], - Array [ - 1499007600000, - 3.25, - ], - Array [ - 1499008200000, - 3.3, - ], - Array [ - 1499008800000, - 3.5333333333333, - ], - Array [ - 1499009400000, - 3.7166666666667, - ], - Array [ - 1499010000000, - 3.7333333333333, - ], - Array [ - 1499010600000, - 3.9833333333333, - ], - Array [ - 1499011200000, - 4.1666666666667, - ], - Array [ - 1499011800000, - 2.7166666666667, - ], - Array [ - 1499012400000, - 1.0333333333333, - ], - Array [ - 1499013000000, - 1.1, - ], - Array [ - 1499013600000, - 1.2166666666667, - ], - Array [ - 1499014200000, - 1.2, - ], - Array [ - 1499014800000, - 0.98333333333333, - ], - Array [ - 1499015400000, - 1.25, - ], - Array [ - 1499016000000, - 1, - ], - Array [ - 1499016600000, - 1.2666666666667, - ], - Array [ - 1499017200000, - 1.0833333333333, - ], - Array [ - 1499017800000, - 1.05, - ], - Array [ - 1499018400000, - 0.93333333333333, - ], - Array [ - 1499019000000, - 1.05, - ], - Array [ - 1499019600000, - 1.5, - ], - ], - "metric": Object { - "app": "elasticsearch", - "description": "Heap memory used by Doc Values. This is a part of Lucene Total.", - "field": "index_stats.total.segments.doc_values_memory_in_bytes", - "format": "0.0 b", - "hasCalculation": false, - "isDerivative": false, - "label": "Doc Values", - "metricAgg": "max", - "title": "Index Memory", - "units": "B", - }, - "timeRange": Object { - "max": 1499054399999, - "min": 1498968000000, - }, - }, - Object { - "bucket_size": "10 mins", - "data": Array [ - Array [ - 1498968000000, - 2.1666666666667, - ], - Array [ - 1498968600000, - 2.3166666666667, - ], - Array [ - 1498969200000, - 2.3666666666667, - ], - Array [ - 1498969800000, - 2.5, - ], - Array [ - 1498970400000, - 2.6166666666667, - ], - Array [ - 1498971000000, - 2.85, - ], - Array [ - 1498971600000, - 2.8666666666667, - ], - Array [ - 1498972200000, - 3.0833333333333, - ], - Array [ - 1498972800000, - 1.6666666666667, - ], - Array [ - 1498973400000, - 0.11666666666667, - ], - Array [ - 1498974000000, - 0.13333333333333, - ], - Array [ - 1498974600000, - 0.43333333333333, - ], - Array [ - 1498975200000, - 1.15, - ], - Array [ - 1498975800000, - 1.1333333333333, - ], - Array [ - 1498976400000, - 1.15, - ], - Array [ - 1498977000000, - 1.05, - ], - Array [ - 1498977600000, - 1.1833333333333, - ], - Array [ - 1498978200000, - 0.91666666666667, - ], - Array [ - 1498978800000, - 0.95, - ], - Array [ - 1498979400000, - 1.0166666666667, - ], - Array [ - 1498980000000, - 1.0333333333333, - ], - Array [ - 1498980600000, - 1.05, - ], - Array [ - 1498981200000, - 1.0333333333333, - ], - Array [ - 1498981800000, - 1.0833333333333, - ], - Array [ - 1498982400000, - 1, - ], - Array [ - 1498983000000, - 1.1333333333333, - ], - Array [ - 1498983600000, - 1.3666666666667, - ], - Array [ - 1498984200000, - 1.9833333333333, - ], - Array [ - 1498984800000, - 2, - ], - Array [ - 1498985400000, - 2.1833333333333, - ], - Array [ - 1498986000000, - 2.2, - ], - Array [ - 1498986600000, - 2.3666666666667, - ], - Array [ - 1498987200000, - 2.4166666666667, - ], - Array [ - 1498987800000, - 2.55, - ], - Array [ - 1498988400000, - 2.7, - ], - Array [ - 1498989000000, - 2.8166666666667, - ], - Array [ - 1498989600000, - 2.9333333333333, - ], - Array [ - 1498990200000, - 3.0833333333333, - ], - Array [ - 1498990800000, - 3.1166666666667, - ], - Array [ - 1498991400000, - 3.3833333333333, - ], - Array [ - 1498992000000, - 3.4666666666667, - ], - Array [ - 1498992600000, - 1.0666666666667, - ], - Array [ - 1498993200000, - 1, - ], - Array [ - 1498993800000, - 1.0833333333333, - ], - Array [ - 1498994400000, - 1.1, - ], - Array [ - 1498995000000, - 1.05, - ], - Array [ - 1498995600000, - 1.0333333333333, - ], - Array [ - 1498996200000, - 1.1166666666667, - ], - Array [ - 1498996800000, - 1.0333333333333, - ], - Array [ - 1498997400000, - 1.0833333333333, - ], - Array [ - 1498998000000, - 1.0666666666667, - ], - Array [ - 1498998600000, - 1.0166666666667, - ], - Array [ - 1498999200000, - 1, - ], - Array [ - 1498999800000, - 1.05, - ], - Array [ - 1499000400000, - 1.0333333333333, - ], - Array [ - 1499001000000, - 1.8166666666667, - ], - Array [ - 1499001600000, - 2.0166666666667, - ], - Array [ - 1499002200000, - 2.0833333333333, - ], - Array [ - 1499002800000, - 2.2, - ], - Array [ - 1499003400000, - 2.3, - ], - Array [ - 1499004000000, - 2.3666666666667, - ], - Array [ - 1499004600000, - 2.5593220338983, - ], - Array [ - 1499005200000, - 2.7166666666667, - ], - Array [ - 1499005800000, - 2.8833333333333, - ], - Array [ - 1499006400000, - 3, - ], - Array [ - 1499007000000, - 3.0833333333333, - ], - Array [ - 1499007600000, - 3.25, - ], - Array [ - 1499008200000, - 3.3, - ], - Array [ - 1499008800000, - 3.5333333333333, - ], - Array [ - 1499009400000, - 3.7166666666667, - ], - Array [ - 1499010000000, - 3.7333333333333, - ], - Array [ - 1499010600000, - 3.9833333333333, - ], - Array [ - 1499011200000, - 4.1666666666667, - ], - Array [ - 1499011800000, - 2.7166666666667, - ], - Array [ - 1499012400000, - 1.0333333333333, - ], - Array [ - 1499013000000, - 1.1, - ], - Array [ - 1499013600000, - 1.2166666666667, - ], - Array [ - 1499014200000, - 1.2, - ], - Array [ - 1499014800000, - 0.98333333333333, - ], - Array [ - 1499015400000, - 1.25, - ], - Array [ - 1499016000000, - 1, - ], - Array [ - 1499016600000, - 1.2666666666667, - ], - Array [ - 1499017200000, - 1.0833333333333, - ], - Array [ - 1499017800000, - 1.05, - ], - Array [ - 1499018400000, - 0.93333333333333, - ], - Array [ - 1499019000000, - 1.05, - ], - Array [ - 1499019600000, - 1.5, - ], - ], - "metric": Object { - "app": "elasticsearch", - "description": "Heap memory used by Norms (normalization factors for query-time, text scoring). This is a part of Lucene Total.", - "field": "index_stats.total.segments.norms_memory_in_bytes", - "format": "0.0 b", - "hasCalculation": false, - "isDerivative": false, - "label": "Norms", + "label": "Version Map", "metricAgg": "max", "title": "Index Memory", "units": "B", diff --git a/x-pack/plugins/monitoring/server/lib/details/get_metrics.test.js b/x-pack/plugins/monitoring/server/lib/details/get_metrics.test.js index 3c991f08f6153..80234ee369aee 100644 --- a/x-pack/plugins/monitoring/server/lib/details/get_metrics.test.js +++ b/x-pack/plugins/monitoring/server/lib/details/get_metrics.test.js @@ -87,13 +87,8 @@ describe('getMetrics and getSeries', () => { const req = getMockReq(nonDerivMetricsBuckets); const metricSet = [ { - name: 'index_1', - keys: [ - 'index_mem_overall_1', - 'index_mem_stored_fields', - 'index_mem_doc_values', - 'index_mem_norms', - ], + name: 'index_3', + keys: ['index_mem_fixed_bit_set', 'index_mem_versions'], }, ]; const result = await getMetrics(req, indexPattern, metricSet); diff --git a/x-pack/plugins/monitoring/server/lib/elasticsearch/nodes/get_nodes/__fixtures__/cluster_data.json b/x-pack/plugins/monitoring/server/lib/elasticsearch/nodes/get_nodes/__fixtures__/cluster_data.json index b8abe525b3fa6..a2c58a801cd8c 100644 --- a/x-pack/plugins/monitoring/server/lib/elasticsearch/nodes/get_nodes/__fixtures__/cluster_data.json +++ b/x-pack/plugins/monitoring/server/lib/elasticsearch/nodes/get_nodes/__fixtures__/cluster_data.json @@ -2785,17 +2785,10 @@ }, "segments": { "count": 46, - "doc_values_memory_in_bytes": 61544, "file_sizes": {}, "fixed_bit_set_memory_in_bytes": 400, "index_writer_memory_in_bytes": 287996, "max_unsafe_auto_id_timestamp": 1518549739793, - "memory_in_bytes": 306088, - "norms_memory_in_bytes": 11520, - "points_memory_in_bytes": 3705, - "stored_fields_memory_in_bytes": 14456, - "term_vectors_memory_in_bytes": 0, - "terms_memory_in_bytes": 214863, "version_map_memory_in_bytes": 10008 }, "shards": { diff --git a/x-pack/plugins/monitoring/server/lib/elasticsearch/shards/__fixtures__/cluster.json b/x-pack/plugins/monitoring/server/lib/elasticsearch/shards/__fixtures__/cluster.json index a49eb35086469..4f9daf62924c7 100644 --- a/x-pack/plugins/monitoring/server/lib/elasticsearch/shards/__fixtures__/cluster.json +++ b/x-pack/plugins/monitoring/server/lib/elasticsearch/shards/__fixtures__/cluster.json @@ -49,17 +49,10 @@ }, "segments": { "count": 202, - "doc_values_memory_in_bytes": 602248, "file_sizes": {}, "fixed_bit_set_memory_in_bytes": 608, "index_writer_memory_in_bytes": 2368414, "max_unsafe_auto_id_timestamp": 1505411847867, - "memory_in_bytes": 5079404, - "norms_memory_in_bytes": 475392, - "points_memory_in_bytes": 11512, - "stored_fields_memory_in_bytes": 65080, - "term_vectors_memory_in_bytes": 0, - "terms_memory_in_bytes": 3925172, "version_map_memory_in_bytes": 697814 }, "shards": { diff --git a/x-pack/plugins/monitoring/server/lib/metrics/__snapshots__/metrics.test.js.snap b/x-pack/plugins/monitoring/server/lib/metrics/__snapshots__/metrics.test.js.snap index 56d923da56202..cbd6a610d5eb8 100644 --- a/x-pack/plugins/monitoring/server/lib/metrics/__snapshots__/metrics.test.js.snap +++ b/x-pack/plugins/monitoring/server/lib/metrics/__snapshots__/metrics.test.js.snap @@ -2577,20 +2577,6 @@ Object { "units": "ms", "uuidField": "source_node.uuid", }, - "index_mem_doc_values": SingleIndexMemoryMetric { - "app": "elasticsearch", - "derivative": false, - "description": "Heap memory used by Doc Values. This is a part of Lucene Total.", - "field": "index_stats.total.segments.doc_values_memory_in_bytes", - "format": "0.0 b", - "label": "Doc Values", - "metricAgg": "max", - "timestampField": "timestamp", - "title": "Index Memory", - "type": "index", - "units": "B", - "uuidField": "source_node.uuid", - }, "index_mem_fielddata": IndexMemoryMetric { "app": "elasticsearch", "derivative": false, @@ -2614,91 +2600,7 @@ Object { "label": "Fixed Bitsets", "metricAgg": "max", "timestampField": "timestamp", - "title": "Index Memory", - "type": "index", - "units": "B", - "uuidField": "source_node.uuid", - }, - "index_mem_norms": SingleIndexMemoryMetric { - "app": "elasticsearch", - "derivative": false, - "description": "Heap memory used by Norms (normalization factors for query-time, text scoring). This is a part of Lucene Total.", - "field": "index_stats.total.segments.norms_memory_in_bytes", - "format": "0.0 b", - "label": "Norms", - "metricAgg": "max", - "timestampField": "timestamp", - "title": "Index Memory", - "type": "index", - "units": "B", - "uuidField": "source_node.uuid", - }, - "index_mem_overall": SingleIndexMemoryMetric { - "app": "elasticsearch", - "derivative": false, - "description": "Total heap memory used by Lucene for current index. This is the sum of other fields for primary and replica shards.", - "field": "index_stats.total.segments.memory_in_bytes", - "format": "0.0 b", - "label": "Lucene Total", - "metricAgg": "max", - "timestampField": "timestamp", - "title": "Index Memory", - "type": "index", - "units": "B", - "uuidField": "source_node.uuid", - }, - "index_mem_overall_1": SingleIndexMemoryMetric { - "app": "elasticsearch", - "derivative": false, - "description": "Total heap memory used by Lucene for current index. This is the sum of other fields for primary and replica shards.", - "field": "index_stats.total.segments.memory_in_bytes", - "format": "0.0 b", - "label": "Lucene Total", - "metricAgg": "max", - "timestampField": "timestamp", - "title": "Index Memory - Lucene 1", - "type": "index", - "units": "B", - "uuidField": "source_node.uuid", - }, - "index_mem_overall_2": SingleIndexMemoryMetric { - "app": "elasticsearch", - "derivative": false, - "description": "Total heap memory used by Lucene for current index. This is the sum of other fields for primary and replica shards.", - "field": "index_stats.total.segments.memory_in_bytes", - "format": "0.0 b", - "label": "Lucene Total", - "metricAgg": "max", - "timestampField": "timestamp", - "title": "Index Memory - Lucene 2", - "type": "index", - "units": "B", - "uuidField": "source_node.uuid", - }, - "index_mem_overall_3": SingleIndexMemoryMetric { - "app": "elasticsearch", - "derivative": false, - "description": "Total heap memory used by Lucene for current index. This is the sum of other fields for primary and replica shards.", - "field": "index_stats.total.segments.memory_in_bytes", - "format": "0.0 b", - "label": "Lucene Total", - "metricAgg": "max", - "timestampField": "timestamp", - "title": "Index Memory - Lucene 3", - "type": "index", - "units": "B", - "uuidField": "source_node.uuid", - }, - "index_mem_points": SingleIndexMemoryMetric { - "app": "elasticsearch", - "derivative": false, - "description": "Heap memory used by Points (e.g., numbers, IPs, and geo data). This is a part of Lucene Total.", - "field": "index_stats.total.segments.points_memory_in_bytes", - "format": "0.0 b", - "label": "Points", - "metricAgg": "max", - "timestampField": "timestamp", - "title": "Index Memory", + "title": "Index Memory - Lucene", "type": "index", "units": "B", "uuidField": "source_node.uuid", @@ -2731,48 +2633,6 @@ Object { "units": "B", "uuidField": "source_node.uuid", }, - "index_mem_stored_fields": SingleIndexMemoryMetric { - "app": "elasticsearch", - "derivative": false, - "description": "Heap memory used by Stored Fields (e.g., _source). This is a part of Lucene Total.", - "field": "index_stats.total.segments.stored_fields_memory_in_bytes", - "format": "0.0 b", - "label": "Stored Fields", - "metricAgg": "max", - "timestampField": "timestamp", - "title": "Index Memory", - "type": "index", - "units": "B", - "uuidField": "source_node.uuid", - }, - "index_mem_term_vectors": SingleIndexMemoryMetric { - "app": "elasticsearch", - "derivative": false, - "description": "Heap memory used by Term Vectors. This is a part of Lucene Total.", - "field": "index_stats.total.segments.term_vectors_memory_in_bytes", - "format": "0.0 b", - "label": "Term Vectors", - "metricAgg": "max", - "timestampField": "timestamp", - "title": "Index Memory", - "type": "index", - "units": "B", - "uuidField": "source_node.uuid", - }, - "index_mem_terms": SingleIndexMemoryMetric { - "app": "elasticsearch", - "derivative": false, - "description": "Heap memory used by Terms (e.g., text). This is a part of Lucene Total.", - "field": "index_stats.total.segments.terms_memory_in_bytes", - "format": "0.0 b", - "label": "Terms", - "metricAgg": "max", - "timestampField": "timestamp", - "title": "Index Memory", - "type": "index", - "units": "B", - "uuidField": "source_node.uuid", - }, "index_mem_versions": SingleIndexMemoryMetric { "app": "elasticsearch", "derivative": false, @@ -4145,20 +4005,6 @@ Object { "units": "ms", "uuidField": "source_node.uuid", }, - "node_index_mem_doc_values": NodeIndexMemoryMetric { - "app": "elasticsearch", - "derivative": false, - "description": "Heap memory used by Doc Values. This is a part of Lucene Total.", - "field": "node_stats.indices.segments.doc_values_memory_in_bytes", - "format": "0.0 b", - "label": "Doc Values", - "metricAgg": "max", - "timestampField": "timestamp", - "title": "Index Memory", - "type": "node", - "units": "B", - "uuidField": "source_node.uuid", - }, "node_index_mem_fielddata": IndexMemoryMetric { "app": "elasticsearch", "derivative": false, @@ -4182,91 +4028,7 @@ Object { "label": "Fixed Bitsets", "metricAgg": "max", "timestampField": "timestamp", - "title": "Index Memory", - "type": "node", - "units": "B", - "uuidField": "source_node.uuid", - }, - "node_index_mem_norms": NodeIndexMemoryMetric { - "app": "elasticsearch", - "derivative": false, - "description": "Heap memory used by Norms (normalization factors for query-time, text scoring). This is a part of Lucene Total.", - "field": "node_stats.indices.segments.norms_memory_in_bytes", - "format": "0.0 b", - "label": "Norms", - "metricAgg": "max", - "timestampField": "timestamp", - "title": "Index Memory", - "type": "node", - "units": "B", - "uuidField": "source_node.uuid", - }, - "node_index_mem_overall": NodeIndexMemoryMetric { - "app": "elasticsearch", - "derivative": false, - "description": "Total heap memory used by Lucene for current index. This is the sum of other fields for primary and replica shards on this node.", - "field": "node_stats.indices.segments.memory_in_bytes", - "format": "0.0 b", - "label": "Lucene Total", - "metricAgg": "max", - "timestampField": "timestamp", - "title": "Index Memory", - "type": "node", - "units": "B", - "uuidField": "source_node.uuid", - }, - "node_index_mem_overall_1": NodeIndexMemoryMetric { - "app": "elasticsearch", - "derivative": false, - "description": "Total heap memory used by Lucene for current index. This is the sum of other fields for primary and replica shards on this node.", - "field": "node_stats.indices.segments.memory_in_bytes", - "format": "0.0 b", - "label": "Lucene Total", - "metricAgg": "max", - "timestampField": "timestamp", - "title": "Index Memory - Lucene 1", - "type": "node", - "units": "B", - "uuidField": "source_node.uuid", - }, - "node_index_mem_overall_2": NodeIndexMemoryMetric { - "app": "elasticsearch", - "derivative": false, - "description": "Total heap memory used by Lucene for current index. This is the sum of other fields for primary and replica shards on this node.", - "field": "node_stats.indices.segments.memory_in_bytes", - "format": "0.0 b", - "label": "Lucene Total", - "metricAgg": "max", - "timestampField": "timestamp", - "title": "Index Memory - Lucene 2", - "type": "node", - "units": "B", - "uuidField": "source_node.uuid", - }, - "node_index_mem_overall_3": NodeIndexMemoryMetric { - "app": "elasticsearch", - "derivative": false, - "description": "Total heap memory used by Lucene for current index. This is the sum of other fields for primary and replica shards on this node.", - "field": "node_stats.indices.segments.memory_in_bytes", - "format": "0.0 b", - "label": "Lucene Total", - "metricAgg": "max", - "timestampField": "timestamp", - "title": "Index Memory - Lucene 3", - "type": "node", - "units": "B", - "uuidField": "source_node.uuid", - }, - "node_index_mem_points": NodeIndexMemoryMetric { - "app": "elasticsearch", - "derivative": false, - "description": "Heap memory used by Points (e.g., numbers, IPs, and geo data). This is a part of Lucene Total.", - "field": "node_stats.indices.segments.points_memory_in_bytes", - "format": "0.0 b", - "label": "Points", - "metricAgg": "max", - "timestampField": "timestamp", - "title": "Index Memory", + "title": "Index Memory - Lucene", "type": "node", "units": "B", "uuidField": "source_node.uuid", @@ -4299,48 +4061,6 @@ Object { "units": "B", "uuidField": "source_node.uuid", }, - "node_index_mem_stored_fields": NodeIndexMemoryMetric { - "app": "elasticsearch", - "derivative": false, - "description": "Heap memory used by Stored Fields (e.g., _source). This is a part of Lucene Total.", - "field": "node_stats.indices.segments.stored_fields_memory_in_bytes", - "format": "0.0 b", - "label": "Stored Fields", - "metricAgg": "max", - "timestampField": "timestamp", - "title": "Index Memory", - "type": "node", - "units": "B", - "uuidField": "source_node.uuid", - }, - "node_index_mem_term_vectors": NodeIndexMemoryMetric { - "app": "elasticsearch", - "derivative": false, - "description": "Heap memory used by Term Vectors. This is a part of Lucene Total.", - "field": "node_stats.indices.segments.term_vectors_memory_in_bytes", - "format": "0.0 b", - "label": "Term Vectors", - "metricAgg": "max", - "timestampField": "timestamp", - "title": "Index Memory", - "type": "node", - "units": "B", - "uuidField": "source_node.uuid", - }, - "node_index_mem_terms": NodeIndexMemoryMetric { - "app": "elasticsearch", - "derivative": false, - "description": "Heap memory used by Terms (e.g., text). This is a part of Lucene Total.", - "field": "node_stats.indices.segments.terms_memory_in_bytes", - "format": "0.0 b", - "label": "Terms", - "metricAgg": "max", - "timestampField": "timestamp", - "title": "Index Memory", - "type": "node", - "units": "B", - "uuidField": "source_node.uuid", - }, "node_index_mem_versions": NodeIndexMemoryMetric { "app": "elasticsearch", "derivative": false, diff --git a/x-pack/plugins/monitoring/server/lib/metrics/elasticsearch/metrics.js b/x-pack/plugins/monitoring/server/lib/metrics/elasticsearch/metrics.js index 6fe93619a5f9b..83841b0ecb39e 100644 --- a/x-pack/plugins/monitoring/server/lib/metrics/elasticsearch/metrics.js +++ b/x-pack/plugins/monitoring/server/lib/metrics/elasticsearch/metrics.js @@ -307,73 +307,6 @@ export const metrics = { metricAgg: 'max', units: '', }), - index_mem_overall: new SingleIndexMemoryMetric({ - field: 'memory_in_bytes', - label: i18n.translate('xpack.monitoring.metrics.esIndex.luceneTotalLabel', { - defaultMessage: 'Lucene Total', - }), - description: i18n.translate('xpack.monitoring.metrics.esIndex.luceneTotalDescription', { - defaultMessage: - 'Total heap memory used by Lucene for current index. This is the sum of other fields for primary and replica shards.', - }), - }), - index_mem_overall_1: new SingleIndexMemoryMetric({ - field: 'memory_in_bytes', - title: i18n.translate('xpack.monitoring.metrics.esIndex.indexMemoryLucene1Title', { - defaultMessage: 'Index Memory - Lucene 1', - }), - label: i18n.translate('xpack.monitoring.metrics.esIndex.indexMemoryLucene1.luceneTotalLabel', { - defaultMessage: 'Lucene Total', - }), - description: i18n.translate( - 'xpack.monitoring.metrics.esIndex.indexMemoryLucene1.luceneTotalDescription', - { - defaultMessage: - 'Total heap memory used by Lucene for current index. This is the sum of other fields for primary and replica shards.', - } - ), - }), - index_mem_overall_2: new SingleIndexMemoryMetric({ - field: 'memory_in_bytes', - title: i18n.translate('xpack.monitoring.metrics.esIndex.indexMemoryLucene2Title', { - defaultMessage: 'Index Memory - Lucene 2', - }), - label: i18n.translate('xpack.monitoring.metrics.esIndex.indexMemoryLucene2.luceneTotalLabel', { - defaultMessage: 'Lucene Total', - }), - description: i18n.translate( - 'xpack.monitoring.metrics.esIndex.indexMemoryLucene2.luceneTotalDescription', - { - defaultMessage: - 'Total heap memory used by Lucene for current index. This is the sum of other fields for primary and replica shards.', - } - ), - }), - index_mem_overall_3: new SingleIndexMemoryMetric({ - field: 'memory_in_bytes', - title: i18n.translate('xpack.monitoring.metrics.esIndex.indexMemoryLucene3Title', { - defaultMessage: 'Index Memory - Lucene 3', - }), - label: i18n.translate('xpack.monitoring.metrics.esIndex.indexMemoryLucene3.luceneTotalLabel', { - defaultMessage: 'Lucene Total', - }), - description: i18n.translate( - 'xpack.monitoring.metrics.esIndex.indexMemoryLucene3.luceneTotalDescription', - { - defaultMessage: - 'Total heap memory used by Lucene for current index. This is the sum of other fields for primary and replica shards.', - } - ), - }), - index_mem_doc_values: new SingleIndexMemoryMetric({ - field: 'doc_values_memory_in_bytes', - label: i18n.translate('xpack.monitoring.metrics.esIndex.docValuesLabel', { - defaultMessage: 'Doc Values', - }), - description: i18n.translate('xpack.monitoring.metrics.esIndex.docValuesDescription', { - defaultMessage: 'Heap memory used by Doc Values. This is a part of Lucene Total.', - }), - }), // Note: This is not segment memory, unlike SingleIndexMemoryMetrics index_mem_fielddata: new IndexMemoryMetric({ field: 'index_stats.total.fielddata.memory_size_in_bytes', @@ -389,6 +322,9 @@ export const metrics = { }), index_mem_fixed_bit_set: new SingleIndexMemoryMetric({ field: 'fixed_bit_set_memory_in_bytes', + title: i18n.translate('xpack.monitoring.metrics.esIndex.fixedBitsetsTitle', { + defaultMessage: 'Index Memory - Lucene', + }), label: i18n.translate('xpack.monitoring.metrics.esIndex.fixedBitsetsLabel', { defaultMessage: 'Fixed Bitsets', }), @@ -397,26 +333,6 @@ export const metrics = { 'Heap memory used by Fixed Bit Sets (e.g., deeply nested documents). This is a part of Lucene Total.', }), }), - index_mem_norms: new SingleIndexMemoryMetric({ - field: 'norms_memory_in_bytes', - label: i18n.translate('xpack.monitoring.metrics.esIndex.normsLabel', { - defaultMessage: 'Norms', - }), - description: i18n.translate('xpack.monitoring.metrics.esIndex.normsDescription', { - defaultMessage: - 'Heap memory used by Norms (normalization factors for query-time, text scoring). This is a part of Lucene Total.', - }), - }), - index_mem_points: new SingleIndexMemoryMetric({ - field: 'points_memory_in_bytes', - label: i18n.translate('xpack.monitoring.metrics.esIndex.pointsLabel', { - defaultMessage: 'Points', - }), - description: i18n.translate('xpack.monitoring.metrics.esIndex.pointsDescription', { - defaultMessage: - 'Heap memory used by Points (e.g., numbers, IPs, and geo data). This is a part of Lucene Total.', - }), - }), // Note: This is not segment memory, unlike SingleIndexMemoryMetrics index_mem_query_cache: new IndexMemoryMetric({ field: 'index_stats.total.query_cache.memory_size_in_bytes', @@ -448,34 +364,6 @@ export const metrics = { }), type: 'index', }), - index_mem_stored_fields: new SingleIndexMemoryMetric({ - field: 'stored_fields_memory_in_bytes', - label: i18n.translate('xpack.monitoring.metrics.esIndex.storedFieldsLabel', { - defaultMessage: 'Stored Fields', - }), - description: i18n.translate('xpack.monitoring.metrics.esIndex.storedFieldsDescription', { - defaultMessage: - 'Heap memory used by Stored Fields (e.g., _source). This is a part of Lucene Total.', - }), - }), - index_mem_term_vectors: new SingleIndexMemoryMetric({ - field: 'term_vectors_memory_in_bytes', - label: i18n.translate('xpack.monitoring.metrics.esIndex.termVectorsLabel', { - defaultMessage: 'Term Vectors', - }), - description: i18n.translate('xpack.monitoring.metrics.esIndex.termVectorsDescription', { - defaultMessage: 'Heap memory used by Term Vectors. This is a part of Lucene Total.', - }), - }), - index_mem_terms: new SingleIndexMemoryMetric({ - field: 'terms_memory_in_bytes', - label: i18n.translate('xpack.monitoring.metrics.esIndex.termsLabel', { - defaultMessage: 'Terms', - }), - description: i18n.translate('xpack.monitoring.metrics.esIndex.termsDescription', { - defaultMessage: 'Heap memory used by Terms (e.g., text). This is a part of Lucene Total.', - }), - }), index_mem_versions: new SingleIndexMemoryMetric({ field: 'version_map_memory_in_bytes', label: i18n.translate('xpack.monitoring.metrics.esIndex.versionMapLabel', { @@ -1050,73 +938,6 @@ export const metrics = { metricAgg: 'max', units: '', }), - node_index_mem_overall: new NodeIndexMemoryMetric({ - field: 'memory_in_bytes', - label: i18n.translate('xpack.monitoring.metrics.esNode.luceneTotalLabel', { - defaultMessage: 'Lucene Total', - }), - description: i18n.translate('xpack.monitoring.metrics.esNode.luceneTotalDescription', { - defaultMessage: - 'Total heap memory used by Lucene for current index. This is the sum of other fields for primary and replica shards on this node.', - }), - }), - node_index_mem_overall_1: new NodeIndexMemoryMetric({ - field: 'memory_in_bytes', - label: i18n.translate('xpack.monitoring.metrics.esNode.indexMemoryLucene1.lucenceTotalLabel', { - defaultMessage: 'Lucene Total', - }), - title: i18n.translate('xpack.monitoring.metrics.esNode.indexMemoryLucene1Title', { - defaultMessage: 'Index Memory - Lucene 1', - }), - description: i18n.translate( - 'xpack.monitoring.metrics.esNode.indexMemoryLucene1.lucenceTotalDescription', - { - defaultMessage: - 'Total heap memory used by Lucene for current index. This is the sum of other fields for primary and replica shards on this node.', - } - ), - }), - node_index_mem_overall_2: new NodeIndexMemoryMetric({ - field: 'memory_in_bytes', - label: i18n.translate('xpack.monitoring.metrics.esNode.indexMemoryLucene2.lucenceTotalLabel', { - defaultMessage: 'Lucene Total', - }), - title: i18n.translate('xpack.monitoring.metrics.esNode.indexMemoryLucene2Title', { - defaultMessage: 'Index Memory - Lucene 2', - }), - description: i18n.translate( - 'xpack.monitoring.metrics.esNode.indexMemoryLucene2.lucenceTotalDescription', - { - defaultMessage: - 'Total heap memory used by Lucene for current index. This is the sum of other fields for primary and replica shards on this node.', - } - ), - }), - node_index_mem_overall_3: new NodeIndexMemoryMetric({ - field: 'memory_in_bytes', - label: i18n.translate('xpack.monitoring.metrics.esNode.indexMemoryLucene3.lucenceTotalLabel', { - defaultMessage: 'Lucene Total', - }), - title: i18n.translate('xpack.monitoring.metrics.esNode.indexMemoryLucene3Title', { - defaultMessage: 'Index Memory - Lucene 3', - }), - description: i18n.translate( - 'xpack.monitoring.metrics.esNode.indexMemoryLucene3.lucenceTotalDescription', - { - defaultMessage: - 'Total heap memory used by Lucene for current index. This is the sum of other fields for primary and replica shards on this node.', - } - ), - }), - node_index_mem_doc_values: new NodeIndexMemoryMetric({ - field: 'doc_values_memory_in_bytes', - label: i18n.translate('xpack.monitoring.metrics.esNode.docValuesLabel', { - defaultMessage: 'Doc Values', - }), - description: i18n.translate('xpack.monitoring.metrics.esNode.docValuesDescription', { - defaultMessage: 'Heap memory used by Doc Values. This is a part of Lucene Total.', - }), - }), // Note: This is not segment memory, unlike the rest of the SingleIndexMemoryMetrics node_index_mem_fielddata: new IndexMemoryMetric({ field: 'node_stats.indices.fielddata.memory_size_in_bytes', @@ -1132,6 +953,9 @@ export const metrics = { }), node_index_mem_fixed_bit_set: new NodeIndexMemoryMetric({ field: 'fixed_bit_set_memory_in_bytes', + title: i18n.translate('xpack.monitoring.metrics.esNode.fixedBitsetsTitle', { + defaultMessage: 'Index Memory - Lucene', + }), label: i18n.translate('xpack.monitoring.metrics.esNode.fixedBitsetsLabel', { defaultMessage: 'Fixed Bitsets', }), @@ -1140,26 +964,6 @@ export const metrics = { 'Heap memory used by Fixed Bit Sets (e.g., deeply nested documents). This is a part of Lucene Total.', }), }), - node_index_mem_norms: new NodeIndexMemoryMetric({ - field: 'norms_memory_in_bytes', - label: i18n.translate('xpack.monitoring.metrics.esNode.normsLabel', { - defaultMessage: 'Norms', - }), - description: i18n.translate('xpack.monitoring.metrics.esNode.normsDescription', { - defaultMessage: - 'Heap memory used by Norms (normalization factors for query-time, text scoring). This is a part of Lucene Total.', - }), - }), - node_index_mem_points: new NodeIndexMemoryMetric({ - field: 'points_memory_in_bytes', - label: i18n.translate('xpack.monitoring.metrics.esNode.pointsLabel', { - defaultMessage: 'Points', - }), - description: i18n.translate('xpack.monitoring.metrics.esNode.pointsDescription', { - defaultMessage: - 'Heap memory used by Points (e.g., numbers, IPs, and geo data). This is a part of Lucene Total.', - }), - }), // Note: This is not segment memory, unlike SingleIndexMemoryMetrics node_index_mem_query_cache: new IndexMemoryMetric({ field: 'node_stats.indices.query_cache.memory_size_in_bytes', @@ -1191,34 +995,6 @@ export const metrics = { }), type: 'node', }), - node_index_mem_stored_fields: new NodeIndexMemoryMetric({ - field: 'stored_fields_memory_in_bytes', - label: i18n.translate('xpack.monitoring.metrics.esNode.storedFieldsLabel', { - defaultMessage: 'Stored Fields', - }), - description: i18n.translate('xpack.monitoring.metrics.esNode.storedFieldsDescription', { - defaultMessage: - 'Heap memory used by Stored Fields (e.g., _source). This is a part of Lucene Total.', - }), - }), - node_index_mem_term_vectors: new NodeIndexMemoryMetric({ - field: 'term_vectors_memory_in_bytes', - label: i18n.translate('xpack.monitoring.metrics.esNode.termVectorsLabel', { - defaultMessage: 'Term Vectors', - }), - description: i18n.translate('xpack.monitoring.metrics.esNode.termVectorsDescription', { - defaultMessage: 'Heap memory used by Term Vectors. This is a part of Lucene Total.', - }), - }), - node_index_mem_terms: new NodeIndexMemoryMetric({ - field: 'terms_memory_in_bytes', - label: i18n.translate('xpack.monitoring.metrics.esNode.termsLabel', { - defaultMessage: 'Terms', - }), - description: i18n.translate('xpack.monitoring.metrics.esNode.termsDescription', { - defaultMessage: 'Heap memory used by Terms (e.g., text). This is a part of Lucene Total.', - }), - }), node_index_mem_versions: new NodeIndexMemoryMetric({ field: 'version_map_memory_in_bytes', label: i18n.translate('xpack.monitoring.metrics.esNode.versionMapLabel', { diff --git a/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch/metric_set_index_detail.js b/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch/metric_set_index_detail.js index 14712ecd59f0e..fce09eac4918f 100644 --- a/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch/metric_set_index_detail.js +++ b/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch/metric_set_index_detail.js @@ -8,25 +8,7 @@ export const metricSet = { advanced: [ { - keys: [ - 'index_mem_overall_1', - 'index_mem_stored_fields', - 'index_mem_doc_values', - 'index_mem_norms', - ], - name: 'index_1', - }, - { - keys: ['index_mem_overall_2', 'index_mem_terms', 'index_mem_points'], - name: 'index_2', - }, - { - keys: [ - 'index_mem_overall_3', - 'index_mem_fixed_bit_set', - 'index_mem_term_vectors', - 'index_mem_versions', - ], + keys: ['index_mem_fixed_bit_set', 'index_mem_versions'], name: 'index_3', }, { @@ -82,10 +64,6 @@ export const metricSet = { keys: ['index_store_total_size', 'index_store_primaries_size'], name: 'index_size', }, - { - keys: ['index_mem_overall', 'index_mem_terms', 'index_mem_points'], - name: 'index_mem', - }, 'index_document_count', { keys: ['index_segment_count_total', 'index_segment_count_primaries'], diff --git a/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch/metric_set_node_detail.js b/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch/metric_set_node_detail.js index dcb5b70cf8963..5303dc452f850 100644 --- a/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch/metric_set_node_detail.js +++ b/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch/metric_set_node_detail.js @@ -20,25 +20,7 @@ export const metricSets = { name: 'node_gc_time', }, { - keys: [ - 'node_index_mem_overall_1', - 'node_index_mem_stored_fields', - 'node_index_mem_doc_values', - 'node_index_mem_norms', - ], - name: 'node_index_1', - }, - { - keys: ['node_index_mem_overall_2', 'node_index_mem_terms', 'node_index_mem_points'], - name: 'node_index_2', - }, - { - keys: [ - 'node_index_mem_overall_3', - 'node_index_mem_fixed_bit_set', - 'node_index_mem_term_vectors', - 'node_index_mem_versions', - ], + keys: ['node_index_mem_fixed_bit_set', 'node_index_mem_versions'], name: 'node_index_3', }, { @@ -101,10 +83,6 @@ export const metricSets = { keys: ['node_jvm_mem_max_in_bytes', 'node_jvm_mem_used_in_bytes'], name: 'node_jvm_mem', }, - { - keys: ['node_index_mem_overall', 'node_index_mem_terms', 'node_index_mem_points'], - name: 'node_mem', - }, { keys: [], name: 'node_cpu_metric', diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 45b6828e25fe6..a4ec0285361e4 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -18325,8 +18325,6 @@ "xpack.monitoring.metrics.esIndex.disk.storePrimariesDescription": "ディスク上のプライマリシャードのサイズです。", "xpack.monitoring.metrics.esIndex.disk.storePrimariesLabel": "格納サイズ(プライマリ)", "xpack.monitoring.metrics.esIndex.diskTitle": "ディスク", - "xpack.monitoring.metrics.esIndex.docValuesDescription": "ドキュメント値が使用中のヒープ領域です。Lucene の一部です。", - "xpack.monitoring.metrics.esIndex.docValuesLabel": "ドキュメント値", "xpack.monitoring.metrics.esIndex.fielddataDescription": "フィールドデータ(例:グローバル序数またはテキストフィールドで特別に有効化されたフィールドデータ)が使用中のヒープ領域です。同じシャードのものですが、Lucene 合計には含まれません。", "xpack.monitoring.metrics.esIndex.fielddataLabel": "フィールドデータ", "xpack.monitoring.metrics.esIndex.fixedBitsetsDescription": "固定ビットセット(例:ディープネスト構造のドキュメント)が使用中のヒープ領域です。Lucene の一部です。", @@ -18339,15 +18337,6 @@ "xpack.monitoring.metrics.esIndex.indexMemoryEs.queryCacheDescription": "クエリキャッシュ(例:キャッシュされたフィルター)が使用中のヒープ領域です。同じシャードのものですが、Lucene 合計には含まれません。", "xpack.monitoring.metrics.esIndex.indexMemoryEs.queryCacheLabel": "クエリキャッシュ", "xpack.monitoring.metrics.esIndex.indexMemoryEsTitle": "インデックスメモリー - {elasticsearch}", - "xpack.monitoring.metrics.esIndex.indexMemoryLucene1.luceneTotalDescription": "Lucene が現在のインデックスに使用中の合計ヒープ領域です。これはプライマリとレプリカシャードの他のフィールドの合計です。", - "xpack.monitoring.metrics.esIndex.indexMemoryLucene1.luceneTotalLabel": "Lucene 合計", - "xpack.monitoring.metrics.esIndex.indexMemoryLucene1Title": "インデックスメモリー - Lucene 1", - "xpack.monitoring.metrics.esIndex.indexMemoryLucene2.luceneTotalDescription": "Lucene が現在のインデックスに使用中の合計ヒープ領域です。これはプライマリとレプリカシャードの他のフィールドの合計です。", - "xpack.monitoring.metrics.esIndex.indexMemoryLucene2.luceneTotalLabel": "Lucene 合計", - "xpack.monitoring.metrics.esIndex.indexMemoryLucene2Title": "インデックスメモリー - Lucene 2", - "xpack.monitoring.metrics.esIndex.indexMemoryLucene3.luceneTotalDescription": "Lucene が現在のインデックスに使用中の合計ヒープ領域です。これはプライマリとレプリカシャードの他のフィールドの合計です。", - "xpack.monitoring.metrics.esIndex.indexMemoryLucene3.luceneTotalLabel": "Lucene 合計", - "xpack.monitoring.metrics.esIndex.indexMemoryLucene3Title": "インデックスメモリー - Lucene 3", "xpack.monitoring.metrics.esIndex.indexWriterDescription": "Index Writer が使用中のヒープ領域です。Lucene 合計の一部ではありません。", "xpack.monitoring.metrics.esIndex.indexWriterLabel": "Index Writer", "xpack.monitoring.metrics.esIndex.latency.indexingLatencyDescription": "ドキュメントのインデックスの平均レイテンシです。ドキュメントのインデックスの所要時間をインデックス数で割った時間です。プライマリシャードのみが含まれています。", @@ -18355,12 +18344,6 @@ "xpack.monitoring.metrics.esIndex.latency.searchLatencyDescription": "検索の平均レイテンシです。検索の実行に所要した時間を送信された検索数で割った時間です。プライマリとレプリカシャードが含まれています。", "xpack.monitoring.metrics.esIndex.latency.searchLatencyLabel": "検索レイテンシ", "xpack.monitoring.metrics.esIndex.latencyTitle": "レイテンシ", - "xpack.monitoring.metrics.esIndex.luceneTotalDescription": "Lucene が現在のインデックスに使用中の合計ヒープ領域です。これはプライマリとレプリカシャードの他のフィールドの合計です。", - "xpack.monitoring.metrics.esIndex.luceneTotalLabel": "Lucene 合計", - "xpack.monitoring.metrics.esIndex.normsDescription": "Norms(クエリ時間、テキストスコアリングの規格化因子)が使用中のヒープ領域です。Lucene の一部です。", - "xpack.monitoring.metrics.esIndex.normsLabel": "Norms", - "xpack.monitoring.metrics.esIndex.pointsDescription": "ポイント(例:数字、IP、地理データ)が使用中のヒープ領域です。Lucene の一部です。", - "xpack.monitoring.metrics.esIndex.pointsLabel": "ポイント", "xpack.monitoring.metrics.esIndex.refreshTime.primariesDescription": "プライマリシャードの更新オペレーションの所要時間です。", "xpack.monitoring.metrics.esIndex.refreshTime.primariesLabel": "プライマリ", "xpack.monitoring.metrics.esIndex.refreshTime.totalDescription": "プライマリとレプリカシャードの更新オペレーションの所要時間です。", @@ -18383,17 +18366,6 @@ "xpack.monitoring.metrics.esIndex.searchRate.totalShardsDescription": "プライマリとレプリカシャードで実行されている検索リクエストの数です。1 つの検索を複数シャードに対して実行することができます!", "xpack.monitoring.metrics.esIndex.searchRate.totalShardsLabel": "合計シャード", "xpack.monitoring.metrics.esIndex.searchRateTitle": "検索レート", - "xpack.monitoring.metrics.esIndex.segmentCount.primariesDescription": "プライマリシャードのセグメント数です。", - "xpack.monitoring.metrics.esIndex.segmentCount.primariesLabel": "プライマリ", - "xpack.monitoring.metrics.esIndex.segmentCount.totalDescription": "プライマリとレプリカシャードのセグメント数です。", - "xpack.monitoring.metrics.esIndex.segmentCount.totalLabel": "合計", - "xpack.monitoring.metrics.esIndex.segmentCountTitle": "セグメントカウント", - "xpack.monitoring.metrics.esIndex.storedFieldsDescription": "格納フィールド(例:_source)が使用中のヒープ領域です。Lucene の一部です。", - "xpack.monitoring.metrics.esIndex.storedFieldsLabel": "格納フィールド", - "xpack.monitoring.metrics.esIndex.termsDescription": "用語が使用中のヒープ領域です(例:テキスト)。Lucene の一部です。", - "xpack.monitoring.metrics.esIndex.termsLabel": "用語", - "xpack.monitoring.metrics.esIndex.termVectorsDescription": "用語ベクトルが使用中のヒープ領域です。Lucene の一部です。", - "xpack.monitoring.metrics.esIndex.termVectorsLabel": "用語ベクトル", "xpack.monitoring.metrics.esIndex.throttleTime.indexingDescription": "プライマリとレプリカシャードのインデックスオペレーションのスロットリングの所要時間です。", "xpack.monitoring.metrics.esIndex.throttleTime.indexingLabel": "インデックス", "xpack.monitoring.metrics.esIndex.throttleTime.indexingPrimariesDescription": "プライマリシャードのインデックスオペレーションのスロットリングの所要時間です。", @@ -18420,8 +18392,6 @@ "xpack.monitoring.metrics.esNode.diskFreeSpaceLabel": "ディスクの空き容量", "xpack.monitoring.metrics.esNode.documentCountDescription": "プライマリシャードのみのドキュメントの合計数です。", "xpack.monitoring.metrics.esNode.documentCountLabel": "ドキュメントカウント", - "xpack.monitoring.metrics.esNode.docValuesDescription": "ドキュメント値が使用中のヒープ領域です。Lucene の一部です。", - "xpack.monitoring.metrics.esNode.docValuesLabel": "ドキュメント値", "xpack.monitoring.metrics.esNode.fielddataDescription": "フィールドデータ(例:グローバル序数またはテキストフィールドで特別に有効化されたフィールドデータ)が使用中のヒープ領域です。同じシャードのものですが、Lucene 合計には含まれません。", "xpack.monitoring.metrics.esNode.fielddataLabel": "フィールドデータ", "xpack.monitoring.metrics.esNode.fixedBitsetsDescription": "固定ビットセット(例:ディープネスト構造のドキュメント)が使用中のヒープ領域です。Lucene の一部です。", @@ -18451,15 +18421,6 @@ "xpack.monitoring.metrics.esNode.indexMemoryEs.queryCacheDescription": "クエリキャッシュ(例:キャッシュされたフィルター)が使用中のヒープ領域です。同じシャードのものですが、Lucene 合計には含まれません。", "xpack.monitoring.metrics.esNode.indexMemoryEs.queryCacheLabel": "クエリキャッシュ", "xpack.monitoring.metrics.esNode.indexMemoryEsTitle": "インデックスメモリー - {elasticsearch}", - "xpack.monitoring.metrics.esNode.indexMemoryLucene1.lucenceTotalDescription": "Lucene が現在のインデックスに使用中の合計ヒープ領域です。これはノードのプライマリとレプリカシャードの他のフィールドの合計です。", - "xpack.monitoring.metrics.esNode.indexMemoryLucene1.lucenceTotalLabel": "Lucene 合計", - "xpack.monitoring.metrics.esNode.indexMemoryLucene1Title": "インデックスメモリー - Lucene 1", - "xpack.monitoring.metrics.esNode.indexMemoryLucene2.lucenceTotalDescription": "Lucene が現在のインデックスに使用中の合計ヒープ領域です。これはノードのプライマリとレプリカシャードの他のフィールドの合計です。", - "xpack.monitoring.metrics.esNode.indexMemoryLucene2.lucenceTotalLabel": "Lucene 合計", - "xpack.monitoring.metrics.esNode.indexMemoryLucene2Title": "インデックスメモリー - Lucene 2", - "xpack.monitoring.metrics.esNode.indexMemoryLucene3.lucenceTotalDescription": "Lucene が現在のインデックスに使用中の合計ヒープ領域です。これはノードのプライマリとレプリカシャードの他のフィールドの合計です。", - "xpack.monitoring.metrics.esNode.indexMemoryLucene3.lucenceTotalLabel": "Lucene 合計", - "xpack.monitoring.metrics.esNode.indexMemoryLucene3Title": "インデックスメモリー - Lucene 3", "xpack.monitoring.metrics.esNode.indexThrottlingTimeDescription": "インデックススロットリングの所要時間です。結合に時間がかかっていることを示します。", "xpack.monitoring.metrics.esNode.indexThrottlingTimeLabel": "インデックススロットリング時間", "xpack.monitoring.metrics.esNode.indexWriterDescription": "Index Writer が使用中のヒープ領域です。Lucene 合計の一部ではありません。", @@ -18475,14 +18436,8 @@ "xpack.monitoring.metrics.esNode.latency.searchDescription": "検索の平均レイテンシです。検索の実行に所要した時間を送信された検索数で割った時間です。プライマリとレプリカシャードが含まれています。", "xpack.monitoring.metrics.esNode.latency.searchLabel": "検索", "xpack.monitoring.metrics.esNode.latencyTitle": "レイテンシ", - "xpack.monitoring.metrics.esNode.luceneTotalDescription": "Lucene が現在のインデックスに使用中の合計ヒープ領域です。これはノードのプライマリとレプリカシャードの他のフィールドの合計です。", - "xpack.monitoring.metrics.esNode.luceneTotalLabel": "Lucene 合計", "xpack.monitoring.metrics.esNode.mergeRateDescription": "結合されたセグメントのバイト数です。この数字が大きいほどディスクアクティビティが多いことを示します。", "xpack.monitoring.metrics.esNode.mergeRateLabel": "結合レート", - "xpack.monitoring.metrics.esNode.normsDescription": "Norms(クエリ時間、テキストスコアリングの規格化因子)が使用中のヒープ領域です。Lucene の一部です。", - "xpack.monitoring.metrics.esNode.normsLabel": "Norms", - "xpack.monitoring.metrics.esNode.pointsDescription": "ポイント(例:数字、IP、地理データ)が使用中のヒープ領域です。Lucene の一部です。", - "xpack.monitoring.metrics.esNode.pointsLabel": "ポイント", "xpack.monitoring.metrics.esNode.readThreads.getQueueDescription": "キューにある GET オペレーションの数です。", "xpack.monitoring.metrics.esNode.readThreads.getQueueLabel": "GET キュー", "xpack.monitoring.metrics.esNode.readThreads.getRejectionsDescription": "キューがいっぱいの時に拒否された GET オペレーションの数です。", @@ -18502,15 +18457,9 @@ "xpack.monitoring.metrics.esNode.searchRateTitle": "検索レート", "xpack.monitoring.metrics.esNode.segmentCountDescription": "このノードのプライマリとレプリカシャードの最大セグメントカウントです。", "xpack.monitoring.metrics.esNode.segmentCountLabel": "セグメントカウント", - "xpack.monitoring.metrics.esNode.storedFieldsDescription": "格納フィールド(例:_source)が使用中のヒープ領域です。Lucene の一部です。", - "xpack.monitoring.metrics.esNode.storedFieldsLabel": "格納フィールド", "xpack.monitoring.metrics.esNode.systemLoad.last1MinuteDescription": "過去 1 分間の平均負荷です。", "xpack.monitoring.metrics.esNode.systemLoad.last1MinuteLabel": "1m", "xpack.monitoring.metrics.esNode.systemLoadTitle": "システム負荷", - "xpack.monitoring.metrics.esNode.termsDescription": "用語が使用中のヒープ領域です(例:テキスト)。Lucene の一部です。", - "xpack.monitoring.metrics.esNode.termsLabel": "用語", - "xpack.monitoring.metrics.esNode.termVectorsDescription": "用語ベクトルが使用中のヒープ領域です。Lucene の一部です。", - "xpack.monitoring.metrics.esNode.termVectorsLabel": "用語ベクトル", "xpack.monitoring.metrics.esNode.threadQueue.getDescription": "このノードでプロセス待ちの Get オペレーションの数です。", "xpack.monitoring.metrics.esNode.threadQueue.getLabel": "Get", "xpack.monitoring.metrics.esNode.threadQueueTitle": "スレッドキュー", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index ccdc7f1d7bccb..4dc213d5897d8 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -18596,8 +18596,6 @@ "xpack.monitoring.metrics.esIndex.disk.storePrimariesDescription": "磁盘上主分片的大小。", "xpack.monitoring.metrics.esIndex.disk.storePrimariesLabel": "存储(主分片)", "xpack.monitoring.metrics.esIndex.diskTitle": "磁盘", - "xpack.monitoring.metrics.esIndex.docValuesDescription": "文档值使用的堆内存。这是 Lucene 合计的组成部分。", - "xpack.monitoring.metrics.esIndex.docValuesLabel": "文档值", "xpack.monitoring.metrics.esIndex.fielddataDescription": "Fielddata(例如全局序号或文本字段上显式启用的 Fielddata)使用的堆内存。这适用于相同的分片,但不是 Lucene 合计的组成部分。", "xpack.monitoring.metrics.esIndex.fielddataLabel": "Fielddata", "xpack.monitoring.metrics.esIndex.fixedBitsetsDescription": "固定位集(例如深嵌套文档)使用的堆内存。这是 Lucene 合计的组成部分。", @@ -18610,15 +18608,6 @@ "xpack.monitoring.metrics.esIndex.indexMemoryEs.queryCacheDescription": "查询缓存(例如缓存的筛选)使用的堆内存。这适用于相同的分片,但不是 Lucene 合计的组成部分。", "xpack.monitoring.metrics.esIndex.indexMemoryEs.queryCacheLabel": "查询缓存", "xpack.monitoring.metrics.esIndex.indexMemoryEsTitle": "索引内存 - {elasticsearch}", - "xpack.monitoring.metrics.esIndex.indexMemoryLucene1.luceneTotalDescription": "Lucene 用于当前索引的堆内存合计。这是主分片和副本分片的其他字段合计。", - "xpack.monitoring.metrics.esIndex.indexMemoryLucene1.luceneTotalLabel": "Lucene 合计", - "xpack.monitoring.metrics.esIndex.indexMemoryLucene1Title": "索引内存 - Lucene 1", - "xpack.monitoring.metrics.esIndex.indexMemoryLucene2.luceneTotalDescription": "Lucene 用于当前索引的堆内存合计。这是主分片和副本分片的其他字段合计。", - "xpack.monitoring.metrics.esIndex.indexMemoryLucene2.luceneTotalLabel": "Lucene 合计", - "xpack.monitoring.metrics.esIndex.indexMemoryLucene2Title": "索引内存 - Lucene 2", - "xpack.monitoring.metrics.esIndex.indexMemoryLucene3.luceneTotalDescription": "Lucene 用于当前索引的堆内存合计。这是主分片和副本分片的其他字段合计。", - "xpack.monitoring.metrics.esIndex.indexMemoryLucene3.luceneTotalLabel": "Lucene 合计", - "xpack.monitoring.metrics.esIndex.indexMemoryLucene3Title": "索引内存 - Lucene 3", "xpack.monitoring.metrics.esIndex.indexWriterDescription": "索引编写器使用的堆内存。这不是 Lucene 合计的组成部分。", "xpack.monitoring.metrics.esIndex.indexWriterLabel": "索引编写器", "xpack.monitoring.metrics.esIndex.latency.indexingLatencyDescription": "索引文档的平均延迟,即索引文档所用时间除以索引文档的数目。这仅考虑主分片。", @@ -18626,12 +18615,6 @@ "xpack.monitoring.metrics.esIndex.latency.searchLatencyDescription": "搜索的平均延迟,即执行搜索所用的时间除以提交的搜索数目。这考虑主分片和副本分片。", "xpack.monitoring.metrics.esIndex.latency.searchLatencyLabel": "搜索延迟", "xpack.monitoring.metrics.esIndex.latencyTitle": "延迟", - "xpack.monitoring.metrics.esIndex.luceneTotalDescription": "Lucene 用于当前索引的堆内存合计。这是主分片和副本分片的其他字段合计。", - "xpack.monitoring.metrics.esIndex.luceneTotalLabel": "Lucene 合计", - "xpack.monitoring.metrics.esIndex.normsDescription": "Norms(查询时间、文本评分的标准化因子)使用的堆内存。这是 Lucene 合计的组成部分。", - "xpack.monitoring.metrics.esIndex.normsLabel": "Norms", - "xpack.monitoring.metrics.esIndex.pointsDescription": "Points(数字、IP 和地理数据)使用的堆内存。这是 Lucene 合计的组成部分。", - "xpack.monitoring.metrics.esIndex.pointsLabel": "点", "xpack.monitoring.metrics.esIndex.refreshTime.primariesDescription": "对主分片执行刷新操作所花费的时间量。", "xpack.monitoring.metrics.esIndex.refreshTime.primariesLabel": "主分片", "xpack.monitoring.metrics.esIndex.refreshTime.totalDescription": "对主分片和副本分片执行刷新操作所花费的时间量。", @@ -18654,17 +18637,6 @@ "xpack.monitoring.metrics.esIndex.searchRate.totalShardsDescription": "跨主分片和副本分片执行的搜索请求数目。可以对多个分片运行单个搜索!", "xpack.monitoring.metrics.esIndex.searchRate.totalShardsLabel": "分片合计", "xpack.monitoring.metrics.esIndex.searchRateTitle": "搜索速率", - "xpack.monitoring.metrics.esIndex.segmentCount.primariesDescription": "主分片的段数。", - "xpack.monitoring.metrics.esIndex.segmentCount.primariesLabel": "主分片", - "xpack.monitoring.metrics.esIndex.segmentCount.totalDescription": "主分片和副本分片的段数。", - "xpack.monitoring.metrics.esIndex.segmentCount.totalLabel": "合计", - "xpack.monitoring.metrics.esIndex.segmentCountTitle": "段计数", - "xpack.monitoring.metrics.esIndex.storedFieldsDescription": "存储字段(例如 _source)使用的堆内存。这是 Lucene 合计的组成部分。", - "xpack.monitoring.metrics.esIndex.storedFieldsLabel": "存储字段", - "xpack.monitoring.metrics.esIndex.termsDescription": "字词(例如文本)使用的堆内存。这是 Lucene 合计的组成部分。", - "xpack.monitoring.metrics.esIndex.termsLabel": "词", - "xpack.monitoring.metrics.esIndex.termVectorsDescription": "字词向量使用的堆内存。这是 Lucene 合计的组成部分。", - "xpack.monitoring.metrics.esIndex.termVectorsLabel": "字词向量", "xpack.monitoring.metrics.esIndex.throttleTime.indexingDescription": "对主分片和副本分片限制索引操作所花费的时间量。", "xpack.monitoring.metrics.esIndex.throttleTime.indexingLabel": "索引", "xpack.monitoring.metrics.esIndex.throttleTime.indexingPrimariesDescription": "对主分片限制索引操作所花费的时间量。", @@ -18691,8 +18663,6 @@ "xpack.monitoring.metrics.esNode.diskFreeSpaceLabel": "磁盘可用空间", "xpack.monitoring.metrics.esNode.documentCountDescription": "总文档数目,仅包括主分片。", "xpack.monitoring.metrics.esNode.documentCountLabel": "文档计数", - "xpack.monitoring.metrics.esNode.docValuesDescription": "文档值使用的堆内存。这是 Lucene 合计的组成部分。", - "xpack.monitoring.metrics.esNode.docValuesLabel": "文档值", "xpack.monitoring.metrics.esNode.fielddataDescription": "Fielddata(例如全局序号或文本字段上显式启用的 Fielddata)使用的堆内存。这适用于相同的分片,但不是 Lucene 合计的组成部分。", "xpack.monitoring.metrics.esNode.fielddataLabel": "Fielddata", "xpack.monitoring.metrics.esNode.fixedBitsetsDescription": "固定位集(例如深嵌套文档)使用的堆内存。这是 Lucene 合计的组成部分。", @@ -18722,15 +18692,6 @@ "xpack.monitoring.metrics.esNode.indexMemoryEs.queryCacheDescription": "查询缓存(例如缓存的筛选)使用的堆内存。这适用于相同的分片,但不是 Lucene 合计的组成部分。", "xpack.monitoring.metrics.esNode.indexMemoryEs.queryCacheLabel": "查询缓存", "xpack.monitoring.metrics.esNode.indexMemoryEsTitle": "索引内存 - {elasticsearch}", - "xpack.monitoring.metrics.esNode.indexMemoryLucene1.lucenceTotalDescription": "Lucene 用于当前索引的堆内存合计。这是此节点上主分片和副本分片的其他字段合计。", - "xpack.monitoring.metrics.esNode.indexMemoryLucene1.lucenceTotalLabel": "Lucene 合计", - "xpack.monitoring.metrics.esNode.indexMemoryLucene1Title": "索引内存 - Lucene 1", - "xpack.monitoring.metrics.esNode.indexMemoryLucene2.lucenceTotalDescription": "Lucene 用于当前索引的堆内存合计。这是此节点上主分片和副本分片的其他字段合计。", - "xpack.monitoring.metrics.esNode.indexMemoryLucene2.lucenceTotalLabel": "Lucene 合计", - "xpack.monitoring.metrics.esNode.indexMemoryLucene2Title": "索引内存 - Lucene 2", - "xpack.monitoring.metrics.esNode.indexMemoryLucene3.lucenceTotalDescription": "Lucene 用于当前索引的堆内存合计。这是此节点上主分片和副本分片的其他字段合计。", - "xpack.monitoring.metrics.esNode.indexMemoryLucene3.lucenceTotalLabel": "Lucene 合计", - "xpack.monitoring.metrics.esNode.indexMemoryLucene3Title": "索引内存 - Lucene 3", "xpack.monitoring.metrics.esNode.indexThrottlingTimeDescription": "因索引限制所花费的时间量,其表示合并缓慢。", "xpack.monitoring.metrics.esNode.indexThrottlingTimeLabel": "索引限制时间", "xpack.monitoring.metrics.esNode.indexWriterDescription": "索引编写器使用的堆内存。这不是 Lucene 合计的组成部分。", @@ -18746,14 +18707,8 @@ "xpack.monitoring.metrics.esNode.latency.searchDescription": "搜索的平均延迟,即执行搜索所用的时间除以提交的搜索数目。这考虑主分片和副本分片。", "xpack.monitoring.metrics.esNode.latency.searchLabel": "搜索", "xpack.monitoring.metrics.esNode.latencyTitle": "延迟", - "xpack.monitoring.metrics.esNode.luceneTotalDescription": "Lucene 用于当前索引的堆内存合计。这是此节点上主分片和副本分片的其他字段合计。", - "xpack.monitoring.metrics.esNode.luceneTotalLabel": "Lucene 合计", "xpack.monitoring.metrics.esNode.mergeRateDescription": "已合并段的字节数。较大数值表示磁盘活动较密集。", "xpack.monitoring.metrics.esNode.mergeRateLabel": "合并速率", - "xpack.monitoring.metrics.esNode.normsDescription": "Norms(查询时间、文本评分的标准化因子)使用的堆内存。这是 Lucene 合计的组成部分。", - "xpack.monitoring.metrics.esNode.normsLabel": "Norms", - "xpack.monitoring.metrics.esNode.pointsDescription": "Points(数字、IP 和地理数据)使用的堆内存。这是 Lucene 合计的组成部分。", - "xpack.monitoring.metrics.esNode.pointsLabel": "点", "xpack.monitoring.metrics.esNode.readThreads.getQueueDescription": "队列中的 GET 操作数目。", "xpack.monitoring.metrics.esNode.readThreads.getQueueLabel": "GET 队列", "xpack.monitoring.metrics.esNode.readThreads.getRejectionsDescription": "被拒绝(发生在队列已满时)的 GET 操作数目。", @@ -18773,15 +18728,9 @@ "xpack.monitoring.metrics.esNode.searchRateTitle": "搜索速率", "xpack.monitoring.metrics.esNode.segmentCountDescription": "此节点上主分片和副本分片的最大段计数。", "xpack.monitoring.metrics.esNode.segmentCountLabel": "段计数", - "xpack.monitoring.metrics.esNode.storedFieldsDescription": "存储字段(例如 _source)使用的堆内存。这是 Lucene 合计的组成部分。", - "xpack.monitoring.metrics.esNode.storedFieldsLabel": "存储字段", "xpack.monitoring.metrics.esNode.systemLoad.last1MinuteDescription": "过去 1 分钟的负载平均值。", "xpack.monitoring.metrics.esNode.systemLoad.last1MinuteLabel": "1 分钟", "xpack.monitoring.metrics.esNode.systemLoadTitle": "系统负载", - "xpack.monitoring.metrics.esNode.termsDescription": "字词(例如文本)使用的堆内存。这是 Lucene 合计的组成部分。", - "xpack.monitoring.metrics.esNode.termsLabel": "词", - "xpack.monitoring.metrics.esNode.termVectorsDescription": "字词向量使用的堆内存。这是 Lucene 合计的组成部分。", - "xpack.monitoring.metrics.esNode.termVectorsLabel": "字词向量", "xpack.monitoring.metrics.esNode.threadQueue.getDescription": "此节点上等候处理的 Get 操作数目。", "xpack.monitoring.metrics.esNode.threadQueue.getLabel": "获取", "xpack.monitoring.metrics.esNode.threadQueueTitle": "线程队列", diff --git a/x-pack/test/api_integration/apis/monitoring/elasticsearch/fixtures/index_detail.json b/x-pack/test/api_integration/apis/monitoring/elasticsearch/fixtures/index_detail.json index 65094144d6ff0..31c18ec43f414 100644 --- a/x-pack/test/api_integration/apis/monitoring/elasticsearch/fixtures/index_detail.json +++ b/x-pack/test/api_integration/apis/monitoring/elasticsearch/fixtures/index_detail.json @@ -501,299 +501,6 @@ ] } ], - "index_mem": [ - { - "bucket_size": "10 seconds", - "timeRange": { - "min": 1507235508000, - "max": 1507235712000 - }, - "metric": { - "app": "elasticsearch", - "field": "index_stats.total.segments.memory_in_bytes", - "metricAgg": "max", - "label": "Lucene Total", - "title": "Index Memory", - "description": "Total heap memory used by Lucene for current index. This is the sum of other fields for primary and replica shards.", - "units": "B", - "format": "0.0 b", - "hasCalculation": false, - "isDerivative": false - }, - "data": [ - [ - 1507235520000, - 2378656 - ], - [ - 1507235530000, - 2378656 - ], - [ - 1507235540000, - 2378656 - ], - [ - 1507235550000, - 2378656 - ], - [ - 1507235560000, - 2378656 - ], - [ - 1507235570000, - 2378656 - ], - [ - 1507235580000, - 2378656 - ], - [ - 1507235590000, - 2378656 - ], - [ - 1507235600000, - 2378656 - ], - [ - 1507235610000, - 2378656 - ], - [ - 1507235620000, - 2378656 - ], - [ - 1507235630000, - 2378656 - ], - [ - 1507235640000, - 2378656 - ], - [ - 1507235650000, - 2378656 - ], - [ - 1507235660000, - 2378656 - ], - [ - 1507235670000, - 2378656 - ], - [ - 1507235680000, - 2378656 - ], - [ - 1507235690000, - 2378656 - ], - [ - 1507235700000, - 2378656 - ] - ] - }, - { - "bucket_size": "10 seconds", - "timeRange": { - "min": 1507235508000, - "max": 1507235712000 - }, - "metric": { - "app": "elasticsearch", - "field": "index_stats.total.segments.terms_memory_in_bytes", - "metricAgg": "max", - "label": "Terms", - "title": "Index Memory", - "description": "Heap memory used by Terms (e.g., text). This is a part of Lucene Total.", - "units": "B", - "format": "0.0 b", - "hasCalculation": false, - "isDerivative": false - }, - "data": [ - [ - 1507235520000, - 1889180 - ], - [ - 1507235530000, - 1889180 - ], - [ - 1507235540000, - 1889180 - ], - [ - 1507235550000, - 1889180 - ], - [ - 1507235560000, - 1889180 - ], - [ - 1507235570000, - 1889180 - ], - [ - 1507235580000, - 1889180 - ], - [ - 1507235590000, - 1889180 - ], - [ - 1507235600000, - 1889180 - ], - [ - 1507235610000, - 1889180 - ], - [ - 1507235620000, - 1889180 - ], - [ - 1507235630000, - 1889180 - ], - [ - 1507235640000, - 1889180 - ], - [ - 1507235650000, - 1889180 - ], - [ - 1507235660000, - 1889180 - ], - [ - 1507235670000, - 1889180 - ], - [ - 1507235680000, - 1889180 - ], - [ - 1507235690000, - 1889180 - ], - [ - 1507235700000, - 1889180 - ] - ] - }, - { - "bucket_size": "10 seconds", - "timeRange": { - "min": 1507235508000, - "max": 1507235712000 - }, - "metric": { - "app": "elasticsearch", - "field": "index_stats.total.segments.points_memory_in_bytes", - "metricAgg": "max", - "label": "Points", - "title": "Index Memory", - "description": "Heap memory used by Points (e.g., numbers, IPs, and geo data). This is a part of Lucene Total.", - "units": "B", - "format": "0.0 b", - "hasCalculation": false, - "isDerivative": false - }, - "data": [ - [ - 1507235520000, - 4644 - ], - [ - 1507235530000, - 4644 - ], - [ - 1507235540000, - 4644 - ], - [ - 1507235550000, - 4644 - ], - [ - 1507235560000, - 4644 - ], - [ - 1507235570000, - 4644 - ], - [ - 1507235580000, - 4644 - ], - [ - 1507235590000, - 4644 - ], - [ - 1507235600000, - 4644 - ], - [ - 1507235610000, - 4644 - ], - [ - 1507235620000, - 4644 - ], - [ - 1507235630000, - 4644 - ], - [ - 1507235640000, - 4644 - ], - [ - 1507235650000, - 4644 - ], - [ - 1507235660000, - 4644 - ], - [ - 1507235670000, - 4644 - ], - [ - 1507235680000, - 4644 - ], - [ - 1507235690000, - 4644 - ], - [ - 1507235700000, - 4644 - ] - ] - } - ], "index_document_count": [ { "bucket_size": "10 seconds", diff --git a/x-pack/test/api_integration/apis/monitoring/elasticsearch/fixtures/index_detail_advanced.json b/x-pack/test/api_integration/apis/monitoring/elasticsearch/fixtures/index_detail_advanced.json index 01985489bf0d2..e58b82de53a81 100644 --- a/x-pack/test/api_integration/apis/monitoring/elasticsearch/fixtures/index_detail_advanced.json +++ b/x-pack/test/api_integration/apis/monitoring/elasticsearch/fixtures/index_detail_advanced.json @@ -10,321 +10,7 @@ "status": "green" }, "metrics": { - "index_1": [{ - "bucket_size": "10 seconds", - "timeRange": { - "min": 1507235508000, - "max": 1507235712000 - }, - "metric": { - "app": "elasticsearch", - "field": "index_stats.total.segments.memory_in_bytes", - "metricAgg": "max", - "label": "Lucene Total", - "title": "Index Memory - Lucene 1", - "description": "Total heap memory used by Lucene for current index. This is the sum of other fields for primary and replica shards.", - "units": "B", - "format": "0.0 b", - "hasCalculation": false, - "isDerivative": false - }, - "data": [ - [1507235520000, 2378656], - [1507235530000, 2378656], - [1507235540000, 2378656], - [1507235550000, 2378656], - [1507235560000, 2378656], - [1507235570000, 2378656], - [1507235580000, 2378656], - [1507235590000, 2378656], - [1507235600000, 2378656], - [1507235610000, 2378656], - [1507235620000, 2378656], - [1507235630000, 2378656], - [1507235640000, 2378656], - [1507235650000, 2378656], - [1507235660000, 2378656], - [1507235670000, 2378656], - [1507235680000, 2378656], - [1507235690000, 2378656], - [1507235700000, 2378656] - ] - }, { - "bucket_size": "10 seconds", - "timeRange": { - "min": 1507235508000, - "max": 1507235712000 - }, - "metric": { - "app": "elasticsearch", - "field": "index_stats.total.segments.stored_fields_memory_in_bytes", - "metricAgg": "max", - "label": "Stored Fields", - "title": "Index Memory", - "description": "Heap memory used by Stored Fields (e.g., _source). This is a part of Lucene Total.", - "units": "B", - "format": "0.0 b", - "hasCalculation": false, - "isDerivative": false - }, - "data": [ - [1507235520000, 19024], - [1507235530000, 19024], - [1507235540000, 19024], - [1507235550000, 19024], - [1507235560000, 19024], - [1507235570000, 19024], - [1507235580000, 19024], - [1507235590000, 19024], - [1507235600000, 19024], - [1507235610000, 19024], - [1507235620000, 19024], - [1507235630000, 19024], - [1507235640000, 19024], - [1507235650000, 19024], - [1507235660000, 19024], - [1507235670000, 19024], - [1507235680000, 19024], - [1507235690000, 19024], - [1507235700000, 19024] - ] - }, { - "bucket_size": "10 seconds", - "timeRange": { - "min": 1507235508000, - "max": 1507235712000 - }, - "metric": { - "app": "elasticsearch", - "field": "index_stats.total.segments.doc_values_memory_in_bytes", - "metricAgg": "max", - "label": "Doc Values", - "title": "Index Memory", - "description": "Heap memory used by Doc Values. This is a part of Lucene Total.", - "units": "B", - "format": "0.0 b", - "hasCalculation": false, - "isDerivative": false - }, - "data": [ - [1507235520000, 232336], - [1507235530000, 232336], - [1507235540000, 232336], - [1507235550000, 232336], - [1507235560000, 232336], - [1507235570000, 232336], - [1507235580000, 232336], - [1507235590000, 232336], - [1507235600000, 232336], - [1507235610000, 232336], - [1507235620000, 232336], - [1507235630000, 232336], - [1507235640000, 232336], - [1507235650000, 232336], - [1507235660000, 232336], - [1507235670000, 232336], - [1507235680000, 232336], - [1507235690000, 232336], - [1507235700000, 232336] - ] - }, { - "bucket_size": "10 seconds", - "timeRange": { - "min": 1507235508000, - "max": 1507235712000 - }, - "metric": { - "app": "elasticsearch", - "field": "index_stats.total.segments.norms_memory_in_bytes", - "metricAgg": "max", - "label": "Norms", - "title": "Index Memory", - "description": "Heap memory used by Norms (normalization factors for query-time, text scoring). This is a part of Lucene Total.", - "units": "B", - "format": "0.0 b", - "hasCalculation": false, - "isDerivative": false - }, - "data": [ - [1507235520000, 233472], - [1507235530000, 233472], - [1507235540000, 233472], - [1507235550000, 233472], - [1507235560000, 233472], - [1507235570000, 233472], - [1507235580000, 233472], - [1507235590000, 233472], - [1507235600000, 233472], - [1507235610000, 233472], - [1507235620000, 233472], - [1507235630000, 233472], - [1507235640000, 233472], - [1507235650000, 233472], - [1507235660000, 233472], - [1507235670000, 233472], - [1507235680000, 233472], - [1507235690000, 233472], - [1507235700000, 233472] - ] - }], - "index_2": [{ - "bucket_size": "10 seconds", - "timeRange": { - "min": 1507235508000, - "max": 1507235712000 - }, - "metric": { - "app": "elasticsearch", - "field": "index_stats.total.segments.memory_in_bytes", - "metricAgg": "max", - "label": "Lucene Total", - "title": "Index Memory - Lucene 2", - "description": "Total heap memory used by Lucene for current index. This is the sum of other fields for primary and replica shards.", - "units": "B", - "format": "0.0 b", - "hasCalculation": false, - "isDerivative": false - }, - "data": [ - [1507235520000, 2378656], - [1507235530000, 2378656], - [1507235540000, 2378656], - [1507235550000, 2378656], - [1507235560000, 2378656], - [1507235570000, 2378656], - [1507235580000, 2378656], - [1507235590000, 2378656], - [1507235600000, 2378656], - [1507235610000, 2378656], - [1507235620000, 2378656], - [1507235630000, 2378656], - [1507235640000, 2378656], - [1507235650000, 2378656], - [1507235660000, 2378656], - [1507235670000, 2378656], - [1507235680000, 2378656], - [1507235690000, 2378656], - [1507235700000, 2378656] - ] - }, { - "bucket_size": "10 seconds", - "timeRange": { - "min": 1507235508000, - "max": 1507235712000 - }, - "metric": { - "app": "elasticsearch", - "field": "index_stats.total.segments.terms_memory_in_bytes", - "metricAgg": "max", - "label": "Terms", - "title": "Index Memory", - "description": "Heap memory used by Terms (e.g., text). This is a part of Lucene Total.", - "units": "B", - "format": "0.0 b", - "hasCalculation": false, - "isDerivative": false - }, - "data": [ - [1507235520000, 1889180], - [1507235530000, 1889180], - [1507235540000, 1889180], - [1507235550000, 1889180], - [1507235560000, 1889180], - [1507235570000, 1889180], - [1507235580000, 1889180], - [1507235590000, 1889180], - [1507235600000, 1889180], - [1507235610000, 1889180], - [1507235620000, 1889180], - [1507235630000, 1889180], - [1507235640000, 1889180], - [1507235650000, 1889180], - [1507235660000, 1889180], - [1507235670000, 1889180], - [1507235680000, 1889180], - [1507235690000, 1889180], - [1507235700000, 1889180] - ] - }, { - "bucket_size": "10 seconds", - "timeRange": { - "min": 1507235508000, - "max": 1507235712000 - }, - "metric": { - "app": "elasticsearch", - "field": "index_stats.total.segments.points_memory_in_bytes", - "metricAgg": "max", - "label": "Points", - "title": "Index Memory", - "description": "Heap memory used by Points (e.g., numbers, IPs, and geo data). This is a part of Lucene Total.", - "units": "B", - "format": "0.0 b", - "hasCalculation": false, - "isDerivative": false - }, - "data": [ - [1507235520000, 4644], - [1507235530000, 4644], - [1507235540000, 4644], - [1507235550000, 4644], - [1507235560000, 4644], - [1507235570000, 4644], - [1507235580000, 4644], - [1507235590000, 4644], - [1507235600000, 4644], - [1507235610000, 4644], - [1507235620000, 4644], - [1507235630000, 4644], - [1507235640000, 4644], - [1507235650000, 4644], - [1507235660000, 4644], - [1507235670000, 4644], - [1507235680000, 4644], - [1507235690000, 4644], - [1507235700000, 4644] - ] - }], "index_3": [{ - "bucket_size": "10 seconds", - "timeRange": { - "min": 1507235508000, - "max": 1507235712000 - }, - "metric": { - "app": "elasticsearch", - "field": "index_stats.total.segments.memory_in_bytes", - "metricAgg": "max", - "label": "Lucene Total", - "title": "Index Memory - Lucene 3", - "description": "Total heap memory used by Lucene for current index. This is the sum of other fields for primary and replica shards.", - "units": "B", - "format": "0.0 b", - "hasCalculation": false, - "isDerivative": false - }, - "data": [ - [1507235520000, 2378656], - [1507235530000, 2378656], - [1507235540000, 2378656], - [1507235550000, 2378656], - [1507235560000, 2378656], - [1507235570000, 2378656], - [1507235580000, 2378656], - [1507235590000, 2378656], - [1507235600000, 2378656], - [1507235610000, 2378656], - [1507235620000, 2378656], - [1507235630000, 2378656], - [1507235640000, 2378656], - [1507235650000, 2378656], - [1507235660000, 2378656], - [1507235670000, 2378656], - [1507235680000, 2378656], - [1507235690000, 2378656], - [1507235700000, 2378656] - ] - }, { "bucket_size": "10 seconds", "timeRange": { "min": 1507235508000, @@ -335,7 +21,7 @@ "field": "index_stats.total.segments.fixed_bit_set_memory_in_bytes", "metricAgg": "max", "label": "Fixed Bitsets", - "title": "Index Memory", + "title": "Index Memory - Lucene", "description": "Heap memory used by Fixed Bit Sets (e.g., deeply nested documents). This is a part of Lucene Total.", "units": "B", "format": "0.0 b", @@ -363,45 +49,6 @@ [1507235690000, 0], [1507235700000, 0] ] - }, { - "bucket_size": "10 seconds", - "timeRange": { - "min": 1507235508000, - "max": 1507235712000 - }, - "metric": { - "app": "elasticsearch", - "field": "index_stats.total.segments.term_vectors_memory_in_bytes", - "metricAgg": "max", - "label": "Term Vectors", - "title": "Index Memory", - "description": "Heap memory used by Term Vectors. This is a part of Lucene Total.", - "units": "B", - "format": "0.0 b", - "hasCalculation": false, - "isDerivative": false - }, - "data": [ - [1507235520000, 0], - [1507235530000, 0], - [1507235540000, 0], - [1507235550000, 0], - [1507235560000, 0], - [1507235570000, 0], - [1507235580000, 0], - [1507235590000, 0], - [1507235600000, 0], - [1507235610000, 0], - [1507235620000, 0], - [1507235630000, 0], - [1507235640000, 0], - [1507235650000, 0], - [1507235660000, 0], - [1507235670000, 0], - [1507235680000, 0], - [1507235690000, 0], - [1507235700000, 0] - ] }, { "bucket_size": "10 seconds", "timeRange": { diff --git a/x-pack/test/api_integration/apis/monitoring/elasticsearch/fixtures/node_detail.json b/x-pack/test/api_integration/apis/monitoring/elasticsearch/fixtures/node_detail.json index 32096b0b97067..0a7e3ee12a18f 100644 --- a/x-pack/test/api_integration/apis/monitoring/elasticsearch/fixtures/node_detail.json +++ b/x-pack/test/api_integration/apis/monitoring/elasticsearch/fixtures/node_detail.json @@ -709,299 +709,6 @@ ] } ], - "node_mem": [ - { - "bucket_size": "10 seconds", - "timeRange": { - "min": 1507235508000, - "max": 1507235712000 - }, - "metric": { - "app": "elasticsearch", - "field": "node_stats.indices.segments.memory_in_bytes", - "metricAgg": "max", - "label": "Lucene Total", - "title": "Index Memory", - "description": "Total heap memory used by Lucene for current index. This is the sum of other fields for primary and replica shards on this node.", - "units": "B", - "format": "0.0 b", - "hasCalculation": false, - "isDerivative": false - }, - "data": [ - [ - 1507235520000, - 4797457 - ], - [ - 1507235530000, - 4797457 - ], - [ - 1507235540000, - 4797457 - ], - [ - 1507235550000, - 4797457 - ], - [ - 1507235560000, - 4823580 - ], - [ - 1507235570000, - 4823580 - ], - [ - 1507235580000, - 4823580 - ], - [ - 1507235590000, - 4823580 - ], - [ - 1507235600000, - 4823580 - ], - [ - 1507235610000, - 4838368 - ], - [ - 1507235620000, - 4741420 - ], - [ - 1507235630000, - 4741420 - ], - [ - 1507235640000, - 4741420 - ], - [ - 1507235650000, - 4741420 - ], - [ - 1507235660000, - 4741420 - ], - [ - 1507235670000, - 4757998 - ], - [ - 1507235680000, - 4787542 - ], - [ - 1507235690000, - 4787542 - ], - [ - 1507235700000, - 4787542 - ] - ] - }, - { - "bucket_size": "10 seconds", - "timeRange": { - "min": 1507235508000, - "max": 1507235712000 - }, - "metric": { - "app": "elasticsearch", - "field": "node_stats.indices.segments.terms_memory_in_bytes", - "metricAgg": "max", - "label": "Terms", - "title": "Index Memory", - "description": "Heap memory used by Terms (e.g., text). This is a part of Lucene Total.", - "units": "B", - "format": "0.0 b", - "hasCalculation": false, - "isDerivative": false - }, - "data": [ - [ - 1507235520000, - 3764438 - ], - [ - 1507235530000, - 3764438 - ], - [ - 1507235540000, - 3764438 - ], - [ - 1507235550000, - 3764438 - ], - [ - 1507235560000, - 3786762 - ], - [ - 1507235570000, - 3786762 - ], - [ - 1507235580000, - 3786762 - ], - [ - 1507235590000, - 3786762 - ], - [ - 1507235600000, - 3786762 - ], - [ - 1507235610000, - 3799306 - ], - [ - 1507235620000, - 3715996 - ], - [ - 1507235630000, - 3715996 - ], - [ - 1507235640000, - 3715996 - ], - [ - 1507235650000, - 3715996 - ], - [ - 1507235660000, - 3715996 - ], - [ - 1507235670000, - 3729890 - ], - [ - 1507235680000, - 3755528 - ], - [ - 1507235690000, - 3755528 - ], - [ - 1507235700000, - 3755528 - ] - ] - }, - { - "bucket_size": "10 seconds", - "timeRange": { - "min": 1507235508000, - "max": 1507235712000 - }, - "metric": { - "app": "elasticsearch", - "field": "node_stats.indices.segments.points_memory_in_bytes", - "metricAgg": "max", - "label": "Points", - "title": "Index Memory", - "description": "Heap memory used by Points (e.g., numbers, IPs, and geo data). This is a part of Lucene Total.", - "units": "B", - "format": "0.0 b", - "hasCalculation": false, - "isDerivative": false - }, - "data": [ - [ - 1507235520000, - 12171 - ], - [ - 1507235530000, - 12171 - ], - [ - 1507235540000, - 12171 - ], - [ - 1507235550000, - 12171 - ], - [ - 1507235560000, - 12198 - ], - [ - 1507235570000, - 12198 - ], - [ - 1507235580000, - 12198 - ], - [ - 1507235590000, - 12198 - ], - [ - 1507235600000, - 12198 - ], - [ - 1507235610000, - 12218 - ], - [ - 1507235620000, - 12120 - ], - [ - 1507235630000, - 12120 - ], - [ - 1507235640000, - 12120 - ], - [ - 1507235650000, - 12120 - ], - [ - 1507235660000, - 12120 - ], - [ - 1507235670000, - 12140 - ], - [ - 1507235680000, - 12166 - ], - [ - 1507235690000, - 12166 - ], - [ - 1507235700000, - 12166 - ] - ] - } - ], "node_cpu_metric": [ { "bucket_size": "10 seconds", diff --git a/x-pack/test/api_integration/apis/monitoring/elasticsearch/fixtures/node_detail_advanced.json b/x-pack/test/api_integration/apis/monitoring/elasticsearch/fixtures/node_detail_advanced.json index 2eb7d54effdfb..e08fabe28d91a 100644 --- a/x-pack/test/api_integration/apis/monitoring/elasticsearch/fixtures/node_detail_advanced.json +++ b/x-pack/test/api_integration/apis/monitoring/elasticsearch/fixtures/node_detail_advanced.json @@ -268,331 +268,7 @@ ] } ], - "node_index_1": [ - { - "bucket_size": "10 seconds", - "timeRange": { - "min": 1507235508000, - "max": 1507235712000 - }, - "metric": { - "app": "elasticsearch", - "field": "node_stats.indices.segments.memory_in_bytes", - "metricAgg": "max", - "label": "Lucene Total", - "title": "Index Memory - Lucene 1", - "description": "Total heap memory used by Lucene for current index. This is the sum of other fields for primary and replica shards on this node.", - "units": "B", - "format": "0.0 b", - "hasCalculation": false, - "isDerivative": false - }, - "data": [ - [1507235520000, 4797457], - [1507235530000, 4797457], - [1507235540000, 4797457], - [1507235550000, 4797457], - [1507235560000, 4823580], - [1507235570000, 4823580], - [1507235580000, 4823580], - [1507235590000, 4823580], - [1507235600000, 4823580], - [1507235610000, 4838368], - [1507235620000, 4741420], - [1507235630000, 4741420], - [1507235640000, 4741420], - [1507235650000, 4741420], - [1507235660000, 4741420], - [1507235670000, 4757998], - [1507235680000, 4787542], - [1507235690000, 4787542], - [1507235700000, 4787542] - ] - }, - { - "bucket_size": "10 seconds", - "timeRange": { - "min": 1507235508000, - "max": 1507235712000 - }, - "metric": { - "app": "elasticsearch", - "field": "node_stats.indices.segments.stored_fields_memory_in_bytes", - "metricAgg": "max", - "label": "Stored Fields", - "title": "Index Memory", - "description": "Heap memory used by Stored Fields (e.g., _source). This is a part of Lucene Total.", - "units": "B", - "format": "0.0 b", - "hasCalculation": false, - "isDerivative": false - }, - "data": [ - [1507235520000, 56792], - [1507235530000, 56792], - [1507235540000, 56792], - [1507235550000, 56792], - [1507235560000, 57728], - [1507235570000, 57728], - [1507235580000, 57728], - [1507235590000, 57728], - [1507235600000, 57728], - [1507235610000, 58352], - [1507235620000, 56192], - [1507235630000, 56192], - [1507235640000, 56192], - [1507235650000, 56192], - [1507235660000, 56192], - [1507235670000, 56816], - [1507235680000, 57440], - [1507235690000, 57440], - [1507235700000, 57440] - ] - }, - { - "bucket_size": "10 seconds", - "timeRange": { - "min": 1507235508000, - "max": 1507235712000 - }, - "metric": { - "app": "elasticsearch", - "field": "node_stats.indices.segments.doc_values_memory_in_bytes", - "metricAgg": "max", - "label": "Doc Values", - "title": "Index Memory", - "description": "Heap memory used by Doc Values. This is a part of Lucene Total.", - "units": "B", - "format": "0.0 b", - "hasCalculation": false, - "isDerivative": false - }, - "data": [ - [1507235520000, 516824], - [1507235530000, 516824], - [1507235540000, 516824], - [1507235550000, 516824], - [1507235560000, 517292], - [1507235570000, 517292], - [1507235580000, 517292], - [1507235590000, 517292], - [1507235600000, 517292], - [1507235610000, 517612], - [1507235620000, 514808], - [1507235630000, 514808], - [1507235640000, 514808], - [1507235650000, 514808], - [1507235660000, 514808], - [1507235670000, 515312], - [1507235680000, 516008], - [1507235690000, 516008], - [1507235700000, 516008] - ] - }, - { - "bucket_size": "10 seconds", - "timeRange": { - "min": 1507235508000, - "max": 1507235712000 - }, - "metric": { - "app": "elasticsearch", - "field": "node_stats.indices.segments.norms_memory_in_bytes", - "metricAgg": "max", - "label": "Norms", - "title": "Index Memory", - "description": "Heap memory used by Norms (normalization factors for query-time, text scoring). This is a part of Lucene Total.", - "units": "B", - "format": "0.0 b", - "hasCalculation": false, - "isDerivative": false - }, - "data": [ - [1507235520000, 447232], - [1507235530000, 447232], - [1507235540000, 447232], - [1507235550000, 447232], - [1507235560000, 449600], - [1507235570000, 449600], - [1507235580000, 449600], - [1507235590000, 449600], - [1507235600000, 449600], - [1507235610000, 450880], - [1507235620000, 442304], - [1507235630000, 442304], - [1507235640000, 442304], - [1507235650000, 442304], - [1507235660000, 442304], - [1507235670000, 443840], - [1507235680000, 446400], - [1507235690000, 446400], - [1507235700000, 446400] - ] - } - ], - "node_index_2": [ - { - "bucket_size": "10 seconds", - "timeRange": { - "min": 1507235508000, - "max": 1507235712000 - }, - "metric": { - "app": "elasticsearch", - "field": "node_stats.indices.segments.memory_in_bytes", - "metricAgg": "max", - "label": "Lucene Total", - "title": "Index Memory - Lucene 2", - "description": "Total heap memory used by Lucene for current index. This is the sum of other fields for primary and replica shards on this node.", - "units": "B", - "format": "0.0 b", - "hasCalculation": false, - "isDerivative": false - }, - "data": [ - [1507235520000, 4797457], - [1507235530000, 4797457], - [1507235540000, 4797457], - [1507235550000, 4797457], - [1507235560000, 4823580], - [1507235570000, 4823580], - [1507235580000, 4823580], - [1507235590000, 4823580], - [1507235600000, 4823580], - [1507235610000, 4838368], - [1507235620000, 4741420], - [1507235630000, 4741420], - [1507235640000, 4741420], - [1507235650000, 4741420], - [1507235660000, 4741420], - [1507235670000, 4757998], - [1507235680000, 4787542], - [1507235690000, 4787542], - [1507235700000, 4787542] - ] - }, - { - "bucket_size": "10 seconds", - "timeRange": { - "min": 1507235508000, - "max": 1507235712000 - }, - "metric": { - "app": "elasticsearch", - "field": "node_stats.indices.segments.terms_memory_in_bytes", - "metricAgg": "max", - "label": "Terms", - "title": "Index Memory", - "description": "Heap memory used by Terms (e.g., text). This is a part of Lucene Total.", - "units": "B", - "format": "0.0 b", - "hasCalculation": false, - "isDerivative": false - }, - "data": [ - [1507235520000, 3764438], - [1507235530000, 3764438], - [1507235540000, 3764438], - [1507235550000, 3764438], - [1507235560000, 3786762], - [1507235570000, 3786762], - [1507235580000, 3786762], - [1507235590000, 3786762], - [1507235600000, 3786762], - [1507235610000, 3799306], - [1507235620000, 3715996], - [1507235630000, 3715996], - [1507235640000, 3715996], - [1507235650000, 3715996], - [1507235660000, 3715996], - [1507235670000, 3729890], - [1507235680000, 3755528], - [1507235690000, 3755528], - [1507235700000, 3755528] - ] - }, - { - "bucket_size": "10 seconds", - "timeRange": { - "min": 1507235508000, - "max": 1507235712000 - }, - "metric": { - "app": "elasticsearch", - "field": "node_stats.indices.segments.points_memory_in_bytes", - "metricAgg": "max", - "label": "Points", - "title": "Index Memory", - "description": "Heap memory used by Points (e.g., numbers, IPs, and geo data). This is a part of Lucene Total.", - "units": "B", - "format": "0.0 b", - "hasCalculation": false, - "isDerivative": false - }, - "data": [ - [1507235520000, 12171], - [1507235530000, 12171], - [1507235540000, 12171], - [1507235550000, 12171], - [1507235560000, 12198], - [1507235570000, 12198], - [1507235580000, 12198], - [1507235590000, 12198], - [1507235600000, 12198], - [1507235610000, 12218], - [1507235620000, 12120], - [1507235630000, 12120], - [1507235640000, 12120], - [1507235650000, 12120], - [1507235660000, 12120], - [1507235670000, 12140], - [1507235680000, 12166], - [1507235690000, 12166], - [1507235700000, 12166] - ] - } - ], "node_index_3": [ - { - "bucket_size": "10 seconds", - "timeRange": { - "min": 1507235508000, - "max": 1507235712000 - }, - "metric": { - "app": "elasticsearch", - "field": "node_stats.indices.segments.memory_in_bytes", - "metricAgg": "max", - "label": "Lucene Total", - "title": "Index Memory - Lucene 3", - "description": "Total heap memory used by Lucene for current index. This is the sum of other fields for primary and replica shards on this node.", - "units": "B", - "format": "0.0 b", - "hasCalculation": false, - "isDerivative": false - }, - "data": [ - [1507235520000, 4797457], - [1507235530000, 4797457], - [1507235540000, 4797457], - [1507235550000, 4797457], - [1507235560000, 4823580], - [1507235570000, 4823580], - [1507235580000, 4823580], - [1507235590000, 4823580], - [1507235600000, 4823580], - [1507235610000, 4838368], - [1507235620000, 4741420], - [1507235630000, 4741420], - [1507235640000, 4741420], - [1507235650000, 4741420], - [1507235660000, 4741420], - [1507235670000, 4757998], - [1507235680000, 4787542], - [1507235690000, 4787542], - [1507235700000, 4787542] - ] - }, { "bucket_size": "10 seconds", "timeRange": { @@ -604,7 +280,7 @@ "field": "node_stats.indices.segments.fixed_bit_set_memory_in_bytes", "metricAgg": "max", "label": "Fixed Bitsets", - "title": "Index Memory", + "title": "Index Memory - Lucene", "description": "Heap memory used by Fixed Bit Sets (e.g., deeply nested documents). This is a part of Lucene Total.", "units": "B", "format": "0.0 b", @@ -633,46 +309,6 @@ [1507235700000, 3976] ] }, - { - "bucket_size": "10 seconds", - "timeRange": { - "min": 1507235508000, - "max": 1507235712000 - }, - "metric": { - "app": "elasticsearch", - "field": "node_stats.indices.segments.term_vectors_memory_in_bytes", - "metricAgg": "max", - "label": "Term Vectors", - "title": "Index Memory", - "description": "Heap memory used by Term Vectors. This is a part of Lucene Total.", - "units": "B", - "format": "0.0 b", - "hasCalculation": false, - "isDerivative": false - }, - "data": [ - [1507235520000, 0], - [1507235530000, 0], - [1507235540000, 0], - [1507235550000, 0], - [1507235560000, 0], - [1507235570000, 0], - [1507235580000, 0], - [1507235590000, 0], - [1507235600000, 0], - [1507235610000, 0], - [1507235620000, 0], - [1507235630000, 0], - [1507235640000, 0], - [1507235650000, 0], - [1507235660000, 0], - [1507235670000, 0], - [1507235680000, 0], - [1507235690000, 0], - [1507235700000, 0] - ] - }, { "bucket_size": "10 seconds", "timeRange": { From 9a21f0cbd19f5770588f790bcd68f17983060ce1 Mon Sep 17 00:00:00 2001 From: Tiago Costa Date: Tue, 16 Nov 2021 14:12:55 +0000 Subject: [PATCH 019/148] skip flaky suites (#118472) --- .../apps/ml/data_visualizer/index_data_visualizer.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/functional/apps/ml/data_visualizer/index_data_visualizer.ts b/x-pack/test/functional/apps/ml/data_visualizer/index_data_visualizer.ts index bcdf978d46cad..55a11e6ec2d20 100644 --- a/x-pack/test/functional/apps/ml/data_visualizer/index_data_visualizer.ts +++ b/x-pack/test/functional/apps/ml/data_visualizer/index_data_visualizer.ts @@ -166,7 +166,8 @@ export default function ({ getService }: FtrProviderContext) { await ml.securityUI.loginAsMlPowerUser(); }); - describe('with farequote', function () { + // FLAKY: https://github.com/elastic/kibana/issues/118472 + describe.skip('with farequote', function () { // Run tests on full farequote index. it(`${farequoteDataViewTestData.suiteTitle} loads the data visualizer selector page`, async () => { // Start navigation from the base of the ML app. From bf9bec1bfefbbb62864cf899256b92bccd8ab75a Mon Sep 17 00:00:00 2001 From: Nick Partridge Date: Tue, 16 Nov 2021 08:41:32 -0600 Subject: [PATCH 020/148] [Charts] Add rtl label support to elastic charts (#118606) --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 7bca78ce94f5c..b7b543abde704 100644 --- a/package.json +++ b/package.json @@ -99,7 +99,7 @@ "@elastic/apm-rum": "^5.9.1", "@elastic/apm-rum-react": "^1.3.1", "@elastic/apm-synthtrace": "link:bazel-bin/packages/elastic-apm-synthtrace", - "@elastic/charts": "39.0.0", + "@elastic/charts": "39.0.1", "@elastic/datemath": "link:bazel-bin/packages/elastic-datemath", "@elastic/elasticsearch": "npm:@elastic/elasticsearch-canary@^8.0.0-canary.35", "@elastic/ems-client": "8.0.0", diff --git a/yarn.lock b/yarn.lock index 9972f5a2e1dcd..c6bfd7ca788a7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2337,10 +2337,10 @@ dependencies: object-hash "^1.3.0" -"@elastic/charts@39.0.0": - version "39.0.0" - resolved "https://registry.yarnpkg.com/@elastic/charts/-/charts-39.0.0.tgz#85e615f550d03d8fb880bf44e891452b4341706b" - integrity sha512-EnmOXFAN5u9rkcwM4L2AksxoWpOpZRXbjX2HYAxgj8WcBb14zYoYeyENMQyG/qu2Rm6PnUni0dgy+mPOTEnGmw== +"@elastic/charts@39.0.1": + version "39.0.1" + resolved "https://registry.yarnpkg.com/@elastic/charts/-/charts-39.0.1.tgz#7891d6efb3a12eb73fcb57d9a1f71565c22f4501" + integrity sha512-k64+vrfRkP7Gn8+T0Vtdev/DKpy6G+M9H6OFQcf1fgXAd7qOnTXVaN4Ru+BRTPylTFwxf9pqHraz8Ayi+3VpjA== dependencies: "@popperjs/core" "^2.4.0" chroma-js "^2.1.0" From 253838648b4ffa5e04e256ea6e41572a6c0b4c95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patryk=20Kopyci=C5=84ski?= Date: Tue, 16 Nov 2021 15:45:36 +0100 Subject: [PATCH 021/148] [Osquery] Fix RBAC (#118692) --- x-pack/plugins/osquery/server/plugin.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/osquery/server/plugin.ts b/x-pack/plugins/osquery/server/plugin.ts index 16f0b17cc10df..77dfde5800c1e 100644 --- a/x-pack/plugins/osquery/server/plugin.ts +++ b/x-pack/plugins/osquery/server/plugin.ts @@ -134,7 +134,7 @@ const registerFeatures = (features: SetupPlugins['features']) => { groupType: 'mutually_exclusive', privileges: [ { - api: [`${PLUGIN_ID}-writeSavedQueries`], + api: [`${PLUGIN_ID}-writeSavedQueries`, `${PLUGIN_ID}-readSavedQueries`], id: 'saved_queries_all', includeIn: 'all', name: 'All', @@ -168,7 +168,7 @@ const registerFeatures = (features: SetupPlugins['features']) => { groupType: 'mutually_exclusive', privileges: [ { - api: [`${PLUGIN_ID}-writePacks`], + api: [`${PLUGIN_ID}-writePacks`, `${PLUGIN_ID}-readPacks`], id: 'packs_all', includeIn: 'all', name: 'All', From 244eaa1ef313ff8d96411c41be234f0451d80dd3 Mon Sep 17 00:00:00 2001 From: Julia Bardi <90178898+juliaElastic@users.noreply.github.com> Date: Tue, 16 Nov 2021 15:47:57 +0100 Subject: [PATCH 022/148] fixed reference error (#118679) --- .../plugins/fleet/server/collectors/fleet_server_collector.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/fleet/server/collectors/fleet_server_collector.ts b/x-pack/plugins/fleet/server/collectors/fleet_server_collector.ts index a08ed450b5b30..9a1aca9486c60 100644 --- a/x-pack/plugins/fleet/server/collectors/fleet_server_collector.ts +++ b/x-pack/plugins/fleet/server/collectors/fleet_server_collector.ts @@ -43,7 +43,7 @@ export const getFleetServerUsage = async ( .getSettings(soClient) .then((settings) => settings.fleet_server_hosts?.length ?? 0) .catch((err) => { - if (isBoom(error) && error.output.statusCode === 404) { + if (isBoom(err) && err.output.statusCode === 404) { return 0; } From 42553ecadda10e4edc177351eec344e68ce5d1e7 Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Tue, 16 Nov 2021 17:06:37 +0200 Subject: [PATCH 023/148] [Telemetry] revert to v2 endpoint (#118682) --- src/plugins/telemetry/common/constants.ts | 6 +++--- .../get_telemetry_channel_endpoint.test.ts | 14 ++++++-------- .../get_telemetry_channel_endpoint.ts | 2 +- .../public/services/telemetry_service.test.ts | 8 ++++---- .../server/routes/telemetry_opt_in_stats.test.ts | 4 ++-- 5 files changed, 16 insertions(+), 18 deletions(-) diff --git a/src/plugins/telemetry/common/constants.ts b/src/plugins/telemetry/common/constants.ts index d6111d4124a07..5e7b52dd35cf7 100644 --- a/src/plugins/telemetry/common/constants.ts +++ b/src/plugins/telemetry/common/constants.ts @@ -35,7 +35,7 @@ export const PAYLOAD_CONTENT_ENCODING = 'aes256gcm'; /** * The endpoint version when hitting the remote telemetry service */ -export const ENDPOINT_VERSION = 'v3'; +export const ENDPOINT_VERSION = 'v2'; /** * The staging telemetry endpoint for the remote telemetry service. @@ -53,6 +53,6 @@ export const ENDPOINT_PROD = 'https://telemetry.elastic.co/'; * The telemetry channels for the remote telemetry service. */ export const TELEMETRY_CHANNELS = { - SNAPSHOT_CHANNEL: 'kibana-snapshot', - OPT_IN_STATUS_CHANNEL: 'kibana-opt_in_status', + SNAPSHOT_CHANNEL: 'xpack', + OPT_IN_STATUS_CHANNEL: 'opt_in_status', }; diff --git a/src/plugins/telemetry/common/telemetry_config/get_telemetry_channel_endpoint.test.ts b/src/plugins/telemetry/common/telemetry_config/get_telemetry_channel_endpoint.test.ts index c7f9984269581..6718a3e5f6462 100644 --- a/src/plugins/telemetry/common/telemetry_config/get_telemetry_channel_endpoint.test.ts +++ b/src/plugins/telemetry/common/telemetry_config/get_telemetry_channel_endpoint.test.ts @@ -41,12 +41,12 @@ describe('getChannel', () => { it('returns correct snapshot channel name', () => { const channelName = getChannel('snapshot'); - expect(channelName).toMatchInlineSnapshot(`"kibana-snapshot"`); + expect(channelName).toMatchInlineSnapshot(`"xpack"`); }); it('returns correct optInStatus channel name', () => { const channelName = getChannel('optInStatus'); - expect(channelName).toMatchInlineSnapshot(`"kibana-opt_in_status"`); + expect(channelName).toMatchInlineSnapshot(`"opt_in_status"`); }); }); @@ -68,14 +68,12 @@ describe('getTelemetryChannelEndpoint', () => { describe('snapshot channel', () => { it('returns correct prod endpoint', () => { const endpoint = getTelemetryChannelEndpoint({ env: 'prod', channelName: 'snapshot' }); - expect(endpoint).toMatchInlineSnapshot( - `"https://telemetry.elastic.co/v3/send/kibana-snapshot"` - ); + expect(endpoint).toMatchInlineSnapshot(`"https://telemetry.elastic.co/xpack/v2/send"`); }); it('returns correct staging endpoint', () => { const endpoint = getTelemetryChannelEndpoint({ env: 'staging', channelName: 'snapshot' }); expect(endpoint).toMatchInlineSnapshot( - `"https://telemetry-staging.elastic.co/v3/send/kibana-snapshot"` + `"https://telemetry-staging.elastic.co/xpack/v2/send"` ); }); }); @@ -84,13 +82,13 @@ describe('getTelemetryChannelEndpoint', () => { it('returns correct prod endpoint', () => { const endpoint = getTelemetryChannelEndpoint({ env: 'prod', channelName: 'optInStatus' }); expect(endpoint).toMatchInlineSnapshot( - `"https://telemetry.elastic.co/v3/send/kibana-opt_in_status"` + `"https://telemetry.elastic.co/opt_in_status/v2/send"` ); }); it('returns correct staging endpoint', () => { const endpoint = getTelemetryChannelEndpoint({ env: 'staging', channelName: 'optInStatus' }); expect(endpoint).toMatchInlineSnapshot( - `"https://telemetry-staging.elastic.co/v3/send/kibana-opt_in_status"` + `"https://telemetry-staging.elastic.co/opt_in_status/v2/send"` ); }); }); diff --git a/src/plugins/telemetry/common/telemetry_config/get_telemetry_channel_endpoint.ts b/src/plugins/telemetry/common/telemetry_config/get_telemetry_channel_endpoint.ts index 75d83611b8c8d..393ceda4552be 100644 --- a/src/plugins/telemetry/common/telemetry_config/get_telemetry_channel_endpoint.ts +++ b/src/plugins/telemetry/common/telemetry_config/get_telemetry_channel_endpoint.ts @@ -49,5 +49,5 @@ export function getTelemetryChannelEndpoint({ const baseUrl = getBaseUrl(env); const channelPath = getChannel(channelName); - return `${baseUrl}${ENDPOINT_VERSION}/send/${channelPath}`; + return `${baseUrl}${channelPath}/${ENDPOINT_VERSION}/send`; } diff --git a/src/plugins/telemetry/public/services/telemetry_service.test.ts b/src/plugins/telemetry/public/services/telemetry_service.test.ts index ca4af0a903400..8987dde232e86 100644 --- a/src/plugins/telemetry/public/services/telemetry_service.test.ts +++ b/src/plugins/telemetry/public/services/telemetry_service.test.ts @@ -143,7 +143,7 @@ describe('TelemetryService', () => { }); expect(telemetryService.getTelemetryUrl()).toMatchInlineSnapshot( - `"https://telemetry-staging.elastic.co/v3/send/kibana-snapshot"` + `"https://telemetry-staging.elastic.co/xpack/v2/send"` ); }); @@ -153,7 +153,7 @@ describe('TelemetryService', () => { }); expect(telemetryService.getTelemetryUrl()).toMatchInlineSnapshot( - `"https://telemetry.elastic.co/v3/send/kibana-snapshot"` + `"https://telemetry.elastic.co/xpack/v2/send"` ); }); }); @@ -165,7 +165,7 @@ describe('TelemetryService', () => { }); expect(telemetryService.getOptInStatusUrl()).toMatchInlineSnapshot( - `"https://telemetry-staging.elastic.co/v3/send/kibana-opt_in_status"` + `"https://telemetry-staging.elastic.co/opt_in_status/v2/send"` ); }); @@ -175,7 +175,7 @@ describe('TelemetryService', () => { }); expect(telemetryService.getOptInStatusUrl()).toMatchInlineSnapshot( - `"https://telemetry.elastic.co/v3/send/kibana-opt_in_status"` + `"https://telemetry.elastic.co/opt_in_status/v2/send"` ); }); }); diff --git a/src/plugins/telemetry/server/routes/telemetry_opt_in_stats.test.ts b/src/plugins/telemetry/server/routes/telemetry_opt_in_stats.test.ts index edf9cf5b5e18c..00bf675a0494a 100644 --- a/src/plugins/telemetry/server/routes/telemetry_opt_in_stats.test.ts +++ b/src/plugins/telemetry/server/routes/telemetry_opt_in_stats.test.ts @@ -40,7 +40,7 @@ describe('sendTelemetryOptInStatus', () => { expect(fetch).toBeCalledTimes(1); expect((fetch as jest.MockedFunction).mock.calls[0]).toMatchInlineSnapshot(` Array [ - "https://telemetry.elastic.co/v3/send/kibana-opt_in_status", + "https://telemetry.elastic.co/opt_in_status/v2/send", Object { "body": "mock_opt_in_hashed_value", "headers": Object { @@ -71,7 +71,7 @@ describe('sendTelemetryOptInStatus', () => { expect(fetch).toBeCalledTimes(1); expect((fetch as jest.MockedFunction).mock.calls[0]).toMatchInlineSnapshot(` Array [ - "https://telemetry-staging.elastic.co/v3/send/kibana-opt_in_status", + "https://telemetry-staging.elastic.co/opt_in_status/v2/send", Object { "body": "mock_opt_in_hashed_value", "headers": Object { From 1c82dae7e40fba863ccf8869a77c4b79578f8620 Mon Sep 17 00:00:00 2001 From: Steph Milovic Date: Tue, 16 Nov 2021 08:22:29 -0700 Subject: [PATCH 024/148] [Security Solution] Timeline sourcerer bug fix (#118619) --- .../components/sourcerer/index.test.tsx | 34 +++++- .../common/components/sourcerer/index.tsx | 14 +-- .../common/store/sourcerer/helpers.test.ts | 102 +++++------------- .../public/common/store/sourcerer/helpers.ts | 48 +-------- .../__snapshots__/index.test.tsx.snap | 2 - .../timeline/eql_tab_content/index.test.tsx | 6 +- .../timeline/eql_tab_content/index.tsx | 45 ++------ .../__snapshots__/index.test.tsx.snap | 2 - .../timeline/query_tab_content/index.test.tsx | 2 - .../timeline/query_tab_content/index.tsx | 33 +----- .../timeline/epic_local_storage.test.tsx | 2 - 11 files changed, 80 insertions(+), 210 deletions(-) diff --git a/x-pack/plugins/security_solution/public/common/components/sourcerer/index.test.tsx b/x-pack/plugins/security_solution/public/common/components/sourcerer/index.test.tsx index c2da7e78d64e0..5bc2ce27e2353 100644 --- a/x-pack/plugins/security_solution/public/common/components/sourcerer/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/sourcerer/index.test.tsx @@ -643,7 +643,7 @@ describe('timeline sourcerer', () => { .simulate('click'); }); - it('renders "alerts only" checkbox', () => { + it('renders "alerts only" checkbox, unchecked', () => { wrapper .find( `[data-test-subj="timeline-sourcerer-popover"] [data-test-subj="sourcerer-alert-only-checkbox"]` @@ -653,6 +653,9 @@ describe('timeline sourcerer', () => { expect(wrapper.find(`[data-test-subj="sourcerer-alert-only-checkbox"]`).first().text()).toEqual( 'Show only detection alerts' ); + expect( + wrapper.find(`[data-test-subj="sourcerer-alert-only-checkbox"] input`).first().prop('checked') + ).toEqual(false); }); it('data view selector is enabled', () => { @@ -691,6 +694,35 @@ describe('timeline sourcerer', () => { it('render save button', () => { expect(wrapper.find(`[data-test-subj="sourcerer-save"]`).exists()).toBeTruthy(); }); + + it('Checks box when only alerts index is selected in timeline', () => { + const state2 = { + ...mockGlobalState, + sourcerer: { + ...mockGlobalState.sourcerer, + sourcererScopes: { + ...mockGlobalState.sourcerer.sourcererScopes, + [SourcererScopeName.timeline]: { + ...mockGlobalState.sourcerer.sourcererScopes[SourcererScopeName.timeline], + loading: false, + selectedDataViewId: id, + selectedPatterns: [`${mockGlobalState.sourcerer.signalIndexName}`], + }, + }, + }, + }; + + store = createStore(state2, SUB_PLUGINS_REDUCER, kibanaObservable, storage); + wrapper = mount( + + + + ); + wrapper.find(`[data-test-subj="timeline-sourcerer-trigger"]`).first().simulate('click'); + expect( + wrapper.find(`[data-test-subj="sourcerer-alert-only-checkbox"] input`).first().prop('checked') + ).toEqual(true); + }); }); describe('Sourcerer integration tests', () => { diff --git a/x-pack/plugins/security_solution/public/common/components/sourcerer/index.tsx b/x-pack/plugins/security_solution/public/common/components/sourcerer/index.tsx index 6f223cbb4aa30..84dbbba32b729 100644 --- a/x-pack/plugins/security_solution/public/common/components/sourcerer/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/sourcerer/index.tsx @@ -48,11 +48,6 @@ export const Sourcerer = React.memo(({ scope: scopeId } const isDetectionsSourcerer = scopeId === SourcererScopeName.detections; const isTimelineSourcerer = scopeId === SourcererScopeName.timeline; - const [isOnlyDetectionAlertsChecked, setIsOnlyDetectionAlertsChecked] = useState(false); - - const isOnlyDetectionAlerts: boolean = - isDetectionsSourcerer || (isTimelineSourcerer && isOnlyDetectionAlertsChecked); - const sourcererScopeSelector = useMemo(() => sourcererSelectors.getSourcererScopeSelector(), []); const { defaultDataView, @@ -61,6 +56,13 @@ export const Sourcerer = React.memo(({ scope: scopeId } sourcererScope: { selectedDataViewId, selectedPatterns, loading }, } = useDeepEqualSelector((state) => sourcererScopeSelector(state, scopeId)); + const [isOnlyDetectionAlertsChecked, setIsOnlyDetectionAlertsChecked] = useState( + isTimelineSourcerer && selectedPatterns.join() === signalIndexName + ); + + const isOnlyDetectionAlerts: boolean = + isDetectionsSourcerer || (isTimelineSourcerer && isOnlyDetectionAlertsChecked); + const [isPopoverOpen, setPopoverIsOpen] = useState(false); const [dataViewId, setDataViewId] = useState(selectedDataViewId ?? defaultDataView.id); @@ -244,7 +246,7 @@ export const Sourcerer = React.memo(({ scope: scopeId } fullWidth onChange={onChangeSuper} options={dataViewSelectOptions} - placeholder={i18n.PICK_INDEX_PATTERNS} + placeholder={i18n.INDEX_PATTERNS_CHOOSE_DATA_VIEW_LABEL} valueOfSelected={dataViewId} /> diff --git a/x-pack/plugins/security_solution/public/common/store/sourcerer/helpers.test.ts b/x-pack/plugins/security_solution/public/common/store/sourcerer/helpers.test.ts index 83a556442f849..5945b453673c3 100644 --- a/x-pack/plugins/security_solution/public/common/store/sourcerer/helpers.test.ts +++ b/x-pack/plugins/security_solution/public/common/store/sourcerer/helpers.test.ts @@ -7,11 +7,7 @@ import { mockGlobalState } from '../../mock'; import { SourcererScopeName } from './model'; -import { - defaultDataViewByEventType, - getScopePatternListSelection, - validateSelectedPatterns, -} from './helpers'; +import { getScopePatternListSelection, validateSelectedPatterns } from './helpers'; const signalIndexName = mockGlobalState.sourcerer.signalIndexName; @@ -23,10 +19,6 @@ const dataView = { const patternListNoSignals = mockGlobalState.sourcerer.defaultDataView.patternList .filter((p) => p !== signalIndexName) .sort(); -const patternListSignals = [ - signalIndexName, - ...mockGlobalState.sourcerer.defaultDataView.patternList.filter((p) => p !== signalIndexName), -].sort(); describe('sourcerer store helpers', () => { describe('getScopePatternListSelection', () => { @@ -130,6 +122,29 @@ describe('sourcerer store helpers', () => { }, }); }); + it('sets to alerts in timeline even when does not yet exist', () => { + const dataViewNoSignals = { + ...mockGlobalState.sourcerer.defaultDataView, + patternList: patternListNoSignals, + }; + const stateNoSignals = { + ...mockGlobalState.sourcerer, + defaultDataView: dataViewNoSignals, + kibanaDataViews: [dataViewNoSignals], + }; + const result = validateSelectedPatterns(stateNoSignals, { + ...payload, + id: SourcererScopeName.timeline, + selectedPatterns: [`${mockGlobalState.sourcerer.signalIndexName}`], + }); + expect(result).toEqual({ + [SourcererScopeName.timeline]: { + ...mockGlobalState.sourcerer.sourcererScopes[SourcererScopeName.timeline], + selectedDataViewId: dataView.id, + selectedPatterns: [signalIndexName], + }, + }); + }); describe('handles missing dataViewId, 7.16 -> 8.0', () => { it('selectedPatterns.length > 0 & all selectedPatterns exist in defaultDataView, set dataViewId to defaultDataView.id', () => { const result = validateSelectedPatterns(mockGlobalState.sourcerer, { @@ -175,73 +190,4 @@ describe('sourcerer store helpers', () => { }); }); }); - describe('defaultDataViewByEventType', () => { - it('defaults with no eventType', () => { - const result = defaultDataViewByEventType({ state: mockGlobalState.sourcerer }); - expect(result).toEqual({ - selectedDataViewId: dataView.id, - selectedPatterns: patternListSignals, - }); - }); - it('defaults with eventType: all', () => { - const result = defaultDataViewByEventType({ - state: mockGlobalState.sourcerer, - eventType: 'all', - }); - expect(result).toEqual({ - selectedDataViewId: dataView.id, - selectedPatterns: patternListSignals, - }); - }); - it('defaults with eventType: raw', () => { - const result = defaultDataViewByEventType({ - state: mockGlobalState.sourcerer, - eventType: 'raw', - }); - expect(result).toEqual({ - selectedDataViewId: dataView.id, - selectedPatterns: patternListNoSignals, - }); - }); - it('defaults with eventType: alert', () => { - const result = defaultDataViewByEventType({ - state: mockGlobalState.sourcerer, - eventType: 'alert', - }); - expect(result).toEqual({ - selectedDataViewId: dataView.id, - selectedPatterns: [signalIndexName], - }); - }); - it('defaults with eventType: signal', () => { - const result = defaultDataViewByEventType({ - state: mockGlobalState.sourcerer, - eventType: 'signal', - }); - expect(result).toEqual({ - selectedDataViewId: dataView.id, - selectedPatterns: [signalIndexName], - }); - }); - it('defaults with eventType: custom', () => { - const result = defaultDataViewByEventType({ - state: mockGlobalState.sourcerer, - eventType: 'custom', - }); - expect(result).toEqual({ - selectedDataViewId: dataView.id, - selectedPatterns: patternListSignals, - }); - }); - it('defaults with eventType: eql', () => { - const result = defaultDataViewByEventType({ - state: mockGlobalState.sourcerer, - eventType: 'eql', - }); - expect(result).toEqual({ - selectedDataViewId: dataView.id, - selectedPatterns: patternListSignals, - }); - }); - }); }); diff --git a/x-pack/plugins/security_solution/public/common/store/sourcerer/helpers.ts b/x-pack/plugins/security_solution/public/common/store/sourcerer/helpers.ts index c99ed720c7f00..ca06d05254cfa 100644 --- a/x-pack/plugins/security_solution/public/common/store/sourcerer/helpers.ts +++ b/x-pack/plugins/security_solution/public/common/store/sourcerer/helpers.ts @@ -7,16 +7,8 @@ import { isEmpty } from 'lodash'; import { SourcererDataView, SourcererModel, SourcererScopeById, SourcererScopeName } from './model'; -import { TimelineEventsType } from '../../../../common'; import { SelectedDataViewPayload } from './actions'; -export interface Args { - eventType?: TimelineEventsType; - id: SourcererScopeName; - selectedPatterns: string[]; - state: SourcererModel; -} - export const getScopePatternListSelection = ( theDataView: SourcererDataView | undefined, sourcererScope: SourcererScopeName, @@ -45,7 +37,7 @@ export const validateSelectedPatterns = ( state: SourcererModel, payload: SelectedDataViewPayload ): Partial => { - const { id, eventType, ...rest } = payload; + const { id, ...rest } = payload; let dataView = state.kibanaDataViews.find((p) => p.id === rest.selectedDataViewId); // dedupe because these could come from a silly url or pre 8.0 timeline const dedupePatterns = [...new Set(rest.selectedPatterns)]; @@ -57,10 +49,12 @@ export const validateSelectedPatterns = ( // so redoing the dataView != null check (dataView != null && dataView.patternList.includes(pattern)) || // this is a hack, but sometimes signal index is deleted and is getting regenerated. it gets set before it is put in the dataView - state.signalIndexName == null + state.signalIndexName == null || + state.signalIndexName === pattern ) : // 7.16 -> 8.0 this will get hit because dataView == null dedupePatterns; + if (selectedPatterns.length > 0 && dataView == null) { // we have index patterns, but not a data view id // find out if we have these index patterns in the defaultDataView @@ -74,7 +68,6 @@ export const validateSelectedPatterns = ( ); } } - // TO DO: Steph/sourcerer If dataView is still undefined here, create temporary dataView // and prompt user to go create this dataView // currently UI will take the undefined dataView and default to defaultDataView anyways @@ -101,36 +94,3 @@ export const validateSelectedPatterns = ( }, }; }; - -// TODO: Steph/sourcerer eventType will be alerts only, when ui updates delete raw -export const defaultDataViewByEventType = ({ - state, - eventType, -}: { - state: SourcererModel; - eventType?: TimelineEventsType; -}) => { - const { - signalIndexName, - defaultDataView: { id, patternList }, - } = state; - if (signalIndexName != null && (eventType === 'signal' || eventType === 'alert')) { - return { - selectedPatterns: [signalIndexName], - selectedDataViewId: id, - }; - } else if (eventType === 'raw') { - return { - selectedPatterns: patternList.filter((index) => index !== signalIndexName).sort(), - selectedDataViewId: id, - }; - } - return { - selectedPatterns: [ - // remove signalIndexName in case its already in there and add it whether or not it exists yet in the patternList - ...patternList.filter((index) => index !== signalIndexName), - signalIndexName, - ].sort(), - selectedDataViewId: id, - }; -}; diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/eql_tab_content/__snapshots__/index.test.tsx.snap b/x-pack/plugins/security_solution/public/timelines/components/timeline/eql_tab_content/__snapshots__/index.test.tsx.snap index 78f19e390ae28..7c0f0a1ac7f8e 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/eql_tab_content/__snapshots__/index.test.tsx.snap +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/eql_tab_content/__snapshots__/index.test.tsx.snap @@ -128,7 +128,6 @@ In other use cases the message field can be used to concatenate different values } end="2018-03-24T03:33:52.253Z" eqlOptions={Object {}} - eventType="all" expandedDetail={Object {}} isLive={false} itemsPerPage={5} @@ -1129,6 +1128,5 @@ In other use cases the message field can be used to concatenate different values start="2018-03-23T18:49:23.132Z" timelineId="test" timerangeKind="absolute" - updateEventTypeAndIndexesName={[MockFunction]} /> `; diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/eql_tab_content/index.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/eql_tab_content/index.test.tsx index 553a3d0e82d29..58a295fa48208 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/eql_tab_content/index.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/eql_tab_content/index.test.tsx @@ -91,12 +91,11 @@ describe('Timeline', () => { (useSourcererDataView as jest.Mock).mockReturnValue(mockSourcererScope); props = { + activeTab: TimelineTabs.eql, columns: defaultHeaders, end: endDate, eqlOptions: {}, expandedDetail: {}, - eventType: 'all', - timelineId: TimelineId.test, isLive: false, itemsPerPage: 5, itemsPerPageOptions: [5, 10, 20], @@ -105,9 +104,8 @@ describe('Timeline', () => { rowRenderers: defaultRowRenderers, showExpandedDetails: false, start: startDate, + timelineId: TimelineId.test, timerangeKind: 'absolute', - updateEventTypeAndIndexesName: jest.fn(), - activeTab: TimelineTabs.eql, }; }); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/eql_tab_content/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/eql_tab_content/index.tsx index 71a4b5c920928..42f9801057190 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/eql_tab_content/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/eql_tab_content/index.tsx @@ -33,7 +33,6 @@ import { TimelineRefetch } from '../refetch_timeline'; import { ControlColumnProps, RowRenderer, - TimelineEventsType, TimelineId, TimelineTabs, ToggleDetailPanel, @@ -43,7 +42,6 @@ import { ExitFullScreen } from '../../../../common/components/exit_full_screen'; import { SuperDatePicker } from '../../../../common/components/super_date_picker'; import { EventDetailsWidthProvider } from '../../../../common/components/events_viewer/event_details_width_context'; import { inputsModel, inputsSelectors, State } from '../../../../common/store'; -import { sourcererActions } from '../../../../common/store/sourcerer'; import { SourcererScopeName } from '../../../../common/store/sourcerer/model'; import { timelineDefaults } from '../../../../timelines/store/timeline/defaults'; import { useSourcererDataView } from '../../../../common/containers/sourcerer'; @@ -159,7 +157,6 @@ export const EqlTabContentComponent: React.FC = ({ columns, end, eqlOptions, - eventType, expandedDetail, timelineId, isLive, @@ -171,7 +168,6 @@ export const EqlTabContentComponent: React.FC = ({ showExpandedDetails, start, timerangeKind, - updateEventTypeAndIndexesName, }) => { const dispatch = useDispatch(); const { query: eqlQuery = '', ...restEqlOption } = eqlOptions; @@ -293,7 +289,9 @@ export const EqlTabContentComponent: React.FC = ({ - + {activeTab === TimelineTabs.eql && ( + + )} @@ -374,21 +372,13 @@ const makeMapStateToProps = () => { const mapStateToProps = (state: State, { timelineId }: OwnProps) => { const timeline: TimelineModel = getTimeline(state, timelineId) ?? timelineDefaults; const input: inputsModel.InputsRange = getInputsTimeline(state); - const { - activeTab, - columns, - eqlOptions, - eventType, - expandedDetail, - itemsPerPage, - itemsPerPageOptions, - } = timeline; + const { activeTab, columns, eqlOptions, expandedDetail, itemsPerPage, itemsPerPageOptions } = + timeline; return { activeTab, columns, eqlOptions, - eventType: eventType ?? 'raw', end: input.timerange.to, expandedDetail, timelineId, @@ -404,28 +394,7 @@ const makeMapStateToProps = () => { }; return mapStateToProps; }; -const mapDispatchToProps = (dispatch: Dispatch, { timelineId }: OwnProps) => ({ - updateEventTypeAndIndexesName: ( - newEventType: TimelineEventsType, - newIndexNames: string[], - newDataViewId: string - ) => { - dispatch(timelineActions.updateEventType({ id: timelineId, eventType: newEventType })); - dispatch( - timelineActions.updateDataView({ - dataViewId: newDataViewId, - id: timelineId, - indexNames: newIndexNames, - }) - ); - dispatch( - sourcererActions.setSelectedDataView({ - id: SourcererScopeName.timeline, - selectedDataViewId: newDataViewId, - selectedPatterns: newIndexNames, - }) - ); - }, +const mapDispatchToProps = (dispatch: Dispatch) => ({ onEventClosed: (args: ToggleDetailPanel) => { dispatch(timelineActions.toggleDetailPanel(args)); }, @@ -442,13 +411,11 @@ const EqlTabContent = connector( prevProps.activeTab === nextProps.activeTab && isTimerangeSame(prevProps, nextProps) && deepEqual(prevProps.eqlOptions, nextProps.eqlOptions) && - prevProps.eventType === nextProps.eventType && prevProps.isLive === nextProps.isLive && prevProps.itemsPerPage === nextProps.itemsPerPage && prevProps.onEventClosed === nextProps.onEventClosed && prevProps.showExpandedDetails === nextProps.showExpandedDetails && prevProps.timelineId === nextProps.timelineId && - prevProps.updateEventTypeAndIndexesName === nextProps.updateEventTypeAndIndexesName && deepEqual(prevProps.columns, nextProps.columns) && deepEqual(prevProps.itemsPerPageOptions, nextProps.itemsPerPageOptions) ) diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/query_tab_content/__snapshots__/index.test.tsx.snap b/x-pack/plugins/security_solution/public/timelines/components/timeline/query_tab_content/__snapshots__/index.test.tsx.snap index 26b9eb4729999..cc6feb69561df 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/query_tab_content/__snapshots__/index.test.tsx.snap +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/query_tab_content/__snapshots__/index.test.tsx.snap @@ -261,7 +261,6 @@ In other use cases the message field can be used to concatenate different values ] } end="2018-03-24T03:33:52.253Z" - eventType="all" expandedDetail={Object {}} filters={Array []} isLive={false} @@ -1277,6 +1276,5 @@ In other use cases the message field can be used to concatenate different values status="active" timelineId="test" timerangeKind="absolute" - updateEventTypeAndIndexesName={[MockFunction]} /> `; diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/query_tab_content/index.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/query_tab_content/index.test.tsx index 23f0fa0b9f289..07176b0514237 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/query_tab_content/index.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/query_tab_content/index.test.tsx @@ -108,7 +108,6 @@ describe('Timeline', () => { columns: defaultHeaders, dataProviders: mockDataProviders, end: endDate, - eventType: 'all', expandedDetail: {}, filters: [], timelineId: TimelineId.test, @@ -126,7 +125,6 @@ describe('Timeline', () => { start: startDate, status: TimelineStatus.active, timerangeKind: 'absolute', - updateEventTypeAndIndexesName: jest.fn(), activeTab: TimelineTabs.query, show: true, }; diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/query_tab_content/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/query_tab_content/index.tsx index 0b92a7e5c6493..643bd679e04ee 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/query_tab_content/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/query_tab_content/index.tsx @@ -38,7 +38,6 @@ import { ControlColumnProps, KueryFilterQueryKind, RowRenderer, - TimelineEventsType, TimelineId, TimelineTabs, ToggleDetailPanel, @@ -47,7 +46,6 @@ import { requiredFieldsForActions } from '../../../../detections/components/aler import { SuperDatePicker } from '../../../../common/components/super_date_picker'; import { EventDetailsWidthProvider } from '../../../../common/components/events_viewer/event_details_width_context'; import { inputsModel, inputsSelectors, State } from '../../../../common/store'; -import { sourcererActions } from '../../../../common/store/sourcerer'; import { SourcererScopeName } from '../../../../common/store/sourcerer/model'; import { timelineDefaults } from '../../../../timelines/store/timeline/defaults'; import { useSourcererDataView } from '../../../../common/containers/sourcerer'; @@ -164,7 +162,6 @@ export const QueryTabContentComponent: React.FC = ({ columns, dataProviders, end, - eventType, expandedDetail, filters, timelineId, @@ -183,7 +180,6 @@ export const QueryTabContentComponent: React.FC = ({ status, sort, timerangeKind, - updateEventTypeAndIndexesName, }) => { const dispatch = useDispatch(); const { portalNode: timelineEventsCountPortalNode } = useTimelineEventsCountPortal(); @@ -368,7 +364,9 @@ export const QueryTabContentComponent: React.FC = ({ - + {activeTab === TimelineTabs.query && ( + + )} @@ -461,7 +459,6 @@ const makeMapStateToProps = () => { activeTab, columns, dataProviders, - eventType, expandedDetail, filters, itemsPerPage, @@ -487,7 +484,6 @@ const makeMapStateToProps = () => { activeTab, columns, dataProviders, - eventType: eventType ?? 'raw', end: input.timerange.to, expandedDetail, filters: timelineFilter, @@ -511,27 +507,6 @@ const makeMapStateToProps = () => { }; const mapDispatchToProps = (dispatch: Dispatch, { timelineId }: OwnProps) => ({ - updateEventTypeAndIndexesName: ( - newEventType: TimelineEventsType, - newIndexNames: string[], - newDataViewId: string - ) => { - dispatch(timelineActions.updateEventType({ id: timelineId, eventType: newEventType })); - dispatch( - timelineActions.updateDataView({ - dataViewId: newDataViewId, - id: timelineId, - indexNames: newIndexNames, - }) - ); - dispatch( - sourcererActions.setSelectedDataView({ - id: SourcererScopeName.timeline, - selectedPatterns: newIndexNames, - selectedDataViewId: newDataViewId, - }) - ); - }, onEventClosed: (args: ToggleDetailPanel) => { dispatch(timelineActions.toggleDetailPanel(args)); }, @@ -548,7 +523,6 @@ const QueryTabContent = connector( compareQueryProps(prevProps, nextProps) && prevProps.activeTab === nextProps.activeTab && isTimerangeSame(prevProps, nextProps) && - prevProps.eventType === nextProps.eventType && prevProps.isLive === nextProps.isLive && prevProps.itemsPerPage === nextProps.itemsPerPage && prevProps.onEventClosed === nextProps.onEventClosed && @@ -557,7 +531,6 @@ const QueryTabContent = connector( prevProps.showExpandedDetails === nextProps.showExpandedDetails && prevProps.status === nextProps.status && prevProps.timelineId === nextProps.timelineId && - prevProps.updateEventTypeAndIndexesName === nextProps.updateEventTypeAndIndexesName && deepEqual(prevProps.columns, nextProps.columns) && deepEqual(prevProps.dataProviders, nextProps.dataProviders) && deepEqual(prevProps.itemsPerPageOptions, nextProps.itemsPerPageOptions) && diff --git a/x-pack/plugins/security_solution/public/timelines/store/timeline/epic_local_storage.test.tsx b/x-pack/plugins/security_solution/public/timelines/store/timeline/epic_local_storage.test.tsx index 131f255b5a7a7..af27d2a11ad4b 100644 --- a/x-pack/plugins/security_solution/public/timelines/store/timeline/epic_local_storage.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/store/timeline/epic_local_storage.test.tsx @@ -71,7 +71,6 @@ describe('epicLocalStorage', () => { columns: defaultHeaders, dataProviders: mockDataProviders, end: endDate, - eventType: 'all', expandedDetail: {}, filters: [], isLive: false, @@ -89,7 +88,6 @@ describe('epicLocalStorage', () => { sort, timelineId: 'foo', timerangeKind: 'absolute', - updateEventTypeAndIndexesName: jest.fn(), activeTab: TimelineTabs.query, show: true, }; From 0d16bd553b67abe93b06d691b94febf53bb2700d Mon Sep 17 00:00:00 2001 From: vladpro25 <91911546+vladpro25@users.noreply.github.com> Date: Tue, 16 Nov 2021 17:28:27 +0200 Subject: [PATCH 025/148] Add autocomplete for search_after and pit in search query (#117864) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../console/server/lib/spec_definitions/js/search.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/plugins/console/server/lib/spec_definitions/js/search.ts b/src/plugins/console/server/lib/spec_definitions/js/search.ts index 5a3b37e2e4135..88d08076bc207 100644 --- a/src/plugins/console/server/lib/spec_definitions/js/search.ts +++ b/src/plugins/console/server/lib/spec_definitions/js/search.ts @@ -102,6 +102,13 @@ export const search = (specService: SpecDefinitionsService) => { }, ], }, + pit: { + __template: { + id: '', + keep_alive: '1m', + }, + }, + search_after: [], stored_fields: ['{field}'], suggest: { __template: { From 1eee9aa9924e1d4894506aa990932a62af94a679 Mon Sep 17 00:00:00 2001 From: Lukas Olson Date: Tue, 16 Nov 2021 08:40:27 -0700 Subject: [PATCH 026/148] Add deprecation level for data plugin config renames (#118442) * Add deprecation level for data plugin config renames * Make warning level instead of critical Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- src/plugins/data/server/config_deprecations.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/plugins/data/server/config_deprecations.ts b/src/plugins/data/server/config_deprecations.ts index 47a88217611a3..d98364a8e83c6 100644 --- a/src/plugins/data/server/config_deprecations.ts +++ b/src/plugins/data/server/config_deprecations.ts @@ -13,7 +13,10 @@ export const autocompleteConfigDeprecationProvider: ConfigDeprecationProvider = }) => [ renameFromRoot( 'kibana.autocompleteTerminateAfter', - 'data.autocomplete.valueSuggestions.terminateAfter' + 'data.autocomplete.valueSuggestions.terminateAfter', + { level: 'warning' } ), - renameFromRoot('kibana.autocompleteTimeout', 'data.autocomplete.valueSuggestions.timeout'), + renameFromRoot('kibana.autocompleteTimeout', 'data.autocomplete.valueSuggestions.timeout', { + level: 'warning', + }), ]; From 0118e1a400e4aba0001b8c3ec1a847ec3bf276d0 Mon Sep 17 00:00:00 2001 From: Lukas Olson Date: Tue, 16 Nov 2021 08:40:56 -0700 Subject: [PATCH 027/148] Remove autocomplete first-time user experience (#118252) * Remvoe autocomplete first-time user experience * Remove unused translations --- ...-plugin-core-public.doclinksstart.links.md | 1 - ...kibana-plugin-core-public.doclinksstart.md | 6 +- .../public/doc_links/doc_links_service.ts | 2 - src/core/public/public.api.md | 1 - .../autocomplete_ftue_popover.test.tsx | 86 --------------- .../autocomplete_ftue_popover.tsx | 104 ------------------ .../query_string_input/query_bar_top_row.tsx | 39 +++---- .../translations/translations/ja-JP.json | 4 - .../translations/translations/zh-CN.json | 4 - 9 files changed, 21 insertions(+), 226 deletions(-) delete mode 100644 src/plugins/data/public/ui/query_string_input/autocomplete_ftue_popover.test.tsx delete mode 100644 src/plugins/data/public/ui/query_string_input/autocomplete_ftue_popover.tsx diff --git a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md b/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md index 37524daa39c51..d7f159ad6f627 100644 --- a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md +++ b/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md @@ -163,7 +163,6 @@ readonly links: { readonly luceneQuerySyntax: string; readonly percolate: string; readonly queryDsl: string; - readonly autocompleteChanges: string; }; readonly date: { readonly dateMath: string; diff --git a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.md b/docs/development/core/public/kibana-plugin-core-public.doclinksstart.md index a1363b7a519d1..1b2774fdd223f 100644 --- a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.md +++ b/docs/development/core/public/kibana-plugin-core-public.doclinksstart.md @@ -15,7 +15,7 @@ export interface DocLinksStart | Property | Type | Description | | --- | --- | --- | -| [DOC\_LINK\_VERSION](./kibana-plugin-core-public.doclinksstart.doc_link_version.md) | string | | -| [ELASTIC\_WEBSITE\_URL](./kibana-plugin-core-public.doclinksstart.elastic_website_url.md) | string | | -| [links](./kibana-plugin-core-public.doclinksstart.links.md) | { readonly settings: string; readonly elasticStackGetStarted: string; readonly upgrade: { readonly upgradingElasticStack: string; }; readonly apm: { readonly kibanaSettings: string; readonly supportedServiceMaps: string; readonly customLinks: string; readonly droppedTransactionSpans: string; readonly upgrading: string; readonly metaData: string; }; readonly canvas: { readonly guide: string; }; readonly dashboard: { readonly guide: string; readonly drilldowns: string; readonly drilldownsTriggerPicker: string; readonly urlDrilldownTemplateSyntax: string; readonly urlDrilldownVariables: string; }; readonly discover: Record<string, string>; readonly filebeat: { readonly base: string; readonly installation: string; readonly configuration: string; readonly elasticsearchOutput: string; readonly elasticsearchModule: string; readonly startup: string; readonly exportedFields: string; readonly suricataModule: string; readonly zeekModule: string; }; readonly auditbeat: { readonly base: string; readonly auditdModule: string; readonly systemModule: string; }; readonly metricbeat: { readonly base: string; readonly configure: string; readonly httpEndpoint: string; readonly install: string; readonly start: string; }; readonly enterpriseSearch: { readonly base: string; readonly appSearchBase: string; readonly workplaceSearchBase: string; }; readonly heartbeat: { readonly base: string; }; readonly libbeat: { readonly getStarted: string; }; readonly logstash: { readonly base: string; }; readonly functionbeat: { readonly base: string; }; readonly winlogbeat: { readonly base: string; }; readonly aggs: { readonly composite: string; readonly composite\_missing\_bucket: string; readonly date\_histogram: string; readonly date\_range: string; readonly date\_format\_pattern: string; readonly filter: string; readonly filters: string; readonly geohash\_grid: string; readonly histogram: string; readonly ip\_range: string; readonly range: string; readonly significant\_terms: string; readonly terms: string; readonly terms\_doc\_count\_error: string; readonly avg: string; readonly avg\_bucket: string; readonly max\_bucket: string; readonly min\_bucket: string; readonly sum\_bucket: string; readonly cardinality: string; readonly count: string; readonly cumulative\_sum: string; readonly derivative: string; readonly geo\_bounds: string; readonly geo\_centroid: string; readonly max: string; readonly median: string; readonly min: string; readonly moving\_avg: string; readonly percentile\_ranks: string; readonly serial\_diff: string; readonly std\_dev: string; readonly sum: string; readonly top\_hits: string; }; readonly runtimeFields: { readonly overview: string; readonly mapping: string; }; readonly scriptedFields: { readonly scriptFields: string; readonly scriptAggs: string; readonly painless: string; readonly painlessApi: string; readonly painlessLangSpec: string; readonly painlessSyntax: string; readonly painlessWalkthrough: string; readonly luceneExpressions: string; }; readonly search: { readonly sessions: string; readonly sessionLimits: string; }; readonly indexPatterns: { readonly introduction: string; readonly fieldFormattersNumber: string; readonly fieldFormattersString: string; readonly runtimeFields: string; }; readonly addData: string; readonly kibana: string; readonly upgradeAssistant: { readonly overview: string; readonly batchReindex: string; readonly remoteReindex: string; }; readonly rollupJobs: string; readonly elasticsearch: Record<string, string>; readonly siem: { readonly privileges: string; readonly guide: string; readonly gettingStarted: string; readonly ml: string; readonly ruleChangeLog: string; readonly detectionsReq: string; readonly networkMap: string; readonly troubleshootGaps: string; }; readonly securitySolution: { readonly trustedApps: string; }; readonly query: { readonly eql: string; readonly kueryQuerySyntax: string; readonly luceneQuerySyntax: string; readonly percolate: string; readonly queryDsl: string; readonly autocompleteChanges: string; }; readonly date: { readonly dateMath: string; readonly dateMathIndexNames: string; }; readonly management: Record<string, string>; readonly ml: Record<string, string>; readonly transforms: Record<string, string>; readonly visualize: Record<string, string>; readonly apis: Readonly<{ bulkIndexAlias: string; byteSizeUnits: string; createAutoFollowPattern: string; createFollower: string; createIndex: string; createSnapshotLifecyclePolicy: string; createRoleMapping: string; createRoleMappingTemplates: string; createRollupJobsRequest: string; createApiKey: string; createPipeline: string; createTransformRequest: string; cronExpressions: string; executeWatchActionModes: string; indexExists: string; openIndex: string; putComponentTemplate: string; painlessExecute: string; painlessExecuteAPIContexts: string; putComponentTemplateMetadata: string; putSnapshotLifecyclePolicy: string; putIndexTemplateV1: string; putWatch: string; simulatePipeline: string; timeUnits: string; updateTransform: string; }>; readonly observability: Readonly<{ guide: string; infrastructureThreshold: string; logsThreshold: string; metricsThreshold: string; monitorStatus: string; monitorUptime: string; tlsCertificate: string; uptimeDurationAnomaly: string; }>; readonly alerting: Record<string, string>; readonly maps: Record<string, string>; readonly monitoring: Record<string, string>; readonly security: Readonly<{ apiKeyServiceSettings: string; clusterPrivileges: string; elasticsearchSettings: string; elasticsearchEnableSecurity: string; elasticsearchEnableApiKeys: string; indicesPrivileges: string; kibanaTLS: string; kibanaPrivileges: string; mappingRoles: string; mappingRolesFieldRules: string; runAsPrivilege: string; }>; readonly spaces: Readonly<{ kibanaLegacyUrlAliases: string; kibanaDisableLegacyUrlAliasesApi: string; }>; readonly watcher: Record<string, string>; readonly ccs: Record<string, string>; readonly plugins: Record<string, string>; readonly snapshotRestore: Record<string, string>; readonly ingest: Record<string, string>; readonly fleet: Readonly<{ datastreamsILM: string; beatsAgentComparison: string; guide: string; fleetServer: string; fleetServerAddFleetServer: string; settings: string; settingsFleetServerHostSettings: string; settingsFleetServerProxySettings: string; troubleshooting: string; elasticAgent: string; datastreams: string; datastreamsNamingScheme: string; installElasticAgent: string; upgradeElasticAgent: string; upgradeElasticAgent712lower: string; learnMoreBlog: string; apiKeysLearnMore: string; onPremRegistry: string; }>; readonly ecs: { readonly guide: string; }; readonly clients: { readonly guide: string; readonly goOverview: string; readonly javaIndex: string; readonly jsIntro: string; readonly netGuide: string; readonly perlGuide: string; readonly phpGuide: string; readonly pythonGuide: string; readonly rubyOverview: string; readonly rustGuide: string; }; readonly endpoints: { readonly troubleshooting: string; }; } | | +| [DOC\_LINK\_VERSION](./kibana-plugin-core-public.doclinksstart.doc_link_version.md) | string | | +| [ELASTIC\_WEBSITE\_URL](./kibana-plugin-core-public.doclinksstart.elastic_website_url.md) | string | | +| [links](./kibana-plugin-core-public.doclinksstart.links.md) | {
readonly settings: string;
readonly elasticStackGetStarted: string;
readonly upgrade: {
readonly upgradingElasticStack: string;
};
readonly apm: {
readonly kibanaSettings: string;
readonly supportedServiceMaps: string;
readonly customLinks: string;
readonly droppedTransactionSpans: string;
readonly upgrading: string;
readonly metaData: string;
};
readonly canvas: {
readonly guide: string;
};
readonly dashboard: {
readonly guide: string;
readonly drilldowns: string;
readonly drilldownsTriggerPicker: string;
readonly urlDrilldownTemplateSyntax: string;
readonly urlDrilldownVariables: string;
};
readonly discover: Record<string, string>;
readonly filebeat: {
readonly base: string;
readonly installation: string;
readonly configuration: string;
readonly elasticsearchOutput: string;
readonly elasticsearchModule: string;
readonly startup: string;
readonly exportedFields: string;
readonly suricataModule: string;
readonly zeekModule: string;
};
readonly auditbeat: {
readonly base: string;
readonly auditdModule: string;
readonly systemModule: string;
};
readonly metricbeat: {
readonly base: string;
readonly configure: string;
readonly httpEndpoint: string;
readonly install: string;
readonly start: string;
};
readonly enterpriseSearch: {
readonly base: string;
readonly appSearchBase: string;
readonly workplaceSearchBase: string;
};
readonly heartbeat: {
readonly base: string;
};
readonly libbeat: {
readonly getStarted: string;
};
readonly logstash: {
readonly base: string;
};
readonly functionbeat: {
readonly base: string;
};
readonly winlogbeat: {
readonly base: string;
};
readonly aggs: {
readonly composite: string;
readonly composite_missing_bucket: string;
readonly date_histogram: string;
readonly date_range: string;
readonly date_format_pattern: string;
readonly filter: string;
readonly filters: string;
readonly geohash_grid: string;
readonly histogram: string;
readonly ip_range: string;
readonly range: string;
readonly significant_terms: string;
readonly terms: string;
readonly terms_doc_count_error: string;
readonly avg: string;
readonly avg_bucket: string;
readonly max_bucket: string;
readonly min_bucket: string;
readonly sum_bucket: string;
readonly cardinality: string;
readonly count: string;
readonly cumulative_sum: string;
readonly derivative: string;
readonly geo_bounds: string;
readonly geo_centroid: string;
readonly max: string;
readonly median: string;
readonly min: string;
readonly moving_avg: string;
readonly percentile_ranks: string;
readonly serial_diff: string;
readonly std_dev: string;
readonly sum: string;
readonly top_hits: string;
};
readonly runtimeFields: {
readonly overview: string;
readonly mapping: string;
};
readonly scriptedFields: {
readonly scriptFields: string;
readonly scriptAggs: string;
readonly painless: string;
readonly painlessApi: string;
readonly painlessLangSpec: string;
readonly painlessSyntax: string;
readonly painlessWalkthrough: string;
readonly luceneExpressions: string;
};
readonly search: {
readonly sessions: string;
readonly sessionLimits: string;
};
readonly indexPatterns: {
readonly introduction: string;
readonly fieldFormattersNumber: string;
readonly fieldFormattersString: string;
readonly runtimeFields: string;
};
readonly addData: string;
readonly kibana: string;
readonly upgradeAssistant: {
readonly overview: string;
readonly batchReindex: string;
readonly remoteReindex: string;
};
readonly rollupJobs: string;
readonly elasticsearch: Record<string, string>;
readonly siem: {
readonly privileges: string;
readonly guide: string;
readonly gettingStarted: string;
readonly ml: string;
readonly ruleChangeLog: string;
readonly detectionsReq: string;
readonly networkMap: string;
readonly troubleshootGaps: string;
};
readonly securitySolution: {
readonly trustedApps: string;
};
readonly query: {
readonly eql: string;
readonly kueryQuerySyntax: string;
readonly luceneQuerySyntax: string;
readonly percolate: string;
readonly queryDsl: string;
};
readonly date: {
readonly dateMath: string;
readonly dateMathIndexNames: string;
};
readonly management: Record<string, string>;
readonly ml: Record<string, string>;
readonly transforms: Record<string, string>;
readonly visualize: Record<string, string>;
readonly apis: Readonly<{
bulkIndexAlias: string;
byteSizeUnits: string;
createAutoFollowPattern: string;
createFollower: string;
createIndex: string;
createSnapshotLifecyclePolicy: string;
createRoleMapping: string;
createRoleMappingTemplates: string;
createRollupJobsRequest: string;
createApiKey: string;
createPipeline: string;
createTransformRequest: string;
cronExpressions: string;
executeWatchActionModes: string;
indexExists: string;
openIndex: string;
putComponentTemplate: string;
painlessExecute: string;
painlessExecuteAPIContexts: string;
putComponentTemplateMetadata: string;
putSnapshotLifecyclePolicy: string;
putIndexTemplateV1: string;
putWatch: string;
simulatePipeline: string;
timeUnits: string;
updateTransform: string;
}>;
readonly observability: Readonly<{
guide: string;
infrastructureThreshold: string;
logsThreshold: string;
metricsThreshold: string;
monitorStatus: string;
monitorUptime: string;
tlsCertificate: string;
uptimeDurationAnomaly: string;
}>;
readonly alerting: Record<string, string>;
readonly maps: Record<string, string>;
readonly monitoring: Record<string, string>;
readonly security: Readonly<{
apiKeyServiceSettings: string;
clusterPrivileges: string;
elasticsearchSettings: string;
elasticsearchEnableSecurity: string;
elasticsearchEnableApiKeys: string;
indicesPrivileges: string;
kibanaTLS: string;
kibanaPrivileges: string;
mappingRoles: string;
mappingRolesFieldRules: string;
runAsPrivilege: string;
}>;
readonly spaces: Readonly<{
kibanaLegacyUrlAliases: string;
kibanaDisableLegacyUrlAliasesApi: string;
}>;
readonly watcher: Record<string, string>;
readonly ccs: Record<string, string>;
readonly plugins: Record<string, string>;
readonly snapshotRestore: Record<string, string>;
readonly ingest: Record<string, string>;
readonly fleet: Readonly<{
datastreamsILM: string;
beatsAgentComparison: string;
guide: string;
fleetServer: string;
fleetServerAddFleetServer: string;
settings: string;
settingsFleetServerHostSettings: string;
settingsFleetServerProxySettings: string;
troubleshooting: string;
elasticAgent: string;
datastreams: string;
datastreamsNamingScheme: string;
installElasticAgent: string;
upgradeElasticAgent: string;
upgradeElasticAgent712lower: string;
learnMoreBlog: string;
apiKeysLearnMore: string;
onPremRegistry: string;
}>;
readonly ecs: {
readonly guide: string;
};
readonly clients: {
readonly guide: string;
readonly goOverview: string;
readonly javaIndex: string;
readonly jsIntro: string;
readonly netGuide: string;
readonly perlGuide: string;
readonly phpGuide: string;
readonly pythonGuide: string;
readonly rubyOverview: string;
readonly rustGuide: string;
};
readonly endpoints: {
readonly troubleshooting: string;
};
} | | diff --git a/src/core/public/doc_links/doc_links_service.ts b/src/core/public/doc_links/doc_links_service.ts index ee4e50627074a..e9b82de9eaafa 100644 --- a/src/core/public/doc_links/doc_links_service.ts +++ b/src/core/public/doc_links/doc_links_service.ts @@ -256,7 +256,6 @@ export class DocLinksService { luceneQuerySyntax: `${ELASTICSEARCH_DOCS}query-dsl-query-string-query.html#query-string-syntax`, percolate: `${ELASTICSEARCH_DOCS}query-dsl-percolate-query.html`, queryDsl: `${ELASTICSEARCH_DOCS}query-dsl.html`, - autocompleteChanges: `${KIBANA_DOCS}kibana-concepts-analysts.html#autocomplete-suggestions`, }, search: { sessions: `${KIBANA_DOCS}search-sessions.html`, @@ -688,7 +687,6 @@ export interface DocLinksStart { readonly luceneQuerySyntax: string; readonly percolate: string; readonly queryDsl: string; - readonly autocompleteChanges: string; }; readonly date: { readonly dateMath: string; diff --git a/src/core/public/public.api.md b/src/core/public/public.api.md index 1dc7ead282927..2e75d3f1ba035 100644 --- a/src/core/public/public.api.md +++ b/src/core/public/public.api.md @@ -634,7 +634,6 @@ export interface DocLinksStart { readonly luceneQuerySyntax: string; readonly percolate: string; readonly queryDsl: string; - readonly autocompleteChanges: string; }; readonly date: { readonly dateMath: string; diff --git a/src/plugins/data/public/ui/query_string_input/autocomplete_ftue_popover.test.tsx b/src/plugins/data/public/ui/query_string_input/autocomplete_ftue_popover.test.tsx deleted file mode 100644 index 6f71a0dc7679d..0000000000000 --- a/src/plugins/data/public/ui/query_string_input/autocomplete_ftue_popover.test.tsx +++ /dev/null @@ -1,86 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import React, { ReactElement } from 'react'; -import { mountWithIntl as mount } from '@kbn/test/jest'; -import { AutocompleteFtuePopover } from './autocomplete_ftue_popover'; -import { EuiTourStep } from '@elastic/eui'; -import { act } from 'react-dom/test-utils'; -import { coreMock } from '../../../../../core/public/mocks'; -import { KibanaContextProvider } from '../../../../kibana_react/public'; -import { IStorageWrapper } from '../../../../kibana_utils/public'; -const startMock = coreMock.createStart(); - -describe('AutocompleteFtuePopover', () => { - function wrapInContext(props: { - isVisible?: boolean; - storage: IStorageWrapper; - children: ReactElement; - }) { - const services = { docLinks: startMock.docLinks }; - return ( - - - - ); - } - - const createMockStorage = () => ({ - get: jest.fn(), - set: jest.fn(), - remove: jest.fn(), - clear: jest.fn(), - }); - - it('should hide popover if local storage flag is set', () => { - const children = ; - const storage = createMockStorage(); - storage.get.mockReturnValue(true); - const instance = mount(wrapInContext({ storage, children })); - expect(instance.find(EuiTourStep).prop('isStepOpen')).toBe(false); - }); - - it('should render popover if local storage flag is not set', () => { - const children = ; - const instance = mount( - wrapInContext({ - storage: createMockStorage(), - isVisible: true, - children, - }) - ); - expect(instance.find(EuiTourStep).prop('isStepOpen')).toBe(true); - }); - - it('should hide popover if it is closed', async () => { - const props = { - children: , - showAutocompleteFtuePopover: true, - storage: createMockStorage(), - }; - const instance = mount(wrapInContext(props)); - act(() => { - instance.find(EuiTourStep).prop('closePopover')!(); - }); - expect(instance.find(EuiTourStep).prop('isStepOpen')).toBe(false); - }); - - it('should set local storage flag and hide on closing with button', () => { - const props = { - children: , - showAutocompleteFtuePopover: true, - storage: createMockStorage(), - }; - const instance = mount(wrapInContext(props)); - act(() => { - instance.find(EuiTourStep).prop('footerAction')!.props.onClick(); - }); - expect(props.storage.set).toHaveBeenCalledWith(expect.any(String), true); - expect(instance.find(EuiTourStep).prop('isStepOpen')).toBe(false); - }); -}); diff --git a/src/plugins/data/public/ui/query_string_input/autocomplete_ftue_popover.tsx b/src/plugins/data/public/ui/query_string_input/autocomplete_ftue_popover.tsx deleted file mode 100644 index 8f42e9f715369..0000000000000 --- a/src/plugins/data/public/ui/query_string_input/autocomplete_ftue_popover.tsx +++ /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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { ReactElement, useEffect, useState } from 'react'; -import React from 'react'; -import { EuiButtonEmpty, EuiLink, EuiText, EuiTourStep } from '@elastic/eui'; -import { IStorageWrapper } from 'src/plugins/kibana_utils/public'; -import { i18n } from '@kbn/i18n'; -import { FormattedMessage } from '@kbn/i18n/react'; -import { useKibana } from '../../../../kibana_react/public'; - -const AUTOCOMPLETE_FTUE_POPOVER_STORAGE_KEY = 'data.autocompleteFtuePopover'; - -export function AutocompleteFtuePopover({ - isVisible, - storage, - children, -}: { - isVisible?: boolean; - storage: IStorageWrapper; - children: ReactElement; -}) { - const kibana = useKibana(); - const autocompleteChangesLink = kibana.services.docLinks!.links.query.autocompleteChanges; - - const [autocompleteFtuePopoverDismissed, setAutocompleteFtuePopoverDismissed] = useState(() => - Boolean(storage.get(AUTOCOMPLETE_FTUE_POPOVER_STORAGE_KEY)) - ); - const [autocompleteFtuePopoverVisible, setAutocompleteFtuePopoverVisible] = useState(false); - - useEffect(() => { - if (!autocompleteFtuePopoverDismissed && isVisible) { - setAutocompleteFtuePopoverVisible(true); - } - }, [autocompleteFtuePopoverDismissed, isVisible]); - - return ( - {}} - closePopover={() => { - setAutocompleteFtuePopoverVisible(false); - setAutocompleteFtuePopoverDismissed(true); - }} - content={ - - - {i18n.translate('data.autocompleteFtuePopover.learnMoreLink', { - defaultMessage: 'Learn more.', - })} - - ), - }} - /> - - } - minWidth={300} - anchorPosition="downCenter" - zIndex={4002} - anchorClassName="eui-displayBlock" - step={1} - stepsTotal={1} - isStepOpen={autocompleteFtuePopoverVisible} - subtitle={''} - title={i18n.translate('data.autocompleteFtuePopover.title', { - defaultMessage: 'Autocomplete is now faster!', - })} - footerAction={ - { - storage.set(AUTOCOMPLETE_FTUE_POPOVER_STORAGE_KEY, true); - setAutocompleteFtuePopoverDismissed(true); - setAutocompleteFtuePopoverVisible(false); - }} - > - {i18n.translate('data.autocompleteFtuePopover.dismissAction', { - defaultMessage: "Don't show again", - })} - - } - > -
{ - setAutocompleteFtuePopoverVisible(false); - }} - > - {children} -
-
- ); -} diff --git a/src/plugins/data/public/ui/query_string_input/query_bar_top_row.tsx b/src/plugins/data/public/ui/query_string_input/query_bar_top_row.tsx index 90db5abe418b7..a78055f0d61a1 100644 --- a/src/plugins/data/public/ui/query_string_input/query_bar_top_row.tsx +++ b/src/plugins/data/public/ui/query_string_input/query_bar_top_row.tsx @@ -26,7 +26,6 @@ import QueryStringInputUI from './query_string_input'; import { UI_SETTINGS } from '../../../common'; import { PersistedLog, getQueryLog } from '../../query'; import { NoDataPopover } from './no_data_popover'; -import { AutocompleteFtuePopover } from './autocomplete_ftue_popover'; const QueryStringInput = withKibana(QueryStringInputUI); @@ -174,26 +173,24 @@ export default function QueryBarTopRow(props: QueryBarTopRowProps) { return ( - - - + ); } diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index a4ec0285361e4..64e03b9f1efee 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -1569,10 +1569,6 @@ "data.advancedSettings.timepicker.today": "今日", "data.aggTypes.buckets.ranges.rangesFormatMessage": "{gte} {from} と {lt} {to}", "data.aggTypes.buckets.ranges.rangesFormatMessageArrowRight": "{from} → {to}", - "data.autocompleteFtuePopover.content": "パフォーマンス改善のため、自動入力の動作方法が変更されました。{learnMoreLink}", - "data.autocompleteFtuePopover.dismissAction": "今後表示しない", - "data.autocompleteFtuePopover.learnMoreLink": "詳細情報", - "data.autocompleteFtuePopover.title": "自動入力が高速になりました。", "data.errors.fetchError": "ネットワークとプロキシ構成を確認してください。問題が解決しない場合は、ネットワーク管理者に問い合わせてください。", "data.filter.applyFilterActionTitle": "現在のビューにフィルターを適用", "data.filter.applyFilters.popupHeader": "適用するフィルターの選択", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 4dc213d5897d8..626eca1befeea 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -1585,10 +1585,6 @@ "data.advancedSettings.timepicker.today": "今日", "data.aggTypes.buckets.ranges.rangesFormatMessage": "{gte} {from} 且 {lt} {to}", "data.aggTypes.buckets.ranges.rangesFormatMessageArrowRight": "{from} → {to}", - "data.autocompleteFtuePopover.content": "我们已更改自动完成的工作原理,以改善性能。{learnMoreLink}", - "data.autocompleteFtuePopover.dismissAction": "不再显示", - "data.autocompleteFtuePopover.learnMoreLink": "了解详情。", - "data.autocompleteFtuePopover.title": "现在自动完成会更快!", "data.errors.fetchError": "请检查您的网络和代理配置。如果问题持续存在,请联系网络管理员。", "data.filter.applyFilterActionTitle": "将筛选应用于当前视图", "data.filter.applyFilters.popupHeader": "选择要应用的筛选", From 5f31aa18a0215a1ec71327955f6e856f01a82184 Mon Sep 17 00:00:00 2001 From: Adam Locke Date: Tue, 16 Nov 2021 10:47:24 -0500 Subject: [PATCH 028/148] [DOCS] Indicate that security is enabled (#118620) Removes the statement "When security is enabled" -- security is always enabled on Cloud, so this statement is unnecessary. --- docs/getting-started/quick-start-guide.asciidoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/getting-started/quick-start-guide.asciidoc b/docs/getting-started/quick-start-guide.asciidoc index 2bddd9bf61452..03e40c7cc6cef 100644 --- a/docs/getting-started/quick-start-guide.asciidoc +++ b/docs/getting-started/quick-start-guide.asciidoc @@ -11,7 +11,7 @@ When you've finished, you'll know how to: [float] === Required privileges -When security is enabled, you must have `read`, `write`, and `manage` privileges on the `kibana_sample_data_*` indices. +You must have `read`, `write`, and `manage` privileges on the `kibana_sample_data_*` indices. Learn how to <>, or refer to {ref}/security-privileges.html[Security privileges] for more information. [float] @@ -144,4 +144,4 @@ image::images/dashboard_sampleDataAddFilter_7.15.0.png[The [eCommerce] Revenue D *Create a dashboard with your own data.* Ready to learn more about analyzing your data in *Dashboard*? Go to <>. -*Try out the {ml-features}.* Ready to analyze the sample data sets and generate models for its patterns of behavior? Go to {ml-docs}/ml-getting-started.html[Getting started with {ml}]. \ No newline at end of file +*Try out the {ml-features}.* Ready to analyze the sample data sets and generate models for its patterns of behavior? Go to {ml-docs}/ml-getting-started.html[Getting started with {ml}]. From d6e5853887c18913d3acd482b7e2c007b7904d7c Mon Sep 17 00:00:00 2001 From: Nicolas Chaulet Date: Tue, 16 Nov 2021 11:11:53 -0500 Subject: [PATCH 029/148] [Fleet] Output API endpoints (#118589) --- .../plugins/fleet/common/constants/routes.ts | 2 + .../openapi/components/schemas/output.yaml | 2 + .../fleet/common/openapi/paths/outputs.yaml | 43 ++++ .../openapi/paths/outputs@{output_id}.yaml | 35 ++- .../fleet/common/types/rest_spec/output.ts | 4 + x-pack/plugins/fleet/server/errors/index.ts | 2 + .../fleet/server/routes/output/handler.ts | 55 ++++- .../fleet/server/routes/output/index.ts | 30 ++- .../plugins/fleet/server/services/output.ts | 14 +- .../fleet/server/types/rest_spec/output.ts | 23 +- .../apis/outputs/crud.ts | 212 ++++++++++++++++-- 11 files changed, 393 insertions(+), 29 deletions(-) diff --git a/x-pack/plugins/fleet/common/constants/routes.ts b/x-pack/plugins/fleet/common/constants/routes.ts index be4103c549f1a..235a1c5bd85e5 100644 --- a/x-pack/plugins/fleet/common/constants/routes.ts +++ b/x-pack/plugins/fleet/common/constants/routes.ts @@ -65,6 +65,8 @@ export const OUTPUT_API_ROUTES = { LIST_PATTERN: `${API_ROOT}/outputs`, INFO_PATTERN: `${API_ROOT}/outputs/{outputId}`, UPDATE_PATTERN: `${API_ROOT}/outputs/{outputId}`, + DELETE_PATTERN: `${API_ROOT}/outputs/{outputId}`, + CREATE_PATTERN: `${API_ROOT}/outputs`, }; // Settings API routes diff --git a/x-pack/plugins/fleet/common/openapi/components/schemas/output.yaml b/x-pack/plugins/fleet/common/openapi/components/schemas/output.yaml index b4e060ca0c151..e695f0048e6ad 100644 --- a/x-pack/plugins/fleet/common/openapi/components/schemas/output.yaml +++ b/x-pack/plugins/fleet/common/openapi/components/schemas/output.yaml @@ -5,6 +5,8 @@ properties: type: string is_default: type: boolean + is_default_monitoring: + type: boolean name: type: string type: diff --git a/x-pack/plugins/fleet/common/openapi/paths/outputs.yaml b/x-pack/plugins/fleet/common/openapi/paths/outputs.yaml index 94fe7c16e520d..6425149bd81f1 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/outputs.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/outputs.yaml @@ -20,3 +20,46 @@ get: perPage: type: integer operationId: get-outputs +post: + summary: Outputs + description: 'Create a new output' + tags: [] + responses: + '200': + description: OK + content: + application/json: + schema: + type: object + properties: + item: + $ref: ../components/schemas/output.yaml + requestBody: + content: + application/json: + schema: + type: object + properties: + id: + type: string + name: + type: string + type: + type: string + enum: ["elasticsearch"] + is_default: + type: boolean + is_default_monitoring: + type: boolean + hosts: + type: array + items: + type: string + ca_sha256: + type: string + config_yaml: + type: string + required: + - name + - type + operationId: post-outputs diff --git a/x-pack/plugins/fleet/common/openapi/paths/outputs@{output_id}.yaml b/x-pack/plugins/fleet/common/openapi/paths/outputs@{output_id}.yaml index 2f8f5e76ebaff..326a65692a03b 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/outputs@{output_id}.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/outputs@{output_id}.yaml @@ -20,6 +20,23 @@ parameters: name: outputId in: path required: true +delete: + summary: Output - Delete + operationId: delete-output + responses: + '200': + description: OK + content: + application/json: + schema: + type: object + properties: + id: + type: string + required: + - id + parameters: + - $ref: ../components/headers/kbn_xsrf.yaml put: summary: Output - Update operationId: update-output @@ -29,14 +46,26 @@ put: schema: type: object properties: - hosts: + name: + type: string + type: type: string + enum: ["elasticsearch"] + is_default: + type: boolean + is_default_monitoring: + type: boolean + hosts: + type: array + items: + type: string ca_sha256: type: string - config: - type: object config_yaml: type: string + required: + - name + - type responses: '200': description: OK diff --git a/x-pack/plugins/fleet/common/types/rest_spec/output.ts b/x-pack/plugins/fleet/common/types/rest_spec/output.ts index ef3c2f9f998ca..f8eb20b51f208 100644 --- a/x-pack/plugins/fleet/common/types/rest_spec/output.ts +++ b/x-pack/plugins/fleet/common/types/rest_spec/output.ts @@ -11,6 +11,10 @@ export interface GetOneOutputResponse { item: Output; } +export interface DeleteOutputResponse { + id: string; +} + export interface GetOneOutputRequest { params: { outputId: string; diff --git a/x-pack/plugins/fleet/server/errors/index.ts b/x-pack/plugins/fleet/server/errors/index.ts index 6075b7e441fdf..b2039dad4d57c 100644 --- a/x-pack/plugins/fleet/server/errors/index.ts +++ b/x-pack/plugins/fleet/server/errors/index.ts @@ -53,6 +53,8 @@ export class HostedAgentPolicyRestrictionRelatedError extends IngestManagerError export class FleetSetupError extends IngestManagerError {} export class GenerateServiceTokenError extends IngestManagerError {} +export class OutputUnauthorizedError extends IngestManagerError {} + export class ArtifactsClientError extends IngestManagerError {} export class ArtifactsClientAccessDeniedError extends IngestManagerError { constructor(deniedPackageName: string, allowedPackageName: string) { diff --git a/x-pack/plugins/fleet/server/routes/output/handler.ts b/x-pack/plugins/fleet/server/routes/output/handler.ts index 0c56d55423e4b..98b42775ae223 100644 --- a/x-pack/plugins/fleet/server/routes/output/handler.ts +++ b/x-pack/plugins/fleet/server/routes/output/handler.ts @@ -8,8 +8,17 @@ import type { RequestHandler } from 'src/core/server'; import type { TypeOf } from '@kbn/config-schema'; -import type { GetOneOutputRequestSchema, PutOutputRequestSchema } from '../../types'; -import type { GetOneOutputResponse, GetOutputsResponse } from '../../../common'; +import type { + DeleteOutputRequestSchema, + GetOneOutputRequestSchema, + PostOutputRequestSchema, + PutOutputRequestSchema, +} from '../../types'; +import type { + DeleteOutputResponse, + GetOneOutputResponse, + GetOutputsResponse, +} from '../../../common'; import { outputService } from '../../services/output'; import { defaultIngestErrorHandler } from '../../errors'; @@ -78,3 +87,45 @@ export const putOuputHandler: RequestHandler< return defaultIngestErrorHandler({ error, response }); } }; + +export const postOuputHandler: RequestHandler< + undefined, + undefined, + TypeOf +> = async (context, request, response) => { + const soClient = context.core.savedObjects.client; + try { + const { id, ...data } = request.body; + const output = await outputService.create(soClient, data, { id }); + + const body: GetOneOutputResponse = { + item: output, + }; + + return response.ok({ body }); + } catch (error) { + return defaultIngestErrorHandler({ error, response }); + } +}; + +export const deleteOutputHandler: RequestHandler> = + async (context, request, response) => { + const soClient = context.core.savedObjects.client; + try { + await outputService.delete(soClient, request.params.outputId); + + const body: DeleteOutputResponse = { + id: request.params.outputId, + }; + + return response.ok({ body }); + } catch (error) { + if (error.isBoom && error.output.statusCode === 404) { + return response.notFound({ + body: { message: `Output ${request.params.outputId} not found` }, + }); + } + + return defaultIngestErrorHandler({ error, response }); + } + }; diff --git a/x-pack/plugins/fleet/server/routes/output/index.ts b/x-pack/plugins/fleet/server/routes/output/index.ts index 5bdbfc7387414..9ef8bab6ea408 100644 --- a/x-pack/plugins/fleet/server/routes/output/index.ts +++ b/x-pack/plugins/fleet/server/routes/output/index.ts @@ -9,12 +9,20 @@ import type { IRouter } from 'src/core/server'; import { PLUGIN_ID, OUTPUT_API_ROUTES } from '../../constants'; import { + DeleteOutputRequestSchema, GetOneOutputRequestSchema, GetOutputsRequestSchema, + PostOutputRequestSchema, PutOutputRequestSchema, } from '../../types'; -import { getOneOuputHandler, getOutputsHandler, putOuputHandler } from './handler'; +import { + deleteOutputHandler, + getOneOuputHandler, + getOutputsHandler, + postOuputHandler, + putOuputHandler, +} from './handler'; export const registerRoutes = (router: IRouter) => { router.get( @@ -37,8 +45,26 @@ export const registerRoutes = (router: IRouter) => { { path: OUTPUT_API_ROUTES.UPDATE_PATTERN, validate: PutOutputRequestSchema, - options: { tags: [`access:${PLUGIN_ID}-read`] }, + options: { tags: [`access:${PLUGIN_ID}-all`] }, }, putOuputHandler ); + + router.post( + { + path: OUTPUT_API_ROUTES.CREATE_PATTERN, + validate: PostOutputRequestSchema, + options: { tags: [`access:${PLUGIN_ID}-all`] }, + }, + postOuputHandler + ); + + router.delete( + { + path: OUTPUT_API_ROUTES.DELETE_PATTERN, + validate: DeleteOutputRequestSchema, + options: { tags: [`access:${PLUGIN_ID}-all`] }, + }, + deleteOutputHandler + ); }; diff --git a/x-pack/plugins/fleet/server/services/output.ts b/x-pack/plugins/fleet/server/services/output.ts index e39f70671a232..0626caa37df9a 100644 --- a/x-pack/plugins/fleet/server/services/output.ts +++ b/x-pack/plugins/fleet/server/services/output.ts @@ -11,6 +11,7 @@ import uuid from 'uuid/v5'; import type { NewOutput, Output, OutputSOAttributes } from '../types'; import { DEFAULT_OUTPUT, OUTPUT_SAVED_OBJECT_TYPE } from '../constants'; import { decodeCloudId, normalizeHostsForAgents, SO_SEARCH_LIMIT } from '../../common'; +import { OutputUnauthorizedError } from '../errors'; import { appContextService } from './app_context'; @@ -222,10 +223,19 @@ class OutputService { const originalOutput = await this.get(soClient, id); if (originalOutput.is_preconfigured && !fromPreconfiguration) { - throw new Error( + throw new OutputUnauthorizedError( `Preconfigured output ${id} cannot be deleted outside of kibana config file.` ); } + + if (originalOutput.is_default && !fromPreconfiguration) { + throw new OutputUnauthorizedError(`Default output ${id} cannot be deleted.`); + } + + if (originalOutput.is_default_monitoring && !fromPreconfiguration) { + throw new OutputUnauthorizedError(`Default monitoring output ${id} cannot be deleted.`); + } + return soClient.delete(SAVED_OBJECT_TYPE, outputIdToUuid(id)); } @@ -240,7 +250,7 @@ class OutputService { const originalOutput = await this.get(soClient, id); if (originalOutput.is_preconfigured && !fromPreconfiguration) { - throw new Error( + throw new OutputUnauthorizedError( `Preconfigured output ${id} cannot be updated outside of kibana config file.` ); } diff --git a/x-pack/plugins/fleet/server/types/rest_spec/output.ts b/x-pack/plugins/fleet/server/types/rest_spec/output.ts index 5e6cc37e6d459..05a307009d527 100644 --- a/x-pack/plugins/fleet/server/types/rest_spec/output.ts +++ b/x-pack/plugins/fleet/server/types/rest_spec/output.ts @@ -13,16 +13,37 @@ export const GetOneOutputRequestSchema = { }), }; +export const DeleteOutputRequestSchema = { + params: schema.object({ + outputId: schema.string(), + }), +}; + export const GetOutputsRequestSchema = {}; +export const PostOutputRequestSchema = { + body: schema.object({ + id: schema.maybe(schema.string()), + name: schema.string(), + type: schema.oneOf([schema.literal('elasticsearch')]), + is_default: schema.boolean({ defaultValue: false }), + is_default_monitoring: schema.boolean({ defaultValue: false }), + hosts: schema.maybe(schema.arrayOf(schema.uri({ scheme: ['http', 'https'] }))), + ca_sha256: schema.maybe(schema.string()), + config_yaml: schema.maybe(schema.string()), + }), +}; + export const PutOutputRequestSchema = { params: schema.object({ outputId: schema.string(), }), body: schema.object({ + name: schema.maybe(schema.string()), + is_default: schema.maybe(schema.boolean()), + is_default_monitoring: schema.maybe(schema.boolean()), hosts: schema.maybe(schema.arrayOf(schema.uri({ scheme: ['http', 'https'] }))), ca_sha256: schema.maybe(schema.string()), - config: schema.maybe(schema.recordOf(schema.string(), schema.any())), config_yaml: schema.maybe(schema.string()), }), }; diff --git a/x-pack/test/fleet_api_integration/apis/outputs/crud.ts b/x-pack/test/fleet_api_integration/apis/outputs/crud.ts index 521675b87fb11..86ce4a8fdf617 100644 --- a/x-pack/test/fleet_api_integration/apis/outputs/crud.ts +++ b/x-pack/test/fleet_api_integration/apis/outputs/crud.ts @@ -39,31 +39,205 @@ export default function (providerContext: FtrProviderContext) { await esArchiver.unload('x-pack/test/functional/es_archives/fleet/empty_fleet_server'); }); - it('GET /outputs should list the default output', async () => { - const { body: getOutputsRes } = await supertest.get(`/api/fleet/outputs`).expect(200); + describe('GET /outputs', () => { + it('should list the default output', async () => { + const { body: getOutputsRes } = await supertest.get(`/api/fleet/outputs`).expect(200); + + expect(getOutputsRes.items.length).to.eql(1); + }); + }); + + describe('GET /outputs/{outputId}', () => { + it('should allow return the default output', async () => { + const { body: getOutputRes } = await supertest + .get(`/api/fleet/outputs/${defaultOutputId}`) + .expect(200); + + expect(getOutputRes.item).to.have.keys('id', 'name', 'type', 'is_default', 'hosts'); + }); + }); - expect(getOutputsRes.items.length).to.eql(1); + describe('PUT /outputs/{outputId}', () => { + it('should explicitly set port on ES hosts', async function () { + await supertest + .put(`/api/fleet/outputs/${defaultOutputId}`) + .set('kbn-xsrf', 'xxxx') + .send({ hosts: ['https://test.fr'] }) + .expect(200); + + const { + body: { item: output }, + } = await supertest.get(`/api/fleet/outputs/${defaultOutputId}`).expect(200); + + expect(output.hosts).to.eql(['https://test.fr:443']); + }); + + it('should return a 404 when updating a non existing output', async function () { + await supertest + .put(`/api/fleet/outputs/idonotexists`) + .set('kbn-xsrf', 'xxxx') + .send({ hosts: ['https://test.fr'] }) + .expect(404); + }); }); - it('GET /outputs/{defaultOutputId} should return the default output', async () => { - const { body: getOutputRes } = await supertest - .get(`/api/fleet/outputs/${defaultOutputId}`) - .expect(200); + describe('POST /outputs', () => { + it('should allow to create an output ', async function () { + const { body: postResponse } = await supertest + .post(`/api/fleet/outputs`) + .set('kbn-xsrf', 'xxxx') + .send({ name: 'My output', type: 'elasticsearch', hosts: ['https://test.fr'] }) + .expect(200); + + const { id: _, ...itemWithoutId } = postResponse.item; + expect(itemWithoutId).to.eql({ + name: 'My output', + type: 'elasticsearch', + hosts: ['https://test.fr:443'], + is_default: false, + is_default_monitoring: false, + }); + }); + + it('should toggle default output when creating a new default output ', async function () { + await supertest + .post(`/api/fleet/outputs`) + .set('kbn-xsrf', 'xxxx') + .send({ + name: 'default output 1', + type: 'elasticsearch', + hosts: ['https://test.fr'], + is_default: true, + }) + .expect(200); + + const { + body: { item: output2 }, + } = await supertest + .post(`/api/fleet/outputs`) + .set('kbn-xsrf', 'xxxx') + .send({ + name: 'default output 2', + type: 'elasticsearch', + hosts: ['https://test.fr'], + is_default: true, + }) + .expect(200); - expect(getOutputRes.item).to.have.keys('id', 'name', 'type', 'is_default', 'hosts'); + const { + body: { items: outputs }, + } = await supertest.get(`/api/fleet/outputs`).expect(200); + + const defaultOutputs = outputs.filter((o: any) => o.is_default); + expect(defaultOutputs).to.have.length(1); + expect(defaultOutputs[0].id).eql(output2.id); + }); + + it('should toggle default monitoring output when creating a new default monitoring output ', async function () { + await supertest + .post(`/api/fleet/outputs`) + .set('kbn-xsrf', 'xxxx') + .send({ + name: 'default monitoring output 1', + type: 'elasticsearch', + hosts: ['https://test.fr'], + is_default_monitoring: true, + }) + .expect(200); + + const { + body: { item: output2 }, + } = await supertest + .post(`/api/fleet/outputs`) + .set('kbn-xsrf', 'xxxx') + .send({ + name: 'default monitoring output 2', + type: 'elasticsearch', + hosts: ['https://test.fr'], + is_default_monitoring: true, + }) + .expect(200); + + const { + body: { items: outputs }, + } = await supertest.get(`/api/fleet/outputs`).expect(200); + + const defaultOutputs = outputs.filter((o: any) => o.is_default_monitoring); + expect(defaultOutputs).to.have.length(1); + expect(defaultOutputs[0].id).eql(output2.id); + }); }); - it('PUT /output/{defaultOutputId} should explicitly set port on ES hosts', async function () { - await supertest - .put(`/api/fleet/outputs/${defaultOutputId}`) - .set('kbn-xsrf', 'xxxx') - .send({ hosts: ['https://test.fr'] }) - .expect(200); - - const { body: getSettingsRes } = await supertest - .get(`/api/fleet/outputs/${defaultOutputId}`) - .expect(200); - expect(getSettingsRes.item.hosts).to.eql(['https://test.fr:443']); + describe('DELETE /outputs/{outputId}', () => { + let outputId: string; + let defaultOutputIdToDelete: string; + let defaultMonitoringOutputId: string; + + before(async () => { + const { body: postResponse } = await supertest + .post(`/api/fleet/outputs`) + .set('kbn-xsrf', 'xxxx') + .send({ + name: 'Output to delete test', + type: 'elasticsearch', + hosts: ['https://test.fr'], + }) + .expect(200); + outputId = postResponse.item.id; + + const { body: defaultOutputPostResponse } = await supertest + .post(`/api/fleet/outputs`) + .set('kbn-xsrf', 'xxxx') + .send({ + name: 'Default Output to delete test', + type: 'elasticsearch', + hosts: ['https://test.fr'], + is_default: true, + }) + .expect(200); + defaultOutputIdToDelete = defaultOutputPostResponse.item.id; + const { body: defaultMonitoringOutputPostResponse } = await supertest + .post(`/api/fleet/outputs`) + .set('kbn-xsrf', 'xxxx') + .send({ + name: 'Default Output to delete test', + type: 'elasticsearch', + hosts: ['https://test.fr'], + is_default_monitoring: true, + }) + .expect(200); + defaultMonitoringOutputId = defaultMonitoringOutputPostResponse.item.id; + }); + + it('should return a 400 when deleting a default output ', async function () { + await supertest + .delete(`/api/fleet/outputs/${defaultOutputIdToDelete}`) + .set('kbn-xsrf', 'xxxx') + .expect(400); + }); + + it('should return a 400 when deleting a default output ', async function () { + await supertest + .delete(`/api/fleet/outputs/${defaultMonitoringOutputId}`) + .set('kbn-xsrf', 'xxxx') + .expect(400); + }); + + it('should return a 404 when deleting a non existing output ', async function () { + await supertest + .delete(`/api/fleet/outputs/idonotexists`) + .set('kbn-xsrf', 'xxxx') + .expect(404); + }); + + it('should allow to delete an output ', async function () { + const { body: deleteResponse } = await supertest + .delete(`/api/fleet/outputs/${outputId}`) + .set('kbn-xsrf', 'xxxx') + .expect(200); + + expect(deleteResponse.id).to.eql(outputId); + }); }); }); } From 0ef053240df65257c1680f026f9d52fd38b33e64 Mon Sep 17 00:00:00 2001 From: Tobias Stadler Date: Tue, 16 Nov 2021 17:36:17 +0100 Subject: [PATCH 030/148] [Docs] Use reference to docker image (#114152) * Use reference to docker image * Incorporate review by @jbudz Co-authored-by: Jonathan Budzenski Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Jonathan Budzenski --- docs/setup/docker.asciidoc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/setup/docker.asciidoc b/docs/setup/docker.asciidoc index 01fc6e2e76f92..98155308a41f3 100644 --- a/docs/setup/docker.asciidoc +++ b/docs/setup/docker.asciidoc @@ -97,10 +97,10 @@ services: By default, {kib] auto-generates a keystore file for secure settings at startup. To persist your {kibana-ref}/secure-settings.html[secure settings], use the `kibana-keystore` utility to bind-mount the parent directory of the keystore to the container. For example: -[source,sh] +["source","sh",subs="attributes"] ---- -docker run -it --rm -v full_path_to/config:/usr/share/kibana/config -v full_path_to/data:/usr/share/kibana/data docker.elastic.co/kibana/kibana:7.14.0 bin/kibana-keystore create -docker run -it --rm -v full_path_to/config:/usr/share/kibana/config -v full_path_to/data:/usr/share/kibana/data docker.elastic.co/kibana/kibana:7.14.0 bin/kibana-keystore add test_keystore_setting +docker run -it --rm -v full_path_to/config:/usr/share/kibana/config -v full_path_to/data:/usr/share/kibana/data {docker-image} bin/kibana-keystore create +docker run -it --rm -v full_path_to/config:/usr/share/kibana/config -v full_path_to/data:/usr/share/kibana/data {docker-image} bin/kibana-keystore add test_keystore_setting ---- [float] From f1ea4794e6b0f57199f0af0eb567e9f4530bce97 Mon Sep 17 00:00:00 2001 From: Hannah Mudge Date: Tue, 16 Nov 2021 10:09:02 -0700 Subject: [PATCH 031/148] [Dashboard] Page now resets to zero when rows per page is changed in "Add from Library" panel (#118627) * Page now resets to 0 when rows per page is changed. Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- src/plugins/saved_objects/public/finder/saved_object_finder.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/saved_objects/public/finder/saved_object_finder.tsx b/src/plugins/saved_objects/public/finder/saved_object_finder.tsx index 0a2e4ff78be26..a4c8f1f64276b 100644 --- a/src/plugins/saved_objects/public/finder/saved_object_finder.tsx +++ b/src/plugins/saved_objects/public/finder/saved_object_finder.tsx @@ -512,6 +512,7 @@ class SavedObjectFinderUi extends React.Component< }} onChangeItemsPerPage={(perPage) => { this.setState({ + page: 0, perPage, }); }} From 597e76d68ac85474e45e3011f2ad90b623430b81 Mon Sep 17 00:00:00 2001 From: Nick Partridge Date: Tue, 16 Nov 2021 11:11:31 -0600 Subject: [PATCH 032/148] fix renovate config (#118713) --- renovate.json | 110 ++++++++++++++++++++++++++++++++++++++++++++ renovate.json5 | 122 ------------------------------------------------- 2 files changed, 110 insertions(+), 122 deletions(-) create mode 100644 renovate.json delete mode 100644 renovate.json5 diff --git a/renovate.json b/renovate.json new file mode 100644 index 0000000000000..21df347cf038f --- /dev/null +++ b/renovate.json @@ -0,0 +1,110 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": ["config:base", ":disableDependencyDashboard"], + "ignorePaths": ["**/__fixtures__/**", "**/fixtures/**"], + "enabledManagers": ["npm"], + "baseBranches": ["main", "7.16", "7.15"], + "prConcurrentLimit": 0, + "prHourlyLimit": 0, + "separateMajorMinor": false, + "rangeStrategy": "bump", + "semanticCommits": "disabled", + "vulnerabilityAlerts": { + "enabled": false + }, + "lockFileMaintenance": { + "enabled": false + }, + "packageRules": [ + { + "matchPackagePatterns": [".*"], + "enabled": false + }, + { + "groupName": "@elastic/charts", + "matchPackageNames": ["@elastic/charts"], + "reviewers": ["team:datavis"], + "matchBaseBranches": ["main"], + "labels": ["release_note:skip", "v8.0.0", "v7.16.0", "auto-backport"], + "draftPR": true, + "enabled": true + }, + { + "groupName": "@elastic/elasticsearch", + "matchPackageNames": ["@elastic/elasticsearch"], + "reviewers": ["team:kibana-operations", "team:kibana-core"], + "matchBaseBranches": ["main"], + "labels": ["release_note:skip", "v8.0.0", "Team:Operations", "Team:Core", "backport:skip"], + "enabled": true + }, + { + "groupName": "@elastic/elasticsearch", + "matchPackageNames": ["@elastic/elasticsearch"], + "reviewers": ["team:kibana-operations", "team:kibana-core"], + "matchBaseBranches": ["7.16"], + "labels": ["release_note:skip", "Team:Operations", "Team:Core", "backport:skip"], + "enabled": true + }, + { + "groupName": "@elastic/elasticsearch", + "matchPackageNames": ["@elastic/elasticsearch"], + "reviewers": ["team:kibana-operations", "team:kibana-core"], + "matchBaseBranches": ["7.15"], + "labels": ["release_note:skip", "Team:Operations", "Team:Core", "backport:skip"], + "enabled": true + }, + { + "groupName": "babel", + "matchPackageNames": ["@types/babel__core"], + "matchPackagePatterns": ["^@babel", "^babel-plugin"], + "reviewers": ["team:kibana-operations"], + "matchBaseBranches": ["main"], + "labels": ["Team:Operations", "release_note:skip"], + "enabled": true + }, + { + "groupName": "polyfills", + "matchPackageNames": ["core-js"], + "matchPackagePatterns": ["polyfill"], + "excludePackageNames": ["@loaders.gl/polyfills"], + "reviewers": ["team:kibana-operations"], + "matchBaseBranches": ["main"], + "labels": ["Team:Operations", "release_note:skip"], + "enabled": true + }, + { + "groupName": "vega related modules", + "matchPackageNames": ["vega", "vega-lite", "vega-schema-url-parser", "vega-tooltip"], + "reviewers": ["team:kibana-vis-editors"], + "matchBaseBranches": ["main"], + "labels": ["Feature:Vega", "Team:VisEditors"], + "enabled": true + }, + { + "groupName": "cypress", + "matchPackageNames": ["eslint-plugin-cypress"], + "matchPackagePatterns": ["^cypress"], + "reviewers": ["Team:apm", "Team: SecuritySolution"], + "matchBaseBranches": ["main"], + "labels": ["buildkite-ci", "ci:all-cypress-suites"], + "enabled": true + }, + { + "groupName": "platform security modules", + "matchPackageNames": [ + "broadcast-channel", + "node-forge", + "@types/node-forge", + "require-in-the-middle", + "tough-cookie", + "@types/tough-cookie", + "xml-crypto", + "@types/xml-crypto" + ], + "reviewers": ["team:kibana-security"], + "matchBaseBranches": ["main"], + "labels": ["Team:Security", "release_note:skip", "auto-backport"], + "enabled": true + } + ] +} diff --git a/renovate.json5 b/renovate.json5 deleted file mode 100644 index d979b24f1fe09..0000000000000 --- a/renovate.json5 +++ /dev/null @@ -1,122 +0,0 @@ -{ - extends: [ - 'config:base', - ':disableDependencyDashboard', - ], - ignorePaths: [ - '**/__fixtures__/**', - '**/fixtures/**', - ], - enabledManagers: [ - 'npm', - ], - baseBranches: [ - 'main', - '7.16', - '7.15', - ], - prConcurrentLimit: 0, - prHourlyLimit: 0, - separateMajorMinor: false, - rangeStrategy: 'bump', - semanticCommits: false, - vulnerabilityAlerts: { - enabled: false, - }, - npm: { - lockFileMaintenance: { - enabled: false, - }, - packageRules: [ - { - packagePatterns: [ - '.*', - ], - enabled: false, - }, - { - groupName: '@elastic/charts', - packageNames: ['@elastic/charts'], - reviewers: ['team:datavis'], - matchBaseBranches: ['main'], - labels: ['release_note:skip', 'v8.0.0', 'v7.16.0', 'auto-backport'], - draftPR: true, - enabled: true, - }, - { - groupName: '@elastic/elasticsearch', - packageNames: ['@elastic/elasticsearch'], - reviewers: ['team:kibana-operations', 'team:kibana-core'], - matchBaseBranches: ['main'], - labels: ['release_note:skip', 'v8.0.0', 'Team:Operations', 'Team:Core', 'backport:skip'], - enabled: true, - }, - { - groupName: '@elastic/elasticsearch', - packageNames: ['@elastic/elasticsearch'], - reviewers: ['team:kibana-operations', 'team:kibana-core'], - matchBaseBranches: ['7.16'], - labels: ['release_note:skip', 'Team:Operations', 'Team:Core', 'backport:skip'], - enabled: true, - }, - { - groupName: '@elastic/elasticsearch', - packageNames: ['@elastic/elasticsearch'], - reviewers: ['team:kibana-operations', 'team:kibana-core'], - matchBaseBranches: ['7.15'], - labels: ['release_note:skip', 'Team:Operations', 'Team:Core', 'backport:skip'], - enabled: true, - }, - { - groupName: 'babel', - packageNames: ['@types/babel__core'], - matchPackagePatterns: ["^@babel", "^babel-plugin"], - reviewers: ['team:kibana-operations'], - matchBaseBranches: ['main'], - labels: ['Team:Operations', 'release_note:skip'], - enabled: true, - }, - { - groupName: 'polyfills', - packageNames: ['core-js'], - matchPackagePatterns: ["polyfill"], - excludePackageNames: ['@loaders.gl/polyfills'], - reviewers: ['team:kibana-operations'], - matchBaseBranches: ['main'], - labels: ['Team:Operations', 'release_note:skip'], - enabled: true, - }, - { - groupName: 'vega related modules', - packageNames: ['vega', 'vega-lite', 'vega-schema-url-parser', 'vega-tooltip'], - reviewers: ['team:kibana-vis-editors'], - matchBaseBranches: ['main'], - labels: ['Feature:Vega', 'Team:VisEditors'], - enabled: true, - }, - { - groupName: 'cypress', - packageNames: ['eslint-plugin-cypress'], - matchPackagePatterns: ["^cypress"], - reviewers: ['Team:apm', 'Team: SecuritySolution'], - matchBaseBranches: ['main'], - labels: ['buildkite-ci', 'ci:all-cypress-suites'], - enabled: true, - } - { - groupName: 'platform security modules', - packageNames: [ - 'broadcast-channel', - 'node-forge', '@types/node-forge', - 'require-in-the-middle', - 'tough-cookie', '@types/tough-cookie', - 'xml-crypto', '@types/xml-crypto' - ], - reviewers: ['team:kibana-security'], - matchBaseBranches: ['main'], - labels: ['Team:Security', 'release_note:skip', 'auto-backport'], - enabled: true, - }, - ], - }, -} From c1f6a2cef7f8e892a64efe5a388c28a91e07778c Mon Sep 17 00:00:00 2001 From: Kaarina Tungseth Date: Tue, 16 Nov 2021 11:13:24 -0600 Subject: [PATCH 033/148] [DOCS] Removes images from Canvas (#117935) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- docs/user/canvas.asciidoc | 3 --- 1 file changed, 3 deletions(-) diff --git a/docs/user/canvas.asciidoc b/docs/user/canvas.asciidoc index 1f469b697c218..df95dc06ee0b8 100644 --- a/docs/user/canvas.asciidoc +++ b/docs/user/canvas.asciidoc @@ -112,9 +112,6 @@ Choose the type of element you want to use, then use the preconfigured demo data By default, most of the elements you create use the demo data until you change the data source. The demo data includes a small data set that you can use to experiment with your element. . Click *Add element*, then select the element you want to use. -+ -[role="screenshot"] -image::images/canvas-element-select.gif[Canvas elements] . To connect the element to your data, select *Data*, then select one of the following data sources: From d94b6562c04efaf868bb80eab8c2dd856438c7ba Mon Sep 17 00:00:00 2001 From: Tre Date: Tue, 16 Nov 2021 12:58:51 -0500 Subject: [PATCH 034/148] [QA][refactor] Use ui settings - discover histogram (#114997) * [QA][refactor] Use ui settings - discover histogram Use ui settings instead of setting absolute range for timepicker. Stacked on top of: https://github.com/elastic/kibana/pull/114530 * Use TimeStrings interface. --- .../apps/discover/_discover_histogram.ts | 37 ++++++++++--------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/test/functional/apps/discover/_discover_histogram.ts b/test/functional/apps/discover/_discover_histogram.ts index 36abcd81d53a0..62d6ede323054 100644 --- a/test/functional/apps/discover/_discover_histogram.ts +++ b/test/functional/apps/discover/_discover_histogram.ts @@ -8,6 +8,7 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../ftr_provider_context'; +import { TimeStrings } from '../../page_objects/common_page'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const esArchiver = getService('esArchiver'); @@ -40,10 +41,12 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { 'test/functional/fixtures/es_archiver/long_window_logstash_index_pattern' ); await security.testUser.restoreDefaults(); + await PageObjects.common.unsetTime(); }); - async function prepareTest(fromTime: string, toTime: string, interval?: string) { - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + async function prepareTest(time: TimeStrings, interval?: string) { + await PageObjects.common.setTime(time); + await PageObjects.common.navigateToApp('discover'); await PageObjects.discover.waitUntilSearchingHasFinished(); if (interval) { await PageObjects.discover.setChartInterval(interval); @@ -52,32 +55,32 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { } it('should visualize monthly data with different day intervals', async () => { - const fromTime = 'Nov 1, 2017 @ 00:00:00.000'; - const toTime = 'Mar 21, 2018 @ 00:00:00.000'; - await prepareTest(fromTime, toTime, 'Month'); + const from = 'Nov 1, 2017 @ 00:00:00.000'; + const to = 'Mar 21, 2018 @ 00:00:00.000'; + await prepareTest({ from, to }, 'Month'); const chartCanvasExist = await elasticChart.canvasExists(); expect(chartCanvasExist).to.be(true); }); it('should visualize weekly data with within DST changes', async () => { - const fromTime = 'Mar 1, 2018 @ 00:00:00.000'; - const toTime = 'May 1, 2018 @ 00:00:00.000'; - await prepareTest(fromTime, toTime, 'Week'); + const from = 'Mar 1, 2018 @ 00:00:00.000'; + const to = 'May 1, 2018 @ 00:00:00.000'; + await prepareTest({ from, to }, 'Week'); const chartCanvasExist = await elasticChart.canvasExists(); expect(chartCanvasExist).to.be(true); }); it('should visualize monthly data with different years scaled to 30 days', async () => { - const fromTime = 'Jan 1, 2010 @ 00:00:00.000'; - const toTime = 'Mar 21, 2019 @ 00:00:00.000'; - await prepareTest(fromTime, toTime, 'Day'); + const from = 'Jan 1, 2010 @ 00:00:00.000'; + const to = 'Mar 21, 2019 @ 00:00:00.000'; + await prepareTest({ from, to }, 'Day'); const chartCanvasExist = await elasticChart.canvasExists(); expect(chartCanvasExist).to.be(true); const chartIntervalIconTip = await PageObjects.discover.getChartIntervalWarningIcon(); expect(chartIntervalIconTip).to.be(true); }); it('should allow hide/show histogram, persisted in url state', async () => { - const fromTime = 'Jan 1, 2010 @ 00:00:00.000'; - const toTime = 'Mar 21, 2019 @ 00:00:00.000'; - await prepareTest(fromTime, toTime); + const from = 'Jan 1, 2010 @ 00:00:00.000'; + const to = 'Mar 21, 2019 @ 00:00:00.000'; + await prepareTest({ from, to }); let canvasExists = await elasticChart.canvasExists(); expect(canvasExists).to.be(true); await testSubjects.click('discoverChartOptionsToggle'); @@ -95,10 +98,10 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { expect(canvasExists).to.be(true); }); it('should allow hiding the histogram, persisted in saved search', async () => { - const fromTime = 'Jan 1, 2010 @ 00:00:00.000'; - const toTime = 'Mar 21, 2019 @ 00:00:00.000'; + const from = 'Jan 1, 2010 @ 00:00:00.000'; + const to = 'Mar 21, 2019 @ 00:00:00.000'; const savedSearch = 'persisted hidden histogram'; - await prepareTest(fromTime, toTime); + await prepareTest({ from, to }); await testSubjects.click('discoverChartOptionsToggle'); await testSubjects.click('discoverChartToggle'); let canvasExists = await elasticChart.canvasExists(); From 8c76499c9e2aa99192a30b2237b99aee68a70591 Mon Sep 17 00:00:00 2001 From: Tim Roes Date: Tue, 16 Nov 2021 19:01:18 +0100 Subject: [PATCH 035/148] Fix flaky KQL suggestion tests (#118670) --- test/functional/services/query_bar.ts | 18 +++++++++++++++++- .../apps/discover/value_suggestions.ts | 19 +++++-------------- .../value_suggestions_non_timebased.ts | 9 +-------- 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/test/functional/services/query_bar.ts b/test/functional/services/query_bar.ts index f0728f2b022e3..55a27f0423eed 100644 --- a/test/functional/services/query_bar.ts +++ b/test/functional/services/query_bar.ts @@ -76,8 +76,24 @@ export class QueryBarService extends FtrService { expect((await queryLanguageButton.getVisibleText()).toLowerCase()).to.eql(lang); } - public async getSuggestions() { + /** + * Returns the currently shown suggestions texts of the query bar. Since there is no loading + * indicator to wait for to validate if suggestion loading is done, this method is private + * and should not be used in tests. Instead {@link #expectSuggestions} should be used, which + * properly waits for the expected suggestions. + */ + private async getSuggestions() { const suggestions = await this.testSubjects.findAll('autoCompleteSuggestionText'); return Promise.all(suggestions.map((suggestion) => suggestion.getVisibleText())); } + + public async expectSuggestions({ count, contains }: { count: number; contains?: string }) { + await this.retry.try(async () => { + const suggestions = await this.getSuggestions(); + expect(suggestions.length).to.be(count); + if (contains) { + expect(suggestions).to.contain(contains); + } + }); + } } diff --git a/x-pack/test/functional/apps/discover/value_suggestions.ts b/x-pack/test/functional/apps/discover/value_suggestions.ts index 9a56ee944debb..6cef272279548 100644 --- a/x-pack/test/functional/apps/discover/value_suggestions.ts +++ b/x-pack/test/functional/apps/discover/value_suggestions.ts @@ -5,7 +5,6 @@ * 2.0. */ -import expect from '@kbn/expect'; import { FtrProviderContext } from '../../ftr_provider_context'; import { UI_SETTINGS } from '../../../../../src/plugins/data/common'; @@ -56,16 +55,13 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { ); await queryBar.setQuery('extension.raw : '); - const suggestions = await queryBar.getSuggestions(); - expect(suggestions.length).to.be(0); + await queryBar.expectSuggestions({ count: 0 }); }); it('show up if in range', async () => { await PageObjects.timePicker.setDefaultAbsoluteRange(); await queryBar.setQuery('extension.raw : '); - const suggestions = await queryBar.getSuggestions(); - expect(suggestions.length).to.be(5); - expect(suggestions).to.contain('"jpg"'); + await queryBar.expectSuggestions({ count: 5, contains: '"jpg"' }); }); }); @@ -90,8 +86,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); }); - // FLAKY: https://github.com/elastic/kibana/issues/116892 - describe.skip('useTimeRange disabled', () => { + describe('useTimeRange disabled', () => { before(async () => { await setAutocompleteUseTimeRange(false); }); @@ -117,17 +112,13 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { ); await queryBar.setQuery('extension.raw : '); - const suggestions = await queryBar.getSuggestions(); - expect(suggestions.length).to.be(5); - expect(suggestions).to.contain('"jpg"'); + await queryBar.expectSuggestions({ count: 5, contains: '"jpg"' }); }); it('show up', async () => { await PageObjects.timePicker.setDefaultAbsoluteRange(); await queryBar.setQuery('extension.raw : '); - const suggestions = await queryBar.getSuggestions(); - expect(suggestions.length).to.be(5); - expect(suggestions).to.contain('"jpg"'); + await queryBar.expectSuggestions({ count: 5, contains: '"jpg"' }); }); }); }); diff --git a/x-pack/test/functional/apps/discover/value_suggestions_non_timebased.ts b/x-pack/test/functional/apps/discover/value_suggestions_non_timebased.ts index ecf8fd31ce932..b95cbea20cf82 100644 --- a/x-pack/test/functional/apps/discover/value_suggestions_non_timebased.ts +++ b/x-pack/test/functional/apps/discover/value_suggestions_non_timebased.ts @@ -5,13 +5,11 @@ * 2.0. */ -import expect from '@kbn/expect'; import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const esArchiver = getService('esArchiver'); const queryBar = getService('queryBar'); - const retry = getService('retry'); const PageObjects = getPageObjects(['common', 'settings', 'context', 'header']); describe('value suggestions non time based', function describeIndexTests() { @@ -30,12 +28,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { it('shows all autosuggest options for a filter in discover context app', async () => { await PageObjects.common.navigateToApp('discover'); await queryBar.setQuery('type.keyword : '); - - await retry.try(async () => { - const suggestions = await queryBar.getSuggestions(); - expect(suggestions.length).to.be(1); - expect(suggestions).to.contain('"apache"'); - }); + await queryBar.expectSuggestions({ count: 1, contains: '"apache"' }); }); }); } From 4f958691e1dbcf2fc063ca954c46460c28cf45bd Mon Sep 17 00:00:00 2001 From: ymao1 Date: Tue, 16 Nov 2021 13:04:59 -0500 Subject: [PATCH 036/148] Removing incorrect deprecation message for task manager max workers (#118615) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- x-pack/plugins/task_manager/server/index.test.ts | 2 +- x-pack/plugins/task_manager/server/index.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/task_manager/server/index.test.ts b/x-pack/plugins/task_manager/server/index.test.ts index 6fb512bebbd85..2145c01dfe68f 100644 --- a/x-pack/plugins/task_manager/server/index.test.ts +++ b/x-pack/plugins/task_manager/server/index.test.ts @@ -41,7 +41,7 @@ describe('deprecations', () => { const { messages } = applyTaskManagerDeprecations({ max_workers: 1000 }); expect(messages).toMatchInlineSnapshot(` Array [ - "setting \\"xpack.task_manager.max_workers\\" (1000) greater than 100 is deprecated. Values greater than 100 will not be supported starting in 8.0.", + "setting \\"xpack.task_manager.max_workers\\" (1000) greater than 100 is deprecated.", ] `); }); diff --git a/x-pack/plugins/task_manager/server/index.ts b/x-pack/plugins/task_manager/server/index.ts index 58fba0b6f68c7..0c967e1aa0389 100644 --- a/x-pack/plugins/task_manager/server/index.ts +++ b/x-pack/plugins/task_manager/server/index.ts @@ -65,7 +65,7 @@ export const config: PluginConfigDescriptor = { addDeprecation({ level: 'critical', configPath: `${fromPath}.max_workers`, - message: `setting "${fromPath}.max_workers" (${taskManager?.max_workers}) greater than ${MAX_WORKERS_LIMIT} is deprecated. Values greater than ${MAX_WORKERS_LIMIT} will not be supported starting in 8.0.`, + message: `setting "${fromPath}.max_workers" (${taskManager?.max_workers}) greater than ${MAX_WORKERS_LIMIT} is deprecated.`, correctiveActions: { manualSteps: [ `Maximum allowed value of "${fromPath}.max_workers" is ${MAX_WORKERS_LIMIT}.` + From 61ee7a8c19a4c63a3bb2a92a11f6e314aad4e6f8 Mon Sep 17 00:00:00 2001 From: Kaarina Tungseth Date: Tue, 16 Nov 2021 12:07:25 -0600 Subject: [PATCH 037/148] [DOCS] Adds the 7.16 dashboard docs (#117916) * [DOCS] 7.16 docs * Review comments Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- docs/user/dashboard/dashboard.asciidoc | 22 +++++++++++++++---- .../make-dashboards-interactive.asciidoc | 16 +++++++++----- 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/docs/user/dashboard/dashboard.asciidoc b/docs/user/dashboard/dashboard.asciidoc index 474b45f4989fb..364a7d9e53ddd 100644 --- a/docs/user/dashboard/dashboard.asciidoc +++ b/docs/user/dashboard/dashboard.asciidoc @@ -361,17 +361,31 @@ To exit *Edit* mode, click *Switch to view mode*. [float] [[download-csv]] -== Download panel data +== View the panel data and requests -Download panel data in a CSV file. When you download visualization panels with multiple layers, each layer produces a CSV file, and the file names contain the visualization and layer index names. +View the data in visualizations and the requests that collect the data. -. Open the panel menu, then select *Inspect*. +. Open the panel menu, then click *More > Inspect*. -. Click *Download CSV*, then select the format type from the dropdown: +. View and download the panel data. + +.. Open the *View* dropdown, then click *Data*. + +.. Click *Download CSV*, then select the format type from the dropdown: * *Formatted CSV* — Contains human-readable dates and numbers. * *Unformatted* — Best used for computer use. ++ +When you download visualization panels with multiple layers, each layer produces a CSV file, and the file names contain the visualization and layer {data-source} names. + +. View the requests that collect the data. + +.. Open the *View* dropdown, then click *Requests*. + +.. From the dropdown, select the requests you want to view. + +.. To view the requests in *Console*, click *Request*, then click *Open in Console*. [float] [[share-the-dashboard]] diff --git a/docs/user/dashboard/make-dashboards-interactive.asciidoc b/docs/user/dashboard/make-dashboards-interactive.asciidoc index 6e09fd34f508e..54a723f63e253 100644 --- a/docs/user/dashboard/make-dashboards-interactive.asciidoc +++ b/docs/user/dashboard/make-dashboards-interactive.asciidoc @@ -94,20 +94,26 @@ To save the panel to the dashboard: [[explore-the-underlying-documents]] === Open panel data in Discover -You can add interactions to panels that allow you to open *Discover* and explore the panel data. To use the *Discover* interactions, the panel must use only one index pattern, and you must enable <> and <> in kibana.yml. +You can add interactions to panels that allow you to open and explore the data in *Discover*. To use the interactions, the panel must use only one {data-view}. -If you are using 7.13.0 and earlier, panel interactions are enabled by default. +There are three types of *Discover* interactions you can add to dashboards: -There are two types of *Discover* interactions that you can add to dashboards: - -* *Panel interactions* — Opens the panel data in *Discover*, including the dashboard-level filters, but not the panel-level filters. +* *Panel interactions* — Opens panel data in *Discover*, including the dashboard-level filters, but not the panel-level filters. ++ +To enable panel interactions, configure <> in kibana.yml. If you are using 7.13.0 and earlier, panel interactions are enabled by default. + To use panel interactions, open the panel menu, then click *Explore underlying data*. * *Series data interactions* — Opens the series data in *Discover*. + +To enable series data interactions, configure <> in kibana.yml. If you are using 7.13.0 and earlier, data series interactions are enabled by default. ++ To use series data interactions, click a data series in the panel. +* *Saved search interactions* — Opens <> data in *Discover*. ++ +To use saved search interactions, open the panel menu, then click *More > View saved search*. + [float] [[create-drilldowns]] === Create drilldowns From 33c1313daf257eea32d686bb0900041f0a38281e Mon Sep 17 00:00:00 2001 From: Kaarina Tungseth Date: Tue, 16 Nov 2021 12:08:10 -0600 Subject: [PATCH 038/148] [DOCS] Adds the 7.16 TSVB docs (#117931) * [DOCS] Adds the 7.16 TSVB docs * Fixes broken link * Update docs/user/dashboard/tsvb.asciidoc Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> * Update docs/user/dashboard/tsvb.asciidoc Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> * Review comments Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- docs/index.asciidoc | 1 + docs/user/dashboard/tsvb.asciidoc | 104 ++++++++++++------------------ 2 files changed, 42 insertions(+), 63 deletions(-) diff --git a/docs/index.asciidoc b/docs/index.asciidoc index f9ed2abc4b8cf..ec1a99fa5bffc 100644 --- a/docs/index.asciidoc +++ b/docs/index.asciidoc @@ -13,6 +13,7 @@ include::{docs-root}/shared/versions/stack/{source_branch}.asciidoc[] :es-docker-image: {es-docker-repo}:{version} :blob: {kib-repo}blob/{branch}/ :security-ref: https://www.elastic.co/community/security/ +:Data-source: Data view :data-source: data view :data-sources: data views :a-data-source: a data view diff --git a/docs/user/dashboard/tsvb.asciidoc b/docs/user/dashboard/tsvb.asciidoc index c944ec2c9e083..7efd8425e5611 100644 --- a/docs/user/dashboard/tsvb.asciidoc +++ b/docs/user/dashboard/tsvb.asciidoc @@ -15,33 +15,11 @@ With *TSVB*, you can: [role="screenshot"] image::images/tsvb-screenshot.png[TSVB overview] -[float] -[[tsvb-required-choices]] -==== Open and set up TSVB - -Open *TSVB*, then configure the required settings. - -. On the dashboard, click *All types*, then select *TSVB*. - -. In *TSVB*, click *Panel options*, then specify the required *Data* settings. - -.. From the *Index pattern* dropdown, select the index pattern you want to visualize. -+ -To visualize the data in an {es} index, open the *Index pattern selection mode* menu, deselect *Use only {kib} index patterns*, then enter the {es} index. - -.. From the *Time field* dropdown, select the field you want to visualize, then enter the field *Interval*. - -.. Select a *Drop last bucket* option. -+ -By default, *TSVB* drops the last bucket because the time filter intersects the time range of the last bucket. To view the partial data, select *No*. - -.. To view a filtered set of documents, enter <> in the *Panel filter* field. - [float] [[tsvb-index-pattern-mode]] -==== Change the {data-source} mode +==== Open and set up TSVB -You can create *TSVB* visualizations with only {data-sources}, or {es} index strings. +Open *TSVB*, then configure the required settings. You can create *TSVB* visualizations with only {data-sources}, or {es} index strings. When you use only {data-sources}, you are able to: @@ -53,28 +31,56 @@ When you use only {data-sources}, you are able to: * Improve performance -IMPORTANT: Creating *TSVB* visualizations with an {es} index string is deprecated. To use an {es} index string, contact your administrator, or go to <> and set `metrics:allowStringIndices` to `true`. Creating *TSVB* visualizations with an {es} index string will be removed in a future release. -Creating visualizations with only {data-sources} is the default one for new visualizations but it can also be switched for the old implementations: +IMPORTANT: Creating *TSVB* visualizations with an {es} index string is deprecated and will be removed in a fytyre release. By default, you create *TSVB* visualizations with only {data-sources}. To use an {es} index string, contact your administrator, or go to <> and set `metrics:allowStringIndices` to `true`. + +. On the dashboard, click *All types*, then select *TSVB*. -. Click *Panel options*, then open the *Index pattern selection mode* options next to the *Index pattern* dropdown. +. In *TSVB*, click *Panel options*, then specify the *Data* settings. -. Select *Use only Kibana index patterns*. +. Open the *Index pattern selection mode* options next to the *Index pattern* dropdown. -. From the *Index pattern* drodpown, select the index pattern, then select the *Time field*. +. Select *Use only {kib} {data-sources}*. + +. From the *Index pattern* drodpown, select the {data-source}, then select the *Time field* and *Interval*. + +. Select a *Drop last bucket* option. + -image::images/tsvb_index_pattern_selection_mode.png[Change index pattern selection mode action] +By default, *TSVB* drops the last bucket because the time filter intersects the time range of the last bucket. To view the partial data, select *No*. + +. To view a filtered set of documents, enter <> in the *Panel filter* field. [float] -[[configure-the-data-series]] +[[tsvb-function-reference]] ==== Configure the series Each *TSVB* visualization shares the same options to create a *Series*. Each series can be thought of as a separate {es} aggregation. -For each series, the *Options* control the styling and {es} options, and are inherited from *Panel options*. +The *Options* control the styling and {es} options, and are inherited from *Panel options*. When you have separate options for each series, you can compare different {es} indices, and view two time ranges from the same index. To configure the value of each series, select the function, then configure the function inputs. Only the last function is displayed. -. From the *Aggregation* dropdown, select the function for the series. +. From the *Aggregation* dropdown, select the function for the series. *TSVB* provides you with shortcuts for some frequently-used functions: ++ +*Filter Ratio*:: + Returns a percent value by calculating a metric on two sets of documents. + For example, calculate the error rate as a percentage of the overall events over time. ++ +*Counter Rate*:: + Used when dealing with monotonically increasing counters. Shortcut for *Max*, *Derivative*, and *Positive Only*. ++ +*Positive Only*:: + Removes any negative values from the results, which can be used as a post-processing step + after a derivative. ++ +*Series Agg*:: + Applies a function to all of the *Group by* series to reduce the values to a single number. + This function must always be the last metric in the series. + For example, if the *Time Series* visualization shows 10 series, the sum *Series Agg* calculates + the sum of all 10 bars and outputs a single Y value per X value. This is often confused + with the overall sum function, which outputs a single Y value per unique series. ++ +*Math*:: + For each series, apply simple and advanced calculations. Only use *Math* for the last function in a series. . To display each group separately, select one of the following options from the *Group by* dropdown: @@ -82,7 +88,7 @@ To configure the value of each series, select the function, then configure the f * *Terms* — Displays the top values of the field. The color is only configurable in the *Time Series* chart. To configure, click *Options*, then select an option from the *Split color theme* dropdown. -. Click *Options*, then configure the inputs for the function. +. Click *Options*, then configure the inputs for the function. For example, to use a different field format, make a selection from the *Data formatter* dropdown. [float] [[configure-the-visualizations]] @@ -124,37 +130,9 @@ To change this behavior, click *Panel options*, then specify a URL in the *Item The *Markdown* visualization supports Markdown with Handlebar (mustache) syntax to insert dynamic data, and supports custom CSS. -[float] -[[tsvb-function-reference]] -==== TSVB function reference - -*TSVB* provides you with shortcuts for some frequently-used functions. - -*Filter Ratio*:: - Returns a percent value by calculating a metric on two sets of documents. - For example, calculate the error rate as a percentage of the overall events over time. - -*Counter Rate*:: - Used when dealing with monotonically increasing counters. Shortcut for *Max*, *Derivative*, and *Positive Only*. - -*Positive Only*:: - Removes any negative values from the results, which can be used as a post-processing step - after a derivative. - -*Series Agg*:: - Applies a function to all of the *Group by* series to reduce the values to a single number. - This function must always be the last metric in the series. - For example, if the *Time Series* visualization shows 10 series, the sum *Series Agg* calculates - the sum of all 10 bars and output a single Y value per X value. This is often confused - with the overall sum function, which outputs a single Y value per unique series. - -*Math*:: - The math context is able to do simple and advanced calculations per series. - This function must always be the last metric in the series. - [float] [[save-the-tsvb-panel]] -===== Save and add the panel +==== Save and add the panel Save the panel to the *Visualize Library* and add it to the dashboard, or add it to the dashboard without saving. From 3e3e9017f850d8f4f39d44fe733073f2120db022 Mon Sep 17 00:00:00 2001 From: Shahzad Date: Tue, 16 Nov 2021 19:17:21 +0100 Subject: [PATCH 039/148] [Exploratory view] Apply fix deep equality check (#118529) --- .../views/view_actions.test.tsx | 54 +++++++++++++++++++ .../exploratory_view/views/view_actions.tsx | 17 +++++- 2 files changed, 70 insertions(+), 1 deletion(-) 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 index 934d8f7fdbfe7..8f0180c6be4bd 100644 --- 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 @@ -85,4 +85,58 @@ describe('ViewActions', () => { 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).toContain('euiButton-isDisabled'); + + 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 index e85ce8ff40c69..2b9e8a26b0c2a 100644 --- 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 @@ -10,11 +10,23 @@ import { EuiButton, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { isEqual, pickBy } from 'lodash'; import { allSeriesKey, convertAllShortSeries, 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); } @@ -29,7 +41,10 @@ export function ViewActions({ onApply }: Props) { if (noChanges) { noChanges = !allSeries.some( (series, index) => - !isEqual(removeUndefinedProps(series), removeUndefinedProps(urlAllSeries[index])) + !isEqual( + removeUndefinedEmptyValues(series), + removeUndefinedEmptyValues(urlAllSeries[index]) + ) ); } From 16592f94f6ba453c9a7dd802040a1dc195ac3993 Mon Sep 17 00:00:00 2001 From: Vadim Yakhin Date: Tue, 16 Nov 2021 10:26:46 -0800 Subject: [PATCH 040/148] Remove getaslocaldatetimestring (#118105) * Revert "Fix bug where number rendered as date (#116224)" This reverts commit 8c6ef2054f7b3d8dfe4c042789a63badec269fec. * Remove the usage of getAsLocalDateTimeString * Remove test Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../__mocks__/content_sources.mock.ts | 2 +- .../example_result_detail_card.test.tsx | 30 ------------------- .../example_result_detail_card.tsx | 7 +---- .../display_settings/result_detail.test.tsx | 5 +--- 4 files changed, 3 insertions(+), 41 deletions(-) diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/__mocks__/content_sources.mock.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/__mocks__/content_sources.mock.ts index 7222edad56822..48cbf4ba00d87 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/__mocks__/content_sources.mock.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/__mocks__/content_sources.mock.ts @@ -376,7 +376,7 @@ export const exampleResult = { source: 'custom', }, ], - schemaFields: { cats: 'text', dogs: 'text' }, + schemaFields: {}, }; export const mostRecentIndexJob = { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/example_result_detail_card.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/example_result_detail_card.test.tsx index eeb7f6b54f2c0..82a421d85df01 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/example_result_detail_card.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/example_result_detail_card.test.tsx @@ -14,8 +14,6 @@ import React from 'react'; import { shallow } from 'enzyme'; -import { EuiText } from '@elastic/eui'; - import { ExampleResultDetailCard } from './example_result_detail_card'; describe('ExampleResultDetailCard', () => { @@ -38,32 +36,4 @@ describe('ExampleResultDetailCard', () => { expect(wrapper.find('[data-test-subj="DefaultUrlLabel"]')).toHaveLength(1); }); - - it('shows formatted value when date can be parsed', () => { - const date = '2021-06-28'; - setMockValues({ - ...exampleResult, - searchResultConfig: { detailFields: [{ fieldName: 'date', label: 'Date' }] }, - exampleDocuments: [{ date }], - schemaFields: { date: 'date' }, - }); - const wrapper = shallow(); - - expect(wrapper.find(EuiText).children().text()).toContain( - new Date(Date.parse(date)).toLocaleString() - ); - }); - - it('shows non-formatted value when not a date field', () => { - const value = '9999'; - setMockValues({ - ...exampleResult, - searchResultConfig: { detailFields: [{ fieldName: 'value', label: 'Value' }] }, - exampleDocuments: [{ value }], - schemaFields: { value: 'text' }, - }); - const wrapper = shallow(); - - expect(wrapper.find(EuiText).children().text()).toContain(value); - }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/example_result_detail_card.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/example_result_detail_card.tsx index 734e370e4c53d..4abe24c87bfc9 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/example_result_detail_card.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/example_result_detail_card.tsx @@ -12,9 +12,7 @@ import { useValues } from 'kea'; import { EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiText, EuiTitle } from '@elastic/eui'; -import { SchemaType } from '../../../../../shared/schema/types'; import { URL_LABEL } from '../../../../constants'; -import { getAsLocalDateTimeString } from '../../../../utils'; import { CustomSourceIcon } from './custom_source_icon'; import { DisplaySettingsLogic } from './display_settings_logic'; @@ -27,7 +25,6 @@ export const ExampleResultDetailCard: React.FC = () => { titleFieldHover, urlFieldHover, exampleDocuments, - schemaFields, } = useValues(DisplaySettingsLogic); const result = exampleDocuments[0]; @@ -65,8 +62,6 @@ export const ExampleResultDetailCard: React.FC = () => { {detailFields.length > 0 ? ( detailFields.map(({ fieldName, label }, index) => { const value = result[fieldName]; - const fieldType = (schemaFields as { [key: string]: SchemaType })[fieldName]; - const dateValue = fieldType === SchemaType.Date && getAsLocalDateTimeString(value); return (
{

{label}

-
{dateValue || value}
+
{value}
); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/result_detail.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/result_detail.test.tsx index bbc7460ea5258..f400527c6c003 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/result_detail.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/result_detail.test.tsx @@ -47,7 +47,7 @@ import { ExampleResultDetailCard } from './example_result_detail_card'; import { ResultDetail } from './result_detail'; describe('ResultDetail', () => { - const { searchResultConfig, exampleDocuments, schemaFields } = exampleResult; + const { searchResultConfig, exampleDocuments } = exampleResult; const availableFieldOptions = [ { value: 'foo', @@ -70,7 +70,6 @@ describe('ResultDetail', () => { searchResultConfig, availableFieldOptions, exampleDocuments, - schemaFields, }); }); @@ -95,7 +94,6 @@ describe('ResultDetail', () => { }, availableFieldOptions, exampleDocuments, - schemaFields, }); const wrapper = shallow(); @@ -124,7 +122,6 @@ describe('ResultDetail', () => { }, availableFieldOptions, exampleDocuments, - schemaFields, }); const wrapper = mount(); From 130c604c121b13f4a56fae129ee4d9b61e4258a5 Mon Sep 17 00:00:00 2001 From: Oliver Gupte Date: Tue, 16 Nov 2021 13:33:31 -0500 Subject: [PATCH 041/148] [APM] Fixes tutorial links to correct APM integration version (#118732) (#118733) --- x-pack/plugins/apm/public/tutorial/config_agent/index.tsx | 5 +++-- .../public/tutorial/tutorial_fleet_instructions/index.tsx | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/apm/public/tutorial/config_agent/index.tsx b/x-pack/plugins/apm/public/tutorial/config_agent/index.tsx index bce16ae6ef1f9..8e8bf5cf32134 100644 --- a/x-pack/plugins/apm/public/tutorial/config_agent/index.tsx +++ b/x-pack/plugins/apm/public/tutorial/config_agent/index.tsx @@ -9,7 +9,8 @@ import { i18n } from '@kbn/i18n'; import { HttpStart } from 'kibana/public'; import React, { useEffect, useMemo, useState } from 'react'; import styled from 'styled-components'; -import { APIReturnType } from '../..//services/rest/createCallApmApi'; +import { SUPPORTED_APM_PACKAGE_VERSION } from '../../../common/fleet'; +import { APIReturnType } from '../../services/rest/createCallApmApi'; import { getCommands } from './commands/get_commands'; import { getPolicyOptions, PolicyOption } from './get_policy_options'; import { PolicySelector } from './policy_selector'; @@ -65,7 +66,7 @@ function getFleetLink({ } : { label: GET_STARTED_WITH_FLEET_LABEL, - href: `${basePath}/app/integrations#/detail/apm-0.4.0/overview`, + href: `${basePath}/app/integrations#/detail/apm-${SUPPORTED_APM_PACKAGE_VERSION}/overview`, }; } diff --git a/x-pack/plugins/apm/public/tutorial/tutorial_fleet_instructions/index.tsx b/x-pack/plugins/apm/public/tutorial/tutorial_fleet_instructions/index.tsx index 7df52b20376b0..099d737affec7 100644 --- a/x-pack/plugins/apm/public/tutorial/tutorial_fleet_instructions/index.tsx +++ b/x-pack/plugins/apm/public/tutorial/tutorial_fleet_instructions/index.tsx @@ -19,6 +19,7 @@ import { i18n } from '@kbn/i18n'; import { HttpStart } from 'kibana/public'; import React, { useEffect, useState } from 'react'; import styled from 'styled-components'; +import { SUPPORTED_APM_PACKAGE_VERSION } from '../../../common/fleet'; import { APIReturnType } from '../../services/rest/createCallApmApi'; interface Props { @@ -98,7 +99,7 @@ function TutorialFleetInstructions({ http, basePath, isDarkTheme }: Props) { {i18n.translate( 'xpack.apm.tutorial.apmServer.fleet.apmIntegration.button', From 83917e36c2fb39609cb0cc64e18ad14cb8cd3f18 Mon Sep 17 00:00:00 2001 From: Justin Kambic Date: Tue, 16 Nov 2021 13:36:09 -0500 Subject: [PATCH 042/148] [Exploratory View] Disable form row for super select (#118093) * Disable form row for super select. The super select seems not to receive focus when clicking the form row, even when it's enabled. * Improve report selection accessibility. * Implement style change from PR feedback. * Prepend label instead of expanding header size. Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../series_editor/columns/report_type_select.tsx | 8 +++++++- .../series_editor/series_editor.tsx | 15 +++++++++++++-- 2 files changed, 20 insertions(+), 3 deletions(-) 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 index 31a8c7cb7bfae..ddabdf83323cf 100644 --- 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 @@ -35,7 +35,11 @@ export const reportTypesList: Array<{ { reportType: 'device-data-distribution', label: DEVICE_DISTRIBUTION_LABEL }, ]; -export function ReportTypesSelect() { +interface Props { + prepend: string; +} + +export function ReportTypesSelect({ prepend }: Props) { const { setReportType, reportType: selectedReportType, allSeries } = useSeriesStorage(); const onReportTypeChange = (reportType: ReportViewType) => { @@ -52,12 +56,14 @@ export function ReportTypesSelect() { 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/series_editor.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/series_editor.tsx index 4d77c04fc7805..0402dcc4d990a 100644 --- 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 @@ -118,8 +118,12 @@ export const SeriesEditor = React.memo(function () {
- - + + @@ -205,3 +209,10 @@ export const REPORT_TYPE_LABEL = i18n.translate( 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', + } +); From 9aaee3c6de433b5d03ce1f87fe1793beb5d486b3 Mon Sep 17 00:00:00 2001 From: Justin Ibarra Date: Tue, 16 Nov 2021 09:58:55 -0900 Subject: [PATCH 043/148] [Detection Rules] Add 7.16 rules (#118657) --- ...ion_email_powershell_exchange_mailbox.json | 4 +- .../collection_posh_audio_capture.json | 70 ++ ...d_control_remote_file_copy_powershell.json | 4 +- ..._full_network_packet_capture_detected.json | 53 ++ .../credential_access_posh_minidump.json | 81 ++ ...asion_azure_blob_permissions_modified.json | 52 ++ ...e_evasion_clearing_windows_event_logs.json | 4 +- ...ion_defender_exclusion_via_powershell.json | 4 +- ...disabling_windows_defender_powershell.json | 4 +- ...efense_evasion_dns_over_https_enabled.json | 50 ++ ...n_execution_msbuild_started_by_script.json | 4 +- ...nse_evasion_kubernetes_events_deleted.json | 60 ++ ...isc_lolbin_connecting_to_the_internet.json | 4 +- ...picious_process_access_direct_syscall.json | 49 ++ ...evasion_suspicious_zoom_child_process.json | 4 +- ...scovery_posh_suspicious_api_functions.json | 90 ++ .../execution_posh_portable_executable.json | 52 ++ ...tion_scheduled_task_powershell_source.json | 4 +- .../execution_via_compiled_html_file.json | 4 +- .../exfiltration_rds_snapshot_export.json | 4 +- .../exfiltration_rds_snapshot_restored.json | 47 ++ ..._eventbridge_rule_disabled_or_deleted.json | 48 ++ ...mpact_efs_filesystem_or_mount_deleted.json | 55 ++ .../impact_hosts_file_modified.json | 6 +- .../impact_kubernetes_pod_deleted.json | 47 ++ ...mpact_virtual_network_device_modified.json | 47 ++ ...e_shadow_copy_deletion_via_powershell.json | 4 +- .../rules/prepackaged_rules/index.ts | 796 +++++++++--------- ...ious_ms_exchange_worker_child_process.json | 4 +- ...istence_local_scheduled_task_creation.json | 4 +- ...stence_local_scheduled_task_scripting.json | 4 +- ...ll_exch_mailbox_activesync_add_device.json | 4 +- ..._53_hosted_zone_associated_with_a_vpc.json | 54 ++ .../persistence_route_table_created.json | 51 ++ ...ersistence_system_shells_via_services.json | 4 +- .../persistence_webshell_detection.json | 4 +- ...calation_aws_suspicious_saml_activity.json | 76 ++ ...netes_rolebindings_created_or_patched.json | 47 ++ ...ilege_escalation_sts_assumerole_usage.json | 74 ++ .../threat_intel_module_match.json | 6 +- 40 files changed, 1562 insertions(+), 421 deletions(-) create mode 100644 x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_posh_audio_capture.json create mode 100644 x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_azure_full_network_packet_capture_detected.json create mode 100644 x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_posh_minidump.json create mode 100644 x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_azure_blob_permissions_modified.json create mode 100644 x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_dns_over_https_enabled.json create mode 100644 x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_kubernetes_events_deleted.json create mode 100644 x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_suspicious_process_access_direct_syscall.json create mode 100644 x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_posh_suspicious_api_functions.json create mode 100644 x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_posh_portable_executable.json create mode 100644 x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/exfiltration_rds_snapshot_restored.json create mode 100644 x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_aws_eventbridge_rule_disabled_or_deleted.json create mode 100644 x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_efs_filesystem_or_mount_deleted.json create mode 100644 x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_kubernetes_pod_deleted.json create mode 100644 x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_virtual_network_device_modified.json create mode 100644 x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_route_53_hosted_zone_associated_with_a_vpc.json create mode 100644 x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_route_table_created.json create mode 100644 x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_aws_suspicious_saml_activity.json create mode 100644 x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_gcp_kubernetes_rolebindings_created_or_patched.json create mode 100644 x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_sts_assumerole_usage.json diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_email_powershell_exchange_mailbox.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_email_powershell_exchange_mailbox.json index 6e2073bbb82b6..627cbfa777416 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_email_powershell_exchange_mailbox.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_email_powershell_exchange_mailbox.json @@ -15,7 +15,7 @@ "language": "eql", "license": "Elastic License v2", "name": "Exporting Exchange Mailbox via PowerShell", - "query": "process where event.type in (\"start\", \"process_started\") and\n process.name: (\"powershell.exe\", \"pwsh.exe\") and process.args : \"New-MailboxExportRequest*\"\n", + "query": "process where event.type in (\"start\", \"process_started\") and\n process.name: (\"powershell.exe\", \"pwsh.exe\", \"powershell_ise.exe\") and process.args : \"New-MailboxExportRequest*\"\n", "references": [ "https://www.volexity.com/blog/2020/12/14/dark-halo-leverages-solarwinds-compromise-to-breach-organizations/", "https://docs.microsoft.com/en-us/powershell/module/exchange/new-mailboxexportrequest?view=exchange-ps" @@ -61,5 +61,5 @@ ], "timestamp_override": "event.ingested", "type": "eql", - "version": 5 + "version": 6 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_posh_audio_capture.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_posh_audio_capture.json new file mode 100644 index 0000000000000..9aad786eb459f --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_posh_audio_capture.json @@ -0,0 +1,70 @@ +{ + "author": [ + "Elastic" + ], + "description": "Detects PowerShell Scripts that can record audio, a common feature in popular post-exploitation tooling.", + "from": "now-9m", + "index": [ + "winlogbeat-*", + "logs-windows.*" + ], + "language": "kuery", + "license": "Elastic License v2", + "name": "PowerShell Suspicious Script with Audio Capture Capabilities", + "query": "event.code:\"4104\" and \n powershell.file.script_block_text : (\n Get-MicrophoneAudio or (waveInGetNumDevs and mciSendStringA)\n )\n", + "references": [ + "https://github.com/PowerShellMafia/PowerSploit/blob/master/Exfiltration/Get-MicrophoneAudio.ps1" + ], + "risk_score": 47, + "rule_id": "2f2f4939-0b34-40c2-a0a3-844eb7889f43", + "severity": "medium", + "tags": [ + "Elastic", + "Host", + "Windows", + "Threat Detection", + "Collection" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0009", + "name": "Collection", + "reference": "https://attack.mitre.org/tactics/TA0009/" + }, + "technique": [ + { + "id": "T1123", + "name": "Audio Capture", + "reference": "https://attack.mitre.org/techniques/T1123/" + } + ] + }, + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0002", + "name": "Execution", + "reference": "https://attack.mitre.org/tactics/TA0002/" + }, + "technique": [ + { + "id": "T1059", + "name": "Command and Scripting Interpreter", + "reference": "https://attack.mitre.org/techniques/T1059/", + "subtechnique": [ + { + "id": "T1059.001", + "name": "PowerShell", + "reference": "https://attack.mitre.org/techniques/T1059/001/" + } + ] + } + ] + } + ], + "timestamp_override": "event.ingested", + "type": "query", + "version": 1 +} diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_remote_file_copy_powershell.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_remote_file_copy_powershell.json index 45d61878990a3..3ffd0391df866 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_remote_file_copy_powershell.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_remote_file_copy_powershell.json @@ -12,7 +12,7 @@ "language": "eql", "license": "Elastic License v2", "name": "Remote File Download via PowerShell", - "query": "sequence by host.id, process.entity_id with maxspan=30s\n [network where process.name : \"powershell.exe\" and network.protocol == \"dns\" and\n not dns.question.name : (\"localhost\", \"*.microsoft.com\", \"*.azureedge.net\", \"*.powershellgallery.com\", \"*.windowsupdate.com\", \"metadata.google.internal\") and \n not user.domain : \"NT AUTHORITY\"]\n [file where process.name : \"powershell.exe\" and event.type == \"creation\" and file.extension : (\"exe\", \"dll\", \"ps1\", \"bat\") and \n not file.name : \"__PSScriptPolicy*.ps1\"]\n", + "query": "sequence by host.id, process.entity_id with maxspan=30s\n [network where process.name : (\"powershell.exe\", \"pwsh.exe\", \"powershell_ise.exe\") and network.protocol == \"dns\" and\n not dns.question.name : (\"localhost\", \"*.microsoft.com\", \"*.azureedge.net\", \"*.powershellgallery.com\", \"*.windowsupdate.com\", \"metadata.google.internal\") and \n not user.domain : \"NT AUTHORITY\"]\n [file where process.name : \"powershell.exe\" and event.type == \"creation\" and file.extension : (\"exe\", \"dll\", \"ps1\", \"bat\") and \n not file.name : \"__PSScriptPolicy*.ps1\"]\n", "risk_score": 47, "rule_id": "33f306e8-417c-411b-965c-c2812d6d3f4d", "severity": "medium", @@ -63,5 +63,5 @@ } ], "type": "eql", - "version": 2 + "version": 3 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_azure_full_network_packet_capture_detected.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_azure_full_network_packet_capture_detected.json new file mode 100644 index 0000000000000..110345fd316bb --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_azure_full_network_packet_capture_detected.json @@ -0,0 +1,53 @@ +{ + "author": [ + "Austin Songer" + ], + "description": "Identifies potential full network packet capture in Azure. Packet Capture is an Azure Network Watcher feature that can be used to inspect network traffic. This feature can potentially be abused to read sensitive data from unencrypted internal traffic.", + "false_positives": [ + "Full Network Packet Capture may be done by a system or network administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. Full Network Packet Capture from unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." + ], + "from": "now-25m", + "index": [ + "filebeat-*", + "logs-azure*" + ], + "language": "kuery", + "license": "Elastic License v2", + "name": "Azure Full Network Packet Capture Detected", + "note": "## Config\n\nThe Azure Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", + "query": "event.dataset:azure.activitylogs and azure.activitylogs.operation_name:\n (\n \"MICROSOFT.NETWORK/*/STARTPACKETCAPTURE/ACTION\" or\n \"MICROSOFT.NETWORK/*/VPNCONNECTIONS/STARTPACKETCAPTURE/ACTION\" or\n \"MICROSOFT.NETWORK/*/PACKETCAPTURES/WRITE\"\n ) and \nevent.outcome:(Success or success)\n", + "references": [ + "https://docs.microsoft.com/en-us/azure/role-based-access-control/resource-provider-operations" + ], + "risk_score": 47, + "rule_id": "3ad77ed4-4dcf-4c51-8bfc-e3f7ce316b2f", + "severity": "medium", + "tags": [ + "Elastic", + "Cloud", + "Azure", + "Continuous Monitoring", + "SecOps", + "Monitoring" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0006", + "name": "Credential Access", + "reference": "https://attack.mitre.org/tactics/TA0006/" + }, + "technique": [ + { + "id": "T1040", + "name": "Network Sniffing", + "reference": "https://attack.mitre.org/techniques/T1040/" + } + ] + } + ], + "timestamp_override": "event.ingested", + "type": "query", + "version": 1 +} diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_posh_minidump.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_posh_minidump.json new file mode 100644 index 0000000000000..f0ef3e493a41b --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_posh_minidump.json @@ -0,0 +1,81 @@ +{ + "author": [ + "Elastic" + ], + "description": "This rule detects PowerShell scripts that have capabilities to dump process memory using WindowsErrorReporting or Dbghelp.dll MiniDumpWriteDump. Attackers can use this tooling to dump LSASS and get access to credentials.", + "false_positives": [ + "Powershell Scripts that use this capability for troubleshooting." + ], + "from": "now-9m", + "index": [ + "winlogbeat-*", + "logs-windows.*" + ], + "language": "kuery", + "license": "Elastic License v2", + "name": "PowerShell MiniDump Script", + "query": "event.code:\"4104\" and powershell.file.script_block_text:(MiniDumpWriteDump or MiniDumpWithFullMemory or pmuDetirWpmuDiniM)\n", + "references": [ + "https://github.com/PowerShellMafia/PowerSploit/blob/master/Exfiltration/Out-Minidump.ps1", + "https://github.com/FuzzySecurity/PowerShell-Suite/blob/master/Get-ProcessMiniDump.ps1" + ], + "risk_score": 73, + "rule_id": "577ec21e-56fe-4065-91d8-45eb8224fe77", + "severity": "high", + "tags": [ + "Elastic", + "Host", + "Windows", + "Threat Detection", + "Credential Access" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0006", + "name": "Credential Access", + "reference": "https://attack.mitre.org/tactics/TA0006/" + }, + "technique": [ + { + "id": "T1003", + "name": "OS Credential Dumping", + "reference": "https://attack.mitre.org/techniques/T1003/", + "subtechnique": [ + { + "id": "T1003.001", + "name": "LSASS Memory", + "reference": "https://attack.mitre.org/techniques/T1003/001/" + } + ] + } + ] + }, + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0002", + "name": "Execution", + "reference": "https://attack.mitre.org/tactics/TA0002/" + }, + "technique": [ + { + "id": "T1059", + "name": "Command and Scripting Interpreter", + "reference": "https://attack.mitre.org/techniques/T1059/", + "subtechnique": [ + { + "id": "T1059.001", + "name": "PowerShell", + "reference": "https://attack.mitre.org/techniques/T1059/001/" + } + ] + } + ] + } + ], + "timestamp_override": "event.ingested", + "type": "query", + "version": 1 +} diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_azure_blob_permissions_modified.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_azure_blob_permissions_modified.json new file mode 100644 index 0000000000000..2b299df062662 --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_azure_blob_permissions_modified.json @@ -0,0 +1,52 @@ +{ + "author": [ + "Austin Songer" + ], + "description": "Identifies when the Azure role-based access control (Azure RBAC) permissions are modified for an Azure Blob. An adversary may modify the permissions on a blob to weaken their target's security controls or an administrator may inadvertently modify the permissions, which could lead to data exposure or loss.", + "false_positives": [ + "Blob permissions may be modified by system administrators. Verify that the configuration change was expected. Exceptions can be added to this rule to filter expected behavior." + ], + "index": [ + "filebeat-*", + "logs-azure*" + ], + "language": "kuery", + "license": "Elastic License v2", + "name": "Azure Blob Permissions Modification", + "note": "## Config\n\nThe Azure Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", + "query": "event.dataset:azure.activitylogs and azure.activitylogs.operation_name:(\n \"MICROSOFT.STORAGE/STORAGEACCOUNTS/BLOBSERVICES/CONTAINERS/BLOBS/MANAGEOWNERSHIP/ACTION\" or\n \"MICROSOFT.STORAGE/STORAGEACCOUNTS/BLOBSERVICES/CONTAINERS/BLOBS/MODIFYPERMISSIONS/ACTION\") and \n event.outcome:(Success or success)\n", + "references": [ + "https://docs.microsoft.com/en-us/azure/role-based-access-control/built-in-roles" + ], + "risk_score": 47, + "rule_id": "d79c4b2a-6134-4edd-86e6-564a92a933f9", + "severity": "medium", + "tags": [ + "Elastic", + "Cloud", + "Azure", + "Continuous Monitoring", + "SecOps", + "Identity and Access" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0005", + "name": "Defense Evasion", + "reference": "https://attack.mitre.org/tactics/TA0005/" + }, + "technique": [ + { + "id": "T1222", + "name": "File and Directory Permissions Modification", + "reference": "https://attack.mitre.org/techniques/T1222/" + } + ] + } + ], + "timestamp_override": "event.ingested", + "type": "query", + "version": 1 +} diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_clearing_windows_event_logs.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_clearing_windows_event_logs.json index 2759055b0fe5b..43e4ae9182112 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_clearing_windows_event_logs.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_clearing_windows_event_logs.json @@ -12,7 +12,7 @@ "language": "eql", "license": "Elastic License v2", "name": "Clearing Windows Event Logs", - "query": "process where event.type in (\"process_started\", \"start\") and\n (process.name : \"wevtutil.exe\" or process.pe.original_file_name == \"wevtutil.exe\") and\n process.args : (\"/e:false\", \"cl\", \"clear-log\") or\n process.name : \"powershell.exe\" and process.args : \"Clear-EventLog\"\n", + "query": "process where event.type in (\"process_started\", \"start\") and\n (process.name : \"wevtutil.exe\" or process.pe.original_file_name == \"wevtutil.exe\") and\n process.args : (\"/e:false\", \"cl\", \"clear-log\") or\n process.name : (\"powershell.exe\", \"pwsh.exe\", \"powershell_ise.exe\") and process.args : \"Clear-EventLog\"\n", "risk_score": 21, "rule_id": "d331bbe2-6db4-4941-80a5-8270db72eb61", "severity": "low", @@ -49,5 +49,5 @@ ], "timestamp_override": "event.ingested", "type": "eql", - "version": 10 + "version": 11 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_defender_exclusion_via_powershell.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_defender_exclusion_via_powershell.json index 716040d337c10..5e05108d7b85c 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_defender_exclusion_via_powershell.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_defender_exclusion_via_powershell.json @@ -13,7 +13,7 @@ "license": "Elastic License v2", "name": "Windows Defender Exclusions Added via PowerShell", "note": "## Triage and analysis\n\n### Investigating Windows Defender Exclusions\n\nMicrosoft Windows Defender is an anti-virus product built-in within Microsoft Windows. Since this software product is\nused to prevent and stop malware, it's important to monitor what specific exclusions are made to the product's configuration\nsettings. These can often be signs of an adversary or malware trying to bypass Windows Defender's capabilities. One of the more\nnotable [examples](https://www.cyberbit.com/blog/endpoint-security/latest-trickbot-variant-has-new-tricks-up-its-sleeve/) was observed in 2018 where Trickbot incorporated mechanisms to disable Windows Defense to avoid detection.\n\n#### Possible investigation steps:\n- With this specific rule, it's completely possible to trigger detections on network administrative activity or benign users\nusing scripting and PowerShell to configure the different exclusions for Windows Defender. Therefore, it's important to\nidentify the source of the activity first and determine if there is any mal-intent behind the events.\n- The actual exclusion such as the process, the file or directory should be reviewed in order to determine the original\nintent behind the exclusion. Is the excluded file or process malicious in nature or is it related to software that needs\nto be legitimately whitelisted from Windows Defender?\n\n### False Positive Analysis\n- This rule has a higher chance to produce false positives based on the nature around configuring exclusions by possibly\na network administrator. In order to validate the activity further, review the specific exclusion made and determine based\non the exclusion of the original intent behind the exclusion. There are often many legitimate reasons why exclusions are made\nwith Windows Defender so it's important to gain context around the exclusion.\n\n### Related Rules\n- Windows Defender Disabled via Registry Modification\n- Disabling Windows Defender Security Settings via PowerShell\n\n### Response and Remediation\n- Since this is related to post-exploitation activity, immediate response should be taken to review, investigate and\npotentially isolate further activity\n- If further analysis showed malicious intent was behind the Defender exclusions, administrators should remove\nthe exclusion and ensure antimalware capability has not been disabled or deleted\n- Exclusion lists for antimalware capabilities should always be routinely monitored for review\n", - "query": "process where event.type == \"start\" and\n (process.name : (\"powershell.exe\", \"pwsh.exe\") or process.pe.original_file_name : (\"powershell.exe\", \"pwsh.exe\")) and\n process.args : (\"*Add-MpPreference*-Exclusion*\", \"*Set-MpPreference*-Exclusion*\")\n", + "query": "process where event.type == \"start\" and\n (process.name : (\"powershell.exe\", \"pwsh.exe\", \"powershell_ise.exe\") or process.pe.original_file_name in (\"powershell.exe\", \"pwsh.dll\", \"powershell_ise.exe\")) and\n process.args : (\"*Add-MpPreference*-Exclusion*\", \"*Set-MpPreference*-Exclusion*\")\n", "references": [ "https://www.bitdefender.com/files/News/CaseStudies/study/400/Bitdefender-PR-Whitepaper-MosaicLoader-creat5540-en-EN.pdf" ], @@ -80,5 +80,5 @@ ], "timestamp_override": "event.ingested", "type": "eql", - "version": 3 + "version": 4 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_disabling_windows_defender_powershell.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_disabling_windows_defender_powershell.json index 0222561c624a0..b59d6f18370cb 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_disabling_windows_defender_powershell.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_disabling_windows_defender_powershell.json @@ -15,7 +15,7 @@ "language": "eql", "license": "Elastic License v2", "name": "Disabling Windows Defender Security Settings via PowerShell", - "query": "process where event.type == \"start\" and\n (process.name : (\"powershell.exe\", \"pwsh.exe\") or process.pe.original_file_name == \"PowerShell.EXE\") and\n process.args : \"Set-MpPreference\" and process.args : (\"-Disable*\", \"Disabled\", \"NeverSend\", \"-Exclusion*\")\n", + "query": "process where event.type == \"start\" and\n (process.name : (\"powershell.exe\", \"pwsh.exe\", \"powershell_ise.exe\") or process.pe.original_file_name in (\"powershell.exe\", \"pwsh.dll\", \"powershell_ise.exe\")) and\n process.args : \"Set-MpPreference\" and process.args : (\"-Disable*\", \"Disabled\", \"NeverSend\", \"-Exclusion*\")\n", "references": [ "https://docs.microsoft.com/en-us/powershell/module/defender/set-mppreference?view=windowsserver2019-ps" ], @@ -55,5 +55,5 @@ ], "timestamp_override": "event.ingested", "type": "eql", - "version": 1 + "version": 2 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_dns_over_https_enabled.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_dns_over_https_enabled.json new file mode 100644 index 0000000000000..2183daf7dc1f0 --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_dns_over_https_enabled.json @@ -0,0 +1,50 @@ +{ + "author": [ + "Austin Songer" + ], + "description": "Identifies when a user enables DNS-over-HTTPS. This can be used to hide internet activity or be used to hide the process of exfiltrating data. With this enabled organization will lose visibility into data such as query type, response and originating IP that are used to determine bad actors.", + "from": "now-9m", + "index": [ + "winlogbeat-*", + "logs-endpoint.events.*", + "logs-windows.*" + ], + "language": "eql", + "license": "Elastic License v2", + "name": "DNS-over-HTTPS Enabled via Registry", + "query": "registry where event.type in (\"creation\", \"change\") and\n (registry.path : \"*\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Edge\\\\BuiltInDnsClientEnabled\" and\n registry.data.strings : \"1\") or\n (registry.path : \"*\\\\SOFTWARE\\\\Google\\\\Chrome\\\\DnsOverHttpsMode\" and\n registry.data.strings : \"secure\") or\n (registry.path : \"*\\\\SOFTWARE\\\\Policies\\\\Mozilla\\\\Firefox\\\\DNSOverHTTPS\" and\n registry.data.strings : \"1\")\n", + "references": [ + "https://www.tenforums.com/tutorials/151318-how-enable-disable-dns-over-https-doh-microsoft-edge.html", + "https://chromeenterprise.google/policies/?policy=DnsOverHttpsMode" + ], + "risk_score": 21, + "rule_id": "a22a09c2-2162-4df0-a356-9aacbeb56a04", + "severity": "low", + "tags": [ + "Elastic", + "Host", + "Windows", + "Threat Detection", + "Defense Evasion" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0005", + "name": "Defense Evasion", + "reference": "https://attack.mitre.org/tactics/TA0005/" + }, + "technique": [ + { + "id": "T1562", + "name": "Impair Defenses", + "reference": "https://attack.mitre.org/techniques/T1562/" + } + ] + } + ], + "timestamp_override": "event.ingested", + "type": "eql", + "version": 1 +} diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_execution_msbuild_started_by_script.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_execution_msbuild_started_by_script.json index 60b2a8f50c3f4..ab74d4a99f6c5 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_execution_msbuild_started_by_script.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_execution_msbuild_started_by_script.json @@ -15,7 +15,7 @@ "language": "eql", "license": "Elastic License v2", "name": "Microsoft Build Engine Started by a Script Process", - "query": "process where event.type == \"start\" and\n (process.name : \"MSBuild.exe\" or process.pe.original_file_name == \"MSBuild.exe\") and\n process.parent.name : (\"cmd.exe\", \"powershell.exe\", \"cscript.exe\", \"wscript.exe\", \"mshta.exe\")\n", + "query": "process where event.type == \"start\" and\n (process.name : \"MSBuild.exe\" or process.pe.original_file_name == \"MSBuild.exe\") and\n process.parent.name : (\"cmd.exe\", \"powershell.exe\", \"pwsh.exe\", \"powershell_ise.exe\", \"cscript.exe\", \"wscript.exe\", \"mshta.exe\")\n", "risk_score": 21, "rule_id": "9d110cb3-5f4b-4c9a-b9f5-53f0a1707ae2", "severity": "low", @@ -61,5 +61,5 @@ ], "timestamp_override": "event.ingested", "type": "eql", - "version": 9 + "version": 10 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_kubernetes_events_deleted.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_kubernetes_events_deleted.json new file mode 100644 index 0000000000000..f31648a9bd5cc --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_kubernetes_events_deleted.json @@ -0,0 +1,60 @@ +{ + "author": [ + "Austin Songer" + ], + "description": "Identifies when Events are deleted in Azure Kubernetes. Kubernetes events are objects that log any state changes. Example events are a container creation, an image pull, or a pod scheduling on a node. An adversary may delete events in Azure Kubernetes in an attempt to evade detection.", + "false_positives": [ + "Events deletions may be done by a system or network administrator. Verify whether the username, hostname, and/or resource name should be making changes in your environment. Events deletions from unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." + ], + "from": "now-25m", + "index": [ + "filebeat-*", + "logs-azure*" + ], + "language": "kuery", + "license": "Elastic License v2", + "name": "Azure Kubernetes Events Deleted", + "note": "## Config\n\nThe Azure Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", + "query": "event.dataset:azure.activitylogs and azure.activitylogs.operation_name:\"MICROSOFT.KUBERNETES/CONNECTEDCLUSTERS/EVENTS.K8S.IO/EVENTS/DELETE\" and \nevent.outcome:(Success or success)\n", + "references": [ + "https://docs.microsoft.com/en-us/azure/role-based-access-control/resource-provider-operations#microsoftkubernetes" + ], + "risk_score": 47, + "rule_id": "8b64d36a-1307-4b2e-a77b-a0027e4d27c8", + "severity": "medium", + "tags": [ + "Elastic", + "Cloud", + "Azure", + "Continuous Monitoring", + "SecOps", + "Log Auditing" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0005", + "name": "Defense Evasion", + "reference": "https://attack.mitre.org/tactics/TA0005/" + }, + "technique": [ + { + "id": "T1562", + "name": "Impair Defenses", + "reference": "https://attack.mitre.org/techniques/T1562/", + "subtechnique": [ + { + "id": "T1562.001", + "name": "Disable or Modify Tools", + "reference": "https://attack.mitre.org/techniques/T1562/001/" + } + ] + } + ] + } + ], + "timestamp_override": "event.ingested", + "type": "query", + "version": 1 +} diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_misc_lolbin_connecting_to_the_internet.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_misc_lolbin_connecting_to_the_internet.json index 5f45aa836ddf5..9e8519cb576ef 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_misc_lolbin_connecting_to_the_internet.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_misc_lolbin_connecting_to_the_internet.json @@ -12,7 +12,7 @@ "language": "eql", "license": "Elastic License v2", "name": "Network Connection via Signed Binary", - "query": "sequence by process.entity_id\n [process where (process.name : \"expand.exe\" or process.name : \"extrac.exe\" or\n process.name : \"ieexec.exe\" or process.name : \"makecab.exe\") and\n event.type == \"start\"]\n [network where (process.name : \"expand.exe\" or process.name : \"extrac.exe\" or\n process.name : \"ieexec.exe\" or process.name : \"makecab.exe\") and\n not cidrmatch(destination.ip,\n \"10.0.0.0/8\", \"127.0.0.0/8\", \"169.254.0.0/16\", \"172.16.0.0/12\", \"192.0.0.0/24\", \"192.0.0.0/29\", \"192.0.0.8/32\",\n \"192.0.0.9/32\", \"192.0.0.10/32\", \"192.0.0.170/32\", \"192.0.0.171/32\", \"192.0.2.0/24\", \"192.31.196.0/24\",\n \"192.52.193.0/24\", \"192.168.0.0/16\", \"192.88.99.0/24\", \"224.0.0.0/4\", \"100.64.0.0/10\", \"192.175.48.0/24\",\n \"198.18.0.0/15\", \"198.51.100.0/24\", \"203.0.113.0/24\", \"240.0.0.0/4\", \"::1\", \"FE80::/10\", \"FF00::/8\")]\n", + "query": "sequence by process.entity_id\n [process where (process.name : \"expand.exe\" or process.name : \"extrac32.exe\" or\n process.name : \"ieexec.exe\" or process.name : \"makecab.exe\") and\n event.type == \"start\"]\n [network where (process.name : \"expand.exe\" or process.name : \"extrac32.exe\" or\n process.name : \"ieexec.exe\" or process.name : \"makecab.exe\") and\n not cidrmatch(destination.ip,\n \"10.0.0.0/8\", \"127.0.0.0/8\", \"169.254.0.0/16\", \"172.16.0.0/12\", \"192.0.0.0/24\", \"192.0.0.0/29\", \"192.0.0.8/32\",\n \"192.0.0.9/32\", \"192.0.0.10/32\", \"192.0.0.170/32\", \"192.0.0.171/32\", \"192.0.2.0/24\", \"192.31.196.0/24\",\n \"192.52.193.0/24\", \"192.168.0.0/16\", \"192.88.99.0/24\", \"224.0.0.0/4\", \"100.64.0.0/10\", \"192.175.48.0/24\",\n \"198.18.0.0/15\", \"198.51.100.0/24\", \"203.0.113.0/24\", \"240.0.0.0/4\", \"::1\", \"FE80::/10\", \"FF00::/8\")]\n", "references": [ "https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml" ], @@ -53,5 +53,5 @@ } ], "type": "eql", - "version": 8 + "version": 9 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_suspicious_process_access_direct_syscall.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_suspicious_process_access_direct_syscall.json new file mode 100644 index 0000000000000..a3da88721574b --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_suspicious_process_access_direct_syscall.json @@ -0,0 +1,49 @@ +{ + "author": [ + "Elastic" + ], + "description": "Identifies suspicious process access events from unknown memory region. Endpoint security solutions usually hook userland Windows APIs in order to decide if the code that is being executed is malicious or not. It's possible to bypass hooked functions by writing malicious functions that call syscalls directly.", + "from": "now-9m", + "index": [ + "winlogbeat-*", + "logs-windows.*" + ], + "language": "eql", + "license": "Elastic License v2", + "name": "Suspicious Process Access via Direct System Call", + "query": "process where event.code == \"10\" and\n length(winlog.event_data.CallTrace) > 0 and\n \n /* Sysmon CallTrace starting with unknown memory module instead of ntdll which host Windows NT Syscalls */\n not winlog.event_data.CallTrace : (\"?:\\\\WINDOWS\\\\SYSTEM32\\\\ntdll.dll*\", \"?:\\\\WINDOWS\\\\SysWOW64\\\\ntdll.dll*\")\n", + "references": [ + "https://twitter.com/SBousseaden/status/1278013896440324096", + "https://www.ired.team/offensive-security/defense-evasion/using-syscalls-directly-from-visual-studio-to-bypass-avs-edrs" + ], + "risk_score": 73, + "rule_id": "2dd480be-1263-4d9c-8672-172928f6789a", + "severity": "high", + "tags": [ + "Elastic", + "Host", + "Windows", + "Threat Detection", + "Defense Evasion" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0005", + "name": "Defense Evasion", + "reference": "https://attack.mitre.org/tactics/TA0005/" + }, + "technique": [ + { + "id": "T1055", + "name": "Process Injection", + "reference": "https://attack.mitre.org/techniques/T1055/" + } + ] + } + ], + "timestamp_override": "event.ingested", + "type": "eql", + "version": 1 +} diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_suspicious_zoom_child_process.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_suspicious_zoom_child_process.json index 9905feceb6811..b1caf3a677657 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_suspicious_zoom_child_process.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_suspicious_zoom_child_process.json @@ -12,7 +12,7 @@ "language": "eql", "license": "Elastic License v2", "name": "Suspicious Zoom Child Process", - "query": "process where event.type in (\"start\", \"process_started\", \"info\") and\n process.parent.name : \"Zoom.exe\" and process.name : (\"cmd.exe\", \"powershell.exe\", \"pwsh.exe\")\n", + "query": "process where event.type in (\"start\", \"process_started\", \"info\") and\n process.parent.name : \"Zoom.exe\" and process.name : (\"cmd.exe\", \"powershell.exe\", \"pwsh.exe\", \"powershell_ise.exe\")\n", "risk_score": 47, "rule_id": "97aba1ef-6034-4bd3-8c1a-1e0996b27afa", "severity": "medium", @@ -47,5 +47,5 @@ ], "timestamp_override": "event.ingested", "type": "eql", - "version": 4 + "version": 5 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_posh_suspicious_api_functions.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_posh_suspicious_api_functions.json new file mode 100644 index 0000000000000..a1a60acd191b3 --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_posh_suspicious_api_functions.json @@ -0,0 +1,90 @@ +{ + "author": [ + "Elastic" + ], + "description": "This rule detects the use of discovery-related Windows API Functions in Powershell Scripts. Attackers can use these functions to perform various situational awareness related activities, like enumerating users, shares, sessions, domain trusts, groups, etc.,", + "false_positives": [ + "Legitimate Powershell Scripts that make use of these Functions" + ], + "from": "now-9m", + "index": [ + "winlogbeat-*", + "logs-windows.*" + ], + "language": "kuery", + "license": "Elastic License v2", + "name": "PowerShell Suspicious Discovery Related Windows API Functions", + "query": "event.code:\"4104\" and \n powershell.file.script_block_text : (\n NetShareEnum or\n NetWkstaUserEnum or\n NetSessionEnum or\n NetLocalGroupEnum or\n NetLocalGroupGetMembers or\n DsGetSiteName or\n DsEnumerateDomainTrusts or\n WTSEnumerateSessionsEx or\n WTSQuerySessionInformation or\n LsaGetLogonSessionData or\n QueryServiceObjectSecurity\n )\n", + "references": [ + "https://github.com/BC-SECURITY/Empire/blob/9259e5106986847d2bb770c4289c0c0f1adf2344/data/module_source/situational_awareness/network/powerview.ps1#L21413" + ], + "risk_score": 47, + "rule_id": "61ac3638-40a3-44b2-855a-985636ca985e", + "severity": "medium", + "tags": [ + "Elastic", + "Host", + "Windows", + "Threat Detection", + "Discovery" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0007", + "name": "Discovery", + "reference": "https://attack.mitre.org/tactics/TA0007/" + }, + "technique": [ + { + "id": "T1135", + "name": "Network Share Discovery", + "reference": "https://attack.mitre.org/techniques/T1135/" + }, + { + "id": "T1069", + "name": "Permission Groups Discovery", + "reference": "https://attack.mitre.org/techniques/T1069/", + "subtechnique": [ + { + "id": "T1069.001", + "name": "Local Groups", + "reference": "https://attack.mitre.org/techniques/T1069/001/" + } + ] + } + ] + }, + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0002", + "name": "Execution", + "reference": "https://attack.mitre.org/tactics/TA0002/" + }, + "technique": [ + { + "id": "T1059", + "name": "Command and Scripting Interpreter", + "reference": "https://attack.mitre.org/techniques/T1059/", + "subtechnique": [ + { + "id": "T1059.001", + "name": "PowerShell", + "reference": "https://attack.mitre.org/techniques/T1059/001/" + } + ] + }, + { + "id": "T1106", + "name": "Native API", + "reference": "https://attack.mitre.org/techniques/T1106/" + } + ] + } + ], + "timestamp_override": "event.ingested", + "type": "query", + "version": 1 +} diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_posh_portable_executable.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_posh_portable_executable.json new file mode 100644 index 0000000000000..e247f26a8f5a5 --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_posh_portable_executable.json @@ -0,0 +1,52 @@ +{ + "author": [ + "Elastic" + ], + "description": "This rule detects the presence of Portable Executables in a PowerShell Script by Looking for its encoded header. Attackers embed PEs into PowerShell Scripts for Injecting them into the memory, avoiding defenses by not writing to disk.,", + "from": "now-9m", + "index": [ + "winlogbeat-*", + "logs-windows.*" + ], + "language": "kuery", + "license": "Elastic License v2", + "name": "Suspicious Portable Executable Encoded in Powershell Script", + "query": "event.code:\"4104\" and \n powershell.file.script_block_text : (\n TVqQAAMAAAAEAAAA\n )\n", + "risk_score": 47, + "rule_id": "ad84d445-b1ce-4377-82d9-7c633f28bf9a", + "severity": "medium", + "tags": [ + "Elastic", + "Host", + "Windows", + "Threat Detection", + "Execution" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0002", + "name": "Execution", + "reference": "https://attack.mitre.org/tactics/TA0002/" + }, + "technique": [ + { + "id": "T1059", + "name": "Command and Scripting Interpreter", + "reference": "https://attack.mitre.org/techniques/T1059/", + "subtechnique": [ + { + "id": "T1059.001", + "name": "PowerShell", + "reference": "https://attack.mitre.org/techniques/T1059/001/" + } + ] + } + ] + } + ], + "timestamp_override": "event.ingested", + "type": "query", + "version": 1 +} diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_scheduled_task_powershell_source.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_scheduled_task_powershell_source.json index 3814b00321417..84fd67fa7e037 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_scheduled_task_powershell_source.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_scheduled_task_powershell_source.json @@ -15,7 +15,7 @@ "language": "eql", "license": "Elastic License v2", "name": "Outbound Scheduled Task Activity via PowerShell", - "query": "sequence by host.id, process.entity_id with maxspan = 5s\n [library where dll.name : \"taskschd.dll\" and process.name : (\"powershell.exe\", \"pwsh.exe\")]\n [network where process.name : (\"powershell.exe\", \"pwsh.exe\") and destination.port == 135 and not destination.address in (\"127.0.0.1\", \"::1\")]\n", + "query": "sequence by host.id, process.entity_id with maxspan = 5s\n [library where dll.name : \"taskschd.dll\" and process.name : (\"powershell.exe\", \"pwsh.exe\", \"powershell_ise.exe\")]\n [network where process.name : (\"powershell.exe\", \"pwsh.exe\", \"powershell_ise.exe\") and destination.port == 135 and not destination.address in (\"127.0.0.1\", \"::1\")]\n", "references": [ "https://www.volexity.com/blog/2020/12/14/dark-halo-leverages-solarwinds-compromise-to-breach-organizations/" ], @@ -54,5 +54,5 @@ } ], "type": "eql", - "version": 3 + "version": 4 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_via_compiled_html_file.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_via_compiled_html_file.json index 73c796c4e206d..a8d42d4a93b7a 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_via_compiled_html_file.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_via_compiled_html_file.json @@ -15,7 +15,7 @@ "language": "eql", "license": "Elastic License v2", "name": "Process Activity via Compiled HTML File", - "query": "process where event.type in (\"start\", \"process_started\") and \n process.parent.name : \"hh.exe\" and \n process.name : (\"mshta.exe\", \"cmd.exe\", \"powershell.exe\", \"pwsh.exe\", \"cscript.exe\", \"wscript.exe\")\n", + "query": "process where event.type in (\"start\", \"process_started\") and \n process.parent.name : \"hh.exe\" and \n process.name : (\"mshta.exe\", \"cmd.exe\", \"powershell.exe\", \"pwsh.exe\", \"powershell_ise.exe\", \"cscript.exe\", \"wscript.exe\")\n", "risk_score": 47, "rule_id": "e3343ab9-4245-4715-b344-e11c56b0a47f", "severity": "medium", @@ -74,5 +74,5 @@ ], "timestamp_override": "event.ingested", "type": "eql", - "version": 9 + "version": 10 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/exfiltration_rds_snapshot_export.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/exfiltration_rds_snapshot_export.json index b59adc45b4236..0048aae78e28f 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/exfiltration_rds_snapshot_export.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/exfiltration_rds_snapshot_export.json @@ -22,7 +22,7 @@ "https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_StartExportTask.html" ], "risk_score": 21, - "rule_id": "119c8877-8613-416d-a98a-96b6664ee73a5", + "rule_id": "119c8877-8613-416d-a98a-96b6664ee73a", "severity": "low", "tags": [ "Elastic", @@ -45,5 +45,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 2 + "version": 1 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/exfiltration_rds_snapshot_restored.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/exfiltration_rds_snapshot_restored.json new file mode 100644 index 0000000000000..860cbe82eb206 --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/exfiltration_rds_snapshot_restored.json @@ -0,0 +1,47 @@ +{ + "author": [ + "Austin Songer" + ], + "description": "Identifies when an attempt was made to restored RDS Snapshot. Snapshots are sometimes shared by threat actors in order to exfiltrate bulk data. If the permissions were modified, verify if the snapshot was shared with an unauthorized or unexpected AWS account.", + "false_positives": [ + "Restoring snapshots may be done by a system or network administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. Snapshot restoration from unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." + ], + "index": [ + "filebeat-*", + "logs-aws*" + ], + "language": "kuery", + "license": "Elastic License v2", + "name": "AWS RDS Snapshot Restored", + "note": "## Config\n\nThe AWS Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", + "query": "event.dataset:aws.cloudtrail and event.provider:rds.amazonaws.com and event.action:RestoreDBInstanceFromDBSnapshot and\nevent.outcome:success\n", + "references": [ + "https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_RestoreDBInstanceFromDBSnapshot.html", + "https://github.com/RhinoSecurityLabs/pacu/blob/master/pacu/modules/rds__explore_snapshots/main.py" + ], + "risk_score": 47, + "rule_id": "bf1073bf-ce26-4607-b405-ba1ed8e9e204", + "severity": "medium", + "tags": [ + "Elastic", + "Cloud", + "AWS", + "Continuous Monitoring", + "SecOps", + "Asset Visibility" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0010", + "name": "Exfiltration", + "reference": "https://attack.mitre.org/tactics/TA0010/" + }, + "technique": [] + } + ], + "timestamp_override": "event.ingested", + "type": "query", + "version": 1 +} diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_aws_eventbridge_rule_disabled_or_deleted.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_aws_eventbridge_rule_disabled_or_deleted.json new file mode 100644 index 0000000000000..b215ed36aba4c --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_aws_eventbridge_rule_disabled_or_deleted.json @@ -0,0 +1,48 @@ +{ + "author": [ + "Austin Songer" + ], + "description": "Identifies when a user disabled or deleted an EventBridge rule. This activity can result in an unintended loss of visibility in applications or breaking the flow with other AWS services.", + "false_positives": [ + "EventBridge Rules could be deleted or disabled by a system administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. EventBridge Rules being deleted or disabled from unfamiliar users should be investigated. If known behavior is causing false positives, it can be exempted from the rule." + ], + "from": "now-20m", + "index": [ + "filebeat-*", + "logs-aws*" + ], + "language": "kuery", + "license": "Elastic License v2", + "name": "AWS EventBridge Rule Disabled or Deleted", + "note": "## Config\n\nThe AWS Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", + "query": "event.dataset:aws.cloudtrail and event.provider:eventbridge.amazonaws.com and event.action:(DeleteRule or DisableRule) and \nevent.outcome:success\n", + "references": [ + "https://docs.aws.amazon.com/eventbridge/latest/APIReference/API_DeleteRule.html", + "https://docs.aws.amazon.com/eventbridge/latest/APIReference/API_DisableRule.html" + ], + "risk_score": 21, + "rule_id": "87594192-4539-4bc4-8543-23bc3d5bd2b4", + "severity": "low", + "tags": [ + "Elastic", + "Cloud", + "AWS", + "Continuous Monitoring", + "SecOps", + "Monitoring" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0040", + "name": "Impact", + "reference": "https://attack.mitre.org/tactics/TA0040/" + }, + "technique": [] + } + ], + "timestamp_override": "event.ingested", + "type": "query", + "version": 1 +} diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_efs_filesystem_or_mount_deleted.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_efs_filesystem_or_mount_deleted.json new file mode 100644 index 0000000000000..52fadfdf8ee19 --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_efs_filesystem_or_mount_deleted.json @@ -0,0 +1,55 @@ +{ + "author": [ + "Austin Songer" + ], + "description": "Detects when a EFS File System or Mount is deleted. An adversary could break any file system using the mount target that is being deleted, which might disrupt instances or applications using those mounts. The mount must be deleted prior to deleting the File System, or the adversary will be unable to delete the File System.", + "false_positives": [ + "File System or Mount being deleted may be performed by a system administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. File System Mount deleted from unfamiliar users should be investigated. If known behavior is causing false positives, it can be exempted from the rule." + ], + "from": "now-60m", + "index": [ + "filebeat-*", + "logs-aws*" + ], + "interval": "10m", + "language": "kuery", + "license": "Elastic License v2", + "name": "AWS EFS File System or Mount Deleted", + "note": "## Config\n\nThe AWS Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", + "query": "event.dataset:aws.cloudtrail and event.provider:elasticfilesystem.amazonaws.com and \nevent.action:(DeleteMountTarget or DeleteFileSystem) and event.outcome:success\n", + "references": [ + "https://docs.aws.amazon.com/efs/latest/ug/API_DeleteFileSystem.html", + "https://docs.aws.amazon.com/efs/latest/ug/API_DeleteMountTarget.html" + ], + "risk_score": 47, + "rule_id": "536997f7-ae73-447d-a12d-bff1e8f5f0a0", + "severity": "medium", + "tags": [ + "Elastic", + "Cloud", + "AWS", + "Continuous Monitoring", + "SecOps", + "Data Protection" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0040", + "name": "Impact", + "reference": "https://attack.mitre.org/tactics/TA0040/" + }, + "technique": [ + { + "id": "T1485", + "name": "Data Destruction", + "reference": "https://attack.mitre.org/techniques/T1485/" + } + ] + } + ], + "timestamp_override": "event.ingested", + "type": "query", + "version": 1 +} diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_hosts_file_modified.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_hosts_file_modified.json index 56c943c85cb2a..18f4f1c2e50e2 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_hosts_file_modified.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_hosts_file_modified.json @@ -13,8 +13,8 @@ "language": "eql", "license": "Elastic License v2", "name": "Hosts File Modified", - "note": "## Config\n\nFor Windows systems using Auditbeat, this rule requires adding 'C:/Windows/System32/drivers/etc' as an additional path in the 'file_integrity' module of auditbeat.yml.", - "query": "file where event.type in (\"change\", \"creation\") and\n file.path : (\"/private/etc/hosts\", \"/etc/hosts\", \"?:\\\\Windows\\\\System32\\\\drivers\\\\etc\\\\hosts\") \n", + "note": "## Config\n\nFor Windows systems using Auditbeat, this rule requires adding `C:/Windows/System32/drivers/etc` as an additional path in the 'file_integrity' module of auditbeat.yml.", + "query": "any where\n\n /* file events for creation; file change events are not captured by some of the included sources for linux and so may\n miss this, which is the purpose of the process + command line args logic below */\n (\n event.category == \"file\" and event.type in (\"change\", \"creation\") and\n file.path : (\"/private/etc/hosts\", \"/etc/hosts\", \"?:\\\\Windows\\\\System32\\\\drivers\\\\etc\\\\hosts\")\n )\n or\n\n /* process events for change targeting linux only */\n (\n event.category == \"process\" and event.type in (\"start\") and\n process.name in (\"nano\", \"vim\", \"vi\", \"emacs\", \"echo\", \"sed\") and\n process.args : (\"/etc/hosts\")\n )\n", "references": [ "https://www.elastic.co/guide/en/beats/auditbeat/current/auditbeat-reference-yml.html" ], @@ -56,5 +56,5 @@ ], "timestamp_override": "event.ingested", "type": "eql", - "version": 5 + "version": 6 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_kubernetes_pod_deleted.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_kubernetes_pod_deleted.json new file mode 100644 index 0000000000000..318904f9029de --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_kubernetes_pod_deleted.json @@ -0,0 +1,47 @@ +{ + "author": [ + "Austin Songer" + ], + "description": "Identifies the deletion of Azure Kubernetes Pods. Adversary may delete a kubernetes pod to disrupt the normal behavior of the environment.", + "false_positives": [ + "Pods may be deleted by a system administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. Pods deletions from unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." + ], + "from": "now-25m", + "index": [ + "filebeat-*", + "logs-azure*" + ], + "language": "kuery", + "license": "Elastic License v2", + "name": "Azure Kubernetes Pods Deleted", + "note": "## Config\n\nThe Azure Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", + "query": "event.dataset:azure.activitylogs and azure.activitylogs.operation_name:\"MICROSOFT.KUBERNETES/CONNECTEDCLUSTERS/PODS/DELETE\" and \nevent.outcome:(Success or success)\n", + "references": [ + "https://docs.microsoft.com/en-us/azure/role-based-access-control/resource-provider-operations#microsoftkubernetes" + ], + "risk_score": 47, + "rule_id": "83a1931d-8136-46fc-b7b9-2db4f639e014", + "severity": "medium", + "tags": [ + "Elastic", + "Cloud", + "Azure", + "Continuous Monitoring", + "SecOps", + "Asset Visibility" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0040", + "name": "Impact", + "reference": "https://attack.mitre.org/tactics/TA0040/" + }, + "technique": [] + } + ], + "timestamp_override": "event.ingested", + "type": "query", + "version": 1 +} diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_virtual_network_device_modified.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_virtual_network_device_modified.json new file mode 100644 index 0000000000000..a378a3d607abb --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_virtual_network_device_modified.json @@ -0,0 +1,47 @@ +{ + "author": [ + "Austin Songer" + ], + "description": "Identifies when a virtual network device is being modified or deleted. This can be a network virtual appliance, virtual hub, or virtual router.", + "false_positives": [ + "Virtual Network Device being modified or deleted may be performed by a system administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. Virtual Network Device modified or deleted from unfamiliar users should be investigated. If known behavior is causing false positives, it can be exempted from the rule." + ], + "from": "now-25m", + "index": [ + "filebeat-*", + "logs-azure*" + ], + "language": "kuery", + "license": "Elastic License v2", + "name": "Azure Virtual Network Device Modified or Deleted", + "note": "## Config\n\nThe Azure Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", + "query": "event.dataset:azure.activitylogs and azure.activitylogs.operation_name:(\"MICROSOFT.NETWORK/NETWORKINTERFACES/TAPCONFIGURATIONS/WRITE\" or\n\"MICROSOFT.NETWORK/NETWORKINTERFACES/TAPCONFIGURATIONS/DELETE\" or \"MICROSOFT.NETWORK/NETWORKINTERFACES/WRITE\" or\n\"MICROSOFT.NETWORK/NETWORKINTERFACES/JOIN/ACTION\" or \"MICROSOFT.NETWORK/NETWORKINTERFACES/DELETE\"or\n\"MICROSOFT.NETWORK/NETWORKVIRTUALAPPLIANCES/DELETE\" or \"MICROSOFT.NETWORK/NETWORKVIRTUALAPPLIANCES/WRITE\" or\n\"MICROSOFT.NETWORK/VIRTUALHUBS/DELETE\" or \"MICROSOFT.NETWORK/VIRTUALHUBS/WRITE\" or\n\"MICROSOFT.NETWORK/VIRTUALROUTERS/WRITE\" or \"MICROSOFT.NETWORK/VIRTUALROUTERS/DELETE\") and \nevent.outcome:(Success or success)\n", + "references": [ + "https://docs.microsoft.com/en-us/azure/role-based-access-control/resource-provider-operations" + ], + "risk_score": 21, + "rule_id": "573f6e7a-7acf-4bcd-ad42-c4969124d3c0", + "severity": "low", + "tags": [ + "Elastic", + "Cloud", + "Azure", + "Continuous Monitoring", + "SecOps", + "Network Security" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0040", + "name": "Impact", + "reference": "https://attack.mitre.org/tactics/TA0040/" + }, + "technique": [] + } + ], + "timestamp_override": "event.ingested", + "type": "query", + "version": 1 +} diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_volume_shadow_copy_deletion_via_powershell.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_volume_shadow_copy_deletion_via_powershell.json index 43dce4acf4df8..59aceaad39ec2 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_volume_shadow_copy_deletion_via_powershell.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_volume_shadow_copy_deletion_via_powershell.json @@ -13,7 +13,7 @@ "language": "eql", "license": "Elastic License v2", "name": "Volume Shadow Copy Deletion via PowerShell", - "query": "process where event.type in (\"start\", \"process_started\") and\n process.name : (\"powershell.exe\", \"pwsh.exe\") and \n process.args : (\"*Get-WmiObject*\", \"*gwmi*\", \"*Get-CimInstance*\", \"*gcim*\") and\n process.args : (\"*Win32_ShadowCopy*\") and\n process.args : (\"*.Delete()*\", \"*Remove-WmiObject*\", \"*rwmi*\", \"*Remove-CimInstance*\", \"*rcim*\")\n", + "query": "process where event.type in (\"start\", \"process_started\") and\n process.name : (\"powershell.exe\", \"pwsh.exe\", \"powershell_ise.exe\") and \n process.args : (\"*Get-WmiObject*\", \"*gwmi*\", \"*Get-CimInstance*\", \"*gcim*\") and\n process.args : (\"*Win32_ShadowCopy*\") and\n process.args : (\"*.Delete()*\", \"*Remove-WmiObject*\", \"*rwmi*\", \"*Remove-CimInstance*\", \"*rcim*\")\n", "references": [ "https://docs.microsoft.com/en-us/previous-versions/windows/desktop/vsswmi/win32-shadowcopy", "https://powershell.one/wmi/root/cimv2/win32_shadowcopy", @@ -48,5 +48,5 @@ ], "timestamp_override": "event.ingested", "type": "eql", - "version": 1 + "version": 2 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/index.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/index.ts index 1c5006f5e6f48..474f7f1181ab8 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/index.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/index.ts @@ -220,385 +220,404 @@ import rule207 from './initial_access_unusual_dns_service_file_writes.json'; import rule208 from './lateral_movement_dns_server_overflow.json'; import rule209 from './credential_access_root_console_failure_brute_force.json'; import rule210 from './initial_access_unsecure_elasticsearch_node.json'; -import rule211 from './credential_access_domain_backup_dpapi_private_keys.json'; -import rule212 from './persistence_gpo_schtask_service_creation.json'; -import rule213 from './credential_access_credentials_keychains.json'; -import rule214 from './credential_access_kerberosdump_kcc.json'; -import rule215 from './defense_evasion_attempt_del_quarantine_attrib.json'; -import rule216 from './execution_suspicious_psexesvc.json'; -import rule217 from './execution_via_xp_cmdshell_mssql_stored_procedure.json'; -import rule218 from './privilege_escalation_printspooler_service_suspicious_file.json'; -import rule219 from './privilege_escalation_printspooler_suspicious_spl_file.json'; -import rule220 from './defense_evasion_azure_diagnostic_settings_deletion.json'; -import rule221 from './execution_command_virtual_machine.json'; -import rule222 from './execution_via_hidden_shell_conhost.json'; -import rule223 from './impact_resource_group_deletion.json'; -import rule224 from './persistence_via_telemetrycontroller_scheduledtask_hijack.json'; -import rule225 from './persistence_via_update_orchestrator_service_hijack.json'; -import rule226 from './collection_update_event_hub_auth_rule.json'; -import rule227 from './credential_access_iis_apppoolsa_pwd_appcmd.json'; -import rule228 from './credential_access_iis_connectionstrings_dumping.json'; -import rule229 from './defense_evasion_event_hub_deletion.json'; -import rule230 from './defense_evasion_firewall_policy_deletion.json'; -import rule231 from './defense_evasion_sdelete_like_filename_rename.json'; -import rule232 from './lateral_movement_remote_ssh_login_enabled.json'; -import rule233 from './persistence_azure_automation_account_created.json'; -import rule234 from './persistence_azure_automation_runbook_created_or_modified.json'; -import rule235 from './persistence_azure_automation_webhook_created.json'; -import rule236 from './privilege_escalation_uac_bypass_diskcleanup_hijack.json'; -import rule237 from './credential_access_attempts_to_brute_force_okta_user_account.json'; -import rule238 from './credential_access_storage_account_key_regenerated.json'; -import rule239 from './defense_evasion_suspicious_okta_user_password_reset_or_unlock_attempts.json'; -import rule240 from './defense_evasion_system_critical_proc_abnormal_file_activity.json'; -import rule241 from './defense_evasion_unusual_system_vp_child_program.json'; -import rule242 from './discovery_blob_container_access_mod.json'; -import rule243 from './persistence_mfa_disabled_for_azure_user.json'; -import rule244 from './persistence_user_added_as_owner_for_azure_application.json'; -import rule245 from './persistence_user_added_as_owner_for_azure_service_principal.json'; -import rule246 from './defense_evasion_dotnet_compiler_parent_process.json'; -import rule247 from './defense_evasion_suspicious_managedcode_host_process.json'; -import rule248 from './execution_command_shell_started_by_unusual_process.json'; -import rule249 from './defense_evasion_masquerading_as_elastic_endpoint_process.json'; -import rule250 from './defense_evasion_masquerading_suspicious_werfault_childproc.json'; -import rule251 from './defense_evasion_masquerading_werfault.json'; -import rule252 from './credential_access_key_vault_modified.json'; -import rule253 from './credential_access_mimikatz_memssp_default_logs.json'; -import rule254 from './defense_evasion_code_injection_conhost.json'; -import rule255 from './defense_evasion_network_watcher_deletion.json'; -import rule256 from './initial_access_external_guest_user_invite.json'; -import rule257 from './defense_evasion_masquerading_renamed_autoit.json'; -import rule258 from './impact_azure_automation_runbook_deleted.json'; -import rule259 from './initial_access_consent_grant_attack_via_azure_registered_application.json'; -import rule260 from './persistence_azure_conditional_access_policy_modified.json'; -import rule261 from './persistence_azure_privileged_identity_management_role_modified.json'; -import rule262 from './command_and_control_teamviewer_remote_file_copy.json'; -import rule263 from './defense_evasion_installutil_beacon.json'; -import rule264 from './defense_evasion_mshta_beacon.json'; -import rule265 from './defense_evasion_network_connection_from_windows_binary.json'; -import rule266 from './defense_evasion_rundll32_no_arguments.json'; -import rule267 from './defense_evasion_suspicious_scrobj_load.json'; -import rule268 from './defense_evasion_suspicious_wmi_script.json'; -import rule269 from './execution_ms_office_written_file.json'; -import rule270 from './execution_pdf_written_file.json'; -import rule271 from './lateral_movement_cmd_service.json'; -import rule272 from './persistence_app_compat_shim.json'; -import rule273 from './command_and_control_remote_file_copy_desktopimgdownldr.json'; -import rule274 from './command_and_control_remote_file_copy_mpcmdrun.json'; -import rule275 from './defense_evasion_execution_suspicious_explorer_winword.json'; -import rule276 from './defense_evasion_suspicious_zoom_child_process.json'; -import rule277 from './ml_linux_anomalous_compiler_activity.json'; -import rule278 from './ml_linux_anomalous_kernel_module_arguments.json'; -import rule279 from './ml_linux_anomalous_sudo_activity.json'; -import rule280 from './ml_linux_system_information_discovery.json'; -import rule281 from './ml_linux_system_network_configuration_discovery.json'; -import rule282 from './ml_linux_system_network_connection_discovery.json'; -import rule283 from './ml_linux_system_process_discovery.json'; -import rule284 from './ml_linux_system_user_discovery.json'; -import rule285 from './discovery_post_exploitation_external_ip_lookup.json'; -import rule286 from './initial_access_zoom_meeting_with_no_passcode.json'; -import rule287 from './defense_evasion_gcp_logging_sink_deletion.json'; -import rule288 from './defense_evasion_gcp_pub_sub_topic_deletion.json'; -import rule289 from './defense_evasion_gcp_firewall_rule_created.json'; -import rule290 from './defense_evasion_gcp_firewall_rule_deleted.json'; -import rule291 from './defense_evasion_gcp_firewall_rule_modified.json'; -import rule292 from './defense_evasion_gcp_logging_bucket_deletion.json'; -import rule293 from './defense_evasion_gcp_storage_bucket_permissions_modified.json'; -import rule294 from './impact_gcp_storage_bucket_deleted.json'; -import rule295 from './initial_access_gcp_iam_custom_role_creation.json'; -import rule296 from './persistence_gcp_iam_service_account_key_deletion.json'; -import rule297 from './persistence_gcp_key_created_for_service_account.json'; -import rule298 from './defense_evasion_gcp_storage_bucket_configuration_modified.json'; -import rule299 from './exfiltration_gcp_logging_sink_modification.json'; -import rule300 from './impact_gcp_iam_role_deletion.json'; -import rule301 from './impact_gcp_service_account_deleted.json'; -import rule302 from './impact_gcp_service_account_disabled.json'; -import rule303 from './impact_gcp_virtual_private_cloud_network_deleted.json'; -import rule304 from './impact_gcp_virtual_private_cloud_route_created.json'; -import rule305 from './impact_gcp_virtual_private_cloud_route_deleted.json'; -import rule306 from './ml_linux_anomalous_metadata_process.json'; -import rule307 from './ml_linux_anomalous_metadata_user.json'; -import rule308 from './ml_windows_anomalous_metadata_process.json'; -import rule309 from './ml_windows_anomalous_metadata_user.json'; -import rule310 from './persistence_gcp_service_account_created.json'; -import rule311 from './collection_gcp_pub_sub_subscription_creation.json'; -import rule312 from './collection_gcp_pub_sub_topic_creation.json'; -import rule313 from './defense_evasion_gcp_pub_sub_subscription_deletion.json'; -import rule314 from './persistence_azure_pim_user_added_global_admin.json'; -import rule315 from './command_and_control_cobalt_strike_default_teamserver_cert.json'; -import rule316 from './defense_evasion_enable_inbound_rdp_with_netsh.json'; -import rule317 from './defense_evasion_execution_lolbas_wuauclt.json'; -import rule318 from './privilege_escalation_unusual_svchost_childproc_childless.json'; -import rule319 from './command_and_control_rdp_tunnel_plink.json'; -import rule320 from './privilege_escalation_uac_bypass_winfw_mmc_hijack.json'; -import rule321 from './persistence_ms_office_addins_file.json'; -import rule322 from './discovery_adfind_command_activity.json'; -import rule323 from './discovery_security_software_wmic.json'; -import rule324 from './execution_command_shell_via_rundll32.json'; -import rule325 from './execution_suspicious_cmd_wmi.json'; -import rule326 from './lateral_movement_via_startup_folder_rdp_smb.json'; -import rule327 from './privilege_escalation_uac_bypass_com_interface_icmluautil.json'; -import rule328 from './privilege_escalation_uac_bypass_mock_windir.json'; -import rule329 from './defense_evasion_potential_processherpaderping.json'; -import rule330 from './privilege_escalation_uac_bypass_dll_sideloading.json'; -import rule331 from './execution_shared_modules_local_sxs_dll.json'; -import rule332 from './privilege_escalation_uac_bypass_com_clipup.json'; -import rule333 from './initial_access_via_explorer_suspicious_child_parent_args.json'; -import rule334 from './execution_from_unusual_directory.json'; -import rule335 from './execution_from_unusual_path_cmdline.json'; -import rule336 from './credential_access_kerberoasting_unusual_process.json'; -import rule337 from './discovery_peripheral_device.json'; -import rule338 from './lateral_movement_mount_hidden_or_webdav_share_net.json'; -import rule339 from './defense_evasion_deleting_websvr_access_logs.json'; -import rule340 from './defense_evasion_log_files_deleted.json'; -import rule341 from './defense_evasion_timestomp_touch.json'; -import rule342 from './lateral_movement_dcom_hta.json'; -import rule343 from './lateral_movement_execution_via_file_shares_sequence.json'; -import rule344 from './privilege_escalation_uac_bypass_com_ieinstal.json'; -import rule345 from './command_and_control_common_webservices.json'; -import rule346 from './command_and_control_encrypted_channel_freesslcert.json'; -import rule347 from './defense_evasion_process_termination_followed_by_deletion.json'; -import rule348 from './lateral_movement_remote_file_copy_hidden_share.json'; -import rule349 from './attempt_to_deactivate_okta_network_zone.json'; -import rule350 from './attempt_to_delete_okta_network_zone.json'; -import rule351 from './lateral_movement_dcom_mmc20.json'; -import rule352 from './lateral_movement_dcom_shellwindow_shellbrowserwindow.json'; -import rule353 from './okta_attempt_to_deactivate_okta_application.json'; -import rule354 from './okta_attempt_to_delete_okta_application.json'; -import rule355 from './okta_attempt_to_delete_okta_policy_rule.json'; -import rule356 from './okta_attempt_to_modify_okta_application.json'; -import rule357 from './persistence_administrator_role_assigned_to_okta_user.json'; -import rule358 from './lateral_movement_executable_tool_transfer_smb.json'; -import rule359 from './command_and_control_dns_tunneling_nslookup.json'; -import rule360 from './lateral_movement_execution_from_tsclient_mup.json'; -import rule361 from './lateral_movement_rdp_sharprdp_target.json'; -import rule362 from './defense_evasion_clearing_windows_security_logs.json'; -import rule363 from './persistence_google_workspace_api_access_granted_via_domain_wide_delegation_of_authority.json'; -import rule364 from './execution_suspicious_short_program_name.json'; -import rule365 from './lateral_movement_incoming_wmi.json'; -import rule366 from './persistence_via_hidden_run_key_valuename.json'; -import rule367 from './credential_access_potential_ssh_bruteforce.json'; -import rule368 from './credential_access_promt_for_pwd_via_osascript.json'; -import rule369 from './lateral_movement_remote_services.json'; -import rule370 from './application_added_to_google_workspace_domain.json'; -import rule371 from './domain_added_to_google_workspace_trusted_domains.json'; -import rule372 from './execution_suspicious_image_load_wmi_ms_office.json'; -import rule373 from './execution_suspicious_powershell_imgload.json'; -import rule374 from './google_workspace_admin_role_deletion.json'; -import rule375 from './google_workspace_mfa_enforcement_disabled.json'; -import rule376 from './google_workspace_policy_modified.json'; -import rule377 from './mfa_disabled_for_google_workspace_organization.json'; -import rule378 from './persistence_evasion_registry_ifeo_injection.json'; -import rule379 from './persistence_google_workspace_admin_role_assigned_to_user.json'; -import rule380 from './persistence_google_workspace_custom_admin_role_created.json'; -import rule381 from './persistence_google_workspace_role_modified.json'; -import rule382 from './persistence_suspicious_image_load_scheduled_task_ms_office.json'; -import rule383 from './defense_evasion_masquerading_trusted_directory.json'; -import rule384 from './exfiltration_microsoft_365_exchange_transport_rule_creation.json'; -import rule385 from './initial_access_microsoft_365_exchange_safelinks_disabled.json'; -import rule386 from './microsoft_365_exchange_dkim_signing_config_disabled.json'; -import rule387 from './persistence_appcertdlls_registry.json'; -import rule388 from './persistence_appinitdlls_registry.json'; -import rule389 from './persistence_registry_uncommon.json'; -import rule390 from './persistence_run_key_and_startup_broad.json'; -import rule391 from './persistence_services_registry.json'; -import rule392 from './persistence_startup_folder_file_written_by_suspicious_process.json'; -import rule393 from './persistence_startup_folder_scripts.json'; -import rule394 from './persistence_suspicious_com_hijack_registry.json'; -import rule395 from './persistence_via_lsa_security_support_provider_registry.json'; -import rule396 from './defense_evasion_microsoft_365_exchange_malware_filter_policy_deletion.json'; -import rule397 from './defense_evasion_microsoft_365_exchange_malware_filter_rule_mod.json'; -import rule398 from './defense_evasion_microsoft_365_exchange_safe_attach_rule_disabled.json'; -import rule399 from './exfiltration_microsoft_365_exchange_transport_rule_mod.json'; -import rule400 from './initial_access_microsoft_365_exchange_anti_phish_policy_deletion.json'; -import rule401 from './initial_access_microsoft_365_exchange_anti_phish_rule_mod.json'; -import rule402 from './lateral_movement_suspicious_rdp_client_imageload.json'; -import rule403 from './persistence_runtime_run_key_startup_susp_procs.json'; -import rule404 from './persistence_suspicious_scheduled_task_runtime.json'; -import rule405 from './defense_evasion_microsoft_365_exchange_dlp_policy_removed.json'; -import rule406 from './lateral_movement_scheduled_task_target.json'; -import rule407 from './persistence_microsoft_365_exchange_management_role_assignment.json'; -import rule408 from './persistence_microsoft_365_teams_guest_access_enabled.json'; -import rule409 from './credential_access_dump_registry_hives.json'; -import rule410 from './defense_evasion_scheduledjobs_at_protocol_enabled.json'; -import rule411 from './persistence_ms_outlook_vba_template.json'; -import rule412 from './persistence_suspicious_service_created_registry.json'; -import rule413 from './privilege_escalation_named_pipe_impersonation.json'; -import rule414 from './credential_access_cmdline_dump_tool.json'; -import rule415 from './credential_access_copy_ntds_sam_volshadowcp_cmdline.json'; -import rule416 from './credential_access_lsass_memdump_file_created.json'; -import rule417 from './lateral_movement_incoming_winrm_shell_execution.json'; -import rule418 from './lateral_movement_powershell_remoting_target.json'; -import rule419 from './command_and_control_port_forwarding_added_registry.json'; -import rule420 from './defense_evasion_hide_encoded_executable_registry.json'; -import rule421 from './lateral_movement_rdp_enabled_registry.json'; -import rule422 from './privilege_escalation_printspooler_registry_copyfiles.json'; -import rule423 from './privilege_escalation_rogue_windir_environment_var.json'; -import rule424 from './initial_access_scripts_process_started_via_wmi.json'; -import rule425 from './command_and_control_iexplore_via_com.json'; -import rule426 from './command_and_control_remote_file_copy_scripts.json'; -import rule427 from './persistence_local_scheduled_task_scripting.json'; -import rule428 from './persistence_startup_folder_file_written_by_unsigned_process.json'; -import rule429 from './command_and_control_remote_file_copy_powershell.json'; -import rule430 from './credential_access_microsoft_365_brute_force_user_account_attempt.json'; -import rule431 from './microsoft_365_teams_custom_app_interaction_allowed.json'; -import rule432 from './persistence_microsoft_365_teams_external_access_enabled.json'; -import rule433 from './credential_access_microsoft_365_potential_password_spraying_attack.json'; -import rule434 from './impact_stop_process_service_threshold.json'; -import rule435 from './collection_winrar_encryption.json'; -import rule436 from './defense_evasion_unusual_dir_ads.json'; -import rule437 from './discovery_admin_recon.json'; -import rule438 from './discovery_file_dir_discovery.json'; -import rule439 from './discovery_net_view.json'; -import rule440 from './discovery_remote_system_discovery_commands_windows.json'; -import rule441 from './persistence_via_windows_management_instrumentation_event_subscription.json'; -import rule442 from './execution_scripting_osascript_exec_followed_by_netcon.json'; -import rule443 from './execution_shell_execution_via_apple_scripting.json'; -import rule444 from './persistence_creation_change_launch_agents_file.json'; -import rule445 from './persistence_creation_modif_launch_deamon_sequence.json'; -import rule446 from './persistence_folder_action_scripts_runtime.json'; -import rule447 from './persistence_login_logout_hooks_defaults.json'; -import rule448 from './privilege_escalation_explicit_creds_via_scripting.json'; -import rule449 from './command_and_control_sunburst_c2_activity_detected.json'; -import rule450 from './defense_evasion_azure_application_credential_modification.json'; -import rule451 from './defense_evasion_azure_service_principal_addition.json'; -import rule452 from './defense_evasion_solarwinds_backdoor_service_disabled_via_registry.json'; -import rule453 from './execution_apt_solarwinds_backdoor_child_cmd_powershell.json'; -import rule454 from './execution_apt_solarwinds_backdoor_unusual_child_processes.json'; -import rule455 from './initial_access_azure_active_directory_powershell_signin.json'; -import rule456 from './collection_email_powershell_exchange_mailbox.json'; -import rule457 from './execution_scheduled_task_powershell_source.json'; -import rule458 from './persistence_powershell_exch_mailbox_activesync_add_device.json'; -import rule459 from './persistence_docker_shortcuts_plist_modification.json'; -import rule460 from './persistence_evasion_hidden_local_account_creation.json'; -import rule461 from './persistence_finder_sync_plugin_pluginkit.json'; -import rule462 from './discovery_security_software_grep.json'; -import rule463 from './credential_access_cookies_chromium_browsers_debugging.json'; -import rule464 from './credential_access_ssh_backdoor_log.json'; -import rule465 from './persistence_credential_access_modify_auth_module_or_config.json'; -import rule466 from './persistence_credential_access_modify_ssh_binaries.json'; -import rule467 from './credential_access_collection_sensitive_files.json'; -import rule468 from './persistence_ssh_authorized_keys_modification.json'; -import rule469 from './defense_evasion_defender_disabled_via_registry.json'; -import rule470 from './defense_evasion_privacy_controls_tcc_database_modification.json'; -import rule471 from './execution_initial_access_suspicious_browser_childproc.json'; -import rule472 from './execution_script_via_automator_workflows.json'; -import rule473 from './persistence_modification_sublime_app_plugin_or_script.json'; -import rule474 from './privilege_escalation_applescript_with_admin_privs.json'; -import rule475 from './credential_access_dumping_keychain_security.json'; -import rule476 from './initial_access_azure_active_directory_high_risk_signin.json'; -import rule477 from './initial_access_suspicious_mac_ms_office_child_process.json'; -import rule478 from './credential_access_mitm_localhost_webproxy.json'; -import rule479 from './persistence_kde_autostart_modification.json'; -import rule480 from './persistence_user_account_added_to_privileged_group_ad.json'; -import rule481 from './defense_evasion_attempt_to_disable_gatekeeper.json'; -import rule482 from './defense_evasion_sandboxed_office_app_suspicious_zip_file.json'; -import rule483 from './persistence_emond_rules_file_creation.json'; -import rule484 from './persistence_emond_rules_process_execution.json'; -import rule485 from './discovery_users_domain_built_in_commands.json'; -import rule486 from './execution_pentest_eggshell_remote_admin_tool.json'; -import rule487 from './defense_evasion_install_root_certificate.json'; -import rule488 from './persistence_credential_access_authorization_plugin_creation.json'; -import rule489 from './persistence_directory_services_plugins_modification.json'; -import rule490 from './defense_evasion_modify_environment_launchctl.json'; -import rule491 from './defense_evasion_safari_config_change.json'; -import rule492 from './defense_evasion_apple_softupdates_modification.json'; -import rule493 from './credential_access_mod_wdigest_security_provider.json'; -import rule494 from './credential_access_saved_creds_vaultcmd.json'; -import rule495 from './defense_evasion_file_creation_mult_extension.json'; -import rule496 from './execution_enumeration_via_wmiprvse.json'; -import rule497 from './execution_suspicious_jar_child_process.json'; -import rule498 from './persistence_shell_profile_modification.json'; -import rule499 from './persistence_suspicious_calendar_modification.json'; -import rule500 from './persistence_time_provider_mod.json'; -import rule501 from './privilege_escalation_exploit_adobe_acrobat_updater.json'; -import rule502 from './defense_evasion_sip_provider_mod.json'; -import rule503 from './execution_com_object_xwizard.json'; -import rule504 from './privilege_escalation_disable_uac_registry.json'; -import rule505 from './defense_evasion_unusual_ads_file_creation.json'; -import rule506 from './persistence_loginwindow_plist_modification.json'; -import rule507 from './persistence_periodic_tasks_file_mdofiy.json'; -import rule508 from './persistence_via_atom_init_file_modification.json'; -import rule509 from './privilege_escalation_lsa_auth_package.json'; -import rule510 from './privilege_escalation_port_monitor_print_pocessor_abuse.json'; -import rule511 from './credential_access_dumping_hashes_bi_cmds.json'; -import rule512 from './lateral_movement_mounting_smb_share.json'; -import rule513 from './privilege_escalation_echo_nopasswd_sudoers.json'; -import rule514 from './privilege_escalation_ld_preload_shared_object_modif.json'; -import rule515 from './privilege_escalation_root_crontab_filemod.json'; -import rule516 from './defense_evasion_create_mod_root_certificate.json'; -import rule517 from './privilege_escalation_sudo_buffer_overflow.json'; -import rule518 from './execution_installer_spawned_network_event.json'; -import rule519 from './initial_access_suspicious_ms_exchange_files.json'; -import rule520 from './initial_access_suspicious_ms_exchange_process.json'; -import rule521 from './initial_access_suspicious_ms_exchange_worker_child_process.json'; -import rule522 from './persistence_evasion_registry_startup_shell_folder_modified.json'; -import rule523 from './persistence_local_scheduled_job_creation.json'; -import rule524 from './persistence_via_wmi_stdregprov_run_services.json'; -import rule525 from './credential_access_persistence_network_logon_provider_modification.json'; -import rule526 from './lateral_movement_defense_evasion_lanman_nullsessionpipe_modification.json'; -import rule527 from './collection_microsoft_365_new_inbox_rule.json'; -import rule528 from './ml_high_count_network_denies.json'; -import rule529 from './ml_high_count_network_events.json'; -import rule530 from './ml_rare_destination_country.json'; -import rule531 from './ml_spike_in_traffic_to_a_country.json'; -import rule532 from './command_and_control_tunneling_via_earthworm.json'; -import rule533 from './lateral_movement_evasion_rdp_shadowing.json'; -import rule534 from './threat_intel_module_match.json'; -import rule535 from './exfiltration_ec2_vm_export_failure.json'; -import rule536 from './exfiltration_ec2_full_network_packet_capture_detected.json'; -import rule537 from './impact_azure_service_principal_credentials_added.json'; -import rule538 from './persistence_ec2_security_group_configuration_change_detection.json'; -import rule539 from './defense_evasion_disabling_windows_logs.json'; -import rule540 from './persistence_route_53_domain_transfer_lock_disabled.json'; -import rule541 from './persistence_route_53_domain_transferred_to_another_account.json'; -import rule542 from './initial_access_okta_user_attempted_unauthorized_access.json'; -import rule543 from './credential_access_user_excessive_sso_logon_errors.json'; -import rule544 from './persistence_exchange_suspicious_mailbox_right_delegation.json'; -import rule545 from './privilege_escalation_new_or_modified_federation_domain.json'; -import rule546 from './privilege_escalation_sts_getsessiontoken_abuse.json'; -import rule547 from './defense_evasion_suspicious_execution_from_mounted_device.json'; -import rule548 from './defense_evasion_unusual_network_connection_via_dllhost.json'; -import rule549 from './defense_evasion_amsienable_key_mod.json'; -import rule550 from './impact_rds_group_deletion.json'; -import rule551 from './persistence_rds_group_creation.json'; -import rule552 from './persistence_route_table_modified_or_deleted.json'; -import rule553 from './exfiltration_rds_snapshot_export.json'; -import rule554 from './persistence_rds_instance_creation.json'; -import rule555 from './ml_auth_rare_hour_for_a_user_to_logon.json'; -import rule556 from './ml_auth_rare_source_ip_for_a_user.json'; -import rule557 from './ml_auth_rare_user_logon.json'; -import rule558 from './ml_auth_spike_in_failed_logon_events.json'; -import rule559 from './ml_auth_spike_in_logon_events.json'; -import rule560 from './ml_auth_spike_in_logon_events_from_a_source_ip.json'; -import rule561 from './privilege_escalation_cyberarkpas_error_audit_event_promotion.json'; -import rule562 from './privilege_escalation_cyberarkpas_recommended_events_to_monitor_promotion.json'; -import rule563 from './privilege_escalation_printspooler_malicious_driver_file_changes.json'; -import rule564 from './privilege_escalation_printspooler_malicious_registry_modification.json'; -import rule565 from './privilege_escalation_printspooler_suspicious_file_deletion.json'; -import rule566 from './privilege_escalation_unusual_printspooler_childprocess.json'; -import rule567 from './defense_evasion_disabling_windows_defender_powershell.json'; -import rule568 from './defense_evasion_enable_network_discovery_with_netsh.json'; -import rule569 from './defense_evasion_execution_windefend_unusual_path.json'; -import rule570 from './defense_evasion_agent_spoofing_mismatched_id.json'; -import rule571 from './defense_evasion_agent_spoofing_multiple_hosts.json'; -import rule572 from './defense_evasion_parent_process_pid_spoofing.json'; -import rule573 from './impact_microsoft_365_potential_ransomware_activity.json'; -import rule574 from './impact_microsoft_365_unusual_volume_of_file_deletion.json'; -import rule575 from './initial_access_microsoft_365_user_restricted_from_sending_email.json'; -import rule576 from './defense_evasion_elasticache_security_group_creation.json'; -import rule577 from './defense_evasion_elasticache_security_group_modified_or_deleted.json'; -import rule578 from './impact_volume_shadow_copy_deletion_via_powershell.json'; -import rule579 from './defense_evasion_defender_exclusion_via_powershell.json'; -import rule580 from './defense_evasion_whitespace_padding_in_command_line.json'; -import rule581 from './defense_evasion_frontdoor_firewall_policy_deletion.json'; -import rule582 from './persistence_webshell_detection.json'; -import rule583 from './defense_evasion_execution_control_panel_suspicious_args.json'; -import rule584 from './credential_access_potential_lsa_memdump_via_mirrordump.json'; -import rule585 from './discovery_virtual_machine_fingerprinting_grep.json'; -import rule586 from './impact_backup_file_deletion.json'; -import rule587 from './persistence_screensaver_engine_unexpected_child_process.json'; -import rule588 from './persistence_screensaver_plist_file_modification.json'; -import rule589 from './persistence_via_bits_job_notify_command.json'; +import rule211 from './impact_virtual_network_device_modified.json'; +import rule212 from './credential_access_domain_backup_dpapi_private_keys.json'; +import rule213 from './persistence_gpo_schtask_service_creation.json'; +import rule214 from './credential_access_credentials_keychains.json'; +import rule215 from './credential_access_kerberosdump_kcc.json'; +import rule216 from './defense_evasion_attempt_del_quarantine_attrib.json'; +import rule217 from './execution_suspicious_psexesvc.json'; +import rule218 from './execution_via_xp_cmdshell_mssql_stored_procedure.json'; +import rule219 from './privilege_escalation_printspooler_service_suspicious_file.json'; +import rule220 from './privilege_escalation_printspooler_suspicious_spl_file.json'; +import rule221 from './defense_evasion_azure_diagnostic_settings_deletion.json'; +import rule222 from './execution_command_virtual_machine.json'; +import rule223 from './execution_via_hidden_shell_conhost.json'; +import rule224 from './impact_resource_group_deletion.json'; +import rule225 from './persistence_via_telemetrycontroller_scheduledtask_hijack.json'; +import rule226 from './persistence_via_update_orchestrator_service_hijack.json'; +import rule227 from './collection_update_event_hub_auth_rule.json'; +import rule228 from './credential_access_iis_apppoolsa_pwd_appcmd.json'; +import rule229 from './credential_access_iis_connectionstrings_dumping.json'; +import rule230 from './defense_evasion_event_hub_deletion.json'; +import rule231 from './defense_evasion_firewall_policy_deletion.json'; +import rule232 from './defense_evasion_sdelete_like_filename_rename.json'; +import rule233 from './lateral_movement_remote_ssh_login_enabled.json'; +import rule234 from './persistence_azure_automation_account_created.json'; +import rule235 from './persistence_azure_automation_runbook_created_or_modified.json'; +import rule236 from './persistence_azure_automation_webhook_created.json'; +import rule237 from './privilege_escalation_uac_bypass_diskcleanup_hijack.json'; +import rule238 from './credential_access_attempts_to_brute_force_okta_user_account.json'; +import rule239 from './credential_access_storage_account_key_regenerated.json'; +import rule240 from './defense_evasion_suspicious_okta_user_password_reset_or_unlock_attempts.json'; +import rule241 from './defense_evasion_system_critical_proc_abnormal_file_activity.json'; +import rule242 from './defense_evasion_unusual_system_vp_child_program.json'; +import rule243 from './discovery_blob_container_access_mod.json'; +import rule244 from './persistence_mfa_disabled_for_azure_user.json'; +import rule245 from './persistence_user_added_as_owner_for_azure_application.json'; +import rule246 from './persistence_user_added_as_owner_for_azure_service_principal.json'; +import rule247 from './defense_evasion_dotnet_compiler_parent_process.json'; +import rule248 from './defense_evasion_suspicious_managedcode_host_process.json'; +import rule249 from './execution_command_shell_started_by_unusual_process.json'; +import rule250 from './defense_evasion_masquerading_as_elastic_endpoint_process.json'; +import rule251 from './defense_evasion_masquerading_suspicious_werfault_childproc.json'; +import rule252 from './defense_evasion_masquerading_werfault.json'; +import rule253 from './credential_access_key_vault_modified.json'; +import rule254 from './credential_access_mimikatz_memssp_default_logs.json'; +import rule255 from './defense_evasion_code_injection_conhost.json'; +import rule256 from './defense_evasion_network_watcher_deletion.json'; +import rule257 from './initial_access_external_guest_user_invite.json'; +import rule258 from './defense_evasion_masquerading_renamed_autoit.json'; +import rule259 from './impact_azure_automation_runbook_deleted.json'; +import rule260 from './initial_access_consent_grant_attack_via_azure_registered_application.json'; +import rule261 from './persistence_azure_conditional_access_policy_modified.json'; +import rule262 from './persistence_azure_privileged_identity_management_role_modified.json'; +import rule263 from './command_and_control_teamviewer_remote_file_copy.json'; +import rule264 from './defense_evasion_installutil_beacon.json'; +import rule265 from './defense_evasion_mshta_beacon.json'; +import rule266 from './defense_evasion_network_connection_from_windows_binary.json'; +import rule267 from './defense_evasion_rundll32_no_arguments.json'; +import rule268 from './defense_evasion_suspicious_scrobj_load.json'; +import rule269 from './defense_evasion_suspicious_wmi_script.json'; +import rule270 from './execution_ms_office_written_file.json'; +import rule271 from './execution_pdf_written_file.json'; +import rule272 from './lateral_movement_cmd_service.json'; +import rule273 from './persistence_app_compat_shim.json'; +import rule274 from './command_and_control_remote_file_copy_desktopimgdownldr.json'; +import rule275 from './command_and_control_remote_file_copy_mpcmdrun.json'; +import rule276 from './defense_evasion_execution_suspicious_explorer_winword.json'; +import rule277 from './defense_evasion_suspicious_zoom_child_process.json'; +import rule278 from './ml_linux_anomalous_compiler_activity.json'; +import rule279 from './ml_linux_anomalous_kernel_module_arguments.json'; +import rule280 from './ml_linux_anomalous_sudo_activity.json'; +import rule281 from './ml_linux_system_information_discovery.json'; +import rule282 from './ml_linux_system_network_configuration_discovery.json'; +import rule283 from './ml_linux_system_network_connection_discovery.json'; +import rule284 from './ml_linux_system_process_discovery.json'; +import rule285 from './ml_linux_system_user_discovery.json'; +import rule286 from './discovery_post_exploitation_external_ip_lookup.json'; +import rule287 from './initial_access_zoom_meeting_with_no_passcode.json'; +import rule288 from './defense_evasion_gcp_logging_sink_deletion.json'; +import rule289 from './defense_evasion_gcp_pub_sub_topic_deletion.json'; +import rule290 from './defense_evasion_gcp_firewall_rule_created.json'; +import rule291 from './defense_evasion_gcp_firewall_rule_deleted.json'; +import rule292 from './defense_evasion_gcp_firewall_rule_modified.json'; +import rule293 from './defense_evasion_gcp_logging_bucket_deletion.json'; +import rule294 from './defense_evasion_gcp_storage_bucket_permissions_modified.json'; +import rule295 from './impact_gcp_storage_bucket_deleted.json'; +import rule296 from './initial_access_gcp_iam_custom_role_creation.json'; +import rule297 from './persistence_gcp_iam_service_account_key_deletion.json'; +import rule298 from './persistence_gcp_key_created_for_service_account.json'; +import rule299 from './defense_evasion_gcp_storage_bucket_configuration_modified.json'; +import rule300 from './exfiltration_gcp_logging_sink_modification.json'; +import rule301 from './impact_gcp_iam_role_deletion.json'; +import rule302 from './impact_gcp_service_account_deleted.json'; +import rule303 from './impact_gcp_service_account_disabled.json'; +import rule304 from './impact_gcp_virtual_private_cloud_network_deleted.json'; +import rule305 from './impact_gcp_virtual_private_cloud_route_created.json'; +import rule306 from './impact_gcp_virtual_private_cloud_route_deleted.json'; +import rule307 from './ml_linux_anomalous_metadata_process.json'; +import rule308 from './ml_linux_anomalous_metadata_user.json'; +import rule309 from './ml_windows_anomalous_metadata_process.json'; +import rule310 from './ml_windows_anomalous_metadata_user.json'; +import rule311 from './persistence_gcp_service_account_created.json'; +import rule312 from './collection_gcp_pub_sub_subscription_creation.json'; +import rule313 from './collection_gcp_pub_sub_topic_creation.json'; +import rule314 from './defense_evasion_gcp_pub_sub_subscription_deletion.json'; +import rule315 from './persistence_azure_pim_user_added_global_admin.json'; +import rule316 from './command_and_control_cobalt_strike_default_teamserver_cert.json'; +import rule317 from './defense_evasion_enable_inbound_rdp_with_netsh.json'; +import rule318 from './defense_evasion_execution_lolbas_wuauclt.json'; +import rule319 from './privilege_escalation_unusual_svchost_childproc_childless.json'; +import rule320 from './command_and_control_rdp_tunnel_plink.json'; +import rule321 from './privilege_escalation_uac_bypass_winfw_mmc_hijack.json'; +import rule322 from './persistence_ms_office_addins_file.json'; +import rule323 from './discovery_adfind_command_activity.json'; +import rule324 from './discovery_security_software_wmic.json'; +import rule325 from './execution_command_shell_via_rundll32.json'; +import rule326 from './execution_suspicious_cmd_wmi.json'; +import rule327 from './lateral_movement_via_startup_folder_rdp_smb.json'; +import rule328 from './privilege_escalation_uac_bypass_com_interface_icmluautil.json'; +import rule329 from './privilege_escalation_uac_bypass_mock_windir.json'; +import rule330 from './defense_evasion_potential_processherpaderping.json'; +import rule331 from './privilege_escalation_uac_bypass_dll_sideloading.json'; +import rule332 from './execution_shared_modules_local_sxs_dll.json'; +import rule333 from './privilege_escalation_uac_bypass_com_clipup.json'; +import rule334 from './initial_access_via_explorer_suspicious_child_parent_args.json'; +import rule335 from './execution_from_unusual_directory.json'; +import rule336 from './execution_from_unusual_path_cmdline.json'; +import rule337 from './credential_access_kerberoasting_unusual_process.json'; +import rule338 from './discovery_peripheral_device.json'; +import rule339 from './lateral_movement_mount_hidden_or_webdav_share_net.json'; +import rule340 from './defense_evasion_deleting_websvr_access_logs.json'; +import rule341 from './defense_evasion_log_files_deleted.json'; +import rule342 from './defense_evasion_timestomp_touch.json'; +import rule343 from './lateral_movement_dcom_hta.json'; +import rule344 from './lateral_movement_execution_via_file_shares_sequence.json'; +import rule345 from './privilege_escalation_uac_bypass_com_ieinstal.json'; +import rule346 from './command_and_control_common_webservices.json'; +import rule347 from './command_and_control_encrypted_channel_freesslcert.json'; +import rule348 from './defense_evasion_process_termination_followed_by_deletion.json'; +import rule349 from './lateral_movement_remote_file_copy_hidden_share.json'; +import rule350 from './attempt_to_deactivate_okta_network_zone.json'; +import rule351 from './attempt_to_delete_okta_network_zone.json'; +import rule352 from './lateral_movement_dcom_mmc20.json'; +import rule353 from './lateral_movement_dcom_shellwindow_shellbrowserwindow.json'; +import rule354 from './okta_attempt_to_deactivate_okta_application.json'; +import rule355 from './okta_attempt_to_delete_okta_application.json'; +import rule356 from './okta_attempt_to_delete_okta_policy_rule.json'; +import rule357 from './okta_attempt_to_modify_okta_application.json'; +import rule358 from './persistence_administrator_role_assigned_to_okta_user.json'; +import rule359 from './lateral_movement_executable_tool_transfer_smb.json'; +import rule360 from './command_and_control_dns_tunneling_nslookup.json'; +import rule361 from './lateral_movement_execution_from_tsclient_mup.json'; +import rule362 from './lateral_movement_rdp_sharprdp_target.json'; +import rule363 from './defense_evasion_clearing_windows_security_logs.json'; +import rule364 from './persistence_google_workspace_api_access_granted_via_domain_wide_delegation_of_authority.json'; +import rule365 from './execution_suspicious_short_program_name.json'; +import rule366 from './lateral_movement_incoming_wmi.json'; +import rule367 from './persistence_via_hidden_run_key_valuename.json'; +import rule368 from './credential_access_potential_ssh_bruteforce.json'; +import rule369 from './credential_access_promt_for_pwd_via_osascript.json'; +import rule370 from './lateral_movement_remote_services.json'; +import rule371 from './application_added_to_google_workspace_domain.json'; +import rule372 from './domain_added_to_google_workspace_trusted_domains.json'; +import rule373 from './execution_suspicious_image_load_wmi_ms_office.json'; +import rule374 from './execution_suspicious_powershell_imgload.json'; +import rule375 from './google_workspace_admin_role_deletion.json'; +import rule376 from './google_workspace_mfa_enforcement_disabled.json'; +import rule377 from './google_workspace_policy_modified.json'; +import rule378 from './mfa_disabled_for_google_workspace_organization.json'; +import rule379 from './persistence_evasion_registry_ifeo_injection.json'; +import rule380 from './persistence_google_workspace_admin_role_assigned_to_user.json'; +import rule381 from './persistence_google_workspace_custom_admin_role_created.json'; +import rule382 from './persistence_google_workspace_role_modified.json'; +import rule383 from './persistence_suspicious_image_load_scheduled_task_ms_office.json'; +import rule384 from './defense_evasion_masquerading_trusted_directory.json'; +import rule385 from './exfiltration_microsoft_365_exchange_transport_rule_creation.json'; +import rule386 from './initial_access_microsoft_365_exchange_safelinks_disabled.json'; +import rule387 from './microsoft_365_exchange_dkim_signing_config_disabled.json'; +import rule388 from './persistence_appcertdlls_registry.json'; +import rule389 from './persistence_appinitdlls_registry.json'; +import rule390 from './persistence_registry_uncommon.json'; +import rule391 from './persistence_run_key_and_startup_broad.json'; +import rule392 from './persistence_services_registry.json'; +import rule393 from './persistence_startup_folder_file_written_by_suspicious_process.json'; +import rule394 from './persistence_startup_folder_scripts.json'; +import rule395 from './persistence_suspicious_com_hijack_registry.json'; +import rule396 from './persistence_via_lsa_security_support_provider_registry.json'; +import rule397 from './defense_evasion_microsoft_365_exchange_malware_filter_policy_deletion.json'; +import rule398 from './defense_evasion_microsoft_365_exchange_malware_filter_rule_mod.json'; +import rule399 from './defense_evasion_microsoft_365_exchange_safe_attach_rule_disabled.json'; +import rule400 from './exfiltration_microsoft_365_exchange_transport_rule_mod.json'; +import rule401 from './initial_access_microsoft_365_exchange_anti_phish_policy_deletion.json'; +import rule402 from './initial_access_microsoft_365_exchange_anti_phish_rule_mod.json'; +import rule403 from './lateral_movement_suspicious_rdp_client_imageload.json'; +import rule404 from './persistence_runtime_run_key_startup_susp_procs.json'; +import rule405 from './persistence_suspicious_scheduled_task_runtime.json'; +import rule406 from './defense_evasion_microsoft_365_exchange_dlp_policy_removed.json'; +import rule407 from './lateral_movement_scheduled_task_target.json'; +import rule408 from './persistence_microsoft_365_exchange_management_role_assignment.json'; +import rule409 from './persistence_microsoft_365_teams_guest_access_enabled.json'; +import rule410 from './credential_access_dump_registry_hives.json'; +import rule411 from './defense_evasion_scheduledjobs_at_protocol_enabled.json'; +import rule412 from './persistence_ms_outlook_vba_template.json'; +import rule413 from './persistence_suspicious_service_created_registry.json'; +import rule414 from './privilege_escalation_named_pipe_impersonation.json'; +import rule415 from './credential_access_cmdline_dump_tool.json'; +import rule416 from './credential_access_copy_ntds_sam_volshadowcp_cmdline.json'; +import rule417 from './credential_access_lsass_memdump_file_created.json'; +import rule418 from './lateral_movement_incoming_winrm_shell_execution.json'; +import rule419 from './lateral_movement_powershell_remoting_target.json'; +import rule420 from './command_and_control_port_forwarding_added_registry.json'; +import rule421 from './defense_evasion_hide_encoded_executable_registry.json'; +import rule422 from './lateral_movement_rdp_enabled_registry.json'; +import rule423 from './privilege_escalation_printspooler_registry_copyfiles.json'; +import rule424 from './privilege_escalation_rogue_windir_environment_var.json'; +import rule425 from './initial_access_scripts_process_started_via_wmi.json'; +import rule426 from './command_and_control_iexplore_via_com.json'; +import rule427 from './command_and_control_remote_file_copy_scripts.json'; +import rule428 from './persistence_local_scheduled_task_scripting.json'; +import rule429 from './persistence_startup_folder_file_written_by_unsigned_process.json'; +import rule430 from './command_and_control_remote_file_copy_powershell.json'; +import rule431 from './credential_access_microsoft_365_brute_force_user_account_attempt.json'; +import rule432 from './microsoft_365_teams_custom_app_interaction_allowed.json'; +import rule433 from './persistence_microsoft_365_teams_external_access_enabled.json'; +import rule434 from './credential_access_microsoft_365_potential_password_spraying_attack.json'; +import rule435 from './impact_stop_process_service_threshold.json'; +import rule436 from './collection_winrar_encryption.json'; +import rule437 from './defense_evasion_unusual_dir_ads.json'; +import rule438 from './discovery_admin_recon.json'; +import rule439 from './discovery_file_dir_discovery.json'; +import rule440 from './discovery_net_view.json'; +import rule441 from './discovery_remote_system_discovery_commands_windows.json'; +import rule442 from './persistence_via_windows_management_instrumentation_event_subscription.json'; +import rule443 from './execution_scripting_osascript_exec_followed_by_netcon.json'; +import rule444 from './execution_shell_execution_via_apple_scripting.json'; +import rule445 from './persistence_creation_change_launch_agents_file.json'; +import rule446 from './persistence_creation_modif_launch_deamon_sequence.json'; +import rule447 from './persistence_folder_action_scripts_runtime.json'; +import rule448 from './persistence_login_logout_hooks_defaults.json'; +import rule449 from './privilege_escalation_explicit_creds_via_scripting.json'; +import rule450 from './command_and_control_sunburst_c2_activity_detected.json'; +import rule451 from './defense_evasion_azure_application_credential_modification.json'; +import rule452 from './defense_evasion_azure_service_principal_addition.json'; +import rule453 from './defense_evasion_solarwinds_backdoor_service_disabled_via_registry.json'; +import rule454 from './execution_apt_solarwinds_backdoor_child_cmd_powershell.json'; +import rule455 from './execution_apt_solarwinds_backdoor_unusual_child_processes.json'; +import rule456 from './initial_access_azure_active_directory_powershell_signin.json'; +import rule457 from './collection_email_powershell_exchange_mailbox.json'; +import rule458 from './execution_scheduled_task_powershell_source.json'; +import rule459 from './persistence_powershell_exch_mailbox_activesync_add_device.json'; +import rule460 from './persistence_docker_shortcuts_plist_modification.json'; +import rule461 from './persistence_evasion_hidden_local_account_creation.json'; +import rule462 from './persistence_finder_sync_plugin_pluginkit.json'; +import rule463 from './discovery_security_software_grep.json'; +import rule464 from './credential_access_cookies_chromium_browsers_debugging.json'; +import rule465 from './credential_access_ssh_backdoor_log.json'; +import rule466 from './persistence_credential_access_modify_auth_module_or_config.json'; +import rule467 from './persistence_credential_access_modify_ssh_binaries.json'; +import rule468 from './credential_access_collection_sensitive_files.json'; +import rule469 from './persistence_ssh_authorized_keys_modification.json'; +import rule470 from './defense_evasion_defender_disabled_via_registry.json'; +import rule471 from './defense_evasion_privacy_controls_tcc_database_modification.json'; +import rule472 from './execution_initial_access_suspicious_browser_childproc.json'; +import rule473 from './execution_script_via_automator_workflows.json'; +import rule474 from './persistence_modification_sublime_app_plugin_or_script.json'; +import rule475 from './privilege_escalation_applescript_with_admin_privs.json'; +import rule476 from './credential_access_dumping_keychain_security.json'; +import rule477 from './initial_access_azure_active_directory_high_risk_signin.json'; +import rule478 from './initial_access_suspicious_mac_ms_office_child_process.json'; +import rule479 from './credential_access_mitm_localhost_webproxy.json'; +import rule480 from './persistence_kde_autostart_modification.json'; +import rule481 from './persistence_user_account_added_to_privileged_group_ad.json'; +import rule482 from './defense_evasion_attempt_to_disable_gatekeeper.json'; +import rule483 from './defense_evasion_sandboxed_office_app_suspicious_zip_file.json'; +import rule484 from './persistence_emond_rules_file_creation.json'; +import rule485 from './persistence_emond_rules_process_execution.json'; +import rule486 from './discovery_users_domain_built_in_commands.json'; +import rule487 from './execution_pentest_eggshell_remote_admin_tool.json'; +import rule488 from './defense_evasion_install_root_certificate.json'; +import rule489 from './persistence_credential_access_authorization_plugin_creation.json'; +import rule490 from './persistence_directory_services_plugins_modification.json'; +import rule491 from './defense_evasion_modify_environment_launchctl.json'; +import rule492 from './defense_evasion_safari_config_change.json'; +import rule493 from './defense_evasion_apple_softupdates_modification.json'; +import rule494 from './credential_access_mod_wdigest_security_provider.json'; +import rule495 from './credential_access_saved_creds_vaultcmd.json'; +import rule496 from './defense_evasion_file_creation_mult_extension.json'; +import rule497 from './execution_enumeration_via_wmiprvse.json'; +import rule498 from './execution_suspicious_jar_child_process.json'; +import rule499 from './persistence_shell_profile_modification.json'; +import rule500 from './persistence_suspicious_calendar_modification.json'; +import rule501 from './persistence_time_provider_mod.json'; +import rule502 from './privilege_escalation_exploit_adobe_acrobat_updater.json'; +import rule503 from './defense_evasion_sip_provider_mod.json'; +import rule504 from './execution_com_object_xwizard.json'; +import rule505 from './privilege_escalation_disable_uac_registry.json'; +import rule506 from './defense_evasion_unusual_ads_file_creation.json'; +import rule507 from './persistence_loginwindow_plist_modification.json'; +import rule508 from './persistence_periodic_tasks_file_mdofiy.json'; +import rule509 from './persistence_via_atom_init_file_modification.json'; +import rule510 from './privilege_escalation_lsa_auth_package.json'; +import rule511 from './privilege_escalation_port_monitor_print_pocessor_abuse.json'; +import rule512 from './credential_access_dumping_hashes_bi_cmds.json'; +import rule513 from './lateral_movement_mounting_smb_share.json'; +import rule514 from './privilege_escalation_echo_nopasswd_sudoers.json'; +import rule515 from './privilege_escalation_ld_preload_shared_object_modif.json'; +import rule516 from './privilege_escalation_root_crontab_filemod.json'; +import rule517 from './defense_evasion_create_mod_root_certificate.json'; +import rule518 from './privilege_escalation_sudo_buffer_overflow.json'; +import rule519 from './execution_installer_spawned_network_event.json'; +import rule520 from './initial_access_suspicious_ms_exchange_files.json'; +import rule521 from './initial_access_suspicious_ms_exchange_process.json'; +import rule522 from './initial_access_suspicious_ms_exchange_worker_child_process.json'; +import rule523 from './persistence_evasion_registry_startup_shell_folder_modified.json'; +import rule524 from './persistence_local_scheduled_job_creation.json'; +import rule525 from './persistence_via_wmi_stdregprov_run_services.json'; +import rule526 from './credential_access_persistence_network_logon_provider_modification.json'; +import rule527 from './lateral_movement_defense_evasion_lanman_nullsessionpipe_modification.json'; +import rule528 from './collection_microsoft_365_new_inbox_rule.json'; +import rule529 from './ml_high_count_network_denies.json'; +import rule530 from './ml_high_count_network_events.json'; +import rule531 from './ml_rare_destination_country.json'; +import rule532 from './ml_spike_in_traffic_to_a_country.json'; +import rule533 from './command_and_control_tunneling_via_earthworm.json'; +import rule534 from './lateral_movement_evasion_rdp_shadowing.json'; +import rule535 from './threat_intel_module_match.json'; +import rule536 from './exfiltration_ec2_vm_export_failure.json'; +import rule537 from './exfiltration_ec2_full_network_packet_capture_detected.json'; +import rule538 from './impact_azure_service_principal_credentials_added.json'; +import rule539 from './persistence_ec2_security_group_configuration_change_detection.json'; +import rule540 from './defense_evasion_disabling_windows_logs.json'; +import rule541 from './persistence_route_53_domain_transfer_lock_disabled.json'; +import rule542 from './persistence_route_53_domain_transferred_to_another_account.json'; +import rule543 from './initial_access_okta_user_attempted_unauthorized_access.json'; +import rule544 from './credential_access_user_excessive_sso_logon_errors.json'; +import rule545 from './persistence_exchange_suspicious_mailbox_right_delegation.json'; +import rule546 from './privilege_escalation_new_or_modified_federation_domain.json'; +import rule547 from './privilege_escalation_sts_assumerole_usage.json'; +import rule548 from './privilege_escalation_sts_getsessiontoken_abuse.json'; +import rule549 from './defense_evasion_suspicious_execution_from_mounted_device.json'; +import rule550 from './defense_evasion_unusual_network_connection_via_dllhost.json'; +import rule551 from './defense_evasion_amsienable_key_mod.json'; +import rule552 from './impact_rds_group_deletion.json'; +import rule553 from './persistence_rds_group_creation.json'; +import rule554 from './persistence_route_table_created.json'; +import rule555 from './persistence_route_table_modified_or_deleted.json'; +import rule556 from './exfiltration_rds_snapshot_export.json'; +import rule557 from './persistence_rds_instance_creation.json'; +import rule558 from './privilege_escalation_gcp_kubernetes_rolebindings_created_or_patched.json'; +import rule559 from './ml_auth_rare_hour_for_a_user_to_logon.json'; +import rule560 from './ml_auth_rare_source_ip_for_a_user.json'; +import rule561 from './ml_auth_rare_user_logon.json'; +import rule562 from './ml_auth_spike_in_failed_logon_events.json'; +import rule563 from './ml_auth_spike_in_logon_events.json'; +import rule564 from './ml_auth_spike_in_logon_events_from_a_source_ip.json'; +import rule565 from './privilege_escalation_cyberarkpas_error_audit_event_promotion.json'; +import rule566 from './privilege_escalation_cyberarkpas_recommended_events_to_monitor_promotion.json'; +import rule567 from './defense_evasion_kubernetes_events_deleted.json'; +import rule568 from './impact_kubernetes_pod_deleted.json'; +import rule569 from './exfiltration_rds_snapshot_restored.json'; +import rule570 from './privilege_escalation_printspooler_malicious_driver_file_changes.json'; +import rule571 from './privilege_escalation_printspooler_malicious_registry_modification.json'; +import rule572 from './privilege_escalation_printspooler_suspicious_file_deletion.json'; +import rule573 from './privilege_escalation_unusual_printspooler_childprocess.json'; +import rule574 from './defense_evasion_disabling_windows_defender_powershell.json'; +import rule575 from './defense_evasion_enable_network_discovery_with_netsh.json'; +import rule576 from './defense_evasion_execution_windefend_unusual_path.json'; +import rule577 from './defense_evasion_agent_spoofing_mismatched_id.json'; +import rule578 from './defense_evasion_agent_spoofing_multiple_hosts.json'; +import rule579 from './defense_evasion_parent_process_pid_spoofing.json'; +import rule580 from './impact_microsoft_365_potential_ransomware_activity.json'; +import rule581 from './impact_microsoft_365_unusual_volume_of_file_deletion.json'; +import rule582 from './initial_access_microsoft_365_user_restricted_from_sending_email.json'; +import rule583 from './defense_evasion_elasticache_security_group_creation.json'; +import rule584 from './defense_evasion_elasticache_security_group_modified_or_deleted.json'; +import rule585 from './impact_volume_shadow_copy_deletion_via_powershell.json'; +import rule586 from './persistence_route_53_hosted_zone_associated_with_a_vpc.json'; +import rule587 from './defense_evasion_defender_exclusion_via_powershell.json'; +import rule588 from './defense_evasion_dns_over_https_enabled.json'; +import rule589 from './defense_evasion_whitespace_padding_in_command_line.json'; +import rule590 from './defense_evasion_frontdoor_firewall_policy_deletion.json'; +import rule591 from './credential_access_azure_full_network_packet_capture_detected.json'; +import rule592 from './persistence_webshell_detection.json'; +import rule593 from './impact_efs_filesystem_or_mount_deleted.json'; +import rule594 from './defense_evasion_execution_control_panel_suspicious_args.json'; +import rule595 from './defense_evasion_azure_blob_permissions_modified.json'; +import rule596 from './privilege_escalation_aws_suspicious_saml_activity.json'; +import rule597 from './credential_access_potential_lsa_memdump_via_mirrordump.json'; +import rule598 from './discovery_virtual_machine_fingerprinting_grep.json'; +import rule599 from './impact_backup_file_deletion.json'; +import rule600 from './credential_access_posh_minidump.json'; +import rule601 from './persistence_screensaver_engine_unexpected_child_process.json'; +import rule602 from './persistence_screensaver_plist_file_modification.json'; +import rule603 from './defense_evasion_suspicious_process_access_direct_syscall.json'; +import rule604 from './discovery_posh_suspicious_api_functions.json'; +import rule605 from './execution_posh_portable_executable.json'; +import rule606 from './impact_aws_eventbridge_rule_disabled_or_deleted.json'; +import rule607 from './collection_posh_audio_capture.json'; +import rule608 from './persistence_via_bits_job_notify_command.json'; export const rawRules = [ rule1, @@ -1190,4 +1209,23 @@ export const rawRules = [ rule587, rule588, rule589, + rule590, + rule591, + rule592, + rule593, + rule594, + rule595, + rule596, + rule597, + rule598, + rule599, + rule600, + rule601, + rule602, + rule603, + rule604, + rule605, + rule606, + rule607, + rule608, ]; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_suspicious_ms_exchange_worker_child_process.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_suspicious_ms_exchange_worker_child_process.json index a095c0ab582d4..ea4d8c6eae210 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_suspicious_ms_exchange_worker_child_process.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_suspicious_ms_exchange_worker_child_process.json @@ -12,7 +12,7 @@ "language": "eql", "license": "Elastic License v2", "name": "Microsoft Exchange Worker Spawning Suspicious Processes", - "query": "process where event.type == \"start\" and\n process.parent.name : \"w3wp.exe\" and process.parent.args : \"MSExchange*AppPool\" and\n (process.name : (\"cmd.exe\", \"powershell.exe\", \"pwsh.exe\") or\n process.pe.original_file_name : (\"cmd.exe\", \"powershell.exe\", \"pwsh.exe\"))\n", + "query": "process where event.type == \"start\" and\n process.parent.name : \"w3wp.exe\" and process.parent.args : \"MSExchange*AppPool\" and\n (process.name : (\"cmd.exe\", \"powershell.exe\", \"pwsh.exe\", \"powershell_ise.exe\") or\n process.pe.original_file_name in (\"cmd.exe\", \"powershell.exe\", \"pwsh.dll\", \"powershell_ise.exe\"))\n", "references": [ "https://www.microsoft.com/security/blog/2021/03/02/hafnium-targeting-exchange-servers", "https://www.volexity.com/blog/2021/03/02/active-exploitation-of-microsoft-exchange-zero-day-vulnerabilities", @@ -47,5 +47,5 @@ ], "timestamp_override": "event.ingested", "type": "eql", - "version": 1 + "version": 2 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_local_scheduled_task_creation.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_local_scheduled_task_creation.json index 8b6fa370f4ab9..3c9626dcf5513 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_local_scheduled_task_creation.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_local_scheduled_task_creation.json @@ -15,7 +15,7 @@ "language": "eql", "license": "Elastic License v2", "name": "Local Scheduled Task Creation", - "query": "sequence with maxspan=1m\n [process where event.type != \"end\" and\n ((process.name : (\"cmd.exe\", \"wscript.exe\", \"rundll32.exe\", \"regsvr32.exe\", \"wmic.exe\", \"mshta.exe\",\n \"powershell.exe\", \"pwsh.exe\", \"WmiPrvSe.exe\", \"wsmprovhost.exe\", \"winrshost.exe\") or\n process.pe.original_file_name : (\"cmd.exe\", \"wscript.exe\", \"rundll32.exe\", \"regsvr32.exe\", \"wmic.exe\", \"mshta.exe\",\n \"powershell.exe\", \"pwsh.exe\", \"WmiPrvSe.exe\", \"wsmprovhost.exe\",\n \"winrshost.exe\")) or\n process.code_signature.trusted == false)] by process.entity_id\n [process where event.type == \"start\" and\n (process.name : \"schtasks.exe\" or process.pe.original_file_name == \"schtasks.exe\") and\n process.args : (\"/create\", \"-create\") and process.args : (\"/RU\", \"/SC\", \"/TN\", \"/TR\", \"/F\", \"/XML\") and\n /* exclude SYSTEM SIDs - look for task creations by non-SYSTEM user */\n not user.id : (\"S-1-5-18\", \"S-1-5-19\", \"S-1-5-20\")] by process.parent.entity_id\n", + "query": "sequence with maxspan=1m\n [process where event.type != \"end\" and\n ((process.name : (\"cmd.exe\", \"wscript.exe\", \"rundll32.exe\", \"regsvr32.exe\", \"wmic.exe\", \"mshta.exe\",\n \"powershell.exe\", \"pwsh.exe\", \"powershell_ise.exe\", \"WmiPrvSe.exe\", \"wsmprovhost.exe\", \"winrshost.exe\") or\n process.pe.original_file_name : (\"cmd.exe\", \"wscript.exe\", \"rundll32.exe\", \"regsvr32.exe\", \"wmic.exe\", \"mshta.exe\",\n \"powershell.exe\", \"pwsh.dll\", \"powershell_ise.exe\", \"WmiPrvSe.exe\", \"wsmprovhost.exe\",\n \"winrshost.exe\")) or\n process.code_signature.trusted == false)] by process.entity_id\n [process where event.type == \"start\" and\n (process.name : \"schtasks.exe\" or process.pe.original_file_name == \"schtasks.exe\") and\n process.args : (\"/create\", \"-create\") and process.args : (\"/RU\", \"/SC\", \"/TN\", \"/TR\", \"/F\", \"/XML\") and\n /* exclude SYSTEM SIDs - look for task creations by non-SYSTEM user */\n not user.id : (\"S-1-5-18\", \"S-1-5-19\", \"S-1-5-20\")] by process.parent.entity_id\n", "risk_score": 21, "rule_id": "afcce5ad-65de-4ed2-8516-5e093d3ac99a", "severity": "low", @@ -52,5 +52,5 @@ ], "timestamp_override": "event.ingested", "type": "eql", - "version": 8 + "version": 9 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_local_scheduled_task_scripting.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_local_scheduled_task_scripting.json index 128fdd9de5575..1489cb58d0110 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_local_scheduled_task_scripting.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_local_scheduled_task_scripting.json @@ -16,7 +16,7 @@ "license": "Elastic License v2", "name": "Scheduled Task Created by a Windows Script", "note": "## Triage and analysis\n\nDecode the base64 encoded Tasks Actions registry value to investigate the task's configured action.", - "query": "sequence by host.id with maxspan = 30s\n [library where dll.name : \"taskschd.dll\" and process.name : (\"cscript.exe\", \"wscript.exe\", \"powershell.exe\")]\n [registry where registry.path : \"HKLM\\\\SOFTWARE\\\\Microsoft\\\\Windows NT\\\\CurrentVersion\\\\Schedule\\\\TaskCache\\\\Tasks\\\\*\\\\Actions\"]\n", + "query": "sequence by host.id with maxspan = 30s\n [library where dll.name : \"taskschd.dll\" and process.name : (\"cscript.exe\", \"wscript.exe\", \"powershell.exe\", \"pwsh.exe\", \"powershell_ise.exe\")]\n [registry where registry.path : \"HKLM\\\\SOFTWARE\\\\Microsoft\\\\Windows NT\\\\CurrentVersion\\\\Schedule\\\\TaskCache\\\\Tasks\\\\*\\\\Actions\"]\n", "risk_score": 47, "rule_id": "689b9d57-e4d5-4357-ad17-9c334609d79a", "severity": "medium", @@ -52,5 +52,5 @@ } ], "type": "eql", - "version": 4 + "version": 5 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_powershell_exch_mailbox_activesync_add_device.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_powershell_exch_mailbox_activesync_add_device.json index 75044e20ca5fd..6973f97220bcb 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_powershell_exch_mailbox_activesync_add_device.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_powershell_exch_mailbox_activesync_add_device.json @@ -15,7 +15,7 @@ "language": "eql", "license": "Elastic License v2", "name": "New ActiveSyncAllowedDeviceID Added via PowerShell", - "query": "process where event.type in (\"start\", \"process_started\") and\n process.name: (\"powershell.exe\", \"pwsh.exe\") and process.args : \"Set-CASMailbox*ActiveSyncAllowedDeviceIDs*\"\n", + "query": "process where event.type in (\"start\", \"process_started\") and\n process.name: (\"powershell.exe\", \"pwsh.exe\", \"powershell_ise.exe\") and process.args : \"Set-CASMailbox*ActiveSyncAllowedDeviceIDs*\"\n", "references": [ "https://www.volexity.com/blog/2020/12/14/dark-halo-leverages-solarwinds-compromise-to-breach-organizations/", "https://docs.microsoft.com/en-us/powershell/module/exchange/set-casmailbox?view=exchange-ps" @@ -56,5 +56,5 @@ ], "timestamp_override": "event.ingested", "type": "eql", - "version": 5 + "version": 6 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_route_53_hosted_zone_associated_with_a_vpc.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_route_53_hosted_zone_associated_with_a_vpc.json new file mode 100644 index 0000000000000..93b8da585c9ff --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_route_53_hosted_zone_associated_with_a_vpc.json @@ -0,0 +1,54 @@ +{ + "author": [ + "Austin Songer" + ], + "description": "Identifies when a Route53 private hosted zone has been associated with VPC.", + "false_positives": [ + "A private hosted zone may be asssociated with a VPC by a system or network administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. If known behavior is causing false positives, it can be exempted from the rule." + ], + "from": "now-60m", + "index": [ + "filebeat-*", + "logs-aws*" + ], + "interval": "10m", + "language": "kuery", + "license": "Elastic License v2", + "name": "AWS Route53 private hosted zone associated with a VPC", + "note": "## Config\n\nThe AWS Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", + "query": "event.dataset:aws.cloudtrail and event.provider:route53.amazonaws.com and event.action:AssociateVPCWithHostedZone and \nevent.outcome:success\n", + "references": [ + "https://docs.aws.amazon.com/Route53/latest/APIReference/API_AssociateVPCWithHostedZone.html" + ], + "risk_score": 21, + "rule_id": "e3c27562-709a-42bd-82f2-3ed926cced19", + "severity": "low", + "tags": [ + "Elastic", + "Cloud", + "AWS", + "Continuous Monitoring", + "SecOps", + "Asset Visibility" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0003", + "name": "Persistence", + "reference": "https://attack.mitre.org/tactics/TA0003/" + }, + "technique": [ + { + "id": "T1098", + "name": "Account Manipulation", + "reference": "https://attack.mitre.org/techniques/T1098/" + } + ] + } + ], + "timestamp_override": "event.ingested", + "type": "query", + "version": 1 +} diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_route_table_created.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_route_table_created.json new file mode 100644 index 0000000000000..1784c34feb085 --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_route_table_created.json @@ -0,0 +1,51 @@ +{ + "author": [ + "Elastic", + "Austin Songer" + ], + "description": "Identifies when an AWS Route Table has been created.", + "false_positives": [ + "Route Table being created may be done by a system or network administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. Route Table being created from unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule. Automated processes that uses Terraform may lead to false positives." + ], + "from": "now-60m", + "index": [ + "filebeat-*", + "logs-aws*" + ], + "interval": "10m", + "language": "kuery", + "license": "Elastic License v2", + "name": "AWS Route Table Created", + "note": "## Config\n\nThe AWS Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", + "query": "event.dataset:aws.cloudtrail and event.provider:cloudtrail.amazonaws.com and event.action:(CreateRoute or CreateRouteTable) and \nevent.outcome:success\n", + "references": [ + "https://docs.datadoghq.com/security_platform/default_rules/cloudtrail-aws-route-table-modified/", + "https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_CreateRoute.html", + "https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_CreateRouteTable" + ], + "risk_score": 21, + "rule_id": "e12c0318-99b1-44f2-830c-3a38a43207ca", + "severity": "low", + "tags": [ + "Elastic", + "Cloud", + "AWS", + "Continuous Monitoring", + "SecOps", + "Network Security" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0003", + "name": "Persistence", + "reference": "https://attack.mitre.org/tactics/TA0003/" + }, + "technique": [] + } + ], + "timestamp_override": "event.ingested", + "type": "query", + "version": 1 +} diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_system_shells_via_services.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_system_shells_via_services.json index 709396a5eaf2f..4d069dd56132e 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_system_shells_via_services.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_system_shells_via_services.json @@ -12,7 +12,7 @@ "language": "eql", "license": "Elastic License v2", "name": "System Shells via Services", - "query": "process where event.type in (\"start\", \"process_started\") and\n process.parent.name : \"services.exe\" and\n process.name : (\"cmd.exe\", \"powershell.exe\") and\n \n /* Third party FP's */\n not process.args : \"NVDisplay.ContainerLocalSystem\"\n", + "query": "process where event.type in (\"start\", \"process_started\") and\n process.parent.name : \"services.exe\" and\n process.name : (\"cmd.exe\", \"powershell.exe\", \"pwsh.exe\", \"powershell_ise.exe\") and\n \n /* Third party FP's */\n not process.args : \"NVDisplay.ContainerLocalSystem\"\n", "risk_score": 47, "rule_id": "0022d47d-39c7-4f69-a232-4fe9dc7a3acd", "severity": "medium", @@ -49,5 +49,5 @@ ], "timestamp_override": "event.ingested", "type": "eql", - "version": 9 + "version": 10 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_webshell_detection.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_webshell_detection.json index 8da3be0b69d91..3d8a9fc545b1f 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_webshell_detection.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_webshell_detection.json @@ -16,7 +16,7 @@ "license": "Elastic License v2", "name": "Webshell Detection: Script Process Child of Common Web Processes", "note": "## Triage and analysis\n\nDetections should be investigated to identify if the activity corresponds to legitimate activity. As this rule detects post-exploitation process activity, investigations into this should be prioritized.", - "query": "process where event.type == \"start\" and\n process.parent.name : (\"w3wp.exe\", \"httpd.exe\", \"nginx.exe\", \"php.exe\", \"php-cgi.exe\", \"tomcat.exe\") and \n process.name : (\"cmd.exe\", \"cscript.exe\", \"powershell.exe\", \"pwsh.exe\", \"wmic.exe\", \"wscript.exe\")\n", + "query": "process where event.type == \"start\" and\n process.parent.name : (\"w3wp.exe\", \"httpd.exe\", \"nginx.exe\", \"php.exe\", \"php-cgi.exe\", \"tomcat.exe\") and \n process.name : (\"cmd.exe\", \"cscript.exe\", \"powershell.exe\", \"pwsh.exe\", \"powershell_ise.exe\", \"wmic.exe\", \"wscript.exe\")\n", "references": [ "https://www.microsoft.com/security/blog/2020/02/04/ghost-in-the-shell-investigating-web-shell-attacks/" ], @@ -71,5 +71,5 @@ ], "timestamp_override": "event.ingested", "type": "eql", - "version": 2 + "version": 3 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_aws_suspicious_saml_activity.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_aws_suspicious_saml_activity.json new file mode 100644 index 0000000000000..22e3aa6cce8d9 --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_aws_suspicious_saml_activity.json @@ -0,0 +1,76 @@ +{ + "author": [ + "Austin Songer" + ], + "description": "Identifies when SAML activity has occurred in AWS. An adversary could manipulate SAML to maintain access to the target.", + "false_positives": [ + "SAML Provider could be updated by a system administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. SAML Provider being updated from unfamiliar users should be investigated. If known behavior is causing false positives, it can be exempted from the rule." + ], + "from": "now-25m", + "index": [ + "filebeat-*", + "logs-aws*" + ], + "language": "kuery", + "license": "Elastic License v2", + "name": "AWS SAML Activity", + "note": "## Config\n\nThe AWS Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", + "query": "event.dataset:aws.cloudtrail and event.provider:(iam.amazonaws.com or sts.amazonaws.com) and event.action:(Assumerolewithsaml or \nUpdateSAMLProvider) and event.outcome:success\n", + "references": [ + "https://docs.aws.amazon.com/IAM/latest/APIReference/API_UpdateSAMLProvider.html", + "https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRoleWithSAML.html" + ], + "risk_score": 21, + "rule_id": "979729e7-0c52-4c4c-b71e-88103304a79f", + "severity": "low", + "tags": [ + "Elastic", + "Cloud", + "AWS", + "Continuous Monitoring", + "SecOps", + "Identity and Access" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0005", + "name": "Defense Evasion", + "reference": "https://attack.mitre.org/tactics/TA0005/" + }, + "technique": [ + { + "id": "T1550", + "name": "Use Alternate Authentication Material", + "reference": "https://attack.mitre.org/techniques/T1550/", + "subtechnique": [ + { + "id": "T1550.001", + "name": "Application Access Token", + "reference": "https://attack.mitre.org/techniques/T1550/001/" + } + ] + } + ] + }, + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0001", + "name": "Initial Access", + "reference": "https://attack.mitre.org/tactics/TA0001/" + }, + "technique": [ + { + "id": "T1078", + "name": "Valid Accounts", + "reference": "https://attack.mitre.org/techniques/T1078/" + } + ] + } + ], + "timestamp_override": "event.ingested", + "type": "query", + "version": 1 +} diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_gcp_kubernetes_rolebindings_created_or_patched.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_gcp_kubernetes_rolebindings_created_or_patched.json new file mode 100644 index 0000000000000..fbba3ff429579 --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_gcp_kubernetes_rolebindings_created_or_patched.json @@ -0,0 +1,47 @@ +{ + "author": [ + "Elastic", + "Austin Songer" + ], + "description": "Identifies the creation or patching of potential malicious rolebinding. You can assign these roles to Kubernetes subjects (users, groups, or service accounts) with role bindings and cluster role bindings.", + "from": "now-20m", + "index": [ + "filebeat-*", + "logs-gcp*" + ], + "language": "kuery", + "license": "Elastic License v2", + "name": "GCP Kubernetes Rolebindings Created or Patched", + "note": "## Config\n\nThe GCP Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", + "query": "event.dataset:(googlecloud.audit or gcp.audit) and event.action:(io.k8s.authorization.rbac.v*.clusterrolebindings.create or \nio.k8s.authorization.rbac.v*.rolebindings.create or io.k8s.authorization.rbac.v*.clusterrolebindings.patch or \nio.k8s.authorization.rbac.v*.rolebindings.patch) and event.outcome:success\n", + "references": [ + "https://cloud.google.com/kubernetes-engine/docs/how-to/audit-logging", + "https://unofficial-kubernetes.readthedocs.io/en/latest/admin/authorization/rbac/", + "https://cloud.google.com/kubernetes-engine/docs/how-to/role-based-access-control" + ], + "risk_score": 47, + "rule_id": "2f0bae2d-bf20-4465-be86-1311addebaa3", + "severity": "medium", + "tags": [ + "Elastic", + "Cloud", + "GCP", + "Continuous Monitoring", + "SecOps", + "Configuration Audit" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0004", + "name": "Privilege Escalation", + "reference": "https://attack.mitre.org/tactics/TA0004/" + }, + "technique": [] + } + ], + "timestamp_override": "event.ingested", + "type": "query", + "version": 1 +} diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_sts_assumerole_usage.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_sts_assumerole_usage.json new file mode 100644 index 0000000000000..37fcef44719af --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_sts_assumerole_usage.json @@ -0,0 +1,74 @@ +{ + "author": [ + "Austin Songer" + ], + "description": "Identifies the use of AssumeRole. AssumeRole returns a set of temporary security credentials that can be used to access AWS resources. An adversary could use those credentials to move laterally and escalate privileges.", + "false_positives": [ + "Automated processes that uses Terraform may lead to false positives." + ], + "index": [ + "filebeat-*", + "logs-aws*" + ], + "language": "kuery", + "license": "Elastic License v2", + "name": "AWS Security Token Service (STS) AssumeRole Usage", + "note": "## Config\n\nThe AWS Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", + "query": "event.dataset:aws.cloudtrail and event.provider:sts.amazonaws.com and event.action:AssumedRole and \naws.cloudtrail.user_identity.session_context.session_issuer.type:Role and event.outcome:success\n", + "references": [ + "https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html" + ], + "risk_score": 21, + "rule_id": "93075852-b0f5-4b8b-89c3-a226efae5726", + "severity": "low", + "tags": [ + "Elastic", + "Cloud", + "AWS", + "Continuous Monitoring", + "SecOps", + "Identity and Access" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0004", + "name": "Privilege Escalation", + "reference": "https://attack.mitre.org/tactics/TA0004/" + }, + "technique": [ + { + "id": "T1548", + "name": "Abuse Elevation Control Mechanism", + "reference": "https://attack.mitre.org/techniques/T1548/" + } + ] + }, + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0008", + "name": "Lateral Movement", + "reference": "https://attack.mitre.org/tactics/TA0008/" + }, + "technique": [ + { + "id": "T1550", + "name": "Use Alternate Authentication Material", + "reference": "https://attack.mitre.org/techniques/T1550/", + "subtechnique": [ + { + "id": "T1550.001", + "name": "Application Access Token", + "reference": "https://attack.mitre.org/techniques/T1550/001/" + } + ] + } + ] + } + ], + "timestamp_override": "event.ingested", + "type": "query", + "version": 1 +} diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/threat_intel_module_match.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/threat_intel_module_match.json index e4b1309c42644..72cc903ef1eed 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/threat_intel_module_match.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/threat_intel_module_match.json @@ -3,7 +3,7 @@ "Elastic" ], "description": "This rule is triggered when indicators from the Threat Intel Filebeat module has a match against local file or network observations.", - "from": "now-10m", + "from": "now-65m", "index": [ "auditbeat-*", "endgame-*", @@ -12,7 +12,7 @@ "packetbeat-*", "winlogbeat-*" ], - "interval": "9m", + "interval": "1h", "language": "kuery", "license": "Elastic License v2", "name": "Threat Intel Filebeat Module Indicator Match", @@ -194,5 +194,5 @@ "timeline_id": "495ad7a7-316e-4544-8a0f-9c098daee76e", "timeline_title": "Generic Threat Match Timeline", "type": "threat_match", - "version": 2 + "version": 3 } From 2705cc95fa67a9fd9656058620656d7b8e5fd0d8 Mon Sep 17 00:00:00 2001 From: Tyler Smalley Date: Tue, 16 Nov 2021 11:13:23 -0800 Subject: [PATCH 044/148] skip flaky suite (#106631) --- .../apps/discover/feature_controls/discover_security.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/functional/apps/discover/feature_controls/discover_security.ts b/x-pack/test/functional/apps/discover/feature_controls/discover_security.ts index 0a12de3fb44d6..7032f25debb8f 100644 --- a/x-pack/test/functional/apps/discover/feature_controls/discover_security.ts +++ b/x-pack/test/functional/apps/discover/feature_controls/discover_security.ts @@ -31,7 +31,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await PageObjects.timePicker.setDefaultAbsoluteRange(); } - describe('discover feature controls security', () => { + // Failing: See https://github.com/elastic/kibana/issues/106631 + describe.skip('discover feature controls security', () => { before(async () => { await kibanaServer.importExport.load( 'x-pack/test/functional/fixtures/kbn_archiver/discover/feature_controls/security' From 66aca8b486342727de3f5c95821bbeb22fae3d29 Mon Sep 17 00:00:00 2001 From: Tyler Smalley Date: Tue, 16 Nov 2021 11:14:15 -0800 Subject: [PATCH 045/148] skip flaky suite (#118745) --- x-pack/test/functional/apps/maps/sample_data.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/functional/apps/maps/sample_data.js b/x-pack/test/functional/apps/maps/sample_data.js index 483379b2f4914..00549d3cb92dc 100644 --- a/x-pack/test/functional/apps/maps/sample_data.js +++ b/x-pack/test/functional/apps/maps/sample_data.js @@ -18,7 +18,8 @@ export default function ({ getPageObjects, getService, updateBaselines }) { // Only update the baseline images from Jenkins session images after comparing them // These tests might fail locally because of scaling factors and resolution. - describe('maps loaded from sample data', () => { + // Failing: See https://github.com/elastic/kibana/issues/118745 + describe.skip('maps loaded from sample data', () => { before(async () => { //installing the sample data with test user with super user role and then switching roles with limited privileges await security.testUser.setRoles(['superuser'], false); From 1e7e9abdad3c756f58fe698ae0d68819f02285c4 Mon Sep 17 00:00:00 2001 From: Dave Snider Date: Tue, 16 Nov 2021 14:39:38 -0500 Subject: [PATCH 046/148] Integrations back in menu, icons for app search cards (#118446) * Integrations back in menu, icons for app search cards * title case Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- src/core/public/chrome/ui/header/collapsible_nav.tsx | 2 -- .../plugins/enterprise_search/server/integrations.ts | 10 +++++----- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/core/public/chrome/ui/header/collapsible_nav.tsx b/src/core/public/chrome/ui/header/collapsible_nav.tsx index ef380ee47e235..498efcfd9076e 100644 --- a/src/core/public/chrome/ui/header/collapsible_nav.tsx +++ b/src/core/public/chrome/ui/header/collapsible_nav.tsx @@ -113,8 +113,6 @@ export function CollapsibleNav({ (link) => // Filterting out hidden links, !link.hidden && - // integrations link in favor of a specific Add Data button at the bottom, - link.id !== 'integrations' && // and non-data overview pages !overviewIDsToHide.includes(link.id) ), diff --git a/x-pack/plugins/enterprise_search/server/integrations.ts b/x-pack/plugins/enterprise_search/server/integrations.ts index 633f5638cc05c..fe8e584b65bed 100644 --- a/x-pack/plugins/enterprise_search/server/integrations.ts +++ b/x-pack/plugins/enterprise_search/server/integrations.ts @@ -305,12 +305,12 @@ export const registerEnterpriseSearchIntegrations = ( customIntegrations.registerCustomIntegration({ id: 'app_search_web_crawler', title: i18n.translate('xpack.enterpriseSearch.appSearch.integrations.webCrawlerName', { - defaultMessage: 'Web Crawler', + defaultMessage: 'Web site crawler', }), description: i18n.translate( 'xpack.enterpriseSearch.appSearch.integrations.webCrawlerDescription', { - defaultMessage: "Add search to your website with App Search's web crawler.", + defaultMessage: 'Add search to your website with the App Search web crawler.', } ), categories: ['website_search'], @@ -318,7 +318,7 @@ export const registerEnterpriseSearchIntegrations = ( icons: [ { type: 'eui', - src: 'globe', + src: 'logoAppSearch', }, ], shipper: 'enterprise_search', @@ -338,7 +338,7 @@ export const registerEnterpriseSearchIntegrations = ( icons: [ { type: 'eui', - src: 'exportAction', + src: 'logoAppSearch', }, ], shipper: 'enterprise_search', @@ -358,7 +358,7 @@ export const registerEnterpriseSearchIntegrations = ( icons: [ { type: 'eui', - src: 'editorCodeBlock', + src: 'logoAppSearch', }, ], shipper: 'enterprise_search', From 9e2f017c24fd03399a7c99e67ba6ad534076cc45 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 16 Nov 2021 13:37:56 -0700 Subject: [PATCH 047/148] Update dependency core-js to ^3.19.1 (main) (#118743) Co-authored-by: Renovate Bot Co-authored-by: spalger --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index b7b543abde704..f866db8ef57e8 100644 --- a/package.json +++ b/package.json @@ -205,7 +205,7 @@ "constate": "^1.3.2", "content-disposition": "0.5.3", "copy-to-clipboard": "^3.0.8", - "core-js": "^3.18.3", + "core-js": "^3.19.1", "cronstrue": "^1.51.0", "cytoscape": "^3.10.0", "cytoscape-dagre": "^2.2.2", diff --git a/yarn.lock b/yarn.lock index c6bfd7ca788a7..983a2d18d4ec0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11269,10 +11269,10 @@ core-js@^2.4.0, core-js@^2.5.0, core-js@^2.6.9: resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.9.tgz#6b4b214620c834152e179323727fc19741b084f2" integrity sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A== -core-js@^3.0.1, core-js@^3.0.4, core-js@^3.18.3, core-js@^3.6.5, core-js@^3.8.2: - version "3.18.3" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.18.3.tgz#86a0bba2d8ec3df860fefcc07a8d119779f01509" - integrity sha512-tReEhtMReZaPFVw7dajMx0vlsz3oOb8ajgPoHVYGxr8ErnZ6PcYEvvmjGmXlfpnxpkYSdOQttjB+MvVbCGfvLw== +core-js@^3.0.1, core-js@^3.0.4, core-js@^3.19.1, core-js@^3.6.5, core-js@^3.8.2: + version "3.19.1" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.19.1.tgz#f6f173cae23e73a7d88fa23b6e9da329276c6641" + integrity sha512-Tnc7E9iKd/b/ff7GFbhwPVzJzPztGrChB8X8GLqoYGdEOG8IpLnK1xPyo3ZoO3HsK6TodJS58VGPOxA+hLHQMg== core-util-is@1.0.2, core-util-is@^1.0.2, core-util-is@~1.0.0: version "1.0.2" From 0e432b77d6ce85d2dc51e4e35ec283e4cd45658b Mon Sep 17 00:00:00 2001 From: Esteban Beltran Date: Tue, 16 Nov 2021 16:19:11 -0500 Subject: [PATCH 048/148] [Security Solution] Refactor/host isolation exceptions add edit to remove redux (#118543) --- .../public/common/store/actions.ts | 4 +- .../host_isolation_exceptions/service.ts | 34 +- .../host_isolation_exceptions/store/action.ts | 41 -- .../store/builders.ts | 10 - .../store/middleware.test.ts | 237 ------------ .../store/middleware.ts | 170 --------- .../store/reducer.test.ts | 10 - .../store/reducer.ts | 44 +-- .../store/selector.ts | 19 - .../pages/host_isolation_exceptions/types.ts | 17 - .../view/components/form_flyout.test.tsx | 246 +++++++----- .../view/components/form_flyout.tsx | 360 ++++++++---------- .../view/host_isolation_exceptions_list.tsx | 13 +- .../public/management/store/middleware.ts | 6 - 14 files changed, 330 insertions(+), 881 deletions(-) delete mode 100644 x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/store/action.ts delete mode 100644 x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/store/middleware.test.ts delete mode 100644 x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/store/middleware.ts diff --git a/x-pack/plugins/security_solution/public/common/store/actions.ts b/x-pack/plugins/security_solution/public/common/store/actions.ts index ff6b0e80b78ad..1987edc0e7307 100644 --- a/x-pack/plugins/security_solution/public/common/store/actions.ts +++ b/x-pack/plugins/security_solution/public/common/store/actions.ts @@ -9,7 +9,6 @@ import { EndpointAction } from '../../management/pages/endpoint_hosts/store/acti import { PolicyDetailsAction } from '../../management/pages/policy/store/policy_details'; import { TrustedAppsPageAction } from '../../management/pages/trusted_apps/store/action'; import { EventFiltersPageAction } from '../../management/pages/event_filters/store/action'; -import { HostIsolationExceptionsPageAction } from '../../management/pages/host_isolation_exceptions/store/action'; export { appActions } from './app'; export { dragAndDropActions } from './drag_and_drop'; @@ -22,5 +21,4 @@ export type AppAction = | RoutingAction | PolicyDetailsAction | TrustedAppsPageAction - | EventFiltersPageAction - | HostIsolationExceptionsPageAction; + | EventFiltersPageAction; diff --git a/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/service.ts b/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/service.ts index 2bb987271615a..143426226eec8 100644 --- a/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/service.ts +++ b/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/service.ts @@ -13,6 +13,7 @@ import { UpdateExceptionListItemSchema, } from '@kbn/securitysolution-io-ts-list-types'; import { ENDPOINT_HOST_ISOLATION_EXCEPTIONS_LIST_ID } from '@kbn/securitysolution-list-constants'; +import { transformNewItemOutput, transformOutput } from '@kbn/securitysolution-list-hooks'; import { HttpStart } from 'kibana/public'; import { EXCEPTION_LIST_ITEM_URL, EXCEPTION_LIST_URL } from '../event_filters/constants'; import { HOST_ISOLATION_EXCEPTIONS_LIST } from './constants'; @@ -68,16 +69,14 @@ export async function getHostIsolationExceptionItems({ return entries; } -export async function createHostIsolationExceptionItem({ - http, - exception, -}: { - http: HttpStart; - exception: CreateExceptionListItemSchema; -}): Promise { +export async function createHostIsolationExceptionItem( + http: HttpStart, + exception: CreateExceptionListItemSchema +): Promise { await ensureHostIsolationExceptionsListExists(http); + const entry = transformNewItemOutput(exception); return http.post(EXCEPTION_LIST_ITEM_URL, { - body: JSON.stringify(exception), + body: JSON.stringify(entry), }); } @@ -109,8 +108,25 @@ export async function updateOneHostIsolationExceptionItem( exception: UpdateExceptionListItemSchema ): Promise { await ensureHostIsolationExceptionsListExists(http); + const entry = transformOutput(exception); + + // Clean unnecessary fields for update action + const fieldsToRemove: Array = [ + 'created_at', + 'created_by', + 'created_at', + 'created_by', + 'list_id', + 'tie_breaker_id', + 'updated_at', + 'updated_by', + ]; + + fieldsToRemove.forEach((field) => { + delete entry[field as keyof UpdateExceptionListItemSchema]; + }); return http.put(EXCEPTION_LIST_ITEM_URL, { - body: JSON.stringify(exception), + body: JSON.stringify(entry), }); } export async function getHostIsolationExceptionSummary( diff --git a/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/store/action.ts b/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/store/action.ts deleted file mode 100644 index 6b712d470d298..0000000000000 --- a/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/store/action.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 { UpdateExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types'; -import { Action } from 'redux'; -import { HostIsolationExceptionsPageState } from '../types'; - -export type HostIsolationExceptionsFormStateChanged = - Action<'hostIsolationExceptionsFormStateChanged'> & { - payload: HostIsolationExceptionsPageState['form']['status']; - }; - -export type HostIsolationExceptionsFormEntryChanged = - Action<'hostIsolationExceptionsFormEntryChanged'> & { - payload: HostIsolationExceptionsPageState['form']['entry']; - }; - -export type HostIsolationExceptionsCreateEntry = Action<'hostIsolationExceptionsCreateEntry'> & { - payload: HostIsolationExceptionsPageState['form']['entry']; -}; - -export type HostIsolationExceptionsMarkToEdit = Action<'hostIsolationExceptionsMarkToEdit'> & { - payload: { - id: string; - }; -}; - -export type HostIsolationExceptionsSubmitEdit = Action<'hostIsolationExceptionsSubmitEdit'> & { - payload: UpdateExceptionListItemSchema; -}; - -export type HostIsolationExceptionsPageAction = - | HostIsolationExceptionsCreateEntry - | HostIsolationExceptionsFormStateChanged - | HostIsolationExceptionsFormEntryChanged - | HostIsolationExceptionsMarkToEdit - | HostIsolationExceptionsSubmitEdit; diff --git a/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/store/builders.ts b/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/store/builders.ts index 8f32d9cf8d456..4d74378e87298 100644 --- a/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/store/builders.ts +++ b/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/store/builders.ts @@ -6,22 +6,12 @@ */ import { MANAGEMENT_DEFAULT_PAGE, MANAGEMENT_DEFAULT_PAGE_SIZE } from '../../../common/constants'; -import { createUninitialisedResourceState } from '../../../state'; import { HostIsolationExceptionsPageState } from '../types'; export const initialHostIsolationExceptionsPageState = (): HostIsolationExceptionsPageState => ({ - entries: createUninitialisedResourceState(), location: { page_index: MANAGEMENT_DEFAULT_PAGE, page_size: MANAGEMENT_DEFAULT_PAGE_SIZE, filter: '', }, - form: { - entry: undefined, - status: createUninitialisedResourceState(), - }, - deletion: { - item: undefined, - status: createUninitialisedResourceState(), - }, }); diff --git a/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/store/middleware.test.ts b/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/store/middleware.test.ts deleted file mode 100644 index fe666800059bf..0000000000000 --- a/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/store/middleware.test.ts +++ /dev/null @@ -1,237 +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 { - CreateExceptionListItemSchema, - UpdateEndpointListItemSchema, -} from '@kbn/securitysolution-io-ts-list-types'; -import { applyMiddleware, createStore, Store } from 'redux'; -import { coreMock } from '../../../../../../../../src/core/public/mocks'; -import { AppAction } from '../../../../common/store/actions'; -import { - createSpyMiddleware, - MiddlewareActionSpyHelper, -} from '../../../../common/store/test_utils'; -import { - isFailedResourceState, - isLoadedResourceState, - isLoadingResourceState, -} from '../../../state'; -import { - createHostIsolationExceptionItem, - getOneHostIsolationExceptionItem, - updateOneHostIsolationExceptionItem, -} from '../service'; -import { HostIsolationExceptionsPageState } from '../types'; -import { createEmptyHostIsolationException } from '../utils'; -import { initialHostIsolationExceptionsPageState } from './builders'; -import { createHostIsolationExceptionsPageMiddleware } from './middleware'; -import { hostIsolationExceptionsPageReducer } from './reducer'; - -jest.mock('../service'); -const createHostIsolationExceptionItemMock = createHostIsolationExceptionItem as jest.Mock; -const getOneHostIsolationExceptionItemMock = getOneHostIsolationExceptionItem as jest.Mock; -const updateOneHostIsolationExceptionItemMock = updateOneHostIsolationExceptionItem as jest.Mock; - -const fakeCoreStart = coreMock.createStart({ basePath: '/mock' }); - -const createStoreSetup = () => { - const spyMiddleware = createSpyMiddleware(); - - return { - spyMiddleware, - store: createStore( - hostIsolationExceptionsPageReducer, - applyMiddleware( - createHostIsolationExceptionsPageMiddleware(fakeCoreStart), - spyMiddleware.actionSpyMiddleware - ) - ), - }; -}; - -describe('Host isolation exceptions middleware', () => { - let store: Store; - let spyMiddleware: MiddlewareActionSpyHelper; - let initialState: HostIsolationExceptionsPageState; - - beforeEach(() => { - initialState = initialHostIsolationExceptionsPageState(); - - const storeSetup = createStoreSetup(); - - store = storeSetup.store as Store; - spyMiddleware = storeSetup.spyMiddleware; - }); - - describe('initial state', () => { - it('sets initial state properly', async () => { - expect(createStoreSetup().store.getState()).toStrictEqual(initialState); - }); - }); - - describe('When adding an item to host isolation exceptions', () => { - let entry: CreateExceptionListItemSchema; - beforeEach(() => { - createHostIsolationExceptionItemMock.mockReset(); - entry = { - ...createEmptyHostIsolationException(), - name: 'test name', - description: 'description', - entries: [ - { - field: 'destination.ip', - operator: 'included', - type: 'match', - value: '10.0.0.1', - }, - ], - }; - }); - - it('should dispatch a form loading state when an entry is submited', async () => { - const waiter = spyMiddleware.waitForAction('hostIsolationExceptionsFormStateChanged', { - validate({ payload }) { - return isLoadingResourceState(payload); - }, - }); - store.dispatch({ - type: 'hostIsolationExceptionsCreateEntry', - payload: entry, - }); - await waiter; - }); - - it('should dispatch a form success state when an entry is confirmed by the API', async () => { - const waiter = spyMiddleware.waitForAction('hostIsolationExceptionsFormStateChanged', { - validate({ payload }) { - return isLoadedResourceState(payload); - }, - }); - store.dispatch({ - type: 'hostIsolationExceptionsCreateEntry', - payload: entry, - }); - await waiter; - expect(createHostIsolationExceptionItemMock).toHaveBeenCalledWith({ - http: fakeCoreStart.http, - exception: entry, - }); - }); - - it('should dispatch a form failure state when an entry is rejected by the API', async () => { - createHostIsolationExceptionItemMock.mockRejectedValue({ - body: { message: 'error message', statusCode: 500, error: 'Not today' }, - }); - const waiter = spyMiddleware.waitForAction('hostIsolationExceptionsFormStateChanged', { - validate({ payload }) { - return isFailedResourceState(payload); - }, - }); - store.dispatch({ - type: 'hostIsolationExceptionsCreateEntry', - payload: entry, - }); - await waiter; - }); - }); - - describe('When updating an item from host isolation exceptions', () => { - const fakeId = 'dc5d1d00-2766-11ec-981f-7f84cfc8764f'; - let fakeException: UpdateEndpointListItemSchema; - beforeEach(() => { - fakeException = { - ...createEmptyHostIsolationException(), - name: 'name edit me', - description: 'initial description', - id: fakeId, - item_id: fakeId, - entries: [ - { - field: 'destination.ip', - operator: 'included', - type: 'match', - value: '10.0.0.5', - }, - ], - }; - getOneHostIsolationExceptionItemMock.mockReset(); - getOneHostIsolationExceptionItemMock.mockImplementation(async () => { - return fakeException; - }); - }); - - it('should load data from an entry when an exception is marked to edit', async () => { - const waiter = spyMiddleware.waitForAction('hostIsolationExceptionsFormEntryChanged'); - store.dispatch({ - type: 'hostIsolationExceptionsMarkToEdit', - payload: { - id: fakeId, - }, - }); - await waiter; - expect(getOneHostIsolationExceptionItemMock).toHaveBeenCalledWith(fakeCoreStart.http, fakeId); - }); - - it('should call the update API when an item edit is submitted', async () => { - const waiter = Promise.all([ - // loading status - spyMiddleware.waitForAction('hostIsolationExceptionsFormStateChanged', { - validate: ({ payload }) => { - return isLoadingResourceState(payload); - }, - }), - // loaded status - spyMiddleware.waitForAction('hostIsolationExceptionsFormStateChanged', { - validate({ payload }) { - return isLoadedResourceState(payload); - }, - }), - ]); - store.dispatch({ - type: 'hostIsolationExceptionsSubmitEdit', - payload: fakeException, - }); - expect(updateOneHostIsolationExceptionItemMock).toHaveBeenCalledWith(fakeCoreStart.http, { - name: 'name edit me', - description: 'initial description', - id: fakeId, - item_id: fakeId, - entries: [ - { - field: 'destination.ip', - operator: 'included', - type: 'match', - value: '10.0.0.5', - }, - ], - namespace_type: 'agnostic', - os_types: ['windows', 'linux', 'macos'], - tags: ['policy:all'], - type: 'simple', - comments: [], - }); - await waiter; - }); - - it('should dispatch a form failure state when an entry is rejected by the API', async () => { - updateOneHostIsolationExceptionItemMock.mockRejectedValue({ - body: { message: 'error message', statusCode: 500, error: 'Not today' }, - }); - const waiter = spyMiddleware.waitForAction('hostIsolationExceptionsFormStateChanged', { - validate({ payload }) { - return isFailedResourceState(payload); - }, - }); - store.dispatch({ - type: 'hostIsolationExceptionsSubmitEdit', - payload: fakeException, - }); - await waiter; - }); - }); -}); diff --git a/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/store/middleware.ts b/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/store/middleware.ts deleted file mode 100644 index 7d6fff88b6875..0000000000000 --- a/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/store/middleware.ts +++ /dev/null @@ -1,170 +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 { - CreateExceptionListItemSchema, - ExceptionListItemSchema, - UpdateExceptionListItemSchema, -} from '@kbn/securitysolution-io-ts-list-types'; -import { CoreStart, HttpSetup, HttpStart } from 'kibana/public'; -import { transformNewItemOutput, transformOutput } from '@kbn/securitysolution-list-hooks'; -import { ImmutableObject } from '../../../../../common/endpoint/types'; -import { ImmutableMiddleware, ImmutableMiddlewareAPI } from '../../../../common/store'; -import { AppAction } from '../../../../common/store/actions'; -import { - createFailedResourceState, - createLoadedResourceState, - createLoadingResourceState, -} from '../../../state/async_resource_builders'; -import { - createHostIsolationExceptionItem, - getOneHostIsolationExceptionItem, - updateOneHostIsolationExceptionItem, -} from '../service'; -import { HostIsolationExceptionsPageState } from '../types'; -import { HostIsolationExceptionsPageAction } from './action'; - -export const SEARCHABLE_FIELDS: Readonly = [`name`, `description`, `entries.value`]; - -export function hostIsolationExceptionsMiddlewareFactory(coreStart: CoreStart) { - return createHostIsolationExceptionsPageMiddleware(coreStart); -} - -export const createHostIsolationExceptionsPageMiddleware = ( - coreStart: CoreStart -): ImmutableMiddleware => { - return (store) => (next) => async (action) => { - next(action); - - if (action.type === 'hostIsolationExceptionsCreateEntry') { - createHostIsolationException(store, coreStart.http); - } - - if (action.type === 'hostIsolationExceptionsMarkToEdit') { - loadHostIsolationExceptionsItem(store, coreStart.http, action.payload.id); - } - - if (action.type === 'hostIsolationExceptionsSubmitEdit') { - updateHostIsolationExceptionsItem(store, coreStart.http, action.payload); - } - }; -}; - -async function createHostIsolationException( - store: ImmutableMiddlewareAPI< - HostIsolationExceptionsPageState, - HostIsolationExceptionsPageAction - >, - http: HttpStart -) { - const { dispatch } = store; - const entry = transformNewItemOutput( - store.getState().form.entry as CreateExceptionListItemSchema - ); - - dispatch({ - type: 'hostIsolationExceptionsFormStateChanged', - payload: { - type: 'LoadingResourceState', - }, - }); - try { - const response = await createHostIsolationExceptionItem({ - http, - exception: entry, - }); - dispatch({ - type: 'hostIsolationExceptionsFormStateChanged', - payload: createLoadedResourceState(response), - }); - } catch (error) { - dispatch({ - type: 'hostIsolationExceptionsFormStateChanged', - payload: createFailedResourceState(error.body ?? error), - }); - } -} - -async function loadHostIsolationExceptionsItem( - store: ImmutableMiddlewareAPI< - HostIsolationExceptionsPageState, - HostIsolationExceptionsPageAction - >, - http: HttpSetup, - id: string -) { - const { dispatch } = store; - try { - const exception: UpdateExceptionListItemSchema = await getOneHostIsolationExceptionItem( - http, - id - ); - dispatch({ - type: 'hostIsolationExceptionsFormEntryChanged', - payload: exception, - }); - } catch (error) { - dispatch({ - type: 'hostIsolationExceptionsFormStateChanged', - payload: createFailedResourceState(error.body ?? error), - }); - } -} -async function updateHostIsolationExceptionsItem( - store: ImmutableMiddlewareAPI< - HostIsolationExceptionsPageState, - HostIsolationExceptionsPageAction - >, - http: HttpSetup, - exception: ImmutableObject -) { - const { dispatch } = store; - dispatch({ - type: 'hostIsolationExceptionsFormStateChanged', - payload: createLoadingResourceState(createLoadedResourceState(exception)), - }); - - try { - const entry = transformOutput(exception as UpdateExceptionListItemSchema); - // Clean unnecessary fields for update action - const fieldsToRemove: Array = [ - 'created_at', - 'created_by', - 'created_at', - 'created_by', - 'list_id', - 'tie_breaker_id', - 'updated_at', - 'updated_by', - ]; - - fieldsToRemove.forEach((field) => { - delete entry[field as keyof UpdateExceptionListItemSchema]; - }); - const response: ExceptionListItemSchema = await updateOneHostIsolationExceptionItem( - http, - entry - ); - - // notify the update was correct - dispatch({ - type: 'hostIsolationExceptionsFormStateChanged', - payload: createLoadedResourceState(response), - }); - - // clear the form - dispatch({ - type: 'hostIsolationExceptionsFormEntryChanged', - payload: undefined, - }); - } catch (error) { - dispatch({ - type: 'hostIsolationExceptionsFormStateChanged', - payload: createFailedResourceState(error.body ?? error), - }); - } -} diff --git a/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/store/reducer.test.ts b/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/store/reducer.test.ts index 17708516763bd..e70957fa2d74d 100644 --- a/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/store/reducer.test.ts +++ b/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/store/reducer.test.ts @@ -11,7 +11,6 @@ import { initialHostIsolationExceptionsPageState } from './builders'; import { HOST_ISOLATION_EXCEPTIONS_PATH } from '../../../../../common/constants'; import { hostIsolationExceptionsPageReducer } from './reducer'; import { getCurrentLocation } from './selector'; -import { createEmptyHostIsolationException } from '../utils'; describe('Host isolation exceptions Reducer', () => { let initialState: HostIsolationExceptionsPageState; @@ -42,13 +41,4 @@ describe('Host isolation exceptions Reducer', () => { }); }); }); - it('should set an initial loading state when creating new entries', () => { - const entry = createEmptyHostIsolationException(); - const result = hostIsolationExceptionsPageReducer(initialState, { - type: 'hostIsolationExceptionsCreateEntry', - payload: entry, - }); - expect(result.form.status).toEqual({ type: 'UninitialisedResourceState' }); - expect(result.form.entry).toBe(entry); - }); }); diff --git a/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/store/reducer.ts b/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/store/reducer.ts index afa82f3f8b20e..e5dcdbac0d881 100644 --- a/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/store/reducer.ts +++ b/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/store/reducer.ts @@ -15,15 +15,8 @@ import { extractHostIsolationExceptionsPageLocation } from '../../../common/rout import { HostIsolationExceptionsPageState } from '../types'; import { initialHostIsolationExceptionsPageState } from './builders'; import { MANAGEMENT_ROUTING_HOST_ISOLATION_EXCEPTIONS_PATH } from '../../../common/constants'; -import { UserChangedUrl } from '../../../../common/store/routing/action'; -import { createUninitialisedResourceState } from '../../../state'; type StateReducer = ImmutableReducer; -type CaseReducer = ( - state: Immutable, - action: Immutable -) => Immutable; - const isHostIsolationExceptionsPageLocation = (location: Immutable) => { return ( matchPath(location.pathname ?? '', { @@ -37,42 +30,7 @@ export const hostIsolationExceptionsPageReducer: StateReducer = ( state = initialHostIsolationExceptionsPageState(), action ) => { - switch (action.type) { - case 'hostIsolationExceptionsCreateEntry': { - return { - ...state, - form: { - entry: action.payload, - status: createUninitialisedResourceState(), - }, - }; - } - case 'hostIsolationExceptionsFormStateChanged': { - return { - ...state, - form: { - ...state.form, - status: action.payload, - }, - }; - } - case 'hostIsolationExceptionsFormEntryChanged': { - return { - ...state, - form: { - ...state.form, - entry: action.payload, - }, - }; - } - case 'userChangedUrl': - return userChangedUrl(state, action); - } - return state; -}; - -const userChangedUrl: CaseReducer = (state, action) => { - if (isHostIsolationExceptionsPageLocation(action.payload)) { + if (action.type === 'userChangedUrl' && isHostIsolationExceptionsPageLocation(action.payload)) { const location = extractHostIsolationExceptionsPageLocation( parse(action.payload.search.slice(1)) ); diff --git a/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/store/selector.ts b/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/store/selector.ts index 43009ddd1d03e..f4531faa646e8 100644 --- a/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/store/selector.ts +++ b/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/store/selector.ts @@ -5,11 +5,7 @@ * 2.0. */ -import { UpdateExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types'; -import { createSelector } from 'reselect'; import { Immutable } from '../../../../../common/endpoint/types'; -import { ServerApiError } from '../../../../common/types'; -import { isFailedResourceState } from '../../../state/async_resource_state'; import { HostIsolationExceptionsPageState } from '../types'; type StoreState = Immutable; @@ -18,18 +14,3 @@ type HostIsolationExceptionsSelector = (state: StoreState) => T; export const getCurrentLocation: HostIsolationExceptionsSelector = ( state ) => state.location; - -const getFormState: HostIsolationExceptionsSelector = (state) => { - return state.form; -}; - -export const getFormStatusFailure: HostIsolationExceptionsSelector = - createSelector(getFormState, (form) => { - if (isFailedResourceState(form.status)) { - return form.status.error; - } - }); - -export const getExceptionToEdit: HostIsolationExceptionsSelector< - UpdateExceptionListItemSchema | undefined -> = (state) => (state.form.entry ? (state.form.entry as UpdateExceptionListItemSchema) : undefined); diff --git a/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/types.ts b/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/types.ts index 2e61a39eb7542..9affcc8c50438 100644 --- a/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/types.ts +++ b/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/types.ts @@ -5,14 +5,6 @@ * 2.0. */ -import type { - CreateExceptionListItemSchema, - ExceptionListItemSchema, - FoundExceptionListItemSchema, - UpdateExceptionListItemSchema, -} from '@kbn/securitysolution-io-ts-list-types'; -import { AsyncResourceState } from '../../state/async_resource_state'; - export interface HostIsolationExceptionsPageLocation { page_index: number; page_size: number; @@ -23,14 +15,5 @@ export interface HostIsolationExceptionsPageLocation { } export interface HostIsolationExceptionsPageState { - entries: AsyncResourceState; location: HostIsolationExceptionsPageLocation; - deletion: { - item?: ExceptionListItemSchema; - status: AsyncResourceState; - }; - form: { - entry?: CreateExceptionListItemSchema | UpdateExceptionListItemSchema; - status: AsyncResourceState; - }; } diff --git a/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/view/components/form_flyout.test.tsx b/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/view/components/form_flyout.test.tsx index 3f0a8b9990b83..4ed79cabdb32b 100644 --- a/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/view/components/form_flyout.test.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/view/components/form_flyout.test.tsx @@ -12,36 +12,52 @@ import { } from '../../../../../common/mock/endpoint'; import userEvent from '@testing-library/user-event'; import { HostIsolationExceptionsFormFlyout } from './form_flyout'; -import { act } from 'react-dom/test-utils'; -import { HOST_ISOLATION_EXCEPTIONS_PATH } from '../../../../../../common/constants'; import uuid from 'uuid'; import { createEmptyHostIsolationException } from '../../utils'; +import { waitFor, waitForElementToBeRemoved } from '@testing-library/react'; +import { + createHostIsolationExceptionItem, + updateOneHostIsolationExceptionItem, + getOneHostIsolationExceptionItem, +} from '../../service'; +import { getHostIsolationExceptionsListPath } from '../../../../common/routing'; jest.mock('../../service.ts'); jest.mock('../../../../../common/hooks/use_license'); +const createHostIsolationExceptionItemMock = createHostIsolationExceptionItem as jest.Mock; +const updateOneHostIsolationExceptionItemMock = updateOneHostIsolationExceptionItem as jest.Mock; +const getOneHostIsolationExceptionItemMock = getOneHostIsolationExceptionItem as jest.Mock; + describe('When on the host isolation exceptions flyout form', () => { let mockedContext: AppContextTestRender; let render: () => ReturnType; let renderResult: ReturnType; - let waitForAction: AppContextTestRender['middlewareSpy']['waitForAction']; + let onCancel: () => void; - beforeEach(() => { + beforeEach(async () => { + onCancel = jest.fn(); mockedContext = createAppRootMockRenderer(); - render = () => { - return mockedContext.render(); - }; - waitForAction = mockedContext.middlewareSpy.waitForAction; + mockedContext.history.push(getHostIsolationExceptionsListPath({ show: 'create' })); + + createHostIsolationExceptionItemMock.mockReset(); + updateOneHostIsolationExceptionItemMock.mockReset(); + getOneHostIsolationExceptionItemMock.mockReset(); }); describe('When creating a new exception', () => { beforeEach(() => { - mockedContext.history.push(`${HOST_ISOLATION_EXCEPTIONS_PATH}?show=create`); + render = () => { + return mockedContext.render(); + }; }); - - describe('with invalida data', () => { - it('should show disabled buttons when the form first load', () => { + describe('with invalid data', () => { + beforeEach(async () => { renderResult = render(); + await waitForElementToBeRemoved(renderResult.queryByTestId('loading-spinner')); + }); + + it('should show disabled buttons when the form first load', async () => { expect(renderResult.getByTestId('add-exception-cancel-button')).not.toHaveAttribute( 'disabled' ); @@ -49,11 +65,29 @@ describe('When on the host isolation exceptions flyout form', () => { 'disabled' ); }); + + it('should disable submit if the data is invalid', async () => { + const ipInput = renderResult.getByTestId('hostIsolationExceptions-form-ip-input'); + const nameInput = renderResult.getByTestId('hostIsolationExceptions-form-name-input'); + const confirmButton = renderResult.getByTestId('add-exception-confirm-button'); + userEvent.type(nameInput, 'test name'); + userEvent.clear(ipInput); + userEvent.type(ipInput, 'not an ip'); + expect(confirmButton).toHaveAttribute('disabled'); + }); + + it('should call onCancel when cancel is pressed', async () => { + const cancelButton = renderResult.getByTestId('add-exception-cancel-button'); + userEvent.click(cancelButton); + expect(onCancel).toHaveBeenCalled(); + }); }); describe('with valid data', () => { - beforeEach(() => { + beforeEach(async () => { renderResult = render(); + await waitForElementToBeRemoved(renderResult.queryByTestId('loading-spinner')); + const ipInput = renderResult.getByTestId('hostIsolationExceptions-form-ip-input'); const nameInput = renderResult.getByTestId('hostIsolationExceptions-form-name-input'); userEvent.type(nameInput, 'test name'); @@ -72,60 +106,60 @@ describe('When on the host isolation exceptions flyout form', () => { it('should submit the entry data when submit is pressed with valid data', async () => { const confirmButton = renderResult.getByTestId('add-exception-confirm-button'); expect(confirmButton).not.toHaveAttribute('disabled'); - const waiter = waitForAction('hostIsolationExceptionsCreateEntry'); userEvent.click(confirmButton); - expect(await waiter).toBeTruthy(); + await waitFor(() => { + expect(createHostIsolationExceptionItemMock).toHaveBeenCalled(); + }); }); - it('should disable the submit button when an operation is in progress', () => { - act(() => { - mockedContext.store.dispatch({ - type: 'hostIsolationExceptionsFormStateChanged', - payload: { - type: 'LoadingResourceState', - previousState: { type: 'UninitialisedResourceState' }, - }, + it('should disable the submit button when an operation is in progress', async () => { + // simulate a pending request + createHostIsolationExceptionItemMock.mockImplementationOnce(() => { + return new Promise((resolve) => { + setTimeout(resolve, 300); }); }); const confirmButton = renderResult.getByTestId('add-exception-confirm-button'); - expect(confirmButton).toHaveAttribute('disabled'); + expect(confirmButton).not.toHaveAttribute('disabled'); + userEvent.click(confirmButton); + await waitFor(() => { + expect(createHostIsolationExceptionItemMock).toHaveBeenCalled(); + expect(confirmButton).toHaveAttribute('disabled'); + }); }); - it('should show a toast and close the flyout when the operation is finished', () => { - mockedContext.history.push(`${HOST_ISOLATION_EXCEPTIONS_PATH}?show=create`); - act(() => { - mockedContext.store.dispatch({ - type: 'hostIsolationExceptionsFormStateChanged', - payload: { - type: 'LoadedResourceState', - previousState: { type: 'UninitialisedResourceState' }, - }, - }); + it('should show a toast and close the flyout when the operation is finished calling onCancel', async () => { + const confirmButton = renderResult.getByTestId('add-exception-confirm-button'); + userEvent.click(confirmButton); + await waitFor(() => { + expect(mockedContext.coreStart.notifications.toasts.addSuccess).toHaveBeenCalled(); + expect(onCancel).toHaveBeenCalled(); }); - expect(mockedContext.coreStart.notifications.toasts.addSuccess).toHaveBeenCalled(); - expect(mockedContext.history.location.search).toBe(''); }); it('should show an error toast if operation fails and enable the submit button', async () => { - act(() => { - mockedContext.store.dispatch({ - type: 'hostIsolationExceptionsFormStateChanged', - payload: { - type: 'FailedResourceState', - error: new Error('mocked error'), - }, - }); - }); - expect(mockedContext.coreStart.notifications.toasts.addDanger).toHaveBeenCalled(); + createHostIsolationExceptionItemMock.mockRejectedValue(new Error('not valid')); const confirmButton = renderResult.getByTestId('add-exception-confirm-button'); - expect(confirmButton).not.toHaveAttribute('disabled'); + userEvent.click(confirmButton); + await waitFor(() => { + expect(mockedContext.coreStart.notifications.toasts.addDanger).toHaveBeenCalledWith( + 'There was an error creating the exception: "not valid"' + ); + expect(confirmButton).not.toHaveAttribute('disabled'); + }); }); }); }); + describe('When editing an existing exception', () => { - const fakeId = 'dc5d1d00-2766-11ec-981f-7f84cfc8764f'; + const fakeId = uuid.v4(); beforeEach(() => { - mockedContext.history.push(`${HOST_ISOLATION_EXCEPTIONS_PATH}?show=edit&id=${fakeId}`); + mockedContext.history.push(getHostIsolationExceptionsListPath({ show: 'edit', id: fakeId })); + render = () => { + return mockedContext.render( + + ); + }; }); describe('without loaded data', () => { @@ -135,71 +169,38 @@ describe('When on the host isolation exceptions flyout form', () => { }); it('should request to load data about the editing exception', async () => { - const waiter = waitForAction('hostIsolationExceptionsMarkToEdit', { - validate: ({ payload }) => { - return payload.id === fakeId; - }, - }); renderResult = render(); - expect(await waiter).toBeTruthy(); - }); - - it('should show a warning toast if the item fails to load', () => { - renderResult = render(); - act(() => { - mockedContext.store.dispatch({ - type: 'hostIsolationExceptionsFormEntryChanged', - payload: undefined, - }); - - mockedContext.store.dispatch({ - type: 'hostIsolationExceptionsFormStateChanged', - payload: { - type: 'FailedResourceState', - error: new Error('mocked error'), - }, - }); + await waitFor(() => { + expect(getOneHostIsolationExceptionItemMock).toHaveBeenCalledWith( + mockedContext.coreStart.http, + fakeId + ); }); - expect(mockedContext.coreStart.notifications.toasts.addWarning).toHaveBeenCalled(); }); }); describe('with loaded data', () => { beforeEach(async () => { - mockedContext.store.dispatch({ - type: 'hostIsolationExceptionsFormEntryChanged', - payload: { - ...createEmptyHostIsolationException(), - name: 'name edit me', - description: 'initial description', - id: fakeId, - item_id: uuid.v4(), - entries: [ - { - field: 'destination.ip', - operator: 'included', - type: 'match', - value: '10.0.0.5', - }, - ], - }, + getOneHostIsolationExceptionItemMock.mockReturnValueOnce({ + ...createEmptyHostIsolationException(), + name: 'name edit me', + description: 'initial description', + id: fakeId, + item_id: fakeId, + entries: [ + { + field: 'destination.ip', + operator: 'included', + type: 'match', + value: '10.0.0.5', + }, + ], }); renderResult = render(); + await waitForElementToBeRemoved(renderResult.queryByTestId('loading-spinner')); }); - it('should request data again if the url id is changed', async () => { - const otherId = 'd75fbd74-2a92-11ec-8d3d-0242ac130003'; - act(() => { - mockedContext.history.push(`${HOST_ISOLATION_EXCEPTIONS_PATH}?show=edit&id=${otherId}`); - }); - await waitForAction('hostIsolationExceptionsMarkToEdit', { - validate: ({ payload }) => { - return payload.id === otherId; - }, - }); - }); - - it('should enable the buttons from the start', () => { + it('should enable the buttons after data is loaded', () => { expect(renderResult.getByTestId('add-exception-cancel-button')).not.toHaveAttribute( 'disabled' ); @@ -208,12 +209,47 @@ describe('When on the host isolation exceptions flyout form', () => { ); }); + it('should disable submit if the data is invalid', async () => { + const ipInput = renderResult.getByTestId('hostIsolationExceptions-form-ip-input'); + const nameInput = renderResult.getByTestId('hostIsolationExceptions-form-name-input'); + const confirmButton = renderResult.getByTestId('add-exception-confirm-button'); + userEvent.type(nameInput, 'test name'); + userEvent.clear(ipInput); + userEvent.type(ipInput, 'not an ip'); + expect(confirmButton).toHaveAttribute('disabled'); + }); + it('should submit the entry data when submit is pressed with valid data', async () => { const confirmButton = renderResult.getByTestId('add-exception-confirm-button'); expect(confirmButton).not.toHaveAttribute('disabled'); - const waiter = waitForAction('hostIsolationExceptionsSubmitEdit'); userEvent.click(confirmButton); - expect(await waiter).toBeTruthy(); + await waitFor(() => { + expect(updateOneHostIsolationExceptionItemMock).toHaveBeenCalledWith( + mockedContext.coreStart.http, + { + comments: [], + description: 'initial description', + entries: [ + { field: 'destination.ip', operator: 'included', type: 'match', value: '10.0.0.5' }, + ], + id: fakeId, + item_id: fakeId, + list_id: 'endpoint_host_isolation_exceptions', + name: 'name edit me', + namespace_type: 'agnostic', + os_types: ['windows', 'linux', 'macos'], + tags: ['policy:all'], + type: 'simple', + } + ); + }); + expect(confirmButton).toHaveAttribute('disabled'); + }); + + it('should call onCancel when cancel is pressed', async () => { + const cancelButton = renderResult.getByTestId('add-exception-cancel-button'); + userEvent.click(cancelButton); + expect(onCancel).toHaveBeenCalled(); }); }); }); diff --git a/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/view/components/form_flyout.tsx b/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/view/components/form_flyout.tsx index b73e3ac6f0111..35d834afa1756 100644 --- a/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/view/components/form_flyout.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/view/components/form_flyout.tsx @@ -21,19 +21,11 @@ import { CreateExceptionListItemSchema, UpdateExceptionListItemSchema, } from '@kbn/securitysolution-io-ts-list-types'; -import { omit } from 'lodash'; -import React, { memo, useCallback, useEffect, useMemo, useState } from 'react'; -import { useDispatch } from 'react-redux'; -import { useHistory } from 'react-router-dom'; -import { Dispatch } from 'redux'; -import { useQueryClient } from 'react-query'; +import React, { memo, useCallback, useMemo, useState } from 'react'; +import { useMutation, useQuery, useQueryClient } from 'react-query'; +import { ServerApiError } from '../../../../../common/types'; import { Loader } from '../../../../../common/components/loader'; -import { useToasts } from '../../../../../common/lib/kibana'; -import { getHostIsolationExceptionsListPath } from '../../../../common/routing'; -import { - isLoadedResourceState, - isLoadingResourceState, -} from '../../../../state/async_resource_state'; +import { useHttp, useToasts } from '../../../../../common/lib/kibana'; import { getCreateErrorMessage, getCreationSuccessMessage, @@ -41,221 +33,169 @@ import { getUpdateErrorMessage, getUpdateSuccessMessage, } from './translations'; -import { HostIsolationExceptionsPageAction } from '../../store/action'; -import { getCurrentLocation, getExceptionToEdit, getFormStatusFailure } from '../../store/selector'; import { createEmptyHostIsolationException } from '../../utils'; -import { - useHostIsolationExceptionsNavigateCallback, - useHostIsolationExceptionsSelector, -} from '../hooks'; import { HostIsolationExceptionsForm } from './form'; +import { + createHostIsolationExceptionItem, + getOneHostIsolationExceptionItem, + updateOneHostIsolationExceptionItem, +} from '../../service'; -export const HostIsolationExceptionsFormFlyout: React.FC<{}> = memo(() => { - const dispatch = useDispatch>(); - const toasts = useToasts(); - const location = useHostIsolationExceptionsSelector(getCurrentLocation); - const creationInProgress = useHostIsolationExceptionsSelector((state) => - isLoadingResourceState(state.form.status) - ); - const creationSuccessful = useHostIsolationExceptionsSelector((state) => - isLoadedResourceState(state.form.status) - ); - const creationFailure = useHostIsolationExceptionsSelector(getFormStatusFailure); - const exceptionToEdit = useHostIsolationExceptionsSelector(getExceptionToEdit); - const navigateCallback = useHostIsolationExceptionsNavigateCallback(); - const queryClient = useQueryClient(); - const history = useHistory(); - - const [formHasError, setFormHasError] = useState(true); - const [exception, setException] = useState< - CreateExceptionListItemSchema | UpdateExceptionListItemSchema | undefined - >(undefined); - - const onCancel = useCallback( - () => - navigateCallback({ - show: undefined, - id: undefined, - }), - [navigateCallback] - ); +export const HostIsolationExceptionsFormFlyout = memo( + ({ onCancel, id }: { onCancel: () => void; id?: string }) => { + const http = useHttp(); + const toasts = useToasts(); + const queryClient = useQueryClient(); - // load data to edit or create - useEffect(() => { - if (location.show === 'create' && exception === undefined) { - setException(createEmptyHostIsolationException()); - } else if (location.show === 'edit') { - // prevent flyout to show edit without an id - if (!location.id) { - onCancel(); - return; - } - // load the exception to edit - if (!exceptionToEdit || location.id !== exceptionToEdit.id) { - dispatch({ - type: 'hostIsolationExceptionsMarkToEdit', - payload: { id: location.id }, - }); - } else if (exception === undefined) { - setException(exceptionToEdit); - } - } - }, [dispatch, exception, exceptionToEdit, location.id, location.show, onCancel]); + const isEditing = id !== undefined; + const [exception, setException] = useState< + CreateExceptionListItemSchema | UpdateExceptionListItemSchema | undefined + >(undefined); - // handle creation and edit success - useEffect(() => { - if (creationSuccessful && exception?.name) { - onCancel(); - dispatch({ - type: 'hostIsolationExceptionsFormStateChanged', - payload: { - type: 'UninitialisedResourceState', + useQuery( + ['hostIsolationExceptions', 'form', id], + async () => { + // for editing, fetch from the API + if (id !== undefined) { + return getOneHostIsolationExceptionItem(http, id); + } + // for adding, return a new empty object + return createEmptyHostIsolationException(); + }, + { + refetchIntervalInBackground: false, + refetchOnWindowFocus: false, + onSuccess: (data) => { + setException(data); + }, + onError: (error) => { + toasts.addWarning(getLoadErrorMessage(error)); + onCancel(); }, - }); - if (exception?.item_id) { - toasts.addSuccess(getUpdateSuccessMessage(exception.name)); - } else { - toasts.addSuccess(getCreationSuccessMessage(exception.name)); } - queryClient.invalidateQueries('hostIsolationExceptions'); - } - }, [ - creationSuccessful, - dispatch, - exception?.item_id, - exception?.name, - onCancel, - queryClient, - toasts, - ]); + ); - // handle load item to edit error - useEffect(() => { - if (creationFailure && location.show === 'edit' && !exception?.item_id) { - toasts.addWarning(getLoadErrorMessage(creationFailure)); - history.replace(getHostIsolationExceptionsListPath(omit(location, ['show', 'id']))); - dispatch({ - type: 'hostIsolationExceptionsFormStateChanged', - payload: { - type: 'UninitialisedResourceState', + const mutation = useMutation( + () => { + if (isEditing) { + return updateOneHostIsolationExceptionItem( + http, + exception as UpdateExceptionListItemSchema + ); + } else { + return createHostIsolationExceptionItem(http, exception as CreateExceptionListItemSchema); + } + }, + { + onSuccess: () => { + if (exception?.name) { + if (isEditing) { + toasts.addSuccess(getUpdateSuccessMessage(exception.name)); + } else { + toasts.addSuccess(getCreationSuccessMessage(exception.name)); + } + } + queryClient.invalidateQueries('hostIsolationExceptions'); + onCancel(); }, - }); - } - }, [creationFailure, dispatch, exception?.item_id, history, location, toasts]); - - // handle edit or creation error - useEffect(() => { - if (creationFailure) { - // failed to load the entry - if (exception?.item_id) { - toasts.addDanger(getUpdateErrorMessage(creationFailure)); - } else { - toasts.addDanger(getCreateErrorMessage(creationFailure)); - } - dispatch({ - type: 'hostIsolationExceptionsFormStateChanged', - payload: { - type: 'UninitialisedResourceState', + onError: (error: ServerApiError) => { + if (isEditing) { + toasts.addDanger(getUpdateErrorMessage(error)); + } else { + toasts.addDanger(getCreateErrorMessage(error)); + } }, - }); - } - }, [creationFailure, dispatch, exception?.item_id, toasts]); + } + ); - const handleOnCancel = useCallback(() => { - if (creationInProgress) return; - onCancel(); - }, [creationInProgress, onCancel]); + const [formHasError, setFormHasError] = useState(true); - const handleOnSubmit = useCallback(() => { - if (exception?.item_id) { - dispatch({ - type: 'hostIsolationExceptionsSubmitEdit', - payload: exception, - }); - } else { - dispatch({ - type: 'hostIsolationExceptionsCreateEntry', - payload: exception, - }); - } - }, [dispatch, exception]); + const handleOnCancel = useCallback(() => { + if (mutation.isLoading) return; + onCancel(); + }, [mutation, onCancel]); - const confirmButtonMemo = useMemo( - () => ( - - {exception?.item_id ? ( - - ) : ( - - )} - - ), - [formHasError, creationInProgress, handleOnSubmit, exception?.item_id] - ); + const handleOnSubmit = useCallback(() => { + mutation.mutate(); + }, [mutation]); - return exception ? ( - - - - {exception?.item_id ? ( -

- -

+ const confirmButtonMemo = useMemo( + () => ( + + {isEditing ? ( + ) : ( -

- -

+ )} -
-
+ + ), + [formHasError, handleOnSubmit, isEditing, mutation.isLoading] + ); + + return exception ? ( + + + + {isEditing ? ( +

+ +

+ ) : ( +

+ +

+ )} +
+
- - - + + + - - - - - - - - {confirmButtonMemo} - - -
- ) : ( - - ); -}); + + + + + + + + {confirmButtonMemo} + + +
+ ) : ( + + ); + } +); HostIsolationExceptionsFormFlyout.displayName = 'HostIsolationExceptionsFormFlyout'; diff --git a/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/view/host_isolation_exceptions_list.tsx b/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/view/host_isolation_exceptions_list.tsx index 010a435ec761b..103bee41d3ac5 100644 --- a/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/view/host_isolation_exceptions_list.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/view/host_isolation_exceptions_list.tsx @@ -133,6 +133,15 @@ export const HostIsolationExceptionsList = () => { setItemToDelete(null); }; + const handleCloseFlyout = useCallback( + () => + navigateCallback({ + show: undefined, + id: undefined, + }), + [navigateCallback] + ); + return ( { } hideHeader={!hasDataToShow} > - {showFlyout && } + {showFlyout && ( + + )} {itemToDelete ? ( diff --git a/x-pack/plugins/security_solution/public/management/store/middleware.ts b/x-pack/plugins/security_solution/public/management/store/middleware.ts index b67b4687da010..d011a9dcb91a7 100644 --- a/x-pack/plugins/security_solution/public/management/store/middleware.ts +++ b/x-pack/plugins/security_solution/public/management/store/middleware.ts @@ -16,13 +16,11 @@ import { MANAGEMENT_STORE_POLICY_DETAILS_NAMESPACE, MANAGEMENT_STORE_TRUSTED_APPS_NAMESPACE, MANAGEMENT_STORE_EVENT_FILTERS_NAMESPACE, - MANAGEMENT_STORE_HOST_ISOLATION_EXCEPTIONS_NAMESPACE, } from '../common/constants'; import { policyDetailsMiddlewareFactory } from '../pages/policy/store/policy_details'; import { endpointMiddlewareFactory } from '../pages/endpoint_hosts/store/middleware'; import { trustedAppsPageMiddlewareFactory } from '../pages/trusted_apps/store/middleware'; import { eventFiltersPageMiddlewareFactory } from '../pages/event_filters/store/middleware'; -import { hostIsolationExceptionsMiddlewareFactory } from '../pages/host_isolation_exceptions/store/middleware'; type ManagementSubStateKey = keyof State[typeof MANAGEMENT_STORE_GLOBAL_NAMESPACE]; @@ -52,9 +50,5 @@ export const managementMiddlewareFactory: SecuritySubPluginMiddlewareFactory = ( createSubStateSelector(MANAGEMENT_STORE_EVENT_FILTERS_NAMESPACE), eventFiltersPageMiddlewareFactory(coreStart, depsStart) ), - substateMiddlewareFactory( - createSubStateSelector(MANAGEMENT_STORE_HOST_ISOLATION_EXCEPTIONS_NAMESPACE), - hostIsolationExceptionsMiddlewareFactory(coreStart) - ), ]; }; From 76b38f2da530dc62314b137991d52b41102649ec Mon Sep 17 00:00:00 2001 From: Tyler Smalley Date: Tue, 16 Nov 2021 13:23:26 -0800 Subject: [PATCH 049/148] Revert "skip flaky suite (#118745)" (#118782) This reverts commit 66aca8b486342727de3f5c95821bbeb22fae3d29. --- x-pack/test/functional/apps/maps/sample_data.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/x-pack/test/functional/apps/maps/sample_data.js b/x-pack/test/functional/apps/maps/sample_data.js index 00549d3cb92dc..483379b2f4914 100644 --- a/x-pack/test/functional/apps/maps/sample_data.js +++ b/x-pack/test/functional/apps/maps/sample_data.js @@ -18,8 +18,7 @@ export default function ({ getPageObjects, getService, updateBaselines }) { // Only update the baseline images from Jenkins session images after comparing them // These tests might fail locally because of scaling factors and resolution. - // Failing: See https://github.com/elastic/kibana/issues/118745 - describe.skip('maps loaded from sample data', () => { + describe('maps loaded from sample data', () => { before(async () => { //installing the sample data with test user with super user role and then switching roles with limited privileges await security.testUser.setRoles(['superuser'], false); From d5e2e78d902c1c78648d9202fd1369476abc79e9 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Tue, 16 Nov 2021 14:36:21 -0700 Subject: [PATCH 050/148] [maps] restructure layers folder (#118395) * [maps] restructure layers folder * eslint Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- x-pack/plugins/maps/public/api/setup_api.ts | 2 +- .../maps/public/classes/layers/index.ts | 9 ++++++++ .../layer_template.test.tsx.snap | 0 .../choropleth_layer_wizard.tsx | 2 +- .../create_choropleth_layer_descriptor.ts | 16 ++++++------- .../choropleth_layer_wizard/index.ts | 0 .../layer_template.test.tsx | 2 +- .../layer_template.tsx | 17 ++++++++------ .../file_upload_wizard/config.tsx | 4 ++-- .../{ => wizards}/file_upload_wizard/index.ts | 0 .../file_upload_wizard/wizard.tsx | 16 ++++++------- .../icons/cloropleth_layer_icon.tsx | 0 .../icons/clusters_layer_icon.tsx | 0 .../icons/documents_layer_icon.tsx | 0 .../{ => wizards}/icons/draw_layer_icon.tsx | 0 .../icons/ems_boundaries_layer_icon.tsx | 0 .../icons/heatmap_layer_icon.tsx | 0 .../icons/point_2_point_layer_icon.tsx | 0 .../icons/top_hits_layer_icon.tsx | 0 .../{ => wizards}/icons/tracks_layer_icon.tsx | 0 .../icons/vector_tile_layer_icon.tsx | 0 .../icons/web_map_service_layer_icon.tsx | 0 .../icons/world_map_layer_icon.tsx | 0 .../public/classes/layers/wizards/index.ts | 13 +++++++++++ .../{ => wizards}/layer_wizard_registry.ts | 4 ++-- .../{ => wizards}/load_layer_wizards.ts | 23 +++++++++++-------- .../new_vector_layer_wizard/config.tsx | 8 +++---- .../create_new_index_pattern.ts | 6 ++--- .../new_vector_layer_wizard/index.ts | 0 .../new_vector_layer_wizard/wizard.tsx | 8 +++---- .../create_layer_descriptor.test.ts | 4 ++-- .../observability/create_layer_descriptor.ts | 18 +++++++-------- .../observability/display_select.tsx | 0 .../solution_layers/observability/index.ts | 0 .../observability/layer_select.tsx | 0 .../observability/metric_select.tsx | 0 .../observability_layer_template.tsx | 0 .../observability_layer_wizard.tsx | 4 ++-- .../security/create_layer_descriptors.test.ts | 2 +- .../security/create_layer_descriptors.ts | 14 +++++------ .../solution_layers/security/index.ts | 0 .../security/index_pattern_select.tsx | 2 +- .../security/security_index_pattern_utils.ts | 2 +- .../security/security_layer_template.tsx | 0 .../security/security_layer_wizard.tsx | 2 +- .../ems_boundaries_layer_wizard.tsx | 4 ++-- .../ems_base_map_layer_wizard.tsx | 4 ++-- .../clusters_layer_wizard.tsx | 4 ++-- .../heatmap_layer_wizard.tsx | 4 ++-- .../es_geo_line_source/layer_wizard.tsx | 4 ++-- .../point_2_point_layer_wizard.tsx | 4 ++-- .../es_documents_layer_wizard.tsx | 4 ++-- .../es_search_source/top_hits/wizard.tsx | 4 ++-- .../kibana_base_map_layer_wizard.tsx | 2 +- .../layer_wizard.tsx | 4 ++-- .../sources/wms_source/wms_layer_wizard.tsx | 4 ++-- .../sources/xyz_tms_source/layer_wizard.tsx | 4 ++-- .../flyout_body/flyout_body.tsx | 2 +- .../flyout_body/layer_wizard_select.test.tsx | 4 ++-- .../flyout_body/layer_wizard_select.tsx | 6 +---- .../add_layer_panel/view.tsx | 2 +- .../map_container/map_container.tsx | 2 +- x-pack/plugins/maps/public/index.ts | 2 +- .../public/lazy_load_bundle/lazy/index.ts | 2 +- x-pack/plugins/maps/public/plugin.ts | 2 +- 65 files changed, 135 insertions(+), 111 deletions(-) create mode 100644 x-pack/plugins/maps/public/classes/layers/index.ts rename x-pack/plugins/maps/public/classes/layers/{ => wizards}/choropleth_layer_wizard/__snapshots__/layer_template.test.tsx.snap (100%) rename x-pack/plugins/maps/public/classes/layers/{ => wizards}/choropleth_layer_wizard/choropleth_layer_wizard.tsx (93%) rename x-pack/plugins/maps/public/classes/layers/{ => wizards}/choropleth_layer_wizard/create_choropleth_layer_descriptor.ts (88%) rename x-pack/plugins/maps/public/classes/layers/{ => wizards}/choropleth_layer_wizard/index.ts (100%) rename x-pack/plugins/maps/public/classes/layers/{ => wizards}/choropleth_layer_wizard/layer_template.test.tsx (96%) rename x-pack/plugins/maps/public/classes/layers/{ => wizards}/choropleth_layer_wizard/layer_template.tsx (96%) rename x-pack/plugins/maps/public/classes/layers/{ => wizards}/file_upload_wizard/config.tsx (92%) rename x-pack/plugins/maps/public/classes/layers/{ => wizards}/file_upload_wizard/index.ts (100%) rename x-pack/plugins/maps/public/classes/layers/{ => wizards}/file_upload_wizard/wizard.tsx (89%) rename x-pack/plugins/maps/public/classes/layers/{ => wizards}/icons/cloropleth_layer_icon.tsx (100%) rename x-pack/plugins/maps/public/classes/layers/{ => wizards}/icons/clusters_layer_icon.tsx (100%) rename x-pack/plugins/maps/public/classes/layers/{ => wizards}/icons/documents_layer_icon.tsx (100%) rename x-pack/plugins/maps/public/classes/layers/{ => wizards}/icons/draw_layer_icon.tsx (100%) rename x-pack/plugins/maps/public/classes/layers/{ => wizards}/icons/ems_boundaries_layer_icon.tsx (100%) rename x-pack/plugins/maps/public/classes/layers/{ => wizards}/icons/heatmap_layer_icon.tsx (100%) rename x-pack/plugins/maps/public/classes/layers/{ => wizards}/icons/point_2_point_layer_icon.tsx (100%) rename x-pack/plugins/maps/public/classes/layers/{ => wizards}/icons/top_hits_layer_icon.tsx (100%) rename x-pack/plugins/maps/public/classes/layers/{ => wizards}/icons/tracks_layer_icon.tsx (100%) rename x-pack/plugins/maps/public/classes/layers/{ => wizards}/icons/vector_tile_layer_icon.tsx (100%) rename x-pack/plugins/maps/public/classes/layers/{ => wizards}/icons/web_map_service_layer_icon.tsx (100%) rename x-pack/plugins/maps/public/classes/layers/{ => wizards}/icons/world_map_layer_icon.tsx (100%) create mode 100644 x-pack/plugins/maps/public/classes/layers/wizards/index.ts rename x-pack/plugins/maps/public/classes/layers/{ => wizards}/layer_wizard_registry.ts (93%) rename x-pack/plugins/maps/public/classes/layers/{ => wizards}/load_layer_wizards.ts (71%) rename x-pack/plugins/maps/public/classes/layers/{ => wizards}/new_vector_layer_wizard/config.tsx (85%) rename x-pack/plugins/maps/public/classes/layers/{ => wizards}/new_vector_layer_wizard/create_new_index_pattern.ts (84%) rename x-pack/plugins/maps/public/classes/layers/{ => wizards}/new_vector_layer_wizard/index.ts (100%) rename x-pack/plugins/maps/public/classes/layers/{ => wizards}/new_vector_layer_wizard/wizard.tsx (95%) rename x-pack/plugins/maps/public/classes/layers/{ => wizards}/solution_layers/observability/create_layer_descriptor.test.ts (98%) rename x-pack/plugins/maps/public/classes/layers/{ => wizards}/solution_layers/observability/create_layer_descriptor.ts (92%) rename x-pack/plugins/maps/public/classes/layers/{ => wizards}/solution_layers/observability/display_select.tsx (100%) rename x-pack/plugins/maps/public/classes/layers/{ => wizards}/solution_layers/observability/index.ts (100%) rename x-pack/plugins/maps/public/classes/layers/{ => wizards}/solution_layers/observability/layer_select.tsx (100%) rename x-pack/plugins/maps/public/classes/layers/{ => wizards}/solution_layers/observability/metric_select.tsx (100%) rename x-pack/plugins/maps/public/classes/layers/{ => wizards}/solution_layers/observability/observability_layer_template.tsx (100%) rename x-pack/plugins/maps/public/classes/layers/{ => wizards}/solution_layers/observability/observability_layer_wizard.tsx (90%) rename x-pack/plugins/maps/public/classes/layers/{ => wizards}/solution_layers/security/create_layer_descriptors.test.ts (99%) rename x-pack/plugins/maps/public/classes/layers/{ => wizards}/solution_layers/security/create_layer_descriptors.ts (93%) rename x-pack/plugins/maps/public/classes/layers/{ => wizards}/solution_layers/security/index.ts (100%) rename x-pack/plugins/maps/public/classes/layers/{ => wizards}/solution_layers/security/index_pattern_select.tsx (96%) rename x-pack/plugins/maps/public/classes/layers/{ => wizards}/solution_layers/security/security_index_pattern_utils.ts (98%) rename x-pack/plugins/maps/public/classes/layers/{ => wizards}/solution_layers/security/security_layer_template.tsx (100%) rename x-pack/plugins/maps/public/classes/layers/{ => wizards}/solution_layers/security/security_layer_wizard.tsx (94%) diff --git a/x-pack/plugins/maps/public/api/setup_api.ts b/x-pack/plugins/maps/public/api/setup_api.ts index 3fb80afc665c2..31c91f11651ef 100644 --- a/x-pack/plugins/maps/public/api/setup_api.ts +++ b/x-pack/plugins/maps/public/api/setup_api.ts @@ -6,7 +6,7 @@ */ import type { SourceRegistryEntry } from '../classes/sources/source_registry'; -import type { LayerWizard } from '../classes/layers/layer_wizard_registry'; +import type { LayerWizard } from '../classes/layers'; export interface MapsSetupApi { registerLayerWizard(layerWizard: LayerWizard): void; diff --git a/x-pack/plugins/maps/public/classes/layers/index.ts b/x-pack/plugins/maps/public/classes/layers/index.ts new file mode 100644 index 0000000000000..688cbd409c450 --- /dev/null +++ b/x-pack/plugins/maps/public/classes/layers/index.ts @@ -0,0 +1,9 @@ +/* + * 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 type { LayerWizard, LayerWizardWithMeta, RenderWizardArguments } from './wizards'; +export { getLayerWizards, registerLayerWizard } from './wizards'; diff --git a/x-pack/plugins/maps/public/classes/layers/choropleth_layer_wizard/__snapshots__/layer_template.test.tsx.snap b/x-pack/plugins/maps/public/classes/layers/wizards/choropleth_layer_wizard/__snapshots__/layer_template.test.tsx.snap similarity index 100% rename from x-pack/plugins/maps/public/classes/layers/choropleth_layer_wizard/__snapshots__/layer_template.test.tsx.snap rename to x-pack/plugins/maps/public/classes/layers/wizards/choropleth_layer_wizard/__snapshots__/layer_template.test.tsx.snap diff --git a/x-pack/plugins/maps/public/classes/layers/choropleth_layer_wizard/choropleth_layer_wizard.tsx b/x-pack/plugins/maps/public/classes/layers/wizards/choropleth_layer_wizard/choropleth_layer_wizard.tsx similarity index 93% rename from x-pack/plugins/maps/public/classes/layers/choropleth_layer_wizard/choropleth_layer_wizard.tsx rename to x-pack/plugins/maps/public/classes/layers/wizards/choropleth_layer_wizard/choropleth_layer_wizard.tsx index f047dad76d90a..2670a6ac82c78 100644 --- a/x-pack/plugins/maps/public/classes/layers/choropleth_layer_wizard/choropleth_layer_wizard.tsx +++ b/x-pack/plugins/maps/public/classes/layers/wizards/choropleth_layer_wizard/choropleth_layer_wizard.tsx @@ -7,7 +7,7 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; -import { LAYER_WIZARD_CATEGORY } from '../../../../common/constants'; +import { LAYER_WIZARD_CATEGORY } from '../../../../../common/constants'; import { LayerWizard, RenderWizardArguments } from '../layer_wizard_registry'; import { LayerTemplate } from './layer_template'; import { ChoroplethLayerIcon } from '../icons/cloropleth_layer_icon'; diff --git a/x-pack/plugins/maps/public/classes/layers/choropleth_layer_wizard/create_choropleth_layer_descriptor.ts b/x-pack/plugins/maps/public/classes/layers/wizards/choropleth_layer_wizard/create_choropleth_layer_descriptor.ts similarity index 88% rename from x-pack/plugins/maps/public/classes/layers/choropleth_layer_wizard/create_choropleth_layer_descriptor.ts rename to x-pack/plugins/maps/public/classes/layers/wizards/choropleth_layer_wizard/create_choropleth_layer_descriptor.ts index ad507aa171631..dc647089b3516 100644 --- a/x-pack/plugins/maps/public/classes/layers/choropleth_layer_wizard/create_choropleth_layer_descriptor.ts +++ b/x-pack/plugins/maps/public/classes/layers/wizards/choropleth_layer_wizard/create_choropleth_layer_descriptor.ts @@ -14,20 +14,20 @@ import { SOURCE_TYPES, STYLE_TYPE, VECTOR_STYLES, -} from '../../../../common/constants'; -import { getJoinAggKey } from '../../../../common/get_agg_key'; +} from '../../../../../common/constants'; +import { getJoinAggKey } from '../../../../../common/get_agg_key'; import { ColorDynamicOptions, CountAggDescriptor, EMSFileSourceDescriptor, ESSearchSourceDescriptor, -} from '../../../../common/descriptor_types'; -import { VectorStyle } from '../../styles/vector/vector_style'; -import { GeoJsonVectorLayer } from '../vector_layer'; -import { EMSFileSource } from '../../sources/ems_file_source'; +} from '../../../../../common/descriptor_types'; +import { VectorStyle } from '../../../styles/vector/vector_style'; +import { GeoJsonVectorLayer } from '../../vector_layer'; +import { EMSFileSource } from '../../../sources/ems_file_source'; // @ts-ignore -import { ESSearchSource } from '../../sources/es_search_source'; -import { getDefaultDynamicProperties } from '../../styles/vector/vector_style_defaults'; +import { ESSearchSource } from '../../../sources/es_search_source'; +import { getDefaultDynamicProperties } from '../../../styles/vector/vector_style_defaults'; const defaultDynamicProperties = getDefaultDynamicProperties(); diff --git a/x-pack/plugins/maps/public/classes/layers/choropleth_layer_wizard/index.ts b/x-pack/plugins/maps/public/classes/layers/wizards/choropleth_layer_wizard/index.ts similarity index 100% rename from x-pack/plugins/maps/public/classes/layers/choropleth_layer_wizard/index.ts rename to x-pack/plugins/maps/public/classes/layers/wizards/choropleth_layer_wizard/index.ts diff --git a/x-pack/plugins/maps/public/classes/layers/choropleth_layer_wizard/layer_template.test.tsx b/x-pack/plugins/maps/public/classes/layers/wizards/choropleth_layer_wizard/layer_template.test.tsx similarity index 96% rename from x-pack/plugins/maps/public/classes/layers/choropleth_layer_wizard/layer_template.test.tsx rename to x-pack/plugins/maps/public/classes/layers/wizards/choropleth_layer_wizard/layer_template.test.tsx index 6c352b4a39340..38cabd6dc5aea 100644 --- a/x-pack/plugins/maps/public/classes/layers/choropleth_layer_wizard/layer_template.test.tsx +++ b/x-pack/plugins/maps/public/classes/layers/wizards/choropleth_layer_wizard/layer_template.test.tsx @@ -5,7 +5,7 @@ * 2.0. */ -jest.mock('../../../kibana_services', () => { +jest.mock('../../../../kibana_services', () => { const MockIndexPatternSelect = (props: unknown) => { return
; }; diff --git a/x-pack/plugins/maps/public/classes/layers/choropleth_layer_wizard/layer_template.tsx b/x-pack/plugins/maps/public/classes/layers/wizards/choropleth_layer_wizard/layer_template.tsx similarity index 96% rename from x-pack/plugins/maps/public/classes/layers/choropleth_layer_wizard/layer_template.tsx rename to x-pack/plugins/maps/public/classes/layers/wizards/choropleth_layer_wizard/layer_template.tsx index 5bfa815eafd80..ab94f239b2183 100644 --- a/x-pack/plugins/maps/public/classes/layers/choropleth_layer_wizard/layer_template.tsx +++ b/x-pack/plugins/maps/public/classes/layers/wizards/choropleth_layer_wizard/layer_template.tsx @@ -19,14 +19,17 @@ import { EuiTitle, } from '@elastic/eui'; import { IndexPatternField, IndexPattern } from 'src/plugins/data/public'; -import { getDataViewLabel, getDataViewSelectPlaceholder } from '../../../../common/i18n_getters'; +import { getDataViewLabel, getDataViewSelectPlaceholder } from '../../../../../common/i18n_getters'; import { RenderWizardArguments } from '../layer_wizard_registry'; -import { EMSFileSelect } from '../../../components/ems_file_select'; -import { GeoIndexPatternSelect } from '../../../components/geo_index_pattern_select'; -import { SingleFieldSelect } from '../../../components/single_field_select'; -import { getGeoFields, getSourceFields, getTermsFields } from '../../../index_pattern_util'; -import { getEmsFileLayers } from '../../../util'; -import { getIndexPatternSelectComponent, getIndexPatternService } from '../../../kibana_services'; +import { EMSFileSelect } from '../../../../components/ems_file_select'; +import { GeoIndexPatternSelect } from '../../../../components/geo_index_pattern_select'; +import { SingleFieldSelect } from '../../../../components/single_field_select'; +import { getGeoFields, getSourceFields, getTermsFields } from '../../../../index_pattern_util'; +import { getEmsFileLayers } from '../../../../util'; +import { + getIndexPatternSelectComponent, + getIndexPatternService, +} from '../../../../kibana_services'; import { createEmsChoroplethLayerDescriptor, createEsChoroplethLayerDescriptor, diff --git a/x-pack/plugins/maps/public/classes/layers/file_upload_wizard/config.tsx b/x-pack/plugins/maps/public/classes/layers/wizards/file_upload_wizard/config.tsx similarity index 92% rename from x-pack/plugins/maps/public/classes/layers/file_upload_wizard/config.tsx rename to x-pack/plugins/maps/public/classes/layers/wizards/file_upload_wizard/config.tsx index 96102d7e0e998..586667b9a1ecb 100644 --- a/x-pack/plugins/maps/public/classes/layers/file_upload_wizard/config.tsx +++ b/x-pack/plugins/maps/public/classes/layers/wizards/file_upload_wizard/config.tsx @@ -7,9 +7,9 @@ import { i18n } from '@kbn/i18n'; import React from 'react'; -import { LayerWizard, RenderWizardArguments } from '../../layers/layer_wizard_registry'; +import { LayerWizard, RenderWizardArguments } from '../layer_wizard_registry'; import { ClientFileCreateSourceEditor, UPLOAD_STEPS } from './wizard'; -import { getFileUpload } from '../../../kibana_services'; +import { getFileUpload } from '../../../../kibana_services'; export const uploadLayerWizardConfig: LayerWizard = { categories: [], diff --git a/x-pack/plugins/maps/public/classes/layers/file_upload_wizard/index.ts b/x-pack/plugins/maps/public/classes/layers/wizards/file_upload_wizard/index.ts similarity index 100% rename from x-pack/plugins/maps/public/classes/layers/file_upload_wizard/index.ts rename to x-pack/plugins/maps/public/classes/layers/wizards/file_upload_wizard/index.ts diff --git a/x-pack/plugins/maps/public/classes/layers/file_upload_wizard/wizard.tsx b/x-pack/plugins/maps/public/classes/layers/wizards/file_upload_wizard/wizard.tsx similarity index 89% rename from x-pack/plugins/maps/public/classes/layers/file_upload_wizard/wizard.tsx rename to x-pack/plugins/maps/public/classes/layers/wizards/file_upload_wizard/wizard.tsx index f29a4c3a55e28..2ec05f72c8d94 100644 --- a/x-pack/plugins/maps/public/classes/layers/file_upload_wizard/wizard.tsx +++ b/x-pack/plugins/maps/public/classes/layers/wizards/file_upload_wizard/wizard.tsx @@ -10,14 +10,14 @@ import { i18n } from '@kbn/i18n'; import React, { Component } from 'react'; import { FeatureCollection } from 'geojson'; import { EuiPanel } from '@elastic/eui'; -import { DEFAULT_MAX_RESULT_WINDOW, SCALING_TYPES } from '../../../../common/constants'; -import { GeoJsonFileSource } from '../../sources/geojson_file_source'; -import { GeoJsonVectorLayer } from '../../layers/vector_layer'; -import { createDefaultLayerDescriptor } from '../../sources/es_search_source'; -import { RenderWizardArguments } from '../../layers/layer_wizard_registry'; -import { FileUploadGeoResults } from '../../../../../file_upload/public'; -import { ES_FIELD_TYPES } from '../../../../../../../src/plugins/data/public'; -import { getFileUploadComponent } from '../../../kibana_services'; +import { DEFAULT_MAX_RESULT_WINDOW, SCALING_TYPES } from '../../../../../common/constants'; +import { GeoJsonFileSource } from '../../../sources/geojson_file_source'; +import { GeoJsonVectorLayer } from '../../vector_layer'; +import { createDefaultLayerDescriptor } from '../../../sources/es_search_source'; +import { RenderWizardArguments } from '../layer_wizard_registry'; +import { FileUploadGeoResults } from '../../../../../../file_upload/public'; +import { ES_FIELD_TYPES } from '../../../../../../../../src/plugins/data/public'; +import { getFileUploadComponent } from '../../../../kibana_services'; export enum UPLOAD_STEPS { CONFIGURE_UPLOAD = 'CONFIGURE_UPLOAD', diff --git a/x-pack/plugins/maps/public/classes/layers/icons/cloropleth_layer_icon.tsx b/x-pack/plugins/maps/public/classes/layers/wizards/icons/cloropleth_layer_icon.tsx similarity index 100% rename from x-pack/plugins/maps/public/classes/layers/icons/cloropleth_layer_icon.tsx rename to x-pack/plugins/maps/public/classes/layers/wizards/icons/cloropleth_layer_icon.tsx diff --git a/x-pack/plugins/maps/public/classes/layers/icons/clusters_layer_icon.tsx b/x-pack/plugins/maps/public/classes/layers/wizards/icons/clusters_layer_icon.tsx similarity index 100% rename from x-pack/plugins/maps/public/classes/layers/icons/clusters_layer_icon.tsx rename to x-pack/plugins/maps/public/classes/layers/wizards/icons/clusters_layer_icon.tsx diff --git a/x-pack/plugins/maps/public/classes/layers/icons/documents_layer_icon.tsx b/x-pack/plugins/maps/public/classes/layers/wizards/icons/documents_layer_icon.tsx similarity index 100% rename from x-pack/plugins/maps/public/classes/layers/icons/documents_layer_icon.tsx rename to x-pack/plugins/maps/public/classes/layers/wizards/icons/documents_layer_icon.tsx diff --git a/x-pack/plugins/maps/public/classes/layers/icons/draw_layer_icon.tsx b/x-pack/plugins/maps/public/classes/layers/wizards/icons/draw_layer_icon.tsx similarity index 100% rename from x-pack/plugins/maps/public/classes/layers/icons/draw_layer_icon.tsx rename to x-pack/plugins/maps/public/classes/layers/wizards/icons/draw_layer_icon.tsx diff --git a/x-pack/plugins/maps/public/classes/layers/icons/ems_boundaries_layer_icon.tsx b/x-pack/plugins/maps/public/classes/layers/wizards/icons/ems_boundaries_layer_icon.tsx similarity index 100% rename from x-pack/plugins/maps/public/classes/layers/icons/ems_boundaries_layer_icon.tsx rename to x-pack/plugins/maps/public/classes/layers/wizards/icons/ems_boundaries_layer_icon.tsx diff --git a/x-pack/plugins/maps/public/classes/layers/icons/heatmap_layer_icon.tsx b/x-pack/plugins/maps/public/classes/layers/wizards/icons/heatmap_layer_icon.tsx similarity index 100% rename from x-pack/plugins/maps/public/classes/layers/icons/heatmap_layer_icon.tsx rename to x-pack/plugins/maps/public/classes/layers/wizards/icons/heatmap_layer_icon.tsx diff --git a/x-pack/plugins/maps/public/classes/layers/icons/point_2_point_layer_icon.tsx b/x-pack/plugins/maps/public/classes/layers/wizards/icons/point_2_point_layer_icon.tsx similarity index 100% rename from x-pack/plugins/maps/public/classes/layers/icons/point_2_point_layer_icon.tsx rename to x-pack/plugins/maps/public/classes/layers/wizards/icons/point_2_point_layer_icon.tsx diff --git a/x-pack/plugins/maps/public/classes/layers/icons/top_hits_layer_icon.tsx b/x-pack/plugins/maps/public/classes/layers/wizards/icons/top_hits_layer_icon.tsx similarity index 100% rename from x-pack/plugins/maps/public/classes/layers/icons/top_hits_layer_icon.tsx rename to x-pack/plugins/maps/public/classes/layers/wizards/icons/top_hits_layer_icon.tsx diff --git a/x-pack/plugins/maps/public/classes/layers/icons/tracks_layer_icon.tsx b/x-pack/plugins/maps/public/classes/layers/wizards/icons/tracks_layer_icon.tsx similarity index 100% rename from x-pack/plugins/maps/public/classes/layers/icons/tracks_layer_icon.tsx rename to x-pack/plugins/maps/public/classes/layers/wizards/icons/tracks_layer_icon.tsx diff --git a/x-pack/plugins/maps/public/classes/layers/icons/vector_tile_layer_icon.tsx b/x-pack/plugins/maps/public/classes/layers/wizards/icons/vector_tile_layer_icon.tsx similarity index 100% rename from x-pack/plugins/maps/public/classes/layers/icons/vector_tile_layer_icon.tsx rename to x-pack/plugins/maps/public/classes/layers/wizards/icons/vector_tile_layer_icon.tsx diff --git a/x-pack/plugins/maps/public/classes/layers/icons/web_map_service_layer_icon.tsx b/x-pack/plugins/maps/public/classes/layers/wizards/icons/web_map_service_layer_icon.tsx similarity index 100% rename from x-pack/plugins/maps/public/classes/layers/icons/web_map_service_layer_icon.tsx rename to x-pack/plugins/maps/public/classes/layers/wizards/icons/web_map_service_layer_icon.tsx diff --git a/x-pack/plugins/maps/public/classes/layers/icons/world_map_layer_icon.tsx b/x-pack/plugins/maps/public/classes/layers/wizards/icons/world_map_layer_icon.tsx similarity index 100% rename from x-pack/plugins/maps/public/classes/layers/icons/world_map_layer_icon.tsx rename to x-pack/plugins/maps/public/classes/layers/wizards/icons/world_map_layer_icon.tsx diff --git a/x-pack/plugins/maps/public/classes/layers/wizards/index.ts b/x-pack/plugins/maps/public/classes/layers/wizards/index.ts new file mode 100644 index 0000000000000..d925fb50eb60d --- /dev/null +++ b/x-pack/plugins/maps/public/classes/layers/wizards/index.ts @@ -0,0 +1,13 @@ +/* + * 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 type { + LayerWizard, + LayerWizardWithMeta, + RenderWizardArguments, +} from './layer_wizard_registry'; +export { getLayerWizards, registerLayerWizard } from './layer_wizard_registry'; diff --git a/x-pack/plugins/maps/public/classes/layers/layer_wizard_registry.ts b/x-pack/plugins/maps/public/classes/layers/wizards/layer_wizard_registry.ts similarity index 93% rename from x-pack/plugins/maps/public/classes/layers/layer_wizard_registry.ts rename to x-pack/plugins/maps/public/classes/layers/wizards/layer_wizard_registry.ts index 1c4ff5a457ba3..251af230d5278 100644 --- a/x-pack/plugins/maps/public/classes/layers/layer_wizard_registry.ts +++ b/x-pack/plugins/maps/public/classes/layers/wizards/layer_wizard_registry.ts @@ -8,8 +8,8 @@ /* eslint-disable @typescript-eslint/consistent-type-definitions */ import { ReactElement, FunctionComponent } from 'react'; -import type { LayerDescriptor } from '../../../common/descriptor_types'; -import { LAYER_WIZARD_CATEGORY } from '../../../common/constants'; +import type { LayerDescriptor } from '../../../../common/descriptor_types'; +import { LAYER_WIZARD_CATEGORY } from '../../../../common/constants'; export type RenderWizardArguments = { previewLayers: (layerDescriptors: LayerDescriptor[]) => void; diff --git a/x-pack/plugins/maps/public/classes/layers/load_layer_wizards.ts b/x-pack/plugins/maps/public/classes/layers/wizards/load_layer_wizards.ts similarity index 71% rename from x-pack/plugins/maps/public/classes/layers/load_layer_wizards.ts rename to x-pack/plugins/maps/public/classes/layers/wizards/load_layer_wizards.ts index 928c6a5362c66..0b9558a393e78 100644 --- a/x-pack/plugins/maps/public/classes/layers/load_layer_wizards.ts +++ b/x-pack/plugins/maps/public/classes/layers/wizards/load_layer_wizards.ts @@ -10,21 +10,24 @@ import { uploadLayerWizardConfig } from './file_upload_wizard'; import { esDocumentsLayerWizardConfig, esTopHitsLayerWizardConfig, -} from '../sources/es_search_source'; -import { clustersLayerWizardConfig, heatmapLayerWizardConfig } from '../sources/es_geo_grid_source'; -import { geoLineLayerWizardConfig } from '../sources/es_geo_line_source'; +} from '../../sources/es_search_source'; +import { + clustersLayerWizardConfig, + heatmapLayerWizardConfig, +} from '../../sources/es_geo_grid_source'; +import { geoLineLayerWizardConfig } from '../../sources/es_geo_line_source'; // @ts-ignore -import { point2PointLayerWizardConfig } from '../sources/es_pew_pew_source'; +import { point2PointLayerWizardConfig } from '../../sources/es_pew_pew_source'; // @ts-ignore -import { emsBoundariesLayerWizardConfig } from '../sources/ems_file_source'; +import { emsBoundariesLayerWizardConfig } from '../../sources/ems_file_source'; // @ts-ignore -import { emsBaseMapLayerWizardConfig } from '../sources/ems_tms_source'; +import { emsBaseMapLayerWizardConfig } from '../../sources/ems_tms_source'; // @ts-ignore -import { kibanaBasemapLayerWizardConfig } from '../sources/kibana_tilemap_source'; -import { tmsLayerWizardConfig } from '../sources/xyz_tms_source'; +import { kibanaBasemapLayerWizardConfig } from '../../sources/kibana_tilemap_source'; +import { tmsLayerWizardConfig } from '../../sources/xyz_tms_source'; // @ts-ignore -import { wmsLayerWizardConfig } from '../sources/wms_source'; -import { mvtVectorSourceWizardConfig } from '../sources/mvt_single_layer_vector_source'; +import { wmsLayerWizardConfig } from '../../sources/wms_source'; +import { mvtVectorSourceWizardConfig } from '../../sources/mvt_single_layer_vector_source'; import { ObservabilityLayerWizardConfig } from './solution_layers/observability'; import { SecurityLayerWizardConfig } from './solution_layers/security'; import { choroplethLayerWizardConfig } from './choropleth_layer_wizard'; diff --git a/x-pack/plugins/maps/public/classes/layers/new_vector_layer_wizard/config.tsx b/x-pack/plugins/maps/public/classes/layers/wizards/new_vector_layer_wizard/config.tsx similarity index 85% rename from x-pack/plugins/maps/public/classes/layers/new_vector_layer_wizard/config.tsx rename to x-pack/plugins/maps/public/classes/layers/wizards/new_vector_layer_wizard/config.tsx index 0c3d1dc41d640..d6376470ae71f 100644 --- a/x-pack/plugins/maps/public/classes/layers/new_vector_layer_wizard/config.tsx +++ b/x-pack/plugins/maps/public/classes/layers/wizards/new_vector_layer_wizard/config.tsx @@ -7,11 +7,11 @@ import { i18n } from '@kbn/i18n'; import React from 'react'; -import { LayerWizard, RenderWizardArguments } from '../../layers/layer_wizard_registry'; +import { LayerWizard, RenderWizardArguments } from '../layer_wizard_registry'; import { NewVectorLayerEditor } from './wizard'; -import { DrawLayerIcon } from '../../layers/icons/draw_layer_icon'; -import { getFileUpload } from '../../../kibana_services'; -import { LAYER_WIZARD_CATEGORY } from '../../../../common/constants'; +import { DrawLayerIcon } from '../icons/draw_layer_icon'; +import { getFileUpload } from '../../../../kibana_services'; +import { LAYER_WIZARD_CATEGORY } from '../../../../../common/constants'; const ADD_VECTOR_DRAWING_LAYER = 'ADD_VECTOR_DRAWING_LAYER'; diff --git a/x-pack/plugins/maps/public/classes/layers/new_vector_layer_wizard/create_new_index_pattern.ts b/x-pack/plugins/maps/public/classes/layers/wizards/new_vector_layer_wizard/create_new_index_pattern.ts similarity index 84% rename from x-pack/plugins/maps/public/classes/layers/new_vector_layer_wizard/create_new_index_pattern.ts rename to x-pack/plugins/maps/public/classes/layers/wizards/new_vector_layer_wizard/create_new_index_pattern.ts index 596d2ce86bbe2..90ef4b90a4992 100644 --- a/x-pack/plugins/maps/public/classes/layers/new_vector_layer_wizard/create_new_index_pattern.ts +++ b/x-pack/plugins/maps/public/classes/layers/wizards/new_vector_layer_wizard/create_new_index_pattern.ts @@ -5,9 +5,9 @@ * 2.0. */ -import { getHttp } from '../../../kibana_services'; -import { CreateDocSourceResp, IndexSourceMappings } from '../../../../common/types'; -import { INDEX_SOURCE_API_PATH } from '../../../../common/constants'; +import { getHttp } from '../../../../kibana_services'; +import { CreateDocSourceResp, IndexSourceMappings } from '../../../../../common/types'; +import { INDEX_SOURCE_API_PATH } from '../../../../../common/constants'; export const createNewIndexAndPattern = async ({ indexName, diff --git a/x-pack/plugins/maps/public/classes/layers/new_vector_layer_wizard/index.ts b/x-pack/plugins/maps/public/classes/layers/wizards/new_vector_layer_wizard/index.ts similarity index 100% rename from x-pack/plugins/maps/public/classes/layers/new_vector_layer_wizard/index.ts rename to x-pack/plugins/maps/public/classes/layers/wizards/new_vector_layer_wizard/index.ts diff --git a/x-pack/plugins/maps/public/classes/layers/new_vector_layer_wizard/wizard.tsx b/x-pack/plugins/maps/public/classes/layers/wizards/new_vector_layer_wizard/wizard.tsx similarity index 95% rename from x-pack/plugins/maps/public/classes/layers/new_vector_layer_wizard/wizard.tsx rename to x-pack/plugins/maps/public/classes/layers/wizards/new_vector_layer_wizard/wizard.tsx index d26853850c387..b06cb50acb979 100644 --- a/x-pack/plugins/maps/public/classes/layers/new_vector_layer_wizard/wizard.tsx +++ b/x-pack/plugins/maps/public/classes/layers/wizards/new_vector_layer_wizard/wizard.tsx @@ -10,10 +10,10 @@ import { EuiPanel, EuiCallOut } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { createNewIndexAndPattern } from './create_new_index_pattern'; import { RenderWizardArguments } from '../layer_wizard_registry'; -import { GeoJsonVectorLayer } from '../vector_layer'; -import { ESSearchSource } from '../../sources/es_search_source'; -import { ADD_LAYER_STEP_ID } from '../../../connected_components/add_layer_panel/view'; -import { getFileUpload, getIndexNameFormComponent } from '../../../kibana_services'; +import { GeoJsonVectorLayer } from '../../vector_layer'; +import { ESSearchSource } from '../../../sources/es_search_source'; +import { ADD_LAYER_STEP_ID } from '../../../../connected_components/add_layer_panel/view'; +import { getFileUpload, getIndexNameFormComponent } from '../../../../kibana_services'; interface State { indexName: string; diff --git a/x-pack/plugins/maps/public/classes/layers/solution_layers/observability/create_layer_descriptor.test.ts b/x-pack/plugins/maps/public/classes/layers/wizards/solution_layers/observability/create_layer_descriptor.test.ts similarity index 98% rename from x-pack/plugins/maps/public/classes/layers/solution_layers/observability/create_layer_descriptor.test.ts rename to x-pack/plugins/maps/public/classes/layers/wizards/solution_layers/observability/create_layer_descriptor.test.ts index 8955342824a77..7c762ac3409f8 100644 --- a/x-pack/plugins/maps/public/classes/layers/solution_layers/observability/create_layer_descriptor.test.ts +++ b/x-pack/plugins/maps/public/classes/layers/wizards/solution_layers/observability/create_layer_descriptor.test.ts @@ -5,9 +5,9 @@ * 2.0. */ -import { emsWorldLayerId } from '../../../../../common/constants'; +import { emsWorldLayerId } from '../../../../../../common/constants'; -jest.mock('../../../../kibana_services', () => { +jest.mock('../../../../../kibana_services', () => { return { getIsDarkMode() { return false; diff --git a/x-pack/plugins/maps/public/classes/layers/solution_layers/observability/create_layer_descriptor.ts b/x-pack/plugins/maps/public/classes/layers/wizards/solution_layers/observability/create_layer_descriptor.ts similarity index 92% rename from x-pack/plugins/maps/public/classes/layers/solution_layers/observability/create_layer_descriptor.ts rename to x-pack/plugins/maps/public/classes/layers/wizards/solution_layers/observability/create_layer_descriptor.ts index 9f5a65faad850..26a9f14b8160f 100644 --- a/x-pack/plugins/maps/public/classes/layers/solution_layers/observability/create_layer_descriptor.ts +++ b/x-pack/plugins/maps/public/classes/layers/wizards/solution_layers/observability/create_layer_descriptor.ts @@ -14,7 +14,7 @@ import { SizeDynamicOptions, StylePropertyField, VectorStylePropertiesDescriptor, -} from '../../../../../common/descriptor_types'; +} from '../../../../../../common/descriptor_types'; import { AGG_TYPE, COLOR_MAP_TYPE, @@ -25,17 +25,17 @@ import { SOURCE_TYPES, STYLE_TYPE, VECTOR_STYLES, -} from '../../../../../common/constants'; -import { getJoinAggKey, getSourceAggKey } from '../../../../../common/get_agg_key'; +} from '../../../../../../common/constants'; +import { getJoinAggKey, getSourceAggKey } from '../../../../../../common/get_agg_key'; import { OBSERVABILITY_LAYER_TYPE } from './layer_select'; import { OBSERVABILITY_METRIC_TYPE } from './metric_select'; import { DISPLAY } from './display_select'; -import { VectorStyle } from '../../../styles/vector/vector_style'; -import { EMSFileSource } from '../../../sources/ems_file_source'; -import { ESGeoGridSource } from '../../../sources/es_geo_grid_source'; -import { GeoJsonVectorLayer } from '../../vector_layer'; -import { HeatmapLayer } from '../../heatmap_layer'; -import { getDefaultDynamicProperties } from '../../../styles/vector/vector_style_defaults'; +import { VectorStyle } from '../../../../styles/vector/vector_style'; +import { EMSFileSource } from '../../../../sources/ems_file_source'; +import { ESGeoGridSource } from '../../../../sources/es_geo_grid_source'; +import { GeoJsonVectorLayer } from '../../../vector_layer'; +import { HeatmapLayer } from '../../../heatmap_layer'; +import { getDefaultDynamicProperties } from '../../../../styles/vector/vector_style_defaults'; // redefining APM constant to avoid making maps app depend on APM plugin export const APM_INDEX_PATTERN_ID = 'apm_static_index_pattern_id'; diff --git a/x-pack/plugins/maps/public/classes/layers/solution_layers/observability/display_select.tsx b/x-pack/plugins/maps/public/classes/layers/wizards/solution_layers/observability/display_select.tsx similarity index 100% rename from x-pack/plugins/maps/public/classes/layers/solution_layers/observability/display_select.tsx rename to x-pack/plugins/maps/public/classes/layers/wizards/solution_layers/observability/display_select.tsx diff --git a/x-pack/plugins/maps/public/classes/layers/solution_layers/observability/index.ts b/x-pack/plugins/maps/public/classes/layers/wizards/solution_layers/observability/index.ts similarity index 100% rename from x-pack/plugins/maps/public/classes/layers/solution_layers/observability/index.ts rename to x-pack/plugins/maps/public/classes/layers/wizards/solution_layers/observability/index.ts diff --git a/x-pack/plugins/maps/public/classes/layers/solution_layers/observability/layer_select.tsx b/x-pack/plugins/maps/public/classes/layers/wizards/solution_layers/observability/layer_select.tsx similarity index 100% rename from x-pack/plugins/maps/public/classes/layers/solution_layers/observability/layer_select.tsx rename to x-pack/plugins/maps/public/classes/layers/wizards/solution_layers/observability/layer_select.tsx diff --git a/x-pack/plugins/maps/public/classes/layers/solution_layers/observability/metric_select.tsx b/x-pack/plugins/maps/public/classes/layers/wizards/solution_layers/observability/metric_select.tsx similarity index 100% rename from x-pack/plugins/maps/public/classes/layers/solution_layers/observability/metric_select.tsx rename to x-pack/plugins/maps/public/classes/layers/wizards/solution_layers/observability/metric_select.tsx diff --git a/x-pack/plugins/maps/public/classes/layers/solution_layers/observability/observability_layer_template.tsx b/x-pack/plugins/maps/public/classes/layers/wizards/solution_layers/observability/observability_layer_template.tsx similarity index 100% rename from x-pack/plugins/maps/public/classes/layers/solution_layers/observability/observability_layer_template.tsx rename to x-pack/plugins/maps/public/classes/layers/wizards/solution_layers/observability/observability_layer_template.tsx diff --git a/x-pack/plugins/maps/public/classes/layers/solution_layers/observability/observability_layer_wizard.tsx b/x-pack/plugins/maps/public/classes/layers/wizards/solution_layers/observability/observability_layer_wizard.tsx similarity index 90% rename from x-pack/plugins/maps/public/classes/layers/solution_layers/observability/observability_layer_wizard.tsx rename to x-pack/plugins/maps/public/classes/layers/wizards/solution_layers/observability/observability_layer_wizard.tsx index 74f241b67de3b..a69b09fffd9ee 100644 --- a/x-pack/plugins/maps/public/classes/layers/solution_layers/observability/observability_layer_wizard.tsx +++ b/x-pack/plugins/maps/public/classes/layers/wizards/solution_layers/observability/observability_layer_wizard.tsx @@ -7,11 +7,11 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; -import { LAYER_WIZARD_CATEGORY } from '../../../../../common/constants'; +import { LAYER_WIZARD_CATEGORY } from '../../../../../../common/constants'; import { LayerWizard, RenderWizardArguments } from '../../layer_wizard_registry'; import { ObservabilityLayerTemplate } from './observability_layer_template'; import { APM_INDEX_PATTERN_ID } from './create_layer_descriptor'; -import { getIndexPatternService } from '../../../../kibana_services'; +import { getIndexPatternService } from '../../../../../kibana_services'; export const ObservabilityLayerWizardConfig: LayerWizard = { categories: [LAYER_WIZARD_CATEGORY.ELASTICSEARCH, LAYER_WIZARD_CATEGORY.SOLUTIONS], diff --git a/x-pack/plugins/maps/public/classes/layers/solution_layers/security/create_layer_descriptors.test.ts b/x-pack/plugins/maps/public/classes/layers/wizards/solution_layers/security/create_layer_descriptors.test.ts similarity index 99% rename from x-pack/plugins/maps/public/classes/layers/solution_layers/security/create_layer_descriptors.test.ts rename to x-pack/plugins/maps/public/classes/layers/wizards/solution_layers/security/create_layer_descriptors.test.ts index cc6a7dfd9e796..b5d4edc8cb43b 100644 --- a/x-pack/plugins/maps/public/classes/layers/solution_layers/security/create_layer_descriptors.test.ts +++ b/x-pack/plugins/maps/public/classes/layers/wizards/solution_layers/security/create_layer_descriptors.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -jest.mock('../../../../kibana_services', () => { +jest.mock('../../../../../kibana_services', () => { return { getIsDarkMode() { return false; diff --git a/x-pack/plugins/maps/public/classes/layers/solution_layers/security/create_layer_descriptors.ts b/x-pack/plugins/maps/public/classes/layers/wizards/solution_layers/security/create_layer_descriptors.ts similarity index 93% rename from x-pack/plugins/maps/public/classes/layers/solution_layers/security/create_layer_descriptors.ts rename to x-pack/plugins/maps/public/classes/layers/wizards/solution_layers/security/create_layer_descriptors.ts index 23c3fda066a8f..5792d861f6f5c 100644 --- a/x-pack/plugins/maps/public/classes/layers/solution_layers/security/create_layer_descriptors.ts +++ b/x-pack/plugins/maps/public/classes/layers/wizards/solution_layers/security/create_layer_descriptors.ts @@ -12,7 +12,7 @@ import { LayerDescriptor, SizeDynamicOptions, VectorStylePropertiesDescriptor, -} from '../../../../../common/descriptor_types'; +} from '../../../../../../common/descriptor_types'; import { AGG_TYPE, COUNT_PROP_NAME, @@ -21,14 +21,14 @@ import { STYLE_TYPE, SYMBOLIZE_AS_TYPES, VECTOR_STYLES, -} from '../../../../../common/constants'; -import { GeoJsonVectorLayer } from '../../vector_layer'; -import { VectorStyle } from '../../../styles/vector/vector_style'; +} from '../../../../../../common/constants'; +import { GeoJsonVectorLayer } from '../../../vector_layer'; +import { VectorStyle } from '../../../../styles/vector/vector_style'; // @ts-ignore -import { ESSearchSource } from '../../../sources/es_search_source'; +import { ESSearchSource } from '../../../../sources/es_search_source'; // @ts-ignore -import { ESPewPewSource } from '../../../sources/es_pew_pew_source'; -import { getDefaultDynamicProperties } from '../../../styles/vector/vector_style_defaults'; +import { ESPewPewSource } from '../../../../sources/es_pew_pew_source'; +import { getDefaultDynamicProperties } from '../../../../styles/vector/vector_style_defaults'; import { APM_INDEX_PATTERN_TITLE } from '../observability'; const defaultDynamicProperties = getDefaultDynamicProperties(); diff --git a/x-pack/plugins/maps/public/classes/layers/solution_layers/security/index.ts b/x-pack/plugins/maps/public/classes/layers/wizards/solution_layers/security/index.ts similarity index 100% rename from x-pack/plugins/maps/public/classes/layers/solution_layers/security/index.ts rename to x-pack/plugins/maps/public/classes/layers/wizards/solution_layers/security/index.ts diff --git a/x-pack/plugins/maps/public/classes/layers/solution_layers/security/index_pattern_select.tsx b/x-pack/plugins/maps/public/classes/layers/wizards/solution_layers/security/index_pattern_select.tsx similarity index 96% rename from x-pack/plugins/maps/public/classes/layers/solution_layers/security/index_pattern_select.tsx rename to x-pack/plugins/maps/public/classes/layers/wizards/solution_layers/security/index_pattern_select.tsx index 336b67f32fa43..4cae99322777a 100644 --- a/x-pack/plugins/maps/public/classes/layers/solution_layers/security/index_pattern_select.tsx +++ b/x-pack/plugins/maps/public/classes/layers/wizards/solution_layers/security/index_pattern_select.tsx @@ -8,7 +8,7 @@ import React, { ChangeEvent, Component } from 'react'; import { EuiFormRow, EuiSelect, EuiSelectOption } from '@elastic/eui'; import { getSecurityIndexPatterns, IndexPatternMeta } from './security_index_pattern_utils'; -import { getDataViewLabel } from '../../../../../common/i18n_getters'; +import { getDataViewLabel } from '../../../../../../common/i18n_getters'; interface Props { value: string; diff --git a/x-pack/plugins/maps/public/classes/layers/solution_layers/security/security_index_pattern_utils.ts b/x-pack/plugins/maps/public/classes/layers/wizards/solution_layers/security/security_index_pattern_utils.ts similarity index 98% rename from x-pack/plugins/maps/public/classes/layers/solution_layers/security/security_index_pattern_utils.ts rename to x-pack/plugins/maps/public/classes/layers/wizards/solution_layers/security/security_index_pattern_utils.ts index eb78bf6a3147f..e4c6340772a0a 100644 --- a/x-pack/plugins/maps/public/classes/layers/solution_layers/security/security_index_pattern_utils.ts +++ b/x-pack/plugins/maps/public/classes/layers/wizards/solution_layers/security/security_index_pattern_utils.ts @@ -8,7 +8,7 @@ /* eslint-disable @typescript-eslint/consistent-type-definitions */ import minimatch from 'minimatch'; -import { getIndexPatternService, getUiSettings } from '../../../../kibana_services'; +import { getIndexPatternService, getUiSettings } from '../../../../../kibana_services'; export type IndexPatternMeta = { id: string; diff --git a/x-pack/plugins/maps/public/classes/layers/solution_layers/security/security_layer_template.tsx b/x-pack/plugins/maps/public/classes/layers/wizards/solution_layers/security/security_layer_template.tsx similarity index 100% rename from x-pack/plugins/maps/public/classes/layers/solution_layers/security/security_layer_template.tsx rename to x-pack/plugins/maps/public/classes/layers/wizards/solution_layers/security/security_layer_template.tsx diff --git a/x-pack/plugins/maps/public/classes/layers/solution_layers/security/security_layer_wizard.tsx b/x-pack/plugins/maps/public/classes/layers/wizards/solution_layers/security/security_layer_wizard.tsx similarity index 94% rename from x-pack/plugins/maps/public/classes/layers/solution_layers/security/security_layer_wizard.tsx rename to x-pack/plugins/maps/public/classes/layers/wizards/solution_layers/security/security_layer_wizard.tsx index c03a4dc432c88..f055683722deb 100644 --- a/x-pack/plugins/maps/public/classes/layers/solution_layers/security/security_layer_wizard.tsx +++ b/x-pack/plugins/maps/public/classes/layers/wizards/solution_layers/security/security_layer_wizard.tsx @@ -7,7 +7,7 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; -import { LAYER_WIZARD_CATEGORY } from '../../../../../common/constants'; +import { LAYER_WIZARD_CATEGORY } from '../../../../../../common/constants'; import { LayerWizard, RenderWizardArguments } from '../../layer_wizard_registry'; import { getSecurityIndexPatterns } from './security_index_pattern_utils'; import { SecurityLayerTemplate } from './security_layer_template'; diff --git a/x-pack/plugins/maps/public/classes/sources/ems_file_source/ems_boundaries_layer_wizard.tsx b/x-pack/plugins/maps/public/classes/sources/ems_file_source/ems_boundaries_layer_wizard.tsx index dd2317506e5f9..ff899101ced49 100644 --- a/x-pack/plugins/maps/public/classes/sources/ems_file_source/ems_boundaries_layer_wizard.tsx +++ b/x-pack/plugins/maps/public/classes/sources/ems_file_source/ems_boundaries_layer_wizard.tsx @@ -8,7 +8,7 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; import { GeoJsonVectorLayer } from '../../layers/vector_layer'; -import { LayerWizard, RenderWizardArguments } from '../../layers/layer_wizard_registry'; +import { LayerWizard, RenderWizardArguments } from '../../layers'; import { EMSFileCreateSourceEditor } from './create_source_editor'; import { EMSFileSource, getSourceTitle } from './ems_file_source'; @@ -16,7 +16,7 @@ import { EMSFileSource, getSourceTitle } from './ems_file_source'; import { getEMSSettings } from '../../../kibana_services'; import { EMSFileSourceDescriptor } from '../../../../common/descriptor_types'; import { LAYER_WIZARD_CATEGORY } from '../../../../common/constants'; -import { EMSBoundariesLayerIcon } from '../../layers/icons/ems_boundaries_layer_icon'; +import { EMSBoundariesLayerIcon } from '../../layers/wizards/icons/ems_boundaries_layer_icon'; function getDescription() { const emsSettings = getEMSSettings(); diff --git a/x-pack/plugins/maps/public/classes/sources/ems_tms_source/ems_base_map_layer_wizard.tsx b/x-pack/plugins/maps/public/classes/sources/ems_tms_source/ems_base_map_layer_wizard.tsx index 859d8b95cef3f..9138b199fd578 100644 --- a/x-pack/plugins/maps/public/classes/sources/ems_tms_source/ems_base_map_layer_wizard.tsx +++ b/x-pack/plugins/maps/public/classes/sources/ems_tms_source/ems_base_map_layer_wizard.tsx @@ -7,7 +7,7 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; -import { LayerWizard, RenderWizardArguments } from '../../layers/layer_wizard_registry'; +import { LayerWizard, RenderWizardArguments } from '../../layers'; // @ts-ignore import { EMSTMSSource, getSourceTitle } from './ems_tms_source'; // @ts-ignore @@ -16,7 +16,7 @@ import { EmsTmsSourceConfig } from './tile_service_select'; import { CreateSourceEditor } from './create_source_editor'; import { getEMSSettings } from '../../../kibana_services'; import { LAYER_WIZARD_CATEGORY } from '../../../../common/constants'; -import { WorldMapLayerIcon } from '../../layers/icons/world_map_layer_icon'; +import { WorldMapLayerIcon } from '../../layers/wizards/icons/world_map_layer_icon'; function getDescription() { const emsSettings = getEMSSettings(); diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/clusters_layer_wizard.tsx b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/clusters_layer_wizard.tsx index ad046eeb02d47..37586cf9f15ed 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/clusters_layer_wizard.tsx +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/clusters_layer_wizard.tsx @@ -10,7 +10,7 @@ import React from 'react'; // @ts-ignore import { CreateSourceEditor } from './create_source_editor'; import { ESGeoGridSource, clustersTitle } from './es_geo_grid_source'; -import { LayerWizard, RenderWizardArguments } from '../../layers/layer_wizard_registry'; +import { LayerWizard, RenderWizardArguments } from '../../layers'; import { GeoJsonVectorLayer } from '../../layers/vector_layer'; import { ESGeoGridSourceDescriptor, @@ -29,7 +29,7 @@ import { STYLE_TYPE, } from '../../../../common/constants'; import { NUMERICAL_COLOR_PALETTES } from '../../styles/color_palettes'; -import { ClustersLayerIcon } from '../../layers/icons/clusters_layer_icon'; +import { ClustersLayerIcon } from '../../layers/wizards/icons/clusters_layer_icon'; export const clustersLayerWizardConfig: LayerWizard = { categories: [LAYER_WIZARD_CATEGORY.ELASTICSEARCH], diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/heatmap_layer_wizard.tsx b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/heatmap_layer_wizard.tsx index 8fc26f3593750..4b80cedb18b19 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/heatmap_layer_wizard.tsx +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/heatmap_layer_wizard.tsx @@ -10,11 +10,11 @@ import React from 'react'; // @ts-ignore import { CreateSourceEditor } from './create_source_editor'; import { ESGeoGridSource, heatmapTitle } from './es_geo_grid_source'; -import { LayerWizard, RenderWizardArguments } from '../../layers/layer_wizard_registry'; +import { LayerWizard, RenderWizardArguments } from '../../layers'; import { HeatmapLayer } from '../../layers/heatmap_layer'; import { ESGeoGridSourceDescriptor } from '../../../../common/descriptor_types'; import { LAYER_WIZARD_CATEGORY, RENDER_AS } from '../../../../common/constants'; -import { HeatmapLayerIcon } from '../../layers/icons/heatmap_layer_icon'; +import { HeatmapLayerIcon } from '../../layers/wizards/icons/heatmap_layer_icon'; export const heatmapLayerWizardConfig: LayerWizard = { categories: [LAYER_WIZARD_CATEGORY.ELASTICSEARCH], diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_line_source/layer_wizard.tsx b/x-pack/plugins/maps/public/classes/sources/es_geo_line_source/layer_wizard.tsx index ba1c3c4eece4b..85932658383de 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_line_source/layer_wizard.tsx +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_line_source/layer_wizard.tsx @@ -9,12 +9,12 @@ import { i18n } from '@kbn/i18n'; import React from 'react'; import { CreateSourceEditor } from './create_source_editor'; import { ESGeoLineSource, geoLineTitle, REQUIRES_GOLD_LICENSE_MSG } from './es_geo_line_source'; -import { LayerWizard, RenderWizardArguments } from '../../layers/layer_wizard_registry'; +import { LayerWizard, RenderWizardArguments } from '../../layers'; import { LAYER_WIZARD_CATEGORY, STYLE_TYPE, VECTOR_STYLES } from '../../../../common/constants'; import { VectorStyle } from '../../styles/vector/vector_style'; import { GeoJsonVectorLayer } from '../../layers/vector_layer'; import { getIsGoldPlus } from '../../../licensed_features'; -import { TracksLayerIcon } from '../../layers/icons/tracks_layer_icon'; +import { TracksLayerIcon } from '../../layers/wizards/icons/tracks_layer_icon'; export const geoLineLayerWizardConfig: LayerWizard = { categories: [LAYER_WIZARD_CATEGORY.ELASTICSEARCH], diff --git a/x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/point_2_point_layer_wizard.tsx b/x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/point_2_point_layer_wizard.tsx index 84dea15daf48f..c35b8677c1093 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/point_2_point_layer_wizard.tsx +++ b/x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/point_2_point_layer_wizard.tsx @@ -22,9 +22,9 @@ import { import { NUMERICAL_COLOR_PALETTES } from '../../styles/color_palettes'; // @ts-ignore import { CreateSourceEditor } from './create_source_editor'; -import { LayerWizard, RenderWizardArguments } from '../../layers/layer_wizard_registry'; +import { LayerWizard, RenderWizardArguments } from '../../layers'; import { ColorDynamicOptions, SizeDynamicOptions } from '../../../../common/descriptor_types'; -import { Point2PointLayerIcon } from '../../layers/icons/point_2_point_layer_icon'; +import { Point2PointLayerIcon } from '../../layers/wizards/icons/point_2_point_layer_icon'; export const point2PointLayerWizardConfig: LayerWizard = { categories: [LAYER_WIZARD_CATEGORY.ELASTICSEARCH], diff --git a/x-pack/plugins/maps/public/classes/sources/es_search_source/es_documents_layer_wizard.tsx b/x-pack/plugins/maps/public/classes/sources/es_search_source/es_documents_layer_wizard.tsx index 601fcee50ab2a..b5aeb28715aef 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_search_source/es_documents_layer_wizard.tsx +++ b/x-pack/plugins/maps/public/classes/sources/es_search_source/es_documents_layer_wizard.tsx @@ -9,11 +9,11 @@ import { i18n } from '@kbn/i18n'; import React from 'react'; // @ts-ignore import { CreateSourceEditor } from './create_source_editor'; -import { LayerWizard, RenderWizardArguments } from '../../layers/layer_wizard_registry'; +import { LayerWizard, RenderWizardArguments } from '../../layers'; import { ESSearchSource, sourceTitle } from './es_search_source'; import { BlendedVectorLayer, GeoJsonVectorLayer, MvtVectorLayer } from '../../layers/vector_layer'; import { LAYER_WIZARD_CATEGORY, SCALING_TYPES } from '../../../../common/constants'; -import { DocumentsLayerIcon } from '../../layers/icons/documents_layer_icon'; +import { DocumentsLayerIcon } from '../../layers/wizards/icons/documents_layer_icon'; import { ESSearchSourceDescriptor, VectorLayerDescriptor, diff --git a/x-pack/plugins/maps/public/classes/sources/es_search_source/top_hits/wizard.tsx b/x-pack/plugins/maps/public/classes/sources/es_search_source/top_hits/wizard.tsx index b4339eb20b1fd..3e5af637dc336 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_search_source/top_hits/wizard.tsx +++ b/x-pack/plugins/maps/public/classes/sources/es_search_source/top_hits/wizard.tsx @@ -8,10 +8,10 @@ import { i18n } from '@kbn/i18n'; import React from 'react'; import { CreateSourceEditor } from './create_source_editor'; -import { LayerWizard, RenderWizardArguments } from '../../../layers/layer_wizard_registry'; +import { LayerWizard, RenderWizardArguments } from '../../../layers'; import { GeoJsonVectorLayer } from '../../../layers/vector_layer'; import { LAYER_WIZARD_CATEGORY } from '../../../../../common/constants'; -import { TopHitsLayerIcon } from '../../../layers/icons/top_hits_layer_icon'; +import { TopHitsLayerIcon } from '../../../layers/wizards/icons/top_hits_layer_icon'; import { ESSearchSourceDescriptor } from '../../../../../common/descriptor_types'; import { ESSearchSource } from '../es_search_source'; diff --git a/x-pack/plugins/maps/public/classes/sources/kibana_tilemap_source/kibana_base_map_layer_wizard.tsx b/x-pack/plugins/maps/public/classes/sources/kibana_tilemap_source/kibana_base_map_layer_wizard.tsx index 26893086ba8f7..70f56f8f4e6d2 100644 --- a/x-pack/plugins/maps/public/classes/sources/kibana_tilemap_source/kibana_base_map_layer_wizard.tsx +++ b/x-pack/plugins/maps/public/classes/sources/kibana_tilemap_source/kibana_base_map_layer_wizard.tsx @@ -7,7 +7,7 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; -import { LayerWizard, RenderWizardArguments } from '../../layers/layer_wizard_registry'; +import { LayerWizard, RenderWizardArguments } from '../../layers'; // @ts-ignore import { CreateSourceEditor } from './create_source_editor'; // @ts-ignore diff --git a/x-pack/plugins/maps/public/classes/sources/mvt_single_layer_vector_source/layer_wizard.tsx b/x-pack/plugins/maps/public/classes/sources/mvt_single_layer_vector_source/layer_wizard.tsx index a3f7ceafd54ef..bf6ff368594cc 100644 --- a/x-pack/plugins/maps/public/classes/sources/mvt_single_layer_vector_source/layer_wizard.tsx +++ b/x-pack/plugins/maps/public/classes/sources/mvt_single_layer_vector_source/layer_wizard.tsx @@ -9,11 +9,11 @@ import { i18n } from '@kbn/i18n'; import React from 'react'; import { MVTSingleLayerVectorSourceEditor } from './mvt_single_layer_vector_source_editor'; import { MVTSingleLayerVectorSource, sourceTitle } from './mvt_single_layer_vector_source'; -import { LayerWizard, RenderWizardArguments } from '../../layers/layer_wizard_registry'; +import { LayerWizard, RenderWizardArguments } from '../../layers'; import { MvtVectorLayer } from '../../layers/vector_layer'; import { LAYER_WIZARD_CATEGORY } from '../../../../common/constants'; import { TiledSingleLayerVectorSourceSettings } from '../../../../common/descriptor_types'; -import { VectorTileLayerIcon } from '../../layers/icons/vector_tile_layer_icon'; +import { VectorTileLayerIcon } from '../../layers/wizards/icons/vector_tile_layer_icon'; export const mvtVectorSourceWizardConfig: LayerWizard = { categories: [LAYER_WIZARD_CATEGORY.REFERENCE], diff --git a/x-pack/plugins/maps/public/classes/sources/wms_source/wms_layer_wizard.tsx b/x-pack/plugins/maps/public/classes/sources/wms_source/wms_layer_wizard.tsx index 33d86f693c8f0..adbb23b921d4b 100644 --- a/x-pack/plugins/maps/public/classes/sources/wms_source/wms_layer_wizard.tsx +++ b/x-pack/plugins/maps/public/classes/sources/wms_source/wms_layer_wizard.tsx @@ -11,10 +11,10 @@ import { i18n } from '@kbn/i18n'; import { WMSCreateSourceEditor } from './wms_create_source_editor'; // @ts-ignore import { sourceTitle, WMSSource } from './wms_source'; -import { LayerWizard, RenderWizardArguments } from '../../layers/layer_wizard_registry'; +import { LayerWizard, RenderWizardArguments } from '../../layers'; import { TileLayer } from '../../layers/tile_layer/tile_layer'; import { LAYER_WIZARD_CATEGORY } from '../../../../common/constants'; -import { WebMapServiceLayerIcon } from '../../layers/icons/web_map_service_layer_icon'; +import { WebMapServiceLayerIcon } from '../../layers/wizards/icons/web_map_service_layer_icon'; export const wmsLayerWizardConfig: LayerWizard = { categories: [LAYER_WIZARD_CATEGORY.REFERENCE], diff --git a/x-pack/plugins/maps/public/classes/sources/xyz_tms_source/layer_wizard.tsx b/x-pack/plugins/maps/public/classes/sources/xyz_tms_source/layer_wizard.tsx index 249a05472d5fc..95a2b104c7a1b 100644 --- a/x-pack/plugins/maps/public/classes/sources/xyz_tms_source/layer_wizard.tsx +++ b/x-pack/plugins/maps/public/classes/sources/xyz_tms_source/layer_wizard.tsx @@ -9,10 +9,10 @@ import { i18n } from '@kbn/i18n'; import React from 'react'; import { XYZTMSEditor, XYZTMSSourceConfig } from './xyz_tms_editor'; import { XYZTMSSource, sourceTitle } from './xyz_tms_source'; -import { LayerWizard, RenderWizardArguments } from '../../layers/layer_wizard_registry'; +import { LayerWizard, RenderWizardArguments } from '../../layers'; import { TileLayer } from '../../layers/tile_layer/tile_layer'; import { LAYER_WIZARD_CATEGORY } from '../../../../common/constants'; -import { WorldMapLayerIcon } from '../../layers/icons/world_map_layer_icon'; +import { WorldMapLayerIcon } from '../../layers/wizards/icons/world_map_layer_icon'; export const tmsLayerWizardConfig: LayerWizard = { categories: [LAYER_WIZARD_CATEGORY.REFERENCE], diff --git a/x-pack/plugins/maps/public/connected_components/add_layer_panel/flyout_body/flyout_body.tsx b/x-pack/plugins/maps/public/connected_components/add_layer_panel/flyout_body/flyout_body.tsx index bcc7bbae8a9cc..4b3ad3f19ef2e 100644 --- a/x-pack/plugins/maps/public/connected_components/add_layer_panel/flyout_body/flyout_body.tsx +++ b/x-pack/plugins/maps/public/connected_components/add_layer_panel/flyout_body/flyout_body.tsx @@ -9,7 +9,7 @@ import React, { Fragment } from 'react'; import { EuiButtonEmpty, EuiSpacer } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { LayerWizardSelect } from './layer_wizard_select'; -import { LayerWizard, RenderWizardArguments } from '../../../classes/layers/layer_wizard_registry'; +import { LayerWizard, RenderWizardArguments } from '../../../classes/layers'; type Props = RenderWizardArguments & { layerWizard: LayerWizard | null; diff --git a/x-pack/plugins/maps/public/connected_components/add_layer_panel/flyout_body/layer_wizard_select.test.tsx b/x-pack/plugins/maps/public/connected_components/add_layer_panel/flyout_body/layer_wizard_select.test.tsx index 68f795dd9a29a..c8bec5a7a1157 100644 --- a/x-pack/plugins/maps/public/connected_components/add_layer_panel/flyout_body/layer_wizard_select.test.tsx +++ b/x-pack/plugins/maps/public/connected_components/add_layer_panel/flyout_body/layer_wizard_select.test.tsx @@ -5,7 +5,7 @@ * 2.0. */ -jest.mock('../../../classes/layers/layer_wizard_registry', () => ({})); +jest.mock('../../../classes/layers', () => ({})); import React from 'react'; import { shallow } from 'enzyme'; @@ -19,7 +19,7 @@ const defaultProps = { describe('LayerWizardSelect', () => { beforeAll(() => { // eslint-disable-next-line @typescript-eslint/no-var-requires - require('../../../classes/layers/layer_wizard_registry').getLayerWizards = async () => { + require('../../../classes/layers').getLayerWizards = async () => { return [ { categories: [LAYER_WIZARD_CATEGORY.ELASTICSEARCH], diff --git a/x-pack/plugins/maps/public/connected_components/add_layer_panel/flyout_body/layer_wizard_select.tsx b/x-pack/plugins/maps/public/connected_components/add_layer_panel/flyout_body/layer_wizard_select.tsx index 1e92dd16d9dac..a4dfb3497078b 100644 --- a/x-pack/plugins/maps/public/connected_components/add_layer_panel/flyout_body/layer_wizard_select.tsx +++ b/x-pack/plugins/maps/public/connected_components/add_layer_panel/flyout_body/layer_wizard_select.tsx @@ -20,11 +20,7 @@ import { } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; -import { - getLayerWizards, - LayerWizard, - LayerWizardWithMeta, -} from '../../../classes/layers/layer_wizard_registry'; +import { getLayerWizards, LayerWizard, LayerWizardWithMeta } from '../../../classes/layers'; import { LAYER_WIZARD_CATEGORY } from '../../../../common/constants'; import './layer_wizard_select.scss'; diff --git a/x-pack/plugins/maps/public/connected_components/add_layer_panel/view.tsx b/x-pack/plugins/maps/public/connected_components/add_layer_panel/view.tsx index 4b3b10889790a..e6f954e75f169 100644 --- a/x-pack/plugins/maps/public/connected_components/add_layer_panel/view.tsx +++ b/x-pack/plugins/maps/public/connected_components/add_layer_panel/view.tsx @@ -19,7 +19,7 @@ import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import { FlyoutBody } from './flyout_body'; import { LayerDescriptor } from '../../../common/descriptor_types'; -import { LayerWizard } from '../../classes/layers/layer_wizard_registry'; +import { LayerWizard } from '../../classes/layers'; export const ADD_LAYER_STEP_ID = 'ADD_LAYER_STEP_ID'; const ADD_LAYER_STEP_LABEL = i18n.translate('xpack.maps.addLayerPanel.addLayer', { diff --git a/x-pack/plugins/maps/public/connected_components/map_container/map_container.tsx b/x-pack/plugins/maps/public/connected_components/map_container/map_container.tsx index 2fad5d4eb64ac..ab08c950891f9 100644 --- a/x-pack/plugins/maps/public/connected_components/map_container/map_container.tsx +++ b/x-pack/plugins/maps/public/connected_components/map_container/map_container.tsx @@ -26,7 +26,7 @@ import { RawValue } from '../../../common/constants'; import { FLYOUT_STATE } from '../../reducers/ui'; import { MapSettings } from '../../reducers/map'; import { MapSettingsPanel } from '../map_settings_panel'; -import { registerLayerWizards } from '../../classes/layers/load_layer_wizards'; +import { registerLayerWizards } from '../../classes/layers/wizards/load_layer_wizards'; import { RenderToolTipContent } from '../../classes/tooltips/tooltip_property'; import { ILayer } from '../../classes/layers/layer'; diff --git a/x-pack/plugins/maps/public/index.ts b/x-pack/plugins/maps/public/index.ts index 3370b963f548e..5778c8d3b654f 100644 --- a/x-pack/plugins/maps/public/index.ts +++ b/x-pack/plugins/maps/public/index.ts @@ -39,5 +39,5 @@ export type { SourceStatus, } from './classes/sources/vector_source/vector_source'; export type { IField } from './classes/fields/field'; -export type { LayerWizard, RenderWizardArguments } from './classes/layers/layer_wizard_registry'; +export type { LayerWizard, RenderWizardArguments } from './classes/layers'; export type { DataRequest } from './classes/util/data_request'; diff --git a/x-pack/plugins/maps/public/lazy_load_bundle/lazy/index.ts b/x-pack/plugins/maps/public/lazy_load_bundle/lazy/index.ts index 114fa86bc1d99..fb5321dfc03f8 100644 --- a/x-pack/plugins/maps/public/lazy_load_bundle/lazy/index.ts +++ b/x-pack/plugins/maps/public/lazy_load_bundle/lazy/index.ts @@ -9,7 +9,7 @@ import '../../_index.scss'; export * from '../../embeddable/map_embeddable'; export * from '../../kibana_services'; export { renderApp } from '../../render_app'; -export * from '../../classes/layers/solution_layers/security'; +export * from '../../classes/layers/wizards/solution_layers/security'; export { createTileMapLayerDescriptor } from '../../classes/layers/create_tile_map_layer_descriptor'; export { createRegionMapLayerDescriptor } from '../../classes/layers/create_region_map_layer_descriptor'; export { createBasemapLayerDescriptor } from '../../classes/layers/create_basemap_layer_descriptor'; diff --git a/x-pack/plugins/maps/public/plugin.ts b/x-pack/plugins/maps/public/plugin.ts index b8538975bdc9c..657828fa772fa 100644 --- a/x-pack/plugins/maps/public/plugin.ts +++ b/x-pack/plugins/maps/public/plugin.ts @@ -52,7 +52,7 @@ import { MapsStartApi, suggestEMSTermJoinConfig, } from './api'; -import { registerLayerWizard } from './classes/layers/layer_wizard_registry'; +import { registerLayerWizard } from './classes/layers'; import { registerSource } from './classes/sources/source_registry'; import type { SharePluginSetup, SharePluginStart } from '../../../../src/plugins/share/public'; import type { MapsEmsPluginSetup } from '../../../../src/plugins/maps_ems/public'; From 13638cfe8245f77ac44959f35662feb8fb1ddd8e Mon Sep 17 00:00:00 2001 From: Kevin Qualters <56408403+kqualters-elastic@users.noreply.github.com> Date: Tue, 16 Nov 2021 16:39:04 -0500 Subject: [PATCH 051/148] Prevent duplicate names from appearing in cell actions (#118648) --- .../lib/cell_actions/default_cell_actions.tsx | 14 +++++++------- .../public/common/lib/cell_actions/helpers.ts | 6 ++++-- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/x-pack/plugins/security_solution/public/common/lib/cell_actions/default_cell_actions.tsx b/x-pack/plugins/security_solution/public/common/lib/cell_actions/default_cell_actions.tsx index 012b84e06ed82..3526724a54b41 100644 --- a/x-pack/plugins/security_solution/public/common/lib/cell_actions/default_cell_actions.tsx +++ b/x-pack/plugins/security_solution/public/common/lib/cell_actions/default_cell_actions.tsx @@ -60,14 +60,15 @@ const cellActionLink = [ header?: ColumnHeaderOptions; timelineId: string; pageSize: number; - }) => - getLink(header?.id, header?.type, header?.linkField) + }) => { + return getLink(header?.id, header?.type, header?.linkField) ? ({ rowIndex, columnId, Component, closePopover }: EuiDataGridColumnCellActionProps) => { const pageRowIndex = getPageRowIndex(rowIndex, pageSize); const ecs = pageRowIndex < ecsData.length ? ecsData[pageRowIndex] : null; - const linkValues = header && getOr([], header.linkField ?? '', ecs); + const link = getLink(columnId, header?.type, header?.linkField); + const linkField = header?.linkField ? header?.linkField : link?.linkField; + const linkValues = header && getOr([], linkField ?? '', ecs); const eventId = header && get('_id' ?? '', ecs); - if (pageRowIndex >= data.length) { // data grid expects each cell action always return an element, it crashes if returns null return <>; @@ -78,9 +79,7 @@ const cellActionLink = [ fieldName: columnId, }); - const link = getLink(columnId, header?.type, header?.linkField); const value = parseValue(head(values)); - return link && eventId && values && !isEmpty(value) ? ( ); } - : EmptyComponent, + : EmptyComponent; + }, ]; export const cellActions: TGridCellAction[] = [ diff --git a/x-pack/plugins/security_solution/public/common/lib/cell_actions/helpers.ts b/x-pack/plugins/security_solution/public/common/lib/cell_actions/helpers.ts index 1c40d8df48bfe..2db645106fc5c 100644 --- a/x-pack/plugins/security_solution/public/common/lib/cell_actions/helpers.ts +++ b/x-pack/plugins/security_solution/public/common/lib/cell_actions/helpers.ts @@ -35,6 +35,7 @@ export const COLUMNS_WITH_LINKS = [ { columnId: SIGNAL_RULE_NAME_FIELD_NAME, label: i18n.VIEW_RULE_DETAILS, + linkField: 'signal.rule.id', }, ...PORT_NAMES.map((p) => ({ columnId: p, @@ -59,7 +60,8 @@ export const COLUMNS_WITH_LINKS = [ ]; export const getLink = (cId?: string, fieldType?: string, linkField?: string) => - cId && COLUMNS_WITH_LINKS.find( - (c) => c.columnId === cId || (c.fieldType && fieldType === c.fieldType && linkField != null) + (c) => + (cId && c.columnId === cId) || + (c.fieldType && fieldType === c.fieldType && (linkField != null || c.linkField !== undefined)) ); From 7f1796e9c0074915443454cde426274d095d91eb Mon Sep 17 00:00:00 2001 From: Spencer Date: Tue, 16 Nov 2021 13:47:53 -0800 Subject: [PATCH 052/148] [babel] fix require statement (#118775) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- packages/kbn-babel-preset/webpack_preset.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/kbn-babel-preset/webpack_preset.js b/packages/kbn-babel-preset/webpack_preset.js index 0c949eae5b55b..f9e4490f8cbf6 100644 --- a/packages/kbn-babel-preset/webpack_preset.js +++ b/packages/kbn-babel-preset/webpack_preset.js @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -const { USES_STYLED_COMPONENTS } = require.resolve('./styled_components_files'); +const { USES_STYLED_COMPONENTS } = require('./styled_components_files'); module.exports = () => { return { From 899a803ca46790cb0d7ec4b63d74fdd97ede48fe Mon Sep 17 00:00:00 2001 From: James Rodewig <40268737+jrodewig@users.noreply.github.com> Date: Tue, 16 Nov 2021 16:59:24 -0500 Subject: [PATCH 053/148] [DOCS] Remove snapshot and restore docs (#114836) With https://github.com/elastic/elasticsearch/pull/79081, we now cover Kibana's **Snapshot and Restore** feature in the Elasticsearch docs. This removes and redirects the related docs from Kibana. It also updates some references to the `.kibana` system indices to include the `kibana` feature state. The `kibana` feature state is now the preferred way to back up and restore system indices and other configuration data for Kibana. Relates to https://github.com/elastic/elasticsearch/issues/79675 --- .../images/create-policy-example.png | Bin 141385 -> 0 bytes .../snapshot-restore/images/create-policy.png | Bin 87896 -> 0 bytes .../snapshot-restore/images/register_repo.png | Bin 94316 -> 0 bytes .../images/repository_list.png | Bin 171094 -> 0 bytes .../images/snapshot-restore.png | Bin 123854 -> 0 bytes .../images/snapshot-retention.png | Bin 128059 -> 0 bytes .../images/snapshot_details.png | Bin 190417 -> 0 bytes .../snapshot-restore/images/snapshot_list.png | Bin 100618 -> 0 bytes .../snapshot-restore/index.asciidoc | 299 ------------------ docs/redirects.asciidoc | 8 + docs/setup/upgrade.asciidoc | 4 +- .../setup/upgrade/upgrade-migrations.asciidoc | 6 +- docs/template.asciidoc | 1 - docs/user/management.asciidoc | 4 +- .../public/doc_links/doc_links_service.ts | 2 +- 15 files changed, 15 insertions(+), 309 deletions(-) delete mode 100644 docs/management/snapshot-restore/images/create-policy-example.png delete mode 100644 docs/management/snapshot-restore/images/create-policy.png delete mode 100644 docs/management/snapshot-restore/images/register_repo.png delete mode 100644 docs/management/snapshot-restore/images/repository_list.png delete mode 100644 docs/management/snapshot-restore/images/snapshot-restore.png delete mode 100644 docs/management/snapshot-restore/images/snapshot-retention.png delete mode 100644 docs/management/snapshot-restore/images/snapshot_details.png delete mode 100644 docs/management/snapshot-restore/images/snapshot_list.png delete mode 100644 docs/management/snapshot-restore/index.asciidoc diff --git a/docs/management/snapshot-restore/images/create-policy-example.png b/docs/management/snapshot-restore/images/create-policy-example.png deleted file mode 100644 index 4ab5e438b306b4bafa1ba1f3fb8acd6e14e6915f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 141385 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%0D%_LXQ3&a^I<>(gIzYrsxdub~)dJd@8Eu0!3x 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 SmXq~_9o!eZw|LJl)PDeR-dc(P diff --git a/docs/management/snapshot-restore/images/create-policy.png b/docs/management/snapshot-restore/images/create-policy.png deleted file mode 100644 index 3ba33e2522bd5b28d7c60ec29bd089f50eaa170f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 87896 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 a62{vs&@s@78(OE(oPbMCef&el&h=RDgIONK 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 HO#J^J_ej9= diff --git a/docs/management/snapshot-restore/images/register_repo.png b/docs/management/snapshot-restore/images/register_repo.png deleted file mode 100644 index c742028ce108cfe1a7022a63555c5eda85fe064f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 94316 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 aIg)@mACoWlYo~5XEg>Q+Tp*<5^M3)$X~xF@ diff --git a/docs/management/snapshot-restore/images/repository_list.png b/docs/management/snapshot-restore/images/repository_list.png deleted file mode 100644 index c4eb4fc1a3d1a84825a8ea00a67616486e987047..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 171094 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 - body={ - <> -

    {ROLES_DISABLED_DESCRIPTION(productName)}

    -

    {ROLES_DISABLED_NOTE}

    - - } - actions={[ - - {ENABLE_ROLES_BUTTON} - , - , - - {ENABLE_ROLES_LINK} - , - ]} - /> -); +export const RolesEmptyPrompt: React.FC = ({ onEnable, docsLink, productName }) => { + const { security } = useValues(KibanaLogic); + const [currentUser, setCurrentUser] = useState(null); + const isSuperUser = currentUser?.roles.includes('superuser'); + const rbacDisabledLabel = !isSuperUser && ( + + {RBAC_BUTTON_DISABLED_LABEL} + + ); + + useEffect(() => { + security.authc + .getCurrentUser() + .then(setCurrentUser) + .catch(() => { + setCurrentUser(null); + }); + }, [security.authc]); + + if (!currentUser) { + return null; + } + + return ( + {ROLES_DISABLED_TITLE}} + body={ + <> +

    {ROLES_DISABLED_DESCRIPTION(productName)}

    +

    {ROLES_DISABLED_NOTE}

    + + } + actions={[ + + {ENABLE_ROLES_BUTTON} + , + rbacDisabledLabel, + , + + {ENABLE_ROLES_LINK} + , + ]} + /> + ); +}; From 0fdb0b9c3549e08777e6b82763e02b89dd85fac0 Mon Sep 17 00:00:00 2001 From: Justin Kambic Date: Thu, 18 Nov 2021 16:04:12 -0500 Subject: [PATCH 129/148] [Uptime] Add `7*` to supported index pattern defaults (#112861) * Add `7.16` to supported index pattern defaults. * Update supported index pattern based on requirements update. * Fix broken unit tests. Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../uptime/common/constants/settings_defaults.ts | 2 +- x-pack/plugins/uptime/public/pages/settings.test.tsx | 4 ++-- .../__snapshots__/get_monitor_charts.test.ts.snap | 2 +- .../__snapshots__/get_monitor_details.test.ts.snap | 4 ++-- .../uptime/server/lib/requests/get_certs.test.ts | 2 +- .../lib/requests/get_monitor_availability.test.ts | 10 +++++----- .../server/lib/requests/get_monitor_status.test.ts | 10 +++++----- .../server/lib/requests/get_network_events.test.ts | 2 +- .../uptime/server/lib/requests/get_pings.test.ts | 10 +++++----- .../apis/uptime/rest/fixtures/doc_count.json | 2 +- 10 files changed, 24 insertions(+), 24 deletions(-) diff --git a/x-pack/plugins/uptime/common/constants/settings_defaults.ts b/x-pack/plugins/uptime/common/constants/settings_defaults.ts index b57bc8a85d7cd..8fbc4c19df6b0 100644 --- a/x-pack/plugins/uptime/common/constants/settings_defaults.ts +++ b/x-pack/plugins/uptime/common/constants/settings_defaults.ts @@ -8,7 +8,7 @@ import { DynamicSettings } from '../runtime_types'; export const DYNAMIC_SETTINGS_DEFAULTS: DynamicSettings = { - heartbeatIndices: 'heartbeat-8*,synthetics-*', + heartbeatIndices: 'heartbeat-8*,heartbeat-7*,synthetics-*', certAgeThreshold: 730, certExpirationThreshold: 30, defaultConnectors: [], diff --git a/x-pack/plugins/uptime/public/pages/settings.test.tsx b/x-pack/plugins/uptime/public/pages/settings.test.tsx index 84bd4270951cf..f02e35506135b 100644 --- a/x-pack/plugins/uptime/public/pages/settings.test.tsx +++ b/x-pack/plugins/uptime/public/pages/settings.test.tsx @@ -29,7 +29,7 @@ describe('settings', () => { it('handles no spaces error', async () => { const { getByText, getByTestId } = render(); - expect(getByText('heartbeat-8*,synthetics-*')); + expect(getByText('heartbeat-8*,heartbeat-7*,synthetics-*')); fireEvent.input(getByTestId('heartbeat-indices-input-loaded'), { target: { value: 'heartbeat-8*, synthetics-*' }, @@ -41,7 +41,7 @@ describe('settings', () => { it('it show select a connector flyout', async () => { const { getByText, getByTestId } = render(); - expect(getByText('heartbeat-8*,synthetics-*')); + expect(getByText('heartbeat-8*,heartbeat-7*,synthetics-*')); fireEvent.click(getByTestId('createConnectorButton')); await waitFor(() => expect(getByText('Select a connector'))); diff --git a/x-pack/plugins/uptime/server/lib/requests/__snapshots__/get_monitor_charts.test.ts.snap b/x-pack/plugins/uptime/server/lib/requests/__snapshots__/get_monitor_charts.test.ts.snap index 2d1bdf791e39a..14e4261c28283 100644 --- a/x-pack/plugins/uptime/server/lib/requests/__snapshots__/get_monitor_charts.test.ts.snap +++ b/x-pack/plugins/uptime/server/lib/requests/__snapshots__/get_monitor_charts.test.ts.snap @@ -55,7 +55,7 @@ Array [ }, "size": 0, }, - "index": "heartbeat-8*,synthetics-*", + "index": "heartbeat-8*,heartbeat-7*,synthetics-*", }, ] `; diff --git a/x-pack/plugins/uptime/server/lib/requests/__snapshots__/get_monitor_details.test.ts.snap b/x-pack/plugins/uptime/server/lib/requests/__snapshots__/get_monitor_details.test.ts.snap index 56b7ed25a74ad..9464f9960b8d2 100644 --- a/x-pack/plugins/uptime/server/lib/requests/__snapshots__/get_monitor_details.test.ts.snap +++ b/x-pack/plugins/uptime/server/lib/requests/__snapshots__/get_monitor_details.test.ts.snap @@ -55,7 +55,7 @@ Array [ }, "size": 0, }, - "index": "heartbeat-8*,synthetics-*", + "index": "heartbeat-8*,heartbeat-7*,synthetics-*", }, ] `; @@ -103,7 +103,7 @@ Array [ }, ], }, - "index": "heartbeat-8*,synthetics-*", + "index": "heartbeat-8*,heartbeat-7*,synthetics-*", }, ] `; diff --git a/x-pack/plugins/uptime/server/lib/requests/get_certs.test.ts b/x-pack/plugins/uptime/server/lib/requests/get_certs.test.ts index a6b37215c141a..dbbbf5d82c970 100644 --- a/x-pack/plugins/uptime/server/lib/requests/get_certs.test.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_certs.test.ts @@ -212,7 +212,7 @@ describe('getCerts', () => { }, ], }, - "index": "heartbeat-8*,synthetics-*", + "index": "heartbeat-8*,heartbeat-7*,synthetics-*", }, ], ] diff --git a/x-pack/plugins/uptime/server/lib/requests/get_monitor_availability.test.ts b/x-pack/plugins/uptime/server/lib/requests/get_monitor_availability.test.ts index 0f1bd606307e5..ee8386dfce5d7 100644 --- a/x-pack/plugins/uptime/server/lib/requests/get_monitor_availability.test.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_monitor_availability.test.ts @@ -241,7 +241,7 @@ describe('monitor availability', () => { }, "size": 0, }, - "index": "heartbeat-8*,synthetics-*", + "index": "heartbeat-8*,heartbeat-7*,synthetics-*", } `); }); @@ -387,7 +387,7 @@ describe('monitor availability', () => { }, "size": 0, }, - "index": "heartbeat-8*,synthetics-*", + "index": "heartbeat-8*,heartbeat-7*,synthetics-*", } `); @@ -701,7 +701,7 @@ describe('monitor availability', () => { }, "size": 0, }, - "index": "heartbeat-8*,synthetics-*", + "index": "heartbeat-8*,heartbeat-7*,synthetics-*", } `); @@ -799,7 +799,7 @@ describe('monitor availability', () => { }, "size": 0, }, - "index": "heartbeat-8*,synthetics-*", + "index": "heartbeat-8*,heartbeat-7*,synthetics-*", }, ] `); @@ -929,7 +929,7 @@ describe('monitor availability', () => { }, "size": 0, }, - "index": "heartbeat-8*,synthetics-*", + "index": "heartbeat-8*,heartbeat-7*,synthetics-*", } `); }); diff --git a/x-pack/plugins/uptime/server/lib/requests/get_monitor_status.test.ts b/x-pack/plugins/uptime/server/lib/requests/get_monitor_status.test.ts index 08b675576a5d2..4a790ad2a1e99 100644 --- a/x-pack/plugins/uptime/server/lib/requests/get_monitor_status.test.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_monitor_status.test.ts @@ -197,7 +197,7 @@ describe('getMonitorStatus', () => { }, "size": 0, }, - "index": "heartbeat-8*,synthetics-*", + "index": "heartbeat-8*,heartbeat-7*,synthetics-*", } `); }); @@ -311,7 +311,7 @@ describe('getMonitorStatus', () => { }, "size": 0, }, - "index": "heartbeat-8*,synthetics-*", + "index": "heartbeat-8*,heartbeat-7*,synthetics-*", } `); }); @@ -510,7 +510,7 @@ describe('getMonitorStatus', () => { }, "size": 0, }, - "index": "heartbeat-8*,synthetics-*", + "index": "heartbeat-8*,heartbeat-7*,synthetics-*", } `); }); @@ -629,7 +629,7 @@ describe('getMonitorStatus', () => { }, "size": 0, }, - "index": "heartbeat-8*,synthetics-*", + "index": "heartbeat-8*,heartbeat-7*,synthetics-*", } `); }); @@ -754,7 +754,7 @@ describe('getMonitorStatus', () => { }, "size": 0, }, - "index": "heartbeat-8*,synthetics-*", + "index": "heartbeat-8*,heartbeat-7*,synthetics-*", } `); expect(result.length).toBe(3); diff --git a/x-pack/plugins/uptime/server/lib/requests/get_network_events.test.ts b/x-pack/plugins/uptime/server/lib/requests/get_network_events.test.ts index e0cd17327a9b6..68fd53729f58d 100644 --- a/x-pack/plugins/uptime/server/lib/requests/get_network_events.test.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_network_events.test.ts @@ -215,7 +215,7 @@ describe('getNetworkEvents', () => { "size": 1000, "track_total_hits": true, }, - "index": "heartbeat-8*,synthetics-*", + "index": "heartbeat-8*,heartbeat-7*,synthetics-*", }, ], ] diff --git a/x-pack/plugins/uptime/server/lib/requests/get_pings.test.ts b/x-pack/plugins/uptime/server/lib/requests/get_pings.test.ts index 96b95fafa921e..7b9a97a4f5cb9 100644 --- a/x-pack/plugins/uptime/server/lib/requests/get_pings.test.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_pings.test.ts @@ -175,7 +175,7 @@ describe('getAll', () => { }, ], }, - "index": "heartbeat-8*,synthetics-*", + "index": "heartbeat-8*,heartbeat-7*,synthetics-*", }, ] `); @@ -244,7 +244,7 @@ describe('getAll', () => { }, ], }, - "index": "heartbeat-8*,synthetics-*", + "index": "heartbeat-8*,heartbeat-7*,synthetics-*", }, ] `); @@ -313,7 +313,7 @@ describe('getAll', () => { }, ], }, - "index": "heartbeat-8*,synthetics-*", + "index": "heartbeat-8*,heartbeat-7*,synthetics-*", }, ] `); @@ -387,7 +387,7 @@ describe('getAll', () => { }, ], }, - "index": "heartbeat-8*,synthetics-*", + "index": "heartbeat-8*,heartbeat-7*,synthetics-*", }, ] `); @@ -506,7 +506,7 @@ describe('getAll', () => { }, ], }, - "index": "heartbeat-8*,synthetics-*", + "index": "heartbeat-8*,heartbeat-7*,synthetics-*", }, ] `); diff --git a/x-pack/test/api_integration/apis/uptime/rest/fixtures/doc_count.json b/x-pack/test/api_integration/apis/uptime/rest/fixtures/doc_count.json index 5151f0adb0011..5edaafd30ad21 100644 --- a/x-pack/test/api_integration/apis/uptime/rest/fixtures/doc_count.json +++ b/x-pack/test/api_integration/apis/uptime/rest/fixtures/doc_count.json @@ -1,5 +1,5 @@ { "indexExists": true, "docCount": 1, - "indices": "heartbeat-8*,synthetics-*" + "indices": "heartbeat-8*,heartbeat-7*,synthetics-*" } From 5aecd60484e13109e4753b19f123143b84e88982 Mon Sep 17 00:00:00 2001 From: Kristof C Date: Thu, 18 Nov 2021 15:34:08 -0600 Subject: [PATCH 130/148] [Cases] [104391] Prevent onSave error when field has not changed (#118825) * [Cases] [104391] Update onSave call to confirm a change before attempting to save. * Update tests * Fixes from PR Co-authored-by: Kristof-Pierre Cummings --- .../user_action_tree/index.test.tsx | 36 +++++++++++-------- .../user_action_markdown.test.tsx | 27 ++++++++++++-- .../user_action_tree/user_action_markdown.tsx | 5 +-- 3 files changed, 49 insertions(+), 19 deletions(-) diff --git a/x-pack/plugins/cases/public/components/user_action_tree/index.test.tsx b/x-pack/plugins/cases/public/components/user_action_tree/index.test.tsx index 5241b0e66fb38..fc59ec3e614e3 100644 --- a/x-pack/plugins/cases/public/components/user_action_tree/index.test.tsx +++ b/x-pack/plugins/cases/public/components/user_action_tree/index.test.tsx @@ -11,7 +11,6 @@ import { waitFor } from '@testing-library/react'; // eslint-disable-next-line @kbn/eslint/module_migration import routeData from 'react-router'; -import { getFormMock, useFormMock, useFormDataMock } from '../__mock__/form'; import { useUpdateComment } from '../../containers/use_update_comment'; import { basicCase, @@ -71,9 +70,6 @@ describe(`UserActionTree`, () => { isLoadingIds: [], patchComment, })); - const formHookMock = getFormMock(sampleData); - useFormMock.mockImplementation(() => ({ form: formHookMock })); - useFormDataMock.mockImplementation(() => [{ content: sampleData.content, comment: '' }]); jest .spyOn(routeData, 'useParams') @@ -259,6 +255,13 @@ describe(`UserActionTree`, () => { .first() .simulate('click'); + wrapper + .find(`.euiMarkdownEditorTextArea`) + .first() + .simulate('change', { + target: { value: sampleData.content }, + }); + wrapper .find( `[data-test-subj="comment-create-action-${props.data.comments[0].id}"] [data-test-subj="user-action-save-markdown"]` @@ -304,6 +307,13 @@ describe(`UserActionTree`, () => { .first() .simulate('click'); + wrapper + .find(`.euiMarkdownEditorTextArea`) + .first() + .simulate('change', { + target: { value: sampleData.content }, + }); + wrapper .find(`[data-test-subj="description-action"] [data-test-subj="user-action-save-markdown"]`) .first() @@ -322,22 +332,17 @@ describe(`UserActionTree`, () => { }); }); - it('quotes', async () => { - const commentData = { - comment: '', - }; - const setFieldValue = jest.fn(); - - const formHookMock = getFormMock(commentData); - useFormMock.mockImplementation(() => ({ form: { ...formHookMock, setFieldValue } })); + it('shows quoted text in last MarkdownEditorTextArea', async () => { + const quoteableText = `> ${defaultProps.data.description} \n\n`; - const props = defaultProps; const wrapper = mount( - + ); + expect(wrapper.find(`.euiMarkdownEditorTextArea`).text()).not.toContain(quoteableText); + wrapper .find(`[data-test-subj="description-action"] [data-test-subj="property-actions-ellipses"]`) .first() @@ -347,8 +352,9 @@ describe(`UserActionTree`, () => { .find(`[data-test-subj="description-action"] [data-test-subj="property-actions-quote"]`) .first() .simulate('click'); + await waitFor(() => { - expect(setFieldValue).toBeCalledWith('comment', `> ${props.data.description} \n\n`); + expect(wrapper.find(`.euiMarkdownEditorTextArea`).text()).toContain(quoteableText); }); }); diff --git a/x-pack/plugins/cases/public/components/user_action_tree/user_action_markdown.test.tsx b/x-pack/plugins/cases/public/components/user_action_tree/user_action_markdown.test.tsx index 43c51e9e394dd..0695f9d5a2c44 100644 --- a/x-pack/plugins/cases/public/components/user_action_tree/user_action_markdown.test.tsx +++ b/x-pack/plugins/cases/public/components/user_action_tree/user_action_markdown.test.tsx @@ -13,6 +13,7 @@ import { waitFor } from '@testing-library/react'; const onChangeEditable = jest.fn(); const onSaveContent = jest.fn(); +const newValue = 'Hello from Tehas'; const hyperlink = `[hyperlink](http://elastic.co)`; const defaultProps = { content: `A link to a timeline ${hyperlink}`, @@ -37,18 +38,40 @@ describe('UserActionMarkdown ', () => { expect(wrapper.find(`[data-test-subj="markdown-link"]`).first().text()).toContain('hyperlink'); }); - it('Save button click calls onSaveContent and onChangeEditable', async () => { + it('Save button click calls onSaveContent and onChangeEditable when text area value changed', async () => { const wrapper = mount( ); + + wrapper + .find(`.euiMarkdownEditorTextArea`) + .first() + .simulate('change', { + target: { value: newValue }, + }); + + wrapper.find(`[data-test-subj="user-action-save-markdown"]`).first().simulate('click'); + + await waitFor(() => { + expect(onSaveContent).toHaveBeenCalledWith(newValue); + expect(onChangeEditable).toHaveBeenCalledWith(defaultProps.id); + }); + }); + it('Does not call onSaveContent if no change from current text', async () => { + const wrapper = mount( + + + + ); + wrapper.find(`[data-test-subj="user-action-save-markdown"]`).first().simulate('click'); await waitFor(() => { - expect(onSaveContent).toHaveBeenCalledWith(defaultProps.content); expect(onChangeEditable).toHaveBeenCalledWith(defaultProps.id); }); + expect(onSaveContent).not.toHaveBeenCalled(); }); it('Cancel button click calls only onChangeEditable', async () => { const wrapper = mount( diff --git a/x-pack/plugins/cases/public/components/user_action_tree/user_action_markdown.tsx b/x-pack/plugins/cases/public/components/user_action_tree/user_action_markdown.tsx index 7b94fc0290027..692fbbb318b22 100644 --- a/x-pack/plugins/cases/public/components/user_action_tree/user_action_markdown.tsx +++ b/x-pack/plugins/cases/public/components/user_action_tree/user_action_markdown.tsx @@ -49,11 +49,12 @@ export const UserActionMarkdown = forwardRef { const { isValid, data } = await submit(); - if (isValid) { + + if (isValid && data.content !== content) { onSaveContent(data.content); } onChangeEditable(id); - }, [id, onChangeEditable, onSaveContent, submit]); + }, [content, id, onChangeEditable, onSaveContent, submit]); const setComment = useCallback( (newComment) => { From 6aba4fbe024f975ea07e6df705c2e1032378bf51 Mon Sep 17 00:00:00 2001 From: Tiago Costa Date: Thu, 18 Nov 2021 22:06:18 +0000 Subject: [PATCH 131/148] chore(NA): splits types from code on @elastic/apm-synthtrace (#118786) * chore(NA): auto creation of the package.json for the new types pkg rule * chore(NA): first alpha api extractor working version * chore(NA): support kbn-analytics * chore(NA): correctly read tsconfig files and deps from ts_config rule * chore(NA): layed out pkg_npm_types tree artifact custom rule * chore(NA): missing todos * chore(NA): node modules link mapping * chore(NA): fully working pkg_npm_types rule * chore(NA): fix changes on new packages using elastic datemath pkgs * docs(NA): remove todo * docs(NA): last todo text correction * chore(NA): removed commented lines * fix(NA): include missing package version * chore(NA): include license keys * chore(NA): change mock types package into private * chore(NA): split types_pkg from code_pkg on @elastic/apm-synthtrace * chore(NA): disable validator on ts_project rule * chore(NA): move into ts_project wrapper * chore(NA): complete types exports * chore(NA): export types as type only * chore(NA): fix type exports * chore(NA): only include exception type Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- package.json | 1 + packages/BUILD.bazel | 1 + packages/elastic-apm-synthtrace/BUILD.bazel | 34 ++++++++++++++------ packages/elastic-apm-synthtrace/package.json | 1 - packages/elastic-apm-synthtrace/src/index.ts | 1 + yarn.lock | 4 +++ 6 files changed, 32 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index c15bb092f17d8..53d9e1ac15dba 100644 --- a/package.json +++ b/package.json @@ -511,6 +511,7 @@ "@types/deep-freeze-strict": "^1.1.0", "@types/delete-empty": "^2.0.0", "@types/ejs": "^3.0.6", + "@types/elastic__apm-synthtrace": "link:bazel-bin/packages/elastic-apm-synthtrace/npm_module_types", "@types/elastic__datemath": "link:bazel-bin/packages/elastic-datemath/npm_module_types", "@types/elasticsearch": "^5.0.33", "@types/enzyme": "^3.10.8", diff --git a/packages/BUILD.bazel b/packages/BUILD.bazel index b96fea80f027b..74c28790ae06e 100644 --- a/packages/BUILD.bazel +++ b/packages/BUILD.bazel @@ -74,6 +74,7 @@ filegroup( filegroup( name = "build_pkg_types", srcs = [ + "//packages/elastic-apm-synthtrace:build_types", "//packages/elastic-datemath:build_types", ], ) diff --git a/packages/elastic-apm-synthtrace/BUILD.bazel b/packages/elastic-apm-synthtrace/BUILD.bazel index 8ae1632ffee4c..7fb188de435b6 100644 --- a/packages/elastic-apm-synthtrace/BUILD.bazel +++ b/packages/elastic-apm-synthtrace/BUILD.bazel @@ -1,9 +1,10 @@ -load("@npm//@bazel/typescript:index.bzl", "ts_config", "ts_project") -load("@build_bazel_rules_nodejs//:index.bzl", "js_library", "pkg_npm") -load("//src/dev/bazel:index.bzl", "jsts_transpiler") +load("@npm//@bazel/typescript:index.bzl", "ts_config") +load("@build_bazel_rules_nodejs//:index.bzl", "js_library") +load("//src/dev/bazel:index.bzl", "jsts_transpiler", "pkg_npm", "pkg_npm_types", "ts_project") PKG_BASE_NAME = "elastic-apm-synthtrace" PKG_REQUIRE_NAME = "@elastic/apm-synthtrace" +TYPES_PKG_REQUIRE_NAME = "@types/elastic__apm-synthtrace" SOURCE_FILES = glob( [ @@ -31,21 +32,18 @@ RUNTIME_DEPS = [ "@npm//moment", "@npm//object-hash", "@npm//p-limit", - "@npm//utility-types", - "@npm//uuid", "@npm//yargs", ] TYPES_DEPS = [ "//packages/elastic-datemath:npm_module_types", "@npm//@elastic/elasticsearch", - "@npm//moment", - "@npm//p-limit", "@npm//@types/jest", "@npm//@types/lodash", "@npm//@types/node", - "@npm//@types/uuid", "@npm//@types/object-hash", + "@npm//moment", + "@npm//p-limit", ] jsts_transpiler( @@ -75,12 +73,13 @@ ts_project( root_dir = "src", source_map = True, tsconfig = ":tsconfig", + validate = False, ) js_library( name = PKG_BASE_NAME, srcs = NPM_MODULE_EXTRA_FILES, - deps = RUNTIME_DEPS + [":target_node", ":tsc_types"], + deps = RUNTIME_DEPS + [":target_node"], package_name = PKG_REQUIRE_NAME, visibility = ["//visibility:public"], ) @@ -99,3 +98,20 @@ filegroup( ], visibility = ["//visibility:public"], ) + +pkg_npm_types( + name = "npm_module_types", + srcs = SRCS, + deps = [":tsc_types"], + package_name = TYPES_PKG_REQUIRE_NAME, + tsconfig = ":tsconfig", + visibility = ["//visibility:public"], +) + +filegroup( + name = "build_types", + srcs = [ + ":npm_module_types", + ], + visibility = ["//visibility:public"], +) diff --git a/packages/elastic-apm-synthtrace/package.json b/packages/elastic-apm-synthtrace/package.json index 43699e4795586..d2f2016a891b3 100644 --- a/packages/elastic-apm-synthtrace/package.json +++ b/packages/elastic-apm-synthtrace/package.json @@ -4,6 +4,5 @@ "description": "Elastic APM trace data generator", "license": "SSPL-1.0 OR Elastic License 2.0", "main": "./target_node/index.js", - "types": "./target_types/index.d.ts", "private": true } diff --git a/packages/elastic-apm-synthtrace/src/index.ts b/packages/elastic-apm-synthtrace/src/index.ts index 70105438ff5ae..931215c75fde4 100644 --- a/packages/elastic-apm-synthtrace/src/index.ts +++ b/packages/elastic-apm-synthtrace/src/index.ts @@ -6,6 +6,7 @@ * Side Public License, v 1. */ +export type { Exception } from './lib/entity'; export { service } from './lib/service'; export { browser } from './lib/browser'; export { timerange } from './lib/timerange'; diff --git a/yarn.lock b/yarn.lock index c6279d6577e14..2f3d3865b54ee 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5386,6 +5386,10 @@ resolved "https://registry.yarnpkg.com/@types/ejs/-/ejs-3.0.6.tgz#aca442289df623bfa8e47c23961f0357847b83fe" integrity sha512-fj1hi+ZSW0xPLrJJD+YNwIh9GZbyaIepG26E/gXvp8nCa2pYokxUYO1sK9qjGxp2g8ryZYuon7wmjpwE2cyASQ== +"@types/elastic__apm-synthtrace@link:bazel-bin/packages/elastic-apm-synthtrace/npm_module_types": + version "0.0.0" + uid "" + "@types/elastic__datemath@link:bazel-bin/packages/elastic-datemath/npm_module_types": version "0.0.0" uid "" From fd81bf58fc950ee37550f02a1d875e24e996a43c Mon Sep 17 00:00:00 2001 From: liza-mae Date: Thu, 18 Nov 2021 15:54:18 -0700 Subject: [PATCH 132/148] Fix upgrade tests for maps and dashboards (#119046) --- x-pack/test/upgrade/apps/dashboard/dashboard_smoke_tests.ts | 5 ----- x-pack/test/upgrade/apps/maps/maps_smoke_tests.ts | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/x-pack/test/upgrade/apps/dashboard/dashboard_smoke_tests.ts b/x-pack/test/upgrade/apps/dashboard/dashboard_smoke_tests.ts index 2c79191f6269d..c983361071170 100644 --- a/x-pack/test/upgrade/apps/dashboard/dashboard_smoke_tests.ts +++ b/x-pack/test/upgrade/apps/dashboard/dashboard_smoke_tests.ts @@ -12,7 +12,6 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ getPageObjects, getService }: FtrProviderContext) { const find = getService('find'); const log = getService('log'); - const pieChart = getService('pieChart'); const renderable = getService('renderable'); const dashboardExpect = getService('dashboardExpect'); const PageObjects = getPageObjects(['common', 'header', 'home', 'dashboard', 'timePicker']); @@ -63,10 +62,6 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await PageObjects.home.launchSampleDashboard('flights'); await PageObjects.header.waitUntilLoadingHasFinished(); await renderable.waitForRender(); - log.debug('Checking pie charts rendered'); - await pieChart.expectPieSliceCount(4); - log.debug('Checking area, bar and heatmap charts rendered'); - await dashboardExpect.seriesElementCount(15); log.debug('Checking saved searches rendered'); await dashboardExpect.savedSearchRowCount(49); log.debug('Checking input controls rendered'); diff --git a/x-pack/test/upgrade/apps/maps/maps_smoke_tests.ts b/x-pack/test/upgrade/apps/maps/maps_smoke_tests.ts index fb8d8c6c59a9d..53acb8b016313 100644 --- a/x-pack/test/upgrade/apps/maps/maps_smoke_tests.ts +++ b/x-pack/test/upgrade/apps/maps/maps_smoke_tests.ts @@ -168,7 +168,7 @@ export default function ({ await PageObjects.header.waitUntilLoadingHasFinished(); await PageObjects.maps.waitForLayersToLoad(); await PageObjects.maps.toggleLayerVisibility('Road map - desaturated'); - await PageObjects.maps.toggleLayerVisibility('Total Requests by Destination'); + await PageObjects.maps.toggleLayerVisibility('Total Requests by Country'); await PageObjects.timePicker.setCommonlyUsedTime('sample_data range'); await PageObjects.maps.enterFullScreen(); await PageObjects.maps.closeLegend(); From 8c8c62e4d3e4db9ccac15b6957a033bea3535623 Mon Sep 17 00:00:00 2001 From: Marshall Main <55718608+marshallmain@users.noreply.github.com> Date: Thu, 18 Nov 2021 15:14:21 -0800 Subject: [PATCH 133/148] [Security Solution] Dedupe alerts by querying _id before creation (#119045) * Dedupe alerts by querying _id before creation * Update alert chunk size * Use aggregations to find existing alert _ids * Remove tightly coupled tests * Add api integration test for alert deduplication * Remove unused import * Cleaner util implementation * Skip flaky test Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../create_persistence_rule_type_wrapper.ts | 85 +++++++++++-- .../server/utils/persistence_types.ts | 14 ++- .../factories/bulk_create_factory.ts | 76 ++--------- .../create_indicator_match_alert_type.test.ts | 118 ------------------ .../query/create_query_alert_type.test.ts | 47 ------- .../tests/generating_signals.ts | 67 ++++++++++ .../detection_engine_api_integration/utils.ts | 14 ++- 7 files changed, 172 insertions(+), 249 deletions(-) diff --git a/x-pack/plugins/rule_registry/server/utils/create_persistence_rule_type_wrapper.ts b/x-pack/plugins/rule_registry/server/utils/create_persistence_rule_type_wrapper.ts index e575b49d17766..afdcf856a872f 100644 --- a/x-pack/plugins/rule_registry/server/utils/create_persistence_rule_type_wrapper.ts +++ b/x-pack/plugins/rule_registry/server/utils/create_persistence_rule_type_wrapper.ts @@ -5,7 +5,9 @@ * 2.0. */ -import { VERSION } from '@kbn/rule-data-utils'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { chunk } from 'lodash'; +import { ALERT_UUID, VERSION } from '@kbn/rule-data-utils'; import { getCommonAlertFields } from './get_common_alert_fields'; import { CreatePersistenceRuleTypeWrapper } from './persistence_types'; @@ -26,22 +28,87 @@ export const createPersistenceRuleTypeWrapper: CreatePersistenceRuleTypeWrapper if (ruleDataClient.isWriteEnabled() && numAlerts) { const commonRuleFields = getCommonAlertFields(options); + const CHUNK_SIZE = 10000; + const alertChunks = chunk(alerts, CHUNK_SIZE); + const filteredAlerts: typeof alerts = []; + + for (const alertChunk of alertChunks) { + const request: estypes.SearchRequest = { + body: { + query: { + ids: { + values: alertChunk.map((alert) => alert._id), + }, + }, + aggs: { + uuids: { + terms: { + field: ALERT_UUID, + size: CHUNK_SIZE, + }, + }, + }, + size: 0, + }, + }; + const response = await ruleDataClient + .getReader({ namespace: options.spaceId }) + .search(request); + const uuidsMap: Record = {}; + const aggs = response.aggregations as + | Record }> + | undefined; + if (aggs != null) { + aggs.uuids.buckets.forEach((bucket) => (uuidsMap[bucket.key] = true)); + const newAlerts = alertChunk.filter((alert) => !uuidsMap[alert._id]); + filteredAlerts.push(...newAlerts); + } else { + filteredAlerts.push(...alertChunk); + } + } + + if (filteredAlerts.length === 0) { + return { createdAlerts: [] }; + } + + const augmentedAlerts = filteredAlerts.map((alert) => { + return { + ...alert, + _source: { + [VERSION]: ruleDataClient.kibanaVersion, + ...commonRuleFields, + ...alert._source, + }, + }; + }); + const response = await ruleDataClient .getWriter({ namespace: options.spaceId }) .bulk({ - body: alerts.flatMap((alert) => [ - { index: { _id: alert.id } }, - { - [VERSION]: ruleDataClient.kibanaVersion, - ...commonRuleFields, - ...alert.fields, - }, + body: augmentedAlerts.flatMap((alert) => [ + { create: { _id: alert._id } }, + alert._source, ]), refresh, }); - return response; + + if (response == null) { + return { createdAlerts: [] }; + } + + return { + createdAlerts: augmentedAlerts.map((alert, idx) => { + const responseItem = response.body.items[idx].create; + return { + _id: responseItem?._id ?? '', + _index: responseItem?._index ?? '', + ...alert._source, + }; + }), + }; } else { logger.debug('Writing is disabled.'); + return { createdAlerts: [] }; } }, }, diff --git a/x-pack/plugins/rule_registry/server/utils/persistence_types.ts b/x-pack/plugins/rule_registry/server/utils/persistence_types.ts index 326a8bef49abd..5541bc6a6d00e 100644 --- a/x-pack/plugins/rule_registry/server/utils/persistence_types.ts +++ b/x-pack/plugins/rule_registry/server/utils/persistence_types.ts @@ -5,8 +5,6 @@ * 2.0. */ -import type { TransportResult } from '@elastic/elasticsearch'; -import { BulkResponse } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { Logger } from '@kbn/logging'; import { AlertExecutorOptions, @@ -19,13 +17,17 @@ import { import { WithoutReservedActionGroups } from '../../../alerting/common'; import { IRuleDataClient } from '../rule_data_client'; -export type PersistenceAlertService = ( +export type PersistenceAlertService = ( alerts: Array<{ - id: string; - fields: Record; + _id: string; + _source: T; }>, refresh: boolean | 'wait_for' -) => Promise | undefined>; +) => Promise>; + +export interface PersistenceAlertServiceResult { + createdAlerts: Array; +} export interface PersistenceServices { alertWithPersistence: PersistenceAlertService; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/bulk_create_factory.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/bulk_create_factory.ts index 0ad88c61bab36..07b93f04e965f 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/bulk_create_factory.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/bulk_create_factory.ts @@ -6,12 +6,11 @@ */ import { performance } from 'perf_hooks'; -import { countBy, isEmpty } from 'lodash'; import { Logger } from 'kibana/server'; import { BaseHit } from '../../../../../common/detection_engine/types'; import { BuildRuleMessage } from '../../signals/rule_messages'; -import { errorAggregator, makeFloatString } from '../../signals/utils'; +import { makeFloatString } from '../../signals/utils'; import { RefreshTypes } from '../../types'; import { PersistenceAlertService } from '../../../../../../rule_registry/server'; @@ -45,11 +44,11 @@ export const bulkCreateFactory = const start = performance.now(); - const response = await alertWithPersistence( + const { createdAlerts } = await alertWithPersistence( wrappedDocs.map((doc) => ({ - id: doc._id, + _id: doc._id, // `fields` should have already been merged into `doc._source` - fields: doc._source, + _source: doc._source, })), refreshForBulkCreate ); @@ -62,64 +61,11 @@ export const bulkCreateFactory = ) ); - if (response == null) { - return { - errors: [ - 'alertWithPersistence returned undefined response. Alerts as Data write flag may be disabled.', - ], - success: false, - bulkCreateDuration: makeFloatString(end - start), - createdItemsCount: 0, - createdItems: [], - }; - } - - logger.debug( - buildRuleMessage(`took property says bulk took: ${response.body.took} milliseconds`) - ); - - const createdItems = wrappedDocs - .map((doc, index) => { - const responseIndex = response.body.items[index].index; - return { - _id: responseIndex?._id ?? '', - _index: responseIndex?._index ?? '', - ...doc._source, - }; - }) - .filter((_, index) => response.body.items[index].index?.status === 201); - const createdItemsCount = createdItems.length; - - const duplicateSignalsCount = countBy(response.body.items, 'create.status')['409']; - const errorCountByMessage = errorAggregator(response.body, [409]); - - logger.debug(buildRuleMessage(`bulk created ${createdItemsCount} signals`)); - - if (duplicateSignalsCount > 0) { - logger.debug(buildRuleMessage(`ignored ${duplicateSignalsCount} duplicate signals`)); - } - - if (!isEmpty(errorCountByMessage)) { - logger.error( - buildRuleMessage( - `[-] bulkResponse had errors with responses of: ${JSON.stringify(errorCountByMessage)}` - ) - ); - - return { - errors: Object.keys(errorCountByMessage), - success: false, - bulkCreateDuration: makeFloatString(end - start), - createdItemsCount: createdItems.length, - createdItems, - }; - } else { - return { - errors: [], - success: true, - bulkCreateDuration: makeFloatString(end - start), - createdItemsCount: createdItems.length, - createdItems, - }; - } + return { + errors: [], + success: true, + bulkCreateDuration: makeFloatString(end - start), + createdItemsCount: createdAlerts.length, + createdItems: createdAlerts, + }; }; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/create_indicator_match_alert_type.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/create_indicator_match_alert_type.test.ts index 89e8e7f70e4aa..29054a4022715 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/create_indicator_match_alert_type.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/create_indicator_match_alert_type.test.ts @@ -14,7 +14,6 @@ import { allowedExperimentalValues } from '../../../../../common/experimental_fe import { createRuleTypeMocks } from '../__mocks__/rule_type'; import { createIndicatorMatchAlertType } from './create_indicator_match_alert_type'; import { sampleDocNoSortId } from '../../signals/__mocks__/es_results'; -import { CountResponse } from 'kibana/server'; import { RuleParams } from '../../schemas/rule_schemas'; import { createSecurityRuleTypeWrapper } from '../create_security_rule_type_wrapper'; import { createMockConfig } from '../../routes/__mocks__'; @@ -133,121 +132,4 @@ describe('Indicator Match Alerts', () => { await executor({ params }); expect(dependencies.ruleDataClient.getWriter).not.toBeCalled(); }); - - it('sends an alert when enrichments are found', async () => { - const indicatorMatchAlertType = securityRuleTypeWrapper( - createIndicatorMatchAlertType({ - experimentalFeatures: allowedExperimentalValues, - logger: dependencies.logger, - version: '1.0.0', - }) - ); - - dependencies.alerting.registerType(indicatorMatchAlertType); - - // threat list count - services.scopedClusterClient.asCurrentUser.count.mockReturnValue( - elasticsearchClientMock.createSuccessTransportRequestPromise({ count: 1 } as CountResponse) - ); - - services.scopedClusterClient.asCurrentUser.search.mockReturnValueOnce( - elasticsearchClientMock.createSuccessTransportRequestPromise({ - hits: { - hits: [ - { - ...sampleDocNoSortId(v4()), - _source: { - ...sampleDocNoSortId(v4())._source, - 'threat.indicator.file.hash.md5': 'a1b2c3', - }, - fields: { - ...sampleDocNoSortId(v4()).fields, - 'threat.indicator.file.hash.md5': ['a1b2c3'], - }, - }, - ], - total: { - relation: 'eq', - value: 1, - }, - }, - took: 0, - timed_out: false, - _shards: { - failed: 0, - skipped: 0, - successful: 1, - total: 1, - }, - }) - ); - - services.scopedClusterClient.asCurrentUser.search.mockReturnValueOnce( - elasticsearchClientMock.createSuccessTransportRequestPromise({ - hits: { - hits: [ - { - ...sampleDocNoSortId(v4()), - _source: { - ...sampleDocNoSortId(v4())._source, - 'file.hash.md5': 'a1b2c3', - }, - fields: { - ...sampleDocNoSortId(v4()).fields, - 'file.hash.md5': ['a1b2c3'], - }, - }, - ], - total: { - relation: 'eq', - value: 1, - }, - }, - took: 0, - timed_out: false, - _shards: { - failed: 0, - skipped: 0, - successful: 1, - total: 1, - }, - }) - ); - - services.scopedClusterClient.asCurrentUser.search.mockReturnValueOnce( - elasticsearchClientMock.createSuccessTransportRequestPromise({ - hits: { - hits: [ - { - ...sampleDocNoSortId(v4()), - _source: { - ...sampleDocNoSortId(v4())._source, - 'file.hash.md5': 'a1b2c3', - }, - fields: { - ...sampleDocNoSortId(v4()).fields, - 'file.hash.md5': ['a1b2c3'], - }, - }, - ], - total: { - relation: 'eq', - value: 1, - }, - }, - took: 0, - timed_out: false, - _shards: { - failed: 0, - skipped: 0, - successful: 1, - total: 1, - }, - }) - ); - - await executor({ params }); - - expect(dependencies.ruleDataClient.getWriter).toBeCalled(); - }); }); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/query/create_query_alert_type.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/query/create_query_alert_type.test.ts index 40ef2b46ed8d9..07eb096d0dd83 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/query/create_query_alert_type.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/query/create_query_alert_type.test.ts @@ -5,13 +5,10 @@ * 2.0. */ -import { v4 } from 'uuid'; - // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { elasticsearchClientMock } from 'src/core/server/elasticsearch/client/mocks'; import { allowedExperimentalValues } from '../../../../../common/experimental_features'; -import { sampleDocNoSortId } from '../../signals/__mocks__/es_results'; import { createQueryAlertType } from './create_query_alert_type'; import { createRuleTypeMocks } from '../__mocks__/rule_type'; import { createSecurityRuleTypeWrapper } from '../create_security_rule_type_wrapper'; @@ -79,48 +76,4 @@ describe('Custom Query Alerts', () => { await executor({ params }); expect(dependencies.ruleDataClient.getWriter).not.toBeCalled(); }); - - it('sends a properly formatted alert when events are found', async () => { - const queryAlertType = securityRuleTypeWrapper( - createQueryAlertType({ - experimentalFeatures: allowedExperimentalValues, - logger: dependencies.logger, - version: '1.0.0', - }) - ); - - dependencies.alerting.registerType(queryAlertType); - - const params = { - query: '*:*', - index: ['*'], - from: 'now-1m', - to: 'now', - language: 'kuery', - type: 'query', - }; - - services.scopedClusterClient.asCurrentUser.search.mockReturnValue( - elasticsearchClientMock.createSuccessTransportRequestPromise({ - hits: { - hits: [sampleDocNoSortId(v4()), sampleDocNoSortId(v4()), sampleDocNoSortId(v4())], - total: { - relation: 'eq', - value: 3, - }, - }, - took: 0, - timed_out: false, - _shards: { - failed: 0, - skipped: 0, - successful: 1, - total: 1, - }, - }) - ); - - await executor({ params }); - expect(dependencies.ruleDataClient.getWriter).toBeCalled(); - }); }); diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/generating_signals.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/generating_signals.ts index b28ff3fdc714d..073c5a9971f4b 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/generating_signals.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/generating_signals.ts @@ -56,6 +56,7 @@ import { ALERT_GROUP_ID, ALERT_THRESHOLD_RESULT, } from '../../../../plugins/security_solution/common/field_maps/field_names'; +import { DETECTION_ENGINE_RULES_URL } from '../../../../plugins/security_solution/common/constants'; /** * Specific _id to use for some of the tests. If the archiver changes and you see errors @@ -1157,5 +1158,71 @@ export default ({ getService }: FtrProviderContext) => { }); }); }); + + describe.skip('Signal deduplication', async () => { + before(async () => { + await esArchiver.load('x-pack/test/functional/es_archives/auditbeat/hosts'); + }); + + after(async () => { + await esArchiver.unload('x-pack/test/functional/es_archives/auditbeat/hosts'); + }); + + beforeEach(async () => { + await deleteSignalsIndex(supertest, log); + }); + + afterEach(async () => { + await deleteSignalsIndex(supertest, log); + await deleteAllAlerts(supertest, log); + }); + + it('should not generate duplicate signals', async () => { + const rule: QueryCreateSchema = { + ...getRuleForSignalTesting(['auditbeat-*']), + query: `_id:${ID}`, + }; + + const ruleResponse = await createRule(supertest, log, rule); + + const signals = await getOpenSignals(supertest, log, es, ruleResponse); + expect(signals.hits.hits.length).to.eql(1); + + const statusResponse = await supertest + .post(`${DETECTION_ENGINE_RULES_URL}/_find_statuses`) + .set('kbn-xsrf', 'true') + .send({ ids: [ruleResponse.id] }); + const initialStatusDate = new Date( + statusResponse.body[ruleResponse.id].current_status.status_date + ); + + const initialSignal = signals.hits.hits[0]; + + // Disable the rule then re-enable to trigger another run + await supertest + .patch(DETECTION_ENGINE_RULES_URL) + .set('kbn-xsrf', 'true') + .send({ rule_id: ruleResponse.rule_id, enabled: false }) + .expect(200); + + await supertest + .patch(DETECTION_ENGINE_RULES_URL) + .set('kbn-xsrf', 'true') + .send({ rule_id: ruleResponse.rule_id, enabled: true }) + .expect(200); + + await waitForRuleSuccessOrStatus( + supertest, + log, + ruleResponse.id, + 'succeeded', + initialStatusDate + ); + + const newSignals = await getOpenSignals(supertest, log, es, ruleResponse); + expect(newSignals.hits.hits.length).to.eql(1); + expect(newSignals.hits.hits[0]).to.eql(initialSignal); + }); + }); }); }; diff --git a/x-pack/test/detection_engine_api_integration/utils.ts b/x-pack/test/detection_engine_api_integration/utils.ts index cc915324a4a35..bb4f564edaf1e 100644 --- a/x-pack/test/detection_engine_api_integration/utils.ts +++ b/x-pack/test/detection_engine_api_integration/utils.ts @@ -1308,7 +1308,8 @@ export const waitForRuleSuccessOrStatus = async ( supertest: SuperTest.SuperTest, log: ToolingLog, id: string, - status: 'succeeded' | 'failed' | 'partial failure' | 'warning' = 'succeeded' + status: 'succeeded' | 'failed' | 'partial failure' | 'warning' = 'succeeded', + afterDate?: Date ): Promise => { await waitFor( async () => { @@ -1324,15 +1325,20 @@ export const waitForRuleSuccessOrStatus = async ( )}, status: ${JSON.stringify(response.status)}` ); } - if (response.body[id]?.current_status?.status !== status) { + const currentStatus = response.body[id]?.current_status; + + if (currentStatus?.status !== status) { log.debug( `Did not get an expected status of ${status} while waiting for a rule success or status for rule id ${id} (waitForRuleSuccessOrStatus). Will continue retrying until status is found. body: ${JSON.stringify( response.body )}, status: ${JSON.stringify(response.status)}` ); } - - return response.body[id]?.current_status?.status === status; + return ( + currentStatus != null && + currentStatus.status === status && + (afterDate ? new Date(currentStatus.status_date) > afterDate : true) + ); } catch (e) { if ((e as Error).message.includes('got 503 "Service Unavailable"')) { return false; From 55de7bb3b2e2f6f813a45b4cd9bf501f6a6f18b2 Mon Sep 17 00:00:00 2001 From: Steph Milovic Date: Thu, 18 Nov 2021 20:50:10 -0700 Subject: [PATCH 134/148] fix (#119065) --- x-pack/plugins/timelines/public/container/index.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/x-pack/plugins/timelines/public/container/index.tsx b/x-pack/plugins/timelines/public/container/index.tsx index e43d9571f8001..28e4a5ffda4af 100644 --- a/x-pack/plugins/timelines/public/container/index.tsx +++ b/x-pack/plugins/timelines/public/container/index.tsx @@ -275,6 +275,7 @@ export const useTimelineEvents = ({ filterQuery: createFilter(filterQuery), querySize: limit, sort, + runtimeMappings, timerange: { interval: '12h', from: startDate, From e5c4846f7d178058bcb0c8b820580d8781220db3 Mon Sep 17 00:00:00 2001 From: Diana Derevyankina <54894989+DziyanaDzeraviankina@users.noreply.github.com> Date: Fri, 19 Nov 2021 10:10:56 +0300 Subject: [PATCH 135/148] [TSVB] Measure the usage of `use_kibana_indexes` setting and different TSVB chart types (#116407) * [TSVB] Measure the usage of `use_kibana_indexes` setting and different TSVB chart types * Update telemetry schema * Exclude sample data visualizations from statistics * Update register_timeseries_collector.test Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- src/plugins/telemetry/schema/oss_plugins.json | 26 ++++++ src/plugins/vis_types/timeseries/kibana.json | 2 +- .../vis_types/timeseries/server/plugin.ts | 4 +- .../get_usage_collector.test.ts | 20 +++++ .../usage_collector/get_usage_collector.ts | 80 ++++++++++++++++++- .../register_timeseries_collector.test.ts | 2 +- .../register_timeseries_collector.ts | 20 ++++- 7 files changed, 145 insertions(+), 9 deletions(-) diff --git a/src/plugins/telemetry/schema/oss_plugins.json b/src/plugins/telemetry/schema/oss_plugins.json index d40bf9aa5d610..cd5d3818bcdec 100644 --- a/src/plugins/telemetry/schema/oss_plugins.json +++ b/src/plugins/telemetry/schema/oss_plugins.json @@ -9250,11 +9250,37 @@ "description": "Number of TSVB visualizations using \"last value\" as a time range" } }, + "timeseries_use_es_indices_total": { + "type": "long", + "_meta": { "description": "Number of TSVB visualizations using elasticsearch indices" } + }, "timeseries_table_use_aggregate_function": { "type": "long", "_meta": { "description": "Number of TSVB table visualizations using aggregate function" } + }, + "timeseries_types": { + "properties": { + "table": { + "type": "long" + }, + "gauge": { + "type": "long" + }, + "markdown": { + "type": "long" + }, + "top_n": { + "type": "long" + }, + "timeseries": { + "type": "long" + }, + "metric": { + "type": "long" + } + } } } }, diff --git a/src/plugins/vis_types/timeseries/kibana.json b/src/plugins/vis_types/timeseries/kibana.json index 5cc425e4edf71..63cabc70a9587 100644 --- a/src/plugins/vis_types/timeseries/kibana.json +++ b/src/plugins/vis_types/timeseries/kibana.json @@ -5,7 +5,7 @@ "server": true, "ui": true, "requiredPlugins": ["charts", "data", "expressions", "visualizations", "visualize"], - "optionalPlugins": ["usageCollection"], + "optionalPlugins": ["home","usageCollection"], "requiredBundles": ["kibanaUtils", "kibanaReact", "fieldFormats"], "owner": { "name": "Vis Editors", diff --git a/src/plugins/vis_types/timeseries/server/plugin.ts b/src/plugins/vis_types/timeseries/server/plugin.ts index 5347d9ab7bfbc..248016f1a9836 100644 --- a/src/plugins/vis_types/timeseries/server/plugin.ts +++ b/src/plugins/vis_types/timeseries/server/plugin.ts @@ -21,6 +21,7 @@ import { first, map } from 'rxjs/operators'; import { VisTypeTimeseriesConfig } from './config'; import { getVisData } from './lib/get_vis_data'; import { UsageCollectionSetup } from '../../../usage_collection/server'; +import { HomeServerPluginSetup } from '../../../home/server'; import { PluginStart } from '../../../data/server'; import { IndexPatternsService } from '../../../data/common'; import { visDataRoutes } from './routes/vis'; @@ -47,6 +48,7 @@ export interface LegacySetup { interface VisTypeTimeseriesPluginSetupDependencies { usageCollection?: UsageCollectionSetup; + home?: HomeServerPluginSetup; } interface VisTypeTimeseriesPluginStartDependencies { @@ -128,7 +130,7 @@ export class VisTypeTimeseriesPlugin implements Plugin { fieldsRoutes(router, framework); if (plugins.usageCollection) { - registerTimeseriesUsageCollector(plugins.usageCollection); + registerTimeseriesUsageCollector(plugins.usageCollection, plugins.home); } return { diff --git a/src/plugins/vis_types/timeseries/server/usage_collector/get_usage_collector.test.ts b/src/plugins/vis_types/timeseries/server/usage_collector/get_usage_collector.test.ts index 3f3a204d29263..573c6c0e00fe2 100644 --- a/src/plugins/vis_types/timeseries/server/usage_collector/get_usage_collector.test.ts +++ b/src/plugins/vis_types/timeseries/server/usage_collector/get_usage_collector.test.ts @@ -22,7 +22,9 @@ const mockedSavedObject = { type: 'metrics', title: 'TSVB visualization 1', params: { + type: 'gauge', time_range_mode: TIME_RANGE_DATA_MODES.ENTIRE_TIME_RANGE, + use_kibana_indexes: true, }, }), }, @@ -33,7 +35,9 @@ const mockedSavedObject = { type: 'metrics', title: 'TSVB visualization 2', params: { + type: 'top_n', time_range_mode: TIME_RANGE_DATA_MODES.LAST_VALUE, + use_kibana_indexes: false, }, }), }, @@ -44,7 +48,9 @@ const mockedSavedObject = { type: 'metrics', title: 'TSVB visualization 3', params: { + type: 'markdown', time_range_mode: undefined, + use_kibana_indexes: false, }, }), }, @@ -78,7 +84,9 @@ const mockedSavedObjectsByValue = [ savedVis: { type: 'metrics', params: { + type: 'markdown', time_range_mode: TIME_RANGE_DATA_MODES.LAST_VALUE, + use_kibana_indexes: false, }, }, }, @@ -93,7 +101,9 @@ const mockedSavedObjectsByValue = [ savedVis: { type: 'metrics', params: { + type: 'timeseries', time_range_mode: TIME_RANGE_DATA_MODES.ENTIRE_TIME_RANGE, + use_kibana_indexes: true, }, }, }, @@ -115,6 +125,7 @@ const mockedSavedObjectsByValue = [ aggregate_function: 'sum', }, ], + use_kibana_indexes: true, }, }, }, @@ -241,7 +252,16 @@ describe('Timeseries visualization usage collector', () => { expect(result).toStrictEqual({ timeseries_use_last_value_mode_total: 5, + timeseries_use_es_indices_total: 4, timeseries_table_use_aggregate_function: 2, + timeseries_types: { + gauge: 1, + markdown: 2, + metric: 0, + table: 2, + timeseries: 1, + top_n: 1, + }, }); }); }); diff --git a/src/plugins/vis_types/timeseries/server/usage_collector/get_usage_collector.ts b/src/plugins/vis_types/timeseries/server/usage_collector/get_usage_collector.ts index 58f0c9c7f1459..cc08b8789d368 100644 --- a/src/plugins/vis_types/timeseries/server/usage_collector/get_usage_collector.ts +++ b/src/plugins/vis_types/timeseries/server/usage_collector/get_usage_collector.ts @@ -14,12 +14,22 @@ import type { ISavedObjectsRepository, SavedObjectsFindResult, } from '../../../../../core/server'; +import type { HomeServerPluginSetup } from '../../../../home/server'; import type { SavedVisState } from '../../../../visualizations/common'; import type { Panel } from '../../common/types'; export interface TimeseriesUsage { timeseries_use_last_value_mode_total: number; + timeseries_use_es_indices_total: number; timeseries_table_use_aggregate_function: number; + timeseries_types: { + table: number; + gauge: number; + markdown: number; + top_n: number; + timeseries: number; + metric: number; + }; } const doTelemetryFoVisualizations = async ( @@ -59,31 +69,80 @@ const doTelemetryForByValueVisualizations = async ( } }; +const getDefaultTSVBVisualizations = (home?: HomeServerPluginSetup) => { + const titles: string[] = []; + const sampleDataSets = home?.sampleData.getSampleDatasets() ?? []; + + sampleDataSets.forEach((sampleDataSet) => + sampleDataSet.savedObjects.forEach((savedObject) => { + try { + if (savedObject.type === 'visualization') { + const visState = JSON.parse(savedObject.attributes?.visState); + + if (visState.type === 'metrics') { + titles.push(visState.title); + } + } + } catch (e) { + // Let it go, visState is invalid and we'll don't need to handle it + } + }) + ); + + return titles; +}; + export const getStats = async ( - soClient: SavedObjectsClientContract | ISavedObjectsRepository + soClient: SavedObjectsClientContract | ISavedObjectsRepository, + home?: HomeServerPluginSetup ): Promise => { const timeseriesUsage = { timeseries_use_last_value_mode_total: 0, + timeseries_use_es_indices_total: 0, timeseries_table_use_aggregate_function: 0, + timeseries_types: { + gauge: 0, + markdown: 0, + metric: 0, + table: 0, + timeseries: 0, + top_n: 0, + }, }; + // we want to exclude the TSVB Sample Data visualizations from the stats + // in order to have more accurate results + const excludedFromStatsVisualizations = getDefaultTSVBVisualizations(home); + function telemetryUseLastValueMode(visState: SavedVisState) { if ( visState.type === 'metrics' && visState.params.type !== 'timeseries' && (!visState.params.time_range_mode || - visState.params.time_range_mode === TIME_RANGE_DATA_MODES.LAST_VALUE) + visState.params.time_range_mode === TIME_RANGE_DATA_MODES.LAST_VALUE) && + !excludedFromStatsVisualizations.includes(visState.title) ) { timeseriesUsage.timeseries_use_last_value_mode_total++; } } + function telemetryUseESIndices(visState: SavedVisState) { + if ( + visState.type === 'metrics' && + !visState.params.use_kibana_indexes && + !excludedFromStatsVisualizations.includes(visState.title) + ) { + timeseriesUsage.timeseries_use_es_indices_total++; + } + } + function telemetryTableAggFunction(visState: SavedVisState) { if ( visState.type === 'metrics' && visState.params.type === 'table' && visState.params.series && - visState.params.series.length > 0 + visState.params.series.length > 0 && + !excludedFromStatsVisualizations.includes(visState.title) ) { const usesAggregateFunction = visState.params.series.some( (s) => s.aggregate_by && s.aggregate_function @@ -94,17 +153,30 @@ export const getStats = async ( } } + function telemetryPanelTypes(visState: SavedVisState) { + if (visState.type === 'metrics' && !excludedFromStatsVisualizations.includes(visState.title)) { + timeseriesUsage.timeseries_types[visState.params.type]++; + } + } await Promise.all([ // last value usage telemetry doTelemetryFoVisualizations(soClient, telemetryUseLastValueMode), doTelemetryForByValueVisualizations(soClient, telemetryUseLastValueMode), + // elasticsearch indices usage telemetry + doTelemetryFoVisualizations(soClient, telemetryUseESIndices), + doTelemetryForByValueVisualizations(soClient, telemetryUseESIndices), // table aggregate function telemetry doTelemetryFoVisualizations(soClient, telemetryTableAggFunction), doTelemetryForByValueVisualizations(soClient, telemetryTableAggFunction), + // panel types usage telemetry + doTelemetryFoVisualizations(soClient, telemetryPanelTypes), + doTelemetryForByValueVisualizations(soClient, telemetryPanelTypes), ]); return timeseriesUsage.timeseries_use_last_value_mode_total || - timeseriesUsage.timeseries_table_use_aggregate_function + timeseriesUsage.timeseries_use_es_indices_total || + timeseriesUsage.timeseries_table_use_aggregate_function || + Object.values(timeseriesUsage.timeseries_types).some((visualizationCount) => visualizationCount) ? timeseriesUsage : undefined; }; diff --git a/src/plugins/vis_types/timeseries/server/usage_collector/register_timeseries_collector.test.ts b/src/plugins/vis_types/timeseries/server/usage_collector/register_timeseries_collector.test.ts index 26a74821fe5ae..3714cc6b30c45 100644 --- a/src/plugins/vis_types/timeseries/server/usage_collector/register_timeseries_collector.test.ts +++ b/src/plugins/vis_types/timeseries/server/usage_collector/register_timeseries_collector.test.ts @@ -46,7 +46,7 @@ describe('registerTimeseriesUsageCollector', () => { const mockedCollectorFetchContext = createCollectorFetchContextMock(); const fetchResult = await usageCollector.fetch(mockedCollectorFetchContext); expect(mockGetStats).toBeCalledTimes(1); - expect(mockGetStats).toBeCalledWith(mockedCollectorFetchContext.soClient); + expect(mockGetStats).toBeCalledWith(mockedCollectorFetchContext.soClient, undefined); expect(fetchResult).toBe(mockStats); }); }); diff --git a/src/plugins/vis_types/timeseries/server/usage_collector/register_timeseries_collector.ts b/src/plugins/vis_types/timeseries/server/usage_collector/register_timeseries_collector.ts index b96d6ce4c5da8..e8fd666fb28d1 100644 --- a/src/plugins/vis_types/timeseries/server/usage_collector/register_timeseries_collector.ts +++ b/src/plugins/vis_types/timeseries/server/usage_collector/register_timeseries_collector.ts @@ -8,8 +8,12 @@ import { getStats, TimeseriesUsage } from './get_usage_collector'; import type { UsageCollectionSetup } from '../../../../usage_collection/server'; +import type { HomeServerPluginSetup } from '../../../../home/server'; -export function registerTimeseriesUsageCollector(collectorSet: UsageCollectionSetup) { +export function registerTimeseriesUsageCollector( + collectorSet: UsageCollectionSetup, + home?: HomeServerPluginSetup +) { const collector = collectorSet.makeUsageCollector({ type: 'vis_type_timeseries', isReady: () => true, @@ -18,12 +22,24 @@ export function registerTimeseriesUsageCollector(collectorSet: UsageCollectionSe type: 'long', _meta: { description: 'Number of TSVB visualizations using "last value" as a time range' }, }, + timeseries_use_es_indices_total: { + type: 'long', + _meta: { description: 'Number of TSVB visualizations using elasticsearch indices' }, + }, timeseries_table_use_aggregate_function: { type: 'long', _meta: { description: 'Number of TSVB table visualizations using aggregate function' }, }, + timeseries_types: { + table: { type: 'long' }, + gauge: { type: 'long' }, + markdown: { type: 'long' }, + top_n: { type: 'long' }, + timeseries: { type: 'long' }, + metric: { type: 'long' }, + }, }, - fetch: async ({ soClient }) => await getStats(soClient), + fetch: async ({ soClient }) => await getStats(soClient, home), }); collectorSet.registerCollector(collector); From eb81db2ddd0b26d23a453a5635cf1e6cf5e59a28 Mon Sep 17 00:00:00 2001 From: Milton Hultgren Date: Fri, 19 Nov 2021 09:59:51 +0100 Subject: [PATCH 136/148] [Logs UI] Set explicit format for all range clauses (#115912) * [Logs UI] Set explicit format for all range clauses * Add integration test for /metrics/overview/top * Add tests for process list and chart * Add test for log_analysis/validation/log_entry_datasets * Use endpoint route constant --- .../queries/log_entry_datasets.ts | 1 + .../server/lib/host_details/process_list.ts | 1 + .../lib/host_details/process_list_chart.ts | 1 + .../server/lib/infra_ml/queries/common.ts | 1 + .../server/lib/log_analysis/queries/common.ts | 1 + .../queries/log_entry_category_examples.ts | 1 + .../queries/log_entry_examples.ts | 1 + .../overview/lib/create_top_nodes_query.ts | 1 + .../api_integration/apis/metrics_ui/index.js | 4 ++ ..._analysis_validation_log_entry_datasets.ts | 62 +++++++++++++++++++ .../apis/metrics_ui/metrics_overview_top.ts | 52 ++++++++++++++++ .../apis/metrics_ui/metrics_process_list.ts | 58 +++++++++++++++++ .../metrics_ui/metrics_process_list_chart.ts | 50 +++++++++++++++ 13 files changed, 234 insertions(+) create mode 100644 x-pack/test/api_integration/apis/metrics_ui/infra_log_analysis_validation_log_entry_datasets.ts create mode 100644 x-pack/test/api_integration/apis/metrics_ui/metrics_overview_top.ts create mode 100644 x-pack/test/api_integration/apis/metrics_ui/metrics_process_list.ts create mode 100644 x-pack/test/api_integration/apis/metrics_ui/metrics_process_list_chart.ts diff --git a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/queries/log_entry_datasets.ts b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/queries/log_entry_datasets.ts index 4386b6ccef9c1..a658c7deb317c 100644 --- a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/queries/log_entry_datasets.ts +++ b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/queries/log_entry_datasets.ts @@ -29,6 +29,7 @@ export const createLogEntryDatasetsQuery = ( [timestampField]: { gte: startTime, lte: endTime, + format: 'epoch_millis', }, }, }, diff --git a/x-pack/plugins/infra/server/lib/host_details/process_list.ts b/x-pack/plugins/infra/server/lib/host_details/process_list.ts index 6e608bfa2ddca..27563e3218aae 100644 --- a/x-pack/plugins/infra/server/lib/host_details/process_list.ts +++ b/x-pack/plugins/infra/server/lib/host_details/process_list.ts @@ -26,6 +26,7 @@ export const getProcessList = async ( [TIMESTAMP_FIELD]: { gte: to - 60 * 1000, // 1 minute lte: to, + format: 'epoch_millis', }, }, }, diff --git a/x-pack/plugins/infra/server/lib/host_details/process_list_chart.ts b/x-pack/plugins/infra/server/lib/host_details/process_list_chart.ts index 7ff66a80e967b..03b7e8f825686 100644 --- a/x-pack/plugins/infra/server/lib/host_details/process_list_chart.ts +++ b/x-pack/plugins/infra/server/lib/host_details/process_list_chart.ts @@ -30,6 +30,7 @@ export const getProcessListChart = async ( [TIMESTAMP_FIELD]: { gte: to - 60 * 1000, // 1 minute lte: to, + format: 'epoch_millis', }, }, }, diff --git a/x-pack/plugins/infra/server/lib/infra_ml/queries/common.ts b/x-pack/plugins/infra/server/lib/infra_ml/queries/common.ts index 594dc3371f3a2..8fbe7bd98ed9c 100644 --- a/x-pack/plugins/infra/server/lib/infra_ml/queries/common.ts +++ b/x-pack/plugins/infra/server/lib/infra_ml/queries/common.ts @@ -44,6 +44,7 @@ export const createTimeRangeFilters = (startTime: number, endTime: number) => [ timestamp: { gte: startTime, lte: endTime, + format: 'epoch_millis', }, }, }, diff --git a/x-pack/plugins/infra/server/lib/log_analysis/queries/common.ts b/x-pack/plugins/infra/server/lib/log_analysis/queries/common.ts index b05e4ce00fe9c..293cd8e6153e7 100644 --- a/x-pack/plugins/infra/server/lib/log_analysis/queries/common.ts +++ b/x-pack/plugins/infra/server/lib/log_analysis/queries/common.ts @@ -36,6 +36,7 @@ export const createTimeRangeFilters = (startTime: number, endTime: number) => [ timestamp: { gte: startTime, lte: endTime, + format: 'epoch_millis', }, }, }, diff --git a/x-pack/plugins/infra/server/lib/log_analysis/queries/log_entry_category_examples.ts b/x-pack/plugins/infra/server/lib/log_analysis/queries/log_entry_category_examples.ts index dd68de4e49d34..c79f4ddc2dc56 100644 --- a/x-pack/plugins/infra/server/lib/log_analysis/queries/log_entry_category_examples.ts +++ b/x-pack/plugins/infra/server/lib/log_analysis/queries/log_entry_category_examples.ts @@ -30,6 +30,7 @@ export const createLogEntryCategoryExamplesQuery = ( [timestampField]: { gte: startTime, lte: endTime, + format: 'epoch_millis', }, }, }, diff --git a/x-pack/plugins/infra/server/lib/log_analysis/queries/log_entry_examples.ts b/x-pack/plugins/infra/server/lib/log_analysis/queries/log_entry_examples.ts index d6099404daa80..a975c6a79f99a 100644 --- a/x-pack/plugins/infra/server/lib/log_analysis/queries/log_entry_examples.ts +++ b/x-pack/plugins/infra/server/lib/log_analysis/queries/log_entry_examples.ts @@ -32,6 +32,7 @@ export const createLogEntryExamplesQuery = ( [timestampField]: { gte: startTime, lte: endTime, + format: 'epoch_millis', }, }, }, diff --git a/x-pack/plugins/infra/server/routes/overview/lib/create_top_nodes_query.ts b/x-pack/plugins/infra/server/routes/overview/lib/create_top_nodes_query.ts index ccead528749cd..a915a7882e231 100644 --- a/x-pack/plugins/infra/server/routes/overview/lib/create_top_nodes_query.ts +++ b/x-pack/plugins/infra/server/routes/overview/lib/create_top_nodes_query.ts @@ -26,6 +26,7 @@ export const createTopNodesQuery = ( [TIMESTAMP_FIELD]: { gte: options.timerange.from, lte: options.timerange.to, + format: 'epoch_millis', }, }, }, diff --git a/x-pack/test/api_integration/apis/metrics_ui/index.js b/x-pack/test/api_integration/apis/metrics_ui/index.js index dfba4ee0985ba..72c79faaa4372 100644 --- a/x-pack/test/api_integration/apis/metrics_ui/index.js +++ b/x-pack/test/api_integration/apis/metrics_ui/index.js @@ -19,5 +19,9 @@ export default function ({ loadTestFile }) { loadTestFile(require.resolve('./ip_to_hostname')); loadTestFile(require.resolve('./http_source')); loadTestFile(require.resolve('./metric_threshold_alert')); + loadTestFile(require.resolve('./metrics_overview_top')); + loadTestFile(require.resolve('./metrics_process_list')); + loadTestFile(require.resolve('./metrics_process_list_chart')); + loadTestFile(require.resolve('./infra_log_analysis_validation_log_entry_datasets')); }); } diff --git a/x-pack/test/api_integration/apis/metrics_ui/infra_log_analysis_validation_log_entry_datasets.ts b/x-pack/test/api_integration/apis/metrics_ui/infra_log_analysis_validation_log_entry_datasets.ts new file mode 100644 index 0000000000000..9867abcc67a7d --- /dev/null +++ b/x-pack/test/api_integration/apis/metrics_ui/infra_log_analysis_validation_log_entry_datasets.ts @@ -0,0 +1,62 @@ +/* + * 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 expect from '@kbn/expect'; +import { + LOG_ANALYSIS_VALIDATE_DATASETS_PATH, + validateLogEntryDatasetsRequestPayloadRT, + validateLogEntryDatasetsResponsePayloadRT, +} from '../../../../plugins/infra/common/http_api/log_analysis/validation/datasets'; +import { decodeOrThrow } from '../../../../plugins/infra/common/runtime_types'; +import { FtrProviderContext } from '../../ftr_provider_context'; + +export default function ({ getService }: FtrProviderContext) { + const esArchiver = getService('esArchiver'); + const supertest = getService('supertest'); + + describe('API /infra/log_analysis/validation/log_entry_datasets', () => { + before(() => + esArchiver.load('x-pack/test/functional/es_archives/infra/8.0.0/logs_and_metrics') + ); + after(() => + esArchiver.unload('x-pack/test/functional/es_archives/infra/8.0.0/logs_and_metrics') + ); + + it('works', async () => { + const response = await supertest + .post(LOG_ANALYSIS_VALIDATE_DATASETS_PATH) + .set({ + 'kbn-xsrf': 'some-xsrf-token', + }) + .send( + validateLogEntryDatasetsRequestPayloadRT.encode({ + data: { + endTime: Date.now().valueOf(), + indices: ['filebeat-*'], + startTime: 1562766600672, + timestampField: '@timestamp', + runtimeMappings: {}, + }, + }) + ) + .expect(200); + + const { + data: { datasets }, + } = decodeOrThrow(validateLogEntryDatasetsResponsePayloadRT)(response.body); + + expect(datasets.length).to.be(1); + expect(datasets[0].indexName).to.be('filebeat-*'); + expect(datasets[0].datasets).to.eql([ + 'elasticsearch.gc', + 'elasticsearch.server', + 'kibana.log', + 'nginx.access', + ]); + }); + }); +} diff --git a/x-pack/test/api_integration/apis/metrics_ui/metrics_overview_top.ts b/x-pack/test/api_integration/apis/metrics_ui/metrics_overview_top.ts new file mode 100644 index 0000000000000..ee73c9bd92a54 --- /dev/null +++ b/x-pack/test/api_integration/apis/metrics_ui/metrics_overview_top.ts @@ -0,0 +1,52 @@ +/* + * 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 expect from '@kbn/expect'; +import { + TopNodesRequestRT, + TopNodesResponseRT, +} from '../../../../plugins/infra/common/http_api/overview_api'; +import { decodeOrThrow } from '../../../../plugins/infra/common/runtime_types'; +import { FtrProviderContext } from '../../ftr_provider_context'; +import { DATES } from './constants'; + +export default function ({ getService }: FtrProviderContext) { + const esArchiver = getService('esArchiver'); + const supertest = getService('supertest'); + + const { min, max } = DATES['7.0.0'].hosts; + + describe('API /metrics/overview/top', () => { + before(() => esArchiver.load('x-pack/test/functional/es_archives/infra/7.0.0/hosts')); + after(() => esArchiver.unload('x-pack/test/functional/es_archives/infra/7.0.0/hosts')); + + it('works', async () => { + const response = await supertest + .post('/api/metrics/overview/top') + .set({ + 'kbn-xsrf': 'some-xsrf-token', + }) + .send( + TopNodesRequestRT.encode({ + sourceId: 'default', + bucketSize: '300s', + size: 5, + timerange: { + from: min, + to: max, + }, + }) + ) + .expect(200); + + const { series } = decodeOrThrow(TopNodesResponseRT)(response.body); + + expect(series.length).to.be(1); + expect(series[0].id).to.be('demo-stack-mysql-01'); + }); + }); +} diff --git a/x-pack/test/api_integration/apis/metrics_ui/metrics_process_list.ts b/x-pack/test/api_integration/apis/metrics_ui/metrics_process_list.ts new file mode 100644 index 0000000000000..bba38f622b0ab --- /dev/null +++ b/x-pack/test/api_integration/apis/metrics_ui/metrics_process_list.ts @@ -0,0 +1,58 @@ +/* + * 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 expect from '@kbn/expect'; +import { + ProcessListAPIRequestRT, + ProcessListAPIResponseRT, +} from '../../../../plugins/infra/common/http_api/host_details/process_list'; +import { decodeOrThrow } from '../../../../plugins/infra/common/runtime_types'; +import { FtrProviderContext } from '../../ftr_provider_context'; + +export default function ({ getService }: FtrProviderContext) { + const esArchiver = getService('esArchiver'); + const supertest = getService('supertest'); + + describe('API /metrics/process_list', () => { + before(() => esArchiver.load('x-pack/test/functional/es_archives/infra/8.0.0/metrics_and_apm')); + after(() => + esArchiver.unload('x-pack/test/functional/es_archives/infra/8.0.0/metrics_and_apm') + ); + + it('works', async () => { + const response = await supertest + .post('/api/metrics/process_list') + .set({ + 'kbn-xsrf': 'some-xsrf-token', + }) + .send( + ProcessListAPIRequestRT.encode({ + hostTerm: { + 'host.name': 'gke-observability-8--observability-8--bc1afd95-nhhw', + }, + indexPattern: 'metrics-*,metricbeat-*', + to: 1564432800000, + sortBy: { + name: 'cpu', + isAscending: false, + }, + searchFilter: [ + { + match_all: {}, + }, + ], + }) + ) + .expect(200); + + const { processList, summary } = decodeOrThrow(ProcessListAPIResponseRT)(response.body); + + expect(processList.length).to.be(10); + expect(summary.total).to.be(178); + }); + }); +} diff --git a/x-pack/test/api_integration/apis/metrics_ui/metrics_process_list_chart.ts b/x-pack/test/api_integration/apis/metrics_ui/metrics_process_list_chart.ts new file mode 100644 index 0000000000000..ba4d7123556c1 --- /dev/null +++ b/x-pack/test/api_integration/apis/metrics_ui/metrics_process_list_chart.ts @@ -0,0 +1,50 @@ +/* + * 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 expect from '@kbn/expect'; +import { + ProcessListAPIChartRequestRT, + ProcessListAPIChartResponseRT, +} from '../../../../plugins/infra/common/http_api/host_details/process_list'; +import { decodeOrThrow } from '../../../../plugins/infra/common/runtime_types'; +import { FtrProviderContext } from '../../ftr_provider_context'; + +export default function ({ getService }: FtrProviderContext) { + const esArchiver = getService('esArchiver'); + const supertest = getService('supertest'); + + describe('API /metrics/process_list/chart', () => { + before(() => esArchiver.load('x-pack/test/functional/es_archives/infra/8.0.0/metrics_and_apm')); + after(() => + esArchiver.unload('x-pack/test/functional/es_archives/infra/8.0.0/metrics_and_apm') + ); + + it('works', async () => { + const response = await supertest + .post('/api/metrics/process_list/chart') + .set({ + 'kbn-xsrf': 'some-xsrf-token', + }) + .send( + ProcessListAPIChartRequestRT.encode({ + hostTerm: { + 'host.name': 'gke-observability-8--observability-8--bc1afd95-nhhw', + }, + indexPattern: 'metrics-*,metricbeat-*', + to: 1564432800000, + command: '/usr/lib/systemd/systemd-journald', + }) + ) + .expect(200); + + const { cpu, memory } = decodeOrThrow(ProcessListAPIChartResponseRT)(response.body); + + expect(cpu.rows.length).to.be(16); + expect(memory.rows.length).to.be(16); + }); + }); +} From a28419a3276580838929c58c01198efd2ee4a291 Mon Sep 17 00:00:00 2001 From: Pierre Gayvallet Date: Fri, 19 Nov 2021 10:41:51 +0100 Subject: [PATCH 137/148] Improve the status page user interface (#118512) * initial improvements * add status expanded row * fix row ordering by status * fix data-test-subj * fix status summary row label * fix load_status unit tests * fix status_table unit tests * fix FTR tests * add server_status tests * add unit test for some of the new components * add unit tests for added libs * i18n for added text * update snapshots * resolve merge conflicts Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../__snapshots__/server_status.test.tsx.snap | 33 +++++ .../__snapshots__/status_table.test.tsx.snap | 45 +++++-- .../core_app/status/components/index.ts | 2 + .../status/components/server_status.test.tsx | 14 +- .../status/components/server_status.tsx | 15 +-- .../status/components/status_badge.test.tsx | 57 ++++++++ .../status/components/status_badge.tsx | 30 +++++ .../status/components/status_expanded_row.tsx | 36 ++++++ .../status/components/status_section.tsx | 40 ++++++ .../status/components/status_table.test.tsx | 13 +- .../status/components/status_table.tsx | 119 +++++++++++++---- .../status/components/version_header.test.tsx | 46 +++++++ .../status/components/version_header.tsx | 65 ++++++++++ src/core/public/core_app/status/lib/index.ts | 3 +- .../core_app/status/lib/load_status.test.ts | 27 ++-- .../public/core_app/status/lib/load_status.ts | 33 ++--- .../core_app/status/lib/status_level.test.ts | 122 ++++++++++++++++++ .../core_app/status/lib/status_level.ts | 44 +++++++ .../public/core_app/status/status_app.tsx | 84 +++--------- src/core/types/status.ts | 4 +- test/functional/apps/status_page/index.ts | 13 +- 21 files changed, 701 insertions(+), 144 deletions(-) create mode 100644 src/core/public/core_app/status/components/status_badge.test.tsx create mode 100644 src/core/public/core_app/status/components/status_badge.tsx create mode 100644 src/core/public/core_app/status/components/status_expanded_row.tsx create mode 100644 src/core/public/core_app/status/components/status_section.tsx create mode 100644 src/core/public/core_app/status/components/version_header.test.tsx create mode 100644 src/core/public/core_app/status/components/version_header.tsx create mode 100644 src/core/public/core_app/status/lib/status_level.test.ts create mode 100644 src/core/public/core_app/status/lib/status_level.ts diff --git a/src/core/public/core_app/status/components/__snapshots__/server_status.test.tsx.snap b/src/core/public/core_app/status/components/__snapshots__/server_status.test.tsx.snap index 7682a848b0b17..bcc60f5908592 100644 --- a/src/core/public/core_app/status/components/__snapshots__/server_status.test.tsx.snap +++ b/src/core/public/core_app/status/components/__snapshots__/server_status.test.tsx.snap @@ -65,3 +65,36 @@ exports[`ServerStatus renders correctly for red state 2`] = ` `; + +exports[`ServerStatus renders correctly for yellow state 2`] = ` + + + + + + Yellow + + + + + +`; diff --git a/src/core/public/core_app/status/components/__snapshots__/status_table.test.tsx.snap b/src/core/public/core_app/status/components/__snapshots__/status_table.test.tsx.snap index c30637ed85a57..1966b609894a0 100644 --- a/src/core/public/core_app/status/components/__snapshots__/status_table.test.tsx.snap +++ b/src/core/public/core_app/status/components/__snapshots__/status_table.test.tsx.snap @@ -1,31 +1,54 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`StatusTable renders when statuses is provided 1`] = ` - + + , "render": [Function], + "width": "40px", }, ] } data-test-subj="statusBreakdown" + isExpandable={true} + itemId={[Function]} + itemIdToExpandedRowMap={Object {}} items={ Array [ Object { "id": "plugin:1", + "original": Object { + "level": "available", + "summary": "Ready", + }, "state": Object { "id": "available", "message": "Ready", @@ -35,14 +58,16 @@ exports[`StatusTable renders when statuses is provided 1`] = ` }, ] } - noItemsMessage={ - - } responsive={true} rowProps={[Function]} + sorting={ + Object { + "sort": Object { + "direction": "asc", + "field": "state", + }, + } + } tableLayout="fixed" /> `; diff --git a/src/core/public/core_app/status/components/index.ts b/src/core/public/core_app/status/components/index.ts index fc491c7e71b39..c305ebf24b041 100644 --- a/src/core/public/core_app/status/components/index.ts +++ b/src/core/public/core_app/status/components/index.ts @@ -9,3 +9,5 @@ export { MetricTile, MetricTiles } from './metric_tiles'; export { ServerStatus } from './server_status'; export { StatusTable } from './status_table'; +export { StatusSection } from './status_section'; +export { VersionHeader } from './version_header'; diff --git a/src/core/public/core_app/status/components/server_status.test.tsx b/src/core/public/core_app/status/components/server_status.test.tsx index e4fa84d317dd6..13e6a36a65cfd 100644 --- a/src/core/public/core_app/status/components/server_status.test.tsx +++ b/src/core/public/core_app/status/components/server_status.test.tsx @@ -9,9 +9,9 @@ import React from 'react'; import { mount } from 'enzyme'; import { ServerStatus } from './server_status'; -import { FormattedStatus } from '../lib'; +import { StatusState } from '../lib'; -const getStatus = (parts: Partial = {}): FormattedStatus['state'] => ({ +const getStatus = (parts: Partial = {}): StatusState => ({ id: 'available', title: 'Green', uiColor: 'success', @@ -27,6 +27,16 @@ describe('ServerStatus', () => { expect(component.find('EuiBadge')).toMatchSnapshot(); }); + it('renders correctly for yellow state', () => { + const status = getStatus({ + id: 'degraded', + title: 'Yellow', + }); + const component = mount(); + expect(component.find('EuiTitle').text()).toMatchInlineSnapshot(`"Kibana status is Yellow"`); + expect(component.find('EuiBadge')).toMatchSnapshot(); + }); + it('renders correctly for red state', () => { const status = getStatus({ id: 'unavailable', diff --git a/src/core/public/core_app/status/components/server_status.tsx b/src/core/public/core_app/status/components/server_status.tsx index 01dabdfd484fe..1147e21d17737 100644 --- a/src/core/public/core_app/status/components/server_status.tsx +++ b/src/core/public/core_app/status/components/server_status.tsx @@ -7,13 +7,14 @@ */ import React, { FunctionComponent } from 'react'; -import { EuiText, EuiFlexGroup, EuiFlexItem, EuiTitle, EuiBadge } from '@elastic/eui'; +import { EuiText, EuiFlexGroup, EuiFlexItem, EuiTitle } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import type { FormattedStatus } from '../lib'; +import type { StatusState } from '../lib'; +import { StatusBadge } from './status_badge'; interface ServerStateProps { name: string; - serverState: FormattedStatus['state']; + serverState: StatusState; } export const ServerStatus: FunctionComponent = ({ name, serverState }) => ( @@ -26,13 +27,7 @@ export const ServerStatus: FunctionComponent = ({ name, server defaultMessage="Kibana status is {kibanaStatus}" values={{ kibanaStatus: ( - - {serverState.title} - + ), }} /> diff --git a/src/core/public/core_app/status/components/status_badge.test.tsx b/src/core/public/core_app/status/components/status_badge.test.tsx new file mode 100644 index 0000000000000..b0870e51d98d1 --- /dev/null +++ b/src/core/public/core_app/status/components/status_badge.test.tsx @@ -0,0 +1,57 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React from 'react'; +import { shallowWithIntl } from '@kbn/test/jest'; +import { StatusBadge, StatusWithoutMessage } from './status_badge'; + +const getStatus = (parts: Partial = {}): StatusWithoutMessage => ({ + id: 'available', + title: 'Green', + uiColor: 'secondary', + ...parts, +}); + +describe('StatusBadge', () => { + it('propagates the correct properties to `EuiBadge`', () => { + const status = getStatus(); + + const component = shallowWithIntl(); + + expect(component).toMatchInlineSnapshot(` + + Green + + `); + }); + + it('propagates `data-test-subj` if provided', () => { + const status = getStatus({ + id: 'critical', + title: 'Red', + uiColor: 'danger', + }); + + const component = shallowWithIntl( + + ); + + expect(component).toMatchInlineSnapshot(` + + Red + + `); + }); +}); diff --git a/src/core/public/core_app/status/components/status_badge.tsx b/src/core/public/core_app/status/components/status_badge.tsx new file mode 100644 index 0000000000000..b46451a99a38c --- /dev/null +++ b/src/core/public/core_app/status/components/status_badge.tsx @@ -0,0 +1,30 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React, { FC } from 'react'; +import { EuiBadge } from '@elastic/eui'; +import type { StatusState } from '../lib'; + +export type StatusWithoutMessage = Omit; + +interface StatusBadgeProps { + status: StatusWithoutMessage; + 'data-test-subj'?: string; +} + +export const StatusBadge: FC = (props) => { + return ( + + {props.status.title} + + ); +}; diff --git a/src/core/public/core_app/status/components/status_expanded_row.tsx b/src/core/public/core_app/status/components/status_expanded_row.tsx new file mode 100644 index 0000000000000..b85ca94a5efe9 --- /dev/null +++ b/src/core/public/core_app/status/components/status_expanded_row.tsx @@ -0,0 +1,36 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React, { FC, useMemo } from 'react'; +import { EuiCodeBlock, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import type { FormattedStatus } from '../lib'; + +interface StatusExpandedRowProps { + status: FormattedStatus; +} + +export const StatusExpandedRow: FC = ({ status }) => { + const { original } = status; + const statusAsString = useMemo(() => JSON.stringify(original, null, 2), [original]); + + return ( + + + + {statusAsString} + + + + ); +}; diff --git a/src/core/public/core_app/status/components/status_section.tsx b/src/core/public/core_app/status/components/status_section.tsx new file mode 100644 index 0000000000000..5cfa0e34971a6 --- /dev/null +++ b/src/core/public/core_app/status/components/status_section.tsx @@ -0,0 +1,40 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React, { FC, useMemo } from 'react'; +import { EuiFlexGroup, EuiFlexItem, EuiPageContent, EuiSpacer, EuiTitle } from '@elastic/eui'; +import { StatusTable } from './status_table'; +import { FormattedStatus, getHighestStatus } from '../lib'; +import { StatusBadge } from './status_badge'; + +interface StatusSectionProps { + id: string; + title: string; + statuses: FormattedStatus[]; +} + +export const StatusSection: FC = ({ id, title, statuses }) => { + const highestStatus = useMemo(() => getHighestStatus(statuses), [statuses]); + + return ( + + + + +

    {title}

    +
    +
    + + + +
    + + +
    + ); +}; diff --git a/src/core/public/core_app/status/components/status_table.test.tsx b/src/core/public/core_app/status/components/status_table.test.tsx index 3cb5d1126ef31..1aa39325d808e 100644 --- a/src/core/public/core_app/status/components/status_table.test.tsx +++ b/src/core/public/core_app/status/components/status_table.test.tsx @@ -8,6 +8,7 @@ import React from 'react'; import { shallow } from 'enzyme'; +import { ServiceStatus } from '../../../../types/status'; import { StatusTable } from './status_table'; const state = { @@ -17,13 +18,21 @@ const state = { title: 'green', }; +const createServiceStatus = (parts: Partial = {}): ServiceStatus => ({ + level: 'available', + summary: 'Ready', + ...parts, +}); + describe('StatusTable', () => { it('renders when statuses is provided', () => { - const component = shallow(); + const component = shallow( + + ); expect(component).toMatchSnapshot(); }); - it('renders when statuses is not provided', () => { + it('renders empty when statuses is not provided', () => { const component = shallow(); expect(component.isEmptyRender()).toBe(true); }); diff --git a/src/core/public/core_app/status/components/status_table.tsx b/src/core/public/core_app/status/components/status_table.tsx index 07a25d99a326b..755469145e01b 100644 --- a/src/core/public/core_app/status/components/status_table.tsx +++ b/src/core/public/core_app/status/components/status_table.tsx @@ -6,50 +6,115 @@ * Side Public License, v 1. */ -import React, { FunctionComponent } from 'react'; -import { EuiBasicTable, EuiIcon } from '@elastic/eui'; +import React, { FunctionComponent, ReactElement, useState } from 'react'; +import { + EuiInMemoryTable, + EuiIcon, + EuiButtonIcon, + EuiBasicTableColumn, + EuiScreenReaderOnly, +} from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import type { FormattedStatus } from '../lib'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { FormattedStatus, getLevelSortValue } from '../lib'; +import { StatusExpandedRow } from './status_expanded_row'; interface StatusTableProps { statuses?: FormattedStatus[]; } -const tableColumns = [ - { - field: 'state', - name: '', - render: (state: FormattedStatus['state']) => ( - - ), - width: '32px', - }, - { - field: 'id', - name: i18n.translate('core.statusPage.statusTable.columns.idHeader', { - defaultMessage: 'ID', - }), - }, - { - field: 'state', - name: i18n.translate('core.statusPage.statusTable.columns.statusHeader', { - defaultMessage: 'Status', - }), - render: (state: FormattedStatus['state']) => {state.message}, - }, -]; +const expandLabel = i18n.translate('core.statusPage.statusTable.columns.expandRow.expandLabel', { + defaultMessage: 'Expand', +}); + +const collapseLabel = i18n.translate( + 'core.statusPage.statusTable.columns.expandRow.collapseLabel', + { defaultMessage: 'Collapse' } +); export const StatusTable: FunctionComponent = ({ statuses }) => { + const [itemIdToExpandedRowMap, setItemIdToExpandedRowMap] = useState< + Record + >({}); if (!statuses) { return null; } + + const toggleDetails = (item: FormattedStatus) => { + const newRowMap = { ...itemIdToExpandedRowMap }; + if (itemIdToExpandedRowMap[item.id]) { + delete newRowMap[item.id]; + } else { + newRowMap[item.id] = ; + } + setItemIdToExpandedRowMap(newRowMap); + }; + + const tableColumns: Array> = [ + { + field: 'state', + name: i18n.translate('core.statusPage.statusTable.columns.statusHeader', { + defaultMessage: 'Status', + }), + render: (state: FormattedStatus['state']) => ( + + ), + width: '100px', + align: 'center' as const, + sortable: (row: FormattedStatus) => getLevelSortValue(row), + }, + { + field: 'id', + name: i18n.translate('core.statusPage.statusTable.columns.idHeader', { + defaultMessage: 'ID', + }), + sortable: true, + }, + { + field: 'state', + name: i18n.translate('core.statusPage.statusTable.columns.statusSummaryHeader', { + defaultMessage: 'Status summary', + }), + render: (state: FormattedStatus['state']) => {state.message}, + }, + { + name: ( + + + + ), + align: 'right', + width: '40px', + isExpander: true, + render: (item: FormattedStatus) => ( + toggleDetails(item)} + aria-label={itemIdToExpandedRowMap[item.id] ? collapseLabel : expandLabel} + iconType={itemIdToExpandedRowMap[item.id] ? 'arrowUp' : 'arrowDown'} + /> + ), + }, + ]; + return ( - + columns={tableColumns} + itemId={(item) => item.id} items={statuses} + isExpandable={true} + itemIdToExpandedRowMap={itemIdToExpandedRowMap} rowProps={({ state }) => ({ className: `status-table-row-${state.uiColor}`, })} + sorting={{ + sort: { + direction: 'asc', + field: 'state', + }, + }} data-test-subj="statusBreakdown" /> ); diff --git a/src/core/public/core_app/status/components/version_header.test.tsx b/src/core/public/core_app/status/components/version_header.test.tsx new file mode 100644 index 0000000000000..d51927f83550b --- /dev/null +++ b/src/core/public/core_app/status/components/version_header.test.tsx @@ -0,0 +1,46 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React from 'react'; +import { mountWithIntl, findTestSubject } from '@kbn/test/jest'; +import type { ServerVersion } from '../../../../types/status'; +import { VersionHeader } from './version_header'; + +const buildServerVersion = (parts: Partial = {}): ServerVersion => ({ + number: 'version_number', + build_hash: 'build_hash', + build_number: 9000, + build_snapshot: false, + ...parts, +}); + +describe('VersionHeader', () => { + it('displays the version', () => { + const version = buildServerVersion({ number: '8.42.13' }); + const component = mountWithIntl(); + + const versionNode = findTestSubject(component, 'statusBuildVersion'); + expect(versionNode.text()).toEqual('VERSION: 8.42.13'); + }); + + it('displays the build number', () => { + const version = buildServerVersion({ build_number: 42 }); + const component = mountWithIntl(); + + const buildNumberNode = findTestSubject(component, 'statusBuildNumber'); + expect(buildNumberNode.text()).toEqual('BUILD: 42'); + }); + + it('displays the build hash', () => { + const version = buildServerVersion({ build_hash: 'some_hash' }); + const component = mountWithIntl(); + + const buildHashNode = findTestSubject(component, 'statusBuildHash'); + expect(buildHashNode.text()).toEqual('COMMIT: some_hash'); + }); +}); diff --git a/src/core/public/core_app/status/components/version_header.tsx b/src/core/public/core_app/status/components/version_header.tsx new file mode 100644 index 0000000000000..cd19dbc205615 --- /dev/null +++ b/src/core/public/core_app/status/components/version_header.tsx @@ -0,0 +1,65 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React, { FC } from 'react'; +import { EuiFlexGroup, EuiFlexItem, EuiPageContent, EuiText } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; +import type { ServerVersion } from '../../../../types/status'; + +interface VersionHeaderProps { + version: ServerVersion; +} + +export const VersionHeader: FC = ({ version }) => { + const { build_hash: buildHash, build_number: buildNumber, number } = version; + return ( + + + + +

    + {number}, + }} + /> +

    +
    +
    + + +

    + {buildNumber}, + }} + /> +

    +
    +
    + + +

    + {buildHash}, + }} + /> +

    +
    +
    +
    +
    + ); +}; diff --git a/src/core/public/core_app/status/lib/index.ts b/src/core/public/core_app/status/lib/index.ts index c3434e07319b0..305e235c21e07 100644 --- a/src/core/public/core_app/status/lib/index.ts +++ b/src/core/public/core_app/status/lib/index.ts @@ -9,4 +9,5 @@ export { formatNumber } from './format_number'; export { loadStatus } from './load_status'; export type { DataType } from './format_number'; -export type { Metric, FormattedStatus, ProcessedServerResponse } from './load_status'; +export type { Metric, FormattedStatus, ProcessedServerResponse, StatusState } from './load_status'; +export { getHighestStatus, groupByLevel, getLevelSortValue, orderedLevels } from './status_level'; diff --git a/src/core/public/core_app/status/lib/load_status.test.ts b/src/core/public/core_app/status/lib/load_status.test.ts index b6e7ba9b91e97..555e793b41aa5 100644 --- a/src/core/public/core_app/status/lib/load_status.test.ts +++ b/src/core/public/core_app/status/lib/load_status.test.ts @@ -37,11 +37,11 @@ const mockedResponse: StatusResponse = { }, }, plugins: { - '1': { + plugin1: { level: 'available', summary: 'Ready', }, - '2': { + plugin2: { level: 'degraded', summary: 'Something is weird', }, @@ -165,39 +165,50 @@ describe('response processing', () => { expect(notifications.toasts.addDanger).toHaveBeenCalledTimes(1); }); - test('includes the plugin statuses', async () => { + test('includes core statuses', async () => { const data = await loadStatus({ http, notifications }); - expect(data.statuses).toEqual([ + expect(data.coreStatus).toEqual([ { - id: 'core:elasticsearch', + id: 'elasticsearch', state: { id: 'available', title: 'Green', message: 'Elasticsearch is available', uiColor: 'success', }, + original: mockedResponse.status.core.elasticsearch, }, { - id: 'core:savedObjects', + id: 'savedObjects', state: { id: 'available', title: 'Green', message: 'SavedObjects service has completed migrations and is available', uiColor: 'success', }, + original: mockedResponse.status.core.savedObjects, }, + ]); + }); + + test('includes the plugin statuses', async () => { + const data = await loadStatus({ http, notifications }); + + expect(data.pluginStatus).toEqual([ { - id: 'plugin:1', + id: 'plugin1', state: { id: 'available', title: 'Green', message: 'Ready', uiColor: 'success' }, + original: mockedResponse.status.plugins.plugin1, }, { - id: 'plugin:2', + id: 'plugin2', state: { id: 'degraded', title: 'Yellow', message: 'Something is weird', uiColor: 'warning', }, + original: mockedResponse.status.plugins.plugin2, }, ]); }); diff --git a/src/core/public/core_app/status/lib/load_status.ts b/src/core/public/core_app/status/lib/load_status.ts index 0baa67d4e793c..31f20bf5c4edf 100644 --- a/src/core/public/core_app/status/lib/load_status.ts +++ b/src/core/public/core_app/status/lib/load_status.ts @@ -21,12 +21,15 @@ export interface Metric { export interface FormattedStatus { id: string; - state: { - id: ServiceStatusLevel; - title: string; - message: string; - uiColor: string; - }; + state: StatusState; + original: ServiceStatus; +} + +export interface StatusState { + id: ServiceStatusLevel; + title: string; + message: string; + uiColor: string; } interface StatusUIAttributes { @@ -96,6 +99,7 @@ function formatStatus(id: string, status: ServiceStatus): FormattedStatus { return { id, + original: status, state: { id: status.level, message: status.summary, @@ -105,7 +109,7 @@ function formatStatus(id: string, status: ServiceStatus): FormattedStatus { }; } -const STATUS_LEVEL_UI_ATTRS: Record = { +export const STATUS_LEVEL_UI_ATTRS: Record = { critical: { title: i18n.translate('core.status.redTitle', { defaultMessage: 'Red', @@ -178,14 +182,13 @@ export async function loadStatus({ return { name: response.name, version: response.version, - statuses: [ - ...Object.entries(response.status.core).map(([serviceName, status]) => - formatStatus(`core:${serviceName}`, status) - ), - ...Object.entries(response.status.plugins).map(([pluginName, status]) => - formatStatus(`plugin:${pluginName}`, status) - ), - ], + coreStatus: Object.entries(response.status.core).map(([serviceName, status]) => + formatStatus(serviceName, status) + ), + pluginStatus: Object.entries(response.status.plugins).map(([pluginName, status]) => + formatStatus(pluginName, status) + ), + serverState: formatStatus('overall', response.status.overall).state, metrics: formatMetrics(response), }; diff --git a/src/core/public/core_app/status/lib/status_level.test.ts b/src/core/public/core_app/status/lib/status_level.test.ts new file mode 100644 index 0000000000000..44322748992a0 --- /dev/null +++ b/src/core/public/core_app/status/lib/status_level.test.ts @@ -0,0 +1,122 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { ServiceStatus } from '../../../../types/status'; +import { getLevelSortValue, groupByLevel, getHighestStatus } from './status_level'; +import { FormattedStatus, StatusState } from './load_status'; + +type CreateStatusInput = Partial> & { + state?: Partial; +}; + +const dummyStatus: ServiceStatus = { + level: 'available', + summary: 'not used in this logic', +}; + +const createFormattedStatus = (parts: CreateStatusInput = {}): FormattedStatus => ({ + original: dummyStatus, + id: 'id', + ...parts, + state: { + id: 'available', + title: 'Green', + message: 'alright', + uiColor: 'primary', + ...parts.state, + }, +}); + +describe('getLevelSortValue', () => { + it('returns the correct value for `critical` state', () => { + expect(getLevelSortValue(createFormattedStatus({ state: { id: 'critical' } }))).toEqual(0); + }); + + it('returns the correct value for `unavailable` state', () => { + expect(getLevelSortValue(createFormattedStatus({ state: { id: 'unavailable' } }))).toEqual(1); + }); + + it('returns the correct value for `degraded` state', () => { + expect(getLevelSortValue(createFormattedStatus({ state: { id: 'degraded' } }))).toEqual(2); + }); + + it('returns the correct value for `available` state', () => { + expect(getLevelSortValue(createFormattedStatus({ state: { id: 'available' } }))).toEqual(3); + }); +}); + +describe('groupByLevel', () => { + it('groups statuses by their level', () => { + const result = groupByLevel([ + createFormattedStatus({ + id: 'available-1', + state: { id: 'available', title: 'green', uiColor: '#00FF00' }, + }), + createFormattedStatus({ + id: 'critical-1', + state: { id: 'critical', title: 'red', uiColor: '#FF0000' }, + }), + createFormattedStatus({ + id: 'degraded-1', + state: { id: 'degraded', title: 'yellow', uiColor: '#FFFF00' }, + }), + createFormattedStatus({ + id: 'critical-2', + state: { id: 'critical', title: 'red', uiColor: '#FF0000' }, + }), + ]); + + expect(result.size).toEqual(3); + expect(result.get('available')!.map((e) => e.id)).toEqual(['available-1']); + expect(result.get('degraded')!.map((e) => e.id)).toEqual(['degraded-1']); + expect(result.get('critical')!.map((e) => e.id)).toEqual(['critical-1', 'critical-2']); + }); + + it('returns an empty map when input list is empty', () => { + const result = groupByLevel([]); + expect(result.size).toEqual(0); + }); +}); + +describe('getHighestStatus', () => { + it('returns the values from the highest status', () => { + expect( + getHighestStatus([ + createFormattedStatus({ state: { id: 'available', title: 'green', uiColor: '#00FF00' } }), + createFormattedStatus({ state: { id: 'critical', title: 'red', uiColor: '#FF0000' } }), + createFormattedStatus({ state: { id: 'degraded', title: 'yellow', uiColor: '#FFFF00' } }), + ]) + ).toEqual({ + id: 'critical', + title: 'red', + uiColor: '#FF0000', + }); + }); + + it('handles multiple statuses with the same level', () => { + expect( + getHighestStatus([ + createFormattedStatus({ state: { id: 'degraded', title: 'yellow', uiColor: '#FF0000' } }), + createFormattedStatus({ state: { id: 'available', title: 'green', uiColor: '#00FF00' } }), + createFormattedStatus({ state: { id: 'degraded', title: 'yellow', uiColor: '#FFFF00' } }), + ]) + ).toEqual({ + id: 'degraded', + title: 'yellow', + uiColor: '#FF0000', + }); + }); + + it('returns the default values for `available` when the input list is empty', () => { + expect(getHighestStatus([])).toEqual({ + id: 'available', + title: 'Green', + uiColor: 'success', + }); + }); +}); diff --git a/src/core/public/core_app/status/lib/status_level.ts b/src/core/public/core_app/status/lib/status_level.ts new file mode 100644 index 0000000000000..f0c3be949057f --- /dev/null +++ b/src/core/public/core_app/status/lib/status_level.ts @@ -0,0 +1,44 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { ServiceStatusLevel } from '../../../../types/status'; +import { FormattedStatus, StatusState, STATUS_LEVEL_UI_ATTRS } from './load_status'; + +export const orderedLevels: ServiceStatusLevel[] = [ + 'critical', + 'unavailable', + 'degraded', + 'available', +]; + +export const groupByLevel = (statuses: FormattedStatus[]) => { + return statuses.reduce((map, status) => { + const existing = map.get(status.state.id) ?? []; + map.set(status.state.id, [...existing, status]); + return map; + }, new Map()); +}; + +export const getHighestStatus = (statuses: FormattedStatus[]): Omit => { + const grouped = groupByLevel(statuses); + for (const level of orderedLevels) { + if (grouped.has(level) && grouped.get(level)!.length) { + const { message, ...status } = grouped.get(level)![0].state; + return status; + } + } + return { + id: 'available', + title: STATUS_LEVEL_UI_ATTRS.available.title, + uiColor: STATUS_LEVEL_UI_ATTRS.available.uiColor, + }; +}; + +export const getLevelSortValue = (status: FormattedStatus) => { + return orderedLevels.indexOf(status.state.id); +}; diff --git a/src/core/public/core_app/status/status_app.tsx b/src/core/public/core_app/status/status_app.tsx index 7d7e30319fb2f..7ec1518719874 100644 --- a/src/core/public/core_app/status/status_app.tsx +++ b/src/core/public/core_app/status/status_app.tsx @@ -7,22 +7,13 @@ */ import React, { Component } from 'react'; -import { - EuiLoadingSpinner, - EuiText, - EuiTitle, - EuiPage, - EuiPageBody, - EuiPageContent, - EuiSpacer, - EuiFlexGroup, - EuiFlexItem, -} from '@elastic/eui'; +import { EuiLoadingSpinner, EuiText, EuiPage, EuiPageBody, EuiSpacer } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; +import { i18n } from '@kbn/i18n'; import { HttpSetup } from '../../http'; import { NotificationsSetup } from '../../notifications'; import { loadStatus, ProcessedServerResponse } from './lib'; -import { MetricTiles, StatusTable, ServerStatus } from './components'; +import { MetricTiles, ServerStatus, StatusSection, VersionHeader } from './components'; interface StatusAppProps { http: HttpSetup; @@ -74,69 +65,36 @@ export class StatusApp extends Component { ); } - // Extract the items needed to render each component - const { metrics, statuses, serverState, name, version } = data!; - const { build_hash: buildHash, build_number: buildNumber } = version; + const { metrics, coreStatus, pluginStatus, serverState, name, version } = data!; return ( + + - - - - - -

    - -

    -
    -
    - - - - -

    - {buildNumber}, - }} - /> -

    -
    -
    - - -

    - {buildHash}, - }} - /> -

    -
    -
    -
    -
    -
    - - + + - -
    +
    ); diff --git a/src/core/types/status.ts b/src/core/types/status.ts index 58c954fb70050..ad5c5b13c9a3a 100644 --- a/src/core/types/status.ts +++ b/src/core/types/status.ts @@ -28,9 +28,7 @@ export interface ServiceStatus extends Omit { * but overwriting the `level` to its stringified version. */ export type CoreStatus = { - [ServiceName in keyof CoreStatusFromServer]: Omit & { - level: ServiceStatusLevel; - }; + [ServiceName in keyof CoreStatusFromServer]: ServiceStatus; }; export type ServerMetrics = Omit & { diff --git a/test/functional/apps/status_page/index.ts b/test/functional/apps/status_page/index.ts index 08693372cc6eb..99f32fa5da4c7 100644 --- a/test/functional/apps/status_page/index.ts +++ b/test/functional/apps/status_page/index.ts @@ -20,12 +20,19 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await PageObjects.common.navigateToApp('status_page'); }); - it('should show the build hash and number', async () => { + it('should show the build version', async () => { + const buildVersionText = await testSubjects.getVisibleText('statusBuildVersion'); + expect(buildVersionText).to.contain('VERSION: '); + }); + + it('should show the build number', async () => { const buildNumberText = await testSubjects.getVisibleText('statusBuildNumber'); - expect(buildNumberText).to.contain('BUILD '); + expect(buildNumberText).to.contain('BUILD: '); + }); + it('should show the build hash', async () => { const hashText = await testSubjects.getVisibleText('statusBuildHash'); - expect(hashText).to.contain('COMMIT '); + expect(hashText).to.contain('COMMIT: '); }); it('should display the server metrics', async () => { From ad6b687dadd2d98c8cd89222cdd9134edbbde1af Mon Sep 17 00:00:00 2001 From: Cristina Amico Date: Fri, 19 Nov 2021 11:29:02 +0100 Subject: [PATCH 138/148] [Fleet] Split package policy Upgrade endpoint (#118854) * [Fleet] Split package policy Upgrade endpoint * Add openapi specs --- .../plugins/fleet/common/constants/routes.ts | 1 + .../plugins/fleet/common/openapi/bundled.json | 243 +++++++++++++++++- .../plugins/fleet/common/openapi/bundled.yaml | 180 +++++++++++-- .../components/schemas/upgrade_diff.yaml | 3 + .../fleet/common/openapi/entrypoint.yaml | 4 + .../paths/package_policies@upgrade.yaml | 34 +++ .../package_policies@upgrade_dryrun.yaml | 32 +++ .../plugins/fleet/common/services/routes.ts | 4 + .../hooks/use_request/package_policy.ts | 6 +- .../server/routes/package_policy/handlers.ts | 85 +++--- .../server/routes/package_policy/index.ts | 12 + .../fleet/server/services/package_policy.ts | 1 - .../server/types/rest_spec/package_policy.ts | 7 +- .../apis/package_policy/upgrade.ts | 52 +--- 14 files changed, 559 insertions(+), 105 deletions(-) create mode 100644 x-pack/plugins/fleet/common/openapi/components/schemas/upgrade_diff.yaml create mode 100644 x-pack/plugins/fleet/common/openapi/paths/package_policies@upgrade.yaml create mode 100644 x-pack/plugins/fleet/common/openapi/paths/package_policies@upgrade_dryrun.yaml diff --git a/x-pack/plugins/fleet/common/constants/routes.ts b/x-pack/plugins/fleet/common/constants/routes.ts index 235a1c5bd85e5..9fc20bbf38eb7 100644 --- a/x-pack/plugins/fleet/common/constants/routes.ts +++ b/x-pack/plugins/fleet/common/constants/routes.ts @@ -46,6 +46,7 @@ export const PACKAGE_POLICY_API_ROUTES = { UPDATE_PATTERN: `${PACKAGE_POLICY_API_ROOT}/{packagePolicyId}`, DELETE_PATTERN: `${PACKAGE_POLICY_API_ROOT}/delete`, UPGRADE_PATTERN: `${PACKAGE_POLICY_API_ROOT}/upgrade`, + DRYRUN_PATTERN: `${PACKAGE_POLICY_API_ROOT}/upgrade/dryrun`, }; // Agent policy API routes diff --git a/x-pack/plugins/fleet/common/openapi/bundled.json b/x-pack/plugins/fleet/common/openapi/bundled.json index a9e92e3fc293a..1e17c693e01b9 100644 --- a/x-pack/plugins/fleet/common/openapi/bundled.json +++ b/x-pack/plugins/fleet/common/openapi/bundled.json @@ -1603,6 +1603,115 @@ ] } }, + "/package_policies/upgrade": { + "post": { + "summary": "Package policy - Upgrade", + "operationId": "upgrade-package-policy", + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "packagePolicyIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "packagePolicyIds" + ] + } + } + } + }, + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "success": { + "type": "boolean" + } + }, + "required": [ + "id", + "success" + ] + } + } + } + } + } + } + } + }, + "/package_policies/upgrade/dryrun": { + "post": { + "summary": "Package policy - Upgrade Dry run", + "operationId": "upgrade-package-policy", + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "packagePolicyIds": { + "type": "array", + "items": { + "type": "string" + } + }, + "packageVersion": { + "type": "string" + } + }, + "required": [ + "packagePolicyIds" + ] + } + } + } + }, + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "hasErrors": { + "type": "boolean" + }, + "diff": { + "schema": null, + "$ref": "#/components/schemas/upgrade_diff" + }, + "required": [ + "hasErrors" + ] + } + } + } + } + } + } + } + }, "/package_policies/{packagePolicyId}": { "get": { "summary": "Package policy - Info", @@ -1716,6 +1825,74 @@ } }, "operationId": "get-outputs" + }, + "post": { + "summary": "Outputs", + "description": "Create a new output", + "tags": [], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "item": { + "$ref": "#/components/schemas/output" + } + } + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "elasticsearch" + ] + }, + "is_default": { + "type": "boolean" + }, + "is_default_monitoring": { + "type": "boolean" + }, + "hosts": { + "type": "array", + "items": { + "type": "string" + } + }, + "ca_sha256": { + "type": "string" + }, + "config_yaml": { + "type": "string" + } + }, + "required": [ + "name", + "type" + ] + } + } + } + }, + "operationId": "post-outputs" } }, "/outputs/{outputId}": { @@ -1754,6 +1931,35 @@ "required": true } ], + "delete": { + "summary": "Output - Delete", + "operationId": "delete-output", + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "id": { + "type": "string" + } + }, + "required": [ + "id" + ] + } + } + } + } + }, + "parameters": [ + { + "$ref": "#/components/parameters/kbn_xsrf" + } + ] + }, "put": { "summary": "Output - Update", "operationId": "update-output", @@ -1763,19 +1969,38 @@ "schema": { "type": "object", "properties": { - "hosts": { + "name": { "type": "string" }, + "type": { + "type": "string", + "enum": [ + "elasticsearch" + ] + }, + "is_default": { + "type": "boolean" + }, + "is_default_monitoring": { + "type": "boolean" + }, + "hosts": { + "type": "array", + "items": { + "type": "string" + } + }, "ca_sha256": { "type": "string" }, - "config": { - "type": "object" - }, "config_yaml": { "type": "string" } - } + }, + "required": [ + "name", + "type" + ] } } } @@ -2626,6 +2851,11 @@ "created_at" ] }, + "upgrade_diff": { + "title": "Package policy Upgrade dryrun", + "type": "array", + "items": {} + }, "update_package_policy": { "title": "Update package policy", "allOf": [ @@ -2652,6 +2882,9 @@ "is_default": { "type": "boolean" }, + "is_default_monitoring": { + "type": "boolean" + }, "name": { "type": "string" }, diff --git a/x-pack/plugins/fleet/common/openapi/bundled.yaml b/x-pack/plugins/fleet/common/openapi/bundled.yaml index b997e31f4bb8d..1d7f1cb9ccf1f 100644 --- a/x-pack/plugins/fleet/common/openapi/bundled.yaml +++ b/x-pack/plugins/fleet/common/openapi/bundled.yaml @@ -8,9 +8,9 @@ info: name: Fleet Team license: name: Elastic License 2.0 - url: 'https://www.elastic.co/licensing/elastic-license' + url: https://www.elastic.co/licensing/elastic-license servers: - - url: 'http://localhost:5601/api/fleet' + - url: http://localhost:5601/api/fleet description: local paths: /setup: @@ -99,7 +99,7 @@ paths: $ref: '#/components/schemas/search_result' operationId: list-all-packages parameters: [] - '/epm/packages/{pkgkey}': + /epm/packages/{pkgkey}: get: summary: Packages - Info tags: [] @@ -361,7 +361,7 @@ paths: application/json: schema: $ref: '#/components/schemas/bulk_upgrade_agents' - '/agents/{agentId}': + /agents/{agentId}: parameters: - schema: type: string @@ -422,7 +422,7 @@ paths: operationId: delete-agent parameters: - $ref: '#/components/parameters/kbn_xsrf' - '/agents/{agentId}/reassign': + /agents/{agentId}/reassign: parameters: - schema: type: string @@ -453,7 +453,7 @@ paths: type: string required: - policy_id - '/agents/{agentId}/unenroll': + /agents/{agentId}/unenroll: parameters: - schema: type: string @@ -498,7 +498,7 @@ paths: type: boolean force: type: boolean - '/agents/{agentId}/upgrade': + /agents/{agentId}/upgrade: parameters: - schema: type: string @@ -666,7 +666,7 @@ paths: security: [] parameters: - $ref: '#/components/parameters/kbn_xsrf' - '/agent_policies/{agentPolicyId}': + /agent_policies/{agentPolicyId}: parameters: - schema: type: string @@ -714,7 +714,7 @@ paths: $ref: '#/components/schemas/new_agent_policy' parameters: - $ref: '#/components/parameters/kbn_xsrf' - '/agent_policies/{agentPolicyId}/copy': + /agent_policies/{agentPolicyId}/copy: parameters: - schema: type: string @@ -832,7 +832,7 @@ paths: operationId: create-enrollment-api-keys parameters: - $ref: '#/components/parameters/kbn_xsrf' - '/enrollment-api-keys/{keyId}': + /enrollment-api-keys/{keyId}: parameters: - schema: type: string @@ -973,7 +973,75 @@ paths: - success parameters: - $ref: '#/components/parameters/kbn_xsrf' - '/package_policies/{packagePolicyId}': + /package_policies/upgrade: + post: + summary: Package policy - Upgrade + operationId: upgrade-package-policy + requestBody: + content: + application/json: + schema: + type: object + properties: + packagePolicyIds: + type: array + items: + type: string + required: + - packagePolicyIds + responses: + '200': + description: OK + content: + application/json: + schema: + type: array + items: + type: object + properties: + id: + type: string + name: + type: string + success: + type: boolean + required: + - id + - success + /package_policies/upgrade/dryrun: + post: + summary: Package policy - Upgrade Dry run + operationId: upgrade-package-policy + requestBody: + content: + application/json: + schema: + type: object + properties: + packagePolicyIds: + type: array + items: + type: string + packageVersion: + type: string + required: + - packagePolicyIds + responses: + '200': + description: OK + content: + application/json: + schema: + type: object + properties: + hasErrors: + type: boolean + diff: + schema: null + $ref: '#/components/schemas/upgrade_diff' + required: + - hasErrors + /package_policies/{packagePolicyId}: get: summary: Package policy - Info tags: [] @@ -1044,7 +1112,51 @@ paths: perPage: type: integer operationId: get-outputs - '/outputs/{outputId}': + post: + summary: Outputs + description: Create a new output + tags: [] + responses: + '200': + description: OK + content: + application/json: + schema: + type: object + properties: + item: + $ref: '#/components/schemas/output' + requestBody: + content: + application/json: + schema: + type: object + properties: + id: + type: string + name: + type: string + type: + type: string + enum: + - elasticsearch + is_default: + type: boolean + is_default_monitoring: + type: boolean + hosts: + type: array + items: + type: string + ca_sha256: + type: string + config_yaml: + type: string + required: + - name + - type + operationId: post-outputs + /outputs/{outputId}: get: summary: Output - Info tags: [] @@ -1067,6 +1179,23 @@ paths: name: outputId in: path required: true + delete: + summary: Output - Delete + operationId: delete-output + responses: + '200': + description: OK + content: + application/json: + schema: + type: object + properties: + id: + type: string + required: + - id + parameters: + - $ref: '#/components/parameters/kbn_xsrf' put: summary: Output - Update operationId: update-output @@ -1076,14 +1205,27 @@ paths: schema: type: object properties: - hosts: + name: + type: string + type: type: string + enum: + - elasticsearch + is_default: + type: boolean + is_default_monitoring: + type: boolean + hosts: + type: array + items: + type: string ca_sha256: type: string - config: - type: object config_yaml: type: string + required: + - name + - type responses: '200': description: OK @@ -1098,7 +1240,7 @@ paths: - item parameters: - $ref: '#/components/parameters/kbn_xsrf' - '/epm/packages/{pkgName}/stats': + /epm/packages/{pkgName}/stats: get: summary: Get stats for a package tags: [] @@ -1653,6 +1795,10 @@ components: - api_key - active - created_at + upgrade_diff: + title: Package policy Upgrade dryrun + type: array + items: {} update_package_policy: title: Update package policy allOf: @@ -1669,6 +1815,8 @@ components: type: string is_default: type: boolean + is_default_monitoring: + type: boolean name: type: string type: diff --git a/x-pack/plugins/fleet/common/openapi/components/schemas/upgrade_diff.yaml b/x-pack/plugins/fleet/common/openapi/components/schemas/upgrade_diff.yaml new file mode 100644 index 0000000000000..e3a2fc708dc62 --- /dev/null +++ b/x-pack/plugins/fleet/common/openapi/components/schemas/upgrade_diff.yaml @@ -0,0 +1,3 @@ +title: Package policy Upgrade dryrun +type: array +items: {} \ No newline at end of file diff --git a/x-pack/plugins/fleet/common/openapi/entrypoint.yaml b/x-pack/plugins/fleet/common/openapi/entrypoint.yaml index ad8ef1408ae6b..5495f2b3ccacf 100644 --- a/x-pack/plugins/fleet/common/openapi/entrypoint.yaml +++ b/x-pack/plugins/fleet/common/openapi/entrypoint.yaml @@ -62,6 +62,10 @@ paths: $ref: paths/package_policies.yaml /package_policies/delete: $ref: paths/package_policies@delete.yaml + /package_policies/upgrade: + $ref: paths/package_policies@upgrade.yaml + /package_policies/upgrade/dryrun: + $ref: paths/package_policies@upgrade_dryrun.yaml '/package_policies/{packagePolicyId}': $ref: 'paths/package_policies@{package_policy_id}.yaml' /outputs: diff --git a/x-pack/plugins/fleet/common/openapi/paths/package_policies@upgrade.yaml b/x-pack/plugins/fleet/common/openapi/paths/package_policies@upgrade.yaml new file mode 100644 index 0000000000000..92c316a498905 --- /dev/null +++ b/x-pack/plugins/fleet/common/openapi/paths/package_policies@upgrade.yaml @@ -0,0 +1,34 @@ +post: + summary: Package policy - Upgrade + operationId: upgrade-package-policy + requestBody: + content: + application/json: + schema: + type: object + properties: + packagePolicyIds: + type: array + items: + type: string + required: + - packagePolicyIds + responses: + '200': + description: OK + content: + application/json: + schema: + type: array + items: + type: object + properties: + id: + type: string + name: + type: string + success: + type: boolean + required: + - id + - success diff --git a/x-pack/plugins/fleet/common/openapi/paths/package_policies@upgrade_dryrun.yaml b/x-pack/plugins/fleet/common/openapi/paths/package_policies@upgrade_dryrun.yaml new file mode 100644 index 0000000000000..8b3b0c6147621 --- /dev/null +++ b/x-pack/plugins/fleet/common/openapi/paths/package_policies@upgrade_dryrun.yaml @@ -0,0 +1,32 @@ +post: + summary: Package policy - Upgrade Dry run + operationId: upgrade-package-policy + requestBody: + content: + application/json: + schema: + type: object + properties: + packagePolicyIds: + type: array + items: + type: string + packageVersion: + type: string + required: + - packagePolicyIds + responses: + '200': + description: OK + content: + application/json: + schema: + type: object + properties: + hasErrors: + type: boolean + diff: + schema: + $ref: ../components/schemas/upgrade_diff.yaml + required: + - hasErrors diff --git a/x-pack/plugins/fleet/common/services/routes.ts b/x-pack/plugins/fleet/common/services/routes.ts index 79ea19360c849..77445d88356ce 100644 --- a/x-pack/plugins/fleet/common/services/routes.ts +++ b/x-pack/plugins/fleet/common/services/routes.ts @@ -89,6 +89,10 @@ export const packagePolicyRouteService = { getUpgradePath: () => { return PACKAGE_POLICY_API_ROUTES.UPGRADE_PATTERN; }, + + getDryRunPath: () => { + return PACKAGE_POLICY_API_ROUTES.DRYRUN_PATTERN; + }, }; export const agentPolicyRouteService = { diff --git a/x-pack/plugins/fleet/public/hooks/use_request/package_policy.ts b/x-pack/plugins/fleet/public/hooks/use_request/package_policy.ts index 5aa36ba2e8268..6223c1a397104 100644 --- a/x-pack/plugins/fleet/public/hooks/use_request/package_policy.ts +++ b/x-pack/plugins/fleet/public/hooks/use_request/package_policy.ts @@ -77,9 +77,8 @@ export function sendUpgradePackagePolicyDryRun( packagePolicyIds: string[], packageVersion?: string ) { - const body: { packagePolicyIds: string[]; dryRun: boolean; packageVersion?: string } = { + const body: { packagePolicyIds: string[]; packageVersion?: string } = { packagePolicyIds, - dryRun: true, }; if (packageVersion) { @@ -87,7 +86,7 @@ export function sendUpgradePackagePolicyDryRun( } return sendRequest({ - path: packagePolicyRouteService.getUpgradePath(), + path: packagePolicyRouteService.getDryRunPath(), method: 'post', body: JSON.stringify(body), }); @@ -99,7 +98,6 @@ export function sendUpgradePackagePolicy(packagePolicyIds: string[]) { method: 'post', body: JSON.stringify({ packagePolicyIds, - dryRun: false, }), }); } diff --git a/x-pack/plugins/fleet/server/routes/package_policy/handlers.ts b/x-pack/plugins/fleet/server/routes/package_policy/handlers.ts index f61890f852798..330db62bbd604 100644 --- a/x-pack/plugins/fleet/server/routes/package_policy/handlers.ts +++ b/x-pack/plugins/fleet/server/routes/package_policy/handlers.ts @@ -18,6 +18,7 @@ import type { UpdatePackagePolicyRequestSchema, DeletePackagePoliciesRequestSchema, UpgradePackagePoliciesRequestSchema, + DryRunPackagePoliciesRequestSchema, } from '../../types'; import type { CreatePackagePolicyResponse, @@ -192,8 +193,6 @@ export const deletePackagePolicyHandler: RequestHandler< } }; -// TODO: Separate the upgrade and dry-run processes into separate endpoints, and address -// duplicate logic in error handling as part of https://github.com/elastic/kibana/issues/63123 export const upgradePackagePolicyHandler: RequestHandler< unknown, unknown, @@ -203,50 +202,56 @@ export const upgradePackagePolicyHandler: RequestHandler< const esClient = context.core.elasticsearch.client.asCurrentUser; const user = appContextService.getSecurity()?.authc.getCurrentUser(request) || undefined; try { - if (request.body.dryRun) { - const body: UpgradePackagePolicyDryRunResponse = []; - - for (const id of request.body.packagePolicyIds) { - const result = await packagePolicyService.getUpgradeDryRunDiff( - soClient, - id, - request.body.packageVersion - ); - body.push(result); - } - - const firstFatalError = body.find((item) => item.statusCode && item.statusCode !== 200); - - if (firstFatalError) { - return response.customError({ - statusCode: firstFatalError.statusCode!, - body: { message: firstFatalError.body!.message }, - }); - } + const body: UpgradePackagePolicyResponse = await packagePolicyService.upgrade( + soClient, + esClient, + request.body.packagePolicyIds, + { user } + ); - return response.ok({ - body, + const firstFatalError = body.find((item) => item.statusCode && item.statusCode !== 200); + + if (firstFatalError) { + return response.customError({ + statusCode: firstFatalError.statusCode!, + body: { message: firstFatalError.body!.message }, }); - } else { - const body: UpgradePackagePolicyResponse = await packagePolicyService.upgrade( - soClient, - esClient, - request.body.packagePolicyIds, - { user } - ); + } + return response.ok({ + body, + }); + } catch (error) { + return defaultIngestErrorHandler({ error, response }); + } +}; - const firstFatalError = body.find((item) => item.statusCode && item.statusCode !== 200); +export const dryRunUpgradePackagePolicyHandler: RequestHandler< + unknown, + unknown, + TypeOf +> = async (context, request, response) => { + const soClient = context.core.savedObjects.client; + try { + const body: UpgradePackagePolicyDryRunResponse = []; + const { packagePolicyIds, packageVersion } = request.body; - if (firstFatalError) { - return response.customError({ - statusCode: firstFatalError.statusCode!, - body: { message: firstFatalError.body!.message }, - }); - } - return response.ok({ - body, + for (const id of packagePolicyIds) { + const result = await packagePolicyService.getUpgradeDryRunDiff(soClient, id, packageVersion); + body.push(result); + } + + const firstFatalError = body.find((item) => item.statusCode && item.statusCode !== 200); + + if (firstFatalError) { + return response.customError({ + statusCode: firstFatalError.statusCode!, + body: { message: firstFatalError.body!.message }, }); } + + return response.ok({ + body, + }); } catch (error) { return defaultIngestErrorHandler({ error, response }); } diff --git a/x-pack/plugins/fleet/server/routes/package_policy/index.ts b/x-pack/plugins/fleet/server/routes/package_policy/index.ts index 9639f22e479f5..596532a17a8c8 100644 --- a/x-pack/plugins/fleet/server/routes/package_policy/index.ts +++ b/x-pack/plugins/fleet/server/routes/package_policy/index.ts @@ -15,6 +15,7 @@ import { UpdatePackagePolicyRequestSchema, DeletePackagePoliciesRequestSchema, UpgradePackagePoliciesRequestSchema, + DryRunPackagePoliciesRequestSchema, } from '../../types'; import { @@ -24,6 +25,7 @@ import { updatePackagePolicyHandler, deletePackagePolicyHandler, upgradePackagePolicyHandler, + dryRunUpgradePackagePolicyHandler, } from './handlers'; export const registerRoutes = (router: IRouter) => { @@ -86,4 +88,14 @@ export const registerRoutes = (router: IRouter) => { }, upgradePackagePolicyHandler ); + + // Upgrade - DryRun + router.post( + { + path: PACKAGE_POLICY_API_ROUTES.DRYRUN_PATTERN, + validate: DryRunPackagePoliciesRequestSchema, + options: { tags: [`access:${PLUGIN_ID}-all`] }, + }, + dryRunUpgradePackagePolicyHandler + ); }; diff --git a/x-pack/plugins/fleet/server/services/package_policy.ts b/x-pack/plugins/fleet/server/services/package_policy.ts index 856bf077b33d3..4a91979224017 100644 --- a/x-pack/plugins/fleet/server/services/package_policy.ts +++ b/x-pack/plugins/fleet/server/services/package_policy.ts @@ -428,7 +428,6 @@ class PackagePolicyService { currentVersion: currentVersion || 'unknown', newVersion: packagePolicy.package.version, status: 'success', - dryRun: false, eventType: 'package-policy-upgrade' as UpdateEventType, }; sendTelemetryEvents( diff --git a/x-pack/plugins/fleet/server/types/rest_spec/package_policy.ts b/x-pack/plugins/fleet/server/types/rest_spec/package_policy.ts index 4ccc57aca0ebd..34649602d2a02 100644 --- a/x-pack/plugins/fleet/server/types/rest_spec/package_policy.ts +++ b/x-pack/plugins/fleet/server/types/rest_spec/package_policy.ts @@ -40,7 +40,12 @@ export const DeletePackagePoliciesRequestSchema = { export const UpgradePackagePoliciesRequestSchema = { body: schema.object({ packagePolicyIds: schema.arrayOf(schema.string()), - dryRun: schema.maybe(schema.boolean()), + }), +}; + +export const DryRunPackagePoliciesRequestSchema = { + body: schema.object({ + packagePolicyIds: schema.arrayOf(schema.string()), packageVersion: schema.maybe(schema.string()), }), }; diff --git a/x-pack/test/fleet_api_integration/apis/package_policy/upgrade.ts b/x-pack/test/fleet_api_integration/apis/package_policy/upgrade.ts index 5a61d69ed8ba6..0747a452c5864 100644 --- a/x-pack/test/fleet_api_integration/apis/package_policy/upgrade.ts +++ b/x-pack/test/fleet_api_integration/apis/package_policy/upgrade.ts @@ -124,11 +124,10 @@ export default function (providerContext: FtrProviderContext) { describe('dry run', function () { it('returns a valid diff', async function () { const { body }: { body: UpgradePackagePolicyDryRunResponse } = await supertest - .post(`/api/fleet/package_policies/upgrade`) + .post(`/api/fleet/package_policies/upgrade/dryrun`) .set('kbn-xsrf', 'xxxx') .send({ packagePolicyIds: [packagePolicyId], - dryRun: true, packageVersion: '0.2.0-add-non-required-test-var', }) .expect(200); @@ -145,14 +144,12 @@ export default function (providerContext: FtrProviderContext) { }); describe('upgrade', function () { - it('should respond with an error when "dryRun: false" is provided', async function () { + it('should respond with an error', async function () { await supertest .post(`/api/fleet/package_policies/upgrade`) .set('kbn-xsrf', 'xxxx') .send({ packagePolicyIds: [packagePolicyId], - dryRun: false, - packageVersion: '0.2.0-add-non-required-test-var', }) .expect(400); }); @@ -234,11 +231,10 @@ export default function (providerContext: FtrProviderContext) { describe('dry run', function () { it('returns a valid diff', async function () { const { body }: { body: UpgradePackagePolicyDryRunResponse } = await supertest - .post(`/api/fleet/package_policies/upgrade`) + .post(`/api/fleet/package_policies/upgrade/dryrun`) .set('kbn-xsrf', 'xxxx') .send({ packagePolicyIds: [packagePolicyId], - dryRun: true, }) .expect(200); @@ -265,7 +261,6 @@ export default function (providerContext: FtrProviderContext) { .set('kbn-xsrf', 'xxxx') .send({ packagePolicyIds: [packagePolicyId], - dryRun: false, }) .expect(200); @@ -345,11 +340,10 @@ export default function (providerContext: FtrProviderContext) { describe('dry run', function () { it('returns a valid diff', async function () { const { body }: { body: UpgradePackagePolicyDryRunResponse } = await supertest - .post(`/api/fleet/package_policies/upgrade`) + .post(`/api/fleet/package_policies/upgrade/dryrun`) .set('kbn-xsrf', 'xxxx') .send({ packagePolicyIds: [packagePolicyId], - dryRun: true, }) .expect(200); @@ -371,7 +365,6 @@ export default function (providerContext: FtrProviderContext) { .set('kbn-xsrf', 'xxxx') .send({ packagePolicyIds: [packagePolicyId], - dryRun: false, }) .expect(200); @@ -455,11 +448,10 @@ export default function (providerContext: FtrProviderContext) { describe('dry run', function () { it('returns a valid diff', async function () { const { body }: { body: UpgradePackagePolicyDryRunResponse } = await supertest - .post(`/api/fleet/package_policies/upgrade`) + .post(`/api/fleet/package_policies/upgrade/dryrun`) .set('kbn-xsrf', 'xxxx') .send({ packagePolicyIds: [packagePolicyId], - dryRun: true, }) .expect(200); @@ -476,7 +468,6 @@ export default function (providerContext: FtrProviderContext) { .set('kbn-xsrf', 'xxxx') .send({ packagePolicyIds: [packagePolicyId], - dryRun: false, }) .expect(200); @@ -556,11 +547,10 @@ export default function (providerContext: FtrProviderContext) { describe('dry run', function () { it('returns a diff with errors', async function () { const { body }: { body: UpgradePackagePolicyDryRunResponse } = await supertest - .post(`/api/fleet/package_policies/upgrade`) + .post(`/api/fleet/package_policies/upgrade/dryrun`) .set('kbn-xsrf', 'xxxx') .send({ packagePolicyIds: [packagePolicyId], - dryRun: true, }) .expect(200); @@ -575,7 +565,6 @@ export default function (providerContext: FtrProviderContext) { .set('kbn-xsrf', 'xxxx') .send({ packagePolicyIds: [packagePolicyId], - dryRun: false, }) .expect(400); }); @@ -656,11 +645,10 @@ export default function (providerContext: FtrProviderContext) { describe('dry run', function () { it('returns a diff with errors', async function () { const { body }: { body: UpgradePackagePolicyDryRunResponse } = await supertest - .post(`/api/fleet/package_policies/upgrade`) + .post(`/api/fleet/package_policies/upgrade/dryrun`) .set('kbn-xsrf', 'xxxx') .send({ packagePolicyIds: [packagePolicyId], - dryRun: true, }) .expect(200); @@ -675,7 +663,6 @@ export default function (providerContext: FtrProviderContext) { .set('kbn-xsrf', 'xxxx') .send({ packagePolicyIds: [packagePolicyId], - dryRun: false, }) .expect(400); }); @@ -756,11 +743,10 @@ export default function (providerContext: FtrProviderContext) { describe('dry run', function () { it('returns a valid diff', async function () { const { body }: { body: UpgradePackagePolicyDryRunResponse } = await supertest - .post(`/api/fleet/package_policies/upgrade`) + .post(`/api/fleet/package_policies/upgrade/dryrun`) .set('kbn-xsrf', 'xxxx') .send({ packagePolicyIds: [packagePolicyId], - dryRun: true, }) .expect(200); @@ -775,7 +761,6 @@ export default function (providerContext: FtrProviderContext) { .set('kbn-xsrf', 'xxxx') .send({ packagePolicyIds: [packagePolicyId], - dryRun: false, }) .expect(200); @@ -884,11 +869,10 @@ export default function (providerContext: FtrProviderContext) { describe('dry run', function () { it('returns a valid diff', async function () { const { body }: { body: UpgradePackagePolicyDryRunResponse } = await supertest - .post(`/api/fleet/package_policies/upgrade`) + .post(`/api/fleet/package_policies/upgrade/dryrun`) .set('kbn-xsrf', 'xxxx') .send({ packagePolicyIds: [packagePolicyId], - dryRun: true, }) .expect(200); @@ -903,7 +887,6 @@ export default function (providerContext: FtrProviderContext) { .set('kbn-xsrf', 'xxxx') .send({ packagePolicyIds: [packagePolicyId], - dryRun: false, }) .expect(200); @@ -981,11 +964,10 @@ export default function (providerContext: FtrProviderContext) { describe('dry run', function () { it('returns a valid diff', async function () { const { body }: { body: UpgradePackagePolicyDryRunResponse } = await supertest - .post(`/api/fleet/package_policies/upgrade`) + .post(`/api/fleet/package_policies/upgrade/dryrun`) .set('kbn-xsrf', 'xxxx') .send({ packagePolicyIds: [packagePolicyId], - dryRun: true, }) .expect(200); @@ -1023,7 +1005,6 @@ export default function (providerContext: FtrProviderContext) { .set('kbn-xsrf', 'xxxx') .send({ packagePolicyIds: [packagePolicyId], - dryRun: false, }) .expect(200); @@ -1033,24 +1014,22 @@ export default function (providerContext: FtrProviderContext) { }); describe('when package policy is not found', function () { - it('should return an 200 with errors when "dryRun:true" is provided', async function () { + it('should return an 200 with errors when performing a dryrun', async function () { await supertest - .post(`/api/fleet/package_policies/upgrade`) + .post(`/api/fleet/package_policies/upgrade/dryrun`) .set('kbn-xsrf', 'xxxx') .send({ packagePolicyIds: ['xxxx', 'yyyy'], - dryRun: true, }) .expect(404); }); - it('should return a 200 with errors and "success:false" when "dryRun:false" is provided', async function () { + it('should return a 200 with errors and "success:false" when trying to upgrade', async function () { await supertest .post(`/api/fleet/package_policies/upgrade`) .set('kbn-xsrf', 'xxxx') .send({ packagePolicyIds: ['xxxx', 'yyyy'], - dryRun: false, }) .expect(404); }); @@ -1126,11 +1105,10 @@ export default function (providerContext: FtrProviderContext) { describe('dry run', function () { it('should respond with a bad request', async function () { await supertest - .post(`/api/fleet/package_policies/upgrade`) + .post(`/api/fleet/package_policies/upgrade/dryrun`) .set('kbn-xsrf', 'xxxx') .send({ packagePolicyIds: [packagePolicyId], - dryRun: true, packageVersion: '0.1.0', }) .expect(400); @@ -1144,8 +1122,6 @@ export default function (providerContext: FtrProviderContext) { .set('kbn-xsrf', 'xxxx') .send({ packagePolicyIds: [packagePolicyId], - dryRun: false, - packageVersion: '0.1.0', }) .expect(400); }); From 8398d53da4542c0673861d07ce565515318114ea Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Fri, 19 Nov 2021 13:00:35 +0100 Subject: [PATCH 139/148] [Lens] Get rid of giant union type (#118848) --- .../embedded_lens_example/public/app.tsx | 3 +- .../field_data_row/action_menu/lens_utils.ts | 27 +- x-pack/plugins/lens/public/index.ts | 4 +- .../datapanel.test.tsx | 5 +- .../bucket_nesting_editor.test.tsx | 6 +- .../dimension_panel/bucket_nesting_editor.tsx | 4 +- .../dimension_panel/dimension_editor.tsx | 4 +- .../dimension_panel/dimension_panel.test.tsx | 43 +- .../dimension_panel/dimension_panel.tsx | 6 +- .../dimensions_editor_helpers.tsx | 4 +- .../droppable/droppable.test.ts | 27 +- .../droppable/get_drop_props.ts | 18 +- .../dimension_panel/filtering.tsx | 4 +- .../dimension_panel/format_selector.tsx | 6 +- .../dimension_panel/reference_editor.test.tsx | 12 +- .../dimension_panel/time_scaling.tsx | 4 +- .../dimension_panel/time_shift.tsx | 4 +- .../indexpattern.test.ts | 64 ++- .../indexpattern_datasource/indexpattern.tsx | 9 +- .../indexpattern_suggestions.test.tsx | 58 +- .../indexpattern_suggestions.ts | 12 +- .../layerpanel.test.tsx | 3 +- .../indexpattern_datasource/loader.test.ts | 9 +- .../operations/definitions.test.ts | 7 +- .../definitions/calculations/utils.test.ts | 5 +- .../operations/definitions/column_types.ts | 5 + .../operations/definitions/count.tsx | 7 +- .../definitions/date_histogram.test.tsx | 10 +- .../operations/definitions/date_histogram.tsx | 509 +++++++++--------- .../definitions/filters/filters.test.tsx | 2 +- .../formula/editor/formula_help.tsx | 4 +- .../definitions/formula/formula.test.tsx | 27 +- .../definitions/formula/formula.tsx | 5 +- .../definitions/formula/generate.ts | 24 +- .../operations/definitions/formula/parse.ts | 16 +- .../operations/definitions/formula/util.ts | 10 +- .../definitions/formula/validation.ts | 32 +- .../operations/definitions/helpers.tsx | 36 +- .../operations/definitions/index.ts | 125 ++--- .../definitions/last_value.test.tsx | 11 +- .../definitions/percentile.test.tsx | 5 +- .../operations/definitions/percentile.tsx | 14 +- .../definitions/ranges/ranges.test.tsx | 21 +- .../operations/definitions/ranges/ranges.tsx | 2 +- .../definitions/static_value.test.tsx | 11 +- .../operations/definitions/static_value.tsx | 12 +- .../definitions/terms/terms.test.tsx | 23 +- .../operations/index.ts | 4 +- .../operations/layer_helpers.test.ts | 203 +++---- .../operations/layer_helpers.ts | 61 ++- .../operations/time_scale_utils.test.ts | 6 +- .../operations/time_scale_utils.ts | 4 +- .../time_shift_utils.tsx | 4 +- .../indexpattern_datasource/to_expression.ts | 73 +-- .../public/indexpattern_datasource/types.ts | 8 +- .../public/indexpattern_datasource/utils.tsx | 18 +- .../packs/pack_queries_status_table.tsx | 3 +- 57 files changed, 862 insertions(+), 781 deletions(-) diff --git a/x-pack/examples/embedded_lens_example/public/app.tsx b/x-pack/examples/embedded_lens_example/public/app.tsx index 3921b3a51dc45..f1b683f2430f7 100644 --- a/x-pack/examples/embedded_lens_example/public/app.tsx +++ b/x-pack/examples/embedded_lens_example/public/app.tsx @@ -27,6 +27,7 @@ import { PersistedIndexPatternLayer, XYState, LensEmbeddableInput, + DateHistogramIndexPatternColumn, } from '../../../plugins/lens/public'; import { StartDependencies } from './plugin'; @@ -55,7 +56,7 @@ function getLensAttributes( params: { interval: 'auto' }, scale: 'interval', sourceField: defaultIndexPattern.timeFieldName!, - }, + } as DateHistogramIndexPatternColumn, }, }; diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/field_data_row/action_menu/lens_utils.ts b/x-pack/plugins/data_visualizer/public/application/common/components/field_data_row/action_menu/lens_utils.ts index db04712271587..70aa103b86d53 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/field_data_row/action_menu/lens_utils.ts +++ b/x-pack/plugins/data_visualizer/public/application/common/components/field_data_row/action_menu/lens_utils.ts @@ -10,7 +10,10 @@ import type { Filter } from '@kbn/es-query'; import type { IndexPattern } from '../../../../../../../../../src/plugins/data/common'; import type { CombinedQuery } from '../../../../index_data_visualizer/types/combined_query'; import type { - IndexPatternColumn, + DateHistogramIndexPatternColumn, + GenericIndexPatternColumn, + RangeIndexPatternColumn, + TermsIndexPatternColumn, TypedLensByValueInput, XYLayerConfig, } from '../../../../../../../lens/public'; @@ -18,7 +21,7 @@ import { FieldVisConfig } from '../../stats_table/types'; import { JOB_FIELD_TYPES } from '../../../../../../common'; interface ColumnsAndLayer { - columns: Record; + columns: Record; layer: XYLayerConfig; } @@ -32,7 +35,7 @@ const COUNT = i18n.translate('xpack.dataVisualizer.index.lensChart.countLabel', export function getNumberSettings(item: FieldVisConfig, defaultIndexPattern: IndexPattern) { // if index has no timestamp field if (defaultIndexPattern.timeFieldName === undefined) { - const columns: Record = { + const columns: Record = { col1: { label: item.fieldName!, dataType: 'number', @@ -44,7 +47,7 @@ export function getNumberSettings(item: FieldVisConfig, defaultIndexPattern: Ind ranges: [], }, sourceField: item.fieldName!, - }, + } as RangeIndexPatternColumn, col2: { label: COUNT, dataType: 'number', @@ -64,7 +67,7 @@ export function getNumberSettings(item: FieldVisConfig, defaultIndexPattern: Ind return { columns, layer }; } - const columns: Record = { + const columns: Record = { col2: { dataType: 'number', isBucketed: false, @@ -83,7 +86,7 @@ export function getNumberSettings(item: FieldVisConfig, defaultIndexPattern: Ind params: { interval: 'auto' }, scale: 'interval', sourceField: defaultIndexPattern.timeFieldName!, - }, + } as DateHistogramIndexPatternColumn, }; const layer: XYLayerConfig = { @@ -97,7 +100,7 @@ export function getNumberSettings(item: FieldVisConfig, defaultIndexPattern: Ind return { columns, layer }; } export function getDateSettings(item: FieldVisConfig) { - const columns: Record = { + const columns: Record = { col2: { dataType: 'number', isBucketed: false, @@ -114,7 +117,7 @@ export function getDateSettings(item: FieldVisConfig) { params: { interval: 'auto' }, scale: 'interval', sourceField: item.fieldName!, - }, + } as DateHistogramIndexPatternColumn, }; const layer: XYLayerConfig = { accessors: ['col2'], @@ -128,7 +131,7 @@ export function getDateSettings(item: FieldVisConfig) { } export function getKeywordSettings(item: FieldVisConfig) { - const columns: Record = { + const columns: Record = { col1: { label: TOP_VALUES_LABEL, dataType: 'string', @@ -140,7 +143,7 @@ export function getKeywordSettings(item: FieldVisConfig) { orderDirection: 'desc', }, sourceField: item.fieldName!, - }, + } as TermsIndexPatternColumn, col2: { label: COUNT, dataType: 'number', @@ -161,7 +164,7 @@ export function getKeywordSettings(item: FieldVisConfig) { } export function getBooleanSettings(item: FieldVisConfig) { - const columns: Record = { + const columns: Record = { col1: { label: TOP_VALUES_LABEL, dataType: 'string', @@ -173,7 +176,7 @@ export function getBooleanSettings(item: FieldVisConfig) { orderDirection: 'desc', }, sourceField: item.fieldName!, - }, + } as TermsIndexPatternColumn, col2: { label: COUNT, dataType: 'number', diff --git a/x-pack/plugins/lens/public/index.ts b/x-pack/plugins/lens/public/index.ts index fb7cefb22d175..29dce6f0d1090 100644 --- a/x-pack/plugins/lens/public/index.ts +++ b/x-pack/plugins/lens/public/index.ts @@ -31,10 +31,10 @@ export type { DatatableVisualizationState } from './datatable_visualization/visu export type { IndexPatternPersistedState, PersistedIndexPatternLayer, - IndexPatternColumn, - FieldBasedIndexPatternColumn, OperationType, IncompleteColumn, + GenericIndexPatternColumn, + FieldBasedIndexPatternColumn, FiltersIndexPatternColumn, RangeIndexPatternColumn, TermsIndexPatternColumn, diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.test.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.test.tsx index a6a3cda0ca033..6fe61d3e3c29a 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.test.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.test.tsx @@ -26,6 +26,7 @@ import { fieldFormatsServiceMock } from '../../../../../src/plugins/field_format import { indexPatternFieldEditorPluginMock } from '../../../../../src/plugins/index_pattern_field_editor/public/mocks'; import { getFieldByNameFactory } from './pure_helpers'; import { uiActionsPluginMock } from '../../../../../src/plugins/ui_actions/public/mocks'; +import { TermsIndexPatternColumn } from './operations'; const fieldsOne = [ { @@ -173,7 +174,7 @@ const initialState: IndexPatternPrivateState = { type: 'alphabetical', }, }, - }, + } as TermsIndexPatternColumn, col2: { label: 'My Op', dataType: 'number', @@ -200,7 +201,7 @@ const initialState: IndexPatternPrivateState = { type: 'alphabetical', }, }, - }, + } as TermsIndexPatternColumn, col2: { label: 'My Op', dataType: 'number', diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/bucket_nesting_editor.test.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/bucket_nesting_editor.test.tsx index b48d13d6d3499..fbecfeed0f321 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/bucket_nesting_editor.test.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/bucket_nesting_editor.test.tsx @@ -8,7 +8,7 @@ import { mount } from 'enzyme'; import React from 'react'; import { BucketNestingEditor } from './bucket_nesting_editor'; -import { IndexPatternColumn } from '../indexpattern'; +import { GenericIndexPatternColumn } from '../indexpattern'; import { IndexPatternField } from '../types'; const fieldMap: Record = { @@ -20,7 +20,7 @@ const fieldMap: Record = { const getFieldByName = (name: string): IndexPatternField | undefined => fieldMap[name]; describe('BucketNestingEditor', () => { - function mockCol(col: Partial = {}): IndexPatternColumn { + function mockCol(col: Partial = {}): GenericIndexPatternColumn { const result = { dataType: 'string', isBucketed: true, @@ -35,7 +35,7 @@ describe('BucketNestingEditor', () => { ...col, }; - return result as IndexPatternColumn; + return result as GenericIndexPatternColumn; } it('should display the top level grouping when at the root', () => { diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/bucket_nesting_editor.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/bucket_nesting_editor.tsx index 8456552be8ec6..3979bfb8c9ac4 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/bucket_nesting_editor.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/bucket_nesting_editor.tsx @@ -10,7 +10,7 @@ import { i18n } from '@kbn/i18n'; import { EuiFormRow, EuiSwitch, EuiSelect } from '@elastic/eui'; import { IndexPatternLayer, IndexPatternField } from '../types'; import { hasField } from '../utils'; -import { IndexPatternColumn } from '../operations'; +import { GenericIndexPatternColumn } from '../operations'; function nestColumn(columnOrder: string[], outer: string, inner: string) { const result = columnOrder.filter((c) => c !== inner); @@ -22,7 +22,7 @@ function nestColumn(columnOrder: string[], outer: string, inner: string) { } function getFieldName( - column: IndexPatternColumn, + column: GenericIndexPatternColumn, getFieldByName: (name: string) => IndexPatternField | undefined ) { return hasField(column) diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_editor.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_editor.tsx index d34430e717e66..c8452340e993a 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_editor.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_editor.tsx @@ -19,7 +19,7 @@ import { } from '@elastic/eui'; import { IndexPatternDimensionEditorProps } from './dimension_panel'; import { OperationSupportMatrix } from './operation_support'; -import { IndexPatternColumn } from '../indexpattern'; +import { GenericIndexPatternColumn } from '../indexpattern'; import { operationDefinitionMap, getOperationDisplay, @@ -62,7 +62,7 @@ import type { TemporaryState } from './dimensions_editor_helpers'; const operationPanels = getOperationDisplay(); export interface DimensionEditorProps extends IndexPatternDimensionEditorProps { - selectedColumn?: IndexPatternColumn; + selectedColumn?: GenericIndexPatternColumn; layerType: LayerType; operationSupportMatrix: OperationSupportMatrix; currentIndexPattern: IndexPattern; diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.test.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.test.tsx index 6d9e1ae3fe81b..06c1bb931f730 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.test.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.test.tsx @@ -27,7 +27,12 @@ import { IUiSettingsClient, SavedObjectsClientContract, HttpSetup, CoreSetup } f import { IStorageWrapper } from 'src/plugins/kibana_utils/public'; import { generateId } from '../../id_generator'; import { IndexPatternPrivateState } from '../types'; -import { IndexPatternColumn, replaceColumn } from '../operations'; +import { + FiltersIndexPatternColumn, + GenericIndexPatternColumn, + replaceColumn, + TermsIndexPatternColumn, +} from '../operations'; import { documentField } from '../document_field'; import { OperationMetadata } from '../../types'; import { DateHistogramIndexPatternColumn } from '../operations/definitions/date_histogram'; @@ -108,7 +113,7 @@ const expectedIndexPatterns = { }, }; -const bytesColumn: IndexPatternColumn = { +const bytesColumn: GenericIndexPatternColumn = { label: 'Max of bytes', dataType: 'number', isBucketed: false, @@ -133,7 +138,7 @@ describe('IndexPatternDimensionEditorPanel', () => { let setState: jest.Mock; let defaultProps: IndexPatternDimensionEditorProps; - function getStateWithColumns(columns: Record) { + function getStateWithColumns(columns: Record) { return { ...state, layers: { first: { ...state.layers.first, columns, columnOrder: Object.keys(columns) } }, @@ -171,7 +176,7 @@ describe('IndexPatternDimensionEditorPanel', () => { interval: '1d', }, sourceField: 'timestamp', - }, + } as DateHistogramIndexPatternColumn, }, incompleteColumns: {}, }, @@ -264,7 +269,7 @@ describe('IndexPatternDimensionEditorPanel', () => { // Private operationType: 'filters', params: { filters: [] }, - }, + } as FiltersIndexPatternColumn, })} /> ); @@ -427,7 +432,7 @@ describe('IndexPatternDimensionEditorPanel', () => { operationType: 'date_histogram', sourceField: '@timestamp', params: { interval: 'auto' }, - }, + } as DateHistogramIndexPatternColumn, col1: { label: 'Counter rate', dataType: 'number', @@ -464,7 +469,7 @@ describe('IndexPatternDimensionEditorPanel', () => { operationType: 'date_histogram', sourceField: '@timestamp', params: { interval: 'auto' }, - }, + } as DateHistogramIndexPatternColumn, col1: { label: 'Cumulative sum', dataType: 'number', @@ -839,7 +844,7 @@ describe('IndexPatternDimensionEditorPanel', () => { // Private operationType: 'filters', params: { filters: [] }, - }, + } as FiltersIndexPatternColumn, })} /> ); @@ -1066,7 +1071,7 @@ describe('IndexPatternDimensionEditorPanel', () => { }); describe('time scaling', () => { - function getProps(colOverrides: Partial) { + function getProps(colOverrides: Partial) { return { ...defaultProps, state: getStateWithColumns({ @@ -1080,7 +1085,7 @@ describe('IndexPatternDimensionEditorPanel', () => { params: { interval: '1d', }, - }, + } as DateHistogramIndexPatternColumn, col2: { dataType: 'number', isBucketed: false, @@ -1088,7 +1093,7 @@ describe('IndexPatternDimensionEditorPanel', () => { operationType: 'count', sourceField: 'Records', ...colOverrides, - } as IndexPatternColumn, + } as GenericIndexPatternColumn, }), columnId: 'col2', }; @@ -1296,7 +1301,7 @@ describe('IndexPatternDimensionEditorPanel', () => { }); describe('time shift', () => { - function getProps(colOverrides: Partial) { + function getProps(colOverrides: Partial) { return { ...defaultProps, state: getStateWithColumns({ @@ -1310,7 +1315,7 @@ describe('IndexPatternDimensionEditorPanel', () => { params: { interval: '1d', }, - }, + } as DateHistogramIndexPatternColumn, col2: { dataType: 'number', isBucketed: false, @@ -1318,7 +1323,7 @@ describe('IndexPatternDimensionEditorPanel', () => { operationType: 'count', sourceField: 'Records', ...colOverrides, - } as IndexPatternColumn, + } as GenericIndexPatternColumn, }), columnId: 'col2', }; @@ -1334,7 +1339,7 @@ describe('IndexPatternDimensionEditorPanel', () => { label: 'Count of records', operationType: 'count', sourceField: 'Records', - } as IndexPatternColumn, + } as GenericIndexPatternColumn, }), columnId: 'col2', }; @@ -1483,7 +1488,7 @@ describe('IndexPatternDimensionEditorPanel', () => { }); describe('filtering', () => { - function getProps(colOverrides: Partial) { + function getProps(colOverrides: Partial) { return { ...defaultProps, state: getStateWithColumns({ @@ -1497,7 +1502,7 @@ describe('IndexPatternDimensionEditorPanel', () => { params: { interval: '1d', }, - }, + } as DateHistogramIndexPatternColumn, col2: { dataType: 'number', isBucketed: false, @@ -1505,7 +1510,7 @@ describe('IndexPatternDimensionEditorPanel', () => { operationType: 'count', sourceField: 'Records', ...colOverrides, - } as IndexPatternColumn, + } as GenericIndexPatternColumn, }), columnId: 'col2', }; @@ -1522,7 +1527,7 @@ describe('IndexPatternDimensionEditorPanel', () => { orderBy: { type: 'alphabetical' }, size: 5, }, - })} + } as TermsIndexPatternColumn)} /> ); expect( diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.tsx index f27b2c8938b2c..6479fb5b8af4f 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.tsx @@ -12,7 +12,7 @@ import { IUiSettingsClient, SavedObjectsClientContract, HttpSetup } from 'kibana import { IStorageWrapper } from 'src/plugins/kibana_utils/public'; import { DatasourceDimensionTriggerProps, DatasourceDimensionEditorProps } from '../../types'; import { DataPublicPluginStart } from '../../../../../../src/plugins/data/public'; -import { IndexPatternColumn } from '../indexpattern'; +import { GenericIndexPatternColumn } from '../indexpattern'; import { isColumnInvalid } from '../utils'; import { IndexPatternPrivateState } from '../types'; import { DimensionEditor } from './dimension_editor'; @@ -56,7 +56,7 @@ export const IndexPatternDimensionTriggerComponent = function IndexPatternDimens [layer, columnId, currentIndexPattern, invalid] ); - const selectedColumn: IndexPatternColumn | null = layer.columns[props.columnId] ?? null; + const selectedColumn: GenericIndexPatternColumn | null = layer.columns[props.columnId] ?? null; if (!selectedColumn) { return null; @@ -126,7 +126,7 @@ export const IndexPatternDimensionEditorComponent = function IndexPatternDimensi } const operationSupportMatrix = getOperationSupportMatrix(props); - const selectedColumn: IndexPatternColumn | null = + const selectedColumn: GenericIndexPatternColumn | null = props.state.layers[layerId].columns[props.columnId] || null; return ( }; export function getErrorMessage( - selectedColumn: IndexPatternColumn | undefined, + selectedColumn: GenericIndexPatternColumn | undefined, incompleteOperation: boolean, input: 'none' | 'field' | 'fullReference' | 'managedReference' | undefined, fieldInvalid: boolean diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/droppable/droppable.test.ts b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/droppable/droppable.test.ts index 85807721f80f6..fa200e8b55626 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/droppable/droppable.test.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/droppable/droppable.test.ts @@ -14,7 +14,12 @@ import { IStorageWrapper } from 'src/plugins/kibana_utils/public'; import { IndexPatternLayer, IndexPatternPrivateState } from '../../types'; import { documentField } from '../../document_field'; import { OperationMetadata, DropType } from '../../../types'; -import { IndexPatternColumn, MedianIndexPatternColumn } from '../../operations'; +import { + DateHistogramIndexPatternColumn, + GenericIndexPatternColumn, + MedianIndexPatternColumn, + TermsIndexPatternColumn, +} from '../../operations'; import { getFieldByNameFactory } from '../../pure_helpers'; import { generateId } from '../../../id_generator'; import { layerTypes } from '../../../../common'; @@ -128,7 +133,7 @@ const oneColumnLayer: IndexPatternLayer = { interval: '1d', }, sourceField: 'timestamp', - }, + } as DateHistogramIndexPatternColumn, }, incompleteColumns: {}, }; @@ -150,7 +155,7 @@ const multipleColumnsLayer: IndexPatternLayer = { size: 10, }, sourceField: 'src', - }, + } as TermsIndexPatternColumn, col3: { label: 'Top values of dest', dataType: 'string', @@ -164,7 +169,7 @@ const multipleColumnsLayer: IndexPatternLayer = { size: 10, }, sourceField: 'dest', - }, + } as TermsIndexPatternColumn, col4: { label: 'Median of bytes', dataType: 'number', @@ -416,7 +421,7 @@ describe('IndexPatternDimensionEditorPanel', () => { interval: '1d', }, sourceField: 'timestamp', - }, + } as DateHistogramIndexPatternColumn, }, }; @@ -771,7 +776,7 @@ describe('IndexPatternDimensionEditorPanel', () => { interval: '1d', }, sourceField: 'timestamp', - }, + } as DateHistogramIndexPatternColumn, col2: { label: 'Top values of bar', dataType: 'number', @@ -783,7 +788,7 @@ describe('IndexPatternDimensionEditorPanel', () => { orderDirection: 'asc', size: 5, }, - }, + } as TermsIndexPatternColumn, col3: { operationType: 'average', sourceField: 'memory', @@ -1158,17 +1163,17 @@ describe('IndexPatternDimensionEditorPanel', () => { label: 'Date histogram of timestamp', dataType: 'date', isBucketed: true, - } as IndexPatternColumn, + } as GenericIndexPatternColumn, col2: { label: 'Top values of bar', dataType: 'number', isBucketed: true, - } as IndexPatternColumn, + } as GenericIndexPatternColumn, col3: { label: 'Top values of memory', dataType: 'number', isBucketed: true, - } as IndexPatternColumn, + } as GenericIndexPatternColumn, }, }, }, @@ -1293,7 +1298,7 @@ describe('IndexPatternDimensionEditorPanel', () => { size: 10, }, sourceField: 'src', - }, + } as TermsIndexPatternColumn, col3: { label: 'Count', dataType: 'number', diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/droppable/get_drop_props.ts b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/droppable/get_drop_props.ts index 0e87cc680c2f6..08361490cdc2c 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/droppable/get_drop_props.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/droppable/get_drop_props.ts @@ -16,7 +16,7 @@ import { hasField, isDraggedField } from '../../utils'; import { DragContextState } from '../../../drag_drop/providers'; import { OperationMetadata } from '../../../types'; import { getOperationTypesForField } from '../../operations'; -import { IndexPatternColumn } from '../../indexpattern'; +import { GenericIndexPatternColumn } from '../../indexpattern'; import { IndexPatternPrivateState, IndexPattern, @@ -36,7 +36,7 @@ const operationLabels = getOperationDisplay(); export function getNewOperation( field: IndexPatternField | undefined | false, filterOperations: (meta: OperationMetadata) => boolean, - targetColumn: IndexPatternColumn + targetColumn: GenericIndexPatternColumn ) { if (!field) { return; @@ -50,7 +50,10 @@ export function getNewOperation( return shouldOperationPersist ? targetColumn.operationType : newOperations[0]; } -export function getField(column: IndexPatternColumn | undefined, indexPattern: IndexPattern) { +export function getField( + column: GenericIndexPatternColumn | undefined, + indexPattern: IndexPattern +) { if (!column) { return; } @@ -89,7 +92,10 @@ export function getDropProps(props: GetDropProps) { } } -function hasTheSameField(sourceColumn: IndexPatternColumn, targetColumn?: IndexPatternColumn) { +function hasTheSameField( + sourceColumn: GenericIndexPatternColumn, + targetColumn?: GenericIndexPatternColumn +) { return ( targetColumn && hasField(targetColumn) && @@ -127,11 +133,11 @@ function getDropPropsForField({ return; } -function getDropPropsForSameGroup(targetColumn?: IndexPatternColumn): DropProps { +function getDropPropsForSameGroup(targetColumn?: GenericIndexPatternColumn): DropProps { return targetColumn ? { dropTypes: ['reorder'] } : { dropTypes: ['duplicate_compatible'] }; } -function getDropPropsForCompatibleGroup(targetColumn?: IndexPatternColumn): DropProps { +function getDropPropsForCompatibleGroup(targetColumn?: GenericIndexPatternColumn): DropProps { return { dropTypes: targetColumn ? ['replace_compatible', 'replace_duplicate_compatible', 'swap_compatible'] diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/filtering.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/filtering.tsx index ddd9718839649..d88edff3f0cc3 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/filtering.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/filtering.tsx @@ -18,7 +18,7 @@ import { EuiPopoverProps, } from '@elastic/eui'; import type { Query } from 'src/plugins/data/public'; -import { IndexPatternColumn, operationDefinitionMap } from '../operations'; +import { GenericIndexPatternColumn, operationDefinitionMap } from '../operations'; import { validateQuery } from '../operations/definitions/filters'; import { QueryInput } from '../query_input'; import type { IndexPattern, IndexPatternLayer } from '../types'; @@ -54,7 +54,7 @@ export function Filtering({ indexPattern, isInitiallyOpen, }: { - selectedColumn: IndexPatternColumn; + selectedColumn: GenericIndexPatternColumn; indexPattern: IndexPattern; columnId: string; layer: IndexPatternLayer; diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/format_selector.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/format_selector.tsx index ff10810208e70..7ee25a790db62 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/format_selector.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/format_selector.tsx @@ -8,7 +8,7 @@ import React, { useCallback, useMemo, useState } from 'react'; import { i18n } from '@kbn/i18n'; import { EuiFormRow, EuiComboBox, EuiSpacer, EuiRange } from '@elastic/eui'; -import { IndexPatternColumn } from '../indexpattern'; +import { GenericIndexPatternColumn } from '../indexpattern'; const supportedFormats: Record = { number: { @@ -36,7 +36,7 @@ const defaultOption = { }; interface FormatSelectorProps { - selectedColumn: IndexPatternColumn; + selectedColumn: GenericIndexPatternColumn; onChange: (newFormat?: { id: string; params?: Record }) => void; } @@ -136,7 +136,7 @@ export function FormatSelector(props: FormatSelectorProps) { onChange={(e) => { setState({ decimalPlaces: Number(e.currentTarget.value) }); onChange({ - id: (selectedColumn.params as { format: { id: string } }).format.id, + id: currentFormat.id, params: { decimals: Number(e.currentTarget.value), }, diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/reference_editor.test.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/reference_editor.test.tsx index 21251b59d4533..16251654a6355 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/reference_editor.test.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/reference_editor.test.tsx @@ -17,7 +17,11 @@ import type { DataPublicPluginStart } from 'src/plugins/data/public'; import { OperationMetadata } from '../../types'; import { createMockedIndexPattern, createMockedIndexPatternWithoutType } from '../mocks'; import { ReferenceEditor, ReferenceEditorProps } from './reference_editor'; -import { insertOrReplaceColumn } from '../operations'; +import { + insertOrReplaceColumn, + LastValueIndexPatternColumn, + TermsIndexPatternColumn, +} from '../operations'; import { FieldSelect } from './field_select'; jest.mock('../operations'); @@ -123,7 +127,7 @@ describe('reference editor', () => { operationType: 'terms', sourceField: 'dest', params: { size: 5, orderBy: { type: 'alphabetical' }, orderDirection: 'desc' }, - }, + } as TermsIndexPatternColumn, }, }} validation={{ @@ -490,7 +494,7 @@ describe('reference editor', () => { params: { sortField: 'timestamp', }, - }, + } as LastValueIndexPatternColumn, }, }} validation={{ @@ -522,7 +526,7 @@ describe('reference editor', () => { params: { sortField: 'timestamp', }, - }, + } as LastValueIndexPatternColumn, }, incompleteColumns: { ref: { operationType: 'max' }, diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/time_scaling.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/time_scaling.tsx index 8a670e7562573..6e3a43cbb1a03 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/time_scaling.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/time_scaling.tsx @@ -19,7 +19,7 @@ import { i18n } from '@kbn/i18n'; import React from 'react'; import { adjustTimeScaleLabelSuffix, - IndexPatternColumn, + GenericIndexPatternColumn, operationDefinitionMap, } from '../operations'; import type { TimeScaleUnit } from '../../../common/expressions'; @@ -60,7 +60,7 @@ export function TimeScaling({ layer, updateLayer, }: { - selectedColumn: IndexPatternColumn; + selectedColumn: GenericIndexPatternColumn; columnId: string; layer: IndexPatternLayer; updateLayer: (newLayer: IndexPatternLayer) => void; diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/time_shift.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/time_shift.tsx index c2415c9c9a75a..36cc4a3c22e44 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/time_shift.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/time_shift.tsx @@ -14,7 +14,7 @@ import { Query } from 'src/plugins/data/public'; import { parseTimeShift } from '../../../../../../src/plugins/data/common'; import { adjustTimeScaleLabelSuffix, - IndexPatternColumn, + GenericIndexPatternColumn, operationDefinitionMap, } from '../operations'; import { IndexPattern, IndexPatternLayer } from '../types'; @@ -70,7 +70,7 @@ export function TimeShift({ activeData, layerId, }: { - selectedColumn: IndexPatternColumn; + selectedColumn: GenericIndexPatternColumn; indexPattern: IndexPattern; columnId: string; layer: IndexPatternLayer; diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.test.ts b/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.test.ts index 8f180d4a021e0..e6b9eccbc7da1 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.test.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.test.ts @@ -8,7 +8,7 @@ import React from 'react'; import 'jest-canvas-mock'; import { IStorageWrapper } from 'src/plugins/kibana_utils/public'; -import { getIndexPatternDatasource, IndexPatternColumn } from './indexpattern'; +import { getIndexPatternDatasource, GenericIndexPatternColumn } from './indexpattern'; import { DatasourcePublicAPI, Operation, Datasource, FramePublicAPI } from '../types'; import { coreMock } from 'src/core/public/mocks'; import { IndexPatternPersistedState, IndexPatternPrivateState } from './types'; @@ -16,11 +16,20 @@ import { dataPluginMock } from '../../../../../src/plugins/data/public/mocks'; import { Ast } from '@kbn/interpreter/common'; import { chartPluginMock } from '../../../../../src/plugins/charts/public/mocks'; import { getFieldByNameFactory } from './pure_helpers'; -import { operationDefinitionMap, getErrorMessages } from './operations'; +import { + operationDefinitionMap, + getErrorMessages, + TermsIndexPatternColumn, + DateHistogramIndexPatternColumn, + MovingAverageIndexPatternColumn, + MathIndexPatternColumn, + FormulaIndexPatternColumn, +} from './operations'; import { createMockedFullReference } from './operations/mocks'; import { indexPatternFieldEditorPluginMock } from 'src/plugins/index_pattern_field_editor/public/mocks'; import { uiActionsPluginMock } from '../../../../../src/plugins/ui_actions/public/mocks'; import { fieldFormatsServiceMock } from '../../../../../src/plugins/field_formats/public/mocks'; +import { TinymathAST } from 'packages/kbn-tinymath'; jest.mock('./loader'); jest.mock('../id_generator'); @@ -200,7 +209,7 @@ describe('IndexPattern Data Source', () => { orderBy: { type: 'alphabetical' }, orderDirection: 'asc', }, - }, + } as TermsIndexPatternColumn, }, }, }, @@ -209,7 +218,7 @@ describe('IndexPattern Data Source', () => { describe('uniqueLabels', () => { it('appends a suffix to duplicates', () => { - const col: IndexPatternColumn = { + const col: GenericIndexPatternColumn = { dataType: 'number', isBucketed: false, label: 'Foo', @@ -355,7 +364,7 @@ describe('IndexPattern Data Source', () => { params: { interval: '1d', }, - }, + } as DateHistogramIndexPatternColumn, }, }, }, @@ -505,7 +514,7 @@ describe('IndexPattern Data Source', () => { params: { interval: 'auto', }, - }, + } as DateHistogramIndexPatternColumn, col3: { label: 'Date 2', dataType: 'date', @@ -515,7 +524,7 @@ describe('IndexPattern Data Source', () => { params: { interval: 'auto', }, - }, + } as DateHistogramIndexPatternColumn, }, }, }, @@ -552,7 +561,7 @@ describe('IndexPattern Data Source', () => { params: { interval: 'auto', }, - }, + } as DateHistogramIndexPatternColumn, }, }, }, @@ -601,7 +610,7 @@ describe('IndexPattern Data Source', () => { params: { interval: 'auto', }, - }, + } as DateHistogramIndexPatternColumn, }, }, }, @@ -727,7 +736,7 @@ describe('IndexPattern Data Source', () => { params: { interval: 'auto', }, - }, + } as DateHistogramIndexPatternColumn, }, }, }, @@ -794,7 +803,7 @@ describe('IndexPattern Data Source', () => { params: { interval: 'auto', }, - }, + } as DateHistogramIndexPatternColumn, metric: { label: 'Count of records', dataType: 'number', @@ -812,7 +821,7 @@ describe('IndexPattern Data Source', () => { params: { window: 5, }, - }, + } as MovingAverageIndexPatternColumn, }, }, }, @@ -850,7 +859,7 @@ describe('IndexPattern Data Source', () => { params: { interval: '1d', }, - }, + } as DateHistogramIndexPatternColumn, bucket2: { label: 'Terms', dataType: 'string', @@ -862,7 +871,7 @@ describe('IndexPattern Data Source', () => { orderDirection: 'asc', size: 10, }, - }, + } as TermsIndexPatternColumn, }, }, }, @@ -902,7 +911,7 @@ describe('IndexPattern Data Source', () => { params: { interval: 'auto', }, - }, + } as DateHistogramIndexPatternColumn, }, }, }, @@ -947,7 +956,6 @@ describe('IndexPattern Data Source', () => { label: 'Reference', dataType: 'number', isBucketed: false, - // @ts-expect-error not a valid type operationType: 'testReference', references: ['col1'], }, @@ -983,7 +991,6 @@ describe('IndexPattern Data Source', () => { label: 'Reference', dataType: 'number', isBucketed: false, - // @ts-expect-error not a valid type operationType: 'testReference', references: ['col1'], }, @@ -1030,7 +1037,7 @@ describe('IndexPattern Data Source', () => { params: { interval: 'auto', }, - }, + } as DateHistogramIndexPatternColumn, formula: { label: 'Formula', dataType: 'number', @@ -1042,7 +1049,7 @@ describe('IndexPattern Data Source', () => { isFormulaBroken: false, }, references: ['math'], - }, + } as FormulaIndexPatternColumn, countX0: { label: 'countX0', dataType: 'number', @@ -1062,8 +1069,7 @@ describe('IndexPattern Data Source', () => { tinymathAst: { type: 'function', name: 'add', - // @ts-expect-error String args are not valid tinymath, but signals something unique to Lens - args: ['countX0', 'count'], + args: ['countX0', 'count'] as unknown as TinymathAST[], location: { min: 0, max: 17, @@ -1073,7 +1079,7 @@ describe('IndexPattern Data Source', () => { }, references: ['countX0', 'count'], customLabel: true, - }, + } as MathIndexPatternColumn, }, }, }, @@ -1217,7 +1223,7 @@ describe('IndexPattern Data Source', () => { operationType: 'sum', sourceField: 'test', params: {}, - } as IndexPatternColumn, + } as GenericIndexPatternColumn, col2: { label: 'Cumulative sum', dataType: 'number', @@ -1226,7 +1232,7 @@ describe('IndexPattern Data Source', () => { operationType: 'cumulative_sum', references: ['col1'], params: {}, - } as IndexPatternColumn, + } as GenericIndexPatternColumn, }, }, }, @@ -1268,7 +1274,7 @@ describe('IndexPattern Data Source', () => { operationType: 'sum', sourceField: 'test', params: {}, - } as IndexPatternColumn, + } as GenericIndexPatternColumn, col2: { label: 'Cumulative sum', dataType: 'number', @@ -1277,7 +1283,7 @@ describe('IndexPattern Data Source', () => { operationType: 'cumulative_sum', references: ['col1'], params: {}, - } as IndexPatternColumn, + } as GenericIndexPatternColumn, }, }, }, @@ -1368,7 +1374,7 @@ describe('IndexPattern Data Source', () => { dataType: 'date', isBucketed: true, sourceField: 'timestamp', - }, + } as DateHistogramIndexPatternColumn, col2: { operationType: 'count', label: '', @@ -1606,7 +1612,7 @@ describe('IndexPattern Data Source', () => { params: { interval: '1d', }, - }, + } as DateHistogramIndexPatternColumn, bucket2: { label: 'Terms', dataType: 'string', @@ -1618,7 +1624,7 @@ describe('IndexPattern Data Source', () => { orderDirection: 'asc', size: 10, }, - }, + } as TermsIndexPatternColumn, }, }, }, diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.tsx index b970ad092c7f4..fc9e2c7ed44a8 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.tsx @@ -44,7 +44,7 @@ import { import { isColumnInvalid, isDraggedField, normalizeOperationDataType } from './utils'; import { LayerPanel } from './layerpanel'; -import { IndexPatternColumn, getErrorMessages, insertNewColumn } from './operations'; +import { GenericIndexPatternColumn, getErrorMessages, insertNewColumn } from './operations'; import { IndexPatternField, IndexPatternPrivateState, IndexPatternPersistedState } from './types'; import { KibanaContextProvider } from '../../../../../src/plugins/kibana_react/public'; import { DataPublicPluginStart } from '../../../../../src/plugins/data/public'; @@ -58,10 +58,13 @@ import { GeoFieldWorkspacePanel } from '../editor_frame_service/editor_frame/wor import { DraggingIdentifier } from '../drag_drop'; import { getStateTimeShiftWarningMessages } from './time_shift_utils'; import { getPrecisionErrorWarningMessages } from './utils'; -export type { OperationType, IndexPatternColumn } from './operations'; +export type { OperationType, GenericIndexPatternColumn } from './operations'; export { deleteColumn } from './operations'; -export function columnToOperation(column: IndexPatternColumn, uniqueLabel?: string): Operation { +export function columnToOperation( + column: GenericIndexPatternColumn, + uniqueLabel?: string +): Operation { const { dataType, label, isBucketed, scale } = column; return { dataType: normalizeOperationDataType(dataType), diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.test.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.test.tsx index 5df02482a2745..a821dcee29d6d 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.test.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.test.tsx @@ -18,6 +18,12 @@ import { import { documentField } from './document_field'; import { getFieldByNameFactory } from './pure_helpers'; import { isEqual } from 'lodash'; +import { DateHistogramIndexPatternColumn, TermsIndexPatternColumn } from './operations'; +import { + MathIndexPatternColumn, + RangeIndexPatternColumn, + StaticValueIndexPatternColumn, +} from './operations/definitions'; jest.mock('./loader'); jest.mock('../id_generator'); @@ -179,7 +185,7 @@ function testInitialState(): IndexPatternPrivateState { orderBy: { type: 'alphabetical' }, orderDirection: 'asc', }, - }, + } as TermsIndexPatternColumn, }, }, }, @@ -733,7 +739,7 @@ describe('IndexPattern Data Source suggestions', () => { orderDirection: 'asc', size: 5, }, - }, + } as TermsIndexPatternColumn, colb: { dataType: 'number', isBucketed: false, @@ -768,7 +774,7 @@ describe('IndexPattern Data Source suggestions', () => { params: { interval: 'w', }, - }, + } as DateHistogramIndexPatternColumn, colb: { dataType: 'number', isBucketed: false, @@ -976,7 +982,7 @@ describe('IndexPattern Data Source suggestions', () => { orderDirection: 'asc', size: 5, }, - }, + } as TermsIndexPatternColumn, }, columnOrder: ['cola'], }, @@ -1086,7 +1092,7 @@ describe('IndexPattern Data Source suggestions', () => { operationType: 'date_histogram', sourceField: 'timestamp', params: { interval: 'auto' }, - }, + } as DateHistogramIndexPatternColumn, metric: { label: '', customLabel: true, @@ -1218,7 +1224,7 @@ describe('IndexPattern Data Source suggestions', () => { params: { value: '0' }, references: [], scale: 'ratio', - }, + } as StaticValueIndexPatternColumn, }, }, currentLayer: { @@ -1506,7 +1512,7 @@ describe('IndexPattern Data Source suggestions', () => { orderBy: { type: 'alphabetical' }, orderDirection: 'asc', }, - }, + } as TermsIndexPatternColumn, }, }, }, @@ -1648,7 +1654,7 @@ describe('IndexPattern Data Source suggestions', () => { orderDirection: 'asc', size: 5, }, - }, + } as TermsIndexPatternColumn, colb: { label: 'My Op', customLabel: true, @@ -1726,7 +1732,7 @@ describe('IndexPattern Data Source suggestions', () => { orderDirection: 'asc', size: 5, }, - }, + } as TermsIndexPatternColumn, colb: { label: 'My Op', customLabel: true, @@ -1830,7 +1836,7 @@ describe('IndexPattern Data Source suggestions', () => { maxBars: 100, ranges: [], }, - }, + } as RangeIndexPatternColumn, }, }, }, @@ -1876,7 +1882,7 @@ describe('IndexPattern Data Source suggestions', () => { maxBars: 100, ranges: [{ from: 1, to: 2, label: '' }], }, - }, + } as RangeIndexPatternColumn, }, }, }, @@ -1954,7 +1960,7 @@ describe('IndexPattern Data Source suggestions', () => { it("should not propose an over time suggestion if there's a top values aggregation with an high size", () => { const initialState = testInitialState(); - (initialState.layers.first.columns.col1 as { params: { size: number } }).params!.size = 6; + (initialState.layers.first.columns.col1 as TermsIndexPatternColumn).params!.size = 6; const suggestions = getDatasourceSuggestionsFromCurrentState({ ...initialState, indexPatterns: { 1: { ...initialState.indexPatterns['1'], timeFieldName: undefined } }, @@ -1995,7 +2001,7 @@ describe('IndexPattern Data Source suggestions', () => { orderBy: { type: 'alphabetical' }, orderDirection: 'asc', }, - }, + } as TermsIndexPatternColumn, }, }, }, @@ -2080,7 +2086,7 @@ describe('IndexPattern Data Source suggestions', () => { orderBy: { type: 'alphabetical' }, orderDirection: 'asc', }, - }, + } as TermsIndexPatternColumn, col2: { label: 'My Op', customLabel: true, @@ -2094,7 +2100,7 @@ describe('IndexPattern Data Source suggestions', () => { orderBy: { type: 'alphabetical' }, orderDirection: 'asc', }, - }, + } as TermsIndexPatternColumn, col3: { label: 'My Op', customLabel: true, @@ -2108,7 +2114,7 @@ describe('IndexPattern Data Source suggestions', () => { orderBy: { type: 'alphabetical' }, orderDirection: 'asc', }, - }, + } as TermsIndexPatternColumn, col4: { label: 'My Op', customLabel: true, @@ -2217,7 +2223,7 @@ describe('IndexPattern Data Source suggestions', () => { params: { interval: 'd', }, - }, + } as DateHistogramIndexPatternColumn, id2: { label: 'Average of field1', dataType: 'number', @@ -2348,7 +2354,7 @@ describe('IndexPattern Data Source suggestions', () => { params: { interval: 'd', }, - }, + } as DateHistogramIndexPatternColumn, id2: { label: 'Top 5', dataType: 'string', @@ -2357,7 +2363,7 @@ describe('IndexPattern Data Source suggestions', () => { operationType: 'terms', sourceField: 'dest', params: { size: 5, orderBy: { type: 'alphabetical' }, orderDirection: 'asc' }, - }, + } as TermsIndexPatternColumn, id3: { label: 'Average of field1', dataType: 'number', @@ -2403,7 +2409,7 @@ describe('IndexPattern Data Source suggestions', () => { operationType: 'terms', sourceField: 'nonExistingField', params: { size: 5, orderBy: { type: 'alphabetical' }, orderDirection: 'asc' }, - }, + } as TermsIndexPatternColumn, }, columnOrder: ['col1', 'col2'], }, @@ -2539,7 +2545,7 @@ describe('IndexPattern Data Source suggestions', () => { operationType: 'date_histogram', sourceField: 'timestamp', params: { interval: 'auto' }, - }, + } as DateHistogramIndexPatternColumn, ref: { label: '', dataType: 'number', @@ -2629,7 +2635,7 @@ describe('IndexPattern Data Source suggestions', () => { operationType: 'date_histogram', sourceField: 'timestamp', params: { interval: 'auto' }, - }, + } as DateHistogramIndexPatternColumn, metric: { label: '', dataType: 'number', @@ -2681,7 +2687,7 @@ describe('IndexPattern Data Source suggestions', () => { params: { tinymathAst: '', }, - }, + } as MathIndexPatternColumn, ref4: { label: '', dataType: 'number', @@ -2691,7 +2697,7 @@ describe('IndexPattern Data Source suggestions', () => { params: { tinymathAst: '', }, - }, + } as MathIndexPatternColumn, }, }, }, @@ -2756,7 +2762,7 @@ describe('IndexPattern Data Source suggestions', () => { operationType: 'date_histogram', sourceField: 'timestamp', params: { interval: 'auto' }, - }, + } as DateHistogramIndexPatternColumn, ref: { label: '', dataType: 'number', @@ -2806,7 +2812,7 @@ describe('IndexPattern Data Source suggestions', () => { tinymathAst: '', }, references: ['metric'], - }, + } as MathIndexPatternColumn, metric: { label: '', dataType: 'number', diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.ts b/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.ts index 8b940ec1f05af..6b15a5a8d1daf 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.ts @@ -16,7 +16,7 @@ import { getMetricOperationTypes, getOperationTypesForField, operationDefinitionMap, - IndexPatternColumn, + BaseIndexPatternColumn, OperationType, getExistingColumnGroups, isReferenced, @@ -62,11 +62,11 @@ function buildSuggestion({ // two match up. const layers = mapValues(updatedState.layers, (layer) => ({ ...layer, - columns: pick(layer.columns, layer.columnOrder) as Record, + columns: pick(layer.columns, layer.columnOrder) as Record, })); const columnOrder = layers[layerId].columnOrder; - const columnMap = layers[layerId].columns as Record; + const columnMap = layers[layerId].columns as Record; const isMultiRow = Object.values(columnMap).some((column) => column.isBucketed); return { @@ -221,7 +221,7 @@ function getExistingLayerSuggestionsForField( indexPattern, field, columnId: generateId(), - op: metricOperation.type, + op: metricOperation.type as OperationType, visualizationGroups: [], }); if (layerWithNewMetric) { @@ -243,7 +243,7 @@ function getExistingLayerSuggestionsForField( indexPattern, field, columnId: metrics[0], - op: metricOperation.type, + op: metricOperation.type as OperationType, visualizationGroups: [], }); if (layerWithReplacedMetric) { @@ -336,7 +336,7 @@ function createNewLayerWithMetricAggregation( return insertNewColumn({ op: 'date_histogram', layer: insertNewColumn({ - op: metricOperation.type, + op: metricOperation.type as OperationType, layer: { indexPatternId: indexPattern.id, columns: {}, columnOrder: [] }, columnId: generateId(), field, diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/layerpanel.test.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/layerpanel.test.tsx index 6161bcee4678f..335796442bd8b 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/layerpanel.test.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/layerpanel.test.tsx @@ -13,6 +13,7 @@ import { ShallowWrapper } from 'enzyme'; import { EuiSelectable } from '@elastic/eui'; import { ChangeIndexPattern } from './change_indexpattern'; import { getFieldByNameFactory } from './pure_helpers'; +import { TermsIndexPatternColumn } from './operations'; interface IndexPatternPickerOption { label: string; @@ -160,7 +161,7 @@ const initialState: IndexPatternPrivateState = { type: 'alphabetical', }, }, - }, + } as TermsIndexPatternColumn, col2: { label: 'My Op', dataType: 'number', diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/loader.test.ts b/x-pack/plugins/lens/public/indexpattern_datasource/loader.test.ts index d731069e6e7eb..431b8a84341e8 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/loader.test.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/loader.test.ts @@ -26,6 +26,7 @@ import { } from './types'; import { createMockedRestrictedIndexPattern, createMockedIndexPattern } from './mocks'; import { documentField } from './document_field'; +import { DateHistogramIndexPatternColumn } from './operations'; const createMockStorage = (lastData?: Record) => { return { @@ -512,7 +513,7 @@ describe('loader', () => { interval: 'm', }, sourceField: 'timestamp', - }, + } as DateHistogramIndexPatternColumn, col2: { dataType: 'number', isBucketed: false, @@ -563,7 +564,7 @@ describe('loader', () => { interval: 'm', }, sourceField: 'timestamp', - }, + } as DateHistogramIndexPatternColumn, col2: { dataType: 'number', isBucketed: false, @@ -650,7 +651,7 @@ describe('loader', () => { interval: 'm', }, sourceField: 'timestamp', - }, + } as DateHistogramIndexPatternColumn, col2: { dataType: 'number', isBucketed: false, @@ -870,7 +871,7 @@ describe('loader', () => { interval: 'm', }, sourceField: 'timestamp', - }, + } as DateHistogramIndexPatternColumn, }, indexPatternId: '1', }, diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions.test.ts b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions.test.ts index c131b16512823..974e37c2aea8e 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions.test.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions.test.ts @@ -19,7 +19,8 @@ import { import { getFieldByNameFactory } from '../pure_helpers'; import { documentField } from '../document_field'; import { IndexPattern, IndexPatternLayer, IndexPatternField } from '../types'; -import { IndexPatternColumn } from '.'; +import { GenericIndexPatternColumn } from '.'; +import { DateHistogramIndexPatternColumn } from './definitions/date_histogram'; const indexPatternFields = [ { @@ -77,7 +78,7 @@ const indexPattern = { }; const baseColumnArgs: { - previousColumn: IndexPatternColumn; + previousColumn: GenericIndexPatternColumn; indexPattern: IndexPattern; layer: IndexPatternLayer; field: IndexPatternField; @@ -113,7 +114,7 @@ const layer: IndexPatternLayer = { operationType: 'date_histogram', sourceField: 'timestamp', params: { interval: 'auto' }, - }, + } as DateHistogramIndexPatternColumn, metric: { label: 'metricLabel', customLabel: true, diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/calculations/utils.test.ts b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/calculations/utils.test.ts index 8b1eaeb109d9b..1dacb334413f8 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/calculations/utils.test.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/calculations/utils.test.ts @@ -9,6 +9,7 @@ import { checkReferences, checkForDataLayerType } from './utils'; import { operationDefinitionMap } from '..'; import { createMockedFullReference } from '../../mocks'; import { layerTypes } from '../../../../../common'; +import { DateHistogramIndexPatternColumn } from '../date_histogram'; // Mock prevents issue with circular loading jest.mock('..'); @@ -35,7 +36,6 @@ describe('utils', () => { columns: { ref: { label: 'Label', - // @ts-expect-error test-only operation type operationType: 'testReference', isBucketed: false, dataType: 'number', @@ -57,7 +57,6 @@ describe('utils', () => { columns: { ref: { label: 'Label', - // @ts-expect-error test-only operation type operationType: 'testReference', isBucketed: false, dataType: 'number', @@ -70,7 +69,7 @@ describe('utils', () => { dataType: 'date', sourceField: 'timestamp', params: { interval: 'auto' }, - }, + } as DateHistogramIndexPatternColumn, }, columnOrder: ['invalid', 'ref'], indexPatternId: '', diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/column_types.ts b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/column_types.ts index 15bd7d4242b92..233138ef4ff0a 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/column_types.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/column_types.ts @@ -42,6 +42,11 @@ export interface ReferenceBasedIndexPatternColumn references: string[]; } +export type GenericIndexPatternColumn = + | BaseIndexPatternColumn + | FieldBasedIndexPatternColumn + | ReferenceBasedIndexPatternColumn; + // Used to store the temporary invalid state export interface IncompleteColumn { operationType?: OperationType; diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/count.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/count.tsx index a6134ddc67bc0..6290abac77844 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/count.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/count.tsx @@ -11,7 +11,7 @@ import { buildExpressionFunction } from '../../../../../../../src/plugins/expres import { OperationDefinition } from './index'; import { FormattedIndexPatternColumn, FieldBasedIndexPatternColumn } from './column_types'; import { IndexPatternField } from '../../types'; -import { getInvalidFieldMessage, getFilter } from './helpers'; +import { getInvalidFieldMessage, getFilter, isColumnFormatted } from './helpers'; import { adjustTimeScaleLabelSuffix, adjustTimeScaleOnOtherColumnChange, @@ -84,9 +84,8 @@ export const countOperation: OperationDefinition { interval: '42w', }, sourceField: 'timestamp', - }, + } as DateHistogramIndexPatternColumn, }, }; }); @@ -332,7 +332,7 @@ describe('date_histogram', () => { interval: 'd', }, sourceField: 'other_timestamp', - }, + } as DateHistogramIndexPatternColumn, }, }; const instance = shallow( @@ -366,7 +366,7 @@ describe('date_histogram', () => { interval: 'auto', }, sourceField: 'timestamp', - }, + } as DateHistogramIndexPatternColumn, }, }; @@ -401,7 +401,7 @@ describe('date_histogram', () => { interval: 'auto', }, sourceField: 'timestamp', - }, + } as DateHistogramIndexPatternColumn, }, }; @@ -594,7 +594,7 @@ describe('date_histogram', () => { operationType: 'date_histogram', sourceField: 'missing', params: { interval: 'auto' }, - }, + } as DateHistogramIndexPatternColumn, } ) ).toEqual('Missing field'); diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/date_histogram.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/date_histogram.tsx index ea875c069150d..efc7a10090cfa 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/date_histogram.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/date_histogram.tsx @@ -71,272 +71,275 @@ function getMultipleDateHistogramsErrorMessage(layer: IndexPatternLayer, columnI }); } -export const dateHistogramOperation: OperationDefinition = - { - type: 'date_histogram', - displayName: i18n.translate('xpack.lens.indexPattern.dateHistogram', { - defaultMessage: 'Date histogram', - }), - input: 'field', - priority: 5, // Highest priority level used - operationParams: [{ name: 'interval', type: 'string', required: false }], - getErrorMessage: (layer, columnId, indexPattern) => - [ - ...(getInvalidFieldMessage( - layer.columns[columnId] as FieldBasedIndexPatternColumn, - indexPattern - ) || []), - getMultipleDateHistogramsErrorMessage(layer, columnId) || '', - ].filter(Boolean), - getHelpMessage: (props) => , - getPossibleOperationForField: ({ aggregationRestrictions, aggregatable, type }) => { - if ( - (type === 'date' || type === 'date_range') && - aggregatable && - (!aggregationRestrictions || aggregationRestrictions.date_histogram) - ) { - return { - dataType: 'date', - isBucketed: true, - scale: 'interval', - }; - } - }, - getDefaultLabel: (column, indexPattern) => getSafeName(column.sourceField, indexPattern), - buildColumn({ field }, columnParams) { +export const dateHistogramOperation: OperationDefinition< + DateHistogramIndexPatternColumn, + 'field', + { interval: string } +> = { + type: 'date_histogram', + displayName: i18n.translate('xpack.lens.indexPattern.dateHistogram', { + defaultMessage: 'Date histogram', + }), + input: 'field', + priority: 5, // Highest priority level used + operationParams: [{ name: 'interval', type: 'string', required: false }], + getErrorMessage: (layer, columnId, indexPattern) => + [ + ...(getInvalidFieldMessage( + layer.columns[columnId] as FieldBasedIndexPatternColumn, + indexPattern + ) || []), + getMultipleDateHistogramsErrorMessage(layer, columnId) || '', + ].filter(Boolean), + getHelpMessage: (props) => , + getPossibleOperationForField: ({ aggregationRestrictions, aggregatable, type }) => { + if ( + (type === 'date' || type === 'date_range') && + aggregatable && + (!aggregationRestrictions || aggregationRestrictions.date_histogram) + ) { return { - label: field.displayName, dataType: 'date', - operationType: 'date_histogram', - sourceField: field.name, isBucketed: true, scale: 'interval', - params: { - interval: columnParams?.interval ?? autoInterval, - }, }; - }, - isTransferable: (column, newIndexPattern) => { - const newField = newIndexPattern.getFieldByName(column.sourceField); + } + }, + getDefaultLabel: (column, indexPattern) => getSafeName(column.sourceField, indexPattern), + buildColumn({ field }, columnParams) { + return { + label: field.displayName, + dataType: 'date', + operationType: 'date_histogram', + sourceField: field.name, + isBucketed: true, + scale: 'interval', + params: { + interval: columnParams?.interval ?? autoInterval, + }, + }; + }, + isTransferable: (column, newIndexPattern) => { + const newField = newIndexPattern.getFieldByName(column.sourceField); - return Boolean( - newField && - newField.type === 'date' && - newField.aggregatable && - (!newField.aggregationRestrictions || newField.aggregationRestrictions.date_histogram) - ); - }, - onFieldChange: (oldColumn, field) => { - return { - ...oldColumn, - label: field.displayName, - sourceField: field.name, - }; - }, - toEsAggsFn: (column, columnId, indexPattern) => { - const usedField = indexPattern.getFieldByName(column.sourceField); - let timeZone: string | undefined; - let interval = column.params?.interval ?? autoInterval; - if ( - usedField && - usedField.aggregationRestrictions && - usedField.aggregationRestrictions.date_histogram - ) { - interval = restrictedInterval(usedField.aggregationRestrictions) as string; - timeZone = usedField.aggregationRestrictions.date_histogram.time_zone; - } - return buildExpressionFunction('aggDateHistogram', { - id: columnId, - enabled: true, - schema: 'segment', - field: column.sourceField, - time_zone: timeZone, - useNormalizedEsInterval: !usedField?.aggregationRestrictions?.date_histogram, - interval, - drop_partials: false, - min_doc_count: 0, - extended_bounds: extendedBoundsToAst({}), - }).toAst(); - }, - paramEditor: function ParamEditor({ - layer, - columnId, - currentColumn, - updateLayer, - dateRange, - data, - indexPattern, - }: ParamEditorProps) { - const field = currentColumn && indexPattern.getFieldByName(currentColumn.sourceField); - const intervalIsRestricted = - field!.aggregationRestrictions && field!.aggregationRestrictions.date_histogram; + return Boolean( + newField && + newField.type === 'date' && + newField.aggregatable && + (!newField.aggregationRestrictions || newField.aggregationRestrictions.date_histogram) + ); + }, + onFieldChange: (oldColumn, field) => { + return { + ...oldColumn, + label: field.displayName, + sourceField: field.name, + }; + }, + toEsAggsFn: (column, columnId, indexPattern) => { + const usedField = indexPattern.getFieldByName(column.sourceField); + let timeZone: string | undefined; + let interval = column.params?.interval ?? autoInterval; + if ( + usedField && + usedField.aggregationRestrictions && + usedField.aggregationRestrictions.date_histogram + ) { + interval = restrictedInterval(usedField.aggregationRestrictions) as string; + timeZone = usedField.aggregationRestrictions.date_histogram.time_zone; + } + return buildExpressionFunction('aggDateHistogram', { + id: columnId, + enabled: true, + schema: 'segment', + field: column.sourceField, + time_zone: timeZone, + useNormalizedEsInterval: !usedField?.aggregationRestrictions?.date_histogram, + interval, + drop_partials: false, + min_doc_count: 0, + extended_bounds: extendedBoundsToAst({}), + }).toAst(); + }, + paramEditor: function ParamEditor({ + layer, + columnId, + currentColumn, + updateLayer, + dateRange, + data, + indexPattern, + }: ParamEditorProps) { + const field = currentColumn && indexPattern.getFieldByName(currentColumn.sourceField); + const intervalIsRestricted = + field!.aggregationRestrictions && field!.aggregationRestrictions.date_histogram; - const interval = parseInterval(currentColumn.params.interval); + const interval = parseInterval(currentColumn.params.interval); - // We force the interval value to 1 if it's empty, since that is the ES behavior, - // and the isValidInterval function doesn't handle the empty case properly. Fixing - // isValidInterval involves breaking changes in other areas. - const isValid = isValidInterval( - `${interval.value === '' ? '1' : interval.value}${interval.unit}`, - restrictedInterval(field!.aggregationRestrictions) - ); + // We force the interval value to 1 if it's empty, since that is the ES behavior, + // and the isValidInterval function doesn't handle the empty case properly. Fixing + // isValidInterval involves breaking changes in other areas. + const isValid = isValidInterval( + `${interval.value === '' ? '1' : interval.value}${interval.unit}`, + restrictedInterval(field!.aggregationRestrictions) + ); - function onChangeAutoInterval(ev: EuiSwitchEvent) { - const { fromDate, toDate } = dateRange; - const value = ev.target.checked - ? data.search.aggs.calculateAutoTimeExpression({ from: fromDate, to: toDate }) || '1h' - : autoInterval; - updateLayer(updateColumnParam({ layer, columnId, paramName: 'interval', value })); - } + function onChangeAutoInterval(ev: EuiSwitchEvent) { + const { fromDate, toDate } = dateRange; + const value = ev.target.checked + ? data.search.aggs.calculateAutoTimeExpression({ from: fromDate, to: toDate }) || '1h' + : autoInterval; + updateLayer(updateColumnParam({ layer, columnId, paramName: 'interval', value })); + } - const setInterval = (newInterval: typeof interval) => { - const isCalendarInterval = calendarOnlyIntervals.has(newInterval.unit); - const value = `${isCalendarInterval ? '1' : newInterval.value}${newInterval.unit || 'd'}`; + const setInterval = (newInterval: typeof interval) => { + const isCalendarInterval = calendarOnlyIntervals.has(newInterval.unit); + const value = `${isCalendarInterval ? '1' : newInterval.value}${newInterval.unit || 'd'}`; - updateLayer(updateColumnParam({ layer, columnId, paramName: 'interval', value })); - }; + updateLayer(updateColumnParam({ layer, columnId, paramName: 'interval', value })); + }; - return ( - <> - {!intervalIsRestricted && ( - - - - )} - {currentColumn.params.interval !== autoInterval && ( - + {!intervalIsRestricted && ( + + - {intervalIsRestricted ? ( - - ) : ( - <> - - - { - const newInterval = { - ...interval, - value: e.target.value, - }; - setInterval(newInterval); - }} - /> - - - { - const newInterval = { - ...interval, - unit: e.target.value, - }; - setInterval(newInterval); - }} - isInvalid={!isValid} - options={[ - { - value: 'ms', - text: i18n.translate( - 'xpack.lens.indexPattern.dateHistogram.milliseconds', - { - defaultMessage: 'milliseconds', - } - ), - }, - { - value: 's', - text: i18n.translate('xpack.lens.indexPattern.dateHistogram.seconds', { - defaultMessage: 'seconds', - }), - }, - { - value: 'm', - text: i18n.translate('xpack.lens.indexPattern.dateHistogram.minutes', { - defaultMessage: 'minutes', - }), - }, - { - value: 'h', - text: i18n.translate('xpack.lens.indexPattern.dateHistogram.hours', { - defaultMessage: 'hours', - }), - }, - { - value: 'd', - text: i18n.translate('xpack.lens.indexPattern.dateHistogram.days', { - defaultMessage: 'days', - }), - }, - { - value: 'w', - text: i18n.translate('xpack.lens.indexPattern.dateHistogram.week', { - defaultMessage: 'week', - }), - }, - { - value: 'M', - text: i18n.translate('xpack.lens.indexPattern.dateHistogram.month', { - defaultMessage: 'month', - }), - }, - // Quarterly intervals appear to be unsupported by esaggs - { - value: 'y', - text: i18n.translate('xpack.lens.indexPattern.dateHistogram.year', { - defaultMessage: 'year', - }), - }, - ]} - /> - - - {!isValid && ( - <> - - - {i18n.translate('xpack.lens.indexPattern.invalidInterval', { - defaultMessage: 'Invalid interval value', - })} - - - )} - - )} - - )} - - ); - }, - }; + checked={currentColumn.params.interval !== autoInterval} + onChange={onChangeAutoInterval} + compressed + /> + + )} + {currentColumn.params.interval !== autoInterval && ( + + {intervalIsRestricted ? ( + + ) : ( + <> + + + { + const newInterval = { + ...interval, + value: e.target.value, + }; + setInterval(newInterval); + }} + /> + + + { + const newInterval = { + ...interval, + unit: e.target.value, + }; + setInterval(newInterval); + }} + isInvalid={!isValid} + options={[ + { + value: 'ms', + text: i18n.translate( + 'xpack.lens.indexPattern.dateHistogram.milliseconds', + { + defaultMessage: 'milliseconds', + } + ), + }, + { + value: 's', + text: i18n.translate('xpack.lens.indexPattern.dateHistogram.seconds', { + defaultMessage: 'seconds', + }), + }, + { + value: 'm', + text: i18n.translate('xpack.lens.indexPattern.dateHistogram.minutes', { + defaultMessage: 'minutes', + }), + }, + { + value: 'h', + text: i18n.translate('xpack.lens.indexPattern.dateHistogram.hours', { + defaultMessage: 'hours', + }), + }, + { + value: 'd', + text: i18n.translate('xpack.lens.indexPattern.dateHistogram.days', { + defaultMessage: 'days', + }), + }, + { + value: 'w', + text: i18n.translate('xpack.lens.indexPattern.dateHistogram.week', { + defaultMessage: 'week', + }), + }, + { + value: 'M', + text: i18n.translate('xpack.lens.indexPattern.dateHistogram.month', { + defaultMessage: 'month', + }), + }, + // Quarterly intervals appear to be unsupported by esaggs + { + value: 'y', + text: i18n.translate('xpack.lens.indexPattern.dateHistogram.year', { + defaultMessage: 'year', + }), + }, + ]} + /> + + + {!isValid && ( + <> + + + {i18n.translate('xpack.lens.indexPattern.invalidInterval', { + defaultMessage: 'Invalid interval value', + })} + + + )} + + )} + + )} + + ); + }, +}; function parseInterval(currentInterval: string) { const interval = currentInterval || ''; diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/filters.test.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/filters.test.tsx index 640ea3a1a41f6..b215e6ed7e318 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/filters.test.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/filters.test.tsx @@ -74,7 +74,7 @@ describe('filters', () => { }, ], }, - }, + } as FiltersIndexPatternColumn, col2: { label: 'Count', dataType: 'number', diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/editor/formula_help.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/editor/formula_help.tsx index 47dd8fbc9c569..203774c6b1561 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/editor/formula_help.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/editor/formula_help.tsx @@ -28,7 +28,7 @@ import { hasFunctionFieldArgument } from '../validation'; import type { GenericOperationDefinition, - IndexPatternColumn, + GenericIndexPatternColumn, OperationDefinition, ParamEditorProps, } from '../../index'; @@ -503,7 +503,7 @@ export function getFunctionSignatureLabel( function getFunctionArgumentsStringified( params: Required< - OperationDefinition + OperationDefinition >['operationParams'] ) { return params diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula.test.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula.test.tsx index d3dc8e95933a3..93df78ec3f5ff 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula.test.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula.test.tsx @@ -6,15 +6,18 @@ */ import { createMockedIndexPattern } from '../../../mocks'; -import { formulaOperation, GenericOperationDefinition, IndexPatternColumn } from '../index'; +import { formulaOperation, GenericOperationDefinition, GenericIndexPatternColumn } from '../index'; import { FormulaIndexPatternColumn } from './formula'; import { regenerateLayerFromAst } from './parse'; import type { IndexPattern, IndexPatternField, IndexPatternLayer } from '../../../types'; import { tinymathFunctions } from './util'; +import { TermsIndexPatternColumn } from '../terms'; +import { MovingAverageIndexPatternColumn } from '../calculations'; +import { StaticValueIndexPatternColumn } from '../static_value'; jest.mock('../../layer_helpers', () => { return { - getColumnOrder: jest.fn(({ columns }: { columns: Record }) => + getColumnOrder: jest.fn(({ columns }: { columns: Record }) => Object.keys(columns) ), getManagedColumnsFrom: jest.fn().mockReturnValue([]), @@ -113,7 +116,7 @@ describe('formula', () => { orderDirection: 'asc', }, sourceField: 'category', - }, + } as TermsIndexPatternColumn, }, }; }); @@ -191,7 +194,7 @@ describe('formula', () => { }, }, }, - } as IndexPatternColumn, + } as GenericIndexPatternColumn, layer, indexPattern, }) @@ -225,7 +228,7 @@ describe('formula', () => { // Need to test with multiple replaces due to string replace query: `category.keyword: "Men's Clothing" or category.keyword: "Men's Shoes"`, }, - } as IndexPatternColumn, + } as GenericIndexPatternColumn, layer, indexPattern, }) @@ -254,7 +257,7 @@ describe('formula', () => { language: 'lucene', query: `*`, }, - } as IndexPatternColumn, + } as GenericIndexPatternColumn, layer, indexPattern, }) @@ -285,7 +288,7 @@ describe('formula', () => { references: ['col2'], timeScale: 'd', params: { window: 3 }, - }, + } as MovingAverageIndexPatternColumn, layer: { indexPatternId: '1', columnOrder: [], @@ -299,7 +302,7 @@ describe('formula', () => { references: ['col2'], timeScale: 'd', params: { window: 3 }, - }, + } as MovingAverageIndexPatternColumn, col2: { dataType: 'number', isBucketed: false, @@ -345,7 +348,7 @@ describe('formula', () => { orderDirection: 'asc', }, sourceField: 'category', - }, + } as TermsIndexPatternColumn, layer: { indexPatternId: '1', columnOrder: [], @@ -361,7 +364,7 @@ describe('formula', () => { orderDirection: 'asc', }, sourceField: 'category', - }, + } as TermsIndexPatternColumn, }, }, indexPattern, @@ -392,7 +395,7 @@ describe('formula', () => { params: { value: '0', }, - }, + } as StaticValueIndexPatternColumn, layer, indexPattern, }) @@ -668,7 +671,7 @@ describe('formula', () => { scale: 'ratio', params: { formula, isFormulaBroken: isBroken }, references: [], - }, + } as FormulaIndexPatternColumn, }, columnOrder: [], indexPatternId: '', diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula.tsx index 511f18415272e..5842cde4fea31 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula.tsx @@ -15,6 +15,7 @@ import { regenerateLayerFromAst } from './parse'; import { generateFormula } from './generate'; import { filterByVisibleOperation } from './util'; import { getManagedColumnsFrom } from '../../layer_helpers'; +import { isColumnFormatted } from '../helpers'; const defaultLabel = i18n.translate('xpack.lens.indexPattern.formulaLabel', { defaultMessage: 'Formula', @@ -120,8 +121,8 @@ export const formulaOperation: OperationDefinition>; @@ -33,12 +35,12 @@ export function getSafeFieldName({ } export function generateFormula( - previousColumn: ReferenceBasedIndexPatternColumn | IndexPatternColumn, + previousColumn: ReferenceBasedIndexPatternColumn | GenericIndexPatternColumn, layer: IndexPatternLayer, previousFormula: string, operationDefinitionMap: Record | undefined ) { - if (previousColumn.operationType === 'static_value') { + if (isColumnOfType('static_value', previousColumn)) { if (previousColumn.params && 'value' in previousColumn.params) { return String(previousColumn.params.value); // make sure it's a string } @@ -81,17 +83,25 @@ export function generateFormula( return previousFormula; } +interface ParameterizedColumn extends BaseIndexPatternColumn { + params: OperationParams; +} + +function isParameterizedColumn(col: GenericIndexPatternColumn): col is ParameterizedColumn { + return Boolean('params' in col && col.params); +} + function extractParamsForFormula( - column: IndexPatternColumn | ReferenceBasedIndexPatternColumn, + column: GenericIndexPatternColumn, operationDefinitionMap: Record | undefined ) { if (!operationDefinitionMap) { return []; } const def = operationDefinitionMap[column.operationType]; - if ('operationParams' in def && column.params) { + if ('operationParams' in def && isParameterizedColumn(column)) { return (def.operationParams || []).flatMap(({ name, required }) => { - const value = (column.params as OperationParams)![name]; + const value = column.params[name]; if (isObject(value)) { return Object.keys(value).map((subName) => ({ name: `${name}-${subName}`, diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/parse.ts b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/parse.ts index adccecc875c22..ead2467416ce2 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/parse.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/parse.ts @@ -8,7 +8,11 @@ import { i18n } from '@kbn/i18n'; import { isObject } from 'lodash'; import type { TinymathAST, TinymathVariable, TinymathLocation } from '@kbn/tinymath'; -import { OperationDefinition, GenericOperationDefinition, IndexPatternColumn } from '../index'; +import { + OperationDefinition, + GenericOperationDefinition, + GenericIndexPatternColumn, +} from '../index'; import { IndexPattern, IndexPatternLayer } from '../../../types'; import { mathOperation } from './math'; import { documentField } from '../../../document_field'; @@ -67,8 +71,8 @@ function extractColumns( layer: IndexPatternLayer, indexPattern: IndexPattern, label: string -): Array<{ column: IndexPatternColumn; location?: TinymathLocation }> { - const columns: Array<{ column: IndexPatternColumn; location?: TinymathLocation }> = []; +): Array<{ column: GenericIndexPatternColumn; location?: TinymathLocation }> { + const columns: Array<{ column: GenericIndexPatternColumn; location?: TinymathLocation }> = []; function parseNode(node: TinymathAST) { if (typeof node === 'number' || node.type !== 'function') { @@ -102,7 +106,7 @@ function extractColumns( const mappedParams = getOperationParams(nodeOperation, namedArguments || []); const newCol = ( - nodeOperation as OperationDefinition + nodeOperation as OperationDefinition ).buildColumn( { layer, @@ -139,7 +143,7 @@ function extractColumns( const mappedParams = getOperationParams(nodeOperation, namedArguments || []); const newCol = ( - nodeOperation as OperationDefinition + nodeOperation as OperationDefinition ).buildColumn( { layer, @@ -227,7 +231,7 @@ export function regenerateLayerFromAst( isFormulaBroken: !isValid, }, references: !isValid ? [] : [getManagedId(columnId, extracted.length - 1)], - }; + } as FormulaIndexPatternColumn; return { newLayer: { diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/util.ts b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/util.ts index f1530ba46caef..db267bfb0d564 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/util.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/util.ts @@ -13,7 +13,11 @@ import type { TinymathNamedArgument, TinymathVariable, } from 'packages/kbn-tinymath'; -import type { OperationDefinition, IndexPatternColumn, GenericOperationDefinition } from '../index'; +import type { + OperationDefinition, + GenericIndexPatternColumn, + GenericOperationDefinition, +} from '../index'; import type { GroupedNodes } from './types'; export const unquotedStringRegex = /[^0-9A-Za-z._@\[\]/]/; @@ -46,8 +50,8 @@ export function getValueOrName(node: TinymathAST) { export function getOperationParams( operation: - | OperationDefinition - | OperationDefinition, + | OperationDefinition + | OperationDefinition, params: TinymathNamedArgument[] = [] ): Record { const formalArgs: Record = (operation.operationParams || []).reduce( diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/validation.ts b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/validation.ts index 1a8d8529a9b90..d6b9a1fff8e9d 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/validation.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/validation.ts @@ -20,7 +20,11 @@ import { tinymathFunctions, } from './util'; -import type { OperationDefinition, IndexPatternColumn, GenericOperationDefinition } from '../index'; +import type { + OperationDefinition, + GenericIndexPatternColumn, + GenericOperationDefinition, +} from '../index'; import type { IndexPattern, IndexPatternLayer } from '../../../types'; import type { TinymathNodeTypes } from './types'; import { parseTimeShift } from '../../../../../../../../src/plugins/data/common'; @@ -482,8 +486,8 @@ function checkSingleQuery(namedArguments: TinymathNamedArgument[] | undefined) { function validateNameArguments( node: TinymathFunction, nodeOperation: - | OperationDefinition - | OperationDefinition, + | OperationDefinition + | OperationDefinition, namedArguments: TinymathNamedArgument[] | undefined, indexPattern: IndexPattern ) { @@ -749,16 +753,16 @@ function runFullASTValidation( export function canHaveParams( operation: - | OperationDefinition - | OperationDefinition + | OperationDefinition + | OperationDefinition ) { return Boolean((operation.operationParams || []).length) || operation.filterable; } export function getInvalidParams( operation: - | OperationDefinition - | OperationDefinition, + | OperationDefinition + | OperationDefinition, params: TinymathNamedArgument[] = [] ) { return validateParams(operation, params).filter( @@ -768,8 +772,8 @@ export function getInvalidParams( export function getMissingParams( operation: - | OperationDefinition - | OperationDefinition, + | OperationDefinition + | OperationDefinition, params: TinymathNamedArgument[] = [] ) { return validateParams(operation, params).filter( @@ -779,8 +783,8 @@ export function getMissingParams( export function getWrongTypeParams( operation: - | OperationDefinition - | OperationDefinition, + | OperationDefinition + | OperationDefinition, params: TinymathNamedArgument[] = [] ) { return validateParams(operation, params).filter( @@ -789,7 +793,7 @@ export function getWrongTypeParams( } function getReturnedType( - operation: OperationDefinition, + operation: OperationDefinition, indexPattern: IndexPattern, firstArg: TinymathAST ) { @@ -822,8 +826,8 @@ function getDuplicateParams(params: TinymathNamedArgument[] = []) { export function validateParams( operation: - | OperationDefinition - | OperationDefinition, + | OperationDefinition + | OperationDefinition, params: TinymathNamedArgument[] = [] ) { const paramsObj = getOperationParams(operation, params); diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/helpers.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/helpers.tsx index a399183694863..9b22ef02fb3b5 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/helpers.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/helpers.tsx @@ -6,8 +6,12 @@ */ import { i18n } from '@kbn/i18n'; -import { IndexPatternColumn, operationDefinitionMap } from '.'; -import { FieldBasedIndexPatternColumn, ReferenceBasedIndexPatternColumn } from './column_types'; +import { GenericIndexPatternColumn, operationDefinitionMap } from '.'; +import { + FieldBasedIndexPatternColumn, + FormattedIndexPatternColumn, + ReferenceBasedIndexPatternColumn, +} from './column_types'; import { IndexPattern } from '../../types'; export function getInvalidFieldMessage( @@ -36,7 +40,7 @@ export function getInvalidFieldMessage( operationDefinition && field && !operationDefinition.isTransferable( - column as IndexPatternColumn, + column as GenericIndexPatternColumn, indexPattern, operationDefinitionMap ) @@ -90,19 +94,35 @@ export function isValidNumber( ); } +export function isColumnOfType( + type: C['operationType'], + column: GenericIndexPatternColumn +): column is C { + return column.operationType === type; +} + +export function isColumnFormatted( + column: GenericIndexPatternColumn +): column is FormattedIndexPatternColumn { + return Boolean( + 'params' in column && + (column as FormattedIndexPatternColumn).params && + 'format' in (column as FormattedIndexPatternColumn).params! + ); +} + export function getFormatFromPreviousColumn( - previousColumn: IndexPatternColumn | ReferenceBasedIndexPatternColumn | undefined + previousColumn: GenericIndexPatternColumn | ReferenceBasedIndexPatternColumn | undefined ) { return previousColumn?.dataType === 'number' && - previousColumn.params && - 'format' in previousColumn.params && - previousColumn.params.format + isColumnFormatted(previousColumn) && + previousColumn.params ? { format: previousColumn.params.format } : undefined; } export function getFilter( - previousColumn: IndexPatternColumn | undefined, + previousColumn: GenericIndexPatternColumn | undefined, columnParams: { kql?: string | undefined; lucene?: string | undefined } | undefined ) { let filter = previousColumn?.filter; diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/index.ts b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/index.ts index 5898cfc26d88c..f18bdb9498f25 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/index.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/index.ts @@ -7,93 +7,51 @@ import { IUiSettingsClient, SavedObjectsClientContract, HttpSetup, CoreStart } from 'kibana/public'; import { IStorageWrapper } from 'src/plugins/kibana_utils/public'; -import { termsOperation, TermsIndexPatternColumn } from './terms'; -import { filtersOperation, FiltersIndexPatternColumn } from './filters'; -import { cardinalityOperation, CardinalityIndexPatternColumn } from './cardinality'; -import { percentileOperation, PercentileIndexPatternColumn } from './percentile'; +import { termsOperation } from './terms'; +import { filtersOperation } from './filters'; +import { cardinalityOperation } from './cardinality'; +import { percentileOperation } from './percentile'; import { minOperation, - MinIndexPatternColumn, averageOperation, - AvgIndexPatternColumn, sumOperation, - SumIndexPatternColumn, maxOperation, - MaxIndexPatternColumn, medianOperation, - MedianIndexPatternColumn, } from './metrics'; -import { dateHistogramOperation, DateHistogramIndexPatternColumn } from './date_histogram'; +import { dateHistogramOperation } from './date_histogram'; import { cumulativeSumOperation, - CumulativeSumIndexPatternColumn, counterRateOperation, - CounterRateIndexPatternColumn, derivativeOperation, - DerivativeIndexPatternColumn, movingAverageOperation, - MovingAverageIndexPatternColumn, - OverallSumIndexPatternColumn, overallSumOperation, - OverallMinIndexPatternColumn, overallMinOperation, - OverallMaxIndexPatternColumn, overallMaxOperation, - OverallAverageIndexPatternColumn, overallAverageOperation, } from './calculations'; -import { countOperation, CountIndexPatternColumn } from './count'; -import { - mathOperation, - MathIndexPatternColumn, - formulaOperation, - FormulaIndexPatternColumn, -} from './formula'; -import { staticValueOperation, StaticValueIndexPatternColumn } from './static_value'; -import { lastValueOperation, LastValueIndexPatternColumn } from './last_value'; +import { countOperation } from './count'; +import { mathOperation, formulaOperation } from './formula'; +import { staticValueOperation } from './static_value'; +import { lastValueOperation } from './last_value'; import { FrameDatasourceAPI, OperationMetadata, ParamEditorCustomProps } from '../../../types'; -import type { BaseIndexPatternColumn, ReferenceBasedIndexPatternColumn } from './column_types'; +import type { + BaseIndexPatternColumn, + GenericIndexPatternColumn, + ReferenceBasedIndexPatternColumn, +} from './column_types'; import { IndexPattern, IndexPatternField, IndexPatternLayer } from '../../types'; import { DateRange, LayerType } from '../../../../common'; import { ExpressionAstFunction } from '../../../../../../../src/plugins/expressions/public'; import { DataPublicPluginStart } from '../../../../../../../src/plugins/data/public'; -import { RangeIndexPatternColumn, rangeOperation } from './ranges'; +import { rangeOperation } from './ranges'; import { IndexPatternDimensionEditorProps } from '../../dimension_panel'; -/** - * A union type of all available column types. If a column is of an unknown type somewhere - * withing the indexpattern data source it should be typed as `IndexPatternColumn` to make - * typeguards possible that consider all available column types. - */ -export type IndexPatternColumn = - | FiltersIndexPatternColumn - | RangeIndexPatternColumn - | TermsIndexPatternColumn - | DateHistogramIndexPatternColumn - | MinIndexPatternColumn - | MaxIndexPatternColumn - | AvgIndexPatternColumn - | CardinalityIndexPatternColumn - | SumIndexPatternColumn - | MedianIndexPatternColumn - | PercentileIndexPatternColumn - | CountIndexPatternColumn - | LastValueIndexPatternColumn - | CumulativeSumIndexPatternColumn - | OverallSumIndexPatternColumn - | OverallMinIndexPatternColumn - | OverallMaxIndexPatternColumn - | OverallAverageIndexPatternColumn - | CounterRateIndexPatternColumn - | DerivativeIndexPatternColumn - | MovingAverageIndexPatternColumn - | MathIndexPatternColumn - | FormulaIndexPatternColumn - | StaticValueIndexPatternColumn; - -export type FieldBasedIndexPatternColumn = Extract; - -export type { IncompleteColumn } from './column_types'; +export type { + IncompleteColumn, + BaseIndexPatternColumn, + GenericIndexPatternColumn, + FieldBasedIndexPatternColumn, +} from './column_types'; export type { TermsIndexPatternColumn } from './terms'; export type { FiltersIndexPatternColumn } from './filters'; @@ -125,7 +83,7 @@ export type { StaticValueIndexPatternColumn } from './static_value'; // List of all operation definitions registered to this data source. // If you want to implement a new operation, add the definition to this array and -// the column type to the `IndexPatternColumn` union type below. +// the column type to the `GenericIndexPatternColumn` union type below. const internalOperationDefinitions = [ filtersOperation, termsOperation, @@ -227,7 +185,7 @@ interface BaseOperationDefinitionProps { getDefaultLabel: ( column: C, indexPattern: IndexPattern, - columns: Record + columns: Record ) => string; /** * This function is called if another column in the same layer changed or got added/removed. @@ -337,7 +295,7 @@ interface OperationParam { defaultValue?: string | number; } -interface FieldlessOperationDefinition { +interface FieldlessOperationDefinition { input: 'none'; /** @@ -350,9 +308,9 @@ interface FieldlessOperationDefinition { */ buildColumn: ( arg: BaseBuildColumnArgs & { - previousColumn?: IndexPatternColumn; + previousColumn?: GenericIndexPatternColumn; }, - columnParams?: (IndexPatternColumn & C)['params'] + columnParams?: P ) => C; /** * Returns the meta data of the operation if applied. Undefined @@ -372,7 +330,7 @@ interface FieldlessOperationDefinition { ) => ExpressionAstFunction; } -interface FieldBasedOperationDefinition { +interface FieldBasedOperationDefinition { input: 'field'; /** @@ -391,9 +349,9 @@ interface FieldBasedOperationDefinition { buildColumn: ( arg: BaseBuildColumnArgs & { field: IndexPatternField; - previousColumn?: IndexPatternColumn; + previousColumn?: GenericIndexPatternColumn; }, - columnParams?: (IndexPatternColumn & C)['params'] & { + columnParams?: P & { kql?: string; lucene?: string; shift?: string; @@ -498,7 +456,7 @@ interface FullReferenceOperationDefinition { buildColumn: ( arg: BaseBuildColumnArgs & { referenceIds: string[]; - previousColumn?: IndexPatternColumn; + previousColumn?: GenericIndexPatternColumn; }, columnParams?: (ReferenceBasedIndexPatternColumn & C)['params'] & { kql?: string; @@ -528,7 +486,7 @@ interface ManagedReferenceOperationDefinition */ buildColumn: ( arg: BaseBuildColumnArgs & { - previousColumn?: IndexPatternColumn | ReferenceBasedIndexPatternColumn; + previousColumn?: GenericIndexPatternColumn; }, columnParams?: (ReferenceBasedIndexPatternColumn & C)['params'], operationDefinitionMap?: Record @@ -559,9 +517,9 @@ interface ManagedReferenceOperationDefinition ) => IndexPatternLayer; } -interface OperationDefinitionMap { - field: FieldBasedOperationDefinition; - none: FieldlessOperationDefinition; +interface OperationDefinitionMap { + field: FieldBasedOperationDefinition; + none: FieldlessOperationDefinition; fullReference: FullReferenceOperationDefinition; managedReference: ManagedReferenceOperationDefinition; } @@ -573,24 +531,25 @@ interface OperationDefinitionMap { */ export type OperationDefinition< C extends BaseIndexPatternColumn, - Input extends keyof OperationDefinitionMap -> = BaseOperationDefinitionProps & OperationDefinitionMap[Input]; + Input extends keyof OperationDefinitionMap, + P = {} +> = BaseOperationDefinitionProps & OperationDefinitionMap[Input]; /** * A union type of all available operation types. The operation type is a unique id of an operation. * Each column is assigned to exactly one operation type. */ -export type OperationType = typeof internalOperationDefinitions[number]['type']; +export type OperationType = string; /** * This is an operation definition of an unspecified column out of all possible * column types. */ export type GenericOperationDefinition = - | OperationDefinition - | OperationDefinition - | OperationDefinition - | OperationDefinition; + | OperationDefinition + | OperationDefinition + | OperationDefinition + | OperationDefinition; /** * List of all available operation definitions diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/last_value.test.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/last_value.test.tsx index 13e16fe1af4d0..26074b47e0f48 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/last_value.test.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/last_value.test.tsx @@ -15,6 +15,7 @@ import { createMockedIndexPattern } from '../../mocks'; import { LastValueIndexPatternColumn } from './last_value'; import { lastValueOperation } from './index'; import type { IndexPattern, IndexPatternLayer } from '../../types'; +import { TermsIndexPatternColumn } from './terms'; const uiSettingsMock = {} as IUiSettingsClient; @@ -56,7 +57,7 @@ describe('last_value', () => { orderDirection: 'asc', }, sourceField: 'category', - }, + } as TermsIndexPatternColumn, col2: { label: 'Last value of a', dataType: 'number', @@ -66,7 +67,7 @@ describe('last_value', () => { params: { sortField: 'datefield', }, - }, + } as LastValueIndexPatternColumn, }, }; }); @@ -467,7 +468,7 @@ describe('last_value', () => { params: { sortField: 'timestamp' }, scale: 'ratio', sourceField: 'bytes', - }, + } as LastValueIndexPatternColumn, }, columnOrder: [], indexPatternId: '', @@ -499,7 +500,7 @@ describe('last_value', () => { col1: { ...errorLayer.columns.col1, params: { - ...errorLayer.columns.col1.params, + ...(errorLayer.columns.col1 as LastValueIndexPatternColumn).params, sortField: 'notExisting', }, } as LastValueIndexPatternColumn, @@ -530,7 +531,7 @@ describe('last_value', () => { col1: { ...errorLayer.columns.col1, params: { - ...errorLayer.columns.col1.params, + ...(errorLayer.columns.col1 as LastValueIndexPatternColumn).params, sortField: 'bytes', }, } as LastValueIndexPatternColumn, diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/percentile.test.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/percentile.test.tsx index 61f2390820067..a8851c79be2ae 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/percentile.test.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/percentile.test.tsx @@ -17,6 +17,7 @@ import { PercentileIndexPatternColumn } from './percentile'; import { EuiFieldNumber } from '@elastic/eui'; import { act } from 'react-dom/test-utils'; import { EuiFormRow } from '@elastic/eui'; +import { TermsIndexPatternColumn } from './terms'; const uiSettingsMock = {} as IUiSettingsClient; @@ -58,7 +59,7 @@ describe('percentile', () => { orderDirection: 'asc', }, sourceField: 'category', - }, + } as TermsIndexPatternColumn, col2: { label: '23rd percentile of a', dataType: 'number', @@ -68,7 +69,7 @@ describe('percentile', () => { params: { percentile: 23, }, - }, + } as PercentileIndexPatternColumn, }, }; }); diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/percentile.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/percentile.tsx index 9c9f7e8b66a1f..3aaeb9d944728 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/percentile.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/percentile.tsx @@ -17,6 +17,7 @@ import { getSafeName, isValidNumber, getFilter, + isColumnOfType, } from './helpers'; import { FieldBasedIndexPatternColumn } from './column_types'; import { adjustTimeScaleLabelSuffix } from '../time_scale_utils'; @@ -53,7 +54,11 @@ const DEFAULT_PERCENTILE_VALUE = 95; const supportedFieldTypes = ['number', 'histogram']; -export const percentileOperation: OperationDefinition = { +export const percentileOperation: OperationDefinition< + PercentileIndexPatternColumn, + 'field', + { percentile: number } +> = { type: 'percentile', displayName: i18n.translate('xpack.lens.indexPattern.percentile', { defaultMessage: 'Percentile', @@ -91,9 +96,8 @@ export const percentileOperation: OperationDefinition { const existingPercentileParam = - previousColumn?.operationType === 'percentile' && - previousColumn.params && - 'percentile' in previousColumn.params && + previousColumn && + isColumnOfType('percentile', previousColumn) && previousColumn.params.percentile; const newPercentileParam = columnParams?.percentile ?? (existingPercentileParam || DEFAULT_PERCENTILE_VALUE); @@ -174,7 +178,7 @@ export const percentileOperation: OperationDefinition { ranges: [{ from: 0, to: DEFAULT_INTERVAL, label: '' }], maxBars: 'auto', }, - }, + } as RangeIndexPatternColumn, col2: { label: 'Count', dataType: 'number', @@ -385,10 +385,10 @@ describe('ranges', () => { col1: { ...layer.columns.col1, params: { - ...layer.columns.col1.params, + ...(layer.columns.col1 as RangeIndexPatternColumn).params, maxBars: MAX_HISTOGRAM_VALUE, }, - }, + } as RangeIndexPatternColumn, }, }); }); @@ -424,7 +424,7 @@ describe('ranges', () => { col1: { ...layer.columns.col1, params: { - ...layer.columns.col1.params, + ...(layer.columns.col1 as RangeIndexPatternColumn).params, maxBars: GRANULARITY_DEFAULT_VALUE - GRANULARITY_STEP, }, }, @@ -448,7 +448,7 @@ describe('ranges', () => { col1: { ...layer.columns.col1, params: { - ...layer.columns.col1.params, + ...(layer.columns.col1 as RangeIndexPatternColumn).params, maxBars: GRANULARITY_DEFAULT_VALUE, }, }, @@ -511,7 +511,10 @@ describe('ranges', () => { currentColumn={ { ...layer.columns.col1, - params: { ...layer.columns.col1.params, parentFormat: undefined }, + params: { + ...(layer.columns.col1 as RangeIndexPatternColumn).params, + parentFormat: undefined, + }, } as RangeIndexPatternColumn } /> @@ -565,7 +568,7 @@ describe('ranges', () => { col1: { ...layer.columns.col1, params: { - ...layer.columns.col1.params, + ...(layer.columns.col1 as RangeIndexPatternColumn).params, ranges: [ { from: 0, to: DEFAULT_INTERVAL, label: '' }, { from: 50, to: Infinity, label: '' }, @@ -620,7 +623,7 @@ describe('ranges', () => { col1: { ...layer.columns.col1, params: { - ...layer.columns.col1.params, + ...(layer.columns.col1 as RangeIndexPatternColumn).params, ranges: [ { from: 0, to: DEFAULT_INTERVAL, label: '' }, { from: DEFAULT_INTERVAL, to: Infinity, label: 'customlabel' }, @@ -670,7 +673,7 @@ describe('ranges', () => { col1: { ...layer.columns.col1, params: { - ...layer.columns.col1.params, + ...(layer.columns.col1 as RangeIndexPatternColumn).params, ranges: [{ from: 0, to: 50, label: '' }], }, }, diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/ranges/ranges.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/ranges/ranges.tsx index 6e397a926c7a0..63ec5293ddd79 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/ranges/ranges.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/ranges/ranges.tsx @@ -244,7 +244,7 @@ export const rangeOperation: OperationDefinition { const original = jest.requireActual('lodash'); @@ -65,7 +66,7 @@ describe('static_value', () => { orderDirection: 'asc', }, sourceField: 'category', - }, + } as TermsIndexPatternColumn, col2: { label: 'Static value: 23', dataType: 'number', @@ -75,7 +76,7 @@ describe('static_value', () => { params: { value: '23', }, - }, + } as StaticValueIndexPatternColumn, }, }; }); @@ -256,7 +257,7 @@ describe('static_value', () => { scale: 'ratio', params: { value: '23' }, references: [], - }, + } as StaticValueIndexPatternColumn, }) ).toEqual({ label: 'Static value: 23', @@ -303,7 +304,7 @@ describe('static_value', () => { scale: 'ratio', params: { value: '23' }, references: [], - }, + } as StaticValueIndexPatternColumn, }, { value: '53' } ) @@ -351,7 +352,7 @@ describe('static_value', () => { params: { value: '0', }, - }, + } as StaticValueIndexPatternColumn, }, } as IndexPatternLayer; const instance = shallow( diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/static_value.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/static_value.tsx index b66092e8a48c3..45a35d18873fc 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/static_value.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/static_value.tsx @@ -8,7 +8,7 @@ import React, { useCallback } from 'react'; import { i18n } from '@kbn/i18n'; import { EuiFieldNumber, EuiFormLabel, EuiSpacer } from '@elastic/eui'; import { OperationDefinition } from './index'; -import { ReferenceBasedIndexPatternColumn } from './column_types'; +import { ReferenceBasedIndexPatternColumn, GenericIndexPatternColumn } from './column_types'; import type { IndexPattern } from '../../types'; import { useDebouncedValue } from '../../../shared_components'; import { getFormatFromPreviousColumn, isValidNumber } from './helpers'; @@ -46,6 +46,12 @@ export interface StaticValueIndexPatternColumn extends ReferenceBasedIndexPatter }; } +function isStaticValueColumnLike( + col: GenericIndexPatternColumn +): col is StaticValueIndexPatternColumn { + return Boolean('params' in col && col.params && 'value' in col.params); +} + export const staticValueOperation: OperationDefinition< StaticValueIndexPatternColumn, 'managedReference' @@ -102,8 +108,8 @@ export const staticValueOperation: OperationDefinition< }, buildColumn({ previousColumn, layer, indexPattern }, columnParams, operationDefinitionMap) { const existingStaticValue = - previousColumn?.params && - 'value' in previousColumn.params && + previousColumn && + isStaticValueColumnLike(previousColumn) && isValidNumber(previousColumn.params.value) ? previousColumn.params.value : undefined; diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms/terms.test.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms/terms.test.tsx index 180d5ed5e49b7..9b19ab43473d2 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms/terms.test.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms/terms.test.tsx @@ -20,9 +20,10 @@ import { dataPluginMock } from '../../../../../../../../src/plugins/data/public/ import { createMockedIndexPattern } from '../../../mocks'; import { ValuesInput } from './values_input'; import type { TermsIndexPatternColumn } from '.'; -import { termsOperation } from '../index'; +import { termsOperation, LastValueIndexPatternColumn } from '../index'; import { IndexPattern, IndexPatternLayer } from '../../../types'; import { FrameDatasourceAPI } from '../../../../types'; +import { DateHistogramIndexPatternColumn } from '../date_histogram'; const uiSettingsMock = {} as IUiSettingsClient; @@ -61,7 +62,7 @@ describe('terms', () => { orderDirection: 'asc', }, sourceField: 'source', - }, + } as TermsIndexPatternColumn, col2: { label: 'Count', dataType: 'number', @@ -357,7 +358,7 @@ describe('terms', () => { params: { sortField: 'datefield', }, - }, + } as LastValueIndexPatternColumn, }, columnOrder: [], indexPatternId: '', @@ -472,7 +473,7 @@ describe('terms', () => { params: { sortField: 'time', }, - }, + } as LastValueIndexPatternColumn, }, columnOrder: [], indexPatternId: '', @@ -551,7 +552,7 @@ describe('terms', () => { orderDirection: 'asc', }, sourceField: 'category', - }, + } as TermsIndexPatternColumn, }, columnOrder: [], indexPatternId: '', @@ -583,7 +584,7 @@ describe('terms', () => { orderDirection: 'asc', }, sourceField: 'category', - }, + } as TermsIndexPatternColumn, col1: { label: 'Value of timestamp', dataType: 'date', @@ -595,7 +596,7 @@ describe('terms', () => { interval: 'w', }, sourceField: 'timestamp', - }, + } as DateHistogramIndexPatternColumn, }, columnOrder: [], indexPatternId: '', @@ -627,7 +628,7 @@ describe('terms', () => { orderDirection: 'desc', }, sourceField: 'category', - }, + } as TermsIndexPatternColumn, }, columnOrder: [], indexPatternId: '', @@ -755,7 +756,7 @@ describe('terms', () => { { ...layer.columns.col1, params: { - ...layer.columns.col1.params, + ...(layer.columns.col1 as TermsIndexPatternColumn).params, otherBucket: true, }, } as TermsIndexPatternColumn @@ -783,7 +784,7 @@ describe('terms', () => { ...layer.columns.col1, sourceField: 'bytes', params: { - ...layer.columns.col1.params, + ...(layer.columns.col1 as TermsIndexPatternColumn).params, otherBucket: true, }, } as TermsIndexPatternColumn @@ -1018,7 +1019,7 @@ describe('terms', () => { }, scale: 'ordinal', sourceField: 'bytes', - }, + } as TermsIndexPatternColumn, }, columnOrder: [], indexPatternId: '', diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/index.ts b/x-pack/plugins/lens/public/indexpattern_datasource/operations/index.ts index 86add22b2b8ce..b9d675716c788 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/index.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/index.ts @@ -10,7 +10,9 @@ export * from './layer_helpers'; export * from './time_scale_utils'; export type { OperationType, - IndexPatternColumn, + BaseIndexPatternColumn, + GenericOperationDefinition, + GenericIndexPatternColumn, FieldBasedIndexPatternColumn, IncompleteColumn, RequiredReference, diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/layer_helpers.test.ts b/x-pack/plugins/lens/public/indexpattern_datasource/operations/layer_helpers.test.ts index 3dc0677f3b9b6..66ed0e83c97e4 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/layer_helpers.test.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/layer_helpers.test.ts @@ -21,13 +21,21 @@ import { operationDefinitionMap, OperationType } from '../operations'; import { TermsIndexPatternColumn } from './definitions/terms'; import { DateHistogramIndexPatternColumn } from './definitions/date_histogram'; import { AvgIndexPatternColumn } from './definitions/metrics'; -import type { IndexPattern, IndexPatternLayer } from '../types'; +import type { IndexPattern, IndexPatternLayer, IndexPatternPrivateState } from '../types'; import { documentField } from '../document_field'; import { getFieldByNameFactory } from '../pure_helpers'; import { generateId } from '../../id_generator'; import { createMockedFullReference, createMockedManagedReference } from './mocks'; -import { IndexPatternColumn, OperationDefinition } from './definitions'; +import { + FiltersIndexPatternColumn, + FormulaIndexPatternColumn, + GenericIndexPatternColumn, + MathIndexPatternColumn, + MovingAverageIndexPatternColumn, + OperationDefinition, +} from './definitions'; import { TinymathAST } from 'packages/kbn-tinymath'; +import { CoreStart } from 'kibana/public'; jest.mock('../operations'); jest.mock('../../id_generator'); @@ -292,7 +300,7 @@ describe('state_helpers', () => { params: { interval: 'h', }, - }, + } as DateHistogramIndexPatternColumn, }, }; expect( @@ -323,7 +331,7 @@ describe('state_helpers', () => { params: { interval: 'h', }, - }, + } as DateHistogramIndexPatternColumn, col3: { label: 'Reference', dataType: 'number', @@ -362,7 +370,7 @@ describe('state_helpers', () => { params: { interval: 'h', }, - }, + } as DateHistogramIndexPatternColumn, col3: { label: 'Count of records', dataType: 'document', @@ -458,7 +466,7 @@ describe('state_helpers', () => { params: { interval: 'h', }, - }, + } as DateHistogramIndexPatternColumn, }, }, columnId: 'col2', @@ -488,7 +496,7 @@ describe('state_helpers', () => { params: { interval: 'h', }, - }, + } as DateHistogramIndexPatternColumn, }, }, columnId: 'col2', @@ -520,7 +528,7 @@ describe('state_helpers', () => { orderDirection: 'asc', size: 5, }, - }, + } as TermsIndexPatternColumn, }, }, columnId: 'col2', @@ -598,7 +606,7 @@ describe('state_helpers', () => { params: { interval: 'h', }, - }, + } as DateHistogramIndexPatternColumn, }, }, columnId: 'col2', @@ -680,8 +688,8 @@ describe('state_helpers', () => { layer, indexPattern, columnId: 'col1', - // @ts-expect-error invalid type op: 'testReference', + visualizationGroups: [], }); expect(result.columnOrder).toEqual(['id1', 'col1']); expect(result.columns).toEqual( @@ -700,8 +708,8 @@ describe('state_helpers', () => { col1: { dataType: 'number', isBucketed: false, + label: '', - // @ts-expect-error only in test operationType: 'testReference', references: ['ref1'], }, @@ -745,7 +753,7 @@ describe('state_helpers', () => { params: { interval: 'h', }, - }, + } as DateHistogramIndexPatternColumn, }, }, columnId: 'col2', @@ -848,7 +856,7 @@ describe('state_helpers', () => { params: { interval: 'h', }, - }, + } as DateHistogramIndexPatternColumn, }, }, columnId: 'col1', @@ -878,7 +886,7 @@ describe('state_helpers', () => { params: { interval: 'h', }, - }, + } as DateHistogramIndexPatternColumn, }, }, columnId: 'col1', @@ -914,7 +922,7 @@ describe('state_helpers', () => { params: { interval: 'h', }, - }, + } as DateHistogramIndexPatternColumn, }, }, columnId: 'col1', @@ -948,7 +956,7 @@ describe('state_helpers', () => { params: { interval: 'h', }, - }, + } as DateHistogramIndexPatternColumn, }, incompleteColumns: { col1: { operationType: 'terms' }, @@ -986,7 +994,7 @@ describe('state_helpers', () => { params: { filters: [], }, - }, + } as FiltersIndexPatternColumn, }, }, indexPattern, @@ -1022,7 +1030,7 @@ describe('state_helpers', () => { params: { interval: 'h', }, - }, + } as DateHistogramIndexPatternColumn, }, }, indexPattern, @@ -1058,7 +1066,7 @@ describe('state_helpers', () => { params: { interval: 'h', }, - }, + } as DateHistogramIndexPatternColumn, }, }, indexPattern, @@ -1093,7 +1101,7 @@ describe('state_helpers', () => { params: { interval: 'h', }, - }, + } as DateHistogramIndexPatternColumn, }, }, indexPattern, @@ -1128,7 +1136,7 @@ describe('state_helpers', () => { orderDirection: 'asc', size: 5, }, - }, + } as TermsIndexPatternColumn, }, }, indexPattern, @@ -1160,7 +1168,7 @@ describe('state_helpers', () => { orderDirection: 'asc', size: 5, }, - }, + } as TermsIndexPatternColumn, }, }, indexPattern, @@ -1215,7 +1223,7 @@ describe('state_helpers', () => { scale: 'ratio', params: { isFormulaBroken: false, formula: 'average(bytes)' }, references: [], - }, + } as FormulaIndexPatternColumn, }, }, indexPattern, @@ -1244,7 +1252,7 @@ describe('state_helpers', () => { scale: 'ratio', params: { isFormulaBroken: false, formula: 'average(bytes)' }, references: [], - }, + } as FormulaIndexPatternColumn, }, }, indexPattern, @@ -1490,8 +1498,8 @@ describe('state_helpers', () => { layer, indexPattern, columnId: 'col1', - // @ts-expect-error op: 'testReference', + visualizationGroups: [], }); expect(result.columnOrder).toEqual(['id1', 'col1']); @@ -1531,8 +1539,8 @@ describe('state_helpers', () => { layer, indexPattern, columnId: 'col1', - // @ts-expect-error test only op: 'testReference', + visualizationGroups: [], }); expect(result.columnOrder).toEqual(['col1', 'id1']); @@ -1572,8 +1580,8 @@ describe('state_helpers', () => { layer, indexPattern, columnId: 'col1', - // @ts-expect-error op: 'testReference', + visualizationGroups: [], }); expect(result.incompleteColumns).toEqual({ @@ -1612,8 +1620,8 @@ describe('state_helpers', () => { layer, indexPattern, columnId: 'col1', - // @ts-expect-error op: 'testReference', + visualizationGroups: [], }); expect(result.incompleteColumns).toEqual({}); @@ -1631,8 +1639,8 @@ describe('state_helpers', () => { operationDefinitionMap.secondTest = { input: 'fullReference', displayName: 'Reference test 2', - // @ts-expect-error this type is not statically available type: 'secondTest', + selectionStyle: 'full', requiredReferences: [ { // Any numeric metric that isn't also a reference @@ -1641,7 +1649,6 @@ describe('state_helpers', () => { meta.dataType === 'number' && !meta.isBucketed, }, ], - // @ts-expect-error don't want to define valid arguments buildColumn: jest.fn((args) => { return { label: 'Test reference', @@ -1684,7 +1691,6 @@ describe('state_helpers', () => { dataType: 'number', isBucketed: false, - // @ts-expect-error not a valid type operationType: 'testReference', references: [], }, @@ -1693,7 +1699,6 @@ describe('state_helpers', () => { dataType: 'number', isBucketed: false, - // @ts-expect-error not a valid type operationType: 'testReference', references: ['ref1', 'invalid'], }, @@ -1704,8 +1709,8 @@ describe('state_helpers', () => { layer, indexPattern, columnId: 'output', - // @ts-expect-error not statically available op: 'secondTest', + visualizationGroups: [], }) ).toEqual( expect.objectContaining({ @@ -1738,7 +1743,6 @@ describe('state_helpers', () => { dataType: 'number', isBucketed: false, - // @ts-expect-error not a valid type operationType: 'testReference', references: [], }, @@ -1747,7 +1751,6 @@ describe('state_helpers', () => { dataType: 'number', isBucketed: false, - // @ts-expect-error not a valid type operationType: 'testReference', references: ['ref1', 'invalid'], }, @@ -1757,8 +1760,8 @@ describe('state_helpers', () => { layer, indexPattern, columnId: 'output', - // @ts-expect-error not statically available op: 'secondTest', + visualizationGroups: [], }); expect(layer.columns.output).toEqual( expect.objectContaining({ references: ['ref1', 'invalid'] }) @@ -1787,7 +1790,7 @@ describe('state_helpers', () => { isFormulaBroken: false, }, references: ['formulaX3'], - }, + } as FormulaIndexPatternColumn, formulaX0: { customLabel: true, dataType: 'number' as const, @@ -1802,7 +1805,7 @@ describe('state_helpers', () => { label: 'formulaX1', references: ['formulaX0'], params: { tinymathAst: 'formulaX0' }, - }, + } as MathIndexPatternColumn, formulaX2: { customLabel: true, dataType: 'number' as const, @@ -1811,13 +1814,13 @@ describe('state_helpers', () => { operationType: 'moving_average' as const, params: { window: 5 }, references: ['formulaX1'], - }, + } as MovingAverageIndexPatternColumn, formulaX3: { ...math, label: 'formulaX3', references: ['formulaX2'], params: { tinymathAst: 'formulaX2' }, - }, + } as MathIndexPatternColumn, }, }; @@ -1826,8 +1829,8 @@ describe('state_helpers', () => { layer, indexPattern, columnId: 'source', - // @ts-expect-error not statically available op: 'secondTest', + visualizationGroups: [], }) ).toEqual( expect.objectContaining({ @@ -1854,12 +1857,11 @@ describe('state_helpers', () => { operationType: 'date_histogram' as const, sourceField: 'timestamp', params: { interval: 'auto' }, - }, + } as DateHistogramIndexPatternColumn, output: { label: 'Test reference', dataType: 'number', isBucketed: false, - // @ts-expect-error not a valid type operationType: 'testReference', references: ['fieldReused'], }, @@ -1870,8 +1872,8 @@ describe('state_helpers', () => { layer, indexPattern, columnId: 'output', - // @ts-expect-error not statically available op: 'secondTest', + visualizationGroups: [], }) ).toEqual( expect.objectContaining({ @@ -1922,7 +1924,6 @@ describe('state_helpers', () => { dataType: 'number', isBucketed: false, - // @ts-expect-error not a valid type operationType: 'testReference', references: ['col1'], }, @@ -1967,7 +1968,6 @@ describe('state_helpers', () => { dataType: 'number', isBucketed: false, - // @ts-expect-error not a valid type operationType: 'testReference', references: ['col1'], filter: { language: 'kuery', query: 'bytes > 4000' }, @@ -2113,7 +2113,6 @@ describe('state_helpers', () => { dataType: 'number', isBucketed: false, - // @ts-expect-error not a valid type operationType: 'testReference', references: ['col1'], }, @@ -2281,7 +2280,6 @@ describe('state_helpers', () => { dataType: 'number', isBucketed: false, - // @ts-expect-error not a valid type operationType: 'testReference', references: ['col1'], }, @@ -2310,7 +2308,6 @@ describe('state_helpers', () => { dataType: 'number', isBucketed: false, - // @ts-expect-error not a valid type operationType: 'testReference', references: ['col1'], }, @@ -2356,7 +2353,6 @@ describe('state_helpers', () => { dataType: 'number', isBucketed: false, - // @ts-expect-error not a valid type operationType: 'testReference', references: ['col1'], }, @@ -2365,7 +2361,6 @@ describe('state_helpers', () => { dataType: 'number', isBucketed: false, - // @ts-expect-error not a valid type operationType: 'testReference', references: ['col2'], }, @@ -2469,7 +2464,7 @@ describe('state_helpers', () => { params: { interval: 'h', }, - }, + } as DateHistogramIndexPatternColumn, }, }) ).toEqual(['col1']); @@ -2496,7 +2491,7 @@ describe('state_helpers', () => { }, orderDirection: 'asc', }, - }, + } as TermsIndexPatternColumn, col2: { label: 'Average of bytes', dataType: 'number', @@ -2517,7 +2512,7 @@ describe('state_helpers', () => { params: { interval: '1d', }, - }, + } as DateHistogramIndexPatternColumn, }, }) ).toEqual(['col1', 'col3', 'col2']); @@ -2548,7 +2543,7 @@ describe('state_helpers', () => { params: { interval: 'auto', }, - }, + } as DateHistogramIndexPatternColumn, formula: { label: 'Formula', dataType: 'number', @@ -2560,7 +2555,7 @@ describe('state_helpers', () => { isFormulaBroken: false, }, references: ['math'], - }, + } as FormulaIndexPatternColumn, countX0: { label: 'countX0', dataType: 'number', @@ -2580,8 +2575,7 @@ describe('state_helpers', () => { tinymathAst: { type: 'function', name: 'add', - // @ts-expect-error String args are not valid tinymath, but signals something unique to Lens - args: ['countX0', 'count'], + args: ['countX0', 'count'] as unknown as TinymathAST[], location: { min: 0, max: 17, @@ -2591,7 +2585,7 @@ describe('state_helpers', () => { }, references: ['countX0', 'count'], customLabel: true, - }, + } as MathIndexPatternColumn, }, }) ).toEqual(['date', 'count', 'formula', 'countX0', 'math']); @@ -2679,7 +2673,7 @@ describe('state_helpers', () => { orderDirection: 'asc', size: 3, }, - }, + } as TermsIndexPatternColumn, col2: { dataType: 'number', isBucketed: false, @@ -2713,7 +2707,7 @@ describe('state_helpers', () => { params: { window: 7, }, - }, + } as MovingAverageIndexPatternColumn, col2: { dataType: 'number', isBucketed: false, @@ -2742,7 +2736,7 @@ describe('state_helpers', () => { params: { interval: 'd', }, - }, + } as DateHistogramIndexPatternColumn, col2: { dataType: 'number', isBucketed: false, @@ -2765,10 +2759,10 @@ describe('state_helpers', () => { operationDefinitionMap.date_histogram.transfer = ((oldColumn) => ({ ...oldColumn, params: { - ...oldColumn.params, + ...(oldColumn as DateHistogramIndexPatternColumn).params, interval: 'w', }, - })) as OperationDefinition['transfer']; + })) as OperationDefinition['transfer']; const layer: IndexPatternLayer = { columnOrder: ['col1', 'col2'], columns: { @@ -2781,7 +2775,7 @@ describe('state_helpers', () => { params: { interval: 'd', }, - }, + } as DateHistogramIndexPatternColumn, }, indexPatternId: 'original', }; @@ -2813,7 +2807,7 @@ describe('state_helpers', () => { orderDirection: 'asc', size: 3, }, - }, + } as TermsIndexPatternColumn, col2: { dataType: 'number', isBucketed: false, @@ -2846,7 +2840,7 @@ describe('state_helpers', () => { orderDirection: 'asc', size: 3, }, - }, + } as TermsIndexPatternColumn, col2: { dataType: 'number', isBucketed: false, @@ -2895,15 +2889,19 @@ describe('state_helpers', () => { indexPatternId: '1', columnOrder: [], columns: { - col1: - // @ts-expect-error not statically analyzed - { operationType: 'testReference', references: [] }, + col1: { + operationType: 'testReference', + references: [], + label: '', + dataType: 'number', + isBucketed: false, + }, }, }, indexPattern, - {}, + {} as IndexPatternPrivateState, '1', - {} + {} as CoreStart ); expect(mock).toHaveBeenCalled(); expect(errors).toHaveLength(1); @@ -2919,20 +2917,26 @@ describe('state_helpers', () => { indexPatternId: '1', columnOrder: [], columns: { - col1: - // @ts-expect-error not statically analyzed - { operationType: 'managedReference', references: ['col2'] }, + col1: { + operationType: 'managedReference', + references: ['col2'], + label: '', + dataType: 'number', + isBucketed: false, + }, col2: { - // @ts-expect-error not statically analyzed operationType: 'testReference', references: [], + label: '', + dataType: 'number', + isBucketed: false, }, }, }, indexPattern, - {}, + {} as IndexPatternPrivateState, '1', - {} + {} as CoreStart ); expect(notCalledMock).not.toHaveBeenCalled(); expect(mock).toHaveBeenCalledTimes(1); @@ -2953,19 +2957,22 @@ describe('state_helpers', () => { indexPatternId: '1', columnOrder: [], columns: { - col1: - // @ts-expect-error not statically analyzed - { operationType: 'testReference', references: [] }, + col1: { + operationType: 'testReference', + references: [], + label: '', + dataType: 'number', + isBucketed: false, + }, }, incompleteColumns: { - // @ts-expect-error not statically analyzed col1: { operationType: 'testIncompleteReference' }, }, }, indexPattern, - {}, + {} as IndexPatternPrivateState, '1', - {} + {} as CoreStart ); expect(savedRef).toHaveBeenCalled(); expect(incompleteRef).not.toHaveBeenCalled(); @@ -2982,22 +2989,32 @@ describe('state_helpers', () => { indexPatternId: '1', columnOrder: [], columns: { - col1: - // @ts-expect-error not statically analyzed - { operationType: 'testReference', references: [] }, + col1: { + operationType: 'testReference', + references: [], + label: '', + dataType: 'number', + isBucketed: false, + }, }, }, indexPattern, - {}, + {} as IndexPatternPrivateState, '1', - {} + {} as CoreStart ); expect(mock).toHaveBeenCalledWith( { indexPatternId: '1', columnOrder: [], columns: { - col1: { operationType: 'testReference', references: [] }, + col1: { + operationType: 'testReference', + references: [], + dataType: 'number', + isBucketed: false, + label: '', + }, }, }, 'col1', @@ -3021,7 +3038,7 @@ describe('state_helpers', () => { params: { interval: 'd', }, - }, + } as DateHistogramIndexPatternColumn, }, indexPatternId: 'original', }; @@ -3047,7 +3064,7 @@ describe('state_helpers', () => { orderBy: { type: 'alphabetical' }, orderDirection: 'asc', }, - }, + } as TermsIndexPatternColumn, }, indexPatternId: 'original', }; @@ -3073,7 +3090,7 @@ describe('state_helpers', () => { orderBy: { type: 'alphabetical' }, orderDirection: 'asc', }, - }, + } as TermsIndexPatternColumn, }, indexPatternId: 'original', }; diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/layer_helpers.ts b/x-pack/plugins/lens/public/indexpattern_datasource/operations/layer_helpers.ts index 67546ca6009cf..289161c9d3e37 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/layer_helpers.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/layer_helpers.ts @@ -18,10 +18,10 @@ import { operationDefinitionMap, operationDefinitions, OperationType, - IndexPatternColumn, RequiredReference, OperationDefinition, GenericOperationDefinition, + TermsIndexPatternColumn, } from './definitions'; import type { IndexPattern, @@ -31,9 +31,14 @@ import type { } from '../types'; import { getSortScoreByPriority } from './operations'; import { generateId } from '../../id_generator'; -import { ReferenceBasedIndexPatternColumn } from './definitions/column_types'; +import { + GenericIndexPatternColumn, + ReferenceBasedIndexPatternColumn, + BaseIndexPatternColumn, +} from './definitions/column_types'; import { FormulaIndexPatternColumn, regenerateLayerFromAst } from './definitions/formula'; import type { TimeScaleUnit } from '../../../common/expressions'; +import { isColumnOfType } from './definitions/helpers'; interface ColumnAdvancedParams { filter?: Query | undefined; @@ -57,7 +62,7 @@ interface ColumnChange { interface ColumnCopy { layer: IndexPatternLayer; targetId: string; - sourceColumn: IndexPatternColumn; + sourceColumn: GenericIndexPatternColumn; sourceColumnId: string; indexPattern: IndexPattern; shouldDeleteSource?: boolean; @@ -92,7 +97,7 @@ export function copyColumn({ function copyReferencesRecursively( layer: IndexPatternLayer, - sourceColumn: IndexPatternColumn, + sourceColumn: GenericIndexPatternColumn, sourceId: string, targetId: string, indexPattern: IndexPattern @@ -511,7 +516,7 @@ export function replaceColumn({ if (operationDefinition.input === 'managedReference') { const newColumn = operationDefinition.buildColumn( { ...baseOptions, layer: tempLayer }, - previousColumn.params, + 'params' in previousColumn ? previousColumn.params : undefined, operationDefinitionMap ) as FormulaIndexPatternColumn; @@ -665,11 +670,11 @@ export function replaceColumn({ function removeOrphanedColumns( previousDefinition: - | OperationDefinition - | OperationDefinition - | OperationDefinition - | OperationDefinition, - previousColumn: IndexPatternColumn, + | OperationDefinition + | OperationDefinition + | OperationDefinition + | OperationDefinition, + previousColumn: GenericIndexPatternColumn, tempLayer: IndexPatternLayer, indexPattern: IndexPattern ) { @@ -765,7 +770,7 @@ function applyReferenceTransition({ }: { layer: IndexPatternLayer; columnId: string; - previousColumn: IndexPatternColumn; + previousColumn: GenericIndexPatternColumn; op: OperationType; indexPattern: IndexPattern; visualizationGroups: VisualizationDimensionGroupConfig[]; @@ -962,7 +967,10 @@ function applyReferenceTransition({ ); } -function copyCustomLabel(newColumn: IndexPatternColumn, previousOptions: IndexPatternColumn) { +function copyCustomLabel( + newColumn: GenericIndexPatternColumn, + previousOptions: GenericIndexPatternColumn +) { const adjustedColumn = { ...newColumn }; const operationChanged = newColumn.operationType !== previousOptions.operationType; const fieldChanged = @@ -978,7 +986,7 @@ function copyCustomLabel(newColumn: IndexPatternColumn, previousOptions: IndexPa function addBucket( layer: IndexPatternLayer, - column: IndexPatternColumn, + column: BaseIndexPatternColumn, addedColumnId: string, visualizationGroups: VisualizationDimensionGroupConfig[], targetGroup?: string @@ -1071,7 +1079,7 @@ export function reorderByGroups( function addMetric( layer: IndexPatternLayer, - column: IndexPatternColumn, + column: BaseIndexPatternColumn, addedColumnId: string ): IndexPatternLayer { const tempLayer = { @@ -1096,7 +1104,7 @@ export function getMetricOperationTypes(field: IndexPatternField) { }); } -export function updateColumnParam({ +export function updateColumnParam({ layer, columnId, paramName, @@ -1107,18 +1115,19 @@ export function updateColumnParam({ paramName: string; value: unknown; }): IndexPatternLayer { + const oldColumn = layer.columns[columnId]; return { ...layer, columns: { ...layer.columns, [columnId]: { - ...layer.columns[columnId], + ...oldColumn, params: { - ...layer.columns[columnId].params, + ...('params' in oldColumn ? oldColumn.params : {}), [paramName]: value, }, }, - } as Record, + } as Record, }; } @@ -1228,7 +1237,7 @@ export function getExistingColumnGroups(layer: IndexPatternLayer): [string[], st * Returns true if the given column can be applied to the given index pattern */ export function isColumnTransferable( - column: IndexPatternColumn, + column: GenericIndexPatternColumn, newIndexPattern: IndexPattern, layer: IndexPatternLayer ): boolean { @@ -1373,9 +1382,7 @@ export function hasTermsWithManyBuckets(layer: IndexPatternLayer): boolean { return layer.columnOrder.some((columnId) => { const column = layer.columns[columnId]; if (column) { - return ( - column.isBucketed && column.params && 'size' in column.params && column.params.size > 5 - ); + return isColumnOfType('terms', column) && column.params.size > 5; } }); } @@ -1447,7 +1454,7 @@ function maybeValidateOperations({ column, validation, }: { - column: IndexPatternColumn; + column: GenericIndexPatternColumn; validation: RequiredReference; }) { if (!validation.specificOperations) { @@ -1463,7 +1470,7 @@ export function isColumnValidAsReference({ column, validation, }: { - column: IndexPatternColumn; + column: GenericIndexPatternColumn; validation: RequiredReference; }): boolean { if (!column) return false; @@ -1481,14 +1488,14 @@ export function isColumnValidAsReference({ export function getManagedColumnsFrom( columnId: string, - columns: Record -): Array<[string, IndexPatternColumn]> { + columns: Record +): Array<[string, GenericIndexPatternColumn]> { const allNodes: Record = {}; Object.entries(columns).forEach(([id, col]) => { allNodes[id] = 'references' in col ? [...col.references] : []; }); const queue: string[] = allNodes[columnId]; - const store: Array<[string, IndexPatternColumn]> = []; + const store: Array<[string, GenericIndexPatternColumn]> = []; while (queue.length > 0) { const nextId = queue.shift()!; diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/time_scale_utils.test.ts b/x-pack/plugins/lens/public/indexpattern_datasource/operations/time_scale_utils.test.ts index dbdfd5c564125..30f8c85a81b90 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/time_scale_utils.test.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/time_scale_utils.test.ts @@ -7,7 +7,7 @@ import type { IndexPatternLayer } from '../types'; import type { TimeScaleUnit } from '../../../common/expressions'; -import type { IndexPatternColumn } from './definitions'; +import type { DateHistogramIndexPatternColumn, GenericIndexPatternColumn } from './definitions'; import { adjustTimeScaleLabelSuffix, adjustTimeScaleOnOtherColumnChange } from './time_scale_utils'; export const DEFAULT_TIME_SCALE = 's' as TimeScaleUnit; @@ -97,7 +97,7 @@ describe('time scale utils', () => { }); describe('adjustTimeScaleOnOtherColumnChange', () => { - const baseColumn: IndexPatternColumn = { + const baseColumn: GenericIndexPatternColumn = { operationType: 'count', sourceField: 'Records', label: 'Count of records per second', @@ -135,7 +135,7 @@ describe('time scale utils', () => { label: '', sourceField: 'date', params: { interval: 'auto' }, - }, + } as DateHistogramIndexPatternColumn, }, }, 'col1', diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/time_scale_utils.ts b/x-pack/plugins/lens/public/indexpattern_datasource/operations/time_scale_utils.ts index a6c056933f022..a8e71c0fd86e5 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/time_scale_utils.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/time_scale_utils.ts @@ -8,7 +8,7 @@ import { unitSuffixesLong } from '../../../common/suffix_formatter'; import type { TimeScaleUnit } from '../../../common/expressions'; import type { IndexPatternLayer } from '../types'; -import type { IndexPatternColumn } from './definitions'; +import type { GenericIndexPatternColumn } from './definitions'; export const DEFAULT_TIME_SCALE = 's' as TimeScaleUnit; @@ -44,7 +44,7 @@ export function adjustTimeScaleLabelSuffix( return `${cleanedLabel}${getSuffix(newTimeScale, newShift)}`; } -export function adjustTimeScaleOnOtherColumnChange( +export function adjustTimeScaleOnOtherColumnChange( layer: IndexPatternLayer, thisColumnId: string, changedColumnId: string diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/time_shift_utils.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/time_shift_utils.tsx index 1258100375a39..d7f238171128d 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/time_shift_utils.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/time_shift_utils.tsx @@ -11,7 +11,7 @@ import { uniq } from 'lodash'; import { FormattedMessage } from '@kbn/i18n/react'; import { IndexPattern, - IndexPatternColumn, + GenericIndexPatternColumn, IndexPatternLayer, IndexPatternPrivateState, } from './types'; @@ -229,7 +229,7 @@ export function getStateTimeShiftWarningMessages( export function getColumnTimeShiftWarnings( dateHistogramInterval: ReturnType, - column: IndexPatternColumn + column: GenericIndexPatternColumn ) { const { isValueTooSmall, isValueNotMultiple } = getLayerTimeShiftChecks(dateHistogramInterval); diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/to_expression.ts b/x-pack/plugins/lens/public/indexpattern_datasource/to_expression.ts index 15b9b47d7a565..432c932b85da8 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/to_expression.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/to_expression.ts @@ -20,12 +20,14 @@ import { ExpressionAstExpressionBuilder, ExpressionAstFunction, } from '../../../../../src/plugins/expressions/public'; -import { IndexPatternColumn } from './indexpattern'; +import { GenericIndexPatternColumn } from './indexpattern'; import { operationDefinitionMap } from './operations'; import { IndexPattern, IndexPatternPrivateState, IndexPatternLayer } from './types'; -import { dateHistogramOperation } from './operations/definitions'; +import { DateHistogramIndexPatternColumn, RangeIndexPatternColumn } from './operations/definitions'; +import { FormattedIndexPatternColumn } from './operations/definitions/column_types'; +import { isColumnFormatted, isColumnOfType } from './operations/definitions/helpers'; -type OriginalColumn = { id: string } & IndexPatternColumn; +type OriginalColumn = { id: string } & GenericIndexPatternColumn; function getExpressionForLayer( layer: IndexPatternLayer, @@ -147,50 +149,29 @@ function getExpressionForLayer( }, }; }, {} as Record); - - type FormattedColumn = Required< - Extract< - IndexPatternColumn, - | { - params?: { - format: unknown; - }; - } - // when formatters are nested there's a slightly different format - | { - params: { - format?: unknown; - parentFormat?: unknown; - }; - } - > - >; const columnsWithFormatters = columnEntries.filter( ([, col]) => - col.params && - (('format' in col.params && col.params.format) || - ('parentFormat' in col.params && col.params.parentFormat)) - ) as Array<[string, FormattedColumn]>; - const formatterOverrides: ExpressionAstFunction[] = columnsWithFormatters.map( - ([id, col]: [string, FormattedColumn]) => { - // TODO: improve the type handling here - const parentFormat = 'parentFormat' in col.params ? col.params!.parentFormat! : undefined; - const format = (col as FormattedColumn).params!.format; + (isColumnOfType('range', col) && col.params?.parentFormat) || + (isColumnFormatted(col) && col.params?.format) + ) as Array<[string, RangeIndexPatternColumn | FormattedIndexPatternColumn]>; + const formatterOverrides: ExpressionAstFunction[] = columnsWithFormatters.map(([id, col]) => { + // TODO: improve the type handling here + const parentFormat = 'parentFormat' in col.params! ? col.params!.parentFormat! : undefined; + const format = col.params!.format; - const base: ExpressionAstFunction = { - type: 'function', - function: 'lens_format_column', - arguments: { - format: format ? [format.id] : [''], - columnId: [id], - decimals: typeof format?.params?.decimals === 'number' ? [format.params.decimals] : [], - parentFormat: parentFormat ? [JSON.stringify(parentFormat)] : [], - }, - }; + const base: ExpressionAstFunction = { + type: 'function', + function: 'lens_format_column', + arguments: { + format: format ? [format.id] : [''], + columnId: [id], + decimals: typeof format?.params?.decimals === 'number' ? [format.params.decimals] : [], + parentFormat: parentFormat ? [JSON.stringify(parentFormat)] : [], + }, + }; - return base; - } - ); + return base; + }); const firstDateHistogramColumn = columnEntries.find( ([, col]) => col.operationType === 'date_histogram' @@ -254,7 +235,9 @@ function getExpressionForLayer( const allDateHistogramFields = Object.values(columns) .map((column) => - column.operationType === dateHistogramOperation.type ? column.sourceField : null + isColumnOfType('date_histogram', column) + ? column.sourceField + : null ) .filter((field): field is string => Boolean(field)); @@ -291,7 +274,7 @@ function getExpressionForLayer( } // Topologically sorts references so that we can execute them in sequence -function sortedReferences(columns: Array) { +function sortedReferences(columns: Array) { const allNodes: Record = {}; columns.forEach(([id, col]) => { allNodes[id] = 'references' in col ? col.references : []; diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/types.ts b/x-pack/plugins/lens/public/indexpattern_datasource/types.ts index 515693b4dd5c8..a0d43c5523c5b 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/types.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/types.ts @@ -5,17 +5,17 @@ * 2.0. */ -import type { IndexPatternColumn, IncompleteColumn } from './operations'; +import type { IncompleteColumn, GenericIndexPatternColumn } from './operations'; import type { IndexPatternAggRestrictions } from '../../../../../src/plugins/data/public'; import type { FieldSpec } from '../../../../../src/plugins/data/common'; import type { DragDropIdentifier } from '../drag_drop/providers'; import type { FieldFormatParams } from '../../../../../src/plugins/field_formats/common'; export type { - FieldBasedIndexPatternColumn, - IndexPatternColumn, + GenericIndexPatternColumn, OperationType, IncompleteColumn, + FieldBasedIndexPatternColumn, FiltersIndexPatternColumn, RangeIndexPatternColumn, TermsIndexPatternColumn, @@ -67,7 +67,7 @@ export type IndexPatternField = FieldSpec & { export interface IndexPatternLayer { columnOrder: string[]; - columns: Record; + columns: Record; // Each layer is tied to the index pattern that created it indexPatternId: string; // Partial columns represent the temporary invalid states diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/utils.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/utils.tsx index 6d3f75a403dd7..f1f8f2cfe3e62 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/utils.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/utils.tsx @@ -24,7 +24,7 @@ import type { ReferenceBasedIndexPatternColumn, } from './operations/definitions/column_types'; -import { operationDefinitionMap, IndexPatternColumn } from './operations'; +import { operationDefinitionMap, GenericIndexPatternColumn } from './operations'; import { getInvalidFieldMessage } from './operations/definitions/helpers'; import { isQueryValid } from './operations/definitions/filters'; @@ -65,7 +65,7 @@ export function isColumnInvalid( columnId: string, indexPattern: IndexPattern ) { - const column: IndexPatternColumn | undefined = layer.columns[columnId]; + const column: GenericIndexPatternColumn | undefined = layer.columns[columnId]; if (!column || !indexPattern) return; const operationDefinition = column.operationType && operationDefinitionMap[column.operationType]; @@ -75,12 +75,9 @@ export function isColumnInvalid( 'references' in column && Boolean(getReferencesErrors(layer, column, indexPattern).filter(Boolean).length); - const operationErrorMessages = operationDefinition.getErrorMessage?.( - layer, - columnId, - indexPattern, - operationDefinitionMap - ); + const operationErrorMessages = + operationDefinition && + operationDefinition.getErrorMessage?.(layer, columnId, indexPattern, operationDefinitionMap); const filterHasError = column.filter ? !isQueryValid(column.filter, indexPattern) : false; @@ -108,7 +105,10 @@ function getReferencesErrors( }); } -export function fieldIsInvalid(column: IndexPatternColumn | undefined, indexPattern: IndexPattern) { +export function fieldIsInvalid( + column: GenericIndexPatternColumn | undefined, + indexPattern: IndexPattern +) { if (!column || !hasField(column)) { return false; } diff --git a/x-pack/plugins/osquery/public/packs/pack_queries_status_table.tsx b/x-pack/plugins/osquery/public/packs/pack_queries_status_table.tsx index 5aacffb52cb49..5567d4562b1d8 100644 --- a/x-pack/plugins/osquery/public/packs/pack_queries_status_table.tsx +++ b/x-pack/plugins/osquery/public/packs/pack_queries_status_table.tsx @@ -28,6 +28,7 @@ import { TypedLensByValueInput, PersistedIndexPatternLayer, PieVisualizationState, + TermsIndexPatternColumn, } from '../../../lens/public'; import { FilterStateStore, DataView } from '../../../../../src/plugins/data/common'; import { useKibana } from '../common/lib/kibana'; @@ -88,7 +89,7 @@ function getLensAttributes( }, orderDirection: 'desc', }, - }, + } as TermsIndexPatternColumn, 'ed999e9d-204c-465b-897f-fe1a125b39ed': { sourceField: 'Records', isBucketed: false, From b55b52c298b5105216006fb4d16c5037a61c08c8 Mon Sep 17 00:00:00 2001 From: Marta Bondyra Date: Fri, 19 Nov 2021 13:03:11 +0100 Subject: [PATCH 140/148] [Lens] Add max steps limit to coloring (#119132) * [Lens] add max steps limit to coloring * customize EmptyPlaceholder usage * refactor --- x-pack/plugins/lens/common/types.ts | 7 +- .../metric_visualization/palette_config.tsx | 1 + .../coloring/color_stops.test.tsx | 27 ++++++ .../coloring/color_stops.tsx | 82 +++++++++++-------- .../shared_components/coloring/constants.ts | 1 + .../shared_components/empty_placeholder.tsx | 21 +++-- 6 files changed, 97 insertions(+), 42 deletions(-) diff --git a/x-pack/plugins/lens/common/types.ts b/x-pack/plugins/lens/common/types.ts index 307ed856c7c66..152eef4ebd3fe 100644 --- a/x-pack/plugins/lens/common/types.ts +++ b/x-pack/plugins/lens/common/types.ts @@ -58,8 +58,13 @@ export interface CustomPaletteParams { colorStops?: ColorStop[]; steps?: number; } +export type CustomPaletteParamsConfig = CustomPaletteParams & { + maxSteps?: number; +}; -export type RequiredPaletteParamTypes = Required; +export type RequiredPaletteParamTypes = Required & { + maxSteps?: number; +}; export type LayerType = 'data' | 'referenceLine'; diff --git a/x-pack/plugins/lens/public/metric_visualization/palette_config.tsx b/x-pack/plugins/lens/public/metric_visualization/palette_config.tsx index 59147a33963d1..08cff1c777d2e 100644 --- a/x-pack/plugins/lens/public/metric_visualization/palette_config.tsx +++ b/x-pack/plugins/lens/public/metric_visualization/palette_config.tsx @@ -12,6 +12,7 @@ export const DEFAULT_PALETTE_NAME = 'status'; export const DEFAULT_COLOR_STEPS = 3; export const defaultPaletteParams: RequiredPaletteParamTypes = { ...sharedDefaultParams, + maxSteps: 5, name: DEFAULT_PALETTE_NAME, rangeType: 'number', steps: DEFAULT_COLOR_STEPS, diff --git a/x-pack/plugins/lens/public/shared_components/coloring/color_stops.test.tsx b/x-pack/plugins/lens/public/shared_components/coloring/color_stops.test.tsx index b6482b0d89e04..5489c0cbd9693 100644 --- a/x-pack/plugins/lens/public/shared_components/coloring/color_stops.test.tsx +++ b/x-pack/plugins/lens/public/shared_components/coloring/color_stops.test.tsx @@ -58,6 +58,33 @@ describe('Color Stops component', () => { ).toBe(true); }); + it('should disable "add new" button if there is maxStops configured', () => { + props.colorStops = [ + { color: '#aaa', stop: 20 }, + { color: '#bbb', stop: 40 }, + { color: '#ccc', stop: 60 }, + { color: '#ccc', stop: 80 }, + { color: '#ccc', stop: 90 }, + ]; + const component = mount(); + const componentWithMaxSteps = mount( + + ); + expect( + component + .find('[data-test-subj="my-test_dynamicColoring_addStop"]') + .first() + .prop('isDisabled') + ).toBe(false); + + expect( + componentWithMaxSteps + .find('[data-test-subj="my-test_dynamicColoring_addStop"]') + .first() + .prop('isDisabled') + ).toBe(true); + }); + it('should add a new stop with default color and reasonable distance from last one', () => { let component = mount(); const addStopButton = component diff --git a/x-pack/plugins/lens/public/shared_components/coloring/color_stops.tsx b/x-pack/plugins/lens/public/shared_components/coloring/color_stops.tsx index 1431e6ad135be..65f07351021b7 100644 --- a/x-pack/plugins/lens/public/shared_components/coloring/color_stops.tsx +++ b/x-pack/plugins/lens/public/shared_components/coloring/color_stops.tsx @@ -22,7 +22,7 @@ import useUnmount from 'react-use/lib/useUnmount'; import { DEFAULT_COLOR } from './constants'; import { getDataMinMax, getStepValue, isValidColor } from './utils'; import { TooltipWrapper, useDebouncedValue } from '../index'; -import type { ColorStop, CustomPaletteParams } from '../../../common'; +import type { ColorStop, CustomPaletteParamsConfig } from '../../../common'; const idGeneratorFn = htmlIdGenerator(); @@ -44,7 +44,7 @@ export interface CustomStopsProps { colorStops: ColorStop[]; onChange: (colorStops: ColorStop[]) => void; dataBounds: { min: number; max: number }; - paletteConfiguration: CustomPaletteParams | undefined; + paletteConfiguration: CustomPaletteParamsConfig | undefined; 'data-test-prefix': string; } export const CustomStops = ({ @@ -80,6 +80,9 @@ export const CustomStops = ({ }); const [sortedReason, setSortReason] = useState(''); const shouldEnableDelete = localColorStops.length > 2; + const shouldDisableAdd = Boolean( + paletteConfiguration?.maxSteps && localColorStops.length >= paletteConfiguration?.maxSteps + ); const [popoverInFocus, setPopoverInFocus] = useState(false); @@ -257,38 +260,51 @@ export const CustomStops = ({ - { - const newColorStops = [...localColorStops]; - const length = newColorStops.length; - const { max } = getDataMinMax(rangeType, dataBounds); - const step = getStepValue( - colorStops, - newColorStops.map(({ color, stop }) => ({ color, stop: Number(stop) })), - max - ); - const prevColor = localColorStops[length - 1].color || DEFAULT_COLOR; - const newStop = step + Number(localColorStops[length - 1].stop); - newColorStops.push({ - color: prevColor, - stop: String(newStop), - id: idGeneratorFn(), - }); - setLocalColorStops(newColorStops); - }} + - {i18n.translate('xpack.lens.dynamicColoring.customPalette.addColorStop', { - defaultMessage: 'Add color stop', - })} - + { + const newColorStops = [...localColorStops]; + const length = newColorStops.length; + const { max } = getDataMinMax(rangeType, dataBounds); + const step = getStepValue( + colorStops, + newColorStops.map(({ color, stop }) => ({ color, stop: Number(stop) })), + max + ); + const prevColor = localColorStops[length - 1].color || DEFAULT_COLOR; + const newStop = step + Number(localColorStops[length - 1].stop); + newColorStops.push({ + color: prevColor, + stop: String(newStop), + id: idGeneratorFn(), + }); + setLocalColorStops(newColorStops); + }} + > + {i18n.translate('xpack.lens.dynamicColoring.customPalette.addColorStop', { + defaultMessage: 'Add color stop', + })} + + ); }; diff --git a/x-pack/plugins/lens/public/shared_components/coloring/constants.ts b/x-pack/plugins/lens/public/shared_components/coloring/constants.ts index 29b50d3aee22d..fafa2cd613930 100644 --- a/x-pack/plugins/lens/public/shared_components/coloring/constants.ts +++ b/x-pack/plugins/lens/public/shared_components/coloring/constants.ts @@ -16,6 +16,7 @@ export const DEFAULT_MAX_STOP = 100; export const DEFAULT_COLOR_STEPS = 5; export const DEFAULT_COLOR = '#6092C0'; // Same as EUI ColorStops default for new stops export const defaultPaletteParams: RequiredPaletteParamTypes = { + maxSteps: undefined, name: DEFAULT_PALETTE_NAME, reverse: false, rangeType: 'percent', diff --git a/x-pack/plugins/lens/public/shared_components/empty_placeholder.tsx b/x-pack/plugins/lens/public/shared_components/empty_placeholder.tsx index 5812b02759803..8115a9f647e94 100644 --- a/x-pack/plugins/lens/public/shared_components/empty_placeholder.tsx +++ b/x-pack/plugins/lens/public/shared_components/empty_placeholder.tsx @@ -9,17 +9,22 @@ import React from 'react'; import { EuiIcon, EuiText, IconType, EuiSpacer } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -export const EmptyPlaceholder = (props: { icon: IconType }) => ( +const noResultsMessage = ( + +); + +export const EmptyPlaceholder = ({ + icon, + message = noResultsMessage, +}: { + icon: IconType; + message?: JSX.Element; +}) => ( <> - + -

    - -

    +

    {message}

    ); From b2e30c8e1a7a86a875f76bc00d24f663fa4fa3a5 Mon Sep 17 00:00:00 2001 From: Pierre Gayvallet Date: Fri, 19 Nov 2021 13:19:24 +0100 Subject: [PATCH 141/148] use type.displayName for search filters and search query (#119025) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../public/lib/parse_query.test.ts | 54 ++++++++++++++----- .../public/lib/parse_query.ts | 12 ++++- .../objects_table/saved_objects_table.tsx | 15 +++--- 3 files changed, 60 insertions(+), 21 deletions(-) diff --git a/src/plugins/saved_objects_management/public/lib/parse_query.test.ts b/src/plugins/saved_objects_management/public/lib/parse_query.test.ts index 3ab2d14ba491d..76335aa1febc7 100644 --- a/src/plugins/saved_objects_management/public/lib/parse_query.test.ts +++ b/src/plugins/saved_objects_management/public/lib/parse_query.test.ts @@ -7,30 +7,29 @@ */ import { Query } from '@elastic/eui'; +import type { SavedObjectManagementTypeInfo } from '../../common'; import { parseQuery } from './parse_query'; +const createType = (name: string, displayName?: string): SavedObjectManagementTypeInfo => ({ + name, + displayName: displayName ?? name, + hidden: false, + namespaceType: 'multiple', +}); + describe('getQueryText', () => { it('parses the query text', () => { const query = Query.parse('some search'); - expect(parseQuery(query)).toEqual({ + expect(parseQuery(query, [])).toEqual({ queryText: 'some search', }); }); - it('parses the types', () => { - const query = Query.parse('type:(index-pattern or dashboard) kibana'); - - expect(parseQuery(query)).toEqual({ - queryText: 'kibana', - visibleTypes: ['index-pattern', 'dashboard'], - }); - }); - it('parses the tags', () => { const query = Query.parse('tag:(tag-1 or tag-2) kibana'); - expect(parseQuery(query)).toEqual({ + expect(parseQuery(query, [])).toEqual({ queryText: 'kibana', selectedTags: ['tag-1', 'tag-2'], }); @@ -39,7 +38,7 @@ describe('getQueryText', () => { it('parses all the fields', () => { const query = Query.parse('tag:(tag-1 or tag-2) type:(index-pattern) kibana'); - expect(parseQuery(query)).toEqual({ + expect(parseQuery(query, [])).toEqual({ queryText: 'kibana', visibleTypes: ['index-pattern'], selectedTags: ['tag-1', 'tag-2'], @@ -49,8 +48,37 @@ describe('getQueryText', () => { it('does not fail on unknown fields', () => { const query = Query.parse('unknown:(hello or dolly) some search'); - expect(parseQuery(query)).toEqual({ + expect(parseQuery(query, [])).toEqual({ queryText: 'some search', }); }); + + it('parses the types when provided types are empty', () => { + const query = Query.parse('type:(index-pattern or dashboard) kibana'); + + expect(parseQuery(query, [])).toEqual({ + queryText: 'kibana', + visibleTypes: ['index-pattern', 'dashboard'], + }); + }); + + it('maps displayName to name when parsing the types', () => { + const query = Query.parse('type:(i-p or dash) kibana'); + const types = [createType('index-pattern', 'i-p'), createType('dashboard', 'dash')]; + + expect(parseQuery(query, types)).toEqual({ + queryText: 'kibana', + visibleTypes: ['index-pattern', 'dashboard'], + }); + }); + + it('maps displayName to name even when some types are missing', () => { + const query = Query.parse('type:(i-p or dashboard) kibana'); + const types = [createType('index-pattern', 'i-p')]; + + expect(parseQuery(query, types)).toEqual({ + queryText: 'kibana', + visibleTypes: ['index-pattern', 'dashboard'], + }); + }); }); diff --git a/src/plugins/saved_objects_management/public/lib/parse_query.ts b/src/plugins/saved_objects_management/public/lib/parse_query.ts index bef60a038353e..9676ad22a93be 100644 --- a/src/plugins/saved_objects_management/public/lib/parse_query.ts +++ b/src/plugins/saved_objects_management/public/lib/parse_query.ts @@ -7,6 +7,7 @@ */ import { Query } from '@elastic/eui'; +import type { SavedObjectManagementTypeInfo } from '../../common'; interface ParsedQuery { queryText?: string; @@ -14,7 +15,7 @@ interface ParsedQuery { selectedTags?: string[]; } -export function parseQuery(query: Query): ParsedQuery { +export function parseQuery(query: Query, types: SavedObjectManagementTypeInfo[]): ParsedQuery { let queryText: string | undefined; let visibleTypes: string[] | undefined; let selectedTags: string[] | undefined; @@ -27,7 +28,14 @@ export function parseQuery(query: Query): ParsedQuery { .join(' '); } if (query.ast.getFieldClauses('type')) { - visibleTypes = query.ast.getFieldClauses('type')[0].value as string[]; + const displayedTypes = query.ast.getFieldClauses('type')[0].value as string[]; + const displayNameToNameMap = types.reduce((map, type) => { + map.set(type.displayName, type.name); + return map; + }, new Map()); + visibleTypes = displayedTypes.map((type) => { + return displayNameToNameMap.get(type) ?? type; + }); } if (query.ast.getFieldClauses('tag')) { selectedTags = query.ast.getFieldClauses('tag')[0].value as string[]; diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx index a73a695c5b39d..d4b3ecac5b8db 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx @@ -149,7 +149,10 @@ export class SavedObjectsTable extends Component { const { taggingApi } = this.props; - const { queryText, visibleTypes, selectedTags } = parseQuery(this.state.activeQuery); + const { queryText, visibleTypes, selectedTags } = parseQuery( + this.state.activeQuery, + this.props.allowedTypes + ); const allowedTypes = this.props.allowedTypes.map((type) => type.name); @@ -210,7 +213,7 @@ export class SavedObjectsTable extends Component { const { activeQuery: query, page, perPage } = this.state; const { notifications, http, allowedTypes, taggingApi } = this.props; - const { queryText, visibleTypes, selectedTags } = parseQuery(query); + const { queryText, visibleTypes, selectedTags } = parseQuery(query, allowedTypes); const searchTypes = allowedTypes .map((type) => type.name) @@ -404,8 +407,8 @@ export class SavedObjectsTable extends Component { const { exportAllSelectedOptions, isIncludeReferencesDeepChecked, activeQuery } = this.state; - const { notifications, http, taggingApi } = this.props; - const { queryText, selectedTags } = parseQuery(activeQuery); + const { notifications, http, taggingApi, allowedTypes } = this.props; + const { queryText, selectedTags } = parseQuery(activeQuery, allowedTypes); const exportTypes = Object.entries(exportAllSelectedOptions).reduce((accum, [id, selected]) => { if (selected) { accum.push(id); @@ -658,8 +661,8 @@ export class SavedObjectsTable extends Component ({ - value: type.name, - name: type.name, + value: type.displayName, + name: type.displayName, view: `${type.displayName} (${savedObjectCounts[type.name] || 0})`, })); From 9df09ae6a6c8e482cc4496075168321e9f70bef6 Mon Sep 17 00:00:00 2001 From: Felix Barnsteiner Date: Fri, 19 Nov 2021 13:44:10 +0100 Subject: [PATCH 142/148] Remove transaction breakdown metrics (#115385) --- .../elasticsearch_fieldnames.test.ts.snap | 6 --- .../apm/common/elasticsearch_fieldnames.ts | 1 - x-pack/plugins/apm/dev_docs/apm_queries.md | 22 -------- .../apm/ftr_e2e/cypress/tasks/es_archiver.ts | 19 ++++--- .../__snapshots__/queries.test.ts.snap | 52 ++----------------- .../routes/transactions/breakdown/index.ts | 16 +----- .../constants/elasticsearch_fieldnames.ts | 1 - 7 files changed, 16 insertions(+), 101 deletions(-) diff --git a/x-pack/plugins/apm/common/__snapshots__/elasticsearch_fieldnames.test.ts.snap b/x-pack/plugins/apm/common/__snapshots__/elasticsearch_fieldnames.test.ts.snap index 2d1433324858b..6da21bf2bf2c7 100644 --- a/x-pack/plugins/apm/common/__snapshots__/elasticsearch_fieldnames.test.ts.snap +++ b/x-pack/plugins/apm/common/__snapshots__/elasticsearch_fieldnames.test.ts.snap @@ -209,8 +209,6 @@ exports[`Error TBT_FIELD 1`] = `undefined`; exports[`Error TRACE_ID 1`] = `"trace id"`; -exports[`Error TRANSACTION_BREAKDOWN_COUNT 1`] = `undefined`; - exports[`Error TRANSACTION_DOM_INTERACTIVE 1`] = `undefined`; exports[`Error TRANSACTION_DURATION 1`] = `undefined`; @@ -448,8 +446,6 @@ exports[`Span TBT_FIELD 1`] = `undefined`; exports[`Span TRACE_ID 1`] = `"trace id"`; -exports[`Span TRANSACTION_BREAKDOWN_COUNT 1`] = `undefined`; - exports[`Span TRANSACTION_DOM_INTERACTIVE 1`] = `undefined`; exports[`Span TRANSACTION_DURATION 1`] = `undefined`; @@ -701,8 +697,6 @@ exports[`Transaction TBT_FIELD 1`] = `undefined`; exports[`Transaction TRACE_ID 1`] = `"trace id"`; -exports[`Transaction TRANSACTION_BREAKDOWN_COUNT 1`] = `undefined`; - exports[`Transaction TRANSACTION_DOM_INTERACTIVE 1`] = `undefined`; exports[`Transaction TRANSACTION_DURATION 1`] = `1337`; diff --git a/x-pack/plugins/apm/common/elasticsearch_fieldnames.ts b/x-pack/plugins/apm/common/elasticsearch_fieldnames.ts index 4a4cad5454c4b..b42c23ee2df94 100644 --- a/x-pack/plugins/apm/common/elasticsearch_fieldnames.ts +++ b/x-pack/plugins/apm/common/elasticsearch_fieldnames.ts @@ -51,7 +51,6 @@ export const TRANSACTION_RESULT = 'transaction.result'; export const TRANSACTION_NAME = 'transaction.name'; export const TRANSACTION_ID = 'transaction.id'; export const TRANSACTION_SAMPLED = 'transaction.sampled'; -export const TRANSACTION_BREAKDOWN_COUNT = 'transaction.breakdown.count'; export const TRANSACTION_PAGE_URL = 'transaction.page.url'; // for transaction metrics export const TRANSACTION_ROOT = 'transaction.root'; diff --git a/x-pack/plugins/apm/dev_docs/apm_queries.md b/x-pack/plugins/apm/dev_docs/apm_queries.md index 0fbcd4fc1c8a8..e6021fa31b9f7 100644 --- a/x-pack/plugins/apm/dev_docs/apm_queries.md +++ b/x-pack/plugins/apm/dev_docs/apm_queries.md @@ -315,28 +315,6 @@ GET apm-*-metric-*,metrics-apm*/_search?terminate_after=1000 The above example is overly simplified. In reality [we do a bit more](https://github.com/elastic/kibana/blob/fe9b5332e157fd456f81aecfd4ffa78d9e511a66/x-pack/plugins/apm/server/lib/metrics/by_agent/shared/memory/index.ts#L51-L71) to properly calculate memory usage inside containers. Please note that an [Exists Query](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-exists-query.html) is used in the filter context in the query to ensure that the memory fields exist. - - -# Transaction breakdown metrics - -A pre-aggregations of transaction documents where `transaction.breakdown.count` is the number of original transactions. - -Noteworthy fields: `transaction.name`, `transaction.type` - -#### Sample document - -```json -{ - "@timestamp": "2021-09-27T21:59:59.828Z", - "processor.event": "metric", - "metricset.name": "transaction_breakdown", - "transaction.breakdown.count": 12, - "transaction.name": "GET /api/products", - "transaction.type": "request" -} -} -``` - # Span breakdown metrics A pre-aggregations of span documents where `span.self_time.count` is the number of original spans. Measures the "self-time" for a span type, and optional subtype, within a transaction group. diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/tasks/es_archiver.ts b/x-pack/plugins/apm/ftr_e2e/cypress/tasks/es_archiver.ts index a2ff99c5c377e..383a6fa68cf8a 100644 --- a/x-pack/plugins/apm/ftr_e2e/cypress/tasks/es_archiver.ts +++ b/x-pack/plugins/apm/ftr_e2e/cypress/tasks/es_archiver.ts @@ -5,26 +5,29 @@ * 2.0. */ -import Path from 'path'; +import path from 'path'; import { execSync } from 'child_process'; -const ES_ARCHIVE_DIR = './cypress/fixtures/es_archiver'; +const ES_ARCHIVE_DIR = path.resolve( + __dirname, + '../../cypress/fixtures/es_archiver' +); // Otherwise execSync would inject NODE_TLS_REJECT_UNAUTHORIZED=0 and node would abort if used over https const NODE_TLS_REJECT_UNAUTHORIZED = '1'; -export const esArchiverLoad = (folder: string) => { - const path = Path.join(ES_ARCHIVE_DIR, folder); +export const esArchiverLoad = (archiveName: string) => { + const archivePath = path.join(ES_ARCHIVE_DIR, archiveName); execSync( - `node ../../../../scripts/es_archiver load "${path}" --config ../../../test/functional/config.js`, + `node ../../../../scripts/es_archiver load "${archivePath}" --config ../../../test/functional/config.js`, { env: { ...process.env, NODE_TLS_REJECT_UNAUTHORIZED }, stdio: 'inherit' } ); }; -export const esArchiverUnload = (folder: string) => { - const path = Path.join(ES_ARCHIVE_DIR, folder); +export const esArchiverUnload = (archiveName: string) => { + const archivePath = path.join(ES_ARCHIVE_DIR, archiveName); execSync( - `node ../../../../scripts/es_archiver unload "${path}" --config ../../../test/functional/config.js`, + `node ../../../../scripts/es_archiver unload "${archivePath}" --config ../../../test/functional/config.js`, { env: { ...process.env, NODE_TLS_REJECT_UNAUTHORIZED }, stdio: 'inherit' } ); }; diff --git a/x-pack/plugins/apm/server/routes/transactions/__snapshots__/queries.test.ts.snap b/x-pack/plugins/apm/server/routes/transactions/__snapshots__/queries.test.ts.snap index 66cc8b53421d3..d9e84c1557fa0 100644 --- a/x-pack/plugins/apm/server/routes/transactions/__snapshots__/queries.test.ts.snap +++ b/x-pack/plugins/apm/server/routes/transactions/__snapshots__/queries.test.ts.snap @@ -45,11 +45,6 @@ Object { "field": "span.self_time.sum.us", }, }, - "total_transaction_breakdown_count": Object { - "sum": Object { - "field": "transaction.breakdown.count", - }, - }, "types": Object { "aggs": Object { "subtypes": Object { @@ -94,11 +89,6 @@ Object { "field": "span.self_time.sum.us", }, }, - "total_transaction_breakdown_count": Object { - "sum": Object { - "field": "transaction.breakdown.count", - }, - }, "types": Object { "aggs": Object { "subtypes": Object { @@ -151,20 +141,8 @@ Object { }, }, Object { - "bool": Object { - "minimum_should_match": 1, - "should": Array [ - Object { - "exists": Object { - "field": "span.self_time.sum.us", - }, - }, - Object { - "exists": Object { - "field": "transaction.breakdown.count", - }, - }, - ], + "exists": Object { + "field": "span.self_time.sum.us", }, }, ], @@ -191,11 +169,6 @@ Object { "field": "span.self_time.sum.us", }, }, - "total_transaction_breakdown_count": Object { - "sum": Object { - "field": "transaction.breakdown.count", - }, - }, "types": Object { "aggs": Object { "subtypes": Object { @@ -240,11 +213,6 @@ Object { "field": "span.self_time.sum.us", }, }, - "total_transaction_breakdown_count": Object { - "sum": Object { - "field": "transaction.breakdown.count", - }, - }, "types": Object { "aggs": Object { "subtypes": Object { @@ -297,20 +265,8 @@ Object { }, }, Object { - "bool": Object { - "minimum_should_match": 1, - "should": Array [ - Object { - "exists": Object { - "field": "span.self_time.sum.us", - }, - }, - Object { - "exists": Object { - "field": "transaction.breakdown.count", - }, - }, - ], + "exists": Object { + "field": "span.self_time.sum.us", }, }, Object { diff --git a/x-pack/plugins/apm/server/routes/transactions/breakdown/index.ts b/x-pack/plugins/apm/server/routes/transactions/breakdown/index.ts index 2c3bca8443db0..9c229a005b355 100644 --- a/x-pack/plugins/apm/server/routes/transactions/breakdown/index.ts +++ b/x-pack/plugins/apm/server/routes/transactions/breakdown/index.ts @@ -15,7 +15,6 @@ import { SPAN_SELF_TIME_SUM, TRANSACTION_TYPE, TRANSACTION_NAME, - TRANSACTION_BREAKDOWN_COUNT, } from '../../../../common/elasticsearch_fieldnames'; import { Setup } from '../../../lib/helpers/setup_request'; import { rangeQuery, kqlQuery } from '../../../../../observability/server'; @@ -51,11 +50,6 @@ export async function getTransactionBreakdown({ field: SPAN_SELF_TIME_SUM, }, }, - total_transaction_breakdown_count: { - sum: { - field: TRANSACTION_BREAKDOWN_COUNT, - }, - }, types: { terms: { field: SPAN_TYPE, @@ -92,15 +86,7 @@ export async function getTransactionBreakdown({ ...rangeQuery(start, end), ...environmentQuery(environment), ...kqlQuery(kuery), - { - bool: { - should: [ - { exists: { field: SPAN_SELF_TIME_SUM } }, - { exists: { field: TRANSACTION_BREAKDOWN_COUNT } }, - ], - minimum_should_match: 1, - }, - }, + { exists: { field: SPAN_SELF_TIME_SUM } }, ]; if (transactionName) { diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/constants/elasticsearch_fieldnames.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/constants/elasticsearch_fieldnames.ts index 01dd2a49b9be0..1b20b82c1202c 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/constants/elasticsearch_fieldnames.ts +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/constants/elasticsearch_fieldnames.ts @@ -49,7 +49,6 @@ export const TRANSACTION_RESULT = 'transaction.result'; export const TRANSACTION_NAME = 'transaction.name'; export const TRANSACTION_ID = 'transaction.id'; export const TRANSACTION_SAMPLED = 'transaction.sampled'; -export const TRANSACTION_BREAKDOWN_COUNT = 'transaction.breakdown.count'; export const TRANSACTION_PAGE_URL = 'transaction.page.url'; // for transaction metrics export const TRANSACTION_ROOT = 'transaction.root'; From 0e680aba70deb255f63452e7b1b3839f4ce835df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20St=C3=BCrmer?= Date: Fri, 19 Nov 2021 14:14:41 +0100 Subject: [PATCH 143/148] [Infra UI] Select the palette option in test using clicks (#119042) --- x-pack/test/functional/page_objects/infra_home_page.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/x-pack/test/functional/page_objects/infra_home_page.ts b/x-pack/test/functional/page_objects/infra_home_page.ts index 2f2c1407fc041..4ab0cf61b7a17 100644 --- a/x-pack/test/functional/page_objects/infra_home_page.ts +++ b/x-pack/test/functional/page_objects/infra_home_page.ts @@ -121,8 +121,12 @@ export function InfraHomePageProvider({ getService, getPageObjects }: FtrProvide }, async changePalette(paletteId: string) { - await testSubjects.find('legendControlsPalette'); - await testSubjects.selectValue('legendControlsPalette', paletteId); + const paletteSelector = await testSubjects.find('legendControlsPalette'); + await paletteSelector.click(); + const paletteSelectorEntry = await paletteSelector.findByCssSelector( + `option[value=${paletteId}]` + ); + await paletteSelectorEntry.click(); }, async applyLegendControls() { From f775bedcf365a06ca6e5c6c85c2bef8c98f6cd17 Mon Sep 17 00:00:00 2001 From: Rudolf Meijering Date: Fri, 19 Nov 2021 14:41:04 +0100 Subject: [PATCH 144/148] waitForIndexStatusYellow: Don't reject on 408 status from health api (#119136) --- .../actions/wait_for_index_status_yellow.ts | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/core/server/saved_objects/migrations/actions/wait_for_index_status_yellow.ts b/src/core/server/saved_objects/migrations/actions/wait_for_index_status_yellow.ts index 9d4df0ced8c0b..676471d99b7d2 100644 --- a/src/core/server/saved_objects/migrations/actions/wait_for_index_status_yellow.ts +++ b/src/core/server/saved_objects/migrations/actions/wait_for_index_status_yellow.ts @@ -40,11 +40,16 @@ export const waitForIndexStatusYellow = }: WaitForIndexStatusYellowParams): TaskEither.TaskEither => () => { return client.cluster - .health({ - index, - wait_for_status: 'yellow', - timeout, - }) + .health( + { + index, + wait_for_status: 'yellow', + timeout, + }, + // Don't reject on status code 408 so that we can handle the timeout + // explicitly and provide more context in the error message + { ignore: [408] } + ) .then((res) => { if (res.body.timed_out === true) { return Either.left({ From dbf0e3d76b77c710007f4fdfe62b88bd6f15062e Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Fri, 19 Nov 2021 15:53:55 +0200 Subject: [PATCH 145/148] [i18n] [main] Integrate 7.16.0 Translations (#119000) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../translations/translations/ja-JP.json | 16246 ++++++++------- .../translations/translations/zh-CN.json | 16361 +++++++++------- 2 files changed, 18010 insertions(+), 14597 deletions(-) diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 9be504204ea6a..8a2e43d0f54bf 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -76,7116 +76,6402 @@ } }, "messages": { - "xpack.lens.formula.absFunction.markdown": "\n絶対値を計算します。負の値は-1で乗算されます。正の値は同じままです。\n\n例:海水位までの平均距離を計算します `abs(average(altitude))`\n ", - "xpack.lens.formula.addFunction.markdown": "\n2つの数値を加算します。\n+記号も使用できます\n\n例:2つのフィールドの合計を計算します\n\n`sum(price) + sum(tax)`\n\n例:固定値でカウントをオフセットします\n\n`add(count(), 5)`\n ", - "xpack.lens.formula.cbrtFunction.markdown": "\n値の立方根。\n\n例:体積から側面の長さを計算します\n`cbrt(last_value(volume))`\n ", - "xpack.lens.formula.ceilFunction.markdown": "\n値の上限(切り上げ)。\n\n例:価格を次のドル単位まで切り上げます\n`ceil(sum(price))`\n ", - "xpack.lens.formula.clampFunction.markdown": "\n最小値から最大値までの値を制限します。\n\n例:確実に異常値を特定します\n```\nclamp(\n average(bytes),\n percentile(bytes, percentile=5),\n percentile(bytes, percentile=95)\n)\n```\n", - "xpack.lens.formula.cubeFunction.markdown": "\n数値の三乗を計算します。\n\n例:側面の長さから体積を計算します\n`cube(last_value(length))`\n ", - "xpack.lens.formula.divideFunction.markdown": "\n1番目の数値を2番目の数値で除算します。\n/記号も使用できます\n\n例:利益率を計算します\n`sum(profit) / sum(revenue)`\n\n例:`divide(sum(bytes), 2)`\n ", - "xpack.lens.formula.expFunction.markdown": "\n*e*をn乗します。\n\n例:自然指数関数を計算します\n\n`exp(last_value(duration))`\n ", - "xpack.lens.formula.fixFunction.markdown": "\n正の値の場合は、下限を取ります。負の値の場合は、上限を取ります。\n\n例:ゼロに向かって端数処理します\n`fix(sum(profit))`\n ", - "xpack.lens.formula.floorFunction.markdown": "\n最も近い整数値まで切り捨てます\n\n例:価格を切り捨てます\n`floor(sum(price))`\n ", - "xpack.lens.formula.logFunction.markdown": "\nオプションで底をとる対数。デフォルトでは自然対数の底*e*を使用します。\n\n例:値を格納するために必要なビット数を計算します\n```\nlog(sum(bytes))\nlog(sum(bytes), 2)\n```\n ", - "xpack.lens.formula.modFunction.markdown": "\n関数を数値で除算した後の余り\n\n例:値の最後の3ビットを計算します\n`mod(sum(price), 1000)`\n ", - "xpack.lens.formula.multiplyFunction.markdown": "\n2つの数値を乗算します。\n*記号も使用できます。\n\n例:現在の税率を入れた価格を計算します\n`sum(bytes) * last_value(tax_rate)`\n\n例:一定の税率を入れた価格を計算します\n`multiply(sum(price), 1.2)`\n ", - "xpack.lens.formula.powFunction.markdown": "\n値を特定の乗数で累乗します。2番目の引数は必須です\n\n例:側面の長さに基づいて体積を計算します\n`pow(last_value(length), 3)`\n ", - "xpack.lens.formula.roundFunction.markdown": "\n特定の小数位に四捨五入します。デフォルトは0です。\n\n例:セントに四捨五入します\n```\nround(sum(bytes))\nround(sum(bytes), 2)\n```\n ", - "xpack.lens.formula.sqrtFunction.markdown": "\n正の値のみの平方根\n\n例:面積に基づいて側面の長さを計算します\n`sqrt(last_value(area))`\n ", - "xpack.lens.formula.squareFunction.markdown": "\n値を2乗します\n\n例:側面の長さに基づいて面積を計算します\n`square(last_value(length))`\n ", - "xpack.lens.formula.subtractFunction.markdown": "\n2番目の数値から1番目の数値を減算します。\n-記号も使用できます。\n\n例:フィールドの範囲を計算します\n`subtract(max(bytes), min(bytes))`\n ", - "xpack.lens.formulaDocumentation.filterRatioDescription.markdown": "### フィルター比率:\n\n`kql=''`を使用すると、1つのセットのドキュメントをフィルターして、同じグループの他のドキュメントと比較します。\n例:経時的なエラー率の変化を表示する\n\n```\ncount(kql='response.status_code > 400') / count()\n```\n ", - "xpack.lens.formulaDocumentation.markdown": "## 仕組み\n\nLens式では、Elasticsearchの集計および数学関数を使用して演算を実行できます\n。主に次の3種類の関数があります。\n\n* `sum(bytes)`などのElasticsearchメトリック\n* 時系列関数は`cumulative_sum()`などのElasticsearchメトリックを入力として使用します\n* `round()`などの数学関数\n\nこれらのすべての関数を使用する式の例:\n\n```\nround(100 * moving_average(\n average(cpu.load.pct),\n window=10,\n kql='datacenter.name: east*'\n))\n```\n\nElasticsearchの関数はフィールド名を取り、フィールドは引用符で囲むこともできます。`sum(bytes)`は\n`sum('bytes')`と同じです。\n\n一部の関数は、`moving_average(count(), window=5)`のような名前付き引数を取ります。\n\nElasticsearchメトリックはKQLまたはLucene構文を使用してフィルターできます。フィルターを追加するには、名前付き\nパラメーター`kql='field: value'`または`lucene=''`を使用します。KQLまたはLuceneクエリを作成するときには、必ず引用符を使用してください\n。検索が引用符で囲まれている場合は、`kql='Women's''のようにバックスラッシュでエスケープします。\n\n数学関数は位置引数を取ることができます。たとえば、pow(count(), 3)はcount() * count() * count()と同じです。\n\n+、-、/、*記号を使用して、基本演算を実行できます。", - "xpack.lens.formulaDocumentation.percentOfTotalDescription.markdown": "### 合計の割合\n\nすべてのグループで式は`overall_sum`を計算できます。\nこれは各グループを合計の割合に変換できます。\n\n```\nsum(products.base_price) / overall_sum(sum(products.base_price))\n```\n ", - "xpack.lens.formulaDocumentation.weekOverWeekDescription.markdown": "### 週単位:\n\n`shift='1w'`を使用すると、前の週から各グループの値を取得します\n。時間シフトは*Top values*関数と使用しないでください。\n\n```\npercentile(system.network.in.bytes, percentile=99) /\npercentile(system.network.in.bytes, percentile=99, shift='1w')\n```\n ", - "xpack.lens.indexPattern.cardinality.documentation.markdown": "\n指定されたフィールドの一意の値の数を計算します。数値、文字列、日付、ブール値で機能します。\n\n例:異なる製品の数を計算します。\n`unique_count(product.name)`\n\n例:「clothes」グループから異なる製品の数を計算します。\n`unique_count(product.name, kql='product.group=clothes')`\n ", - "xpack.lens.indexPattern.count.documentation.markdown": "\nドキュメント数を計算します。\n\n例:ドキュメント数を計算します。\n`count()`\n\n例:特定のフィルターと一致するドキュメントの数を計算します。\n`count(kql='price > 500')`\n ", - "xpack.lens.indexPattern.counterRate.documentation.markdown": "\n増加し続けるカウンターのレートを計算します。この関数は、経時的に単調に増加する種類の測定を含むカウンターメトリックフィールドでのみ結果を生成します。\n値が小さくなる場合は、カウンターリセットであると解釈されます。最も正確な結果を得るには、フィールドの「max`」で「counter_rate」を計算してください。\n\nこの計算はフィルターで定義された別の系列または上位値のディメンションに対して個別に実行されます。\n式で使用されるときには、現在の間隔を使用します。\n\n例:Memcachedサーバーで経時的に受信されたバイトの比率を可視化します。\n`counter_rate(max(memcached.stats.read.bytes))`\n ", - "xpack.lens.indexPattern.cumulativeSum.documentation.markdown": "\n経時的なメトリックの累計値を計算し、系列のすべての前の値を各値に追加します。この関数を使用するには、日付ヒストグラムディメンションも構成する必要があります。\n\nこの計算はフィルターで定義された別の系列または上位値のディメンションに対して個別に実行されます。\n\n例:経時的に累積された受信バイト数を可視化します。\n`cumulative_sum(sum(bytes))`\n ", - "xpack.lens.indexPattern.differences.documentation.markdown": "\n経時的にメトリックの最後の値に対する差異を計算します。この関数を使用するには、日付ヒストグラムディメンションも構成する必要があります。\n差異ではデータが連続する必要があります。差異を使用するときにデータが空の場合は、データヒストグラム間隔を大きくしてみてください。\n\nこの計算はフィルターで定義された別の系列または上位値のディメンションに対して個別に実行されます。\n\n例:経時的に受信したバイト数の変化を可視化します。\n`differences(sum(bytes))`\n ", - "xpack.lens.indexPattern.lastValue.documentation.markdown": "\n最後のドキュメントからフィールドの値を返し、インデックスパターンのデフォルト時刻フィールドで並べ替えます。\n\nこの関数はエンティティの最新の状態を取得する際に役立ちます。\n\n例:サーバーAの現在のステータスを取得:\n`last_value(server.status, kql='server.name=\"A\"')`\n ", - "xpack.lens.indexPattern.metric.documentation.markdown": "\nフィールドの{metric}を返します。この関数は数値フィールドでのみ動作します。\n\n例:価格の{metric}を取得:\n`{metric}(price)`\n\n例:英国からの注文の価格の{metric}を取得:\n`{metric}(price, kql='location:UK')`\n ", - "xpack.lens.indexPattern.movingAverage.documentation.markdown": "\n経時的なメトリックの移動平均を計算します。最後のn番目の値を平均化し、現在の値を計算します。この関数を使用するには、日付ヒストグラムディメンションも構成する必要があります。\nデフォルトウィンドウ値は{defaultValue}です\n\nこの計算はフィルターで定義された別の系列または上位値のディメンションに対して個別に実行されます。\n\n指名パラメーター「window」を取ります。これは現在値の平均計算に含める最後の値の数を指定します。\n\n例:測定の線を平滑化:\n`moving_average(sum(bytes), window=5)`\n ", - "xpack.lens.indexPattern.overall_average.documentation.markdown": "\n現在のグラフの系列のすべてのデータポイントのメトリックの平均を計算します。系列は日付ヒストグラムまたは間隔関数を使用してディメンションによって定義されます。\n上位の値やフィルターなどのデータを分解する他のディメンションは別の系列として処理されます。\n\n日付ヒストグラムまたは間隔関数が現在のグラフで使用されている場合、使用されている関数に関係なく、「overall_average」はすべてのディメンションで平均値を計算します。\n\n例:平均からの収束:\n`sum(bytes) - overall_average(sum(bytes))`\n ", - "xpack.lens.indexPattern.overall_max.documentation.markdown": "\n現在のグラフの系列のすべてのデータポイントのメトリックの最大値を計算します。系列は日付ヒストグラムまたは間隔関数を使用してディメンションによって定義されます。\n上位の値やフィルターなどのデータを分解する他のディメンションは別の系列として処理されます。\n\n日付ヒストグラムまたは間隔関数が現在のグラフで使用されている場合、使用されている関数に関係なく、「overall_max」はすべてのディメンションで最大値を計算します。\n\n例:範囲の割合\n`(sum(bytes) - overall_min(sum(bytes))) / (overall_max(sum(bytes)) - overall_min(sum(bytes)))`\n ", - "xpack.lens.indexPattern.overall_min.documentation.markdown": "\n現在のグラフの系列のすべてのデータポイントのメトリックの最小値を計算します。系列は日付ヒストグラムまたは間隔関数を使用してディメンションによって定義されます。\n上位の値やフィルターなどのデータを分解する他のディメンションは別の系列として処理されます。\n\n日付ヒストグラムまたは間隔関数が現在のグラフで使用されている場合、使用されている関数に関係なく、「overall_min」はすべてのディメンションで最小値を計算します。\n\n例:範囲の割合\n`(sum(bytes) - overall_min(sum(bytes)) / (overall_max(sum(bytes)) - overall_min(sum(bytes)))`\n ", - "xpack.lens.indexPattern.overall_sum.documentation.markdown": "\n現在のグラフの系列のすべてのデータポイントのメトリックの合計を計算します。系列は日付ヒストグラムまたは間隔関数を使用してディメンションによって定義されます。\n上位の値やフィルターなどのデータを分解する他のディメンションは別の系列として処理されます。\n\n日付ヒストグラムまたは間隔関数が現在のグラフで使用されている場合、使用されている関数に関係なく、「overall_sum」はすべてのディメンションで合計値を計算します。\n\n例:合計の割合\n`sum(bytes) / overall_sum(sum(bytes))`\n ", - "xpack.lens.indexPattern.percentile.documentation.markdown": "\nフィールドの値の指定された百分位数を返します。これはドキュメントに出現する値のnパーセントが小さい値です。\n\n例:値の95 %より大きいバイト数を取得:\n`percentile(bytes, percentile=95)`\n ", - "xpack.lens.app.addToLibrary": "ライブラリに保存", - "xpack.lens.app.cancel": "キャンセル", - "xpack.lens.app.cancelButtonAriaLabel": "変更を保存せずに最後に使用していたアプリに戻る", - "xpack.lens.app.docLoadingError": "保存されたドキュメントの保存中にエラーが発生", - "xpack.lens.app.downloadButtonAriaLabel": "データを CSV ファイルとしてダウンロード", - "xpack.lens.app.downloadButtonFormulasWarning": "CSVには、スプレッドシートアプリケーションで式と解釈される可能性のある文字が含まれています。", - "xpack.lens.app.downloadCSV": "CSV をダウンロード", - "xpack.lens.app.save": "保存", - "xpack.lens.app.saveAndReturn": "保存して戻る", - "xpack.lens.app.saveAndReturnButtonAriaLabel": "現在のLensビジュアライゼーションを保存し、前回使用していたアプリに戻る", - "xpack.lens.app.saveAs": "名前を付けて保存", - "xpack.lens.app.saveButtonAriaLabel": "現在のLensビジュアライゼーションを保存", - "xpack.lens.app.saveModalType": "レンズビジュアライゼーション", - "xpack.lens.app.saveVisualization.successNotificationText": "保存された'{visTitle}'", - "xpack.lens.app.unsavedFilename": "未保存", - "xpack.lens.app.unsavedWorkMessage": "作業内容を保存せずに、Lens から移動しますか?", - "xpack.lens.app.unsavedWorkTitle": "保存されていない変更", - "xpack.lens.app.updatePanel": "{originatingAppName}でパネルを更新", - "xpack.lens.app404": "404 Not Found", - "xpack.lens.breadcrumbsByValue": "ビジュアライゼーションを編集", - "xpack.lens.breadcrumbsCreate": "作成", - "xpack.lens.breadcrumbsTitle": "Visualizeライブラリ", - "xpack.lens.chartSwitch.dataLossDescription": "このビジュアライゼーションタイプを選択すると、現在適用されている構成選択の一部が失われます。", - "xpack.lens.chartSwitch.dataLossLabel": "警告", - "xpack.lens.chartSwitch.experimentalLabel": "実験的", - "xpack.lens.chartSwitch.noResults": "{term}の結果が見つかりませんでした。", - "xpack.lens.chartTitle.unsaved": "保存されていないビジュアライゼーション", - "xpack.lens.configPanel.addLayerButton": "レイヤーを追加", - "xpack.lens.configPanel.color.tooltip.auto": "カスタム色を指定しない場合、Lensは自動的に色を選択します。", - "xpack.lens.configPanel.color.tooltip.custom": "[自動]モードに戻すには、カスタム色をオフにしてください。", - "xpack.lens.configPanel.color.tooltip.disabled": "レイヤーに「内訳条件」が含まれている場合は、個別の系列をカスタム色にできません。", - "xpack.lens.configPanel.selectVisualization": "ビジュアライゼーションを選択してください", - "xpack.lens.configPanel.visualizationType": "ビジュアライゼーションタイプ", - "xpack.lens.configure.configurePanelTitle": "{groupLabel}", - "xpack.lens.configure.editConfig": "{label}構成の編集", - "xpack.lens.configure.emptyConfig": "フィールドを追加するか、ドラッグアンドドロップします", - "xpack.lens.configure.invalidConfigTooltip": "無効な構成です。", - "xpack.lens.configure.invalidConfigTooltipClick": "詳細はクリックしてください。", - "xpack.lens.customBucketContainer.dragToReorder": "ドラッグして並べ替え", - "xpack.lens.dataPanelWrapper.switchDatasource": "データソースに切り替える", - "xpack.lens.datatable.addLayer": "ビジュアライゼーションレイヤーを追加", - "xpack.lens.datatable.breakdownColumns": "列", - "xpack.lens.datatable.breakdownColumns.description": "フィールドでメトリックを列に分割します。列数を少なくし、横スクロールを避けることをお勧めします。", - "xpack.lens.datatable.breakdownRows": "行", - "xpack.lens.datatable.breakdownRows.description": "フィールドで表の行を分割します。これは高カーディナリティ内訳にお勧めです。", - "xpack.lens.datatable.conjunctionSign": " & ", - "xpack.lens.datatable.expressionHelpLabel": "データベースレンダー", - "xpack.lens.datatable.groupLabel": "表形式の値と単一の値", - "xpack.lens.datatable.label": "表", - "xpack.lens.datatable.metrics": "メトリック", - "xpack.lens.datatable.suggestionLabel": "表として", - "xpack.lens.datatable.titleLabel": "タイトル", - "xpack.lens.datatable.visualizationName": "データベース", - "xpack.lens.datatable.visualizationOf": "テーブル {operations}", - "xpack.lens.datatypes.boolean": "ブール", - "xpack.lens.datatypes.date": "日付", - "xpack.lens.datatypes.geoPoint": "geo_point", - "xpack.lens.datatypes.geoShape": "geo_shape", - "xpack.lens.datatypes.histogram": "ヒストグラム", - "xpack.lens.datatypes.ipAddress": "IP", - "xpack.lens.datatypes.number": "数字", - "xpack.lens.datatypes.record": "レコード", - "xpack.lens.datatypes.string": "文字列", - "xpack.lens.deleteLayerAriaLabel": "レイヤー {index} を削除", - "xpack.lens.dimensionContainer.close": "閉じる", - "xpack.lens.dimensionContainer.closeConfiguration": "構成を閉じる", - "xpack.lens.discover.visualizeFieldLegend": "Visualize フィールド", - "xpack.lens.dragDrop.altOption": "Alt/Option", - "xpack.lens.dragDrop.announce.cancelled": "移動がキャンセルされました。{label}は初期位置に戻りました", - "xpack.lens.dragDrop.announce.cancelledItem": "移動がキャンセルされました。{label}は位置{position}の{groupLabel}グループに戻りました", - "xpack.lens.dragDrop.announce.dropped.duplicated": "位置{position}の{groupLabel}グループで{label}を複製しました", - "xpack.lens.dragDrop.announce.dropped.duplicateIncompatible": "{label}のコピーを{nextLabel}に変換し、位置{position}の{groupLabel}グループに追加しました", - "xpack.lens.dragDrop.announce.dropped.moveCompatible": "位置{position}の{groupLabel}グループに{label}を移動しました", - "xpack.lens.dragDrop.announce.dropped.moveIncompatible": "{label}を{nextLabel}に変換し、位置{position}の{groupLabel}グループに移動しました", - "xpack.lens.dragDrop.announce.dropped.reordered": "{groupLabel}グループの{label}を位置{prevPosition}から位置{position}に並べ替えました", - "xpack.lens.dragDrop.announce.dropped.replaceDuplicateIncompatible": "{label}のコピーを{nextLabel}に変換し、位置{position}の{groupLabel}グループで{dropLabel}を置き換えました", - "xpack.lens.dragDrop.announce.dropped.replaceIncompatible": "{label}を{nextLabel}に変換し、位置{position}の{groupLabel}グループで{dropLabel}を置き換えました", - "xpack.lens.dragDrop.announce.dropped.swapCompatible": "位置{dropPosition}で{label}を{dropGroupLabel}に移動し、位置{position}で{dropLabel}を {groupLabel}グループに移動しました", - "xpack.lens.dragDrop.announce.dropped.swapIncompatible": "位置{position}で{label}を{groupLabel}の{nextLabel}に変換し、位置{dropPosition}で{dropGroupLabel}グループの{dropLabel}と入れ替えました", - "xpack.lens.dragDrop.announce.droppedDefault": "位置{position}の{dropGroupLabel}グループで{label}を追加しました", - "xpack.lens.dragDrop.announce.droppedNoPosition": "{label}を{dropLabel}に追加しました", - "xpack.lens.dragDrop.announce.duplicate.short": " AltキーまたはOptionを押し続けると複製します。", - "xpack.lens.dragDrop.announce.duplicated.replace": "位置{position}の{groupLabel}で{dropLabel}を{label}に置き換えました", - "xpack.lens.dragDrop.announce.duplicated.replaceDuplicateCompatible": "位置{position}の{groupLabel}で{dropLabel}を{label}のコピーに置き換えました", - "xpack.lens.dragDrop.announce.lifted": "{label}を上げました", - "xpack.lens.dragDrop.announce.selectedTarget.default": "位置{position}の{dropGroupLabel}グループに{label}を追加しました。スペースまたはEnterを押して追加します", - "xpack.lens.dragDrop.announce.selectedTarget.defaultNoPosition": "{label}を{dropLabel}に追加します。スペースまたはEnterを押して追加します", - "xpack.lens.dragDrop.announce.selectedTarget.duplicated": "位置{position}の{dropGroupLabel}グループに{label}を複製しました。AltまたはOptionを押しながらスペースバーまたはEnterキーを押すと、複製します", - "xpack.lens.dragDrop.announce.selectedTarget.duplicatedInGroup": "位置{position}の{dropGroupLabel}グループに{label}を複製しました。スペースまたはEnterを押して複製します", - "xpack.lens.dragDrop.announce.selectedTarget.duplicateIncompatible": "{label}のコピーを{nextLabel}に変換し、位置{position}で{groupLabel}グループに移動します。AltまたはOptionを押しながらスペースバーまたはEnterキーを押すと、複製します", - "xpack.lens.dragDrop.announce.selectedTarget.moveCompatibleMain": "位置{position}で{groupLabel}の{label}を{dropGroupLabel}グループの位置{dropPosition}にドラッグしています。スペースバーまたはEnterキーを押すと移動します。{duplicateCopy}{swapCopy}", - "xpack.lens.dragDrop.announce.selectedTarget.moveIncompatible": "{label}を{nextLabel}に変換し、位置{dropPosition}で{dropGroupLabel}グループに移動します。スペースまたはEnterを押して移動します", - "xpack.lens.dragDrop.announce.selectedTarget.moveIncompatibleMain": "位置{position}で{groupLabel}の{label}を{dropGroupLabel}グループの位置{dropPosition}にドラッグしています。スペースバーまたはEnterキーを押して、{label}を{nextLabel}に変換して移動します。{duplicateCopy}{swapCopy}", - "xpack.lens.dragDrop.announce.selectedTarget.noSelected": "対象が選択されていません。矢印キーを使用して対象を選択してください", - "xpack.lens.dragDrop.announce.selectedTarget.reordered": "{groupLabel}グループの{label}を位置{prevPosition}から位置{position}に並べ替えます。スペースまたはEnterを押して並べ替えます", - "xpack.lens.dragDrop.announce.selectedTarget.reorderedBack": "{label}は初期位置{prevPosition}に戻りました", - "xpack.lens.dragDrop.announce.selectedTarget.replaceDuplicateCompatible": "位置{position}で{label}を複製し、{groupLabel}グループで{dropLabel}を置き換えます。AltまたはOptionを押しながらスペースバーまたはEnterキーを押すと、複製して置換します", - "xpack.lens.dragDrop.announce.selectedTarget.replaceDuplicateIncompatible": "{label}のコピーを{nextLabel}に変換し、位置{position}で{groupLabel}グループの{dropLabel}を置き換えます。AltまたはOptionを押しながらスペースバーまたはEnterキーを押すと、複製して置換します", - "xpack.lens.dragDrop.announce.selectedTarget.replaceIncompatibleMain": "位置{position}の{groupLabel}の{label}を、位置{dropPosition}の{dropGroupLabel}グループの{dropLabel}にドラッグしています。スペースバーまたはEnterキーを押して、{label}を{nextLabel}に変換して、{dropLabel}を置き換えます。{duplicateCopy}{swapCopy}", - "xpack.lens.dragDrop.announce.selectedTarget.replaceMain": "位置{position}の{groupLabel}の{label}を、位置{dropPosition}の{dropGroupLabel}グループの{dropLabel}にドラッグしています。スペースまたはEnterを押して、{dropLabel}を{label}で置き換えます。{duplicateCopy}{swapCopy}", - "xpack.lens.dragDrop.announce.selectedTarget.swapCompatible": "位置{position}の{groupLabel}の{label}を、位置{dropPosition}の{dropGroupLabel}グループの{dropLabel}と入れ替えます。Shiftキーを押しながらスペースバーまたはEnterキーを押すと、入れ替えます", - "xpack.lens.dragDrop.announce.selectedTarget.swapIncompatible": "位置{position}で{label}を{groupLabel}の{nextLabel}に変換し、位置{dropPosition}で{dropGroupLabel}グループの{dropLabel}と入れ替えます。Shiftキーを押しながらスペースバーまたはEnterキーを押すと、入れ替えます", - "xpack.lens.dragDrop.announce.swap.short": " Shiftキーを押すと入れ替えます。", - "xpack.lens.dragDrop.duplicate": "複製", - "xpack.lens.dragDrop.keyboardInstructions": "スペースまたはEnterを押してドラッグを開始します。ドラッグするときには、左右の矢印キーを使用して、ドロップ対象間を移動します。もう一度スペースまたはEnterを押すと終了します。", - "xpack.lens.dragDrop.keyboardInstructionsReorder": "スペースまたはEnterを押してドラッグを開始します。ドラッグするときには、上下矢印キーを使用すると、グループの項目を並べ替えます。左右矢印キーを使用すると、グループの外側でドロップ対象を選択します。もう一度スペースまたはEnterを押すと終了します。", - "xpack.lens.dragDrop.shift": "Shift", - "xpack.lens.dragDrop.swap": "入れ替える", - "xpack.lens.dynamicColoring.customPalette.addColorStop": "色経由点を追加", - "xpack.lens.dynamicColoring.customPalette.deleteButtonAriaLabel": "削除", - "xpack.lens.dynamicColoring.customPalette.deleteButtonDisabled": "2つ以上の経由点が必要であるため、この色経由点を削除することはできません", - "xpack.lens.dynamicColoring.customPalette.deleteButtonLabel": "削除", - "xpack.lens.dynamicColoring.customPalette.sortReason": "新しい経由値{value}のため、色経由点が並べ替えられました", - "xpack.lens.dynamicColoring.customPalette.stopAriaLabel": "{index}を停止", - "xpack.lens.editorFrame.buildExpressionError": "グラフの準備中に予期しないエラーが発生しました", - "xpack.lens.editorFrame.colorIndicatorLabel": "このディメンションの色:{hex}", - "xpack.lens.editorFrame.dataFailure": "データの読み込み中にエラーが発生しました。", - "xpack.lens.editorFrame.emptyWorkspace": "開始するにはここにフィールドをドロップしてください", - "xpack.lens.editorFrame.emptyWorkspaceHeading": "Lensはビジュアライゼーションを作成するための新しいツールです", - "xpack.lens.editorFrame.emptyWorkspaceSimple": "ここにフィールドをドロップ", - "xpack.lens.editorFrame.expandRenderingErrorButton": "エラーの詳細を表示", - "xpack.lens.editorFrame.expressionFailure": "式でエラーが発生しました", - "xpack.lens.editorFrame.expressionFailureMessage": "リクエストエラー:{type}, {reason}", - "xpack.lens.editorFrame.expressionFailureMessageWithContext": "リクエストエラー:{type}、{context}の{reason}", - "xpack.lens.editorFrame.expressionMissingDatasource": "ビジュアライゼーションのデータソースが見つかりませんでした", - "xpack.lens.editorFrame.expressionMissingVisualizationType": "ビジュアライゼーションタイプが見つかりません。", - "xpack.lens.editorFrame.goToForums": "リクエストとフィードバック", - "xpack.lens.editorFrame.invisibleIndicatorLabel": "このディメンションは現在グラフに表示されません", - "xpack.lens.editorFrame.networkErrorMessage": "ネットワークエラーです。しばらくたってから再試行するか、管理者に連絡してください。", - "xpack.lens.editorFrame.noColorIndicatorLabel": "このディメンションには個別の色がありません", - "xpack.lens.editorFrame.paletteColorIndicatorLabel": "このディメンションはパレットを使用しています", - "xpack.lens.editorFrame.previewErrorLabel": "レンダリングのプレビューに失敗しました", - "xpack.lens.editorFrame.requiredDimensionWarningLabel": "必要な次元", - "xpack.lens.editorFrame.suggestionPanelTitle": "提案", - "xpack.lens.editorFrame.workspaceLabel": "ワークスペース", - "xpack.lens.embeddable.failure": "ビジュアライゼーションを表示できませんでした", - "xpack.lens.embeddable.fixErrors": "Lensエディターで編集し、エラーを修正", - "xpack.lens.embeddable.moreErrors": "Lensエディターで編集すると、エラーの詳細が表示されます", - "xpack.lens.embeddableDisplayName": "レンズ", - "xpack.lens.fieldFormats.longSuffix.d": "日単位", - "xpack.lens.fieldFormats.longSuffix.h": "時間単位", - "xpack.lens.fieldFormats.longSuffix.m": "分単位", - "xpack.lens.fieldFormats.longSuffix.s": "秒単位", - "xpack.lens.fieldFormats.suffix.d": "/d", - "xpack.lens.fieldFormats.suffix.h": "/h", - "xpack.lens.fieldFormats.suffix.m": "/m", - "xpack.lens.fieldFormats.suffix.s": "/s", - "xpack.lens.fieldFormats.suffix.title": "接尾辞", - "xpack.lens.filterBy.removeLabel": "フィルターを削除", - "xpack.lens.fittingFunctionsDescription.carry": "ギャップを最後の値で埋める", - "xpack.lens.fittingFunctionsDescription.linear": "ギャップを線で埋める", - "xpack.lens.fittingFunctionsDescription.lookahead": "ギャップを次の値で埋める", - "xpack.lens.fittingFunctionsDescription.none": "ギャップを埋めない", - "xpack.lens.fittingFunctionsDescription.zero": "ギャップをゼロで埋める", - "xpack.lens.fittingFunctionsTitle.carry": "最後", - "xpack.lens.fittingFunctionsTitle.linear": "線形", - "xpack.lens.fittingFunctionsTitle.lookahead": "次へ", - "xpack.lens.fittingFunctionsTitle.none": "非表示", - "xpack.lens.fittingFunctionsTitle.zero": "ゼロ", - "xpack.lens.formula.base": "基数", - "xpack.lens.formula.decimals": "小数点以下", - "xpack.lens.formula.disableWordWrapLabel": "単語の折り返しを無効にする", - "xpack.lens.formula.editorHelpInlineHideLabel": "関数リファレンスを非表示", - "xpack.lens.formula.editorHelpInlineHideToolTip": "関数リファレンスを非表示", - "xpack.lens.formula.editorHelpInlineShowToolTip": "関数リファレンスを表示", - "xpack.lens.formula.editorHelpOverlayToolTip": "機能リファレンス", - "xpack.lens.formula.fullScreenEnterLabel": "拡張", - "xpack.lens.formula.fullScreenExitLabel": "縮小", - "xpack.lens.formula.kqlExtraArguments": "[kql]?:文字列、[lucene]?:文字列", - "xpack.lens.formula.left": "左", - "xpack.lens.formula.max": "最高", - "xpack.lens.formula.min": "分", - "xpack.lens.formula.number": "数字", - "xpack.lens.formula.optionalArgument": "任意。デフォルト値は{defaultValue}です", - "xpack.lens.formula.requiredArgument": "必須", - "xpack.lens.formula.right": "右", - "xpack.lens.formula.shiftExtraArguments": "[shift]?:文字列", - "xpack.lens.formula.string": "文字列", - "xpack.lens.formula.value": "値", - "xpack.lens.formulaCommonFormulaDocumentation": "最も一般的な式は2つの値を分割して割合を生成します。正確に表示するには、[値形式]を[割合]に設定します。", - "xpack.lens.formulaDocumentation.columnCalculationSection": "列計算", - "xpack.lens.formulaDocumentation.columnCalculationSectionDescription": "各行でこれらの関数が実行されますが、コンテキストとして列全体が提供されます。これはウィンドウ関数とも呼ばれます。", - "xpack.lens.formulaDocumentation.elasticsearchSection": "Elasticsearch", - "xpack.lens.formulaDocumentation.elasticsearchSectionDescription": "これらの関数は結果テーブルの各行の未加工ドキュメントで実行され、内訳ディメンションと一致するすべてのドキュメントを単一の値に集約します。", - "xpack.lens.formulaDocumentation.filterRatio": "フィルター比率", - "xpack.lens.formulaDocumentation.header": "式リファレンス", - "xpack.lens.formulaDocumentation.mathSection": "数学処理", - "xpack.lens.formulaDocumentation.mathSectionDescription": "これらの関数は、他の関数で計算された同じ行の単一の値を使用して、結果テーブルの各行で実行されます。", - "xpack.lens.formulaDocumentation.percentOfTotal": "合計の割合", - "xpack.lens.formulaDocumentation.weekOverWeek": "週単位", - "xpack.lens.formulaDocumentationHeading": "仕組み", - "xpack.lens.formulaEnableWordWrapLabel": "単語の折り返しを有効にする", - "xpack.lens.formulaExampleMarkdown": "例", - "xpack.lens.formulaFrequentlyUsedHeading": "一般的な式", - "xpack.lens.formulaPlaceholderText": "関数を演算と組み合わせて式を入力します。例:", - "xpack.lens.formulaSearchPlaceholder": "検索関数", - "xpack.lens.functions.counterRate.args.byHelpText": "カウンターレート計算を分割する列", - "xpack.lens.functions.counterRate.args.inputColumnIdHelpText": "カウンターレートを計算する列", - "xpack.lens.functions.counterRate.args.outputColumnIdHelpText": "結果のカウンターレートを格納する列", - "xpack.lens.functions.counterRate.args.outputColumnNameHelpText": "結果のカウンターレートを格納する列の名前", - "xpack.lens.functions.counterRate.help": "データテーブルの列のカウンターレートを計算します", - "xpack.lens.functions.lastValue.missingSortField": "このインデックスパターンには日付フィールドが含まれていません", - "xpack.lens.functions.mergeTables.help": "任意の数の Kibana 表を 1 つの表に結合し、インスペクターアダプター経由で公開するヘルパー", - "xpack.lens.functions.renameColumns.help": "データベースの列の名前の変更をアシストします", - "xpack.lens.functions.renameColumns.idMap.help": "キーが古い列 ID で値が対応する新しい列 ID となるように JSON エンコーディングされたオブジェクトです。他の列 ID はすべてのそのままです。", - "xpack.lens.functions.timeScale.dateColumnMissingMessage": "指定した dateColumnId {columnId} は存在しません。", - "xpack.lens.functions.timeScale.timeInfoMissingMessage": "日付ヒストグラム情報を取得できませんでした", - "xpack.lens.geoFieldWorkspace.dropMessage": "Mapsで開くにはここにフィールドをドロップします", - "xpack.lens.geoFieldWorkspace.dropZoneLabel": "Mapsで開くにはゾーンをドロップします", - "xpack.lens.heatmap.addLayer": "ビジュアライゼーションレイヤーを追加", - "xpack.lens.heatmap.cellValueLabel": "セル値", - "xpack.lens.heatmap.expressionHelpLabel": "ヒートマップレンダラー", - "xpack.lens.heatmap.groupLabel": "ヒートマップ", - "xpack.lens.heatmap.heatmapLabel": "ヒートマップ", - "xpack.lens.heatmap.horizontalAxisLabel": "横軸", - "xpack.lens.heatmap.titleLabel": "タイトル", - "xpack.lens.heatmap.verticalAxisLabel": "縦軸", - "xpack.lens.heatmap.visualizationName": "ヒートマップ", - "xpack.lens.heatmapChart.config.cellHeight.help": "グリッドセルの高さを指定します", - "xpack.lens.heatmapChart.config.cellWidth.help": "グリッドセルの幅を指定します", - "xpack.lens.heatmapChart.config.isCellLabelVisible.help": "セルラベルの表示・非表示を指定します。", - "xpack.lens.heatmapChart.config.isXAxisLabelVisible.help": "x軸のラベルを表示するかどうかを指定します。", - "xpack.lens.heatmapChart.config.isYAxisLabelVisible.help": "Y軸のラベルを表示するかどうかを指定します。", - "xpack.lens.heatmapChart.config.strokeColor.help": "グリッドストローク色を指定します", - "xpack.lens.heatmapChart.config.strokeWidth.help": "グリッドストローク幅を指定します", - "xpack.lens.heatmapChart.config.yAxisLabelColor.help": "Y軸ラベルの色を指定します。", - "xpack.lens.heatmapChart.config.yAxisLabelWidth.help": "Y軸ラベルの幅を指定します。", - "xpack.lens.heatmapChart.gridConfig.help": "ヒートマップレイアウトを構成します。", - "xpack.lens.heatmapChart.legend.help": "チャートの凡例を構成します。", - "xpack.lens.heatmapChart.legend.isVisible.help": "判例の表示・非表示を指定します。", - "xpack.lens.heatmapChart.legend.maxLines.help": "凡例項目ごとの行数を指定します。", - "xpack.lens.heatmapChart.legend.position.help": "凡例の配置を指定します。", - "xpack.lens.heatmapChart.legend.shouldTruncate.help": "凡例項目を切り捨てるかどうかを指定します。", - "xpack.lens.heatmapChart.legendVisibility.hide": "非表示", - "xpack.lens.heatmapChart.legendVisibility.show": "表示", - "xpack.lens.heatmapVisualization.arrayValuesWarningMessage": "{label}には配列値が含まれます。可視化が想定通りに表示されない場合があります。", - "xpack.lens.heatmapVisualization.heatmapGroupLabel": "ヒートマップ", - "xpack.lens.heatmapVisualization.heatmapLabel": "ヒートマップ", - "xpack.lens.heatmapVisualization.missingXAccessorLongMessage": "横軸の構成がありません。", - "xpack.lens.heatmapVisualization.missingXAccessorShortMessage": "横軸がありません。", - "xpack.lens.indexPattern.advancedSettings": "高度なオプションを追加", - "xpack.lens.indexPattern.allFieldsLabel": "すべてのフィールド", - "xpack.lens.indexPattern.allFieldsLabelHelp": "使用可能なフィールドには、フィルターと一致する最初の 500 件のドキュメントのデータがあります。すべてのフィールドを表示するには、空のフィールドを展開します。一部のフィールドタイプは、完全なテキストおよびグラフィックフィールドを含む Lens では、ビジュアライゼーションできません。", - "xpack.lens.indexPattern.availableFieldsLabel": "利用可能なフィールド", - "xpack.lens.indexPattern.avg": "平均", - "xpack.lens.indexPattern.avg.description": "集約されたドキュメントから抽出された数値の平均値を計算する単一値メトリック集約", - "xpack.lens.indexPattern.avgOf": "{name} の平均", - "xpack.lens.indexPattern.bytesFormatLabel": "バイト(1024)", - "xpack.lens.indexPattern.calculations.dateHistogramErrorMessage": "{name} が動作するには、日付ヒストグラムが必要です。日付ヒストグラムを追加するか、別の関数を選択します。", - "xpack.lens.indexPattern.calculations.layerDataType": "このタイプのレイヤーでは{name}が無効です。", - "xpack.lens.indexPattern.cardinality": "ユニークカウント", - "xpack.lens.indexPattern.cardinality.signature": "フィールド:文字列", - "xpack.lens.indexPattern.cardinalityOf": "{name} のユニークカウント", - "xpack.lens.indexPattern.chooseField": "フィールドを選択", - "xpack.lens.indexPattern.chooseFieldLabel": "この関数を使用するには、フィールドを選択してください。", - "xpack.lens.indexPattern.chooseSubFunction": "サブ関数を選択", - "xpack.lens.indexPattern.columnFormatLabel": "値の形式", - "xpack.lens.indexPattern.columnLabel": "表示名", - "xpack.lens.indexPattern.count": "カウント", - "xpack.lens.indexPattern.counterRate": "カウンターレート", - "xpack.lens.indexPattern.counterRate.signature": "メトリック:数値", - "xpack.lens.indexPattern.CounterRateOf": "{name} のカウンターレート", - "xpack.lens.indexPattern.countOf": "レコード数", - "xpack.lens.indexPattern.cumulative_sum.signature": "メトリック:数値", - "xpack.lens.indexPattern.cumulativeSum": "累積和", - "xpack.lens.indexPattern.cumulativeSumOf": "{name}の累積和", - "xpack.lens.indexPattern.dateHistogram": "日付ヒストグラム", - "xpack.lens.indexPattern.dateHistogram.autoAdvancedExplanation": "間隔は次のロジックに従います。", - "xpack.lens.indexPattern.dateHistogram.autoBasicExplanation": "自動日付ヒストグラムは、間隔でデータフィールドをバケットに分割します。", - "xpack.lens.indexPattern.dateHistogram.autoBoundHeader": "対象間隔の測定", - "xpack.lens.indexPattern.dateHistogram.autoHelpText": "仕組み", - "xpack.lens.indexPattern.dateHistogram.autoInterval": "時間範囲のカスタマイズ", - "xpack.lens.indexPattern.dateHistogram.autoIntervalHeader": "使用される間隔", - "xpack.lens.indexPattern.dateHistogram.autoLongerExplanation": "間隔を選択するには、Lensは指定された時間範囲を{targetBarSetting}設定で除算します。Lensはデータに最適な間隔を計算します。たとえば、30分、1時間、12です。棒の最大数は{maxBarSetting}値で設定します。", - "xpack.lens.indexPattern.dateHistogram.days": "日", - "xpack.lens.indexPattern.dateHistogram.hours": "時間", - "xpack.lens.indexPattern.dateHistogram.milliseconds": "ミリ秒", - "xpack.lens.indexPattern.dateHistogram.minimumInterval": "最低間隔", - "xpack.lens.indexPattern.dateHistogram.minutes": "分", - "xpack.lens.indexPattern.dateHistogram.month": "月", - "xpack.lens.indexPattern.dateHistogram.moreThanYear": "1年を超える", - "xpack.lens.indexPattern.dateHistogram.restrictedInterval": "集約の制限により間隔は {intervalValue} に固定されています。", - "xpack.lens.indexPattern.dateHistogram.seconds": "秒", - "xpack.lens.indexPattern.dateHistogram.titleHelp": "自動日付ヒストグラムの仕組み", - "xpack.lens.indexPattern.dateHistogram.upTo": "最大", - "xpack.lens.indexPattern.dateHistogram.week": "週", - "xpack.lens.indexPattern.dateHistogram.year": "年", - "xpack.lens.indexPattern.decimalPlacesLabel": "小数点以下", - "xpack.lens.indexPattern.defaultFormatLabel": "デフォルト", - "xpack.lens.indexPattern.derivative": "差異", - "xpack.lens.indexPattern.derivativeOf": "{name} の差異", - "xpack.lens.indexPattern.differences.signature": "メトリック:数値", - "xpack.lens.indexPattern.emptyDimensionButton": "空のディメンション", - "xpack.lens.indexPattern.emptyFieldsLabel": "空のフィールド", - "xpack.lens.indexPattern.emptyFieldsLabelHelp": "空のフィールドには、フィルターに基づく最初の 500 件のドキュメントの値が含まれていませんでした。", - "xpack.lens.indexPattern.existenceErrorAriaLabel": "存在の取り込みに失敗しました", - "xpack.lens.indexPattern.existenceErrorLabel": "フィールド情報を読み込めません", - "xpack.lens.indexPattern.existenceTimeoutAriaLabel": "存在の取り込みがタイムアウトしました", - "xpack.lens.indexPattern.existenceTimeoutLabel": "フィールド情報に時間がかかりすぎました", - "xpack.lens.indexPattern.fieldDistributionLabel": "分布", - "xpack.lens.indexPattern.fieldItem.visualizeGeoFieldLinkText": "Mapsで可視化", - "xpack.lens.indexPattern.fieldItemTooltip": "可視化するには、ドラッグアンドドロップします。", - "xpack.lens.indexPattern.fieldNoOperation": "フィールド{field}は演算なしで使用できません", - "xpack.lens.indexPattern.fieldNotFound": "フィールド {invalidField} が見つかりませんでした", - "xpack.lens.indexPattern.fieldPanelEmptyStringValue": "空の文字列", - "xpack.lens.indexPattern.fieldPlaceholder": "フィールド", - "xpack.lens.indexPattern.fieldStatsButtonAriaLabel": "プレビュー{fieldName}:{fieldType}", - "xpack.lens.indexPattern.fieldStatsButtonEmptyLabel": "このフィールドにはデータがありませんが、ドラッグアンドドロップで可視化できます。", - "xpack.lens.indexPattern.fieldStatsButtonLabel": "フィールドプレビューを表示するには、クリックします。可視化するには、ドラッグアンドドロップします。", - "xpack.lens.indexPattern.fieldStatsCountLabel": "カウント", - "xpack.lens.indexPattern.fieldStatsDisplayToggle": "次のどちらかを切り替えます:", - "xpack.lens.indexPattern.fieldStatsLimited": "範囲タイプフィールドの概要情報がありません。", - "xpack.lens.indexPattern.fieldStatsNoData": "このフィールドは空です。500件のサンプリングされたドキュメントに存在しません。このフィールドを構成に追加すると、空白のグラフが作成される場合があります。", - "xpack.lens.indexPattern.fieldTimeDistributionLabel": "時間分布", - "xpack.lens.indexPattern.fieldTopValuesLabel": "トップの値", - "xpack.lens.indexPattern.fieldWrongType": "フィールド{invalidField}の型が正しくありません", - "xpack.lens.indexPattern.filterBy.clickToEdit": "クリックして編集", - "xpack.lens.indexPattern.filterBy.emptyFilterQuery": "(空)", - "xpack.lens.indexPattern.filterBy.label": "フィルタリング条件", - "xpack.lens.indexPattern.filters": "フィルター", - "xpack.lens.indexPattern.filters.addaFilter": "フィルターを追加", - "xpack.lens.indexPattern.filters.clickToEdit": "クリックして編集", - "xpack.lens.indexPattern.filters.isInvalid": "このクエリは無効です", - "xpack.lens.indexPattern.filters.label.placeholder": "すべてのレコード", - "xpack.lens.indexPattern.filters.queryPlaceholderKql": "{example}", - "xpack.lens.indexPattern.filters.queryPlaceholderLucene": "{example}", - "xpack.lens.indexPattern.filters.removeFilter": "フィルターを削除", - "xpack.lens.indexPattern.formulaExpressionNotHandled": "式{operation}の演算には次のパラメーターがありません:{params}", - "xpack.lens.indexPattern.formulaExpressionParseError": "式{expression}を解析できません", - "xpack.lens.indexPattern.formulaExpressionWrongType": "式の演算{operation}のパラメーターの型が正しくありません:{params}", - "xpack.lens.indexPattern.formulaFieldNotRequired": "演算{operation}ではどのフィールドも引数として使用できません", - "xpack.lens.indexPattern.formulaFieldValue": "フィールド", - "xpack.lens.indexPattern.formulaLabel": "式", - "xpack.lens.indexPattern.formulaMathMissingArgument": "式{operation}の演算には{count}個の引数がありません:{params}", - "xpack.lens.indexPattern.formulaMetricValue": "メトリック", - "xpack.lens.indexPattern.formulaNoFieldForOperation": "フィールドなし", - "xpack.lens.indexPattern.formulaNoOperation": "演算なし", - "xpack.lens.indexPattern.formulaOperationDoubleQueryError": "kql=またはlucene=のいずれかのみを使用します。両方は使用できません", - "xpack.lens.indexPattern.formulaOperationDuplicateParams": "演算{operation}のパラメーターが複数回宣言されました:{params}", - "xpack.lens.indexPattern.formulaOperationQueryError": "{rawQuery}では{language}=''に単一引用符が必要です", - "xpack.lens.indexPattern.formulaOperationTooManyFirstArguments": "式の演算{operation}には{supported, plural, one {1つの} other {サポートされている}} {type}が必要です。検出:{text}", - "xpack.lens.indexPattern.formulaOperationValue": "演算", - "xpack.lens.indexPattern.formulaOperationwrongArgument": "式の演算{operation}は{type}パラメーターをサポートしていません。検出:{text}", - "xpack.lens.indexPattern.formulaOperationWrongFirstArgument": "{operation}の最初の引数は{type}名でなければなりません。{argument}が見つかりました", - "xpack.lens.indexPattern.formulaParameterNotRequired": "演算{operation}ではどのパラメーターも使用できません", - "xpack.lens.indexPattern.formulaPartLabel": "{label}の一部", - "xpack.lens.indexPattern.formulaWarning": "現在適用されている式", - "xpack.lens.indexPattern.formulaWarningText": "式を上書きするには、クイック関数を選択します", - "xpack.lens.indexPattern.formulaWithTooManyArguments": "演算{operation}の引数が多すぎます", - "xpack.lens.indexPattern.functionsLabel": "関数を選択", - "xpack.lens.indexPattern.groupByDropdown": "グループ分けの条件", - "xpack.lens.indexPattern.incompleteOperation": "(未完了)", - "xpack.lens.indexPattern.intervals": "間隔", - "xpack.lens.indexPattern.invalidInterval": "無効な間隔値", - "xpack.lens.indexPattern.invalidOperationLabel": "選択した関数はこのフィールドで動作しません。", - "xpack.lens.indexPattern.invalidReferenceConfiguration": "ディメンション\"{dimensionLabel}\"の構成が正しくありません", - "xpack.lens.indexPattern.invalidTimeShift": "無効な時間シフトです。正の整数の後に単位s、m、h、d、w、M、yのいずれかを入力します。例:3時間は3hです", - "xpack.lens.indexPattern.lastValue": "最終値", - "xpack.lens.indexPattern.lastValue.invalidTypeSortField": "フィールド {invalidField} は日付フィールドではないため、並べ替えで使用できません", - "xpack.lens.indexPattern.lastValue.signature": "フィールド:文字列", - "xpack.lens.indexPattern.lastValue.sortField": "日付フィールドで並べ替え", - "xpack.lens.indexPattern.lastValue.sortFieldNotFound": "フィールド {invalidField} が見つかりませんでした", - "xpack.lens.indexPattern.lastValue.sortFieldPlaceholder": "並べ替えフィールド", - "xpack.lens.indexPattern.lastValueOf": "{name} の最後の値", - "xpack.lens.indexPattern.layerErrorWrapper": "レイヤー{position}エラー:{wrappedMessage}", - "xpack.lens.indexPattern.max": "最高", - "xpack.lens.indexPattern.max.description": "集約されたドキュメントから抽出された数値の最大値を返す単一値メトリック集約。", - "xpack.lens.indexPattern.maxOf": "{name} の最高値", - "xpack.lens.indexPattern.median": "中央", - "xpack.lens.indexPattern.median.description": "集約されたドキュメントから抽出された中央値を計算する単一値メトリック集約。", - "xpack.lens.indexPattern.medianOf": "{name} の中央値", - "xpack.lens.indexPattern.metaFieldsLabel": "メタフィールド", - "xpack.lens.indexPattern.metric.signature": "フィールド:文字列", - "xpack.lens.indexPattern.min": "最低", - "xpack.lens.indexPattern.min.description": "集約されたドキュメントから抽出された数値の最小値を返す単一値メトリック集約。", - "xpack.lens.indexPattern.minOf": "{name} の最低値", - "xpack.lens.indexPattern.missingFieldLabel": "見つからないフィールド", - "xpack.lens.indexPattern.missingReferenceError": "\"{dimensionLabel}\"は完全に構成されていません", - "xpack.lens.indexPattern.moveToWorkspace": "{field}をワークスペースに追加", - "xpack.lens.indexPattern.moveToWorkspaceDisabled": "このフィールドは自動的にワークスペースに追加できません。構成パネルで直接使用することはできます。", - "xpack.lens.indexPattern.moving_average.signature": "メトリック:数値、[window]:数値", - "xpack.lens.indexPattern.movingAverage": "移動平均", - "xpack.lens.indexPattern.movingAverage.basicExplanation": "移動平均はデータ全体でウィンドウをスライドし、平均値を表示します。移動平均は日付ヒストグラムでのみサポートされています。", - "xpack.lens.indexPattern.movingAverage.helpText": "仕組み", - "xpack.lens.indexPattern.movingAverage.limitations": "最初の移動平均値は2番目の項目から開始します。", - "xpack.lens.indexPattern.movingAverage.longerExplanation": "移動平均を計算するには、Lensはウィンドウの平均値を使用し、ギャップのスキップポリシーを適用します。 見つからない値がある場合、バケットがスキップされます。次の値に対して計算が実行されます。", - "xpack.lens.indexPattern.movingAverage.tableExplanation": "たとえば、データ[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]がある場合、ウィンドウサイズ5でシンプルな移動平均を計算できます。", - "xpack.lens.indexPattern.movingAverage.titleHelp": "移動平均の仕組み", - "xpack.lens.indexPattern.movingAverage.window": "ウィンドウサイズ", - "xpack.lens.indexPattern.movingAverage.windowInitialPartial": "要求されたアイテム数に達するまで、ウィンドウは部分的です。 例:ウィンドウサイズ5。", - "xpack.lens.indexPattern.movingAverage.windowLimitations": "ウィンドウには現在の値が含まれません。", - "xpack.lens.indexPattern.movingAverageOf": "{name} の移動平均", - "xpack.lens.indexPattern.multipleDateHistogramsError": "\"{dimensionLabel}\"は唯一の日付ヒストグラムではありません。時間シフトを使用するときには、1つの日付ヒストグラムのみを使用していることを確認してください。", - "xpack.lens.indexPattern.numberFormatLabel": "数字", - "xpack.lens.indexPattern.ofDocumentsLabel": "ドキュメント", - "xpack.lens.indexPattern.otherDocsLabel": "その他", - "xpack.lens.indexPattern.overall_metric": "メトリック:数値", - "xpack.lens.indexPattern.overallAverageOf": "{name}の全体平均値", - "xpack.lens.indexPattern.overallMax": "全体最高", - "xpack.lens.indexPattern.overallMaxOf": "{name}の全体最大値", - "xpack.lens.indexPattern.overallMin": "全体最低", - "xpack.lens.indexPattern.overallMinOf": "{name}の全体最小値", - "xpack.lens.indexPattern.overallSum": "全体合計", - "xpack.lens.indexPattern.overallSumOf": "{name}の全体平方和", - "xpack.lens.indexPattern.percentageOfLabel": "{percentage}% の", - "xpack.lens.indexPattern.percentFormatLabel": "割合(%)", - "xpack.lens.indexPattern.percentile": "パーセンタイル", - "xpack.lens.indexPattern.percentile.errorMessage": "パーセンタイルは1~99の範囲の整数でなければなりません。", - "xpack.lens.indexPattern.percentile.percentileValue": "パーセンタイル", - "xpack.lens.indexPattern.percentile.signature": "フィールド:文字列、[percentile]:数値", - "xpack.lens.indexPattern.percentileOf": "{name}の{percentile, selectordinal, other {#}}パーセンタイル", - "xpack.lens.indexPattern.pinnedTopValuesLabel": "{field}のフィルター", - "xpack.lens.indexPattern.quickFunctionsLabel": "クイック機能", - "xpack.lens.indexPattern.range.isInvalid": "この範囲は無効です", - "xpack.lens.indexPattern.ranges.addRange": "範囲を追加", - "xpack.lens.indexPattern.ranges.customIntervalsToggle": "カスタム範囲を作成", - "xpack.lens.indexPattern.ranges.customRangeLabelPlaceholder": "カスタムラベル", - "xpack.lens.indexPattern.ranges.customRanges": "範囲", - "xpack.lens.indexPattern.ranges.customRangesRemoval": "カスタム範囲を削除", - "xpack.lens.indexPattern.ranges.decreaseButtonLabel": "粒度を下げる", - "xpack.lens.indexPattern.ranges.deleteRange": "範囲を削除", - "xpack.lens.indexPattern.ranges.granularity": "間隔粒度", - "xpack.lens.indexPattern.ranges.granularityHelpText": "仕組み", - "xpack.lens.indexPattern.ranges.granularityPopoverAdvancedExplanation": "間隔は10、5、または2ずつ増分します。たとえば、間隔を100または0.2にすることができます。", - "xpack.lens.indexPattern.ranges.granularityPopoverBasicExplanation": "間隔の粒度は、フィールドの最小値と最大値に基づいて、フィールドを均等な幅の間隔に分割します。", - "xpack.lens.indexPattern.ranges.granularityPopoverExplanation": "間隔のサイズは「nice」値です。スライダーの粒度を変更すると、「nice」間隔が同じときには、間隔が同じままです。最小粒度は1です。最大値は{setting}です。最大粒度を変更するには、[高度な設定]に移動します。", - "xpack.lens.indexPattern.ranges.granularityPopoverTitle": "粒度間隔の仕組み", - "xpack.lens.indexPattern.ranges.increaseButtonLabel": "粒度を上げる", - "xpack.lens.indexPattern.ranges.lessThanOrEqualAppend": "≤", - "xpack.lens.indexPattern.ranges.lessThanOrEqualTooltip": "以下", - "xpack.lens.indexPattern.ranges.lessThanPrepend": "<", - "xpack.lens.indexPattern.ranges.lessThanTooltip": "より小さい", - "xpack.lens.indexPattern.records": "記録", - "xpack.lens.indexPattern.referenceFunctionPlaceholder": "サブ関数", - "xpack.lens.indexPattern.removeColumnAriaLabel": "フィールドを追加するか、{groupLabel}までドラッグアンドドロップします", - "xpack.lens.indexPattern.removeColumnLabel": "「{groupLabel}」から構成を削除", - "xpack.lens.indexPattern.sortField.invalid": "無効なフィールドです。インデックスパターンを確認するか、別のフィールドを選択してください。", - "xpack.lens.indexpattern.suggestions.nestingChangeLabel": "各 {outerOperation} の {innerOperation}", - "xpack.lens.indexpattern.suggestions.overallLabel": "全体の {operation}", - "xpack.lens.indexpattern.suggestions.overTimeLabel": "一定時間", - "xpack.lens.indexPattern.sum": "合計", - "xpack.lens.indexPattern.sum.description": "集約されたドキュメントから抽出された数値を合計する単一値メトリック集約。", - "xpack.lens.indexPattern.sumOf": "{name} の合計", - "xpack.lens.indexPattern.terms": "トップの値", - "xpack.lens.indexPattern.terms.advancedSettings": "高度な設定", - "xpack.lens.indexPattern.terms.missingBucketDescription": "このフィールドなしでドキュメントを含める", - "xpack.lens.indexPattern.terms.missingLabel": "(欠落値)", - "xpack.lens.indexPattern.terms.orderAlphabetical": "アルファベット順", - "xpack.lens.indexPattern.terms.orderAscending": "昇順", - "xpack.lens.indexPattern.terms.orderBy": "ランク条件", - "xpack.lens.indexPattern.terms.orderByHelp": "上位の値がランク付けされる条件となるディメンションを指定します。", - "xpack.lens.indexPattern.terms.orderDescending": "降順", - "xpack.lens.indexPattern.terms.orderDirection": "ランク方向", - "xpack.lens.indexPattern.terms.otherBucketDescription": "他の値を「その他」としてグループ化", - "xpack.lens.indexPattern.terms.otherLabel": "その他", - "xpack.lens.indexPattern.terms.size": "値の数", - "xpack.lens.indexPattern.termsOf": "{name} のトップの値", - "xpack.lens.indexPattern.termsWithMultipleShifts": "単一のレイヤーでは、メトリックを異なる時間シフトと動的な上位の値と組み合わせることができません。すべてのメトリックで同じ時間シフト値を使用するか、上位の値ではなくフィルターを使用します。", - "xpack.lens.indexPattern.termsWithMultipleShiftsFixActionLabel": "フィルターを使用", - "xpack.lens.indexPattern.timeScale.enableTimeScale": "単位で正規化", - "xpack.lens.indexPattern.timeScale.label": "単位で正規化", - "xpack.lens.indexPattern.timeScale.tooltip": "基本の日付間隔に関係なく、常に指定された時間単位のレートとして表示されるように値を正規化します。", - "xpack.lens.indexPattern.timeShift.12hours": "12時間前(12h)", - "xpack.lens.indexPattern.timeShift.3hours": "3時間前(3h)", - "xpack.lens.indexPattern.timeShift.3months": "3か月前(3M)", - "xpack.lens.indexPattern.timeShift.6hours": "6時間前(6h)", - "xpack.lens.indexPattern.timeShift.6months": "6か月前(6M)", - "xpack.lens.indexPattern.timeShift.day": "1日前(1d)", - "xpack.lens.indexPattern.timeShift.help": "時間シフトと単位を入力", - "xpack.lens.indexPattern.timeShift.hour": "1時間前(1h)", - "xpack.lens.indexPattern.timeShift.label": "時間シフト", - "xpack.lens.indexPattern.timeShift.month": "1か月前(1M)", - "xpack.lens.indexPattern.timeShift.noMultipleHelp": "時間シフトは日付ヒストグラム間隔の乗数でなければなりません。時間シフトまたは日付ヒストグラム間隔を調整", - "xpack.lens.indexPattern.timeShift.tooSmallHelp": "時間シフトは日付ヒストグラム間隔よりも大きくなければなりません。時間シフトを増やすか、日付ヒストグラムで間隔を小さくしてください", - "xpack.lens.indexPattern.timeShift.week": "1週間前(1w)", - "xpack.lens.indexPattern.timeShift.year": "1年前(1y)", - "xpack.lens.indexPattern.timeShiftMultipleWarning": "{label}は{columnTimeShift}の時間シフトを使用しています。これは{interval}の日付ヒストグラム間隔の乗数ではありません。不一致のデータを防止するには、時間シフトとして{interval}を使用します。", - "xpack.lens.indexPattern.timeShiftPlaceholder": "カスタム値を入力(例:8w)", - "xpack.lens.indexPattern.timeShiftSmallWarning": "{label}は{columnTimeShift}の時間シフトを使用しています。これは{interval}の日付ヒストグラム間隔よりも小さいです。不一致のデータを防止するには、時間シフトとして{interval}を使用します。", - "xpack.lens.indexPattern.uniqueLabel": "{label} [{num}]", - "xpack.lens.indexPattern.useAsTopLevelAgg": "最初にこのフィールドでグループ化", - "xpack.lens.indexPatterns.clearFiltersLabel": "名前とタイプフィルターを消去", - "xpack.lens.indexPatterns.fieldFiltersLabel": "タイプでフィルタリング", - "xpack.lens.indexPatterns.noAvailableDataLabel": "データを含むフィールドはありません。", - "xpack.lens.indexPatterns.noDataLabel": "フィールドがありません。", - "xpack.lens.indexPatterns.noEmptyDataLabel": "空のフィールドがありません。", - "xpack.lens.indexPatterns.noFields.extendTimeBullet": "時間範囲を拡張中", - "xpack.lens.indexPatterns.noFields.fieldTypeFilterBullet": "別のフィールドフィルターを使用", - "xpack.lens.indexPatterns.noFields.globalFiltersBullet": "グローバルフィルターを変更", - "xpack.lens.indexPatterns.noFields.tryText": "試行対象:", - "xpack.lens.indexPatterns.noFilteredFieldsLabel": "選択したフィルターと一致するフィールドはありません。", - "xpack.lens.indexPatterns.noMetaDataLabel": "メタフィールドがありません。", - "xpack.lens.indexPatternSuggestion.removeLayerLabel": "{indexPatternTitle}のみを表示", - "xpack.lens.indexPatternSuggestion.removeLayerPositionLabel": "レイヤー{layerNumber}のみを表示", - "xpack.lens.labelInput.label": "ラベル", - "xpack.lens.layerPanel.layerVisualizationType": "レイヤービジュアライゼーションタイプ", - "xpack.lens.lensSavedObjectLabel": "レンズビジュアライゼーション", - "xpack.lens.metric.addLayer": "ビジュアライゼーションレイヤーを追加", - "xpack.lens.metric.groupLabel": "表形式の値と単一の値", - "xpack.lens.metric.label": "メトリック", - "xpack.lens.pageTitle": "レンズ", - "xpack.lens.paletteHeatmapGradient.customize": "編集", - "xpack.lens.paletteHeatmapGradient.customizeLong": "パレットを編集", - "xpack.lens.paletteHeatmapGradient.label": "色", - "xpack.lens.palettePicker.label": "カラーパレット", - "xpack.lens.paletteTableGradient.customize": "編集", - "xpack.lens.paletteTableGradient.label": "色", - "xpack.lens.pie.addLayer": "ビジュアライゼーションレイヤーを追加", - "xpack.lens.pie.arrayValues": "{label}には配列値が含まれます。可視化が想定通りに表示されない場合があります。", - "xpack.lens.pie.donutLabel": "ドーナッツ", - "xpack.lens.pie.expressionHelpLabel": "円表示", - "xpack.lens.pie.groupLabel": "比率", - "xpack.lens.pie.groupsizeLabel": "サイズ単位", - "xpack.lens.pie.pielabel": "円", - "xpack.lens.pie.pieWithNegativeWarningLabel": "{chartType}グラフは負の値では表示できません。別のビジュアライゼーションを試してください。", - "xpack.lens.pie.sliceGroupLabel": "スライス", - "xpack.lens.pie.suggestionLabel": "{chartName}として", - "xpack.lens.pie.treemapGroupLabel": "グループ分けの条件", - "xpack.lens.pie.treemaplabel": "ツリーマップ", - "xpack.lens.pie.treemapSuggestionLabel": "ツリーマップとして", - "xpack.lens.pie.visualizationName": "円", - "xpack.lens.pieChart.categoriesInLegendLabel": "ラベルを非表示", - "xpack.lens.pieChart.fitInsideOnlyLabel": "内部のみ", - "xpack.lens.pieChart.hiddenNumbersLabel": "グラフから非表示", - "xpack.lens.pieChart.labelPositionLabel": "位置", - "xpack.lens.pieChart.legendVisibility.auto": "自動", - "xpack.lens.pieChart.legendVisibility.hide": "非表示", - "xpack.lens.pieChart.legendVisibility.show": "表示", - "xpack.lens.pieChart.nestedLegendLabel": "ネスト済み", - "xpack.lens.pieChart.numberLabels": "値", - "xpack.lens.pieChart.percentDecimalsLabel": "割合の最大小数点桁数", - "xpack.lens.pieChart.showCategoriesLabel": "内部または外部", - "xpack.lens.pieChart.showFormatterValuesLabel": "値を表示", - "xpack.lens.pieChart.showPercentValuesLabel": "割合を表示", - "xpack.lens.pieChart.showTreemapCategoriesLabel": "ラベルを表示", - "xpack.lens.pieChart.valuesLabel": "ラベル", - "xpack.lens.resetLayerAriaLabel": "レイヤー {index} をリセット", - "xpack.lens.resetVisualizationAriaLabel": "ビジュアライゼーションをリセット", - "xpack.lens.searchTitle": "Lens:ビジュアライゼーションを作成", - "xpack.lens.section.configPanelLabel": "構成パネル", - "xpack.lens.section.dataPanelLabel": "データパネル", - "xpack.lens.section.workspaceLabel": "ビジュアライゼーションワークスペース", - "xpack.lens.shared.chartValueLabelVisibilityLabel": "ラベル", - "xpack.lens.shared.curveLabel": "視覚オプション", - "xpack.lens.shared.legend.filterForValueButtonAriaLabel": "値でフィルター", - "xpack.lens.shared.legend.filterOptionsLegend": "{legendDataLabel}、フィルターオプション", - "xpack.lens.shared.legend.filterOutValueButtonAriaLabel": "値を除外", - "xpack.lens.shared.legendAlignmentLabel": "アラインメント", - "xpack.lens.shared.legendInsideAlignmentLabel": "アラインメント", - "xpack.lens.shared.legendInsideColumnsLabel": "列の数", - "xpack.lens.shared.legendInsideLocationAlignmentLabel": "アラインメント", - "xpack.lens.shared.legendInsideTooltip": "凡例をビジュアライゼーション内に配置する必要があります", - "xpack.lens.shared.legendIsTruncated": "テキストを切り捨てる必要があります", - "xpack.lens.shared.legendLabel": "凡例", - "xpack.lens.shared.legendLocationBottomLeft": "左下", - "xpack.lens.shared.legendLocationBottomRight": "右下", - "xpack.lens.shared.legendLocationLabel": "場所", - "xpack.lens.shared.legendLocationTopLeft": "左上", - "xpack.lens.shared.legendLocationTopRight": "右上", - "xpack.lens.shared.legendPositionBottom": "一番下", - "xpack.lens.shared.legendPositionLeft": "左", - "xpack.lens.shared.legendPositionRight": "右", - "xpack.lens.shared.legendPositionTop": "トップ", - "xpack.lens.shared.legendVisibilityLabel": "表示", - "xpack.lens.shared.legendVisibleTooltip": "凡例を表示する必要があります", - "xpack.lens.shared.maxLinesLabel": "最大行", - "xpack.lens.shared.nestedLegendLabel": "ネスト済み", - "xpack.lens.shared.truncateLegend": "テキストを切り捨て", - "xpack.lens.shared.valueInLegendLabel": "値を表示", - "xpack.lens.sugegstion.refreshSuggestionLabel": "更新", - "xpack.lens.suggestion.refreshSuggestionTooltip": "選択したビジュアライゼーションに基づいて、候補を更新します。", - "xpack.lens.suggestions.currentVisLabel": "現在のビジュアライゼーション", - "xpack.lens.table.actionsLabel": "アクションを表示", - "xpack.lens.table.alignment.center": "中央", - "xpack.lens.table.alignment.label": "テキスト配置", - "xpack.lens.table.alignment.left": "左", - "xpack.lens.table.alignment.right": "右", - "xpack.lens.table.columnFilter.filterForValueText": "列のフィルター", - "xpack.lens.table.columnFilter.filterOutValueText": "列を除外", - "xpack.lens.table.columnVisibilityLabel": "列を非表示", - "xpack.lens.table.defaultAriaLabel": "データ表ビジュアライゼーション", - "xpack.lens.table.dynamicColoring.cell": "セル", - "xpack.lens.table.dynamicColoring.continuity.aboveLabel": "範囲の上", - "xpack.lens.table.dynamicColoring.continuity.allLabel": "範囲の上下", - "xpack.lens.table.dynamicColoring.continuity.belowLabel": "範囲の下", - "xpack.lens.table.dynamicColoring.continuity.label": "色の連続", - "xpack.lens.table.dynamicColoring.continuity.noneLabel": "範囲内", - "xpack.lens.table.dynamicColoring.customPalette.colorStopsHelpPercentage": "割合値は使用可能なデータ値の全範囲に対して相対的です。", - "xpack.lens.table.dynamicColoring.customPalette.colorStopsLabel": "色経由点", - "xpack.lens.table.dynamicColoring.customPalette.continuityHelp": "最初の色経由点の前、最後の色経由点の後に色が表示される方法を指定します。", - "xpack.lens.table.dynamicColoring.label": "値別の色", - "xpack.lens.table.dynamicColoring.none": "なし", - "xpack.lens.table.dynamicColoring.rangeType.label": "値型", - "xpack.lens.table.dynamicColoring.rangeType.number": "数字", - "xpack.lens.table.dynamicColoring.rangeType.percent": "割合(%)", - "xpack.lens.table.dynamicColoring.reverse.label": "色を反転", - "xpack.lens.table.dynamicColoring.text": "テキスト", - "xpack.lens.table.hide.hideLabel": "非表示", - "xpack.lens.table.palettePanelContainer.back": "戻る", - "xpack.lens.table.palettePanelTitle": "色の編集", - "xpack.lens.table.resize.reset": "幅のリセット", - "xpack.lens.table.sort.ascLabel": "昇順に並べ替える", - "xpack.lens.table.sort.descLabel": "降順に並べ替える", - "xpack.lens.table.summaryRow.average": "平均", - "xpack.lens.table.summaryRow.count": "値カウント", - "xpack.lens.table.summaryRow.customlabel": "概要ラベル", - "xpack.lens.table.summaryRow.label": "概要行", - "xpack.lens.table.summaryRow.maximum": "最高", - "xpack.lens.table.summaryRow.minimum": "最低", - "xpack.lens.table.summaryRow.none": "なし", - "xpack.lens.table.summaryRow.sum": "合計", - "xpack.lens.table.tableCellFilter.filterForValueAriaLabel": "値のフィルター:{cellContent}", - "xpack.lens.table.tableCellFilter.filterForValueText": "値でフィルター", - "xpack.lens.table.tableCellFilter.filterOutValueAriaLabel": "値の除外:{cellContent}", - "xpack.lens.table.tableCellFilter.filterOutValueText": "値を除外", - "xpack.lens.timeScale.removeLabel": "時間単位で正規化を削除", - "xpack.lens.timeShift.removeLabel": "時間シフトを削除", - "xpack.lens.visTypeAlias.description": "ドラッグアンドドロップエディターでビジュアライゼーションを作成します。いつでもビジュアライゼーションタイプを切り替えることができます。", - "xpack.lens.visTypeAlias.note": "ほとんどのユーザーに推奨されます。", - "xpack.lens.visTypeAlias.title": "レンズ", - "xpack.lens.visTypeAlias.type": "レンズ", - "xpack.lens.visualizeGeoFieldMessage": "Lensは{fieldType}フィールドを可視化できません", - "xpack.lens.xyChart.addDataLayerLabel": "ビジュアライゼーションレイヤーを追加", - "xpack.lens.xyChart.addLayer": "レイヤーを追加", - "xpack.lens.xyChart.addLayerTooltip": "複数のレイヤーを使用すると、ビジュアライゼーションタイプを組み合わせたり、別のインデックスパターンを可視化したりすることができます。", - "xpack.lens.xyChart.axisExtent.custom": "カスタム", - "xpack.lens.xyChart.axisExtent.dataBounds": "データ境界", - "xpack.lens.xyChart.axisExtent.disabledDataBoundsMessage": "折れ線グラフのみをデータ境界に合わせることができます", - "xpack.lens.xyChart.axisExtent.full": "完全", - "xpack.lens.xyChart.axisExtent.label": "境界", - "xpack.lens.xyChart.axisNameLabel": "軸名", - "xpack.lens.xyChart.axisOrientation.angled": "傾斜", - "xpack.lens.xyChart.axisOrientation.horizontal": "横", - "xpack.lens.xyChart.axisOrientation.label": "向き", - "xpack.lens.xyChart.axisOrientation.vertical": "縦", - "xpack.lens.xyChart.axisSide.auto": "自動", - "xpack.lens.xyChart.axisSide.bottom": "一番下", - "xpack.lens.xyChart.axisSide.label": "軸側", - "xpack.lens.xyChart.axisSide.left": "左", - "xpack.lens.xyChart.axisSide.right": "右", - "xpack.lens.xyChart.axisSide.top": "トップ", - "xpack.lens.xyChart.axisTitlesSettings.help": "xおよびy軸のタイトルを表示", - "xpack.lens.xyChart.bottomAxisDisabledHelpText": "この設定は、下の軸が有効であるときにのみ適用されます。", - "xpack.lens.xyChart.bottomAxisLabel": "下の軸", - "xpack.lens.xyChart.boundaryError": "下界は上界よりも大きくなければなりません", - "xpack.lens.xyChart.chartTypeLabel": "チャートタイプ", - "xpack.lens.xyChart.chartTypeLegend": "チャートタイプ", - "xpack.lens.xyChart.curveStyleLabel": "曲線", - "xpack.lens.xyChart.curveType.help": "折れ線グラフで曲線タイプをレンダリングする方法を定義します", - "xpack.lens.xyChart.emptyXLabel": "(空)", - "xpack.lens.xyChart.extentMode.help": "範囲モード", - "xpack.lens.xyChart.fillOpacity.help": "エリアグラフの塗りつぶしの透明度を定義", - "xpack.lens.xyChart.fillOpacityLabel": "塗りつぶしの透明度", - "xpack.lens.xyChart.fittingFunction.help": "欠測値の処理方法を定義", - "xpack.lens.xyChart.floatingColumns.help": "凡例がグラフ内に表示されるときに列数を指定します。", - "xpack.lens.xyChart.Gridlines": "グリッド線", - "xpack.lens.xyChart.gridlinesSettings.help": "xおよびy軸のグリッド線を表示", - "xpack.lens.xyChart.help": "X/Y チャート", - "xpack.lens.xyChart.hideEndzones.help": "部分データの終了ゾーンマーカーを非表示", - "xpack.lens.xyChart.horizontalAlignment.help": "凡例がグラフ内に表示されるときに凡例の横の配置を指定します。", - "xpack.lens.xyChart.horizontalAxisLabel": "横軸", - "xpack.lens.xyChart.inclusiveZero": "境界にはゼロを含める必要があります。", - "xpack.lens.xyChart.isInside.help": "凡例がグラフ内に表示されるかどうかを指定します", - "xpack.lens.xyChart.isVisible.help": "判例の表示・非表示を指定します。", - "xpack.lens.xyChart.labelsOrientation.help": "軸ラベルの回転を定義します", - "xpack.lens.xyChart.leftAxisDisabledHelpText": "この設定は、左の軸が有効であるときにのみ適用されます。", - "xpack.lens.xyChart.leftAxisLabel": "左の軸", - "xpack.lens.xyChart.legend.help": "チャートの凡例を構成します。", - "xpack.lens.xyChart.legendLocation.inside": "内部", - "xpack.lens.xyChart.legendLocation.outside": "外側", - "xpack.lens.xyChart.legendVisibility.auto": "自動", - "xpack.lens.xyChart.legendVisibility.hide": "非表示", - "xpack.lens.xyChart.legendVisibility.show": "表示", - "xpack.lens.xyChart.lowerBoundLabel": "下界", - "xpack.lens.xyChart.maxLines.help": "凡例項目ごとの行数を指定します。", - "xpack.lens.xyChart.missingValuesLabel": "欠測値", - "xpack.lens.xyChart.missingValuesLabelHelpText": "デフォルトでは、Lensではデータのギャップが表示されません。ギャップを埋めるには、選択します。", - "xpack.lens.xyChart.nestUnderRoot": "データセット全体", - "xpack.lens.xyChart.overwriteAxisTitle": "軸タイトルを上書き", - "xpack.lens.xyChart.position.help": "凡例の配置を指定します。", - "xpack.lens.xyChart.renderer.help": "X/Y チャートを再レンダリング", - "xpack.lens.xyChart.rightAxisDisabledHelpText": "この設定は、右の軸が有効であるときにのみ適用されます。", - "xpack.lens.xyChart.rightAxisLabel": "右の軸", - "xpack.lens.xyChart.seriesColor.auto": "自動", - "xpack.lens.xyChart.seriesColor.label": "系列色", - "xpack.lens.xyChart.shouldTruncate.help": "凡例項目が切り捨てられるかどうかを指定します", - "xpack.lens.xyChart.ShowAxisTitleLabel": "表示", - "xpack.lens.xyChart.showEnzones": "部分データマーカーを表示", - "xpack.lens.xyChart.showSingleSeries.help": "エントリが1件の凡例を表示するかどうかを指定します", - "xpack.lens.xyChart.splitSeries": "内訳の基準", - "xpack.lens.xyChart.tickLabels": "目盛ラベル", - "xpack.lens.xyChart.tickLabelsSettings.help": "xおよびy軸の目盛ラベルを表示", - "xpack.lens.xyChart.title.help": "軸のタイトル", - "xpack.lens.xyChart.topAxisDisabledHelpText": "この設定は、上の軸が有効であるときにのみ適用されます。", - "xpack.lens.xyChart.topAxisLabel": "上の軸", - "xpack.lens.xyChart.upperBoundLabel": "上界", - "xpack.lens.xyChart.valuesHistogramDisabledHelpText": "この設定はヒストグラムで変更できません。", - "xpack.lens.xyChart.valuesInLegend.help": "凡例に値を表示", - "xpack.lens.xyChart.valuesPercentageDisabledHelpText": "この設定は割合エリアグラフで変更できません。", - "xpack.lens.xyChart.valuesStackedDisabledHelpText": "この設定は積み上げ棒グラフまたは割合棒グラフで変更できません", - "xpack.lens.xyChart.verticalAlignment.help": "凡例がグラフ内に表示されるときに凡例の縦の配置を指定します。", - "xpack.lens.xyChart.verticalAxisLabel": "縦軸", - "xpack.lens.xyChart.xAxisGridlines.help": "x 軸のグリッド線を表示するかどうかを指定します。", - "xpack.lens.xyChart.xAxisLabelsOrientation.help": "x軸のラベルの向きを指定します。", - "xpack.lens.xyChart.xAxisTickLabels.help": "x軸の目盛ラベルを表示するかどうかを指定します。", - "xpack.lens.xyChart.xAxisTitle.help": "x軸のタイトルを表示するかどうかを指定します。", - "xpack.lens.xyChart.xTitle.help": "x軸のタイトル", - "xpack.lens.xyChart.yLeftAxisgridlines.help": "左y軸のグリッド線を表示するかどうかを指定します。", - "xpack.lens.xyChart.yLeftAxisLabelsOrientation.help": "左y軸のラベルの向きを指定します。", - "xpack.lens.xyChart.yLeftAxisTickLabels.help": "左y軸の目盛ラベルを表示するかどうかを指定します。", - "xpack.lens.xyChart.yLeftAxisTitle.help": "左y軸のタイトルを表示するかどうかを指定します。", - "xpack.lens.xyChart.yLeftExtent.help": "Y左軸範囲", - "xpack.lens.xyChart.yLeftTitle.help": "左y軸のタイトル", - "xpack.lens.xyChart.yRightAxisgridlines.help": "右y軸のグリッド線を表示するかどうかを指定します。", - "xpack.lens.xyChart.yRightAxisLabelsOrientation.help": "右y軸のラベルの向きを指定します。", - "xpack.lens.xyChart.yRightAxisTickLabels.help": "右y軸の目盛ラベルを表示するかどうかを指定します。", - "xpack.lens.xyChart.yRightAxisTitle.help": "右y軸のタイトルを表示するかどうかを指定します。", - "xpack.lens.xyChart.yRightExtent.help": "Y右軸範囲", - "xpack.lens.xyChart.yRightTitle.help": "右 y 軸のタイトル", - "xpack.lens.xySuggestions.asPercentageTitle": "割合(%)", - "xpack.lens.xySuggestions.barChartTitle": "棒グラフ", - "xpack.lens.xySuggestions.dateSuggestion": "{xTitle}の上の {yTitle}", - "xpack.lens.xySuggestions.emptyAxisTitle": "(空)", - "xpack.lens.xySuggestions.flipTitle": "反転", - "xpack.lens.xySuggestions.lineChartTitle": "折れ線グラフ", - "xpack.lens.xySuggestions.nonDateSuggestion": "{yTitle}/{xTitle}", - "xpack.lens.xySuggestions.stackedChartTitle": "スタック", - "xpack.lens.xySuggestions.unstackedChartTitle": "スタックが解除されました", - "xpack.lens.xySuggestions.yAxixConjunctionSign": " & ", - "xpack.lens.xyVisualization.areaLabel": "エリア", - "xpack.lens.xyVisualization.arrayValues": "{label}には配列値が含まれます。可視化が想定通りに表示されない場合があります。", - "xpack.lens.xyVisualization.barGroupLabel": "棒", - "xpack.lens.xyVisualization.barHorizontalFullLabel": "横棒", - "xpack.lens.xyVisualization.barHorizontalLabel": "H.棒", - "xpack.lens.xyVisualization.barLabel": "縦棒", - "xpack.lens.xyVisualization.dataFailureSplitShort": "{axis} がありません。", - "xpack.lens.xyVisualization.dataFailureYShort": "{axis} がありません。", - "xpack.lens.xyVisualization.dataTypeFailureXLong": "{axis}のデータ型が一致しません。日付と数値間隔型を混合することはできません。", - "xpack.lens.xyVisualization.dataTypeFailureXOrdinalLong": "{axis}のデータ型が一致しません。別の関数を使用してください。", - "xpack.lens.xyVisualization.dataTypeFailureXShort": "{axis}のデータ型が正しくありません。", - "xpack.lens.xyVisualization.dataTypeFailureYLong": "{axis}のディメンション{label}のデータ型が正しくありません。数値が想定されていますが、{dataType}です", - "xpack.lens.xyVisualization.dataTypeFailureYShort": "{axis}のデータ型が正しくありません。", - "xpack.lens.xyVisualization.lineGroupLabel": "折れ線と面", - "xpack.lens.xyVisualization.lineLabel": "折れ線", - "xpack.lens.xyVisualization.mixedBarHorizontalLabel": "混在した横棒", - "xpack.lens.xyVisualization.mixedLabel": "ミックスされた XY", - "xpack.lens.xyVisualization.noDataLabel": "結果が見つかりませんでした", - "xpack.lens.xyVisualization.stackedAreaLabel": "面積み上げ", - "xpack.lens.xyVisualization.stackedBarHorizontalFullLabel": "積み上げ横棒", - "xpack.lens.xyVisualization.stackedBarHorizontalLabel": "H.積み上げ棒", - "xpack.lens.xyVisualization.stackedBarLabel": "積み上げ縦棒", - "xpack.lens.xyVisualization.stackedPercentageAreaLabel": "面割合", - "xpack.lens.xyVisualization.stackedPercentageBarHorizontalFullLabel": "横棒割合", - "xpack.lens.xyVisualization.stackedPercentageBarHorizontalLabel": "H.割合棒", - "xpack.lens.xyVisualization.stackedPercentageBarLabel": "縦棒割合", - "xpack.lens.xyVisualization.xyLabel": "XY", - "advancedSettings.advancedSettingsLabel": "高度な設定", - "advancedSettings.badge.readOnly.text": "読み取り専用", - "advancedSettings.badge.readOnly.tooltip": "高度な設定を保存できません", - "advancedSettings.callOutCautionDescription": "これらの設定は非常に上級ユーザー向けなのでご注意ください。ここでの変更は Kibana の重要な部分に不具合を生じさせる可能性があります。これらの設定は非公開、サポート対象外、または実験的な場合があります。フィールドにデフォルト値がある場合、そのフィールドを未入力のままにするとデフォルトに戻り、他の構成で許容されないことがあります。カスタム設定を削除すると、Kibana の構成から永久に削除されます。", - "advancedSettings.callOutCautionTitle": "注意:不具合につながる可能性があります", - "advancedSettings.categoryNames.dashboardLabel": "ダッシュボード", - "advancedSettings.categoryNames.discoverLabel": "Discover", - "advancedSettings.categoryNames.generalLabel": "一般", - "advancedSettings.categoryNames.machineLearningLabel": "機械学習", - "advancedSettings.categoryNames.notificationsLabel": "通知", - "advancedSettings.categoryNames.observabilityLabel": "オブザーバビリティ", - "advancedSettings.categoryNames.reportingLabel": "レポート", - "advancedSettings.categoryNames.searchLabel": "検索", - "advancedSettings.categoryNames.securitySolutionLabel": "セキュリティソリューション", - "advancedSettings.categoryNames.timelionLabel": "Timelion", - "advancedSettings.categoryNames.visualizationsLabel": "ビジュアライゼーション", - "advancedSettings.categorySearchLabel": "カテゴリー", - "advancedSettings.featureCatalogueTitle": "日付形式の変更、ダークモードの有効化など、Kibanaエクスペリエンスをカスタマイズします。", - "advancedSettings.field.changeImageLinkAriaLabel": "{ariaName} を変更", - "advancedSettings.field.changeImageLinkText": "画像を変更", - "advancedSettings.field.codeEditorSyntaxErrorMessage": "無効な JSON 構文", - "advancedSettings.field.customSettingAriaLabel": "カスタム設定", - "advancedSettings.field.customSettingTooltip": "カスタム設定", - "advancedSettings.field.defaultValueText": "デフォルト:{value}", - "advancedSettings.field.defaultValueTypeJsonText": "デフォルト:{value}", - "advancedSettings.field.deprecationClickAreaLabel": "クリックすると {settingName} のサポート終了に関するドキュメントが表示されます。", - "advancedSettings.field.helpText": "この設定は Kibana サーバーにより上書きされ、変更することはできません。", - "advancedSettings.field.imageChangeErrorMessage": "画像を保存できませんでした", - "advancedSettings.field.invalidIconLabel": "無効", - "advancedSettings.field.offLabel": "オフ", - "advancedSettings.field.onLabel": "オン", - "advancedSettings.field.resetToDefaultLinkAriaLabel": "{ariaName} をデフォルトにリセット", - "advancedSettings.field.resetToDefaultLinkText": "デフォルトにリセット", - "advancedSettings.field.settingIsUnsaved": "設定は現在保存されていません。", - "advancedSettings.field.unsavedIconLabel": "未保存", - "advancedSettings.form.cancelButtonLabel": "変更をキャンセル", - "advancedSettings.form.clearNoSearchResultText": "(検索結果を消去)", - "advancedSettings.form.clearSearchResultText": "(検索結果を消去)", - "advancedSettings.form.noSearchResultText": "{queryText} {clearSearch}の設定が見つかりません", - "advancedSettings.form.requiresPageReloadToastButtonLabel": "ページを再読み込み", - "advancedSettings.form.requiresPageReloadToastDescription": "設定を有効にするためにページの再読み込みが必要です。", - "advancedSettings.form.saveButtonLabel": "変更を保存", - "advancedSettings.form.saveButtonTooltipWithInvalidChanges": "保存前に無効な設定を修正してください。", - "advancedSettings.form.saveErrorMessage": "を保存できませんでした", - "advancedSettings.form.searchResultText": "検索用語により {settingsCount} 件の設定が非表示になっています {clearSearch}", - "advancedSettings.pageTitle": "設定", - "advancedSettings.searchBar.unableToParseQueryErrorMessage": "クエリをパースできません", - "advancedSettings.searchBarAriaLabel": "高度な設定を検索", - "advancedSettings.voiceAnnouncement.ariaLabel": "詳細設定結果情報", - "alerts.documentationTitle": "ドキュメンテーションを表示", - "alerts.noPermissionsMessage": "アラートを表示するには、Kibanaスペースでアラート機能の権限が必要です。詳細については、Kibana管理者に連絡してください。", - "alerts.noPermissionsTitle": "Kibana機能権限が必要です", - "autocomplete.fieldRequiredError": "値を空にすることはできません", - "autocomplete.invalidDateError": "有効な日付ではありません", - "autocomplete.invalidNumberError": "有効な数値ではありません", - "autocomplete.loadingDescription": "読み込み中...", - "autocomplete.selectField": "最初にフィールドを選択してください...", - "bfetch.disableBfetchCompression": "バッチ圧縮を無効にする", - "bfetch.disableBfetchCompressionDesc": "バッチ圧縮を無効にします。個別の要求をデバッグできますが、応答サイズが大きくなります。", - "charts.advancedSettings.visualization.colorMappingText": "互換性パレットを使用して、グラフで値を特定の色にマッピング色にマッピングします。", - "charts.advancedSettings.visualization.colorMappingTextDeprecation": "この設定はサポートが終了し、Kibana 8.0 ではサポートされません。", - "charts.advancedSettings.visualization.colorMappingTitle": "カラーマッピング", - "charts.colormaps.bluesText": "青", - "charts.colormaps.greensText": "緑", - "charts.colormaps.greenToRedText": "緑から赤", - "charts.colormaps.greysText": "グレー", - "charts.colormaps.redsText": "赤", - "charts.colormaps.yellowToRedText": "黄色から赤", - "charts.colorPicker.clearColor": "色をリセット", - "charts.colorPicker.setColor.screenReaderDescription": "値 {legendDataLabel} の色を設定", - "charts.countText": "カウント", - "charts.functions.palette.args.colorHelpText": "パレットの色です。{html} カラー名、{hex}、{hsl}、{hsla}、{rgb}、または {rgba} を使用できます。", - "charts.functions.palette.args.gradientHelpText": "サポートされている場合グラデーションパレットを作成しますか?", - "charts.functions.palette.args.reverseHelpText": "パレットを反転させますか?", - "charts.functions.palette.args.stopHelpText": "パレットの色経由点。使用するときには、各色に関連付ける必要があります。", - "charts.functions.paletteHelpText": "カラーパレットを作成します。", - "charts.functions.systemPalette.args.nameHelpText": "パレットリストのパレットの名前", - "charts.functions.systemPaletteHelpText": "動的カラーパレットを作成します。", - "charts.legend.toggleLegendButtonAriaLabel": "凡例を切り替える", - "charts.legend.toggleLegendButtonTitle": "凡例を切り替える", - "charts.palettes.complimentaryLabel": "無料", - "charts.palettes.coolLabel": "Cool", - "charts.palettes.customLabel": "カスタム", - "charts.palettes.defaultPaletteLabel": "デフォルト", - "charts.palettes.grayLabel": "グレー", - "charts.palettes.kibanaPaletteLabel": "互換性", - "charts.palettes.negativeLabel": "負", - "charts.palettes.positiveLabel": "正", - "charts.palettes.statusLabel": "ステータス", - "charts.palettes.temperatureLabel": "温度", - "charts.palettes.warmLabel": "ウォーム", - "charts.partialData.bucketTooltipText": "選択された時間範囲にはこのバケット全体は含まれていません。一部データが含まれている可能性があります。", - "console.autocomplete.addMethodMetaText": "メソド", - "console.consoleDisplayName": "コンソール", - "console.consoleMenu.copyAsCurlFailedMessage": "要求をcURLとしてコピーできませんでした", - "console.consoleMenu.copyAsCurlMessage": "リクエストが URL としてコピーされました", - "console.devToolsDescription": "コンソールでデータを操作するには、cURLをスキップして、JSONインターフェイスを使用します。", - "console.devToolsTitle": "Elasticsearch APIとの連携", - "console.exampleOutputTextarea": "開発ツールコンソールエディターの例", - "console.helpPage.keyboardCommands.autoIndentDescription": "現在のリクエストを自動インデントします", - "console.helpPage.keyboardCommands.closeAutoCompleteMenuDescription": "自動入力メニューを閉じます", - "console.helpPage.keyboardCommands.collapseAllScopesDescription": "現在のスコープを除きすべてのスコープを最小表示します。シフトを追加して拡張します。", - "console.helpPage.keyboardCommands.collapseExpandCurrentScopeDescription": "現在のスコープを最小/拡張表示します。", - "console.helpPage.keyboardCommands.jumpToPreviousNextRequestDescription": "前/次のリクエストの開始または終了に移動します。", - "console.helpPage.keyboardCommands.openAutoCompleteDescription": "自動入力を開きます(未入力時を含む)", - "console.helpPage.keyboardCommands.openDocumentationDescription": "現在のリクエストのドキュメントを開きます", - "console.helpPage.keyboardCommands.selectCurrentlySelectedInAutoCompleteMenuDescription": "現在の選択項目または自動入力メニューで最も使用されている用語を選択します", - "console.helpPage.keyboardCommands.submitRequestDescription": "リクエストを送信します", - "console.helpPage.keyboardCommands.switchFocusToAutoCompleteMenuDescription": "自動入力メニューに焦点を切り替えます。矢印を使用してさらに用語を選択します", - "console.helpPage.keyboardCommandsTitle": "キーボードコマンド", - "console.helpPage.pageTitle": "ヘルプ", - "console.helpPage.requestFormatDescription": "ホワイトエディターに 1 つ以上のリクエストを入力できます。コンソールはコンパクトなフォーマットのリクエストを理解できます。", - "console.helpPage.requestFormatTitle": "リクエストフォーマット", - "console.historyPage.applyHistoryButtonLabel": "適用", - "console.historyPage.clearHistoryButtonLabel": "クリア", - "console.historyPage.closehistoryButtonLabel": "閉じる", - "console.historyPage.itemOfRequestListAriaLabel": "リクエスト:{historyItem}", - "console.historyPage.noHistoryTextMessage": "履歴がありません", - "console.historyPage.pageTitle": "履歴", - "console.historyPage.requestListAriaLabel": "リクエストの送信履歴", - "console.inputTextarea": "開発ツールコンソール", - "console.loadingError.buttonLabel": "コンソールの再読み込み", - "console.loadingError.message": "最新データを取得するために再読み込みを試してください。", - "console.loadingError.title": "コンソールを読み込めません", - "console.notification.error.couldNotSaveRequestTitle": "リクエストをコンソール履歴に保存できませんでした。", - "console.notification.error.historyQuotaReachedMessage": "リクエスト履歴が満杯です。コンソール履歴を消去して、新しいリクエストを保存します。", - "console.notification.error.noRequestSelectedTitle": "リクエストを選択していません。リクエストの中にカーソルを置いて選択します。", - "console.notification.error.unknownErrorTitle": "不明なリクエストエラー", - "console.outputTextarea": "開発ツールコンソール出力", - "console.pageHeading": "コンソール", - "console.requestInProgressBadgeText": "リクエストが進行中", - "console.requestOptions.autoIndentButtonLabel": "自動インデント", - "console.requestOptions.copyAsUrlButtonLabel": "cURL としてコピー", - "console.requestOptions.openDocumentationButtonLabel": "ドキュメントを開く", - "console.requestOptionsButtonAriaLabel": "リクエストオプション", - "console.requestTimeElapasedBadgeTooltipContent": "経過時間", - "console.sendRequestButtonTooltip": "クリックしてリクエストを送信", - "console.settingsPage.autocompleteLabel": "自動入力", - "console.settingsPage.cancelButtonLabel": "キャンセル", - "console.settingsPage.fieldsLabelText": "フィールド", - "console.settingsPage.fontSizeLabel": "フォントサイズ", - "console.settingsPage.indicesAndAliasesLabelText": "インデックスとエイリアス", - "console.settingsPage.jsonSyntaxLabel": "JSON構文", - "console.settingsPage.pageTitle": "コンソール設定", - "console.settingsPage.pollingLabelText": "自動入力候補を自動的に更新", - "console.settingsPage.refreshButtonLabel": "自動入力候補の更新", - "console.settingsPage.refreshingDataDescription": "コンソールは、Elasticsearchをクエリして自動入力候補を更新します。クラスターが大きい場合や、ネットワークの制限がある場合には、自動更新で問題が発生する可能性があります。", - "console.settingsPage.refreshingDataLabel": "自動入力候補を更新しています", - "console.settingsPage.saveButtonLabel": "保存", - "console.settingsPage.templatesLabelText": "テンプレート", - "console.settingsPage.tripleQuotesMessage": "出力ウィンドウでは三重引用符を使用してください", - "console.settingsPage.wrapLongLinesLabelText": "長い行を改行", - "console.topNav.helpTabDescription": "ヘルプ", - "console.topNav.helpTabLabel": "ヘルプ", - "console.topNav.historyTabDescription": "履歴", - "console.topNav.historyTabLabel": "履歴", - "console.topNav.settingsTabDescription": "設定", - "console.topNav.settingsTabLabel": "設定", - "console.welcomePage.closeButtonLabel": "閉じる", - "console.welcomePage.pageTitle": "コンソールへようこそ", - "console.welcomePage.quickIntroDescription": "コンソール UI は、エディターペイン(左)と応答ペイン(右)の 2 つのペインに分かれています。エディターでリクエストを入力し、Elasticsearch に送信します。結果が右側の応答ペインに表示されます。", - "console.welcomePage.quickIntroTitle": "UI の簡単な説明", - "console.welcomePage.quickTips.cUrlFormatForRequestsDescription": "cURL フォーマットのリクエストを貼り付けると、Console 構文に変換されます。", - "console.welcomePage.quickTips.keyboardShortcutsDescription": "ヘルプボタンでキーボードショートカットが学べます。便利な情報が揃っています!", - "console.welcomePage.quickTips.resizeEditorDescription": "間の区切りをドラッグすることで、エディターとアウトプットペインのサイズを変更できます。", - "console.welcomePage.quickTips.submitRequestDescription": "緑の三角形のボタンをクリックして ES にリクエストを送信します。", - "console.welcomePage.quickTips.useWrenchMenuDescription": "レンチメニューで他の便利な機能が使えます。", - "console.welcomePage.quickTipsTitle": "今のうちにいくつか簡単なコツをお教えします", - "console.welcomePage.supportedRequestFormatDescription": "リクエストの入力中、コンソールが候補を提案するので、Enter/Tabを押して確定できます。これらの候補はリクエストの構造、およびインデックス、タイプに基づくものです。", - "console.welcomePage.supportedRequestFormatTitle": "コンソールは cURL と同様に、コンパクトなフォーマットのリクエストを理解できます。", - "core.application.appContainer.loadingAriaLabel": "アプリケーションを読み込んでいます", - "core.application.appNotFound.pageDescription": "この URL にアプリケーションが見つかりませんでした。前の画面に戻るか、メニューからアプリを選択してみてください。", - "core.application.appNotFound.title": "アプリケーションが見つかりません", - "core.application.appRenderError.defaultTitle": "アプリケーションエラー", - "core.chrome.browserDeprecationLink": "Web サイトのサポートマトリックス", - "core.chrome.browserDeprecationWarning": "このソフトウェアの将来のバージョンでは、Internet Explorerのサポートが削除されます。{link}をご確認ください。", - "core.chrome.legacyBrowserWarning": "ご使用のブラウザが Kibana のセキュリティ要件を満たしていません。", - "core.euiAccordion.isLoading": "読み込み中", - "core.euiBasicTable.selectAllRows": "すべての行を選択", - "core.euiBasicTable.selectThisRow": "この行を選択", - "core.euiBasicTable.tableAutoCaptionWithoutPagination": "この表には{itemCount}行あります。", - "core.euiBasicTable.tableAutoCaptionWithPagination": "この表には{totalItemCount}行中{itemCount}行あります; {page}/{pageCount}ページ。", - "core.euiBasicTable.tableCaptionWithPagination": "{tableCaption}; {page}/{pageCount}ページ。", - "core.euiBasicTable.tablePagination": "前の表のページネーション: {tableCaption}", - "core.euiBasicTable.tableSimpleAutoCaptionWithPagination": "この表には{itemCount}行あります; {page}/{pageCount}ページ。", - "core.euiBottomBar.customScreenReaderAnnouncement": "ドキュメントの最後には、新しいリージョンランドマーク{landmarkHeading}とページレベルのコントロールがあります。", - "core.euiBottomBar.screenReaderAnnouncement": "ドキュメントの最後には、新しいリージョンランドマークとページレベルのコントロールがあります。", - "core.euiBottomBar.screenReaderHeading": "ページレベルのコントロール", - "core.euiBreadcrumbs.collapsedBadge.ariaLabel": "折りたたまれたブレッドクラムを表示", - "core.euiBreadcrumbs.nav.ariaLabel": "ブレッドクラム", - "core.euiCardSelect.select": "選択してください", - "core.euiCardSelect.selected": "利用不可", - "core.euiCardSelect.unavailable": "選択済み", - "core.euiCodeBlock.copyButton": "コピー", - "core.euiCodeBlock.fullscreenCollapse": "縮小", - "core.euiCodeBlock.fullscreenExpand": "拡張", - "core.euiCollapsedItemActions.allActions": "すべてのアクション", - "core.euiColorPicker.alphaLabel": "アルファチャネル(不透明)値", - "core.euiColorPicker.closeLabel": "下矢印キーを押すと、色オプションを含むポップオーバーが開きます", - "core.euiColorPicker.colorErrorMessage": "無効な色値", - "core.euiColorPicker.colorLabel": "色値", - "core.euiColorPicker.openLabel": "Escapeキーを押すと、ポップオーバーを閉じます", - "core.euiColorPicker.popoverLabel": "色選択ダイアログ", - "core.euiColorPicker.transparent": "透明", - "core.euiColorPickerSwatch.ariaLabel": "色として{color}を選択します", - "core.euiColorStops.screenReaderAnnouncement": "{label}:{readOnly} {disabled}色終了位置ピッカー。各終了には数値と対応するカラー値があります。上下矢印キーを使用して、個別の終了を選択します。Enterキーを押すと、新しい終了を作成します。", - "core.euiColorStopThumb.buttonAriaLabel": "Enterキーを押すと、この点を変更します。Escapeキーを押すと、グループにフォーカスします", - "core.euiColorStopThumb.buttonTitle": "クリックすると編集できます。ドラッグすると再配置できます", - "core.euiColorStopThumb.removeLabel": "この終了を削除", - "core.euiColorStopThumb.screenReaderAnnouncement": "カラー終了編集フォームのポップアップが開きました。Tabを押してフォームコントロールを閲覧するか、Escでこのポップアップを閉じます。", - "core.euiColorStopThumb.stopErrorMessage": "値が範囲外です", - "core.euiColorStopThumb.stopLabel": "点値", - "core.euiColumnActions.hideColumn": "列を非表示", - "core.euiColumnActions.moveLeft": "左に移動", - "core.euiColumnActions.moveRight": "右に移動", - "core.euiColumnActions.sort": "{schemaLabel}を並べ替える", - "core.euiColumnSelector.button": "列", - "core.euiColumnSelector.buttonActivePlural": "{numberOfHiddenFields}個の列が非表示です", - "core.euiColumnSelector.buttonActiveSingular": "{numberOfHiddenFields}個の列が非表示です", - "core.euiColumnSelector.hideAll": "すべて非表示", - "core.euiColumnSelector.search": "検索", - "core.euiColumnSelector.searchcolumns": "列を検索", - "core.euiColumnSelector.selectAll": "すべて表示", - "core.euiColumnSorting.button": "フィールドの並べ替え", - "core.euiColumnSorting.clearAll": "並び替えを消去", - "core.euiColumnSorting.emptySorting": "現在並び替えられているフィールドはありません", - "core.euiColumnSorting.pickFields": "並び替え基準でフィールドの選択", - "core.euiColumnSorting.sortFieldAriaLabel": "並べ替え基準:", - "core.euiColumnSortingDraggable.defaultSortAsc": "A-Z", - "core.euiColumnSortingDraggable.defaultSortDesc": "Z-A", - "core.euiComboBoxOptionsList.allOptionsSelected": "利用可能なオプションをすべて選択しました", - "core.euiComboBoxOptionsList.alreadyAdded": "{label} はすでに追加されています", - "core.euiComboBoxOptionsList.createCustomOption": "{searchValue}をカスタムオプションとして追加", - "core.euiComboBoxOptionsList.delimiterMessage": "各項目を{delimiter}で区切って追加", - "core.euiComboBoxOptionsList.loadingOptions": "オプションを読み込み中", - "core.euiComboBoxOptionsList.noAvailableOptions": "利用可能なオプションがありません", - "core.euiComboBoxOptionsList.noMatchingOptions": "{searchValue} はどのオプションにも一致していません", - "core.euiComboBoxPill.removeSelection": "グループの選択項目から {children} を削除してください", - "core.euiCommonlyUsedTimeRanges.legend": "頻繁に使用", - "core.euiControlBar.customScreenReaderAnnouncement": "ドキュメントの最後には、新しいリージョンランドマーク{landmarkHeading}とページレベルのコントロールがあります。", - "core.euiControlBar.screenReaderAnnouncement": "ドキュメントの最後には、新しいリージョンランドマークとページレベルのコントロールがあります。", - "core.euiControlBar.screenReaderHeading": "ページレベルのコントロール", - "core.euiDataGrid.ariaLabel": "{label}; {page}/{pageCount}ページ。", - "core.euiDataGrid.ariaLabelledBy": "{page}/{pageCount}ページ。", - "core.euiDataGrid.screenReaderNotice": "セルにはインタラクティブコンテンツが含まれます。", - "core.euiDataGridCellButtons.expandButtonTitle": "クリックするか enter を押すと、セルのコンテンツとインタラクトできます。", - "core.euiDataGridHeaderCell.headerActions": "ヘッダーアクション", - "core.euiDataGridSchema.booleanSortTextAsc": "False-True", - "core.euiDataGridSchema.booleanSortTextDesc": "True-False", - "core.euiDataGridSchema.currencySortTextAsc": "低-高", - "core.euiDataGridSchema.currencySortTextDesc": "高-低", - "core.euiDataGridSchema.dateSortTextAsc": "旧-新", - "core.euiDataGridSchema.dateSortTextDesc": "新-旧", - "core.euiDataGridSchema.jsonSortTextAsc": "小-大", - "core.euiDataGridSchema.jsonSortTextDesc": "大-小", - "core.euiDataGridSchema.numberSortTextAsc": "低-高", - "core.euiDataGridSchema.numberSortTextDesc": "高-低", - "core.euiDatePopoverButton.outdatedTitle": "更新が必要:{title}", - "core.euiFieldPassword.maskPassword": "パスワードをマスク", - "core.euiFieldPassword.showPassword": "プレーンテキストとしてパスワードを表示します。注記:パスワードは画面上に見えるように表示されます。", - "core.euiFilePicker.clearSelectedFiles": "選択したファイルを消去", - "core.euiFilePicker.removeSelected": "削除", - "core.euiFlyout.closeAriaLabel": "このダイアログを閉じる", - "core.euiForm.addressFormErrors": "ハイライトされたエラーを修正してください。", - "core.euiFormControlLayoutClearButton.label": "インプットを消去", - "core.euiHeaderLinks.appNavigation": "アプリメニュー", - "core.euiHeaderLinks.openNavigationMenu": "メニューを開く", - "core.euiHue.label": "HSV カラーモードの「色相」値を選択", - "core.euiImage.closeImage": "全画面 {alt} 画像を閉じる", - "core.euiImage.openImage": "全画面 {alt} 画像を開く", - "core.euiLink.external.ariaLabel": "外部リンク", - "core.euiLink.newTarget.screenReaderOnlyText": "(新しいタブまたはウィンドウで開く)", - "core.euiMarkdownEditorFooter.closeButton": "閉じる", - "core.euiMarkdownEditorFooter.errorsTitle": "エラー", - "core.euiMarkdownEditorFooter.openUploadModal": "ファイルのアップロードモーダルを開く", - "core.euiMarkdownEditorFooter.showMarkdownHelp": "マークダウンヘルプを表示", - "core.euiMarkdownEditorFooter.showSyntaxErrors": "エラーを表示", - "core.euiMarkdownEditorFooter.supportedFileTypes": "サポートされているファイル:{supportedFileTypes}", - "core.euiMarkdownEditorFooter.syntaxTitle": "構文ヘルプ", - "core.euiMarkdownEditorFooter.unsupportedFileType": "ファイルタイプがサポートされていません", - "core.euiMarkdownEditorFooter.uploadingFiles": "クリックすると、ファイルをアップロードします", - "core.euiMarkdownEditorToolbar.editor": "エディター", - "core.euiMarkdownEditorToolbar.previewMarkdown": "プレビュー", - "core.euiModal.closeModal": "このモーダルウィンドウを閉じます", - "core.euiNotificationEventMessages.accordionAriaLabelButtonText": "+ {eventName}の{messagesLength}メスえーいj", - "core.euiNotificationEventMessages.accordionButtonText": "+ {messagesLength}以上", - "core.euiNotificationEventMessages.accordionHideText": "非表示", - "core.euiNotificationEventMeta.contextMenuButton": "{eventName}のメニュー", - "core.euiNotificationEventReadButton.markAsRead": "既読に設定", - "core.euiNotificationEventReadButton.markAsReadAria": "{eventName}を既読に設定", - "core.euiNotificationEventReadButton.markAsUnread": "未読に設定", - "core.euiNotificationEventReadButton.markAsUnreadAria": "{eventName}を未読に設定", - "core.euiNotificationEventReadIcon.read": "読み取り", - "core.euiNotificationEventReadIcon.readAria": "{eventName}は既読です", - "core.euiNotificationEventReadIcon.unread": "未読", - "core.euiNotificationEventReadIcon.unreadAria": "{eventName}は未読です", - "core.euiPagination.disabledNextPage": "次のページ", - "core.euiPagination.disabledPreviousPage": "前のページ", - "core.euiPagination.firstRangeAriaLabel": "ページ2を{lastPage}にスキップしています", - "core.euiPagination.lastRangeAriaLabel": "ページ{firstPage}を{lastPage}にスキップしています", - "core.euiPagination.nextPage": "次のページ、{page}", - "core.euiPagination.pageOfTotalCompressed": "{total}ページ中{page}ページ", - "core.euiPagination.previousPage": "前のページ、{page}", - "core.euiPaginationButton.longPageString": "{page}/{totalPages}ページ", - "core.euiPaginationButton.shortPageString": "{page}ページ", - "core.euiPinnableListGroup.pinExtraActionLabel": "項目をピン留め", - "core.euiPinnableListGroup.pinnedExtraActionLabel": "項目のピン留めを外す", - "core.euiPopover.screenReaderAnnouncement": "これはダイアログです。ダイアログを閉じるには、 escape を押してください。", - "core.euiProgress.valueText": "{value}%", - "core.euiQuickSelect.applyButton": "適用", - "core.euiQuickSelect.fullDescription": "現在 {timeTense} {timeValue} {timeUnit}に設定されています。", - "core.euiQuickSelect.legendText": "時間範囲をすばやく選択", - "core.euiQuickSelect.nextLabel": "次の時間ウィンドウ", - "core.euiQuickSelect.previousLabel": "前の時間ウィンドウ", - "core.euiQuickSelect.quickSelectTitle": "すばやく選択", - "core.euiQuickSelect.tenseLabel": "時間テンス", - "core.euiQuickSelect.unitLabel": "時間単位", - "core.euiQuickSelect.valueLabel": "時間値", - "core.euiRecentlyUsed.legend": "最近使用した日付範囲", - "core.euiRefreshInterval.fullDescription": "現在{optionValue} {optionText}に設定されている間隔を更新します。", - "core.euiRefreshInterval.legend": "以下の感覚ごとに更新", - "core.euiRefreshInterval.start": "開始", - "core.euiRefreshInterval.stop": "停止", - "core.euiRelativeTab.fullDescription": "単位は変更可能です。現在 {unit} に設定されています。", - "core.euiRelativeTab.numberInputError": "0以上でなければなりません", - "core.euiRelativeTab.numberInputLabel": "時間スパンの量", - "core.euiRelativeTab.relativeDate": "{position} 日付", - "core.euiRelativeTab.roundingLabel": "{unit} に四捨五入する", - "core.euiRelativeTab.unitInputLabel": "相対的時間スパン", - "core.euiResizableButton.horizontalResizerAriaLabel": "左右矢印キーを押してパネルサイズを調整します", - "core.euiResizableButton.verticalResizerAriaLabel": "上下矢印キーを押してパネルサイズを調整します", - "core.euiResizablePanel.toggleButtonAriaLabel": "押すと、このパネルを切り替えます", - "core.euiSaturation.ariaLabel": "HSVカラーモード彩度と値2軸スライダー", - "core.euiSaturation.screenReaderInstructions": "矢印キーで四角のカラーグラデーションを操作します。座標は、0~1の範囲のHSVカラーモード「彩度」および「値」数値を計算するために使用されます。左右キーで彩度を変更します。上下キーで値を変更します。", - "core.euiSelectable.loadingOptions": "オプションを読み込み中", - "core.euiSelectable.noAvailableOptions": "オプションがありません", - "core.euiSelectable.noMatchingOptions": "{searchValue} はどのオプションにも一致していません", - "core.euiSelectable.placeholderName": "フィルターオプション", - "core.euiSelectableListItem.excludedOption": "除外されたオプション。", - "core.euiSelectableListItem.excludedOptionInstructions": "このオプションの選択を解除するには、Enterを押します。", - "core.euiSelectableListItem.includedOption": "追加されたオプション。", - "core.euiSelectableListItem.includedOptionInstructions": "このオプションを除外するには、Enterを押します", - "core.euiSelectableTemplateSitewide.loadingResults": "結果を読み込み中", - "core.euiSelectableTemplateSitewide.noResults": "結果がありません", - "core.euiSelectableTemplateSitewide.onFocusBadgeGoTo": "移動:", - "core.euiSelectableTemplateSitewide.searchPlaceholder": "検索しています...", - "core.euiStat.loadingText": "統計を読み込み中です", - "core.euiStepStrings.complete": "ステップ{number}: {title}は完了しました", - "core.euiStepStrings.current": "現在のステップ{number}:{title}", - "core.euiStepStrings.disabled": "ステップ{number}: {title}は無効です", - "core.euiStepStrings.errors": "ステップ{number}: {title}にはエラーがあります", - "core.euiStepStrings.incomplete": "ステップ{number}: {title}は完了していません", - "core.euiStepStrings.loading": "ステップ{number}: {title}を読み込んでいます", - "core.euiStepStrings.simpleComplete": "ステップ{number}は完了しました", - "core.euiStepStrings.simpleCurrent": "現在のステップは{number}です", - "core.euiStepStrings.simpleDisabled": "ステップ{number}は無効です", - "core.euiStepStrings.simpleErrors": "ステップ{number}にはエラーがあります", - "core.euiStepStrings.simpleIncomplete": "ステップ{number}は完了していません", - "core.euiStepStrings.simpleLoading": "ステップ{number}を読み込んでいます", - "core.euiStepStrings.simpleStep": "ステップ{number}", - "core.euiStepStrings.simpleWarning": "ステップ{number}には警告があります", - "core.euiStepStrings.step": "ステップ{number}: {title}", - "core.euiStepStrings.warning": "ステップ{number}: {title}には警告があります", - "core.euiStyleSelector.buttonLegend": "データグリッドの表示密度を選択", - "core.euiStyleSelector.buttonText": "密度", - "core.euiStyleSelector.labelCompact": "コンパクト密度", - "core.euiStyleSelector.labelExpanded": "拡張密度", - "core.euiStyleSelector.labelNormal": "標準密度", - "core.euiSuperDatePicker.showDatesButtonLabel": "日付を表示", - "core.euiSuperSelect.screenReaderAnnouncement": "{optionsCount} 件のアイテムのフォームセレクターを使用しています。1 つのオプションを選択する必要があります。上下の矢印キーで移動するか、Escキーで閉じます。", - "core.euiSuperSelectControl.selectAnOption": "オプションの選択:{selectedValue} を選択済み", - "core.euiSuperUpdateButton.cannotUpdateTooltip": "アップデートできません", - "core.euiSuperUpdateButton.clickToApplyTooltip": "クリックして適用", - "core.euiSuperUpdateButton.refreshButtonLabel": "更新", - "core.euiSuperUpdateButton.updateButtonLabel": "更新", - "core.euiSuperUpdateButton.updatingButtonLabel": "更新中", - "core.euiTableHeaderCell.titleTextWithDesc": "{innerText}; {description}", - "core.euiTablePagination.rowsPerPage": "ページごとの行数", - "core.euiTablePagination.rowsPerPageOption": "{rowsPerPage}行", - "core.euiTableSortMobile.sorting": "並べ替え", - "core.euiToast.dismissToast": "トーストを閉じる", - "core.euiToast.newNotification": "新しい通知が表示されます", - "core.euiToast.notification": "通知", - "core.euiTourStep.closeTour": "ツアーを閉じる", - "core.euiTourStep.endTour": "ツアーを終了", - "core.euiTourStep.skipTour": "ツアーをスキップ", - "core.euiTourStepIndicator.ariaLabel": "ステップ{number} {status}", - "core.euiTourStepIndicator.isActive": "アクティブ", - "core.euiTourStepIndicator.isComplete": "完了", - "core.euiTourStepIndicator.isIncomplete": "未完了", - "core.euiTreeView.ariaLabel": "{nodeLabel} {ariaLabel} のチャイルド", - "core.euiTreeView.listNavigationInstructions": "矢印キーを使ってこのリストをすばやくナビゲートすることができます。", - "core.fatalErrors.clearYourSessionButtonLabel": "セッションを消去", - "core.fatalErrors.goBackButtonLabel": "戻る", - "core.fatalErrors.somethingWentWrongTitle": "問題が発生しました", - "core.fatalErrors.tryRefreshingPageDescription": "ページを更新してみてください。うまくいかない場合は、前のページに戻るか、セッションデータを消去してください。", - "core.notifications.errorToast.closeModal": "閉じる", - "core.notifications.globalToast.ariaLabel": "通知メッセージリスト", - "core.notifications.unableUpdateUISettingNotificationMessageTitle": "UI 設定を更新できません", - "core.status.greenTitle": "緑", - "core.status.redTitle": "赤", - "core.status.yellowTitle": "黄", - "core.statusPage.loadStatus.serverIsDownErrorMessage": "サーバーステータスのリクエストに失敗しました。サーバーがダウンしている可能性があります。", - "core.statusPage.loadStatus.serverStatusCodeErrorMessage": "サーバーステータスのリクエストに失敗しました。ステータスコード:{responseStatus}", - "core.statusPage.metricsTiles.columns.heapTotalHeader": "ヒープ合計", - "core.statusPage.metricsTiles.columns.heapUsedHeader": "使用ヒープ", - "core.statusPage.metricsTiles.columns.loadHeader": "読み込み", - "core.statusPage.metricsTiles.columns.requestsPerSecHeader": "1秒あたりのリクエスト", - "core.statusPage.metricsTiles.columns.resTimeAvgHeader": "平均応答時間", - "core.statusPage.metricsTiles.columns.resTimeMaxHeader": "最長応答時間", - "core.statusPage.serverStatus.statusTitle": "Kibanaのステータス:{kibanaStatus}", - "core.statusPage.statusApp.loadingErrorText": "ステータスの読み込み中にエラーが発生しました", - "core.statusPage.statusApp.statusActions.buildText": "ビルド{buildNum}", - "core.statusPage.statusApp.statusActions.commitText": "COMMIT {buildSha}", - "core.statusPage.statusApp.statusTitle": "プラグインステータス", - "core.statusPage.statusTable.columns.idHeader": "ID", - "core.statusPage.statusTable.columns.statusHeader": "ステータス", - "core.toasts.errorToast.seeFullError": "完全なエラーを表示", - "core.ui_settings.params.darkModeText": "Kibana UIのダークモードを有効にします。この設定を適用するにはページの更新が必要です。", - "core.ui_settings.params.darkModeTitle": "ダークモード", - "core.ui_settings.params.dateFormat.dayOfWeekText": "週の初めの曜日を設定します", - "core.ui_settings.params.dateFormat.dayOfWeekTitle": "曜日", - "core.ui_settings.params.dateFormat.optionsLinkText": "フォーマット", - "core.ui_settings.params.dateFormat.scaled.intervalsLinkText": "ISO8601間隔", - "core.ui_settings.params.dateFormat.scaledText": "時間ベースのデータが順番にレンダリングされ、フォーマットされたタイムスタンプが測定値の間隔に適応すべき状況で使用されるフォーマットを定義する値です。キーは{intervalsLink}です。", - "core.ui_settings.params.dateFormat.scaledTitle": "スケーリングされたデータフォーマットです", - "core.ui_settings.params.dateFormat.timezone.invalidValidationMessage": "無効なタイムゾーン:{timezone}", - "core.ui_settings.params.dateFormat.timezoneText": "使用されるタイムゾーンです。{defaultOption}ではご使用のブラウザーにより検知されたタイムゾーンが使用されます。", - "core.ui_settings.params.dateFormat.timezoneTitle": "データフォーマットのタイムゾーン", - "core.ui_settings.params.dateFormatText": "きちんとフォーマットされたデータを表示する際、この{formatLink}を使用します", - "core.ui_settings.params.dateFormatTitle": "データフォーマット", - "core.ui_settings.params.dateNanosFormatText": "Elasticsearchの{dateNanosLink}データタイプに使用されます", - "core.ui_settings.params.dateNanosFormatTitle": "ナノ秒フォーマットでの日付", - "core.ui_settings.params.dateNanosLinkTitle": "date_nanos", - "core.ui_settings.params.dayOfWeekText.invalidValidationMessage": "無効な曜日:{dayOfWeek}", - "core.ui_settings.params.defaultRoute.defaultRouteIsRelativeValidationMessage": "相対URLでなければなりません。", - "core.ui_settings.params.defaultRoute.defaultRouteText": "この設定は、Kibana起動時のデフォルトのルートを設定します。この設定で、Kibana起動時のランディングページを変更できます。ルートは相対URLでなければなりません。", - "core.ui_settings.params.defaultRoute.defaultRouteTitle": "デフォルトのルート", - "core.ui_settings.params.disableAnimationsText": "Kibana UIの不要なアニメーションをオフにします。変更を適用するにはページを更新してください。", - "core.ui_settings.params.disableAnimationsTitle": "アニメーションを無効にする", - "core.ui_settings.params.notifications.banner.markdownLinkText": "マークダウン対応", - "core.ui_settings.params.notifications.bannerLifetimeText": "バナー通知が画面に表示される時間(ミリ秒単位)です。", - "core.ui_settings.params.notifications.bannerLifetimeTitle": "バナー通知時間", - "core.ui_settings.params.notifications.bannerText": "すべてのユーザーへの一時的な通知を目的としたカスタムバナーです。{markdownLink}", - "core.ui_settings.params.notifications.bannerTitle": "カスタムバナー通知", - "core.ui_settings.params.notifications.errorLifetimeText": "エラー通知が画面に表示される時間(ミリ秒単位)です。", - "core.ui_settings.params.notifications.errorLifetimeTitle": "エラー通知時間", - "core.ui_settings.params.notifications.infoLifetimeText": "情報通知が画面に表示される時間(ミリ秒単位)です。", - "core.ui_settings.params.notifications.infoLifetimeTitle": "情報通知時間", - "core.ui_settings.params.notifications.warningLifetimeText": "警告通知が画面に表示される時間(ミリ秒単位)です。", - "core.ui_settings.params.notifications.warningLifetimeTitle": "警告通知時間", - "core.ui_settings.params.storeUrlText": "URLが長くなりすぎるためブラウザーが対応できない場合があります。セッションストレージにURLの一部を保存することでこの問題に対処できるかどうかをテストしています。結果を教えてください!", - "core.ui_settings.params.storeUrlTitle": "セッションストレージにURLを格納", - "core.ui_settings.params.themeVersionTitle": "テーマバージョン", - "core.ui.chrome.headerGlobalNav.goHomePageIconAriaLabel": "Elastic ホーム", - "core.ui.chrome.headerGlobalNav.helpMenuAskElasticTitle": "Elastic に確認する", - "core.ui.chrome.headerGlobalNav.helpMenuButtonAriaLabel": "ヘルプメニュー", - "core.ui.chrome.headerGlobalNav.helpMenuDocumentation": "ドキュメント", - "core.ui.chrome.headerGlobalNav.helpMenuGiveFeedbackOnApp": "{appName} についてのフィードバックを作成する", - "core.ui.chrome.headerGlobalNav.helpMenuGiveFeedbackTitle": "フィードバックを作成する", - "core.ui.chrome.headerGlobalNav.helpMenuKibanaDocumentationTitle": "Kibanaドキュメント", - "core.ui.chrome.headerGlobalNav.helpMenuOpenGitHubIssueTitle": "GitHubで問題を開く", - "core.ui.chrome.headerGlobalNav.helpMenuTitle": "ヘルプ", - "core.ui.chrome.headerGlobalNav.helpMenuVersion": "v {version}", - "core.ui.chrome.headerGlobalNav.logoAriaLabel": "Elastic ロゴ", - "core.ui.enterpriseSearchNavList.label": "エンタープライズサーチ", - "core.ui.errorUrlOverflow.bigUrlWarningNotificationMessage": "{advancedSettingsLink}で{storeInSessionStorageParam}オプションを有効にするか、オンスクリーンビジュアルを簡素化してください。", - "core.ui.errorUrlOverflow.bigUrlWarningNotificationMessage.advancedSettingsLinkText": "高度な設定", - "core.ui.errorUrlOverflow.bigUrlWarningNotificationTitle": "URLが大きく、Kibanaの動作が停止する可能性があります", - "core.ui.errorUrlOverflow.errorTitle": "このオブジェクトのURLは長すぎます。表示できません", - "core.ui.errorUrlOverflow.optionsToFixError.doNotUseIEText": "最新のブラウザーにアップグレードしてください。他の対応ブラウザーでは、いずれもこの制限がありません。", - "core.ui.errorUrlOverflow.optionsToFixError.enableOptionText": "{kibanaSettingsLink}で{storeInSessionStorageConfig}オプションを有効にしてください。", - "core.ui.errorUrlOverflow.optionsToFixError.enableOptionText.advancedSettingsLinkText": "高度な設定", - "core.ui.errorUrlOverflow.optionsToFixError.removeStuffFromDashboardText": "コンテンツまたはフィルターを削除すると、編集しているオブジェクトがシンプルになります。", - "core.ui.errorUrlOverflow.optionsToFixErrorDescription": "次を試してください。", - "core.ui.kibanaNavList.label": "分析", - "core.ui.legacyBrowserMessage": "この Elastic インストレーションは、現在ご使用のブラウザが満たしていない厳格なセキュリティ要件が有効になっています。", - "core.ui.legacyBrowserTitle": "ブラウザをアップグレードしてください", - "core.ui.loadingIndicatorAriaLabel": "コンテンツを読み込んでいます", - "core.ui.managementNavList.label": "管理", - "core.ui.observabilityNavList.label": "オブザーバビリティ", - "core.ui.overlays.banner.attentionTitle": "注意", - "core.ui.overlays.banner.closeButtonLabel": "閉じる", - "core.ui.primaryNav.pinnedLinksAriaLabel": "ピン留めされたリンク", - "core.ui.primaryNav.screenReaderLabel": "プライマリ", - "core.ui.primaryNav.toggleNavAriaLabel": "プライマリナビゲーションを切り替える", - "core.ui.primaryNavSection.screenReaderLabel": "プライマリナビゲーションリンク、{category}", - "core.ui.publicBaseUrlWarning.configMissingDescription": "{configKey}が見つかりません。本番環境を実行するときに構成してください。一部の機能が正常に動作しない場合があります。", - "core.ui.publicBaseUrlWarning.configMissingTitle": "構成がありません", - "core.ui.publicBaseUrlWarning.muteWarningButtonLabel": "ミュート警告", - "core.ui.publicBaseUrlWarning.seeDocumentationLinkLabel": "ドキュメントを参照してください。", - "core.ui.recentLinks.linkItem.screenReaderLabel": "{recentlyAccessedItemLinklabel}、タイプ:{pageType}", - "core.ui.recentlyViewed": "最近閲覧", - "core.ui.recentlyViewedAriaLabel": "最近閲覧したリンク", - "core.ui.securityNavList.label": "セキュリティ", - "core.ui.welcomeErrorMessage": "Elasticが正常に読み込まれませんでした。詳細はサーバーアウトプットを確認してください。", - "core.ui.welcomeMessage": "Elastic の読み込み中", - "dashboard.actions.DownloadCreateDrilldownAction.displayName": "CSV をダウンロード", - "dashboard.actions.downloadOptionsUnsavedFilename": "無題", - "dashboard.actions.toggleExpandPanelMenuItem.expandedDisplayName": "最小化", - "dashboard.actions.toggleExpandPanelMenuItem.notExpandedDisplayName": "パネルを最大化", - "dashboard.addPanel.noMatchingObjectsMessage": "一致するオブジェクトが見つかりませんでした。", - "dashboard.addPanel.savedObjectAddedToContainerSuccessMessageTitle": "{savedObjectName} が追加されました", - "dashboard.appLeaveConfirmModal.cancelButtonLabel": "キャンセル", - "dashboard.appLeaveConfirmModal.unsavedChangesSubtitle": "作業を保存せずにダッシュボードから移動しますか?", - "dashboard.appLeaveConfirmModal.unsavedChangesTitle": "保存されていない変更", - "dashboard.badge.readOnly.text": "読み取り専用", - "dashboard.badge.readOnly.tooltip": "ダッシュボードを保存できません", - "dashboard.changeViewModeConfirmModal.cancelButtonLabel": "編集を続行", - "dashboard.changeViewModeConfirmModal.confirmButtonLabel": "変更を破棄", - "dashboard.changeViewModeConfirmModal.description": "表示モードに戻ったときに変更内容を保持または破棄できます。 破棄された変更を回復することはできません。", - "dashboard.changeViewModeConfirmModal.keepUnsavedChangesButtonLabel": "変更を保持", - "dashboard.changeViewModeConfirmModal.leaveEditModeTitle": "保存されていない変更があります", - "dashboard.cloneModal.cloneDashboardTitleAriaLabel": "クローンダッシュボードタイトル", - "dashboard.createConfirmModal.cancelButtonLabel": "キャンセル", - "dashboard.createConfirmModal.confirmButtonLabel": "やり直す", - "dashboard.createConfirmModal.continueButtonLabel": "編集を続行", - "dashboard.createConfirmModal.unsavedChangesSubtitle": "編集を続行するか、空のダッシュボードで始めることができます。", - "dashboard.createConfirmModal.unsavedChangesTitle": "新しいダッシュボードはすでに実行中です", - "dashboard.dashboardAppBreadcrumbsTitle": "ダッシュボード", - "dashboard.dashboardGrid.toast.unableToLoadDashboardDangerMessage": "ダッシュボードが読み込めません。", - "dashboard.dashboardPageTitle": "ダッシュボード", - "dashboard.dashboardWasNotSavedDangerMessage": "ダッシュボード「{dashTitle}」が保存されませんでした。エラー:{errorMessage}", - "dashboard.dashboardWasSavedSuccessMessage": "ダッシュボード「{dashTitle}」が保存されました。", - "dashboard.discardChangesConfirmModal.cancelButtonLabel": "キャンセル", - "dashboard.discardChangesConfirmModal.confirmButtonLabel": "変更を破棄", - "dashboard.discardChangesConfirmModal.discardChangesDescription": "変更を破棄すると、元に戻すことはできません。", - "dashboard.discardChangesConfirmModal.discardChangesTitle": "ダッシュボードへの変更を破棄しますか?", - "dashboard.editorMenu.aggBasedGroupTitle": "アグリゲーションに基づく", - "dashboard.embedUrlParamExtension.filterBar": "フィルターバー", - "dashboard.embedUrlParamExtension.include": "含める", - "dashboard.embedUrlParamExtension.query": "クエリ", - "dashboard.embedUrlParamExtension.timeFilter": "時間フィルター", - "dashboard.embedUrlParamExtension.topMenu": "トップメニュー", - "dashboard.emptyDashboardAdditionalPrivilege": "このダッシュボードを編集するには、追加権限が必要です。", - "dashboard.emptyDashboardTitle": "このダッシュボードは空です。", - "dashboard.emptyWidget.addPanelDescription": "データに関するストーリーを伝えるコンテンツを作成します。", - "dashboard.emptyWidget.addPanelTitle": "最初のビジュアライゼーションを追加", - "dashboard.factory.displayName": "ダッシュボード", - "dashboard.featureCatalogue.dashboardDescription": "ビジュアライゼーションと保存された検索のコレクションの表示と共有を行います。", - "dashboard.featureCatalogue.dashboardSubtitle": "ダッシュボードでデータを分析します。", - "dashboard.featureCatalogue.dashboardTitle": "ダッシュボード", - "dashboard.fillDashboardTitle": "このダッシュボードは空です。コンテンツを追加しましょう!", - "dashboard.helpMenu.appName": "ダッシュボード", - "dashboard.howToStartWorkingOnNewDashboardDescription": "上のメニューバーで[編集]をクリックすると、パネルの追加を開始します。", - "dashboard.howToStartWorkingOnNewDashboardEditLinkAriaLabel": "ダッシュボードを編集", - "dashboard.labs.enableLabsDescription": "このフラグはビューアーで[ラボ]ボタンを使用できるかどうかを決定します。ダッシュボードで実験的機能を有効および無効にするための簡単な方法です。", - "dashboard.labs.enableUI": "ダッシュボードで[ラボ]ボタンを有効にする", - "dashboard.listing.createNewDashboard.combineDataViewFromKibanaAppDescription": "あらゆるKibanaアプリからダッシュボードにデータビューを組み合わせて、すべてを1か所に表示できます。", - "dashboard.listing.createNewDashboard.createButtonLabel": "新規ダッシュボードを作成", - "dashboard.listing.createNewDashboard.newToKibanaDescription": "Kibanaは初心者ですか?{sampleDataInstallLink}してお試しください。", - "dashboard.listing.createNewDashboard.sampleDataInstallLinkText": "サンプルデータをインストール", - "dashboard.listing.createNewDashboard.title": "初めてのダッシュボードを作成してみましょう。", - "dashboard.listing.readonlyNoItemsBody": "使用可能なダッシュボードはありません。権限を変更してこのスペースにダッシュボードを表示するには、管理者に問い合わせてください。", - "dashboard.listing.readonlyNoItemsTitle": "表示するダッシュボードがありません", - "dashboard.listing.table.descriptionColumnName": "説明", - "dashboard.listing.table.entityName": "ダッシュボード", - "dashboard.listing.table.entityNamePlural": "ダッシュボード", - "dashboard.listing.table.titleColumnName": "タイトル", - "dashboard.listing.unsaved.discardAria": "{title}への変更を破棄", - "dashboard.listing.unsaved.discardTitle": "変更を破棄", - "dashboard.listing.unsaved.editAria": "{title}の編集を続行", - "dashboard.listing.unsaved.editTitle": "編集を続行", - "dashboard.listing.unsaved.loading": "読み込み中", - "dashboard.listing.unsaved.unsavedChangesTitle": "次の{dash}には保存されていない変更があります。", - "dashboard.migratedChanges": "一部のパネルは正常に最新バージョンに更新されました。", - "dashboard.noMatchRoute.bannerText": "ダッシュボードアプリケーションはこのルート{route}を認識できません。", - "dashboard.noMatchRoute.bannerTitleText": "ページが見つかりません", - "dashboard.panel.AddToLibrary": "ライブラリに保存", - "dashboard.panel.addToLibrary.successMessage": "パネル {panelTitle} は Visualize ライブラリに追加されました", - "dashboard.panel.clonedToast": "クローンパネル", - "dashboard.panel.clonePanel": "パネルのクローン", - "dashboard.panel.copyToDashboard.cancel": "キャンセル", - "dashboard.panel.copyToDashboard.description": "パネルのコピー先を選択します。コピー先のダッシュボードに移動します。", - "dashboard.panel.copyToDashboard.existingDashboardOptionLabel": "既存のダッシュボード", - "dashboard.panel.copyToDashboard.goToDashboard": "コピーしてダッシュボードを開く", - "dashboard.panel.copyToDashboard.newDashboardOptionLabel": "新規ダッシュボード", - "dashboard.panel.copyToDashboard.title": "ダッシュボードにコピー", - "dashboard.panel.invalidData": "URL の無効なデータ", - "dashboard.panel.LibraryNotification": "Visualize ライブラリ通知", - "dashboard.panel.libraryNotification.ariaLabel": "ライブラリ情報を表示し、このパネルのリンクを解除します", - "dashboard.panel.libraryNotification.toolTip": "このパネルを編集すると、他のダッシュボードに影響する場合があります。このパネルのみを変更するには、ライブラリからリンクを解除します。", - "dashboard.panel.removePanel.replacePanel": "パネルの交換", - "dashboard.panel.title.clonedTag": "コピー", - "dashboard.panel.unableToMigratePanelDataForSixOneZeroErrorMessage": "「6.1.0」のダッシュボードの互換性のため、パネルデータを移行できませんでした。パネルには想定された列または行フィールドがありません", - "dashboard.panel.unableToMigratePanelDataForSixThreeZeroErrorMessage": "「6.3.0」のダッシュボードの互換性のため、パネルデータを移行できませんでした。パネルに必要なフィールドがありません:{key}", - "dashboard.panel.unlinkFromLibrary": "ライブラリからのリンクを解除", - "dashboard.panel.unlinkFromLibrary.successMessage": "パネル {panelTitle} は Visualize ライブラリに接続されていません", - "dashboard.panelStorageError.clearError": "保存されていない変更の消去中にエラーが発生しました。{message}", - "dashboard.panelStorageError.getError": "保存されていない変更の取得中にエラーが発生しました。{message}", - "dashboard.panelStorageError.setError": "保存されていない変更の設定中にエラーが発生しました。{message}", - "dashboard.placeholder.factory.displayName": "プレースホルダー", - "dashboard.savedDashboard.newDashboardTitle": "新規ダッシュボード", - "dashboard.solutionToolbar.addPanelButtonLabel": "ビジュアライゼーションを作成", - "dashboard.solutionToolbar.editorMenuButtonLabel": "すべてのタイプ", - "dashboard.strings.dashboardEditTitle": "{title}を編集中", - "dashboard.topNav.cloneModal.cancelButtonLabel": "キャンセル", - "dashboard.topNav.cloneModal.cloneDashboardModalHeaderTitle": "ダッシュボードのクローンを作成", - "dashboard.topNav.cloneModal.confirmButtonLabel": "クローンの確認", - "dashboard.topNav.cloneModal.confirmCloneDescription": "クローンの確認", - "dashboard.topNav.cloneModal.dashboardExistsDescription": "{confirmClone}をクリックして重複タイトルでダッシュボードのクローンを作成します。", - "dashboard.topNav.cloneModal.dashboardExistsTitle": "「{newDashboardName}」というタイトルのダッシュボードがすでに存在します。", - "dashboard.topNav.cloneModal.enterNewNameForDashboardDescription": "ダッシュボードの新しい名前を入力してください。", - "dashboard.topNav.labsButtonAriaLabel": "ラボ", - "dashboard.topNav.labsConfigDescription": "ラボ", - "dashboard.topNav.options.hideAllPanelTitlesSwitchLabel": "パネルタイトルを表示", - "dashboard.topNav.options.syncColorsBetweenPanelsSwitchLabel": "パネル全体でカラーパレットを同期", - "dashboard.topNav.options.useMarginsBetweenPanelsSwitchLabel": "パネルの間に余白を使用", - "dashboard.topNav.saveModal.descriptionFormRowLabel": "説明", - "dashboard.topNav.saveModal.objectType": "ダッシュボード", - "dashboard.topNav.saveModal.storeTimeWithDashboardFormRowHelpText": "有効化すると、ダッシュボードが読み込まれるごとに現在選択された時刻の時間フィルターが変更されます。", - "dashboard.topNav.saveModal.storeTimeWithDashboardFormRowLabel": "ダッシュボードに時刻を保存", - "dashboard.topNav.showCloneModal.dashboardCopyTitle": "{title}のコピー", - "dashboard.topNave.cancelButtonAriaLabel": "表示モードに切り替える", - "dashboard.topNave.cloneButtonAriaLabel": "クローンを作成", - "dashboard.topNave.cloneConfigDescription": "ダッシュボードのコピーを作成します", - "dashboard.topNave.editButtonAriaLabel": "編集", - "dashboard.topNave.editConfigDescription": "編集モードに切り替えます", - "dashboard.topNave.fullScreenButtonAriaLabel": "全画面", - "dashboard.topNave.fullScreenConfigDescription": "全画面モード", - "dashboard.topNave.optionsButtonAriaLabel": "オプション", - "dashboard.topNave.optionsConfigDescription": "オプション", - "dashboard.topNave.saveAsButtonAriaLabel": "名前を付けて保存", - "dashboard.topNave.saveAsConfigDescription": "新しいダッシュボードとして保存", - "dashboard.topNave.saveButtonAriaLabel": "保存", - "dashboard.topNave.saveConfigDescription": "プロンプトを表示せずにダッシュボードをクイック保存", - "dashboard.topNave.shareButtonAriaLabel": "共有", - "dashboard.topNave.shareConfigDescription": "ダッシュボードを共有します", - "dashboard.topNave.viewConfigDescription": "表示専用モードに切り替え", - "dashboard.unsavedChangesBadge": "保存されていない変更", - "dashboard.urlWasRemovedInSixZeroWarningMessage": "URL「dashboard/create」は6.0で廃止されました。ブックマークを更新してください。", - "data.advancedSettings.autocompleteIgnoreTimerange": "時間範囲を使用", - "data.advancedSettings.autocompleteIgnoreTimerangeText": "このプロパティを無効にすると、現在の時間範囲からではなく、データセットからオートコンプリートの候補を取得します。{learnMoreLink}", - "data.advancedSettings.autocompleteValueSuggestionMethod": "自動入力値候補の提案方法", - "data.advancedSettings.autocompleteValueSuggestionMethodLearnMoreLink": "詳細情報", - "data.advancedSettings.autocompleteValueSuggestionMethodLink": "詳細情報", - "data.advancedSettings.autocompleteValueSuggestionMethodText": "KQL自動入力で値の候補をクエリするために使用される方法。terms_enumを選択すると、Elasticsearch用語enum APIを使用して、自動入力候補のパフォーマンスを改善します。terms_aggを選択すると、Elasticsearch用語アグリゲーションを使用します。{learnMoreLink}", - "data.advancedSettings.courier.customRequestPreference.requestPreferenceLinkText": "リクエスト設定", - "data.advancedSettings.courier.customRequestPreferenceText": "{setRequestReferenceSetting} が {customSettingValue} に設定されている時に使用される {requestPreferenceLink} です。", - "data.advancedSettings.courier.customRequestPreferenceTitle": "カスタムリクエスト設定", - "data.advancedSettings.courier.ignoreFilterText": "この構成は、似ていないインデックスにアクセスするビジュアライゼーションを含むダッシュボードのサポートを強化します。無効にすると、すべてのフィルターがすべてのビジュアライゼーションに適用されます。有効にすると、ビジュアライゼーションのインデックスにフィルター対象のフィールドが含まれていない場合、ビジュアライゼーションの際にフィルターが無視されます。", - "data.advancedSettings.courier.ignoreFilterTitle": "フィルターの無視", - "data.advancedSettings.courier.maxRequestsText": "Kibanaから送信された_msearchリクエストに使用される{maxRequestsLink}設定を管理します。この構成を無効にしてElasticsearchのデフォルトを使用するには、0に設定します。", - "data.advancedSettings.courier.maxRequestsTitle": "最大同時シャードリクエスト", - "data.advancedSettings.courier.requestPreferenceCustom": "カスタム", - "data.advancedSettings.courier.requestPreferenceNone": "なし", - "data.advancedSettings.courier.requestPreferenceSessionId": "セッションID", - "data.advancedSettings.courier.requestPreferenceText": "どのシャードが検索リクエストを扱うかを設定できます。
      \n
    • {sessionId}:同じシャードのすべての検索リクエストを実行するため、オペレーションを制限します。\n これにはリクエスト間でシャードのキャッシュを共有できるというメリットがあります。
    • \n
    • {custom}:独自の設定が可能になります。\n 'courier:customRequestPreference'で設定値をカスタマイズします。
    • \n
    • {none}:設定されていないことを意味します。\n これにより、リクエストが全シャードコピー間に分散されるため、パフォーマンスが改善される可能性があります。\n ただし、シャードによって更新ステータスが異なる場合があるため、結果に矛盾が生じる可能性があります。
    • \n
    ", - "data.advancedSettings.courier.requestPreferenceTitle": "リクエスト設定", - "data.advancedSettings.defaultIndexText": "インデックスが設定されていない時にアクセスするインデックスです", - "data.advancedSettings.defaultIndexTitle": "デフォルトのインデックス", - "data.advancedSettings.docTableHighlightText": "Discover と保存された検索ダッシュボードの結果をハイライトします。ハイライトすることで、大きなドキュメントを扱う際にリクエストが遅くなります。", - "data.advancedSettings.docTableHighlightTitle": "結果をハイライト", - "data.advancedSettings.histogram.barTargetText": "日付ヒストグラムで「自動」間隔を使用する際、この数に近いバケットの作成を試みます", - "data.advancedSettings.histogram.barTargetTitle": "目標バケット数", - "data.advancedSettings.histogram.maxBarsText": "Kibana全体で日付の密度とヒストグラム数を制限し、\n テストクエリを使用するときのパフォーマンスを向上させます。テストクエリのバケットが多すぎる場合は、\n バケットの間隔が増えます。この設定は個別に\n 各ヒストグラムアグリゲーションに適用されます。他の種類のアグリゲーションには適用されません。\n この設定の最大値を求めるには、Elasticsearch「search.max_buckets」\n 値を各ビジュアライゼーションのアグリゲーションの最大数で除算します。", - "data.advancedSettings.histogram.maxBarsTitle": "バケットの最大数", - "data.advancedSettings.historyLimitText": "履歴があるフィールド(例:クエリインプット)に個の数の最近の値が表示されます", - "data.advancedSettings.historyLimitTitle": "履歴制限数", - "data.advancedSettings.metaFieldsText": "_source の外にあり、ドキュメントが表示される時に融合されるフィールドです", - "data.advancedSettings.metaFieldsTitle": "メタフィールド", - "data.advancedSettings.pinFiltersText": "フィルターがデフォルトでグローバル(ピン付けされた状態)になるかの設定です", - "data.advancedSettings.pinFiltersTitle": "フィルターをデフォルトでピン付けする", - "data.advancedSettings.query.allowWildcardsText": "設定すると、クエリ句の頭に*が使えるようになります。現在クエリバーで実験的クエリ機能が有効になっている場合にのみ適用されます。基本的なLuceneクエリでリーディングワイルドカードを無効にするには、{queryStringOptionsPattern}を使用します。", - "data.advancedSettings.query.allowWildcardsTitle": "クエリでリーディングワイルドカードを許可する", - "data.advancedSettings.query.queryStringOptions.optionsLinkText": "オプション", - "data.advancedSettings.query.queryStringOptionsText": "Luceneクエリ文字列パーサーの{optionsLink}。「{queryLanguage}」が{luceneLanguage}に設定されているときにのみ使用されます。", - "data.advancedSettings.query.queryStringOptionsTitle": "クエリ文字列のオプション", - "data.advancedSettings.searchQueryLanguageKql": "KQL", - "data.advancedSettings.searchQueryLanguageLucene": "Lucene", - "data.advancedSettings.searchQueryLanguageText": "クエリ言語はクエリバーで使用されます。KQLはKibana用に特別に開発された新しい言語です。", - "data.advancedSettings.searchQueryLanguageTitle": "クエリ言語", - "data.advancedSettings.searchTimeout": "検索タイムアウト", - "data.advancedSettings.searchTimeoutDesc": "検索セッションの最大タイムアウトを変更するか、0 に設定してタイムアウトを無効にすると、クエリは完了するまで実行されます。", - "data.advancedSettings.sortOptions.optionsLinkText": "オプション", - "data.advancedSettings.sortOptionsText": "Elasticsearch の並べ替えパラメーターの {optionsLink}", - "data.advancedSettings.sortOptionsTitle": "並べ替えオプション", - "data.advancedSettings.suggestFilterValuesText": "フィルターエディターがフィールドの値の候補を表示しないようにするには、このプロパティをfalseにしてください。", - "data.advancedSettings.suggestFilterValuesTitle": "フィルターエディターの候補値", - "data.advancedSettings.timepicker.last15Minutes": "過去15分間", - "data.advancedSettings.timepicker.last1Hour": "過去1時間", - "data.advancedSettings.timepicker.last1Year": "過去1年間", - "data.advancedSettings.timepicker.last24Hours": "過去 24 時間", - "data.advancedSettings.timepicker.last30Days": "過去30日間", - "data.advancedSettings.timepicker.last30Minutes": "過去30分間", - "data.advancedSettings.timepicker.last7Days": "過去7日間", - "data.advancedSettings.timepicker.last90Days": "過去90日間", - "data.advancedSettings.timepicker.quickRanges.acceptedFormatsLinkText": "対応フォーマット", - "data.advancedSettings.timepicker.quickRangesText": "時間フィルターのクイックセクションに表示される範囲のリストです。それぞれのオブジェクトに「開始」、「終了」({acceptedFormatsLink}を参照)、「表示」(表示するタイトル)が含まれるオブジェクトの配列です。", - "data.advancedSettings.timepicker.quickRangesTitle": "タイムピッカーのクイック範囲", - "data.advancedSettings.timepicker.refreshIntervalDefaultsText": "時間フィルターのデフォルト更新間隔「値」はミリ秒で指定する必要があります。", - "data.advancedSettings.timepicker.refreshIntervalDefaultsTitle": "タイムピッカーの更新間隔", - "data.advancedSettings.timepicker.thisWeek": "今週", - "data.advancedSettings.timepicker.timeDefaultsText": "時間フィルターが選択されずにKibanaが起動した際に使用される時間フィルターです", - "data.advancedSettings.timepicker.timeDefaultsTitle": "デフォルトのタイムピッカー", - "data.advancedSettings.timepicker.today": "今日", - "data.aggTypes.buckets.ranges.rangesFormatMessage": "{gte} {from} と {lt} {to}", - "data.aggTypes.buckets.ranges.rangesFormatMessageArrowRight": "{from} → {to}", - "data.errors.fetchError": "ネットワークとプロキシ構成を確認してください。問題が解決しない場合は、ネットワーク管理者に問い合わせてください。", - "data.filter.applyFilterActionTitle": "現在のビューにフィルターを適用", - "data.filter.applyFilters.popupHeader": "適用するフィルターの選択", - "data.filter.applyFiltersPopup.cancelButtonLabel": "キャンセル", - "data.filter.applyFiltersPopup.saveButtonLabel": "適用", - "data.filter.filterBar.addFilterButtonLabel": "フィルターを追加します", - "data.filter.filterBar.deleteFilterButtonLabel": "削除", - "data.filter.filterBar.disabledFilterPrefix": "無効", - "data.filter.filterBar.disableFilterButtonLabel": "一時的に無効にする", - "data.filter.filterBar.editFilterButtonLabel": "フィルターを編集", - "data.filter.filterBar.enableFilterButtonLabel": "再度有効にする", - "data.filter.filterBar.excludeFilterButtonLabel": "結果を除外", - "data.filter.filterBar.fieldNotFound": "インデックスパターン {indexPattern} にフィールド {key} がありません", - "data.filter.filterBar.filterItemBadgeAriaLabel": "フィルターアクション", - "data.filter.filterBar.filterItemBadgeIconAriaLabel": "{filter}を削除", - "data.filter.filterBar.includeFilterButtonLabel": "結果を含める", - "data.filter.filterBar.indexPatternSelectPlaceholder": "インデックスパターンの選択", - "data.filter.filterBar.labelErrorInfo": "インデックスパターン{indexPattern}が見つかりません", - "data.filter.filterBar.labelErrorText": "エラー", - "data.filter.filterBar.labelWarningInfo": "フィールド{fieldName}は現在のビューに存在しません", - "data.filter.filterBar.labelWarningText": "警告", - "data.filter.filterBar.moreFilterActionsMessage": "フィルター:{innerText}。他のフィルターアクションを使用するには選択してください。", - "data.filter.filterBar.negatedFilterPrefix": "NOT ", - "data.filter.filterBar.pinFilterButtonLabel": "すべてのアプリにピン付け", - "data.filter.filterBar.pinnedFilterPrefix": "ピン付け済み", - "data.filter.filterBar.unpinFilterButtonLabel": "ピンを外す", - "data.filter.filterEditor.cancelButtonLabel": "キャンセル", - "data.filter.filterEditor.createCustomLabelInputLabel": "カスタムラベル", - "data.filter.filterEditor.createCustomLabelSwitchLabel": "カスタムラベルを作成しますか?", - "data.filter.filterEditor.doesNotExistOperatorOptionLabel": "存在しない", - "data.filter.filterEditor.editFilterPopupTitle": "フィルターを編集", - "data.filter.filterEditor.editFilterValuesButtonLabel": "フィルター値を編集", - "data.filter.filterEditor.editQueryDslButtonLabel": "クエリ DSL として編集", - "data.filter.filterEditor.existsOperatorOptionLabel": "存在する", - "data.filter.filterEditor.falseOptionLabel": "false", - "data.filter.filterEditor.fieldSelectLabel": "フィールド", - "data.filter.filterEditor.fieldSelectPlaceholder": "フィールドを選択", - "data.filter.filterEditor.indexPatternSelectLabel": "インデックスパターン", - "data.filter.filterEditor.isBetweenOperatorOptionLabel": "is between", - "data.filter.filterEditor.isNotBetweenOperatorOptionLabel": "is not between", - "data.filter.filterEditor.isNotOneOfOperatorOptionLabel": "is not one of", - "data.filter.filterEditor.isNotOperatorOptionLabel": "is not", - "data.filter.filterEditor.isOneOfOperatorOptionLabel": "is one of", - "data.filter.filterEditor.isOperatorOptionLabel": "is", - "data.filter.filterEditor.operatorSelectLabel": "演算子", - "data.filter.filterEditor.operatorSelectPlaceholderSelect": "選択してください", - "data.filter.filterEditor.operatorSelectPlaceholderWaiting": "待機中", - "data.filter.filterEditor.queryDslLabel": "Elasticsearch クエリ DSL", - "data.filter.filterEditor.rangeEndInputPlaceholder": "範囲の終了値", - "data.filter.filterEditor.rangeInputLabel": "範囲", - "data.filter.filterEditor.rangeStartInputPlaceholder": "範囲の開始値", - "data.filter.filterEditor.saveButtonLabel": "保存", - "data.filter.filterEditor.trueOptionLabel": "true", - "data.filter.filterEditor.valueInputLabel": "値", - "data.filter.filterEditor.valueInputPlaceholder": "値を入力", - "data.filter.filterEditor.valueSelectPlaceholder": "値を選択", - "data.filter.filterEditor.valuesSelectLabel": "値", - "data.filter.filterEditor.valuesSelectPlaceholder": "値を選択", - "data.filter.options.changeAllFiltersButtonLabel": "すべてのフィルターの変更", - "data.filter.options.deleteAllFiltersButtonLabel": "すべて削除", - "data.filter.options.disableAllFiltersButtonLabel": "すべて無効にする", - "data.filter.options.enableAllFiltersButtonLabel": "すべて有効にする", - "data.filter.options.invertDisabledFiltersButtonLabel": "有効・無効を反転", - "data.filter.options.invertNegatedFiltersButtonLabel": "含める・除外を反転", - "data.filter.options.pinAllFiltersButtonLabel": "すべてピン付け", - "data.filter.options.unpinAllFiltersButtonLabel": "すべてのピンを外す", - "data.filter.searchBar.changeAllFiltersTitle": "すべてのフィルターの変更", - "data.functions.esaggs.help": "AggConfig 集約を実行します", - "data.functions.esaggs.inspector.dataRequest.description": "このリクエストはElasticsearchにクエリし、ビジュアライゼーション用のデータを取得します。", - "data.functions.esaggs.inspector.dataRequest.title": "データ", - "data.inspector.table..dataDescriptionTooltip": "ビジュアライゼーションの元のデータを表示", - "data.inspector.table.dataTitle": "データ", - "data.inspector.table.downloadCSVToggleButtonLabel": "CSV をダウンロード", - "data.inspector.table.downloadOptionsUnsavedFilename": "未保存", - "data.inspector.table.exportButtonFormulasWarning": "CSVには、スプレッドシートアプリケーションで式と解釈される可能性のある文字が含まれています。", - "data.inspector.table.filterForValueButtonAriaLabel": "値でフィルター", - "data.inspector.table.filterForValueButtonTooltip": "値でフィルター", - "data.inspector.table.filterOutValueButtonAriaLabel": "値を除外", - "data.inspector.table.filterOutValueButtonTooltip": "値を除外", - "data.inspector.table.formattedCSVButtonLabel": "フォーマット済み CSV", - "data.inspector.table.formattedCSVButtonTooltip": "データを表形式でダウンロード", - "data.inspector.table.noDataAvailableDescription": "エレメントがデータを提供しませんでした。", - "data.inspector.table.noDataAvailableTitle": "利用可能なデータがありません", - "data.inspector.table.rawCSVButtonLabel": "CSV", - "data.inspector.table.rawCSVButtonTooltip": "日付をタイムスタンプとしてなど、提供されたデータをそのままダウンロードします", - "data.inspector.table.tableLabel": "テーブル{index}", - "data.inspector.table.tableSelectorLabel": "選択済み:", - "data.kueryAutocomplete.andOperatorDescription": "{bothArguments} が true であることを条件とする", - "data.kueryAutocomplete.andOperatorDescription.bothArgumentsText": "両方の引数", - "data.kueryAutocomplete.equalOperatorDescription": "一部の値に{equals}", - "data.kueryAutocomplete.equalOperatorDescription.equalsText": "一致する", - "data.kueryAutocomplete.existOperatorDescription": "いずれかの形式中に{exists}", - "data.kueryAutocomplete.existOperatorDescription.existsText": "存在する", - "data.kueryAutocomplete.filterResultsDescription": "{fieldName}を含む結果をフィルタリング", - "data.kueryAutocomplete.greaterThanOperatorDescription": "が一部の値{greaterThan}", - "data.kueryAutocomplete.greaterThanOperatorDescription.greaterThanText": "より大きい", - "data.kueryAutocomplete.greaterThanOrEqualOperatorDescription": "が一部の値{greaterThanOrEqualTo}", - "data.kueryAutocomplete.greaterThanOrEqualOperatorDescription.greaterThanOrEqualToText": "よりも大きいまたは等しい", - "data.kueryAutocomplete.lessThanOperatorDescription": "が一部の値{lessThan}", - "data.kueryAutocomplete.lessThanOperatorDescription.lessThanText": "より小さい", - "data.kueryAutocomplete.lessThanOrEqualOperatorDescription": "が一部の値{lessThanOrEqualTo}", - "data.kueryAutocomplete.lessThanOrEqualOperatorDescription.lessThanOrEqualToText": "より小さいまたは等しい", - "data.kueryAutocomplete.orOperatorDescription": "{oneOrMoreArguments} が true であることを条件とする", - "data.kueryAutocomplete.orOperatorDescription.oneOrMoreArgumentsText": "1つ以上の引数", - "data.noDataPopover.content": "この時間範囲にはデータが含まれていません。表示するフィールドを増やし、グラフを作成するには、時間範囲を広げるか、調整してください。", - "data.noDataPopover.dismissAction": "今後表示しない", - "data.noDataPopover.subtitle": "ヒント", - "data.noDataPopover.title": "空のデータセット", - "data.painlessError.buttonTxt": "スクリプトを編集", - "data.painlessError.painlessScriptedFieldErrorMessage": "インデックスパターン{indexPatternName}でのランタイムフィールドまたはスクリプトフィールドの実行エラー", - "data.parseEsInterval.invalidEsCalendarIntervalErrorMessage": "無効なカレンダー間隔:{interval}、1よりも大きな値が必要です", - "data.parseEsInterval.invalidEsIntervalFormatErrorMessage": "無効な間隔形式:{interval}", - "data.query.queryBar.clearInputLabel": "インプットを消去", - "data.query.queryBar.comboboxAriaLabel": "{pageType} ページの検索とフィルタリング", - "data.query.queryBar.kqlFullLanguageName": "Kibana クエリ言語", - "data.query.queryBar.kqlLanguageName": "KQL", - "data.query.queryBar.KQLNestedQuerySyntaxInfoDocLinkText": "ドキュメント", - "data.query.queryBar.KQLNestedQuerySyntaxInfoOptOutText": "今後表示しない", - "data.query.queryBar.KQLNestedQuerySyntaxInfoText": "ネストされたフィールドをクエリされているようです。ネストされたクエリに対しては、ご希望の結果により異なる方法で KQL 構文を構築することができます。詳細については、{link}をご覧ください。", - "data.query.queryBar.KQLNestedQuerySyntaxInfoTitle": "KQL ネストされたクエリ構文", - "data.query.queryBar.kqlOffLabel": "オフ", - "data.query.queryBar.kqlOnLabel": "オン", - "data.query.queryBar.languageSwitcher.toText": "検索用にKibana Query Languageに切り替える", - "data.query.queryBar.luceneLanguageName": "Lucene", - "data.query.queryBar.searchInputAriaLabel": "{pageType} ページの検索とフィルタリングを行うには入力を開始してください", - "data.query.queryBar.searchInputPlaceholder": "検索", - "data.query.queryBar.syntaxOptionsDescription": "{docsLink}(KQL)は、シンプルなクエリ構文とスクリプトフィールドのサポートを提供します。KQLにはオートコンプリート機能もあります。KQLをオフにする場合は、{nonKqlModeHelpText}", - "data.query.queryBar.syntaxOptionsDescription.nonKqlModeHelpText": "KibanaはLuceneを使用します。", - "data.query.queryBar.syntaxOptionsTitle": "構文オプション", - "data.search.aggs.aggGroups.bucketsText": "バケット", - "data.search.aggs.aggGroups.metricsText": "メトリック", - "data.search.aggs.aggGroups.noneText": "なし", - "data.search.aggs.aggTypesLabel": "{fieldName} の範囲", - "data.search.aggs.buckets.dateHistogram.customLabel.help": "このアグリゲーションのカスタムラベルを表します", - "data.search.aggs.buckets.dateHistogram.dropPartials.help": "このアグリゲーションでdrop_partialsを使用するかどうかを指定します", - "data.search.aggs.buckets.dateHistogram.enabled.help": "このアグリゲーションが有効かどうかを指定します", - "data.search.aggs.buckets.dateHistogram.extendedBounds.help": "extended_bounds設定を使用すると、強制的にヒストグラムアグリゲーションを実行し、特定の最小値に対してバケットの作成を開始し、最大値までバケットを作成し続けます。 ", - "data.search.aggs.buckets.dateHistogram.field.help": "このアグリゲーションで使用するフィールド", - "data.search.aggs.buckets.dateHistogram.format.help": "このアグリゲーションで使用するフォーマット", - "data.search.aggs.buckets.dateHistogram.id.help": "このアグリゲーションのID", - "data.search.aggs.buckets.dateHistogram.interval.help": "このアグリゲーションで使用する間隔", - "data.search.aggs.buckets.dateHistogram.json.help": "アグリゲーションがElasticsearchに送信されるときに含める高度なJSON", - "data.search.aggs.buckets.dateHistogram.minDocCount.help": "このアグリゲーションで使用する最小ドキュメントカウント", - "data.search.aggs.buckets.dateHistogram.scaleMetricValues.help": "このアグリゲーションでscaleMetricValuesを使用するかどうかを指定します", - "data.search.aggs.buckets.dateHistogram.schema.help": "このアグリゲーションで使用するスキーマ", - "data.search.aggs.buckets.dateHistogram.timeRange.help": "このアグリゲーションで使用する時間範囲", - "data.search.aggs.buckets.dateHistogram.timeZone.help": "このアグリゲーションで使用するタイムゾーン", - "data.search.aggs.buckets.dateHistogram.useNormalizedEsInterval.help": "このアグリゲーションでuseNormalizedEsIntervalを使用するかどうかを指定します", - "data.search.aggs.buckets.dateHistogramLabel": "{intervalDescription} ごとの {fieldName}", - "data.search.aggs.buckets.dateHistogramTitle": "日付ヒストグラム", - "data.search.aggs.buckets.dateRange.customLabel.help": "このアグリゲーションのカスタムラベルを表します", - "data.search.aggs.buckets.dateRange.enabled.help": "このアグリゲーションが有効かどうかを指定します", - "data.search.aggs.buckets.dateRange.field.help": "このアグリゲーションで使用するフィールド", - "data.search.aggs.buckets.dateRange.id.help": "このアグリゲーションのID", - "data.search.aggs.buckets.dateRange.json.help": "アグリゲーションがElasticsearchに送信されるときに含める高度なJSON", - "data.search.aggs.buckets.dateRange.ranges.help": "このアグリゲーションで使用する範囲。", - "data.search.aggs.buckets.dateRange.schema.help": "このアグリゲーションで使用するスキーマ", - "data.search.aggs.buckets.dateRange.timeZone.help": "このアグリゲーションで使用するタイムゾーン。", - "data.search.aggs.buckets.dateRangeTitle": "日付範囲", - "data.search.aggs.buckets.filter.customLabel.help": "このアグリゲーションのカスタムラベルを表します", - "data.search.aggs.buckets.filter.enabled.help": "このアグリゲーションが有効かどうかを指定します", - "data.search.aggs.buckets.filter.filter.help": "KQLまたはLuceneクエリに基づいて結果をフィルタリングします。geo_bounding_boxと一緒に使用しないでください", - "data.search.aggs.buckets.filter.geoBoundingBox.help": "バウンディングボックス内の点の位置に基づいて結果をフィルタリングします", - "data.search.aggs.buckets.filter.id.help": "このアグリゲーションのID", - "data.search.aggs.buckets.filter.json.help": "アグリゲーションがElasticsearchに送信されるときに含める高度なJSON", - "data.search.aggs.buckets.filter.schema.help": "このアグリゲーションで使用するスキーマ", - "data.search.aggs.buckets.filters.enabled.help": "このアグリゲーションが有効かどうかを指定します", - "data.search.aggs.buckets.filters.filters.help": "このアグリゲーションで使用するフィルター", - "data.search.aggs.buckets.filters.id.help": "このアグリゲーションのID", - "data.search.aggs.buckets.filters.json.help": "アグリゲーションがElasticsearchに送信されるときに含める高度なJSON", - "data.search.aggs.buckets.filters.schema.help": "このアグリゲーションで使用するスキーマ", - "data.search.aggs.buckets.filtersTitle": "フィルター", - "data.search.aggs.buckets.filterTitle": "フィルター", - "data.search.aggs.buckets.geoHash.autoPrecision.help": "このアグリゲーションで自動精度を使用するかどうかを指定します", - "data.search.aggs.buckets.geoHash.boundingBox.help": "バウンディングボックス内の点の位置に基づいて結果をフィルタリングします", - "data.search.aggs.buckets.geoHash.customLabel.help": "このアグリゲーションのカスタムラベルを表します", - "data.search.aggs.buckets.geoHash.enabled.help": "このアグリゲーションが有効かどうかを指定します", - "data.search.aggs.buckets.geoHash.field.help": "このアグリゲーションで使用するフィールド", - "data.search.aggs.buckets.geoHash.id.help": "このアグリゲーションのID", - "data.search.aggs.buckets.geoHash.isFilteredByCollar.help": "カラーでフィルタリングするかどうかを指定します", - "data.search.aggs.buckets.geoHash.json.help": "アグリゲーションがElasticsearchに送信されるときに含める高度なJSON", - "data.search.aggs.buckets.geoHash.precision.help": "このアグリゲーションで使用する精度。", - "data.search.aggs.buckets.geoHash.schema.help": "このアグリゲーションで使用するスキーマ", - "data.search.aggs.buckets.geoHash.useGeocentroid.help": "このアグリゲーションでgeocentroid使用するかどうかを指定します", - "data.search.aggs.buckets.geohashGridTitle": "ジオハッシュ", - "data.search.aggs.buckets.geoTile.customLabel.help": "このアグリゲーションのカスタムラベルを表します", - "data.search.aggs.buckets.geoTile.enabled.help": "このアグリゲーションが有効かどうかを指定します", - "data.search.aggs.buckets.geoTile.field.help": "このアグリゲーションで使用するフィールド", - "data.search.aggs.buckets.geoTile.id.help": "このアグリゲーションのID", - "data.search.aggs.buckets.geoTile.json.help": "アグリゲーションがElasticsearchに送信されるときに含める高度なJSON", - "data.search.aggs.buckets.geoTile.precision.help": "このアグリゲーションで使用する精度。", - "data.search.aggs.buckets.geoTile.schema.help": "このアグリゲーションで使用するスキーマ", - "data.search.aggs.buckets.geoTile.useGeocentroid.help": "このアグリゲーションでgeocentroid使用するかどうかを指定します", - "data.search.aggs.buckets.geotileGridTitle": "ジオタイル", - "data.search.aggs.buckets.histogram.customLabel.help": "このアグリゲーションのカスタムラベルを表します", - "data.search.aggs.buckets.histogram.enabled.help": "このアグリゲーションが有効かどうかを指定します", - "data.search.aggs.buckets.histogram.extendedBounds.help": "extended_bounds設定を使用すると、強制的にヒストグラムアグリゲーションを実行し、特定の最小値に対してバケットの作成を開始し、最大値までバケットを作成し続けます。 ", - "data.search.aggs.buckets.histogram.field.help": "このアグリゲーションで使用するフィールド", - "data.search.aggs.buckets.histogram.hasExtendedBounds.help": "このアグリゲーションでhas_extended_boundsを使用するかどうかを指定します", - "data.search.aggs.buckets.histogram.id.help": "このアグリゲーションのID", - "data.search.aggs.buckets.histogram.interval.help": "このアグリゲーションで使用する間隔", - "data.search.aggs.buckets.histogram.intervalBase.help": "このアグリゲーションで使用するIntervalBase", - "data.search.aggs.buckets.histogram.json.help": "アグリゲーションがElasticsearchに送信されるときに含める高度なJSON", - "data.search.aggs.buckets.histogram.maxBars.help": "間隔を計算して、この数の棒を取得します", - "data.search.aggs.buckets.histogram.minDocCount.help": "このアグリゲーションでmin_doc_countを使用するかどうかを指定します", - "data.search.aggs.buckets.histogram.schema.help": "このアグリゲーションで使用するスキーマ", - "data.search.aggs.buckets.histogramTitle": "ヒストグラム", - "data.search.aggs.buckets.intervalOptions.autoDisplayName": "自動", - "data.search.aggs.buckets.intervalOptions.dailyDisplayName": "日", - "data.search.aggs.buckets.intervalOptions.hourlyDisplayName": "時間", - "data.search.aggs.buckets.intervalOptions.millisecondDisplayName": "ミリ秒", - "data.search.aggs.buckets.intervalOptions.minuteDisplayName": "分", - "data.search.aggs.buckets.intervalOptions.monthlyDisplayName": "月", - "data.search.aggs.buckets.intervalOptions.secondDisplayName": "秒", - "data.search.aggs.buckets.intervalOptions.weeklyDisplayName": "週", - "data.search.aggs.buckets.intervalOptions.yearlyDisplayName": "年", - "data.search.aggs.buckets.ipRange.customLabel.help": "このアグリゲーションのカスタムラベルを表します", - "data.search.aggs.buckets.ipRange.enabled.help": "このアグリゲーションが有効かどうかを指定します", - "data.search.aggs.buckets.ipRange.field.help": "このアグリゲーションで使用するフィールド", - "data.search.aggs.buckets.ipRange.id.help": "このアグリゲーションのID", - "data.search.aggs.buckets.ipRange.ipRangeType.help": "このアグリゲーションで使用するIP範囲タイプ。値mask、fromTOのいずれかを取ります。", - "data.search.aggs.buckets.ipRange.json.help": "アグリゲーションがElasticsearchに送信されるときに含める高度なJSON", - "data.search.aggs.buckets.ipRange.ranges.help": "このアグリゲーションで使用する範囲。", - "data.search.aggs.buckets.ipRange.schema.help": "このアグリゲーションで使用するスキーマ", - "data.search.aggs.buckets.ipRangeLabel": "{fieldName} IP 範囲", - "data.search.aggs.buckets.ipRangeTitle": "IP範囲", - "data.search.aggs.buckets.range.customLabel.help": "このアグリゲーションのカスタムラベルを表します", - "data.search.aggs.buckets.range.enabled.help": "このアグリゲーションが有効かどうかを指定します", - "data.search.aggs.buckets.range.field.help": "このアグリゲーションで使用するフィールド", - "data.search.aggs.buckets.range.id.help": "このアグリゲーションのID", - "data.search.aggs.buckets.range.json.help": "アグリゲーションがElasticsearchに送信されるときに含める高度なJSON", - "data.search.aggs.buckets.range.ranges.help": "このアグリゲーションで使用するシリアル化された範囲。", - "data.search.aggs.buckets.range.schema.help": "このアグリゲーションで使用するスキーマ", - "data.search.aggs.buckets.rangeTitle": "範囲", - "data.search.aggs.buckets.shardDelay.customLabel.help": "このアグリゲーションのカスタムラベルを表します", - "data.search.aggs.buckets.shardDelay.delay.help": "処理するシャード間の遅延。例:\"5s\".", - "data.search.aggs.buckets.shardDelay.enabled.help": "このアグリゲーションが有効かどうかを指定します", - "data.search.aggs.buckets.shardDelay.id.help": "このアグリゲーションのID", - "data.search.aggs.buckets.shardDelay.json.help": "アグリゲーションがElasticsearchに送信されるときに含める高度なJSON", - "data.search.aggs.buckets.shardDelay.schema.help": "このアグリゲーションで使用するスキーマ", - "data.search.aggs.buckets.significantTerms.customLabel.help": "このアグリゲーションのカスタムラベルを表します", - "data.search.aggs.buckets.significantTerms.enabled.help": "このアグリゲーションが有効かどうかを指定します", - "data.search.aggs.buckets.significantTerms.exclude.help": "結果から除外する特定のバケット値", - "data.search.aggs.buckets.significantTerms.excludeLabel": "除外", - "data.search.aggs.buckets.significantTerms.field.help": "このアグリゲーションで使用するフィールド", - "data.search.aggs.buckets.significantTerms.id.help": "このアグリゲーションのID", - "data.search.aggs.buckets.significantTerms.include.help": "結果に含める特定のバケット値", - "data.search.aggs.buckets.significantTerms.includeLabel": "含める", - "data.search.aggs.buckets.significantTerms.json.help": "アグリゲーションがElasticsearchに送信されるときに含める高度なJSON", - "data.search.aggs.buckets.significantTerms.schema.help": "このアグリゲーションで使用するスキーマ", - "data.search.aggs.buckets.significantTerms.size.help": "取得するバケットの最大数", - "data.search.aggs.buckets.significantTermsLabel": "{fieldName} のトップ {size} の珍しいアイテム", - "data.search.aggs.buckets.significantTermsTitle": "重要な用語", - "data.search.aggs.buckets.terms.customLabel.help": "このアグリゲーションのカスタムラベルを表します", - "data.search.aggs.buckets.terms.enabled.help": "このアグリゲーションが有効かどうかを指定します", - "data.search.aggs.buckets.terms.exclude.help": "結果から除外する特定のバケット値", - "data.search.aggs.buckets.terms.excludeLabel": "除外", - "data.search.aggs.buckets.terms.field.help": "このアグリゲーションで使用するフィールド", - "data.search.aggs.buckets.terms.id.help": "このアグリゲーションのID", - "data.search.aggs.buckets.terms.include.help": "結果に含める特定のバケット値", - "data.search.aggs.buckets.terms.includeLabel": "含める", - "data.search.aggs.buckets.terms.json.help": "アグリゲーションがElasticsearchに送信されるときに含める高度なJSON", - "data.search.aggs.buckets.terms.missingBucket.help": "trueに設定すると、見つからないフィールドのすべてのバケットをグループ化します", - "data.search.aggs.buckets.terms.missingBucketLabel": "欠測値", - "data.search.aggs.buckets.terms.missingBucketLabel.help": "ドキュメントのフィールドが見つからないときにグラフで使用される既定のラベル。", - "data.search.aggs.buckets.terms.order.help": "結果を返す順序:昇順または降順", - "data.search.aggs.buckets.terms.orderAgg.help": "結果の並べ替えで使用するアグリゲーション構成", - "data.search.aggs.buckets.terms.orderAscendingTitle": "昇順", - "data.search.aggs.buckets.terms.orderBy.help": "結果を並べ替える基準のフィールド", - "data.search.aggs.buckets.terms.orderDescendingTitle": "降順", - "data.search.aggs.buckets.terms.otherBucket.help": "trueに設定すると、許可されたサイズを超えるすべてのバケットをグループ化します", - "data.search.aggs.buckets.terms.otherBucketDescription": "このリクエストは、データバケットの基準外のドキュメントの数をカウントします。", - "data.search.aggs.buckets.terms.otherBucketLabel": "その他", - "data.search.aggs.buckets.terms.otherBucketLabel.help": "他のバケットのドキュメントのグラフで使用される既定のラベル", - "data.search.aggs.buckets.terms.otherBucketTitle": "他のバケット", - "data.search.aggs.buckets.terms.schema.help": "このアグリゲーションで使用するスキーマ", - "data.search.aggs.buckets.terms.size.help": "取得するバケットの最大数", - "data.search.aggs.buckets.termsTitle": "用語", - "data.search.aggs.error.aggNotFound": "「{type}」に登録されたアグリゲーションタイプが見つかりません。", - "data.search.aggs.function.buckets.dateHistogram.help": "ヒストグラムアグリゲーションのシリアル化されたアグリゲーション構成を生成します", - "data.search.aggs.function.buckets.dateRange.help": "日付範囲アグリゲーションのシリアル化されたアグリゲーション構成を生成します", - "data.search.aggs.function.buckets.filter.help": "フィルターアグリゲーションのシリアル化されたアグリゲーション構成を生成します", - "data.search.aggs.function.buckets.filters.help": "フィルターアグリゲーションのシリアル化されたアグリゲーション構成を生成します", - "data.search.aggs.function.buckets.geoHash.help": "ジオハッシュアグリゲーションのシリアル化されたアグリゲーション構成を生成します", - "data.search.aggs.function.buckets.geoTile.help": "ジオタイルアグリゲーションのシリアル化されたアグリゲーション構成を生成します", - "data.search.aggs.function.buckets.histogram.help": "ヒストグラムアグリゲーションのシリアル化されたアグリゲーション構成を生成します", - "data.search.aggs.function.buckets.ipRange.help": "IP範囲アグリゲーションのシリアル化されたアグリゲーション構成を生成します", - "data.search.aggs.function.buckets.range.help": "範囲アグリゲーションのシリアル化されたアグリゲーション構成を生成します", - "data.search.aggs.function.buckets.shardDelay.help": "シャード遅延アグリゲーションのシリアル化されたアグリゲーション構成を生成します", - "data.search.aggs.function.buckets.significantTerms.help": "重要な用語アグリゲーションのシリアル化されたアグリゲーション構成を生成します", - "data.search.aggs.function.buckets.terms.help": "用語アグリゲーションのシリアル化されたアグリゲーション構成を生成します", - "data.search.aggs.function.metrics.avg.help": "平均値アグリゲーションのシリアル化されたアグリゲーション構成を生成します", - "data.search.aggs.function.metrics.bucket_avg.help": "平均値バケットアグリゲーションのシリアル化されたアグリゲーション構成を生成します", - "data.search.aggs.function.metrics.bucket_max.help": "最大値バケットアグリゲーションのシリアル化されたアグリゲーション構成を生成します", - "data.search.aggs.function.metrics.bucket_min.help": "最小値バケットアグリゲーションのシリアル化されたアグリゲーション構成を生成します", - "data.search.aggs.function.metrics.bucket_sum.help": "合計値バケットアグリゲーションのシリアル化されたアグリゲーション構成を生成します", - "data.search.aggs.function.metrics.cardinality.help": "カーディナリティアグリゲーションのシリアル化されたアグリゲーション構成を生成します", - "data.search.aggs.function.metrics.count.help": "カウントアグリゲーションのシリアル化されたアグリゲーション構成を生成します", - "data.search.aggs.function.metrics.cumulative_sum.help": "合計値バケットアグリゲーションのシリアル化されたアグリゲーション構成を生成します", - "data.search.aggs.function.metrics.derivative.help": "微分アグリゲーションのシリアル化されたアグリゲーション構成を生成します", - "data.search.aggs.function.metrics.filtered_metric.help": "フィルタリングされたメトリックアグリゲーションのシリアル化されたアグリゲーション構成を生成します", - "data.search.aggs.function.metrics.geo_bounds.help": "ジオ境界アグリゲーションのシリアル化されたアグリゲーション構成を生成します", - "data.search.aggs.function.metrics.geo_centroid.help": "ジオ中心アグリゲーションのシリアル化されたアグリゲーション構成を生成します", - "data.search.aggs.function.metrics.max.help": "最大値アグリゲーションのシリアル化されたアグリゲーション構成を生成します", - "data.search.aggs.function.metrics.median.help": "中央値アグリゲーションのシリアル化されたアグリゲーション構成を生成します", - "data.search.aggs.function.metrics.min.help": "最小値アグリゲーションのシリアル化されたアグリゲーション構成を生成します", - "data.search.aggs.function.metrics.moving_avg.help": "移動平均値アグリゲーションのシリアル化されたアグリゲーション構成を生成します", - "data.search.aggs.function.metrics.percentile_ranks.help": "パーセンタイル順位アグリゲーションのシリアル化されたアグリゲーション構成を生成します", - "data.search.aggs.function.metrics.percentiles.help": "パーセンタイルアグリゲーションのシリアル化されたアグリゲーション構成を生成します", - "data.search.aggs.function.metrics.serial_diff.help": "シリアル差異アグリゲーションのシリアル化されたアグリゲーション構成を生成します", - "data.search.aggs.function.metrics.singlePercentile.help": "パーセンタイルアグリゲーションのシリアル化されたアグリゲーション構成を生成します", - "data.search.aggs.function.metrics.std_deviation.help": "標準偏差アグリゲーションのシリアル化されたアグリゲーション構成を生成します", - "data.search.aggs.function.metrics.sum.help": "合計値アグリゲーションのシリアル化されたアグリゲーション構成を生成します", - "data.search.aggs.function.metrics.top_hit.help": "上位一致のシリアル化されたアグリゲーション構成を生成します", - "data.search.aggs.histogram.missingMaxMinValuesWarning": "自動スケールヒストグラムバケットから最高値と最低値を取得できません。これによりビジュアライゼーションのパフォーマンスが低下する可能性があります。", - "data.search.aggs.metrics.averageBucketTitle": "平均バケット", - "data.search.aggs.metrics.averageLabel": "平均 {field}", - "data.search.aggs.metrics.averageTitle": "平均", - "data.search.aggs.metrics.avg.customLabel.help": "このアグリゲーションのカスタムラベルを表します", - "data.search.aggs.metrics.avg.enabled.help": "このアグリゲーションが有効かどうかを指定します", - "data.search.aggs.metrics.avg.field.help": "このアグリゲーションで使用するフィールド", - "data.search.aggs.metrics.avg.id.help": "このアグリゲーションのID", - "data.search.aggs.metrics.avg.json.help": "アグリゲーションがElasticsearchに送信されるときに含める高度なJSON", - "data.search.aggs.metrics.avg.schema.help": "このアグリゲーションで使用するスキーマ", - "data.search.aggs.metrics.bucket_avg.customBucket.help": "兄弟パイプラインアグリゲーションを構築するために使用するアグリゲーション構成", - "data.search.aggs.metrics.bucket_avg.customLabel.help": "このアグリゲーションのカスタムラベルを表します", - "data.search.aggs.metrics.bucket_avg.customMetric.help": "兄弟パイプラインアグリゲーションを構築するために使用するアグリゲーション構成", - "data.search.aggs.metrics.bucket_avg.enabled.help": "このアグリゲーションが有効かどうかを指定します", - "data.search.aggs.metrics.bucket_avg.id.help": "このアグリゲーションのID", - "data.search.aggs.metrics.bucket_avg.json.help": "アグリゲーションがElasticsearchに送信されるときに含める高度なJSON", - "data.search.aggs.metrics.bucket_avg.schema.help": "このアグリゲーションで使用するスキーマ", - "data.search.aggs.metrics.bucket_max.customBucket.help": "兄弟パイプラインアグリゲーションを構築するために使用するアグリゲーション構成", - "data.search.aggs.metrics.bucket_max.customLabel.help": "このアグリゲーションのカスタムラベルを表します", - "data.search.aggs.metrics.bucket_max.customMetric.help": "兄弟パイプラインアグリゲーションを構築するために使用するアグリゲーション構成", - "data.search.aggs.metrics.bucket_max.enabled.help": "このアグリゲーションが有効かどうかを指定します", - "data.search.aggs.metrics.bucket_max.id.help": "このアグリゲーションのID", - "data.search.aggs.metrics.bucket_max.json.help": "アグリゲーションがElasticsearchに送信されるときに含める高度なJSON", - "data.search.aggs.metrics.bucket_max.schema.help": "このアグリゲーションで使用するスキーマ", - "data.search.aggs.metrics.bucket_min.customBucket.help": "兄弟パイプラインアグリゲーションを構築するために使用するアグリゲーション構成", - "data.search.aggs.metrics.bucket_min.customLabel.help": "このアグリゲーションのカスタムラベルを表します", - "data.search.aggs.metrics.bucket_min.customMetric.help": "兄弟パイプラインアグリゲーションを構築するために使用するアグリゲーション構成", - "data.search.aggs.metrics.bucket_min.enabled.help": "このアグリゲーションが有効かどうかを指定します", - "data.search.aggs.metrics.bucket_min.id.help": "このアグリゲーションのID", - "data.search.aggs.metrics.bucket_min.json.help": "アグリゲーションがElasticsearchに送信されるときに含める高度なJSON", - "data.search.aggs.metrics.bucket_min.schema.help": "このアグリゲーションで使用するスキーマ", - "data.search.aggs.metrics.bucket_sum.customBucket.help": "兄弟パイプラインアグリゲーションを構築するために使用するアグリゲーション構成", - "data.search.aggs.metrics.bucket_sum.customLabel.help": "このアグリゲーションのカスタムラベルを表します", - "data.search.aggs.metrics.bucket_sum.customMetric.help": "兄弟パイプラインアグリゲーションを構築するために使用するアグリゲーション構成", - "data.search.aggs.metrics.bucket_sum.enabled.help": "このアグリゲーションが有効かどうかを指定します", - "data.search.aggs.metrics.bucket_sum.id.help": "このアグリゲーションのID", - "data.search.aggs.metrics.bucket_sum.json.help": "アグリゲーションがElasticsearchに送信されるときに含める高度なJSON", - "data.search.aggs.metrics.bucket_sum.schema.help": "このアグリゲーションで使用するスキーマ", - "data.search.aggs.metrics.cardinality.customLabel.help": "このアグリゲーションのカスタムラベルを表します", - "data.search.aggs.metrics.cardinality.enabled.help": "このアグリゲーションが有効かどうかを指定します", - "data.search.aggs.metrics.cardinality.field.help": "このアグリゲーションで使用するフィールド", - "data.search.aggs.metrics.cardinality.id.help": "このアグリゲーションのID", - "data.search.aggs.metrics.cardinality.json.help": "アグリゲーションがElasticsearchに送信されるときに含める高度なJSON", - "data.search.aggs.metrics.cardinality.schema.help": "このアグリゲーションで使用するスキーマ", - "data.search.aggs.metrics.count.customLabel.help": "このアグリゲーションのカスタムラベルを表します", - "data.search.aggs.metrics.count.enabled.help": "このアグリゲーションが有効かどうかを指定します", - "data.search.aggs.metrics.count.id.help": "このアグリゲーションのID", - "data.search.aggs.metrics.count.schema.help": "このアグリゲーションで使用するスキーマ", - "data.search.aggs.metrics.countLabel": "カウント", - "data.search.aggs.metrics.countTitle": "カウント", - "data.search.aggs.metrics.cumulative_sum.buckets_path.help": "関心があるメトリックへのパス", - "data.search.aggs.metrics.cumulative_sum.customLabel.help": "このアグリゲーションのカスタムラベルを表します", - "data.search.aggs.metrics.cumulative_sum.customMetric.help": "親パイプラインアグリゲーションを構築するために使用するアグリゲーション構成", - "data.search.aggs.metrics.cumulative_sum.enabled.help": "このアグリゲーションが有効かどうかを指定します", - "data.search.aggs.metrics.cumulative_sum.id.help": "このアグリゲーションのID", - "data.search.aggs.metrics.cumulative_sum.json.help": "アグリゲーションがElasticsearchに送信されるときに含める高度なJSON", - "data.search.aggs.metrics.cumulative_sum.metricAgg.help": "親パイプラインアグリゲーションを構築するために使用するアグリゲーション構成を検索するためのID", - "data.search.aggs.metrics.cumulative_sum.schema.help": "このアグリゲーションで使用するスキーマ", - "data.search.aggs.metrics.cumulativeSumLabel": "累積和", - "data.search.aggs.metrics.cumulativeSumTitle": "累積和", - "data.search.aggs.metrics.derivative.buckets_path.help": "関心があるメトリックへのパス", - "data.search.aggs.metrics.derivative.customLabel.help": "このアグリゲーションのカスタムラベルを表します", - "data.search.aggs.metrics.derivative.customMetric.help": "親パイプラインアグリゲーションを構築するために使用するアグリゲーション構成", - "data.search.aggs.metrics.derivative.enabled.help": "このアグリゲーションが有効かどうかを指定します", - "data.search.aggs.metrics.derivative.id.help": "このアグリゲーションのID", - "data.search.aggs.metrics.derivative.json.help": "アグリゲーションがElasticsearchに送信されるときに含める高度なJSON", - "data.search.aggs.metrics.derivative.metricAgg.help": "親パイプラインアグリゲーションを構築するために使用するアグリゲーション構成を検索するためのID", - "data.search.aggs.metrics.derivative.schema.help": "このアグリゲーションで使用するスキーマ", - "data.search.aggs.metrics.derivativeLabel": "派生", - "data.search.aggs.metrics.derivativeTitle": "派生", - "data.search.aggs.metrics.filtered_metric.customBucket.help": "兄弟パイプラインアグリゲーションを構築するために使用するアグリゲーション構成フィルターアグリゲーションでなければなりません", - "data.search.aggs.metrics.filtered_metric.customLabel.help": "このアグリゲーションのカスタムラベルを表します", - "data.search.aggs.metrics.filtered_metric.customMetric.help": "兄弟パイプラインアグリゲーションを構築するために使用するアグリゲーション構成", - "data.search.aggs.metrics.filtered_metric.enabled.help": "このアグリゲーションが有効かどうかを指定します", - "data.search.aggs.metrics.filtered_metric.id.help": "このアグリゲーションのID", - "data.search.aggs.metrics.filtered_metric.schema.help": "このアグリゲーションで使用するスキーマ", - "data.search.aggs.metrics.filteredMetricLabel": "フィルタリング済み", - "data.search.aggs.metrics.filteredMetricTitle": "フィルタリングされたメトリック", - "data.search.aggs.metrics.geo_bounds.customLabel.help": "このアグリゲーションのカスタムラベルを表します", - "data.search.aggs.metrics.geo_bounds.enabled.help": "このアグリゲーションが有効かどうかを指定します", - "data.search.aggs.metrics.geo_bounds.field.help": "このアグリゲーションで使用するフィールド", - "data.search.aggs.metrics.geo_bounds.id.help": "このアグリゲーションのID", - "data.search.aggs.metrics.geo_bounds.json.help": "アグリゲーションがElasticsearchに送信されるときに含める高度なJSON", - "data.search.aggs.metrics.geo_bounds.schema.help": "このアグリゲーションで使用するスキーマ", - "data.search.aggs.metrics.geo_centroid.customLabel.help": "このアグリゲーションのカスタムラベルを表します", - "data.search.aggs.metrics.geo_centroid.enabled.help": "このアグリゲーションが有効かどうかを指定します", - "data.search.aggs.metrics.geo_centroid.field.help": "このアグリゲーションで使用するフィールド", - "data.search.aggs.metrics.geo_centroid.id.help": "このアグリゲーションのID", - "data.search.aggs.metrics.geo_centroid.json.help": "アグリゲーションがElasticsearchに送信されるときに含める高度なJSON", - "data.search.aggs.metrics.geo_centroid.schema.help": "このアグリゲーションで使用するスキーマ", - "data.search.aggs.metrics.geoBoundsLabel": "境界", - "data.search.aggs.metrics.geoBoundsTitle": "境界", - "data.search.aggs.metrics.geoCentroidLabel": "ジオセントロイド", - "data.search.aggs.metrics.geoCentroidTitle": "ジオセントロイド", - "data.search.aggs.metrics.max.customLabel.help": "このアグリゲーションのカスタムラベルを表します", - "data.search.aggs.metrics.max.enabled.help": "このアグリゲーションが有効かどうかを指定します", - "data.search.aggs.metrics.max.field.help": "このアグリゲーションで使用するフィールド", - "data.search.aggs.metrics.max.id.help": "このアグリゲーションのID", - "data.search.aggs.metrics.max.json.help": "アグリゲーションがElasticsearchに送信されるときに含める高度なJSON", - "data.search.aggs.metrics.max.schema.help": "このアグリゲーションで使用するスキーマ", - "data.search.aggs.metrics.maxBucketTitle": "最高バケット", - "data.search.aggs.metrics.maxLabel": "最高 {field}", - "data.search.aggs.metrics.maxTitle": "最高", - "data.search.aggs.metrics.median.customLabel.help": "このアグリゲーションのカスタムラベルを表します", - "data.search.aggs.metrics.median.enabled.help": "このアグリゲーションが有効かどうかを指定します", - "data.search.aggs.metrics.median.field.help": "このアグリゲーションで使用するフィールド", - "data.search.aggs.metrics.median.id.help": "このアグリゲーションのID", - "data.search.aggs.metrics.median.json.help": "アグリゲーションがElasticsearchに送信されるときに含める高度なJSON", - "data.search.aggs.metrics.median.schema.help": "このアグリゲーションで使用するスキーマ", - "data.search.aggs.metrics.medianLabel": "中央 {field}", - "data.search.aggs.metrics.medianTitle": "中央", - "data.search.aggs.metrics.metricAggregationsSubtypeTitle": "メトリック集約", - "data.search.aggs.metrics.min.customLabel.help": "このアグリゲーションのカスタムラベルを表します", - "data.search.aggs.metrics.min.enabled.help": "このアグリゲーションが有効かどうかを指定します", - "data.search.aggs.metrics.min.field.help": "このアグリゲーションで使用するフィールド", - "data.search.aggs.metrics.min.id.help": "このアグリゲーションのID", - "data.search.aggs.metrics.min.json.help": "アグリゲーションがElasticsearchに送信されるときに含める高度なJSON", - "data.search.aggs.metrics.min.schema.help": "このアグリゲーションで使用するスキーマ", - "data.search.aggs.metrics.minBucketTitle": "最低バケット", - "data.search.aggs.metrics.minLabel": "最低 {field}", - "data.search.aggs.metrics.minTitle": "最低", - "data.search.aggs.metrics.moving_avg.customLabel.help": "このアグリゲーションのカスタムラベルを表します", - "data.search.aggs.metrics.moving_avg.customMetric.help": "親パイプラインアグリゲーションを構築するために使用するアグリゲーション構成", - "data.search.aggs.metrics.moving_avg.enabled.help": "このアグリゲーションが有効かどうかを指定します", - "data.search.aggs.metrics.moving_avg.id.help": "このアグリゲーションのID", - "data.search.aggs.metrics.moving_avg.json.help": "アグリゲーションがElasticsearchに送信されるときに含める高度なJSON", - "data.search.aggs.metrics.moving_avg.metricAgg.help": "親パイプラインアグリゲーションを構築するために使用するアグリゲーション構成を検索するためのID", - "data.search.aggs.metrics.moving_avg.schema.help": "このアグリゲーションで使用するスキーマ", - "data.search.aggs.metrics.moving_avg.script.help": "親パイプラインアグリゲーションを構築するために使用するアグリゲーション構成を検索するためのID", - "data.search.aggs.metrics.moving_avg.window.help": "ヒストグラム全体でスライドするウィンドウのサイズ。", - "data.search.aggs.metrics.movingAvgLabel": "移動平均", - "data.search.aggs.metrics.movingAvgTitle": "移動平均", - "data.search.aggs.metrics.overallAverageLabel": "全体平均", - "data.search.aggs.metrics.overallMaxLabel": "全体最高", - "data.search.aggs.metrics.overallMinLabel": "全体最低", - "data.search.aggs.metrics.overallSumLabel": "全体合計", - "data.search.aggs.metrics.parentPipelineAggregationsSubtypeTitle": "親パイプライン集約", - "data.search.aggs.metrics.percentile_ranks.customLabel.help": "このアグリゲーションのカスタムラベルを表します", - "data.search.aggs.metrics.percentile_ranks.enabled.help": "このアグリゲーションが有効かどうかを指定します", - "data.search.aggs.metrics.percentile_ranks.field.help": "このアグリゲーションで使用するフィールド", - "data.search.aggs.metrics.percentile_ranks.id.help": "このアグリゲーションのID", - "data.search.aggs.metrics.percentile_ranks.json.help": "アグリゲーションがElasticsearchに送信されるときに含める高度なJSON", - "data.search.aggs.metrics.percentile_ranks.schema.help": "このアグリゲーションで使用するスキーマ", - "data.search.aggs.metrics.percentile_ranks.values.help": "パーセンタイル順位の範囲", - "data.search.aggs.metrics.percentileRanks.valuePropsLabel": "「{label}」の {format} のパーセンタイル順位", - "data.search.aggs.metrics.percentileRanksLabel": "{field} のパーセンタイル順位", - "data.search.aggs.metrics.percentileRanksTitle": "パーセンタイル順位", - "data.search.aggs.metrics.percentiles.customLabel.help": "このアグリゲーションのカスタムラベルを表します", - "data.search.aggs.metrics.percentiles.enabled.help": "このアグリゲーションが有効かどうかを指定します", - "data.search.aggs.metrics.percentiles.field.help": "このアグリゲーションで使用するフィールド", - "data.search.aggs.metrics.percentiles.id.help": "このアグリゲーションのID", - "data.search.aggs.metrics.percentiles.json.help": "アグリゲーションがElasticsearchに送信されるときに含める高度なJSON", - "data.search.aggs.metrics.percentiles.percents.help": "パーセンタイル順位の範囲", - "data.search.aggs.metrics.percentiles.schema.help": "このアグリゲーションで使用するスキーマ", - "data.search.aggs.metrics.percentiles.valuePropsLabel": "{label} の {percentile} パーセンタイル", - "data.search.aggs.metrics.percentilesLabel": "{field} のパーセンタイル", - "data.search.aggs.metrics.percentilesTitle": "パーセンタイル", - "data.search.aggs.metrics.serial_diff.buckets_path.help": "関心があるメトリックへのパス", - "data.search.aggs.metrics.serial_diff.customLabel.help": "このアグリゲーションのカスタムラベルを表します", - "data.search.aggs.metrics.serial_diff.customMetric.help": "親パイプラインアグリゲーションを構築するために使用するアグリゲーション構成", - "data.search.aggs.metrics.serial_diff.enabled.help": "このアグリゲーションが有効かどうかを指定します", - "data.search.aggs.metrics.serial_diff.id.help": "このアグリゲーションのID", - "data.search.aggs.metrics.serial_diff.json.help": "アグリゲーションがElasticsearchに送信されるときに含める高度なJSON", - "data.search.aggs.metrics.serial_diff.metricAgg.help": "親パイプラインアグリゲーションを構築するために使用するアグリゲーション構成を検索するためのID", - "data.search.aggs.metrics.serial_diff.schema.help": "このアグリゲーションで使用するスキーマ", - "data.search.aggs.metrics.serialDiffLabel": "差分の推移", - "data.search.aggs.metrics.serialDiffTitle": "差分の推移", - "data.search.aggs.metrics.siblingPipelineAggregationsSubtypeTitle": "シブリングパイプラインアグリゲーション", - "data.search.aggs.metrics.singlePercentile.customLabel.help": "このアグリゲーションのカスタムラベルを表します", - "data.search.aggs.metrics.singlePercentile.enabled.help": "このアグリゲーションが有効かどうかを指定します", - "data.search.aggs.metrics.singlePercentile.field.help": "このアグリゲーションで使用するフィールド", - "data.search.aggs.metrics.singlePercentile.id.help": "このアグリゲーションのID", - "data.search.aggs.metrics.singlePercentile.json.help": "アグリゲーションがElasticsearchに送信されるときに含める高度なJSON", - "data.search.aggs.metrics.singlePercentile.percentile.help": "取得するパーセンタイル", - "data.search.aggs.metrics.singlePercentile.schema.help": "このアグリゲーションで使用するスキーマ", - "data.search.aggs.metrics.singlePercentileLabel": "パーセンタイル{field}", - "data.search.aggs.metrics.singlePercentileTitle": "パーセンタイル", - "data.search.aggs.metrics.standardDeviation.keyDetailsLabel": "{fieldDisplayName} の標準偏差", - "data.search.aggs.metrics.standardDeviation.lowerKeyDetailsTitle": "下の{label}", - "data.search.aggs.metrics.standardDeviation.upperKeyDetailsTitle": "上の{label}", - "data.search.aggs.metrics.standardDeviationLabel": "{field} の標準偏差", - "data.search.aggs.metrics.standardDeviationTitle": "標準偏差", - "data.search.aggs.metrics.std_deviation.customLabel.help": "このアグリゲーションのカスタムラベルを表します", - "data.search.aggs.metrics.std_deviation.enabled.help": "このアグリゲーションが有効かどうかを指定します", - "data.search.aggs.metrics.std_deviation.field.help": "このアグリゲーションで使用するフィールド", - "data.search.aggs.metrics.std_deviation.id.help": "このアグリゲーションのID", - "data.search.aggs.metrics.std_deviation.json.help": "アグリゲーションがElasticsearchに送信されるときに含める高度なJSON", - "data.search.aggs.metrics.std_deviation.schema.help": "このアグリゲーションで使用するスキーマ", - "data.search.aggs.metrics.sum.customLabel.help": "このアグリゲーションのカスタムラベルを表します", - "data.search.aggs.metrics.sum.enabled.help": "このアグリゲーションが有効かどうかを指定します", - "data.search.aggs.metrics.sum.field.help": "このアグリゲーションで使用するフィールド", - "data.search.aggs.metrics.sum.id.help": "このアグリゲーションのID", - "data.search.aggs.metrics.sum.json.help": "アグリゲーションがElasticsearchに送信されるときに含める高度なJSON", - "data.search.aggs.metrics.sum.schema.help": "このアグリゲーションで使用するスキーマ", - "data.search.aggs.metrics.sumBucketTitle": "合計バケット", - "data.search.aggs.metrics.sumLabel": "{field} の合計", - "data.search.aggs.metrics.sumTitle": "合計", - "data.search.aggs.metrics.timeShift.help": "設定した時間の分だけメトリックの時間範囲をシフトします。例:1時間、7日。[前へ]は日付ヒストグラムまたは時間範囲フィルターから最も近い時間範囲を使用します。", - "data.search.aggs.metrics.top_hit.aggregate.help": "アグリゲーションタイプ", - "data.search.aggs.metrics.top_hit.customLabel.help": "このアグリゲーションのカスタムラベルを表します", - "data.search.aggs.metrics.top_hit.enabled.help": "このアグリゲーションが有効かどうかを指定します", - "data.search.aggs.metrics.top_hit.field.help": "このアグリゲーションで使用するフィールド", - "data.search.aggs.metrics.top_hit.id.help": "このアグリゲーションのID", - "data.search.aggs.metrics.top_hit.json.help": "アグリゲーションがElasticsearchに送信されるときに含める高度なJSON", - "data.search.aggs.metrics.top_hit.schema.help": "このアグリゲーションで使用するスキーマ", - "data.search.aggs.metrics.top_hit.size.help": "取得するバケットの最大数", - "data.search.aggs.metrics.top_hit.sortField.help": "結果を並べ替える基準のフィールド", - "data.search.aggs.metrics.top_hit.sortOrder.help": "結果を返す順序:昇順または降順", - "data.search.aggs.metrics.topHit.ascendingLabel": "昇順", - "data.search.aggs.metrics.topHit.averageLabel": "平均", - "data.search.aggs.metrics.topHit.concatenateLabel": "連結", - "data.search.aggs.metrics.topHit.descendingLabel": "降順", - "data.search.aggs.metrics.topHit.firstPrefixLabel": "最初", - "data.search.aggs.metrics.topHit.lastPrefixLabel": "最後", - "data.search.aggs.metrics.topHit.maxLabel": "最高", - "data.search.aggs.metrics.topHit.minLabel": "最低", - "data.search.aggs.metrics.topHit.sumLabel": "合計", - "data.search.aggs.metrics.topHitTitle": "トップヒット", - "data.search.aggs.metrics.uniqueCountLabel": "{field} のユニークカウント", - "data.search.aggs.metrics.uniqueCountTitle": "ユニークカウント", - "data.search.aggs.otherBucket.labelForMissingValuesLabel": "欠測値のラベル", - "data.search.aggs.otherBucket.labelForOtherBucketLabel": "他のバケットのラベル", - "data.search.aggs.paramTypes.field.invalidSavedFieldParameterErrorMessage": "「{aggType}」アグリゲーションで使用するには、インデックスパターン「{indexPatternTitle}」の保存されたフィールド「{fieldParameter}」が無効です。新しいフィールドを選択してください。", - "data.search.aggs.paramTypes.field.notFoundSavedFieldParameterErrorMessage": "このオブジェクトに関連付けられたフィールド\"{fieldParameter}\"は、インデックスパターンに存在しません。別のフィールドを使用してください。", - "data.search.aggs.paramTypes.field.requiredFieldParameterErrorMessage": "{fieldParameter} は必須パラメーターです", - "data.search.aggs.percentageOfLabel": "{label} の割合", - "data.search.aggs.string.customLabel": "カスタムラベル", - "data.search.dataRequest.title": "データ", - "data.search.es_search.dataRequest.description": "このリクエストはElasticsearchにクエリし、ビジュアライゼーション用のデータを取得します。", - "data.search.es_search.hitsDescription": "クエリにより返されたドキュメントの数です。", - "data.search.es_search.hitsLabel": "ヒット数", - "data.search.es_search.hitsTotalDescription": "クエリに一致するドキュメントの数です。", - "data.search.es_search.hitsTotalLabel": "ヒット数(合計)", - "data.search.es_search.indexPatternDescription": "Elasticsearchインデックスに接続したインデックスパターンです。", - "data.search.es_search.queryTimeDescription": "クエリの処理の所要時間です。リクエストの送信やブラウザーでのパースの時間は含まれません。", - "data.search.es_search.queryTimeLabel": "クエリ時間", - "data.search.es_search.queryTimeValue": "{queryTime}ms", - "data.search.esaggs.error.kibanaRequest": "サーバーでこの検索を実行するには、KibanaRequest が必要です。式実行パラメーターに要求オブジェクトを渡してください。", - "data.search.esdsl.help": "Elasticsearch リクエストを実行", - "data.search.esdsl.index.help": "クエリするElasticsearchインデックス", - "data.search.esdsl.q.help": "クエリDSL", - "data.search.esdsl.size.help": "Elasticsearch 検索 API サイズパラメーター", - "data.search.esErrorTitle": "検索結果を取得できません", - "data.search.functions.cidr.cidr.help": "CIDRブロックを指定", - "data.search.functions.cidr.help": "CIDRに基づく範囲を作成", - "data.search.functions.dateRange.from.help": "開始日を指定", - "data.search.functions.dateRange.help": "日付範囲を作成", - "data.search.functions.dateRange.to.help": "終了日を指定", - "data.search.functions.esaggs.aggConfigs.help": "agg_type 関数で構成されたアグリゲーションのリスト", - "data.search.functions.esaggs.index.help": "indexPatternLoad で取得されたインデックスパターン", - "data.search.functions.esaggs.metricsAtAllLevels.help": "各バケットレベルでメトリックがある列が含まれるかどうか", - "data.search.functions.esaggs.partialRows.help": "一部のデータのみを含む行を返すかどうか", - "data.search.functions.esaggs.timeFields.help": "クエリに対して解決された時間範囲を取得する時刻フィールドを指定します", - "data.search.functions.existsFilter.field.help": "フィルタリングするフィールドを指定します。「field」関数を使用します。", - "data.search.functions.existsFilter.help": "Kibana existsフィルターを作成", - "data.search.functions.existsFilter.negate.help": "フィルターは否定でなければなりません。", - "data.search.functions.extendedBounds.help": "予想バウンドを作成", - "data.search.functions.extendedBounds.max.help": "上限値を指定", - "data.search.functions.extendedBounds.min.help": "下限値を指定", - "data.search.functions.field.help": "Kibanaフィールドを作成します。", - "data.search.functions.field.name.help": "フィールドの名前です", - "data.search.functions.field.script.help": "フィールドがスクリプト化されている場合はフィールドスクリプト。", - "data.search.functions.field.type.help": "フィールド型", - "data.search.functions.geoBoundingBox.arguments.error": "次のパラメーターのグループの1つ以上を指定する必要があります:{parameters}。", - "data.search.functions.geoBoundingBox.bottom_left.help": "左下角を指定", - "data.search.functions.geoBoundingBox.bottom_right.help": "右下角を指定", - "data.search.functions.geoBoundingBox.bottom.help": "下座標を指定", - "data.search.functions.geoBoundingBox.help": "ジオバウンディングボックスを作成", - "data.search.functions.geoBoundingBox.left.help": "左座標を指定", - "data.search.functions.geoBoundingBox.right.help": "右座標を指定", - "data.search.functions.geoBoundingBox.top_left.help": "左上角を指定", - "data.search.functions.geoBoundingBox.top_right.help": "右上角を指定", - "data.search.functions.geoBoundingBox.top.help": "上座標を指定", - "data.search.functions.geoBoundingBox.wkt.help": "よく知られたテキスト(WKT)を指定", - "data.search.functions.geoPoint.arguments.error": "「緯度」、「経度」、または「ポイント」パラメーターを指定してください。", - "data.search.functions.geoPoint.help": "地理ポイントを作成", - "data.search.functions.geoPoint.lat.help": "緯度を指定", - "data.search.functions.geoPoint.lon.help": "経度を指定", - "data.search.functions.geoPoint.point.error": "ポイントパラメーターは文字列または2つの数値にしてください。", - "data.search.functions.geoPoint.point.help": "カンマ区切りの座標が付いた文字列または2つの数値としてポイントを指定", - "data.search.functions.ipRange.from.help": "開始アドレスを指定", - "data.search.functions.ipRange.help": "IP範囲を作成", - "data.search.functions.ipRange.to.help": "終了アドレスを指定", - "data.search.functions.kibana_context.filters.help": "Kibana ジェネリックフィルターを指定します", - "data.search.functions.kibana_context.help": "Kibana グローバルコンテキストを更新します", - "data.search.functions.kibana_context.q.help": "自由形式の Kibana テキストクエリを指定します", - "data.search.functions.kibana_context.savedSearchId.help": "クエリとフィルターに使用する保存検索ID を指定します。", - "data.search.functions.kibana_context.timeRange.help": "Kibana 時間範囲フィルターを指定します", - "data.search.functions.kibana.help": "Kibana グローバルコンテキストを取得します", - "data.search.functions.kibanaFilter.disabled.help": "フィルターは無効でなければなりません", - "data.search.functions.kibanaFilter.field.help": "フリーフォームesdslクエリを指定", - "data.search.functions.kibanaFilter.help": "Kibanaフィルターを作成", - "data.search.functions.kibanaFilter.negate.help": "フィルターは否定でなければなりません", - "data.search.functions.kql.help": "Kibana kqlクエリ", - "data.search.functions.kql.q.help": "Kibana KQLフリーフォームテキストクエリを指定", - "data.search.functions.lucene.help": "Kibana Luceneクエリを作成", - "data.search.functions.lucene.q.help": "Kibanaフリーフォームテキストクエリを指定", - "data.search.functions.numericalRange.from.help": "開始値を指定", - "data.search.functions.numericalRange.help": "数値範囲を作成", - "data.search.functions.numericalRange.label.help": "範囲ラベルを指定", - "data.search.functions.numericalRange.to.help": "終了値を指定", - "data.search.functions.phraseFilter.field.help": "フィルタリングするフィールドを指定します。「field」関数を使用します。", - "data.search.functions.phraseFilter.help": "Kibanaフレーズまたはフレーズフィルターを作成", - "data.search.functions.phraseFilter.negate.help": "フィルターは否定でなければなりません", - "data.search.functions.phraseFilter.phrase.help": "フレーズを指定", - "data.search.functions.queryFilter.help": "クエリフィルターを作成", - "data.search.functions.queryFilter.input.help": "クエリフィルターを指定", - "data.search.functions.queryFilter.label.help": "フィルターラベルを指定", - "data.search.functions.range.gt.help": "より大きい", - "data.search.functions.range.gte.help": "以上", - "data.search.functions.range.help": "Kibana範囲フィルターを作成", - "data.search.functions.range.lt.help": "より小さい", - "data.search.functions.range.lte.help": "以下", - "data.search.functions.rangeFilter.field.help": "フィルタリングするフィールドを指定します。「field」関数を使用します。", - "data.search.functions.rangeFilter.help": "Kibana範囲フィルターを作成", - "data.search.functions.rangeFilter.negate.help": "フィルターは否定でなければなりません", - "data.search.functions.rangeFilter.range.help": "範囲を指定し、「range」関数を使用します。", - "data.search.functions.timerange.from.help": "開始日を指定", - "data.search.functions.timerange.help": "Kibana timerangeを作成", - "data.search.functions.timerange.mode.help": "モードを指定(絶対または相対)", - "data.search.functions.timerange.to.help": "終了日を指定", - "data.search.httpErrorTitle": "データを取得できません", - "data.search.searchBar.savedQueryDescriptionLabelText": "説明", - "data.search.searchBar.savedQueryDescriptionText": "再度使用するクエリテキストとフィルターを保存します。", - "data.search.searchBar.savedQueryForm.titleConflictText": "タイトルがすでに保存されているクエリに使用されています", - "data.search.searchBar.savedQueryFormCancelButtonText": "キャンセル", - "data.search.searchBar.savedQueryFormSaveButtonText": "保存", - "data.search.searchBar.savedQueryFormTitle": "クエリを保存", - "data.search.searchBar.savedQueryIncludeFiltersLabelText": "フィルターを含める", - "data.search.searchBar.savedQueryIncludeTimeFilterLabelText": "時間フィルターを含める", - "data.search.searchBar.savedQueryNameHelpText": "名前が必要です。タイトルの始めと終わりにはスペースを使用できません。名前は固有でなければなりません。", - "data.search.searchBar.savedQueryNameLabelText": "名前", - "data.search.searchBar.savedQueryNoSavedQueriesText": "保存されたクエリがありません。", - "data.search.searchBar.savedQueryPopoverButtonText": "保存されたクエリを表示", - "data.search.searchBar.savedQueryPopoverClearButtonAriaLabel": "現在保存されているクエリを消去", - "data.search.searchBar.savedQueryPopoverClearButtonText": "クリア", - "data.search.searchBar.savedQueryPopoverConfirmDeletionCancelButtonText": "キャンセル", - "data.search.searchBar.savedQueryPopoverConfirmDeletionConfirmButtonText": "削除", - "data.search.searchBar.savedQueryPopoverConfirmDeletionTitle": "「{savedQueryName}」を削除しますか?", - "data.search.searchBar.savedQueryPopoverDeleteButtonAriaLabel": "保存されたクエリ {savedQueryName} を削除", - "data.search.searchBar.savedQueryPopoverSaveAsNewButtonAriaLabel": "新規保存クエリを保存", - "data.search.searchBar.savedQueryPopoverSaveAsNewButtonText": "新規保存", - "data.search.searchBar.savedQueryPopoverSaveButtonAriaLabel": "新規保存クエリを保存", - "data.search.searchBar.savedQueryPopoverSaveButtonText": "現在のクエリを保存", - "data.search.searchBar.savedQueryPopoverSaveChangesButtonAriaLabel": "{title} への変更を保存", - "data.search.searchBar.savedQueryPopoverSaveChangesButtonText": "変更を保存", - "data.search.searchBar.savedQueryPopoverSavedQueryListItemButtonAriaLabel": "保存クエリボタン {savedQueryName}", - "data.search.searchBar.savedQueryPopoverSavedQueryListItemDescriptionAriaLabel": "{savedQueryName}の説明", - "data.search.searchBar.savedQueryPopoverSavedQueryListItemSelectedButtonAriaLabel": "選択されたクエリボタン {savedQueryName} を保存しました。変更を破棄するには押してください。", - "data.search.searchBar.savedQueryPopoverTitleText": "保存されたクエリ", - "data.search.searchSource.fetch.requestTimedOutNotificationMessage": "リクエストがタイムアウトしたため、データが不完全な可能性があります", - "data.search.searchSource.fetch.shardsFailedModal.close": "閉じる", - "data.search.searchSource.fetch.shardsFailedModal.copyToClipboard": "応答をクリップボードにコピー", - "data.search.searchSource.fetch.shardsFailedModal.failureHeader": "{failureName} at {failureDetails}", - "data.search.searchSource.fetch.shardsFailedModal.showDetails": "詳細を表示", - "data.search.searchSource.fetch.shardsFailedModal.tabHeaderRequest": "リクエスト", - "data.search.searchSource.fetch.shardsFailedModal.tabHeaderResponse": "応答", - "data.search.searchSource.fetch.shardsFailedModal.tabHeaderShardFailures": "シャードエラー", - "data.search.searchSource.fetch.shardsFailedModal.tableColIndex": "インデックス", - "data.search.searchSource.fetch.shardsFailedModal.tableColNode": "ノード", - "data.search.searchSource.fetch.shardsFailedModal.tableColReason": "理由", - "data.search.searchSource.fetch.shardsFailedModal.tableColShard": "シャード", - "data.search.searchSource.fetch.shardsFailedModal.tableRowCollapse": "{rowDescription}を折りたたむ", - "data.search.searchSource.fetch.shardsFailedModal.tableRowExpand": "{rowDescription}を展開する", - "data.search.searchSource.fetch.shardsFailedNotificationDescription": "表示されているデータは不完全か誤りの可能性があります。", - "data.search.searchSource.fetch.shardsFailedNotificationMessage": "{shardsTotal} 件中 {shardsFailed} 件のシャードでエラーが発生しました", - "data.search.searchSource.hitsDescription": "クエリにより返されたドキュメントの数です。", - "data.search.searchSource.hitsLabel": "ヒット数", - "data.search.searchSource.hitsTotalDescription": "クエリに一致するドキュメントの数です。", - "data.search.searchSource.hitsTotalLabel": "ヒット数(合計)", - "data.search.searchSource.indexPatternIdDescription": "{kibanaIndexPattern} インデックス内の ID です。", - "data.search.searchSource.queryTimeDescription": "クエリの処理の所要時間です。リクエストの送信やブラウザーでのパースの時間は含まれません。", - "data.search.searchSource.queryTimeLabel": "クエリ時間", - "data.search.searchSource.queryTimeValue": "{queryTime}ms", - "data.search.searchSource.requestTimeDescription": "ブラウザから Elasticsearch にリクエストが送信され返されるまでの所要時間です。リクエストがキューで待機していた時間は含まれません。", - "data.search.searchSource.requestTimeLabel": "リクエスト時間", - "data.search.searchSource.requestTimeValue": "{requestTime}ms", - "data.search.timeBuckets.infinityLabel": "1年を超える", - "data.search.timeBuckets.monthLabel": "1か月", - "data.search.timeBuckets.yearLabel": "1年", - "data.search.timeoutContactAdmin": "クエリがタイムアウトしました。実行時間を延長するには、システム管理者に問い合わせてください。", - "data.search.timeoutIncreaseSetting": "クエリがタイムアウトしました。検索タイムアウト詳細設定で実行時間を延長します。", - "data.search.timeoutIncreaseSettingActionText": "設定を編集", - "data.search.unableToGetSavedQueryToastTitle": "保存したクエリ {savedQueryId} を読み込めません", - "data.searchSession.warning.readDocs": "続きを読む", - "data.searchSessionIndicator.noCapability": "検索セッションを作成するアクセス権がありません。", - "data.searchSessions.sessionService.sessionEditNameError": "検索セッションの名前を編集できませんでした", - "data.searchSessions.sessionService.sessionObjectFetchError": "検索セッション情報を取得できませんでした", - "data.triggers.applyFilterDescription": "Kibanaフィルターが適用されるとき。単一の値または範囲フィルターにすることができます。", - "data.triggers.applyFilterTitle": "フィルターを適用", - "dataViews.ensureDefaultIndexPattern.bannerLabel": "Kibanaでデータの可視化と閲覧を行うには、Elasticsearchからデータを取得するためのインデックスパターンの作成が必要です。", - "dataViews.fetchFieldErrorTitle": "インデックスパターンのフィールド取得中にエラーが発生 {title}(ID:{id})", - "dataViews.indexPatternLoad.error.kibanaRequest": "サーバーでこの検索を実行するには、KibanaRequest が必要です。式実行パラメーターに要求オブジェクトを渡してください。", - "dataViews.unableWriteLabel": "インデックスパターンを書き込めません。このインデックスパターンへの最新の変更を取得するには、ページを更新してください。", - "devTools.badge.readOnly.text": "読み取り専用", - "devTools.badge.readOnly.tooltip": "を保存できませんでした", - "devTools.devToolsTitle": "開発ツール", - "discover.advancedSettings.context.defaultSizeText": "コンテキストビューに表示される周りのエントリーの数", - "discover.advancedSettings.context.defaultSizeTitle": "コンテキストサイズ", - "discover.advancedSettings.context.sizeStepText": "コンテキストサイズを増減させる際の最低単位です", - "discover.advancedSettings.context.sizeStepTitle": "コンテキストサイズのステップ", - "discover.advancedSettings.context.tieBreakerFieldsTitle": "タイブレーカーフィールド", - "discover.advancedSettings.defaultColumnsText": "デフォルトで Discover タブに表示される列です", - "discover.advancedSettings.defaultColumnsTitle": "デフォルトの列", - "discover.advancedSettings.discover.multiFieldsLinkText": "マルチフィールド", - "discover.advancedSettings.discover.readFieldsFromSource": "_sourceからフィールドを読み取る", - "discover.advancedSettings.discover.readFieldsFromSourceDescription": "有効にすると、「_source」から直接ドキュメントを読み込みます。これはまもなく廃止される予定です。無効にすると、上位レベルの検索サービスで新しいフィールドAPI経由でフィールドを取得します。", - "discover.advancedSettings.discover.showMultifields": "マルチフィールドを表示", - "discover.advancedSettings.discover.showMultifieldsDescription": "拡張ドキュメントビューに{multiFields}が表示されるかどうかを制御します。ほとんどの場合、マルチフィールドは元のフィールドと同じです。「searchFieldsFromSource」がオフのときにのみこのオプションを使用できます。", - "discover.advancedSettings.docTableHideTimeColumnText": "Discover と、ダッシュボードのすべての保存された検索で、「時刻」列を非表示にします。", - "discover.advancedSettings.docTableHideTimeColumnTitle": "「時刻」列を非表示", - "discover.advancedSettings.fieldsPopularLimitText": "最も頻繁に使用されるフィールドのトップNを表示します", - "discover.advancedSettings.fieldsPopularLimitTitle": "頻繁に使用されるフィールドの制限", - "discover.advancedSettings.maxDocFieldsDisplayedText": "ドキュメント列でレンダリングされたフィールドの最大数", - "discover.advancedSettings.maxDocFieldsDisplayedTitle": "表示される最大ドキュメントフィールド数", - "discover.advancedSettings.sampleSizeText": "表に表示する行数です", - "discover.advancedSettings.sampleSizeTitle": "行数", - "discover.advancedSettings.searchOnPageLoadText": "Discover の最初の読み込み時に検索を実行するかを制御します。この設定は、保存された検索の読み込み時には影響しません。", - "discover.advancedSettings.searchOnPageLoadTitle": "ページの読み込み時の検索", - "discover.advancedSettings.sortDefaultOrderTitle": "デフォルトの並べ替え方向", - "discover.advancedSettings.sortOrderAsc": "昇順", - "discover.advancedSettings.sortOrderDesc": "降順", - "discover.advancedSettings.params.maxCellHeightTitle": "表のセルの高さの上限", - "discover.advancedSettings.params.maxCellHeightText": "表のセルが使用する高さの上限です。この切り捨てを無効にするには0に設定します", - "discover.backToTopLinkText": "最上部へ戻る。", - "discover.badge.readOnly.text": "読み取り専用", - "discover.badge.readOnly.tooltip": "検索を保存できません", - "discover.bucketIntervalTooltip": "この間隔は選択された時間範囲に表示される{bucketsDescription}が作成されるため、{bucketIntervalDescription}にスケーリングされています。", - "discover.bucketIntervalTooltip.tooLargeBucketsText": "大きすぎるバケット", - "discover.bucketIntervalTooltip.tooManyBucketsText": "バケットが多すぎます", - "discover.clearSelection": "選択した項目をクリア", - "discover.context.breadcrumb": "周りのドキュメント", - "discover.context.contextOfTitle": "#{anchorId}の周りのドキュメント", - "discover.context.failedToLoadAnchorDocumentDescription": "アンカードキュメントの読み込みに失敗しました", - "discover.context.failedToLoadAnchorDocumentErrorDescription": "アンカードキュメントの読み込みに失敗しました。", - "discover.context.invalidTieBreakerFiledSetting": "無効なタイブレーカーフィールド設定", - "discover.context.loadButtonLabel": "読み込み", - "discover.context.loadingDescription": "読み込み中...", - "discover.context.newerDocumentsAriaLabel": "新しいドキュメントの数", - "discover.context.newerDocumentsDescription": "新しいドキュメント", - "discover.context.newerDocumentsWarning": "アンカーよりも新しいドキュメントは{docCount}件しか見つかりませんでした。", - "discover.context.newerDocumentsWarningZero": "アンカーよりも新しいドキュメントは見つかりませんでした。", - "discover.context.olderDocumentsAriaLabel": "古いドキュメントの数", - "discover.context.olderDocumentsDescription": "古いドキュメント", - "discover.context.olderDocumentsWarning": "アンカーよりも古いドキュメントは{docCount}件しか見つかりませんでした。", - "discover.context.olderDocumentsWarningZero": "アンカーよりも古いドキュメントは見つかりませんでした。", - "discover.context.reloadPageDescription.reloadOrVisitTextMessage": "ドキュメントリストを再読み込みするか、ドキュメントリストに戻り、有効なアンカードキュメントを選択してください。", - "discover.context.unableToLoadAnchorDocumentDescription": "アンカードキュメントを読み込めません", - "discover.context.unableToLoadDocumentDescription": "ドキュメントを読み込めません", - "discover.controlColumnHeader": "列の制御", - "discover.copyToClipboardJSON": "ドキュメントをクリップボードにコピー(JSON)", - "discover.discoverBreadcrumbTitle": "Discover", - "discover.discoverDefaultSearchSessionName": "Discover", - "discover.discoverDescription": "ドキュメントにクエリをかけたりフィルターを適用することで、データをインタラクティブに閲覧できます。", - "discover.discoverSubtitle": "インサイトを検索して見つけます。", - "discover.discoverTitle": "Discover", - "discover.doc.couldNotFindDocumentsDescription": "そのIDに一致するドキュメントがありません。", - "discover.doc.failedToExecuteQueryDescription": "検索の実行に失敗しました", - "discover.doc.failedToLocateDocumentDescription": "ドキュメントが見つかりませんでした", - "discover.doc.loadingDescription": "読み込み中…", - "discover.doc.somethingWentWrongDescription": "{indexName}が見つかりません。", - "discover.doc.somethingWentWrongDescriptionAddon": "インデックスが存在することを確認してください。", - "discover.docTable.documentsNavigation": "ドキュメントナビゲーション", - "discover.docTable.limitedSearchResultLabel": "{resultCount}件の結果のみが表示されます。検索結果を絞り込みます。", - "discover.docTable.noResultsTitle": "結果が見つかりませんでした", - "discover.docTable.rows": "行", - "discover.docTable.tableHeader.documentHeader": "ドキュメント", - "discover.docTable.tableHeader.moveColumnLeftButtonAriaLabel": "{columnName}列を左に移動", - "discover.docTable.tableHeader.moveColumnLeftButtonTooltip": "列を左に移動", - "discover.docTable.tableHeader.moveColumnRightButtonAriaLabel": "{columnName}列を右に移動", - "discover.docTable.tableHeader.moveColumnRightButtonTooltip": "列を右に移動", - "discover.docTable.tableHeader.removeColumnButtonAriaLabel": "{columnName}列を削除", - "discover.docTable.tableHeader.removeColumnButtonTooltip": "列の削除", - "discover.docTable.tableHeader.sortByColumnAscendingAriaLabel": "{columnName}を昇順に並べ替える", - "discover.docTable.tableHeader.sortByColumnDescendingAriaLabel": "{columnName}を降順に並べ替える", - "discover.docTable.tableHeader.sortByColumnUnsortedAriaLabel": "{columnName}で並べ替えを止める", - "discover.docTable.tableRow.detailHeading": "拡張ドキュメント", - "discover.docTable.tableRow.filterForValueButtonAriaLabel": "値でフィルター", - "discover.docTable.tableRow.filterForValueButtonTooltip": "値でフィルター", - "discover.docTable.tableRow.filterOutValueButtonAriaLabel": "値を除外", - "discover.docTable.tableRow.filterOutValueButtonTooltip": "値を除外", - "discover.docTable.tableRow.toggleRowDetailsButtonAriaLabel": "行の詳細を切り替える", - "discover.docTable.tableRow.viewSingleDocumentLinkText": "単一のドキュメントを表示", - "discover.docTable.tableRow.viewSurroundingDocumentsLinkText": "周りのドキュメントを表示", - "discover.docTable.totalDocuments": "{totalDocuments}ドキュメント", - "discover.documentsAriaLabel": "ドキュメント", - "discover.docViews.json.jsonTitle": "JSON", - "discover.docViews.table.filterForFieldPresentButtonAriaLabel": "フィールド表示のフィルター", - "discover.docViews.table.filterForFieldPresentButtonTooltip": "フィールド表示のフィルター", - "discover.docViews.table.filterForValueButtonAriaLabel": "値でフィルター", - "discover.docViews.table.filterForValueButtonTooltip": "値でフィルター", - "discover.docViews.table.filterOutValueButtonAriaLabel": "値を除外", - "discover.docViews.table.filterOutValueButtonTooltip": "値を除外", - "discover.docViews.table.scoreSortWarningTooltip": "_scoreの値を取得するには、並べ替える必要があります。", - "discover.docViews.table.tableTitle": "表", - "discover.docViews.table.toggleColumnInTableButtonAriaLabel": "表の列を切り替える", - "discover.docViews.table.toggleColumnInTableButtonTooltip": "表の列を切り替える", - "discover.docViews.table.toggleFieldDetails": "フィールド詳細を切り替える", - "discover.docViews.table.unableToFilterForPresenceOfMetaFieldsTooltip": "メタフィールドの有無でフィルタリングできません", - "discover.docViews.table.unableToFilterForPresenceOfScriptedFieldsTooltip": "スクリプトフィールドの有無でフィルタリングできません", - "discover.embeddable.inspectorRequestDataTitle": "データ", - "discover.embeddable.inspectorRequestDescription": "このリクエストはElasticsearchにクエリをかけ、検索データを取得します。", - "discover.embeddable.search.displayName": "検索", - "discover.field.mappingConflict": "このフィールドは、このパターンと一致するインデックス全体に対して複数の型(文字列、整数など)として定義されています。この競合フィールドを使用することはできますが、Kibana で型を認識する必要がある関数では使用できません。この問題を修正するにはデータのレンダリングが必要です。", - "discover.field.mappingConflict.title": "マッピングの矛盾", - "discover.field.title": "{fieldName} ({fieldDisplayName})", - "discover.fieldChooser.detailViews.emptyStringText": "空の文字列", - "discover.fieldChooser.detailViews.existsInRecordsText": "{value} / {totalValue}件のレコードに存在", - "discover.fieldChooser.detailViews.filterOutValueButtonAriaLabel": "{field}を除外:\"{value}\"", - "discover.fieldChooser.detailViews.filterValueButtonAriaLabel": "{field}を除外:\"{value}\"", - "discover.fieldChooser.detailViews.valueOfRecordsText": "{value} / {totalValue}件のレコード", - "discover.fieldChooser.discoverField.actions": "アクション", - "discover.fieldChooser.discoverField.addButtonAriaLabel": "{field}を表に追加", - "discover.fieldChooser.discoverField.addFieldTooltip": "フィールドを列として追加", - "discover.fieldChooser.discoverField.fieldTopValuesLabel": "トップ5の値", - "discover.fieldChooser.discoverField.multiField": "複数フィールド", - "discover.fieldChooser.discoverField.multiFields": "マルチフィールド", - "discover.fieldChooser.discoverField.multiFieldTooltipContent": "複数フィールドにはフィールドごとに複数の値を入力できます", - "discover.fieldChooser.discoverField.name": "フィールド", - "discover.fieldChooser.discoverField.removeButtonAriaLabel": "{field}を表から削除", - "discover.fieldChooser.discoverField.removeFieldTooltip": "フィールドを表から削除", - "discover.fieldChooser.discoverField.value": "値", - "discover.fieldChooser.fieldCalculator.analysisIsNotAvailableForGeoFieldsErrorMessage": "ジオフィールドは分析できません。", - "discover.fieldChooser.fieldCalculator.analysisIsNotAvailableForObjectFieldsErrorMessage": "オブジェクトフィールドは分析できません。", - "discover.fieldChooser.fieldCalculator.fieldIsNotPresentInDocumentsErrorMessage": "このフィールドはElasticsearchマッピングに表示されますが、ドキュメントテーブルの{hitsLength}件のドキュメントには含まれません。可視化や検索は可能な場合があります。", - "discover.fieldChooser.fieldFilterButtonLabel": "タイプでフィルタリング", - "discover.fieldChooser.fieldsMobileButtonLabel": "フィールド", - "discover.fieldChooser.filter.aggregatableLabel": "集約可能", - "discover.fieldChooser.filter.availableFieldsTitle": "利用可能なフィールド", - "discover.fieldChooser.filter.fieldSelectorLabel": "{id}フィルターオプションの選択", - "discover.fieldChooser.filter.filterByTypeLabel": "タイプでフィルタリング", - "discover.fieldChooser.filter.indexAndFieldsSectionAriaLabel": "インデックスとフィールド", - "discover.fieldChooser.filter.popularTitle": "人気", - "discover.fieldChooser.filter.searchableLabel": "検索可能", - "discover.fieldChooser.filter.selectedFieldsTitle": "スクリプトフィールド", - "discover.fieldChooser.filter.toggleButton.any": "すべて", - "discover.fieldChooser.filter.toggleButton.no": "いいえ", - "discover.fieldChooser.filter.toggleButton.yes": "はい", - "discover.fieldChooser.filter.typeLabel": "型", - "discover.fieldChooser.searchPlaceHolder": "検索フィールド名", - "discover.fieldChooser.toggleFieldFilterButtonHideAriaLabel": "フィールド設定を非表示", - "discover.fieldChooser.toggleFieldFilterButtonShowAriaLabel": "フィールド設定を表示", - "discover.fieldChooser.visualizeButton.label": "可視化", - "discover.fieldList.flyoutBackIcon": "戻る", - "discover.fieldList.flyoutHeading": "フィールドリスト", - "discover.fieldNameIcons.booleanAriaLabel": "ブールフィールド", - "discover.fieldNameIcons.conflictFieldAriaLabel": "矛盾フィールド", - "discover.fieldNameIcons.dateFieldAriaLabel": "日付フィールド", - "discover.fieldNameIcons.geoPointFieldAriaLabel": "地理ポイントフィールド", - "discover.fieldNameIcons.geoShapeFieldAriaLabel": "地理情報シェイプフィールド", - "discover.fieldNameIcons.ipAddressFieldAriaLabel": "IPアドレスフィールド", - "discover.fieldNameIcons.murmur3FieldAriaLabel": "Murmur3フィールド", - "discover.fieldNameIcons.nestedFieldAriaLabel": "入れ子フィールド", - "discover.fieldNameIcons.numberFieldAriaLabel": "数値フィールド", - "discover.fieldNameIcons.sourceFieldAriaLabel": "ソースフィールド", - "discover.fieldNameIcons.stringFieldAriaLabel": "文字列フィールド", - "discover.fieldNameIcons.unknownFieldAriaLabel": "不明なフィールド", - "discover.grid.documentHeader": "ドキュメント", - "discover.grid.filterFor": "フィルター", - "discover.grid.filterForAria": "この{value}でフィルターを適用", - "discover.grid.filterOut": "除外", - "discover.grid.filterOutAria": "この{value}を除外", - "discover.grid.flyout.documentNavigation": "ドキュメントナビゲーション", - "discover.grid.flyout.toastColumnAdded": "列'{columnName}'が追加されました", - "discover.grid.flyout.toastColumnRemoved": "列'{columnName}'が削除されました", - "discover.grid.flyout.toastFilterAdded": "フィルターが追加されました", - "discover.grid.tableRow.detailHeading": "拡張ドキュメント", - "discover.grid.tableRow.viewSingleDocumentLinkTextSimple": "1つのドキュメント", - "discover.grid.tableRow.viewSurroundingDocumentsLinkTextSimple": "周りのドキュメント", - "discover.grid.tableRow.viewText": "表示:", - "discover.grid.viewDoc": "詳細ダイアログを切り替え", - "discover.helpMenu.appName": "Discover", - "discover.hideChart": "グラフを非表示", - "discover.histogramOfFoundDocumentsAriaLabel": "検出されたドキュメントのヒストグラム", - "discover.hitCountSpinnerAriaLabel": "読み込み中の最終一致件数", - "discover.howToSeeOtherMatchingDocumentsDescription": "これらは検索条件に一致した初めの {sampleSize} 件のドキュメントです。他の結果を表示するには検索条件を絞ってください。", - "discover.howToSeeOtherMatchingDocumentsDescriptionGrid": "これらは検索条件に一致した初めの {sampleSize} 件のドキュメントです。他の結果を表示するには検索条件を絞ってください。", - "discover.inspectorRequestDataTitleChart": "グラフデータ", - "discover.inspectorRequestDataTitleDocuments": "ドキュメント", - "discover.inspectorRequestDataTitleTotalHits": "総ヒット数", - "discover.inspectorRequestDescriptionChart": "このリクエストはElasticsearchにクエリをかけ、グラフの集計データを取得します。", - "discover.inspectorRequestDescriptionDocument": "このリクエストはElasticsearchにクエリをかけ、ドキュメントを取得します。", - "discover.inspectorRequestDescriptionTotalHits": "このリクエストはElasticsearchにクエリをかけ、合計一致数を取得します。", - "discover.json.codeEditorAriaLabel": "Elasticsearch ドキュメントの JSON ビューのみを読み込む", - "discover.json.copyToClipboardLabel": "クリップボードにコピー", - "discover.loadingChartResults": "グラフを読み込み中", - "discover.loadingDocuments": "ドキュメントを読み込み中", - "discover.loadingJSON": "JSONを読み込んでいます", - "discover.loadingResults": "結果を読み込み中", - "discover.localMenu.inspectTitle": "検査", - "discover.localMenu.localMenu.newSearchTitle": "新規", - "discover.localMenu.localMenu.optionsTitle": "オプション", - "discover.localMenu.newSearchDescription": "新規検索", - "discover.localMenu.openInspectorForSearchDescription": "検索用にインスペクターを開きます", - "discover.localMenu.openSavedSearchDescription": "保存された検索を開きます", - "discover.localMenu.openTitle": "開く", - "discover.localMenu.optionsDescription": "オプション", - "discover.localMenu.saveSaveSearchObjectType": "検索", - "discover.localMenu.saveSearchDescription": "検索を保存します", - "discover.localMenu.saveTitle": "保存", - "discover.localMenu.shareSearchDescription": "検索を共有します", - "discover.localMenu.shareTitle": "共有", - "discover.noResults.adjustFilters": "フィルターを調整", - "discover.noResults.adjustSearch": "クエリを調整", - "discover.noResults.disableFilters": "フィルターを一時的に無効にしています", - "discover.noResults.expandYourTimeRangeTitle": "時間範囲を拡大", - "discover.noResults.queryMayNotMatchTitle": "期間を長くして検索を試してください。", - "discover.noResults.searchExamples.noResultsBecauseOfError": "検索結果の取得中にエラーが発生しました", - "discover.noResults.searchExamples.noResultsMatchSearchCriteriaTitle": "検索条件と一致する結果がありません。", - "discover.noResultsFound": "結果が見つかりませんでした", - "discover.notifications.invalidTimeRangeText": "指定された時間範囲が無効です。(開始:'{from}'、終了:'{to}')", - "discover.notifications.invalidTimeRangeTitle": "無効な時間範囲", - "discover.notifications.notSavedSearchTitle": "検索「{savedSearchTitle}」は保存されませんでした。", - "discover.notifications.savedSearchTitle": "検索「{savedSearchTitle}」が保存されました。", - "discover.reloadSavedSearchButton": "検索をリセット", - "discover.removeColumnLabel": "列を削除", - "discover.rootBreadcrumb": "Discover", - "discover.savedSearch.savedObjectName": "保存検索", - "discover.searchGenerationWithDescription": "検索{searchTitle}で生成されたテーブル", - "discover.searchGenerationWithDescriptionGrid": "検索{searchTitle}で生成されたテーブル({searchDescription})", - "discover.searchingTitle": "検索中", - "discover.selectColumnHeader": "列を選択", - "discover.selectedDocumentsNumber": "{nr}個のドキュメントが選択されました", - "discover.showAllDocuments": "すべてのドキュメントを表示", - "discover.showChart": "グラフを表示", - "discover.showErrorMessageAgain": "エラーメッセージを表示", - "discover.showSelectedDocumentsOnly": "選択したドキュメントのみを表示", - "discover.skipToBottomButtonLabel": "テーブルの最後に移動", - "discover.sourceViewer.errorMessage": "現在データを取得できませんでした。タブを更新して、再試行してください。", - "discover.sourceViewer.errorMessageTitle": "エラーが発生しました", - "discover.sourceViewer.refresh": "更新", - "discover.toggleSidebarAriaLabel": "サイドバーを切り替える", - "discover.topNav.openSearchPanel.manageSearchesButtonLabel": "検索の管理", - "discover.topNav.openSearchPanel.noSearchesFoundDescription": "一致する検索が見つかりませんでした。", - "discover.topNav.openSearchPanel.openSearchTitle": "検索を開く", - "discover.topNav.optionsPopover.currentViewMode": "{viewModeLabel}: {currentViewMode}", - "discover.uninitializedRefreshButtonText": "データを更新", - "discover.uninitializedText": "クエリを作成、フィルターを追加、または[更新]をクリックして、現在のクエリの結果を取得します。", - "discover.uninitializedTitle": "検索開始", - "embeddableApi.addPanel.createNewDefaultOption": "新規作成", - "embeddableApi.addPanel.displayName": "パネルの追加", - "embeddableApi.addPanel.noMatchingObjectsMessage": "一致するオブジェクトが見つかりませんでした。", - "embeddableApi.addPanel.savedObjectAddedToContainerSuccessMessageTitle": "{savedObjectName} が追加されました", - "embeddableApi.addPanel.Title": "ライブラリから追加", - "embeddableApi.attributeService.saveToLibraryError": "保存中にエラーが発生しました。エラー:{errorMessage}", - "embeddableApi.contextMenuTrigger.description": "パネルの右上のコンテキストメニューをクリックします。", - "embeddableApi.contextMenuTrigger.title": "コンテキストメニュー", - "embeddableApi.customizePanel.action.displayName": "パネルタイトルを編集", - "embeddableApi.customizePanel.modal.cancel": "キャンセル", - "embeddableApi.customizePanel.modal.optionsMenuForm.panelTitleFormRowLabel": "パネルタイトル", - "embeddableApi.customizePanel.modal.optionsMenuForm.panelTitleInputAriaLabel": "パネルのカスタムタイトルを入力してください", - "embeddableApi.customizePanel.modal.optionsMenuForm.resetCustomDashboardButtonLabel": "リセット", - "embeddableApi.customizePanel.modal.saveButtonTitle": "保存", - "embeddableApi.customizePanel.modal.showTitle": "パネルタイトルを表示", - "embeddableApi.customizeTitle.optionsMenuForm.panelTitleFormRowLabel": "パネルタイトル", - "embeddableApi.customizeTitle.optionsMenuForm.panelTitleInputAriaLabel": "このインプットへの変更は直ちに適用されます。Enter を押して閉じます。", - "embeddableApi.customizeTitle.optionsMenuForm.resetCustomDashboardButtonLabel": "タイトルをリセット", - "embeddableApi.errors.embeddableFactoryNotFound": "{type} を読み込めません。Elasticsearch と Kibana のデフォルトのディストリビューションを適切なライセンスでアップグレードしてください。", - "embeddableApi.errors.paneldoesNotExist": "パネルが見つかりません", - "embeddableApi.helloworld.displayName": "こんにちは", - "embeddableApi.panel.dashboardPanelAriaLabel": "ダッシュボードパネル", - "embeddableApi.panel.editPanel.displayName": "{value} を編集", - "embeddableApi.panel.editTitleAriaLabel": "クリックしてタイトルを編集:{title}", - "embeddableApi.panel.enhancedDashboardPanelAriaLabel": "ダッシュボードパネル:{title}", - "embeddableApi.panel.inspectPanel.displayName": "検査", - "embeddableApi.panel.inspectPanel.untitledEmbeddableFilename": "無題", - "embeddableApi.panel.labelAborted": "中断しました", - "embeddableApi.panel.labelError": "エラー", - "embeddableApi.panel.optionsMenu.panelOptionsButtonAriaLabel": "パネルオプション", - "embeddableApi.panel.optionsMenu.panelOptionsButtonEnhancedAriaLabel": "{title} のパネルオプション", - "embeddableApi.panel.placeholderTitle": "[タイトルなし]", - "embeddableApi.panel.removePanel.displayName": "ダッシュボードから削除", - "embeddableApi.panelBadgeTrigger.description": "パネルに埋め込み可能なファイルが読み込まれるときに、アクションがタイトルバーに表示されます。", - "embeddableApi.panelBadgeTrigger.title": "パネルバッジ", - "embeddableApi.panelNotificationTrigger.description": "パネルの右上にアクションが表示されます。", - "embeddableApi.panelNotificationTrigger.title": "パネル通知", - "embeddableApi.samples.contactCard.displayName": "連絡先カード", - "embeddableApi.samples.filterableContainer.displayName": "フィルター可能なダッシュボード", - "embeddableApi.samples.filterableEmbeddable.displayName": "フィルター可能", - "embeddableApi.selectRangeTrigger.description": "ビジュアライゼーションでの値の範囲", - "embeddableApi.selectRangeTrigger.title": "範囲選択", - "embeddableApi.valueClickTrigger.description": "ビジュアライゼーションでデータポイントをクリック", - "embeddableApi.valueClickTrigger.title": "シングルクリック", - "esQuery.kql.errors.endOfInputText": "インプットの終わり", - "esQuery.kql.errors.fieldNameText": "フィールド名", - "esQuery.kql.errors.literalText": "文字通り", - "esQuery.kql.errors.syntaxError": "{expectedList} を期待しましたが {foundInput} が検出されました。", - "esQuery.kql.errors.valueText": "値", - "esQuery.kql.errors.whitespaceText": "空白類", - "esUi.cronEditor.cronDaily.fieldHour.textAtLabel": "に", - "esUi.cronEditor.cronDaily.fieldTimeLabel": "時間", - "esUi.cronEditor.cronDaily.hourSelectLabel": "時間", - "esUi.cronEditor.cronDaily.minuteSelectLabel": "分", - "esUi.cronEditor.cronHourly.fieldMinute.textAtLabel": "に", - "esUi.cronEditor.cronHourly.fieldTimeLabel": "分", - "esUi.cronEditor.cronMonthly.fieldDateLabel": "日付", - "esUi.cronEditor.cronMonthly.fieldHour.textAtLabel": "に", - "esUi.cronEditor.cronMonthly.fieldTimeLabel": "時間", - "esUi.cronEditor.cronMonthly.hourSelectLabel": "時間", - "esUi.cronEditor.cronMonthly.minuteSelectLabel": "分", - "esUi.cronEditor.cronMonthly.textOnTheLabel": "に", - "esUi.cronEditor.cronWeekly.fieldDateLabel": "日", - "esUi.cronEditor.cronWeekly.fieldHour.textAtLabel": "に", - "esUi.cronEditor.cronWeekly.fieldTimeLabel": "時間", - "esUi.cronEditor.cronWeekly.hourSelectLabel": "時間", - "esUi.cronEditor.cronWeekly.minuteSelectLabel": "分", - "esUi.cronEditor.cronWeekly.textOnLabel": "オン", - "esUi.cronEditor.cronYearly.fieldDate.textOnTheLabel": "に", - "esUi.cronEditor.cronYearly.fieldDateLabel": "日付", - "esUi.cronEditor.cronYearly.fieldHour.textAtLabel": "に", - "esUi.cronEditor.cronYearly.fieldMonth.textInLabel": "入", - "esUi.cronEditor.cronYearly.fieldMonthLabel": "月", - "esUi.cronEditor.cronYearly.fieldTimeLabel": "時間", - "esUi.cronEditor.cronYearly.hourSelectLabel": "時間", - "esUi.cronEditor.cronYearly.minuteSelectLabel": "分", - "esUi.cronEditor.day.friday": "金曜日", - "esUi.cronEditor.day.monday": "月曜日", - "esUi.cronEditor.day.saturday": "土曜日", - "esUi.cronEditor.day.sunday": "日曜日", - "esUi.cronEditor.day.thursday": "木曜日", - "esUi.cronEditor.day.tuesday": "火曜日", - "esUi.cronEditor.day.wednesday": "水曜日", - "esUi.cronEditor.fieldFrequencyLabel": "頻度", - "esUi.cronEditor.month.april": "4 月", - "esUi.cronEditor.month.august": "8 月", - "esUi.cronEditor.month.december": "12 月", - "esUi.cronEditor.month.february": "2 月", - "esUi.cronEditor.month.january": "1 月", - "esUi.cronEditor.month.july": "7 月", - "esUi.cronEditor.month.june": "6 月", - "esUi.cronEditor.month.march": "3 月", - "esUi.cronEditor.month.may": "5月", - "esUi.cronEditor.month.november": "11 月", - "esUi.cronEditor.month.october": "10 月", - "esUi.cronEditor.month.september": "9 月", - "esUi.cronEditor.textEveryLabel": "毎", - "esUi.forms.comboBoxField.placeHolderText": "入力してエンターキーを押してください", - "esUi.forms.fieldValidation.indexNameSpacesError": "インデックス名にはスペースを使用できません。", - "esUi.forms.fieldValidation.indexNameStartsWithDotError": "インデックス名の始めにピリオド(.)は使用できません。", - "esUi.forms.fieldValidation.indexPatternSpacesError": "インデックスパターンにはスペースを使用できません。", - "esUi.formWizard.backButtonLabel": "戻る", - "esUi.formWizard.nextButtonLabel": "次へ", - "esUi.formWizard.saveButtonLabel": "保存", - "esUi.formWizard.savingButtonLabel": "保存中...", - "esUi.validation.string.invalidJSONError": "無効なJSON", - "expressionError.errorComponent.description": "表現が失敗し次のメッセージが返されました:", - "expressionError.errorComponent.title": "おっと!表現が失敗しました", - "expressionError.renderer.debug.displayName": "デバッグ", - "expressionError.renderer.debug.helpDescription": "デバッグアウトプットをフォーマットされた {JSON} としてレンダリングします", - "expressionError.renderer.error.displayName": "エラー情報", - "expressionError.renderer.error.helpDescription": "エラーデータをユーザーにわかるようにレンダリングします", - "expressionImage.functions.image.args.dataurlHelpText": "画像の {https} {URL} または {BASE64} データ {URL} です。", - "expressionImage.functions.image.args.modeHelpText": "{contain} はサイズに合わせて拡大・縮小して画像全体を表示し、{cover} はコンテナーを画像で埋め、必要に応じて両端や下をクロップします。{stretch} は画像の高さと幅をコンテナーの 100% になるよう変更します。", - "expressionImage.functions.image.invalidImageModeErrorMessage": "「mode」は「{contain}」、「{cover}」、または「{stretch}」でなければなりません", - "expressionImage.functions.imageHelpText": "画像を表示します。画像アセットは{BASE64}データ{URL}として提供するか、部分式で渡します。", - "expressionImage.renderer.image.displayName": "画像", - "expressionImage.renderer.image.helpDescription": "画像をレンダリングします", - "expressionMetric.functions.metric.args.labelFontHelpText": "ラベルの {CSS} フォントプロパティです。例:{FONT_FAMILY} または {FONT_WEIGHT}。", - "expressionMetric.functions.metric.args.labelHelpText": "メトリックを説明するテキストです。", - "expressionMetric.functions.metric.args.metricFontHelpText": "メトリックの {CSS} フォントプロパティです。例:{FONT_FAMILY} または {FONT_WEIGHT}。", - "expressionMetric.functions.metric.args.metricFormatHelpText": "{NUMERALJS} 形式の文字列。例:{example1} または {example2}。", - "expressionMetric.functions.metricHelpText": "ラベルの上に数字を表示します。", - "expressionMetric.renderer.metric.displayName": "メトリック", - "expressionMetric.renderer.metric.helpDescription": "ラベルの上に数字をレンダリングします", - "expressionRepeatImage.error.repeatImage.missingMaxArgument": "{emptyImageArgument} を指定する場合は、{maxArgument} を設定する必要があります", - "expressionRepeatImage.functions.repeatImage.args.emptyImageHelpText": "この画像のエレメントについて、{CONTEXT}および{maxArg}パラメーターの差異を解消します。画像アセットは{BASE64}データ{URL}として提供するか、部分式で渡します。", - "expressionRepeatImage.functions.repeatImage.args.imageHelpText": "繰り返す画像です。画像アセットは{BASE64}データ{URL}として提供するか、部分式で渡します。", - "expressionRepeatImage.functions.repeatImage.args.maxHelpText": "画像が繰り返される最高回数です。", - "expressionRepeatImage.functions.repeatImage.args.sizeHelpText": "画像の高さまたは幅のピクセル単位での最高値です。画像が縦長の場合、この関数は高さを制限します。", - "expressionRepeatImage.functions.repeatImageHelpText": "繰り返し画像エレメントを構成します。", - "expressionRepeatImage.renderer.repeatImage.displayName": "RepeatImage", - "expressionRepeatImage.renderer.repeatImage.helpDescription": "基本repeatImageを表示", - "expressionRevealImage.functions.revealImage.args.emptyImageHelpText": "表示される背景画像です。画像アセットは「{BASE64}」データ {URL} として提供するか、部分式で渡します。", - "expressionRevealImage.functions.revealImage.args.imageHelpText": "表示する画像です。画像アセットは{BASE64}データ{URL}として提供するか、部分式で渡します。", - "expressionRevealImage.functions.revealImage.args.originHelpText": "画像で埋め始める位置です。たとえば、{list}、または {end}です。", - "expressionRevealImage.functions.revealImage.invalidImageUrl": "無効な画像URL:'{imageUrl}'。", - "expressionRevealImage.functions.revealImage.invalidPercentErrorMessage": "無効な値:「{percent}」。パーセンテージは 0 と 1 の間でなければなりません ", - "expressionRevealImage.functions.revealImageHelpText": "画像表示エレメントを構成します。", - "expressionRevealImage.renderer.revealImage.displayName": "画像の部分表示", - "expressionRevealImage.renderer.revealImage.helpDescription": "カスタムゲージスタイルチャートを作成するため、画像のパーセンテージを表示します", - "expressions.defaultErrorRenderer.errorTitle": "ビジュアライゼーションエラー", - "expressions.execution.functionDisabled": "関数 {fnName} が無効です。", - "expressions.execution.functionNotFound": "関数 {fnName} が見つかりませんでした。", - "expressions.functions.createTable.args.idsHelpText": "位置順序で生成する列ID。IDは行のキーを表します。", - "expressions.functions.createTable.args.nameHelpText": "位置順序で生成する列名。名前は一意でなくてもかまいません。指定しない場合は、デフォルトでIDが使用されます。", - "expressions.functions.createTable.args.rowCountText": "後から値を割り当てられる、テーブルに追加する空の行数。", - "expressions.functions.createTableHelpText": "データテーブルと、列のリスト、1つ以上の空の行を作成します。行を入力するには、{mapColumnFn}または{mathColumnFn}を使用します。", - "expressions.functions.cumulativeSum.args.byHelpText": "累積和計算を分割する列", - "expressions.functions.cumulativeSum.args.inputColumnIdHelpText": "累積和を計算する列", - "expressions.functions.cumulativeSum.args.outputColumnIdHelpText": "結果の累積和を格納する列", - "expressions.functions.cumulativeSum.args.outputColumnNameHelpText": "結果の累積和を格納する列の名前", - "expressions.functions.cumulativeSum.help": "データテーブルの列の累積和を計算します", - "expressions.functions.derivative.args.byHelpText": "微分係数計算を分割する列", - "expressions.functions.derivative.args.inputColumnIdHelpText": "微分係数を計算する列", - "expressions.functions.derivative.args.outputColumnIdHelpText": "結果の微分係数を格納する列", - "expressions.functions.derivative.args.outputColumnNameHelpText": "結果の微分係数を格納する列の名前", - "expressions.functions.derivative.help": "データテーブルの列の微分係数を計算します", - "expressions.functions.font.args.alignHelpText": "水平テキスト配置", - "expressions.functions.font.args.colorHelpText": "文字の色です。", - "expressions.functions.font.args.familyHelpText": "利用可能な{css}ウェブフォント文字列です", - "expressions.functions.font.args.italicHelpText": "テキストを斜体にしますか?", - "expressions.functions.font.args.lHeightHelpText": "ピクセル単位の行の高さです。", - "expressions.functions.font.args.sizeHelpText": "ピクセル単位のフォントサイズです。", - "expressions.functions.font.args.underlineHelpText": "テキストに下線を引きますか?", - "expressions.functions.font.args.weightHelpText": "フォントの重量です。たとえば、{list}、または {end}です。", - "expressions.functions.font.invalidFontWeightErrorMessage": "無効なフォント太さ:'{weight}'", - "expressions.functions.font.invalidTextAlignmentErrorMessage": "無効なテキストアラインメント:'{align}'", - "expressions.functions.fontHelpText": "フォントスタイルを作成します。", - "expressions.functions.mapColumn.args.copyMetaFromHelpText": "設定されている場合、指定した列IDのメタオブジェクトが指定したターゲット列にコピーされます。列が存在しない場合は失敗し、エラーは表示されません。", - "expressions.functions.mapColumn.args.expressionHelpText": "すべての行で実行される式。単一行の{DATATABLE}と一緒に指定され、セル値を返します。", - "expressions.functions.mapColumn.args.idHelpText": "結果列の任意のID。IDが指定されていないときには、指定された名前引数で既存の列からルックアップされます。この名前の列が存在しない場合、この名前と同じIDの新しい列がテーブルに追加されます。", - "expressions.functions.mapColumn.args.nameHelpText": "結果の列の名前です。名前は一意である必要はありません。", - "expressions.functions.mapColumnHelpText": "他の列の結果として計算された列を追加します。引数が指定された場合のみ変更が加えられます。{alterColumnFn}と{staticColumnFn}もご参照ください。", - "expressions.functions.math.args.expressionHelpText": "評価された {TINYMATH} 表現です。{TINYMATH_URL} をご覧ください。", - "expressions.functions.math.args.onErrorHelpText": "{TINYMATH}評価が失敗するか、NaNが返される場合、戻り値はonErrorで指定されます。「'throw'」の場合、例外が発生し、式の実行が終了します(デフォルト)。", - "expressions.functions.math.emptyDatatableErrorMessage": "空のデータベース", - "expressions.functions.math.emptyExpressionErrorMessage": "空の表現", - "expressions.functions.math.executionFailedErrorMessage": "数式の実行に失敗しました。列名を確認してください", - "expressions.functions.math.tooManyResultsErrorMessage": "式は 1 つの数字を返す必要があります。表現を {mean} または {sum} で囲んでみてください", - "expressions.functions.mathColumn.args.copyMetaFromHelpText": "設定されている場合、指定した列IDのメタオブジェクトが指定したターゲット列にコピーされます。列が存在しない場合は失敗し、エラーは表示されません。", - "expressions.functions.mathColumn.args.idHelpText": "結果の列のIDです。一意でなければなりません。", - "expressions.functions.mathColumn.args.nameHelpText": "結果の列の名前です。名前は一意である必要はありません。", - "expressions.functions.mathColumn.arrayValueError": "{name}で配列値に対する演算を実行できません", - "expressions.functions.mathColumn.uniqueIdError": "IDは一意でなければなりません", - "expressions.functions.mathColumnHelpText": "他の列の結果として計算された列を追加します。引数が指定された場合のみ変更が加えられます。{alterColumnFn}と{staticColumnFn}もご参照ください。", - "expressions.functions.mathHelpText": "{TYPE_NUMBER}または{DATATABLE}を{CONTEXT}として使用して、{TINYMATH}数式を解釈します。{DATATABLE}列は列名で表示されます。{CONTEXT}が数字の場合は、{value}と表示されます。", - "expressions.functions.movingAverage.args.byHelpText": "移動平均計算を分割する列", - "expressions.functions.movingAverage.args.inputColumnIdHelpText": "移動平均を計算する列", - "expressions.functions.movingAverage.args.outputColumnIdHelpText": "結果の移動平均を格納する列", - "expressions.functions.movingAverage.args.outputColumnNameHelpText": "結果の移動平均を格納する列の名前", - "expressions.functions.movingAverage.args.windowHelpText": "ヒストグラム全体でスライドするウィンドウのサイズ。", - "expressions.functions.movingAverage.help": "データテーブルの列の移動平均を計算します", - "expressions.functions.overallMetric.args.byHelpText": "全体の計算を分割する列", - "expressions.functions.overallMetric.args.inputColumnIdHelpText": "全体のメトリックを計算する列", - "expressions.functions.overallMetric.args.outputColumnIdHelpText": "結果の全体のメトリックを格納する列", - "expressions.functions.overallMetric.args.outputColumnNameHelpText": "結果の全体のメトリックを格納する列の名前", - "expressions.functions.overallMetric.help": "データテーブルの列の合計値、最小値、最大値、」または平均を計算します", - "expressions.functions.overallMetric.metricHelpText": "計算するメトリック", - "expressions.functions.seriesCalculations.columnConflictMessage": "指定した outputColumnId {columnId} はすでに存在します。別の列 ID を選択してください。", - "expressions.functions.theme.args.defaultHelpText": "テーマ情報がない場合のデフォルト値。", - "expressions.functions.theme.args.variableHelpText": "読み取るテーマ変数名。", - "expressions.functions.themeHelpText": "テーマ設定を読み取ります。", - "expressions.functions.uiSetting.args.default": "パラメーターが設定されていない場合のデフォルト値。", - "expressions.functions.uiSetting.args.parameter": "パラメーター名。", - "expressions.functions.uiSetting.error.kibanaRequest": "サーバーでUI設定を取得するには、KibanaRequest が必要です。式実行パラメーターに要求オブジェクトを渡してください。", - "expressions.functions.uiSetting.error.parameter": "無効なパラメーター\"{parameter}\"です。", - "expressions.functions.uiSetting.help": "UI設定パラメーター値を返します。", - "expressions.functions.var.help": "Kibanaグローバルコンテキストを更新します。", - "expressions.functions.var.name.help": "変数の名前を指定します。", - "expressions.functions.varset.help": "Kibanaグローバルコンテキストを更新します。", - "expressions.functions.varset.name.help": "変数の名前を指定します。", - "expressions.functions.varset.val.help": "変数の値を指定します。指定しないと、入力コンテキストが使用されます。", - "expressions.types.number.fromStringConversionErrorMessage": "\"{string}\" 文字列を数字に変換できません", - "expressionShape.functions.progress.args.barColorHelpText": "背景バーの色です。", - "expressionShape.functions.progress.args.barWeightHelpText": "背景バーの太さです。", - "expressionShape.functions.progress.args.fontHelpText": "ラベルの {CSS} フォントプロパティです。例:{FONT_FAMILY} または {FONT_WEIGHT}。", - "expressionShape.functions.progress.args.labelHelpText": "ラベルの表示・非表示を切り替えるには、{BOOLEAN_TRUE}または{BOOLEAN_FALSE}を使用します。また、ラベルとして表示する文字列を入力することもできます。", - "expressionShape.functions.progress.args.maxHelpText": "進捗エレメントの最高値です。", - "expressionShape.functions.progress.args.shapeHelpText": "{list} または {end} を選択します。", - "expressionShape.functions.progress.args.valueColorHelpText": "進捗バーの色です。", - "expressionShape.functions.progress.args.valueWeightHelpText": "進捗バーの太さです。", - "expressionShape.functions.progress.invalidMaxValueErrorMessage": "無効な {arg} 値:「{max, number}」。「{arg}」は 0 より大きい必要があります", - "expressionShape.functions.progress.invalidValueErrorMessage": "無効な値:「{value, number}」。値は 0 と {max, number} の間でなければなりません", - "expressionShape.functions.progressHelpText": "進捗エレメントを構成します。", - "expressionShape.functions.shape.args.borderHelpText": "図形の外郭の {SVG} カラーです。", - "expressionShape.functions.shape.args.borderWidthHelpText": "境界の太さです。", - "expressionShape.functions.shape.args.fillHelpText": "図形を塗りつぶす {SVG} カラーです。", - "expressionShape.functions.shape.args.maintainAspectHelpText": "図形の元の横縦比を維持しますか?", - "expressionShape.functions.shape.args.shapeHelpText": "図形を選択します。", - "expressionShape.functions.shape.invalidShapeErrorMessage": "無効な値:'{shape}'。このような形状は存在しません。", - "expressionShape.functions.shapeHelpText": "図形を作成します。", - "expressionShape.renderer.progress.displayName": "進捗", - "expressionShape.renderer.progress.helpDescription": "基本進捗状況をレンダリング", - "expressionShape.renderer.shape.displayName": "形状", - "expressionShape.renderer.shape.helpDescription": "基本的な図形をレンダリングします", - "fieldFormats.advancedSettings.format.bytesFormat.numeralFormatLinkText": "数字フォーマット", - "fieldFormats.advancedSettings.format.bytesFormatText": "「バイト」フォーマットのデフォルト{numeralFormatLink}です", - "fieldFormats.advancedSettings.format.bytesFormatTitle": "バイトフォーマット", - "fieldFormats.advancedSettings.format.currencyFormat.numeralFormatLinkText": "数字フォーマット", - "fieldFormats.advancedSettings.format.currencyFormatText": "「通貨」フォーマットのデフォルト{numeralFormatLink}です", - "fieldFormats.advancedSettings.format.currencyFormatTitle": "通貨フォーマット", - "fieldFormats.advancedSettings.format.defaultTypeMapText": "各フィールドタイプにデフォルトで使用するフォーマット名のマップです。フィールドタイプが特に指定されていない場合は {defaultFormat} が使用されます", - "fieldFormats.advancedSettings.format.defaultTypeMapTitle": "フィールドタイプフォーマット名", - "fieldFormats.advancedSettings.format.formattingLocale.numeralLanguageLinkText": "数字言語", - "fieldFormats.advancedSettings.format.formattingLocaleText": "{numeralLanguageLink} locale", - "fieldFormats.advancedSettings.format.formattingLocaleTitle": "フォーマットロケール", - "fieldFormats.advancedSettings.format.numberFormat.numeralFormatLinkText": "数字フォーマット", - "fieldFormats.advancedSettings.format.numberFormatText": "「数字」フォーマットのデフォルト{numeralFormatLink}です", - "fieldFormats.advancedSettings.format.numberFormatTitle": "数字フォーマット", - "fieldFormats.advancedSettings.format.percentFormat.numeralFormatLinkText": "数字フォーマット", - "fieldFormats.advancedSettings.format.percentFormatText": "「パーセント」フォーマットのデフォルト{numeralFormatLink}です", - "fieldFormats.advancedSettings.format.percentFormatTitle": "パーセントフォーマット", - "fieldFormats.advancedSettings.shortenFieldsText": "長いフィールドを短くします。例:foo.bar.bazの代わりにf.b.bazと表示", - "fieldFormats.advancedSettings.shortenFieldsTitle": "フィールドの短縮", - "fieldFormats.boolean.title": "ブール", - "fieldFormats.bytes.title": "バイト", - "fieldFormats.color.title": "色", - "fieldFormats.date_nanos.title": "日付ナノ", - "fieldFormats.date.title": "日付", - "fieldFormats.duration.inputFormats.days": "日", - "fieldFormats.duration.inputFormats.hours": "時間", - "fieldFormats.duration.inputFormats.microseconds": "マイクロ秒", - "fieldFormats.duration.inputFormats.milliseconds": "ミリ秒", - "fieldFormats.duration.inputFormats.minutes": "分", - "fieldFormats.duration.inputFormats.months": "か月", - "fieldFormats.duration.inputFormats.nanoseconds": "ナノ秒", - "fieldFormats.duration.inputFormats.picoseconds": "ピコ秒", - "fieldFormats.duration.inputFormats.seconds": "秒", - "fieldFormats.duration.inputFormats.weeks": "週間", - "fieldFormats.duration.inputFormats.years": "年", - "fieldFormats.duration.negativeLabel": "マイナス", - "fieldFormats.duration.outputFormats.asDays": "日", - "fieldFormats.duration.outputFormats.asDays.short": "d", - "fieldFormats.duration.outputFormats.asHours": "時間", - "fieldFormats.duration.outputFormats.asHours.short": "h", - "fieldFormats.duration.outputFormats.asMilliseconds": "ミリ秒", - "fieldFormats.duration.outputFormats.asMilliseconds.short": "ms", - "fieldFormats.duration.outputFormats.asMinutes": "分", - "fieldFormats.duration.outputFormats.asMinutes.short": "分", - "fieldFormats.duration.outputFormats.asMonths": "か月", - "fieldFormats.duration.outputFormats.asMonths.short": "mon", - "fieldFormats.duration.outputFormats.asSeconds": "秒", - "fieldFormats.duration.outputFormats.asSeconds.short": "s", - "fieldFormats.duration.outputFormats.asWeeks": "週間", - "fieldFormats.duration.outputFormats.asWeeks.short": "w", - "fieldFormats.duration.outputFormats.asYears": "年", - "fieldFormats.duration.outputFormats.asYears.short": "y", - "fieldFormats.duration.outputFormats.humanize.approximate": "人間が読み取り可能(近似値)", - "fieldFormats.duration.outputFormats.humanize.precise": "人間が読み取り可能(正確な値)", - "fieldFormats.duration.title": "期間", - "fieldFormats.histogram.title": "ヒストグラム", - "fieldFormats.ip.title": "IP アドレス", - "fieldFormats.number.title": "数字", - "fieldFormats.percent.title": "割合(%)", - "fieldFormats.relative_date.title": "相対日付", - "fieldFormats.static_lookup.title": "静的ルックアップ", - "fieldFormats.string.emptyLabel": "(空)", - "fieldFormats.string.title": "文字列", - "fieldFormats.string.transformOptions.base64": "Base64 デコード", - "fieldFormats.string.transformOptions.lower": "小文字", - "fieldFormats.string.transformOptions.none": "- なし -", - "fieldFormats.string.transformOptions.short": "短い点線", - "fieldFormats.string.transformOptions.title": "タイトルケース", - "fieldFormats.string.transformOptions.upper": "大文字", - "fieldFormats.string.transformOptions.url": "URL パラメーターデコード", - "fieldFormats.truncated_string.title": "切り詰めた文字列", - "fieldFormats.url.title": "Url", - "fieldFormats.url.types.audio": "音声", - "fieldFormats.url.types.img": "画像", - "fieldFormats.url.types.link": "リンク", - "flot.pie.unableToDrawLabelsInsideCanvasErrorMessage": "キャンバス内のラベルではパイを作成できません", - "flot.time.aprLabel": "4 月", - "flot.time.augLabel": "8 月", - "flot.time.decLabel": "12 月", - "flot.time.febLabel": "2 月", - "flot.time.friLabel": "金", - "flot.time.janLabel": "1月", - "flot.time.julLabel": "7月", - "flot.time.junLabel": "6 月", - "flot.time.marLabel": "3 月", - "flot.time.mayLabel": "5月", - "flot.time.monLabel": "月", - "flot.time.novLabel": "11月", - "flot.time.octLabel": "10 月", - "flot.time.satLabel": "土", - "flot.time.sepLabel": "9月", - "flot.time.sunLabel": "日", - "flot.time.thuLabel": "木", - "flot.time.tueLabel": "火", - "flot.time.wedLabel": "水", - "home.addData.addDataButtonLabel": "データを追加", - "home.addData.sampleDataButtonLabel": "サンプルデータを試す", - "home.addData.sectionTitle": "データを追加して開始する", - "home.addData.text": "データの操作を開始するには、多数の取り込みオプションのいずれかを使用します。アプリまたはサービスからデータを収集するか、ファイルをアップロードします。独自のデータを使用する準備ができていない場合は、サンプルデータセットを追加してください。", - "home.breadcrumbs.homeTitle": "ホーム", - "home.dataManagementDisableCollection": " 収集を停止するには、", - "home.dataManagementDisableCollectionLink": "ここで使用状況データを無効にします。", - "home.dataManagementDisclaimerPrivacy": "使用状況データがどのように製品とサービスの管理と改善につながるのかに関する詳細については ", - "home.dataManagementDisclaimerPrivacyLink": "プライバシーポリシーをご覧ください。", - "home.dataManagementEnableCollection": " 収集を開始するには、", - "home.dataManagementEnableCollectionLink": "ここで使用状況データを有効にします。", - "home.exploreButtonLabel": "独りで閲覧", - "home.exploreYourDataDescription": "すべてのステップを終えたら、データ閲覧準備の完了です。", - "home.header.title": "ようこそホーム", - "home.letsStartDescription": "任意のソースからクラスターにデータを追加して、リアルタイムでデータを分析して可視化します。当社のソリューションを使用すれば、どこからでも検索を追加し、エコシステムを監視して、セキュリティの脅威から保護することができます。", - "home.letsStartTitle": "データを追加して開始する", - "home.loadTutorials.requestFailedErrorMessage": "リクエスト失敗、ステータスコード:{status}", - "home.loadTutorials.unableToLoadErrorMessage": "チュートリアルが読み込めません。", - "home.manageData.devToolsButtonLabel": "開発ツール", - "home.manageData.sectionTitle": "管理", - "home.manageData.stackManagementButtonLabel": "スタック管理", - "home.pageTitle": "ホーム", - "home.recentlyAccessed.recentlyViewedTitle": "最近閲覧", - "home.sampleData.ecommerceSpec.ordersTitle": "[eコマース] 注文", - "home.sampleData.ecommerceSpec.promotionTrackingTitle": "[eコマース] プロモーショントラッキング", - "home.sampleData.ecommerceSpec.revenueDashboardDescription": "サンプルの e コマースの注文と収益を分析します", - "home.sampleData.ecommerceSpec.revenueDashboardTitle": "[eコマース] 収益ダッシュボード", - "home.sampleData.ecommerceSpec.soldProductsPerDayTitle": "[eコマース] 1日の販売製品", - "home.sampleData.ecommerceSpecDescription": "e コマースの注文をトラッキングするサンプルデータ、ビジュアライゼーション、ダッシュボードです。", - "home.sampleData.ecommerceSpecTitle": "サンプル e コマース注文", - "home.sampleData.flightsSpec.airportConnectionsTitle": "[フライト] 空港乗り継ぎ(空港にカーソルを合わせてください)", - "home.sampleData.flightsSpec.delayBucketsTitle": "[フライト] 遅延バケット", - "home.sampleData.flightsSpec.delaysAndCancellationsTitle": "[フライト] 遅延・欠航", - "home.sampleData.flightsSpec.departuresCountMapTitle": "[フライト] 出発カウントマップ", - "home.sampleData.flightsSpec.destinationWeatherTitle": "[フライト] 目的地の天候", - "home.sampleData.flightsSpec.flightLogTitle": "[フライト] 飛行記録", - "home.sampleData.flightsSpec.globalFlightDashboardDescription": "ES-Air、Logstash Airways、Kibana Airlines、JetBeats のサンプル飛行データを分析します", - "home.sampleData.flightsSpec.globalFlightDashboardTitle": "[フライト] グローバルフライトダッシュボード", - "home.sampleData.flightsSpecDescription": "飛行ルートを監視するサンプルデータ、ビジュアライゼーション、ダッシュボードです。", - "home.sampleData.flightsSpecTitle": "サンプル飛行データ", - "home.sampleData.logsSpec.bytesDistributionTitle": "[ログ] バイト分布", - "home.sampleData.logsSpec.discoverTitle": "[ログ] 訪問", - "home.sampleData.logsSpec.goalsTitle": "[ログ] 目標", - "home.sampleData.logsSpec.heatmapTitle": "[ログ] 一意の訪問者ヒートマップ", - "home.sampleData.logsSpec.hostVisitsBytesTableTitle": "[ログ] ホスト、訪問数、バイト表", - "home.sampleData.logsSpec.responseCodesOverTimeTitle": "[ログ] 一定期間の応答コードと注釈", - "home.sampleData.logsSpec.sourceAndDestinationSankeyChartTitle": "[ログ] ソースと行先のサンキーダイアグラム", - "home.sampleData.logsSpec.visitorsMapTitle": "[ログ] ビジターマップ", - "home.sampleData.logsSpec.webTrafficDescription": "Elastic Web サイトのサンプル Webトラフィックログデータを分析します", - "home.sampleData.logsSpec.webTrafficTitle": "[ログ] Webトラフィック", - "home.sampleData.logsSpecDescription": "Web ログを監視するサンプルデータ、ビジュアライゼーション、ダッシュボードです。", - "home.sampleData.logsSpecTitle": "サンプル Web ログ", - "home.sampleDataSet.installedLabel": "{name} がインストールされました", - "home.sampleDataSet.unableToInstallErrorMessage": "サンプルデータセット「{name}」をインストールできません", - "home.sampleDataSet.unableToLoadListErrorMessage": "サンプルデータセットのリストを読み込めません", - "home.sampleDataSet.unableToUninstallErrorMessage": "サンプルデータセット「{name}」をアンインストールできません", - "home.sampleDataSet.uninstalledLabel": "{name} がアンインストールされました", - "home.sampleDataSetCard.addButtonAriaLabel": "{datasetName} を追加", - "home.sampleDataSetCard.addButtonLabel": "データの追加", - "home.sampleDataSetCard.addingButtonAriaLabel": "{datasetName} を追加", - "home.sampleDataSetCard.addingButtonLabel": "追加中", - "home.sampleDataSetCard.dashboardLinkLabel": "ダッシュボード", - "home.sampleDataSetCard.default.addButtonAriaLabel": "{datasetName} を追加", - "home.sampleDataSetCard.default.addButtonLabel": "データの追加", - "home.sampleDataSetCard.default.unableToVerifyErrorMessage": "データセットステータスを確認できません、エラー:{statusMsg}", - "home.sampleDataSetCard.removeButtonAriaLabel": "{datasetName} を削除", - "home.sampleDataSetCard.removeButtonLabel": "削除", - "home.sampleDataSetCard.removingButtonAriaLabel": "{datasetName} を削除中", - "home.sampleDataSetCard.removingButtonLabel": "削除中", - "home.sampleDataSetCard.viewDataButtonAriaLabel": "{datasetName} を表示", - "home.sampleDataSetCard.viewDataButtonLabel": "データを表示", - "home.solutionsSection.sectionTitle": "ソリューションを選択", - "home.tryButtonLabel": "データの追加", - "home.tutorial.addDataToKibanaTitle": "データの追加", - "home.tutorial.card.sampleDataDescription": "これらの「ワンクリック」データセットで Kibana の探索を始めましょう。", - "home.tutorial.card.sampleDataTitle": "サンプルデータ", - "home.tutorial.elasticCloudButtonLabel": "Elastic Cloud", - "home.tutorial.instructionSet.checkStatusButtonLabel": "ステータスを確認", - "home.tutorial.instructionSet.customizeLabel": "コードスニペットのカスタマイズ", - "home.tutorial.instructionSet.noDataLabel": "データが見つかりません", - "home.tutorial.instructionSet.statusCheckTitle": "ステータス確認", - "home.tutorial.instructionSet.successLabel": "成功", - "home.tutorial.introduction.betaLabel": "ベータ", - "home.tutorial.introduction.imageAltDescription": "プライマリダッシュボードのスクリーンショット。", - "home.tutorial.introduction.viewButtonLabel": "エクスポートされたフィールドを表示", - "home.tutorial.noTutorialLabel": "チュートリアル {tutorialId} が見つかりません", - "home.tutorial.savedObject.addedLabel": "{savedObjectsLength} 件の保存されたオブジェクトが追加されました", - "home.tutorial.savedObject.confirmButtonLabel": "上書きを確定", - "home.tutorial.savedObject.defaultButtonLabel": "Kibana オブジェクトを読み込む", - "home.tutorial.savedObject.installLabel": "インデックスパターン、ビジュアライゼーション、事前定義済みのダッシュボードをインポートします。", - "home.tutorial.savedObject.installStatusLabel": "{savedObjectsLength} オブジェクトの {overwriteErrorsLength} がすでに存在します。インポートして既存のオブジェクトを上書きするには、「上書きを確定」をクリックしてください。オブジェクトへの変更はすべて失われます。", - "home.tutorial.savedObject.loadTitle": "Kibana オブジェクトを読み込む", - "home.tutorial.savedObject.requestFailedErrorMessage": "リクエスト失敗、エラー:{message}", - "home.tutorial.savedObject.unableToAddErrorMessage": "{savedObjectsLength} 件中 {errorsLength} 件の kibana オブジェクトが追加できません。エラー:{errorMessage}", - "home.tutorial.selectionLegend": "デプロイタイプ", - "home.tutorial.selfManagedButtonLabel": "自己管理", - "home.tutorial.tabs.sampleDataTitle": "サンプルデータ", - "home.tutorial.unexpectedStatusCheckStateErrorDescription": "予期せぬステータス確認ステータス {statusCheckState}", - "home.tutorial.unhandledInstructionTypeErrorDescription": "予期せぬ指示タイプ {visibleInstructions}", - "home.tutorialDirectory.featureCatalogueDescription": "一般的なアプリやサービスからデータを取り込みます。", - "home.tutorialDirectory.featureCatalogueTitle": "データの追加", - "home.tutorials.activemqLogs.artifacts.dashboards.linkLabel": "ActiveMQ 監査イベント", - "home.tutorials.activemqLogs.longDescription": "Filebeat で ActiveMQ ログを収集します。[詳細]({learnMoreLink})", - "home.tutorials.activemqLogs.nameTitle": "ActiveMQ ログ", - "home.tutorials.activemqLogs.shortDescription": "Filebeat で ActiveMQ ログを収集します。", - "home.tutorials.activemqMetrics.artifacts.application.label": "Discover", - "home.tutorials.activemqMetrics.nameTitle": "ActiveMQ メトリック", - "home.tutorials.activemqMetrics.shortDescription": "ActiveMQ インスタンスから監視メトリックを取得します。", - "home.tutorials.aerospikeMetrics.artifacts.application.label": "Discover", - "home.tutorials.aerospikeMetrics.longDescription": "「aerospike」Metricbeatモジュールは、Aerospikeから内部メトリックを取得します。[詳細]({learnMoreLink})", - "home.tutorials.aerospikeMetrics.nameTitle": "Aerospike メトリック", - "home.tutorials.aerospikeMetrics.shortDescription": "Aerospike サーバーから内部メトリックを取得します。", - "home.tutorials.apacheLogs.artifacts.dashboards.linkLabel": "Apache ログダッシュボード", - "home.tutorials.apacheLogs.longDescription": "apache Filebeatモジュールが、Apache 2 HTTPサーバーにより作成されたアクセスとエラーのログをパースします。[詳細]({learnMoreLink})", - "home.tutorials.apacheLogs.nameTitle": "Apache ログ", - "home.tutorials.apacheLogs.shortDescription": "Apache HTTP サーバーが作成したアクセスとエラーのログを収集しパースします。", - "home.tutorials.apacheMetrics.artifacts.dashboards.linkLabel": "Apache メトリックダッシュボード", - "home.tutorials.apacheMetrics.longDescription": "「apache」Metricbeatモジュールは、Apache 2 HTTPサーバーから内部メトリックを取得します。[詳細]({learnMoreLink})", - "home.tutorials.apacheMetrics.nameTitle": "Apache メトリック", - "home.tutorials.apacheMetrics.shortDescription": "Apache 2 HTTP サーバーから内部メトリックを取得します。", - "home.tutorials.auditbeat.artifacts.dashboards.linkLabel": "セキュリティアプリ", - "home.tutorials.auditbeat.longDescription": "Auditbeat を使用してホストから監査データを収集します。これらにはプロセス、ユーザー、ログイン、ソケット情報、ファイルアクセス、その他が含まれます。[詳細]({learnMoreLink})", - "home.tutorials.auditbeat.nameTitle": "Auditbeat", - "home.tutorials.auditbeat.shortDescription": "ホストから監査データを収集します。", - "home.tutorials.auditdLogs.artifacts.dashboards.linkLabel": "監査イベント", - "home.tutorials.auditdLogs.longDescription": "モジュールは監査デーモン(「auditd」)からログを収集して解析します。[詳細]({learnMoreLink})", - "home.tutorials.auditdLogs.nameTitle": "Auditd ログ", - "home.tutorials.auditdLogs.shortDescription": "Linux auditd デーモンからログを収集します。", - "home.tutorials.awsLogs.artifacts.dashboards.linkLabel": "AWS S3 サーバーアクセスログダッシュボード", - "home.tutorials.awsLogs.longDescription": "SQS通知設定されているS3バケットにAWSログをエクスポートすることで、AWSログを収集します。[詳細]({learnMoreLink})", - "home.tutorials.awsLogs.nameTitle": "AWS S3 ベースのログ", - "home.tutorials.awsLogs.shortDescription": "Filebeat で S3 バケットから AWS ログを収集します。", - "home.tutorials.awsMetrics.artifacts.dashboards.linkLabel": "AWS メトリックダッシュボード", - "home.tutorials.awsMetrics.longDescription": "「aws」Metricbeatモジュールが、AWS APIとCloudwatchから監視メトリックを取得します。[詳細]({learnMoreLink})", - "home.tutorials.awsMetrics.nameTitle": "AWS メトリック", - "home.tutorials.awsMetrics.shortDescription": "AWS API と Cloudwatch からの EC2 インスタンスの監視メトリックです。", - "home.tutorials.azureLogs.artifacts.dashboards.linkLabel": "Apacheログダッシュボード", - "home.tutorials.azureLogs.longDescription": "「azure」Filebeatモジュールは、Azureアクティビティと監査関連ログを収集します。[詳細]({learnMoreLink})", - "home.tutorials.azureLogs.nameTitle": "Azureログ", - "home.tutorials.azureLogs.shortDescription": "Azureアクティビティと監査関連ログを収集します。", - "home.tutorials.azureMetrics.artifacts.dashboards.linkLabel": "Apacheメトリックダッシュボード", - "home.tutorials.azureMetrics.longDescription": "Metricbeatモジュール「azure」は、Azureから監視メトリックを取得します。[詳細]({learnMoreLink})", - "home.tutorials.azureMetrics.nameTitle": "Azure メトリック", - "home.tutorials.azureMetrics.shortDescription": "Azure 監視メトリックをフェッチします。", - "home.tutorials.barracudaLogs.artifacts.dashboards.linkLabel": "セキュリティアプリ", - "home.tutorials.barracudaLogs.longDescription": "これは、SyslogまたはファイルでBarracuda Web Application Firewallログを受信するためのモジュールです。[詳細]({learnMoreLink})", - "home.tutorials.barracudaLogs.nameTitle": "Barracuda ログ", - "home.tutorials.barracudaLogs.shortDescription": "Barracuda Web Application Firewall ログを syslog またはファイルから収集します。", - "home.tutorials.bluecoatLogs.artifacts.dashboards.linkLabel": "セキュリティアプリ", - "home.tutorials.bluecoatLogs.longDescription": "これは、SyslogまたはファイルでBlue Coat Directorログを受信するためのモジュールです。[詳細]({learnMoreLink})", - "home.tutorials.bluecoatLogs.nameTitle": "Blue Coat ログ", - "home.tutorials.bluecoatLogs.shortDescription": "Blue Coat Director ログを syslog またはファイルから収集します。", - "home.tutorials.cefLogs.artifacts.dashboards.linkLabel": "CEF ネットワーク概要ダッシュボード", - "home.tutorials.cefLogs.longDescription": "これは Syslog で Common Event Format(CEF)データを受信するためのモジュールです。Syslog プロトコルでメッセージが受信されると、Syslog 入力がヘッダーを解析し、タイムスタンプ値を設定します。次に、プロセッサーが適用され、CEF エンコードデータを解析します。デコードされたデータは「cef」オブジェクトフィールドに書き込まれます。CEFデータを入力できるすべてのElastic Common Schema(ECS)フィールドが入力されます。 [詳細]({learnMoreLink})", - "home.tutorials.cefLogs.nameTitle": "CEF ログ", - "home.tutorials.cefLogs.shortDescription": "Syslog で Common Event Format(CEF)ログデータを収集します。", - "home.tutorials.cephMetrics.artifacts.application.label": "Discover", - "home.tutorials.cephMetrics.longDescription": "「ceph」Metricbeatモジュールは、Cephから内部メトリックを取得します。[詳細]({learnMoreLink})", - "home.tutorials.cephMetrics.nameTitle": "Ceph メトリック", - "home.tutorials.cephMetrics.shortDescription": "Ceph サーバーから内部メトリックを取得します。", - "home.tutorials.checkpointLogs.artifacts.dashboards.linkLabel": "セキュリティアプリ", - "home.tutorials.checkpointLogs.longDescription": "これは Check Point ファイアウォールログ用のモジュールです。Syslog形式のLog Exporterからのログをサポートします。[詳細]({learnMoreLink})", - "home.tutorials.checkpointLogs.nameTitle": "Check Point ログ", - "home.tutorials.checkpointLogs.shortDescription": "Check Point ファイアウォールログを収集します。", - "home.tutorials.ciscoLogs.artifacts.dashboards.linkLabel": "ASA ファイアウォールダッシュボード", - "home.tutorials.ciscoLogs.longDescription": "これは Cisco ネットワークデバイスのログ用のモジュールです(ASA、FTD、IOS、Nexus)。Syslogのログまたはファイルから読み取られたログを受信するための次のファイルセットが含まれます。[詳細]({learnMoreLink})", - "home.tutorials.ciscoLogs.nameTitle": "Cisco ログ", - "home.tutorials.ciscoLogs.shortDescription": "Syslog またはファイルから Cisco ネットワークデバイスログを収集します。", - "home.tutorials.cloudwatchLogs.longDescription": "FunctionbeatをAWS Lambda関数として実行するようデプロイし、Cloudwatchログを収集します。 [詳細]({learnMoreLink})", - "home.tutorials.cloudwatchLogs.nameTitle": "AWS Cloudwatch ログ", - "home.tutorials.cloudwatchLogs.shortDescription": "Functionbeat で Cloudwatch ログを収集します。", - "home.tutorials.cockroachdbMetrics.artifacts.dashboards.linkLabel": "CockroachDB メトリックダッシュボード", - "home.tutorials.cockroachdbMetrics.longDescription": "Metricbeatモジュール「cockroachdb」は、CockroachDBから監視メトリックを取得します。[詳細]({learnMoreLink})", - "home.tutorials.cockroachdbMetrics.nameTitle": "CockroachDB メトリック", - "home.tutorials.cockroachdbMetrics.shortDescription": "CockroachDB サーバーから監視メトリックを取得します。", - "home.tutorials.common.auditbeat.cloudInstructions.gettingStarted.title": "はじめに", - "home.tutorials.common.auditbeat.premCloudInstructions.gettingStarted.title": "はじめに", - "home.tutorials.common.auditbeat.premInstructions.gettingStarted.title": "はじめに", - "home.tutorials.common.auditbeatCloudInstructions.config.debTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "home.tutorials.common.auditbeatCloudInstructions.config.debTitle": "構成を編集する", - "home.tutorials.common.auditbeatCloudInstructions.config.osxTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "home.tutorials.common.auditbeatCloudInstructions.config.osxTitle": "構成を編集する", - "home.tutorials.common.auditbeatCloudInstructions.config.rpmTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "home.tutorials.common.auditbeatCloudInstructions.config.rpmTitle": "構成を編集する", - "home.tutorials.common.auditbeatCloudInstructions.config.windowsTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "home.tutorials.common.auditbeatCloudInstructions.config.windowsTitle": "構成を編集する", - "home.tutorials.common.auditbeatInstructions.config.debTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワード、{esUrlTemplate} が Elasticsearch の URL、{kibanaUrlTemplate} が Kibana の URL です。", - "home.tutorials.common.auditbeatInstructions.config.debTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "home.tutorials.common.auditbeatInstructions.config.debTitle": "構成を編集する", - "home.tutorials.common.auditbeatInstructions.config.osxTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワード、{esUrlTemplate} が Elasticsearch の URL、{kibanaUrlTemplate} が Kibana の URL です。", - "home.tutorials.common.auditbeatInstructions.config.osxTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "home.tutorials.common.auditbeatInstructions.config.osxTitle": "構成を編集する", - "home.tutorials.common.auditbeatInstructions.config.rpmTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワード、{esUrlTemplate} が Elasticsearch の URL、{kibanaUrlTemplate} が Kibana の URL です。", - "home.tutorials.common.auditbeatInstructions.config.rpmTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "home.tutorials.common.auditbeatInstructions.config.rpmTitle": "構成を編集する", - "home.tutorials.common.auditbeatInstructions.config.windowsTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワード、{esUrlTemplate} が Elasticsearch の URL、{kibanaUrlTemplate} が Kibana の URL です。", - "home.tutorials.common.auditbeatInstructions.config.windowsTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "home.tutorials.common.auditbeatInstructions.config.windowsTitle": "構成を編集する", - "home.tutorials.common.auditbeatInstructions.install.debTextPost": "32 ビットパッケージをお探しですか?[ダウンロードページ]({linkUrl})をご覧ください。", - "home.tutorials.common.auditbeatInstructions.install.debTextPre": "Auditbeatは初めてですか?[クイックスタート]({linkUrl})を参照してください。", - "home.tutorials.common.auditbeatInstructions.install.debTitle": "Auditbeat のダウンロードとインストール", - "home.tutorials.common.auditbeatInstructions.install.osxTextPre": "Auditbeatは初めてですか?[クイックスタート]({linkUrl})を参照してください。", - "home.tutorials.common.auditbeatInstructions.install.osxTitle": "Auditbeat のダウンロードとインストール", - "home.tutorials.common.auditbeatInstructions.install.rpmTextPost": "32 ビットパッケージをお探しですか?[ダウンロードページ]({linkUrl})をご覧ください。", - "home.tutorials.common.auditbeatInstructions.install.rpmTextPre": "Auditbeatは初めてですか?[クイックスタート]({linkUrl})を参照してください。", - "home.tutorials.common.auditbeatInstructions.install.rpmTitle": "Auditbeat のダウンロードとインストール", - "home.tutorials.common.auditbeatInstructions.install.windowsTextPost": "{auditbeatPath} ファイルの {propertyName} を Elasticsearch のインストールに設定します。", - "home.tutorials.common.auditbeatInstructions.install.windowsTextPre": "Auditbeatは初めてですか?[クイックスタート]({guideLinkUrl})を参照してください。\n 1.[ダウンロード]({auditbeatLinkUrl})ページからAuditbeat Windows zipファイルをダウンロードします。\n 2.zipファイルのコンテンツを{folderPath}に解凍します。\n 3.「{directoryName}」ディレクトリの名前を「Auditbeat」に変更します。\n 4.管理者としてPowerShellプロンプトを開きます(PowerShellアイコンを右クリックして「管理者として実行」を選択します)。Windows XPをご使用の場合、PowerShellのダウンロードとインストールが必要な場合があります。\n 5.PowerShell プロンプトで次のコマンドを実行し、Auditbeat を Windows サービスとしてインストールします。", - "home.tutorials.common.auditbeatInstructions.install.windowsTitle": "Auditbeat のダウンロードとインストール", - "home.tutorials.common.auditbeatInstructions.start.debTextPre": "「setup」コマンドで Kibana のダッシュボードを読み込みます。ダッシュボードがすでにセットアップされている場合、このコマンドは省略します。", - "home.tutorials.common.auditbeatInstructions.start.debTitle": "Auditbeat を起動", - "home.tutorials.common.auditbeatInstructions.start.osxTextPre": "「setup」コマンドで Kibana のダッシュボードを読み込みます。ダッシュボードがすでにセットアップされている場合、このコマンドは省略します。", - "home.tutorials.common.auditbeatInstructions.start.osxTitle": "Auditbeat を起動", - "home.tutorials.common.auditbeatInstructions.start.rpmTextPre": "「setup」コマンドで Kibana のダッシュボードを読み込みます。ダッシュボードがすでにセットアップされている場合、このコマンドは省略します。", - "home.tutorials.common.auditbeatInstructions.start.rpmTitle": "Auditbeat を起動", - "home.tutorials.common.auditbeatInstructions.start.windowsTextPre": "「setup」コマンドで Kibana のダッシュボードを読み込みます。ダッシュボードがすでにセットアップされている場合、このコマンドは省略します。", - "home.tutorials.common.auditbeatInstructions.start.windowsTitle": "Auditbeat を起動", - "home.tutorials.common.auditbeatStatusCheck.buttonLabel": "データを確認してください", - "home.tutorials.common.auditbeatStatusCheck.errorText": "まだデータを受信していません", - "home.tutorials.common.auditbeatStatusCheck.successText": "データを受信しました", - "home.tutorials.common.auditbeatStatusCheck.text": "Auditbeat からデータを受け取ったことを確認してください。", - "home.tutorials.common.auditbeatStatusCheck.title": "ステータス", - "home.tutorials.common.cloudInstructions.passwordAndResetLink": "{passwordTemplate}が「Elastic」ユーザーのパスワードです。\\{#config.cloud.profileUrl\\}\n パスワードを忘れた場合[Elastic Cloudでリセットしてください](\\{config.cloud.baseUrl\\}\\{config.cloud.profileUrl\\})。\n \\{/config.cloud.profileUrl\\}", - "home.tutorials.common.filebeat.cloudInstructions.gettingStarted.title": "はじめに", - "home.tutorials.common.filebeat.premCloudInstructions.gettingStarted.title": "はじめに", - "home.tutorials.common.filebeat.premInstructions.gettingStarted.title": "はじめに", - "home.tutorials.common.filebeatCloudInstructions.config.debTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "home.tutorials.common.filebeatCloudInstructions.config.debTitle": "構成を編集する", - "home.tutorials.common.filebeatCloudInstructions.config.osxTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "home.tutorials.common.filebeatCloudInstructions.config.osxTitle": "構成を編集する", - "home.tutorials.common.filebeatCloudInstructions.config.rpmTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "home.tutorials.common.filebeatCloudInstructions.config.rpmTitle": "構成を編集する", - "home.tutorials.common.filebeatCloudInstructions.config.windowsTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "home.tutorials.common.filebeatCloudInstructions.config.windowsTitle": "構成を編集する", - "home.tutorials.common.filebeatEnableInstructions.debTextPost": "「/etc/filebeat/modules.d/{moduleName}.yml」ファイルで設定を変更します。", - "home.tutorials.common.filebeatEnableInstructions.debTitle": "{moduleName} モジュールを有効にし構成します", - "home.tutorials.common.filebeatEnableInstructions.osxTextPost": "「modules.d/{moduleName}.yml」」ファイルで設定を変更します。", - "home.tutorials.common.filebeatEnableInstructions.osxTextPre": "インストールディレクトリから次のファイルを実行します:", - "home.tutorials.common.filebeatEnableInstructions.osxTitle": "{moduleName} モジュールを有効にし構成します", - "home.tutorials.common.filebeatEnableInstructions.rpmTextPost": "「/etc/filebeat/modules.d/{moduleName}.yml」ファイルで設定を変更します。", - "home.tutorials.common.filebeatEnableInstructions.rpmTitle": "{moduleName} モジュールを有効にし構成します", - "home.tutorials.common.filebeatEnableInstructions.windowsTextPost": "「modules.d/{moduleName}.yml」」ファイルで設定を変更します。", - "home.tutorials.common.filebeatEnableInstructions.windowsTextPre": "「{path}」フォルダから次のファイルを実行します:", - "home.tutorials.common.filebeatEnableInstructions.windowsTitle": "{moduleName} モジュールを有効にし構成します", - "home.tutorials.common.filebeatInstructions.config.debTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワード、{esUrlTemplate} が Elasticsearch の URL、{kibanaUrlTemplate} が Kibana の URL です。", - "home.tutorials.common.filebeatInstructions.config.debTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "home.tutorials.common.filebeatInstructions.config.debTitle": "構成を編集する", - "home.tutorials.common.filebeatInstructions.config.osxTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワード、{esUrlTemplate} が Elasticsearch の URL、{kibanaUrlTemplate} が Kibana の URL です。", - "home.tutorials.common.filebeatInstructions.config.osxTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "home.tutorials.common.filebeatInstructions.config.osxTitle": "構成を編集する", - "home.tutorials.common.filebeatInstructions.config.rpmTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワード、{esUrlTemplate} が Elasticsearch の URL、{kibanaUrlTemplate} が Kibana の URL です。", - "home.tutorials.common.filebeatInstructions.config.rpmTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "home.tutorials.common.filebeatInstructions.config.rpmTitle": "構成を編集する", - "home.tutorials.common.filebeatInstructions.config.windowsTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワード、{esUrlTemplate} が Elasticsearch の URL、{kibanaUrlTemplate} が Kibana の URL です。", - "home.tutorials.common.filebeatInstructions.config.windowsTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "home.tutorials.common.filebeatInstructions.config.windowsTitle": "構成を編集する", - "home.tutorials.common.filebeatInstructions.install.debTextPost": "32 ビットパッケージをお探しですか?[ダウンロードページ]({linkUrl})をご覧ください。", - "home.tutorials.common.filebeatInstructions.install.debTextPre": "Filebeatは初めてですか?[クイックスタート]({linkUrl})を参照してください。", - "home.tutorials.common.filebeatInstructions.install.debTitle": "Filebeat のダウンロードとインストール", - "home.tutorials.common.filebeatInstructions.install.osxTextPre": "Filebeatは初めてですか?[クイックスタート]({linkUrl})を参照してください。", - "home.tutorials.common.filebeatInstructions.install.osxTitle": "Filebeat のダウンロードとインストール", - "home.tutorials.common.filebeatInstructions.install.rpmTextPost": "32 ビットパッケージをお探しですか?[ダウンロードページ]({linkUrl})をご覧ください。", - "home.tutorials.common.filebeatInstructions.install.rpmTextPre": "Filebeatは初めてですか?[クイックスタート]({linkUrl})を参照してください。", - "home.tutorials.common.filebeatInstructions.install.rpmTitle": "Filebeat のダウンロードとインストール", - "home.tutorials.common.filebeatInstructions.install.windowsTextPost": "{filebeatPath} ファイルの {propertyName} を Elasticsearch のインストールに設定します。", - "home.tutorials.common.filebeatInstructions.install.windowsTextPre": "Filebeatは初めてですか?[クイックスタート]({guideLinkUrl})を参照してください。\n 1.[ダウンロード]({filebeatLinkUrl})ページからFilebeat Windows zipファイルをダウンロードします。\n 2.zipファイルのコンテンツを{folderPath}に解凍します。\n 3.「{directoryName}」ディレクトリの名前を「Filebeat」に変更します。\n 4.管理者としてPowerShellプロンプトを開きます(PowerShellアイコンを右クリックして「管理者として実行」を選択します)。Windows XPをご使用の場合、PowerShellのダウンロードとインストールが必要な場合があります。\n 5.PowerShell プロンプトで次のコマンドを実行し、Filebeat を Windows サービスとしてインストールします。", - "home.tutorials.common.filebeatInstructions.install.windowsTitle": "Filebeat のダウンロードとインストール", - "home.tutorials.common.filebeatInstructions.start.debTextPre": "「setup」コマンドで Kibana のダッシュボードを読み込みます。ダッシュボードがすでにセットアップされている場合、このコマンドは省略します。", - "home.tutorials.common.filebeatInstructions.start.debTitle": "Filebeat を起動します", - "home.tutorials.common.filebeatInstructions.start.osxTextPre": "「setup」コマンドで Kibana のダッシュボードを読み込みます。ダッシュボードがすでにセットアップされている場合、このコマンドは省略します。", - "home.tutorials.common.filebeatInstructions.start.osxTitle": "Filebeat を起動します", - "home.tutorials.common.filebeatInstructions.start.rpmTextPre": "「setup」コマンドで Kibana のダッシュボードを読み込みます。ダッシュボードがすでにセットアップされている場合、このコマンドは省略します。", - "home.tutorials.common.filebeatInstructions.start.rpmTitle": "Filebeat を起動します", - "home.tutorials.common.filebeatInstructions.start.windowsTextPre": "「setup」コマンドで Kibana のダッシュボードを読み込みます。ダッシュボードがすでにセットアップされている場合、このコマンドは省略します。", - "home.tutorials.common.filebeatInstructions.start.windowsTitle": "Filebeat を起動", - "home.tutorials.common.filebeatStatusCheck.buttonLabel": "データを確認してください", - "home.tutorials.common.filebeatStatusCheck.errorText": "モジュールからまだデータを受け取っていません", - "home.tutorials.common.filebeatStatusCheck.successText": "このモジュールからデータを受け取りました", - "home.tutorials.common.filebeatStatusCheck.text": "Filebeat の「{moduleName}」モジュールからデータを受け取ったことを確認してください。", - "home.tutorials.common.filebeatStatusCheck.title": "モジュールステータス", - "home.tutorials.common.functionbeat.cloudInstructions.gettingStarted.title": "はじめに", - "home.tutorials.common.functionbeat.premCloudInstructions.gettingStarted.title": "はじめに", - "home.tutorials.common.functionbeat.premInstructions.gettingStarted.title": "はじめに", - "home.tutorials.common.functionbeatAWSInstructions.textPost": "「」と「」がアカウント資格情報、「us-east-1」がご希望の地域です。", - "home.tutorials.common.functionbeatAWSInstructions.textPre": "環境で AWS アカウント認証情報を設定します。", - "home.tutorials.common.functionbeatAWSInstructions.title": "AWS 認証情報の設定", - "home.tutorials.common.functionbeatCloudInstructions.config.osxTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "home.tutorials.common.functionbeatCloudInstructions.config.osxTitle": "構成を編集する", - "home.tutorials.common.functionbeatCloudInstructions.config.windowsTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "home.tutorials.common.functionbeatCloudInstructions.config.windowsTitle": "構成を編集する", - "home.tutorials.common.functionbeatEnableOnPremInstructions.defaultTextPost": "「」が投入するロググループの名前で、「」が Functionbeat デプロイのステージングに使用されるが有効な S3 バケット名です。", - "home.tutorials.common.functionbeatEnableOnPremInstructions.defaultTitle": "Cloudwatch ロググループの構成", - "home.tutorials.common.functionbeatEnableOnPremInstructionsOSXLinux.textPre": "「functionbeat.yml」ファイルで設定を変更します。", - "home.tutorials.common.functionbeatEnableOnPremInstructionsWindows.textPre": "{path} ファイルで設定を変更します。", - "home.tutorials.common.functionbeatInstructions.config.osxTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワード、{esUrlTemplate} が Elasticsearch の URL、{kibanaUrlTemplate} が Kibana の URL です。", - "home.tutorials.common.functionbeatInstructions.config.osxTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "home.tutorials.common.functionbeatInstructions.config.osxTitle": "Elastic クラスターの構成", - "home.tutorials.common.functionbeatInstructions.config.windowsTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワード、{esUrlTemplate} が Elasticsearch の URL、{kibanaUrlTemplate} が Kibana の URL です。", - "home.tutorials.common.functionbeatInstructions.config.windowsTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "home.tutorials.common.functionbeatInstructions.config.windowsTitle": "構成を編集する", - "home.tutorials.common.functionbeatInstructions.deploy.osxTextPre": "これにより Functionbeat が Lambda 関数としてインストールされます「setup」コマンドで Elasticsearch の構成を確認し、Kibana インデックスパターンを読み込みます。通常このコマンドを省いても大丈夫です。", - "home.tutorials.common.functionbeatInstructions.deploy.osxTitle": "Functionbeat を AWS Lambda にデプロイ", - "home.tutorials.common.functionbeatInstructions.deploy.windowsTextPre": "これにより Functionbeat が Lambda 関数としてインストールされます「setup」コマンドで Elasticsearch の構成を確認し、Kibana インデックスパターンを読み込みます。通常このコマンドを省いても大丈夫です。", - "home.tutorials.common.functionbeatInstructions.deploy.windowsTitle": "Functionbeat を AWS Lambda にデプロイ", - "home.tutorials.common.functionbeatInstructions.install.linuxTextPre": "Functionbeatは初めてですか?[クイックスタート]({link})を参照してください。", - "home.tutorials.common.functionbeatInstructions.install.linuxTitle": "Functionbeat のダウンロードとインストール", - "home.tutorials.common.functionbeatInstructions.install.osxTextPre": "Functionbeatは初めてですか?[クイックスタート]({link})を参照してください。", - "home.tutorials.common.functionbeatInstructions.install.osxTitle": "Functionbeat のダウンロードとインストール", - "home.tutorials.common.functionbeatInstructions.install.windowsTextPre": "Functionbeatは初めてですか?[クイックスタート]({functionbeatLink})を参照してください。\n 1.[ダウンロード]({elasticLink})ページからFunctionbeat Windows zipファイルをダウンロードします。\n 2.zipファイルのコンテンツを{folderPath}に解凍します。\n 3.「{directoryName} ディレクトリの名前を「Functionbeat」に変更します。\n 4.管理者としてPowerShellプロンプトを開きます(PowerShellアイコンを右クリックして「管理者として実行」を選択します)。Windows XPをご使用の場合、PowerShellのダウンロードとインストールが必要な場合があります。\n 5.PowerShell プロンプトから、Functionbeat ディレクトリに移動します:", - "home.tutorials.common.functionbeatInstructions.install.windowsTitle": "Functionbeat のダウンロードとインストール", - "home.tutorials.common.functionbeatStatusCheck.buttonLabel": "データを確認してください", - "home.tutorials.common.functionbeatStatusCheck.errorText": "Functionbeat からまだデータを受け取っていません", - "home.tutorials.common.functionbeatStatusCheck.successText": "Functionbeat からデータを受け取りました", - "home.tutorials.common.functionbeatStatusCheck.text": "Functionbeat からデータを受け取ったことを確認してください。", - "home.tutorials.common.functionbeatStatusCheck.title": "Functionbeat ステータス", - "home.tutorials.common.heartbeat.cloudInstructions.gettingStarted.title": "はじめに", - "home.tutorials.common.heartbeat.premCloudInstructions.gettingStarted.title": "はじめに", - "home.tutorials.common.heartbeat.premInstructions.gettingStarted.title": "はじめに", - "home.tutorials.common.heartbeatCloudInstructions.config.debTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "home.tutorials.common.heartbeatCloudInstructions.config.debTitle": "構成を編集する", - "home.tutorials.common.heartbeatCloudInstructions.config.osxTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "home.tutorials.common.heartbeatCloudInstructions.config.osxTitle": "構成を編集する", - "home.tutorials.common.heartbeatCloudInstructions.config.rpmTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "home.tutorials.common.heartbeatCloudInstructions.config.rpmTitle": "構成を編集する", - "home.tutorials.common.heartbeatCloudInstructions.config.windowsTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "home.tutorials.common.heartbeatCloudInstructions.config.windowsTitle": "構成を編集する", - "home.tutorials.common.heartbeatEnableCloudInstructions.debTextPre": "「heartbeat.yml」ファイルの「heartbeat.monitors」設定を変更します。", - "home.tutorials.common.heartbeatEnableCloudInstructions.defaultTextPost": "Heartbeatのモニターの設定の詳細は、[Heartbeat設定ドキュメント]({configureLink})をご覧ください。", - "home.tutorials.common.heartbeatEnableCloudInstructions.defaultTitle": "構成を変更 - 監視を追加", - "home.tutorials.common.heartbeatEnableCloudInstructions.osxTextPre": "「heartbeat.yml」ファイルの「heartbeat.monitors」設定を変更します。", - "home.tutorials.common.heartbeatEnableCloudInstructions.rpmTextPre": "「heartbeat.yml」ファイルの「heartbeat.monitors」設定を変更します。", - "home.tutorials.common.heartbeatEnableCloudInstructions.windowsTextPre": "「heartbeat.yml」ファイルの「heartbeat.monitors」設定を変更します。", - "home.tutorials.common.heartbeatEnableOnPremInstructions.debTextPre": "「heartbeat.yml」ファイルの「heartbeat.monitors」設定を変更します。", - "home.tutorials.common.heartbeatEnableOnPremInstructions.defaultTextPost": "{hostTemplate}は監視対象のURLです。Heartbeatの監視を構成する手順の詳細は、[Heartbeat構成ドキュメント]({configureLink})をご覧ください。", - "home.tutorials.common.heartbeatEnableOnPremInstructions.defaultTitle": "構成を変更 - 監視を追加", - "home.tutorials.common.heartbeatEnableOnPremInstructions.osxTextPre": "「heartbeat.yml」ファイルの「heartbeat.monitors」設定を変更します。", - "home.tutorials.common.heartbeatEnableOnPremInstructions.rpmTextPre": "「heartbeat.yml」ファイルの「heartbeat.monitors」設定を変更します。", - "home.tutorials.common.heartbeatEnableOnPremInstructions.windowsTextPre": "「heartbeat.yml」ファイルの「heartbeat.monitors」設定を変更します。", - "home.tutorials.common.heartbeatInstructions.config.debTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワード、{esUrlTemplate} が Elasticsearch の URL、{kibanaUrlTemplate} が Kibana の URL です。", - "home.tutorials.common.heartbeatInstructions.config.debTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "home.tutorials.common.heartbeatInstructions.config.debTitle": "構成を編集する", - "home.tutorials.common.heartbeatInstructions.config.osxTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワード、{esUrlTemplate} が Elasticsearch の URL、{kibanaUrlTemplate} が Kibana の URL です。", - "home.tutorials.common.heartbeatInstructions.config.osxTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "home.tutorials.common.heartbeatInstructions.config.osxTitle": "構成を編集する", - "home.tutorials.common.heartbeatInstructions.config.rpmTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワード、{esUrlTemplate} が Elasticsearch の URL、{kibanaUrlTemplate} が Kibana の URL です。", - "home.tutorials.common.heartbeatInstructions.config.rpmTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "home.tutorials.common.heartbeatInstructions.config.rpmTitle": "構成を編集する", - "home.tutorials.common.heartbeatInstructions.config.windowsTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワード、{esUrlTemplate} が Elasticsearch の URL、{kibanaUrlTemplate} が Kibana の URL です。", - "home.tutorials.common.heartbeatInstructions.config.windowsTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "home.tutorials.common.heartbeatInstructions.config.windowsTitle": "構成を編集する", - "home.tutorials.common.heartbeatInstructions.install.debTextPost": "32 ビットパッケージをお探しですか?[ダウンロードページ]({link})をご覧ください。", - "home.tutorials.common.heartbeatInstructions.install.debTextPre": "Heartbeatは初めてですか?[クイックスタート]({link})を参照してください。", - "home.tutorials.common.heartbeatInstructions.install.debTitle": "Heartbeat のダウンロードとインストール", - "home.tutorials.common.heartbeatInstructions.install.osxTextPre": "Heartbeatは初めてですか?[クイックスタート]({link})を参照してください。", - "home.tutorials.common.heartbeatInstructions.install.osxTitle": "Heartbeat のダウンロードとインストール", - "home.tutorials.common.heartbeatInstructions.install.rpmTextPre": "Heartbeatは初めてですか?[クイックスタート]({link})を参照してください。", - "home.tutorials.common.heartbeatInstructions.install.rpmTitle": "Heartbeat のダウンロードとインストール", - "home.tutorials.common.heartbeatInstructions.install.windowsTextPre": "Heartbeatは初めてですか?[クイックスタート]({heartbeatLink})を参照してください。\n 1.[ダウンロード]({elasticLink})ページからHeartbeat Windows zipファイルをダウンロードします。\n 2.zipファイルのコンテンツを{folderPath}に解凍します。\n 3.「{directoryName} ディレクトリの名前を「Heartbeat」に変更します。\n 4.管理者としてPowerShellプロンプトを開きます(PowerShellアイコンを右クリックして「管理者として実行」を選択します)。Windows XPをご使用の場合、PowerShellのダウンロードとインストールが必要な場合があります。\n 5.PowerShell プロンプトで次のコマンドを実行し、Heartbeat を Windows サービスとしてインストールします。", - "home.tutorials.common.heartbeatInstructions.install.windowsTitle": "Heartbeat のダウンロードとインストール", - "home.tutorials.common.heartbeatInstructions.start.debTextPre": "「setup」コマンドで Kibana のインデックスパターンを読み込みます。", - "home.tutorials.common.heartbeatInstructions.start.debTitle": "Heartbeat を起動します", - "home.tutorials.common.heartbeatInstructions.start.osxTextPre": "「setup」コマンドで Kibana のインデックスパターンを読み込みます。", - "home.tutorials.common.heartbeatInstructions.start.osxTitle": "Heartbeat を起動します", - "home.tutorials.common.heartbeatInstructions.start.rpmTextPre": "「setup」コマンドで Kibana のインデックスパターンを読み込みます。", - "home.tutorials.common.heartbeatInstructions.start.rpmTitle": "Heartbeat を起動します", - "home.tutorials.common.heartbeatInstructions.start.windowsTextPre": "「setup」コマンドで Kibana のインデックスパターンを読み込みます。", - "home.tutorials.common.heartbeatInstructions.start.windowsTitle": "Heartbeat を起動します", - "home.tutorials.common.heartbeatStatusCheck.buttonLabel": "データを確認してください", - "home.tutorials.common.heartbeatStatusCheck.errorText": "Heartbeat からまだデータを受け取っていません", - "home.tutorials.common.heartbeatStatusCheck.successText": "Heartbeat からデータを受け取りました", - "home.tutorials.common.heartbeatStatusCheck.text": "Heartbeat からデータを受け取ったことを確認してください。", - "home.tutorials.common.heartbeatStatusCheck.title": "Heartbeat のステータス", - "home.tutorials.common.logstashInstructions.install.java.osxTextPre": "[こちら]({link})のインストール手順に従ってください。", - "home.tutorials.common.logstashInstructions.install.java.osxTitle": "Java Runtime Environment のダウンロードとインストール", - "home.tutorials.common.logstashInstructions.install.java.windowsTextPre": "[こちら]({link})のインストール手順に従ってください。", - "home.tutorials.common.logstashInstructions.install.java.windowsTitle": "Java Runtime Environment のダウンロードとインストール", - "home.tutorials.common.logstashInstructions.install.logstash.osxTextPre": "Logstash は初めてですか? [入門ガイド]({link})をご覧ください。", - "home.tutorials.common.logstashInstructions.install.logstash.osxTitle": "Logstash のダウンロードとインストール", - "home.tutorials.common.logstashInstructions.install.logstash.windowsTextPre": "Logstash は初めてですか? [入門ガイド]({logstashLink})をご覧ください。\n 1.Logstash Windows zipファイルを[ダウンロード]({elasticLink})します。\n 2.zip ファイルのコンテンツを展開します。", - "home.tutorials.common.logstashInstructions.install.logstash.windowsTitle": "Logstash のダウンロードとインストール", - "home.tutorials.common.metricbeat.cloudInstructions.gettingStarted.title": "はじめに", - "home.tutorials.common.metricbeat.premCloudInstructions.gettingStarted.title": "はじめに", - "home.tutorials.common.metricbeat.premInstructions.gettingStarted.title": "はじめに", - "home.tutorials.common.metricbeatCloudInstructions.config.debTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "home.tutorials.common.metricbeatCloudInstructions.config.debTitle": "構成を編集する", - "home.tutorials.common.metricbeatCloudInstructions.config.osxTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "home.tutorials.common.metricbeatCloudInstructions.config.osxTitle": "構成を編集する", - "home.tutorials.common.metricbeatCloudInstructions.config.rpmTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "home.tutorials.common.metricbeatCloudInstructions.config.rpmTitle": "構成を編集する", - "home.tutorials.common.metricbeatCloudInstructions.config.windowsTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "home.tutorials.common.metricbeatCloudInstructions.config.windowsTitle": "構成を編集する", - "home.tutorials.common.metricbeatEnableInstructions.debTextPost": "「/etc/metricbeat/modules.d/{moduleName}.yml」ファイルで設定を変更します。", - "home.tutorials.common.metricbeatEnableInstructions.debTitle": "{moduleName} モジュールを有効にし構成します", - "home.tutorials.common.metricbeatEnableInstructions.osxTextPost": "「modules.d/{moduleName}.yml」」ファイルで設定を変更します。", - "home.tutorials.common.metricbeatEnableInstructions.osxTextPre": "インストールディレクトリから次のファイルを実行します:", - "home.tutorials.common.metricbeatEnableInstructions.osxTitle": "{moduleName} モジュールを有効にし構成します", - "home.tutorials.common.metricbeatEnableInstructions.rpmTextPost": "「/etc/metricbeat/modules.d/{moduleName}.yml」ファイルで設定を変更します。", - "home.tutorials.common.metricbeatEnableInstructions.rpmTitle": "{moduleName} モジュールを有効にし構成します", - "home.tutorials.common.metricbeatEnableInstructions.windowsTextPost": "「modules.d/{moduleName}.yml」」ファイルで設定を変更します。", - "home.tutorials.common.metricbeatEnableInstructions.windowsTextPre": "「{path}」フォルダから次のファイルを実行します:", - "home.tutorials.common.metricbeatEnableInstructions.windowsTitle": "{moduleName} モジュールを有効にし構成します", - "home.tutorials.common.metricbeatInstructions.config.debTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワード、{esUrlTemplate} が Elasticsearch の URL、{kibanaUrlTemplate} が Kibana の URL です。", - "home.tutorials.common.metricbeatInstructions.config.debTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "home.tutorials.common.metricbeatInstructions.config.debTitle": "構成を編集する", - "home.tutorials.common.metricbeatInstructions.config.osxTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワード、{esUrlTemplate} が Elasticsearch の URL、{kibanaUrlTemplate} が Kibana の URL です。", - "home.tutorials.common.metricbeatInstructions.config.osxTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "home.tutorials.common.metricbeatInstructions.config.osxTitle": "構成を編集する", - "home.tutorials.common.metricbeatInstructions.config.rpmTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワード、{esUrlTemplate} が Elasticsearch の URL、{kibanaUrlTemplate} が Kibana の URL です。", - "home.tutorials.common.metricbeatInstructions.config.rpmTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "home.tutorials.common.metricbeatInstructions.config.rpmTitle": "構成を編集する", - "home.tutorials.common.metricbeatInstructions.config.windowsTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワード、{esUrlTemplate} が Elasticsearch の URL、{kibanaUrlTemplate} が Kibana の URL です。", - "home.tutorials.common.metricbeatInstructions.config.windowsTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "home.tutorials.common.metricbeatInstructions.config.windowsTitle": "構成を編集する", - "home.tutorials.common.metricbeatInstructions.install.debTextPost": "32 ビットパッケージをお探しですか?[ダウンロードページ]({link})をご覧ください。", - "home.tutorials.common.metricbeatInstructions.install.debTextPre": "Metricbeatは初めてですか?[クイックスタート]({link})を参照してください。", - "home.tutorials.common.metricbeatInstructions.install.debTitle": "Metricbeat のダウンロードとインストール", - "home.tutorials.common.metricbeatInstructions.install.osxTextPre": "Metricbeatは初めてですか?[クイックスタート]({link})を参照してください。", - "home.tutorials.common.metricbeatInstructions.install.osxTitle": "Metricbeat のダウンロードとインストール", - "home.tutorials.common.metricbeatInstructions.install.rpmTextPre": "Metricbeatは初めてですか?[クイックスタート]({link})を参照してください。", - "home.tutorials.common.metricbeatInstructions.install.rpmTitle": "Metricbeat のダウンロードとインストール", - "home.tutorials.common.metricbeatInstructions.install.windowsTextPost": "{path} ファイルの「output.elasticsearch」を Elasticsearch のインストールに設定します。", - "home.tutorials.common.metricbeatInstructions.install.windowsTextPre": "Metricbeatは初めてですか?[クイックスタート]({metricbeatLink})を参照してください。\n 1.[ダウンロード]({elasticLink})ページからMetricbeat Windows zipファイルをダウンロードします。\n 2.zipファイルのコンテンツを{folderPath}に解凍します。\n 3.{directoryName}ディレクトリの名前を「Metricbeat」に変更します。\n 4.管理者としてPowerShellプロンプトを開きます(PowerShellアイコンを右クリックして「管理者として実行」を選択します)。Windows XPをご使用の場合、PowerShellのダウンロードとインストールが必要な場合があります。\n 5.PowerShell プロンプトで次のコマンドを実行し、Metricbeat を Windows サービスとしてインストールします。", - "home.tutorials.common.metricbeatInstructions.install.windowsTitle": "Metricbeat のダウンロードとインストール", - "home.tutorials.common.metricbeatInstructions.start.debTextPre": "「setup」コマンドで Kibana のダッシュボードを読み込みます。ダッシュボードがすでにセットアップされている場合、このコマンドは省略します。", - "home.tutorials.common.metricbeatInstructions.start.debTitle": "Metricbeat を起動します", - "home.tutorials.common.metricbeatInstructions.start.osxTextPre": "「setup」コマンドで Kibana のダッシュボードを読み込みます。ダッシュボードがすでにセットアップされている場合、このコマンドは省略します。", - "home.tutorials.common.metricbeatInstructions.start.osxTitle": "Metricbeat を起動します", - "home.tutorials.common.metricbeatInstructions.start.rpmTextPre": "「setup」コマンドで Kibana のダッシュボードを読み込みます。ダッシュボードがすでにセットアップされている場合、このコマンドは省略します。", - "home.tutorials.common.metricbeatInstructions.start.rpmTitle": "Metricbeat を起動します", - "home.tutorials.common.metricbeatInstructions.start.windowsTextPre": "「setup」コマンドで Kibana のダッシュボードを読み込みます。ダッシュボードがすでにセットアップされている場合、このコマンドは省略します。", - "home.tutorials.common.metricbeatInstructions.start.windowsTitle": "Metricbeat を起動します", - "home.tutorials.common.metricbeatStatusCheck.buttonLabel": "データを確認してください", - "home.tutorials.common.metricbeatStatusCheck.errorText": "モジュールからまだデータを受け取っていません", - "home.tutorials.common.metricbeatStatusCheck.successText": "このモジュールからデータを受け取りました", - "home.tutorials.common.metricbeatStatusCheck.text": "Metricbeat の「{moduleName}」モジュールからデータを受け取ったことを確認してください", - "home.tutorials.common.metricbeatStatusCheck.title": "モジュールステータス", - "home.tutorials.common.premCloudInstructions.option1.textPre": "[Elastic Cloud]({link})にアクセスします。アカウントをお持ちでない場合は新規登録してください。14 日間の無料トライアルがご利用いただけます。\n\nElastic Cloud コンソールにログインします\n\nElastic Cloud コンソールで次の手順に従ってクラスターを作成します。\n 1.[デプロイを作成]を選択して[デプロイ名]を指定します\n 2.必要に応じて他のデプロイオプションを変更します(デフォルトも使い始めるのに有効です)\n 3.「デプロイを作成」をクリックします\n 4.デプロイの作成が完了するまで待ちます\n 5.新規クラウド Kibana インスタンスにアクセスし、Kibana ホームの手順に従います。", - "home.tutorials.common.premCloudInstructions.option1.title": "オプション 1:Elastic Cloud でお試しください", - "home.tutorials.common.premCloudInstructions.option2.textPre": "この Kibana インスタンスをマネージド Elasticsearch インスタンスに対して実行している場合は、手動セットアップを行います。\n\n「Elasticsearch」エンドポイントを {urlTemplate} として保存し、クラスターの「パスワード」を {passwordTemplate} として保存します。", - "home.tutorials.common.premCloudInstructions.option2.title": "オプション 2:Kibana を Cloud インスタンスに接続", - "home.tutorials.common.winlogbeat.cloudInstructions.gettingStarted.title": "はじめに", - "home.tutorials.common.winlogbeat.premCloudInstructions.gettingStarted.title": "はじめに", - "home.tutorials.common.winlogbeat.premInstructions.gettingStarted.title": "はじめに", - "home.tutorials.common.winlogbeatCloudInstructions.config.windowsTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "home.tutorials.common.winlogbeatCloudInstructions.config.windowsTitle": "構成を編集する", - "home.tutorials.common.winlogbeatInstructions.config.windowsTextPost": "{passwordTemplate} が「Elastic」ユーザーのパスワード、{esUrlTemplate} が Elasticsearch の URL、{kibanaUrlTemplate} が Kibana の URL です。", - "home.tutorials.common.winlogbeatInstructions.config.windowsTextPre": "{path} を変更して Elastic Cloud への接続情報を設定します:", - "home.tutorials.common.winlogbeatInstructions.config.windowsTitle": "構成を編集する", - "home.tutorials.common.winlogbeatInstructions.install.windowsTextPost": "{path} ファイルの「output.elasticsearch」を Elasticsearch のインストールに設定します。", - "home.tutorials.common.winlogbeatInstructions.install.windowsTextPre": "Winlogbeatは初めてですか?[クイックスタート]({winlogbeatLink})を参照してください。\n 1.[ダウンロード]({elasticLink})ページからWinlogbeat Windows zipファイルをダウンロードします。\n 2.zipファイルのコンテンツを{folderPath}に解凍します。\n 3.{directoryName}ディレクトリの名前を「Winlogbeat」に変更します。\n 4.管理者としてPowerShellプロンプトを開きます(PowerShellアイコンを右クリックして「管理者として実行」を選択します)。Windows XPをご使用の場合、PowerShellのダウンロードとインストールが必要な場合があります。\n 5.PowerShell プロンプトで次のコマンドを実行し、Winlogbeat を Windows サービスとしてインストールします。", - "home.tutorials.common.winlogbeatInstructions.install.windowsTitle": "Winlogbeat のダウンロードとインストール", - "home.tutorials.common.winlogbeatInstructions.start.windowsTextPre": "「setup」コマンドで Kibana のダッシュボードを読み込みます。ダッシュボードがすでにセットアップされている場合、このコマンドは省略します。", - "home.tutorials.common.winlogbeatInstructions.start.windowsTitle": "Winlogbeat を起動", - "home.tutorials.common.winlogbeatStatusCheck.buttonLabel": "データを確認してください", - "home.tutorials.common.winlogbeatStatusCheck.errorText": "まだデータを受信していません", - "home.tutorials.common.winlogbeatStatusCheck.successText": "データを受信しました", - "home.tutorials.common.winlogbeatStatusCheck.text": "Winlogbeat からデータを受け取ったことを確認してください。", - "home.tutorials.common.winlogbeatStatusCheck.title": "モジュールステータス", - "home.tutorials.consulMetrics.artifacts.dashboards.linkLabel": "Consul メトリックダッシュボード", - "home.tutorials.consulMetrics.longDescription": "Metricbeatモジュール「consul」は、Consulから監視メトリックを取得します。[詳細]({learnMoreLink})", - "home.tutorials.consulMetrics.nameTitle": "Consul メトリック", - "home.tutorials.consulMetrics.shortDescription": "CouchdB サーバーから監視メトリックを取得します。", - "home.tutorials.corednsLogs.artifacts.dashboards.linkLabel": "[[Filebeat CoreDNS] 概要", - "home.tutorials.corednsLogs.longDescription": "これは CoreDNS の Filebeatモジュールです。スタンドアロンのCoreDNSデプロイメントとKubernetesでのCoreDNSデプロイメントの両方をサポートします。[詳細]({learnMoreLink})", - "home.tutorials.corednsLogs.nameTitle": "CoreDNS ログ", - "home.tutorials.corednsLogs.shortDescription": "CoreDNS ログを収集します。", - "home.tutorials.corednsMetrics.artifacts.application.label": "Discover", - "home.tutorials.corednsMetrics.longDescription": "「coredns」Metricbeatモジュールが、CoreDNSから監視メトリックを取得します。[詳細]({learnMoreLink})", - "home.tutorials.corednsMetrics.nameTitle": "CoreDNS メトリック", - "home.tutorials.corednsMetrics.shortDescription": "CoreDNS サーバーから監視メトリックを取得します。", - "home.tutorials.couchbaseMetrics.artifacts.application.label": "Discover", - "home.tutorials.couchbaseMetrics.longDescription": "「couchbase」Metricbeatモジュールは、Couchbaseから内部メトリックを取得します。[詳細]({learnMoreLink})", - "home.tutorials.couchbaseMetrics.nameTitle": "Couchbase メトリック", - "home.tutorials.couchbaseMetrics.shortDescription": "Couchbase から内部メトリックを取得します。", - "home.tutorials.couchdbMetrics.artifacts.dashboards.linkLabel": "CouchDB メトリックダッシュボード", - "home.tutorials.couchdbMetrics.longDescription": "「couchdb」Metricbeatモジュールが、CouchDBから監視メトリックを取得します。[詳細]({learnMoreLink})", - "home.tutorials.couchdbMetrics.nameTitle": "CouchDB メトリック", - "home.tutorials.couchdbMetrics.shortDescription": "CouchdB サーバーから監視メトリックを取得します。", - "home.tutorials.crowdstrikeLogs.artifacts.dashboards.linkLabel": "セキュリティアプリ", - "home.tutorials.crowdstrikeLogs.longDescription": "これはFalcon [SIEM Connector](https://www.crowdstrike.com/blog/tech-center/integrate-with-your-siem)を使用したFilebeat module for CrowdStrike Falconです。 このモジュールはこのデータを収集し、ECS に変換して、取り込み、SIEM に表示します。 デフォルトでは、Falcon SIEMコネクターはJSON形式のFalcon Streaming APIイベントデータを出力します。[詳細]({learnMoreLink})", - "home.tutorials.crowdstrikeLogs.nameTitle": "CrowdStrike ログ", - "home.tutorials.crowdstrikeLogs.shortDescription": "Falcon SIEM コネクターを使用して CrowdStrike Falcon ログを収集します。", - "home.tutorials.cylanceLogs.artifacts.dashboards.linkLabel": "セキュリティアプリ", - "home.tutorials.cylanceLogs.longDescription": "これは、SyslogまたはファイルでCylancePROTECTログを受信するためのモジュールです。[詳細]({learnMoreLink})", - "home.tutorials.cylanceLogs.nameTitle": "CylancePROTECT ログ", - "home.tutorials.dockerMetrics.artifacts.dashboards.linkLabel": "Docker メトリックダッシュボード", - "home.tutorials.dockerMetrics.longDescription": "「docker」 Metricbeatモジュールは、Dockerサーバーからメトリックを取得します。[詳細]({learnMoreLink})", - "home.tutorials.dockerMetrics.nameTitle": "Docker メトリック", - "home.tutorials.dockerMetrics.shortDescription": "Docker コンテナーに関するメトリックを取得します。", - "home.tutorials.dropwizardMetrics.artifacts.application.label": "Discover", - "home.tutorials.dropwizardMetrics.longDescription": "「dropwizard」 Metricbeatモジュールは、Dropwizard Javaアプリケーションから内部メトリックを取得します。[詳細]({learnMoreLink})", - "home.tutorials.dropwizardMetrics.nameTitle": "Dropwizard メトリック", - "home.tutorials.dropwizardMetrics.shortDescription": "Dropwizard Java アプリケーションから内部メトリックを取得します。", - "home.tutorials.elasticsearchLogs.artifacts.application.label": "Discover", - "home.tutorials.elasticsearchLogs.longDescription": "「elasticsearch」Filebeatモジュールが、Elasticsearchにより作成されたログをパースします。[詳細]({learnMoreLink})", - "home.tutorials.elasticsearchLogs.nameTitle": "Elasticsearch ログ", - "home.tutorials.elasticsearchLogs.shortDescription": "Elasticsearch により作成されたログを収集しパースします。", - "home.tutorials.elasticsearchMetrics.artifacts.application.label": "Discover", - "home.tutorials.elasticsearchMetrics.longDescription": "「elasticsearch」Metricbeatモジュールは、Elasticsearchから内部メトリックを取得します。[詳細]({learnMoreLink})", - "home.tutorials.elasticsearchMetrics.nameTitle": "Elasticsearch メトリック", - "home.tutorials.elasticsearchMetrics.shortDescription": "Elasticsearch から内部メトリックを取得します。", - "home.tutorials.envoyproxyLogs.artifacts.dashboards.linkLabel": "Envoy Proxy 概要", - "home.tutorials.envoyproxyLogs.longDescription": "これは Envoy Proxy アクセスログ(https://www.envoyproxy.io/docs/envoy/v1.10.0/configuration/access_log)用の Filebeat モジュールです。KubernetesでのスタンドアロンのデプロイメントとEnvoyプロキシデプロイメントの両方をサポートします。[詳細]({learnMoreLink})", - "home.tutorials.envoyproxyLogs.nameTitle": "Envoy Proxy ログ", - "home.tutorials.envoyproxyLogs.shortDescription": "Envoy Proxy ログを収集します。", - "home.tutorials.envoyproxyMetrics.longDescription": "Metricbeatモジュール「envoyproxy」は、Envoy Proxyから監視メトリックを取得します。[詳細]({learnMoreLink})", - "home.tutorials.envoyproxyMetrics.nameTitle": "Envoy Proxy メトリック", - "home.tutorials.envoyproxyMetrics.shortDescription": "Envoy Proxy サーバーから監視メトリックを取得します。", - "home.tutorials.etcdMetrics.artifacts.application.label": "Discover", - "home.tutorials.etcdMetrics.longDescription": "「etcd」Metricbeatモジュールは、Etcdから内部メトリックを取得します。[詳細]({learnMoreLink})", - "home.tutorials.etcdMetrics.nameTitle": "Etcd メトリック", - "home.tutorials.etcdMetrics.shortDescription": "Etcd サーバーから内部メトリックを取得します。", - "home.tutorials.f5Logs.artifacts.dashboards.linkLabel": "セキュリティアプリ", - "home.tutorials.f5Logs.longDescription": "これは、SyslogまたはファイルでBig-IP Access Policy Managerログを受信するためのモジュールです。[詳細]({learnMoreLink})", - "home.tutorials.f5Logs.nameTitle": "F5 ログ", - "home.tutorials.f5Logs.shortDescription": "Syslog またはファイルで F5 Big-IP Access Policy Manager ログを収集します。", - "home.tutorials.fortinetLogs.artifacts.dashboards.linkLabel": "セキュリティアプリ", - "home.tutorials.fortinetLogs.longDescription": "これはSyslog形式で送信されたFortinet FortiOSログのためのモジュールです。[詳細]({learnMoreLink})", - "home.tutorials.fortinetLogs.nameTitle": "Fortinet ログ", - "home.tutorials.fortinetLogs.shortDescription": "Syslog で Fortinet FortiOS ログを収集します。", - "home.tutorials.gcpLogs.artifacts.dashboards.linkLabel": "監査ログダッシュボード", - "home.tutorials.gcpLogs.longDescription": "これは Google Cloud ログのモジュールです。StackdriverからGoogle Pub/Subトピックシンクにエクスポートされた監査、VPCフロー、ファイアウォールログの読み取りをサポートします。[詳細]({learnMoreLink})", - "home.tutorials.gcpLogs.nameTitle": "Google Cloud ログ", - "home.tutorials.gcpLogs.shortDescription": "Google Cloud 監査、ファイアウォール、VPC フローログを収集します。", - "home.tutorials.gcpMetrics.artifacts.dashboards.linkLabel": "Google Cloudメトリックダッシュボード", - "home.tutorials.gcpMetrics.longDescription": "「gcp」Metricbeatモジュールは、Stackdriver Monitoring APIを使用して、Google Cloud Platformから監視メトリックを取得します。[詳細]({learnMoreLink})", - "home.tutorials.gcpMetrics.nameTitle": "Google Cloudメトリック", - "home.tutorials.gcpMetrics.shortDescription": "Stackdriver Monitoring API を使用して、Google Cloud Platform から監視メトリックを取得します。", - "home.tutorials.golangMetrics.artifacts.dashboards.linkLabel": "Golang メトリックダッシュボード", - "home.tutorials.golangMetrics.longDescription": "「{moduleName}」Metricbeatモジュールは、Golangアプリから内部メトリックを取得します。[詳細]({learnMoreLink})", - "home.tutorials.golangMetrics.nameTitle": "Golang メトリック", - "home.tutorials.golangMetrics.shortDescription": "Golang アプリから内部メトリックを取得します。", - "home.tutorials.gsuiteLogs.artifacts.dashboards.linkLabel": "セキュリティアプリ", - "home.tutorials.gsuiteLogs.longDescription": "これは異なるGSuite監査レポートAPIからデータを取り込むためのモジュールです。[詳細]({learnMoreLink})", - "home.tutorials.gsuiteLogs.nameTitle": "GSuite ログ", - "home.tutorials.gsuiteLogs.shortDescription": "GSuite アクティビティレポートを収集します。", - "home.tutorials.haproxyLogs.artifacts.dashboards.linkLabel": "HAProxy 概要", - "home.tutorials.haproxyLogs.longDescription": "このモジュールは、(「haproxy」)プロセスからログを収集して解析します。[詳細]({learnMoreLink})", - "home.tutorials.haproxyLogs.nameTitle": "HAProxy ログ", - "home.tutorials.haproxyLogs.shortDescription": "HAProxy ログを収集します。", - "home.tutorials.haproxyMetrics.artifacts.application.label": "Discover", - "home.tutorials.haproxyMetrics.longDescription": "「haproxy」Metricbeatモジュールは、HAProxyアプリから内部メトリックを取得します。[詳細]({learnMoreLink})", - "home.tutorials.haproxyMetrics.nameTitle": "HAProxy メトリック", - "home.tutorials.haproxyMetrics.shortDescription": "HAProxy サーバーから内部メトリックを取得します。", - "home.tutorials.ibmmqLogs.artifacts.dashboards.linkLabel": "IBM MQ イベント", - "home.tutorials.ibmmqLogs.longDescription": "Filebeat で IBM MQ ログを収集します。[詳細]({learnMoreLink})", - "home.tutorials.ibmmqLogs.nameTitle": "IBM MQ ログ", - "home.tutorials.ibmmqLogs.shortDescription": "Filebeat で IBM MQ ログを収集します。", - "home.tutorials.ibmmqMetrics.artifacts.application.label": "Discover", - "home.tutorials.ibmmqMetrics.nameTitle": "IBM MQ メトリック", - "home.tutorials.ibmmqMetrics.shortDescription": "IBM MQ インスタンスから監視メトリックを取得します。", - "home.tutorials.icingaLogs.artifacts.dashboards.linkLabel": "Icinga Main ログ", - "home.tutorials.icingaLogs.longDescription": "このモジュールは[Icinga](https://www.icinga.com/products/icinga-2/)のメイン、デバッグ、スタートアップログを解析します。[詳細]({learnMoreLink})", - "home.tutorials.icingaLogs.nameTitle": "Icinga ログ", - "home.tutorials.icingaLogs.shortDescription": "Icinga メイン、デバッグ、スタートアップログを収集します。", - "home.tutorials.iisLogs.artifacts.dashboards.linkLabel": "IIS ログダッシュボード", - "home.tutorials.iisLogs.longDescription": "「iis」Filebeatモジュールが、Nginx HTTPサーバーにより作成されたアクセスとエラーのログをパースします。[詳細]({learnMoreLink})", - "home.tutorials.iisLogs.nameTitle": "IIS ログ", - "home.tutorials.iisLogs.shortDescription": "IIS HTTP サーバーにより作成されたアクセスとエラーのログを収集しパースします。", - "home.tutorials.iisMetrics.artifacts.dashboards.linkLabel": "IISメトリックダッシュボード", - "home.tutorials.iisMetrics.longDescription": "「iis」Metricbeatモジュールは、IISサーバーおよび実行中のアプリケーションプールとWebサイトからメトリックを収集します。[詳細]({learnMoreLink})", - "home.tutorials.iisMetrics.nameTitle": "IISメトリック", - "home.tutorials.iisMetrics.shortDescription": "IISサーバー関連メトリックを収集します。", - "home.tutorials.impervaLogs.artifacts.dashboards.linkLabel": "セキュリティアプリ", - "home.tutorials.impervaLogs.longDescription": "これは、SyslogまたはファイルでSecureSphereログを受信するためのモジュールです。[詳細]({learnMoreLink})", - "home.tutorials.impervaLogs.nameTitle": "Imperva ログ", - "home.tutorials.impervaLogs.shortDescription": "Syslog またはファイルから Imperva SecureSphere ログを収集します。", - "home.tutorials.infobloxLogs.artifacts.dashboards.linkLabel": "セキュリティアプリ", - "home.tutorials.infobloxLogs.longDescription": "これは、SyslogまたはファイルでInfoblox NIOSログを受信するためのモジュールです。[詳細]({learnMoreLink})", - "home.tutorials.infobloxLogs.nameTitle": "Infoblox ログ", - "home.tutorials.infobloxLogs.shortDescription": "Syslog またはファイルから Infoblox NIOS ログを収集します。", - "home.tutorials.iptablesLogs.artifacts.dashboards.linkLabel": "Iptables 概要", - "home.tutorials.iptablesLogs.longDescription": "これは iptables と ip6tables ログ用のモジュールです。ネットワーク上で受信した syslog ログ経由や、ファイルからのログをパースします。また、ルールセット名、ルール番号、トラフィックに実行されたアクション (許可/拒否) を含む、Ubiquitiファイアウォールにより追加された接頭辞も認識できます [詳細]({learnMoreLink})", - "home.tutorials.iptablesLogs.nameTitle": "Iptables ログ", - "home.tutorials.iptablesLogs.shortDescription": "iptables および ip6tables ログを収集します。", - "home.tutorials.juniperLogs.artifacts.dashboards.linkLabel": "セキュリティアプリ", - "home.tutorials.juniperLogs.longDescription": "これは、SyslogまたはファイルでJuniper JUNOSログを受信するためのモジュールです。[詳細]({learnMoreLink})", - "home.tutorials.juniperLogs.nameTitle": "Juniper ログ", - "home.tutorials.juniperLogs.shortDescription": "Syslog またはファイルから Juniper JUNOS ログを収集します。", - "home.tutorials.kafkaLogs.artifacts.dashboards.linkLabel": "Kafka ログダッシュボード", - "home.tutorials.kafkaLogs.longDescription": "「kafka」Filebeatモジュールは、Kafkaが作成したログをパースします。[詳細]({learnMoreLink})", - "home.tutorials.kafkaLogs.nameTitle": "Kafka ログ", - "home.tutorials.kafkaLogs.shortDescription": "Kafka が作成したログを収集しパースします。", - "home.tutorials.kafkaMetrics.artifacts.application.label": "Discover", - "home.tutorials.kafkaMetrics.longDescription": "「kafka」Metricbeatモジュールは、Kafkaから内部メトリックを取得します。[詳細]({learnMoreLink})", - "home.tutorials.kafkaMetrics.nameTitle": "Kafka メトリック", - "home.tutorials.kafkaMetrics.shortDescription": "Kafka サーバーから内部メトリックを取得します。", - "home.tutorials.kibanaLogs.artifacts.application.label": "Discover", - "home.tutorials.kibanaLogs.longDescription": "これはKibanaモジュールです。[詳細]({learnMoreLink})", - "home.tutorials.kibanaLogs.nameTitle": "Kibana ログ", - "home.tutorials.kibanaLogs.shortDescription": "Kibana ログを収集します。", - "home.tutorials.kibanaMetrics.artifacts.application.label": "Discover", - "home.tutorials.kibanaMetrics.longDescription": "「kibana」Metricbeatモジュールは、Kibanaから内部メトリックを取得します。[詳細]({learnMoreLink})", - "home.tutorials.kibanaMetrics.nameTitle": "Kibana メトリック", - "home.tutorials.kibanaMetrics.shortDescription": "Kibana から内部メトリックを取得します。", - "home.tutorials.kubernetesMetrics.artifacts.dashboards.linkLabel": "Kubernetes メトリックダッシュボード", - "home.tutorials.kubernetesMetrics.longDescription": "「kubernetes」Metricbeatモジュールは、Kubernetes APIからメトリックを取得します。[詳細]({learnMoreLink})", - "home.tutorials.kubernetesMetrics.nameTitle": "Kubernetes メトリック", - "home.tutorials.kubernetesMetrics.shortDescription": "Kubernetes からメトリックを取得します。", - "home.tutorials.logstashLogs.artifacts.dashboards.linkLabel": "Logstash ログ", - "home.tutorials.logstashLogs.longDescription": "このモジュールはLogstash標準ログと低速ログを解析します。プレーンテキスト形式とJSON形式がサポートされます。[詳細]({learnMoreLink})", - "home.tutorials.logstashLogs.nameTitle": "Logstash ログ", - "home.tutorials.logstashLogs.shortDescription": "Logstash メインおよび低速ログを収集します。", - "home.tutorials.logstashMetrics.artifacts.application.label": "Discover", - "home.tutorials.logstashMetrics.longDescription": "「{moduleName}」Metricbeatモジュールは、Logstashサーバーから内部メトリックを取得します。[詳細]({learnMoreLink})", - "home.tutorials.logstashMetrics.nameTitle": "Logstash メトリック", - "home.tutorials.logstashMetrics.shortDescription": "Logstash サーバーから内部メトリックを取得します。", - "home.tutorials.memcachedMetrics.artifacts.application.label": "Discover", - "home.tutorials.memcachedMetrics.longDescription": "「memcached」Metricbeatモジュールは、Memcachedから内部メトリックを取得します。[詳細]({learnMoreLink})", - "home.tutorials.memcachedMetrics.nameTitle": "Memcached メトリック", - "home.tutorials.memcachedMetrics.shortDescription": "Memcached サーバーから内部メトリックを取得します。", - "home.tutorials.microsoftLogs.artifacts.dashboards.linkLabel": "Microsoft ATP 概要", - "home.tutorials.microsoftLogs.longDescription": "Elastic Securityで使用するMicrosoft Defender ATPアラートを収集します。[詳細]({learnMoreLink})", - "home.tutorials.microsoftLogs.nameTitle": "Microsoft Defender ATP ログ", - "home.tutorials.microsoftLogs.shortDescription": "Microsoft Defender ATP アラートを収集します。", - "home.tutorials.mispLogs.artifacts.dashboards.linkLabel": "MISP 概要", - "home.tutorials.mispLogs.longDescription": "これは MISP プラットフォーム(https://www.circl.lu/doc/misp/)から脅威インテリジェンス情報を読み取るための Filebeatモジュールです。MISP REST APIインターフェイスにアクセスするためにhttpjson入力を使用します。[詳細]({learnMoreLink})", - "home.tutorials.mispLogs.nameTitle": "MISP 脅威インテリジェンスログ", - "home.tutorials.mispLogs.shortDescription": "Filebeat を使用して MISP 脅威インテリジェンスデータを収集します。", - "home.tutorials.mongodbLogs.artifacts.dashboards.linkLabel": "MongoDB概要", - "home.tutorials.mongodbLogs.longDescription": "このモジュールは、[MongoDB](https://www.mongodb.com/)によって作成されたログを収集して解析します。[詳細]({learnMoreLink})", - "home.tutorials.mongodbLogs.nameTitle": "MongoDB ログ", - "home.tutorials.mongodbLogs.shortDescription": "MongoDB ログを収集します。", - "home.tutorials.mongodbMetrics.artifacts.dashboards.linkLabel": "MongoDB メトリックダッシュボード", - "home.tutorials.mongodbMetrics.longDescription": "「mongodb」Metricbeatモジュールは、MongoDBサーバーから内部メトリックを取得します。[詳細]({learnMoreLink})", - "home.tutorials.mongodbMetrics.nameTitle": "MongoDB メトリック", - "home.tutorials.mongodbMetrics.shortDescription": "MongoDB から内部メトリックを取得します。", - "home.tutorials.mssqlLogs.artifacts.application.label": "Discover", - "home.tutorials.mssqlLogs.longDescription": "このモジュールはMSSQLにより作成されたエラーログを解析します。[詳細]({learnMoreLink})", - "home.tutorials.mssqlLogs.nameTitle": "MSSQL ログ", - "home.tutorials.mssqlLogs.shortDescription": "MSSQL ログを収集します。", - "home.tutorials.mssqlMetrics.artifacts.dashboards.linkLabel": "Microsoft SQL Server メトリックダッシュボード", - "home.tutorials.mssqlMetrics.longDescription": "「mssql」Metricbeatモジュールが、Microsoft SQL Serverインスタンスからの監視、ログ、パフォーマンスメトリックを取得します。[詳細]({learnMoreLink})", - "home.tutorials.mssqlMetrics.nameTitle": "Microsoft SQL Serverメトリック", - "home.tutorials.mssqlMetrics.shortDescription": "Microsoft SQL Server インスタンスから監視メトリックを取得します。", - "home.tutorials.muninMetrics.artifacts.application.label": "Discover", - "home.tutorials.muninMetrics.longDescription": "「munin」Metricbeatモジュールは、Muninから内部メトリックを取得します。[詳細]({learnMoreLink})", - "home.tutorials.muninMetrics.nameTitle": "Munin メトリック", - "home.tutorials.muninMetrics.shortDescription": "Munin サーバーから内部メトリックを取得します。", - "home.tutorials.mysqlLogs.artifacts.dashboards.linkLabel": "MySQL ログダッシュボード", - "home.tutorials.mysqlLogs.longDescription": "「mysql」Filebeatモジュールは、MySQLが作成したエラーとスローログをパースします。[詳細]({learnMoreLink})", - "home.tutorials.mysqlLogs.nameTitle": "MySQL ログ", - "home.tutorials.mysqlLogs.shortDescription": "MySQL が作成したエラーとスローログを収集しパースします。", - "home.tutorials.mysqlMetrics.artifacts.dashboards.linkLabel": "MySQL メトリックダッシュボード", - "home.tutorials.mysqlMetrics.longDescription": "「mysql」Metricbeatモジュールは、MySQLサーバーから内部メトリックを取得します。[詳細]({learnMoreLink})", - "home.tutorials.mysqlMetrics.nameTitle": "MySQL メトリック", - "home.tutorials.mysqlMetrics.shortDescription": "MySQL から内部メトリックを取得します。", - "home.tutorials.natsLogs.artifacts.dashboards.linkLabel": "NATSログダッシュボード", - "home.tutorials.natsLogs.longDescription": "「nats」Filebeatモジュールが、Natsにより作成されたログをパースします。[詳細]({learnMoreLink})", - "home.tutorials.natsLogs.nameTitle": "NATSログ", - "home.tutorials.natsLogs.shortDescription": "Nats により作成されたログを収集しパースします。", - "home.tutorials.natsMetrics.artifacts.dashboards.linkLabel": "NATSメトリックダッシュボード", - "home.tutorials.natsMetrics.longDescription": "「nats」Metricbeatモジュールが、Natsから監視メトリックを取得します。[詳細]({learnMoreLink})", - "home.tutorials.natsMetrics.nameTitle": "NATSメトリック", - "home.tutorials.natsMetrics.shortDescription": "Nats サーバーから監視メトリックを取得します。", - "home.tutorials.netflowLogs.artifacts.dashboards.linkLabel": "Netflow 概要", - "home.tutorials.netflowLogs.longDescription": "これは UDP で NetFlow および IPFIX フローレコードを受信するモジュールです。この入力は、NetFlow バージョン 1、5、6、7、8、9、IPFIX をサポートします。NetFlowバージョン9以外では、フィールドが自動的にNetFlow v9にマッピングされます。[詳細]({learnMoreLink})", - "home.tutorials.netflowLogs.nameTitle": "NetFlow / IPFIX Collector", - "home.tutorials.netflowLogs.shortDescription": "NetFlow および IPFIX フローレコードを収集します。", - "home.tutorials.netscoutLogs.artifacts.dashboards.linkLabel": "セキュリティアプリ", - "home.tutorials.netscoutLogs.longDescription": "これは、SyslogまたはファイルでArbor Peakflow SPログを受信するためのモジュールです。[詳細]({learnMoreLink})", - "home.tutorials.netscoutLogs.nameTitle": "Arbor Peakflow ログ", - "home.tutorials.netscoutLogs.shortDescription": "Syslog またはファイルから Netscout Arbor Peakflow SP ログを収集します。", - "home.tutorials.nginxLogs.artifacts.dashboards.linkLabel": "Nginx ログダッシュボード", - "home.tutorials.nginxLogs.longDescription": "「nginx」Filebeatモジュールは、Nginx HTTPサーバーが作成したアクセスとエラーのログをパースします。[詳細]({learnMoreLink})", - "home.tutorials.nginxLogs.nameTitle": "Nginx ログ", - "home.tutorials.nginxLogs.shortDescription": "Nginx HTTP サーバーが作成したアクセスとエラーのログを収集しパースします。", - "home.tutorials.nginxMetrics.artifacts.dashboards.linkLabel": "Nginx メトリックダッシュボード", - "home.tutorials.nginxMetrics.longDescription": "Metricbeat モジュール「nginx」は、Nginx サーバーから内部メトリックを取得します。このモジュールは{statusModuleLink}が作成したウェブページからサーバーステータスデータを取得します。Nginxインストールで有効にする必要があります。[詳細]({learnMoreLink})", - "home.tutorials.nginxMetrics.nameTitle": "Nginx メトリック", - "home.tutorials.nginxMetrics.shortDescription": "Nginx HTTP サーバーから内部メトリックを取得します。", - "home.tutorials.o365Logs.artifacts.dashboards.linkLabel": "O365 監査ダッシュボード", - "home.tutorials.o365Logs.longDescription": "これは Office 365 API エンドポイントのいずれか経由で受信された Office 365 ログのモジュールです。現在、ユーザー、管理者、システム、ポリシーアクションのほか、Office 365 Management Activity APIによって公開されたOffice 365およびAzure ADアクティビティログからのイベントがサポートされています。 [詳細]({learnMoreLink})", - "home.tutorials.o365Logs.nameTitle": "Office 365 ログ", - "home.tutorials.o365Logs.shortDescription": "Office 365 API 経由で Office 365 アクティビティログを収集します。", - "home.tutorials.oktaLogs.artifacts.dashboards.linkLabel": "Okta 概要", - "home.tutorials.oktaLogs.longDescription": "Oktaモジュールは[Okta API](https://developer.okta.com/docs/reference/)からイベントを収集します。 特にこれは[OktaシステムログAPI](https://developer.okta.com/docs/reference/api/system-log/)からの読み取りをサポートします。 [詳細]({learnMoreLink})", - "home.tutorials.oktaLogs.nameTitle": "Okta ログ", - "home.tutorials.oktaLogs.shortDescription": "Okta API 経由で Okta システムログを収集します。", - "home.tutorials.openmetricsMetrics.longDescription": "Metricbeatモジュール「openmetrics」は、OpenMetricsの形式でメトリックを提供するエンドポイントからメトリックをフェッチします。[詳細]({learnMoreLink})", - "home.tutorials.openmetricsMetrics.nameTitle": "OpenMetrics メトリック", - "home.tutorials.openmetricsMetrics.shortDescription": "OpenMetrics 形式でメトリックを提供するエンドポイントからメトリックを取得します。", - "home.tutorials.oracleMetrics.artifacts.application.label": "Discover", - "home.tutorials.oracleMetrics.longDescription": "「{moduleName}」Metricbeatモジュールは、Oraclサーバーから内部メトリックを取得します。[詳細]({learnMoreLink})", - "home.tutorials.oracleMetrics.nameTitle": "Oracleメトリック", - "home.tutorials.oracleMetrics.shortDescription": "Oracleサーバーから内部メトリックを取得します。", - "home.tutorials.osqueryLogs.artifacts.dashboards.linkLabel": "Osquery コンプライアンスパック", - "home.tutorials.osqueryLogs.longDescription": "このモジュールはJSON形式で[osqueryd](https://osquery.readthedocs.io/en/latest/introduction/using-osqueryd/)で書き込まれた結果ログを収集してデコードします。osqueryd を設定するには、ご使用のオペレーティングシステムの osquery インストール手順に従い、「filesystem」ロギングドラバー(デフォルト)を構成します。 UTCタイムスタンプが有効であることを確認してください。 [詳細]({learnMoreLink})", - "home.tutorials.osqueryLogs.nameTitle": "Osquery ログ", - "home.tutorials.osqueryLogs.shortDescription": "JSON 形式で osquery を収集します。", - "home.tutorials.panwLogs.artifacts.dashboards.linkLabel": "PANW ネットワークフロー", - "home.tutorials.panwLogs.longDescription": "このモジュールは、Syslog から受信したログまたはファイルから読み取られたログを監視する Palo Alto Networks PAN-OS ファイアウォール監視ログのモジュールです。現在、トラフィックおよび脅威タイプのメッセージがサポートされています。[詳細]({learnMoreLink})", - "home.tutorials.panwLogs.nameTitle": "Palo Alto Networks PAN-OS ログ", - "home.tutorials.panwLogs.shortDescription": "Syslog またはログファイルから Palo Alto Networks PAN-OS 脅威およびトラフィックログを収集します。", - "home.tutorials.phpFpmMetrics.longDescription": "「php_fpm」Metricbeatモジュールは、PHP-FPMサーバーから内部メトリックを取得します。[詳細]({learnMoreLink})", - "home.tutorials.phpFpmMetrics.nameTitle": "PHP-FPM メトリック", - "home.tutorials.phpFpmMetrics.shortDescription": "PHP-FPM から内部メトリックを取得します。", - "home.tutorials.postgresqlLogs.artifacts.dashboards.linkLabel": "PostgreSQL ログダッシュボード", - "home.tutorials.postgresqlLogs.longDescription": "「postgresql」Filebeatモジュールが、PostgreSQLにより作成されたエラーとスローログをパースします。[詳細]({learnMoreLink})", - "home.tutorials.postgresqlLogs.nameTitle": "PostgreSQL ログ", - "home.tutorials.postgresqlLogs.shortDescription": "PostgreSQL により作成されたエラーとスローログを収集しパースします。", - "home.tutorials.postgresqlMetrics.longDescription": "「postgresql」Metricbeatモジュールは、PostgreSQLサーバーから内部メトリックを取得します。[詳細]({learnMoreLink})", - "home.tutorials.postgresqlMetrics.nameTitle": "PostgreSQL メトリック", - "home.tutorials.postgresqlMetrics.shortDescription": "PostgreSQL から内部メトリックを取得します。", - "home.tutorials.prometheusMetrics.artifacts.application.label": "Discover", - "home.tutorials.prometheusMetrics.longDescription": "「{moduleName}」Metricbeatモジュールは、Prometheusエンドポイントからメトリックを取得します。[詳細]({learnMoreLink})", - "home.tutorials.prometheusMetrics.nameTitle": "Prometheus メトリック", - "home.tutorials.prometheusMetrics.shortDescription": "Prometheus エクスポーターからメトリックを取得します。", - "home.tutorials.rabbitmqLogs.artifacts.application.label": "Discover", - "home.tutorials.rabbitmqLogs.longDescription": "このモジュールは[RabbitMQログファイル](https://www.rabbitmq.com/logging.html)を解析します [詳細]({learnMoreLink})。", - "home.tutorials.rabbitmqLogs.nameTitle": "RabbitMQ ログ", - "home.tutorials.rabbitmqLogs.shortDescription": "RabbitMQ ログを収集します。", - "home.tutorials.rabbitmqMetrics.artifacts.dashboards.linkLabel": "RabbitMQ メトリックダッシュボード", - "home.tutorials.rabbitmqMetrics.longDescription": "「rabbitmq」Metricbeatモジュールは、RabbitMQサーバーから内部メトリックを取得します。[詳細]({learnMoreLink})", - "home.tutorials.rabbitmqMetrics.nameTitle": "RabbitMQ メトリック", - "home.tutorials.rabbitmqMetrics.shortDescription": "RabbitMQ サーバーから内部メトリックを取得します。", - "home.tutorials.radwareLogs.artifacts.dashboards.linkLabel": "セキュリティアプリ", - "home.tutorials.radwareLogs.longDescription": "これは、SyslogまたはファイルでRadware DefenseProログを受信するためのモジュールです。[詳細]({learnMoreLink})", - "home.tutorials.radwareLogs.nameTitle": "Radware DefensePro ログ", - "home.tutorials.radwareLogs.shortDescription": "Syslog またはファイルから Radware DefensePro ログを収集します。", - "home.tutorials.redisenterpriseMetrics.artifacts.application.label": "Discover", - "home.tutorials.redisenterpriseMetrics.nameTitle": "Redis Enterprise メトリック", - "home.tutorials.redisenterpriseMetrics.shortDescription": "Redis Enterprise Server から監視メトリックを取得します。", - "home.tutorials.redisLogs.artifacts.dashboards.linkLabel": "Redis ログダッシュボード", - "home.tutorials.redisLogs.longDescription": "「redis」Filebeat モジュールは、Redis が作成したエラーとスローログをパースします。Redis がエラーログを作成するには、Redis 構成ファイルの「logfile」オプションが「redis-server.log」に設定されていることを確認してください。スローログは「SLOWLOG」コマンドで Redis から直接的に読み込まれます。Redis でスローログを記録するには、「slowlog-log-slower-than」オプションが設定されていることを確認してください。「slowlog」ファイルセットは実験的な機能のためご注意ください。[詳細]({learnMoreLink})", - "home.tutorials.redisLogs.nameTitle": "Redis ログ", - "home.tutorials.redisLogs.shortDescription": "Redis が作成したエラーとスローログを収集しパースします。", - "home.tutorials.redisMetrics.artifacts.dashboards.linkLabel": "Redis メトリックダッシュボード", - "home.tutorials.redisMetrics.longDescription": "「redis」Metricbeatモジュールは、Redisサーバーから内部メトリックを取得します。[詳細]({learnMoreLink})", - "home.tutorials.redisMetrics.nameTitle": "Redis メトリック", - "home.tutorials.redisMetrics.shortDescription": "Redis から内部メトリックを取得します。", - "home.tutorials.santaLogs.artifacts.dashboards.linkLabel": "Santa 概要", - "home.tutorials.santaLogs.longDescription": "このモジュールは、プロセス実行を監視し、バイナリをブラックリスト/ホワイトリストに登録できるmacOS向けのセキュリティツールである[Google Santa](https://github.com/google/santa)からログを収集して解析します。[詳細]({learnMoreLink})", - "home.tutorials.santaLogs.nameTitle": "Google Santa ログ", - "home.tutorials.santaLogs.shortDescription": "MacOS でのプロセス実行に関する Google Santa ログを収集します。", - "home.tutorials.sonicwallLogs.longDescription": "これは、SyslogまたはファイルでSonicwall-FWログを受信するためのモジュールです。[詳細]({learnMoreLink})", - "home.tutorials.sonicwallLogs.nameTitle": "Sonicwall FW ログ", - "home.tutorials.sonicwallLogs.shortDescription": "Syslog またはファイルから Sonicwall-FW ログを収集します。", - "home.tutorials.sophosLogs.artifacts.dashboards.linkLabel": "セキュリティアプリ", - "home.tutorials.sophosLogs.longDescription": "これはSophos製品用モジュールであり、Syslog形式で送信されたXG SFOSログが現在サポートされています。[詳細]({learnMoreLink})", - "home.tutorials.sophosLogs.nameTitle": "Sophos ログ", - "home.tutorials.sophosLogs.shortDescription": "Syslog で Sophos XG SFOS ログを収集します。", - "home.tutorials.squidLogs.artifacts.dashboards.linkLabel": "セキュリティアプリ", - "home.tutorials.squidLogs.longDescription": "これは、SyslogまたはファイルでSquidログを受信するためのモジュールです。[詳細]({learnMoreLink})", - "home.tutorials.squidLogs.nameTitle": "Squid ログ", - "home.tutorials.squidLogs.shortDescription": "Syslog またはファイルから Squid ログを収集します。", - "home.tutorials.stanMetrics.artifacts.dashboards.linkLabel": "Stan メトリックダッシュボード", - "home.tutorials.stanMetrics.longDescription": "Metricbeatモジュール「stan」は、STANから監視メトリックを取得します。[詳細]({learnMoreLink})", - "home.tutorials.stanMetrics.nameTitle": "STAN メトリック", - "home.tutorials.stanMetrics.shortDescription": "STAN サーバーから監視メトリックを取得します。", - "home.tutorials.statsdMetrics.longDescription": "Metricbeatモジュール「statsd」は、statsdから監視メトリックを取得します。[詳細]({learnMoreLink})", - "home.tutorials.statsdMetrics.nameTitle": "statsd メトリック", - "home.tutorials.statsdMetrics.shortDescription": "statsd から監視メトリックを取得します。", - "home.tutorials.suricataLogs.artifacts.dashboards.linkLabel": "Suricata イベント概要", - "home.tutorials.suricataLogs.longDescription": "このモジュールは Suricata IDS/IPS/NSM ログ用です。[Suricata Eve JSON形式](https://suricata.readthedocs.io/en/latest/output/eve/eve-json-format.html)のログを解析します。 [詳細]({learnMoreLink})", - "home.tutorials.suricataLogs.nameTitle": "Suricata ログ", - "home.tutorials.suricataLogs.shortDescription": "Suricata IDS/IPS/NSM ログを収集します。", - "home.tutorials.systemLogs.artifacts.dashboards.linkLabel": "システム Syslog ダッシュボード", - "home.tutorials.systemLogs.longDescription": "このモジュールは、一般的なUnix/Linuxベースのディストリビューションのシステムログサービスが作成したログを収集しパースします。[詳細]({learnMoreLink})", - "home.tutorials.systemLogs.nameTitle": "システムログ", - "home.tutorials.systemLogs.shortDescription": "一般的な Unix/Linux ベースのディストリビューションのシステムログを収集します。", - "home.tutorials.systemMetrics.artifacts.dashboards.linkLabel": "システムメトリックダッシュボード", - "home.tutorials.systemMetrics.longDescription": "Metricbeat モジュール「system」は、ホストから CPU、メモリー、ネットワーク、ディスクの統計を収集します。システム全体の統計とプロセスやファイルシステムごとの統計を収集します。[詳細]({learnMoreLink})", - "home.tutorials.systemMetrics.nameTitle": "システムメトリック", - "home.tutorials.systemMetrics.shortDescription": "ホストから CPU、メモリー、ネットワーク、ディスクの統計を収集します。", - "home.tutorials.tomcatLogs.artifacts.dashboards.linkLabel": "セキュリティアプリ", - "home.tutorials.tomcatLogs.longDescription": "これは、SyslogまたはファイルでApache Tomcatログを受信するためのモジュールです。[詳細]({learnMoreLink})", - "home.tutorials.tomcatLogs.nameTitle": "Tomcat ログ", - "home.tutorials.tomcatLogs.shortDescription": "Syslog またはファイルから Apache Tomcat ログを収集します。", - "home.tutorials.traefikLogs.artifacts.dashboards.linkLabel": "Traefik アクセスログ", - "home.tutorials.traefikLogs.longDescription": "このモジュールは[Træfik](https://traefik.io/)によって作成されたアクセスログを解析します。[詳細]({learnMoreLink})", - "home.tutorials.traefikLogs.nameTitle": "Traefik ログ", - "home.tutorials.traefikLogs.shortDescription": "Traefik アクセスログを収集します。", - "home.tutorials.traefikMetrics.longDescription": "Metricbeatモジュール「traefik」は、Traefikから監視メトリックを取得します。[詳細]({learnMoreLink})", - "home.tutorials.traefikMetrics.nameTitle": "Traefik メトリック", - "home.tutorials.traefikMetrics.shortDescription": "Traefik から監視メトリックを取得します。", - "home.tutorials.uptimeMonitors.artifacts.dashboards.linkLabel": "Uptime アプリ", - "home.tutorials.uptimeMonitors.longDescription": "アクティブなプロービングでサービスの稼働状況を監視します。 HeartbeatはURLのリストに基づいて、シンプルにたずねます。「稼働していますか?」と。 [詳細]({learnMoreLink})", - "home.tutorials.uptimeMonitors.nameTitle": "稼働状況監視", - "home.tutorials.uptimeMonitors.shortDescription": "サービスの稼働状況を監視します。", - "home.tutorials.uwsgiMetrics.artifacts.dashboards.linkLabel": "uWSGI メトリックダッシュボード", - "home.tutorials.uwsgiMetrics.longDescription": "「uwsgi」Metricbeatモジュールは、uWSGIサーバーから内部メトリックを取得します。[詳細]({learnMoreLink})", - "home.tutorials.uwsgiMetrics.nameTitle": "uWSGI メトリック", - "home.tutorials.uwsgiMetrics.shortDescription": "uWSGI サーバーから内部メトリックを取得します。", - "home.tutorials.vsphereMetrics.artifacts.application.label": "Discover", - "home.tutorials.vsphereMetrics.longDescription": "「vsphere」Metricbeatモジュールは、vSphereクラスターから内部メトリックを取得します。[詳細]({learnMoreLink})", - "home.tutorials.vsphereMetrics.nameTitle": "vSphere メトリック", - "home.tutorials.vsphereMetrics.shortDescription": "vSphere から内部メトリックを取得します。", - "home.tutorials.windowsEventLogs.artifacts.application.label": "SIEM アプリ", - "home.tutorials.windowsEventLogs.longDescription": "Winlogbeatを使用してWindows Event Logからのログを収集します。[詳細]({learnMoreLink})", - "home.tutorials.windowsEventLogs.nameTitle": "Windows イベントログ", - "home.tutorials.windowsEventLogs.shortDescription": "Windows イベントログからイベントを取得します。", - "home.tutorials.windowsMetrics.artifacts.application.label": "Discover", - "home.tutorials.windowsMetrics.longDescription": "「windows」Metricbeatモジュールは、Windowsから内部メトリックを取得します。[詳細]({learnMoreLink})", - "home.tutorials.windowsMetrics.nameTitle": "Windows メトリック", - "home.tutorials.windowsMetrics.shortDescription": "Windows から内部メトリックを取得します。", - "home.tutorials.zeekLogs.artifacts.dashboards.linkLabel": "Zeek 概要", - "home.tutorials.zeekLogs.longDescription": "これは Zeek(旧称 Bro)のモジュールです。[Zeek JSON形式](https://www.zeek.org/manual/release/logs/index.html)のログを解析します。 [詳細]({learnMoreLink})", - "home.tutorials.zeekLogs.nameTitle": "Zeek ログ", - "home.tutorials.zeekLogs.shortDescription": "Zeek ネットワークセキュリティ監視ログを収集します。", - "home.tutorials.zookeeperMetrics.artifacts.application.label": "Discover", - "home.tutorials.zookeeperMetrics.longDescription": "「{moduleName}」Metricbeatモジュールは、Zookeeperサーバーから内部メトリックを取得します。[詳細]({learnMoreLink})", - "home.tutorials.zookeeperMetrics.nameTitle": "Zookeeper メトリック", - "home.tutorials.zookeeperMetrics.shortDescription": "Zookeeper サーバーから内部メトリックを取得します。", - "home.tutorials.zscalerLogs.artifacts.dashboards.linkLabel": "セキュリティアプリ", - "home.tutorials.zscalerLogs.longDescription": "これは、Syslog またはファイルで Zscaler NSS ログを受信するためのモジュールです。[詳細]({learnMoreLink})", - "home.tutorials.zscalerLogs.nameTitle": "Zscaler ログ", - "home.tutorials.zscalerLogs.shortDescription": "これは、Syslog またはファイルで Zscaler NSS ログを受信するためのモジュールです。", - "home.welcomeTitle": "Elasticへようこそ", - "indexPatternEditor.aliasLabel": "エイリアス", - "indexPatternEditor.createIndex.noMatch": "名前は1つ以上のデータストリーム、インデックス、またはインデックスエイリアスと一致する必要があります。", - "indexPatternEditor.createIndexPattern.emptyState.checkDataButton": "新規データを確認", - "indexPatternEditor.createIndexPattern.emptyState.haveData": "すでにデータがある場合", - "indexPatternEditor.createIndexPattern.emptyState.integrationCardDescription": "さまざまなソースからデータを追加します。", - "indexPatternEditor.createIndexPattern.emptyState.integrationCardTitle": "統合の追加", - "indexPatternEditor.createIndexPattern.emptyState.learnMore": "詳細について", - "indexPatternEditor.createIndexPattern.emptyState.noDataTitle": "Kibanaを試しますか?まずデータが必要です。", - "indexPatternEditor.createIndexPattern.emptyState.readDocs": "ドキュメンテーションを表示", - "indexPatternEditor.createIndexPattern.emptyState.sampleDataCardDescription": "データセットとKibanaダッシュボードを読み込みます。", - "indexPatternEditor.createIndexPattern.emptyState.sampleDataCardTitle": "サンプルデータの追加", - "indexPatternEditor.createIndexPattern.emptyState.uploadCardDescription": "CSV、NDJSON、またはログファイルをインポートします。", - "indexPatternEditor.createIndexPattern.emptyState.uploadCardTitle": "ファイルをアップロード", - "indexPatternEditor.createIndexPattern.stepTime.noTimeFieldOptionLabel": "--- 時間フィルターを使用しない ---", - "indexPatternEditor.dataStreamLabel": "データストリーム", - "indexPatternEditor.editor.emptyPrompt.flyoutCloseButtonLabel": "閉じる", - "indexPatternEditor.editor.flyoutCloseButtonLabel": "閉じる", - "indexPatternEditor.editor.flyoutSaveButtonLabel": "インデックスパターンを作成", - "indexPatternEditor.editor.form.advancedSettings.hideButtonLabel": "高度な SIEM 設定の非表示化", - "indexPatternEditor.editor.form.advancedSettings.showButtonLabel": "高度なSIEM設定の表示", - "indexPatternEditor.editor.form.allowHiddenLabel": "非表示のインデックスとシステムインデックスを許可", - "indexPatternEditor.editor.form.customIdHelp": "Kibanaは各インデックスパターンの一意のIDを提供します。独自のIDを作成することもできます。", - "indexPatternEditor.editor.form.customIdLabel": "カスタムインデックスパターンID", - "indexPatternEditor.editor.form.noTimeFieldsLabel": "一致するデータストリーム、インデックス、またはインデックスエイリアスにはタイムスタンプフィールドがありません。", - "indexPatternEditor.editor.form.runtimeType.placeholderLabel": "タイムスタンプフィールドを選択", - "indexPatternEditor.editor.form.timeFieldHelp": "グローバル時間フィルターで使用するためのタイムスタンプフィールドを選択してください。", - "indexPatternEditor.editor.form.timeFieldLabel": "タイムスタンプフィールド", - "indexPatternEditor.editor.form.timestampFieldHelp": "グローバル時間フィルターで使用するためのタイムスタンプフィールドを選択してください。", - "indexPatternEditor.editor.form.timestampSelectAriaLabel": "タイムスタンプフィールド", - "indexPatternEditor.editor.form.titleLabel": "名前", - "indexPatternEditor.editor.form.TypeLabel": "インデックスパターンタイプ", - "indexPatternEditor.editor.form.typeSelectAriaLabel": "タイプフィールド", - "indexPatternEditor.emptyIndexPatternPrompt.documentation": "ドキュメンテーションを表示", - "indexPatternEditor.emptyIndexPatternPrompt.learnMore": "詳細について", - "indexPatternEditor.emptyIndexPatternPrompt.youHaveData": "Elasticsearchにデータがあります。", - "indexPatternEditor.form.allowHiddenAriaLabel": "非表示のインデックスとシステムインデックスを許可", - "indexPatternEditor.form.customIndexPatternIdLabel": "カスタムインデックスパターンID", - "indexPatternEditor.form.titleAriaLabel": "タイトルフィールド", - "indexPatternEditor.frozenLabel": "凍結", - "indexPatternEditor.indexLabel": "インデックス", - "indexPatternEditor.loadingHeader": "一致するインデックスを検索中…", - "indexPatternEditor.pagingLabel": "ページごとの行数:{perPage}", - "indexPatternEditor.requireTimestampOption.ValidationErrorMessage": "タイムスタンプフィールドを選択します。", - "indexPatternEditor.rollup.uncaughtError": "ロールアップインデックスパターンエラー:{error}", - "indexPatternEditor.rollupIndexPattern.warning.title": "ベータ機能", - "indexPatternEditor.rollupLabel": "ロールアップ", - "indexPatternEditor.saved": "Saved '{indexPatternTitle}'", - "indexPatternEditor.status.noSystemIndicesLabel": "データストリーム、インデックス、またはインデックスエイリアスがインデックスパターンと一致しません。", - "indexPatternEditor.status.noSystemIndicesWithPromptLabel": "データストリーム、インデックス、またはインデックスエイリアスがインデックスパターンと一致しません。", - "indexPatternEditor.status.notMatchLabel.notMatchDetail": "入力したインデックスパターンはデータストリーム、インデックス、またはインデックスエイリアスと一致しません。{strongIndices}と一致できます。", - "indexPatternEditor.status.notMatchLabel.notMatchNoIndicesDetail": "入力したインデックスパターンはデータストリーム、インデックス、またはインデックスエイリアスと一致しません。", - "indexPatternEditor.title": "インデックスパターンを作成", - "indexPatternEditor.typeSelect.betaLabel": "ベータ", - "indexPatternEditor.typeSelect.rollup": "ロールアップ", - "indexPatternEditor.typeSelect.rollupDescription": "要約データに制限された集約を実行します。", - "indexPatternEditor.typeSelect.rollupTitle": "ロールアップインデックスパターン", - "indexPatternEditor.typeSelect.standard": "スタンダード", - "indexPatternEditor.typeSelect.standardDescription": "すべてのデータに完全アグリゲーションを実行", - "indexPatternEditor.typeSelect.standardTitle": "標準インデックスパターン", - "indexPatternEditor.validations.titleHelpText": "複数の文字の一致にアスタリスク(*)を使用します。ペースと / ? , \" < > | 文字は使用できません。", - "indexPatternEditor.validations.titleIsRequiredErrorMessage": "名前が必要です。", - "indexPatternFieldEditor.cancelField.confirmationModal.cancelButtonLabel": "キャンセル", - "indexPatternFieldEditor.cancelField.confirmationModal.description": "フィールドの変更は破棄されます。続行しますか?", - "indexPatternFieldEditor.cancelField.confirmationModal.title": "変更を破棄", - "indexPatternFieldEditor.color.actions": "アクション", - "indexPatternFieldEditor.color.addColorButton": "色を追加", - "indexPatternFieldEditor.color.backgroundLabel": "背景色", - "indexPatternFieldEditor.color.deleteAria": "削除", - "indexPatternFieldEditor.color.deleteTitle": "色のフォーマットを削除", - "indexPatternFieldEditor.color.exampleLabel": "例", - "indexPatternFieldEditor.color.patternLabel": "パターン(正規表現)", - "indexPatternFieldEditor.color.rangeLabel": "範囲(min:max)", - "indexPatternFieldEditor.color.textColorLabel": "文字の色", - "indexPatternFieldEditor.createField.flyoutAriaLabel": "フィールドを作成", - "indexPatternFieldEditor.date.documentationLabel": "ドキュメント", - "indexPatternFieldEditor.date.momentLabel": "Moment.jsのフォーマットパターン(デフォルト:{defaultPattern})", - "indexPatternFieldEditor.defaultErrorMessage": "このフォーマット構成の使用を試みた際にエラーが発生しました:{message}", - "indexPatternFieldEditor.defaultFormatDropDown": "- デフォルト -", - "indexPatternFieldEditor.defaultFormatHeader": "フォーマット(デフォルト:{defaultFormat})", - "indexPatternFieldEditor.deleteField.savedHeader": "「{fieldName}」が保存されました", - "indexPatternFieldEditor.deleteRuntimeField.confirmationModal.cancelButtonLabel": "キャンセル", - "indexPatternFieldEditor.deleteRuntimeField.confirmationModal.removeButtonLabel": "フィールドの削除", - "indexPatternFieldEditor.deleteRuntimeField.confirmationModal.removeMultipleButtonLabel": "フィールドの削除", - "indexPatternFieldEditor.deleteRuntimeField.confirmationModal.saveButtonLabel": "変更を保存", - "indexPatternFieldEditor.deleteRuntimeField.confirmModal.deleteMultipleTitle": "{count}個のフィールドを削除", - "indexPatternFieldEditor.deleteRuntimeField.confirmModal.deleteSingleTitle": "フィールド'{name}'を削除", - "indexPatternFieldEditor.deleteRuntimeField.confirmModal.multipleDeletionDescription": "これらのランタイムフィールドを削除しようとしています。", - "indexPatternFieldEditor.deleteRuntimeField.confirmModal.typeConfirm": "REMOVEと入力すると確認します", - "indexPatternFieldEditor.deleteRuntimeField.confirmModal.warningChangingFields": "名前または型を変更すると、このフィールドに依存する検索およびビジュアライゼーションが破損する可能性があります。", - "indexPatternFieldEditor.deleteRuntimeField.confirmModal.warningRemovingFields": "フィールドを削除すると、このフィールドに依存する検索およびビジュアライゼーションが破損する可能性があります。", - "indexPatternFieldEditor.duration.decimalPlacesLabel": "小数部分の桁数", - "indexPatternFieldEditor.duration.includeSpace": "サフィックスと値の間にスペースを入れる", - "indexPatternFieldEditor.duration.inputFormatLabel": "インプット形式", - "indexPatternFieldEditor.duration.outputFormatLabel": "アウトプット形式", - "indexPatternFieldEditor.duration.showSuffixLabel": "接尾辞を表示", - "indexPatternFieldEditor.duration.showSuffixLabel.short": "短縮サフィックスを使用", - "indexPatternFieldEditor.durationErrorMessage": "小数部分の桁数は0から20までの間で指定する必要があります", - "indexPatternFieldEditor.editField.flyoutAriaLabel": "{fieldName} フィールドの編集", - "indexPatternFieldEditor.editor.flyoutCancelButtonLabel": "キャンセル", - "indexPatternFieldEditor.editor.flyoutDefaultTitle": "フィールドを作成", - "indexPatternFieldEditor.editor.flyoutEditFieldSubtitle": "インデックスパターン:{patternName}", - "indexPatternFieldEditor.editor.flyoutEditFieldTitle": "「{fieldName}」フィールドの編集", - "indexPatternFieldEditor.editor.flyoutSaveButtonLabel": "保存", - "indexPatternFieldEditor.editor.form.advancedSettings.hideButtonLabel": "高度な SIEM 設定の非表示化", - "indexPatternFieldEditor.editor.form.advancedSettings.showButtonLabel": "高度なSIEM設定の表示", - "indexPatternFieldEditor.editor.form.changeWarning": "名前または型を変更すると、このフィールドに依存する検索およびビジュアライゼーションが破損する可能性があります。", - "indexPatternFieldEditor.editor.form.customLabelDescription": "Discover、Maps、Visualizeでフィールド名の代わりに表示するラベルを作成します。長いフィールド名を短くする際に役立ちます。 クエリとフィルターは元のフィールド名を使用します。", - "indexPatternFieldEditor.editor.form.customLabelLabel": "カスタムラベル", - "indexPatternFieldEditor.editor.form.customLabelTitle": "カスタムラベルを設定", - "indexPatternFieldEditor.editor.form.defineFieldLabel": "スクリプトを定義", - "indexPatternFieldEditor.editor.form.fieldShadowingCalloutDescription": "このフィールドはマッピングされたフィールドの名前を共有します。このフィールドの値は検索結果に返されます。", - "indexPatternFieldEditor.editor.form.fieldShadowingCalloutTitle": "フィールドシャドーイング", - "indexPatternFieldEditor.editor.form.formatDescription": "値を表示する任意の形式を設定します。形式を変更すると値に影響し、Discoverでのハイライトができない可能性があります。", - "indexPatternFieldEditor.editor.form.formatTitle": "フォーマットの設定", - "indexPatternFieldEditor.editor.form.nameAriaLabel": "名前フィールド", - "indexPatternFieldEditor.editor.form.nameLabel": "名前", - "indexPatternFieldEditor.editor.form.popularityDescription": "ポピュラリティを調整し、フィールドリストでフィールドを上下に表示させます。 デフォルトでは、Discoverは選択の多いものから選択の少ないものの順に表示します。", - "indexPatternFieldEditor.editor.form.popularityLabel": "利用頻度", - "indexPatternFieldEditor.editor.form.popularityTitle": "ポピュラリティ", - "indexPatternFieldEditor.editor.form.runtimeType.placeholderLabel": "タイプを選択", - "indexPatternFieldEditor.editor.form.runtimeTypeLabel": "型", - "indexPatternFieldEditor.editor.form.script.learnMoreLinkText": "スクリプト構文の詳細を参照してください。", - "indexPatternFieldEditor.editor.form.scriptEditor.compileErrorMessage": "Painlessスクリプトのコンパイルエラー", - "indexPatternFieldEditor.editor.form.scriptEditorAriaLabel": "スクリプトエディター", - "indexPatternFieldEditor.editor.form.source.scriptFieldHelpText": "スクリプトがないランタイムフィールドは、{source}から値を取得します。フィールドが_sourceに存在しない場合は、検索リクエストは値を返しません。{learnMoreLink}", - "indexPatternFieldEditor.editor.form.typeSelectAriaLabel": "タイプ選択", - "indexPatternFieldEditor.editor.form.validations.customLabelIsRequiredErrorMessage": "フィールドにラベルを付けます。", - "indexPatternFieldEditor.editor.form.validations.nameIsRequiredErrorMessage": "名前が必要です。", - "indexPatternFieldEditor.editor.form.validations.popularityGreaterThan0ErrorMessage": "ポピュラリティはゼロ以上でなければなりません。", - "indexPatternFieldEditor.editor.form.validations.popularityIsRequiredErrorMessage": "フィールドにポピュラリティを割り当てます。", - "indexPatternFieldEditor.editor.form.validations.scriptIsRequiredErrorMessage": "フィールド値を設定するには、スクリプトが必要です。", - "indexPatternFieldEditor.editor.form.valueDescription": "{source}の同じ名前のフィールドから取得するのではなく、フィールドの値を設定します。", - "indexPatternFieldEditor.editor.form.valueTitle": "値を設定", - "indexPatternFieldEditor.editor.runtimeFieldsEditor.existRuntimeFieldNamesValidationErrorMessage": "この名前のフィールドはすでに存在します。", - "indexPatternFieldEditor.fieldPreview.documentIdField.label": "ドキュメントID", - "indexPatternFieldEditor.fieldPreview.documentIdField.loadDocumentsFromCluster": "クラスターからドキュメントを読み込む", - "indexPatternFieldEditor.fieldPreview.documentNav.nextArialabel": "次のドキュメント", - "indexPatternFieldEditor.fieldPreview.documentNav.previousArialabel": "前のドキュメント", - "indexPatternFieldEditor.fieldPreview.emptyPromptDescription": "既存のフィールドの名前を入力するか、スクリプトを定義して、計算された出力のプレビューを表示します。", - "indexPatternFieldEditor.fieldPreview.emptyPromptTitle": "プレビュー", - "indexPatternFieldEditor.fieldPreview.error.documentNotFoundDescription": "ドキュメントIDが見つかりません", - "indexPatternFieldEditor.fieldPreview.errorCallout.title": "プレビューエラー", - "indexPatternFieldEditor.fieldPreview.errorTitle": "フィールドプレビューを読み込めませんでした", - "indexPatternFieldEditor.fieldPreview.filterFieldsPlaceholder": "フィールドのフィルタリング", - "indexPatternFieldEditor.fieldPreview.pinFieldButtonLabel": "フィールドを固定", - "indexPatternFieldEditor.fieldPreview.searchResult.emptyPrompt.clearSearchButtonLabel": "検索のクリア", - "indexPatternFieldEditor.fieldPreview.searchResult.emptyPromptTitle": "このインデックスパターンには一致するフィールドがありません", - "indexPatternFieldEditor.fieldPreview.showLessFieldsButtonLabel": "簡易表示", - "indexPatternFieldEditor.fieldPreview.showMoreFieldsButtonLabel": "詳細表示", - "indexPatternFieldEditor.fieldPreview.subTitle": "開始:{from}", - "indexPatternFieldEditor.fieldPreview.subTitle.customData": "カスタムデータ", - "indexPatternFieldEditor.fieldPreview.title": "プレビュー", - "indexPatternFieldEditor.fieldPreview.updatingPreviewLabel": "更新中...", - "indexPatternFieldEditor.fieldPreview.viewImageButtonLabel": "画像を表示", - "indexPatternFieldEditor.formatHeader": "フォーマット", - "indexPatternFieldEditor.histogram.histogramAsNumberLabel": "アグリゲーションされた数値形式", - "indexPatternFieldEditor.histogram.numeralLabel": "数値形式パターン(任意)", - "indexPatternFieldEditor.histogram.subFormat.bytes": "バイト", - "indexPatternFieldEditor.histogram.subFormat.number": "数字", - "indexPatternFieldEditor.histogram.subFormat.percent": "割合(%)", - "indexPatternFieldEditor.noSuchFieldName": "フィールド名'{fieldName}'はインデックスパターンで見つかりません", - "indexPatternFieldEditor.number.documentationLabel": "ドキュメント", - "indexPatternFieldEditor.number.numeralLabel": "Numeral.js のフォーマットパターン (デフォルト: {defaultPattern})", - "indexPatternFieldEditor.samples.inputHeader": "インプット", - "indexPatternFieldEditor.samples.outputHeader": "アウトプット", - "indexPatternFieldEditor.samplesHeader": "サンプル", - "indexPatternFieldEditor.save.deleteErrorTitle": "フィールド削除を保存できませんでした", - "indexPatternFieldEditor.save.errorTitle": "フィールド変更を保存できませんでした", - "indexPatternFieldEditor.saveRuntimeField.confirmationModal.cancelButtonLabel": "キャンセル", - "indexPatternFieldEditor.saveRuntimeField.confirmModal.title": "変更を'{name}'に保存", - "indexPatternFieldEditor.saveRuntimeField.confirmModal.typeConfirm": "続行するにはCHANGEと入力します", - "indexPatternFieldEditor.staticLookup.actions": "アクション", - "indexPatternFieldEditor.staticLookup.addEntryButton": "エントリーを追加", - "indexPatternFieldEditor.staticLookup.deleteAria": "削除", - "indexPatternFieldEditor.staticLookup.deleteTitle": "エントリーの削除", - "indexPatternFieldEditor.staticLookup.keyLabel": "キー", - "indexPatternFieldEditor.staticLookup.leaveBlankPlaceholder": "値をそのままにするには空欄にします", - "indexPatternFieldEditor.staticLookup.unknownKeyLabel": "不明なキーの値", - "indexPatternFieldEditor.staticLookup.valueLabel": "値", - "indexPatternFieldEditor.string.transformLabel": "変換", - "indexPatternFieldEditor.truncate.lengthLabel": "フィールドの長さ", - "indexPatternFieldEditor.url.heightLabel": "高さ", - "indexPatternFieldEditor.url.labelTemplateHelpText": "ラベルテンプレートのヘルプ", - "indexPatternFieldEditor.url.labelTemplateLabel": "ラベルテンプレート", - "indexPatternFieldEditor.url.offLabel": "オフ", - "indexPatternFieldEditor.url.onLabel": "オン", - "indexPatternFieldEditor.url.openTabLabel": "新規タブで開く", - "indexPatternFieldEditor.url.template.helpLinkText": "URLテンプレートのヘルプ", - "indexPatternFieldEditor.url.typeLabel": "型", - "indexPatternFieldEditor.url.urlTemplateLabel": "URLテンプレート", - "indexPatternFieldEditor.url.widthLabel": "幅", - "indexPatternManagement.actions.cancelButton": "キャンセル", - "indexPatternManagement.actions.createButton": "フィールドを作成", - "indexPatternManagement.actions.deleteButton": "削除", - "indexPatternManagement.actions.saveButton": "フィールドを保存", - "indexPatternManagement.createHeader": "スクリプトフィールドを作成", - "indexPatternManagement.customLabel": "カスタムラベル", - "indexPatternManagement.defaultFormatDropDown": "- デフォルト -", - "indexPatternManagement.defaultFormatHeader": "フォーマット(デフォルト:{defaultFormat})", - "indexPatternManagement.deleteField.cancelButton": "キャンセル", - "indexPatternManagement.deleteField.deleteButton": "削除", - "indexPatternManagement.deleteField.deletedHeader": "「{fieldName}」が削除されました", - "indexPatternManagement.deleteField.savedHeader": "「{fieldName}」が保存されました", - "indexPatternManagement.deleteFieldHeader": "フィールド「{fieldName}」を削除", - "indexPatternManagement.deleteFieldLabel": "削除されたフィールドは復元できません。{separator}続行してよろしいですか?", - "indexPatternManagement.disabledCallOutHeader": "スクリプティングが無効です", - "indexPatternManagement.disabledCallOutLabel": "Elasticsearchでのすべてのインラインスクリプティングが無効になっています。Kibanaでスクリプトフィールドを使用するには、インラインスクリプティングを有効にする必要があります。", - "indexPatternManagement.editHeader": "{fieldName}を編集", - "indexPatternManagement.editIndexPattern.deleteButton": "削除", - "indexPatternManagement.editIndexPattern.deprecation": "スクリプトフィールドは廃止予定です。代わりに{runtimeDocs}を使用してください。", - "indexPatternManagement.editIndexPattern.fields.addFieldButtonLabel": "フィールドの追加", - "indexPatternManagement.editIndexPattern.fields.allLangsDropDown": "すべての言語", - "indexPatternManagement.editIndexPattern.fields.allTypesDropDown": "すべてのフィールドタイプ", - "indexPatternManagement.editIndexPattern.fields.filterAria": "フィールドタイプをフィルター", - "indexPatternManagement.editIndexPattern.fields.filterPlaceholder": "検索", - "indexPatternManagement.editIndexPattern.fields.searchAria": "検索フィールド", - "indexPatternManagement.editIndexPattern.fields.table.additionalInfoAriaLabel": "追加フィールド情報", - "indexPatternManagement.editIndexPattern.fields.table.aggregatableDescription": "これらのフィールドはビジュアライゼーションの集約に使用できます", - "indexPatternManagement.editIndexPattern.fields.table.aggregatableLabel": "集約可能", - "indexPatternManagement.editIndexPattern.fields.table.customLabelTooltip": "フィールドのカスタムラベル。", - "indexPatternManagement.editIndexPattern.fields.table.deleteDescription": "削除", - "indexPatternManagement.editIndexPattern.fields.table.deleteLabel": "削除", - "indexPatternManagement.editIndexPattern.fields.table.editDescription": "編集", - "indexPatternManagement.editIndexPattern.fields.table.editLabel": "編集", - "indexPatternManagement.editIndexPattern.fields.table.excludedDescription": "取得の際に_sourceから除外されるフィールドです", - "indexPatternManagement.editIndexPattern.fields.table.excludedLabel": "除外", - "indexPatternManagement.editIndexPattern.fields.table.formatHeader": "フォーマット", - "indexPatternManagement.editIndexPattern.fields.table.isAggregatableAria": "は集約可能です", - "indexPatternManagement.editIndexPattern.fields.table.isExcludedAria": "は除外されています", - "indexPatternManagement.editIndexPattern.fields.table.isSearchableAria": "は検索可能です", - "indexPatternManagement.editIndexPattern.fields.table.multiTypeAria": "複数タイプのフィールド", - "indexPatternManagement.editIndexPattern.fields.table.multiTypeTooltip": "このフィールドのタイプはインデックスごとに変わります。多くの分析機能には使用できません。", - "indexPatternManagement.editIndexPattern.fields.table.nameHeader": "名前", - "indexPatternManagement.editIndexPattern.fields.table.primaryTimeAriaLabel": "プライマリ時間フィールド", - "indexPatternManagement.editIndexPattern.fields.table.primaryTimeTooltip": "このフィールドはイベントの発生時刻を表します。", - "indexPatternManagement.editIndexPattern.fields.table.runtimeIconTipTitle": "ランタイムフィールド", - "indexPatternManagement.editIndexPattern.fields.table.searchableDescription": "これらのフィールドはフィルターバーで使用できます", - "indexPatternManagement.editIndexPattern.fields.table.searchableHeader": "検索可能", - "indexPatternManagement.editIndexPattern.fields.table.typeHeader": "型", - "indexPatternManagement.editIndexPattern.list.DateHistogramDelaySummary": "遅延:{delay},", - "indexPatternManagement.editIndexPattern.list.dateHistogramSummary": "{aggName} (間隔:{interval}, {delay} {time_zone})", - "indexPatternManagement.editIndexPattern.list.defaultIndexPatternListName": "デフォルト", - "indexPatternManagement.editIndexPattern.list.histogramSummary": "{aggName} (間隔:{interval})", - "indexPatternManagement.editIndexPattern.list.rollupIndexPatternListName": "ロールアップ", - "indexPatternManagement.editIndexPattern.mappingConflictHeader": "マッピングの矛盾", - "indexPatternManagement.editIndexPattern.scripted.addFieldButton": "スクリプトフィールドを追加", - "indexPatternManagement.editIndexPattern.scripted.deleteField.cancelButton": "キャンセル", - "indexPatternManagement.editIndexPattern.scripted.deleteField.deleteButton": "削除", - "indexPatternManagement.editIndexPattern.scripted.deleteFieldLabel": "スクリプトフィールド「{fieldName}」を削除しますか?", - "indexPatternManagement.editIndexPattern.scripted.deprecationLangHeader": "廃止された言語が使用されています", - "indexPatternManagement.editIndexPattern.scripted.deprecationLangLabel.deprecationLangDetail": "次の廃止された言語が使用されています。{deprecatedLangsInUse}これらの言語は、KibanaとElasticsearchの次のメジャーバージョンでサポートされなくなります。問題を避けるため、スクリプトフィールドを{link}に変換してください。", - "indexPatternManagement.editIndexPattern.scripted.deprecationLangLabel.painlessDescription": "Painless", - "indexPatternManagement.editIndexPattern.scripted.newFieldPlaceholder": "新規スクリプトフィールド", - "indexPatternManagement.editIndexPattern.scripted.table.deleteDescription": "このフィールドを削除します", - "indexPatternManagement.editIndexPattern.scripted.table.deleteHeader": "削除", - "indexPatternManagement.editIndexPattern.scripted.table.editDescription": "このフィールドを編集します", - "indexPatternManagement.editIndexPattern.scripted.table.editHeader": "編集", - "indexPatternManagement.editIndexPattern.scripted.table.formatDescription": "フィールドに使用されているフォーマットです", - "indexPatternManagement.editIndexPattern.scripted.table.formatHeader": "フォーマット", - "indexPatternManagement.editIndexPattern.scripted.table.langDescription": "フィールドに使用されている言語です", - "indexPatternManagement.editIndexPattern.scripted.table.langHeader": "言語", - "indexPatternManagement.editIndexPattern.scripted.table.nameDescription": "フィールドの名前です", - "indexPatternManagement.editIndexPattern.scripted.table.nameHeader": "名前", - "indexPatternManagement.editIndexPattern.scripted.table.scriptDescription": "フィールドのスクリプトです", - "indexPatternManagement.editIndexPattern.scripted.table.scriptHeader": "スクリプト", - "indexPatternManagement.editIndexPattern.scriptedLabel": "スクリプトフィールドはビジュアライゼーションで使用され、ドキュメントに表示できます。ただし、検索することはできません。", - "indexPatternManagement.editIndexPattern.source.addButtonLabel": "追加", - "indexPatternManagement.editIndexPattern.source.deleteFilter.cancelButtonLabel": "キャンセル", - "indexPatternManagement.editIndexPattern.source.deleteFilter.deleteButtonLabel": "削除", - "indexPatternManagement.editIndexPattern.source.deleteSourceFilterLabel": "フィールドフィルター「{value}」を削除しますか?", - "indexPatternManagement.editIndexPattern.source.noteLabel": "下の表で、マルチフィールドが一致として誤って表示されます。これらのフィルターは、オリジナルのソースドキュメントのフィールドのみに適用されるため、一致するマルチフィールドはフィルタリングされません。", - "indexPatternManagement.editIndexPattern.source.table.cancelAria": "キャンセル", - "indexPatternManagement.editIndexPattern.source.table.deleteAria": "削除", - "indexPatternManagement.editIndexPattern.source.table.editAria": "編集", - "indexPatternManagement.editIndexPattern.source.table.filterDescription": "フィルター名", - "indexPatternManagement.editIndexPattern.source.table.filterHeader": "フィルター", - "indexPatternManagement.editIndexPattern.source.table.matchesDescription": "フィールドに使用されている言語です", - "indexPatternManagement.editIndexPattern.source.table.matchesHeader": "一致", - "indexPatternManagement.editIndexPattern.source.table.notMatchedLabel": "ソースフィルターが既知のフィールドと一致しません。", - "indexPatternManagement.editIndexPattern.source.table.saveAria": "保存", - "indexPatternManagement.editIndexPattern.sourceLabel": "フィールドフィルターは、ドキュメントの取得時に 1 つまたは複数のフィールドを除外するのに使用される場合もあります。これは Discover アプリでのドキュメントの表示中、またはダッシュボードアプリの保存された検索の結果を表示する表で起こります。ドキュメントに大きなフィールドや重要ではないフィールドが含まれている場合、この程度の低いレベルでフィルターにより除外すると良いかもしれません。", - "indexPatternManagement.editIndexPattern.sourcePlaceholder": "フィールドフィルター、ワイルドカード使用可(例:「user*」と入力して「user」で始まるフィールドをフィルタリング)", - "indexPatternManagement.editIndexPattern.tabs.fieldsHeader": "フィールド", - "indexPatternManagement.editIndexPattern.tabs.scriptedHeader": "スクリプトフィールド", - "indexPatternManagement.editIndexPattern.tabs.sourceHeader": "フィールドフィルター", - "indexPatternManagement.editIndexPattern.timeFilterHeader": "時刻フィールド:「{timeFieldName}」", - "indexPatternManagement.editIndexPattern.timeFilterLabel.mappingAPILink": "フィールドマッピング", - "indexPatternManagement.editIndexPattern.timeFilterLabel.timeFilterDetail": "{indexPatternTitle}でフィールドを表示して編集します。型や検索可否などのフィールド属性はElasticsearchで{mappingAPILink}に基づきます。", - "indexPatternManagement.fieldTypeConflict": "フィールドタイプの矛盾", - "indexPatternManagement.formatHeader": "フォーマット", - "indexPatternManagement.formatLabel": "フォーマットは、特定の値の表示形式を管理できます。また、値を完全に変更したり、Discover でのハイライト機能を無効にしたりすることも可能です。", - "indexPatternManagement.header.runtimeLink": "ランタイムフィールド", - "indexPatternManagement.indexNameLabel": "インデックス名", - "indexPatternManagement.indexPatterns.badge.readOnly.text": "読み取り専用", - "indexPatternManagement.indexPatterns.createFieldBreadcrumb": "フィールドを作成", - "indexPatternManagement.labelHelpText": "このフィールドが Discover、Maps、Visualize に表示されるときに使用するカスタムラベルを設定します。現在、クエリとフィルターはカスタムラベルをサポートせず、元のフィールド名が使用されます。", - "indexPatternManagement.languageLabel": "言語", - "indexPatternManagement.mappingConflictLabel.mappingConflictDetail": "{mappingConflict} {fieldName}というフィールドはすでに存在します。スクリプトフィールドに同じ名前を付けると、同時に両方のフィールドにクエリが実行できなくなります。", - "indexPatternManagement.mappingConflictLabel.mappingConflictLabel": "マッピングの矛盾:", - "indexPatternManagement.multiTypeLabelDesc": "このフィールドのタイプはインデックスごとに変わります。多くの分析機能には使用できません。タイプごとのインデックスは次のとおりです。", - "indexPatternManagement.nameErrorMessage": "名前が必要です", - "indexPatternManagement.nameLabel": "名前", - "indexPatternManagement.namePlaceholder": "新規スクリプトフィールド", - "indexPatternManagement.popularityLabel": "利用頻度", - "indexPatternManagement.script.accessWithLabel": "{code} でフィールドにアクセスします。", - "indexPatternManagement.script.getHelpLabel": "構文のヒントを得たり、スクリプトの結果をプレビューしたりできます。", - "indexPatternManagement.scriptedFieldsDeprecatedBody": "柔軟性とPainlessスクリプトサポートを強化するには、{runtimeDocs}を使用してください。", - "indexPatternManagement.scriptedFieldsDeprecatedTitle": "スクリプトフィールドは廃止予定です。", - "indexPatternManagement.scriptingLanguages.errorFetchingToastDescription": "Elasticsearchから利用可能なスクリプト言語の取得中にエラーが発生しました", - "indexPatternManagement.scriptInvalidErrorMessage": "スクリプトが無効です。詳細については、スクリプトプレビューを表示してください", - "indexPatternManagement.scriptLabel": "スクリプト", - "indexPatternManagement.scriptRequiredErrorMessage": "スクリプトが必要です", - "indexPatternManagement.syntax.default.formatLabel": "doc['some_field'].value", - "indexPatternManagement.syntax.defaultLabel.defaultDetail": "デフォルトで、KibanaのスクリプトフィールドはElasticsearchでの使用を目的に特別に開発されたシンプルでセキュアなスクリプト言語の{painless}を使用します。ドキュメントの値にアクセスするには次のフォーマットを使用します。", - "indexPatternManagement.syntax.defaultLabel.painlessLink": "Painless", - "indexPatternManagement.syntax.kibanaLabel": "現在、Kibanaでは、作成するPainlessスクリプトに特別な制限が1つ設定されています。Named関数を含めることができません。", - "indexPatternManagement.syntax.lucene.commonLabel.commonDetail": "Kibanaの旧バージョンからのアップグレードですか?おなじみの{lucene}は引き続きご利用いただけます。Lucene式はJavaScriptと非常に似ていますが、基本的な計算、ビット処理、比較オペレーション用に開発されたものです。", - "indexPatternManagement.syntax.lucene.commonLabel.luceneLink": "Lucene表現", - "indexPatternManagement.syntax.lucene.limits.fieldsLabel": "格納されたフィールドは利用できません", - "indexPatternManagement.syntax.lucene.limits.sparseLabel": "フィールドがまばらな(ドキュメントの一部にしか値がない)場合、値がないドキュメントには 0 の値が入力されます", - "indexPatternManagement.syntax.lucene.limits.typesLabel": "数字、ブール、日付、geo_pointフィールドのみアクセスできます", - "indexPatternManagement.syntax.lucene.limitsLabel": "Lucene表現には次のいくつかの制限があります。", - "indexPatternManagement.syntax.lucene.operations.arithmeticLabel": "算術演算子:{operators}", - "indexPatternManagement.syntax.lucene.operations.bitwiseLabel": "ビット処理演算子:{operators}", - "indexPatternManagement.syntax.lucene.operations.booleanLabel": "ブール演算子(三項演算子を含む):{operators}", - "indexPatternManagement.syntax.lucene.operations.comparisonLabel": "比較演算子:{operators}", - "indexPatternManagement.syntax.lucene.operations.distanceLabel": "距離関数:{operators}", - "indexPatternManagement.syntax.lucene.operations.mathLabel": "一般的な関数:{operators}", - "indexPatternManagement.syntax.lucene.operations.miscellaneousLabel": "その他関数:{operators}", - "indexPatternManagement.syntax.lucene.operations.trigLabel": "三角ライブラリ関数:{operators}", - "indexPatternManagement.syntax.lucene.operationsLabel": "Lucene表現で利用可能なオペレーションは次のとおりです。", - "indexPatternManagement.syntax.painlessLabel.javaAPIsLink": "ネイティブJava API", - "indexPatternManagement.syntax.painlessLabel.painlessDetail": "Painlessは非常に強力かつ使いやすい言語です。多くの{javaAPIs}にアクセスすることができます。{syntax}について読めば、すぐに習得することができます!", - "indexPatternManagement.syntax.painlessLabel.syntaxLink": "構文", - "indexPatternManagement.syntaxHeader": "構文", - "indexPatternManagement.testScript.errorMessage": "スクリプト内にエラーがあります", - "indexPatternManagement.testScript.fieldsLabel": "追加フィールド", - "indexPatternManagement.testScript.fieldsPlaceholder": "選択してください...", - "indexPatternManagement.testScript.instructions": "スクリプトを実行すると、最初の検索結果10件をプレビューできます。追加フィールドを選択して結果に含み、コンテキストをさらに加えたり、特定の文書上でフィルターにクエリを追加したりすることもできます。", - "indexPatternManagement.testScript.resultsLabel": "最初の10件", - "indexPatternManagement.testScript.resultsTitle": "結果を表示", - "indexPatternManagement.testScript.submitButtonLabel": "スクリプトを実行", - "indexPatternManagement.typeLabel": "型", - "indexPatternManagement.warningCallOutLabel.callOutDetail": "この機能を使う前に、{scripFields}と{scriptsInAggregation}についてよく理解するようにしてください。計算値の表示と集約にスクリプトフィールドが使用できます。そのため非常に遅い場合があり、適切に行わないとKibanaが使用できなくなる可能性もあります。", - "indexPatternManagement.warningCallOutLabel.runtimeLink": "ランタイムフィールド", - "indexPatternManagement.warningCallOutLabel.scripFieldsLink": "スクリプトフィールド", - "indexPatternManagement.warningCallOutLabel.scriptsInAggregationLink": "集約におけるスクリプト", - "indexPatternManagement.warningHeader": "廃止警告:", - "indexPatternManagement.warningLabel.painlessLinkLabel": "Painless", - "indexPatternManagement.warningLabel.warningDetail": "{language}は廃止され、KibanaとElasticsearchの次のメジャーバージョンではサポートされなくなります。新規スクリプトフィールドには{painlessLink}を使うことをお勧めします。", - "inputControl.control.noIndexPatternTooltip": "index-pattern id が見つかりませんでした:{indexPatternId}.", - "inputControl.control.notInitializedTooltip": "コントロールが初期化されていません", - "inputControl.control.noValuesDisableTooltip": "「{indexPatternName}」インデックスパターンでいずれのドキュメントにも存在しない「{fieldName}」フィールドがフィルターの対象になっています。異なるフィールドを選択するか、このフィールドに値が入力されているドキュメントをインデックスしてください。", - "inputControl.editor.controlEditor.controlLabel": "コントロールラベル", - "inputControl.editor.controlEditor.moveControlDownAriaLabel": "コントロールを下に移動", - "inputControl.editor.controlEditor.moveControlUpAriaLabel": "コントロールを上に移動", - "inputControl.editor.controlEditor.removeControlAriaLabel": "コントロールを削除", - "inputControl.editor.controlsTab.addButtonLabel": "追加", - "inputControl.editor.controlsTab.select.addControlAriaLabel": "コントロールを追加", - "inputControl.editor.controlsTab.select.controlTypeAriaLabel": "コントロールタイプを選択してください", - "inputControl.editor.controlsTab.select.listDropDownOptionLabel": "オプションリスト", - "inputControl.editor.controlsTab.select.rangeDropDownOptionLabel": "範囲スライダー", - "inputControl.editor.fieldSelect.fieldLabel": "フィールド", - "inputControl.editor.fieldSelect.selectFieldPlaceholder": "フィールドを選択してください...", - "inputControl.editor.indexPatternSelect.patternLabel": "インデックスパターン", - "inputControl.editor.indexPatternSelect.patternPlaceholder": "インデックスパターンを選択してください...", - "inputControl.editor.listControl.dynamicOptions.stringFieldDescription": "「文字列」フィールドでのみ利用可能", - "inputControl.editor.listControl.dynamicOptions.updateDescription": "ユーザーインプットに対する更新オプション", - "inputControl.editor.listControl.dynamicOptionsLabel": "ダイナミックオプション", - "inputControl.editor.listControl.multiselectDescription": "複数選択を許可", - "inputControl.editor.listControl.multiselectLabel": "複数選択", - "inputControl.editor.listControl.parentDescription": "オプションは親コントロールの値がベースになっています。親が設定されていない場合は無効です。", - "inputControl.editor.listControl.parentLabel": "親コントロール", - "inputControl.editor.listControl.sizeDescription": "オプション数", - "inputControl.editor.listControl.sizeLabel": "サイズ", - "inputControl.editor.optionsTab.pinFiltersLabel": "すべてのアプリケーションのフィルターをピン付け", - "inputControl.editor.optionsTab.updateFilterLabel": "変更するごとに Kibana フィルターを更新", - "inputControl.editor.optionsTab.useTimeFilterLabel": "時間フィルターを使用", - "inputControl.editor.rangeControl.decimalPlacesLabel": "小数部分の桁数", - "inputControl.editor.rangeControl.stepSizeLabel": "ステップサイズ", - "inputControl.function.help": "インプットコントロールビジュアライゼーション", - "inputControl.listControl.disableTooltip": "「{label}」が設定されるまで無効です。", - "inputControl.listControl.unableToFetchTooltip": "用語を取得できません、エラー:{errorMessage}", - "inputControl.rangeControl.unableToFetchTooltip": "範囲(最低値と最高値)を取得できません、エラー: {errorMessage}", - "inputControl.register.controlsDescription": "ドロップダウンメニューと範囲スライダーをダッシュボードに追加します。", - "inputControl.register.controlsTitle": "コントロール", - "inputControl.register.tabs.controlsTitle": "コントロール", - "inputControl.register.tabs.optionsTitle": "オプション", - "inputControl.vis.inputControlVis.applyChangesButtonLabel": "変更を適用", - "inputControl.vis.inputControlVis.cancelChangesButtonLabel": "変更をキャンセル", - "inputControl.vis.inputControlVis.clearFormButtonLabel": "用語を消去", - "inputControl.vis.listControl.partialResultsWarningMessage": "リクエストに長くかかり過ぎているため、用語リストが不完全な可能性があります。完全な結果を得るには、kibana.yml の自動完了設定を調整してください。", - "inputControl.vis.listControl.selectPlaceholder": "選択してください...", - "inputControl.vis.listControl.selectTextPlaceholder": "選択してください...", - "inspector.closeButton": "インスペクターを閉じる", - "inspector.reqTimestampDescription": "リクエストの開始が記録された時刻です", - "inspector.reqTimestampKey": "リクエストのタイムスタンプ", - "inspector.requests.copyToClipboardLabel": "クリップボードにコピー", - "inspector.requests.descriptionRowIconAriaLabel": "説明", - "inspector.requests.failedLabel": " (失敗)", - "inspector.requests.noRequestsLoggedDescription.elementHasNotLoggedAnyRequestsText": "エレメントが(まだ)リクエストを記録していません。", - "inspector.requests.noRequestsLoggedDescription.whatDoesItUsuallyMeanText": "これは通常、データを取得する必要がないか、エレメントがまだデータの取得を開始していないことを意味します。", - "inspector.requests.noRequestsLoggedTitle": "リクエストが記録されていません", - "inspector.requests.requestFailedTooltipTitle": "リクエストに失敗しました", - "inspector.requests.requestInProgressAriaLabel": "リクエストが進行中", - "inspector.requests.requestsDescriptionTooltip": "データを収集したリクエストを表示します", - "inspector.requests.requestsTitle": "リクエスト", - "inspector.requests.requestSucceededTooltipTitle": "リクエスト成功", - "inspector.requests.requestTabLabel": "リクエスト", - "inspector.requests.requestTimeLabel": "{requestTime}ms", - "inspector.requests.requestTooltipDescription": "リクエストの合計所要時間です。", - "inspector.requests.requestWasMadeDescription.requestHadFailureText": "、{failedCount} 件に失敗がありました", - "inspector.requests.responseTabLabel": "応答", - "inspector.requests.searchSessionId": "セッション ID を検索:{searchSessionId}", - "inspector.requests.statisticsTabLabel": "統計", - "inspector.title": "インスペクター", - "inspector.view": "{viewName} を表示", - "kibana_legacy.notify.toaster.errorStatusMessage": "エラー {errStatus} {errStatusText}: {errMessage}", - "kibana_legacy.notify.toaster.unavailableServerErrorMessage": "HTTP リクエストで接続に失敗しました。Kibana サーバーが実行されていて、ご使用のブラウザの接続が正常に動作していることを確認するか、システム管理者にお問い合わせください。", - "kibana_utils.history.savedObjectIsMissingNotificationMessage": "保存されたオブジェクトがありません", - "kibana_utils.stateManagement.stateHash.unableToRestoreUrlErrorMessage": "URL を完全に復元できません。共有機能を使用していることを確認してください。", - "kibana_utils.stateManagement.stateHash.unableToStoreHistoryInSessionErrorMessage": "セッションがいっぱいで安全に削除できるアイテムが見つからないため、Kibana は履歴アイテムを保存できません。\n\nこれは大抵新規タブに移動することで解決されますが、より大きな問題が原因である可能性もあります。このメッセージが定期的に表示される場合は、{gitHubIssuesUrl} で問題を報告してください。", - "kibana_utils.stateManagement.url.restoreUrlErrorTitle": "URLからの状態の復元エラー", - "kibana_utils.stateManagement.url.saveStateInUrlErrorTitle": "URLでの状態の保存エラー", - "kibana-react.dualRangeControl.maxInputAriaLabel": "範囲最大", - "kibana-react.dualRangeControl.minInputAriaLabel": "範囲最小", - "kibana-react.dualRangeControl.mustSetBothErrorMessage": "下と上の値の両方を設定する必要があります", - "kibana-react.dualRangeControl.outsideOfRangeErrorMessage": "値は {min} と {max} の間でなければなりません", - "kibana-react.dualRangeControl.upperValidErrorMessage": "上の値は下の値以上でなければなりません", - "kibana-react.exitFullScreenButton.exitFullScreenModeButtonAriaLabel": "全画面モードを終了", - "kibana-react.exitFullScreenButton.exitFullScreenModeButtonText": "全画面を終了", - "kibana-react.exitFullScreenButton.fullScreenModeDescription": "ESC キーで全画面モードを終了します。", - "kibana-react.kbnOverviewPageHeader.addDataButtonLabel": "データの追加", - "kibana-react.kbnOverviewPageHeader.devToolsButtonLabel": "開発ツール", - "kibana-react.kbnOverviewPageHeader.stackManagementButtonLabel": "管理", - "kibana-react.kibanaCodeEditor.ariaLabel": "コードエディター", - "kibana-react.kibanaCodeEditor.enterKeyLabel": "Enter", - "kibana-react.kibanaCodeEditor.escapeKeyLabel": "Esc", - "kibana-react.kibanaCodeEditor.startEditing": "編集を開始するには{key}を押してください。", - "kibana-react.kibanaCodeEditor.startEditingReadOnly": "コードの操作を開始するには{key}を押してください。", - "kibana-react.kibanaCodeEditor.stopEditing": "編集を停止するには{key}を押してください。", - "kibana-react.kibanaCodeEditor.stopEditingReadOnly": "コードの操作を停止するには{key}を押してください。", - "kibana-react.mountPointPortal.errorMessage": "ポータルコンテンツのレンダリングエラー", - "kibana-react.noDataPage.cantDecide": "どれを使用すべきかわからない場合{link}", - "kibana-react.noDataPage.cantDecide.link": "詳細については、ドキュメントをご確認ください。", - "kibana-react.noDataPage.elasticAgentCard.description": "Elasticエージェントを使用すると、シンプルで統一された方法でコンピューターからデータを収集するできます。", - "kibana-react.noDataPage.elasticAgentCard.title": "Elasticエージェントの追加", - "kibana-react.noDataPage.intro": "データを追加して開始するか、{solution}については{link}をご覧ください。", - "kibana-react.noDataPage.intro.link": "詳細", - "kibana-react.noDataPage.noDataPage.recommended": "推奨", - "kibana-react.noDataPage.welcomeTitle": "Elastic {solution}へようこそ。", - "kibana-react.pageFooter.changeDefaultRouteSuccessToast": "ランディングページが更新されました", - "kibana-react.pageFooter.changeHomeRouteLink": "ログイン時に別のページを表示", - "kibana-react.pageFooter.makeDefaultRouteLink": "これをランディングページにする", - "kibana-react.solutionNav.collapsibleLabel": "サイドナビゲーションを折りたたむ", - "kibana-react.solutionNav.mobileTitleText": "{solutionName}メニュー", - "kibana-react.solutionNav.openLabel": "サイドナビゲーションを開く", - "kibana-react.splitPanel.adjustPanelSizeAriaLabel": "左右のキーを押してパネルサイズを調整します", - "kibana-react.tableListView.listing.createNewItemButtonLabel": "Create {entityName}", - "kibana-react.tableListView.listing.deleteButtonMessage": "{itemCount} 件の {entityName} を削除", - "kibana-react.tableListView.listing.deleteConfirmModalDescription": "削除された {entityNamePlural} は復元できません。", - "kibana-react.tableListView.listing.deleteSelectedConfirmModal.title": "{itemCount} 件の {entityName} を削除", - "kibana-react.tableListView.listing.deleteSelectedItemsConfirmModal.cancelButtonLabel": "キャンセル", - "kibana-react.tableListView.listing.deleteSelectedItemsConfirmModal.confirmButtonLabel": "削除", - "kibana-react.tableListView.listing.deleteSelectedItemsConfirmModal.confirmButtonLabelDeleting": "削除中", - "kibana-react.tableListView.listing.fetchErrorDescription": "{entityName}リストを取得できませんでした。{message}", - "kibana-react.tableListView.listing.fetchErrorTitle": "リストを取得できませんでした", - "kibana-react.tableListView.listing.listingLimitExceeded.advancedSettingsLinkText": "高度な設定", - "kibana-react.tableListView.listing.listingLimitExceededDescription": "{totalItems} 件の {entityNamePlural} がありますが、{listingLimitText} の設定により {listingLimitValue} 件までしか下の表に表示できません。{advancedSettingsLink} の下でこの設定を変更できます。", - "kibana-react.tableListView.listing.listingLimitExceededTitle": "リスティング制限超過", - "kibana-react.tableListView.listing.noAvailableItemsMessage": "利用可能な {entityNamePlural} がありません。", - "kibana-react.tableListView.listing.noMatchedItemsMessage": "検索条件に一致する {entityNamePlural} がありません。", - "kibana-react.tableListView.listing.table.actionTitle": "アクション", - "kibana-react.tableListView.listing.table.editActionDescription": "編集", - "kibana-react.tableListView.listing.table.editActionName": "編集", - "kibana-react.tableListView.listing.unableToDeleteDangerMessage": "{entityName} を削除できません", - "kibanaOverview.addData.sampleDataButtonLabel": "サンプルデータを試す", - "kibanaOverview.addData.sectionTitle": "データを取り込む", - "kibanaOverview.apps.title": "これらのアプリを検索", - "kibanaOverview.breadcrumbs.title": "分析", - "kibanaOverview.header.title": "分析", - "kibanaOverview.kibana.solution.description": "強力な分析ツールやアプリケーションスイートを使用して、データを探索、可視化、分析できます。", - "kibanaOverview.kibana.solution.title": "分析", - "kibanaOverview.manageData.sectionTitle": "データを管理", - "kibanaOverview.more.title": "Elasticではさまざまなことが可能です", - "kibanaOverview.news.title": "新機能", - "kibanaOverview.noDataConfig.solutionName": "分析", - "lists.exceptions.doesNotExistOperatorLabel": "存在しない", - "lists.exceptions.existsOperatorLabel": "存在する", - "lists.exceptions.isInListOperatorLabel": "リストにある", - "lists.exceptions.isNotInListOperatorLabel": "リストにない", - "lists.exceptions.isNotOneOfOperatorLabel": "is not one of", - "lists.exceptions.isNotOperatorLabel": "is not", - "lists.exceptions.isOneOfOperatorLabel": "is one of", - "lists.exceptions.isOperatorLabel": "is", - "management.breadcrumb": "スタック管理", - "management.landing.header": "Stack Management {version}へようこそ", - "management.landing.subhead": "インデックス、インデックスパターン、保存されたオブジェクト、Kibanaの設定、その他を管理します。", - "management.landing.text": "アプリの一覧は左側のメニューにあります。", - "management.nav.label": "管理", - "management.sections.dataTip": "クラスターデータとバックアップを管理します", - "management.sections.dataTitle": "データ", - "management.sections.ingestTip": "データを変換し、クラスターに読み込む方法を管理します", - "management.sections.ingestTitle": "投入", - "management.sections.insightsAndAlertingTip": "データの変化を検出する方法を管理します", - "management.sections.insightsAndAlertingTitle": "アラートとインサイト", - "management.sections.kibanaTip": "Kibanaをカスタマイズし、保存されたオブジェクトを管理します", - "management.sections.kibanaTitle": "Kibana", - "management.sections.section.tip": "機能とデータへのアクセスを制御します", - "management.sections.section.title": "セキュリティ", - "management.sections.stackTip": "ライセンスを管理し、スタックをアップグレードします", - "management.sections.stackTitle": "スタック", - "management.stackManagement.managementDescription": "Elastic Stack の管理を行うセンターコンソールです。", - "management.stackManagement.managementLabel": "スタック管理", - "management.stackManagement.title": "スタック管理", - "monaco.painlessLanguage.autocomplete.docKeywordDescription": "doc['field_name'] 構文を使用して、スクリプトからフィールド値にアクセスします", - "monaco.painlessLanguage.autocomplete.emitKeywordDescription": "戻らずに値を発行します。", - "monaco.painlessLanguage.autocomplete.fieldValueDescription": "フィールド「{fieldName}」の値を取得します", - "monaco.painlessLanguage.autocomplete.paramsKeywordDescription": "スクリプトに渡された変数にアクセスします。", - "newsfeed.emptyPrompt.noNewsText": "Kibana インスタンスがインターネットにアクセスできない場合、管理者にこの機能を無効にするように依頼してください。そうでない場合は、ニュースを取り込み続けます。", - "newsfeed.emptyPrompt.noNewsTitle": "ニュースがない場合", - "newsfeed.flyoutList.closeButtonLabel": "閉じる", - "newsfeed.flyoutList.versionTextLabel": "{version}", - "newsfeed.flyoutList.whatsNewTitle": "Elastic の新機能", - "newsfeed.headerButton.readAriaLabel": "ニュースフィードメニュー - すべての項目が既読です", - "newsfeed.headerButton.unreadAriaLabel": "ニュースフィードメニュー - 未読の項目があります", - "newsfeed.loadingPrompt.gettingNewsText": "最新ニュースを取得しています...", - "presentationUtil.dashboardPicker.searchDashboardPlaceholder": "ダッシュボードを検索...", - "presentationUtil.labs.components.browserSwitchHelp": "このブラウザーでラボを有効にします。ブラウザーを閉じた後も永続します。", - "presentationUtil.labs.components.browserSwitchName": "ブラウザー", - "presentationUtil.labs.components.calloutHelp": "変更を適用するには更新します", - "presentationUtil.labs.components.closeButtonLabel": "閉じる", - "presentationUtil.labs.components.descriptionMessage": "開発中の機能や実験的な機能を試します。", - "presentationUtil.labs.components.disabledStatusMessage": "デフォルト: {status}", - "presentationUtil.labs.components.enabledStatusMessage": "デフォルト: {status}", - "presentationUtil.labs.components.kibanaSwitchHelp": "すべてのKibanaユーザーでこのラボを有効にします。", - "presentationUtil.labs.components.kibanaSwitchName": "Kibana", - "presentationUtil.labs.components.labFlagsLabel": "ラボフラグ", - "presentationUtil.labs.components.noProjectsinSolutionMessage": "現在{solutionName}にはラボがありません。", - "presentationUtil.labs.components.noProjectsMessage": "現在ラボはありません。", - "presentationUtil.labs.components.overrideFlagsLabel": "上書き", - "presentationUtil.labs.components.overridenIconTipLabel": "デフォルトの上書き", - "presentationUtil.labs.components.resetToDefaultLabel": "デフォルトにリセット", - "presentationUtil.labs.components.sessionSwitchHelp": "このブラウザーセッションのラボを有効にします。ブラウザーを閉じるとリセットされます。", - "presentationUtil.labs.components.sessionSwitchName": "セッション", - "presentationUtil.labs.components.titleLabel": "ラボ", - "presentationUtil.labs.enableDeferBelowFoldProjectDescription": "「区切り」の下のすべてのパネル(ウィンドウ下部の下にある非表示の領域)はすぐに読み込まれません。ビューポートを入力するときにのみ読み込まれます", - "presentationUtil.labs.enableDeferBelowFoldProjectName": "「区切り」の下のパネルの読み込みを延期", - "presentationUtil.saveModalDashboard.addToDashboardLabel": "ダッシュボードに追加", - "presentationUtil.saveModalDashboard.dashboardInfoTooltip": "Visualizeライブラリに追加された項目はすべてのダッシュボードで使用できます。ライブラリ項目の編集は、使用されるすべての場所に表示されます。", - "presentationUtil.saveModalDashboard.existingDashboardOptionLabel": "既存", - "presentationUtil.saveModalDashboard.libraryOptionLabel": "ライブラリに追加", - "presentationUtil.saveModalDashboard.newDashboardOptionLabel": "新規", - "presentationUtil.saveModalDashboard.noDashboardOptionLabel": "なし", - "presentationUtil.saveModalDashboard.saveAndGoToDashboardLabel": "保存してダッシュボードを開く", - "presentationUtil.saveModalDashboard.saveLabel": "保存", - "presentationUtil.saveModalDashboard.saveToLibraryLabel": "保存してライブラリに追加", - "presentationUtil.solutionToolbar.editorMenuButtonLabel": "すべてのエディター", - "presentationUtil.solutionToolbar.libraryButtonLabel": "ライブラリから追加", - "presentationUtil.solutionToolbar.quickButton.ariaButtonLabel": "新しい{createType}を作成", - "presentationUtil.solutionToolbar.quickButton.legendLabel": "クイック作成", - "savedObjects.advancedSettings.listingLimitText": "一覧ページ用に取得するオブジェクトの数です", - "savedObjects.advancedSettings.listingLimitTitle": "オブジェクト取得制限", - "savedObjects.advancedSettings.perPageText": "読み込みダイアログで表示されるページごとのオブジェクトの数です", - "savedObjects.advancedSettings.perPageTitle": "ページごとのオブジェクト数", - "savedObjects.confirmModal.cancelButtonLabel": "キャンセル", - "savedObjects.confirmModal.overwriteButtonLabel": "上書き", - "savedObjects.confirmModal.overwriteConfirmationMessage": "{title} を上書きしてよろしいですか?", - "savedObjects.confirmModal.overwriteTitle": "{name} を上書きしますか?", - "savedObjects.confirmModal.saveDuplicateButtonLabel": "{name} を保存", - "savedObjects.confirmModal.saveDuplicateConfirmationMessage": "「{title}」というタイトルの {name} がすでに存在します。保存しますか?", - "savedObjects.finder.filterButtonLabel": "タイプ", - "savedObjects.finder.searchPlaceholder": "検索…", - "savedObjects.finder.sortAsc": "昇順", - "savedObjects.finder.sortAuto": "ベストマッチ", - "savedObjects.finder.sortButtonLabel": "並べ替え", - "savedObjects.finder.sortDesc": "降順", - "savedObjects.overwriteRejectedDescription": "上書き確認が拒否されました", - "savedObjects.saveDuplicateRejectedDescription": "重複ファイルの保存確認が拒否されました", - "savedObjects.saveModal.cancelButtonLabel": "キャンセル", - "savedObjects.saveModal.descriptionLabel": "説明", - "savedObjects.saveModal.duplicateTitleDescription": "「{title}」を保存すると、タイトルが重複します。", - "savedObjects.saveModal.duplicateTitleLabel": "この{objectType}はすでに存在します", - "savedObjects.saveModal.saveAsNewLabel": "新しい {objectType} として保存", - "savedObjects.saveModal.saveButtonLabel": "保存", - "savedObjects.saveModal.saveTitle": "{objectType} を保存", - "savedObjects.saveModal.titleLabel": "タイトル", - "savedObjects.saveModalOrigin.addToOriginLabel": "追加", - "savedObjects.saveModalOrigin.originAfterSavingSwitchLabel": "保存後に{originVerb}から{origin}", - "savedObjects.saveModalOrigin.returnToOriginLabel": "戻る", - "savedObjects.saveModalOrigin.saveAndReturnLabel": "保存して戻る", - "savedObjectsManagement.breadcrumb.index": "保存されたオブジェクト", - "savedObjectsManagement.deleteConfirm.modalDeleteButtonLabel": "削除", - "savedObjectsManagement.deleteConfirm.modalDescription": "このアクションはオブジェクトをKibanaから永久に削除します。", - "savedObjectsManagement.deleteConfirm.modalTitle": "「{title}」を削除しますか?", - "savedObjectsManagement.deleteSavedObjectsConfirmModalDescription": "この操作は次の保存されたオブジェクトを削除します:", - "savedObjectsManagement.importSummary.createdCountHeader": "{createdCount}件の新規項目", - "savedObjectsManagement.importSummary.createdOutcomeLabel": "作成済み", - "savedObjectsManagement.importSummary.errorCountHeader": "{errorCount}件のエラー", - "savedObjectsManagement.importSummary.errorOutcomeLabel": "{errorMessage}", - "savedObjectsManagement.importSummary.overwrittenCountHeader": "{overwrittenCount} overwritten", - "savedObjectsManagement.importSummary.overwrittenOutcomeLabel": "上書き", - "savedObjectsManagement.importSummary.warnings.defaultButtonLabel": "Go", - "savedObjectsManagement.managementSectionLabel": "保存されたオブジェクト", - "savedObjectsManagement.objects.savedObjectsTitle": "保存されたオブジェクト", - "savedObjectsManagement.objectsTable.deleteConfirmModal.sharedObjectsCallout.content": "共有オブジェクトは属しているすべてのスペースから削除されます。", - "savedObjectsManagement.objectsTable.deleteSavedObjectsConfirmModal.cancelButtonLabel": "キャンセル", - "savedObjectsManagement.objectsTable.deleteSavedObjectsConfirmModal.idColumnName": "Id", - "savedObjectsManagement.objectsTable.deleteSavedObjectsConfirmModal.titleColumnName": "タイトル", - "savedObjectsManagement.objectsTable.deleteSavedObjectsConfirmModal.typeColumnName": "型", - "savedObjectsManagement.objectsTable.deleteSavedObjectsConfirmModalTitle": "保存されたオブジェクトの削除", - "savedObjectsManagement.objectsTable.export.successNotification": "ファイルはバックグラウンドでダウンロード中です", - "savedObjectsManagement.objectsTable.export.successWithExcludedObjectsNotification": "ファイルはバックグラウンドでダウンロード中です。一部のオブジェクトはエクスポートから除外されました。除外されたオブジェクトの一覧は、エクスポートされたファイルの最後の行をご覧ください。", - "savedObjectsManagement.objectsTable.export.successWithMissingRefsNotification": "ファイルはバックグラウンドでダウンロード中です。一部の関連オブジェクトが見つかりませんでした。足りないオブジェクトの一覧は、エクスポートされたファイルの最後の行をご覧ください。", - "savedObjectsManagement.objectsTable.exportObjectsConfirmModal.cancelButtonLabel": "キャンセル", - "savedObjectsManagement.objectsTable.exportObjectsConfirmModal.exportAllButtonLabel": "すべてエクスポート", - "savedObjectsManagement.objectsTable.exportObjectsConfirmModal.exportOptionsLabel": "オプション", - "savedObjectsManagement.objectsTable.exportObjectsConfirmModal.includeReferencesDeepLabel": "関連オブジェクトを含める", - "savedObjectsManagement.objectsTable.exportObjectsConfirmModalDescription": "エクスポートするタイプを選択してください", - "savedObjectsManagement.objectsTable.flyout.errorCalloutTitle": "申し訳ございません、エラーが発生しました", - "savedObjectsManagement.objectsTable.flyout.import.cancelButtonLabel": "キャンセル", - "savedObjectsManagement.objectsTable.flyout.import.confirmButtonLabel": "インポート", - "savedObjectsManagement.objectsTable.flyout.importFileErrorMessage": "エラーのためファイルを処理できませんでした:「{error}」", - "savedObjectsManagement.objectsTable.flyout.importPromptText": "インポート", - "savedObjectsManagement.objectsTable.flyout.importSavedObjectTitle": "保存されたオブジェクトのインポート", - "savedObjectsManagement.objectsTable.flyout.importSuccessful.confirmAllChangesButtonLabel": "すべての変更を確定", - "savedObjectsManagement.objectsTable.flyout.importSuccessful.confirmButtonLabel": "完了", - "savedObjectsManagement.objectsTable.flyout.indexPatternConflictsCalloutLinkText": "新規インデックスパターンを作成", - "savedObjectsManagement.objectsTable.flyout.indexPatternConflictsDescription": "次の保存されたオブジェクトは、存在しないインデックスパターンを使用しています。関連付け直す別のインデックスパターンを選択してください。必要に応じて、{indexPatternLink}できます。", - "savedObjectsManagement.objectsTable.flyout.indexPatternConflictsTitle": "インデックスパターンの矛盾", - "savedObjectsManagement.objectsTable.flyout.renderConflicts.columnCountDescription": "影響されるオブジェクトの数です", - "savedObjectsManagement.objectsTable.flyout.renderConflicts.columnCountName": "カウント", - "savedObjectsManagement.objectsTable.flyout.renderConflicts.columnIdDescription": "インデックスパターンのIDです", - "savedObjectsManagement.objectsTable.flyout.renderConflicts.columnIdName": "ID", - "savedObjectsManagement.objectsTable.flyout.renderConflicts.columnNewIndexPatternName": "新規インデックスパターン", - "savedObjectsManagement.objectsTable.flyout.renderConflicts.columnSampleOfAffectedObjectsDescription": "影響されるオブジェクトのサンプル", - "savedObjectsManagement.objectsTable.flyout.renderConflicts.columnSampleOfAffectedObjectsName": "影響されるオブジェクトのサンプル", - "savedObjectsManagement.objectsTable.flyout.selectFileToImportFormRowLabel": "インポートするファイルを選択してください", - "savedObjectsManagement.objectsTable.header.importButtonLabel": "インポート", - "savedObjectsManagement.objectsTable.header.refreshButtonLabel": "更新", - "savedObjectsManagement.objectsTable.header.savedObjectsTitle": "保存されたオブジェクト", - "savedObjectsManagement.objectsTable.howToDeleteSavedObjectsDescription": "保存されたオブジェクトを管理して共有します。オブジェクトの基本データを編集するには、関連付けられたアプリケーションに移動します。", - "savedObjectsManagement.objectsTable.importModeControl.createNewCopies.disabledText": "オブジェクトが以前にコピーまたはインポートされたかどうかを確認します。", - "savedObjectsManagement.objectsTable.importModeControl.createNewCopies.disabledTitle": "既存のオブジェクトを確認", - "savedObjectsManagement.objectsTable.importModeControl.createNewCopies.enabledText": "このオプションを使用すると、オブジェクトの1つ以上のコピーを作成します。", - "savedObjectsManagement.objectsTable.importModeControl.createNewCopies.enabledTitle": "ランダムIDで新しいオブジェクトを作成", - "savedObjectsManagement.objectsTable.importModeControl.importOptionsTitle": "インポートオプション", - "savedObjectsManagement.objectsTable.importModeControl.overwrite.disabledLabel": "競合時にアクションを要求", - "savedObjectsManagement.objectsTable.importModeControl.overwrite.enabledLabel": "自動的に競合を上書き", - "savedObjectsManagement.objectsTable.importSummary.unsupportedTypeError": "サポートされていないオブジェクトタイプ", - "savedObjectsManagement.objectsTable.overwriteModal.body.ambiguousConflict": "「{title}」は複数の既存のオブジェクトと競合します。上書きしますか?", - "savedObjectsManagement.objectsTable.overwriteModal.body.conflict": "「{title}」は既存のオブジェクトと競合します。上書きしますか?", - "savedObjectsManagement.objectsTable.overwriteModal.cancelButtonText": "スキップ", - "savedObjectsManagement.objectsTable.overwriteModal.overwriteButtonText": "上書き", - "savedObjectsManagement.objectsTable.overwriteModal.selectControlLabel": "オブジェクトID", - "savedObjectsManagement.objectsTable.overwriteModal.title": "{type}を上書きしますか?", - "savedObjectsManagement.objectsTable.relationships.columnActions.inspectActionDescription": "この保存されたオブジェクトを確認してください", - "savedObjectsManagement.objectsTable.relationships.columnActions.inspectActionName": "検査", - "savedObjectsManagement.objectsTable.relationships.columnActionsName": "アクション", - "savedObjectsManagement.objectsTable.relationships.columnErrorDescription": "関係でエラーが発生しました", - "savedObjectsManagement.objectsTable.relationships.columnErrorName": "エラー", - "savedObjectsManagement.objectsTable.relationships.columnIdDescription": "保存されたオブジェクトのID", - "savedObjectsManagement.objectsTable.relationships.columnIdName": "Id", - "savedObjectsManagement.objectsTable.relationships.columnRelationship.childAsValue": "子", - "savedObjectsManagement.objectsTable.relationships.columnRelationship.parentAsValue": "親", - "savedObjectsManagement.objectsTable.relationships.columnRelationshipName": "直接関係", - "savedObjectsManagement.objectsTable.relationships.columnTitleDescription": "保存されたオブジェクトのタイトルです", - "savedObjectsManagement.objectsTable.relationships.columnTitleName": "タイトル", - "savedObjectsManagement.objectsTable.relationships.columnTypeDescription": "保存されたオブジェクトのタイプです", - "savedObjectsManagement.objectsTable.relationships.columnTypeName": "型", - "savedObjectsManagement.objectsTable.relationships.invalidRelationShip": "この保存されたオブジェクトには無効な関係がいくつかあります。", - "savedObjectsManagement.objectsTable.relationships.relationshipsTitle": "{title}に関連する保存済みオブジェクトはこちらです。この{type}を削除すると、親オブジェクトに影響しますが、子オブジェクトには影響しません。", - "savedObjectsManagement.objectsTable.relationships.renderErrorMessage": "エラー", - "savedObjectsManagement.objectsTable.relationships.search.filters.relationship.childAsValue.view": "子", - "savedObjectsManagement.objectsTable.relationships.search.filters.relationship.name": "直接関係", - "savedObjectsManagement.objectsTable.relationships.search.filters.relationship.parentAsValue.view": "親", - "savedObjectsManagement.objectsTable.relationships.search.filters.type.name": "型", - "savedObjectsManagement.objectsTable.searchBar.unableToParseQueryErrorMessage": "クエリをパースできません", - "savedObjectsManagement.objectsTable.table.columnActions.inspectActionDescription": "この保存されたオブジェクトを確認してください", - "savedObjectsManagement.objectsTable.table.columnActions.inspectActionName": "検査", - "savedObjectsManagement.objectsTable.table.columnActions.viewRelationshipsActionDescription": "この保存されたオブジェクトと他の保存されたオブジェクトとの関係性を表示します", - "savedObjectsManagement.objectsTable.table.columnActions.viewRelationshipsActionName": "関係", - "savedObjectsManagement.objectsTable.table.columnActionsName": "アクション", - "savedObjectsManagement.objectsTable.table.columnTitleDescription": "保存されたオブジェクトのタイトルです", - "savedObjectsManagement.objectsTable.table.columnTitleName": "タイトル", - "savedObjectsManagement.objectsTable.table.columnTypeDescription": "保存されたオブジェクトのタイプです", - "savedObjectsManagement.objectsTable.table.columnTypeName": "型", - "savedObjectsManagement.objectsTable.table.deleteButtonLabel": "削除", - "savedObjectsManagement.objectsTable.table.deleteButtonTitle": "保存されたオブジェクトを削除できません", - "savedObjectsManagement.objectsTable.table.exportButtonLabel": "エクスポート", - "savedObjectsManagement.objectsTable.table.exportPopoverButtonLabel": "エクスポート", - "savedObjectsManagement.objectsTable.table.typeFilterName": "型", - "savedObjectsManagement.objectsTable.unableFindSavedObjectNotificationMessage": "保存されたオブジェクトが見つかりません", - "savedObjectsManagement.objectsTable.unableFindSavedObjectsNotificationMessage": "保存されたオブジェクトが見つかりません", - "savedObjectsManagement.objectView.unableFindSavedObjectNotificationMessage": "保存されたオブジェクトが見つかりません", - "savedObjectsManagement.view.fieldDoesNotExistErrorMessage": "このオブジェクトに関連付けられたフィールドは、現在このインデックスパターンに存在しません。", - "savedObjectsManagement.view.indexPatternDoesNotExistErrorMessage": "このオブジェクトに関連付けられたインデックスパターンは現在存在しません。", - "savedObjectsManagement.view.savedObjectProblemErrorMessage": "この保存されたオブジェクトに問題があります", - "savedObjectsManagement.view.savedSearchDoesNotExistErrorMessage": "このオブジェクトに関連付けられた保存された検索は現在存在しません。", - "share.advancedSettings.csv.quoteValuesText": "csvエクスポートに値を引用するかどうかです", - "share.advancedSettings.csv.quoteValuesTitle": "CSVの値を引用", - "share.advancedSettings.csv.separatorText": "エクスポートされた値をこの文字列で区切ります", - "share.advancedSettings.csv.separatorTitle": "CSVセパレーター", - "share.contextMenu.embedCodeLabel": "埋め込みコード", - "share.contextMenu.embedCodePanelTitle": "埋め込みコード", - "share.contextMenu.permalinkPanelTitle": "パーマリンク", - "share.contextMenu.permalinksLabel": "パーマリンク", - "share.contextMenuTitle": "この {objectType} を共有", - "share.urlGenerators.error.createUrlFnProvided": "このジェネレーターは非推奨とマークされています。createUrl fn を付けないでください。", - "share.urlGenerators.error.migrationFnGivenNotDeprecated": "移行機能を提供する場合、このジェネレーターに非推奨マークを付ける必要があります", - "share.urlGenerators.error.noCreateUrlFnProvided": "このジェネレーターには非推奨のマークがありません。createUrl fn を付けてください。", - "share.urlGenerators.error.noMigrationFnProvided": "アクセスリンクジェネレーターに非推奨マークが付いている場合、移行機能を提供する必要があります。", - "share.urlGenerators.errors.noGeneratorWithId": "{id} という ID のジェネレーターはありません", - "share.urlPanel.canNotShareAsSavedObjectHelpText": "{objectType} が保存されるまで保存されたオブジェクトを共有することはできません。", - "share.urlPanel.copyIframeCodeButtonLabel": "iFrame コードをコピー", - "share.urlPanel.copyLinkButtonLabel": "リンクをコピー", - "share.urlPanel.generateLinkAsLabel": "名前を付けてリンクを生成", - "share.urlPanel.publicUrlHelpText": "公開URLを使用して、他のユーザーと共有します。ログインプロンプトをなくして、ワンステップの匿名アクセスを可能にします。", - "share.urlPanel.publicUrlLabel": "公開URL", - "share.urlPanel.savedObjectDescription": "この URL を共有することで、他のユーザーがこの {objectType} の最も最近保存されたバージョンを読み込めるようになります。", - "share.urlPanel.savedObjectLabel": "保存されたオブジェクト", - "share.urlPanel.shortUrlHelpText": "互換性が最も高くなるよう、短いスナップショット URL を共有することをお勧めします。Internet Explorer は URL の長さに制限があり、一部の wiki やマークアップパーサーは長い完全なスナップショット URL に対応していませんが、短い URL は正常に動作するはずです。", - "share.urlPanel.shortUrlLabel": "短い URL", - "share.urlPanel.snapshotDescription": "スナップショット URL には、{objectType} の現在の状態がエンコードされています。保存された {objectType} への編集内容はこの URL には反映されません。", - "share.urlPanel.snapshotLabel": "スナップショット", - "share.urlPanel.unableCreateShortUrlErrorMessage": "短い URL を作成できません。エラー:{errorMessage}", - "share.urlPanel.urlGroupTitle": "URL", - "share.urlService.redirect.components.Error.title": "リダイレクトエラー", - "share.urlService.redirect.components.Spinner.label": "リダイレクト中...", - "share.urlService.redirect.RedirectManager.invalidParamParams": "ロケーターパラメーターを解析できませんでした。ロケーターパラメーターはJSONとしてシリアル化し、「p」URL検索パラメーターで設定する必要があります。", - "share.urlService.redirect.RedirectManager.locatorNotFound": "ロケーター[ID = {id}]が存在しません。", - "share.urlService.redirect.RedirectManager.missingParamLocator": "ロケーターIDが指定されていません。URLで「l」検索パラメーターを指定します。これは既存のロケーターIDにしてください。", - "share.urlService.redirect.RedirectManager.missingParamParams": "ロケーターパラメーターが指定されていません。URLで「p」検索パラメーターを指定します。これはロケーターパラメーターのJSONシリアル化オブジェクトにしてください。", - "share.urlService.redirect.RedirectManager.missingParamVersion": "ロケーターパラメーターバージョンが指定されていません。URLで「v」検索パラメーターを指定します。これはロケーターパラメーターが生成されたときのKibanaのリリースバージョンです。", - "telemetry.callout.appliesSettingTitle": "この設定に加えた変更は {allOfKibanaText} に適用され、自動的に保存されます。", - "telemetry.callout.appliesSettingTitle.allOfKibanaText": "Kibana のすべて", - "telemetry.callout.clusterStatisticsDescription": "これは収集される基本的なクラスター統計の例です。インデックス、シャード、ノードの数が含まれます。監視がオンになっているかどうかなどのハイレベルの使用統計も含まれます。", - "telemetry.callout.clusterStatisticsTitle": "クラスター統計", - "telemetry.callout.errorLoadingClusterStatisticsDescription": "クラスター統計の取得中に予期せぬエラーが発生しました。Elasticsearch、Kibana、またはネットワークのエラーが原因の可能性があります。Kibana を確認し、ページを再読み込みして再試行してください。", - "telemetry.callout.errorLoadingClusterStatisticsTitle": "クラスター統計の読み込みエラー", - "telemetry.callout.errorUnprivilegedUserDescription": "暗号化されていないクラスター統計を表示するアクセス権がありません。", - "telemetry.callout.errorUnprivilegedUserTitle": "クラスター統計の表示エラー", - "telemetry.clusterData": "クラスターデータ", - "telemetry.optInErrorToastText": "使用状況統計設定の設定中にエラーが発生しました。", - "telemetry.optInErrorToastTitle": "エラー", - "telemetry.optInNoticeSeenErrorTitle": "エラー", - "telemetry.optInNoticeSeenErrorToastText": "通知の消去中にエラーが発生しました", - "telemetry.optInSuccessOff": "使用状況データ収集がオフです。", - "telemetry.optInSuccessOn": "使用状況データ収集がオンです。", - "telemetry.readOurUsageDataPrivacyStatementLinkText": "プライバシーポリシー", - "telemetry.securityData": "Endpoint Security データ", - "telemetry.telemetryBannerDescription": "Elastic Stackの改善にご協力ください使用状況データの収集は現在無効です。使用状況データの収集を有効にすると、製品とサービスを管理して改善することができます。詳細については、{privacyStatementLink}をご覧ください。", - "telemetry.telemetryConfigAndLinkDescription": "使用状況データの収集を有効にすると、製品とサービスを管理して改善することができます。詳細については、{privacyStatementLink}をご覧ください。", - "telemetry.telemetryOptedInDisableUsage": "ここで使用状況データを無効にする", - "telemetry.telemetryOptedInDismissMessage": "閉じる", - "telemetry.telemetryOptedInNoticeDescription": "使用状況データがどのように製品とサービスの管理と改善につながるのかに関する詳細については、{privacyStatementLink}をご覧ください。収集を停止するには、{disableLink}。", - "telemetry.telemetryOptedInNoticeTitle": "Elastic Stack の改善にご協力ください", - "telemetry.telemetryOptedInPrivacyStatement": "プライバシーポリシー", - "telemetry.usageDataTitle": "使用データ", - "telemetry.welcomeBanner.disableButtonLabel": "無効にする", - "telemetry.welcomeBanner.enableButtonLabel": "有効にする", - "telemetry.welcomeBanner.telemetryConfigDetailsDescription.telemetryPrivacyStatementLinkText": "プライバシーポリシー", - "telemetry.welcomeBanner.title": "Elastic Stack の改善にご協力ください", - "timelion.emptyExpressionErrorMessage": "Timelion エラー:式が入力されていません", - "timelion.expressionSuggestions.argument.description.acceptsText": "受け入れ", - "timelion.expressionSuggestions.func.description.chainableHelpText": "連鎖可能", - "timelion.expressionSuggestions.func.description.dataSourceHelpText": "データソース", - "timelion.fitFunctions.carry.downSampleErrorMessage": "ダウンサンプルには「carry」フィットメソドを使用せず、「scale」または「average」を使用してください", - "timelion.function.help": "Timelion のビジュアライゼーションです。", - "timelion.help.functions.absHelpText": "数列リストの各値の絶対値を返します", - "timelion.help.functions.aggregate.args.functionHelpText": "{functions} の 1 つ", - "timelion.help.functions.aggregateHelpText": "数列のすべての点の処理結果に基づく線を作成します。利用可能な関数:{functions}", - "timelion.help.functions.bars.args.stackHelpText": "バーがスタックした場合はデフォルトで true にする", - "timelion.help.functions.bars.args.widthHelpText": "バーの幅(ピクセル)", - "timelion.help.functions.barsHelpText": "seriesList をバーとして表示", - "timelion.help.functions.color.args.colorHelpText": "16 進数としての数列の色です。例:#c6c6c6 はかわいいライトグレーを示します。複数の色を指定し、複数数列がある場合、グラデーションになります。例:「#00B1CC:#00FF94:#FF3A39:#CC1A6F」", - "timelion.help.functions.colorHelpText": "数列の色を変更します", - "timelion.help.functions.common.args.fitHelpText": "ターゲットの期間と間隔に数列を合わせるためのアルゴリズムです。使用可能:{fitFunctions}", - "timelion.help.functions.common.args.offsetHelpText": "日付表現による数列の取得をオフセットします。例:1 か月前からイベントを作成する -1M は現在のように表示されます。「timerange」によって、チャートの全体的な時間範囲に関連した数列をオフセットします。例:「timerange:-2」は過去に対する全体的なチャート時間範囲の 2 倍をオフセットします。", - "timelion.help.functions.condition.args.elseHelpText": "比較が false の場合に点が設定される値です。ここで seriesList を引き渡した場合、初めの数列が使用されます。", - "timelion.help.functions.condition.args.ifHelpText": "点が比較される値です。ここで seriesList を引き渡した場合、初めの数列が使用されます。", - "timelion.help.functions.condition.args.operator.suggestions.eqHelpText": "equal", - "timelion.help.functions.condition.args.operator.suggestions.gteHelpText": "超過", - "timelion.help.functions.condition.args.operator.suggestions.gtHelpText": "より大きい", - "timelion.help.functions.condition.args.operator.suggestions.lteHelpText": "未満", - "timelion.help.functions.condition.args.operator.suggestions.ltHelpText": "より小さい", - "timelion.help.functions.condition.args.operator.suggestions.neHelpText": "not equal", - "timelion.help.functions.condition.args.operatorHelpText": "比較に使用する比較演算子、有効な演算子は eq(=)、ne(≠), lt(&lt;), lte(≦), gt(>), gte(≧)", - "timelion.help.functions.condition.args.thenHelpText": "比較が true の場合に点が設定される値です。ここで seriesList を引き渡した場合、初めの数列が使用されます。", - "timelion.help.functions.conditionHelpText": "演算子を使って各点を数字、または別の数列の同じ点と比較し、true の場合値を結果の値に設定し、オプションとして else が使用されます。", - "timelion.help.functions.cusum.args.baseHelpText": "開始の数字です。基本的に、数列の初めにこの数字が追加されます", - "timelion.help.functions.cusumHelpText": "ベースから始め、数列の累積和を返します。", - "timelion.help.functions.derivativeHelpText": "一定期間の値の変化をプロットします。", - "timelion.help.functions.divide.args.divisorHelpText": "割る数字または数列です。複数数列を含む seriesList はラベルに適用されます。", - "timelion.help.functions.divideHelpText": "seriesList の 1 つまたは複数の数列の値をインプット seriesList の各数列のそれぞれの配置に割けます。", - "timelion.help.functions.es.args.indexHelpText": "クエリを実行するインデックスで、ワイルドカードが使えます。「metrics」、「split」、「timefield」引数のスクリプトフィールドのフィールド名のインデックスパターン名とフィールド名の入力候補を提供します。", - "timelion.help.functions.es.args.intervalHelpText": "**これは使用しないでください**。fit 関数のデバッグは楽しいですが、間隔ピッカーを使用すべきです。", - "timelion.help.functions.es.args.kibanaHelpText": "Kibana ダッシュボードでフィルターを適用します。Kibana ダッシュボードの使用時にのみ適用されます。", - "timelion.help.functions.es.args.metricHelpText": "Elasticsearch メトリック集約:avg、sum、min、max、percentiles、または基数、後ろにフィールドを付けます。例:「sum:bytes」、「percentiles:bytes:95,99,99.9」、「count」", - "timelion.help.functions.es.args.qHelpText": "Lucene クエリ文字列の構文のクエリ", - "timelion.help.functions.es.args.splitHelpText": "分割する Elasticsearch フィールドと制限です。例:「{hostnameSplitArg}」は上位 10 のホスト名を取得します", - "timelion.help.functions.es.args.timefieldHelpText": "X 軸にフィールドタイプ「date」を使用", - "timelion.help.functions.esHelpText": "Elasticsearch インスタンスからデータを取得します", - "timelion.help.functions.firstHelpText": "これは単純に input seriesList を返す内部機能です。この機能は使わないでください", - "timelion.help.functions.fit.args.modeHelpText": "数列をターゲットに合わせるためのアルゴリズムです。次のいずれかです。{fitFunctions}", - "timelion.help.functions.fitHelpText": "定義された fit 関数を使用して空値を入力します", - "timelion.help.functions.graphite.args.metricHelpText": "取得する Graphite メトリック、例:{metricExample}", - "timelion.help.functions.graphiteHelpText": "[実験] Graphiteからデータを取得します。Kibana の高度な設定で Graphite サーバーを構成します", - "timelion.help.functions.hide.args.hideHelpText": "数列の表示と非表示を切り替えます", - "timelion.help.functions.hideHelpText": "デフォルトで数列を非表示にします", - "timelion.help.functions.holt.args.alphaHelpText": "\n 0 から 1 の平滑化加重です。\n アルファを上げると新しい数列がオリジナルにさらに近くなります。\n 下げると数列がスムーズになります", - "timelion.help.functions.holt.args.betaHelpText": "\n 0 から 1 の傾向加重です。\n ベータを上げると線の上下の動きが長くなります。\n 下げると新しい傾向をより早く反映するようになります", - "timelion.help.functions.holt.args.gammaHelpText": "0 から 1 のシーズン加重です。データが波のようになっていますか?\n この数字を上げると、最近のシーズンの重要性が高まり、波形の動きを速くします。\n 下げると新しいシーズンの重要性が下がり、過去がより重要視されます。", - "timelion.help.functions.holt.args.sampleHelpText": "\n シーズン数列の「予測」を開始する前にサンプリングするシーズンの数です。\n (gamma でのみ有効、デフォルト:all)", - "timelion.help.functions.holt.args.seasonHelpText": "シーズンの長さです、例:パターンが毎週繰り返される場合は 1w。(gamma でのみ有効)", - "timelion.help.functions.holtHelpText": "\n 数列の始めをサンプリングし、\n いくつかのオプションパラメーターを使用して何が起こるか予測します。基本的に、この機能は未来を予測するのではなく、\n 過去のデータに基づき現在何が起きているべきかを予測します。\n この情報は異常検知に役立ちます。null には予測値が入力されます。", - "timelion.help.functions.label.args.labelHelpText": "数列の凡例値です。文字列で $1、$2 などを使用して、正規表現の捕捉グループに合わせることができます。", - "timelion.help.functions.label.args.regexHelpText": "捕捉グループをサポートする正規表現です", - "timelion.help.functions.labelHelpText": "数列のラベルを変更します。%s で既存のラベルを参照します", - "timelion.help.functions.legend.args.columnsHelpText": "凡例を分ける列の数です", - "timelion.help.functions.legend.args.position.suggestions.falseHelpText": "凡例を無効にします", - "timelion.help.functions.legend.args.position.suggestions.neHelpText": "北東の角に凡例を配置します", - "timelion.help.functions.legend.args.position.suggestions.nwHelpText": "北西の角に凡例を配置します", - "timelion.help.functions.legend.args.position.suggestions.seHelpText": "南東の角に凡例を配置します", - "timelion.help.functions.legend.args.position.suggestions.swHelpText": "南西の角に凡例を配置します", - "timelion.help.functions.legend.args.positionHelpText": "凡例を配置する角:nw、ne、se、または sw。false で凡例を無効にすることもできます", - "timelion.help.functions.legend.args.showTimeHelpText": "グラフにカーソルを合わせた時、凡例の時間値を表示します。デフォルト:true", - "timelion.help.functions.legend.args.timeFormatHelpText": "moment.js フォーマットパターンです。デフォルト:{defaultTimeFormat}", - "timelion.help.functions.legendHelpText": "プロットの凡例の位置とスタイルを設定します", - "timelion.help.functions.lines.args.fillHelpText": "0 と 10 の間の数字です。エリアチャートの作成に使用します。", - "timelion.help.functions.lines.args.showHelpText": "線の表示と非表示を切り替えます", - "timelion.help.functions.lines.args.stackHelpText": "線をスタックします。よく誤解を招きます。この機能を使用する際は塗りつぶしを使うようにしましょう。", - "timelion.help.functions.lines.args.stepsHelpText": "線をステップとして表示します。つまり、点の間に中間値を挿入しません。", - "timelion.help.functions.lines.args.widthHelpText": "線の太さです", - "timelion.help.functions.linesHelpText": "seriesList を線として表示します", - "timelion.help.functions.log.args.baseHelpText": "対数のベースを設定します、デフォルトは 10 です", - "timelion.help.functions.logHelpText": "数列リストの各値の対数値を返します(デフォルトのベース:10)", - "timelion.help.functions.max.args.valueHelpText": "点を既存の値と引き渡された値のどちらか高い方に設定します。seriesList を引き渡す場合、数列がちょうど 1 つでなければなりません。", - "timelion.help.functions.maxHelpText": "インプット seriesList の各数列のそれぞれの配置の seriesList の 1 つまたは複数の数列の最高値です", - "timelion.help.functions.min.args.valueHelpText": "点を既存の値と引き渡された値のどちらか低い方に設定します。seriesList を引き渡す場合、数列がちょうど 1 つでなければなりません。", - "timelion.help.functions.minHelpText": "インプット seriesList の各数列のそれぞれの配置の seriesList の 1 つまたは複数の数列の最低値です", - "timelion.help.functions.movingaverage.args.positionHelpText": "結果時間に相対的な平均点の位置です。次のいずれかです。{validPositions}", - "timelion.help.functions.movingaverage.args.windowHelpText": "平均を出す点の数、または日付計算式(例:1d、1M)です。日付計算式が指定された場合、この機能は現在選択された間隔でできるだけ近づけます。日付計算式が間隔で均等に分けられない場合、結果に異常が出る場合があります。", - "timelion.help.functions.movingaverageHelpText": "特定期間の移動平均を計算します。ばらばらの数列を滑らかにするのに有効です。", - "timelion.help.functions.movingstd.args.positionHelpText": "結果時間に相対的な期間スライスの配置です。オプションは {positions} です。デフォルト:{defaultPosition}", - "timelion.help.functions.movingstd.args.windowHelpText": "標準偏差を計算する点の数です。", - "timelion.help.functions.movingstdHelpText": "特定期間の移動標準偏差を計算します。ネイティブ two-pass アルゴリズムを使用します。非常に長い数列や、非常に大きな数字を含む数列では、四捨五入による誤差がより明らかになる可能性があります。", - "timelion.help.functions.multiply.args.multiplierHelpText": "掛ける数字または数列です。複数数列を含む seriesList はラベルに適用されます。", - "timelion.help.functions.multiplyHelpText": "seriesList の 1 つまたは複数の数列の値をインプット seriesList の各数列のそれぞれの配置に掛けます。", - "timelion.help.functions.notAllowedGraphiteUrl": "この Graphite URL は kibana.yml ファイルで構成されていません。\n 「timelion.graphiteUrls」で kibana.yml ファイルの Graphite サーバーリストを構成し、\n Kibana の高度な設定でいずれかを選択してください", - "timelion.help.functions.points.args.fillColorHelpText": "点を塗りつぶす色です。", - "timelion.help.functions.points.args.fillHelpText": "塗りつぶしの透明度を表す 0 から 10 までの数字です", - "timelion.help.functions.points.args.radiusHelpText": "点のサイズです", - "timelion.help.functions.points.args.showHelpText": "点の表示・非表示です", - "timelion.help.functions.points.args.symbolHelpText": "点のシンボルです。次のいずれかです。{validSymbols}", - "timelion.help.functions.points.args.weightHelpText": "点の周りの太さです", - "timelion.help.functions.pointsHelpText": "数列を点として表示します", - "timelion.help.functions.precision.args.precisionHelpText": "各値を切り捨てる桁数です", - "timelion.help.functions.precisionHelpText": "値の小数点以下を切り捨てる桁数です", - "timelion.help.functions.props.args.globalHelpText": "各数列に対し、seriesList にプロップを設定します", - "timelion.help.functions.propsHelpText": "数列に任意のプロパティを設定するため、自己責任で行ってください。例:{example}。", - "timelion.help.functions.quandl.args.codeHelpText": "プロットする Quandl コードです。これらは quandl.com に掲載されています。", - "timelion.help.functions.quandl.args.positionHelpText": "Quandl ソースによっては、複数数列を返すものがあります。どれを使用しますか?1 ベースインデックス", - "timelion.help.functions.quandlHelpText": "\n [実験]\n Quandl コードで quandl.com からデータを取得します。Kibana で {quandlKeyField} を空き API キーに設定\n 高度な設定API は、キーなしでは非常に低いレート制限があります。", - "timelion.help.functions.range.args.maxHelpText": "新しい最高値です", - "timelion.help.functions.range.args.minHelpText": "新しい最低値です", - "timelion.help.functions.rangeHelpText": "同じシェイプを維持しつつ数列の最高値と最低値を変更します", - "timelion.help.functions.scaleInterval.args.intervalHelpText": "新しい間隔の日付計算表記です。例:1 秒 = 1s。1m、5m、1M、1w、1y など。", - "timelion.help.functions.scaleIntervalHelpText": "変更すると、値(通常合計またはカウント)が新しい間隔にスケーリングされます。例:毎秒のレート", - "timelion.help.functions.static.args.labelHelpText": "数列のラベルを簡単に設定する方法です。.label()関数を使用することもできます。", - "timelion.help.functions.static.args.valueHelpText": "表示する単一の値です。複数の値が渡された場合、指定された時間範囲に均等に挿入されます。", - "timelion.help.functions.staticHelpText": "チャートに 1 つの値を挿入します", - "timelion.help.functions.subtract.args.termHelpText": "インプットから引く数字または数列です。複数数列を含む seriesList はラベルに適用されます。", - "timelion.help.functions.subtractHelpText": "seriesList の 1 つまたは複数の数列の値をインプット seriesList の各数列のそれぞれの配置から引きます。", - "timelion.help.functions.sum.args.termHelpText": "インプット数列に足す数字または数列です。複数数列を含む seriesList はラベルに適用されます。", - "timelion.help.functions.sumHelpText": "seriesList の 1 つまたは複数の数列の値をインプット seriesList の各数列のそれぞれの配置に足します。", - "timelion.help.functions.title.args.titleHelpText": "プロットのタイトルです。", - "timelion.help.functions.titleHelpText": "プロットの上部にタイトルを追加します。複数の seriesList がコールされた場合、最後のコールが使用されます。", - "timelion.help.functions.trend.args.endHelpText": "始めまたは終わりからの計算を修了する場所です。たとえば、-10 の場合終わりから 10 点目で計算が終了し、+15 の場合始めから 15 点目で終了します。デフォルト:0", - "timelion.help.functions.trend.args.modeHelpText": "傾向線の生成に使用するアルゴリズムです。次のいずれかです。{validRegressions}", - "timelion.help.functions.trend.args.startHelpText": "始めまたは終わりからの計算を開始する場所です。たとえば、-10 の場合終わりから 10 点目から計算を開始し、+15 の場合始めから 15 点目から開始します。デフォルト:0", - "timelion.help.functions.trendHelpText": "指定された回帰アルゴリズムで傾向線を描きます", - "timelion.help.functions.trim.args.endHelpText": "数列の終わりから切り取るバケットです。デフォルト:1", - "timelion.help.functions.trim.args.startHelpText": "数列の始めから切り取るバケットです。デフォルト:1", - "timelion.help.functions.trimHelpText": "「部分的バケットの問題」に合わせて、数列の始めか終わりの N 個のバケットを無効化するように設定します。", - "timelion.help.functions.worldbank.args.codeHelpText": "Worldbank API パスです。これは通常ドメインの後ろからクエリ文字列までのすべてです。例:{apiPathExample}。", - "timelion.help.functions.worldbankHelpText": "\n [実験]\n 数列へのパスを使用して {worldbankUrl} からデータを取得します。\n Worldbank は主に年間データを提供し、現在の年のデータがないことがよくあります。\n 最近の期間範囲のデータが取得できない場合は、{offsetQuery} をお試しください。", - "timelion.help.functions.worldbankIndicators.args.countryHelpText": "Worldbank の国 ID です。通常は国の 2 文字のコートです", - "timelion.help.functions.worldbankIndicators.args.indicatorHelpText": "使用するインジケーターコードです。{worldbankUrl} で調べる必要があります。多くが分かりづらいものです。例:{indicatorExample} は人口です", - "timelion.help.functions.worldbankIndicatorsHelpText": "\n [実験]\n 国名とインジケーターを使って {worldbankUrl} からデータを取得します。Worldbank は\n 主に年間データを提供し、現在の年のデータがないことがよくあります。最近の期間範囲のデータが取得できない場合は、{offsetQuery} をお試しください。\n 時間範囲", - "timelion.help.functions.yaxis.args.colorHelpText": "軸ラベルの色です", - "timelion.help.functions.yaxis.args.labelHelpText": "軸のラベルです", - "timelion.help.functions.yaxis.args.maxHelpText": "最高値", - "timelion.help.functions.yaxis.args.minHelpText": "最低値", - "timelion.help.functions.yaxis.args.positionHelpText": "左から右", - "timelion.help.functions.yaxis.args.tickDecimalsHelpText": "y 軸とティックラベルの小数点以下の桁数です。", - "timelion.help.functions.yaxis.args.unitsHelpText": "Y 軸のラベルのフォーマットに使用する機能です。次のいずれかです。{formatters}", - "timelion.help.functions.yaxis.args.yaxisHelpText": "この数列をプロットする数字の Y 軸です。例:2 本目の Y 軸は .yaxis(2)になります。", - "timelion.help.functions.yaxisHelpText": "さまざまな Y 軸のオプションを構成します。おそらく最も重要なのは、N 本目(例:2 本目)の Y 軸を追加する機能です。", - "timelion.noFunctionErrorMessage": "そのような関数はありません:{name}", - "timelion.panels.timechart.unknownIntervalErrorMessage": "不明な間隔", - "timelion.requestHandlerErrorTitle": "Timelion リクエストエラー", - "timelion.serverSideErrors.argumentsOverflowErrorMessage": "{functionName} に引き渡された引数が多すぎます", - "timelion.serverSideErrors.bucketsOverflowErrorMessage": "最大バケットを超えました:{bucketCount}/{maxBuckets} が許可されています。より広い間隔または短い期間を選択してください", - "timelion.serverSideErrors.colorFunction.colorNotProvidedErrorMessage": "色が指定されていません", - "timelion.serverSideErrors.conditionFunction.unknownOperatorErrorMessage": "不明な演算子", - "timelion.serverSideErrors.conditionFunction.wrongArgTypeErrorMessage": "数字または seriesList でなければなりません", - "timelion.serverSideErrors.esFunction.indexNotFoundErrorMessage": "Elasticsearch インデックス {index} が見つかりません", - "timelion.serverSideErrors.holtFunction.missingParamsErrorMessage": "シーズンの長さとサンプルサイズ >= 2 を指定する必要があります", - "timelion.serverSideErrors.holtFunction.notEnoughPointsErrorMessage": "二重指数平滑化を使用するには最低 2 つの点が必要です", - "timelion.serverSideErrors.movingaverageFunction.notValidPositionErrorMessage": "有効な配置:{validPositions}", - "timelion.serverSideErrors.movingstdFunction.notValidPositionErrorMessage": "有効な配置:{validPositions}", - "timelion.serverSideErrors.pointsFunction.notValidSymbolErrorMessage": "有効なシンボル:{validSymbols}", - "timelion.serverSideErrors.quandlFunction.unsupportedIntervalErrorMessage": "quandl()でサポートされていない間隔:{interval}. quandl()でサポートされている間隔:{intervals}", - "timelion.serverSideErrors.sheetParseErrorMessage": "予想:文字 {column} で {expectedDescription}", - "timelion.serverSideErrors.unknownArgumentErrorMessage": "{functionName} への不明な引数:{argumentName}", - "timelion.serverSideErrors.unknownArgumentTypeErrorMessage": "引数タイプがサポートされていません:{argument}", - "timelion.serverSideErrors.worldbankFunction.noDataErrorMessage": "Worldbank へのリクエストは成功しましたが、{code} のデータがありませんでした", - "timelion.serverSideErrors.wrongFunctionArgumentTypeErrorMessage": "{functionName}({argumentName})は {requiredTypes} の内の 1 つでなければなりません。{actualType} を入手", - "timelion.serverSideErrors.yaxisFunction.notSupportedUnitTypeErrorMessage": "{units} はサポートされているユニットタイプではありません。", - "timelion.serverSideErrors.yaxisFunction.notValidCurrencyFormatErrorMessage": "通貨は 3 文字のコードでなければなりません", - "timelion.timelionDescription": "グラフに時系列データを表示します。", - "timelion.uiSettings.defaultIndexDescription": "{esParam} で検索するデフォルトの Elasticsearch インデックスです", - "timelion.uiSettings.defaultIndexLabel": "デフォルトのインデックス", - "timelion.uiSettings.experimentalLabel": "実験的", - "timelion.uiSettings.graphiteURLDescription": "{experimentalLabel} Graphite ホストの
    URL", - "timelion.uiSettings.graphiteURLLabel": "Graphite URL", - "timelion.uiSettings.legacyChartsLibraryDeprication": "この設定はサポートが終了し、Kibana 8.0 ではサポートされません。", - "timelion.uiSettings.legacyChartsLibraryDescription": "VisualizeでTimelionグラフのレガシーグラフライブラリを有効にします", - "timelion.uiSettings.legacyChartsLibraryLabel": "Timelionレガシーグラフライブラリ", - "timelion.uiSettings.maximumBucketsDescription": "1つのデータソースが返せるバケットの最大数です", - "timelion.uiSettings.maximumBucketsLabel": "バケットの最大数", - "timelion.uiSettings.minimumIntervalDescription": "「auto」を使用時に計算される最小の間隔です", - "timelion.uiSettings.minimumIntervalLabel": "最低間隔", - "timelion.uiSettings.quandlKeyDescription": "{experimentalLabel} www.quandl.com からの API キーです", - "timelion.uiSettings.quandlKeyLabel": "Quandl キー", - "timelion.uiSettings.targetBucketsDescription": "自動間隔の使用時に目標となるバケット数です。", - "timelion.uiSettings.targetBucketsLabel": "目標バケット数", - "timelion.uiSettings.timeFieldDescription": "{esParam} の使用時にタイムスタンプを含むデフォルトのフィールドです", - "timelion.uiSettings.timeFieldLabel": "時間フィールド", - "timelion.vis.expressionLabel": "Timelion 式", - "timelion.vis.interval.auto": "自動", - "timelion.vis.interval.day": "1日", - "timelion.vis.interval.hour": "1時間", - "timelion.vis.interval.minute": "1分", - "timelion.vis.interval.month": "1か月", - "timelion.vis.interval.second": "1秒", - "timelion.vis.interval.week": "1週間", - "timelion.vis.interval.year": "1年", - "timelion.vis.intervalLabel": "間隔", - "timelion.vis.invalidIntervalErrorMessage": "無効な間隔フォーマット。", - "timelion.vis.selectIntervalHelpText": "オプションを選択するかカスタム値を作成します。例:30s、20m、24h、2d、1w、1M", - "timelion.vis.selectIntervalPlaceholder": "間隔を選択", - "uiActions.actionPanel.more": "詳細", - "uiActions.actionPanel.title": "オプション", - "uiActions.errors.incompatibleAction": "操作に互換性がありません", - "uiActions.triggers.rowClickkDescription": "テーブル行をクリック", - "uiActions.triggers.rowClickTitle": "テーブル行クリック", - "usageCollection.stats.notReadyMessage": "まだ統計が準備できていません。しばらくたってから再試行してください。", - "visDefaultEditor.advancedToggle.advancedLinkLabel": "高度な設定", - "visDefaultEditor.agg.disableAggButtonTooltip": "{schemaTitle} {aggTitle} アグリゲーションを無効にする", - "visDefaultEditor.agg.enableAggButtonTooltip": "{schemaTitle} {aggTitle} アグリゲーションを有効にする", - "visDefaultEditor.agg.errorsAriaLabel": "{schemaTitle} {aggTitle} アグリゲーションにエラーがあります", - "visDefaultEditor.agg.modifyPriorityButtonTooltip": "ドラッグして {schemaTitle} {aggTitle} の優先度を変更する", - "visDefaultEditor.agg.removeDimensionButtonTooltip": "{schemaTitle} {aggTitle} アグリゲーションを削除する", - "visDefaultEditor.agg.toggleEditorButtonAriaLabel": "{schema} エディターを切り替える", - "visDefaultEditor.aggAdd.addButtonLabel": "追加", - "visDefaultEditor.aggAdd.addGroupButtonLabel": "{groupNameLabel}を追加", - "visDefaultEditor.aggAdd.addSubGroupButtonLabel": "サブ {groupNameLabel} を追加", - "visDefaultEditor.aggAdd.bucketLabel": "バケット", - "visDefaultEditor.aggAdd.maxBuckets": "最大{groupNameLabel}数に達しました", - "visDefaultEditor.aggAdd.metricLabel": "メトリック", - "visDefaultEditor.aggParams.errors.aggWrongRunOrderErrorMessage": "「{schema}」集約は他のバケットの前に実行する必要があります!", - "visDefaultEditor.aggSelect.aggregationLabel": "集約", - "visDefaultEditor.aggSelect.helpLinkLabel": "{aggTitle}のヘルプ", - "visDefaultEditor.aggSelect.noCompatibleAggsDescription": "インデックスパターン{indexPatternTitle}には集約可能なフィールドが含まれていません。", - "visDefaultEditor.aggSelect.selectAggPlaceholder": "集約を選択してください", - "visDefaultEditor.aggSelect.subAggregationLabel": "サブ集約", - "visDefaultEditor.buckets.mustHaveBucketErrorMessage": "「日付ヒストグラム」または「ヒストグラム」集約のバケットを追加します。", - "visDefaultEditor.controls.aggNotValidLabel": "- 無効な集約 -", - "visDefaultEditor.controls.aggregateWith.noAggsErrorTooltip": "選択されたフィールドには互換性のある集約がありません。", - "visDefaultEditor.controls.aggregateWithLabel": "集約:", - "visDefaultEditor.controls.aggregateWithTooltip": "複数ヒットまたは複数値のフィールドを 1 つのメトリックにまとめる方法を選択します。", - "visDefaultEditor.controls.changePrecisionLabel": "マップズームの精度を変更", - "visDefaultEditor.controls.columnsLabel": "列", - "visDefaultEditor.controls.customMetricLabel": "カスタムメトリック", - "visDefaultEditor.controls.dateRanges.acceptedDateFormatsLinkText": "許容可能な日付形式", - "visDefaultEditor.controls.dateRanges.addRangeButtonLabel": "範囲を追加", - "visDefaultEditor.controls.dateRanges.errorMessage": "各範囲は1つ以上の有効な日付にしてください。", - "visDefaultEditor.controls.dateRanges.fromColumnLabel": "開始:", - "visDefaultEditor.controls.dateRanges.removeRangeButtonAriaLabel": "{from}から{to}の範囲を削除", - "visDefaultEditor.controls.dateRanges.toColumnLabel": "終了:", - "visDefaultEditor.controls.definiteMetricLabel": "メトリック:{metric}", - "visDefaultEditor.controls.dotSizeRatioHelpText": "最小の点から最大の点までの半径の比率を変更します。", - "visDefaultEditor.controls.dotSizeRatioLabel": "点サイズ率", - "visDefaultEditor.controls.dropPartialBucketsLabel": "不完全なバケットをドロップ", - "visDefaultEditor.controls.dropPartialBucketsTooltip": "時間範囲外にわたるバケットを削除してヒストグラムが不完全なバケットで開始・終了しないようにします。", - "visDefaultEditor.controls.extendedBounds.errorMessage": "最低値は最大値以下でなければなりません。", - "visDefaultEditor.controls.extendedBounds.maxLabel": "最高", - "visDefaultEditor.controls.extendedBounds.minLabel": "最低", - "visDefaultEditor.controls.extendedBoundsLabel": "拡張された境界", - "visDefaultEditor.controls.extendedBoundsTooltip": "最低値と最高値は結果を絞るのではなく、結果セットのバウンドを拡張します。", - "visDefaultEditor.controls.field.fieldIsNotExists": "このオブジェクトに関連付けられたフィールド\"{fieldParameter}\"は、インデックスパターンに存在しません。別のフィールドを使用してください。", - "visDefaultEditor.controls.field.fieldLabel": "フィールド", - "visDefaultEditor.controls.field.invalidFieldForAggregation": "このアグリゲーションで使用するには、インデックスパターン\"{indexPatternTitle}\"の保存されたフィールド\"{fieldParameter}\"が無効です。新しいフィールドを選択してください。", - "visDefaultEditor.controls.field.noCompatibleFieldsDescription": "インデックスパターン` {indexPatternTitle} に次の互換性のあるフィールドタイプが 1 つも含まれていません:{fieldTypes}", - "visDefaultEditor.controls.field.selectFieldPlaceholder": "フィールドの選択", - "visDefaultEditor.controls.filters.addFilterButtonLabel": "フィルターを追加します", - "visDefaultEditor.controls.filters.definiteFilterLabel": "{index} ラベルでフィルタリング", - "visDefaultEditor.controls.filters.filterLabel": "{index} でフィルタリング", - "visDefaultEditor.controls.filters.labelPlaceholder": "ラベル", - "visDefaultEditor.controls.filters.removeFilterButtonAriaLabel": "このフィルターを削除", - "visDefaultEditor.controls.filters.toggleFilterButtonAriaLabel": "フィルターラベルを切り替える", - "visDefaultEditor.controls.includeExclude.addUnitButtonLabel": "値を追加", - "visDefaultEditor.controls.ipRanges.addRangeButtonLabel": "範囲を追加", - "visDefaultEditor.controls.ipRanges.cidrMaskAriaLabel": "CIDR マスク:{mask}", - "visDefaultEditor.controls.ipRanges.cidrMasksButtonLabel": "CIDR マスク", - "visDefaultEditor.controls.ipRanges.fromToButtonLabel": "開始/終了", - "visDefaultEditor.controls.ipRanges.ipRangeFromAriaLabel": "IP 範囲の開始値:{value}", - "visDefaultEditor.controls.ipRanges.ipRangeToAriaLabel": "IP 範囲の終了値:{value}", - "visDefaultEditor.controls.ipRanges.removeCidrMaskButtonAriaLabel": "{mask} の CIDR マスクの値を削除", - "visDefaultEditor.controls.ipRanges.removeEmptyCidrMaskButtonAriaLabel": "CIDR マスクのデフォルトの値を削除", - "visDefaultEditor.controls.ipRanges.removeRangeAriaLabel": "{from}から{to}の範囲を削除", - "visDefaultEditor.controls.ipRangesAriaLabel": "IP 範囲", - "visDefaultEditor.controls.jsonInputLabel": "JSON インプット", - "visDefaultEditor.controls.jsonInputTooltip": "ここに追加された JSON 形式のプロパティは、すべてこのセクションの Elasticsearch 集約定義に融合されます。用語集約における「shard_size」がその例です。", - "visDefaultEditor.controls.maxBars.autoPlaceholder": "自動", - "visDefaultEditor.controls.maxBars.maxBarsHelpText": "間隔は、使用可能なデータに基づいて、自動的に選択されます。棒の最大数は、詳細設定の{histogramMaxBars}以下でなければなりません。", - "visDefaultEditor.controls.maxBars.maxBarsLabel": "棒の最大数", - "visDefaultEditor.controls.metricLabel": "メトリック", - "visDefaultEditor.controls.metrics.bucketTitle": "バケット", - "visDefaultEditor.controls.metrics.metricTitle": "メトリック", - "visDefaultEditor.controls.numberInterval.autoInteralIsUsed": "自動間隔が使用されます", - "visDefaultEditor.controls.numberInterval.minimumIntervalLabel": "最低間隔", - "visDefaultEditor.controls.numberInterval.minimumIntervalTooltip": "入力された値により高度な設定の {histogramMaxBars} で指定されたよりも多くのバケットが作成される場合、間隔は自動的にスケーリングされます。", - "visDefaultEditor.controls.numberInterval.selectIntervalPlaceholder": "間隔を入力", - "visDefaultEditor.controls.numberList.addUnitButtonLabel": "{unitName} を追加", - "visDefaultEditor.controls.numberList.duplicateValueErrorMessage": "重複値。", - "visDefaultEditor.controls.numberList.enterValuePlaceholder": "値を入力", - "visDefaultEditor.controls.numberList.invalidAscOrderErrorMessage": "値は昇順になっていません。", - "visDefaultEditor.controls.numberList.invalidRangeErrorMessage": "値は {min} から {max} の範囲でなければなりません。", - "visDefaultEditor.controls.numberList.removeUnitButtonAriaLabel": "{value} のランク値を削除", - "visDefaultEditor.controls.onlyRequestDataAroundMapExtentLabel": "マップ範囲のデータのみリクエストしてください", - "visDefaultEditor.controls.onlyRequestDataAroundMapExtentTooltip": "geo_bounding_box フィルター集約を適用して、襟付きのマップビューボックスにサブジェクトエリアを絞ります", - "visDefaultEditor.controls.orderAgg.alphabeticalLabel": "アルファベット順", - "visDefaultEditor.controls.orderAgg.orderByLabel": "並び順", - "visDefaultEditor.controls.orderLabel": "順序", - "visDefaultEditor.controls.otherBucket.groupValuesLabel": "他の値を別のバケットにまとめる", - "visDefaultEditor.controls.otherBucket.groupValuesTooltip": "トップ N 以外の値はこのバケットにまとめられます。欠測値があるドキュメントを含めるには、「欠測値を表示」を有効にしてください。", - "visDefaultEditor.controls.otherBucket.showMissingValuesLabel": "欠測値を表示", - "visDefaultEditor.controls.otherBucket.showMissingValuesTooltip": "「文字列」タイプのフィールドにのみ使用できます。有効にすると、欠測値があるドキュメントが検索に含まれます。バケットがトップ N の場合、チャートに表示されます。トップ N ではなく、「他の値を別のバケットにまとえる」が有効な場合、Elasticsearch は欠測値を「他」のバケットに追加します。", - "visDefaultEditor.controls.percentileRanks.percentUnitNameText": "パーセント", - "visDefaultEditor.controls.percentileRanks.valuesLabel": "値", - "visDefaultEditor.controls.percentileRanks.valueUnitNameText": "値", - "visDefaultEditor.controls.percentiles.percentsLabel": "パーセント", - "visDefaultEditor.controls.placeMarkersOffGridLabel": "グリッド外にマーカーを配置(ジオセントロイドを使用)", - "visDefaultEditor.controls.precisionLabel": "精度", - "visDefaultEditor.controls.ranges.addRangeButtonLabel": "範囲を追加", - "visDefaultEditor.controls.ranges.fromLabel": "開始:", - "visDefaultEditor.controls.ranges.greaterThanOrEqualPrepend": "≥", - "visDefaultEditor.controls.ranges.greaterThanOrEqualTooltip": "よりも大きいまたは等しい", - "visDefaultEditor.controls.ranges.lessThanPrepend": "<", - "visDefaultEditor.controls.ranges.lessThanTooltip": "より小さい", - "visDefaultEditor.controls.ranges.removeRangeButtonAriaLabel": "{from}から{to}の範囲を削除", - "visDefaultEditor.controls.ranges.toLabel": "終了:", - "visDefaultEditor.controls.rowsLabel": "行", - "visDefaultEditor.controls.scaleMetricsLabel": "メトリック値のスケーリング(非推奨)", - "visDefaultEditor.controls.scaleMetricsTooltip": "これを有効にすると、手動最低間隔を選択し、広い間隔が使用された場合、カウントと合計メトリックが手動で選択された間隔にスケーリングされます。", - "visDefaultEditor.controls.showEmptyBucketsLabel": "空のバケットを表示", - "visDefaultEditor.controls.showEmptyBucketsTooltip": "結果のあるバケットだけでなくすべてのバケットを表示します", - "visDefaultEditor.controls.sizeLabel": "サイズ", - "visDefaultEditor.controls.sizeTooltip": "トップ K のヒットをリクエスト。複数ヒットは「集約基準」でまとめられます。", - "visDefaultEditor.controls.sortOnLabel": "並べ替えオン", - "visDefaultEditor.controls.splitByLegend": "行または列でチャートを分割します。", - "visDefaultEditor.controls.timeInterval.createsTooLargeBucketsTooltip": "この間隔は、選択された時間範囲に表示するには大きすぎるバケットが作成されるため、にスケーリングされています。", - "visDefaultEditor.controls.timeInterval.createsTooManyBucketsTooltip": "この間隔は選択された時間範囲に表示しきれない数のバケットが作成されるため、にスケーリングされています。", - "visDefaultEditor.controls.timeInterval.invalidFormatErrorMessage": "無効な間隔フォーマット。", - "visDefaultEditor.controls.timeInterval.minimumIntervalLabel": "最低間隔", - "visDefaultEditor.controls.timeInterval.scaledHelpText": "現在 {bucketDescription} にスケーリングされています", - "visDefaultEditor.controls.timeInterval.selectIntervalPlaceholder": "間隔を選択", - "visDefaultEditor.controls.timeInterval.selectOptionHelpText": "オプションを選択するかカスタム値を作成します。例:30s、20m、24h、2d、1w、1M", - "visDefaultEditor.controls.useAutoInterval": "自動間隔を使用", - "visDefaultEditor.editorConfig.dateHistogram.customInterval.helpText": "構成間隔の倍数でなければなりません:{interval}", - "visDefaultEditor.editorConfig.histogram.interval.helpText": "構成間隔の倍数でなければなりません:{interval}", - "visDefaultEditor.metrics.wrongLastBucketTypeErrorMessage": "「{type}」メトリック集約を使用する場合、最後のバケット集約は「Date Histogram」または「Histogram」でなければなりません。", - "visDefaultEditor.options.colorRanges.errorText": "各範囲は前の範囲よりも大きくなければなりません。", - "visDefaultEditor.options.colorSchema.colorSchemaLabel": "配色", - "visDefaultEditor.options.colorSchema.howToChangeColorsDescription": "それぞれの色は凡例で変更できます。", - "visDefaultEditor.options.colorSchema.resetColorsButtonLabel": "色をリセット", - "visDefaultEditor.options.colorSchema.reverseColorSchemaLabel": "図表を反転", - "visDefaultEditor.options.percentageMode.documentationLabel": "Numeral.jsドキュメント", - "visDefaultEditor.options.percentageMode.numeralLabel": "形式パターン", - "visDefaultEditor.options.percentageMode.percentageModeLabel": "百分率モード", - "visDefaultEditor.options.rangeErrorMessage": "値は{min}と{max}の間でなければなりません", - "visDefaultEditor.options.vislibBasicOptions.legendPositionLabel": "凡例位置", - "visDefaultEditor.options.vislibBasicOptions.showTooltipLabel": "ツールヒントを表示", - "visDefaultEditor.palettePicker.label": "カラーパレット", - "visDefaultEditor.sidebar.autoApplyChangesLabelOff": "自動適用がオフです", - "visDefaultEditor.sidebar.autoApplyChangesLabelOn": "自動適用がオンです", - "visDefaultEditor.sidebar.autoApplyChangesOff": "オフ", - "visDefaultEditor.sidebar.autoApplyChangesOffLabel": "自動適用がオフです", - "visDefaultEditor.sidebar.autoApplyChangesOn": "オン", - "visDefaultEditor.sidebar.autoApplyChangesOnLabel": "自動適用がオンです", - "visDefaultEditor.sidebar.autoApplyChangesTooltip": "変更されるごとにビジュアライゼーションを自動的に更新します。", - "visDefaultEditor.sidebar.collapseButtonAriaLabel": "サイドバーを切り替える", - "visDefaultEditor.sidebar.discardChangesButtonLabel": "破棄", - "visDefaultEditor.sidebar.errorButtonTooltip": "ハイライトされたフィールドのエラーを解決する必要があります。", - "visDefaultEditor.sidebar.indexPatternAriaLabel": "インデックスパターン:{title}", - "visDefaultEditor.sidebar.savedSearch.goToDiscoverButtonText": "Discover にこの検索を表示", - "visDefaultEditor.sidebar.savedSearch.linkButtonAriaLabel": "保存された検索へのリンク。クリックして詳細を確認するかリンクを解除します。", - "visDefaultEditor.sidebar.savedSearch.popoverHelpText": "保存したこの検索に今後加える修正は、ビジュアライゼーションに反映されます。自動更新を無効にするには、リンクを削除します。", - "visDefaultEditor.sidebar.savedSearch.popoverTitle": "保存された検索にリンクされています", - "visDefaultEditor.sidebar.savedSearch.titleAriaLabel": "保存された検索:{title}", - "visDefaultEditor.sidebar.savedSearch.unlinkSavedSearchButtonText": "保存された検索へのリンクを削除", - "visDefaultEditor.sidebar.tabs.dataLabel": "データ", - "visDefaultEditor.sidebar.tabs.optionsLabel": "オプション", - "visDefaultEditor.sidebar.updateChartButtonLabel": "更新", - "visDefaultEditor.sidebar.updateInfoTooltip": "CTRL + Enterは更新のショートカットです。", - "visTypeMarkdown.function.font.help": "フォント設定です。", - "visTypeMarkdown.function.help": "マークダウンビジュアライゼーション", - "visTypeMarkdown.function.markdown.help": "レンダリングするマークダウン", - "visTypeMarkdown.function.openLinksInNewTab.help": "新規タブでリンクを開きます", - "visTypeMarkdown.markdownDescription": "テキストと画像をダッシュボードに追加します。", - "visTypeMarkdown.markdownTitleInWizard": "テキスト", - "visTypeMarkdown.params.fontSizeLabel": "ポイント単位のベースフォントサイズです。", - "visTypeMarkdown.params.helpLinkLabel": "ヘルプ", - "visTypeMarkdown.params.openLinksLabel": "新規タブでリンクを開く", - "visTypeMarkdown.tabs.dataText": "データ", - "visTypeMarkdown.tabs.optionsText": "オプション", - "visTypeMetric.colorModes.backgroundOptionLabel": "背景", - "visTypeMetric.colorModes.labelsOptionLabel": "ラベル", - "visTypeMetric.colorModes.noneOptionLabel": "なし", - "visTypeMetric.metricDescription": "計算結果を単独の数字として表示します。", - "visTypeMetric.metricTitle": "メトリック", - "visTypeMetric.params.color.useForLabel": "使用する色", - "visTypeMetric.params.rangesTitle": "範囲", - "visTypeMetric.params.settingsTitle": "設定", - "visTypeMetric.params.showTitleLabel": "タイトルを表示", - "visTypeMetric.params.style.fontSizeLabel": "ポイント単位のメトリックフォントサイズ", - "visTypeMetric.params.style.styleTitle": "スタイル", - "visTypeMetric.schemas.metricTitle": "メトリック", - "visTypeMetric.schemas.splitGroupTitle": "グループを分割", - "expressionMetricVis.function.dimension.splitGroup": "グループを分割", - "expressionMetricVis.function.bucket.help": "バケットディメンションの構成です。", - "expressionMetricVis.function.colorMode.help": "色を変更するメトリックの部分", - "expressionMetricVis.function.dimension.metric": "メトリック", - "expressionMetricVis.function.font.help": "フォント設定です。", - "expressionMetricVis.function.help": "メトリックビジュアライゼーション", - "expressionMetricVis.function.metric.help": "メトリックディメンションの構成です。", - "expressionMetricVis.function.percentageMode.help": "百分率モードでメトリックを表示します。colorRange を設定する必要があります。", - "expressionMetricVis.function.showLabels.help": "メトリック値の下にラベルを表示します。", - "visTypePie.advancedSettings.visualization.legacyPieChartsLibrary.deprecation": "Visualizeの円グラフのレガシーグラフライブラリは廃止予定であり、8.0以降ではサポートされません。", - "visTypePie.advancedSettings.visualization.legacyPieChartsLibrary.description": "Visualizeで円グラフのレガシーグラフライブラリを有効にします。", - "visTypePie.advancedSettings.visualization.legacyPieChartsLibrary.name": "円グラフのレガシーグラフライブラリ", - "visTypePie.controls.truncateLabel": "切り捨て", - "visTypePie.editors.pie.addLegendLabel": "凡例を表示", - "visTypePie.editors.pie.decimalSliderLabel": "割合の最大小数点桁数", - "visTypePie.editors.pie.distinctColorsLabel": "スライスごとに異なる色を使用", - "visTypePie.editors.pie.donutLabel": "ドーナッツ", - "visTypePie.editors.pie.labelPositionLabel": "ラベル位置", - "visTypePie.editors.pie.labelsSettingsTitle": "ラベル設定", - "visTypePie.editors.pie.nestedLegendLabel": "ネスト凡例", - "visTypePie.editors.pie.pieSettingsTitle": "パイ設定", - "visTypePie.editors.pie.showLabelsLabel": "ラベルを表示", - "visTypePie.editors.pie.showTopLevelOnlyLabel": "トップレベルのみ表示", - "visTypePie.editors.pie.showValuesLabel": "値を表示", - "visTypePie.editors.pie.valueFormatsLabel": "値", - "visTypePie.function.adimension.buckets": "スライス", - "visTypePie.function.args.addLegendHelpText": "グラフ凡例を表示", - "visTypePie.function.args.addTooltipHelpText": "スライスにカーソルを置いたときにツールチップを表示", - "visTypePie.function.args.bucketsHelpText": "バケットディメンション構成", - "visTypePie.function.args.distinctColorsHelpText": "スライスごとに異なる色をマッピングします。同じ値のスライスは同じ色になります", - "visTypePie.function.args.isDonutHelpText": "円グラフをドーナツグラフとして表示します", - "visTypePie.function.args.labelsHelpText": "円グラフラベル構成", - "visTypePie.function.args.legendPositionHelpText": "グラフの上、下、左、右に凡例を配置", - "visTypePie.function.args.metricHelpText": "メトリックディメンション構成", - "visTypePie.function.args.nestedLegendHelpText": "詳細凡例を表示", - "visTypePie.function.args.paletteHelpText": "グラフパレット名を定義します", - "visTypePie.function.args.splitColumnHelpText": "列ディメンション構成で分割", - "visTypePie.function.args.splitRowHelpText": "行ディメンション構成で分割", - "visTypePie.function.dimension.metric": "スライスサイズ", - "visTypePie.function.dimension.splitcolumn": "列分割", - "visTypePie.function.dimension.splitrow": "行分割", - "visTypePie.function.pieLabels.help": "円グラフラベルオブジェクトを生成します", - "visTypePie.function.pieLabels.lastLevel.help": "最上位のラベルのみを表示", - "visTypePie.function.pieLabels.percentDecimals.help": "割合として値に表示される10進数を定義します", - "visTypePie.function.pieLabels.position.help": "ラベル位置を定義します", - "visTypePie.function.pieLabels.show.help": "円グラフのラベルを表示します", - "visTypePie.function.pieLabels.truncate.help": "スライス値が表示される文字数を定義します", - "visTypePie.function.pieLabels.values.help": "スライス内の値を定義します", - "visTypePie.function.pieLabels.valuesFormat.help": "値の形式を定義します", - "visTypePie.functions.help": "パイビジュアライゼーション", - "visTypePie.labelPositions.insideOrOutsideText": "内部または外部", - "visTypePie.labelPositions.insideText": "内部", - "visTypePie.legend.filterForValueButtonAriaLabel": "値でフィルター", - "visTypePie.legend.filterOptionsLegend": "{legendDataLabel}、フィルターオプション", - "visTypePie.legend.filterOutValueButtonAriaLabel": "値を除外", - "visTypePie.legendPositions.bottomText": "一番下", - "visTypePie.legendPositions.leftText": "左", - "visTypePie.legendPositions.rightText": "右", - "visTypePie.legendPositions.topText": "トップ", - "visTypePie.pie.metricTitle": "スライスサイズ", - "visTypePie.pie.pieDescription": "全体に対する比率でデータを比較します。", - "visTypePie.pie.pieTitle": "円", - "visTypePie.pie.segmentTitle": "スライスの分割", - "visTypePie.pie.splitTitle": "チャートを分割", - "visTypePie.valuesFormats.percent": "割合を表示", - "visTypePie.valuesFormats.value": "値を表示", - "visTypeTable.defaultAriaLabel": "データ表ビジュアライゼーション", - "visTypeTable.function.adimension.buckets": "バケット", - "visTypeTable.function.args.bucketsHelpText": "バケットディメンション構成", - "visTypeTable.function.args.metricsHelpText": "メトリックディメンション構成", - "visTypeTable.function.args.percentageColHelpText": "割合を表示する列の名前", - "visTypeTable.function.args.perPageHelpText": "表ページの行数はページネーションで使用されます", - "visTypeTable.function.args.rowHelpText": "行値は分割表モードで使用されます。「true」に設定すると、行で分割します", - "visTypeTable.function.args.showToolbarHelpText": "「true」に設定すると、グリッドツールバーと[エクスポート]ボタンを表示します", - "visTypeTable.function.args.showTotalHelpText": "「true」に設定すると、合計行を表示します", - "visTypeTable.function.args.splitColumnHelpText": "列ディメンション構成で分割", - "visTypeTable.function.args.splitRowHelpText": "行ディメンション構成で分割", - "visTypeTable.function.args.titleHelpText": "ビジュアライゼーションタイトル。タイトルはデフォルトファイル名としてCSVエクスポートで使用されます", - "visTypeTable.function.args.totalFuncHelpText": "合計行の集計関数を指定します。使用可能なオプション:", - "visTypeTable.function.dimension.metrics": "メトリック", - "visTypeTable.function.dimension.splitColumn": "列で分割", - "visTypeTable.function.dimension.splitRow": "行で分割", - "visTypeTable.function.help": "表ビジュアライゼーション", - "visTypeTable.params.defaultPercentageCol": "非表示", - "visTypeTable.params.PercentageColLabel": "パーセンテージ列", - "visTypeTable.params.percentageTableColumnName": "{title} パーセント", - "visTypeTable.params.perPageLabel": "ページごとの最大行数", - "visTypeTable.params.showMetricsLabel": "すべてのバケット/レベルのメトリックを表示", - "visTypeTable.params.showPartialRowsLabel": "部分的な行を表示", - "visTypeTable.params.showPartialRowsTip": "部分データのある行を表示。表示されていなくてもすべてのバケット/レベルのメトリックが計算されます。", - "visTypeTable.params.showToolbarLabel": "ツールバーを表示", - "visTypeTable.params.showTotalLabel": "合計を表示", - "visTypeTable.params.totalFunctionLabel": "合計機能", - "visTypeTable.sort.ascLabel": "昇順で並べ替え", - "visTypeTable.sort.descLabel": "降順で並べ替え", - "visTypeTable.tableCellFilter.filterForValueAriaLabel": "値のフィルター:{cellContent}", - "visTypeTable.tableCellFilter.filterForValueText": "値でフィルター", - "visTypeTable.tableCellFilter.filterOutValueAriaLabel": "値の除外:{cellContent}", - "visTypeTable.tableCellFilter.filterOutValueText": "値を除外", - "visTypeTable.tableVisDescription": "行と列にデータを表示します。", - "visTypeTable.tableVisEditorConfig.schemas.bucketTitle": "行を分割", - "visTypeTable.tableVisEditorConfig.schemas.metricTitle": "メトリック", - "visTypeTable.tableVisEditorConfig.schemas.splitTitle": "テーブルを分割", - "visTypeTable.tableVisTitle": "データテーブル", - "visTypeTable.totalAggregations.averageText": "平均", - "visTypeTable.totalAggregations.countText": "カウント", - "visTypeTable.totalAggregations.maxText": "最高", - "visTypeTable.totalAggregations.minText": "最低", - "visTypeTable.totalAggregations.sumText": "合計", - "visTypeTable.vis.controls.exportButtonAriaLabel": "{dataGridAriaLabel} を CSV としてエクスポート", - "visTypeTable.vis.controls.exportButtonFormulasWarning": "CSVには、スプレッドシートアプリケーションで式と解釈される可能性のある文字が含まれています。", - "visTypeTable.vis.controls.exportButtonLabel": "エクスポート", - "visTypeTable.vis.controls.formattedCSVButtonLabel": "フォーマット済み", - "visTypeTable.vis.controls.rawCSVButtonLabel": "未加工", - "visTypeTagCloud.orientations.multipleText": "複数", - "visTypeTagCloud.orientations.rightAngledText": "直角", - "visTypeTagCloud.orientations.singleText": "単一", - "visTypeTagCloud.scales.linearText": "線形", - "visTypeTagCloud.scales.logText": "ログ", - "visTypeTagCloud.scales.squareRootText": "平方根", - "visTypeTagCloud.vis.schemas.metricTitle": "タグサイズ", - "visTypeTagCloud.vis.schemas.segmentTitle": "タグ", - "visTypeTagCloud.vis.tagCloudDescription": "単語の頻度とフォントサイズを表示します。", - "visTypeTagCloud.vis.tagCloudTitle": "タグクラウド", - "visTypeTagCloud.visParams.fontSizeLabel": "フォントサイズ範囲(ピクセル)", - "visTypeTagCloud.visParams.orientationsLabel": "方向", - "visTypeTagCloud.visParams.showLabelToggleLabel": "ラベルを表示", - "visTypeTagCloud.visParams.textScaleLabel": "テキストスケール", - "visTypeTimeseries.addDeleteButtons.addButtonDefaultTooltip": "追加", - "visTypeTimeseries.addDeleteButtons.cloneButtonDefaultTooltip": "クローンを作成", - "visTypeTimeseries.addDeleteButtons.deleteButtonDefaultTooltip": "削除", - "visTypeTimeseries.addDeleteButtons.reEnableTooltip": "再度有効にする", - "visTypeTimeseries.addDeleteButtons.temporarilyDisableTooltip": "一時的に無効にする", - "visTypeTimeseries.advancedSettings.maxBucketsText": "TSVBヒストグラム密度に影響します。「histogram:maxBars」よりも大きく設定する必要があります。", - "visTypeTimeseries.advancedSettings.maxBucketsTitle": "TSVBバケット制限", - "visTypeTimeseries.aggRow.addMetricButtonTooltip": "メトリックを追加", - "visTypeTimeseries.aggRow.deleteMetricButtonTooltip": "メトリックを削除", - "visTypeTimeseries.aggSelect.aggGroups.metricAggLabel": "メトリック集約", - "visTypeTimeseries.aggSelect.aggGroups.parentPipelineAggLabel": "親パイプライン集約", - "visTypeTimeseries.aggSelect.aggGroups.siblingPipelineAggLabel": "シブリングパイプライン集約", - "visTypeTimeseries.aggSelect.aggGroups.specialAggLabel": "特殊集約", - "visTypeTimeseries.aggSelect.selectAggPlaceholder": "集約を選択", - "visTypeTimeseries.annotationsEditor.addDataSourceButtonLabel": "データソースを追加", - "visTypeTimeseries.annotationsEditor.dataSourcesLabel": "データソース", - "visTypeTimeseries.annotationsEditor.fieldsLabel": "フィールド(必須 - コンマ区切りのパス)", - "visTypeTimeseries.annotationsEditor.howToCreateAnnotationDataSourceDescription": "下のボタンをクリックして注釈データソースを作成します。", - "visTypeTimeseries.annotationsEditor.iconLabel": "アイコン(必須)", - "visTypeTimeseries.annotationsEditor.ignoreGlobalFiltersLabel": "グローバルフィルターを無視しますか?", - "visTypeTimeseries.annotationsEditor.ignorePanelFiltersLabel": "パネルフィルターを無視しますか?", - "visTypeTimeseries.annotationsEditor.queryStringLabel": "クエリ文字列", - "visTypeTimeseries.annotationsEditor.rowTemplateHelpText": "eg.{rowTemplateExample}", - "visTypeTimeseries.annotationsEditor.rowTemplateLabel": "行テンプレート (必須)", - "visTypeTimeseries.annotationsEditor.timeFieldLabel": "時間フィールド (必須)", - "visTypeTimeseries.axisLabelOptions.axisLabel": "{unitValue} {unitString}単位", - "visTypeTimeseries.calculateLabel.bucketScriptsLabel": "バケットスクリプト", - "visTypeTimeseries.calculateLabel.countLabel": "カウント", - "visTypeTimeseries.calculateLabel.filterRatioLabel": "フィルターレート", - "visTypeTimeseries.calculateLabel.mathLabel": "数学処理", - "visTypeTimeseries.calculateLabel.positiveRateLabel": "{field} のカウンターレート", - "visTypeTimeseries.calculateLabel.seriesAggLabel": "数列アグリゲーション({metricFunction})", - "visTypeTimeseries.calculateLabel.staticValueLabel": "{metricValue} の静的値", - "visTypeTimeseries.calculateLabel.unknownLabel": "不明", - "visTypeTimeseries.calculation.aggregationLabel": "アグリゲーション", - "visTypeTimeseries.calculation.painlessScriptDescription": "変数は {params}オブジェクトのキーです(例:{paramsName})。バケット間隔(ミリ秒単位)にアクセスするには {paramsInterval} を使用します。", - "visTypeTimeseries.calculation.painlessScriptLabel": "Painless スクリプト", - "visTypeTimeseries.calculation.variablesLabel": "変数", - "visTypeTimeseries.colorPicker.clearIconLabel": "クリア", - "visTypeTimeseries.colorPicker.notAccessibleAriaLabel": "カラーピッカー、アクセス不可", - "visTypeTimeseries.colorPicker.notAccessibleWithValueAriaLabel": "カラーピッカー({value})、アクセス不可", - "visTypeTimeseries.colorRules.adjustChartSizeAriaLabel": "上下の矢印を押してチャートサイズを調整します", - "visTypeTimeseries.colorRules.defaultPrimaryNameLabel": "背景", - "visTypeTimeseries.colorRules.defaultSecondaryNameLabel": "テキスト", - "visTypeTimeseries.colorRules.emptyLabel": "空", - "visTypeTimeseries.colorRules.greaterThanLabel": "> より大きい", - "visTypeTimeseries.colorRules.greaterThanOrEqualLabel": ">= greater than or equal", - "visTypeTimeseries.colorRules.ifMetricIsLabel": "メトリックが", - "visTypeTimeseries.colorRules.lessThanLabel": "< less than", - "visTypeTimeseries.colorRules.lessThanOrEqualLabel": "<= less than or equal", - "visTypeTimeseries.colorRules.setPrimaryColorLabel": "{primaryName} を設定", - "visTypeTimeseries.colorRules.setSecondaryColorLabel": "{secondaryName} を設定", - "visTypeTimeseries.colorRules.valueAriaLabel": "値", - "visTypeTimeseries.cumulativeSum.aggregationLabel": "アグリゲーション", - "visTypeTimeseries.cumulativeSum.metricLabel": "メトリック", - "visTypeTimeseries.dataFormatPicker.bytesLabel": "バイト", - "visTypeTimeseries.dataFormatPicker.customLabel": "カスタム", - "visTypeTimeseries.dataFormatPicker.decimalPlacesLabel": "小数部分の桁数", - "visTypeTimeseries.dataFormatPicker.durationLabel": "期間", - "visTypeTimeseries.dataFormatPicker.formatPatternHelpText": "ドキュメント", - "visTypeTimeseries.dataFormatPicker.formatPatternLabel": "Numeral.js のフォーマットパターン (デフォルト: {defaultPattern})", - "visTypeTimeseries.dataFormatPicker.fromLabel": "開始:", - "visTypeTimeseries.dataFormatPicker.numberLabel": "数字", - "visTypeTimeseries.dataFormatPicker.percentLabel": "パーセント", - "visTypeTimeseries.dataFormatPicker.toLabel": "終了:", - "visTypeTimeseries.defaultDataFormatterLabel": "データフォーマッター", - "visTypeTimeseries.derivative.aggregationLabel": "アグリゲーション", - "visTypeTimeseries.derivative.metricLabel": "メトリック", - "visTypeTimeseries.derivative.unitsLabel": "単位(1s、1m など)", - "visTypeTimeseries.durationOptions.daysLabel": "日", - "visTypeTimeseries.durationOptions.hoursLabel": "時間", - "visTypeTimeseries.durationOptions.humanize": "人間に読解可能", - "visTypeTimeseries.durationOptions.microsecondsLabel": "マイクロ秒", - "visTypeTimeseries.durationOptions.millisecondsLabel": "ミリ秒", - "visTypeTimeseries.durationOptions.minutesLabel": "分", - "visTypeTimeseries.durationOptions.monthsLabel": "か月", - "visTypeTimeseries.durationOptions.nanosecondsLabel": "ナノ秒", - "visTypeTimeseries.durationOptions.picosecondsLabel": "ピコ秒", - "visTypeTimeseries.durationOptions.secondsLabel": "秒", - "visTypeTimeseries.durationOptions.weeksLabel": "週間", - "visTypeTimeseries.durationOptions.yearsLabel": "年", - "visTypeTimeseries.emptyTextValue": "(空)", - "visTypeTimeseries.error.requestForPanelFailedErrorMessage": "このパネルのリクエストに失敗しました", - "visTypeTimeseries.fetchFields.loadIndexPatternFieldsErrorMessage": "index_pattern フィールドを読み込めません", - "visTypeTimeseries.fieldSelect.fieldIsNotValid": "\"{fieldParameter}\"フィールドは無効であり、現在のインデックスで使用できません。新しいフィールドを選択してください。", - "visTypeTimeseries.fieldSelect.selectFieldPlaceholder": "フィールドを選択してください...", - "visTypeTimeseries.filterRatio.aggregationLabel": "アグリゲーション", - "visTypeTimeseries.filterRatio.denominatorLabel": "分母", - "visTypeTimeseries.filterRatio.fieldLabel": "フィールド", - "visTypeTimeseries.filterRatio.metricAggregationLabel": "メトリック集約", - "visTypeTimeseries.filterRatio.numeratorLabel": "分子", - "visTypeTimeseries.function.help": "TSVB ビジュアライゼーション", - "visTypeTimeseries.gauge.dataTab.dataButtonLabel": "データ", - "visTypeTimeseries.gauge.dataTab.metricsButtonLabel": "メトリック", - "visTypeTimeseries.gauge.editor.addSeriesTooltip": "数列を追加", - "visTypeTimeseries.gauge.editor.cloneSeriesTooltip": "数列のクローンを作成", - "visTypeTimeseries.gauge.editor.deleteSeriesTooltip": "数列を削除", - "visTypeTimeseries.gauge.editor.labelPlaceholder": "ラベル", - "visTypeTimeseries.gauge.editor.toggleEditorAriaLabel": "数列エディターを切り替える", - "visTypeTimeseries.gauge.optionsTab.backgroundColorLabel": "背景色:", - "visTypeTimeseries.gauge.optionsTab.colorRulesLabel": "カラールール", - "visTypeTimeseries.gauge.optionsTab.dataLabel": "データ", - "visTypeTimeseries.gauge.optionsTab.gaugeLineWidthLabel": "ゲージ線の幅", - "visTypeTimeseries.gauge.optionsTab.gaugeMaxLabel": "ゲージ最大値(自動は未入力)", - "visTypeTimeseries.gauge.optionsTab.gaugeStyleLabel": "ゲージスタイル", - "visTypeTimeseries.gauge.optionsTab.ignoreGlobalFilterLabel": "グローバルフィルターを無視しますか?", - "visTypeTimeseries.gauge.optionsTab.innerColorLabel": "内側の色:", - "visTypeTimeseries.gauge.optionsTab.innerLineWidthLabel": "内側の線の幅", - "visTypeTimeseries.gauge.optionsTab.optionsButtonLabel": "オプション", - "visTypeTimeseries.gauge.optionsTab.panelFilterLabel": "パネルフィルター", - "visTypeTimeseries.gauge.optionsTab.panelOptionsButtonLabel": "パネルオプション", - "visTypeTimeseries.gauge.optionsTab.styleLabel": "スタイル", - "visTypeTimeseries.gauge.styleOptions.circleLabel": "円", - "visTypeTimeseries.gauge.styleOptions.halfCircleLabel": "半円", - "visTypeTimeseries.getInterval.daysLabel": "日", - "visTypeTimeseries.getInterval.hoursLabel": "時間", - "visTypeTimeseries.getInterval.minutesLabel": "分", - "visTypeTimeseries.getInterval.monthsLabel": "か月", - "visTypeTimeseries.getInterval.secondsLabel": "秒", - "visTypeTimeseries.getInterval.weeksLabel": "週間", - "visTypeTimeseries.getInterval.yearsLabel": "年", - "visTypeTimeseries.handleErrorResponse.unexpectedError": "予期しないエラー", - "visTypeTimeseries.iconSelect.asteriskLabel": "アスタリスク", - "visTypeTimeseries.iconSelect.bellLabel": "ベル", - "visTypeTimeseries.iconSelect.boltLabel": "ボルト", - "visTypeTimeseries.iconSelect.bombLabel": "ボム", - "visTypeTimeseries.iconSelect.bugLabel": "バグ", - "visTypeTimeseries.iconSelect.commentLabel": "コメント", - "visTypeTimeseries.iconSelect.exclamationCircleLabel": "マル感嘆符", - "visTypeTimeseries.iconSelect.exclamationTriangleLabel": "注意三角マーク", - "visTypeTimeseries.iconSelect.fireLabel": "炎", - "visTypeTimeseries.iconSelect.flagLabel": "旗", - "visTypeTimeseries.iconSelect.heartLabel": "ハート", - "visTypeTimeseries.iconSelect.mapMarkerLabel": "マップマーカー", - "visTypeTimeseries.iconSelect.mapPinLabel": "マップピン", - "visTypeTimeseries.iconSelect.starLabel": "星", - "visTypeTimeseries.iconSelect.tagLabel": "タグ", - "visTypeTimeseries.indexPattern.detailLevel": "詳細レベル", - "visTypeTimeseries.indexPattern.detailLevelAriaLabel": "詳細レベル", - "visTypeTimeseries.indexPattern.detailLevelHelpText": "時間範囲に基づき自動およびgte間隔を制御します。デフォルトの間隔は詳細設定の{histogramTargetBars}と{histogramMaxBars}の影響を受けます。", - "visTypeTimeseries.indexPattern.dropLastBucketLabel": "最後のバケットをドロップしますか?", - "visTypeTimeseries.indexPattern.finest": "最も細かい", - "visTypeTimeseries.indexPattern.intervalHelpText": "例:auto、1m、1d、7d、1y、>=1m", - "visTypeTimeseries.indexPattern.intervalLabel": "間隔", - "visTypeTimeseries.indexPattern.timeFieldLabel": "時間フィールド", - "visTypeTimeseries.indexPattern.timeRange.entireTimeRange": "時間範囲全体", - "visTypeTimeseries.indexPattern.timeRange.error": "現在のインデックスタイプでは\"{mode}\"を使用できません。", - "visTypeTimeseries.indexPattern.timeRange.hint": "この設定は、一致するドキュメントに使用される期間をコントロールします。「時間範囲全体」は、タイムピッカーで選択されたすべてのドキュメントと照会します。「最終値」は、期間の終了時から指定期間のドキュメントのみと照会します。", - "visTypeTimeseries.indexPattern.timeRange.label": "データ期間モード", - "visTypeTimeseries.indexPattern.timeRange.lastValue": "最終値", - "visTypeTimeseries.indexPattern.timeRange.selectTimeRange": "選択してください", - "visTypeTimeseries.indexPattern.сoarse": "粗い", - "visTypeTimeseries.kbnVisTypes.metricsDescription": "時系列データの高度な分析を実行します。", - "visTypeTimeseries.kbnVisTypes.metricsTitle": "TSVB", - "visTypeTimeseries.lastValueModeIndicator.lastBucketDate": "バケット:{lastBucketDate}", - "visTypeTimeseries.lastValueModeIndicator.lastValue": "最終値", - "visTypeTimeseries.lastValueModeIndicator.lastValueModeBadgeAriaLabel": "最後の値の詳細を表示", - "visTypeTimeseries.lastValueModeIndicator.panelInterval": "間隔:{formattedPanelInterval}", - "visTypeTimeseries.lastValueModePopover.gearButton": "最終値のインジケーター表示オプションを変更", - "visTypeTimeseries.lastValueModePopover.switch": "最終値モードを使用するときにラベルを表示", - "visTypeTimeseries.lastValueModePopover.title": "最終値オプション", - "visTypeTimeseries.markdown.alignOptions.bottomLabel": "一番下", - "visTypeTimeseries.markdown.alignOptions.middleLabel": "真ん中", - "visTypeTimeseries.markdown.alignOptions.topLabel": "一番上", - "visTypeTimeseries.markdown.dataTab.dataButtonLabel": "データ", - "visTypeTimeseries.markdown.dataTab.metricsButtonLabel": "メトリック", - "visTypeTimeseries.markdown.editor.addSeriesTooltip": "数列を追加", - "visTypeTimeseries.markdown.editor.cloneSeriesTooltip": "数列のクローンを作成", - "visTypeTimeseries.markdown.editor.deleteSeriesTooltip": "数列を削除", - "visTypeTimeseries.markdown.editor.labelPlaceholder": "ラベル", - "visTypeTimeseries.markdown.editor.toggleEditorAriaLabel": "数列エディターを切り替える", - "visTypeTimeseries.markdown.editor.variableNamePlaceholder": "変数名", - "visTypeTimeseries.markdown.optionsTab.backgroundColorLabel": "背景色:", - "visTypeTimeseries.markdown.optionsTab.customCSSLabel": "カスタム CSS(Less をサポート)", - "visTypeTimeseries.markdown.optionsTab.dataLabel": "データ", - "visTypeTimeseries.markdown.optionsTab.ignoreGlobalFilterLabel": "グローバルフィルターを無視しますか?", - "visTypeTimeseries.markdown.optionsTab.openLinksInNewTab": "新規タブでリンクを開きますか?", - "visTypeTimeseries.markdown.optionsTab.optionsButtonLabel": "オプション", - "visTypeTimeseries.markdown.optionsTab.panelFilterLabel": "パネルフィルター", - "visTypeTimeseries.markdown.optionsTab.panelOptionsButtonLabel": "パネルオプション", - "visTypeTimeseries.markdown.optionsTab.showScrollbarsLabel": "スクロールバーを表示しますか?", - "visTypeTimeseries.markdown.optionsTab.styleLabel": "スタイル", - "visTypeTimeseries.markdown.optionsTab.verticalAlignmentLabel": "縦の配列:", - "visTypeTimeseries.markdownEditor.howToAccessEntireTreeDescription": "{all} という特殊な変数もあり、ツリー全体へのアクセスに使用できます。これは group by からデータのリストを作成する際に便利です:", - "visTypeTimeseries.markdownEditor.howToUseVariablesInMarkdownDescription": "次の変数は Markdown で Handlebar(mustache)構文を使用して使用できます。利用可能な表現は {handlebarLink} をご覧ください。", - "visTypeTimeseries.markdownEditor.howUseVariablesInMarkdownDescription.documentationLinkText": "ドキュメンテーションはここをクリックしてください", - "visTypeTimeseries.markdownEditor.nameLabel": "名前", - "visTypeTimeseries.markdownEditor.noVariablesAvailableDescription": "選択されたデータメトリックに利用可能な変数はありません。", - "visTypeTimeseries.markdownEditor.valueLabel": "値", - "visTypeTimeseries.math.aggregationLabel": "アグリゲーション", - "visTypeTimeseries.math.expressionDescription.tinyMathLinkText": "TinyMath", - "visTypeTimeseries.math.expressionLabel": "表現", - "visTypeTimeseries.math.variablesLabel": "変数", - "visTypeTimeseries.metric.dataTab.dataButtonLabel": "データ", - "visTypeTimeseries.metric.dataTab.metricsButtonLabel": "メトリック", - "visTypeTimeseries.metric.editor.addSeriesTooltip": "数列を追加", - "visTypeTimeseries.metric.editor.cloneSeriesTooltip": "数列のクローンを作成", - "visTypeTimeseries.metric.editor.deleteSeriesTooltip": "数列を削除", - "visTypeTimeseries.metric.editor.labelPlaceholder": "ラベル", - "visTypeTimeseries.metric.editor.toggleEditorAriaLabel": "数列エディターを切り替える", - "visTypeTimeseries.metric.optionsTab.colorRulesLabel": "カラールール", - "visTypeTimeseries.metric.optionsTab.dataLabel": "データ", - "visTypeTimeseries.metric.optionsTab.ignoreGlobalFilterLabel": "グローバルフィルターを無視しますか?", - "visTypeTimeseries.metric.optionsTab.optionsButtonLabel": "オプション", - "visTypeTimeseries.metric.optionsTab.panelFilterLabel": "パネルフィルター", - "visTypeTimeseries.metric.optionsTab.panelOptionsButtonLabel": "パネルオプション", - "visTypeTimeseries.metricMissingErrorMessage": "メトリックに {field} がありません", - "visTypeTimeseries.metricSelect.selectMetricPlaceholder": "メトリックを選択してください…", - "visTypeTimeseries.missingPanelConfigDescription": "「{modelType}」にパネル構成が欠けています", - "visTypeTimeseries.movingAverage.aggregationLabel": "アグリゲーション", - "visTypeTimeseries.movingAverage.alpha": "アルファ", - "visTypeTimeseries.movingAverage.beta": "ベータ", - "visTypeTimeseries.movingAverage.gamma": "ガンマ", - "visTypeTimeseries.movingAverage.metricLabel": "メトリック", - "visTypeTimeseries.movingAverage.model.selectPlaceholder": "選択してください", - "visTypeTimeseries.movingAverage.modelLabel": "モデル", - "visTypeTimeseries.movingAverage.modelOptions.exponentiallyWeightedLabel": "指数加重", - "visTypeTimeseries.movingAverage.modelOptions.holtLinearLabel": "Holt-Linear", - "visTypeTimeseries.movingAverage.modelOptions.holtWintersLabel": "Holt-Winters", - "visTypeTimeseries.movingAverage.modelOptions.linearLabel": "線形", - "visTypeTimeseries.movingAverage.modelOptions.simpleLabel": "シンプル", - "visTypeTimeseries.movingAverage.multiplicative": "マルチキャプティブ", - "visTypeTimeseries.movingAverage.multiplicative.selectPlaceholder": "選択してください", - "visTypeTimeseries.movingAverage.multiplicativeOptions.false": "False", - "visTypeTimeseries.movingAverage.multiplicativeOptions.true": "True", - "visTypeTimeseries.movingAverage.period": "期間", - "visTypeTimeseries.movingAverage.windowSizeHint": "ウィンドウは、必ず、期間のサイズの 2 倍以上でなければなりません", - "visTypeTimeseries.movingAverage.windowSizeLabel": "ウィンドウサイズ", - "visTypeTimeseries.noButtonLabel": "いいえ", - "visTypeTimeseries.percentile.aggregationLabel": "アグリゲーション", - "visTypeTimeseries.percentile.fieldLabel": "フィールド", - "visTypeTimeseries.percentile.fillToLabel": "次の基準に合わせる:", - "visTypeTimeseries.percentile.modeLabel": "モード:", - "visTypeTimeseries.percentile.modeOptions.bandLabel": "帯", - "visTypeTimeseries.percentile.modeOptions.lineLabel": "折れ線", - "visTypeTimeseries.percentile.percentile": "パーセンタイル", - "visTypeTimeseries.percentile.percentileAriaLabel": "パーセンタイル", - "visTypeTimeseries.percentile.percents": "パーセント", - "visTypeTimeseries.percentile.shadeLabel": "シェイド(0 から 1):", - "visTypeTimeseries.percentileHdr.numberOfSignificantValueDigits": "大きい値の桁数(HDR ヒストグラム)", - "visTypeTimeseries.percentileHdr.numberOfSignificantValueDigits.hint": "HDR ヒストグラム(ハイダイナミックレンジヒストグラム)は、レイテンシ測定のパーセンタイルランクを計算するときに役立つ別の実装方法です。メモリ消費量が多いというトレードオフがある t-digest 実装よりも高速になります。大きい値の桁数パラメーターは、大きい桁数のヒストグラムで値の解像度を指定します。", - "visTypeTimeseries.percentileRank.aggregationLabel": "アグリゲーション", - "visTypeTimeseries.percentileRank.fieldLabel": "フィールド", - "visTypeTimeseries.percentileRank.values": "値", - "visTypeTimeseries.positiveOnly.aggregationLabel": "アグリゲーション", - "visTypeTimeseries.positiveOnly.metricLabel": "メトリック", - "visTypeTimeseries.positiveRate.aggregationLabel": "アグリゲーション", - "visTypeTimeseries.positiveRate.helpText": "このアグリゲーションは、{link}にのみ適用してください。これは、最大値、微分、正の値のみを適用するショートカットです。", - "visTypeTimeseries.positiveRate.helpTextLink": "単調に数値を増加しています", - "visTypeTimeseries.positiveRate.unitSelectPlaceholder": "スケールを選択...", - "visTypeTimeseries.positiveRate.unitsLabel": "スケール", - "visTypeTimeseries.postiveRate.fieldLabel": "フィールド", - "visTypeTimeseries.replaceVars.errors.markdownErrorDescription": "Markdown、既知の変数、ビルトイン Handlebars 表現のみが使用されていることを確認してください。", - "visTypeTimeseries.replaceVars.errors.markdownErrorTitle": "Markdown の処理中にエラーが発生", - "visTypeTimeseries.replaceVars.errors.unknownVarDescription": "{badVar} は不明な変数です", - "visTypeTimeseries.replaceVars.errors.unknownVarTitle": "Markdown の処理中にエラーが発生", - "visTypeTimeseries.searchStrategyUndefinedErrorMessage": "検索ストラテジが定義されていませんでした", - "visTypeTimeseries.serialDiff.aggregationLabel": "アグリゲーション", - "visTypeTimeseries.serialDiff.lagLabel": "ラグ", - "visTypeTimeseries.serialDiff.metricLabel": "メトリック", - "visTypeTimeseries.series.missingAggregationKeyErrorMessage": "返答から集約キーが欠けています。このリクエストのパーミッションを確認してください。", - "visTypeTimeseries.series.shouldOneSeriesPerRequestErrorMessage": "1 つのリクエストに複数の数列を含めることはできません。", - "visTypeTimeseries.seriesAgg.aggregationLabel": "アグリゲーション", - "visTypeTimeseries.seriesAgg.functionLabel": "関数", - "visTypeTimeseries.seriesAgg.functionOptions.avgLabel": "平均", - "visTypeTimeseries.seriesAgg.functionOptions.countLabel": "系列数", - "visTypeTimeseries.seriesAgg.functionOptions.cumulativeSumLabel": "累積和", - "visTypeTimeseries.seriesAgg.functionOptions.maxLabel": "最高", - "visTypeTimeseries.seriesAgg.functionOptions.minLabel": "最低", - "visTypeTimeseries.seriesAgg.functionOptions.overallAvgLabel": "全体平均", - "visTypeTimeseries.seriesAgg.functionOptions.overallMaxLabel": "全体最高", - "visTypeTimeseries.seriesAgg.functionOptions.overallMinLabel": "全体最低", - "visTypeTimeseries.seriesAgg.functionOptions.overallSumLabel": "全体合計", - "visTypeTimeseries.seriesAgg.functionOptions.sumLabel": "合計", - "visTypeTimeseries.seriesAgg.seriesAggIsNotCompatibleLabel": "数列集約は表の可視化に対応していません。", - "visTypeTimeseries.seriesConfig.filterLabel": "フィルター", - "visTypeTimeseries.seriesConfig.ignoreGlobalFilterDisabledTooltip": "グローバルフィルターはパネルオプションで無視されるため、これは無効です。", - "visTypeTimeseries.seriesConfig.ignoreGlobalFilterLabel": "グローバルフィルターを無視しますか?", - "visTypeTimeseries.seriesConfig.missingSeriesComponentDescription": "パネルタイプ {panelType} の数列コンポーネントが欠けています", - "visTypeTimeseries.seriesConfig.offsetSeriesTimeLabel": "数列の時間を(1m, 1h, 1w, 1d)でオフセット", - "visTypeTimeseries.seriesConfig.templateHelpText": "eg. {templateExample}", - "visTypeTimeseries.seriesConfig.templateLabel": "テンプレート", - "visTypeTimeseries.sort.dragToSortAriaLabel": "ドラッグして並べ替えます", - "visTypeTimeseries.sort.dragToSortTooltip": "ドラッグして並べ替えます", - "visTypeTimeseries.splits.everything.groupByLabel": "グループ分けの条件", - "visTypeTimeseries.splits.filter.groupByLabel": "グループ分けの条件", - "visTypeTimeseries.splits.filter.queryStringLabel": "クエリ文字列", - "visTypeTimeseries.splits.filterItems.labelAriaLabel": "ラベル", - "visTypeTimeseries.splits.filterItems.labelPlaceholder": "ラベル", - "visTypeTimeseries.splits.filters.groupByLabel": "グループ分けの条件", - "visTypeTimeseries.splits.groupBySelect.modeOptions.everythingLabel": "すべて", - "visTypeTimeseries.splits.groupBySelect.modeOptions.filterLabel": "フィルター", - "visTypeTimeseries.splits.groupBySelect.modeOptions.filtersLabel": "フィルター", - "visTypeTimeseries.splits.groupBySelect.modeOptions.termsLabel": "用語", - "visTypeTimeseries.splits.terms.byLabel": "グループ基準", - "visTypeTimeseries.splits.terms.defaultCountLabel": "ドキュメントカウント(デフォルト)", - "visTypeTimeseries.splits.terms.directionLabel": "方向", - "visTypeTimeseries.splits.terms.dirOptions.ascendingLabel": "昇順", - "visTypeTimeseries.splits.terms.dirOptions.descendingLabel": "降順", - "visTypeTimeseries.splits.terms.excludeLabel": "除外", - "visTypeTimeseries.splits.terms.groupByLabel": "グループ分けの条件", - "visTypeTimeseries.splits.terms.includeLabel": "含める", - "visTypeTimeseries.splits.terms.orderByLabel": "並び順", - "visTypeTimeseries.splits.terms.sizePlaceholder": "サイズ", - "visTypeTimeseries.splits.terms.termsLabel": "用語", - "visTypeTimeseries.splits.terms.topLabel": "一番上", - "visTypeTimeseries.static.aggregationLabel": "アグリゲーション", - "visTypeTimeseries.static.staticValuesLabel": "固定値", - "visTypeTimeseries.stdAgg.aggregationLabel": "アグリゲーション", - "visTypeTimeseries.stdAgg.fieldLabel": "フィールド", - "visTypeTimeseries.stdDeviation.aggregationLabel": "アグリゲーション", - "visTypeTimeseries.stdDeviation.fieldLabel": "フィールド", - "visTypeTimeseries.stdDeviation.modeLabel": "モード", - "visTypeTimeseries.stdDeviation.modeOptions.boundsBandLabel": "境界バンド", - "visTypeTimeseries.stdDeviation.modeOptions.lowerBoundLabel": "下の境界", - "visTypeTimeseries.stdDeviation.modeOptions.rawLabel": "未加工", - "visTypeTimeseries.stdDeviation.modeOptions.upperBoundLabel": "上の境界", - "visTypeTimeseries.stdDeviation.sigmaLabel": "シグマ", - "visTypeTimeseries.stdSibling.aggregationLabel": "アグリゲーション", - "visTypeTimeseries.stdSibling.metricLabel": "メトリック", - "visTypeTimeseries.stdSibling.modeLabel": "モード", - "visTypeTimeseries.stdSibling.modeOptions.boundsBandLabel": "境界バンド", - "visTypeTimeseries.stdSibling.modeOptions.lowerBoundLabel": "下の境界", - "visTypeTimeseries.stdSibling.modeOptions.rawLabel": "未加工", - "visTypeTimeseries.stdSibling.modeOptions.upperBoundLabel": "上の境界", - "visTypeTimeseries.stdSibling.sigmaLabel": "シグマ", - "visTypeTimeseries.table.addSeriesTooltip": "数列を追加", - "visTypeTimeseries.table.aggregateFunctionLabel": "集約関数", - "visTypeTimeseries.table.avgLabel": "平均", - "visTypeTimeseries.table.cloneSeriesTooltip": "数列のクローンを作成", - "visTypeTimeseries.table.colorRulesLabel": "カラールール", - "visTypeTimeseries.table.columnNotSortableTooltip": "この列は並べ替えできません", - "visTypeTimeseries.table.cumulativeSumLabel": "累積和", - "visTypeTimeseries.table.dataTab.columnLabel": "列ラベル", - "visTypeTimeseries.table.dataTab.columnsButtonLabel": "列", - "visTypeTimeseries.table.dataTab.defineFieldDescription": "表の可視化は、用語集約でグループ分けの基準となるフィールドを定義する必要があります。", - "visTypeTimeseries.table.dataTab.groupByFieldLabel": "フィールドでグループ分け", - "visTypeTimeseries.table.dataTab.rowsLabel": "行", - "visTypeTimeseries.table.deleteSeriesTooltip": "数列を削除", - "visTypeTimeseries.table.fieldLabel": "フィールド", - "visTypeTimeseries.table.filterLabel": "フィルター", - "visTypeTimeseries.table.labelAriaLabel": "ラベル", - "visTypeTimeseries.table.labelPlaceholder": "ラベル", - "visTypeTimeseries.table.maxLabel": "最高", - "visTypeTimeseries.table.minLabel": "最低", - "visTypeTimeseries.table.noResultsAvailableMessage": "結果がありません。", - "visTypeTimeseries.table.noResultsAvailableWithDescriptionMessage": "結果がありません。このビジュアライゼーションは、フィールドでグループを選択する必要があります。", - "visTypeTimeseries.table.optionsTab.dataLabel": "データ", - "visTypeTimeseries.table.optionsTab.ignoreGlobalFilterLabel": "グローバルフィルターを無視しますか?", - "visTypeTimeseries.table.optionsTab.itemUrlHelpText": "これは mustache テンプレートをサポートしています。{key} が用語に設定されています。", - "visTypeTimeseries.table.optionsTab.itemUrlLabel": "アイテム URL", - "visTypeTimeseries.table.optionsTab.panelFilterLabel": "パネルフィルター", - "visTypeTimeseries.table.optionsTab.panelOptionsButtonLabel": "パネルオプション", - "visTypeTimeseries.table.overallAvgLabel": "全体平均", - "visTypeTimeseries.table.overallMaxLabel": "全体最高", - "visTypeTimeseries.table.overallMinLabel": "全体最低", - "visTypeTimeseries.table.overallSumLabel": "全体合計", - "visTypeTimeseries.table.showTrendArrowsLabel": "傾向矢印を表示しますか?", - "visTypeTimeseries.table.sumLabel": "合計", - "visTypeTimeseries.table.tab.metricsLabel": "メトリック", - "visTypeTimeseries.table.tab.optionsLabel": "オプション", - "visTypeTimeseries.table.templateHelpText": "eg.{templateExample}", - "visTypeTimeseries.table.templateLabel": "テンプレート", - "visTypeTimeseries.table.toggleSeriesEditorAriaLabel": "数列エディターを切り替える", - "visTypeTimeseries.timeSeries.addSeriesTooltip": "数列を追加", - "visTypeTimeseries.timeseries.annotationsTab.annotationsButtonLabel": "注釈", - "visTypeTimeseries.timeSeries.axisMaxLabel": "軸最大値", - "visTypeTimeseries.timeSeries.axisMinLabel": "軸最小値", - "visTypeTimeseries.timeSeries.axisPositionLabel": "軸の配置", - "visTypeTimeseries.timeSeries.barLabel": "バー", - "visTypeTimeseries.timeSeries.chartBar.chartTypeLabel": "チャートタイプ", - "visTypeTimeseries.timeSeries.chartBar.fillLabel": "塗りつぶし(0 から 1)", - "visTypeTimeseries.timeSeries.chartBar.lineWidthLabel": "線の幅", - "visTypeTimeseries.timeSeries.chartBar.stackedLabel": "スタック", - "visTypeTimeseries.timeSeries.chartLine.chartTypeLabel": "チャートタイプ", - "visTypeTimeseries.timeSeries.chartLine.fillLabel": "塗りつぶし(0 から 1)", - "visTypeTimeseries.timeSeries.chartLine.lineWidthLabel": "線の幅", - "visTypeTimeseries.timeSeries.chartLine.pointSizeLabel": "点のサイズ", - "visTypeTimeseries.timeSeries.chartLine.stackedLabel": "スタック", - "visTypeTimeseries.timeSeries.chartLine.stepsLabel": "ステップ", - "visTypeTimeseries.timeSeries.cloneSeriesTooltip": "数列のクローンを作成", - "visTypeTimeseries.timeseries.dataTab.dataButtonLabel": "データ", - "visTypeTimeseries.timeSeries.deleteSeriesTooltip": "数列を削除", - "visTypeTimeseries.timeSeries.gradientLabel": "グラデーション", - "visTypeTimeseries.timeSeries.hideInLegendLabel": "凡例で非表示", - "visTypeTimeseries.timeSeries.labelPlaceholder": "ラベル", - "visTypeTimeseries.timeSeries.leftLabel": "左", - "visTypeTimeseries.timeseries.legendPositionOptions.bottomLabel": "一番下", - "visTypeTimeseries.timeseries.legendPositionOptions.leftLabel": "左", - "visTypeTimeseries.timeseries.legendPositionOptions.rightLabel": "右", - "visTypeTimeseries.timeSeries.lineLabel": "折れ線", - "visTypeTimeseries.timeSeries.noneLabel": "なし", - "visTypeTimeseries.timeSeries.offsetSeriesTimeLabel": "数列の時間を(1m, 1h, 1w, 1d)でオフセット", - "visTypeTimeseries.timeseries.optionsTab.axisMaxLabel": "軸最大値", - "visTypeTimeseries.timeseries.optionsTab.axisMinLabel": "軸最小値", - "visTypeTimeseries.timeseries.optionsTab.axisPositionLabel": "軸の配置", - "visTypeTimeseries.timeseries.optionsTab.axisScaleLabel": "軸のスケール", - "visTypeTimeseries.timeseries.optionsTab.backgroundColorLabel": "背景色:", - "visTypeTimeseries.timeseries.optionsTab.dataLabel": "データ", - "visTypeTimeseries.timeseries.optionsTab.displayGridLabel": "グリッドを表示", - "visTypeTimeseries.timeseries.optionsTab.ignoreDaylightTimeLabel": "夏時間を無視しますか?", - "visTypeTimeseries.timeseries.optionsTab.ignoreGlobalFilterLabel": "グローバルフィルターを無視しますか?", - "visTypeTimeseries.timeseries.optionsTab.legendPositionLabel": "凡例位置", - "visTypeTimeseries.timeseries.optionsTab.maxLinesLabel": "最大凡例行", - "visTypeTimeseries.timeseries.optionsTab.panelFilterLabel": "パネルフィルター", - "visTypeTimeseries.timeseries.optionsTab.panelOptionsButtonLabel": "パネルオプション", - "visTypeTimeseries.timeseries.optionsTab.showLegendLabel": "凡例を表示しますか?", - "visTypeTimeseries.timeseries.optionsTab.styleLabel": "スタイル", - "visTypeTimeseries.timeseries.optionsTab.tooltipMode": "ツールチップ", - "visTypeTimeseries.timeseries.optionsTab.truncateLegendLabel": "凡例を切り捨てますか?", - "visTypeTimeseries.timeSeries.percentLabel": "パーセント", - "visTypeTimeseries.timeseries.positionOptions.leftLabel": "左", - "visTypeTimeseries.timeseries.positionOptions.rightLabel": "右", - "visTypeTimeseries.timeSeries.rainbowLabel": "虹", - "visTypeTimeseries.timeSeries.rightLabel": "右", - "visTypeTimeseries.timeseries.scaleOptions.logLabel": "ログ", - "visTypeTimeseries.timeseries.scaleOptions.normalLabel": "標準", - "visTypeTimeseries.timeSeries.separateAxisLabel": "軸を分けますか?", - "visTypeTimeseries.timeSeries.splitColorThemeLabel": "カラーテーマを分割", - "visTypeTimeseries.timeSeries.stackedLabel": "スタック", - "visTypeTimeseries.timeSeries.stackedWithinSeriesLabel": "数列内でスタック", - "visTypeTimeseries.timeSeries.tab.metricsLabel": "メトリック", - "visTypeTimeseries.timeSeries.tab.optionsLabel": "オプション", - "visTypeTimeseries.timeSeries.templateHelpText": "eg.{templateExample}", - "visTypeTimeseries.timeSeries.templateLabel": "テンプレート", - "visTypeTimeseries.timeSeries.toggleSeriesEditorAriaLabel": "数列エディターを切り替える", - "visTypeTimeseries.timeseries.tooltipOptions.showAll": "すべての値を表示", - "visTypeTimeseries.timeseries.tooltipOptions.showFocused": "フォーカスされた値を表示", - "visTypeTimeseries.topHit.aggregateWith.selectPlaceholder": "選択してください...", - "visTypeTimeseries.topHit.aggregateWithLabel": "集約:", - "visTypeTimeseries.topHit.aggregationLabel": "アグリゲーション", - "visTypeTimeseries.topHit.aggWithOptions.averageLabel": "平均", - "visTypeTimeseries.topHit.aggWithOptions.concatenate": "連結", - "visTypeTimeseries.topHit.aggWithOptions.maxLabel": "最高", - "visTypeTimeseries.topHit.aggWithOptions.minLabel": "最低", - "visTypeTimeseries.topHit.aggWithOptions.sumLabel": "合計", - "visTypeTimeseries.topHit.fieldLabel": "フィールド", - "visTypeTimeseries.topHit.order.selectPlaceholder": "選択してください...", - "visTypeTimeseries.topHit.orderByLabel": "並び順", - "visTypeTimeseries.topHit.orderLabel": "順序", - "visTypeTimeseries.topHit.orderOptions.ascLabel": "昇順", - "visTypeTimeseries.topHit.orderOptions.descLabel": "降順", - "visTypeTimeseries.topHit.sizeLabel": "サイズ", - "visTypeTimeseries.topN.addSeriesTooltip": "数列を追加", - "visTypeTimeseries.topN.cloneSeriesTooltip": "数列のクローンを作成", - "visTypeTimeseries.topN.dataTab.dataButtonLabel": "データ", - "visTypeTimeseries.topN.deleteSeriesTooltip": "数列を削除", - "visTypeTimeseries.topN.labelPlaceholder": "ラベル", - "visTypeTimeseries.topN.optionsTab.backgroundColorLabel": "背景色:", - "visTypeTimeseries.topN.optionsTab.colorRulesLabel": "カラールール", - "visTypeTimeseries.topN.optionsTab.dataLabel": "データ", - "visTypeTimeseries.topN.optionsTab.ignoreGlobalFilterLabel": "グローバルフィルターを無視しますか?", - "visTypeTimeseries.topN.optionsTab.itemUrlDescription": "これは mustache テンプレートをサポートしています。{key} が用語に設定されています。", - "visTypeTimeseries.topN.optionsTab.itemUrlLabel": "アイテム URL", - "visTypeTimeseries.topN.optionsTab.panelFilterLabel": "パネルフィルター", - "visTypeTimeseries.topN.optionsTab.panelOptionsButtonLabel": "パネルオプション", - "visTypeTimeseries.topN.optionsTab.styleLabel": "スタイル", - "visTypeTimeseries.topN.tab.metricsLabel": "メトリック", - "visTypeTimeseries.topN.tab.optionsLabel": "オプション", - "visTypeTimeseries.topN.toggleSeriesEditorAriaLabel": "数列エディターを切り替える", - "visTypeTimeseries.units.auto": "自動", - "visTypeTimeseries.units.perDay": "日単位", - "visTypeTimeseries.units.perHour": "時間単位", - "visTypeTimeseries.units.perMillisecond": "ミリ秒単位", - "visTypeTimeseries.units.perMinute": "分単位", - "visTypeTimeseries.units.perSecond": "秒単位", - "visTypeTimeseries.unsupportedSplit.splitIsUnsupportedDescription": "{modelType} での分割はサポートされていません。", - "visTypeTimeseries.vars.variableNameAriaLabel": "変数名", - "visTypeTimeseries.vars.variableNamePlaceholder": "変数名", - "visTypeTimeseries.visEditorVisualization.applyChangesLabel": "変更を適用", - "visTypeTimeseries.visEditorVisualization.autoApplyLabel": "自動適用", - "visTypeTimeseries.visEditorVisualization.changesHaveNotBeenAppliedMessage": "ビジュアライゼーションへの変更が適用されました。", - "visTypeTimeseries.visEditorVisualization.changesSuccessfullyAppliedMessage": "最新の変更が適用されました。", - "visTypeTimeseries.visEditorVisualization.changesWillBeAutomaticallyAppliedMessage": "変更が自動的に適用されます。", - "visTypeTimeseries.visEditorVisualization.dataViewMode.dismissNoticeButtonText": "閉じる", - "visTypeTimeseries.visEditorVisualization.dataViewMode.link": "確認してください。", - "visTypeTimeseries.visPicker.gaugeLabel": "ゲージ", - "visTypeTimeseries.visPicker.metricLabel": "メトリック", - "visTypeTimeseries.visPicker.tableLabel": "表", - "visTypeTimeseries.visPicker.timeSeriesLabel": "時系列", - "visTypeTimeseries.visPicker.topNLabel": "トップ N", - "visTypeTimeseries.yesButtonLabel": "はい", - "visTypeVega.editor.formatError": "仕様のフォーマット中にエラーが発生", - "visTypeVega.editor.reformatAsHJSONButtonLabel": "HJSON に変換", - "visTypeVega.editor.reformatAsJSONButtonLabel": "JSON に変換しコメントを削除", - "visTypeVega.editor.vegaDocumentationLinkText": "Vega ドキュメント", - "visTypeVega.editor.vegaEditorOptionsButtonAriaLabel": "Vega エディターオプション", - "visTypeVega.editor.vegaHelpButtonAriaLabel": "Vega ヘルプ", - "visTypeVega.editor.vegaHelpLinkText": "Kibana Vega ヘルプ", - "visTypeVega.editor.vegaLiteDocumentationLinkText": "Vega-Lite ドキュメンテーション", - "visTypeVega.emsFileParser.emsFileNameDoesNotExistErrorMessage": "{emsfile} {emsfileName} が存在しません", - "visTypeVega.emsFileParser.missingNameOfFileErrorMessage": "{dataUrlParamValue} の {dataUrlParam} には {nameParam} パラメーター(ファイル名)が必要です", - "visTypeVega.esQueryParser.autointervalValueTypeErrorMessage": "{autointerval} は文字 {trueValue} または数字である必要があります", - "visTypeVega.esQueryParser.dataUrlMustNotHaveLegacyAndBodyQueryValuesAtTheSameTimeErrorMessage": "{dataUrlParam} はレガシー {legacyContext} と {bodyQueryConfigName} の値を同時に含めることができません。", - "visTypeVega.esQueryParser.dataUrlMustNotHaveLegacyContextTogetherWithContextOrTimefieldErrorMessage": "{dataUrlParam} は {legacyContext} と同時に {context} または {timefield} を含めることができません", - "visTypeVega.esQueryParser.legacyContextCanBeTrueErrorMessage": "レガシー {legacyContext} は {trueValue}(時間範囲ピッカーを無視)、または時間フィールドの名前のどちらかです。例:{timestampParam}", - "visTypeVega.esQueryParser.legacyUrlShouldChangeToWarningMessage": "レガシー {urlParam}: {legacyUrl} を {result} に変更する必要があります", - "visTypeVega.esQueryParser.shiftMustValueTypeErrorMessage": "{shiftParam} は数値でなければなりません", - "visTypeVega.esQueryParser.timefilterValueErrorMessage": "{timefilter} のプロパティは {trueValue}、{minValue}、または {maxValue} に設定する必要があります", - "visTypeVega.esQueryParser.unknownUnitValueErrorMessage": "不明な {unitParamName} 値。次のいずれかでなければなりません。[{unitParamValues}]", - "visTypeVega.esQueryParser.unnamedRequest": "無題のリクエスト#{index}", - "visTypeVega.esQueryParser.urlBodyValueTypeErrorMessage": "{configName} はオブジェクトでなければなりません", - "visTypeVega.esQueryParser.urlContextAndUrlTimefieldMustNotBeUsedErrorMessage": "{urlContext} と {timefield} は {queryParam} が設定されている場合使用できません", - "visTypeVega.function.help": "Vega ビジュアライゼーション", - "visTypeVega.inspector.dataSetsLabel": "データセット", - "visTypeVega.inspector.dataViewer.dataSetAriaLabel": "データセット", - "visTypeVega.inspector.dataViewer.gridAriaLabel": "{name}データグリッド", - "visTypeVega.inspector.signalValuesLabel": "単一の値", - "visTypeVega.inspector.signalViewer.gridAriaLabel": "単一の値のデータグリッド", - "visTypeVega.inspector.specLabel": "仕様", - "visTypeVega.inspector.specViewer.copyToClipboardLabel": "クリップボードにコピー", - "visTypeVega.inspector.vegaAdapter.signal": "信号", - "visTypeVega.inspector.vegaAdapter.value": "値", - "visTypeVega.inspector.vegaDebugLabel": "Vegaデバッグ", - "visTypeVega.mapView.experimentalMapLayerInfo": "マップレイヤーはまだ実験段階であり、オフィシャルGA機能のサポートSLAが適用されません。フィードバックがある場合は、{githubLink}で問題を報告してください。", - "visTypeVega.mapView.mapStyleNotFoundWarningMessage": "{mapStyleParam} が見つかりませんでした", - "visTypeVega.mapView.minZoomAndMaxZoomHaveBeenSwappedWarningMessage": "{minZoomPropertyName} と {maxZoomPropertyName} が交換されました", - "visTypeVega.mapView.resettingPropertyToMaxValueWarningMessage": "{name} を {max} にリセットしています", - "visTypeVega.mapView.resettingPropertyToMinValueWarningMessage": "{name} を {min} にリセットしています", - "visTypeVega.type.vegaDescription": "Vega を使用して、新しいタイプのビジュアライゼーションを作成します。", - "visTypeVega.type.vegaNote": "Vega 構文の知識が必要です。", - "visTypeVega.type.vegaTitleInWizard": "カスタムビジュアライゼーション", - "visTypeVega.urlParser.dataUrlRequiresUrlParameterInFormErrorMessage": "{dataUrlParam} には「{formLink}」の形で {urlParam} パラメーターが必要です", - "visTypeVega.urlParser.urlShouldHaveQuerySubObjectWarningMessage": "{urlObject} を使用するには {subObjectName} サブオブジェクトが必要です", - "visTypeVega.vegaParser.autoSizeDoesNotAllowFalse": "{autoSizeParam}が有効です。無効にするには、{autoSizeParam}を{noneParam}に設定してください", - "visTypeVega.vegaParser.baseView.externalUrlsAreNotEnabledErrorMessage": "外部 URL が無効です。{enableExternalUrls}を{kibanaConfigFileName}に追加", - "visTypeVega.vegaParser.baseView.functionIsNotDefinedForGraphErrorMessage": "このグラフには {funcName} が定義されていません", - "visTypeVega.vegaParser.baseView.indexNotFoundErrorMessage": "インデックス {index} が見つかりません", - "visTypeVega.vegaParser.baseView.timeValuesTypeErrorMessage": "時間フィルターの設定エラー:両方の時間の値は相対的または絶対的な日付である必要があります。 {start}、{end}", - "visTypeVega.vegaParser.baseView.unableToFindDefaultIndexErrorMessage": "デフォルトのインデックスが見つかりません", - "visTypeVega.vegaParser.centerOnMarkConfigValueTypeErrorMessage": "{configName} は {trueValue}、{falseValue}、または数字でなければなりません", - "visTypeVega.vegaParser.dataExceedsSomeParamsUseTimesLimitErrorMessage": "データには {urlParam}、{valuesParam}、 {sourceParam} の内複数を含めることができません", - "visTypeVega.vegaParser.hostConfigIsDeprecatedWarningMessage": "{deprecatedConfigName} は廃止されました。代わりに {newConfigName} を使用します。", - "visTypeVega.vegaParser.hostConfigValueTypeErrorMessage": "{configName} が含まれている場合、オブジェクトでなければなりません", - "visTypeVega.vegaParser.inputSpecDoesNotSpecifySchemaErrorMessage": "仕様に基づき、{schemaParam}フィールドには、\nVega({vegaSchemaUrl}を参照)または\nVega-Lite({vegaLiteSchemaUrl}を参照)の有効なURLを入力する必要があります。\nURLは識別子にすぎません。Kibanaやご使用のブラウザーがこのURLにアクセスすることはありません。", - "visTypeVega.vegaParser.invalidVegaSpecErrorMessage": "無効な Vega 仕様", - "visTypeVega.vegaParser.kibanaConfigValueTypeErrorMessage": "{configName} が含まれている場合、オブジェクトでなければなりません", - "visTypeVega.vegaParser.maxBoundsValueTypeWarningMessage": "{maxBoundsConfigName} は 4 つの数字の配列でなければなりません", - "visTypeVega.vegaParser.notSupportedUrlTypeErrorMessage": "{urlObject} はサポートされていません", - "visTypeVega.vegaParser.notValidLibraryVersionForInputSpecWarningMessage": "インプット仕様に {schemaLibrary} {schemaVersion} が使用されていますが、現在のバージョンの {schemaLibrary} は {libraryVersion} です。", - "visTypeVega.vegaParser.paddingConfigValueTypeErrorMessage": "{configName} は数字でなければなりません", - "visTypeVega.vegaParser.someKibanaConfigurationIsNoValidWarningMessage": "{configName} は有効ではありません", - "visTypeVega.vegaParser.someKibanaParamValueTypeWarningMessage": "{configName} はブール値でなければなりません", - "visTypeVega.vegaParser.textTruncateConfigValueTypeErrorMessage": "{configName} はブール値でなければなりません", - "visTypeVega.vegaParser.unexpectedValueForPositionConfigurationErrorMessage": "{configurationName} 構成に予期せぬ値が使用されています", - "visTypeVega.vegaParser.unrecognizedControlsLocationValueErrorMessage": "認識されていない {controlsLocationParam} 値。[{locToDirMap}]のいずれかが想定されます。", - "visTypeVega.vegaParser.unrecognizedDirValueErrorMessage": "認識されていない {dirParam} 値。[{expectedValues}]のいずれかが想定されます。", - "visTypeVega.vegaParser.VLCompilerShouldHaveGeneratedSingleProtectionObjectErrorMessage": "内部エラー:Vega-Lite コンパイラーがシングルプロジェクションオブジェクトを生成したはずです", - "visTypeVega.vegaParser.widthAndHeightParamsAreIgnored": "{autoSizeParam}が有効であるため、{widthParam}および{heightParam}パラメーターは無視されます。無効にする{autoSizeParam}: {noneParam}を設定", - "visTypeVega.vegaParser.widthAndHeightParamsAreRequired": "{autoSizeParam}が{noneParam}に設定されているときには、カットまたは繰り返された{vegaLiteParam}仕様を使用している間に何も表示されません。修正するには、{autoSizeParam}を削除するか、{vegaParam}を使用してください。", - "visTypeVega.visualization.renderErrorTitle": "Vega エラー", - "visTypeVega.visualization.unableToRenderWithoutDataWarningMessage": "データなしにはレンダリングできません", - "visTypeVislib.advancedSettings.visualization.heatmap.maxBucketsText": "1つのデータソースが返せるバケットの最大数です。値が大きいとブラウザのレンダリング速度が下がる可能性があります。", - "visTypeVislib.advancedSettings.visualization.heatmap.maxBucketsTitle": "ヒートマップの最大バケット数", - "visTypeVislib.aggResponse.allDocsTitle": "すべてのドキュメント", - "visTypeVislib.controls.gaugeOptions.alignmentLabel": "アラインメント", - "visTypeVislib.controls.gaugeOptions.autoExtendRangeLabel": "範囲を自動拡張", - "visTypeVislib.controls.gaugeOptions.extendRangeTooltip": "範囲をデータの最高値に広げます。", - "visTypeVislib.controls.gaugeOptions.gaugeTypeLabel": "ゲージタイプ", - "visTypeVislib.controls.gaugeOptions.labelsTitle": "ラベル", - "visTypeVislib.controls.gaugeOptions.rangesTitle": "範囲", - "visTypeVislib.controls.gaugeOptions.showLabelsLabel": "ラベルを表示", - "visTypeVislib.controls.gaugeOptions.showLegendLabel": "凡例を表示", - "visTypeVislib.controls.gaugeOptions.showOutline": "アウトラインを表示", - "visTypeVislib.controls.gaugeOptions.showScaleLabel": "縮尺を表示", - "visTypeVislib.controls.gaugeOptions.styleTitle": "スタイル", - "visTypeVislib.controls.gaugeOptions.subTextLabel": "サブラベル", - "visTypeVislib.controls.heatmapOptions.colorLabel": "色", - "visTypeVislib.controls.heatmapOptions.colorScaleLabel": "カラースケール", - "visTypeVislib.controls.heatmapOptions.colorsNumberLabel": "色の数", - "visTypeVislib.controls.heatmapOptions.labelsTitle": "ラベル", - "visTypeVislib.controls.heatmapOptions.overwriteAutomaticColorLabel": "自動カラーを上書きする", - "visTypeVislib.controls.heatmapOptions.rotateLabel": "回転", - "visTypeVislib.controls.heatmapOptions.scaleToDataBoundsLabel": "データバウンドに合わせる", - "visTypeVislib.controls.heatmapOptions.showLabelsTitle": "ラベルを表示", - "visTypeVislib.controls.heatmapOptions.useCustomRangesLabel": "カスタム範囲を使用", - "visTypeVislib.editors.heatmap.basicSettingsTitle": "基本設定", - "visTypeVislib.editors.heatmap.heatmapSettingsTitle": "ヒートマップ設定", - "visTypeVislib.editors.heatmap.highlightLabel": "ハイライト範囲", - "visTypeVislib.editors.heatmap.highlightLabelTooltip": "チャートのカーソルを当てた部分と凡例の対応するラベルをハイライトします。", - "visTypeVislib.functions.pie.help": "パイビジュアライゼーション", - "visTypeVislib.functions.vislib.help": "Vislib ビジュアライゼーション", - "visTypeVislib.gauge.alignmentAutomaticTitle": "自動", - "visTypeVislib.gauge.alignmentHorizontalTitle": "横", - "visTypeVislib.gauge.alignmentVerticalTitle": "縦", - "visTypeVislib.gauge.gaugeDescription": "メトリックのステータスを示します。", - "visTypeVislib.gauge.gaugeTitle": "ゲージ", - "visTypeVislib.gauge.gaugeTypes.arcText": "弧形", - "visTypeVislib.gauge.gaugeTypes.circleText": "円", - "visTypeVislib.gauge.groupTitle": "グループを分割", - "visTypeVislib.gauge.metricTitle": "メトリック", - "visTypeVislib.goal.goalDescription": "メトリックがどのように目標まで進むのかを追跡します。", - "visTypeVislib.goal.goalTitle": "ゴール", - "visTypeVislib.goal.groupTitle": "グループを分割", - "visTypeVislib.goal.metricTitle": "メトリック", - "visTypeVislib.heatmap.groupTitle": "Y 軸", - "visTypeVislib.heatmap.heatmapDescription": "マトリックスのセルのデータを網掛けにします。", - "visTypeVislib.heatmap.heatmapTitle": "ヒートマップ", - "visTypeVislib.heatmap.metricTitle": "値", - "visTypeVislib.heatmap.segmentTitle": "X 軸", - "visTypeVislib.heatmap.splitTitle": "チャートを分割", - "visTypeVislib.vislib.errors.noResultsFoundTitle": "結果が見つかりませんでした", - "visTypeVislib.vislib.heatmap.maxBucketsText": "定義された数列が多すぎます({nr})。構成されている最大値は {max} です。", - "visTypeVislib.vislib.legend.filterForValueButtonAriaLabel": "値 {legendDataLabel} でフィルタリング", - "visTypeVislib.vislib.legend.filterOptionsLegend": "{legendDataLabel}、フィルターオプション", - "visTypeVislib.vislib.legend.filterOutValueButtonAriaLabel": "値 {legendDataLabel} を除外", - "visTypeVislib.vislib.legend.loadingLabel": "読み込み中…", - "visTypeVislib.vislib.legend.toggleLegendButtonAriaLabel": "凡例を切り替える", - "visTypeVislib.vislib.legend.toggleLegendButtonTitle": "凡例を切り替える", - "visTypeVislib.vislib.legend.toggleOptionsButtonAriaLabel": "{legendDataLabel}、トグルオプション", - "visTypeVislib.vislib.tooltip.fieldLabel": "フィールド", - "visTypeVislib.vislib.tooltip.valueLabel": "値", - "visTypeXy.aggResponse.allDocsTitle": "すべてのドキュメント", - "visTypeXy.area.areaDescription": "軸と線の間のデータを強調します。", - "visTypeXy.area.areaTitle": "エリア", - "visTypeXy.area.groupTitle": "系列を分割", - "visTypeXy.area.metricsTitle": "Y 軸", - "visTypeXy.area.radiusTitle": "点のサイズ", - "visTypeXy.area.segmentTitle": "X 軸", - "visTypeXy.area.splitTitle": "チャートを分割", - "visTypeXy.area.tabs.metricsAxesTitle": "メトリックと軸", - "visTypeXy.area.tabs.panelSettingsTitle": "パネル設定", - "visTypeXy.axisModes.normalText": "標準", - "visTypeXy.axisModes.percentageText": "割合(%)", - "visTypeXy.axisModes.silhouetteText": "シルエット", - "visTypeXy.axisModes.wiggleText": "振動", - "visTypeXy.categoryAxis.rotate.angledText": "傾斜", - "visTypeXy.categoryAxis.rotate.horizontalText": "横", - "visTypeXy.categoryAxis.rotate.verticalText": "縦", - "visTypeXy.chartModes.normalText": "標準", - "visTypeXy.chartModes.stackedText": "スタック", - "visTypeXy.chartTypes.areaText": "エリア", - "visTypeXy.chartTypes.barText": "バー", - "visTypeXy.chartTypes.lineText": "折れ線", - "visTypeXy.controls.pointSeries.categoryAxis.alignLabel": "配置", - "visTypeXy.controls.pointSeries.categoryAxis.filterLabelsLabel": "フィルターラベル", - "visTypeXy.controls.pointSeries.categoryAxis.labelsTitle": "ラベル", - "visTypeXy.controls.pointSeries.categoryAxis.positionLabel": "位置", - "visTypeXy.controls.pointSeries.categoryAxis.showLabel": "軸線とラベルを表示", - "visTypeXy.controls.pointSeries.categoryAxis.showLabelsLabel": "ラベルを表示", - "visTypeXy.controls.pointSeries.categoryAxis.xAxisTitle": "X 軸", - "visTypeXy.controls.pointSeries.gridAxis.dontShowLabel": "非表示", - "visTypeXy.controls.pointSeries.gridAxis.gridText": "グリッド", - "visTypeXy.controls.pointSeries.gridAxis.xAxisLinesLabel": "X 軸線を表示", - "visTypeXy.controls.pointSeries.gridAxis.yAxisLinesLabel": "Y 軸線を表示", - "visTypeXy.controls.pointSeries.series.chartTypeLabel": "チャートタイプ", - "visTypeXy.controls.pointSeries.series.circlesRadius": "点のサイズ", - "visTypeXy.controls.pointSeries.series.lineModeLabel": "線のモード", - "visTypeXy.controls.pointSeries.series.lineWidthLabel": "線の幅", - "visTypeXy.controls.pointSeries.series.metricsTitle": "メトリック", - "visTypeXy.controls.pointSeries.series.modeLabel": "モード", - "visTypeXy.controls.pointSeries.series.newAxisLabel": "新規軸…", - "visTypeXy.controls.pointSeries.series.showDotsLabel": "点を表示", - "visTypeXy.controls.pointSeries.series.showLineLabel": "線を表示", - "visTypeXy.controls.pointSeries.series.valueAxisLabel": "値軸", - "visTypeXy.controls.pointSeries.seriesAccordionAriaLabel": "{agg} オプションを切り替える", - "visTypeXy.controls.pointSeries.valueAxes.addButtonTooltip": "Y 軸を追加します", - "visTypeXy.controls.pointSeries.valueAxes.customExtentsLabel": "カスタム範囲", - "visTypeXy.controls.pointSeries.valueAxes.maxLabel": "最高", - "visTypeXy.controls.pointSeries.valueAxes.minErrorMessage": "最低値は最高値よりも低く設定する必要があります。", - "visTypeXy.controls.pointSeries.valueAxes.minLabel": "最低", - "visTypeXy.controls.pointSeries.valueAxes.minNeededScaleText": "ログスケールが選択されている場合、最低値は 0 よりも大きいものである必要があります。", - "visTypeXy.controls.pointSeries.valueAxes.modeLabel": "モード", - "visTypeXy.controls.pointSeries.valueAxes.positionLabel": "位置", - "visTypeXy.controls.pointSeries.valueAxes.removeButtonTooltip": "Y 軸を削除します", - "visTypeXy.controls.pointSeries.valueAxes.scaleToDataBounds.boundsMargin": "境界マージン", - "visTypeXy.controls.pointSeries.valueAxes.scaleToDataBounds.minNeededBoundsMargin": "境界マージンは 0 以上でなければなりません。", - "visTypeXy.controls.pointSeries.valueAxes.scaleToDataBoundsLabel": "データバウンドに合わせる", - "visTypeXy.controls.pointSeries.valueAxes.scaleTypeLabel": "スケールタイプ", - "visTypeXy.controls.pointSeries.valueAxes.setAxisExtentsLabel": "軸範囲を設定", - "visTypeXy.controls.pointSeries.valueAxes.showLabel": "軸線とラベルを表示", - "visTypeXy.controls.pointSeries.valueAxes.titleLabel": "タイトル", - "visTypeXy.controls.pointSeries.valueAxes.toggleCustomExtendsAriaLabel": "カスタム範囲を切り替える", - "visTypeXy.controls.pointSeries.valueAxes.toggleOptionsAriaLabel": "{axisName} オプションを切り替える", - "visTypeXy.controls.pointSeries.valueAxes.yAxisTitle": "Y 軸", - "visTypeXy.controls.truncateLabel": "切り捨て", - "visTypeXy.editors.elasticChartsOptions.detailedTooltip.label": "詳細ツールチップを表示", - "visTypeXy.editors.elasticChartsOptions.detailedTooltip.tooltip": "単一の値を表示するためのレガシー詳細ツールチップを有効にします。無効にすると、新しい概要のツールチップに複数の値が表示されます。", - "visTypeXy.editors.elasticChartsOptions.fillOpacity": "塗りつぶしの透明度", - "visTypeXy.editors.elasticChartsOptions.missingValuesLabel": "欠測値を埋める", - "visTypeXy.editors.pointSeries.currentTimeMarkerLabel": "現在時刻マーカー", - "visTypeXy.editors.pointSeries.orderBucketsBySumLabel": "バケットを合計で並べ替え", - "visTypeXy.editors.pointSeries.settingsTitle": "設定", - "visTypeXy.editors.pointSeries.showLabels": "チャートに値を表示", - "visTypeXy.editors.pointSeries.thresholdLine.colorLabel": "線の色", - "visTypeXy.editors.pointSeries.thresholdLine.showLabel": "しきい線を表示", - "visTypeXy.editors.pointSeries.thresholdLine.styleLabel": "ラインスタイル", - "visTypeXy.editors.pointSeries.thresholdLine.valueLabel": "しきい値", - "visTypeXy.editors.pointSeries.thresholdLine.widthLabel": "線の幅", - "visTypeXy.editors.pointSeries.thresholdLineSettingsTitle": "しきい線", - "visTypeXy.fittingFunctionsTitle.carry": "最後(ギャップを最後の値で埋める)", - "visTypeXy.fittingFunctionsTitle.linear": "線形(ギャップを線で埋める)", - "visTypeXy.fittingFunctionsTitle.lookahead": "次(ギャップを次の値で埋める)", - "visTypeXy.fittingFunctionsTitle.none": "非表示(ギャップを埋めない)", - "visTypeXy.fittingFunctionsTitle.zero": "ゼロ(ギャップをゼロで埋める)", - "visTypeXy.function.adimension.bucket": "バケット", - "visTypeXy.function.adimension.dotSize": "点のサイズ", - "visTypeXy.function.args.addLegend.help": "グラフ凡例を表示", - "visTypeXy.function.args.addTimeMarker.help": "時刻マーカーを表示", - "visTypeXy.function.args.addTooltip.help": "カーソルを置いたときにツールチップを表示", - "visTypeXy.function.args.args.chartType.help": "グラフの種類。折れ線、エリア、ヒストグラムを選択できます", - "visTypeXy.function.args.categoryAxes.help": "カテゴリ軸構成", - "visTypeXy.function.args.detailedTooltip.help": "詳細ツールチップを表示", - "visTypeXy.function.args.fillOpacity.help": "エリアグラフの塗りつぶしの透明度を定義します", - "visTypeXy.function.args.fittingFunction.help": "適合関数の名前", - "visTypeXy.function.args.gridCategoryLines.help": "グラフにグリッドカテゴリ線を表示", - "visTypeXy.function.args.gridValueAxis.help": "グリッドを表示する値軸の名前", - "visTypeXy.function.args.isVislibVis.help": "古いvislib可視化を示すフラグ。色を含む後方互換性のために使用されます", - "visTypeXy.function.args.labels.help": "グラフラベル構成", - "visTypeXy.function.args.legendPosition.help": "グラフの上、下、左、右に凡例を配置", - "visTypeXy.function.args.orderBucketsBySum.help": "バケットを合計で並べ替え", - "visTypeXy.function.args.palette.help": "グラフパレット名を定義します", - "visTypeXy.function.args.radiusRatio.help": "点サイズ率", - "visTypeXy.function.args.seriesDimension.help": "系列ディメンション構成", - "visTypeXy.function.args.seriesParams.help": "系列パラメーター構成", - "visTypeXy.function.args.splitColumnDimension.help": "列ディメンション構成で分割", - "visTypeXy.function.args.splitRowDimension.help": "行ディメンション構成で分割", - "visTypeXy.function.args.thresholdLine.help": "しきい値線構成", - "visTypeXy.function.args.times.help": "時刻マーカー構成", - "visTypeXy.function.args.valueAxes.help": "値軸構成", - "visTypeXy.function.args.widthDimension.help": "幅ディメンション構成", - "visTypeXy.function.args.xDimension.help": "X軸ディメンション構成", - "visTypeXy.function.args.yDimension.help": "Y軸ディメンション構成", - "visTypeXy.function.args.zDimension.help": "Z軸ディメンション構成", - "visTypeXy.function.categoryAxis.help": "カテゴリ軸オブジェクトを生成します", - "visTypeXy.function.categoryAxis.id.help": "カテゴリ軸のID", - "visTypeXy.function.categoryAxis.labels.help": "軸ラベル構成", - "visTypeXy.function.categoryAxis.position.help": "カテゴリ軸の位置", - "visTypeXy.function.categoryAxis.scale.help": "スケール構成", - "visTypeXy.function.categoryAxis.show.help": "カテゴリ軸を表示", - "visTypeXy.function.categoryAxis.title.help": "カテゴリ軸のタイトル", - "visTypeXy.function.categoryAxis.type.help": "カテゴリ軸の種類。カテゴリまたは値を選択できます", - "visTypeXy.function.dimension.metric": "メトリック", - "visTypeXy.function.dimension.splitcolumn": "列分割", - "visTypeXy.function.dimension.splitrow": "行分割", - "visTypeXy.function.label.color.help": "ラベルの色", - "visTypeXy.function.label.filter.help": "軸の重なるラベルと重複を非表示にします", - "visTypeXy.function.label.help": "ラベルオブジェクトを生成します", - "visTypeXy.function.label.overwriteColor.help": "色を上書き", - "visTypeXy.function.label.rotate.help": "角度を回転", - "visTypeXy.function.label.show.help": "ラベルを表示", - "visTypeXy.function.label.truncate.help": "切り捨てる前の記号の数", - "visTypeXy.function.scale.boundsMargin.help": "境界のマージン", - "visTypeXy.function.scale.defaultYExtents.help": "データ境界にスケールできるフラグ", - "visTypeXy.function.scale.help": "スケールオブジェクトを生成します", - "visTypeXy.function.scale.max.help": "最高値", - "visTypeXy.function.scale.min.help": "最低値", - "visTypeXy.function.scale.mode.help": "スケールモード。標準、割合、小刻み、シルエットを選択できます", - "visTypeXy.function.scale.setYExtents.help": "独自の範囲を設定できるフラグ", - "visTypeXy.function.scale.type.help": "スケールタイプ。線形、対数、平方根を選択できます", - "visTypeXy.function.seriesParam.circlesRadius.help": "円のサイズ(半径)を定義します", - "visTypeXy.function.seriesParam.drawLinesBetweenPoints.help": "点の間に線を描画", - "visTypeXy.function.seriesparam.help": "系列パラメーターオブジェクトを生成します", - "visTypeXy.function.seriesParam.id.help": "系列パラメーターのID", - "visTypeXy.function.seriesParam.interpolate.help": "補間モード。線形、カーディナル、階段状を選択できます", - "visTypeXy.function.seriesParam.label.help": "系列パラメーターの名前", - "visTypeXy.function.seriesParam.lineWidth.help": "線の幅", - "visTypeXy.function.seriesParam.mode.help": "グラフモード。積み上げまたは割合を選択できます", - "visTypeXy.function.seriesParam.show.help": "パラメーターを表示", - "visTypeXy.function.seriesParam.showCircles.help": "円を表示", - "visTypeXy.function.seriesParam.type.help": "グラフの種類。折れ線、エリア、ヒストグラムを選択できます", - "visTypeXy.function.seriesParam.valueAxis.help": "値軸の名前", - "visTypeXy.function.thresholdLine.color.help": "しきい線の色", - "visTypeXy.function.thresholdLine.help": "しきい値線オブジェクトを生成します", - "visTypeXy.function.thresholdLine.show.help": "しきい線を表示", - "visTypeXy.function.thresholdLine.style.help": "しきい線のスタイル。実線、点線、一点鎖線を選択できます", - "visTypeXy.function.thresholdLine.value.help": "しきい値", - "visTypeXy.function.thresholdLine.width.help": "しきい値線の幅", - "visTypeXy.function.timeMarker.class.help": "CSSクラス名", - "visTypeXy.function.timeMarker.color.help": "時刻マーカーの色", - "visTypeXy.function.timemarker.help": "時刻マーカーオブジェクトを生成します", - "visTypeXy.function.timeMarker.opacity.help": "時刻マーカーの透明度", - "visTypeXy.function.timeMarker.time.help": "正確な時刻", - "visTypeXy.function.timeMarker.width.help": "時刻マーカーの幅", - "visTypeXy.function.valueAxis.axisParams.help": "値軸パラメーター", - "visTypeXy.function.valueaxis.help": "値軸オブジェクトを生成します", - "visTypeXy.function.valueAxis.name.help": "値軸の名前", - "visTypeXy.functions.help": "XYビジュアライゼーション", - "visTypeXy.histogram.groupTitle": "系列を分割", - "visTypeXy.histogram.histogramDescription": "軸の縦棒にデータを表示します。", - "visTypeXy.histogram.histogramTitle": "縦棒", - "visTypeXy.histogram.metricTitle": "Y 軸", - "visTypeXy.histogram.radiusTitle": "点のサイズ", - "visTypeXy.histogram.segmentTitle": "X 軸", - "visTypeXy.histogram.splitTitle": "チャートを分割", - "visTypeXy.horizontalBar.groupTitle": "系列を分割", - "visTypeXy.horizontalBar.horizontalBarDescription": "軸の横棒にデータを表示します。", - "visTypeXy.horizontalBar.horizontalBarTitle": "横棒", - "visTypeXy.horizontalBar.metricTitle": "Y 軸", - "visTypeXy.horizontalBar.radiusTitle": "点のサイズ", - "visTypeXy.horizontalBar.segmentTitle": "X 軸", - "visTypeXy.horizontalBar.splitTitle": "チャートを分割", - "visTypeXy.interpolationModes.smoothedText": "スムーズ", - "visTypeXy.interpolationModes.steppedText": "ステップ", - "visTypeXy.interpolationModes.straightText": "直線", - "visTypeXy.legend.filterForValueButtonAriaLabel": "値でフィルター", - "visTypeXy.legend.filterOptionsLegend": "{legendDataLabel}、フィルターオプション", - "visTypeXy.legend.filterOutValueButtonAriaLabel": "値を除外", - "visTypeXy.legendPositions.bottomText": "一番下", - "visTypeXy.legendPositions.leftText": "左", - "visTypeXy.legendPositions.rightText": "右", - "visTypeXy.legendPositions.topText": "トップ", - "visTypeXy.line.groupTitle": "系列を分割", - "visTypeXy.line.lineDescription": "データを系列点として表示します。", - "visTypeXy.line.lineTitle": "折れ線", - "visTypeXy.line.metricTitle": "Y 軸", - "visTypeXy.line.radiusTitle": "点のサイズ", - "visTypeXy.line.segmentTitle": "X 軸", - "visTypeXy.line.splitTitle": "チャートを分割", - "visTypeXy.scaleTypes.linearText": "線形", - "visTypeXy.scaleTypes.logText": "ログ", - "visTypeXy.scaleTypes.squareRootText": "平方根", - "visTypeXy.thresholdLine.style.dashedText": "鎖線", - "visTypeXy.thresholdLine.style.dotdashedText": "点線", - "visTypeXy.thresholdLine.style.fullText": "完全", - "visualizations.advancedSettings.visualizeEnableLabsText": "ユーザーが実験的なビジュアライゼーションを作成、表示、編集できるようになります。無効の場合、\n ユーザーは本番準備が整ったビジュアライゼーションのみを利用できます。", - "visualizations.advancedSettings.visualizeEnableLabsTitle": "実験的なビジュアライゼーションを有効にする", - "visualizations.disabledLabVisualizationLink": "ドキュメンテーションを表示", - "visualizations.disabledLabVisualizationMessage": "ラボビジュアライゼーションを表示するには、高度な設定でラボモードをオンにしてください。", - "visualizations.disabledLabVisualizationTitle": "{title} はラボビジュアライゼーションです。", - "visualizations.displayName": "ビジュアライゼーション", - "visualizations.embeddable.placeholderTitle": "プレースホルダータイトル", - "visualizations.function.range.from.help": "範囲の開始", - "visualizations.function.range.help": "範囲オブジェクトを生成します", - "visualizations.function.range.to.help": "範囲の終了", - "visualizations.function.visDimension.accessor.help": "使用するデータセット内の列(列インデックスまたは列名)", - "visualizations.function.visDimension.error.accessor": "入力された列名は無効です。", - "visualizations.function.visDimension.format.help": "フォーマット", - "visualizations.function.visDimension.formatParams.help": "フォーマットパラメーター", - "visualizations.function.visDimension.help": "visConfig ディメンションオブジェクトを生成します", - "visualizations.function.xyDimension.aggType.help": "集約タイプ", - "visualizations.function.xydimension.help": "XYディメンションオブジェクトを生成します", - "visualizations.function.xyDimension.label.help": "ラベル", - "visualizations.function.xyDimension.params.help": "パラメーター", - "visualizations.function.xyDimension.visDimension.help": "ディメンションオブジェクト構成", - "visualizations.initializeWithoutIndexPatternErrorMessage": "インデックスパターンなしで集約を初期化しようとしています", - "visualizations.newVisWizard.aggBasedGroupDescription": "クラシック Visualize ライブラリを使用して、アグリゲーションに基づいてグラフを作成します。", - "visualizations.newVisWizard.aggBasedGroupTitle": "アグリゲーションに基づく", - "visualizations.newVisWizard.chooseSourceTitle": "ソースの選択", - "visualizations.newVisWizard.experimentalTitle": "実験的", - "visualizations.newVisWizard.experimentalTooltip": "このビジュアライゼーションは今後のリリースで変更または削除される可能性があり、SLA のサポート対象になりません。", - "visualizations.newVisWizard.exploreOptionLinkText": "探索オプション", - "visualizations.newVisWizard.filterVisTypeAriaLabel": "ビジュアライゼーションのタイプでフィルタリング", - "visualizations.newVisWizard.goBackLink": "別のビジュアライゼーションを選択", - "visualizations.newVisWizard.helpTextAriaLabel": "タイプを選択してビジュアライゼーションの作成を始めましょう。ESC を押してこのモーダルを閉じます。Tab キーを押して次に進みます。", - "visualizations.newVisWizard.learnMoreText": "詳細について", - "visualizations.newVisWizard.newVisTypeTitle": "新規 {visTypeName}", - "visualizations.newVisWizard.readDocumentationLink": "ドキュメンテーションを表示", - "visualizations.newVisWizard.searchSelection.notFoundLabel": "一致インデックスまたは保存した検索が見つかりません。", - "visualizations.newVisWizard.searchSelection.savedObjectType.search": "保存検索", - "visualizations.newVisWizard.title": "新規ビジュアライゼーション", - "visualizations.newVisWizard.toolsGroupTitle": "ツール", - "visualizations.noResultsFoundTitle": "結果が見つかりませんでした", - "visualizations.savedObjectName": "ビジュアライゼーション", - "visualizations.savingVisualizationFailed.errorMsg": "ビジュアライゼーションの保存が失敗しました", - "visualizations.visualizationTypeInvalidMessage": "無効なビジュアライゼーションタイプ \"{visType}\"", - "visualize.badge.readOnly.text": "読み取り専用", - "visualize.badge.readOnly.tooltip": "ビジュアライゼーションをライブラリに保存できません", - "visualize.byValue_pageHeading": "{originatingApp}アプリに埋め込まれた{chartType}タイプのビジュアライゼーション", - "visualize.confirmModal.confirmTextDescription": "変更を保存せずにVisualizeエディターから移動しますか?", - "visualize.confirmModal.title": "保存されていない変更", - "visualize.createVisualization.failedToLoadErrorMessage": "ビジュアライゼーションを読み込めませんでした", - "visualize.createVisualization.noIndexPatternOrSavedSearchIdErrorMessage": "indexPatternまたはsavedSearchIdが必要です", - "visualize.createVisualization.noVisTypeErrorMessage": "有効なビジュアライゼーションタイプを指定してください", - "visualize.editor.createBreadcrumb": "作成", - "visualize.editor.defaultEditBreadcrumbText": "ビジュアライゼーションを編集", - "visualize.experimentalVisInfoText": "このビジュアライゼーションはまだ実験段階であり、オフィシャルGA機能のサポートSLAが適用されません。フィードバックがある場合は、{githubLink}で問題を報告してください。", - "visualize.helpMenu.appName": "Visualizeライブラリ", - "visualize.linkedToSearch.unlinkSuccessNotificationText": "保存された検索「{searchTitle}」からリンクが解除されました", - "visualize.listing.betaTitle": "ベータ", - "visualize.listing.betaTooltip": "このビジュアライゼーションはベータ段階で、変更される可能性があります。デザインとコードはオフィシャルGA機能よりも完成度が低く、現状のまま保証なしで提供されています。ベータ機能にはオフィシャルGA機能のSLAが適用されません", - "visualize.listing.breadcrumb": "Visualizeライブラリ", - "visualize.listing.createNew.createButtonLabel": "新規ビジュアライゼーションを追加", - "visualize.listing.createNew.description": "データに基づき異なるビジュアライゼーションを作成できます。", - "visualize.listing.createNew.title": "最初のビジュアライゼーションの作成", - "visualize.listing.experimentalTitle": "実験的", - "visualize.listing.experimentalTooltip": "このビジュアライゼーションは今後のリリースで変更または削除される可能性があり、SLA のサポート対象になりません。", - "visualize.listing.table.descriptionColumnName": "説明", - "visualize.listing.table.entityName": "ビジュアライゼーション", - "visualize.listing.table.entityNamePlural": "ビジュアライゼーション", - "visualize.listing.table.listTitle": "Visualizeライブラリ", - "visualize.listing.table.titleColumnName": "タイトル", - "visualize.listing.table.typeColumnName": "型", - "visualize.listingPageTitle": "Visualizeライブラリ", - "visualize.noMatchRoute.bannerText": "Visualizeアプリケーションはこのルートを認識できません。{route}", - "visualize.noMatchRoute.bannerTitleText": "ページが見つかりません", - "visualize.pageHeading": "{chartName} {chartType}ビジュアライゼーション", - "visualize.topNavMenu.cancelAndReturnButtonTooltip": "完了する前に変更を破棄", - "visualize.topNavMenu.cancelButtonAriaLabel": "変更を保存せずに最後に使用していたアプリに戻る", - "visualize.topNavMenu.cancelButtonLabel": "キャンセル", - "visualize.topNavMenu.openInspectorButtonAriaLabel": "ビジュアライゼーションのインスペクターを開く", - "visualize.topNavMenu.openInspectorButtonLabel": "検査", - "visualize.topNavMenu.openInspectorDisabledButtonTooltip": "このビジュアライゼーションはインスペクターをサポートしていません。", - "visualize.topNavMenu.saveAndReturnVisualizationButtonAriaLabel": "可視化の編集が完了し、前回使用していたアプリに戻ります", - "visualize.topNavMenu.saveAndReturnVisualizationButtonLabel": "保存して戻る", - "visualize.topNavMenu.saveAndReturnVisualizationDisabledButtonTooltip": "完了する前に変更を適用または破棄", - "visualize.topNavMenu.saveVisualization.failureNotificationText": "「{visTitle}」の保存中にエラーが発生しました", - "visualize.topNavMenu.saveVisualization.successNotificationText": "保存された'{visTitle}'", - "visualize.topNavMenu.saveVisualizationAsButtonLabel": "名前を付けて保存", - "visualize.topNavMenu.saveVisualizationButtonAriaLabel": "ビジュアライゼーションを保存", - "visualize.topNavMenu.saveVisualizationButtonLabel": "保存", - "visualize.topNavMenu.saveVisualizationDisabledButtonTooltip": "保存する前に変更を適用または破棄", - "visualize.topNavMenu.saveVisualizationObjectType": "ビジュアライゼーション", - "visualize.topNavMenu.saveVisualizationToLibraryButtonLabel": "ライブラリに保存", - "visualize.topNavMenu.shareVisualizationButtonAriaLabel": "ビジュアライゼーションを共有", - "visualize.topNavMenu.shareVisualizationButtonLabel": "共有", - "visualize.topNavMenu.updatePanel": "{originatingAppName}でパネルを更新", - "visualize.visualizationLoadingFailedErrorMessage": "ビジュアライゼーションを読み込めませんでした", - "visualize.visualizeDescription": "ビジュアライゼーションを作成してElasticsearchインデックスに保存されたデータをアグリゲーションします。", - "visualize.visualizeListingBreadcrumbsTitle": "Visualizeライブラリ", - "visualize.visualizeListingDashboardAppName": "ダッシュボードアプリケーション", - "visualize.visualizeListingDashboardFlowDescription": "ダッシュボードを作成しますか?{dashboardApp}から直接ビジュアライゼーションを作成して追加します。", - "visualize.visualizeListingDeleteErrorTitle": "ビジュアライゼーションの削除中にエラーが発生", - "xpack.actions.actionTypeRegistry.get.missingActionTypeErrorMessage": "アクションタイプ「{id}」は登録されていません。", - "xpack.actions.actionTypeRegistry.register.duplicateActionTypeErrorMessage": "アクションタイプ「{id}」はすでに登録されています。", - "xpack.actions.alertHistoryEsIndexConnector.name": "アラート履歴Elasticsearchインデックス", - "xpack.actions.appName": "アクション", - "xpack.actions.builtin.case.swimlaneTitle": "スイムレーン", - "xpack.actions.builtin.cases.jiraTitle": "Jira", - "xpack.actions.builtin.cases.resilientTitle": "IBM Resilient", - "xpack.actions.builtin.configuration.apiAllowedHostsError": "コネクターアクションの構成エラー:{message}", - "xpack.actions.builtin.email.customViewInKibanaMessage": "このメッセージはKibanaによって送信されました[{kibanaFooterLinkText}]({link})。", - "xpack.actions.builtin.email.errorSendingErrorMessage": "エラー送信メールアドレス", - "xpack.actions.builtin.email.kibanaFooterLinkText": "Kibana を開く", - "xpack.actions.builtin.email.sentByKibanaMessage": "このメッセージは Kibana によって送信されました。", - "xpack.actions.builtin.emailTitle": "メール", - "xpack.actions.builtin.esIndex.errorIndexingErrorMessage": "エラーインデックス作成ドキュメント", - "xpack.actions.builtin.esIndexTitle": "インデックス", - "xpack.actions.builtin.jira.configuration.apiAllowedHostsError": "コネクターアクションの構成エラー:{message}", - "xpack.actions.builtin.pagerduty.invalidTimestampErrorMessage": "タイムスタンプ\"{timestamp}\"の解析エラー", - "xpack.actions.builtin.pagerduty.missingDedupkeyErrorMessage": "eventActionが「{eventAction}」のときにはDedupKeyが必要です", - "xpack.actions.builtin.pagerduty.pagerdutyConfigurationError": "pagerduty アクションの設定エラー:{message}", - "xpack.actions.builtin.pagerduty.postingErrorMessage": "pagerduty イベントの投稿エラー", - "xpack.actions.builtin.pagerduty.postingRetryErrorMessage": "pagerduty イベントの投稿エラー:http status {status}、後ほど再試行", - "xpack.actions.builtin.pagerduty.postingUnexpectedErrorMessage": "pagerduty イベントの投稿エラー:予期せぬステータス {status}", - "xpack.actions.builtin.pagerduty.timestampParsingFailedErrorMessage": "タイムスタンプの解析エラー \"{timestamp}\":{message}", - "xpack.actions.builtin.pagerdutyTitle": "PagerDuty", - "xpack.actions.builtin.serverLog.errorLoggingErrorMessage": "メッセージのロギングエラー", - "xpack.actions.builtin.serverLogTitle": "サーバーログ", - "xpack.actions.builtin.serviceNowITSMTitle": "ServiceNow ITSM", - "xpack.actions.builtin.serviceNowSIRTitle": "ServiceNow SecOps", - "xpack.actions.builtin.serviceNowTitle": "ServiceNow", - "xpack.actions.builtin.slack.errorPostingErrorMessage": "slack メッセージの投稿エラー", - "xpack.actions.builtin.slack.errorPostingRetryDateErrorMessage": "slack メッセージの投稿エラー、 {retryString} で再試行", - "xpack.actions.builtin.slack.errorPostingRetryLaterErrorMessage": "slack メッセージの投稿エラー、後ほど再試行", - "xpack.actions.builtin.slack.slackConfigurationError": "slack アクションの設定エラー:{message}", - "xpack.actions.builtin.slack.slackConfigurationErrorNoHostname": "slack アクションの構成エラー:Web フック URL からホスト名をパースできません", - "xpack.actions.builtin.slack.unexpectedHttpResponseErrorMessage": "slack からの予期せぬ http 応答:{httpStatus} {httpStatusText}", - "xpack.actions.builtin.slack.unexpectedNullResponseErrorMessage": "Slack から予期せぬ null 応答", - "xpack.actions.builtin.slackTitle": "Slack", - "xpack.actions.builtin.swimlane.configuration.apiAllowedHostsError": "コネクターアクションの構成エラー:{message}", - "xpack.actions.builtin.swimlaneTitle": "スイムレーン", - "xpack.actions.builtin.teams.errorPostingRetryDateErrorMessage": "Microsoft Teams メッセージの投稿エラーです。{retryString} に再試行します", - "xpack.actions.builtin.teams.errorPostingRetryLaterErrorMessage": "Microsoft Teams メッセージの投稿エラーです。しばらくたってから再試行します", - "xpack.actions.builtin.teams.invalidResponseErrorMessage": "Microsoft Teams への投稿エラーです。無効な応答です", - "xpack.actions.builtin.teams.teamsConfigurationError": "Teams アクションの設定エラー:{message}", - "xpack.actions.builtin.teams.teamsConfigurationErrorNoHostname": "Teams アクションの構成エラー:Web フック URL からホスト名をパースできません", - "xpack.actions.builtin.teams.unreachableErrorMessage": "Microsoft Teams への投稿エラーです。予期しないエラーです", - "xpack.actions.builtin.teamsTitle": "Microsoft Teams", - "xpack.actions.builtin.webhook.invalidResponseErrorMessage": "Webフックの呼び出しエラー、無効な応答", - "xpack.actions.builtin.webhook.invalidResponseRetryDateErrorMessage": "Webフックの呼び出しエラー、{retryString} に再試行", - "xpack.actions.builtin.webhook.invalidResponseRetryLaterErrorMessage": "Webフックの呼び出しエラー、後ほど再試行", - "xpack.actions.builtin.webhook.invalidUsernamePassword": "ユーザーとパスワードの両方を指定する必要があります", - "xpack.actions.builtin.webhook.requestFailedErrorMessage": "Webフックの呼び出しエラー。要求が失敗しました", - "xpack.actions.builtin.webhook.unreachableErrorMessage": "webhookの呼び出しエラー、予期せぬエラー", - "xpack.actions.builtin.webhook.webhookConfigurationError": "Web フックアクションの構成中にエラーが発生:{message}", - "xpack.actions.builtin.webhook.webhookConfigurationErrorNoHostname": "Webフックアクションの構成エラーです。URLを解析できません。{err}", - "xpack.actions.builtin.webhookTitle": "Web フック", - "xpack.actions.disabledActionTypeError": "アクションタイプ \"{actionType}\" は、Kibana 構成 xpack.actions.enabledActionTypes では有効化されません", - "xpack.actions.featureRegistry.actionsFeatureName": "アクションとコネクター", - "xpack.actions.savedObjects.goToConnectorsButtonText": "コネクターに移動", - "xpack.actions.serverSideErrors.expirerdLicenseErrorMessage": "{licenseType} ライセンスの期限が切れたのでアクションタイプ {actionTypeId} は無効です。", - "xpack.actions.serverSideErrors.invalidLicenseErrorMessage": "{licenseType} ライセンスでサポートされないのでアクションタイプ {actionTypeId} は無効です。ライセンスをアップグレードしてください。", - "xpack.actions.serverSideErrors.predefinedActionDeleteDisabled": "あらかじめ構成されたアクション{id}は削除できません。", - "xpack.actions.serverSideErrors.predefinedActionUpdateDisabled": "あらかじめ構成されたアクション{id}は更新できません。", - "xpack.actions.serverSideErrors.unavailableLicenseErrorMessage": "現時点でライセンス情報を入手できないため、アクションタイプ {actionTypeId} は無効です。", - "xpack.actions.serverSideErrors.unavailableLicenseInformationErrorMessage": "グラフを利用できません。現在ライセンス情報が利用できません。", - "xpack.actions.urlAllowedHostsConfigurationError": "ターゲット{field}「{value}」はKibana構成xpack.actions.allowedHostsに追加されていません", - "xpack.alerting.alertNavigationRegistry.get.missingNavigationError": "「{consumer}」内のアラートタイプ「{alertType}」のナビゲーションは登録されていません。", - "xpack.alerting.alertNavigationRegistry.register.duplicateDefaultError": "「{consumer}」内のデフォルトナビゲーションはすでに登録されています。", - "xpack.alerting.alertNavigationRegistry.register.duplicateNavigationError": "「{consumer}」内のアラートタイプ「{alertType}」のナビゲーションは既に登録されています。", - "xpack.alerting.api.error.disabledApiKeys": "アラートは API キーに依存しますがキーが無効になっているようです", - "xpack.alerting.appName": "アラート", - "xpack.alerting.builtinActionGroups.recovered": "回復済み", - "xpack.alerting.injectActionParams.email.kibanaFooterLinkText": "Kibanaでルールを表示", - "xpack.alerting.rulesClient.invalidDate": "パラメーター{field}の無効な日付:「{dateValue}」", - "xpack.alerting.rulesClient.validateActions.invalidGroups": "無効なアクショングループ:{groups}", - "xpack.alerting.rulesClient.validateActions.misconfiguredConnector": "無効なコネクター:{groups}", - "xpack.alerting.ruleTypeRegistry.get.missingAlertTypeError": "ルールタイプ「{id}」は登録されていません。", - "xpack.alerting.ruleTypeRegistry.register.customRecoveryActionGroupUsageError": "ルールタイプ [id=\"{id}\"] を登録できません。アクショングループ[{actionGroup}] は、復元とアクティブなアクショングループの両方として使用できません。", - "xpack.alerting.ruleTypeRegistry.register.duplicateAlertTypeError": "ルールタイプ\"{id}\"はすでに登録されています。", - "xpack.alerting.savedObjects.goToRulesButtonText": "ルールに移動", - "xpack.alerting.serverSideErrors.expirerdLicenseErrorMessage": "{licenseType} ライセンスの期限が切れたのでアラートタイプ {alertTypeId} は無効です。", - "xpack.alerting.serverSideErrors.invalidLicenseErrorMessage": "アラート{alertTypeId}は無効です。{licenseType}ライセンスが必要です。アップグレードオプションを表示するには、[ライセンス管理]に移動してください。", - "xpack.alerting.serverSideErrors.unavailableLicenseErrorMessage": "現時点でライセンス情報を入手できないため、アラートタイプ {alertTypeId} は無効です。", - "xpack.alerting.serverSideErrors.unavailableLicenseInformationErrorMessage": "アラートを利用できません。現在ライセンス情報が利用できません。", - "xpack.apm.a.thresholdMet": "しきい値一致", - "xpack.apm.addDataButtonLabel": "データの追加", - "xpack.apm.agentConfig.allOptionLabel": "すべて", - "xpack.apm.agentConfig.apiRequestSize.description": "チャンクエンコーディング(HTTPストリーミング)を経由してAPM ServerインテークAPIに送信されるリクエスト本文の最大合計圧縮サイズ。\nわずかなオーバーシュートの可能性があることに注意してください。\n\n使用できるバイト単位は、「b」、「kb」、「mb」です。「1kb」は「1024b」と等価です。", - "xpack.apm.agentConfig.apiRequestSize.label": "API リクエストサイズ", - "xpack.apm.agentConfig.apiRequestTime.description": "APM Server への HTTP リクエストを開いておく最大時間。\n\n注:この値は、APM Server の「read_timeout」設定よりも低くする必要があります。", - "xpack.apm.agentConfig.apiRequestTime.label": "API リクエスト時間", - "xpack.apm.agentConfig.captureBody.description": "HTTPリクエストのトランザクションの場合、エージェントはオプションとしてリクエスト本文(POST変数など)をキャプチャすることができます。\nメッセージブローカーからメッセージを受信すると開始するトランザクションでは、エージェントがテキストメッセージの本文を取り込むことができます。", - "xpack.apm.agentConfig.captureBody.label": "本文をキャプチャ", - "xpack.apm.agentConfig.captureHeaders.description": "「true」に設定すると、メッセージングフレームワーク(Kafkaなど)を使用するときに、エージェントはHTTP要求と応答ヘッダー(Cookieを含む)、およびメッセージヘッダー/プロパティを取り込みます。\n\n注:これを「false」に設定すると、ネットワーク帯域幅、ディスク容量、およびオブジェクト割り当てが減少します。", - "xpack.apm.agentConfig.captureHeaders.label": "ヘッダーのキャプチャ", - "xpack.apm.agentConfig.chooseService.editButton": "編集", - "xpack.apm.agentConfig.chooseService.service.environment.label": "環境", - "xpack.apm.agentConfig.chooseService.service.name.label": "サービス名", - "xpack.apm.agentConfig.circuitBreakerEnabled.description": "Circuit Breakerを有効にすべきかどうかを指定するブール値。 有効にすると、エージェントは定期的にストレス監視をポーリングして、システム/プロセス/JVMのストレス状態を検出します。監視のいずれかがストレスの兆候を検出した場合、`recording`構成オプションの設定が「false」であるかのようにエージェントは一時停止し、リソース消費を最小限に抑えられます。一時停止した場合、エージェントはストレス状態が緩和されたかどうかを検出するために同じ監視のポーリングを継続します。すべての監視でシステム/プロセス/JVMにストレスがないことが認められると、エージェントは再開して完全に機能します。", - "xpack.apm.agentConfig.circuitBreakerEnabled.label": "Cirtcuit Breaker が有効", - "xpack.apm.agentConfig.configTable.appliedTooltipMessage": "1 つ以上のエージェントにより適用されました", - "xpack.apm.agentConfig.configTable.configTable.failurePromptText": "エージェントの構成一覧を取得できませんでした。ユーザーに十分なパーミッションがない可能性があります。", - "xpack.apm.agentConfig.configTable.createConfigButtonLabel": "構成の作成", - "xpack.apm.agentConfig.configTable.emptyPromptTitle": "構成が見つかりません。", - "xpack.apm.agentConfig.configTable.environmentColumnLabel": "サービス環境", - "xpack.apm.agentConfig.configTable.lastUpdatedColumnLabel": "最終更新", - "xpack.apm.agentConfig.configTable.notAppliedTooltipMessage": "まだエージェントにより適用されていません", - "xpack.apm.agentConfig.configTable.serviceNameColumnLabel": "サービス名", - "xpack.apm.agentConfig.configurationsPanelTitle": "構成", - "xpack.apm.agentConfig.configurationsPanelTitle.noPermissionTooltipLabel": "ユーザーロールには、エージェント構成を作成する権限がありません", - "xpack.apm.agentConfig.createConfigButtonLabel": "構成の作成", - "xpack.apm.agentConfig.createConfigTitle": "構成の作成", - "xpack.apm.agentConfig.deleteModal.cancel": "キャンセル", - "xpack.apm.agentConfig.deleteModal.confirm": "削除", - "xpack.apm.agentConfig.deleteModal.text": "サービス「{serviceName}」と環境「{environment}」の構成を削除しようとしています。", - "xpack.apm.agentConfig.deleteModal.title": "構成を削除", - "xpack.apm.agentConfig.deleteSection.deleteConfigFailedText": "「{serviceName}」の構成を削除中に問題が発生しました。エラー:「{errorMessage}」", - "xpack.apm.agentConfig.deleteSection.deleteConfigFailedTitle": "構成を削除できませんでした", - "xpack.apm.agentConfig.deleteSection.deleteConfigSucceededText": "「{serviceName}」の構成が正常に削除されました。エージェントに反映されるまでに少し時間がかかります。", - "xpack.apm.agentConfig.deleteSection.deleteConfigSucceededTitle": "構成が削除されました", - "xpack.apm.agentConfig.editConfigTitle": "構成の編集", - "xpack.apm.agentConfig.enableLogCorrelation.description": "エージェントがSLF4JのMDCと融合してトレースログ相関を有効にすべきかどうかを指定するブール値。「true」に設定した場合、エージェントは現在アクティブなスパンとトランザクションの「trace.id」と「transaction.id」をMDCに設定します。Javaエージェントバージョン1.16.0以降では、エージェントは、エラーメッセージが記録される前に、取り込まれたエラーの「error.id」もMDCに追加します。注:実行時にこの設定を有効にできますが、再起動しないと無効にはできません。", - "xpack.apm.agentConfig.enableLogCorrelation.label": "ログ相関を有効にする", - "xpack.apm.agentConfig.logLevel.description": "エージェントのログ記録レベルを設定します", - "xpack.apm.agentConfig.logLevel.label": "ログレベル", - "xpack.apm.agentConfig.newConfig.description": "APMアプリ内からエージェント構成を微調整してください。変更はAPMエージェントに自動的に伝達されるので、再デプロイする必要はありません。", - "xpack.apm.agentConfig.profilingInferredSpansEnabled.description": "「true」に設定すると、エージェントは、別名統計プロファイラーと呼ばれるサンプリングプロファイラーであるasync-profilerに基づいてメソッド実行用のスパンを作成します。サンプリングプロファイラーのしくみの性質上、推定スパンの期間は厳密ではなく見込みのみです。「profiling_inferred_spans_sampling_interval」では、正確度とオーバーヘッドの間のトレードオフを微調整できます。推定スパンは、プロファイルセッションの終了後に作成されます。つまり、通常のスパンと推定スパンの間にはUIに表示されるタイミングに遅延があります。注:この機能はWindowsで使用できません。", - "xpack.apm.agentConfig.profilingInferredSpansEnabled.label": "プロファイル推定スパンが有効です", - "xpack.apm.agentConfig.profilingInferredSpansExcludedClasses.description": "プロファイラー推定スパンを作成する必要がないクラスを除外します。このオプションは、0文字以上に一致するワイルドカード「*」をサポートします。デフォルトでは、照合時に大文字と小文字の区別はありません。要素の前に「(?-i)」を付けると、照合時に大文字と小文字が区別されます。", - "xpack.apm.agentConfig.profilingInferredSpansExcludedClasses.label": "プロファイル推定スパンでクラスを除外しました", - "xpack.apm.agentConfig.profilingInferredSpansIncludedClasses.description": "設定した場合、エージェントは、このリストに一致するメソッドの推定スパンのみを作成します。値を設定すると、わずかに負荷が低減することがあり、対象となるクラスのスパンのみを作成することによって煩雑になるのを防止できます。このオプションは、0文字以上に一致するワイルドカード「*」をサポートします。例:「org.example.myapp.*」デフォルトでは、照合時に大文字と小文字の区別はありません。要素の前に「(?-i)」を付けると、照合時に大文字と小文字が区別されます。", - "xpack.apm.agentConfig.profilingInferredSpansIncludedClasses.label": "プロファイル推定スパンでクラスを包含しました", - "xpack.apm.agentConfig.profilingInferredSpansMinDuration.description": "推定スパンの最小期間。最小期間もサンプリング間隔によって暗黙的に設定されることに注意してください。ただし、サンプリング間隔を大きくすると、推定スパンの期間の精度も低下します。", - "xpack.apm.agentConfig.profilingInferredSpansMinDuration.label": "プロファイル推定スパン最小期間", - "xpack.apm.agentConfig.profilingInferredSpansSamplingInterval.description": "プロファイルセッション内でスタックトレースを収集する頻度。低い値に設定するほど継続時間の精度が上がります。その代わり、オーバーヘッドが増し、潜在的に無関係なオペレーションのスパンが増えるという犠牲が伴います。プロファイル推定スパンの最小期間は、この設定値と同じです。", - "xpack.apm.agentConfig.profilingInferredSpansSamplingInterval.label": "プロファイル推定サンプリング間隔", - "xpack.apm.agentConfig.range.errorText": "{rangeType, select,\n between {{min}と{max}の間でなければなりません}\n gt {値は{min}よりも大きい値でなければなりません}\n lt {{max}よりも低く設定する必要があります}\n other {整数でなければなりません}\n }", - "xpack.apm.agentConfig.recording.description": "記録中の場合、エージェントは着信HTTPリクエストを計測し、エラーを追跡し、メトリックを収集して送信します。記録なしに設定すると、エージェントはnoopとして動作し、更新された更新のポーリングを除き、データの収集や APM Server との通信を行いません。これは可逆スイッチなので、記録なしに設定されていてもエージェントスレッドは強制終了されませんが、この状態ではほとんどアイドル状態なのでオーバーヘッドは無視できます。この設定を使用すると、Elastic APMが有効か無効かを動的に制御できます。", - "xpack.apm.agentConfig.recording.label": "記録中", - "xpack.apm.agentConfig.sanitizeFiledNames.description": "場合によっては、サニタイズが必要です。つまり、Elastic APM に送信される機密データを削除する必要があります。この構成では、サニタイズされるフィールド名のワイルドカードパターンのリストを使用できます。これらは HTTP ヘッダー(Cookie を含む)と「application/x-www-form-urlencoded」データ(POST フォームフィールド)に適用されます。クエリ文字列と取り込まれた要求本文(「application/json」データなど)はサニタイズされません。", - "xpack.apm.agentConfig.sanitizeFiledNames.label": "フィールド名のサニタイズ", - "xpack.apm.agentConfig.saveConfig.failed.text": "「{serviceName}」の構成の保存中に問題が発生しました。エラー:「{errorMessage}」", - "xpack.apm.agentConfig.saveConfig.failed.title": "構成を保存できませんでした", - "xpack.apm.agentConfig.saveConfig.succeeded.text": "「{serviceName}」の構成を保存しました。エージェントに反映されるまでに少し時間がかかります。", - "xpack.apm.agentConfig.saveConfig.succeeded.title": "構成が保存されました", - "xpack.apm.agentConfig.saveConfigurationButtonLabel": "次のステップ", - "xpack.apm.agentConfig.serverTimeout.description": "APM Server への要求で構成されたタイムアウトより時間がかかる場合、\n要求がキャンセルされ、イベント(例外またはトランザクション)が破棄されます。\n0に設定するとタイムアウトが無効になります。\n\n警告:タイムアウトが無効か高い値に設定されている場合、APM Serverがタイムアウトになると、アプリでメモリの問題が発生する可能性があります。", - "xpack.apm.agentConfig.serverTimeout.label": "サーバータイムアウト", - "xpack.apm.agentConfig.servicePage.alreadyConfiguredOption": "すでに構成済み", - "xpack.apm.agentConfig.servicePage.cancelButton": "キャンセル", - "xpack.apm.agentConfig.servicePage.environment.description": "構成ごとに 1 つの環境のみがサポートされます。", - "xpack.apm.agentConfig.servicePage.environment.fieldLabel": "サービス環境", - "xpack.apm.agentConfig.servicePage.environment.title": "環境", - "xpack.apm.agentConfig.servicePage.service.description": "構成するサービスを選択してください。", - "xpack.apm.agentConfig.servicePage.service.fieldLabel": "サービス名", - "xpack.apm.agentConfig.servicePage.service.title": "サービス", - "xpack.apm.agentConfig.settingsPage.discardChangesButton": "変更を破棄", - "xpack.apm.agentConfig.settingsPage.notFound.message": "リクエストされた構成が存在しません", - "xpack.apm.agentConfig.settingsPage.notFound.title": "申し訳ございません、エラーが発生しました", - "xpack.apm.agentConfig.settingsPage.saveButton": "構成を保存", - "xpack.apm.agentConfig.spanFramesMinDuration.description": "デフォルト設定では、APM エージェントは記録されたすべてのスパンでスタックトレースを収集します。\nこれはコード内でスパンの原因になる厳密な場所を見つけるうえで非常に役立ちますが、このスタックトレースを収集するとオーバーヘッドが生じます。\nこのオプションを負の値(「-1ms」など)に設定すると、すべてのスパンのスタックトレースが収集されます。正の値(たとえば、「5 ms」)に設定すると、スタックトレース収集を、指定値(たとえば、5ミリ秒)以上の期間にわたるスパンに制限されます。\n\nスパンのスタックトレース収集を完全に無効にするには、値を「0ms」に設定します。", - "xpack.apm.agentConfig.spanFramesMinDuration.label": "スパンフレーム最小期間", - "xpack.apm.agentConfig.stackTraceLimit.description": "0 に設定するとスタックトレース収集が無効になります。収集するフレームの最大数として正の整数値が使用されます。-1 に設定すると、すべてのフレームが収集されます。", - "xpack.apm.agentConfig.stackTraceLimit.label": "スタックトレース制限", - "xpack.apm.agentConfig.stressMonitorCpuDurationThreshold.description": "システムに現在ストレスがかかっているか、それとも以前に検出したストレスが緩和されたかを判断するために必要な最小時間。この時期のすべての測定は、関連しきい値と比較してストレス状態の変化を検出できるように一貫性が必要です。「1m」以上にする必要があります。", - "xpack.apm.agentConfig.stressMonitorCpuDurationThreshold.label": "ストレス監視 CPU 期間しきい値", - "xpack.apm.agentConfig.stressMonitorGcReliefThreshold.description": "ヒープにストレスがかからない時期を特定するためにGC監視で使用するしきい値。「stress_monitor_gc_stress_threshold」を超えた場合、エージェントはそれをヒープストレス状態と見なします。ストレス状態が収まったことを確認するには、すべてのヒーププールで占有メモリの割合がこのしきい値よりも低いことを確認します。GC監視は、直近のGCの後で測定したメモリ消費のみに依存します。", - "xpack.apm.agentConfig.stressMonitorGcReliefThreshold.label": "ストレス監視システム GC 緩和しきい値", - "xpack.apm.agentConfig.stressMonitorGcStressThreshold.description": "ヒープストレスを特定するためにGC監視で使用するしきい値。すべてのヒーププールに同じしきい値が使用され、いずれかの使用率がその値を超える場合、エージェントはそれをヒープストレスと見なします。GC監視は、直近のGCの後で測定したメモリ消費のみに依存します。", - "xpack.apm.agentConfig.stressMonitorGcStressThreshold.label": "ストレス監視システム GC ストレスしきい値", - "xpack.apm.agentConfig.stressMonitorSystemCpuReliefThreshold.description": "システムにCPUストレスがかかっていないことを判断するためにシステムCPU監視で使用するしきい値。監視機能でCPUストレスを検出した場合にCPUストレスが緩和されたと判断するには、測定されたシステムCPUが「stress_monitor_cpu_duration_threshold」と同じ長さ以上の期間にわたってこのしきい値を下回る必要があります。", - "xpack.apm.agentConfig.stressMonitorSystemCpuReliefThreshold.label": "ストレス監視システム CPU 緩和しきい値", - "xpack.apm.agentConfig.stressMonitorSystemCpuStressThreshold.description": "システムCPU監視でシステムCPUストレスの検出に使用するしきい値。システムCPUが少なくとも「stress_monitor_cpu_duration_threshold」と同じ長さ以上の期間にわたってこのしきい値を超えると、監視機能はこれをストレス状態と見なします。", - "xpack.apm.agentConfig.stressMonitorSystemCpuStressThreshold.label": "ストレス監視システム CPU ストレスしきい値", - "xpack.apm.agentConfig.transactionIgnoreUrl.description": "特定の URL への要求が命令されないように制限するために使用します。この構成では、無視される URL パスのワイルドカードパターンのカンマ区切りのリストを使用できます。受信 HTTP 要求が検出されると、要求パスが、リストの各要素に対してテストされます。たとえば、このリストに「/home/index」を追加すると、一致して、「http://localhost/home/index」と「http://whatever.com/home/index?value1=123」から命令が削除されます。", - "xpack.apm.agentConfig.transactionIgnoreUrl.label": "URL に基づくトランザクションを無視", - "xpack.apm.agentConfig.transactionMaxSpans.description": "トランザクションごとに記録される範囲を制限します。", - "xpack.apm.agentConfig.transactionMaxSpans.label": "トランザクションの最大範囲", - "xpack.apm.agentConfig.transactionSampleRate.description": "デフォルトでは、エージェントはすべてのトランザクション(たとえば、サービスへのリクエストなど)をサンプリングします。オーバーヘッドやストレージ要件を減らすには、サンプルレートの値を0.0〜1.0に設定します。全体的な時間とサンプリングされないトランザクションの結果は記録されますが、コンテキスト情報、ラベル、スパンは記録されません。", - "xpack.apm.agentConfig.transactionSampleRate.label": "トランザクションのサンプルレート", - "xpack.apm.agentConfig.unsavedSetting.tooltip": "未保存", - "xpack.apm.agentMetrics.java.gcRate": "GC レート", - "xpack.apm.agentMetrics.java.gcRateChartTitle": "1 分ごとのガベージコレクション", - "xpack.apm.agentMetrics.java.gcTime": "GC 時間", - "xpack.apm.agentMetrics.java.gcTimeChartTitle": "1 分ごとのごみ収集の時間", - "xpack.apm.agentMetrics.java.heapMemoryChartTitle": "ヒープ領域", - "xpack.apm.agentMetrics.java.heapMemorySeriesCommitted": "平均実行割当", - "xpack.apm.agentMetrics.java.heapMemorySeriesMax": "平均制限", - "xpack.apm.agentMetrics.java.heapMemorySeriesUsed": "平均使用", - "xpack.apm.agentMetrics.java.nonHeapMemoryChartTitle": "ヒープ領域以外", - "xpack.apm.agentMetrics.java.nonHeapMemorySeriesCommitted": "平均実行割当", - "xpack.apm.agentMetrics.java.nonHeapMemorySeriesUsed": "平均使用", - "xpack.apm.agentMetrics.java.threadCount": "平均カウント", - "xpack.apm.agentMetrics.java.threadCountChartTitle": "スレッド数", - "xpack.apm.agentMetrics.java.threadCountMax": "最高カウント", - "xpack.apm.aggregatedTransactions.fallback.badge": "サンプリングされたトランザクションに基づく", - "xpack.apm.aggregatedTransactions.fallback.tooltip": "メトリックイベントが現在の時間範囲にないか、メトリックイベントドキュメントにないフィールドに基づいてフィルターが適用されたため、このページはトランザクションイベントデータを使用しています。", - "xpack.apm.alertAnnotationButtonAriaLabel": "アラート詳細を表示", - "xpack.apm.alertAnnotationCriticalTitle": "重大アラート", - "xpack.apm.alertAnnotationNoSeverityTitle": "アラート", - "xpack.apm.alertAnnotationWarningTitle": "警告アラート", - "xpack.apm.alerting.fields.environment": "環境", - "xpack.apm.alerting.fields.service": "サービス", - "xpack.apm.alerting.fields.type": "型", - "xpack.apm.alerts.action_variables.environment": "アラートが作成されるトランザクションタイプ", - "xpack.apm.alerts.action_variables.intervalSize": "アラート条件が満たされた期間の長さと単位", - "xpack.apm.alerts.action_variables.serviceName": "アラートが作成されるサービス", - "xpack.apm.alerts.action_variables.threshold": "この値を超えるすべてのトリガーによりアラートが実行されます", - "xpack.apm.alerts.action_variables.transactionType": "アラートが作成されるトランザクションタイプ", - "xpack.apm.alerts.action_variables.triggerValue": "しきい値に達し、アラートをトリガーした値", - "xpack.apm.alerts.anomalySeverity.criticalLabel": "致命的", - "xpack.apm.alerts.anomalySeverity.majorLabel": "メジャー", - "xpack.apm.alerts.anomalySeverity.minor": "マイナー", - "xpack.apm.alerts.anomalySeverity.scoreDetailsDescription": "スコア {value} {value, select, critical {} other {以上}}", - "xpack.apm.alerts.anomalySeverity.warningLabel": "警告", - "xpack.apm.alertTypes.errorCount.defaultActionMessage": "次の条件のため、\\{\\{alertName\\}\\}アラートが実行されています。\n\n- サービス名:\\{\\{context.serviceName\\}\\}\n- 環境:\\{\\{context.environment\\}\\}\n- しきい値\\{\\{context.threshold\\}\\}エラー\n- トリガーされた値:過去\\{\\{context.interval\\}\\}に\\{\\{context.triggerValue\\}\\}件のエラー", - "xpack.apm.alertTypes.errorCount.description": "サービスのエラー数が定義されたしきい値を超過したときにアラートを発行します。", - "xpack.apm.alertTypes.errorCount.reason": "エラー数が{serviceName}の{threshold}を超えています(現在の値は{measured})", - "xpack.apm.alertTypes.transactionDuration.defaultActionMessage": "次の条件のため、\\{\\{alertName\\}\\}アラートが実行されています。\n\n- サービス名:\\{\\{context.serviceName\\}\\}\n- タイプ:\\{\\{context.transactionType\\}\\}\n- 環境:\\{\\{context.environment\\}\\}\n- レイテンシしきい値:\\{\\{context.threshold\\}\\}ミリ秒\n- 観察されたレイテンシ:直前の\\{\\{context.interval\\}\\}に\\{\\{context.triggerValue\\}\\}", - "xpack.apm.alertTypes.transactionDuration.description": "サービスの特定のトランザクションタイプのレイテンシが定義されたしきい値を超えたときにアラートを発行します。", - "xpack.apm.alertTypes.transactionDuration.reason": "レイテンシが{serviceName}の{threshold}を超えています(現在の値は{measured})", - "xpack.apm.alertTypes.transactionDurationAnomaly.defaultActionMessage": "次の条件のため、\\{\\{alertName\\}\\}アラートが実行されています。\n\n- サービス名:\\{\\{context.serviceName\\}\\}\n- タイプ:\\{\\{context.transactionType\\}\\}\n- 環境:\\{\\{context.environment\\}\\}\n- 重要度しきい値:\\{\\{context.threshold\\}\\}%\n- 重要度値:\\{\\{context.triggerValue\\}\\}\n", - "xpack.apm.alertTypes.transactionDurationAnomaly.description": "サービスのレイテンシが異常であるときにアラートを表示します。", - "xpack.apm.alertTypes.transactionDurationAnomaly.reason": "{serviceName}の{severityLevel}異常が検知されました(スコアは{measured})", - "xpack.apm.alertTypes.transactionErrorRate.defaultActionMessage": "次の条件のため、\\{\\{alertName\\}\\}アラートが実行されています。\n\n- サービス名:\\{\\{context.serviceName\\}\\}\n- タイプ:\\{\\{context.transactionType\\}\\}\n- 環境:\\{\\{context.environment\\}\\}\n- しきい値:\\{\\{context.threshold\\}\\}%\n- トリガーされた値:過去\\{\\{context.interval\\}\\}にエラーの\\{\\{context.triggerValue\\}\\}%", - "xpack.apm.alertTypes.transactionErrorRate.description": "サービスのトランザクションエラー率が定義されたしきい値を超過したときにアラートを発行します。", - "xpack.apm.alertTypes.transactionErrorRate.reason": "トランザクションエラー率が{serviceName}の{threshold}を超えています(現在の値は{measured})", - "xpack.apm.analyzeDataButton.label": "データを分析", - "xpack.apm.analyzeDataButton.tooltip": "実験 - データの分析では、任意のディメンションの結果データを選択してフィルタリングし、パフォーマンスの問題の原因または影響を調査することができます", - "xpack.apm.analyzeDataButtonLabel": "データを分析", - "xpack.apm.analyzeDataButtonLabel.message": "実験 - データの分析では、任意のディメンションの結果データを選択してフィルタリングし、パフォーマンスの問題の原因または影響を調査することができます。", - "xpack.apm.anomaly_detection.error.invalid_license": "異常検知を使用するには、Elastic Platinumライセンスのサブスクリプションが必要です。このライセンスがあれば、機械学習を活用して、サービスを監視できます。", - "xpack.apm.anomaly_detection.error.missing_read_privileges": "異常検知ジョブを表示するには、機械学習およびAPMの「読み取り」権限が必要です", - "xpack.apm.anomaly_detection.error.missing_write_privileges": "異常検知ジョブを作成するには、機械学習およびAPMの「書き込み」権限が必要です", - "xpack.apm.anomaly_detection.error.not_available": "機械学習を利用できません", - "xpack.apm.anomaly_detection.error.not_available_in_space": "選択したスペースでは、機械学習を利用できません", - "xpack.apm.anomalyDetection.createJobs.failed.text": "APMサービス環境用に[{environments}]1つ以上の異常検知ジョブを作成しているときに問題が発生しました。エラー:「{errorMessage}」", - "xpack.apm.anomalyDetection.createJobs.failed.title": "異常検知ジョブを作成できませんでした", - "xpack.apm.anomalyDetection.createJobs.succeeded.text": "APMサービス環境[{environments}]の異常検知ジョブが正常に作成されました。機械学習がトラフィック異常値の分析を開始するには、少し時間がかかります。", - "xpack.apm.anomalyDetection.createJobs.succeeded.title": "異常検知ジョブが作成されました", - "xpack.apm.anomalyDetectionSetup.linkLabel": "異常検知", - "xpack.apm.anomalyDetectionSetup.notEnabledForEnvironmentText": "「{currentEnvironment}」環境では、まだ異常検知が有効ではありません。クリックすると、セットアップを続行します。", - "xpack.apm.anomalyDetectionSetup.notEnabledText": "異常検知はまだ有効ではありません。クリックすると、セットアップを続行します。", - "xpack.apm.api.fleet.cloud_apm_package_policy.requiredRoleOnCloud": "スーパーユーザーロールが付与されたElastic Cloudユーザーのみが操作できます。", - "xpack.apm.api.fleet.fleetSecurityRequired": "FleetおよびSecurityプラグインが必要です", - "xpack.apm.apmDescription": "アプリケーション内から自動的に詳細なパフォーマンスメトリックやエラーを集めます。", - "xpack.apm.apmSchema.index": "APMサーバースキーマ - インデックス", - "xpack.apm.apmSettings.index": "APM 設定 - インデックス", - "xpack.apm.backendDetail.dependenciesTableColumnBackend": "サービス", - "xpack.apm.backendDetail.dependenciesTableTitle": "アップストリームサービス", - "xpack.apm.backendDetailFailedTransactionRateChartTitle": "失敗したトランザクション率", - "xpack.apm.backendDetailLatencyChartTitle": "レイテンシ", - "xpack.apm.backendDetailThroughputChartTitle": "スループット", - "xpack.apm.backendErrorRateChart.chartTitle": "失敗したトランザクション率", - "xpack.apm.backendErrorRateChart.previousPeriodLabel": "前の期間", - "xpack.apm.backendLatencyChart.chartTitle": "レイテンシ", - "xpack.apm.backendLatencyChart.previousPeriodLabel": "前の期間", - "xpack.apm.backendThroughputChart.chartTitle": "スループット", - "xpack.apm.backendThroughputChart.previousPeriodLabel": "前の期間", - "xpack.apm.chart.annotation.version": "バージョン", - "xpack.apm.chart.cpuSeries.processAverageLabel": "プロセス平均", - "xpack.apm.chart.cpuSeries.processMaxLabel": "プロセス最大", - "xpack.apm.chart.cpuSeries.systemAverageLabel": "システム平均", - "xpack.apm.chart.cpuSeries.systemMaxLabel": "システム最大", - "xpack.apm.chart.error": "データの取得時にエラーが発生しました。再試行してください", - "xpack.apm.chart.memorySeries.systemAverageLabel": "平均", - "xpack.apm.chart.memorySeries.systemMaxLabel": "最高", - "xpack.apm.clearFilters": "フィルターを消去", - "xpack.apm.compositeSpanCallsLabel": "、{count}件の呼び出し、平均{duration}", - "xpack.apm.compositeSpanDurationLabel": "平均時間", - "xpack.apm.correlations.correlationsTable.excludeDescription": "値を除外", - "xpack.apm.correlations.correlationsTable.excludeLabel": "除外", - "xpack.apm.correlations.correlationsTable.filterDescription": "値でフィルタリング", - "xpack.apm.correlations.correlationsTable.filterLabel": "フィルター", - "xpack.apm.correlations.correlationsTable.loadingText": "読み込み中", - "xpack.apm.correlations.correlationsTable.noDataText": "データなし", - "xpack.apm.correlations.failedTransactions.correlationsTable.fieldNameLabel": "フィールド名", - "xpack.apm.correlations.failedTransactions.correlationsTable.fieldValueLabel": "フィールド値", - "xpack.apm.correlations.failedTransactions.correlationsTable.impactLabel": "インパクト", - "xpack.apm.correlations.failedTransactions.correlationsTable.pValueLabel": "スコア", - "xpack.apm.correlations.failedTransactions.errorTitle": "失敗したトランザクションで相関関係の実行中にエラーが発生しました", - "xpack.apm.correlations.failedTransactions.highImpactText": "高", - "xpack.apm.correlations.failedTransactions.lowImpactText": "低", - "xpack.apm.correlations.failedTransactions.mediumImpactText": "中", - "xpack.apm.correlations.failedTransactions.panelTitle": "失敗したトランザクション", - "xpack.apm.correlations.latencyCorrelations.correlationsTable.actionsLabel": "フィルター", - "xpack.apm.correlations.latencyCorrelations.correlationsTable.correlationColumnDescription": "属性の相関関係スコア[0-1]。スコアが大きいほど、属性の遅延が大きくなります。", - "xpack.apm.correlations.latencyCorrelations.correlationsTable.correlationLabel": "相関関係", - "xpack.apm.correlations.latencyCorrelations.correlationsTable.excludeDescription": "値を除外", - "xpack.apm.correlations.latencyCorrelations.correlationsTable.excludeLabel": "除外", - "xpack.apm.correlations.latencyCorrelations.correlationsTable.fieldNameLabel": "フィールド名", - "xpack.apm.correlations.latencyCorrelations.correlationsTable.fieldValueLabel": "フィールド値", - "xpack.apm.correlations.latencyCorrelations.correlationsTable.filterDescription": "値でフィルタリング", - "xpack.apm.correlations.latencyCorrelations.correlationsTable.filterLabel": "フィルター", - "xpack.apm.correlations.latencyCorrelations.errorTitle": "相関関係の取得中にエラーが発生しました", - "xpack.apm.correlations.latencyCorrelations.panelTitle": "レイテンシ分布", - "xpack.apm.correlations.latencyCorrelations.tableTitle": "相関関係", - "xpack.apm.correlations.latencyPopoverBasicExplanation": "相関関係により、トランザクション応答時間の増加や遅延の原因となっている属性を検出できます。", - "xpack.apm.correlations.latencyPopoverChartExplanation": "遅延分布グラフは、サービスのトランザクションの全体的な遅延を可視化します。表の属性にカーソルを置くと、遅延の分布がグラフに追加されます。", - "xpack.apm.correlations.latencyPopoverFilterExplanation": "フィルターを追加または削除して、APMアプリでクエリに影響を及ぼすこともできます。", - "xpack.apm.correlations.latencyPopoverPerformanceExplanation": "この分析は多数の属性に対して統計検索を実行します。広い時間範囲やトランザクションスループットが高いサービスでは、時間がかかる場合があります。パフォーマンスを改善するには、時間範囲を絞り込みます。", - "xpack.apm.correlations.latencyPopoverTableExplanation": "この表は0~1の相関係数で並べ替えられます。相関値が高い属性は、遅延が長いトランザクションの原因である可能性が高くなります。", - "xpack.apm.correlations.latencyPopoverTitle": "遅延の相関関係", - "xpack.apm.csm.breakdownFilter.browser": "ブラウザー", - "xpack.apm.csm.breakdownFilter.device": "デバイス", - "xpack.apm.csm.breakdownFilter.location": "場所", - "xpack.apm.csm.breakDownFilter.noBreakdown": "内訳なし", - "xpack.apm.csm.breakdownFilter.os": "OS", - "xpack.apm.csm.pageViews.analyze": "分析", - "xpack.apm.customLink.buttom.create": "カスタムリンクを作成", - "xpack.apm.customLink.buttom.create.title": "作成", - "xpack.apm.customLink.buttom.manage": "カスタムリンクを管理", - "xpack.apm.customLink.empty": "カスタムリンクが見つかりません。独自のカスタムリンク、たとえば特定のダッシュボードまたは外部リンクへのリンクをセットアップします。", - "xpack.apm.dependenciesTable.columnErrorRate": "失敗したトランザクション率", - "xpack.apm.dependenciesTable.columnImpact": "インパクト", - "xpack.apm.dependenciesTable.columnLatency": "レイテンシ(平均)", - "xpack.apm.dependenciesTable.columnThroughput": "スループット", - "xpack.apm.dependenciesTable.serviceMapLinkText": "サービスマップを表示", - "xpack.apm.emptyMessage.noDataFoundDescription": "別の時間範囲を試すか検索フィルターをリセットしてください。", - "xpack.apm.emptyMessage.noDataFoundLabel": "データが見つかりません。", - "xpack.apm.error.prompt.body": "詳細はブラウザの開発者コンソールをご確認ください。", - "xpack.apm.error.prompt.title": "申し訳ございませんが、エラーが発生しました :(", - "xpack.apm.errorCountAlert.name": "エラー数しきい値", - "xpack.apm.errorCountAlertTrigger.errors": " エラー", - "xpack.apm.errorGroupDetails.culpritLabel": "原因", - "xpack.apm.errorGroupDetails.errorGroupTitle": "エラーグループ {errorGroupId}", - "xpack.apm.errorGroupDetails.errorOccurrenceTitle": "エラーのオカレンス", - "xpack.apm.errorGroupDetails.exceptionMessageLabel": "例外メッセージ", - "xpack.apm.errorGroupDetails.logMessageLabel": "ログメッセージ", - "xpack.apm.errorGroupDetails.occurrencesChartLabel": "オカレンス", - "xpack.apm.errorGroupDetails.relatedTransactionSample": "関連トランザクションサンプル", - "xpack.apm.errorGroupDetails.unhandledLabel": "未対応", - "xpack.apm.errorRate.chart.errorRate": "失敗したトランザクション率(平均)", - "xpack.apm.errorRate.chart.errorRate.previousPeriodLabel": "前の期間", - "xpack.apm.errorsTable.errorMessageAndCulpritColumnLabel": "エラーメッセージと原因", - "xpack.apm.errorsTable.groupIdColumnDescription": "スタックトレースのハッシュ。動的パラメータのため、エラーメッセージが異なる場合でも、類似したエラーをグループ化します。", - "xpack.apm.errorsTable.groupIdColumnLabel": "グループ ID", - "xpack.apm.errorsTable.latestOccurrenceColumnLabel": "最近のオカレンス", - "xpack.apm.errorsTable.noErrorsLabel": "エラーが見つかりませんでした", - "xpack.apm.errorsTable.occurrencesColumnLabel": "オカレンス", - "xpack.apm.errorsTable.typeColumnLabel": "型", - "xpack.apm.errorsTable.unhandledLabel": "未対応", - "xpack.apm.failedTransactionsCorrelations.licenseCheckText": "失敗したトランザクションの相関関係機能を使用するには、Elastic Platinumライセンスのサブスクリプションが必要です。", - "xpack.apm.featureRegistry.apmFeatureName": "APMおよびユーザーエクスペリエンス", - "xpack.apm.feedbackMenu.appName": "APM", - "xpack.apm.fetcher.error.status": "エラー", - "xpack.apm.fetcher.error.title": "リソースの取得中にエラーが発生しました", - "xpack.apm.fetcher.error.url": "URL", - "xpack.apm.filter.environment.allLabel": "すべて", - "xpack.apm.filter.environment.label": "環境", - "xpack.apm.filter.environment.notDefinedLabel": "未定義", - "xpack.apm.filter.environment.selectEnvironmentLabel": "環境を選択", - "xpack.apm.fleet_integration.settings.advancedOptionsLavel": "高度なオプション", - "xpack.apm.fleet_integration.settings.apm.capturePersonalDataDescription": "IPやユーザーエージェントなどの個人データを取り込みます", - "xpack.apm.fleet_integration.settings.apm.capturePersonalDataTitle": "個人データを取り込む", - "xpack.apm.fleet_integration.settings.apm.defaultServiceEnvironmentDescription": "サービス環境が定義されていないイベントで記録するデフォルトのサービス環境。", - "xpack.apm.fleet_integration.settings.apm.defaultServiceEnvironmentLabel": "デフォルトのサービス環境", - "xpack.apm.fleet_integration.settings.apm.defaultServiceEnvironmentTitle": "サービス構成", - "xpack.apm.fleet_integration.settings.apm.expvarEnabledDescription": "/debug/varsの下に公開されます", - "xpack.apm.fleet_integration.settings.apm.expvarEnabledTitle": "APM Server Golang expvarサポートを有効にする", - "xpack.apm.fleet_integration.settings.apm.hostLabel": "ホスト", - "xpack.apm.fleet_integration.settings.apm.hostTitle": "サーバー構成", - "xpack.apm.fleet_integration.settings.apm.idleTimeoutLabel": "基本接続が終了するまでのアイドル時間", - "xpack.apm.fleet_integration.settings.apm.maxConnectionsLabel": "許可された同時接続数", - "xpack.apm.fleet_integration.settings.apm.maxEventBytesLabel": "イベントごとの最大サイズ(バイト)", - "xpack.apm.fleet_integration.settings.apm.maxHeaderBytesDescription": "リクエストヘッダーサイズおよびタイミング構成の上限を設定します。", - "xpack.apm.fleet_integration.settings.apm.maxHeaderBytesLabel": "リクエストヘッダーの最大サイズ(バイト)", - "xpack.apm.fleet_integration.settings.apm.maxHeaderBytesTitle": "上限", - "xpack.apm.fleet_integration.settings.apm.readTimeoutLabel": "リクエスト全体を読み取る最大期間", - "xpack.apm.fleet_integration.settings.apm.responseHeadersHelpText": "セキュリティポリシー遵守目的で使用できます。", - "xpack.apm.fleet_integration.settings.apm.responseHeadersLabel": "HTTP応答に追加されたカスタムHTTPヘッダー", - "xpack.apm.fleet_integration.settings.apm.responseHeadersTitle": "カスタムヘッダー", - "xpack.apm.fleet_integration.settings.apm.settings.subtitle": "APM統合の設定", - "xpack.apm.fleet_integration.settings.apm.settings.title": "一般", - "xpack.apm.fleet_integration.settings.apm.shutdownTimeoutLabel": "シャットダウン時にリリースを解放する前の最大時間", - "xpack.apm.fleet_integration.settings.apm.urlLabel": "URL", - "xpack.apm.fleet_integration.settings.apm.writeTimeoutLabel": "応答を書き込む最大時間", - "xpack.apm.fleet_integration.settings.apmAgent.description": "{title}アプリケーションの計測を構成します。", - "xpack.apm.fleet_integration.settings.disabledLabel": "無効", - "xpack.apm.fleet_integration.settings.enabledLabel": "有効", - "xpack.apm.fleet_integration.settings.optionalLabel": "オプション", - "xpack.apm.fleet_integration.settings.requiredFieldLabel": "必須フィールド", - "xpack.apm.fleet_integration.settings.requiredLabel": "必須", - "xpack.apm.fleet_integration.settings.rum.enableRumDescription": "リアルユーザー監視(RUM)を有効にする", - "xpack.apm.fleet_integration.settings.rum.enableRumTitle": "RUMを有効にする", - "xpack.apm.fleet_integration.settings.rum.rumAllowHeaderDescription": "エージェントの認証を構成", - "xpack.apm.fleet_integration.settings.rum.rumAllowHeaderHelpText": "ユーザーエージェントが送信する許可された元のヘッダー。", - "xpack.apm.fleet_integration.settings.rum.rumAllowHeaderLabel": "許可された元のヘッダー", - "xpack.apm.fleet_integration.settings.rum.rumAllowHeaderTitle": "カスタムヘッダー", - "xpack.apm.fleet_integration.settings.rum.rumAllowOriginsHelpText": "「Content-Type」、「Content-Encoding」、「Accept」のほかにAccess-Control-Allow-Headersがサポートされています。", - "xpack.apm.fleet_integration.settings.rum.rumAllowOriginsLabel": "Access-Control-Allow-Headers", - "xpack.apm.fleet_integration.settings.rum.rumLibraryPatternHelpText": "スタックトレースフレームのfile_nameおよびabs_pathをこのregexpと照合し、ライブラリフレームを特定します。", - "xpack.apm.fleet_integration.settings.rum.rumLibraryPatternLabel": "ライブラリフレームパターン", - "xpack.apm.fleet_integration.settings.rum.rumResponseHeadersHelpText": "セキュリティポリシー遵守などの目的でRUM応答に追加されます。", - "xpack.apm.fleet_integration.settings.rum.rumResponseHeadersLabel": "カスタムHTTP応答ヘッダー", - "xpack.apm.fleet_integration.settings.rum.settings.subtitle": "RUM JSエージェントの構成を管理します。", - "xpack.apm.fleet_integration.settings.rum.settings.title": "リアルユーザー監視", - "xpack.apm.fleet_integration.settings.selectOrCreateOptions": "オプションを選択または作成", - "xpack.apm.fleet_integration.settings.tls.settings.subtitle": "TLS構成の設定。", - "xpack.apm.fleet_integration.settings.tls.settings.title": "TLS設定", - "xpack.apm.fleet_integration.settings.tls.tlsCertificateLabel": "サーバー証明書へのファイルパス。", - "xpack.apm.fleet_integration.settings.tls.tlsCertificateTitle": "TLS証明書", - "xpack.apm.fleet_integration.settings.tls.tlsCipherSuitesHelpText": "TLS 1.3では構成できません。", - "xpack.apm.fleet_integration.settings.tls.tlsCipherSuitesLabel": "TLS接続の暗号化スイート", - "xpack.apm.fleet_integration.settings.tls.tlsCurveTypesLabel": "ECDHEに基づく暗号化スイートの曲線タイプ", - "xpack.apm.fleet_integration.settings.tls.tlsEnabledTitle": "TLS を有効にする", - "xpack.apm.fleet_integration.settings.tls.tlsKeyLabel": "サーバー証明書鍵へのファイルパス", - "xpack.apm.fleet_integration.settings.tls.tlsSupportedProtocolsLabel": "サポートされているプロトコルバージョン", - "xpack.apm.fleetIntegration.assets.description": "APMでアプリケーショントレースとサービスマップを表示", - "xpack.apm.fleetIntegration.assets.name": "サービス", - "xpack.apm.fleetIntegration.enrollmentFlyout.installApmAgentButtonText": "APMエージェントのインストール", - "xpack.apm.fleetIntegration.enrollmentFlyout.installApmAgentDescription": "エージェントの起動後、ホストでAPMエージェントをインストールし、アプリケーションとサービスからデータを収集できます。", - "xpack.apm.fleetIntegration.enrollmentFlyout.installApmAgentTitle": "APMエージェントのインストール", - "xpack.apm.formatters.hoursTimeUnitLabel": "h", - "xpack.apm.formatters.microsTimeUnitLabel": "μs", - "xpack.apm.formatters.millisTimeUnitLabel": "ms", - "xpack.apm.formatters.minutesTimeUnitLabel": "分", - "xpack.apm.formatters.secondsTimeUnitLabel": "s", - "xpack.apm.header.badge.readOnly.text": "読み取り専用", - "xpack.apm.header.badge.readOnly.tooltip": "を保存できませんでした", - "xpack.apm.helpMenu.upgradeAssistantLink": "アップグレードアシスタント", - "xpack.apm.helpPopover.ariaLabel": "ヘルプ", - "xpack.apm.home.alertsMenu.alerts": "アラートとルール", - "xpack.apm.home.alertsMenu.createAnomalyAlert": "異常ルールを作成", - "xpack.apm.home.alertsMenu.createThresholdAlert": "しきい値ルールを作成", - "xpack.apm.home.alertsMenu.errorCount": "エラー数", - "xpack.apm.home.alertsMenu.transactionDuration": "レイテンシ", - "xpack.apm.home.alertsMenu.transactionErrorRate": "失敗したトランザクション率", - "xpack.apm.home.alertsMenu.viewActiveAlerts": "ルールの管理", - "xpack.apm.home.serviceLogsTabLabel": "ログ", - "xpack.apm.home.serviceMapTabLabel": "サービスマップ", - "xpack.apm.instancesLatencyDistributionChartLegend": "インスタンス", - "xpack.apm.instancesLatencyDistributionChartLegend.previousPeriod": "前の期間", - "xpack.apm.instancesLatencyDistributionChartTitle": "インスタンスのレイテンシ分布", - "xpack.apm.instancesLatencyDistributionChartTooltipClickToFilterDescription": "クリックすると、インスタンスでフィルタリングします", - "xpack.apm.instancesLatencyDistributionChartTooltipLatencyLabel": "レイテンシ", - "xpack.apm.instancesLatencyDistributionChartTooltipThroughputLabel": "スループット", - "xpack.apm.invalidLicense.licenseManagementLink": "ライセンスを更新", - "xpack.apm.invalidLicense.message": "現在ご使用のライセンスが期限切れか有効でなくなったため、APM UI を利用できません。", - "xpack.apm.invalidLicense.title": "無効なライセンス", - "xpack.apm.jvmsTable.cpuColumnLabel": "CPU 平均", - "xpack.apm.jvmsTable.explainServiceNodeNameMissing": "これらのメトリックが所属する JVM を特定できませんでした。7.5 よりも古い APM Server を実行していることが原因である可能性が高いです。この問題は APM Server 7.5 以降にアップグレードすることで解決されます。", - "xpack.apm.jvmsTable.heapMemoryColumnLabel": "ヒープ領域の平均", - "xpack.apm.jvmsTable.nameColumnLabel": "名前", - "xpack.apm.jvmsTable.nameExplanation": "JVM 名はデフォルトでコンピューター ID(該当する場合)またはホスト名ですが、エージェントの「'service_node_name」で手動で構成することもできます。", - "xpack.apm.jvmsTable.noJvmsLabel": "JVM が見つかりませんでした", - "xpack.apm.jvmsTable.nonHeapMemoryColumnLabel": "非ヒープ領域の平均", - "xpack.apm.jvmsTable.threadCountColumnLabel": "最大スレッド数", - "xpack.apm.keyValueFilterList.actionFilterLabel": "値でフィルタリング", - "xpack.apm.latencyCorrelations.licenseCheckText": "遅延の相関関係を使用するには、Elastic Platinumライセンスのサブスクリプションが必要です。使用すると、パフォーマンスの低下に関連しているフィールドを検出できます。", - "xpack.apm.license.betaBadge": "ベータ", - "xpack.apm.license.betaTooltipMessage": "現在、この機能はベータです。不具合を見つけた場合やご意見がある場合、サポートに問い合わせるか、またはディスカッションフォーラムにご報告ください。", - "xpack.apm.license.button": "トライアルを開始", - "xpack.apm.license.title": "無料の 30 日トライアルを開始", - "xpack.apm.localFilters.titles.browser": "ブラウザー", - "xpack.apm.localFilters.titles.device": "デバイス", - "xpack.apm.localFilters.titles.location": "場所", - "xpack.apm.localFilters.titles.os": "OS", - "xpack.apm.localFilters.titles.serviceName": "サービス名", - "xpack.apm.localFilters.titles.transactionUrl": "URL", - "xpack.apm.localFiltersTitle": "フィルター", - "xpack.apm.metrics.transactionChart.machineLearningLabel": "機械学習:", - "xpack.apm.metrics.transactionChart.machineLearningTooltip": "ストリームには、平均レイテンシの想定境界が表示されます。赤色の垂直の注釈は、異常スコアが75以上の異常値を示します。", - "xpack.apm.metrics.transactionChart.machineLearningTooltip.withKuery": "フィルタリングで検索バーを使用しているときには、機械学習結果が表示されません", - "xpack.apm.metrics.transactionChart.viewJob": "ジョブを表示", - "xpack.apm.navigation.serviceMapTitle": "サービスマップ", - "xpack.apm.navigation.servicesTitle": "サービス", - "xpack.apm.navigation.tracesTitle": "トレース", - "xpack.apm.notAvailableLabel": "N/A", - "xpack.apm.profiling.collapseSimilarFrames": "類似した項目を折りたたむ", - "xpack.apm.profiling.highlightFrames": "検索", - "xpack.apm.profiling.table.name": "名前", - "xpack.apm.profiling.table.value": "自己", - "xpack.apm.propertiesTable.agentFeature.noDataAvailableLabel": "利用可能なデータがありません", - "xpack.apm.propertiesTable.agentFeature.noResultFound": "\"{value}\"に対する結果が見つかりませんでした。", - "xpack.apm.propertiesTable.tabs.exceptionStacktraceLabel": "例外のスタックトレース", - "xpack.apm.propertiesTable.tabs.logs.serviceName": "サービス名", - "xpack.apm.propertiesTable.tabs.logsLabel": "ログ", - "xpack.apm.propertiesTable.tabs.logStacktraceLabel": "スタックトレース", - "xpack.apm.propertiesTable.tabs.metadataLabel": "メタデータ", - "xpack.apm.propertiesTable.tabs.timelineLabel": "Timeline", - "xpack.apm.rum.coreVitals.dataUndefined": "N/A", - "xpack.apm.rum.coreVitals.fcp": "初回コンテンツの描画", - "xpack.apm.rum.coreVitals.fcpTooltip": "初回コンテンツの描画(FCP)は初期のレンダリングに集中し、ページの読み込みが開始してから、ページのコンテンツのいずれかの部分が画面に表示されるときまでの時間を測定します。", - "xpack.apm.rum.coreVitals.tbt": "合計ブロック時間", - "xpack.apm.rum.coreVitals.tbtTooltip": "合計ブロック時間(TBT)は、初回コンテンツの描画からトランザクションが完了したときまでに発生する、各長いタスクのブロック時間(50 ミリ秒超)の合計です。", - "xpack.apm.rum.dashboard.backend": "バックエンド", - "xpack.apm.rum.dashboard.dataMissing": "N/A", - "xpack.apm.rum.dashboard.frontend": "フロントエンド", - "xpack.apm.rum.dashboard.impactfulMetrics.highTrafficPages": "高トラフィックページ", - "xpack.apm.rum.dashboard.impactfulMetrics.jsErrors": "JavaScript エラー", - "xpack.apm.rum.dashboard.overall.label": "全体", - "xpack.apm.rum.dashboard.pageLoad.label": "ページの読み込み", - "xpack.apm.rum.dashboard.pageLoadDistribution.label": "ページ読み込み分布", - "xpack.apm.rum.dashboard.pageLoadDuration.label": "ページ読み込み時間", - "xpack.apm.rum.dashboard.pageLoadTime.label": "ページ読み込み時間(秒)", - "xpack.apm.rum.dashboard.pageLoadTimes.label": "ページ読み込み時間", - "xpack.apm.rum.dashboard.pagesLoaded.label": "ページが読み込まれました", - "xpack.apm.rum.dashboard.pageViews": "合計ページビュー", - "xpack.apm.rum.dashboard.resetZoom.label": "ズームをリセット", - "xpack.apm.rum.dashboard.tooltips.backEnd": "バックエンド時間は、最初の 1 バイトを受信するまでの時間(TTFB)です。これは、要求が実行された後、最初の応答パケットが受信された時点です。", - "xpack.apm.rum.dashboard.tooltips.frontEnd": "フロントエンド時間は、合計ページ読み込み時間からバックエンド時間を減算した時間です。", - "xpack.apm.rum.dashboard.tooltips.totalPageLoad": "合計はすべてのページ読み込み時間です。", - "xpack.apm.rum.dashboard.totalPageLoad": "合計", - "xpack.apm.rum.filterGroup.breakdown": "内訳", - "xpack.apm.rum.filterGroup.coreWebVitals": "コアWebバイタル", - "xpack.apm.rum.filterGroup.seconds": "秒", - "xpack.apm.rum.filterGroup.selectBreakdown": "内訳を選択", - "xpack.apm.rum.jsErrors.errorMessage": "エラーメッセージ", - "xpack.apm.rum.jsErrors.errorRate": "エラー率", - "xpack.apm.rum.jsErrors.impactedPageLoads": "影響を受けるページ読み込み数", - "xpack.apm.rum.jsErrors.totalErrors": "合計エラー数", - "xpack.apm.rum.uxMetrics.longestLongTasks": "最長タスク時間", - "xpack.apm.rum.uxMetrics.longestLongTasksTooltip": "最も長いタスクの時間。長いタスクは、UI スレッドを長時間(50 ミリ秒以上)独占し、他の重要なタスク(フレームレートや入力レイテンシ)の実行を妨害するユーザーアクティビティまたはブラウザータスクとして定義されます。", - "xpack.apm.rum.uxMetrics.noOfLongTasks": "時間がかかるタスク数", - "xpack.apm.rum.uxMetrics.noOfLongTasksTooltip": "長いタスクの数。長いタスクは、UI スレッドを長時間(50 ミリ秒以上)独占し、他の重要なタスク(フレームレートや入力レイテンシ)の実行を妨害するユーザーアクティビティまたはブラウザータスクとして定義されます。", - "xpack.apm.rum.uxMetrics.sumLongTasks": "時間がかかるタスクの合計時間", - "xpack.apm.rum.uxMetrics.sumLongTasksTooltip": "長いタスクの合計時間。長いタスクは、UI スレッドを長時間(50 ミリ秒以上)独占し、他の重要なタスク(フレームレートや入力レイテンシ)の実行を妨害するユーザーアクティビティまたはブラウザータスクとして定義されます。", - "xpack.apm.rum.visitorBreakdown": "アクセスユーザー内訳", - "xpack.apm.rum.visitorBreakdown.browser": "ブラウザー", - "xpack.apm.rum.visitorBreakdown.operatingSystem": "オペレーティングシステム", - "xpack.apm.rum.visitorBreakdownMap.avgPageLoadDuration": "平均ページ読み込み時間", - "xpack.apm.rum.visitorBreakdownMap.pageLoadDurationByRegion": "地域別ページ読み込み時間(平均)", - "xpack.apm.searchInput.filter": "フィルター...", - "xpack.apm.selectPlaceholder": "オプションを選択:", - "xpack.apm.serviceDependencies.breakdownChartTitle": "依存関係にかかった時間", - "xpack.apm.serviceDetails.dependenciesTabLabel": "依存関係", - "xpack.apm.serviceDetails.errorsTabLabel": "エラー", - "xpack.apm.serviceDetails.metrics.cpuUsageChartTitle": "CPU 使用状況", - "xpack.apm.serviceDetails.metrics.errorOccurrencesChart.title": "エラーのオカレンス", - "xpack.apm.serviceDetails.metrics.errorsList.title": "エラー", - "xpack.apm.serviceDetails.metrics.memoryUsageChartTitle": "システムメモリー使用状況", - "xpack.apm.serviceDetails.metricsTabLabel": "メトリック", - "xpack.apm.serviceDetails.nodesTabLabel": "JVM", - "xpack.apm.serviceDetails.overviewTabLabel": "概要", - "xpack.apm.serviceDetails.profilingTabExperimentalDescription": "プロファイリングは実験的機能であり、内部利用専用です。", - "xpack.apm.serviceDetails.profilingTabExperimentalLabel": "実験的", - "xpack.apm.serviceDetails.profilingTabLabel": "プロファイリング", - "xpack.apm.serviceDetails.transactionsTabLabel": "トランザクション", - "xpack.apm.serviceHealthStatus.critical": "重大", - "xpack.apm.serviceHealthStatus.healthy": "正常", - "xpack.apm.serviceHealthStatus.unknown": "不明", - "xpack.apm.serviceHealthStatus.warning": "警告", - "xpack.apm.serviceIcons.cloud": "クラウド", - "xpack.apm.serviceIcons.container": "コンテナー", - "xpack.apm.serviceIcons.service": "サービス", - "xpack.apm.serviceIcons.serviceDetails.cloud.availabilityZoneLabel": "{zones, plural, =other {可用性ゾーン}} ", - "xpack.apm.serviceIcons.serviceDetails.cloud.machineTypesLabel": "{machineTypes, plural, =other {コンピュータータイプ}} ", - "xpack.apm.serviceIcons.serviceDetails.cloud.projectIdLabel": "プロジェクト ID", - "xpack.apm.serviceIcons.serviceDetails.cloud.providerLabel": "クラウドプロバイダー", - "xpack.apm.serviceIcons.serviceDetails.container.containerizedLabel": "コンテナー化", - "xpack.apm.serviceIcons.serviceDetails.container.noLabel": "いいえ", - "xpack.apm.serviceIcons.serviceDetails.container.orchestrationLabel": "オーケストレーション", - "xpack.apm.serviceIcons.serviceDetails.container.osLabel": "OS", - "xpack.apm.serviceIcons.serviceDetails.container.totalNumberInstancesLabel": "インスタンスの合計数", - "xpack.apm.serviceIcons.serviceDetails.container.yesLabel": "はい", - "xpack.apm.serviceIcons.serviceDetails.service.agentLabel": "エージェント名・バージョン", - "xpack.apm.serviceIcons.serviceDetails.service.frameworkLabel": "フレームワーク名", - "xpack.apm.serviceIcons.serviceDetails.service.runtimeLabel": "ランタイム名・バージョン", - "xpack.apm.serviceIcons.serviceDetails.service.versionLabel": "サービスバージョン", - "xpack.apm.serviceInventory.mlNudgeMessageTitle": "異常検知を有効にして、正常性ステータスインジケーターをサービスに追加します", - "xpack.apm.serviceInventory.toastText": "現在 Elastic Stack 7.0+ を実行中で、以前のバージョン 6.x からの互換性のないデータを検知しました。このデータを APM で表示するには、移行が必要です。詳細 ", - "xpack.apm.serviceInventory.toastTitle": "選択された時間範囲内にレガシーデータが検知されました。", - "xpack.apm.serviceInventory.upgradeAssistantLinkText": "アップグレードアシスタント", - "xpack.apm.serviceLogs.noInfrastructureMessage": "表示するログメッセージがありません。", - "xpack.apm.serviceMap.anomalyDetectionPopoverDisabled": "APM 設定で異常検知を有効にすると、サービス正常性インジケーターが表示されます。", - "xpack.apm.serviceMap.anomalyDetectionPopoverLink": "異常を表示", - "xpack.apm.serviceMap.anomalyDetectionPopoverNoData": "選択した時間範囲で、異常スコアを検出できませんでした。異常エクスプローラーで詳細を確認してください。", - "xpack.apm.serviceMap.anomalyDetectionPopoverScoreMetric": "スコア(最大)", - "xpack.apm.serviceMap.anomalyDetectionPopoverTitle": "異常検知", - "xpack.apm.serviceMap.anomalyDetectionPopoverTooltip": "サービス正常性インジケーターは、機械学習の異常検知に基づいています。", - "xpack.apm.serviceMap.avgCpuUsagePopoverStat": "CPU使用状況(平均)", - "xpack.apm.serviceMap.avgMemoryUsagePopoverStat": "メモリー使用状況(平均)", - "xpack.apm.serviceMap.avgReqPerMinutePopoverMetric": "スループット(平均)", - "xpack.apm.serviceMap.avgTransDurationPopoverStat": "レイテンシ(平均)", - "xpack.apm.serviceMap.center": "中央", - "xpack.apm.serviceMap.download": "ダウンロード", - "xpack.apm.serviceMap.emptyBanner.docsLink": "詳細はドキュメントをご覧ください", - "xpack.apm.serviceMap.emptyBanner.message": "接続されているサービスや外部リクエストを検出できる場合、システムはそれらをマップします。最新版の APM エージェントが動作していることを確認してください。", - "xpack.apm.serviceMap.emptyBanner.title": "単一のサービスしかないようです。", - "xpack.apm.serviceMap.errorRatePopoverStat": "失敗したトランザクション率(平均)", - "xpack.apm.serviceMap.focusMapButtonText": "焦点マップ", - "xpack.apm.serviceMap.invalidLicenseMessage": "サービスマップを利用するには、Elastic Platinum ライセンスが必要です。これにより、APM データとともにアプリケーションスタックすべてを可視化することができるようになります。", - "xpack.apm.serviceMap.noServicesPromptDescription": "現在選択されている時間範囲と環境内では、マッピングするサービスが見つかりません。別の範囲を試すか、選択した環境を確認してください。サービスがない場合は、セットアップ手順に従って開始してください。", - "xpack.apm.serviceMap.noServicesPromptTitle": "サービスが利用できません", - "xpack.apm.serviceMap.popover.noDataText": "選択した環境のデータがありません。別の環境に切り替えてください。", - "xpack.apm.serviceMap.resourceCountLabel": "{count}個のリソース", - "xpack.apm.serviceMap.serviceDetailsButtonText": "サービス詳細", - "xpack.apm.serviceMap.subtypePopoverStat": "サブタイプ", - "xpack.apm.serviceMap.timeoutPrompt.docsLink": "APM 設定の詳細については、ドキュメントを参照してください", - "xpack.apm.serviceMap.timeoutPromptDescription": "サービスマップのデータの取得中にタイムアウトしました。時間範囲を狭めて範囲を制限するか、小さい値で構成設定「{configName}」を使用してください。", - "xpack.apm.serviceMap.timeoutPromptTitle": "サービスマップタイムアウト", - "xpack.apm.serviceMap.typePopoverStat": "型", - "xpack.apm.serviceMap.viewFullMap": "サービスの全体マップを表示", - "xpack.apm.serviceMap.zoomIn": "ズームイン", - "xpack.apm.serviceMap.zoomOut": "ズームアウト", - "xpack.apm.serviceNodeMetrics.containerId": "コンテナー ID", - "xpack.apm.serviceNodeMetrics.host": "ホスト", - "xpack.apm.serviceNodeMetrics.serviceName": "サービス名", - "xpack.apm.serviceNodeMetrics.unidentifiedServiceNodesWarningDocumentationLink": "APM Server のドキュメンテーション", - "xpack.apm.serviceNodeMetrics.unidentifiedServiceNodesWarningText": "これらのメトリックが所属する JVM を特定できませんでした。7.5 よりも古い APM Server を実行していることが原因である可能性が高いです。この問題は APM Server 7.5 以降にアップグレードすることで解決されます。アップグレードに関する詳細は、{link} をご覧ください。代わりに Kibana クエリバーを使ってホスト名、コンテナー ID、またはその他フィールドでフィルタリングすることもできます。", - "xpack.apm.serviceNodeMetrics.unidentifiedServiceNodesWarningTitle": "JVM を特定できませんでした", - "xpack.apm.serviceNodeNameMissing": "(空)", - "xpack.apm.serviceOveriew.errorsTableOccurrences": "{occurrencesCount} occ.", - "xpack.apm.serviceOverview.dependenciesTableTabLink": "依存関係を表示", - "xpack.apm.serviceOverview.dependenciesTableTitle": "ダウンストリームサービスとバックエンド", - "xpack.apm.serviceOverview.errorsTableColumnLastSeen": "前回の認識", - "xpack.apm.serviceOverview.errorsTableColumnName": "名前", - "xpack.apm.serviceOverview.errorsTableColumnOccurrences": "オカレンス", - "xpack.apm.serviceOverview.errorsTableLinkText": "エラーを表示", - "xpack.apm.serviceOverview.errorsTableTitle": "エラー", - "xpack.apm.serviceOverview.instancesTable.actionMenus.container.subtitle": "このコンテナーのログとインデックスを表示し、さらに詳細を確認できます。", - "xpack.apm.serviceOverview.instancesTable.actionMenus.container.title": "コンテナーの詳細", - "xpack.apm.serviceOverview.instancesTable.actionMenus.containerLogs": "コンテナーログ", - "xpack.apm.serviceOverview.instancesTable.actionMenus.containerMetrics": "コンテナーメトリック", - "xpack.apm.serviceOverview.instancesTable.actionMenus.filterByInstance": "インスタンスで概要をフィルタリング", - "xpack.apm.serviceOverview.instancesTable.actionMenus.metrics": "メトリック", - "xpack.apm.serviceOverview.instancesTable.actionMenus.pod.subtitle": "このポッドのログとメトリックを表示し、さらに詳細を確認できます。", - "xpack.apm.serviceOverview.instancesTable.actionMenus.pod.title": "ポッドの詳細", - "xpack.apm.serviceOverview.instancesTable.actionMenus.podLogs": "ポッドログ", - "xpack.apm.serviceOverview.instancesTable.actionMenus.podMetrics": "ポッドメトリック", - "xpack.apm.serviceOverview.instancesTableColumnCpuUsage": "CPU使用状況(平均)", - "xpack.apm.serviceOverview.instancesTableColumnErrorRate": "失敗したトランザクション率", - "xpack.apm.serviceOverview.instancesTableColumnMemoryUsage": "メモリー使用状況(平均)", - "xpack.apm.serviceOverview.instancesTableColumnNodeName": "ノード名", - "xpack.apm.serviceOverview.instancesTableColumnThroughput": "スループット", - "xpack.apm.serviceOverview.instancesTableTitle": "インスタンス", - "xpack.apm.serviceOverview.instanceTable.details.cloudTitle": "クラウド", - "xpack.apm.serviceOverview.instanceTable.details.containerTitle": "コンテナー", - "xpack.apm.serviceOverview.instanceTable.details.serviceTitle": "サービス", - "xpack.apm.serviceOverview.latencyChartTitle": "レイテンシ", - "xpack.apm.serviceOverview.latencyChartTitle.prepend": "メトリック", - "xpack.apm.serviceOverview.latencyChartTitle.previousPeriodLabel": "前の期間", - "xpack.apm.serviceOverview.latencyColumnAvgLabel": "レイテンシ(平均)", - "xpack.apm.serviceOverview.latencyColumnDefaultLabel": "レイテンシ", - "xpack.apm.serviceOverview.latencyColumnP95Label": "レイテンシ(95 番目)", - "xpack.apm.serviceOverview.latencyColumnP99Label": "レイテンシ(99 番目)", - "xpack.apm.serviceOverview.mlNudgeMessage.content": "APM の異常検知統合で、異常なトランザクションを特定し、アップストリームおよびダウンストリームサービスの正常性を確認します。わずか数分で開始できます。", - "xpack.apm.serviceOverview.mlNudgeMessage.dismissButton": "閉じる", - "xpack.apm.serviceOverview.mlNudgeMessage.learnMoreButton": "使ってみる", - "xpack.apm.serviceOverview.throughtputChart.previousPeriodLabel": "前の期間", - "xpack.apm.serviceOverview.throughtputChartTitle": "スループット", - "xpack.apm.serviceOverview.tpmHelp": "スループットは1分あたりのトランザクション数(tpm)で測定されます", - "xpack.apm.serviceOverview.transactionsTableColumnErrorRate": "失敗したトランザクション率", - "xpack.apm.serviceOverview.transactionsTableColumnImpact": "インパクト", - "xpack.apm.serviceOverview.transactionsTableColumnName": "名前", - "xpack.apm.serviceOverview.transactionsTableColumnThroughput": "スループット", - "xpack.apm.serviceProfiling.valueTypeLabel.allocObjects": "Alloc. objects", - "xpack.apm.serviceProfiling.valueTypeLabel.allocSpace": "Alloc. space", - "xpack.apm.serviceProfiling.valueTypeLabel.cpuTime": "On-CPU", - "xpack.apm.serviceProfiling.valueTypeLabel.inuseObjects": "使用中のオブジェクト", - "xpack.apm.serviceProfiling.valueTypeLabel.inuseSpace": "使用中のスペース", - "xpack.apm.serviceProfiling.valueTypeLabel.samples": "サンプル", - "xpack.apm.serviceProfiling.valueTypeLabel.unknown": "その他", - "xpack.apm.serviceProfiling.valueTypeLabel.wallTime": "Wall", - "xpack.apm.servicesTable.environmentColumnLabel": "環境", - "xpack.apm.servicesTable.healthColumnLabel": "ヘルス", - "xpack.apm.servicesTable.latencyAvgColumnLabel": "レイテンシ(平均)", - "xpack.apm.servicesTable.metricsExplanationLabel": "これらのメトリックは何か。", - "xpack.apm.servicesTable.nameColumnLabel": "名前", - "xpack.apm.servicesTable.notFoundLabel": "サービスが見つかりません", - "xpack.apm.servicesTable.throughputColumnLabel": "スループット", - "xpack.apm.servicesTable.tooltip.metricsExplanation": "サービスメトリックは、トランザクションタイプ「要求」、「ページ読み込み」、または上位の使用可能なトランザクションタイプのいずれかで集計されます。", - "xpack.apm.servicesTable.transactionColumnLabel": "トランザクションタイプ", - "xpack.apm.servicesTable.transactionErrorRate": "失敗したトランザクション率", - "xpack.apm.settings.agentConfig": "エージェントの編集", - "xpack.apm.settings.agentConfig.createConfigButton.tooltip": "エージェント構成を作成する権限がありません", - "xpack.apm.settings.agentConfig.descriptionText": "APMアプリ内からエージェント構成を微調整してください。変更はAPMエージェントに自動的に伝達されるので、再デプロイする必要はありません。", - "xpack.apm.settings.anomaly_detection.legacy_jobs.body": "以前の統合のレガシー機械学習ジョブが見つかりました。これは、APMアプリでは使用されていません。", - "xpack.apm.settings.anomaly_detection.legacy_jobs.button": "ジョブの確認", - "xpack.apm.settings.anomaly_detection.legacy_jobs.title": "レガシーMLジョブはAPMアプリで使用されていません。", - "xpack.apm.settings.anomalyDetection": "異常検知", - "xpack.apm.settings.anomalyDetection.addEnvironments.cancelButtonText": "キャンセル", - "xpack.apm.settings.anomalyDetection.addEnvironments.createJobsButtonText": "ジョブの作成", - "xpack.apm.settings.anomalyDetection.addEnvironments.descriptionText": "異常検知を有効にするサービス環境を選択してください。異常は選択した環境内のすべてのサービスとトランザクションタイプで表面化します。", - "xpack.apm.settings.anomalyDetection.addEnvironments.selectorLabel": "環境", - "xpack.apm.settings.anomalyDetection.addEnvironments.selectorPlaceholder": "環境を選択または追加", - "xpack.apm.settings.anomalyDetection.addEnvironments.titleText": "環境を選択", - "xpack.apm.settings.anomalyDetection.jobList.actionColumnLabel": "アクション", - "xpack.apm.settings.anomalyDetection.jobList.addEnvironments": "MLジョブを作成", - "xpack.apm.settings.anomalyDetection.jobList.emptyListText": "異常検知ジョブがありません。", - "xpack.apm.settings.anomalyDetection.jobList.environmentColumnLabel": "環境", - "xpack.apm.settings.anomalyDetection.jobList.environments": "環境", - "xpack.apm.settings.anomalyDetection.jobList.failedFetchText": "異常検知ジョブを取得できません。", - "xpack.apm.settings.anomalyDetection.jobList.mlDescriptionText": "異常検知を新しい環境に追加するには、機械学習ジョブを作成します。既存の機械学習ジョブは、{mlJobsLink}で管理できます。", - "xpack.apm.settings.anomalyDetection.jobList.mlDescriptionText.mlJobsLinkText": "機械学習", - "xpack.apm.settings.anomalyDetection.jobList.mlJobLinkText": "MLでジョブを表示", - "xpack.apm.settings.apmIndices.applyButton": "変更を適用", - "xpack.apm.settings.apmIndices.applyChanges.failed.text": "インデックスの適用時に何か問題が発生しました。エラー:{errorMessage}", - "xpack.apm.settings.apmIndices.applyChanges.failed.title": "インデックスが適用できませんでした。", - "xpack.apm.settings.apmIndices.applyChanges.succeeded.text": "インデックスの変更の適用に成功しました。これらの変更は、APM UIで直ちに反映されます。", - "xpack.apm.settings.apmIndices.applyChanges.succeeded.title": "適用されるインデックス", - "xpack.apm.settings.apmIndices.cancelButton": "キャンセル", - "xpack.apm.settings.apmIndices.description": "APM UI は、APM インデックスをクエリするためにインデックスパターンを使用しています。APM Server がイベントを書き込むインデックス名をカスタマイズした場合、APM UI が機能するにはこれらパターンをアップデートする必要がある場合があります。ここの設定は、 kibana.yml で設定されたものよりも優先します。", - "xpack.apm.settings.apmIndices.errorIndicesLabel": "エラーインデックス", - "xpack.apm.settings.apmIndices.helpText": "上書き {configurationName}: {defaultValue}", - "xpack.apm.settings.apmIndices.metricsIndicesLabel": "メトリックインデックス", - "xpack.apm.settings.apmIndices.noPermissionTooltipLabel": "ユーザーロールには、APMインデックスを変更する権限がありません", - "xpack.apm.settings.apmIndices.onboardingIndicesLabel": "オンボーディングインデックス", - "xpack.apm.settings.apmIndices.sourcemapIndicesLabel": "ソースマップインデックス", - "xpack.apm.settings.apmIndices.spanIndicesLabel": "スパンインデックス", - "xpack.apm.settings.apmIndices.title": "インデックス", - "xpack.apm.settings.apmIndices.transactionIndicesLabel": "トランザクションインデックス", - "xpack.apm.settings.createApmPackagePolicy.errorToast.title": "クラウドエージェントポリシーでAPMパッケージポリシーを作成できません", - "xpack.apm.settings.customizeApp": "アプリをカスタマイズ", - "xpack.apm.settings.customizeUI.customLink": "カスタムリンク", - "xpack.apm.settings.customizeUI.customLink.create.failed": "リンクを保存できませんでした!", - "xpack.apm.settings.customizeUI.customLink.create.failed.message": "リンクを保存するときに問題が発生しました。エラー:「{errorMessage}」", - "xpack.apm.settings.customizeUI.customLink.create.successed": "リンクを保存しました。", - "xpack.apm.settings.customizeUI.customLink.createCustomLink": "カスタムリンクを作成", - "xpack.apm.settings.customizeUI.customLink.default.label": "Elastic.co", - "xpack.apm.settings.customizeUI.customLink.default.url": "https://www.elastic.co", - "xpack.apm.settings.customizeUI.customLink.delete": "削除", - "xpack.apm.settings.customizeUI.customLink.delete.failed": "カスタムリンクを削除できませんでした", - "xpack.apm.settings.customizeUI.customLink.delete.successed": "カスタムリンクを削除しました。", - "xpack.apm.settings.customizeUI.customLink.emptyPromptText": "変更しましょう。サービスごとのトランザクションの詳細でアクションコンテキストメニューにカスタムリンクを追加できます。自社のサポートポータルへの役立つリンクを作成するか、新しい不具合レポートを発行します。詳細はドキュメントをご覧ください。", - "xpack.apm.settings.customizeUI.customLink.emptyPromptTitle": "リンクが見つかりません。", - "xpack.apm.settings.customizeUI.customLink.flyout.action.title": "リンク", - "xpack.apm.settings.customizeUI.customLink.flyout.close": "閉じる", - "xpack.apm.settings.customizeUI.customLink.flyout.filters.addAnotherFilter": "別のフィルターを追加", - "xpack.apm.settings.customizeUI.customLink.flyOut.filters.defaultOption": "フィールドを選択してください...", - "xpack.apm.settings.customizeUI.customLink.flyOut.filters.defaultOption.value": "値", - "xpack.apm.settings.customizeUI.customLink.flyout.filters.prepend": "フィールド", - "xpack.apm.settings.customizeUI.customLink.flyout.filters.subtitle": "フィルターオプションを使用すると、特定のサービスについてのみ表示されるようにスコープを設定できます。", - "xpack.apm.settings.customizeUI.customLink.flyout.filters.title": "フィルター", - "xpack.apm.settings.customizeUI.customLink.flyout.label": "リンクは APM アプリ全体にわたるトランザクション詳細のコンテキストで利用できるようになります。作成できるリンクの数は無制限です。トランザクションメタデータのいずれかを使用することで、動的変数を参照して URL を入力できます。さらなる詳細および例がドキュメンテーションに記載されています", - "xpack.apm.settings.customizeUI.customLink.flyout.label.doc": "ドキュメンテーション", - "xpack.apm.settings.customizeUI.customLink.flyout.link.label": "ラベル", - "xpack.apm.settings.customizeUI.customLink.flyout.link.label.helpText": "これはアクションコンテキストメニューに表示されるラベルです。できるだけ短くしてください。", - "xpack.apm.settings.customizeUI.customLink.flyout.link.label.placeholder": "例:サポートチケット", - "xpack.apm.settings.customizeUI.customLink.flyout.link.url": "URL", - "xpack.apm.settings.customizeUI.customLink.flyout.link.url.doc": "詳細はドキュメントをご覧ください。", - "xpack.apm.settings.customizeUI.customLink.flyout.link.url.helpText": "URL にフィールド名変数(例:{sample})を追加すると値を適用できます。", - "xpack.apm.settings.customizeUI.customLink.flyout.link.url.placeholder": "例:https://www.elastic.co/", - "xpack.apm.settings.customizeUI.customLink.flyout.required": "必須", - "xpack.apm.settings.customizeUI.customLink.flyout.save": "保存", - "xpack.apm.settings.customizeUI.customLink.flyout.title": "リンクを作成", - "xpack.apm.settings.customizeUI.customLink.info": "これらのリンクは、トランザクション詳細などによって、アプリの選択した領域にあるアクションコンテキストメニューに表示されます。", - "xpack.apm.settings.customizeUI.customLink.license.text": "カスタムリンクを作成するには、Elastic Gold 以上のライセンスが必要です。適切なライセンスがあれば、カスタムリンクを作成してサービスを分析する際にワークフローを改良できます。", - "xpack.apm.settings.customizeUI.customLink.linkPreview.descrition": "上記のフィルターに基づき、サンプルトランザクションドキュメントの値でリンクをテストしてください。", - "xpack.apm.settings.customizeUI.customLink.noPermissionTooltipLabel": "ユーザーロールには、カスタムリンクを作成する権限がありません", - "xpack.apm.settings.customizeUI.customLink.preview.contextVariable.invalid": "無効な変数が定義されているため、サンプルトランザクションドキュメントが見つかりませんでした。", - "xpack.apm.settings.customizeUI.customLink.preview.contextVariable.noMatch": "{variables} に一致する値がサンプルトランザクションドキュメント内にありませんでした。", - "xpack.apm.settings.customizeUI.customLink.preview.transaction.notFound": "定義されたフィルターに基づき、一致するトランザクションドキュメントが見つかりませんでした。", - "xpack.apm.settings.customizeUI.customLink.previewSectionTitle": "プレビュー", - "xpack.apm.settings.customizeUI.customLink.searchInput.filter": "名前と URL でリンクをフィルタリング...", - "xpack.apm.settings.customizeUI.customLink.table.editButtonDescription": "このカスタムリンクを編集", - "xpack.apm.settings.customizeUI.customLink.table.editButtonLabel": "編集", - "xpack.apm.settings.customizeUI.customLink.table.lastUpdated": "最終更新", - "xpack.apm.settings.customizeUI.customLink.table.name": "名前", - "xpack.apm.settings.customizeUI.customLink.table.noResultFound": "\"{value}\"に対する結果が見つかりませんでした。", - "xpack.apm.settings.customizeUI.customLink.table.url": "URL", - "xpack.apm.settings.indices": "インデックス", - "xpack.apm.settings.schema": "スキーマ", - "xpack.apm.settings.schema.confirm.apmServerSettingsCloudLinkText": "クラウドでAPMサーバー設定に移動", - "xpack.apm.settings.schema.confirm.cancelText": "キャンセル", - "xpack.apm.settings.schema.confirm.checkboxLabel": "データストリームに切り替えることを確認する", - "xpack.apm.settings.schema.confirm.irreversibleWarning.message": "移行中には一時的にAPMデータ収集に影響する可能性があります。移行プロセスは数分で完了します。", - "xpack.apm.settings.schema.confirm.irreversibleWarning.title": "データストリームへの切り替えは元に戻せません。", - "xpack.apm.settings.schema.confirm.switchButtonText": "データストリームに切り替える", - "xpack.apm.settings.schema.confirm.title": "選択内容を確認してください", - "xpack.apm.settings.schema.confirm.unsupportedConfigs.descriptionText": "互換性のあるカスタムapm-server.ymlユーザー設定がFleetサーバー設定に移動されます。削除する前に互換性のない設定について通知されます。", - "xpack.apm.settings.schema.confirm.unsupportedConfigs.title": "次のapm-server.ymlユーザー設定は互換性がないため削除されます", - "xpack.apm.settings.schema.descriptionText.irreversibleEmphasisText": "元に戻せません", - "xpack.apm.settings.schema.descriptionText.superuserEmphasisText": "スーパーユーザー", - "xpack.apm.settings.schema.disabledReason": "データストリームへの切り替えを使用できません: {reasons}", - "xpack.apm.settings.schema.disabledReason.cloudApmMigrationEnabled": "クラウド移行が有効ではありません", - "xpack.apm.settings.schema.disabledReason.hasCloudAgentPolicy": "クラウドエージェントポリシーが存在しません", - "xpack.apm.settings.schema.disabledReason.hasRequiredRole": "ユーザーにはスーパーユーザーロールがありません", - "xpack.apm.settings.schema.migrate.classicIndices.currentSetup": "現在の設定", - "xpack.apm.settings.schema.migrate.classicIndices.description": "現在、データのクラシックAPMインデックスを使用しています。このデータスキーマは廃止予定であり、Elastic Stackバージョン8.0でデータストリームに置換されます。", - "xpack.apm.settings.schema.migrate.classicIndices.title": "クラシックAPMインデックス", - "xpack.apm.settings.schema.migrate.dataStreams.buttonText": "データストリームに切り替える", - "xpack.apm.settings.schema.migrate.dataStreams.description": "今後、新しく取り込まれたデータはすべてデータストリームに格納されます。以前に取り込まれたデータはクラシックAPMインデックスに残ります。APMおよびUXアプリは引き続き両方のインデックスをサポートします。", - "xpack.apm.settings.schema.migrate.dataStreams.title": "データストリーム", - "xpack.apm.settings.schema.migrationInProgressPanelDescription": "古いAPMサーバーインスタンスのシャットダウン中に新しいAPMサーバーを含めるFleetサーバーインスタンスを作成しています。数分以内にデータがもう一度アプリに取り込まれます。", - "xpack.apm.settings.schema.migrationInProgressPanelTitle": "データストリームに切り替え中...", - "xpack.apm.settings.schema.success.description": "APM統合が設定されました。現在導入されているエージェントからデータを受信できます。統合に適用されたポリシーは自由に確認できます。", - "xpack.apm.settings.schema.success.returnText": "あるいは、{serviceInventoryLink}に戻ることができます。", - "xpack.apm.settings.schema.success.returnText.serviceInventoryLink": "サービスインベントリ", - "xpack.apm.settings.schema.success.title": "データストリームが正常に設定されました。", - "xpack.apm.settings.schema.success.viewIntegrationInFleet.buttonText": "FleetでAPM統合を表示", - "xpack.apm.settings.title": "設定", - "xpack.apm.settings.unsupportedConfigs.errorToast.title": "APMサーバー設定を取り込めません", - "xpack.apm.settingsLinkLabel": "設定", - "xpack.apm.setupInstructionsButtonLabel": "セットアップの手順", - "xpack.apm.stacktraceTab.causedByFramesToogleButtonLabel": "作成元", - "xpack.apm.stacktraceTab.localVariablesToogleButtonLabel": "ローカル変数", - "xpack.apm.stacktraceTab.noStacktraceAvailableLabel": "利用可能なスタックトレースがありません。", - "xpack.apm.timeComparison.label": "比較", - "xpack.apm.timeComparison.select.dayBefore": "前の日", - "xpack.apm.timeComparison.select.weekBefore": "前の週", - "xpack.apm.toggleHeight.showLessButtonLabel": "表示する行数を減らす", - "xpack.apm.toggleHeight.showMoreButtonLabel": "表示する行数を増やす", - "xpack.apm.tracesTable.avgResponseTimeColumnLabel": "レイテンシ(平均)", - "xpack.apm.tracesTable.impactColumnDescription": "ご利用のサービスで最も頻繁に使用されていて、最も遅いエンドポイントです。レイテンシとスループットを乗算した結果です", - "xpack.apm.tracesTable.impactColumnLabel": "インパクト", - "xpack.apm.tracesTable.nameColumnLabel": "名前", - "xpack.apm.tracesTable.notFoundLabel": "このクエリのトレースが見つかりません", - "xpack.apm.tracesTable.originatingServiceColumnLabel": "発生元サービス", - "xpack.apm.tracesTable.tracesPerMinuteColumnLabel": "1 分あたりのトレース", - "xpack.apm.transactionActionMenu.actionsButtonLabel": "調査", - "xpack.apm.transactionActionMenu.container.subtitle": "このコンテナーのログとインデックスを表示し、さらに詳細を確認できます。", - "xpack.apm.transactionActionMenu.container.title": "コンテナーの詳細", - "xpack.apm.transactionActionMenu.customLink.section": "カスタムリンク", - "xpack.apm.transactionActionMenu.customLink.showAll": "すべて表示", - "xpack.apm.transactionActionMenu.customLink.showFewer": "簡易表示", - "xpack.apm.transactionActionMenu.customLink.subtitle": "リンクは新しいウィンドウで開きます。", - "xpack.apm.transactionActionMenu.host.subtitle": "ホストログとメトリックを表示し、さらに詳細を確認できます。", - "xpack.apm.transactionActionMenu.host.title": "ホストの詳細", - "xpack.apm.transactionActionMenu.pod.subtitle": "このポッドのログとメトリックを表示し、さらに詳細を確認できます。", - "xpack.apm.transactionActionMenu.pod.title": "ポッドの詳細", - "xpack.apm.transactionActionMenu.showContainerLogsLinkLabel": "コンテナーログ", - "xpack.apm.transactionActionMenu.showContainerMetricsLinkLabel": "コンテナーメトリック", - "xpack.apm.transactionActionMenu.showHostLogsLinkLabel": "ホストログ", - "xpack.apm.transactionActionMenu.showHostMetricsLinkLabel": "ホストメトリック", - "xpack.apm.transactionActionMenu.showPodLogsLinkLabel": "ポッドログ", - "xpack.apm.transactionActionMenu.showPodMetricsLinkLabel": "ポッドメトリック", - "xpack.apm.transactionActionMenu.showTraceLogsLinkLabel": "トレースログ", - "xpack.apm.transactionActionMenu.status.subtitle": "ステータスを表示し、さらに詳細を確認できます。", - "xpack.apm.transactionActionMenu.status.title": "ステータスの詳細", - "xpack.apm.transactionActionMenu.trace.subtitle": "トレースログを表示し、さらに詳細を確認できます。", - "xpack.apm.transactionActionMenu.trace.title": "トレースの詳細", - "xpack.apm.transactionActionMenu.viewInUptime": "ステータス", - "xpack.apm.transactionActionMenu.viewSampleDocumentLinkLabel": "サンプルドキュメントを表示", - "xpack.apm.transactionBreakdown.chartTitle": "スパンタイプ別時間", - "xpack.apm.transactionDetails.clearSelectionAriaLabel": "選択した項目をクリア", - "xpack.apm.transactionDetails.distribution.panelTitle": "レイテンシ分布", - "xpack.apm.transactionDetails.emptySelectionText": "クリックおよびドラッグして範囲を選択", - "xpack.apm.transactionDetails.noTraceParentButtonTooltip": "トレースの親が見つかりませんでした", - "xpack.apm.transactionDetails.percentOfTraceLabelExplanation": "{parentType, select, transaction {トランザクション} trace {トレース} }の割合が100%を超えています。これは、この{childType, select, span {スパン} transaction {トランザクション} }がルートトランザクションよりも時間がかかるためです。", - "xpack.apm.transactionDetails.requestMethodLabel": "リクエストメソッド", - "xpack.apm.transactionDetails.resultLabel": "結果", - "xpack.apm.transactionDetails.serviceLabel": "サービス", - "xpack.apm.transactionDetails.servicesTitle": "サービス", - "xpack.apm.transactionDetails.spanFlyout.backendLabel": "バックエンド", - "xpack.apm.transactionDetails.spanFlyout.compositeExampleWarning": "これは連続した類似したスパンのグループのサンプルドキュメントです", - "xpack.apm.transactionDetails.spanFlyout.databaseStatementTitle": "データベースステートメント", - "xpack.apm.transactionDetails.spanFlyout.nameLabel": "名前", - "xpack.apm.transactionDetails.spanFlyout.spanAction": "アクション", - "xpack.apm.transactionDetails.spanFlyout.spanDetailsTitle": "スパン詳細", - "xpack.apm.transactionDetails.spanFlyout.spanSubtype": "サブタイプ", - "xpack.apm.transactionDetails.spanFlyout.spanType": "型", - "xpack.apm.transactionDetails.spanFlyout.spanType.navigationTimingLabel": "ナビゲーションタイミング", - "xpack.apm.transactionDetails.spanFlyout.stackTraceTabLabel": "スタックトレース", - "xpack.apm.transactionDetails.spanFlyout.viewSpanInDiscoverButtonLabel": "Discover でスパンを表示", - "xpack.apm.transactionDetails.spanTypeLegendTitle": "型", - "xpack.apm.transactionDetails.statusCode": "ステータスコード", - "xpack.apm.transactionDetails.syncBadgeAsync": "非同期", - "xpack.apm.transactionDetails.syncBadgeBlocking": "ブロック", - "xpack.apm.transactionDetails.tabs.failedTransactionsCorrelationsBetaDescription": "失敗したトランザクション率はGAではありません。不具合が発生したら報告してください。", - "xpack.apm.transactionDetails.tabs.failedTransactionsCorrelationsBetaLabel": "ベータ", - "xpack.apm.transactionDetails.tabs.failedTransactionsCorrelationsBetaTitle": "失敗したトランザクション率", - "xpack.apm.transactionDetails.tabs.failedTransactionsCorrelationsLabel": "失敗したトランザクションの相関関係", - "xpack.apm.transactionDetails.tabs.latencyLabel": "遅延の相関関係", - "xpack.apm.transactionDetails.tabs.traceSamplesLabel": "トレースのサンプル", - "xpack.apm.transactionDetails.traceNotFound": "選択されたトレースが見つかりません", - "xpack.apm.transactionDetails.traceSampleTitle": "トレースのサンプル", - "xpack.apm.transactionDetails.transactionLabel": "トランザクション", - "xpack.apm.transactionDetails.transFlyout.callout.agentDroppedSpansMessage": "このトランザクションを報告した APM エージェントが、構成に基づき {dropped} 個以上のスパンをドロップしました。", - "xpack.apm.transactionDetails.transFlyout.callout.learnMoreAboutDroppedSpansLinkText": "ドロップされたスパンの詳細。", - "xpack.apm.transactionDetails.transFlyout.transactionDetailsTitle": "トランザクションの詳細", - "xpack.apm.transactionDetails.userAgentAndVersionLabel": "ユーザーエージェントとバージョン", - "xpack.apm.transactionDetails.viewFullTraceButtonLabel": "完全なトレースを表示", - "xpack.apm.transactionDetails.viewingFullTraceButtonTooltip": "現在完全なトレースが表示されています", - "xpack.apm.transactionDistribution.chart.allTransactionsLabel": "すべてのトランザクション", - "xpack.apm.transactionDistribution.chart.currentTransactionMarkerLabel": "現在のサンプル", - "xpack.apm.transactionDistribution.chart.numberOfTransactionsLabel": "# トランザクション", - "xpack.apm.transactionDurationAlert.aggregationType.95th": "95 パーセンタイル", - "xpack.apm.transactionDurationAlert.aggregationType.99th": "99 パーセンタイル", - "xpack.apm.transactionDurationAlert.aggregationType.avg": "平均", - "xpack.apm.transactionDurationAlert.name": "レイテンシしきい値", - "xpack.apm.transactionDurationAlertTrigger.ms": "ms", - "xpack.apm.transactionDurationAlertTrigger.when": "タイミング", - "xpack.apm.transactionDurationAnomalyAlert.name": "レイテンシ異常値", - "xpack.apm.transactionDurationAnomalyAlertTrigger.anomalySeverity": "異常と重要度があります", - "xpack.apm.transactionDurationLabel": "期間", - "xpack.apm.transactionErrorRateAlert.name": "失敗したトランザクション率しきい値", - "xpack.apm.transactionErrorRateAlertTrigger.isAbove": "より大きい", - "xpack.apm.transactionRateLabel": "{displayedValue} tpm", - "xpack.apm.transactions.latency.chart.95thPercentileLabel": "95 パーセンタイル", - "xpack.apm.transactions.latency.chart.99thPercentileLabel": "99 パーセンタイル", - "xpack.apm.transactions.latency.chart.averageLabel": "平均", - "xpack.apm.tutorial.agent_config.choosePolicy.helper": "選択したポリシー構成を下のスニペットに追加します。", - "xpack.apm.tutorial.agent_config.choosePolicyLabel": "ポリシーを選択", - "xpack.apm.tutorial.agent_config.defaultStandaloneConfig": "デフォルトのダッシュボード構成", - "xpack.apm.tutorial.agent_config.fleetPoliciesLabel": "Fleetポリシー", - "xpack.apm.tutorial.agent_config.getStartedWithFleet": "Fleetの基本", - "xpack.apm.tutorial.agent_config.manageFleetPolicies": "Fleetポリシーの管理", - "xpack.apm.tutorial.apmAgents.statusCheck.btnLabel": "エージェントステータスを確認", - "xpack.apm.tutorial.apmAgents.statusCheck.errorMessage": "エージェントからまだデータを受け取っていません", - "xpack.apm.tutorial.apmAgents.statusCheck.successMessage": "1 つまたは複数のエージェントからデータを受け取りました", - "xpack.apm.tutorial.apmAgents.statusCheck.text": "アプリケーションが実行されていてエージェントがデータを送信していることを確認してください。", - "xpack.apm.tutorial.apmAgents.statusCheck.title": "エージェントステータス", - "xpack.apm.tutorial.apmAgents.title": "APM エージェント", - "xpack.apm.tutorial.apmServer.callOut.message": "ご使用の APM Server を 7.0 以上に更新してあることを確認してください。 Kibana の管理セクションにある移行アシスタントで 6.x データを移行することもできます。", - "xpack.apm.tutorial.apmServer.callOut.title": "重要:7.0 以上に更新中", - "xpack.apm.tutorial.apmServer.fleet.apmIntegration.button": "APM統合", - "xpack.apm.tutorial.apmServer.fleet.manageApmIntegration.button": "FleetでAPM統合を管理", - "xpack.apm.tutorial.apmServer.fleet.message": "APMA統合は、APMデータ用にElasticsearchテンプレートとIngest Nodeパイプラインをインストールします。", - "xpack.apm.tutorial.apmServer.statusCheck.btnLabel": "APM Server ステータスを確認", - "xpack.apm.tutorial.apmServer.statusCheck.errorMessage": "APM Server が検出されました。7.0 以上に更新され、動作中であることを確認してください。", - "xpack.apm.tutorial.apmServer.statusCheck.successMessage": "APM Server が正しくセットアップされました", - "xpack.apm.tutorial.apmServer.statusCheck.text": "APM エージェントの導入を開始する前に、APM Server が動作していることを確認してください。", - "xpack.apm.tutorial.apmServer.statusCheck.title": "APM Server ステータス", - "xpack.apm.tutorial.apmServer.title": "APM Server", - "xpack.apm.tutorial.djangoClient.configure.commands.addAgentComment": "インストールされたアプリにエージェントを追加します", - "xpack.apm.tutorial.djangoClient.configure.commands.addTracingMiddlewareComment": "パフォーマンスメトリックを送信するには、追跡ミドルウェアを追加します。", - "xpack.apm.tutorial.djangoClient.configure.commands.allowedCharactersComment": "a-z、A-Z、0-9、-、_、スペース", - "xpack.apm.tutorial.djangoClient.configure.commands.setCustomApmServerUrlComment": "カスタム APM Server URL(デフォルト:{defaultApmServerUrl})を設定します", - "xpack.apm.tutorial.djangoClient.configure.commands.setRequiredServiceNameComment": "任意のサービス名を設定します。使用できる文字:", - "xpack.apm.tutorial.djangoClient.configure.commands.setServiceEnvironmentComment": "サービス環境を設定します", - "xpack.apm.tutorial.djangoClient.configure.commands.useIfApmServerRequiresTokenComment": "APM Server でシークレットトークンが必要な場合に使います", - "xpack.apm.tutorial.djangoClient.configure.textPost": "高度な用途に関しては[ドキュメンテーション]({documentationLink})を参照してください。", - "xpack.apm.tutorial.djangoClient.configure.textPre": "エージェントとは、アプリケーションプロセス内で実行されるライブラリです。APM サービスは「SERVICE_NAME」に基づいてプログラムで作成されます。", - "xpack.apm.tutorial.djangoClient.configure.title": "エージェントの構成", - "xpack.apm.tutorial.djangoClient.install.textPre": "Python 用の APM エージェントを依存関係としてインストールします。", - "xpack.apm.tutorial.djangoClient.install.title": "APM エージェントのインストール", - "xpack.apm.tutorial.dotNetClient.configureAgent.textPost": "エージェントに「IConfiguration」インスタンスが渡されていない場合、(例:非 ASP.NET Core アプリケーションの場合)、エージェントを環境変数で構成することもできます。\n 高度な用途に関しては[ドキュメンテーション]({documentationLink})を参照してください。", - "xpack.apm.tutorial.dotNetClient.configureAgent.title": "appsettings.json ファイルの例:", - "xpack.apm.tutorial.dotNetClient.configureApplication.textPost": "「IConfiguration」インスタンスを渡すのは任意であり、これにより、エージェントはこの「IConfiguration」インスタンス(例:「appsettings.json」ファイル)から構成を読み込みます。", - "xpack.apm.tutorial.dotNetClient.configureApplication.textPre": "「Elastic.Apm.NetCoreAll」パッケージの ASP.NET Core の場合、「Startup.cs」ファイル内の「Configure」メソドの「UseElasticApm」メソドを呼び出します。", - "xpack.apm.tutorial.dotNetClient.configureApplication.title": "エージェントをアプリケーションに追加", - "xpack.apm.tutorial.dotNetClient.download.textPre": "[NuGet]({allNuGetPackagesLink}) から.NETアプリケーションにエージェントパッケージを追加してください。用途の異なる複数の NuGet パッケージがあります。\n\nEntity Framework CoreのASP.NET Coreアプリケーションの場合は、[Elastic.Apm.NetCoreAll]({netCoreAllApmPackageLink})パッケージをダウンロードしてください。このパッケージは、自動的にすべてのエージェントコンポーネントをアプリケーションに追加します。\n\n 依存性を最低限に抑えたい場合、ASP.NET Coreの監視のみに[Elastic.Apm.AspNetCore]({aspNetCorePackageLink})パッケージ、またはEntity Framework Coreの監視のみに[Elastic.Apm.EfCore]({efCorePackageLink})パッケージを使用することができます。\n\n 手動インストルメンテーションのみにパブリックAgent APIを使用する場合は、[Elastic.Apm]({elasticApmPackageLink})パッケージを使用してください。", - "xpack.apm.tutorial.dotNetClient.download.title": "APM エージェントのダウンロード", - "xpack.apm.tutorial.downloadServer.title": "APM Server をダウンロードして展開します", - "xpack.apm.tutorial.downloadServerRpm": "32 ビットパッケージをお探しですか?[ダウンロードページ]({downloadPageLink})をご覧ください。", - "xpack.apm.tutorial.downloadServerTitle": "32 ビットパッケージをお探しですか?[ダウンロードページ]({downloadPageLink})をご覧ください。", - "xpack.apm.tutorial.editConfig.textPre": "Elastic Stack の X-Pack セキュアバージョンをご使用の場合、「apm-server.yml」構成ファイルで認証情報を指定する必要があります。", - "xpack.apm.tutorial.editConfig.title": "構成を編集する", - "xpack.apm.tutorial.elasticCloud.textPre": "APMサーバーを有効にするには、](https://cloud.elastic.co/deployments/{deploymentId}/edit)Elastic Cloudコンソール[に移動し、デプロイ設定でAPMを有効にします。有効になったら、このページを更新してください。", - "xpack.apm.tutorial.elasticCloudInstructions.title": "APM エージェント", - "xpack.apm.tutorial.flaskClient.configure.commands.allowedCharactersComment": "a-z、A-Z、0-9、-、_、スペース", - "xpack.apm.tutorial.flaskClient.configure.commands.configureElasticApmComment": "またはアプリケーションの設定で ELASTIC_APM を使用するよう構成します。", - "xpack.apm.tutorial.flaskClient.configure.commands.initializeUsingEnvironmentVariablesComment": "環境変数を使用して初期化します", - "xpack.apm.tutorial.flaskClient.configure.commands.setCustomApmServerUrlComment": "カスタム APM Server URL(デフォルト:{defaultApmServerUrl})を設定します", - "xpack.apm.tutorial.flaskClient.configure.commands.setRequiredServiceNameComment": "任意のサービス名を設定します。使用できる文字:", - "xpack.apm.tutorial.flaskClient.configure.commands.setServiceEnvironmentComment": "サービス環境を設定します", - "xpack.apm.tutorial.flaskClient.configure.commands.useIfApmServerRequiresTokenComment": "APM Server でシークレットトークンが必要な場合に使います", - "xpack.apm.tutorial.flaskClient.configure.textPost": "高度な用途に関しては[ドキュメンテーション]({documentationLink})を参照してください。", - "xpack.apm.tutorial.flaskClient.configure.textPre": "エージェントとは、アプリケーションプロセス内で実行されるライブラリです。APM サービスは「SERVICE_NAME」に基づいてプログラムで作成されます。", - "xpack.apm.tutorial.flaskClient.configure.title": "エージェントの構成", - "xpack.apm.tutorial.flaskClient.install.textPre": "Python 用の APM エージェントを依存関係としてインストールします。", - "xpack.apm.tutorial.flaskClient.install.title": "APM エージェントのインストール", - "xpack.apm.tutorial.goClient.configure.commands.initializeUsingEnvironmentVariablesComment": "環境変数を使用して初期化します:", - "xpack.apm.tutorial.goClient.configure.commands.setCustomApmServerUrlComment": "カスタム APM Server URL(デフォルト:{defaultApmServerUrl})を設定します", - "xpack.apm.tutorial.goClient.configure.commands.setServiceEnvironment": "サービス環境を設定します", - "xpack.apm.tutorial.goClient.configure.commands.setServiceNameComment": "サービス名を設定します。使用できる文字は # a-z、A-Z、0-9、-、_、スペースです。", - "xpack.apm.tutorial.goClient.configure.commands.usedExecutableNameComment": "ELASTIC_APM_SERVICE_NAME が指定されていない場合、実行ファイルの名前が使用されます。", - "xpack.apm.tutorial.goClient.configure.commands.useIfApmRequiresTokenComment": "APM Server でシークレットトークンが必要な場合に使います", - "xpack.apm.tutorial.goClient.configure.textPost": "高度な構成に関しては[ドキュメンテーション]({documentationLink})を参照してください。", - "xpack.apm.tutorial.goClient.configure.textPre": "エージェントとは、アプリケーションプロセス内で実行されるライブラリです。APM サービスは実行ファイル名または「ELASTIC_APM_SERVICE_NAME」環境変数に基づいてプログラムで作成されます。", - "xpack.apm.tutorial.goClient.configure.title": "エージェントの構成", - "xpack.apm.tutorial.goClient.install.textPre": "Go の APM エージェントパッケージをインストールします。", - "xpack.apm.tutorial.goClient.install.title": "APM エージェントのインストール", - "xpack.apm.tutorial.goClient.instrument.textPost": "Goのソースコードのインストルメンテーションの詳細ガイドは、[ドキュメンテーション]({documentationLink})をご参照ください。", - "xpack.apm.tutorial.goClient.instrument.textPre": "提供されたインストルメンテーションモジュールの 1 つ、またはトレーサー API を直接使用して、Go アプリケーションにインストルメンテーションを設定します。", - "xpack.apm.tutorial.goClient.instrument.title": "アプリケーションのインストルメンテーション", - "xpack.apm.tutorial.introduction": "アプリケーション内から詳細なパフォーマンスメトリックやエラーを収集します。", - "xpack.apm.tutorial.javaClient.download.textPre": "[Maven Central]({mavenCentralLink})からエージェントジャーをダウンロードします。アプリケーションにエージェントを依存関係として「追加しない」でください。", - "xpack.apm.tutorial.javaClient.download.title": "APM エージェントのダウンロード", - "xpack.apm.tutorial.javaClient.startApplication.textPost": "構成オプションと高度な用途に関しては、[ドキュメンテーション]({documentationLink})をご覧ください。", - "xpack.apm.tutorial.javaClient.startApplication.textPre": "「-javaagent」フラグを追加し、システムプロパティを使用してエージェントを構成します。\n\n * 任意のサービス名を設定します(使用可能な文字は a-z、A-Z、0-9、-、_、スペースです)\n * カスタム APM Server URL(デフォルト:{customApmServerUrl})を設定します\n * APM Server シークレットトークンを設定します\n * サービス環境を設定します\n * アプリケーションのベースパッケージを設定します", - "xpack.apm.tutorial.javaClient.startApplication.title": "javaagent フラグでアプリケーションを起動", - "xpack.apm.tutorial.jsClient.enableRealUserMonitoring.textPre": "デフォルトでは、APM Server を実行すると RUM サポートは無効になります。RUMサポートを有効にする手順については、[ドキュメンテーション]({documentationLink})をご覧ください。", - "xpack.apm.tutorial.jsClient.enableRealUserMonitoring.title": "APM Server のリアルユーザー監視サポートを有効にする", - "xpack.apm.tutorial.jsClient.installDependency.commands.setCustomApmServerUrlComment": "カスタム APM Server URL(デフォルト:{defaultApmServerUrl})を設定します", - "xpack.apm.tutorial.jsClient.installDependency.commands.setRequiredServiceNameComment": "任意のサービス名を設定します(使用可能な文字は a-z、A-Z、0-9、-、_、スペースです)", - "xpack.apm.tutorial.jsClient.installDependency.commands.setServiceEnvironmentComment": "サービス環境を設定します", - "xpack.apm.tutorial.jsClient.installDependency.commands.setServiceVersionComment": "サービスバージョンを設定します(ソースマップ機能に必要)", - "xpack.apm.tutorial.jsClient.installDependency.textPost": "React や Angular などのフレームワーク統合には、カスタム依存関係があります。詳細は[統合ドキュメント]({docLink})をご覧ください。", - "xpack.apm.tutorial.jsClient.installDependency.textPre": "「npm install @elastic/apm-rum --save」でエージェントをアプリケーションへの依存関係としてインストールできます。\n\nその後で以下のようにアプリケーションでエージェントを初期化して構成できます。", - "xpack.apm.tutorial.jsClient.installDependency.title": "エージェントを依存関係としてセットアップ", - "xpack.apm.tutorial.jsClient.scriptTags.textPre": "または、スクリプトタグを使用してエージェントのセットアップと構成ができます。` を追加

    37Q4wHUx0 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 diff --git a/docs/management/snapshot-restore/images/snapshot-restore.png b/docs/management/snapshot-restore/images/snapshot-restore.png deleted file mode 100644 index 8ca5dc95e5892691497c4a4e9ec803e0fecbbe03..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 123854 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 DdXIyWq@QLXU9Gb@KgHXwqSEs<=q(kn!zo_ig>a zcsjox`IEnI4b@ccO9pFzlZk?;(2sqy9z1i-cKf+*-fr@?b2&mc&{bLx9qO(o_n^s6 znTD3f|3o|eWZ`~nKbdO~(j3n0!$3_5w-8m z(H3^|KQGk~ya!Y@c&D=!L(Y5iEM}Gajn(LIiYRwcY)!U%;dJxCh1ZXl-zN3E zXW8QUElssb;h&qurP|RgeEbt*^@7PZt@n#Wzy~A5bj4qkUT5PAsFQh#2g8kodaVN! zT)W9Gv>RQcX%-igno7J}7YF9pSo0+)Mn*u0D#Buif?h9^)`k?u2o<1k-f+N>b}`%#_RP?mQp z>XlWwk~BZ=1eY1Es;}e-H*Ox(QqBJqZX&#GHG4*H;OEI81`S_88F$#1Q2+Yj(SdF) zNedR8d@kUBiDmNxJGAHxw96s2>+*NFaf*lJds&Sq z;~1#LWeKfc&!m#Yw?y#`AP=7Sg1InKJ}qc+F~-i%idlENxL15=kt!J`vjbn}POgRz z5wM?Rj6wuq4Y=i1q9*BFpA?!Ua>7P`a#6jSWSd%GWfhOj)_ySM{pyPleGN_iRsglf zE-)4gyI9N|Dy3!X*00yAcWiF#j%g?_nF|pbs@-eeN&QEKGs5}7;d~si>kX3oIY~gqd(N9#DGF|0Vql+ zas`JTp+0xXN^D4$&^jM21Yz5mA@?J#Jb(Y=Oz{|C7-uWJLY`woeYu{c%0=1jq2`wC z5&1efXMWL9H7_C1cpyr)SYM(U=hEyv;wXHJhsh$a)mzT7;q}w7-FBvgSKG;=H*9-U zUec-U3-I{j7y|or-1cEK1?Cuy!x?LLO^+HLMKA83(hA*~5Vb`)E@>T!h0p1cyu78p z2~l*MS5cVyRmUO<*Sup7_%4#TIWr3&1!N-ga2>Urh8q|q)<9y>&+@g(1<+swO z7%khK$^&aKz;NhAhK>5ANv|0zeGUV_3I@GK`mXrmFMiRSn6TF8Bl<_JCF68}b63UqQKGh) zV=~u>gt6|hy6gYkM88*b2;-AR+O{Tmp zN<0cSSkcbY(I?}hJXH_i+eGl!O;j;6DTvI9Tu;YFoJnXlbircbkDpW@J?xW{VYivl zKwk8dF34nMkJ)O(=A@+;3h2v1 zR>LFNH7BWD__m&Yk03kcM9o*Fp~Aj&Th3&2Y4S@o6PTU;z6*fL4@c5GJiao$fh421 zMz5S9PRCXpqEUQ0V7JF?YawDmwZm(Co{uW;aLU+N&QcO>zbemzhQtO-H4F*f7k14i zG5RDm+D%m43y}am6&t?uIXGVph6ZT$ZhNb+$g(FP%-#~8bFQh!G)Lhx^EgP0vNjqJ z?*)HhvPX`k&k7tzheuyi+jr|{QqYJ)YEOA$p_px)C>rfbHTuAWuA;byos()W0!$$p zN9vr_E$~HJHJpE#Rsz2FU+$_obnKE#K|-yg%kd8C`XHMf3`K2BOt^-o%W&=O@~>tX z5Pdz(umd*mu5`I)I21LHZ%4S?uTat3#jr zNBK>ln9Q5>ndfQ3A=PSX3Dz~Dna0r&^6FGHzgXj;ZSP@ko z2hk3@lE%9?|A3GZ)Tapzxv+NFhURg$6?I zjPlcPgV@OtgnGM^urCb7upOq;yIZ1Nf*2PT%dXtmL>NQJyGB5x-I#_%G9)*7dwqe% zTq@3%lNm59=MtYR{T^-t`nXkxT92}%)9pyf(%?K#Lpquis*z2|=1Tu(uXp&WjcqVU ziKrbR8^ph&>f{ZGlN2NY%k=(J|;f`#Nu1^dj@_ z)aP4lYD)-iSvZ#B-V2gz%Ft)Q9Y5*3{>6;Wg(d0la*H4=xw+KZ4I$uu&_B1|(DLm5 z^m*qk<<@Nf9{vX46A!H+q>IH2i9_F7B|C==Jm`pSTrP`UuD)x|0@qHsXnn%3ZBZ1M zLX_N#PIrEBvDYlW7wDp-WILvLSdbrN4;4PjQ3(IF|&@Vz?9QQ-t(eNSlis+gxrKCc5IeP~)K+oQLHVYWIf2@)d25Q3Yq za=(nZfhsmJJ@NGVgs~rX-wG0vK3BAJZRkul$Tl?BO+gnSJ}Wy9i0FUJSkZV5jS(gE zBr)J(X&6$Y{jSR5>*mlAWAycC6d0A41CDSnhvOyYR97qw6;B%WoK55H{!!R#eV-Pt zF`_7hkR@wc`}|7Cr0)FaqWtVIuZ0=%1xxbKBOY>IL=>8-d=d%_eTES41Hck*OKAqI z<_Gl3;?t*)cjYEAgWdm%Wqn&WvcksAuK8>=LKFj$$P*o1(Y=5phb&W1NR89;{J)_4^eEKH+e`DwGxv5paGgsXzj%g zF75dBxjN&WKP~E4rEZ=lZ91=+J|T#XaCe7uz0E;UQ}5PLdFUOAnwiK1j84;iM)DVc ztdvjc?H!gX=`+!c$oBJ*j-WKG6zu%dPom0B9xBa+vB0$_Zs=MzNA#Y$R=04#+P*Us z(o6yS{X(ux*)LI(#tdxMX&Cg`1dRiH(dB9da39Qc#9Pd_3Wy7cH3RS3mL8foohLWo zVZO&|r@I-o#+*^HQ+qWVa~De=SOwwpNz1+P2)F!Y1tL@(w!-M_7=;t$^$&!KJA|Tpxo0_2gJZQX6 z$0_yE>ji4*x&dws5+BK;h(;ic>Edb2eHx$Z&Hbgfo{f@}vz_-W+n!8WOEy!M$}nZWs~Bw4Dt7~!6p1D_HOXv2Z#T#BC7zFY zR!G^Ib)0Q_xlT*PhZ^=A8Zy7lP_PRc`&0fX>Z0KkMK<`KqF<%;0S_nb3s$xO_OH zV_?j$IVO^VaWQ>3^V7{yE=qwJdv-5n3GkCHVbGS^AhUbIVkh~W>o+5i3LAKeO{9d`>U;>SAfz$-ax z$bBm&8I#-IDaW-3E6eYr5lEqZUX@5oV4eB5%uRkesPF#P4Z#r$`zz+sKT)BcVzPm` zJQ;aL&c8scG~`a|^8-b8Lv~7q-JlbPHc&Gbk!`|8Zr&e_sO1{;W2)+?T2T)&{EclR zp408#PFgPVrBBWPvDone&$lLHB$1GCIv;FuTW{F0nZZFaKE?f~SM%Rr`yV0Ny5pUR z;wp{{S?3Vh;%c@p@};u1$DN;(UEYH_zCL2c?u-jCyAt6kS=D#%fBA-Y#3GTFJ1@`< z-lFhs+Un?^HC^NB2?j-btvxEJ0&f4S7p};l0seY}=!kL@K8hM{V-eD3)`1KJ0Fto2 z8|pov$Faf>#)zzsDC65zguxSNp);}Dn~f!cyq@-y_2 zyY=8KXfB5)v3K(WpD$?-&pv0JWZ;K*=(M7#8q4{=KUuY?>;}soK`BGyTA%&3vg%S9 zOK~sDFnexnznLXPC;Z_5Veh@enq0Rz$+Ax)UXhs zWTK_)UTr>`NRw29-c}=h%2!0krB%U#Bcz>Fr2|Yl(T6d)KuH>qQ=I+eA|nk6F2=C> z%Q%HQ9e^T!q8!5khL-xjpQiVFp&Vd-qvwEH=qUFKBi~l>r$@We#rgbI-iMKz8j?71 zJK6U`(X=+B4!FSQ$Mm-kmW7W!uLmQPdBik^S zd8LT%5<_yGfp&*e!;~^~Jg&rlnoN$IeYFzyTEs1I>W)Gk4c6R(k3lj*`0&kFM(CFx zYy3->yir@-55S2Dj&LJeerH`>aoOQ=gA2Vy5H_d7H)Z^0jq8 zx)sBw7jI<{<*uiepPaN9=v6uU>lw`XL5t1(D$Nn!EX4Rco^XiK2V>S7A=&Pb(}s`z znpa2w(qA*o*u>ImvA+3*E7hE~)F{)ci9?PU3_k46Xcv$T` zreM84$Nh|J^?6%x#!NA>TahdNxj6-H?(VWNmuEC6t~DELn6rAh`=19|z9GB;X80nD z0Oi(XA^ET%?T}WHnH!}CgCW2}*HW!-sJ0k~j30FgFBDBsy_kW3th&}G^rZ0uFrNFT z^uis14y4&y6@(<~2Kl~+Y~5NLCQ8ECJ`V)WNUaOgXxV6w>#zjd=b~4Gu36$TS1Wq= zTqSly&W?AKz8ScMJK;&}4K0tmK9Jgb>;fgV>#-9wL(;D~*da`g+sj{)rQVl#Qi#~J zMS-Tdo)}JdU3U1!2&Gy5Uwwt<;$_D?x3O)p2l?0PqJM3!Us^*W$C+GNxwdS#l&20? zvl?d}i(B;RU1@s)b1f3>-d*p{PRDy>qDFvTo*N3&o`H2u&X&g?@OxdEXnSNxMz%EH z|8fc%O(POfpnkvfZBtIaJGublk$zNn%M0wcu_tzG;Vm$T$!%~AOP8~f=H3G*p;uXz zEoV`2XL&g+oqL2|Kz>d19?Bg`+hFhvO*A2^`2%h@)H0>Gb6zS14riecG8hF8 zErcl!wv>Uf1MZy}|B5K8AAYiO9JHL3ZqkRdB4=tiSTbFfnlW?;iJJXS14^HAfGMrY z>88uCe(Q`A=a;!p){;FOvWLO^Hog5Vymm)VKR3>aCBj0G;bO+&2iubtMObyjJldpv zk4Z>@u6N=;zt-mj*!tOtx zw?0S#{dM_R{6GFY{|Q?;gPvUNb?fvul!_Q|he_g(C{Qs0Um#8Ih7>K1v zM2lcEFMeCO@mpH6_*F?wgUvp_NX;cOv|+3%M`q&VQ5W1)e~*~fx37u(nU=9dKZ93( zM$Jdb2KcV5163kGD~xKiRN(s2=EfNp-e5;EW^ttt=#sbC&@j3>hk%!pXp6ee!6@yh`9#OJW!X;%;EhKGSWV?@c>!K+Q15w0yhUk$h=zq!v4mQ}#XGg#jDu?8a_^5R!n+3=5tK`p!umiPMeZotR@y3`nQ zF?{G6a_uNGN54jI*4_i%ki)Kb9U6iSd{(GiBH@BP*kAQ2eOWG0-GR+01Rr2c5$#DU zg7A4yLo|#Dgc6+aJs(@P2K9Po#ObAmtzpOOw{8I~Mk^v)h8<5dxao%_4LkF*o?&MD zG{>@MGz*hteUR28l^g^;>WjJV_W30tfqeW7V-x5;lcEyI_2!OlHt9D9P2K5Wp2%w0 zE0Efq&O}N1Yy-B}n8FyBeIRuUietGf83+CXGcuUXY1tfJ<@JVX`FQJp|B$SG{)^0; ztcV~ypC`QSD-bu!Oata?8b-RVE8v*Oh}HdPwb%nH{-TD0aW(Nm$9hyq#Mc_anv5Sb zn>7BUEZ+{zrM$IE0tJjk9&jsmZH(UR&PB9*Zg^x7D2`F#w+(|Xh*MI;vn7} zzu9PGkN3*+%v;D{?uQPO#HsOES!WtzF}=PoRBid4yYNzmyCKdtcrmyoquTA9QT>!6 z#wXVUgiAG?DmLm}c9Z9Y{z&RJSK@y=l}G|>DVj!4A3%oIZk{Qz>s!vU+-Y^ceFvgD zQa9JcMzbZ5y9DlbG=6(?OCjo49biNuQCpx&F9kH+pX;G~WCWOs=G>#G{fm7pnHn5z z%qupiV_tjha^T?|pxLBV(?TO6@YhF}({zdqm+utOvfSLRz9n*@TjTiM^K_2MjVXs< zuB2~cNvcZ{r&~H?)W+iMqZGHRFJp}8oDn*Id=TWqqBD&Q4KC4Nd6qERuxTJw6Epo} z6&@K=l=kwVFXuE(3Ay&n!jQkU-<$J%0_gm)D07Ky&(OQSmMTj2aVkTY)ndI_VT<*{ ztct9F`S49(HcG8kh1*i(YEHFV10iV~X6w9sFIKkJKMc}t!TH<~5j0WIt=QzM^l3Z7 zPCCCB&A7eR?SH;RYt5Fnz5ml@f71+jHu0Rd@~QLFXKXQ5g@oO$jpl}v3+&i8ak}Xi zX2G`%kl`-`?i!!L^g@OeF$1x+y_fGy#!md)HFVZ&cqxi! zkFU^;YOqQq^QX{F0kq-lTCw2w@*b0_*_*mc1S@2rZ20Uew(-;ATxwNvb2K0+U(BU~ zl00(lAtx%?THv1B;4b4nYA-}5cdM4pd%s_0=ovS-IJe1$HM*oLjMW7PuLRRLqpAz` zM3ClKgg2eHA?fGlJ?Lx5O`!}=9flO;hL?+5=+t9ZB(zUiwbjv<4ZQ;~o0ytW04rmeFCY`oNgz0 zHK%(r(eU%o78A3ezU3uN%e>gC-iogMVa=OQaaE9ap|+zu>iTght4%YxvdZ69X-iYP zUtxQJEhHv4$Ns)FD3CjOlDVD=>o8S=TIs%~_ok8{ zTHi>{Bb&j?6UF7a`D=v@jPNq`JFDwkhLv54-6t+OYA`!QG=BuoH-v~pRs*-v7iw-K zoN_=+=d?nBnpJ-sY7DltZKLn$_x=O0LVn~+Ht8G9b$snL!iyrMQ6{qIyse`|mBCAC^q-}6 zJv^x77bfRI1olepzGFfrWMM)op=ovkm?NRHHuY`90tt76KZ89yPcfWHHmXGQw34(( zlc&C#`*Ed`dM;2EvKy5JeP@)zo(^0K>_RBL%qK1az6zbEt%pnVK&%W7Ge6gsN`2az zZfMT3_=+q1;oBg)JjcH@P3$47qloPl z_`cKpKIfSIqx{yZBQ;Y#W*WvjLf$D?w_2D&zvjMwGfUEs6my<7>T|XB=eLSgu*~^> z7w6mxx8{_^Kn)CW#mze_nq8agT^ZJbPyWt_Jqy#Y8^KP0uoFs@$bICrqIOxPFjDBI znEt|S4>HomPj1;Se++q*jl6IjO*lESFrDIPzU|A{DwTD=>oEX0Ko}ReSCLY-A*n1C zR3qJGyuFZKp#QRk#;wgZY$DPtMKt?)?dGf$so)FbnREE{%0 zv}OC<)POB2gZyY!im&=y90&b}eG09Bsg!4rAg-$qexB~jid`%9zKke*{E@BRci(%H z$1^N9PVq|5$c=b>GwrQXs@jNJx8lwLvnWT!b3RG<7gn6UN-%Y727yOB+)rsNUsk#r zCTDr0q!^H@78Z`CVNaw>P#{i7e&iQh@UFW-+H|XqPnO2A%D10}}Xx---7g*HuK`NiDs;l4$p+AYJnHRDYR`i$N?=M zyBS#Zqc2QHyG1&_mx`K^-UfH9`EnU+2f9^5MgxZZZ6ts$fxAjY!}tA4?0Lo7vK4b9 zb0tpHYM73ex;GafbZ7R?jNX_DGmp3$h|?_ouys>VH)o?9yu8afY_MKDtvtVu`(oJL zT_RVDOvQ=64&vW505o>J-QjCBe(Djg7hcz6iYB#Y#O^-dD~>oY$7O`W1Z)l;d*? z*vGT<4yj+ukmoQ07jPSH>G$FkkZ`){$^5o!0_PL?Rb!(39#G}F;cAn6G|z;cq&v;F z?;@>J)2azck#rsRl&gB$I;rEPfm?NA1-_$S45uxPI=p(vGhOtACu5i>oI5c_m9*C_ zI1TsdT*tlTPsaK|n;vVANLCim*~)W@U3t|w()l^jSAiQ69w9GOwbkud7OIiKO7=5{ zSkIWyuJ^%DMpx7CoSEmE5_TW>N*;>L(jZZsJe!b|UyFt37w+EJXTMDPsz^f-o^uF#pd)?LG>L_dlrSwAm6--BW>cz5o->Se{H~j5^;X>|7#YK+MA|~%9($N`GlxWG^euGXJpAj9(S}6~>IUTI zMy?$|v?t%xtmfUEMh0HL;;5RHC~-A>U|m_F$a^)JTpw3U?kMJe=1qIZ`saq65(Kl; zTV_VCLoLor7D18M%Z?av{8u7Ne(SuymgzoTPY0UDb4NN~;J&_hF(WD z8<_a?Q;U!~e#F9CaaZk1he>x2pK2PFriVJ;c{j((ryk`Hc0>!X+*ooJl4W5R)o=He z4x8=XYRZ6pK|v)V3PrEAd>dP>B^mfl+*HVj!DyUmy5H!#?RJf|DI(svRiq^`#w#_vQ@wWqaX{FR-Qo^j&=54mSDhxlC zvzQ#i7QzxDMhw9Cq3lUoO&vitRB)>#X@OcA`Qyw5~ESuX$1^sk!Gc1Ch&uh7s{$`SXu#QHXXW%(ZP_bH~eJPY#~lIhH!MwrF!iX(BKAs@NKQ zSCyWnzVR+d*@hziG7JLwxkoYh>AAM}0sA_6;rD^>f;Q*RvPf@fw9l#^Xl zLa{NzdjBmX2UZmZt7Pc17GP=-0c)$C3hkT}%d{?PpmV6-{q+Zvm>?BMS=lGc%sHiq z@#|^4*^bz0qUew}W?MWEzBu=OR5F3F{NLg7?6vKTHLXShyj-oZF*_*5#M) zm3gy$knKFEU#yeY@BQ|Yc8Tqy452$h(8S~OWKn{scuudG1nXs+Bgmvt0OmN4i73kpAmY*AAa{jBY#&b>5U_}WY->my=|hguWhra(=z$pV7&TEn|%rNC$OIybw@^h)a^dX zr8#LpGcFybs+Lt&REDL)MVSs=v(oCv&HRe}#z863hO~HqaUJ#Fw8^3t;5~3(00~R0 zS64^e4T%i_Y(wlq#?VKlrm1}2@@hNZmdOxGRH_62)KdEg*%cINtHlEii}F(5p8}#P z6h7<1I5ya+A;SuzTIW@BWtfL=6aaSmte25|vAewT?W=#oIx7g+$v6(WjHqWSD&DdK zmq_gMC9WilJC_PMDy$A+kOcD}vxt=A5{1B5eiub<`8pAnJ0Dku^LSfoCVjoTcO-bU zHl%Ojc8--)?oV+8Au%)GYIq`_R4-Bz+)z@n6@n?TGVr>Vp9J)Gta~1(8>zRlzE|eH zV|#OHG&@nBJ@t$>nrVc2o>iYGpFNM z^y+)e+ZcwaxdHPB;Cq5_@E~za5|)cvv-WqueyMfPBJQg5&Q6#5+ym?RWsEW%^A`5JsnUCWP{%lI(yXOI zlJ@kScrr`X!*CfFcu{!HHs@FAujEg@#lCAC6Ply>Vqo;n*>BmmV^Ql`vCi^(>lPTGS(d`py0LP8ara!BBCJ%P+`zvTLq!;v6PB)zi&%3q>U?Txc>F~=Plbduyq5WroU-l zAtKCIv^80O8+AZl!J(XxRD4m1zTbRW1v7BqOI>r?U#d&uV3oU7PUB?~$&{rm*s5w* z-%_Kf4zf+HBJ?Lj6^&n91gkd&6rJoeBeub!HjCeD=7hpu&Lw#=@L~L42b&DQD|GoGgkq9@f3|CG3HHGt>^@xVznVF*8s@4Cup}1-idKLKh)i_;Msw? zc+6XkKBC)L)#7U9I3S_Q>LF7Do^2Im7x2icJ_SZ5Rv9Qw&D3V;MSGg%gTv%7M5V9~ zuVl^M){TXT`Dii#*GKV1Drj12`vJteTd~5`+9K-aU#h0}2wmgG$g}ju%QxIS_e=SI zeaBE1NTtL9M`P%Zqk(7ccNv9IiSvJ-kF!rgx?3lW9L*g5Nsb7=MY4v-M6;hjP~(FL zz@a#sFQRy=Nlqotmt3Dn$Ge@FklL0q@P$vi0GiUlCz@kY#3bcSJu_}|r#fc-EMIy< ztr{wF?O3>lf}#WL;PTGfPpw+HO(gS}G|i?=!7=G*snEAH=X{c6)VXTDGDGI__Ob^-rk zQ3pPY*vtal(b}|LQA*; z=y3<)eq`$Zz6Ea0c_WIWQJ_V^@}_%Xg_>Di#5IP?qbCDIz#jm@NoA{7`uBE~U(K+n z5Q_70tp-klV$Pg(jY?{`5iR<-vWD5}LwA?5m&q(>bYu&WUxyk+@*mLq(kolUGEB)htnfzWoEcDI{MTlP{u28B84J+UM-5#< z$K`g;fPF(tAgfJ99uNM*=4vXhps!E7P%$Hb`mE^*){I)_*M++L=*7Tl2_`BjAP>1w zdy4j6;$+iiAz)?&nqZnQWyj+yf6BH4&zUd_r%gHs5sU58x4|Xz7D*xf82wfsm{@b* z7qej%EKlbnD&9GyyXl?K4`TM#gIn&GF!0G|3OPf*O&jwpc}CeZz3kTVFoD3~?d|q! z(T|wTE}GAIn6WMaNE&KkO*AU)+U*&q{eMawEZajlKh z4YW&Eg*Inx9n2jvDWS*uXn9@6#Cd4*mobaO9|F{YXm$DOV9?&8iacfax60F*WiNiQ zoG4KgA6h-^9M}bE;+%A(J+m5ySTWeaKuNvtCLoV|pbEJ`^ZrL#oCq-0wr7Txa!4f#vmSj7kpOscSc_hNq*@z~3cop_g%J#Ig>eibc}XBNudfRL>&| zCM_qwc~F{uKM^Kt&!>{E3I?Bejr}NYDCoAiK5nAiG_?NyR zLzqat8Qkw&>mP9+R)VBM?OEodYt5%9mOTx~p&w7Y@g7ut)eDOrH4g8If9t9u{7rlM z(-Ck3yLWt6K0gf<`10h@Zv!4J5-nogig7o?_CAE%Mzdl%8oiEx8gD)zaK6~uCMuNi zh`(ttycN6c+sXg84eH%(Z1&{S)TevSpaE&G#^a~8Z3l@some7HZP(z>wVCDmE{pL? zNh8g)w7@f11VVRTDicvG=pDy)x-*RM4DNDmAOwC(JOFKQQ(a!&Ya4voBXB=N9ntvOO@(8iA1TkhxXBotK zYb#}wN?LaDasJR@aW3+2_6m~eQ#+#g<9sQ8{L<)#?STOkE9Fo;U78&+BR&j0T6 zA6wLOS4li1!{fmcxz1|XyWS)7z;&n`VySj1?xRB*puhB@ZT>trs_S&;km2znws7&nruA^dml+{}8`VKf)J@5J1JiQdm0nY?+@Hk) z!4>i%IzaFpQPwSYn@(|WGATb&NtUHgW(7MV#5$)1AUcX%uY`SOdJB#H+Sjt|B@WvMIK`u`P=Ak@dG_K#2$(lCUiN4_g2up%`zGt)TB z{l8}#()abSXVCRD++>LE%KDZCFGF(JjY)sCOq0O$&b^Gk&MQW|`PGWPQdwih&9Btv zy}J_YHba1ZrGBJ9AM<_NToHh0HLXh<5{XEvy&r57vUH~?QmC`Gf(dvm2h_7jgw^n$ z?ZfQ(Zlb3EJPAg-@EDon0$I`b3F2(F@K844QY zD#iM(UBWVYWbv|l2DC5kl+`2vvd#m-Iwc0yXVvhPBT*0*I%n)$mir6-#4VMIE$h*IuTigd8>UZ93=e<_2N5Y(?f4k{MFcLe1|%+Kj$shhSN&Bez%ohrAUpK^)+tZyp4 zZ$U=afb({;NC{m$kYg9Hi2}`gHI2-XZtQAJ2x3)){2-bBu!QxlOvO>_@KYum=d3Dm zdG>%6&sxIQ3I;9bKSB=af7Y5*yL@AR`uF#U{F*+-4NQdpZ_swCs(qfU#@!j!3P8%@ z6mrdE0WU42(cE(_>1qR1@&}M^yEl;wa#ncxaXLG%NI`AEG-9^=8^cig=OR{*%ZNAc z9>`V)@`-UFgW|U4kxMK%WHmH(7&^MXP#4)hpal*c|ENwFzT}O^db+28hP=pi(|j{` zbZ96O)mOjfEPG5o6@+W?U2+)cikwnVVe#<8oOt{ta-9&@dd%O=)Ib#LqOnNb`B$F+zP50XA6Cv_3!TD#z}ifqsWlvMT&hbl$l5f@CH`dnL{c1uVWF*;u8lw+-9WQcm}7%md~l3a;L!V*0kmNS3A_czGxPYc>$oF3)zZ z9L${y9_G6bY8RW-r>I`Mjb~! z-5=nz$N0zdE4@0Z+NMnNCT|Ixe>T8|IR~r}OvUV^f3#i2i9gsakiYpw)v!q_rMLcy z#G-cByOEET^JShrj%kGo^+`^(=@gLm5~|IjtWt?m=)rwvGn##<_s-|uI(_n9uP{%5 zOE`;B93JuuXNMU+6);UsxT#^Oy@`6%vOK1kRq8aKBWhN3ZZ`PL@MzVuq&`T@%`Oe) ztR;yG%7_LuTp4x%qMvAhYu0q{9rDcwF%0=Xc(nAspy^+Oj72YpbewLpbaw&b>02jr zW|T7;Dz`^0^4uh4_1i#hawB%VBSs_VGTs&IlR++#&{!gRKjDptd-B2CsxQA(x#OnS zs29Bj1s)cn1h38Q!VI2yB+yFT_)_^@)whYc`m8PaL&KWx-PM6PfmUp~e%w9*d{T;} z*QahdWGVE>a9qp;UTB9?>G1=d!AK!SjThHF<$KxAWAG6OXyA2UlMrc5QeY^Xv#%BX zEN++Wu#l7gxJnwg#C;UAs;3tA(obsV<>y*j*3@HacJqfIXJ?eL(Is&eGkn(jxL2@V;$XXh1{WNAPPF(COG&}osl zK2>Z$NqEa+x9V0SyHY;@ZFg1y!(yl-YUNpDSF#WYUL54#{E5rj9wG7+<_kD@p(d>T7U8^7JBzCGm92SFaTI}$ByVwn9RB*}ku@s7W-OChv=I5Sd@>TPc|rF*_s9;* zL*qn_61aodtHh;-H6&}X!Q=c$Greoaha;h61EvBNm5=f{pyl&uiy$ahqKopD=@LH2 z#Ktnre7nLqr!jb*rnt*zAT`)DpC6R`2a~1T^rL3A4Njf&2-5@*2>mq%a_i^fh`An@ zo{j&%Oh^ettk6%YbDq(cU+OduyEf4ihNpGs!)4q%!$ zsNcX6H7r0ov27K1=tFkKXW}Yv28#5RC@iu~f9KqPtMez#!LrUu$}%wa+ZHpsLuRp` zFzcrd;v0NI-6tLB-kJ5zG-gY4DLdUlwdDSkXz#36umuf?tAS2{B@;DTePlMupxotg z@t@pQ7%RMNk+*j?a&8o+^1}$Fo@O|#{d`c-XD78+3Ft8VX5N`eF}R_>`=@Ju2L;am z%tSRUBr#DyFfz{o4M`#B$g>)D-?jNKX|0hLzQ~ubiij8(63}*7AI&kuY@QKL;bd;O zSDX2U5Rl$KU*rfj&JA-%MK|ImLwA4<1$A$=v~f!g8IG9FED>L3nd`$sJ9swiQ=iZJF0YYl?;HGV0{89zBWA|8}wNAKxqJ-cK zkZ$5uGR24E)IGd%+4fu@fzZp>wPT_f8)^e4%>k^T9D9osOY`2CzD!DKR5)lGwu`2W zyntUMZZLN;-Pf{m5mEOq>P)T=Ez%klcL|gq{&Nw%%CZBdwY5#`oLyTE3)B`Cb3nyX zx)-_q8kKtasG-6-vi{nZe{{oGl)}-cb&x>O4f73|-xmug>(FNzEp2V9rhvTC<3&=E zpjXyzNowd(%)iaJZTXA67Ezxwg7;YY!t#xd7Ox7)QXQx6-gewidfa7-95m`sn|XyM0< z^6x%32)kM{(s#BYd!ujfL{xfo&K)57(GoRMl7aQ-X<-0o4Srf-rPh@L;Do4uM|Fwu zb2TL>0js;^Y8&blfXvO>ftK)Zsn6TghZ&!M399+^86hVGAG@h|O1_92*{U~^U}shY zmCE=LzQ^uF8fxokntlvD0?1jAswj6JNIo2Kq^+&-@0oq4RAg-dwg5-zrab%YblYY8 zuv{8=h^VjIw78lQ61&z73;-}%vlk8u^h_Eq zgtYNFC`DdkWTpMD@KBTh0$qlT~4}8h;N)%&wBz!Z`ps{K?tIHtDKs1}o2Z&N&SJ zUjScJ(is4kxIp`FvR+UzYC@!QIU35UJ7)_0#Hy}=^p@fz%SV$AI@xZEynJz&Q^x|2 zpX}`T zzsH6B)ZX;1Y+AneAe#Mv&;4=-$YeRyxA&1!gy|G#fWwY->$*TvUx0~a56amS_m8l+ zBH;Ik;3Spgg9V+IE~RbV+Jr&kEnS~9g`xk*g>}B}UP)2_k2eS~4?i54mV!eZg%_RmtMzy#863S_B`G+ zyNhkHik6LdtCVq2y-0}yPYa(}uYJ`WA9h`(`G;kLoBifBnnCfrkIkp9V;6w3fO)eW z);T7mE7ymJ`)4)`){9#6Xd%ut<1Wd8;(CFJz>YyQXoy>gfg;(?I~ZdVo6qV>e6Tq} z+V3NKvxdY_(zgMZY)%VDtsh^$F(_PdZY|CcY|p)`^L4xv=KN=h=JQ~6O@uN4Ppo`K z26m3`BrlCh70$l)u|YzPKBz1|4RP?m6q9fU&9B z8T6Kv4`U0^-fO^SEIR+9vG~C**K%If-m!B3l9`AsbPL5U^vQUNGf^WxQ6bFs@0c!n zT{@YzGlyVOrRHA;Cx@yDjI<*~JBJwv|EnXzm@ps<(0a9wa+6qwo3U1~4i`lg2{Fh5 z=Yn0K4+5$A4Sf}&%x}ML4pkYK-lHgCew@ovM21Jzol^(0YEvmT_>0A^u^w^#k=$?o zZS*x#Z9GY_)Z!3XREUpxbW}oS=uaBS>vD<+e$a8@v(a#a$|8~6%$=zsB;}+5mR$V% zZ_Q_G2HgCET}9nczqy8tOYLTxYiK%(+6HvVrI|SvtyqU6(oY`=ujvta>Uc zF1dPL%4C?2y~mtUPk>LpGLqIDjT$V%YFc;g5S-BAq2wj&_$adx< zb&=cN?1UuFXAg`LsKEoe?33@^9QSPbxLadA{P;H6@RTzRioOb)Bx zwV`e)CU+~U4Sc4tSKkUzNOmZ3*;zpII|cV;1Xe0#pL|!Ow7jC!<_~wdH1?3G}9d)Ig|3Qzb-9Y}g(Xqtxo#WM)y^V4%YO1Mu3;;h52KD_Z zHv8)|ZaCYjLrva`{H71&tADOIeKs9kvuuSqIHG46KEa_<+hN6*Lt z{dUrh$RTK=k-c0U$}R5)S)&KqI!m`5;63gy>yv zFyMrF^i9LN3T5NBUVT@h3dtd7sdi#OSpp+sxi5Q;ocmF`rSbK-b>iY3Nl*7UTh{@1Ao_h)3>Pz4Dnd`zkHg8BZTbKwF@r+`DeyUo7z@w z?T0&XOmJzl0o=PeCf@%bXC-$UqiA*QDHu zLA@GHO1s^#HoZ!^{6Tv|J7RR9w`F7AyZ*~=U{!i@u6Bth$Mh}u#R8szPb?#7dy9!` z^KAwM+gr*xin4IV$&at#W2R5l0;0!8Lt%c@9Ca0pX_ic5<^7Vy%{a0^S&?P}tL}H2 zFR{OcdM!$zCm#g1m&mqqnG#H+5UM>t^evYzcn^idhj@J+AgqcDTp zi-V-U0JFCL5nz^ZYiQ49?jh9xuGLV^#Z9jYk-b}GNN%tg0j_(77+_MAbBrZ+FGt2y zY?&TOj#MH32;B5a5CGQUl0>Gi#~!t&P-)LaXL{r1Fo+{iINb{$D~bnTKK58$=UlYY zuVcJJ9z!uBx7^co9SaL^S;0a9KoA)nnx;n5D=zwMAAGgeE(}8DRs;ovJN8QeZugi% zZiLs3@V;CisULnd@V(FKzT&W%i*P8@{kP3j#7tjCAM5BkZ zq@k|BD3$*XWM-~T{|96i7IU1`_{ng4lyhe;rV=Q3!H5E@M{aeWY00RjGt9 zaJjoF97BH#q}_a`r6QPBS(Pq6+riHjCGqSO*dx(dgf{ncYVQN^VmnZKSwRm3%+wv8 z4G&72#)O42xA&)vMIqKdwGf$D#?R@`0Pc9&k0)+j=9>?*eiL~XrnCNeFI)m3$+}bR zXAEXj2oA`_+I;K%B0Y+L^VD6(_2n3aIw%%aN_EEM3;pO0O`X(+bE|pg8;T zhPZ|Nb?hN%M)v0tN$<!*)9pSn%@Ib{74z^0@kXbL}>v6I4}^j z(y12(OZ|wa$MJ=_=iC-ab;(SL>yxxi>8e&!{TY{U84zv}h+&kUkr2$^ z*{DMI>vN)CUM`x~{~|BbT46kLWK%IyKc8xZpU!0Ab#DioHfip2w-WSnXAH6z!(_dl zNEj6~aC?f*b#1E6P|BdT8p>_BspHLWj%Vu~7|2OILvAV+YK!hWiXXo8qC&}!^TB!g zkS=vmqN-T)v!!k5rvnE(UHaClHwytZ-MG<6+^-jiIlj9%1oMoO_g0AjRNRp4%45QI zG7R(W0Kdo{a3DIbpsIH&@$W!hul-jzTKiAG3A85E{WFiYxrDqRE;U7Pa1I*O1vm9; zTMn6LG0#;yG#Vg-jKC!y=Vz>TJu92FrzzO=?P= zRKRKJYe4@grC`@w7}!%RgZa&+kH4+3{7DhWeUxo#Kuw=O)|SasDE&J=Cp?0u!0(Os zuHj^+Gtq@5WU_1LY#zwI2 zUz4*BmzCiViK;+QI2Wpf&NL5yI}$WqKYXjR8}Vq5DQ$;(+GR#OsogQ8LD81E13IS= zCcdR7sQU_7FBIv6&Y}gxkI@h8Zab@ctn1LBKxMtOU2ZU|`W8>Xhv3kXx*lOy{AE!p{8e8^}@IIi7dIEk?9W!ov^?t5`ZCeCZ`TF!^ zRyvS@eL!=$Q+lADk8&RNX{lKull)L-wI7k+3)6mFKMJ*4LEhCZz%h(lPR zd9a0Emce<<)RKQrKU*%=m!@&%>I2i!7J%;Rvr)$2dc7M8rCp=O{+2Nv?Gd`Uh@zvhVAzwj;YXG zsQ;&+lzWw-$O@kx_bBCVjtR7`Vhey9?tsumHh6V7K^YRnVlac8J)?jyxR~DJT87wgfQ^JX}9i3ir6YPVy|JB}^Mm2S9F7WN-)|C-Gd4B)@wv+xw9gR7yywbZcx5;piM*?m2A1AQeGnbEi z*A5`z=Z@t{ew49Ekc)EUK;KKC@_q3ZGqSH3@G8K48TI$NR5o|nPgF!Z_5h=)C|FZZvx5fI&) z`}0?)(UIC^8$9psqAf2T*BAtJ!F^otjg**`%=_Y8@0QNvwlO`56M*Y`u%mq9R^Zc0 zctD8cQib7z$=7ouDX_+-n3@B7qhALY{c`zz{nZZecImE)cpy@QKW;PutDl_q(o&3N zGJ`AP5aii?pmA=x?m^J){ksviH8q2i8ULW?1`2MSN#<@E-T1bV{n?9WUhI}z zhdz>RA+bDBdZylsXAV_Oo_mwMqp?RFi5^ksW1l`=z;w&nL&VOd#vOY`W_{igSJ4Hq z#u)Lb#Ix(HlLb-7_gP?DqJQ#3b~9UWjT4QPbD#|>(%-7rO4~+BJ^nV)-41L!V&(I^ zZ9gpA&F9_3(X!`f)^5Mc`|=J28(`IE;a9}OcFzWk7&XQlCB!7)n|>`7I?_30tyse{ zzbkG!GDg{WNqWmUsi3LWtNQl*q3>G);rKumGrv}Af8hRbHhR5f)i82@C{{vDPmNl5=x?bD$DTfNrnmLUFZh4i@Ou|=+p zyDLC5;Wcah$Dirxot{r<@?SjGdjZg{Kac+-y|A(^P3XPycdh>mdE3gkd4zD}U$EQa z!C&|4bSWS<7C-+vPGJ8vNc;1d|2yZ(rNEb$^&Ql#O}aM7D=mMNr&DjJrDWz?pD7}a zfC%#G^TGo!AMw?-=u`;pU9xIQr$A^jkLA6P-|f@38|X_S+w4tI2+2!B_2;rza+$8D z2$9J;JGvlB1)$*ow@3kkN(~91gt>_gU69x~oL(dKy~&6iWX`|r1R$PHMt9J1JrhP& ztT2oc)AvFSVK$NdAecb7$$}zr#iYVI|3`%ez*c$0{vLeY;3sxhPp@-(LD?O?BM@TG zkR?@v$wq)|q%!fO5gl9UuA4wwpOCc}s`o+vS6qV@@;C!-qPy^26>5kqWKY$0n0-A1 zJi!W?aP=0*?NtqUx=B+tphyztO^B;DXhEqg!;E0D2=d074_f&e5f!Prg*0|`CG{y# z5$?y5LryiChdc1Ss!cG^g`;_W z;ZtNBYN6K%CA+IYT zI(_J7Hn}<6c81oDyDTS`gog z(K!jT<~wV(4Y0MozxsA$v>5gQu&HP2Ltq|RDg$OoT4;nw!h+$skj@fdVTtWsqe7Cr zv^Aq??Zw&mbEkHgZ~!eyPzseuqGV2S{x{) z;5@a3QH9d*=;*o}t172FqzlaQt&=-8O`yog|KO((q5IN3Fj>bj-I8R(L^pfE(EKRs z*AL$SCo5(55`DW5N8=PZ#)Ih)DpNDeJQ=q#FQYAqA0jr*@{hOp9$2DHl?3hoQ&M50rnb&kK5Sx1zA-i|BUH2E#4(?9TS|DwZv-)@jbF=B2bgz z1*n=mIqc4e#USwHeh6sd0(_99nN3C#26NTX1ZeDo?k<660+E>tfs;|f6CvgOelL5m z&sIO}1i7b1G?xBtcj_r}sp%lL?G>mNb>N!DHrLMt)-py#!i`SKWAP84&sMy0(e?o6 zEZPZ5@`QRlR$7}O4U~O8&IP!O((QyPouo$SG}E?2Yvj)=&pYOd*Tq!pNFVy0!nt2Q zgU=ih{AMqdHRhO^COoXJ*&oxWUcJ!2MIr^69Fe_!X-kE_7h>aH-Q~-x4chOo|D{i& zlk2p%qqP#=*;6)gPlp#T@uZ0>Kj8X=lsKbsLS)|vE{3kplN{pAGx4;qykDYUD!+5) zxC2{-X!~^&7+7F~nl~wSg2?#+of^Z&H}8lBNN=S-+|+{=bu8!+E$uxH@g@FemnpBGRsSiDVeRh~`Z;jSkL1#`#BYNXa;lAUHY$*s#`#unTfK?vjgh<@X}-Igm|Yxqz z@zay=cWjD6Z_Pzt2`3R;LCrv_0c_f6`q*+%?s; z;vjyz$8QZl`LQru=*Ycw(xN`U)_n@?9p6w`t+ zG~BA~3AZ+y7p#MWQ*jWFYYTjk&P*D61QhH`+P&9)J>2jmfr9SItsDg~v80Bm?9-jD zL?g+AseW)tPCOSf?JKC!ozzEUJGJy4@>it+)pm(zG^jxfBt`j=vFsW37kiCFkNwuOLjVPBxhTO;t``E4UeMuGMSw?Pq`Vx3Rn#R&yog z9Dl+*c>R5x=fE%dM(>lx-kjVlA$OnKYx(kB656V2zr*w&PM+fQ3+Uj@8S^L)OIr-K zARcD$tFf->otY%xU~K_w=$KRfyV`U#gD?I$I6a+^cZlkXiOKRx8=%FS&%|ub8sB0G`qJ@i%>YV^x%k?3@AD@KbF?&1 z|HpljFwMH=Ma$Ytk}W~WO*UqB)x$s`CMx5EkySIErlYJ2U}9(eF>-YS^2t^5?BJmy zck{Ho!z%t7C!-FWE$~+AF$LCvPTKjn{0}i&ol2!EUw(pn<-in2?xE5_tBT5!f7-w` zN0nhiwJS8!kVBSb^l($6tq;;5ad-VM6=s!Pgw-OMU#RizXCTr-POQ!Hj1z>AlV25c zZ|?Hn&)6&{b5C}RzV^3aJu`Kx2L(+zB7g;nvSMmtN>j8aF@4?@Cqj-|=Ig0=d zb%EKL*l+o-;h1K{Ypl2qZ>X$jT|O*PKWQ@3#3YdsEZ5YRTqfv-&^F|E^P4T zJ~5YMq)_-6gDh0x2n_Uao9De?tZntxphI3PQS=EfD5swnynma@XQ#Rzz^JhV`4TPYWq=h#zRu@2=(G&_V0`bIbdo-YTR})Pk zWh4j>tJ>bllnOE!~5YNbJI1Edk~PuEckGm-{kL^NYH%t8VF+riwd-OVa6G7BIv5V zodoi13-{HDLA941U^HyaQ1>jeZr_m^8i&H~AJN2RUiGL7Pd!=^8&1JX{$(@{;>-v?1mwk~C95 z#qOdHafb|5V?v-Si04k#s-!Bs7W`3iVH-cN9wc2t6S^I+l)cbbLZkIDrEL}yijVIK zkuJ|cNgBa7-hMf`fjZ(+Q+6B+IfABKotQ^o%Z*8+F**NO@y*5aDz6>A#V~#C%zeRW8;}~}fSR@GT$&DV9r`L; zx)EOL#-c?5IGNSc2gWld%NXqI5u!vwg_Mo?gA~`juBjtHuF*XTCMm2=O|1cYMMyE; z)E|jEirbHX&ibZrVt%CB@&85uc>?o1%($>QzSWTojG6eN0#Iq$XPR>;G5)adxM?%v<~Dm=~idWdn5$YW%0#`O+yP zVlTHQ2LMmG2+zB0&pBXi^h?{{%$XBTiy>$7a7K9@!)};oH757C!%pab5`OU8@PV{_^srz_~*7%e9c@tu$&c^?ikWRkO5etp`RtSdLY6FdVk2&EtJF( z>7&}XE=_2c$Oi6(g$2e^Kr{lF60 ztJu1H7)ZDHxvz_y#WdCDP zr;yx9)&~?AXrkTW?(cxYA{wN0IH1uv@0NMJgu~a)cZbu_Ryh^BLJ{?(x#A+Lp-P&c z`JT)OAQTDC#SRzO*{R<=qyyLL3U=_G3{EPPYKR1-3D2@acI%j(uDmI34t{D0e7PHv zSo_6Vw)>yMVq->89Xy^8f{rMAG6@Rh!@!X>Am(^C+|~97r*~qS(~MHK-X=GeyURp<}b)eE40vJKKJQ!#sdx`DOMnJf$EXi%KD)> zt+b4tpj=${ejS)(n&g%vCTlWtnD21SlE=WIVd=xm9EWqn7)_KndS3p=RRGJp4wo6AE^`=AFz<==E?Y3 zWOE_sRXgOUk(U@>?~kt;E?xZ1KU%V6jeh?v3@zRcy?P4>vvr6AsD0c3QpLvs O#{{Frb7lMTY{6_+Oyt8lr=kEJ9*?0bPj=cq3!+NGAtE>!s zYni)RS~|JeIJ;;6emjqK>&QV_?wPjt?C#YCgk~~>C-BH?zM*~I)M=jHNmaGmdj(g* z-}-3vu!oN5ZBVO#zt0bRVRNG26d&IHz`kR(==GNOlI2wG_Q$)=FQf0yKD%r?XjK`* z(TUCDudb>pDQPY-tk6sUOHPNopsHA)WK?2Itbhg^LlBmz7!BLR=ih;Gi`wY8zqfgQLv|A1fZXb`90oMM@q1_>1$W2P7j3!J`$nO`id?CUL;|8$+_ zR`Xsf`tKJ1z2QH7yafG2M$<*gWgxnYrrPWTmu1AhOo!RU?J2?^K$4tu) zC19->&4&`p7BA5;*K+NJr^QVsxyO@ze()3 zY_7cEzJ!ZO$52l?x4@?q=>kwuBB0R>iJ;9$U%&YD4g91Tm3gU`B6Mep_;k3{+X^7XgI-hl&gQ{@7 z2v4}E&Gg?+LDcRy2c?_iVIIeCA0<%Ntw68MN-zA8zMj4=r%16Fv|YS_b=SjAvAbT{ zbBSKe__TAH?hIFtx;S9i`Q7q#SjWIAt;DG4(e4x?&VOzvgn+trgxB2wPu+~S98rtj zaBkoIeZ!4i6|2FJiz9N>q-jtQSCR6o{h*}|7|g`^^m~e!{b^Qt^HN ze>pfE9*d;;&zz`$UC;k4;{^tcKm5j0i-<5a`8hqk$wiMH41uWFcMOypH@`q8_N*zS zi8%kysMtCNUKX&_x(<9xqL=jj)hzYvE(nw`6%66^8=b$e^gu7=>AED&W6Zo!5YrN; zx1a_~y1u0T8sw^n?HkkEVcH(*Q2t#Pa9P2Pa-29}a*f}jth0q$DU#hh#KuUUUb^`G z>$vfztoBry=|L3zE8wBQH^Go@^c|cW(PYeRKR#10FXh$OAJiQ9SNLua6Aw9aH!=AZ z4kwG*!zV21{dunr`?6XPG1LC5znt|JmGJR4{%%Oc@Ndz4N66RNF;G^&pvkxQxx?SY z_hJ$TgLUq84>OZ4`d*doR&krjfDRTT*WW8wv^6_#iF3*&cKuy5^bZ`=7WDn`?UaXHLX37PcswiDY=l`hmd z8fs{07z&FrbPOobwmuVg-}(tKhq-Rda;Yaus7IpBZL?g72B*DNolu>@F3OyG^;WNo zXVZ;@6jKZ=S)k6zi$Btko4V?oE@I8bU%M|5=m<9l^hI}0nzMdS&TP{3*@jy~@ia0K zu$Vws1*_=9^TqIL!wQotWmVlESWx;k&oy$vB5*e^R1M$kG;8x(963`{KO%BFPLbYk zCDpzn=5(K8h12w6tASK`vU)74LW)uqKQmEE#S}fbm_(0iznJ6MjM*#5DyRI3M;V)| zx7B)9kmzrfBUk9zY4|fCXAl1R0}4 z`|+-q>957wp;_sH8_qm!$8hUR3GmVzyg6qsQCr`i`RW-{&n;JE{rWP_x^YCMuu?SS z_j-EicOB~&8yzmf!>J?75~c;*)LBJ>(7}kZo>1XnRXvs)K6=JTneKlbS|Ac7lA~7F z-X0{A78So!TfI+4G|If$QW``nAe z|BF57`VNt9(b2agW8$pJXSxony=r_^CQ{O@Y_S!b`iSv&rxOO?iR0{^WBJLQhxFsh z5EjKS^x5lH6 z>HV2c-F~Ve@~GU9SyaE-$=Ju-T^WqnUt_yt*RP(Gm3efOzt{5VF^>u2U^8>tHIG=W ztD+rkHE)7NF}wJ6f>{)Eb8b2LLbTb9^sg-B}hGfA$W&~^I&OiI@-*lVLn0z<=~dn?K@LF zEfQ+f$dV)%BB@{QF^pvC-HXnu4<^d>s2C6A6<#&uQf!y`FKmtKte0I3F~$f28<QQo+?%K0gUk#M(qK2_F?}$bCI|fh}c&Wm2+=g}j za@$jh%_jmK%7zN0gJUD#0lgDPPBK;(P*7XtczHV979xn@6p_Ew1m4xftECAi>6ruC zjZ5Q1)8sKX^1DSlBS|`bPXU99f85b!c*lr>3(Rw~Z#2o6&!!21ajX z?lc=B`qPJY_S;^^z{IzqkV0ljr#C#59cYvZ8au|aKQxzDAB-}!xSFVo!&Gjt{^Y7`?dLRO`4@J@EPmJ zn@CmgM9qjG_A+G=;{tH4oc8sVc5gKR@Cl>Q{ zynaePYDFB{1b;smPZ3t4N!uF}^mRqStRRcFye}(q{Le~MVZ#)l490DyyJ*t8Rhh`7 z$!Y}|Hl8&iQ+EP=N5?ok`x^I=)JGDIv&#GSrqZ=2*$F{kws{`RNO(~SETUn})kAX+ zbHBRfMfbl8hP*xpv{);E2LR*VW1U5fQ8<}F9iPS%o-|6ftGJzFK#q|8)P{YP?+NG{ zQL*Sa>zMOLM{vPekRb>OPwn(LXgJ!>_lPz`zleSdWs_V1>-g{h98d5IXx{$Xy{lNK z1k!eouT57~UaL|~dgWW^1G%$OcEisx_Qy*DrOkkv%Eu|z6?U4}Za8~OsJ=o}rsCLs zQ3mCwkKEtipF3zM8EkS<<(G&$+i^yp4z1hEAHPOC2{VycFX7Qg#NypZsC#fMt~xhr zq-WjnGvE6TCED2S4&~vsmY{1iqAUQ=-AT@C2##`2%6LxkVAO7lY28nwxf;;3x4&PK zp4c`a(@0qoTedy#ffzlGv5NtS*ZTHB{lgTw1Q_UWd3SGbq(aJkqm(^>hv7Thyx%c> z@x)2qxam4C4oD4H16!E6dTi%puHh>vfV-|nP~mE;uuW6%qHz!tdOp?jj;qj(%nILA z%aMMz;dHij{IU&-QI0JeRj#n%t^xZshmwq z@w-<)-hWU#qr+(dFD&D$3p>LmjuSF{ro`4EpXPn%Xx9xt-$U37WjKL)@7iCGx^5bu zHBn*YOeT~fWhoE-=-#^8uxzmk7?Gq%S5j4k(N~EbK7)#-cE8dy$j_D(o84-z6*zn@ z;?xvnkzEOTNu{vFr95b~Nf>*_fQb5)Cv>m-ZPCOSTea@+#rUx-HDiD6y3U#+Qe3#D zL;0?;8b>2|JaoOHrl6nz_4(?uakCb@A`YW3Y`BI}T4ye}67gbq_f0acdR1!Ov%YlL z`dKw7r_7(XS{YR5xM*VX%|a!i?sG@QO6Jvj;l+YlW>HFc#R`?RKb;XgA`9vX_nEFc z&BNpK{jvnCO`xp@bM+N)Pp7u^Q&e~tWqN!Ndk$&~WUcKpgg!!_-s>sl(wG}Q1O3_L6>@0+p#0}mc7MO zkEWBHJ%)&RY}c??xNnrs9GX!lD9|6|YbA8A9bMGss5rtqZX9BKB1o6D5P>>-^h1n! z&yQ+xG570v)t1rdwn=ns*_*dDuC@F%l)iC0X1e!>oSO3*{l-#WSB!}Q6hC`VNnZ$$ zoZAlBDX{v?IAFwMeaO`7DvIn(>aeVSNQBI-e{-6uZYgiDfB`vz55IWg8ydeWxj{Nu zK@w!P?h!4mki>wQge@9I()4+6XxTbf*tC(~6(DPXagHp|wv^z|E2Db(h%Xt@n?{;8 zWqpml60jN#S7H<=ki+@>Y~Q8u14LcIcRke#YkCo^)uZM(Q&nsGss7-1tjT)IwP?Hl zMWIPgYv1l)YR#i-7-B4X1{2hXMqg&p=Xfdk-1FR<&Cvh$w5de2jsimpuLGdcY-g>I zfD0z|N-^)L=m1gtul{4WKu8(9-M=u4B4KNBRJ5ekk7j!*&n?=-P--kjCz?A)L>c;k z$FPl|Rpt0Ln<=`iezBy4X(A<6juzf;k6bLx!~#@B66Ohh8_0Gk-EJ(0eb>N0Lp2(Z0K*|cd;=bKga)C2Hf8` zlk-DRCVPcjr1XaP4Md`~w77Bc1Rb-YI#Lz#oc125rwS+6RT^CuP$S4bzfHoHW|~$4 zR9WCLcAhQv9|T8*?xF!ySs&&XWOt(BkUO6fn;&Yw*W{6+69Rx^WYOo;f4YpZN+b*z z6Th5~`(*C>g#7Q33IZc_`2D@o_Hq~Sarlyrk55lwev5ZB%`z`8>AiVV5q(j9HuE2d zdfc~&uGhyYGS~*AX(f(0>NrHhQUnyf!-Hn3)@7UeFj(kxi$EKS|3;>ZPpIrq4iR}l z(sgJMY7?<;{;?#yIXVoSx*q@_$&^}vG9S0+5Dod|c>tqZk7Xk40LZK9IFL+aTevxm z(Nb8m`|+`}F3>4hgNp<H}jx2o`@aylUp~nEn`Eea-1-F%K z<5hICS!M`=nWueaFm77ve96Kh1|}mkg0=ERcU~K+aKXAG;-FN4fI!C_Tx$Roz5>fl z)5EK-AOe=Brodo%{zP`UU=!7nM-@9g_4sn>1ALuK%K!X(#6t{4?x`50$fyKmnH?4! zy5kD?N2YCu$&@+Z9>BQp@5dX0iN-oDZ5I8>EO7Jw6>HYc-+K3r(_s{ekN z?A!?N4e~qu_Gt&RUQ>IB2dMq3q0p`0XuwPg2V9K*2K?U_)Q)evKR}3|`f}N%-nwyw z=e224-k)AHtWV7iC0+OM@Dw(jQS_AiYmGNEw@-b)2U1gP3&+3)9TQu8mB+Pq+PbAi zV*O**4$_Y!(uaCAX#^xJ(Xs+Y%34?N+n zHQ)$$oOY+Ev8m=>>;!^2|IUm|JcU*9V165b7Y6G|wfd}eZN)8pzjo@l<-9F(%L6-Q|=0d9%Vu^Y&f*-sC6siq5gB4@U1y?Dvqqwr7-s2+bIy);3!pgTJb|9S}KoE6})tSRe{-{Iz~V#%I->3`v7f4yUp_+~z1C266`{bt+Hg z5>D#{Gj59=(1N{qY*K6IanU*URHDt_OY>X)B;DFeg9CpkCa-4N(~91yX$ob$U|wPL*ihc3_n!N}eQ1-@7rLCU^D(RBzf(UvDd7#sAY zw}-uA*!1co3Ffo85XU9xI3CST`_!9Nzs)uVBKnTGIbxrDym;=IA`wJCzP6C4+!A`d zRhtihvl6hB{O7j6l8g+BaNEWozT(?A>WS9CDtI ztaFIE*h?#Kc86E7ANWCw-ccn`J2y?%-UMyLr`Q-xJ|NiQLvtJ!nric;_6XDmLC=+9 z#L3i}Qaq&5-nKRFBF1NlhRzxllTawsAk8&d+{2*fe(_ULpQ{rQj$W+Tm3go02Je)L z)>8!#4KSfZ>UQgj(qgN1a|e;Xd3=TC)=QXlY7u`-=^V8~1xBAX4?Z?)soHX_ah)vQ zI(!&(-?>Gs(yTu0vp?0z85ICA232`$Nj_NiWP>aH-H%g*{M4asinW-?sL5eK%p-Qf z7kCBP;T`xGuHa=*hksOgdfoY=D=}40_@zn8DK_Xvr6R!=<2KYISCuL!Qi2kmyTiMc zgI_Gi-_cdd<>>-iGn$Pa6I;t4S)BX;VTVTQ(O}!1$C%(@Q>EAF=0pVocq3~2VeS|K z9JUIbxN(v`ZV3vzSJYS}SG3rdw+3d<#rVLDy>FNkk}>h*#73M|%TQ&xdzR9XNZs=Q zwlM1m=fa`TGx0ciNk4#CVq(d$c|x}J1yIAwxat@XA{4^?j#K(&7kxU7l)tx3?vW0U z=_Rs=Z&CH6K5#rV0;eg$Z@+c%)8DJ5UvL*RPC{k=n83FAXrx}7D!yp1L-`!A8nTDs zW}gdC4|Vzsw*QQu_Af7vNmdxk77`qd+jsEZ1@UcbC#1^tWz-#rGlZWXan8X1;DGuJ zR5**{JBt%P$A447sc;8kH5qt+YldII+t2#eZ2FtF3Hy#^fm@LQ<{<&OT_7(eVA3lLMd=q*}w zIyir$23n(tU1EBQ?$%-yRnl9Tn%ggIi@?Ojo3=6YC=)924a)vVK&;-&CclB+e}DdB zl7m;SL;3T?*xY%Ju;Z*zRfW<$Y&Qz?K}hmlOWuxw%J&*_no=5G^ zU45?3SsKu^vlA4^xd_#_s4%a#zw%iUTu1okww4t>}Ql62}3$?K&`C- zK(zJk$rXC-SU_TPi$JLde+dA9lr|hes*Re=P5qZZ$b|qQW9$lF2Q-_`sZel-^6UD* z0Ge;lqU9g^?7fk~n&kK%&_}38i=kr+T;T37GF5Ku1;k@&{Ut5{V=bH=%@X#6K)ti$ zLuih@ynU>KsykmcIR>-?qU<3f`3?u3oymJxwk<(5v$Xd6P+j;8b|%vkqn~f&ws*2F z(4g&ti5Sl4q0}1JFto{RN_^|uAwO&BqflGCUWQNlabcq9A8c{C4xkSObZXW;U9<1>XF?U#L7W|4>j9}%^%bY2&k$*rB8h~E_}yHdo2l80+hKTZ&+mJ=^MLgzwO|e%7m|XXD9lbu@m$5iu(pwS@AU|4KF;}L}56SPY0FUXSV(9uI>6h-H z-1q2#{W||1iG!9)Ko>?`zz*6r+pIHb>7m-C`qg!{5Af&4Ii{a) zhUF^80M>8-2yVx`A1_C))=s10A<5fMXRoBM+|`_&4_=}!N`Z(u&GzA{>F1vuA>3v#1y*ZL zQ}y3*#K9z=u@vrg;NmAPty$Dr4o$Hi^>x4YiM~mgL_P>6rQqxs7+3{zV!fPfd>k6i z2i9(z-RhD7fx|cwYm#lx~2*Q>~ajS$g>0126T4zBXp(G9&3Wd-7YC<3xZYPOhUh+qP@PpqM)F@xw)XEWV1hZKd<|`_rsw!=fjAe z&S;8v9Kjs7Zw`@wY3Uk!0o`eGlI_Y#m5bwY%|4 zzb}q|&8!A#kGsiqXKEg zGO^0GUaKAuR_^}h&!r%|^@uEm|GN7rMi**m z%%O*gS<0=`{l z*m&`CZ2#JOivj3{wr8Kl?cL}jEg?^@Gs1>I_973X(?iw6-mX>vq zrZBC)ARqH~nbK9H%Z47GoDhv+?#~cM{1b z1Is<0n5O#o>)!u*5~wzKIe=GP=V@T~ii2l#c6;F#g?d21RmLfX5HlFvI4T$K55Vp)SpS>2YD z7Nt>v>YF$q&4I$=GrTuS9v&WE=$M?sJg*1;E*!Qj__pPK=J)a=pm-&$*tZ=kMBVv- zwIQKYH>ViJ^Y5^1QkL#gg-g+31jh#OZi>Y-u<$d+5y1FcO#hv!pZvh+kNe}*a+!sS z5(>Y25xilI%rP98e~JAsgMDBUeIL^11??OsOPBl9YL6xRwWP$_{fagGf!{Qi5wQ{R z%^_O|7>MuzBtSOS5w#J!PVGfI(^McaSPiYO3AogBJfM~FJ2|6wJm5*xn087P_B$MM zRu4d2)MxqFPIP-&bDe{GMvX6Lo0AIb&Iq%+D(*LX9;DUVTmaXkFDIH^G`*Kk&R}V6 z;F&>>P$I8J2CQ^#y^pH;4c_Y|qy>|M@wRwI#Ba`V)w6$dRg~H~=N$%dXGvO5!j8EU zouB?bU1BQUYrSJraeCSj^SBb!+n&HPZc^ver7L-OOFfh0`P!BXf~SSG1wD2AAv7A` z>U1Wc`I$Cz4P*{4I$@yvJ}(MjtR_;wGEB(UAYr^!SOtP%l@^i{Aa`p^#Q#o_&3?DH^ZjH2xeqHktTR09BUGw z_{YYAu_L~KRq1c7hNQ3e)pO+5TR&j!xgOihA(wdck;;fw5VpB~yNjV5o8Kv2vgGyZ zTJ&mxiTCEuuXO}tBnfAPx80Y>-fot+!hiY0I@kTq=prLJ^SLBUQvN(c{8Ai}@{q@( znA7{{ua7zerLeX}b%b%;)&_~bzwOL5Khw*!`ckiz(Zck4Tw?LHS3@)G#Nu->q_D;7 zVYV?)Z#Q>By8caMTO_)tg$0L*&NjZNrV^^G4U@S4^S$23nWH3@f~#TCDB>*XGemQ3 zf!RK(-raYV0rLIv4Q1@o;pToHfFBB#z_;~dTNY0?n(A;sC3Q5&-pQktpiptqu)$^@ ztZd_1QE!)HmZB>}iqJtWs(OGZ?;;|Rx|8CKgDEjf5U;fQrKZ`_a#S__FzUOfyf?B( z8PK)nm*HR7h*Ln4;{~Iy1s~lE3*gw&t?KhM#l(8PfzR*OLXxD^&|W}}qOip&32Scx z3Y{y@Vuf1sr0_dFi;qgHPr3`jODc7krpraZp1mV%VTey+qvtF%Ce93i8v{duY=(bF zLZg&A;m~cK15Nm!;O1V;gYJ zBS@>Ox3AXpIr!_xRujYSY%5RL1gK47i0sx9QzJw7>o&d|=RMT*cDL}12_FIl2CMRUz_Vp={R+|-1;i>XLYPuGm2M` z6gO#=*?uX5Q(HfgecHQQD30fWbV~)M-qtN$u*5}@!Y<06+;>v0fD89@zS7byU0w}7b}ZD&~f009_e zf5z_zFldVg1{$gP6I6*-TqF}(4}3dA27DXz`B^y<854cFWN{d-_CnVQsigTxp3E=u*|6J0h!w1GRjOx zneTV4xpd&(SI-6t=EkM8la}N(AALJY8_=zoNk++p_f`oLT2!Q{0?+)Chu4zeB7cqb zHB?xFa0qEU8N=7$PaMHHtb-J73@ySg1{1d= zNfXm(=>Bdn#`zL_jE!NMupCyEW)&~5%d`Qrtps zUm~OC05jD4hwRDdb<|*uegs5J-7W?IC1Ai^#I@@fKxTw0I)h0P$kVZE4w}F<#?s+t zZGG%#v90IG%e~p$h+8t&Cd6hAiSFXBs9Vr8Niem|9Zi@|P&qIezuOq%<0+EuSy@88 zZutL8<9Wd2^yAZ$YiSW~nkay5i5o%9EiXSEzIt7GClG&bB5^^!w$%$O!$-bQ?LG~` zTUklE2#(t_o2JAe0vI_0%7DSaxqa0TSX-`0TZ@$-zzTb?vHTEe77;+^Jqg|#@rn8X zHV@yLh_|ldey!`DpRq*(kL67=+kirgZV^~!C7_e?TW*W`l;8hkIn@#~M~6{MKv}Wq zGcM6EZt7~?ecGn+rjT;E+L$vDpsuz?EnP44D=2X8h4!2u4ljH8eLiVaVwr@rezolZ z>;oY3fsE%-ST{l`ioCEfmXsAUn0}a02p-#9b#ElOT{F&m-0kcBYB9ziaUX?mbos|GBiXV*{C_Evd%|Nj-2RM~YX19ryv((gti#ih#W1-<|1}5Xvz+rL5Ff5Yx206u)>5zjcLm7IWjb-l;}P_Jv(P?kbZ zj&D;M7JdN?7ERqRTD%r;>tB3Y_b^>XR#AiI`wrM^kvXPpEBzM}JE@Ke(FC)|Eec^t zNm{`#F50~kxBrEKdkmuQ`D>T*+S?N|j_LRJuO_>O#GeR-*~wYvsAPR(0s2bsZjV4Q z{1*&91z>QBdjSN7&NXfgAl5TN{YJ#9sd1xAE0mqJ^XpB$NZ&z_Ua_Wf|Ak3C0Viwa z<8EF>W`@!A%I6U;60NddS`eus+#mha9hH$$`v2|yJOkez2}o46sD`u^T&0#G-M>s50>seRi>yIcC%bvg_0r{v5mUPon=s}s zNNRWVUD;u1YFO>zthdYH`KWm)kHwYr9igBcBNcTS#eX#s z3WNlgY^>TKW6hcFCvyH1)Q1BN_0vITz4t!EsG2dZ!t{fl^27I#ExF3h*SJTiN@`f* zr~*wrJq?NdzjhAY?*CU~5TG&6jErARnM{WRU(4G*DEby~Ed*ReWci={gf6lGfP1eUP7-DNj^bdi zC51`S!U+P$$GiU+VdWw_iCz5CC(Y-3GGY7snZsjw=ZoIFnc?@$_}pIK`qwSJ5Aa|~ zQoa8)B=1a_>lwU=nf2r$^Wb}jkcImlW z%o(|BFMLyYnv&BgQtqqW+z|pS&@5w^1_F1GTuen1K$0UbZ#(LK$@b68 z{WVBVsm#t6n{@Mx`)z=X1oz-qwW4-6KQIEme%G>%?G2IHviJWF+)y&>0F*&VOKxsn z9|c_<3{^C^0@W(!-UV1M7Ziu4+mKVkNsH-HUd!S8`zAPd-_`xDKKpSg@VNcF7st6> z#Cdgtmhk=(Cr-_$rH|_MKoRDmk-Ku!?o4%oxjm-f@cMM|TJaTnFS5FKTm8KzruZLH zo3@ySUbc50^M{Yv9%e|OFOhTA`J+ZHPOEijbS`KwHsyMGZ~*$4*>Vy6L5fS3Ny?U| z1^w*RO1}gP?=PTgqseDyl+rD!?QnFrpL2EXdW9Ow(4H>n(GfmL-PGi#KFdft-F-X| zw1+H{;>tDf|E65db0~HIj~%(A=Fe-djC}ruTPvR@wffBkLWjD}X^~bsH+_A{f<^Qz zv`oKRIOBobOpDKpz9~hBkc2FU$YiDks|>aZ)pVB$Si|u~v)e={ zL+XV8n~?rydQMgPZJRC+)i+9x3vHl<(Kw!Q1j*G8gej*6wi|hw5`8$_O$zazvUNpa zci39O^;zgWR&p}z}GJ0l+~cTl4b!S&7R_3V?Vg%3gOxC z?H79GFL)k`v|Jv2{7PzF9S*vtK&~=9m13kw?;d#oH?Dvuk8-PNtTI|o7Nkv(MYL6? z++#pR@Jh8tqH|@m$UZ;}Qbc{6OoOhKbSCu)6}|u~Ez%SW0RvSJ)7uw%L08|xoLeQ& z39N!4JVEOR81g9oEcaz;UrRn@_RY<52rYCAhTOp+^4fS({CZL~V(wBvYM2wqK+v~~ z*^jk}yY!YzUS56bd>Gcoa!34v2e}1->^<~Q2TzE35r{}e#l)+EU;Tc|m#91|V?AcN z!Gt9!l)bc8?KTv=&gjSDp7??I39xceO-oF>(%?4(aWS((R8|Q~d3zG~6q++(Fp3an z5#FJi0ea5J0dJ1;ZsQ4yLqz}gX2W{F>^Pw6TRM8h>sdU-det~<-<;?s1=l<&00@huB>4g%Le}G$}t#V_gzji53;0-6I(e@ldJq+119g#R_oQcjEzb^$V z`9b~b9m@7(<*&y8fB#UW`GqxZx%VwcU~K)S%4*Wuz*4`Jnrzl5P-s>KSNTsOkE{90 zl;&S0HtLS1*SpuGQ>N!;14$zHCLp^D)VDNWW?q`veYw79M|;IdrUTWk743Xq3kpiZ zz(66k$b$cz-t~T#oqYh1yfMD$v-dneJFuqFU#&$trz7|BI89pe>IVDhdDNr>f$VY8 z;x3S!<7qrbs0IYOB2$1`@8jhzP>q7|;bn;#BcHYM#(k!_#aer>o{W%hFOrM{dlE49 z0PrjH>B@@&jVw)stUZtw3iO2WK<%%(q|rz1S$;4eyJTY!tX>Bm*dF$}LXmHEDK@#~ zdh8WRo{S@e#-|eF4RXHQ4vp3?rs-X#5PPw<16sw#kKHyJ4u?k(zk#I-N>C<>P(`w| zwgYZA8C?UPWS!WUB!XNo;+q^(oI`g&2HoY38`HZeVGhDAUqJW>k zx;8O;w#3BHvE>qod=00zbHakxG8+o*v?T(^d$cT*>h}C{#5j%L>qYB%Z0-k?>6}c~ zTeYQ%&%*0wS(Qcdhe39;yF96Exp=?GHClxPe7|)+iOQ;gdp+6D=5aQOoF+ROn~qi} zCCf@VU+dlk)g@jSt@D`7dF@AucW0arlzg71$cpNDA-#844H;*VR-ZN_h)^CGPD&o! zpzb(d#aO)-ZR}@X!M(UpaO!PDIkY%){3JYya{Ac20#fo?TjJ<(w+;{Y%)p6==c5Xn zWyO*sXQLjdw|!DvhkxNptoPHP9j~gQ&!>3p(vLhHpMw7=wH%~qC>a^)23A%6NmDf} zSCi>uCsL25J!s2H(Pu)hMT~NVnm?)#eUUfDkZAA<+2CU89;>)37Lg%*cxL#iL$h)pZe7Uaj$*UFaqwlztAjlJ1q{`O~?2}DN%ZL zxcbH8XcB0r$O7EjF*lSb3)nBfJl6#0O%m5sOVf4(#Q5i2hKL^$D`eOf&vudhwgRj3S zk3;G}J)+>nQ)(_DxDKL2S&&^Ql@!=9yoA+@ZOXM^%XAlBF6_cIg!2;Z-P4qxR0r5G z?nR}ycZ^V|h+oAPWj04DXGTS@ClQu$buGgn_63q8AM%_%{%d%d2HQ0{xKm+xxEDgw zF|kqB%ui$$*!`H$E*_n&+d@h&-W{SgCqTd23Gd4#W(q*W{CeW^v~~aEfLm^3BlxfL z^BvZCR}0)vxzF-7mQo(44=cZc4|=$4a2koky+bKyf0ADF2a{N5c6zMV%57-+D`XgW zDny+NH|EhvWDdq>apgLepfW}{>GiUP<%I*@vbR(9-fOZLic()KGgiSq`kML@S*M`f z7AQ!oZr!m`#bIC}Fc8J)*dlx@qtq7cy6YXO=_>UU?dW4U(8#QA2FH6QN0nkNU>NaG zBuJsmJCXXO+R8>j9Q7_@%xc4Hpyf;Fq9w1@ef2H(54h@qZsW}B9kOLWZu{48I8cSk zp)ZBZw%|`-2P(M-$rhd!{{jiWGW-TqvA@5AQ?h#oY-(j#SX_r{Oh4LCNFfQ(_1ygp z*Lpz9+N5Sd?E=eygb}C!YrE1m6!(Z}ziqgbuKuM?iX|U(S#oZB;V&WOs`TTg=CfU% zqPI=;a>$S=)oP{O{3e4iL(`+Z4?3PyBi70s6H7ouN+H3VI!X>+YbLXXcn8X|j?@On z(aUXpG<9mc;N28bQnO>0&Xt`oqi$C(p@FcbT<&H=xpVD^cqsA%qNRtEHu({7uy#Pr``FE^AF^*L=kydV>h)QiicsnwY!N$-AR zL}uCp6i+0Uo&cNc3@IRM^eu?uk^q&jcjUkPEF_k8+E7b%rAjfJrO4oce`QB7?k2?_ zf2X@MYaYK)WU|ets`XYiE{He8#rYTKL`@z}O4!_sp@U*>hgXyq;8*8$3IbYh1@y%k zQeTzLur8zuzXHl;<3_Jnjs$+jsF9@mxA;50{e+jMmhp+04YwQ zmlF;OU3=k-|1Dv}USpSla)Dled|x5y-LZc8r&NE>aEU{@Psg-+pOO%HF9v%@B>1h> zWg7(QZ~?{#b~}&zFf6`Z0V?Xl^Pco>G%Zb&Cs<%tv>*+n=r9`r1+0es(HGRX-J#$olSlt?dSMBmx&4C$(`rHPVh)+qcZkjh}`c2pc+&IOAi z6rxo49;*n_$!q*Uy<0uVH}FRo_m~$VDOfpGR3FFfh*nkQ>9Do|ZJbkNOI!8#9|$ho zW4i9j_SDiDUX8mTCXt539h`j{VHj_<8mJN?_E>{{K8^|ZR}4MBM=~NytkQ#JbKzmH z#vU5u-orPBT03_j367duJ!JiKCz#o6GQAF4IlotB_6BxTSh zEF}B;Utw3kFQ(WA^Ru>SPy30lPm8n?&q@haejO(U$z@2E6!VT8ET-bgi< zWV*ro+r`VLlH~#Dhdt`%d41mBT(pm9`R#IlD+btE_o(L36MO6(+PvflGNe8^kGw;c z)R>&{?GIAIx&v|l&I;FOFOXLKn!L`_sCrK}%HdG<@&e8G!w*vrEwgniSqHeOgxGpB z#xI6k@b~G-&<<9mMKgxn`KqSB5&n0ti* z7puH>X{~k|)?a!8Y@vZzn@hz|q_9`Z@W0eS7g_9n^DI^!T$iV7qn2J&+K_ErXxNIxaf2K(CunM4w_+udIjjM?NXC5z22Iie|zO z9unW~aX8()>bp2(FKJTe@kmF29hLL^H}ti;m$If`ja z!B7W<|G8rPaBeAKemFEGEjeeo8DPzYE=H;ZehD>(FPZatD0iY{3Nz+Fd^tQN!NczT zoL0t0YxYIXIH^ZKPO{&cJt}ann^-A^Fg+_vjL;V0fQlPWWFac?5A1WyJ0HrzLO+Xp_f?#pOAG%1Dsz9aiNy_o#|}rW0y%m? zOablSzy){kD}*Ng;rkdD+?Chzq({dy^tkF2#{BPHa?hWpkfI}aLK}tm&+*h!3s%QK zsZsoR?q|Ogslq}|&dtM)G?*UtZ6Zxx9Udo0$fO3eZUpWvicP^kCN z4eopHP_Wji2g{=f6*!BjCDg|`#9cK_~f5XpA^RGau{Aw^huH&l7*W> z{b;2oE9C`0=?kW-1%Xy3^B#+YhIot1sRPNM$DGryYW$$ea|L6+r$Iy7EIkAGk0>kp zt-~tSz|RXXuaN+DWb_ZK#5I;U9j-8^jIdN!SvM8SCCAQq2R{4`*m->01fT6~`|=2% zjU(V%&_{d*(Ser4eog)z6QJ}JevgjgY;$%s#dbN@aG=432-vJOi9@20Bzm%b$@++> z*?pxRrkeW-IW?X-Yz1+iTSo{?d<^(7`~pmy^am(%)ai$tSo2uN6Tf6!B4 z5WgthX`cqY#3UdZ*e~e7Tz}aUIg-+3X@DC;7F7uGr|YITRQ!-hDj~g z#?cb`m$lSlZ$^rs1Y&pi_9wRjYdJ{3#y|0wF0a!k_{`b(P0Dnh`6 znR+-~lTmTN;pyT6*FwT~;|}G(_7ps=b0^Q8t_}6%u@76g;bR;-2Gx&0zV()o&Co|EuyAu;W{@v6!}vw*HVuutCCJuxk)_9YZgH2#nwUH2rvCFbseaA8?2)>8^p|axx;nV@9@8N17VU z-hGM&PV7s>^2c!or>w}{SQKpr^Xf~>HbLvQ=1__!#THfFsmbPyNSW@JTzu|+#~)cy z0k25XEkdp&J^g=0D=hRw}q3o#?*+$*OUrF z!S_OTS4I#&cAo-e5C@SCI=44!{oyT+f`fsEVZF&mN(iI zFTo@kY*5n^fz3qG%Y-avXj02?hR(o2MHt9)*6?_I`|+sjonmFHkGb`3DH9`KQeSih}b3 zxGusE8tR@KcW2n~wl)u>Egxk7Si7fhiCZbEzR=2}RT|~rj zEv(Ecd>AFTQ7eBhi@aBO=Mqzp!br?&68&FNPC`nVj(Xs@u@Zjre0JtkG)HDHjvE{0 zTBsdwhjMOF`viYh)>?9nKSnohcMNm_9*B%z3C%Ux%l1k(@uJP<>dm9o;j_JP>&9D? zOmT4zM88Ob>@0h4MPzBF%yq`SZ-0Z2@pgfi(* zFrfRi<3QaXwEaC0!Y$6~O!k zLx8&Y?y%m(zKZ*QvG<-)O|4Pas2&wm6qGJisRB|0NG}#zr~)EQ2-16(8bC#mj)dM7 zkSZV`AYD44N*AQ}jtMmo;69sk-Z8%K-~D&T9ph#ALm(u3Kl>?b%{AAYEf+a#Pi^!J z?;PeD1HFR>4ia&yOmmeevkX>2xjiedM{|oUym0oLZGiv}!s2Y4IT@5`-EBo()@^JW z;ioJg5o|svt67pNuvwmYC<~LoXoQ=e?!U&p z7D#;AO(F=A7Cuf>-@=wE*3-32)82sq_B9ZzD2gJpYAWm(D90GDPD&>7_@ifjUXtv( znac)3u+E8BajSNBDqqQ7PQyD)c*oyq5t%-?{Xf%s0SF8{tm_0)9PtP?(x6@bc?RTt z1_|c{1#@?RxZNw81ASe3)cIT(&_3wUFkgh7Vjs-*>9-sPL+pL9)jbcR`Td627lD`_ z${RFxi|dYIPb4*Yhx_zI9s;=-7W;3-#WY1-m~ZT^+%#ngX}ru{yyWXJRKaI+T1pLj zFes==nv!MlsxX)sw%8?;d^o7tO>K6@P{dNMxHp8b(|WrYc_S* zeIIO}aPg=q`zx=4o2i$wslHHQ;wd8A?F##sGeLisxVxDt0c~QczWF1+4zLa0CN`4~ zgJ2^26c!gvuMO2SdhmG2_+*leaCuUladtKTP4-6c(7s2b!_^KgQ$=E4^4kK+Wm^T< zj4J1c7$T{ecQ(a(NfR#;fDI_2r2vnlW{=xF=g6I=v_9^ZRy@V!|#SjPq5ai z(fsDugR8XoVQMj;M@mZfE0|nGL5b~cAJ~*D5C7bjvC{+em(m!U zYzDH>Qn|kXzNxoJ_=?w-S0UTkPE-UPxpZ5_Xw_l3KUW(jk|@P4p620OF@<+D4E~YM z$sBt@n&@3RU?=HMqB^j@DNU{7K&DD}M>H`)YFdT8ZMwJ~ z1Ehrva#}Snt=QOm<*Vv~c~3jSvVX_*UQCR(!{=o$ zhlO`NYX!;te8-dzp@29yU2nk=qcfNkr;F@mg)DK!A+Lr@l>gK5_ezve9?eL zpQX-2xh=LW{Dc)+9MrN)3e_D+DS31ar1Z3xG-xmB-2588-txz5j{WHpm2USv#NGqp zA4xI0qhD3tQ3w;p?Ajl2%$eQ=xPLiiip1_;=EU+i9?4nv`90x@7+s@36dXY+LaHR8EOUs1{vnlQ-*kkhMc6`;k z&=yI^v8h0pY1{9U4fAeUE>0mrL2E*^>pwx+C0QkTQ>0FF3Dm5O@UOIm`{**K0_}QU zrA;I?tPM}1-O8=rzeRR)G4amJos;J%w;~W`yKz?|9jbCnt2&t)Q>`Wx8fyvE^!gbEGKmC7 zzF0B{fS(8Fy3mSTe$MEh2k`w9v9}rM_sl+ z>u&sJOZqEZRh`w2im!2Gg4f!6>4g9;P5=_XA4m95?mXyy@GSXT{-X2(*fbJ*#rk*S z(qJOJe7JQ7cV z$5w*ErtYLS3mkLGD7)VDhPykq-1Zm66a_;UT!JhOLPl~e;fZxdy0ac^PVx4wOK;>h z@8a4I7)4U-OY@}K;e~Y^Le$HfxjOY`+`7Wjjw7W*k?F`-)btIo{{`Iibn3QwtQwXX z+vkx%gRX|f=`D>N!pRQmgzDZ356)4Zc{io#u-B&?qP4vxq}dfGLR0ZyLrju!n7FNV z&60drvVA>~D*m}rMls;IMl4qE4bi|%t}anCu_3;=I-*G48*8G?=j9r@VZqv)Uz>7o zSsdcqrKF}X9$}``eh4y`y1|HaGAVB9N@2TtbY)={;mMzBAGJMERTS+R^OfK-mHtKB z@w;aq3CU6xwnc*^vfYY8$;?>@6D^jx#XehcNE#vwZHzX!49(U0gOarLdItD?Hs&4` zPXDOee@<6|zkq@zyxKd@?ZDAuL@=VkKzn>IC}a*ivs?p#$*m_E)4@Cw@DKm&Y&NHrE$LXR1=|GQG3o zLn%;6WV&Va2BrqK@-9O5MbKq+)aNh#()0CRInxb={oljGT2f!+i9knbr9f||g(##W zmuQh14ObbM52WX!(E^n3d8NVB{oP#|4GoMI%c?rvTV(89g3NYwQ=YDn?e7);>#1z@ zawM)5KX-*!!Q%cw%SG#3D=N8V5`O&odU6}UIIyU&h}edn3QA5HGL2VKtqbBPhg zre&U^6o-7yz-PLI%LO3qp*97g3DVs<9qJImM6(G*`e<0s`^2h!g#t@Xz!+-ztU3~s zsLeSd)W*2O5ztG1kodykK@cNJ)aB<6#P_WT?>tL30B2P;;iCyZJ*U>OJjzP2kG-|P<1BE+os=DssGUH>7f6M*6o7Mb_-o1t;xZ=KNSXk+`FzSRb$Gl zuZeY@>X|%A6(px5UeMB+^O0U_zn3W=_Ao|GLrL+-!IRH!qRct-eQY{4ZR+JtrIbs9 z(YqDf@$Vf`M}S{h%y68l8VucWj#{rZ?2{34Kbp_)TB~_F}9vwiyKaooV6P53bmK& zF5f6+3vf64Qih-O-e0Eb2vfgdlJM{7V#hdq54Ns~cE&RbZ+&hW`Pe~=bxD*7Mk_EC zb=>%^<>Y(_L{x+d{lczMPRj7d>h8|YH3e97r@a2!6t>IgSNq-ZeMuG)YS5eDPAuQ5 zIylAV%N56rPAAMTUr&8dzh@q}VkcOIFpt{U$9a4M4Y&j&LNZVOTg-fpv~yp{bHBU4J1-hD7+}HTmEygIG$qb;eVl z!HOZ}vi>*uH1frc$>ohLK!^;0-IwuAk&5{G9`_rHh~0wsp|F2^t79qU0;t1s6$9!0 z#tWn-bubfC-*Idi0jN~--Z*d|r*vnQ)T>*gq%$l2evs&x$#Q$&rPhl1XD1Kd^GCKh zZK0SKJQIF^xn{3k)YT*(h)+L%C{iM0rFQPK5hD)chGu&|mOojEP#I+MYXO?;?-4-} z(HE}5I!9ER6WPCZHE5^N-n3yY)SjNL(Jq5!6Gqmg0&GiEy~^Q2fZk1r_FUv9=?cZcxqN-XNUpL|Tm|%7S6t<9y!=u(z$svt!8KOkH zt?}~X2=Q$+$$JXgF!(Achxh05Gx8Xs7&i)p_7nzF8N{W+JL?W4KSru$tapQ6VfU3^ zpPN#P^vcDSjM0qME1hIJe~PD#CP=BTWE3vXQ`pc>+TW=w6F5j2ks*4L>5=)3o@Mf~ z+lGf5zo_`Y5#e^Nu=LhIPd5VsEJd|y-Vh>en9d+ZV) zd+#({loBfuZhk+svK&m!&DqApMaT6(BLnqneSUb6P(-zDl+#=7cuvwF-cK!)*ojM* zU;D8k{(49-9TDyE+=*fz>4csZbA0Eh^#Nw=nWB`s%5;G8{PWX6kBvjg*8Yq417m^< zTU8ukHcoadl~|}{Ta?uJcRKzLmGo^B&G2!_SI>iFW_vPVN!IMSA`OdA8?i3lvsGf* zNor{!{R8tX(dnL2TYvt&9T}q64^l*n+Zs%exbAP-+-DHlvDrCkl-#f-V>Tx@iNEuZ zX5P5|qicEt9>@8jdq_y&1O5%M_v|oV?+4r^XJkd08M?#PlQjnu$II%Ef5xifje9kQ z!gVJVF*qQ0_c&~I!o=F?BygPNi{qDFzk*D}eRd%pO_EFT^l{p6Q`g=3MH`|%ZcM5~ zwk2oYquC8a;>Y?UcN{$;%Y$Jx_OROpqkgaPE(}C}#N#ER0!c0gl;zJ0g+sDM3RjJ0S9r z<;aF82vN<+)EUGXr0gcEU(Ytl0_B1TvC40VPh>5L?Dp~@-m)go;|{Y82kZxUU@{Kf zl(fR{<0`iWkKiBcLq+YkL*n8SEb2Rh;3w&I1I-x4%sd_;jYSz@kN#6?>3c%9<0Wp* z6+eW9h+i)X?DQwNuv*i$bKZHKm7yc0*Uoelk{TyCuqb^ECg-vNdol6DOg`(S`UjyG z50|Qfy-Q3=u5!yE59dAPlcrW*lKI`nSOqsk9A-VVP6<%wlo~*{*USaGK3i@+?d$!} zKSj>oENAz~inVfod+cD$^C8U^mm8ku6e>&ZmF*b%4L8$finQGeQTT*(D|l>}07U-` z67sjdbe^AOMlDw)>(znuA12CjbI$Piy-XY>tI)8(gXvpuV7xx|W0D!malLuh!frxc zCr%~C_#z1Z?{8){Km7qp^rn;vha-PLQqgwVW#R%s-jN8)vof!q>>n7>Evg9djk(^& z!|CpSoCdv?c)SU3im433q9E1dYpQqGfud^H0uwAjYqw9tL0ex1Zf9)73R7Sig5?zCt!)?$hHONLu^X+so`9DKb44m+x|L0R7Nx ze*!*_cVqIv`>Qeo_3TfV0Acx&dG#I&`}2o1BmL^diHmInjn}w! z4*SkuvIyE*6tiwcd& zVk2Yk3(w=HzrUgk$@YqUoVncDGQ;b@`Z^)W;HWgwOLzkT5U+Xw#tLl*8ioA}fJCnEFF>Ypkr9Y%{L>wFuzrF2K4n*&9xn5W8|M5zE&$MsVH<+X%0+H^{ z+MOhs(|<37bSJ>$Tq@(jFSmEm#C!YV(TYqTB)#`e-*45eHo|e`#{MUIv zkX2;$S-Nj^cK^Mjf`-!pK5cU#juOsECQug{r+rS)zMukb>$xjdWK(>aOF{foUN1E@VBSwaY_kNqG;n$j` z4gao(o~~o1TVn1pYlMUNHg)HG5NEQ=&m6a7TEXZov@cIQJWJMAIbJ7XlMVL!uNQvi z{^RhO_e%tK{&g;3HXAHrz8yY|YD~=#Sh#-`7|x+#&0 z`Syle#rLOb3iT_APwPVOY*gA!pU%#)LK0~fy|sr9cyWf{_SC!3pi+Nf!XM6tm)Yoc zsBI@vU4-MXUBX)pb2||nB^evcHwR`tmZR8&pwyGI4rjrg?Odc zg=u#(+KZxDi-8_YIOoSP^M#v`;yD$MC(w9|8D%#PW=}&N(dPKpEbO)E-x>^;>7lhV z1q@c!g7}!%>!X#6T0=5|&Oop{25B^xx9;%63JRTkwwY+EFxmP$WTO^S^*|2RXu95~ zmmIp}Fs7(?`1I*Is@omfeg{)rWy0DB7&f+;0Rejv86JlAFLNGz>qI6Uen#BCAL)8f zC+MOXbNC^0?*79z|L7oPrh>!tvvogh+ud_fMgTaK9qniSX<>~woN_ILad-`}#GL`8 zA)h)$W;9$*DNcqMC`DE66nPgkOpWX4_rGRt$O9Nc2Oj~B)0*jx=)rPBZv8YQ$$oT` zHow*eEQKZacmt_VRC_t=_CZ(Map$_Yy;P~P)}RL-^!o(|L{peB`){~AH~KTmS;XHb zTXt9cGoGP#z{dM`e($Ms^X{4VpNaAPzIqeGc3%bJ*Lx>(rvc^e7R?dOr`G&!AThsW z;RD23Dt_%UPReH#$P8}ED`M)l&whBZkadw*IhF!pwTrTBtJsl0+olylrHyDpMrDW1 za!BH8aa%8JcX)g~bj{v@8B7dbgyA33857hi(wGAW>4Zd@Ua3m_4K9b~oQFO#)OrJNya#Vlg)TnI;gX3=hjqsm# z-hCCqVVWWW&BK*P$!_%U>V$=wNEuvXcp1~x;3?AnNS1#acDi{Jr=HkWlpnboIg;)( zY$Votc;hP`XMP=^6@q()uqgeP%U&BmOcDoRnSL_grBJyr=!)!Jv?T2dD z0bM4Mm#p*OT5VkCpz-`PD08ZAL#Vd&Ky)A1VW6H7DT`Yxc_f7hRvBinwabnMrWy68 znGU^woH5KwzQ~=8ZM>Cv_bY~i?TJx?QpJ`FFi&*DwB*?zZ8hob`YV2k--Xzux23&y z*DT@<_J7N(qf`Y5BXA2g zdGKZAvAhoQ8?C4S+sQb8anIOGZ&UnkI4-|Ud84xSJJ#ahfyn0g9n8Qfem_a1L!P$# zeW_Vr)N+nPEq3*bbhVXR%(O)9Ver8S<0^v=+0p(`qv%1}QKJ=23i3r?{QBNk`j9-v zZ4o^&lP(~`@)9>Ra5lZ^GQVPgT|wpK*z1(z9%Tk3Gpt2D1b3d6mWJgaf{G}+SeO?2 zz|X@ACxb~ekl}kaWy*+dSsPB@Jvi{&m!AUSQWe^XnNnr(7iEcWUwNo^*!=t~QU*R9 zs_+8aB|kS{i9_JA?@*N{kBaAjI(!^s25^XxK)-I<5Oqbh$ zS#XlgJDqfa<=@ZwftcQz6%uLwlsSZoTwzA}eiJH&XV$abDUV@&0hiWUcO4LP=NJOA zSDpt^4GkM7O~E>8yq))&2Dgj*c=2a-#@64*+0SZB4J2uG>J~#qRheiNga)Sl1hHXF zC%)^EgYH|!@(LC>^-tKyKRYI&wKnNuQImZ95kt?JD+z5p9VfW}B~|wWmrJ z-gTTADH(-eP3qtRGSzp4i)`1hE`Fz>MMXv3JV3tw*%XH zkj)Jq+f0^%2ZC#g5o)f493tWNQyQq~)}IJ8>h{%#dJm40$Y0d6+|w^{{=x-=CN=#R zAysWJo&!C><(BjdniOS3by-E8TqFF|&uC(Sfx)7fjr)ppzg-t;??@NU%GDp$9MAyDXWkdn zQOvc~txYvv#z~o8#>!mNSP!8(Wb0GO(l$Lu(#^y03OY$8n!<9RDT-n{&eK#2(oqs) zlIe>Kf`yzd9cMiGKTa%v;CCX-0kmYpC?ks+PW z&&CeTT@%@TjJ#ZSzf5~0MBZ4rFzZD?BRY$u^2^gu;UzoWvb`ClGNIP{TIhL_hB7wY z`Zyz5T+Uh2(SDO%loe<^-TNK$8r`Il`IY`yRYZi!&)1P5y_Cnrai9^cPgIc|okIPT_P<>v0Q$gePplo*+->Qf#r z#^`F+GMks62#PlDZ!#+_3sTQN7E!4>DX!5y;_qvK}#X3HJ3A`r~Y?`q!BN*b> zlqTt|7`U%U$#o~cATG5#f9 zd?gqY4y{U~sA;%Pp0lt9G{Rf%!6oPGLec62HYdxMLa~!JOsAsvp21&J23uL7NPaS= z>yC_nX5cX46wz&X^%RcyI5ky@3sr18RCL!0?oU@7pWe|l%W7?52bB~^5z=1lgJKwk z+q_DpDgbvt<3%K~BP#XPRaHX|%%Yr9+w;GR!=a`tCGBY)@v@9Os&O17!zf}g*uc2t z!4#uU7>K_Y^&oqypZ8Jet#tvOlQsg~XCRD>_heBd(xL%0sOWTddU~(p(whnH4fSGH zj*$!u<%A}k;V4WhIEz4`z1o$9q#i_*gZadQB8kaspFzlB5f?eZ^a8{qHBt;?-ns0P z;o0RJgV7R@pHUZm%C3hls860qqX-eHsf89poY~s&qv9ck+MROVsra6nNYfXdo+H`g z>(xtRW`*=?QT*BOqEUuK7Ac-?xM~n47x4ESmM(HBE>ZJN%eGK}(U3U9hpK44Reo}d zkVVYYc0y-0Qxv$t0DSqECE6pOJH497&js@)LIbHdKivAv0LU7?PfoS}EtNC8LZYGrqx zM!{QfdO>%zqN;B8qwq<|G-qBL5U!`;-hrgY^_s70L*?;cEk$B0&){ndCe_Ek4dCS; z?uk@k^8@D-WIv!PkZUiB^oGaphTVAGjIA*z0BNli}1`U!$)!{UW?yR z^7#b}DOox7)Y3jCzHbvgO6cAt*b{R@s>UotEr-6)E!%vyhn{ut^fdF$z^)iM^*4tu z7f(fxVITQNueb54i48uNa9uTGHZcBJghYJAHt%&4(qf5_Ni@cwu8H#UeK@>$e{(7R z1)F^KzQVxjGPYeh|8Ri7HCMhf;a@{Bx#T*aAxfxOkk!`+^1pt|M5rlu&_Lz~KRIBb z&F4MZWwsKf4l;ZQ9JlJ!p*szRmC|qn*Rm8hpTCMz^_;8(cA-@oFa4p2cjZy0m-C?k zVRf|7t~;e2*R-Cp1j89^rXFj7^2=v@^4PZ24+Vtm_x?#<`J+y)J>g<}LP(SH5(;qS znap#2cPV|Vm&N^(bam3xC(CA@Y3n{cs(*^0OA%hSL-T&z!bM$XhfAJ0_@_LGK=NNw z+>A0MIFt@Y7@mC5k{)6dzjgB&n zqq78kI){A5P(PsmH3CRCx`~_QsUvpK#a9ZP79R6G!T#_BQmxuF?q-}<<9GjJb z(3C={sq#~lpIallH)ycZ=(``_zx@&fgy@x5K~$XoTQzBJk=7gFh7s{+uW~=E z9nJmYIP(*5RtKDsq#uMM%KnQ4%&>EtKsG2x+c{&YQenE$@lIcX#(1L|imW|AH`A+SB?I z=wo7eQ9Afr-Ik^EXyEAmoh~<444m!{c2xs4?>Xf|gzb}xN$O>}raG|q;H&b$B{nQ- zoEgosQ&Mv}LB89M`LaJyvAt=%`7AO9oKW3~0>uH}KARs$(6dIrXAdpZE3fV}4#+6? z31a)ur(bszO?ZZP47(xp%VP#u40bu#QG=yTDmWC~ygVHN4EZJi@e|h7^{6a5-q3gN z+`YmTWlDLlo5fcCAWIRe-ethgp=9?i`fV>?I$)ln!pLInJBx!Uaf3yvQI`qObgOO8cD_@E6_`Wo~0_q)$&x43m>J%3J-eS~c_SG%^c!^S$ zGCXvk8S2Sg#dLJ`5T+p=PQVG{rebe+u;PQVkhSkWk033ADUtwiz2GG{$8 zQXi$Jz^|tlOy7UO8vdi1qgpT!YYKom*3DH|zXF=a z9Qft|wf!}RPtwFnVSH{t6uFh0UQ6R`mbZ#A7!=?#G;N9A;r;Oq|F9lVP(b?=2O^Hg z;05MBFu6kFF$1~Hi`p-7!1mF=tjI_5p5Vk%%}xNPN5e?!pbb8!gQ{m9@u3nFyz za+38z1InJBd-O=#suM9$`; z+A|NpT9aolR$)L|Em2v?xWe+%c#wZFR6ef8vkR?m2fJqvv=Wt-De5Fq?TpE_McX^7 zEU-kRv%@l3%aQ#Js0wQiC$P( zMJsj6?{aPwMM2aK8bF+$pJ{x0n?xq;xkfa%eyIS*&8Lq1cH?0vPEZsp@8A{ z?`JVa`WOiNdfE!55*VBzchJA*1F|Z~C=M|_Wdczez@y6Rbeb#YOJo~>-QtTpV_4|( zbnBh`jwD0I>vc+RQ<}8M86ifbUiR^Zl37-SI^wJ#=P`oYySMsykEWAfm|t7=JX> zl07xYtwliyaHfr{?HMo?l+$9S@;u~?oN`*8WMzKYD#OP5P`6fub_LL)odgx9BG!sC zYHDgspO>r`HI(%8oCi=gvecUTY*NoL^^pIFvic6N#RDB<B<_B-K*!l%`Ka^lmN!=iJrBB|sJ;lM~m?@6i26!#kf(gBb~fIo_BWG7GZZ=_M4JmDWx)?h$-t7N|IHe%V~@KVlTHFm=0~YLFCh z8l(HgYXMSGAGJhN`{wt*Jx8H4%b9}F4_*TF1N5`Ip#Q)=`3l4XS3@)=_-!xtPh?90 zi+ykeb9rk#R#(cqgn}!xXZu&%U;veTgk^j|QC31z;dS zL9fEk%e^LHvABibU-m0y*Z89Bld;p@y!|!rl(J=a!_ULo%8Lk-T`T78a^rWb1gU1e z=}3qIhekTmac|^ZAoC?zHxzEBHDa!(hi+knc<=A}j~SLgZLf_I_WXDS#Q}XO;PB!p zh3PJvAMA2}{aTjD7maPGI~>@^1I9?%915lvN-_b$x&zEb!#Kq9yC0y&l=eDi>yO(X z>hWhwMvk1}G3g-sd9x(4y1B`%D`oyU(geg4BIb#~rUc|EV4p3(-;x9&@9LuT%UXzz zU2a^V&abLhtBZ?Aes!%sY7C1z_lwawmCDH12nB_tgRZl$Hm);HujObO&mU+p&k5;xGSXkNIj?mRN zj^z}mS^3PMN>7z?c1dWXOVw+>b=NVY_+LHCoc8r z#bEH5iCdh$GhSXXBKHaGoG${dT$5Lz)A&sU zh0136220={uh(}Q;SXNYe&zz0x$7y{iD_3OSGpmM=9`6d8evT6y;_v0(5Dap5y~{X zqeY%y;;fwXwRm-s=`Tx*XqsXFa2D@(VqcSg8~1ot=@c0I6qb4oWi4vo2KF~&aoV>% zb<}nCrPRD^GCt#F!xoA7{dOcrSbq+O9rj${eaEbJf4_^_bsCkUv2m zjP!xyAuWXTEa)tpa6ZqpM91uT7Tc_&JHjh2YMlIT)RF0uQKVB5lA8Ks$(@w<;6#^B z=xMvE4ZHjTS8$*4gaeVG2K~%-r##?A|!InWw|$!1E%-e{QK%?c8w+H5_|EF(0IesuOuzMuCTuX zdO3PhVX&$WU`y47*noT_Y}bO>(;2!8av_7w^8F`8CxbWTY5SN3JD#((adEA_|JQ4a zODsy+uvRi7Dt+qV_7GRjuyeqnJl;WqS}i=zkj)cjc0?o~bh?r~c9tH>HflI3eKI<< zv!(Aix?XTV&tHD6kQ(s#epkO<2WEDXpQ>QS1BaG|#ix423=+El(~j-7W+>e3(*F9D zTOz9wo*-Z`1z6tVzg8a^Qv=AYh?Cb1uY)EwucN zg<)69Bcyvu<#gf#5}HdFQXf2tIc+=8dMXRbo!_1KcR=;Ud~mYRpk^zO)*<-)CsT2# zVAXHJOps-bla>7t)DE;U>K zJ9JNsN6`9{!*PAabT_a`GvO-%vOe_c?Z6Wl22Nj0WCt~fI6Y^6Ha@nOCXHuRlJatC zY5^V%XTbkYp7{2~;agX3fMyn*YS%F!y3!(I1pJfw03z@gI6C+MXSWRP&PV>~VZgBY zCaq9gu6;>4hXsxW;y{;N8>fA8yJa8!oY+;IP`Kr{JKNsB}Qs&DPh~ zm#>eUTlhtPEY@$BdV5}NhIl4ct)K}YTjFY7&%vp%-|=F0s4T8WHeMv_{2hN?yUbn~ zq{^a28Wm#JlT=R3asFeVAO;Uz>P?-F8(Q!u$rexe_r>?Xi}io3G*d?wEOxMrq)Pj} zZT|OOQ$gr?zu-mTDd;h^y!Q|w5(S|2y?Wssc6%g$JLP*LfT5VL=Aq*803JVpe1#V2 z1<&6WkaeOfz=8JX+pBrVm)+A14-!Ibawt#LX<%|u{ZchR{k8$uC|S@7J5}dR&-(A5 znf~jwec_GR|8hzGmrHU!)BZ2Ng&QMabI(yp#xxQR0!PVN%kydTGnY-|P7E-SU2ix! zIE#wWcc^KGoiD&Q{Wh21MMp{-dI2vzA#V3cpJ^zfw;EVz4ULD?uoAdLT}C#Lv0!1O z8!iD;7-e8qkKJ&Y_sKthYoi#Nw=p z*O3%BbmEQyHgxkfYr$pqhN=}*lVy9(_4ALH%j>5~kqIthcq+LLkDUQJ6*pmlI_3%` zz^?b``S~sWy#J8XKl=XJYaCY(Bq2vNkhtA)jiAuDF+{J~5gx=WBowwEo&ekDx- zsJ(ba90xeYd8eH>yw--S%0o{6+_7k-Mo5dEbW<;_1B(~Pz!iZ&%<6T;6?bfNDWYHU zf<1`mr5R{{(VEI$PWOYA&4EUB);>Tx7JpYTZHQcjEbD9CVTNN*Nu;4{S#FP)e5X-j zXX6k=ekTB{+l7qfr!ocl#Mp%>whsZLq-#18yT*+u!GhxwH|E(8X4f`bw_C~uC4=CU z=#~Rge>9ANpjGa4BK<65|61^;twn9a$p$~aJ?;KKe-1!?2+kPyP0JRyUa{i|YDJ#4 zGPg~!oO96UO}`mAums~fDKAdf6RFmo#R8@D>a(|m4fxmw-aAWNY2jwZXgTph;D-HO zTXAFSt&<;5@o&g?ZVQ+XA<52w8gyoM+)@|YE>Yon-qjFD$qlG z?x9e=-vXn}=tDIk;H}N45stO8oqHr3*ndCR>UrHILSmtD>@>Y-~4IGL)tJ2;Ahw`_Csx7-i;Nk!#_4Yd{BuUrCNVP_A$mN2=6@4e+-0 zcI5vQ0tB&r*aiyPxwum>Us!TDCJbDIa}R|mihO~;&WdXP_tRpa!Pali{0E{}axr|+ z`}@sdx;|t$v{w-Gm~-05^&ohdT^U)hT9iqpgvQ`@2OmN-&iq5pqQes{T;IQ|g5DA= z9jGDkmG^EOH@j$pD03ANkH15=CFWL;_c(5v^xlp zw*{V{0m(i3_^Z zY};zk?r0G}$S!9^yFyEI?O8qZ?eh^yH3wG$JClE9;@ZuS{-DgHz4vW}8T%OgYx0;0 zu!&3+cbC0B@T8TA9Ip0?AGlLBwE}0g7-{3%AIW)MI=zcFxrqv1ThyjH6>8`KHRjs# zLRq81wl%G@^O8<)LrC28FKGjJe*t3X^B#SmrEmPVvQ5X{ANv`3H4huNr6XMNaSHl0 zsL4Mr`7j-nVNJzhRSL5O9>6~dEC0Y;ypI>Ry_}|fVn<`@NNU#FNhU`ddK9lrNb2BZ z%FXJJFk?z@)Gjs#1_ttb!h%a?pj@YDxD<9rAl3E!M#aYNUsYwR-*bCKy9@a_mnwgk zk2fVLhw~eAZp)qUVY$bF|Ew|HH#zSxR>0K)%D>Y2RMBn1)gJLGR=iINMLokJx@VyoT(<4*=lTkuuCuv3V^f5YLX`#jsAOSPk{+?I00p* ziPqOC2cBw{wSBOxFp=123rDo}UfU;mC8nlA;c>yD3xmhu)`B#_T#|@hKn}eA^wUK% z?ej~&(V$AA3T(zo`hO}yDO%}o2j2Scj)^*wWsQ|nzB!KQ-%q?sfGsN(!dbVqN{(jn zsm*ASQk*WZ51ZvrL<<-z#x_CMw&tLjX*vgdpOi`NQZ}lEJ<>8m7J_J1eAjgQ%dzF9y@*6VlP$qMOvuwI4(LAF@S!_B#n1??=@;$IH-mJZJflp?x zB4I^^fpzOMN6IUn?3x1ZTV_C>Fam56A4fR=dTmcG?To_WiFhH&0M@!Y8IT2UMWbaq z?+xv_%4e^xT>qdK!kxAA2IwV)b5drCQoPszUdLPwj;?76ltGx5>mS~N#bECxE0eD&=1+F3I5u9*pWlcv^&gZc_6d?mg;J;9_zN>Y z92UTN!v700zfHI03zX%2$@Wh|)Ag45fUb5olo?>n2e!Y*#Y#O#p3a(+eOxyLVi&`+K{9D2%% z>!DQjC3_mK^%4uR7hb=oMC>1n$0~fh_ds0!bLI;;|87T{Qr?2-j4I)sGc0rO$G@{a z3}@@>h)jD<7D>g!_y-fXw zEF#8MTCOx?^{FvI5?67x7-?wJHw#c%c^~Ys=>A;f$BP?baR~mln_MKS#tW5A)vdF3 z&pF*%0G*wiAFvn1<5%Y%0CM|gR1c}TC+wp$ZzSJ8O?-rM83#-?zl=MBUmeLHwXH{xSmsxpGobH zsW{f*rj7dBzce)Xee$;Qb}TjT8E^VrAP0KEcS5g&=vz!zOa%Te{G4wlQc`{e#5!hO zaq&pM(CzB-)`3R2lv%KIb9g2Be!_H_g_=e)V1zv!?=R-T+qqg}*#5cjGid$O49ixD zV!UN*#LO%(RScKf2>1Fi+QJ{upr-hO!?rOJp^N^Dwm+^mzBM^4 z9;bX!sF#W-4KCir>^Y~E%Th@ z$v;p4V+>P+yDs#_GzBmMhyiatFRzXN)hV5pNSd7iTwft;`?lO;itmpbfP17MS_n_=4_C=PJW`+K#@E_Zi#i@1%|RjcogUL|0wxVI(4MK_V>)~Bb3zo8^|Ng*DT8p-Py zAk3%!K+bm$SkX3=KOF}iF;yRU46YM01qtUm-Yr+Xsyg??d*VeE&KCU%d%K0%gu6NtFjuT%l8JlHqu+4wa; zaY)0S#A+kB=wgL&ZH7dub6uvfqGtfA+VlavFHsNW-bI76GUuj?cIiJB>V1x{Bb;x0Heq_h zkWKu`*ISc#BJoCb^KW|o$G4D&P@!W~iEnA-O9IXpT4bOmB#h!#0jDpC4=P{H%^gpYEZCIm{TBLdK zJ*~Ijw@?@M@6-VO0R{W7!Sx-uv70umK7OF*fRCw7!4W%V-Y)rkk)SA~>@%R`UIP}b zE?pE5NP~)}W4;zs%;3^diIe~{G^Sl53btTjvDyu_@v5>@D22srW`V%N6{KuVk*f8= zj@%+}LYCE6&VyyU^q8GL_Mk^n2kvo=6huG}q_>fDTdU_IYEtz4}AocS&q~H-*Wsc3Ay!FQZlsur{>zc5G zzS&y+rxX3szZfo*yzteuy8$F|8+;x}$9sDQPg^A-ygWaUF!GE&*>K_`EZYPp$@o|P zJLa3^?tle8H@fl2<&(!I$QB*jz)aR)1?nHkuee2Yt6g=m3KM^KJ2E4sLHQ(6Jbj!Z zrG@Y1>SHfnz;8$(gPm+106*;JWH1WM_Mp<(9^tB8?B%m*;u0d)K=(sGYwjHF5n!T= zBzlowc=K74Aw>oo)yr)?{VT%-Izdy5z=m_Oxp-jhFVRq$i-j^OVFL$>g?Cm-iU6)#_7ZvRylIQb587Q1Y4%&R= z0d$^QIbpM-l$8ms#i?Mq)b3&n`cIfnY0o0$Io+11D?((0f8K3#vK~75(gFmDY0F35 zvHF9Plk_HH@@qTeHV!QcS0UbzMEe?EO%Hz*E-dIZ)l!24AxB@Dfbf&jgqy7#;8MSf zxUT#Hmo#tV=}XXZZ`=UMYFN6Ex#G`1*YFG!9KLJPy;J8-H00N0Q$}_*{)-g7B~1zA z@7Fc~DP(!_%u;vas3ijybfbv8IL|Zqp1q4!XG;u}lq@vMo^V>0BtCD(xbXdvBY!7; zE}lxTQwg=j29eD^o&Uk7E5LFpD<_BDISM;t3W^hS_s@TB89rkwm?-5V=V@&W4GQ=I zZZ&92=e>uc4?~ns*NPjUqJgN)`LFl@nWEpcEi4gIjDaXdx1(DU4Akp!g@fmw#{hyM zW|Z1EJb&@eyVt;x2YmrUp@07a41mu6^Zy=DHPKZ=oSpg`h`Z5`*S?-^M>;7rW21Iigw!T{6m*i9ciEkBa~ICHEEC z+3&-Vq=@+|&>d}3Rpt--x^IgATKtgv-@CZ_1{ZIYZ~vtq*p_hw=vx>)OvKslJx?C6 z()#yfsyA5byWN|R?9gBsZRGY4Fs7cIV1YpwbjdOOTGl3Rt=eAD^*-`$sk164K3#hF z-`&LYi%i2ekMTk7Vo-PM1rr%NRgX!P{~3_y?qYW^x^vLQ{iH528MSCAC8k^3_t*UI z&*e;ld3P|eQuV)yphq)qv@_zcWNZjcwfNH-k1tv;XI+r$`a2 z^PzRnpnSS%EdW2t%lmIkGJ#DV6O>}yO8M_6A^-pURy3Gi(#v&t?IExP*Em!4y{BJc z>+Rn8{R5+qP^W(M)b{FTIH9+p=bYuH_DnXEa8 zSaYBK`PQG2*I;aPbh()J{~DJ&q!9KtpZ39_VZG0N@;F}4#672KyRqF5Q_z*!jrisv zcQ`IJk$IM|(~b4_g|B7_P%HKbdfW4$QNi}#UX1DZNiCtFG5%%Bg7HcHG7yIPGn z+3$3n6kGeqga11}PHO-fbH;1S_c?hQ*0TE(q9%N%nK8!fDyK%>_}7;%yd(Q}{m9-< z32U4&?K~Dh2`!55P`;iiF18FP)^eD5sutdch~ysf8%YT$*IK&iZG%0!nH*QFQ|COK zGmKDpPqu2xr1(8>R47&g+qf&*?6;7qFQ>7rm*O(Z>KC?j{Hmx8OOf7kZ}Nwg(rF%* zVcN3-{oT>L(!Aj9+W6WO^-(3}ci;7TwmoM`U^}BXFI-jqZwkvgLZxQu)76M9j{P|C zHt3qD486)m*60iSGBKkjM0<>lGYf(GTZO|FM?{{O*x>T!EmBVOeZ0TmzP@8E%>c9I%U|!9YMEBb80=bc1x0*fH7rbs!X^vUFUQ}oRRLe z-&Mdzw>(=XxNw>Mza4=|`vdc;ng-{%UD3H$X{`e(*iT}_Sm?&%vk%M)<{5v$!N z_SKuGdUl|v4|FgPe5N^7Wq9bI{Qt1`mQihW-`;4Swv;-3ihE0e;4L0pio2(H1$TEy z3k8ZxaDqc|DDF@S1cF;|E5Y3z@@^{UJ^yjXc*ngT?j85T+5OUly?54HbFQhsITu_f zf9#yHo21#fDWqAN+3Smg8OIeqV1Ip>1NZ?rP7WDSw1pGPH0wNroy38D8|)=kF}I_-Brn_7l0^=Amaik51tO9U$}JXkLTkR8G{gQD>qhG&+}mpq-# zul=2M51ZwP^-MTdi>pLW84zUdd-1Uvg?cc(EG{Fp9(Pq^ z#EU*bjFuN+$(s#<8o*~+0{*H)ekeF=0#2HPrr`+XqSa(2#L`g;;=$aKPU=9 z(S^slu058lJ+C*v0o4V&dFbzg2OaFA(?F~1oYQh*d)N!O7c`%8?ak$GwqCHW`3n*8 zTog}d(X{)0{SLrer|_IV{h|JT1opMP{%GPuwyhKZg6C$X-2uPhNQYRyc-eHMadAGx zx&C4^D6Q&hy^~b-hu;ZxD}$|+IeyTmLNokCR(m}oWX>9{B2>eFY)SX{YB38k8~F2^ zjNo!aGf?CSuEZ_G#9m(cy{S?rPv?VJMr)D34?UZ}0LXG|5Kz58FCS3F@G8~7v*HadF|G%rz68q6)uvp3BN&gIH88qYSY({%4h#aM%|7|5> zuc;AB96E91J8%dlh1W*S1SF{8{Be1uFXuWJ?ex|x=B?9ab68AKfxy$|V9M@I26R|h zFA0rZZrWtm)h&Ojt-w;xWvh0b-^^k&So?+7Y*s(xp5PU?7RVf<4GwaAAsbtqSBMYm zUQP+A?42kRXlRH>44JT|aGd&d3%^qadT{+XMJyhmS$Ukwb(X8106no7R&zP2j&dsW zm)D7zhbtCS+BF6+9@uiSJNx>~zChppZR~XVje;tRiBfiGx8V&F z2|=%nqu{QNItho5z&Rd!&bkPgJTEpsmHuN-3EZ>eG5Nv+u6x)RJ^}Oztu|83|_54AR|6xwNJKn zjl5dA`~340Q6f-9hV;VT@EW?bJAud%lZa2Lq>pa>fyV*Kry_nC-LgPawIKjCQ-98O zbx?Fw$hpd;d$q)OYyCZ(&g6TF_vlTJ2k&hJfMYh5EfE1mUieJ&irD!WF4~uvqlN{G zilz37oY@(wS*bKGFC5Z(BHuheE$sAIYV)4UVo}zDbP1bhc_xt_K?ZuVBXNvtKh9FO z=n+47>1%+%MeC_QeVE9W@@u^CcOAGY+!jQR^E&Mw5Q$HMBdHSV>>G_Q@WmF!9IYTp zyaioMpm{N$Ilrz_&PVeP#{k)=yCFDY%mQGaQ;mDaj{~# z%1mU+dq$p$JbqCw`2q{sqL#B_73NdbhD}xlj&(Ek?FWR#YP2*}y1Dr}s)O~uU1sbG zQN+l3oG8N%gz#NKfYxs#W$(iI(kG2y7Gi6kFoJ(@;iBi=f0TVI--RmlA*Ufw( zF5$a7b5uhu+R6(aXGS-(p=~_Zj z>H6G!aOTp#F`lKy2H9N`ozFe|7QRAi$!tASJ5W z{4=koGQj{E_>Ccn!oq3AVOBz zFNJ<+d87?I&{Q_{uev~q?{QHqaXCqn*EJroVtiT(m+yBEt^liEXI6*;%an?i-AY4KY>M*^ym5U zHpCqMrptEmsr_iw$0Fe5l67|a1)8yO@7f}r1_TEIV6WqFDyaR?{n?SxuCRJuo%8d_ z^eq#w`gEXk*a{LkwEXz=q^xR&od4}k4lv6k9%t4W%f$qFGvkTiQyv7;uZOQZEQ)h= zn3HWM@HW)IBeJvA&-7*L9yDW;j(k&+Q&tW6G8B_eTSHdc9y^!co*EkqHbX9_z?f8v1fH(TJ ze^`=$we)MX9|of{K5N-pj9HW}?x}q6MaI$dy6FaI=z6HYS?iULgc*lgi(T8=Bj>GY zW24_&2Tjdtz12rQx$(`4if;nEo9*+6b6yYi0|U=hPvn>H%`_kI)D6ZZv`W8(?Q(Oq zSu@TCk%HWUCaJof&*)Pc(?@!sTP+F=s(oZsZ<}A36Rjz{Qs9d2s-oMXp3%2IV96AI z&bbTsiilDb55}e0=wvWOBYF_C3^9|A$*{zH0fh8M$~}SES_mqOY`d9Z{-lH+^&Tj= z;j@Mm%)gzA@!NyYR(g=(()QW$SxlB>GoZz?mYAEh_9oL-2;zgTs=nWkKOv2N-|N;v z_J`ms`j#%t>cdJ#!ZEgXt9zV19U#W6kQ5Gf6AZa?*_lcT8CtB!Z<6gW=+qWxI~sjL zqj?iWF&DXL4%0<>S`4~W+pKnW6*m#a-1Eo{gZotPipxSkj2KhQcXUa{OuglC+}>;d zVy|109X|IatQ*{|hvSgQD{Q@>L(B=X%=$nY?+ErO;-K5lFpB!&{HL!yZ^EbKC89R% z4<|xqkIC`2Gx{&cmhb(NUFd~zHU$e-_iqx~ut*Ivs*X7|XS7(ae0>vYXoTtvAVa>w z&%CnMH_yWpLU13*DD~WHGiWWffM|-B*`HaTrk1~DI3;-Cv`bnweqjK`Q-4y>TKq1D zuNhpjMoaQ};Zrq}BJUU#sE7;QdS3<75?DptsXLf$YXcsu(mi}jyd(~}C z>Fwqsz2guK9JEsMJR%?uo5uMYztgBFfq+IYbE;V8Cp zK*faydX45wJtqZmCs>&V&ZcY~%QnYD=SV?;6epY8P4t6blQ7{13cUNGm6fK3^S z5&a?IYe@f+$L=!C^C`i}Z#MtwWya>MLpX+IO5L5b+h~m+b8%S&K$D@eKc5Be?1UW{ z?W^7yL@@Jtx(kaC-S7BjEO7a{g_N>lTy5exT|H=2M8Oa9Z=*=oyU~mk9$dHc!k9^0 z%(SLznPkMnEOs&L-SqB*G+OW_-#}nId)go#wj8|W2BC` zhZt6GR-c3jU@j@n2|Uf1ztWDt(GI43`}0|&?R#YNo}n@m=fi8UNNHR^5@cxm(2-lA z07nBv``zrrSk*HOuXU5H9Zx5Cbg7MKkredfrPhac5`m{mCE;cvumW;C%+C};EH1-E zYbxbU&_q!p^}oEkE_6@5*HL?V!rY_YU!&E4MeerUx}N7LqR z2=1bT9VsWs>)^yRaiwaFa6+%pmWqBcb~5MTTM>{DJw$KHc}}VV+l0lt){OMfdY=fd z_bCz1;8!$W$*OM9=F}&nuhbU2-PUfwYz%kW zWyCUvThRHNK)JkXvF@y{9HeFCtUuC@rxdw1l74_q-O+{r;Aa@OdFX}pMQ^hd5Vy3zRD34bLLV|1I{@Al(XWAO$-|GFF4~M zV1DP?S6gE{ctriVL&oj)s4-i#Mg>Cpm5C9`0QI^wj=8H=I`z@JgZ!rF4<$loh+h-6B6VLm`4 zN`H7A4VaHwJ8Bzzr#4S{Bg!><7s;w15yo7Yuc}PEByzp`Kfh8KluO~64a7C6WR1ah z=|Avn8*y0I=_Rb^aFNEHjnU0(Lg6FhU zhUO;SqBzzMI_UazGz7CI*3)|m?C=;ydPW5*3V$mTcsG*}C%J%A>D-NxX>iFcqzpUf z{7`_`i6{=6!bO?2Vwpx<<`-M4mKR>?Rx(QX$U9FY1zh)`=Cnh8sU;ZivI5MrR60xM6*>WP&hD{$MeYhreu_4*L_%y zl)K09eFEvqXN*5KznN{)R*BPwlSlEB66?y$s1Japk7gOVweP=_t%-@g(c`2 z;;P7FyR+MxbKie#`3w=TxE=UF=ph*|Z*QHUge)72$o`c~PPDo-AJlH@YnmY!2bW)L zDucT=#uIIzSL0^z))5@lBW#YjJUu=l0!h2)vLKKpr9&|r(frTx=LV)4FspzZW+Dw>#8Yy*HBR1c>6uZchjyT1=T%YcsAu%i2-U!4;1~K_WOgjtIGTU!I-4py10D zssC32kCT2)LdB(jS=0^T{7h9B3qMbtF4n2BmD{rxmYQYvtN=@8SBVr5AuGv<0Q?k_ z1G6{~>?IZ=pj0hat(vy|^8H*R;Bu%LWa*@T$eT=$cV^uCxg8I<9Q%iCj@}RyF8OFB zxx3Fd9CnIc{raakzWGlnNkJ^O@#E~DA`!@omk?@6ZKsGy5z|tO3^pBK!y`TD_P#WG zSQ0qN5KetAWHeR&)`sc(Vl70VZ8XnLy2DZLu573+mE>B>^9-Mv#?vF=X%)RjnMjsj zgbBuN<0WI7-s@!O81L~WjcQ?N5@Ft|)b6vKY@&B8nqMP0Qg%kSRzbZ_ReOHc`YxB) zz8_jia0D`<$%oK2!u?1rS-jr&L+f6Aq5>tLlCotMHFJ2m>md?9%$|ix8DS!r7y;28Prd9i2(`?`;T_1a~St% z;(@t&rx&9h>|46K2je;ynt9ACrPTr&uQ|Uv0OO=iY&$DL_*uCh9FSj{!t2?qw})0n zD8heoHBMT;>2KUK#KLz5{E7Mfy};fuL1N=9tEqr8xyQCtFYP_#Z5f1;yxU|U>uVDg z%QtYf0isQhgNa{NN9`T=Hk>2LnNB0E;dCoMqxTBGzBF`V!=!Sd#q5~Zziw^8SaRXj zld3e*-a2m>&eNXwXBN!3*9;=n>n@M7B3JYF2Pn`6Kj+nL%OtT|zkOKF@3%ohmpzt`d zU#ihtKu)!iq~S#{?z?-wy5EA1Mu#g!Sv;y} zUnvynozuc~ut*moOqNDZAC2^-4%TTDXzzSli=fjI6&O~l!w>Iwuy5N1ws6XVI%O38 zX2$^T{dcTgfbMDS)jjtJGsb*+k_*Mc679rv@-9_xM(c)Yo2@+5>y0HROy0Zj<2{2)(g#@na4kBK(1&=ZV9VnkW1$HF->GE!86>LjVyFtv2w9Nwf0n ze1&eI?R$Jp2eGncWpb)N&(N|z5ZwJS>haXmC@6^==E++)8^1Vp5RHoA3?o4#Gm4qNkqX4}m4w0ETb=7jssS_LVKTT3J-$^zca+zz## zt?5gdY8sy!?DbJ+VD@!bY3!hx4tyb+2RN7QZ4=5u>K(cRAm*y=6Z#*(o-8NchY4`R z(ydD8^moK;)*UXKm=|}?WSZKWaVczUqyS##IAvYmEYOQy1l`J>UsRx1rAhg-oti$3 zc>l$(*ic`Qt=;jAKpm%?0v}0d_y^Szd`2@m-RK^XbCrL>B0kVMhTBqINJV5*wL;I6 z3n%YWiE|W^Z5Q(y$v**w;1=2_viwt~W`xiFZ1F%}yuM7Ua&Y96?cUgsRv9bkNdH!x zkfQDY*wo7EUNTt+gWH>v&Ut{< zz}9r?C-RI3XghS1)WFjcw%KY65oMXq&lOMFa{ETD3-GOI!0pTal57o`tFK{9-3!Vc zUS-oUO!~OnbC{dd`8B|v66R)Az#CU$@NaaLyvVD6QfJ7C7L%?m_~AO#voyyX1IaT& zi&4m#uJ(2Gp}cknSJYQ`24EVYi-U{i6~rJeH@AW>{=LL^q|stdYNZg>rZ|0S@aqt5 zUFW1!z(bnUFX2PtoEbQnW`(8@6r|d|A8glLCE@J2xO=V8`^(JXV{#2KpCMDHfc)z` zBnnfXI$i2n3ahvIN4m(*$e(W*{4Xh&C5{mUWhuX{^)$^T53-u(@j-Z~ne7hK1C6)v zaslLK26E&(@nDPJ9@r2+0I;IU1?Vf^1+5gGRN6tuIXuHTkZJ1s8p1y^cOULKqm1BS zPO|wd#uf(Rr^{5T8`etSGqlhKbNz~C z>F>IArAENgUY~WS_U*bORHBeynfcUl1-HT!;wLpVR4oz60Xt1G-?>&}{nH+%{Wwe> zd4m3ztb+yUZlFRARd{-tO?x-jlH@N_D|uB-mpqVGg7ZArw5NK`sXfhA4_LxY0{K>L zp3h|H*5`e%VWSK;m3LG*&OJ^$IeU_2c@h4GlsPOMoYN{w-ZCS`hg<>Px;ksGYHo_S zi0SsTb_NWL7rdd!5Lgj2@zc##^e?7b*0q~nvo}lzEH0Ip==4(FEgz1;;`}1?<00Lw zTI#5y!jp<5hwR~~My0(?4%*WJ)5p4>CR9JRh%d>Yp>x z1xbY(;N<4bLs{TP5*-#-m#rU*6T!IJiRmZ!&_2XhZH8k&*L09Y=AxUr&d}`{WAsY# zxX@*7<|@fXQ~-nz$6bwJu`VC)r))9(a<;ET9vAHu&ShUYsW+CWgGWhIYQa4g zsyuFg7WkEdn-G2o?u`ys1vfg4D3i%h0k|pvcc8F@OWilQd*9K-OaHLJr@quH1eeic z?`QZx-iNdw6lSeUi<8#yHy=gm%MCj>62i7tc86xm*h2$OD?R<-YCMiu6LF%dVH4y>srafoOW@48mI}xe#UufD;lHKq!Datg7D5~y< z(IvQzIXvpI4yQ6cJjOs^O&QI`Q@J(v;W9#ipiV=>K>Sk|pb?bi6m8zE^hb5b%3DsB zKm^LaY|0b!H2*QuUjacUAhhZB%{IN&e3p8+$XxEa(83|WmP($bIPh)|N#j+rT+kR; z`J;Gv{jdS<77+fuSR;uHj&~xTF0auvTpOl2CEz3lvEiwGp)p^vGlQF`mEBQlll4~n z;JM$q@krUj128#OPmt{KH20vhvu4xh37EzEQ0^cBl~;k|uS)PPRqYpkjpqsC-u1s5 z2(U%x51ku80% z`R40is^;!H_*?i5;V^Cmpz>p0=rS~M2g?`$LZosNgB1BcO6Fk~87RqEXNl5^&rorT zpXU>uv~@uW2PJgN4c(C+PwkL-yyVjmNRcjtfmxGnw1|7eeT9NgdM|K6xV2I&R5!Es znOkgSe!AS1WXFpENg&}OcFQaO)Jc-Rs%t~}r}Lu-QI9C*!VYZ`D~==qD7~OT!{x#F zgW6Yky>`npo=akXh@8v}M6#!#{a^m^k<_YjxzQnl5;=$_7BmwLTR$y9XA4rW>UDt( zV=4F@f>i;mM*n#*Z0p786N27I+=G6!8f)*JUlF%o^98u$I!p8U)5}1%5;&w`wf~jE zU*i4x8$dl}`o3s}FF9`hhS&o3TU3a9*9rs(Ni<($D}c*|AOv>phH|1ttfxl09zXe$ zj(B$s*Z{7#a6D9AMdBSCQg(~hlU)67$n%4lz8*z!__#GOmF`2g#ZBpTpw+{ ze-GiupC9-R{$=Tj0wnr%1MtRYzn=iu{nzz(&_FWj_ZLK<-$Z>L{2SPFBN+Gh697~G zzT?j{M1eHG?=Sw0`uS(u|GUF*U}w=m{25zLI}o2QY5z0goLjL)Q-i7_fM@A4A@*x1 zIUpJC{o1V25P?4<5GFUN9>~ish#5KOx1stqx?$X`MAzxTbp*wqL8U(Cm~G6?E?5sK z{6E~oPX~#l)+YQ#7Eu8X#n?`RDy^I9iEL zKljk$W>s2Sy9)uo)?G<4!fMWuv^epU1&8|&kw4BLHbIBfyMLHtO|vK3)Bd0i?!%yQ04TVS(S@(f!X4|J`4|7UX}H`hS?~f40*ft@T?({J$wcrrW?Z zHb3V---CJWUKBU(3pE}~LNBs0=a^mSRX+668guco@vw#R@?`q>%yPVT^Jj}Byzue- zMvXn?qjT#1vqMs1;{Pq(Tt-&h&<2ZnD9mEt)gJUzA5-OllsUDT3+Hp*vguvxO>dK( z{|CBQ!Axvidrh8GQ05G)E)mj{F&^2PY-8j0P0zI>T zl;oBJ?SpelW+H8UU(_epR+aCpIP`r-|2yp}%TdYUDIoVb`$E@$OUzt~GuVmel#I_yXEah! z&Hd`o`D*Lfb0(h6@oe0FIgrw~yDK_h1Ltz(!|~yO^2Ls%(A6es(0gaxn}JhG%AZy|`(lyqNZ^Y|qnl@U(lp6V@d2;A`&w zMJXe6#~+%mxyJ;e9dBqjKU$}Wf1+vG`F5-cBkVOx!SC`6vJ`f8qR6P>8=)L!@w^>8 zP+o`N$(NV^YVN`qI#aX1d|p4z4H8PsH1!Ng?uA@9xiYr}&34c*xR7^>ewi&wC2*E- z5TTufY=Mc@@JX9oc2#Dbg*vwL?uhA0$#!k#)n-2@;a|uo;F5%%g=o@oD-Bv-UeU9&9S3(fvt< z6g6cr7_StW?#7)-dGLo<~yFMvEOl|ut$n5j*NP>#{=_YjuEH6`)AZ!L`%x7*cf3NdG z>dW;=WQ$aEGQ}zk%*^GBUX#~BruO@jLqgtVjvlUao4s0~MveXi0d-J+E;n94rqB_p zwgu?+$mBEl(H<1*HE4YscjCoWQG)2;KeLM@H?`B(lT~2Jc;@!?a$0pGXf~CN-f%Ow zPvuQOV0^xlryVx_z2ii)CfjtAv^j^Boqf>kzW$-PBOWs8Fa*S5uF(A8E0EX+`p^ug z%IiMmv6W)@$>Kw8?w@*7{=5#Nq|c)DluSJIdG^b%Yc0zjFBf8V^M5zzxE`cH!gB3` zDy(g$EK}2q1}_k%kF@~CE#*dpq@>~`ae4Y_bxp`i$6VauOoLBZb`GyrSy$D1s=cIU ztbs+6<8LI>W)L!+sBo@DyP1z{)bNCQ%T&Jcv0wVCD!MsU(}mHAwwBJO-6zZSK#Q>o zpE02{BR)l-U9eDWrGDa)+4E~G8n01Z_A>RYZ3>YkGG^Z@gI=}A_rJ@#aUPk~fOw=Sou3*QlPP2>KOy3T%t9t(0ANcJlLfu#Eqtc=mIh8y!9ccA;TDlN0`-ip+(4lqYOu%BMKX$ZaaNH5j%g+vlJcx^!VHb__{K2 z={Q;`N6L%2N2Z-Z;>poZ61kC^_wpnS92G0*NJxs#-Sw(%SQ*0&fdGEx9eT+}LEn|9WP%aNvMSFMf~KFz6opblU2OT2*U?MA$vi zZucjh73Y94@rH!ejsrw^P59J|RW`JkS4(RE%)EmsGXQOHAUzo0-)dD~Mq3ISI&(`1 zOpL}(CFo7&s{&w#j_X_}tdxFF)!Pc`RW;hSqyattg;Y&WLSx5&Gs8dw={ek&TCo&E zfT9p`zVc92g$XTN84!cqhJ&4B1j2g<%3XstVVsGW@v&W7A6{~#a7+{C3dcu)uN^$z z;I3G2&xRdan`EI$7+^t-;*01b#H)3t&ado%=ZrNNNI%u|LB89)6!mZ9J9V7|s1(aj z$hHr3jQ#>QkRlK&04CJ$yK+bGxI|MCcXtg=(Tsh0r}_$t!4}H1?z;b#l4nizlvTwe z|5uD*$6`-s)awGMLN&{=DN6NE^_J51V^1^jTUe&eAe+BAeQNTk@qP$hwrWJTEOHC0 zLgK=|Vd2V4SXv?Oi_ze6kACWuzFBt1Cj(A=9J@)}_WbwhWdL1Pepm&MQEII<5}nlUeMSiw-8t)D`>>SCyyB}(5B z2wlA<4X^(~X=Gr&Yb_7CF`Vvxy990MW9;icxNx}^@j1)`wjV58t}9nC65j23vXeF| zHE61&B)f+TYi63sJdjy>*7P`8cZ z5W!4uU#4O{irn|S>(>P`g&X*)8juHB!*e)1>wVlJQExRqcUJh_fmQ*rOEo;|n*E53 z_DBJ>FA^H(_fM3-5uGg^1S)0FE5g~%+$XC2;DHK4s1n=8i<)ePj0OE8O@aisonz!Bp>L9Tt27ih7=zAqn(J1+TBWRLh+R2YV@B_(u!R2x<-StnD?4={ozp^zU4h> z)xj%wSlQ`)JSi_FyCR-0aKw7J90KKqHrS2K(tMrvlpbkx>8WOum}Rli&OMrL|>zD*V>$k-Csqz%BEGzXq)3doUw+`zG_Dw|lUtzg&V z1~06aMxFul0*oXeG(s`wxw{_Ui>m8kuYK8*AGefNs)~=yeUXX04n;@KbO4U5EwO3hhWmE-#~{A_4zur9SJp%ta#V zt6RDg5Dno1$;D-6$2}9b0idxgYHfENzXcjOwMUBORuQo1WX`ips6Jm^lio>NTUZ&G zHMnu*(EY~pUMJa|a|oYKCs9F|2KIr-TJT7Bo1%7+ym)sVsdWX9?I7N?+N5CM{!Fc9 z9pB7QcAo)xF~Vl4fTu-}B8|_$lSTg*7v;n+*IM>Dv=?B#=Xo5cw|A__iwo2OD{$!n zG=%we`%Qce3nBu!eedACP|qKwPE>#Veo|6V6?#6s4Vf$%)x+pM@l*jYfb?zi7}EMR^kwiI`NV#7$ULhHar@S+w29=Y7 zjuV70oA%tEJT6*jvD5G-SP;eX94et>6ecTfvYz#7{8a|2bgR#C|7ul&hi8&>v^%HH zHa$!3v?hAO8eX8^#Jc|d5FBf9)a--Zj4R5P3u(Oe*)H}#K+-r;b9BbNNngW`|6`dqxMcmNgo#mDQOP(Zqa+4&RdsS zeR9~Jn$XhvX+SGEGW7ZV%K~{U%Y`Y;)wE|Osz$=4n!b4_{$F!~3b+7Mbd-VyNYOGp zjwKnje5XNq@z$ZvH+1^N=;Xq#)p%`>R{t8!skG+1WA~#iwEM3hFluldfB-&U{VEhr zyR|>dX}ET<0QBPY@wZ5+B?X<1$2dGF;?zh;)=)(X093!CD*b3czFkoJLW}kI^s_V+ z=-oh&GJWKuyJiLNh|A48@Ff_h;UiuUSXn{@L^3Rd)lj^w@KZ3w_VePXcP9Y_?#k#n zYB9Xg!Se^W?IVkrg7mAtD<8_M46Eocav_TC4ZeT2DkX;wMEZTEOBk06Er&T8N*(E4 zqngSL?>$ae!TYggr+!L4eoMUsYaayh~Y;TV?G}P)`)u_|-W{Se$nfEUmzTEnW3qA&EB$ z9-tw}IGNpukRIuLDL-Vc_onZuSF40wXx$gvNcgl9wd&{Gh>K5yKUfS^MsQ;(C?Zo# z&UO{OjJERtR?1GwzGbESm;~=GgVhm(Y>?EKL;o&-Pu-t_trvjmi=4$vn9oqJ1G1Y zrtVK;-kFA9KKVJ{_A{S^h4@t`{?`gsr_AQNZ+052;W|JgN=q{Sg%^`KtS>2lyqLa7 ze7?Z7<~LP5FfT+repy2yda8FVA%)c)Ds4-Fjx-Akr3DdiXVV#;Qx@$Ul!i50jQb2Z zwqG5W_GM_5fJ5P+{@uTqf-=}T>cbucZfwepXam*85CE!UFyD$q;`C_Me>MCl{=>Ys z%=T$P6FXo%GFmYcD-4qd<6@LY`W{`b47~7SycQ$aY1J_2v&NKiMGkpu&cRD<@U-VC z^Gfe*rv#PUph`|^yE zrLSs@}q$NVSq9seu)KshK>Q*5ZR&#Z1H&{8BXmWNtTK`1pHJ*!* z7j?KttOgFFOU6f+Ke7Wq$r4T{A(+qNJ>|WijrS%gngU`dWl;s-!?Y&xx95su*e=wK z0PKN?_lMV%QB&h=gzG$#`2QZx?bdP64!$pkp0uZQs48PDMdHJfh4(J~fSu{~Uit{* ztKWcE^%WMU-YPi8ZVH#G&<#A~REQ*W3cu))B0z2cj5ESci#CdydG7j5OZQ~6>5Nq1 zh%rxsTq6L_RrCtRd`%+4bfg<|Imy{TJAvuDt~4DY|LxmMdZokAVk;fAuw`1f^Yjrl z<0MT8ELAjZ8a+<+ys#`FQN@U1TH_Q;tDxsuuy!BT5lcLsrQ%Cp9*>hRO=V=UZx~Is?FZD7R|%+Fx&xsV&2#K~jcev`>L7uRtS^a!T9pYwEua_eLd2{L=86KSYR}U9 zJa;&slNUE$Nz`XA)mi!j>m!QeF77ApCpL0=*b+e2DXPJrmqB&CIEGr0*q@$9w8w1Ax|+kP)F({-VI28tai^&n(C}D#Unu9Hg=x*Rn&Y(_S*Am>ZBhU{ z4v@$iV+(lx#TmBgyo~rEu)y53U*h-LF_zXqJSM}-D(Fd2>;r07iftqDr(T&K=>)AQ z(FLcdRvV#P1u!}E^lu&!-d;R;G?7;%9H<9rd@KI7OJ}^)Q9Gu1f0EnFTHf)q?YuGb z-OLlB#l68b_MQP_6xKjH((E4Nx=qPkK5bizWajM&qfV!9t%iN8Be>)V7Zr9#-4oEpWFz zfy@4I{e+CN0$|ssU3You=>*pHf4R20U#3~k)<2U4?wlBv3`}}X<~iJC!dTk0WK7n> z)pYOIe-lvW?zOtB&N)3>RG_2v1$_nC^48Dp7l#mXD>zVErKE2(UiAWr*ChO@Z7u-V zInuunY`Ob$??EMF@{H5a({g|VfdE3BV{kMsPaG%2-~lc7$vcX!j% z00Cf0d?aj(8U-t>2hTkzKVZ^~YW$++J!qW=%qy+?#;Jx#%pIIly7i31&+(XLMKfEk_k8eXMHWq^4jaMG_^8i&6YfT0ONL9bJgZV1nf}aGJO$iW_7Y> zDQnm2e_UCX&TWUNJh3^Y!MQY}<6XO!K1_QVYm1^an_5bX3h|*@Y5X3X*CR+}NM6sw ziE&n$EO65a><6Ux!qn+LmV4a8Lb~^Gyj+77{)bI$nQ5BtsL#bt2M4b{tap)-8^G_j zRjA3;5UgC{oYgtpmM&d0i}Um3PoKko1K5#B%KK-JkPp6|6M?pBYPHZx`UK3!=wD%! z+88jp$Y{)`&TU$e;cjE03|b7cqZ-#6&!<1Miyzcd7dEs;iCL1l9N5g79KWe~eNcxo z&Ry$^qAVx$U@$@?RJupkxtR6E7LP&#R315TYnK z4B+@{?SlEAClTUjAHc}M^RCaDx{hzyMF z`P!pxr`5k#>m92<9fE6nb>SN*5#g2-9X34$3}XJ4DW~DCP5cYV08T)He6(tg${pH= zxK|T}0%V32P<_!jVdheBFple1-YB)^S-8KzZ_A|L$YxRoV6Y8B3@TRBEj@0^zBVt5 zyrqq@K{83l)K&QuX4q2Q#O;dR>)*?|p4dk-*P<@>)Le{WdvFhZ;1&f>`A%nyA&s;~ z+zus$N2G?x-aP=l+#JaYg~k%e_>!R^i}y}97fyIXLPE532!vkJ7eU*ArfDGuMDneS zifX;Mv3|!bpI+k?MR>TE>d1_E)Jpl)wBo!KWDt!1u#@A?P?>Adi&Y#C1Z+A)JM#GT zzeN~4xP|>lI&7!H92o|yd$N(s4{_5_OnB#3JM?bt^Vw-dS)LExw%*?RBUJ$+2AJwj zDYu%4T37ppWA~lw`K;Ngi66NPL zNa*oqM(XO%fS!!pvkUz%g5QGyR}5THuvL9?T~rrkmdI}0J0Un?WD~mud35iw2!@o& zMa3WRJScEt=dCaB+0PCZax^$~YFEhx&e$>c#L>?lv{D2u_2|zXaiCk9Mh`=9LxAnZ z=_WS_{`Y>=y^&YBix>XCJd2M^*N$z3Z|YuvYz)f~m78>aZ4?DJ$W}Ew?S>N#M*T+M z$VML^M}dS!AahQhFV#P+_rFG{mfHNJ8h^NVCvP*8YTkOvgx_T+oMhnkC6F;19tMJv zhrQYPTDgwpQQC5ob9>tn4bv&P0J2a_)@#(p8mGMBHa2pqjr zf#%vvvwCs7F+Iv7J~4gE`>_VG&$=Vf-{{7Tx$y-azf}7i2H3Aovo{WuN(aq;sY+qR zf6$q*KUsPgf-8SHa7|)B=RX;z{gC;)8j>RqjZ8!7kXn%EZ5Z|1V-ymFlo08yxUy5iJN7Om*d8`L9rACA zg2QZUQr*#E>%T>5n05uY6Xb2x*)EbNoO8YMq$wWA*U4+r>U$odWQ&g+wRti5!$U6< zXF_yeX{Gj?3Wl63kn_0x;If*n8MU-9t(gXn>#L*$M6mHHGdb^%Ju%&O2ho~5)<57Y z0OZEGhtR%t;hN=fxXL%yAd9PL)wQFH>q4?|n?k@XlU@jVw%rDqiSb0mdsf>o7a2Ka z8f41O;s~m=8*JK?@`h^K6V^Qtwzt%EOy>(hnRAb0HCeVNTe5Z9kVlc8N^ZoX*jaTz zLy0zo^i{wX$BdVCPLCB18E-9Lawty_JZSYL{fzZl2bT4`dlz1@)-oy;F4nXjUghJdg)4-dMQG+!ySPP-rTmYqEM1(}sDc8jcc zSp+b){L0RuEIPHd?+^V<*_W)RO3Rihe0ed*m4FWj#r)09N28?e!HHiDChCqT>YXwF zK(MZ*&ovARJB-=&n20O%TwT zd@CAVo6RixM?mSjJd9kVaqpxE@sTuJ1%e9=@Ax6sh?^Hz!=lQ6SQhQ zHd{8%P@OqN*x5jhQ?{5kNfyt3tX{oC*4(Z_GM8kMvLi9~T<7<#$IziA@@8UXD1b(n zf1UP;oX2RelamykVeTGz*j14VAtkXgkvqd7**#0V1 zyJO+O>af(7ff2Ajx|qU}MG-d`4jaQbY0vtP4rWv2hr${1g9R1zd6N?2?Fn?vt0UM2 zM~k^TLu?4s*z^JS`q&IS;DpbtQ!Ywa=61dish1v*=XQD9lt_2eO5T;RKl6a&WaMKW zNr}BDhdTaieS+h>MljMon^@g5mlKZ{&0tuN)_cm()?Q?!9xF~*rqJLgl~EW_GdF3> zSFBm3seK?z1pVwZl)a8hsyiONtm4SVY-#hn+mpKlue3`xd0D;LTb6!sl%1D0BDK~o z!pG>Cd2TXlyejcQbx-(UefKmo9$A&MCf&yR@+xS7WWZSmBj|VrZ`41tGvx(COZkk) z94prS#b-TrxwgV`B{C+y5nbl38_TxBasEF+=M37{i>+ zml02MSG`_)j?{4^J0(mNugquVAHs5CIoPs$;pTmx)@5X`1S%eIVw_uwY#b#rp5I#f zo|d5r%9+y-p+W>~aqARw;GGINx3LH3>V!A?0evG-;`y?=nBLO|Z}xG#C4{ky*wgXfr38?_3)D_3K&W64UL3zp7;;!mE7HiufYVXjQFN!R$>vTg9i8Os5_6ib6iNWP+ z)T^V#M-?I4)syJhvz<6y$y2LOO#ad4T!;O)02kR&k`?F{P@$U>Tg-Jp3jVQY5tj5( z-2Zyx1jDS1;3m9amKVh!J$Ya16x1cvGOa)bK>^aV?4g@CD%f%=YKd*$d3Bucv?gH% zhyNiThk&(qpa+cNL|sfx*Acg_SvH|w%FE%RCemnadlss+>jImOIXKu-tg4CsBJ5_( z&tt{TmVi7Yg$R|Mr54eir)p-8fg^$ljy2ii+LPtT+EsIqupFm6hKT}XfdLL@&8#|M z-^3$rbXEPus#M?*XtiF z|Ip!@>)O}e=RWsw{Ej8$nGW&+vo1x^Y}~XWm#Kk&z!URTqeUK{>GQfZ@lBl$d#k?g z#*;1#UUd}r&dqGUE5z+}J4>2DnYx8h7P#=58;&J7jf*YBVb zPlrly?Ykv@qRP4r5)h&);h2UAhEwQuVySAYF})tTKB~QZ|Bw0)lh0?$?GunL{`#-R zO1obS6T!48K~eGY4%{h3AqZp0@M^q7}C&Q`w( zh9#_#ACV04Xr1ZY5L;g=?1-|Y?5P`AjI{XcEIx|P$L4Q=#L=P9XT6w76Ej>3clu5G zWZ@;YYa-TV89x4F#LdgZ^v7NUdc90XBokOeJpzLrPd?*}m$+mngyitKyu14ocC!|c z4_BhQd=M3sbMcm)OgmOJVS3s~lYU>vMt#BVv|fC|ET;GVl-FQxU3Q*(=@cEcw65ev z3Okju2zRvJurlQUvK6s#`FN| zxrZ?dD~8Q)%19>J?GHl&FJTDQa@uv0CAwW#eR*At`s>nDg9E!$5Y#|0GA>valbtzS zc1oTX#`!(nd+gvx|KIC#_-jK4>J$rET*&NByzQ16@;;ug1dmFbAW?m!tP6qVQ`s~Q z8oV8AIyJ)8K6VrryxDu5dG5jF9m}yqtphM8?U3lZe`(?)sx33>G#>AdJSWYdr|i9_ z*DX|B-CuLf=!m%w$5|@l$^k4f(*Be-cm*@0#aaf8h~-CnPt@0+SN$=e^fe~PXqYl5 znql3e1^MlOghC1}f(|Xt-7Jx5)-X{2($6_6gev6|H^R0=b1W}p8j1SNoQ3taN%>cJ zznb6u+LJp^&`jKg-|7Fw?a!zc zHO`RpMZq!?uxx@)^l0*7M|&B`!_eB=N@RK71a>JNH5MCsQH5 zp9O9%nrWpZAC$(;@KYBwO$y5^UOGzRvXhY+Dg;ijENy^%njo&0(xt7geN@DCIA;>p zJNo=wP4(nD_4$LD3NL}|qo2cm6PH32r`(s?9Q8m{*%8 zoY;hCbGFnI-CD&MfdVrJ{GAH2^zp+HUws7!%_6AUPC`a1EM$?eCUXqdd*A7zLthy> zo?}arRECeG`@&K_7rlemH7$!*=Qr{uceo?dvDkb{VkMM z4vk>u8`>L-HuXptk;GMDHEJ##U2;OEW2FH@8B}c(p^PxYBl-=8tR`~Cv)ko}#`#6N z+vPaIV|-Sr1txz zu&c1=2omJoc$D$JW$rM(Gw<{w;6~y zBDLYC)r5fQWp#+KFE!hBylvGH;a1*7N>;he?TnagKO?m_dLt+V{)+zub^>9a5PS{R1Jo^d;a zNyQ#!^PBBtb0l3(-)I(!%nzE0Q2U8-Gm`1824z#W2}i<7;Wvila81tQAB^Tq;r+UP z5i!^^MzzlDA6wtZ$uA9(xkpycB9|_f05}o5zR|oBSIvfHB9Y3bQ3Ny zny;Uh>a|2LK@vZlRVn~ssOKF-|F^b+=$Q(cGhd@Nx5HUnkqCC>!YK(=Ug?cdGc{bp zJ&)nQ_vN|Es}EzF)XsfQHr@fC-wl5?>z9AsJnk%cA|l~+GJT&O_Qi@s@vtD3cbTib zK5r#>N~_(}L&|0@Vz%_wf}1`f*%7gKRwqHa)43~gICaoowT|f0A6$;46Omr{KsuVC zRqZgB$$N@_Juhrdg}@Z>uY9{oSkStRI2)oo97;aW3rNr?nrX};zQjE#me!twqsZ^e z^s(-5dfu$SteiT`UC}4vBKE8G^i6QpZh=7?z9Oh*xQDi^hT2}>6N`lxA_x{jA;b3Z z&D^`jD@~%2XWyTZdO<(DNta=on0xR79aa5|I~iLwI@Wph^(+5JLVCK>f@Lgte%P)4?+o3Fh&jP)W7w1D`Ijhmf-f7hxZA)xKFPJ58BPkW`$7sShpj21TroB# z?`j%u9KL( zLvA+_sCVq9)dE9W0~SWcN0!1{YaNyu!@G+0v&(_1mCOy*oL2{n7>;gPT(e&rOJ^>s zmiULW#CP^!GRhD_xfb16^|R#c@0lv&xfLB3a^RaEN<&IPw^&ba1s5FDgeg`WgQ*Bxw$ zDSlzTKA($wWn#dNQ_$L7ivSi`rj-Lngx-*ZcBQLZp6(G`dX(-Iv?oRiY6?!|w1{rZ zF_Z=xBB8EoJ9sr+F)-UFcez_~P&T`wB zMiF7y$zqaqy~SNb6Q6Npw%_{c@@cQv@xkG@8@jdv3EMZc%oxXoeeh}`+#`VFc0B2Q zTAg~DxbpA7Ki!Mi%aXeShH+f=fXu2~rx>Hci^F#<_ zn+t}t`t`=KEWBO1XP5V>+`jcaxiS%IYKXD|dBboD(noH>zQYL%zH;B|d%RoL3;z7V z5W1A=t6iEMBBC7IuXuULmLayhO3^Vn4(LvLONG0itz#FDY7ni~1Ew6@?=93~sibwp z%O6+^Z=ySs$1BQ5oBmR1IQNGh9YIp&${=MT-J_Bg;$n_g6Ogt3?q#@DN{7du)b2I( zX!B;XCLuwL3e`=$w`p*uf=p=inc{G)PQw?GwCPGlluku1`8&-Ds9MLb0mYw_H=5ju znDA(&D#`foaKgZAY$8aJ)wNCEyGpel?P!tLeZ4cz^3W(}h-nP>Is}|XZXPS#@sUoh z=nhSG&MS+K*K595GA5`>$fPi=(E_s2v@&a;pFfL3<+NgQ>p+*lVAP01 z@TIs)uf)}+k1-8FZtq&b?rTn*)1fpy)vO~{qT2BH66P8Q{aj<1f>fenu8U4D4&y!I zD+t>=@##EXDNC0ycxL_8N!nR^zclr2(7=1LP7dd z<$0#$xpTM4IC{bT;R(UxFGCaCr|UKTn~)@DNouBJ7EPaNoG~QOuW|Q<3k63Q(Tz=u z;t-|xbKe#iMK%*#`vsJyU#}yDAJC3d`&~J*e8i^UGCuvKLpnSSZn9pD&+yE2&gy%J zFgPdrEUhKyh6$Xbb z9SM&J%HhAza`Xo+QZp|F@k^v$?JLdwk{l5ujE`@}A$TtOUsBsG3G9s-8%U=Lsv`}L zq4NK@21r{jpNuGGnl4lQyeFbUOr@PoHk5mUsquA#L)GSxQb551q4lf+#LszXS}{%N z`6!D6{3_1;TF_u&n4q-{`EHtT&0dSq9yW$bj~eS~ve(iq z7!&c}Oo_kDveNGge!rp5&1OsVTaNrHtWrN17TQ^>dWvt%e1#WX;Xck@m@b* z#eD&j)L`i?GZIB!3MQ5!{(vfW)pm!lEF|%e)Ncxp3#2HZIL}^K*Pp#~z*pta82O)W zxh%Z6bI?2asP3Wt@;fShtvcmMmw-w0SK{$Qy^jw9|7jv@nZUK>qC$7IngG&JN1xb- zWa*1NF}l~|3ZQC*EGJaN_MEE>2x*?n1IO77kaE|EhO8tJTenb zs_;0rieG2-2r%hJb`VdtklCZr>T$kd7@G>OA*z#MF|aQD9smFmviC_>XJ-WIFN)Kh z)Um3nKXz|g>}b$4yisemc(4 z=D^vk;4jF1GNQ1Ef)7!sVqMx%;&<1Lf>9$q_43i*Z?b0fP z@UF_>X&GgKg@j))`OcV8ge1M+n$e!3fFs1J`fTsOb7*l7fJrm3Gng6eG#ge2IKy(2 zi$CSsX+kdBLe|u;#ioqj-r&A;pJNq_4=^IlsB7A~x3&Y4gq#0bdL_p<8i`+IRg#9@ z?sF}B_Rs=8@-t9n$E0-h;_p(X-`~A_H)k@v8cWU0r;i#CY7Ysxt09acfk#u99YZf~ z$nNx2*BPA>ypw~AbNAz!!&*AZUtAZv1qj62_etaK?jZDJm=ps}mj>P`XvOS$42$|4 z*P7Y`ET3RV%e}OT3)#V5NzbK&p3SOx(M}9bd{ucD)q2BUDEIT+*IWJ?Qe(!moD}-1 zCp>XZ2q*eBZD4TVY5ey7EKCa>%E3mP9yi?5Nk!mZ(wwa;?jhm}iX0d2~$(jmuqd%^ke_i5~1=2RQFwx;b2 zysE-yw9jw-W4pc1zS%nqr#o9A1wcBKf*<~zg-wtBRia!{#qKRqbHd6Lv2LUQfH*Q} z$}EEB5qCd}Et+ZaF3JGwNn>od&;SR-Kj7mT9x#a~b^t^}dRHCrDoiFX08qI$>vD%XMZqZPKRTyMxWGTlqIM}6ugt-ByAx=S~h4cO5IjED|Sw6?xP*rXop~Xvus2WA1$Ls{3)o)VY?fM*V z*PJTu=Vzx-9^^YvZuE|kSYSs&z&{UE)%AzL&tcJYfylrlf%vIz41K*8wjyrIw!diz zVkZ8Uz2q}3`X&oS-)HQ)XU5v?-RqqIM8dFsqf5Jd-`2f%W!Hk|&)6_9g&)NPb~5{l zak4MB6or4g0Gc9pGh3UvSL(&sJftE>^(gZxL(R%ri?*igw^f?u$8|`>s%Lp?hvtU7 zkKSzoT27B%O(71z26r3WcW)2*CUqHD4O+GBKcxDKBZ$mZC{s1=oGW6J$uSV!sVqq; zL7=~ibPvCT93a8w!M-j`7FC&KVw_ggMa*Dh|Gqb z+Z#eC!Zp_|ais)%S){v%SRCF6($w0@LnnoVsQUqF+>cz34n=jBo_J zJR_K?ph$kDGx>2{lWhWFv(=v3uxvL5Qp>FL3*GZqn|&*n>f?Illw`&#{Q>tri*OOs z_E?~6@LKj~s*~3Dd28r0CdHHm0(M_PGuP5Uwm0lYU%OHW+U0%>2wGQ*S;JW_m;fG8 zvSB}4R4gbR`+{jQckL(CHRaVr+&4+WNu@&>>@x}n-HB!G;5Ea^;SJD}EV%5rQjCdJ z7v>_p?Be&QJQa&d#{zp{%+MDWQF$LZC^{qpH)~ZC0Z+8bmajt)YGYStu9bSq|CsVO z$|F36i&trpMVmY`K8N|v6TVl7Zh0G3qXo0RGsbMz=p5V90`H1mDv!6&2bC{|$4&`i z{II1(7rCR8MY{#dI37f`d?lgvS<9wYHw{^m$rq-)T|@=tV=jR{|dFX&#^L3{{*S+OGVnYVJxvgHXBFUtWn7 zmfJCshGF1V3IX&l@8xTT>bVtM|0*tBVUYZ0RCQy@jdJg2srb5KO;%F`bh4M%ncFdm$6DjF(jX6xKy zz+cXMQ+}N%@z)-`ijsM1(tdo=Q5GEOpFJ1_Us8ggt|5?nHQL;^i&UF>FJ<)DnSlCE zOah~6&e!uWJKi?$Q31PHSifGYSk@2j=YHq6f%;Ix=ZAgN!%g{NLn^=~x@+OJMtCjU z*soWi!ZTg581$jRR~_YhOm>54|03W1=y$@wtA)W-U<+@u+W8W_v-tB0m_z59;xNSP z*Y6&+TDaX2P+Ie`e=bYSjA~5Y6ux}Yq`kSrLCbCFIQ#^vc~x4JzUW?HmUYJJX_NVS zU(_)u%qDBhEro*Jvn#~l?4QH}S1$E_XHRBe%{KKGemMCMgD!b2um2c zAL5#j5RQ^A!N+so%XL|Kwa1KgXE{@8!*U0lj+458*cn}u{**jEW8Xxw@?|EJA+w(eM5=Z%9^T? z?Tv#w`H&d?>z}-G>tx~D`L=$!hGNe9Z^`X!>`RR3tAL zI7!*tU?s0XX&vMh=O1XDa90HB5Gs|K!RppKj&jzJ5Y8Cpq7!+@qu`p#Zq{0&{R8F= z!GT8LpbOlbN;RcUh3|XUH^+nfZmBER^?pimb11*Cep*?0^nEafO3jb9=k^C>Qf_N* zwT$KykeUIX;c$a|Tzy1+)8ox5t44@9$EBQy;W5lHKk5Ss38)^7Chp86e-#|0XfCnh zjFM_uVG1rve^a8FFgIj&&RN)DfJzP+F)vZKmN4HDwXVYD0kpKMla2a#hS_p4*YAb( zfJcc#bWo9Kefb$v43j=Pv<4^n@VbGvS^JrZ>~~oVa?0*@xGPjvoY=A z>DAWVN=1hrLaD`Zv{m5gwb8`NlOIriIv3OAugH0sK91k11^D|lw-mDY`SaVl(=tTu zog#)_4DZyf>WpsP?PDvwV=TA8pp)BTB0Hi>Bx{NM05T73K|8LDI{%v*o_(4o_BPb3 zU7v>wH|fmXSyPUa;5xshhWm5*!A)@vT4SJ061aDbdJ}?bz6a#P@z=WH$y3#iNSOGV~>G zusjz=8#mZgU0KNLE$~a#_^3vX&$8z@kaeL+h3%~LOu?1zDXLx$>k2zWURhu`e=u_Y zNUn}8&C1;2u`F}^m!Y#&16Xp8L}+6D;nrjtd032;*Rj1BT5j|L=kw|$L8H*!vd&+! zWIT+B(;m}=H>~dyriV)}) zmLjVwhXp^jhqKRAcSe>DdqULEYbSEj26zznF@WZ_ooI6dDqx^(heT%^aDx7 zTURQQ>a5ibRtmpe0d&0S*!N?DmtrpKw&w;AIXtWV1a+>}A9(^!R_;6(q>2zI3VMSq z)+fPAN4pAftojZKLM=HHX~yrdTfW%wzHoVv3gQ#`(~<%78mCXDUnN!Or5i%f*U5xP zh>iTz`*!XH%32zVcGd2GL}-kq?k_HrZ^M9b2^Ax%s*9z*Q66M)Uu87S%8R)UANbc` zhP4e(B1R*K)MIw9!tt2YB~&EOvsi+LCqI@C^Rw(hMQ5{)6K+FgK?-E{DEBbtp#b#n zzPp0P`O|AQXL3)o8>1h;5~BS3_gStGZXCgrc&O2Pfl~?LsG_g+$rA<^1URXM#X z5`A#NP4zga+9{6gZvs64Z zdaqlh11V)83bs;pR4A_>Hac;mn;t!c8jEKUA94yxjDHU2Y+HY5%A5KkAaI7J@?s_fxjZ}A68*b9>j!LScw3M{ozZTW;^bf$Ah>+PsS>-#WV6*nwGC9fq{5&o*ikv zHq`9jm%JIBXE&17Z?AUYO7oP_7O~Y;G#GMAlV}{uz;P>b&o<`daT(Ah!`TvN7}urh zOG=3qD;n9HqFq!jGw+DpiD+mynv3j%&kvP#zZqsM8r0-sLOceLZ0-Pm7U!T!UYLR# z_P{5*#7xt%ei30{zm_~Qxe;tMD2#tF8q}0{B83~#&)*OG=t3B~@S^kGzB#ubzWmaY zEJ6x)@hmXg2=8&LijYkE$+@+WBUP$${-)i3|1^j7+ZXSX2)E%gsFH!MOqA#>UlrTk3_Z&vZF-Q)T1%My+M{ zh5*Gs`y?4c674;?;q{2#o-sDyj*S1JCMZ}7Y)y0<>=f-E4yY*6eu=!?OlskCgZgn3 zAW46_hyD>lX81^RNHB!x^@3rju3w6ch~YA{dQPy`8N{Km`p*eBh@yL#S-!Th&fN$c6qws0p@n z!7d4;*4$+t0#k6s8akIl3e>B|n0ujZ1=pU`;DC}M48!nMc{kaAD(#|H$n}J;Y?)tY zU3bM8VWA0lS(oKt6F|W^eha3a)`8^=l}it_4-Ae1R`?qb6-QFV%e?ab4h+7 zFVkyiG^5wWPPX-A!RiN=@i*mU!o03Y25^&I9lYf6$g615so?3D(t=d^30BWz!+KfO zsA=dXO=>|)nLBRml@nOh;E(r~P!|I;)X6^dVyuDy+{V>RQX}FV^XGZ8?SX;l%nyrk+FFI!j3W1w={*ZH@%pGWt@EEa#jgQ zaNtL@Qnvh=94>%+3~ux%OP6uIZyRg{w%1#LKcZ??bI%?#qh{|OSHn_{v}os}EP^Y^ ztNuDHK5<{Fa_;=>iErfZ+)y23Qp_xP+n(xuSPj}Fm$h@DZCwn!ii|`zXp_5=zUvHL zsGhAw;T>3nJBV~eh!Q_7hIh@c=6~ojs?jeQzGbB&R42`)<;ShT=x7J~Ch*TjlJvp~ zi-u73`KMb$0n+SuiGp=194fe?{vc6bhd!BU-~&SD=RpyJuyMy}&4vMCKr;1+Z@45d zDdvCp0=BU-z$>;V!cnWZdyd1QoAN z71#b8-#Wr-4S7hruxRaaN<@V4{3RFueZd$0C8+){CiV|?75cB| z;y`+i4GR*m$f|7Y)1tK+j3bW7qR0P}Z~W zH&1kBP`}PuL0RW;O9K5Liv`O}&w9L}0La5I=*)Q70mF6+WPy|B9r$kx%Rr{}{~w$6 zj{#%t>E5P~cURr)MAt>;-#7G`m}*_pIA`Opi}~~DJ`w+a<5~aMQgTTIlDBTU{zJS~ z=_e8xD=kZWNR>O_ke^zwP8DxIuS3 zR{vaM&~F|c2Rh_r*5^2q_b_qmrIQF0@J%cM^lhjOn`jqiYLI+p&4$!?{PY-AdX zzo6}yJ)H!!9cYga9Q{6sJM3GkPiGYAR_qLB%IY|Zx}S}Va4)R}yXvnM;Q?GZ`wYu% zSXXW~Nwry6j%C+$R0;7xM2TZS@<7EBhj+<&hj1uRD$g`b!g;e$9$PrOvnLTzPmFg9 ziBhU?JFAv$C5(k~A#pOOHo^M>^R13t|Z<OaGMq(YxmPGE0lKIyY`{?Ye=S+;l;zw+^oL`(Slc;`MYX`jTyd*{!YLN`lB49V}H5lFi>Vcr{e-WzWg z?oJ`zY5;C_ck7haemf9L_2#nNb~R}a+SA?O1o|*OQFGQ2@vn)(8=rP7sELS~l;pYXpUlO^ZW!5F6U!t#1|w`YBvj&iRN zhSYd)(+E;{e6Arv4NZA>=)bM`JCyPY=w5=8Sug5l{E3wgtBxY(E;FwMEXhqD6suJc zJp7BPD>pSt877Rp>Zb9WhJzHgFreSS_a&6*S3GZWKFG6s<#R~ujDnD~^KVHwwc2Yu zeW~vyy%pqnb4e_t~Qdx$4aTI{7-z@!nd8LAT7=8IBkL$>flTiEM^Bq;ydRAoGp*&;b04>s~CFWHs#0BNvd=bs{M2Vv+!7d8Se48_{m6Hgj?b|7&9=~b<38oxUQR?H4yj+BzYtEkxy0YT@Q=;%_vif#9|q(dwDfc# z4miNjT6}Rx*JItwncAO=fRw!kC*Ux9Ynuk>r>B-WU#dH+&w6_Vo5{S;qGSf?QvG?& z#U~E{{tIj(d+hZq99*VjKO1Tm>XrnPHvLL#`t#@KjbC`5+fF*hQHmcacpSb_kQgn01p5B^2X?8;q!;)x`}Ug zc7k`n%RSt1Hg%vEG|AVt#Y5Rp=_?418M|ZXI)gU3v(mb+jYWUm3!uF7s+wN`N zz!RjXh_LGiVvmp6@e=3BY!?EQV*UQ~2 z*e!`W+Z=OfVB#a@Abpp{a)r_QSKi9bfdkSQuQw8)_J)-@4ygyyHqg6qwmi;fN^6_I zuQyfgrwrbWuu>4=#`H3c45?sl`pasOORz(l>HoleFI=Gcx6b_M-~1P< z{z=bib$4`WiTt;ZyN>){`>uU%G`dG9><0o-uTU$K)UK^A9k)xAM-Z{tB5MSL4e(nJ&r`!C0i3|_;-B(& zpDn&vdwt39Vk20sy>}Y0V59@)7ih;Wc!dJ zeU}fmp1mYO0=UYrEeZeqc4Ag)D8+`R2ztU_Jl=_gKhaG~} z*0qg(%d^}Gg~`0IRj{-K+@51rN>lClH9yW4oY(nJ-J=F&vPQ;rqA9Qzxn)TUPmZ`M zD6VE6I5G}`WVElKZjK}Exgz=S6N3dfDOR5YxgobnN)856-+`GIOpf2?6q$ADGbEil znmku+PFt&UB1i?My5Rih-53#%&3d0hL&&&O-~76>bD(=>8LMYP{gwS$Dz0ZlvF>9I zYqc^@p9>s>dEv_>Jdad1ZCB{%2e)uKaj5Ht7DYuKuJ3FwP;lsGY-@bj?@8@4OXKoW z9<6!S<;rKXh+`LRy0H%t^FE6e2NdH29S2RHCJJ%TI`81FdTHR}@MGHaWV<*;w1V@V145~pCw}6P&ZPqHU z9T|(`T+#%``iGF~)FcK`NH2eh(I)rd`|zfzwe5<7m54I-z8lFN`VTh_K~lSrMTt^8 zp8a9#ctcT$==(lC=y@ARR`4AA18jJ0_zh&8OrKRTb+B*2Ng00vLv*FVaBFi~a;P6L z^@3BkjnIn(=_eeD!nXBjwkJEZcXTLu?81G6e^gYqT{b>alRO2>Q#2^b1+D+q8cPjJbT$WcZ zNkel=&?Ol0>=yEH-1KmDv|lUr+7!HY=b3NT z$^I*Z1a7mAcRY0GkumYS3*MN<@fEcNq)ZbBqx~{AH{n4pxeK8 z`v3DZ12jwOuMLR%5p-nS_zMhF?#8KcoR<2K1HHhTb%L52AzNNvvr6CnPQjFRu(PcE zQ6U54Z<`v-s#f4zve?vXP`NwDJ(#wAaPIl_$4Ag}bm7*Kv)B3i1hFVzYo*x8m;0FV z^w?F0XA4&4ECKT!37~y9%jY|C>Ch0hLj7xpU_CSJTS?rC*LqCjK#zM)>tdQ~SnJOg z+ID3!NCV#-tjs)hzV>3T-lk$R`N{YXs}oeDF8%V zkkmeQBr?oSCGnlNi0hFy!hqs6UdvE*m+&J&rj{F5p%z(Vdcb=}neW9jr!(ZW_lglG zD%VN#)*kGq(z!wCfx7jWpgeWMz($JlXQ84H<=C_4ZadRSK5#$`-*_9>8`g8pi}0G0KKU>v*km6^4k-r4wr(yy7|M z9DSwz_G*fE-ob3kO1=F?c~Z|fj*)!{~|WFB}0Pj)ZC`u za)Tl%9%5d1WuaA37?tcQeZPiPS1~~kea}U3KbrA;aHCr1dO^e8uywG|VoHjJ9wq-O0x8e!r}VzY#ki*AD)%a@9IvCvUUUb+1q;%#H;}tYlc% zQ!rfhKHF*3GRG|b6*?eFtatOv$mYV^+bp&5WO*NkAt{f?L#*r?C>ylEM1acGFvUt@ zv8w5c?)7=JD66ttp`~RJWVY}ZpfIi21RWJt$e4~{M!C{Xi&jmD$Pj@tmmQ`dba)uz zb}JdmzH*zr zDnAiv5>VZ3j4Il<@i{I~d1`Khtk)xI7igF@^y_owpOSxY( zclWrBesi^Zfgzie?Pw1%34~MJmfB>Y`a&~Q$>>=!ng-1+S9tZ;*jeKXwQ0d)m_LFm ziPhF*^2X6x!H{6CXXjgpW$#a?a6|7d%4_bQdjxeFxeKqD1+|W*C_^ScHqKWsdyG;t zm)oF;UzjFH9Hbnll2l*f4-`=oqL-|24%fe~*#-`u-)8`A^(4BwM8Z?ds@42L%%B=- zE;y9@#YS?l#CpYjol78m&HM4cWgto=nRWCXF`FKXP!wa3O+lxiYRZmfErW!l*R|eT z9Ur;an6^8FbL~9g4&R+*f{TJZdTrcA)<49whvZM!N8QDC3PNPL#b4*!(D~32UvCQz zYoYc|AWW=hb?i(J2lkBO^kkZ-6gA_$!h|L-AFp=N!~^$?EAl~0jBrs%&As9sbyA-x5Bx|W_?**WN~P3T*Sr$SF#spQb% zG2-fJ&ZHhRjxQ}RYPUJxF-iH||PMyQqcMUz$||Pn*6KJ@t?u38(SlX=_s0dyR8OP!W;X4Q{CuoTw}y=JD&qHcbqKC?C{w4 z`V)3gat0?fQadR5cJ0^tR|vhK00a3-kkOt#?*^gYz?rjtrueI+m{@(ebeV1}cn%Gh zMjKT)iP$NOfz-4o3E67m{kKj8k;32PF%VV#mh1>prv7~a!^ZeWN>32QGK&N&YS(Ns zK>m2Hu-^bdW1~q@ybXy_V-+DwG~)tKsL@+{bIWHt?9FNUuF<3H2m{B$HJ*y$#SPLV zIp^1RP_Zs-=4Y)sBR3Kfl%IcuQ3l_;oxQXz9Uai#IaY3(QK?%ttx(YL^<$X8R;0eK z{5v@_|4XBTrodt;X!#=7>_w@8b;-1zL*;b;Y7wte5U1$8 z9>$-3@6};Xhcx7vn>m~F>UY}0Hjz=9C+iTh0c;8gPPg`<5rrCUR~>t>WBr9h46};# zu@C$1k1a{t9kqwZ+YnfUoR|{JOE0u`SuC<78pGBWtNR62yEWOS7v-(MVSDSi+ASbX zZ$apauX)jsX`DT<>*iM~EcA|F{G{QN)XCvm`^~pE4Z*+;Nx(3w*A*RU13fYt76>|M ze}q?inSyftSfW}qM?uBar6dkF7l_@tzRCKj1AMR)53T8s zMhyx9N%i}ZP#%2v`4E{g<`_+3tXB<16B}hFjAp;O8ERzFm4&cBr4x#Dzq9)$I!Db2 zf{0R!Z|nHHZ{jT{`Rq7BQm;!eZ`0>v)+cEB@`xe=71E99*SA&ddS_KAHt++h@z@C8Ca3g|UjcyNFOE9Zt zqFR)I*GB0rcc&gV^Q1tJt%;VB zIeCp}YQ(kLg`+UIZWJ@N;a<8I3R%awos7NlBOoU5(KUAIT{!I>vx6Vm&DQa9Wz#wR z{8?7`#Dr}hfaHqr1_}TCu^LLnb_5!d(90;d??PKIh=G*H_4O7E_uwZnMbHr71y#M5 z_*EbxuPcNusQ!BWCfhqf*9w=IW5ep4)cMNgow74Pu!S2#uaS!&g(uFsKXIZ2^Qv3q z2&tG4>Eqo+JhwFc1GoDH(a&CPNqDY#C!U)*BTqrB?LFt$Xi2A#YR!$t$=%gZuiPq3OKx=bB$iCImr(WkB^l{gZEw z*sYmppA2FGvB5X%u|3*3uywd-L4DEZTm~b%=lmV_J{)%#n02m` z64%si`4jWwPGz5a>|b4w%AKgMK9fM|c^t0hANYNtbLM<9U6(MYT<}Q3yEE@-;7L$S zI#x)@s21n;_&p<1(D%mgy6F0UnkR)ntH>7sOr`8tj_32(m`J{&$pOEnSHN)+^%8Dak13F|Md*9ec^NEta38R~G;47D5!i`c^Qwrh-h!*~}3g;{8@p9HQ zrS{2a4j9tnYu3Er7 zsr5U1m6^}=4U8#@aPhWUs*^huM45vXj=iAO6J}(gStLalRiIEJ8FM_}K73Ytq+w%e ziT&<6$d~zwgD4;%X_|V}t11RYSt;Ev*S!6X8s;}p#Z24x4QP0GY){1Fk7>Hyjof_j zCL?sqG}E=`FUlx1FB>RYFQ8MkrpYm@b$hLzHQsx(V1G2OLeo?bPAZZMqieDSyOlZ( zZoXNZ*`ORkwNItZKeTC>q#id)WchW)rRY{f#^y0j5><&oVkdt>{@VK;SV{QrX?P=n zBK_%TS|GYVlxZjPL1AAlcQ3U5+mA9Ry8O!JUYjX{|A)Qz4r;Rd_P+JD7eMKPfFKa* zf*_rsfDn-0yL9P>7JBSR7Z8w+RO!+?h!Cpu-XTbDh8Ak_?x6SYocFwcKkv*lb1r6J zhFrPIE^Dv7_gdf2&2vK;am7PV0)PHS7!^Ax^q5>AW9D$=Flbbs(C8IXJ${9EQ+!b_ z9z(nbovdPRV`^uB#hmx0bF`H`D*_Vp{q5>2s(b=Y8U>X&$2HmPOns~+U5w00M%?Q8 zD*t(dcA}90fq@2l+3p`E7>}C$Rnp!~x6NG58Wm!5-{-E74HviE)RYTY&3h*W<|CH3 zAdewkmGYRGR{Xcs;u#Ce1QKGEqa;xz@1lm@j7$?T_49%rZ(Z99oJMn3azS#litqaL3Mi1TTHhDRbh25MAOv1A5TFU zvcp`>i3_+|Lzl`Qg@9tp~=pvKb_D?IJ!&Ia{*5ZoyjGbwB&5={pzqm<^G{{)q|E5JX9r zWgo5i04ynfUsb#Pl1X&y$YW+E>{n1_q##zX83a9&)pLD@Y2SaVAV6tet=9C0Au267 zrmW@GPkQtD4;;_q$%VZuuQ`}~G;4n?oa^*dlWJCfli1_-=OTBDBJHd7m-EjGq{O?g zwo9wJkkz+TJt#@Ra((VLu(PmQl{5iV~^B*#a?A} zX`&zdhrafNgxukmF8qi6B=3IUvlL;;K&-%*f`R4c4Vd zW!tN4YSQq!a^i1HNG_}M3&}{x>^}T-md!yuE5fCne?Y`%{dRzjD)LwGvb09cGnYDk z+fAp2!RV^nzV=im#3Emc>|IWtzi^@fqvZ0sjdbM?ZsW?m-QmH(6D>D>UG*v&{T2Q# z3ejBknM=Nd*DOAXOuw)iZev9u`6s*h@9S-f_YsRKKdc;sh~K;r9bY+AwJqHrcCAw+ zevGCPKa&GiDmkX+M^I6@PaH}q>6j|-)W>;$+t0*1{WQ8|cnrI6#{J^I0OZ!YkeljH zQSo|b=!mEoB`NtH<2JR2k8OTVg#{{W4#Y)}XxWy4P2+;Ie*;JEfb^Or-4{3iG5_+L zj!HT_=~*Z9aN6RNV{nq!zW~|Rb93iCDGlBdHb{VA-ybyY9g@fdl~>OxN+rBD9-|Tr z4_0rcLiikdG{MEdc_sg3*Eg-S} z5BBXpfO(ghgzDcpP`lqWjl}x_rrpe2*YibL;f=VNhI1DI!06v2kl{* zw*YTnvpDUGJ;EgR*MDxH{=>8B;J4V8+lM%|H=1vBXR;zL!1QvZegE3(bA*~)tvN| ziioyO*wm7P&{xRMi0E2#MSKFkqMz~W{QIJ>DKyA1cA|BJ@m1cX`i zn}i35x>7NxflLRpzNW*YO?=Ok037}6*q2_y$z^A$`;+xL0}caW&)rJEV`{08CtKei zNl|j{7nx4RnnPU&(xXTi4t$aj=Ih5t_}@vp#y$ZL^K}Z@eLDb|!CArrFdH%Y%^^qe z45!G5(^7nC^@{#k{AFPVj6QCL1kY@Xw;y*q?hi%AMl2}AG#u7UVi!8&bh(~yiTe&u z`5f)`{nT|Xij5@thQz;Odh^Zas0)c(?%rOlcz$VJtB@_yExL1?0Ej-wYnvPWW};qn zAx08|V|POv)gm^HFk=sBMt;e9pX?4hFLp*JsAJONMUfJ#auFvQT7m-H5Y~}=c`nZm zQJ-mLUoC*8%~cLdAlodMop1TC<~O68Y()*x+e(VZ)%jEljHu7vl!6{s%y8oC4-m+Y zn)g^bg!~~(W?cGpOp7`Ljk%35dC^ra-Mj=5S3OzPnoU!=9D+b^GvDWh>qw2jiC4b z^Q86^%bBF_SoB{2aR^oN7!C6qx331m$}+wz{D0n+0J;6;;`R(e9x8BU;ZT!^Wxpv6 zu4b_H0Pw0Q7(QGb8y-rYqAt(iV=OJr7%=h`B>)++5b#PC>i`lV`axX53eDk%TsjRwiTxg+ z1;qVMqi11b(rb&$@0UsJj$6F|%X0gedV;nzsweb)huA%*nuBJ4o3G^1m6^1AFPNu| z+K~eH9;?T}opweFe-T5J;;$=x4FAlc+yLOx`=@-5KX-S3vb53M26_RZZ$v;JY<#@+ zaYE6$E;qYnvKle%Q(){=F6Bpjlm|jFn<+Wx&~PK}zs0z0i8}>CWBT zgol@0OdYqJL^tOkPhTZ@gJ8eHt^#@pe_IT-falL`o|?}ORO?(uoou&%ybHY0FYd4W zBq#v;=?i)@!Xmy^N#*1PQrX8vizpQ6(T_PSb|rNeNxde;=H=z-PPGB}r(OAMQV{17 zv`y)Qtk)^B_0lbf6Ntg=U0km#`fw~xAs(@#^h@=?3j}LJPofv!Y@;6lJA%{jGJl_&qu5R^)AM_BOOz5}JB|%9<9)KUOerZXUWv+gtxN!b7uIr^ppCORX zNzX#oe}_3)9tThF!rUYsgYt+KCytIl4jdSQKG057z}1}=jq7&;)+1bOi)aA*L&eET zKn+eES;YA~uQFW*!|&t}8yg!gvj9YSU{Utk1|I@4nnXG1v`}Ya!Rig8D5b_H=8jUe z^WpXSd@*(pA_mxU~ zPzckgIL5cIMDa6m@RA2R2IngioCYV2ehgpg<*2M@z+(si(d_KGHkh}7spzk_#`n~$ zrj9Sjvugd0`36Kvgm1OgS?3uSkACn~Gb7yB`vG7ze?pb@~WwJ(yOP{&>ttO7vqXu_Lrraz?y>nad5cY5C_}UkMnq_xctZMke3xyZh&||09WH*O*W@z9{;&H z3n1ymGy@6;L{}qqczj*>R0%A0%Hhp^p!1Wc8ZlV`kl{m&^;=`K2SYMNN$kf)zp@o* zgzIjmdv0Nf+X7Dm->bOl;H2hRn#umPB{sXUGr@fHmR+%_E2~u`+9|^o7F;rV`}3x4 zwb?S-V@NQj?EyuM;t*NXamjc~qwI5{DE2$RrGVIWD@1d5%=8wAr&afGXy@-2*bII; za)Gt5EHfOsh^7D-&|s9%LY?WQTnp^CRCn9p?_ex67lm!G>_R>O!3c^~m!t& z)ERl5ARg_&KxMSQjy&Fp{~m2V5R$Z!>kf@zzN^=jRNu2_zHY=v%(mD@NhskeMqwZg z{&PKDHMM15aFG2DLrci!c=vDVBl8FCYU^X}@wK zKF8K!o3XNKxUt`rj=)MAh3ha;^s0aDaW_f~$X(tTgpS&?H&!tHiA zLAG*K)c9UF)BTAjT&oAbEBjPxXWKpHv*-3eiTr%h1oCJvq0CvS_|ctehmHuCPlE6C zB3-$DX)_E%yw7!{Y{IAHvg&{rHD9`qyx$qlMvXshFg?Xf+|B+BIz3VLv`cUn-QQxj zxPJrxMx4cyJ->D;wkQoA?sEBdQZQYT_fY%h>@T+dBG5|Po?5geP_*KK2iNu?fb*dD z0g&&xH~a|onD1NV$lJKQeeX1_CXhZatz93dv<&wUJ< z{F7fH;G#Y!?R`{$%P@V+C56Rc5+4b9XaePbaVm@Tf~B|aNP+NaDVb?2fe~QZ1wNnG z^DOh~Hp(OJCwsPa<0%x^*1cv3-jrWZ5CTQC^;zg94BM2t;}O%V+EUQs9#zO2_qyHn z`Vhr}8Q5v~brrM@&ZHpu4)*D>7F(wG-A7KuEwx_QV;V-BVkyd~)d5cH1ISRBbb`K* zZ+!8^ZWvCNd=u|Z6tx;hVi)usQiCpyKlkt-{LxWRGliWbDG^gBJseX5n;UNM{cMq$ z^4vQVTo1QeoC%Dr(#M1HY-&Gl5SmQ#VxLbiSzd{JR}H>_0SEh-FMr$!#W7Dg120_w z!M7}8PN8dUXP5igbi`O-LGWv4Y{et{r%%4_hlphwXI=x&kFmz|1Q;XduD! zRyyrs$n{tUyNq;Z|qFFHZ}#g(u2RbOrDf24{CptzdAMPPp3g#zzH} zepQS>vMZ|oK;}kEZOiQ|U(BXV*8=|aMZrQ}x|@^i9Sg9i(HyXSm<=iq)BZr*W7M$r zAA^bJ>6&A`c&$Gia=~7p!uycN*&!K|qPTUA3Q1I zCx7^*sS|EHeKJL|RqR{ZFLXTvRvW<#SK}Y0&>ro(X_QxFLwSsw zrgT8!yXK|isEFOm$fM@XlXJihhv~8jX9b`X_WfU;J0Nj1&-9j-eC$NC6d`WA2)^U9B}Z(%P36ka;bx`I*^BDJ?V6+{hT( znhKQLvWc1X_b?C6f}GHQQt!;2#@tJ8rs~sz7=3Ml9f6s~hK9tpJ~THZ(uOgc^tNU&1+S{cpSg46w5vS~sx_saF7iurwN7*XINz4J)r)^Bu5v%VttIflLP@g29 z*NQ?hIa_oL*>CRnKr7?u@8o5n-%D%RI?<4SE4WNwpIlXQsUBy3;}_;p{aF$7NHf?F z9XwVL`3k=bQfbjE(S;>-p-BWs>t&)`kx9SWOW#*(WJ*O~sk;)(6 zuXxTxXdaS0snuYovn@`b+GoC<0;zoBSoHPDqpXaoX+5A)C*2WMa5;qK)_Y?WPqS}{ zgmsPeA{F`z@PTgJ0>bR$e6?d9A%dY80no^X{o5S{u3H5MN>;D}1ks zaYVhN#U?IQn_9j{Lo_&o-~mOn6oEH@DX+h9ILMi^D0j5`-T}zU zukYzs;3dFR_hWjd51Q{?Ul1%?qj30)+WpEaW?7Zyjy!RR)jLDac|qx zXb3O6?j@zl+Scc<>6-ijP71wne&Y|PnJ4uUHAK*X-?9_FN-Qy=tNciy;__aQId}r5 z!Ml?hzGBOc_Z)Rf#Rv4m6_<5cbo0cG1F}d~>NG6mH25FWi@DEi7PRzYp-aY^B)gwu zgATq%!;1jGGhP{Cdq{YjWJoxeOo)A(aXe|f{kpq31j_(3k2v1wEa!X>NuIecri`jwD!Ce`dJKJ3 z?(|f0p1uy#>)WVyy`QK*_3|0480oBj5R5bmH3(K{@9Mt#n4l2sUUR%EE+r zAD|~+i))-5M_)&z*xzg7SdR1 z+j=@>01G(YQZC53t2G`W7YiKBx#?i-@mIM~=Z@D*M1BdGGn_UXL5#tsgjhO6>&)BZ z>x0_y!nPr}FX&+1vqTcWTl(^2*G9#ogntqVu#awgFTmIxj{AZiY^I4-OSIr}7A4Rg z!(Lw!Qf^~v zF7sS?0IWh$5Ub^JF)GWM^s9XoD9;>GUXdurVLGpC^51pBinu!5fOK{DbEJRB$E9~a^5yeY!oyru4g;>$AwZafaP)XYwFPI0ibek=A0`Zr zxMWt3LjH{zxK=soIgM7x7c46SGzA2{7o>NcYA!Iotupv~HLi;?g1`UWn4^357}v?y zz;i0G{rIb>=snA%rHAx?m%Ed3&$D8^HmX2c`X$vr&sA0LvbwP`TMe7|PaG%xr`w|z zOFsnuUZVxbAH{4E@BSy*A3KxXz%i2apTzbkgD&pLzW;z8FXbsZpT!OQ`*p~WC>*fJX^$D{Q+=qf5P8Avs`TMt z@xQexNmt=APwDXo#CBt4d9=#qzXK=@eB*D#WGeo>dcKQ70WDB*IW6p$A~Wo;t*`#4 ziP$Qk50#kzU4Rez`!oa@lhfm0g@?=k?i2i9h@q6^nV)U+1HtF^_O*>F|KqjNii0D7 zgbMMkhZ)Hk-3BvLySu~2q5p-7q&ry2DKPRZ-RuUa$bkWuz_ZrRD|kT^pP@A%mVvz` z&+`OwBw`OF1KtV-Vd{rq=4z z;D~$i(QO6gW1GcLbAWm5L+nM@FE_p$ga3@J9yxhvROelqqXag+{;fM;(1wI=VV0Yw z_m($Tsd(y^Gt7*<=htV_K{$bFyvx0-^By3HiYOPYq~}n6$WwWC_|P?MJYNcFy^ z8NDgui!SjR2Hef+?!uj>0ymtTY5We&T$-1!1$fUiFPq^FpMts}SrO+wZ^Tmf8^6%Q zI#J1!7#zwjar+M=6$twFTzBO|H(Z)alTuxw5WZLY%#DH|HUol#K;r@s!wYl20&h9v zCh@zQ=_i*+5PrA`phD2(^$a`HX1XK$=C-(BJ}h( z?Z#@Pd?o)sWxu)A5=3*R`~_qMHgfW!W}o;s93B+RoPEz`&6v>sMoiz4LV z%y-c2j+zVLmU>g;yW+)MwUTmD-B%|W8zpWDTH*SdGit8M#h^7G>Ym#LJjLBMHKS`rdZm_TzxzP)oy%iCVuqY+YMB7Vh@4d$qDU`D#O0}7J^av{q}Yp)9z+dV z{-!gi^3HS9s%1f#ESbJYO2j`XLf{$K?>hgeT?L}_Rfs%;T1Fh4Lulb(!p5POA|*!- z%DUmFI#_eU(AM&|SSys_-oPazq6xs=J~@nvkOO-5x-gek!w_?yTrV@BU2du5x- z)kE#0D(Vu|clKik(LV&0_|x)z1oG7%ICrJk5($F;nX?jEy#<2-(I$lGTeIVU_R=aF??elv7#KhJL?Pg0-3LlpqG*0Xz z&~ho5{3hVr(NXWSsn!ndp%suK-%O&Qg#$s4&I=GMiDl1g)EFSkDAg%6>Nq2}T2#nF zHjtU!@eB+fEUDM8FFbuY=8*k~tfs_lSmLN@CJo4&%#@K(i}5{F;!mJqNXX!c;5Ni? z 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 diff --git a/docs/management/snapshot-restore/images/snapshot_details.png b/docs/management/snapshot-restore/images/snapshot_details.png deleted file mode 100644 index e6c463d7acb7f016e71f7e5f0d490cc3a547f73e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 190417 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
  1. !Rc)7LbQ+ToPGJOJjfWg94Bzh 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�g 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 diff --git a/docs/management/snapshot-restore/index.asciidoc b/docs/management/snapshot-restore/index.asciidoc deleted file mode 100644 index b041bd0873a05..0000000000000 --- a/docs/management/snapshot-restore/index.asciidoc +++ /dev/null @@ -1,299 +0,0 @@ -[role="xpack"] -[[snapshot-repositories]] -== Snapshot and Restore - -*Snapshot and Restore* lets you back up a running {es} -cluster using data and state snapshots. -Snapshots are important because they provide a copy of your data in case -something goes wrong. If you need to roll back to an older version of your data, -you can restore a snapshot from the repository. - -To get started, open the main menu, then click *Stack Management > Snapshot and Restore*. -With this UI, you can: - -* Register a repository for storing your snapshots -* View a list of your snapshots and drill down into details -* Restore data into your cluster from a snapshot -* Create a policy to automate snapshot creation and deletion -* Delete a snapshot to free storage space - -[role="screenshot"] -image:management/snapshot-restore/images/snapshot_list.png["Snapshot list"] - -Before using this feature, you should be familiar with how snapshots work. -{ref}/snapshot-restore.html[Snapshot and Restore] is a good source for -more detailed information. - -[float] -[[snapshot-permissions]] -=== Required permissions -The minimum required permissions to access *Snapshot and Restore* include: - -* Cluster privileges: `monitor`, `manage_slm`, `cluster:admin/snapshot`, and `cluster:admin/repository` -* Index privileges: `all` on the `monitor` index if you want to access content in the *Restore Status* tab - -To add privileges, open the main menu, then click *Stack Management > Roles*. - -[float] -[[kib-snapshot-register-repository]] -=== Register a repository -A repository is where your snapshots live. You must register a snapshot -repository before you can perform snapshot and restore operations. - -{kib} supports three repository types -out of the box: shared file system, read-only URL, and source-only. -For more information on these repositories and their settings, -see {ref}/snapshots-register-repository.html[Repositories]. -To use other repositories, such as S3, see -{ref}/snapshots-register-repository.html#snapshots-repository-plugins[Repository plugins]. - -The *Repositories* view displays a list of registered repositories. Click a -repository name to view information about the repository, verify its status, or -clean it up. - -[role="screenshot"] -image:management/snapshot-restore/images/repository_list.png["Repository list"] - - -[float] -[[kib-view-snapshot]] -=== View your snapshots - -A snapshot is a backup taken from a running {es} cluster. You'll find an overview of -your snapshots in the *Snapshots* view, and you can drill down -into each snapshot for further investigation. - -[role="screenshot"] -image:management/snapshot-restore/images/snapshot_details.png["Snapshot details"] - -If you don’t have any snapshots, you can create them using the -{ref}/create-snapshot-api.html[create snapshot API]. - -[float] -[[kib-restore-snapshot]] -=== Restore a snapshot - -The information stored in a snapshot is not tied to a specific -cluster or a cluster name. This enables you to -restore a snapshot made from one cluster to another cluster. You might -use the restore operation to: - -* Recover data lost due to a failure -* Migrate an {es} cluster to a new version -* Move data from one cluster to another cluster - -To get started, go to the *Snapshots* view, find the -snapshot, and click the restore icon in the *Actions* column. -The Restore wizard presents -options for the restore operation, including which -data streams and indices to restore and whether to change index settings. -You can restore an existing index only if it’s closed and has the same -number of shards as the index in the snapshot. - -Once you initiate the restore, you're navigated to the *Restore Status* view, -where you can track the current state for each shard in the snapshot. - -[role="screenshot"] -image:management/snapshot-restore/images/snapshot-restore.png["Snapshot details"] - - -[float] -[[kib-snapshot-policy]] -=== Create a snapshot lifecycle policy - -Use a {ref}/snapshot-lifecycle-management-api.html[snapshot lifecycle policy] -to automate the creation and deletion -of cluster snapshots. Taking automatic snapshots: - -* Ensures your {es} data is backed up on a regular basis -* Ensures a recent and relevant snapshot is available if a situation -arises where a cluster needs to be recovered -* Allows you to manage your snapshots in {kib}, instead of using a -third-party tool - -If you don’t have any snapshot policies, follow the -*Create policy* wizard. It walks you through defining -when and where to take snapshots, the settings you want, -and how long to retain snapshots. - -[role="screenshot"] -image:management/snapshot-restore/images/snapshot-retention.png["Snapshot details"] - -An overview of your policies is on the *Policies* view. -You can drill down into each policy to examine its settings and last successful and failed run. - -You can perform the following actions on a snapshot policy: - -* *Run* a policy immediately without waiting for the scheduled time. This action -is useful before an upgrade or before performing maintenance. -* *Edit* a policy and immediately apply changes to the schedule. -* *Delete* a policy to prevent any future snapshots from being taken. -This action does not cancel any currently ongoing snapshots or remove any previously taken snapshots. - -[role="screenshot"] -image:management/snapshot-restore/images/create-policy.png["Snapshot details"] - -[float] -[[kib-delete-snapshot]] -=== Delete a snapshot - -Delete snapshots to manage your repository storage space. -Find the snapshot in the *Snapshots* view and click the trash icon in the -*Actions* column. To delete snapshots in bulk, select their checkboxes, -and then click *Delete snapshots*. - -[[snapshot-repositories-example]] - -[role="xpack"] -[[snapshot-restore-tutorial]] -=== Tutorial: Snapshot and Restore - - -Ready to try *Snapshot and Restore*? In this tutorial, you'll learn to: - -* Register a repository -* Add snapshots to the repository -* Create a snapshot lifecycle policy -* Restore a snapshot - -==== Before you begin - -This example shows you how to register a shared file system repository -and store snapshots. - -Before you begin, you must first mount the file system to the same location on -all master and data nodes. Then add the file system’s path or parent directory -to the -{ref}/snapshots-register-repository.html#snapshots-filesystem-repository[`path.repo`] -setting in `elasticsearch.yml` for each master and data node. - -[float] -[[register-repo-example]] -==== Register a repository - -Use *Snapshot and Restore* to register the repository where your snapshots -will live. - -. Open the main menu, then click *Stack Management > Snapshot and Restore*. -. Click *Register a repository* in either the introductory message or *Repository view*. -. Enter a name for your repository, for example, `my_backup`. -. Select *Shared file system*. -+ -[role="screenshot"] -image:management/snapshot-restore/images/register_repo.png["Register repository"] - -. Click *Next*. -. In *File system location*, enter the path to the snapshot repository, `/tmp/es-backups`. -. In *Chunk size*, enter `100mb` so that snapshot files are not bigger than that size. -. Use the defaults for all other fields, and then click *Register*. -+ -Your new repository is listed on the *Repositories* view. -The repository currently doesn’t have any snapshots. - - -[float] -==== Add a snapshot to the repository -Use the {ref}/snapshots-take-snapshot.html[snapshot API] to create a snapshot. - -. Open the main menu, click *Dev Tools*, then select *Console*. -. Create the snapshot: -+ -[source,js] -PUT /_snapshot/my_backup/2099-04-25_snapshot?wait_for_completion=true -+ -In this example, the snapshot name is `2099-04-25_snapshot`. You can also -use {ref}/date-math-index-names.html[date math expression] for the snapshot name. - -. Return to *Snapshot and Restore*. -+ -Your new snapshot is available in the *Snapshots* view. - -[[create-policy-example]] -==== Create a snapshot lifecycle policy - -Now you'll automate the creation and deletion of snapshots -using the repository created in the previous example. - -. Open the *Policies* view. -. Click *Create a policy*. -+ -[role="screenshot"] -image:management/snapshot-restore/images/create-policy-example.png["Create policy wizard"] - -. As you walk through the wizard, enter the following values: -+ -|=== -|*Logistics* | - -|Policy name -|`daily-snapshots` - -|Snapshot name -|`` - -|Repository -|`my_backup` - -|Schedule -|Every day at 1:30 a.m. - -|*Snapshot settings* | - -|Data streams and indices -|Select the data streams and indices to back up. By default, all data streams -and indices, including system indices, are backed up. - -|All other settings -|Use the defaults. - -|*Snapshot retention* | - -|Expiration -|`30 days` - -|Snapshots to retain -|Minimum count: `5`, Maximum count: `50` -|=== - -. Review your input, and then click *Create policy*. -+ -Your new policy is listed in the *Policies* view, and you see a summary of its details. - -[[restore-snapshot-example]] -==== Restore a snapshot -Finally, you'll restore data streams and indices from an existing snapshot. - -. In the *Snapshots* view, find the snapshot you want to restore, for example `2099-04-25_snapshot`. -. Click the restore icon in the *Actions* column. -. As you walk through the wizard, enter the following values: -+ -|=== -|*Logistics* | - -|Data streams and indices -|Toggle to choose specific data streams and indices to restore. Use the default -to restore all data streams and indices in the snapshot. - -|Rename data streams and indices -|Toggle to give your restored data streams and indices new names. Use the -default to restore the original data stream and index names. - -|All other fields -|Use the defaults. - -|*Index settings* | - -|Modify index settings -|Toggle to overwrite index settings when they are restored, -or leave in place to keep existing settings. - -|Reset index settings -|Toggle to reset index settings back to the default when they are restored, -or leave in place to keep existing settings. -|=== - -. Review your restore settings, and then click *Restore snapshot*. -+ -The operation loads for a few seconds, -and then you’re navigated to *Restore Status*, -where you can monitor the status of your restored data streams and indices. diff --git a/docs/redirects.asciidoc b/docs/redirects.asciidoc index 2b00ccd67dc96..8b77bb7555027 100644 --- a/docs/redirects.asciidoc +++ b/docs/redirects.asciidoc @@ -7,6 +7,14 @@ The following pages have moved or been deleted. -- +[role="exclude",id="snapshot-repositories"] +== Snapshot and Restore +Refer to {ref}/snapshot-restore.html[Snapshot and Restore]. + +[role="exclude",id="snapshot-restore-tutorial"] +== Tutorial: Snapshot and Restore +Refer to {ref}/snapshot-restore.html[Snapshot and Restore]. + [role="exclude",id="configuring-tls"] == Encrypt TLS communications in {kib} Refer to {ref}/security-basic-setup-https.html#encrypt-kibana-http[Encrypt HTTP client communications for {kib}]. diff --git a/docs/setup/upgrade.asciidoc b/docs/setup/upgrade.asciidoc index f5ed03f85cc1a..29f21b850c13e 100644 --- a/docs/setup/upgrade.asciidoc +++ b/docs/setup/upgrade.asciidoc @@ -44,12 +44,12 @@ a| [[upgrade-before-you-begin]] === Before you begin -WARNING: {kib} automatically runs upgrade migrations when required. To roll back to an earlier version in case of an upgrade failure, you **must** have a backup snapshot available. Use <> to back up {kib} data by targeting the `.kibana*` indices. For more information see <>. +WARNING: {kib} automatically runs upgrade migrations when required. To roll back to an earlier version in case of an upgrade failure, you **must** have a {ref}/snapshot-restore.html[backup snapshot] available. This snapshot must include the `kibana` feature state or all `kibana*` indices. For more information see <>. Before you upgrade {kib}: * Consult the <>. -* Back up your data with <>. To roll back to an earlier version, you **must** have a snapshot of the `.kibana*` indices. +* {ref}/snapshots-take-snapshot.html[Take a snapshot] of your data. To roll back to an earlier version, the snapshot must include the `kibana` feature state or all `.kibana*` indices. * Although not a requirement for rollbacks, we recommend taking a snapshot of all {kib} indices created by the plugins you use such as the `.reporting*` indices created by the reporting plugin. * Before you upgrade production servers, test the upgrades in a dev environment. * See <> for common reasons upgrades fail and how to prevent these. diff --git a/docs/setup/upgrade/upgrade-migrations.asciidoc b/docs/setup/upgrade/upgrade-migrations.asciidoc index adf86d2b2b542..c47c2c1745e94 100644 --- a/docs/setup/upgrade/upgrade-migrations.asciidoc +++ b/docs/setup/upgrade/upgrade-migrations.asciidoc @@ -151,17 +151,17 @@ In order to rollback after a failed upgrade migration, the saved object indices [float] ===== Rollback by restoring a backup snapshot: -1. Before proceeding ensure that you have a recent and successful backup snapshot of all `.kibana*` indices. +1. Before proceeding, {ref}/snapshots-take-snapshot.html[take a snapshot] that contains the `kibana` feature state or all `.kibana*` indices. 2. Shutdown all {kib} instances to be 100% sure that there are no instances currently performing a migration. 3. Delete all saved object indices with `DELETE /.kibana*` -4. Restore the `.kibana* indices and their aliases from the backup snapshot. See {es} {ref}/modules-snapshots.html[snapshots] +4. {ref}/snapshots-restore-snapshot.html[Restore] the `kibana` feature state or all `.kibana* indices and their aliases from the snapshot. 5. Start up all {kib} instances on the older version you wish to rollback to. [float] ===== (Not recommended) Rollback without a backup snapshot: 1. Shutdown all {kib} instances to be 100% sure that there are no {kib} instances currently performing a migration. -2. Create a backup snapshot of the `.kibana*` indices. +2. {ref}/snapshots-take-snapshot.html[Take a snapshot] that includes the `kibana` feature state or all `.kibana*` indices. 3. Delete the version specific indices created by the failed upgrade migration. E.g. if you wish to rollback from a failed upgrade to v7.12.0 `DELETE /.kibana_7.12.0_*,.kibana_task_manager_7.12.0_*` 4. Inspect the output of `GET /_cat/aliases`. If either the `.kibana` and/or `.kibana_task_manager` alias is missing, these will have to be created manually. Find the latest index from the output of `GET /_cat/indices` and create the missing alias to point to the latest index. E.g. if the `.kibana` alias was missing and the latest index is `.kibana_3` create a new alias with `POST /.kibana_3/_aliases/.kibana`. 5. Remove the write block from the rollback indices. `PUT /.kibana,.kibana_task_manager/_settings {"index.blocks.write": false}` diff --git a/docs/template.asciidoc b/docs/template.asciidoc index 16cf8fd04933c..060c8611cc090 100644 --- a/docs/template.asciidoc +++ b/docs/template.asciidoc @@ -26,7 +26,6 @@ Provide a screenshot or video. //Screenshots must be 16:9 ratio. TIP: Need introduction inspiration? Here are some good examples: -* <> * <> * <> diff --git a/docs/user/management.asciidoc b/docs/user/management.asciidoc index 9d6392c39ba84..8888fcf568d94 100644 --- a/docs/user/management.asciidoc +++ b/docs/user/management.asciidoc @@ -45,7 +45,7 @@ through the hot, warm, cold, and delete phases. Such policies help you control operation costs because you can put data in different resource tiers. -| <> +| {ref}/snapshot-restore.html[Snapshot and Restore] |Define a policy that creates, schedules, and automatically deletes snapshots to ensure that you have backups of your cluster in case something goes wrong. @@ -193,8 +193,6 @@ include::{kib-repo-dir}/management/managing-saved-objects.asciidoc[] include::security/index.asciidoc[] -include::{kib-repo-dir}/management/snapshot-restore/index.asciidoc[] - include::{kib-repo-dir}/spaces/index.asciidoc[] include::{kib-repo-dir}/management/managing-tags.asciidoc[] diff --git a/src/core/public/doc_links/doc_links_service.ts b/src/core/public/doc_links/doc_links_service.ts index e9b82de9eaafa..7bdf149491ebc 100644 --- a/src/core/public/doc_links/doc_links_service.ts +++ b/src/core/public/doc_links/doc_links_service.ts @@ -428,7 +428,7 @@ export class DocLinksService { snapshotRestoreRepos: `${PLUGIN_DOCS}repository.html`, }, snapshotRestore: { - guide: `${KIBANA_DOCS}snapshot-repositories.html`, + guide: `${ELASTICSEARCH_DOCS}snapshot-restore.html`, changeIndexSettings: `${ELASTICSEARCH_DOCS}index-modules.html`, createSnapshot: `${ELASTICSEARCH_DOCS}snapshots-take-snapshot.html`, getSnapshot: `${ELASTICSEARCH_DOCS}get-snapshot-api.html`, From 87312b44ef90dcc384f36e5f206355fd2b9c2d26 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Tue, 16 Nov 2021 16:59:59 -0500 Subject: [PATCH 054/148] [Maps] Add gdal integration (#118633) --- ...-plugin-core-public.doclinksstart.links.md | 6 +- .../public/doc_links/doc_links_service.ts | 7 +- src/core/public/public.api.md | 6 +- .../custom_integrations/common/index.ts | 1 + .../apis/custom_integration/integrations.ts | 2 +- x-pack/plugins/maps/kibana.json | 1 + .../plugins/maps/public/assets/gdal_logo.svg | 129 ++++++++++++++++++ x-pack/plugins/maps/server/plugin.ts | 9 +- .../maps/server/register_integrations.ts | 38 ++++++ .../maps/server/tutorials/ems/index.ts | 6 +- 10 files changed, 197 insertions(+), 8 deletions(-) create mode 100644 x-pack/plugins/maps/public/assets/gdal_logo.svg create mode 100644 x-pack/plugins/maps/server/register_integrations.ts diff --git a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md b/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md index d7f159ad6f627..6e50afedbe0b2 100644 --- a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md +++ b/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md @@ -211,7 +211,11 @@ readonly links: { uptimeDurationAnomaly: string; }>; readonly alerting: Record; - readonly maps: Record; + readonly maps: Readonly<{ + guide: string; + importGeospatialPrivileges: string; + gdalTutorial: string; + }>; readonly monitoring: Record; readonly security: Readonly<{ apiKeyServiceSettings: string; diff --git a/src/core/public/doc_links/doc_links_service.ts b/src/core/public/doc_links/doc_links_service.ts index 7bdf149491ebc..a9330ce499cac 100644 --- a/src/core/public/doc_links/doc_links_service.ts +++ b/src/core/public/doc_links/doc_links_service.ts @@ -347,6 +347,7 @@ export class DocLinksService { maps: { guide: `${KIBANA_DOCS}maps.html`, importGeospatialPrivileges: `${KIBANA_DOCS}import-geospatial-data.html#import-geospatial-privileges`, + gdalTutorial: `${ELASTIC_WEBSITE_URL}blog/how-to-ingest-geospatial-data-into-elasticsearch-with-gdal`, }, monitoring: { alertsKibana: `${KIBANA_DOCS}kibana-alerts.html`, @@ -735,7 +736,11 @@ export interface DocLinksStart { uptimeDurationAnomaly: string; }>; readonly alerting: Record; - readonly maps: Record; + readonly maps: Readonly<{ + guide: string; + importGeospatialPrivileges: string; + gdalTutorial: string; + }>; readonly monitoring: Record; readonly security: Readonly<{ apiKeyServiceSettings: string; diff --git a/src/core/public/public.api.md b/src/core/public/public.api.md index 2e75d3f1ba035..593a02a16c15a 100644 --- a/src/core/public/public.api.md +++ b/src/core/public/public.api.md @@ -682,7 +682,11 @@ export interface DocLinksStart { uptimeDurationAnomaly: string; }>; readonly alerting: Record; - readonly maps: Record; + readonly maps: Readonly<{ + guide: string; + importGeospatialPrivileges: string; + gdalTutorial: string; + }>; readonly monitoring: Record; readonly security: Readonly<{ apiKeyServiceSettings: string; diff --git a/src/plugins/custom_integrations/common/index.ts b/src/plugins/custom_integrations/common/index.ts index f00b4c39405d5..7881a4a0ca880 100755 --- a/src/plugins/custom_integrations/common/index.ts +++ b/src/plugins/custom_integrations/common/index.ts @@ -45,6 +45,7 @@ export const INTEGRATION_CATEGORY_DISPLAY = { language_client: 'Language client', upload_file: 'Upload a file', website_search: 'Website search', + geo: 'Geo', }; /** diff --git a/test/api_integration/apis/custom_integration/integrations.ts b/test/api_integration/apis/custom_integration/integrations.ts index 036eb2ef33c78..4d3915f5f2294 100644 --- a/test/api_integration/apis/custom_integration/integrations.ts +++ b/test/api_integration/apis/custom_integration/integrations.ts @@ -22,7 +22,7 @@ export default function ({ getService }: FtrProviderContext) { expect(resp.body).to.be.an('array'); - expect(resp.body.length).to.be(34); + expect(resp.body.length).to.be(35); // Test for sample data card expect(resp.body.findIndex((c: { id: string }) => c.id === 'sample_data_all')).to.be.above( diff --git a/x-pack/plugins/maps/kibana.json b/x-pack/plugins/maps/kibana.json index 2aa2e4a756490..59b86dc6e6394 100644 --- a/x-pack/plugins/maps/kibana.json +++ b/x-pack/plugins/maps/kibana.json @@ -25,6 +25,7 @@ "presentationUtil" ], "optionalPlugins": [ + "customIntegrations", "home", "savedObjectsTagging", "charts", diff --git a/x-pack/plugins/maps/public/assets/gdal_logo.svg b/x-pack/plugins/maps/public/assets/gdal_logo.svg new file mode 100644 index 0000000000000..7753b9558cea2 --- /dev/null +++ b/x-pack/plugins/maps/public/assets/gdal_logo.svg @@ -0,0 +1,129 @@ + + + + + + ]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/x-pack/plugins/maps/server/plugin.ts b/x-pack/plugins/maps/server/plugin.ts index b98f7a8d55e03..b35f680df457c 100644 --- a/x-pack/plugins/maps/server/plugin.ts +++ b/x-pack/plugins/maps/server/plugin.ts @@ -39,6 +39,8 @@ import { EMSSettings } from '../common/ems_settings'; import { PluginStart as DataPluginStart } from '../../../../src/plugins/data/server'; import { EmbeddableSetup } from '../../../../src/plugins/embeddable/server'; import { embeddableMigrations } from './embeddable_migrations'; +import { CustomIntegrationsPluginSetup } from '../../../../src/plugins/custom_integrations/server'; +import { registerIntegrations } from './register_integrations'; interface SetupDeps { features: FeaturesPluginSetupContract; @@ -47,6 +49,7 @@ interface SetupDeps { licensing: LicensingPluginSetup; mapsEms: MapsEmsPluginSetup; embeddable: EmbeddableSetup; + customIntegrations?: CustomIntegrationsPluginSetup; } export interface StartDeps { @@ -159,7 +162,7 @@ export class MapsPlugin implements Plugin { // @ts-ignore setup(core: CoreSetup, plugins: SetupDeps) { - const { usageCollection, home, licensing, features, mapsEms } = plugins; + const { usageCollection, home, licensing, features, mapsEms, customIntegrations } = plugins; const mapsEmsConfig = mapsEms.config; const config$ = this._initializerContext.config.create(); @@ -178,6 +181,10 @@ export class MapsPlugin implements Plugin { this._initHomeData(home, core.http.basePath.prepend, emsSettings); } + if (customIntegrations) { + registerIntegrations(core, customIntegrations); + } + features.registerKibanaFeature({ id: APP_ID, name: i18n.translate('xpack.maps.featureRegistry.mapsFeatureName', { diff --git a/x-pack/plugins/maps/server/register_integrations.ts b/x-pack/plugins/maps/server/register_integrations.ts new file mode 100644 index 0000000000000..8832c746f6db8 --- /dev/null +++ b/x-pack/plugins/maps/server/register_integrations.ts @@ -0,0 +1,38 @@ +/* + * 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 { CoreSetup } from 'kibana/server'; +import { CustomIntegrationsPluginSetup } from '../../../../src/plugins/custom_integrations/server'; +import { APP_ID } from '../common/constants'; + +export function registerIntegrations( + core: CoreSetup, + customIntegrations: CustomIntegrationsPluginSetup +) { + customIntegrations.registerCustomIntegration({ + id: 'ingest_with_gdal', + title: i18n.translate('xpack.maps.registerIntegrations.gdal.integrationTitle', { + defaultMessage: 'GDAL', + }), + description: i18n.translate('xpack.maps.registerIntegrations.gdal.integrationDescription', { + defaultMessage: + 'Upload shapefiles and ingest from relational databases such as PostGIS or Oracle Spatial with GDAL.', + }), + uiInternalPath: + 'https://www.elastic.co/blog/how-to-ingest-geospatial-data-into-elasticsearch-with-gdal', + icons: [ + { + type: 'svg', + src: core.http.basePath.prepend(`/plugins/${APP_ID}/assets/gdal_logo.svg`), + }, + ], + categories: ['upload_file', 'geo'], + shipper: 'other', + isBeta: false, + }); +} diff --git a/x-pack/plugins/maps/server/tutorials/ems/index.ts b/x-pack/plugins/maps/server/tutorials/ems/index.ts index 47cb5476c4b90..2285371444fc7 100644 --- a/x-pack/plugins/maps/server/tutorials/ems/index.ts +++ b/x-pack/plugins/maps/server/tutorials/ems/index.ts @@ -7,7 +7,7 @@ import { i18n } from '@kbn/i18n'; import { TutorialsCategory } from '../../../../../../src/plugins/home/server'; -import { getNewMapPath } from '../../../common/constants'; +import { getNewMapPath, APP_ID } from '../../../common/constants'; export function emsBoundariesSpecProvider({ emsLandingPageUrl, @@ -75,9 +75,9 @@ Indexing EMS administrative boundaries in Elasticsearch allows for search on bou }), euiIconType: 'emsApp', completionTimeMinutes: 1, - previewImagePath: '/plugins/maps/assets/boundaries_screenshot.png', + previewImagePath: `/plugins/${APP_ID}/assets/boundaries_screenshot.png`, onPrem: instructions, elasticCloud: instructions, - integrationBrowserCategories: ['upload_file'], + integrationBrowserCategories: ['upload_file', 'geo'], }); } From f09fd062d3d6895617377af7c3c2cb8c788b7623 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Tue, 16 Nov 2021 16:17:15 -0700 Subject: [PATCH 055/148] [Maps] convert mb_map/utils to typescript (#118787) * [Maps] convert mb_map/utils to typescript * eslint Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../vector_tile_layer/vector_tile_layer.tsx | 4 +- .../connected_components/mb_map/mb_map.tsx | 1 - .../mb_map/{utils.js => utils.ts} | 40 +++++++++++++------ 3 files changed, 29 insertions(+), 16 deletions(-) rename x-pack/plugins/maps/public/connected_components/mb_map/{utils.js => utils.ts} (73%) diff --git a/x-pack/plugins/maps/public/classes/layers/vector_tile_layer/vector_tile_layer.tsx b/x-pack/plugins/maps/public/classes/layers/vector_tile_layer/vector_tile_layer.tsx index 2b36ecc160954..dc682590d123b 100644 --- a/x-pack/plugins/maps/public/classes/layers/vector_tile_layer/vector_tile_layer.tsx +++ b/x-pack/plugins/maps/public/classes/layers/vector_tile_layer/vector_tile_layer.tsx @@ -15,7 +15,6 @@ import { isRetina } from '../../../util'; import { addSpriteSheetToMapFromImageData, loadSpriteSheetImageData, - // @ts-expect-error } from '../../../connected_components/mb_map/utils'; import { DataRequestContext } from '../../../actions'; import { EMSTMSSource } from '../../sources/ems_tms_source'; @@ -28,12 +27,13 @@ interface SourceRequestMeta { interface EmsSprite { height: number; pixelRatio: number; + sdf?: boolean; width: number; x: number; y: number; } -interface EmsSpriteSheet { +export interface EmsSpriteSheet { [spriteName: string]: EmsSprite; } diff --git a/x-pack/plugins/maps/public/connected_components/mb_map/mb_map.tsx b/x-pack/plugins/maps/public/connected_components/mb_map/mb_map.tsx index eb0196ea156aa..32c87f6320d40 100644 --- a/x-pack/plugins/maps/public/connected_components/mb_map/mb_map.tsx +++ b/x-pack/plugins/maps/public/connected_components/mb_map/mb_map.tsx @@ -44,7 +44,6 @@ import { addSpriteSheetToMapFromImageData, loadSpriteSheetImageData, removeOrphanedSourcesAndLayers, - // @ts-expect-error } from './utils'; import { ResizeChecker } from '../../../../../../src/plugins/kibana_utils/public'; import { RenderToolTipContent } from '../../classes/tooltips/tooltip_property'; diff --git a/x-pack/plugins/maps/public/connected_components/mb_map/utils.js b/x-pack/plugins/maps/public/connected_components/mb_map/utils.ts similarity index 73% rename from x-pack/plugins/maps/public/connected_components/mb_map/utils.js rename to x-pack/plugins/maps/public/connected_components/mb_map/utils.ts index 5a2a98a24fca1..022db59263242 100644 --- a/x-pack/plugins/maps/public/connected_components/mb_map/utils.js +++ b/x-pack/plugins/maps/public/connected_components/mb_map/utils.ts @@ -5,13 +5,24 @@ * 2.0. */ +import type { Map as MbMap } from '@kbn/mapbox-gl'; +// @ts-expect-error import { RGBAImage } from './image_utils'; import { isGlDrawLayer } from './sort_layers'; +import { ILayer } from '../../classes/layers/layer'; +import { EmsSpriteSheet } from '../../classes/layers/vector_tile_layer/vector_tile_layer'; -export function removeOrphanedSourcesAndLayers(mbMap, layerList, spatialFilterLayer) { +export function removeOrphanedSourcesAndLayers( + mbMap: MbMap, + layerList: ILayer[], + spatialFilterLayer: ILayer +) { const mbStyle = mbMap.getStyle(); + if (!mbStyle.layers) { + return; + } - const mbLayerIdsToRemove = []; + const mbLayerIdsToRemove: string[] = []; mbStyle.layers.forEach((mbLayer) => { // ignore mapbox layers from spatial filter layer if (spatialFilterLayer.ownsMbLayerId(mbLayer.id)) { @@ -23,10 +34,10 @@ export function removeOrphanedSourcesAndLayers(mbMap, layerList, spatialFilterLa return; } - const layer = layerList.find((layer) => { + const targetLayer = layerList.find((layer) => { return layer.ownsMbLayerId(mbLayer.id); }); - if (!layer) { + if (!targetLayer) { mbLayerIdsToRemove.push(mbLayer.id); } }); @@ -40,10 +51,10 @@ export function removeOrphanedSourcesAndLayers(mbMap, layerList, spatialFilterLa return; } - const layer = layerList.find((layer) => { + const targetLayer = layerList.find((layer) => { return layer.ownsMbSourceId(mbSourceId); }); - if (!layer) { + if (!targetLayer) { mbSourcesToRemove.push(mbSourceId); } } @@ -51,7 +62,7 @@ export function removeOrphanedSourcesAndLayers(mbMap, layerList, spatialFilterLa mbSourcesToRemove.forEach((mbSourceId) => mbMap.removeSource(mbSourceId)); } -function getImageData(img) { +function getImageData(img: HTMLImageElement) { const canvas = window.document.createElement('canvas'); const context = canvas.getContext('2d'); if (!context) { @@ -63,7 +74,7 @@ function getImageData(img) { return context.getImageData(0, 0, img.width, img.height); } -function isCrossOriginUrl(url) { +function isCrossOriginUrl(url: string) { const a = window.document.createElement('a'); a.href = url; return ( @@ -73,15 +84,14 @@ function isCrossOriginUrl(url) { ); } -export async function loadSpriteSheetImageData(imgUrl) { +export async function loadSpriteSheetImageData(imgUrl: string): Promise { return new Promise((resolve, reject) => { const image = new Image(); if (isCrossOriginUrl(imgUrl)) { image.crossOrigin = 'Anonymous'; } - image.onload = (el) => { - const imgData = getImageData(el.currentTarget); - resolve(imgData); + image.onload = (event) => { + resolve(getImageData(image)); }; image.onerror = (e) => { reject(e); @@ -90,7 +100,11 @@ export async function loadSpriteSheetImageData(imgUrl) { }); } -export function addSpriteSheetToMapFromImageData(json, imgData, mbMap) { +export function addSpriteSheetToMapFromImageData( + json: EmsSpriteSheet, + imgData: ImageData, + mbMap: MbMap +) { for (const imageId in json) { if (!(json.hasOwnProperty(imageId) && !mbMap.hasImage(imageId))) { continue; From 10c5318c3d97e8411825362cffe1592aa532d0e8 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 16 Nov 2021 16:38:45 -0700 Subject: [PATCH 056/148] Update babel (main) (#118741) Co-authored-by: Renovate Bot Co-authored-by: spalger --- package.json | 44 +- packages/kbn-babel-preset/node_preset.js | 1 + packages/kbn-babel-preset/webpack_preset.js | 1 + packages/kbn-pm/dist/index.js | 60 +- yarn.lock | 2113 ++++++------------- 5 files changed, 713 insertions(+), 1506 deletions(-) diff --git a/package.json b/package.json index f866db8ef57e8..fcc4b773dddad 100644 --- a/package.json +++ b/package.json @@ -92,7 +92,7 @@ "yarn": "^1.21.1" }, "dependencies": { - "@babel/runtime": "^7.15.4", + "@babel/runtime": "^7.16.3", "@dnd-kit/core": "^3.1.1", "@dnd-kit/sortable": "^4.0.0", "@dnd-kit/utilities": "^2.0.0", @@ -410,25 +410,25 @@ "yauzl": "^2.10.0" }, "devDependencies": { - "@babel/cli": "^7.15.7", - "@babel/core": "^7.15.8", - "@babel/eslint-parser": "^7.15.8", + "@babel/cli": "^7.16.0", + "@babel/core": "^7.16.0", + "@babel/eslint-parser": "^7.16.3", "@babel/eslint-plugin": "^7.14.5", - "@babel/generator": "^7.15.8", - "@babel/parser": "^7.15.8", - "@babel/plugin-proposal-class-properties": "^7.14.5", - "@babel/plugin-proposal-export-namespace-from": "^7.14.5", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.14.5", - "@babel/plugin-proposal-object-rest-spread": "^7.15.6", - "@babel/plugin-proposal-optional-chaining": "^7.14.5", - "@babel/plugin-proposal-private-methods": "^7.14.5", - "@babel/plugin-transform-runtime": "^7.15.8", - "@babel/preset-env": "^7.15.8", - "@babel/preset-react": "^7.14.5", - "@babel/preset-typescript": "^7.15.0", - "@babel/register": "^7.15.3", - "@babel/traverse": "^7.15.4", - "@babel/types": "^7.15.6", + "@babel/generator": "^7.16.0", + "@babel/parser": "^7.16.3", + "@babel/plugin-proposal-class-properties": "^7.16.0", + "@babel/plugin-proposal-export-namespace-from": "^7.16.0", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.16.0", + "@babel/plugin-proposal-object-rest-spread": "^7.16.0", + "@babel/plugin-proposal-optional-chaining": "^7.16.0", + "@babel/plugin-proposal-private-methods": "^7.16.0", + "@babel/plugin-transform-runtime": "^7.16.0", + "@babel/preset-env": "^7.16.0", + "@babel/preset-react": "^7.16.0", + "@babel/preset-typescript": "^7.16.0", + "@babel/register": "^7.16.0", + "@babel/traverse": "^7.16.3", + "@babel/types": "^7.16.0", "@bazel/ibazel": "^0.15.10", "@bazel/typescript": "^3.8.0", "@cypress/snapshot": "^2.1.7", @@ -511,8 +511,8 @@ "@types/deep-freeze-strict": "^1.1.0", "@types/delete-empty": "^2.0.0", "@types/ejs": "^3.0.6", - "@types/elasticsearch": "^5.0.33", "@types/elastic__datemath": "link:bazel-bin/packages/elastic-datemath/npm_module_types", + "@types/elasticsearch": "^5.0.33", "@types/enzyme": "^3.10.8", "@types/eslint": "^7.28.0", "@types/extract-zip": "^1.6.2", @@ -654,9 +654,9 @@ "babel-jest": "^26.6.3", "babel-loader": "^8.2.2", "babel-plugin-add-module-exports": "^1.0.4", - "babel-plugin-istanbul": "^6.0.0", + "babel-plugin-istanbul": "^6.1.1", "babel-plugin-require-context-hook": "^1.0.0", - "babel-plugin-styled-components": "^1.13.2", + "babel-plugin-styled-components": "^1.13.3", "babel-plugin-transform-react-remove-prop-types": "^0.4.24", "backport": "^5.6.6", "callsites": "^3.1.0", diff --git a/packages/kbn-babel-preset/node_preset.js b/packages/kbn-babel-preset/node_preset.js index e70ce15ca3f46..1c74d67716331 100644 --- a/packages/kbn-babel-preset/node_preset.js +++ b/packages/kbn-babel-preset/node_preset.js @@ -32,6 +32,7 @@ module.exports = (_, options = {}) => { // in the package.json in order to have the same polyfills between the environment // and the tests corejs: '3.2.1', + bugfixes: true, ...(options['@babel/preset-env'] || {}), }, diff --git a/packages/kbn-babel-preset/webpack_preset.js b/packages/kbn-babel-preset/webpack_preset.js index f9e4490f8cbf6..ea49c406d50f8 100644 --- a/packages/kbn-babel-preset/webpack_preset.js +++ b/packages/kbn-babel-preset/webpack_preset.js @@ -19,6 +19,7 @@ module.exports = () => { // Please read the explanation for this // in node_preset.js corejs: '3.2.1', + bugfixes: true, }, ], require('./common_preset'), diff --git a/packages/kbn-pm/dist/index.js b/packages/kbn-pm/dist/index.js index 49729eee0aa1e..e73f46a0504a6 100644 --- a/packages/kbn-pm/dist/index.js +++ b/packages/kbn-pm/dist/index.js @@ -542,16 +542,16 @@ Object.defineProperty(exports, "ToolingLog", { return _tooling_log.ToolingLog; } }); -Object.defineProperty(exports, "ToolingLogTextWriter", { +Object.defineProperty(exports, "ToolingLogCollectingWriter", { enumerable: true, get: function () { - return _tooling_log_text_writer.ToolingLogTextWriter; + return _tooling_log_collecting_writer.ToolingLogCollectingWriter; } }); -Object.defineProperty(exports, "pickLevelFromFlags", { +Object.defineProperty(exports, "ToolingLogTextWriter", { enumerable: true, get: function () { - return _log_levels.pickLevelFromFlags; + return _tooling_log_text_writer.ToolingLogTextWriter; } }); Object.defineProperty(exports, "parseLogLevel", { @@ -560,10 +560,10 @@ Object.defineProperty(exports, "parseLogLevel", { return _log_levels.parseLogLevel; } }); -Object.defineProperty(exports, "ToolingLogCollectingWriter", { +Object.defineProperty(exports, "pickLevelFromFlags", { enumerable: true, get: function () { - return _tooling_log_collecting_writer.ToolingLogCollectingWriter; + return _log_levels.pickLevelFromFlags; } }); @@ -8677,10 +8677,10 @@ module.exports = (chalk, temporary) => { Object.defineProperty(exports, "__esModule", { value: true }); -exports.pickLevelFromFlags = pickLevelFromFlags; +exports.LOG_LEVEL_FLAGS = exports.DEFAULT_LOG_LEVEL = void 0; exports.getLogLevelFlagsHelp = getLogLevelFlagsHelp; exports.parseLogLevel = parseLogLevel; -exports.LOG_LEVEL_FLAGS = exports.DEFAULT_LOG_LEVEL = void 0; +exports.pickLevelFromFlags = pickLevelFromFlags; /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one @@ -33051,11 +33051,7 @@ Object.defineProperty(exports, "__esModule", { exports.codeFrameColumns = codeFrameColumns; exports.default = _default; -var _highlight = _interopRequireWildcard(__webpack_require__(357)); - -function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; } - -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } +var _highlight = __webpack_require__(357); let deprecationWarningShown = false; @@ -33150,7 +33146,7 @@ function codeFrameColumns(rawLines, loc, opts = {}) { const hasColumns = loc.start && typeof loc.start.column === "number"; const numberMaxWidth = String(end).length; const highlightedLines = highlighted ? (0, _highlight.default)(rawLines, opts) : rawLines; - let frame = highlightedLines.split(NEWLINE).slice(start, end).map((line, index) => { + let frame = highlightedLines.split(NEWLINE, end).slice(start, end).map((line, index) => { const number = start + 1 + index; const paddedNumber = ` ${number}`.slice(-numberMaxWidth); const gutter = ` ${paddedNumber} |`; @@ -33221,21 +33217,15 @@ function _default(rawLines, lineNumber, colNumber, opts = {}) { Object.defineProperty(exports, "__esModule", { value: true }); -exports.shouldHighlight = shouldHighlight; -exports.getChalk = getChalk; exports.default = highlight; +exports.getChalk = getChalk; +exports.shouldHighlight = shouldHighlight; -var jsTokensNs = _interopRequireWildcard(__webpack_require__(358)); +var _jsTokens = __webpack_require__(358); var _helperValidatorIdentifier = __webpack_require__(359); -var _chalk = _interopRequireDefault(__webpack_require__(362)); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; } - -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } +var _chalk = __webpack_require__(362); const sometimesKeywords = new Set(["as", "async", "from", "get", "of", "set"]); @@ -33257,9 +33247,6 @@ const NEWLINE = /\r\n|[\n\r\u2028\u2029]/; const BRACKET = /^[()[\]{}]$/; let tokenize; { - const { - matchToToken - } = jsTokensNs; const JSX_TAG = /^[a-z][\w-]*$/i; const getTokenType = function (token, offset, text) { @@ -33291,8 +33278,9 @@ let tokenize; tokenize = function* (text) { let match; - while (match = jsTokensNs.default.exec(text)) { - const token = matchToToken(match); + while (match = _jsTokens.default.exec(text)) { + const token = _jsTokens.matchToToken(match); + yield { type: getTokenType(token, match.index, text), value: token.value @@ -33321,14 +33309,14 @@ function highlightTokens(defs, text) { } function shouldHighlight(options) { - return !!_chalk.default.supportsColor || options.forceColor; + return !!_chalk.supportsColor || options.forceColor; } function getChalk(options) { - return options.forceColor ? new _chalk.default.constructor({ + return options.forceColor ? new _chalk.constructor({ enabled: true, level: 1 - }) : _chalk.default; + }) : _chalk; } function highlight(code, options = {}) { @@ -33446,13 +33434,13 @@ Object.defineProperty(exports, "__esModule", { exports.isIdentifierStart = isIdentifierStart; exports.isIdentifierChar = isIdentifierChar; exports.isIdentifierName = isIdentifierName; -let nonASCIIidentifierStartChars = "\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u037f\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u052f\u0531-\u0556\u0559\u0560-\u0588\u05d0-\u05ea\u05ef-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u0860-\u086a\u08a0-\u08b4\u08b6-\u08c7\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u09fc\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0af9\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c39\u0c3d\u0c58-\u0c5a\u0c60\u0c61\u0c80\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d04-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d54-\u0d56\u0d5f-\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e86-\u0e8a\u0e8c-\u0ea3\u0ea5\u0ea7-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f5\u13f8-\u13fd\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f8\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1878\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191e\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1c80-\u1c88\u1c90-\u1cba\u1cbd-\u1cbf\u1ce9-\u1cec\u1cee-\u1cf3\u1cf5\u1cf6\u1cfa\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2118-\u211d\u2124\u2126\u2128\u212a-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309b-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312f\u3131-\u318e\u31a0-\u31bf\u31f0-\u31ff\u3400-\u4dbf\u4e00-\u9ffc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua69d\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua7bf\ua7c2-\ua7ca\ua7f5-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua8fd\ua8fe\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\ua9e0-\ua9e4\ua9e6-\ua9ef\ua9fa-\ua9fe\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa7e-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uab30-\uab5a\uab5c-\uab69\uab70-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc"; -let nonASCIIidentifierChars = "\u200c\u200d\xb7\u0300-\u036f\u0387\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u0669\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7\u06e8\u06ea-\u06ed\u06f0-\u06f9\u0711\u0730-\u074a\u07a6-\u07b0\u07c0-\u07c9\u07eb-\u07f3\u07fd\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u08d3-\u08e1\u08e3-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09cb-\u09cd\u09d7\u09e2\u09e3\u09e6-\u09ef\u09fe\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2\u0ae3\u0ae6-\u0aef\u0afa-\u0aff\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b55-\u0b57\u0b62\u0b63\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c00-\u0c04\u0c3e-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0c66-\u0c6f\u0c81-\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0ce6-\u0cef\u0d00-\u0d03\u0d3b\u0d3c\u0d3e-\u0d44\u0d46-\u0d48\u0d4a-\u0d4d\u0d57\u0d62\u0d63\u0d66-\u0d6f\u0d81-\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0de6-\u0def\u0df2\u0df3\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0e50-\u0e59\u0eb1\u0eb4-\u0ebc\u0ec8-\u0ecd\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e\u0f3f\u0f71-\u0f84\u0f86\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102b-\u103e\u1040-\u1049\u1056-\u1059\u105e-\u1060\u1062-\u1064\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u1369-\u1371\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b4-\u17d3\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u18a9\u1920-\u192b\u1930-\u193b\u1946-\u194f\u19d0-\u19da\u1a17-\u1a1b\u1a55-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1ab0-\u1abd\u1abf\u1ac0\u1b00-\u1b04\u1b34-\u1b44\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1b82\u1ba1-\u1bad\u1bb0-\u1bb9\u1be6-\u1bf3\u1c24-\u1c37\u1c40-\u1c49\u1c50-\u1c59\u1cd0-\u1cd2\u1cd4-\u1ce8\u1ced\u1cf4\u1cf7-\u1cf9\u1dc0-\u1df9\u1dfb-\u1dff\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua620-\ua629\ua66f\ua674-\ua67d\ua69e\ua69f\ua6f0\ua6f1\ua802\ua806\ua80b\ua823-\ua827\ua82c\ua880\ua881\ua8b4-\ua8c5\ua8d0-\ua8d9\ua8e0-\ua8f1\ua8ff-\ua909\ua926-\ua92d\ua947-\ua953\ua980-\ua983\ua9b3-\ua9c0\ua9d0-\ua9d9\ua9e5\ua9f0-\ua9f9\uaa29-\uaa36\uaa43\uaa4c\uaa4d\uaa50-\uaa59\uaa7b-\uaa7d\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uaaeb-\uaaef\uaaf5\uaaf6\uabe3-\uabea\uabec\uabed\uabf0-\uabf9\ufb1e\ufe00-\ufe0f\ufe20-\ufe2f\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f"; +let nonASCIIidentifierStartChars = "\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u037f\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u052f\u0531-\u0556\u0559\u0560-\u0588\u05d0-\u05ea\u05ef-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u0860-\u086a\u0870-\u0887\u0889-\u088e\u08a0-\u08c9\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u09fc\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0af9\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c39\u0c3d\u0c58-\u0c5a\u0c5d\u0c60\u0c61\u0c80\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cdd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d04-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d54-\u0d56\u0d5f-\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e86-\u0e8a\u0e8c-\u0ea3\u0ea5\u0ea7-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f5\u13f8-\u13fd\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f8\u1700-\u1711\u171f-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1878\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191e\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4c\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1c80-\u1c88\u1c90-\u1cba\u1cbd-\u1cbf\u1ce9-\u1cec\u1cee-\u1cf3\u1cf5\u1cf6\u1cfa\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2118-\u211d\u2124\u2126\u2128\u212a-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309b-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312f\u3131-\u318e\u31a0-\u31bf\u31f0-\u31ff\u3400-\u4dbf\u4e00-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua69d\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua7ca\ua7d0\ua7d1\ua7d3\ua7d5-\ua7d9\ua7f2-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua8fd\ua8fe\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\ua9e0-\ua9e4\ua9e6-\ua9ef\ua9fa-\ua9fe\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa7e-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uab30-\uab5a\uab5c-\uab69\uab70-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc"; +let nonASCIIidentifierChars = "\u200c\u200d\xb7\u0300-\u036f\u0387\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u0669\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7\u06e8\u06ea-\u06ed\u06f0-\u06f9\u0711\u0730-\u074a\u07a6-\u07b0\u07c0-\u07c9\u07eb-\u07f3\u07fd\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u0898-\u089f\u08ca-\u08e1\u08e3-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09cb-\u09cd\u09d7\u09e2\u09e3\u09e6-\u09ef\u09fe\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2\u0ae3\u0ae6-\u0aef\u0afa-\u0aff\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b55-\u0b57\u0b62\u0b63\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c00-\u0c04\u0c3c\u0c3e-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0c66-\u0c6f\u0c81-\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0ce6-\u0cef\u0d00-\u0d03\u0d3b\u0d3c\u0d3e-\u0d44\u0d46-\u0d48\u0d4a-\u0d4d\u0d57\u0d62\u0d63\u0d66-\u0d6f\u0d81-\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0de6-\u0def\u0df2\u0df3\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0e50-\u0e59\u0eb1\u0eb4-\u0ebc\u0ec8-\u0ecd\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e\u0f3f\u0f71-\u0f84\u0f86\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102b-\u103e\u1040-\u1049\u1056-\u1059\u105e-\u1060\u1062-\u1064\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u1369-\u1371\u1712-\u1715\u1732-\u1734\u1752\u1753\u1772\u1773\u17b4-\u17d3\u17dd\u17e0-\u17e9\u180b-\u180d\u180f-\u1819\u18a9\u1920-\u192b\u1930-\u193b\u1946-\u194f\u19d0-\u19da\u1a17-\u1a1b\u1a55-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1ab0-\u1abd\u1abf-\u1ace\u1b00-\u1b04\u1b34-\u1b44\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1b82\u1ba1-\u1bad\u1bb0-\u1bb9\u1be6-\u1bf3\u1c24-\u1c37\u1c40-\u1c49\u1c50-\u1c59\u1cd0-\u1cd2\u1cd4-\u1ce8\u1ced\u1cf4\u1cf7-\u1cf9\u1dc0-\u1dff\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua620-\ua629\ua66f\ua674-\ua67d\ua69e\ua69f\ua6f0\ua6f1\ua802\ua806\ua80b\ua823-\ua827\ua82c\ua880\ua881\ua8b4-\ua8c5\ua8d0-\ua8d9\ua8e0-\ua8f1\ua8ff-\ua909\ua926-\ua92d\ua947-\ua953\ua980-\ua983\ua9b3-\ua9c0\ua9d0-\ua9d9\ua9e5\ua9f0-\ua9f9\uaa29-\uaa36\uaa43\uaa4c\uaa4d\uaa50-\uaa59\uaa7b-\uaa7d\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uaaeb-\uaaef\uaaf5\uaaf6\uabe3-\uabea\uabec\uabed\uabf0-\uabf9\ufb1e\ufe00-\ufe0f\ufe20-\ufe2f\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f"; const nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]"); const nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]"); nonASCIIidentifierStartChars = nonASCIIidentifierChars = null; -const astralIdentifierStartCodes = [0, 11, 2, 25, 2, 18, 2, 1, 2, 14, 3, 13, 35, 122, 70, 52, 268, 28, 4, 48, 48, 31, 14, 29, 6, 37, 11, 29, 3, 35, 5, 7, 2, 4, 43, 157, 19, 35, 5, 35, 5, 39, 9, 51, 157, 310, 10, 21, 11, 7, 153, 5, 3, 0, 2, 43, 2, 1, 4, 0, 3, 22, 11, 22, 10, 30, 66, 18, 2, 1, 11, 21, 11, 25, 71, 55, 7, 1, 65, 0, 16, 3, 2, 2, 2, 28, 43, 28, 4, 28, 36, 7, 2, 27, 28, 53, 11, 21, 11, 18, 14, 17, 111, 72, 56, 50, 14, 50, 14, 35, 349, 41, 7, 1, 79, 28, 11, 0, 9, 21, 107, 20, 28, 22, 13, 52, 76, 44, 33, 24, 27, 35, 30, 0, 3, 0, 9, 34, 4, 0, 13, 47, 15, 3, 22, 0, 2, 0, 36, 17, 2, 24, 85, 6, 2, 0, 2, 3, 2, 14, 2, 9, 8, 46, 39, 7, 3, 1, 3, 21, 2, 6, 2, 1, 2, 4, 4, 0, 19, 0, 13, 4, 159, 52, 19, 3, 21, 2, 31, 47, 21, 1, 2, 0, 185, 46, 42, 3, 37, 47, 21, 0, 60, 42, 14, 0, 72, 26, 230, 43, 117, 63, 32, 7, 3, 0, 3, 7, 2, 1, 2, 23, 16, 0, 2, 0, 95, 7, 3, 38, 17, 0, 2, 0, 29, 0, 11, 39, 8, 0, 22, 0, 12, 45, 20, 0, 35, 56, 264, 8, 2, 36, 18, 0, 50, 29, 113, 6, 2, 1, 2, 37, 22, 0, 26, 5, 2, 1, 2, 31, 15, 0, 328, 18, 190, 0, 80, 921, 103, 110, 18, 195, 2749, 1070, 4050, 582, 8634, 568, 8, 30, 114, 29, 19, 47, 17, 3, 32, 20, 6, 18, 689, 63, 129, 74, 6, 0, 67, 12, 65, 1, 2, 0, 29, 6135, 9, 1237, 43, 8, 8952, 286, 50, 2, 18, 3, 9, 395, 2309, 106, 6, 12, 4, 8, 8, 9, 5991, 84, 2, 70, 2, 1, 3, 0, 3, 1, 3, 3, 2, 11, 2, 0, 2, 6, 2, 64, 2, 3, 3, 7, 2, 6, 2, 27, 2, 3, 2, 4, 2, 0, 4, 6, 2, 339, 3, 24, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 7, 2357, 44, 11, 6, 17, 0, 370, 43, 1301, 196, 60, 67, 8, 0, 1205, 3, 2, 26, 2, 1, 2, 0, 3, 0, 2, 9, 2, 3, 2, 0, 2, 0, 7, 0, 5, 0, 2, 0, 2, 0, 2, 2, 2, 1, 2, 0, 3, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 1, 2, 0, 3, 3, 2, 6, 2, 3, 2, 3, 2, 0, 2, 9, 2, 16, 6, 2, 2, 4, 2, 16, 4421, 42717, 35, 4148, 12, 221, 3, 5761, 15, 7472, 3104, 541, 1507, 4938]; -const astralIdentifierCodes = [509, 0, 227, 0, 150, 4, 294, 9, 1368, 2, 2, 1, 6, 3, 41, 2, 5, 0, 166, 1, 574, 3, 9, 9, 370, 1, 154, 10, 176, 2, 54, 14, 32, 9, 16, 3, 46, 10, 54, 9, 7, 2, 37, 13, 2, 9, 6, 1, 45, 0, 13, 2, 49, 13, 9, 3, 2, 11, 83, 11, 7, 0, 161, 11, 6, 9, 7, 3, 56, 1, 2, 6, 3, 1, 3, 2, 10, 0, 11, 1, 3, 6, 4, 4, 193, 17, 10, 9, 5, 0, 82, 19, 13, 9, 214, 6, 3, 8, 28, 1, 83, 16, 16, 9, 82, 12, 9, 9, 84, 14, 5, 9, 243, 14, 166, 9, 71, 5, 2, 1, 3, 3, 2, 0, 2, 1, 13, 9, 120, 6, 3, 6, 4, 0, 29, 9, 41, 6, 2, 3, 9, 0, 10, 10, 47, 15, 406, 7, 2, 7, 17, 9, 57, 21, 2, 13, 123, 5, 4, 0, 2, 1, 2, 6, 2, 0, 9, 9, 49, 4, 2, 1, 2, 4, 9, 9, 330, 3, 19306, 9, 135, 4, 60, 6, 26, 9, 1014, 0, 2, 54, 8, 3, 82, 0, 12, 1, 19628, 1, 5319, 4, 4, 5, 9, 7, 3, 6, 31, 3, 149, 2, 1418, 49, 513, 54, 5, 49, 9, 0, 15, 0, 23, 4, 2, 14, 1361, 6, 2, 16, 3, 6, 2, 1, 2, 4, 262, 6, 10, 9, 419, 13, 1495, 6, 110, 6, 6, 9, 4759, 9, 787719, 239]; +const astralIdentifierStartCodes = [0, 11, 2, 25, 2, 18, 2, 1, 2, 14, 3, 13, 35, 122, 70, 52, 268, 28, 4, 48, 48, 31, 14, 29, 6, 37, 11, 29, 3, 35, 5, 7, 2, 4, 43, 157, 19, 35, 5, 35, 5, 39, 9, 51, 13, 10, 2, 14, 2, 6, 2, 1, 2, 10, 2, 14, 2, 6, 2, 1, 68, 310, 10, 21, 11, 7, 25, 5, 2, 41, 2, 8, 70, 5, 3, 0, 2, 43, 2, 1, 4, 0, 3, 22, 11, 22, 10, 30, 66, 18, 2, 1, 11, 21, 11, 25, 71, 55, 7, 1, 65, 0, 16, 3, 2, 2, 2, 28, 43, 28, 4, 28, 36, 7, 2, 27, 28, 53, 11, 21, 11, 18, 14, 17, 111, 72, 56, 50, 14, 50, 14, 35, 349, 41, 7, 1, 79, 28, 11, 0, 9, 21, 43, 17, 47, 20, 28, 22, 13, 52, 58, 1, 3, 0, 14, 44, 33, 24, 27, 35, 30, 0, 3, 0, 9, 34, 4, 0, 13, 47, 15, 3, 22, 0, 2, 0, 36, 17, 2, 24, 85, 6, 2, 0, 2, 3, 2, 14, 2, 9, 8, 46, 39, 7, 3, 1, 3, 21, 2, 6, 2, 1, 2, 4, 4, 0, 19, 0, 13, 4, 159, 52, 19, 3, 21, 2, 31, 47, 21, 1, 2, 0, 185, 46, 42, 3, 37, 47, 21, 0, 60, 42, 14, 0, 72, 26, 38, 6, 186, 43, 117, 63, 32, 7, 3, 0, 3, 7, 2, 1, 2, 23, 16, 0, 2, 0, 95, 7, 3, 38, 17, 0, 2, 0, 29, 0, 11, 39, 8, 0, 22, 0, 12, 45, 20, 0, 19, 72, 264, 8, 2, 36, 18, 0, 50, 29, 113, 6, 2, 1, 2, 37, 22, 0, 26, 5, 2, 1, 2, 31, 15, 0, 328, 18, 190, 0, 80, 921, 103, 110, 18, 195, 2637, 96, 16, 1070, 4050, 582, 8634, 568, 8, 30, 18, 78, 18, 29, 19, 47, 17, 3, 32, 20, 6, 18, 689, 63, 129, 74, 6, 0, 67, 12, 65, 1, 2, 0, 29, 6135, 9, 1237, 43, 8, 8936, 3, 2, 6, 2, 1, 2, 290, 46, 2, 18, 3, 9, 395, 2309, 106, 6, 12, 4, 8, 8, 9, 5991, 84, 2, 70, 2, 1, 3, 0, 3, 1, 3, 3, 2, 11, 2, 0, 2, 6, 2, 64, 2, 3, 3, 7, 2, 6, 2, 27, 2, 3, 2, 4, 2, 0, 4, 6, 2, 339, 3, 24, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 7, 1845, 30, 482, 44, 11, 6, 17, 0, 322, 29, 19, 43, 1269, 6, 2, 3, 2, 1, 2, 14, 2, 196, 60, 67, 8, 0, 1205, 3, 2, 26, 2, 1, 2, 0, 3, 0, 2, 9, 2, 3, 2, 0, 2, 0, 7, 0, 5, 0, 2, 0, 2, 0, 2, 2, 2, 1, 2, 0, 3, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 1, 2, 0, 3, 3, 2, 6, 2, 3, 2, 3, 2, 0, 2, 9, 2, 16, 6, 2, 2, 4, 2, 16, 4421, 42719, 33, 4152, 8, 221, 3, 5761, 15, 7472, 3104, 541, 1507, 4938]; +const astralIdentifierCodes = [509, 0, 227, 0, 150, 4, 294, 9, 1368, 2, 2, 1, 6, 3, 41, 2, 5, 0, 166, 1, 574, 3, 9, 9, 370, 1, 154, 10, 50, 3, 123, 2, 54, 14, 32, 10, 3, 1, 11, 3, 46, 10, 8, 0, 46, 9, 7, 2, 37, 13, 2, 9, 6, 1, 45, 0, 13, 2, 49, 13, 9, 3, 2, 11, 83, 11, 7, 0, 161, 11, 6, 9, 7, 3, 56, 1, 2, 6, 3, 1, 3, 2, 10, 0, 11, 1, 3, 6, 4, 4, 193, 17, 10, 9, 5, 0, 82, 19, 13, 9, 214, 6, 3, 8, 28, 1, 83, 16, 16, 9, 82, 12, 9, 9, 84, 14, 5, 9, 243, 14, 166, 9, 71, 5, 2, 1, 3, 3, 2, 0, 2, 1, 13, 9, 120, 6, 3, 6, 4, 0, 29, 9, 41, 6, 2, 3, 9, 0, 10, 10, 47, 15, 406, 7, 2, 7, 17, 9, 57, 21, 2, 13, 123, 5, 4, 0, 2, 1, 2, 6, 2, 0, 9, 9, 49, 4, 2, 1, 2, 4, 9, 9, 330, 3, 19306, 9, 87, 9, 39, 4, 60, 6, 26, 9, 1014, 0, 2, 54, 8, 3, 82, 0, 12, 1, 19628, 1, 4706, 45, 3, 22, 543, 4, 4, 5, 9, 7, 3, 6, 31, 3, 149, 2, 1418, 49, 513, 54, 5, 49, 9, 0, 15, 0, 23, 4, 2, 14, 1361, 6, 2, 16, 3, 6, 2, 1, 2, 4, 262, 6, 10, 9, 357, 0, 62, 13, 1495, 6, 110, 6, 6, 9, 4759, 9, 787719, 239]; function isInAstralSet(code, set) { let pos = 0x10000; diff --git a/yarn.lock b/yarn.lock index 983a2d18d4ec0..d1770613f0f6d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@babel/cli@^7.15.7": - version "7.15.7" - resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.15.7.tgz#62658abedb786d09c1f70229224b11a65440d7a1" - integrity sha512-YW5wOprO2LzMjoWZ5ZG6jfbY9JnkDxuHDwvnrThnuYtByorova/I0HNXJedrUfwuXFQfYOjcqDA4PU3qlZGZjg== +"@babel/cli@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.16.0.tgz#a729b7a48eb80b49f48a339529fc4129fd7bcef3" + integrity sha512-WLrM42vKX/4atIoQB+eb0ovUof53UUvecb4qGjU2PDDWRiZr50ZpiV8NpcLo7iSxeGYrRG0Mqembsa+UrTAV6Q== dependencies: commander "^4.0.1" convert-source-map "^1.1.0" @@ -32,36 +32,17 @@ dependencies: "@babel/highlight" "^7.10.4" -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.5.5": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.13.tgz#dcfc826beef65e75c50e21d3837d7d95798dd658" - integrity sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g== - dependencies: - "@babel/highlight" "^7.12.13" - -"@babel/code-frame@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.14.5.tgz#23b08d740e83f49c5e59945fbf1b43e80bbf4edb" - integrity sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw== - dependencies: - "@babel/highlight" "^7.14.5" - -"@babel/code-frame@^7.15.8": - version "7.15.8" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.15.8.tgz#45990c47adadb00c03677baa89221f7cc23d2503" - integrity sha512-2IAnmn8zbvC/jKYhq5Ki9I+DwjlrtMPUCH/CpHvqI4dNnlwHwsxoIhlc8WcYY5LSYknXQtAlFYuHfqAFCvQ4Wg== +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.16.0", "@babel/code-frame@^7.5.5": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.0.tgz#0dfc80309beec8411e65e706461c408b0bb9b431" + integrity sha512-IF4EOMEV+bfYwOmNxGzSnjR2EmQod7f1UXOpZM3l4i4o4QNwzjtJAu/HxdjHq0aYBvdqMuQEY1eg0nqW9ZPORA== dependencies: - "@babel/highlight" "^7.14.5" - -"@babel/compat-data@^7.12.5", "@babel/compat-data@^7.12.7": - version "7.12.7" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.12.7.tgz#9329b4782a7d6bbd7eef57e11addf91ee3ef1e41" - integrity sha512-YaxPMGs/XIWtYqrdEOZOCPsVWfEoriXopnsz3/i7apYPXQ3698UFhS6dVT1KN5qOsWmVgw/FOrmQgpRaZayGsw== + "@babel/highlight" "^7.16.0" -"@babel/compat-data@^7.13.11", "@babel/compat-data@^7.15.0": - version "7.15.0" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.15.0.tgz#2dbaf8b85334796cafbb0f5793a90a2fc010b176" - integrity sha512-0NqAC1IJE0S0+lL1SWFMxMkz1pKCNCjI4tr2Zx4LJSXxCLAdr6KyArnY+sno5m3yH9g737ygOyPABDsnXkpxiA== +"@babel/compat-data@^7.13.11", "@babel/compat-data@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.16.0.tgz#ea269d7f78deb3a7826c39a4048eecda541ebdaa" + integrity sha512-DGjt2QZse5SGd9nfOSqO4WLJ8NN/oHkijbXbPrxuoJO3oIPJL3TciZs9FX+cOHNiY9E9l0opL8g7BmLe3T+9ew== "@babel/core@7.12.9": version "7.12.9" @@ -105,41 +86,20 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/core@>=7.9.0", "@babel/core@^7.1.0", "@babel/core@^7.12.1", "@babel/core@^7.12.3", "@babel/core@^7.7.5": - version "7.12.10" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.12.10.tgz#b79a2e1b9f70ed3d84bbfb6d8c4ef825f606bccd" - integrity sha512-eTAlQKq65zHfkHZV0sIVODCPGVgoo1HdBlbSLi9CqOzuZanMv2ihzY+4paiKr1mH+XmYESMAmJ/dpZ68eN6d8w== - dependencies: - "@babel/code-frame" "^7.10.4" - "@babel/generator" "^7.12.10" - "@babel/helper-module-transforms" "^7.12.1" - "@babel/helpers" "^7.12.5" - "@babel/parser" "^7.12.10" - "@babel/template" "^7.12.7" - "@babel/traverse" "^7.12.10" - "@babel/types" "^7.12.10" - convert-source-map "^1.7.0" - debug "^4.1.0" - gensync "^1.0.0-beta.1" - json5 "^2.1.2" - lodash "^4.17.19" - semver "^5.4.1" - source-map "^0.5.0" - -"@babel/core@^7.15.8": - version "7.15.8" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.15.8.tgz#195b9f2bffe995d2c6c159e72fe525b4114e8c10" - integrity sha512-3UG9dsxvYBMYwRv+gS41WKHno4K60/9GPy1CJaH6xy3Elq8CTtvtjT5R5jmNhXfCYLX2mTw+7/aq5ak/gOE0og== - dependencies: - "@babel/code-frame" "^7.15.8" - "@babel/generator" "^7.15.8" - "@babel/helper-compilation-targets" "^7.15.4" - "@babel/helper-module-transforms" "^7.15.8" - "@babel/helpers" "^7.15.4" - "@babel/parser" "^7.15.8" - "@babel/template" "^7.15.4" - "@babel/traverse" "^7.15.4" - "@babel/types" "^7.15.6" +"@babel/core@>=7.9.0", "@babel/core@^7.1.0", "@babel/core@^7.12.1", "@babel/core@^7.12.3", "@babel/core@^7.16.0", "@babel/core@^7.7.5": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.16.0.tgz#c4ff44046f5fe310525cc9eb4ef5147f0c5374d4" + integrity sha512-mYZEvshBRHGsIAiyH5PzCFTCfbWfoYbO/jcSdXQSUQu1/pW0xDZAUP7KEc32heqWTAfAHhV9j1vH8Sav7l+JNQ== + dependencies: + "@babel/code-frame" "^7.16.0" + "@babel/generator" "^7.16.0" + "@babel/helper-compilation-targets" "^7.16.0" + "@babel/helper-module-transforms" "^7.16.0" + "@babel/helpers" "^7.16.0" + "@babel/parser" "^7.16.0" + "@babel/template" "^7.16.0" + "@babel/traverse" "^7.16.0" + "@babel/types" "^7.16.0" convert-source-map "^1.7.0" debug "^4.1.0" gensync "^1.0.0-beta.2" @@ -147,10 +107,10 @@ semver "^6.3.0" source-map "^0.5.0" -"@babel/eslint-parser@^7.15.8": - version "7.15.8" - resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.15.8.tgz#8988660b59d739500b67d0585fd4daca218d9f11" - integrity sha512-fYP7QFngCvgxjUuw8O057SVH5jCXsbFFOoE77CFDcvzwBVgTOkMD/L4mIC5Ud1xf8chK/no2fRbSSn1wvNmKuQ== +"@babel/eslint-parser@^7.16.3": + version "7.16.3" + resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.16.3.tgz#2a6b1702f3f5aea48e00cea5a5bcc241c437e459" + integrity sha512-iB4ElZT0jAt7PKVaeVulOECdGe6UnmA/O0P9jlF5g5GBOwDVbna8AXhHRu4s27xQf6OkveyA8iTDv1jHdDejgQ== dependencies: eslint-scope "^5.1.1" eslint-visitor-keys "^2.1.0" @@ -163,136 +123,64 @@ dependencies: eslint-rule-composer "^0.3.0" -"@babel/generator@^7.12.1", "@babel/generator@^7.12.10", "@babel/generator@^7.12.5", "@babel/generator@^7.13.0", "@babel/generator@^7.4.4": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.14.5.tgz#848d7b9f031caca9d0cd0af01b063f226f52d785" - integrity sha512-y3rlP+/G25OIX3mYKKIOlQRcqj7YgrvHxOLbVmyLJ9bPmi5ttvUmpydVjcFjZphOktWuA7ovbx91ECloWTfjIA== - dependencies: - "@babel/types" "^7.14.5" - jsesc "^2.5.1" - source-map "^0.5.0" - -"@babel/generator@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.15.4.tgz#85acb159a267ca6324f9793986991ee2022a05b0" - integrity sha512-d3itta0tu+UayjEORPNz6e1T3FtvWlP5N4V5M+lhp/CxT4oAA7/NcScnpRyspUMLK6tu9MNHmQHxRykuN2R7hw== - dependencies: - "@babel/types" "^7.15.4" - jsesc "^2.5.1" - source-map "^0.5.0" - -"@babel/generator@^7.15.8": - version "7.15.8" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.15.8.tgz#fa56be6b596952ceb231048cf84ee499a19c0cd1" - integrity sha512-ECmAKstXbp1cvpTTZciZCgfOt6iN64lR0d+euv3UZisU5awfRawOvg07Utn/qBGuH4bRIEZKrA/4LzZyXhZr8g== +"@babel/generator@^7.12.1", "@babel/generator@^7.12.5", "@babel/generator@^7.16.0", "@babel/generator@^7.4.4": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.16.0.tgz#d40f3d1d5075e62d3500bccb67f3daa8a95265b2" + integrity sha512-RR8hUCfRQn9j9RPKEVXo9LiwoxLPYn6hNZlvUOR8tSnaxlD0p0+la00ZP9/SnRt6HchKr+X0fO2r8vrETiJGew== dependencies: - "@babel/types" "^7.15.6" + "@babel/types" "^7.16.0" jsesc "^2.5.1" source-map "^0.5.0" -"@babel/helper-annotate-as-pure@^7.0.0", "@babel/helper-annotate-as-pure@^7.10.4", "@babel/helper-annotate-as-pure@^7.12.10": - version "7.12.10" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.12.10.tgz#54ab9b000e60a93644ce17b3f37d313aaf1d115d" - integrity sha512-XplmVbC1n+KY6jL8/fgLVXXUauDIB+lD5+GsQEh6F6GBF1dq1qy4DP4yXWzDKcoqXB3X58t61e85Fitoww4JVQ== +"@babel/helper-annotate-as-pure@^7.0.0", "@babel/helper-annotate-as-pure@^7.15.4", "@babel/helper-annotate-as-pure@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.0.tgz#9a1f0ebcda53d9a2d00108c4ceace6a5d5f1f08d" + integrity sha512-ItmYF9vR4zA8cByDocY05o0LGUkp1zhbTQOH1NFyl5xXEqlTJQCEJjieriw+aFpxo16swMxUnUiKS7a/r4vtHg== dependencies: - "@babel/types" "^7.12.10" + "@babel/types" "^7.16.0" -"@babel/helper-annotate-as-pure@^7.14.5", "@babel/helper-annotate-as-pure@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.15.4.tgz#3d0e43b00c5e49fdb6c57e421601a7a658d5f835" - integrity sha512-QwrtdNvUNsPCj2lfNQacsGSQvGX8ee1ttrBrcozUP2Sv/jylewBP/8QFe6ZkBsC8T/GYWonNAWJV4aRR9AL2DA== +"@babel/helper-builder-binary-assignment-operator-visitor@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.16.0.tgz#f1a686b92da794020c26582eb852e9accd0d7882" + integrity sha512-9KuleLT0e77wFUku6TUkqZzCEymBdtuQQ27MhEKzf9UOOJu3cYj98kyaDAzxpC7lV6DGiZFuC8XqDsq8/Kl6aQ== dependencies: - "@babel/types" "^7.15.4" + "@babel/helper-explode-assignable-expression" "^7.16.0" + "@babel/types" "^7.16.0" -"@babel/helper-builder-binary-assignment-operator-visitor@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.10.4.tgz#bb0b75f31bf98cbf9ff143c1ae578b87274ae1a3" - integrity sha512-L0zGlFrGWZK4PbT8AszSfLTM5sDU1+Az/En9VrdT8/LmEiJt4zXt+Jve9DCAnQcbqDhCI+29y/L93mrDzddCcg== - dependencies: - "@babel/helper-explode-assignable-expression" "^7.10.4" - "@babel/types" "^7.10.4" - -"@babel/helper-builder-binary-assignment-operator-visitor@^7.14.5": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.15.4.tgz#21ad815f609b84ee0e3058676c33cf6d1670525f" - integrity sha512-P8o7JP2Mzi0SdC6eWr1zF+AEYvrsZa7GSY1lTayjF5XJhVH0kjLYUZPvTMflP7tBgZoe9gIhTa60QwFpqh/E0Q== - dependencies: - "@babel/helper-explode-assignable-expression" "^7.15.4" - "@babel/types" "^7.15.4" - -"@babel/helper-compilation-targets@^7.12.5": - version "7.12.5" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.12.5.tgz#cb470c76198db6a24e9dbc8987275631e5d29831" - integrity sha512-+qH6NrscMolUlzOYngSBMIOQpKUGPPsc61Bu5W10mg84LxZ7cmvnBHzARKbDoFxVvqqAbj6Tg6N7bSrWSPXMyw== - dependencies: - "@babel/compat-data" "^7.12.5" - "@babel/helper-validator-option" "^7.12.1" - browserslist "^4.14.5" - semver "^5.5.0" - -"@babel/helper-compilation-targets@^7.13.0", "@babel/helper-compilation-targets@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.15.4.tgz#cf6d94f30fbefc139123e27dd6b02f65aeedb7b9" - integrity sha512-rMWPCirulnPSe4d+gwdWXLfAXTTBj8M3guAf5xFQJ0nvFY7tfNAFnWdqaHegHlgDZOCT4qvhF3BYlSJag8yhqQ== +"@babel/helper-compilation-targets@^7.13.0", "@babel/helper-compilation-targets@^7.16.0": + version "7.16.3" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.16.3.tgz#5b480cd13f68363df6ec4dc8ac8e2da11363cbf0" + integrity sha512-vKsoSQAyBmxS35JUOOt+07cLc6Nk/2ljLIHwmq2/NM6hdioUaqEXq/S+nXvbvXbZkNDlWOymPanJGOc4CBjSJA== dependencies: - "@babel/compat-data" "^7.15.0" + "@babel/compat-data" "^7.16.0" "@babel/helper-validator-option" "^7.14.5" - browserslist "^4.16.6" + browserslist "^4.17.5" semver "^6.3.0" -"@babel/helper-create-class-features-plugin@^7.12.1", "@babel/helper-create-class-features-plugin@^7.13.0", "@babel/helper-create-class-features-plugin@^7.3.0": - version "7.13.8" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.13.8.tgz#0367bd0a7505156ce018ca464f7ac91ba58c1a04" - integrity sha512-qioaRrKHQbn4hkRKDHbnuQ6kAxmmOF+kzKGnIfxPK4j2rckSJCpKzr/SSTlohSCiE3uAQpNDJ9FIh4baeE8W+w== +"@babel/helper-create-class-features-plugin@^7.13.0", "@babel/helper-create-class-features-plugin@^7.16.0", "@babel/helper-create-class-features-plugin@^7.3.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.16.0.tgz#090d4d166b342a03a9fec37ef4fd5aeb9c7c6a4b" + integrity sha512-XLwWvqEaq19zFlF5PTgOod4bUA+XbkR4WLQBct1bkzmxJGB0ZEJaoKF4c8cgH9oBtCDuYJ8BP5NB9uFiEgO5QA== dependencies: - "@babel/helper-function-name" "^7.12.13" - "@babel/helper-member-expression-to-functions" "^7.13.0" - "@babel/helper-optimise-call-expression" "^7.12.13" - "@babel/helper-replace-supers" "^7.13.0" - "@babel/helper-split-export-declaration" "^7.12.13" - -"@babel/helper-create-class-features-plugin@^7.14.5", "@babel/helper-create-class-features-plugin@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.15.4.tgz#7f977c17bd12a5fba363cb19bea090394bf37d2e" - integrity sha512-7ZmzFi+DwJx6A7mHRwbuucEYpyBwmh2Ca0RvI6z2+WLZYCqV0JOaLb+u0zbtmDicebgKBZgqbYfLaKNqSgv5Pw== - dependencies: - "@babel/helper-annotate-as-pure" "^7.15.4" - "@babel/helper-function-name" "^7.15.4" - "@babel/helper-member-expression-to-functions" "^7.15.4" - "@babel/helper-optimise-call-expression" "^7.15.4" - "@babel/helper-replace-supers" "^7.15.4" - "@babel/helper-split-export-declaration" "^7.15.4" - -"@babel/helper-create-regexp-features-plugin@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.12.1.tgz#18b1302d4677f9dc4740fe8c9ed96680e29d37e8" - integrity sha512-rsZ4LGvFTZnzdNZR5HZdmJVuXK8834R5QkF3WvcnBhrlVtF0HSIUC6zbreL9MgjTywhKokn8RIYRiq99+DLAxA== - dependencies: - "@babel/helper-annotate-as-pure" "^7.10.4" - "@babel/helper-regex" "^7.10.4" - regexpu-core "^4.7.1" + "@babel/helper-annotate-as-pure" "^7.16.0" + "@babel/helper-function-name" "^7.16.0" + "@babel/helper-member-expression-to-functions" "^7.16.0" + "@babel/helper-optimise-call-expression" "^7.16.0" + "@babel/helper-replace-supers" "^7.16.0" + "@babel/helper-split-export-declaration" "^7.16.0" -"@babel/helper-create-regexp-features-plugin@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.14.5.tgz#c7d5ac5e9cf621c26057722fb7a8a4c5889358c4" - integrity sha512-TLawwqpOErY2HhWbGJ2nZT5wSkR192QpN+nBg1THfBfftrlvOh+WbhrxXCH4q4xJ9Gl16BGPR/48JA+Ryiho/A== +"@babel/helper-create-regexp-features-plugin@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.16.0.tgz#06b2348ce37fccc4f5e18dcd8d75053f2a7c44ff" + integrity sha512-3DyG0zAFAZKcOp7aVr33ddwkxJ0Z0Jr5V99y3I690eYLpukJsJvAbzTy1ewoCqsML8SbIrjH14Jc/nSQ4TvNPA== dependencies: - "@babel/helper-annotate-as-pure" "^7.14.5" + "@babel/helper-annotate-as-pure" "^7.16.0" regexpu-core "^4.7.1" -"@babel/helper-define-map@^7.10.4": - version "7.10.5" - resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.10.5.tgz#b53c10db78a640800152692b13393147acb9bb30" - integrity sha512-fMw4kgFB720aQFXSVaXr79pjjcW5puTCM16+rECJ/plGS+zByelE8l9nCpV1GibxTnFVmUuYG9U8wYfQHdzOEQ== - dependencies: - "@babel/helper-function-name" "^7.10.4" - "@babel/types" "^7.10.5" - lodash "^4.17.19" - -"@babel/helper-define-polyfill-provider@^0.2.2": - version "0.2.3" - resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.2.3.tgz#0525edec5094653a282688d34d846e4c75e9c0b6" - integrity sha512-RH3QDAfRMzj7+0Nqu5oqgO5q9mFtQEVvCRsi8qCEfzLR9p2BHfn5FzhSB2oj1fF7I2+DcTORkYaQ6aTR9Cofew== +"@babel/helper-define-polyfill-provider@^0.2.4": + version "0.2.4" + resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.2.4.tgz#8867aed79d3ea6cade40f801efb7ac5c66916b10" + integrity sha512-OrpPZ97s+aPi6h2n1OXzdhVis1SGSsMU2aMHgLcOKfsp4/v1NWpx3CWT3lBj5eeBq9cDkPkh+YCfdF7O12uNDQ== dependencies: "@babel/helper-compilation-targets" "^7.13.0" "@babel/helper-module-imports" "^7.12.13" @@ -303,370 +191,187 @@ resolve "^1.14.2" semver "^6.1.2" -"@babel/helper-explode-assignable-expression@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.10.4.tgz#40a1cd917bff1288f699a94a75b37a1a2dbd8c7c" - integrity sha512-4K71RyRQNPRrR85sr5QY4X3VwG4wtVoXZB9+L3r1Gp38DhELyHCtovqydRi7c1Ovb17eRGiQ/FD5s8JdU0Uy5A== +"@babel/helper-explode-assignable-expression@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.16.0.tgz#753017337a15f46f9c09f674cff10cee9b9d7778" + integrity sha512-Hk2SLxC9ZbcOhLpg/yMznzJ11W++lg5GMbxt1ev6TXUiJB0N42KPC+7w8a+eWGuqDnUYuwStJoZHM7RgmIOaGQ== dependencies: - "@babel/traverse" "^7.10.4" - "@babel/types" "^7.10.4" + "@babel/types" "^7.16.0" -"@babel/helper-explode-assignable-expression@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.15.4.tgz#f9aec9d219f271eaf92b9f561598ca6b2682600c" - integrity sha512-J14f/vq8+hdC2KoWLIQSsGrC9EFBKE4NFts8pfMpymfApds+fPqR30AOUWc4tyr56h9l/GA1Sxv2q3dLZWbQ/g== +"@babel/helper-function-name@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.16.0.tgz#b7dd0797d00bbfee4f07e9c4ea5b0e30c8bb1481" + integrity sha512-BZh4mEk1xi2h4HFjWUXRQX5AEx4rvaZxHgax9gcjdLWdkjsY7MKt5p0otjsg5noXw+pB+clMCjw+aEVYADMjog== dependencies: - "@babel/types" "^7.15.4" + "@babel/helper-get-function-arity" "^7.16.0" + "@babel/template" "^7.16.0" + "@babel/types" "^7.16.0" -"@babel/helper-function-name@^7.10.4", "@babel/helper-function-name@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.12.13.tgz#93ad656db3c3c2232559fd7b2c3dbdcbe0eb377a" - integrity sha512-TZvmPn0UOqmvi5G4vvw0qZTpVptGkB1GL61R6lKvrSdIxGm5Pky7Q3fpKiIkQCAtRCBUwB0PaThlx9vebCDSwA== +"@babel/helper-get-function-arity@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.0.tgz#0088c7486b29a9cb5d948b1a1de46db66e089cfa" + integrity sha512-ASCquNcywC1NkYh/z7Cgp3w31YW8aojjYIlNg4VeJiHkqyP4AzIvr4qx7pYDb4/s8YcsZWqqOSxgkvjUz1kpDQ== dependencies: - "@babel/helper-get-function-arity" "^7.12.13" - "@babel/template" "^7.12.13" - "@babel/types" "^7.12.13" + "@babel/types" "^7.16.0" -"@babel/helper-function-name@^7.14.5", "@babel/helper-function-name@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.15.4.tgz#845744dafc4381a4a5fb6afa6c3d36f98a787ebc" - integrity sha512-Z91cOMM4DseLIGOnog+Z8OI6YseR9bua+HpvLAQ2XayUGU+neTtX+97caALaLdyu53I/fjhbeCnWnRH1O3jFOw== +"@babel/helper-hoist-variables@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.0.tgz#4c9023c2f1def7e28ff46fc1dbcd36a39beaa81a" + integrity sha512-1AZlpazjUR0EQZQv3sgRNfM9mEVWPK3M6vlalczA+EECcPz3XPh6VplbErL5UoMpChhSck5wAJHthlj1bYpcmg== dependencies: - "@babel/helper-get-function-arity" "^7.15.4" - "@babel/template" "^7.15.4" - "@babel/types" "^7.15.4" + "@babel/types" "^7.16.0" -"@babel/helper-get-function-arity@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.13.tgz#bc63451d403a3b3082b97e1d8b3fe5bd4091e583" - integrity sha512-DjEVzQNz5LICkzN0REdpD5prGoidvbdYk1BVgRUOINaWJP2t6avB27X1guXK1kXNrX0WMfsrm1A/ZBthYuIMQg== +"@babel/helper-member-expression-to-functions@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.16.0.tgz#29287040efd197c77636ef75188e81da8bccd5a4" + integrity sha512-bsjlBFPuWT6IWhl28EdrQ+gTvSvj5tqVP5Xeftp07SEuz5pLnsXZuDkDD3Rfcxy0IsHmbZ+7B2/9SHzxO0T+sQ== dependencies: - "@babel/types" "^7.12.13" + "@babel/types" "^7.16.0" -"@babel/helper-get-function-arity@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.15.4.tgz#098818934a137fce78b536a3e015864be1e2879b" - integrity sha512-1/AlxSF92CmGZzHnC515hm4SirTxtpDnLEJ0UyEMgTMZN+6bxXKg04dKhiRx5Enel+SUA1G1t5Ed/yQia0efrA== +"@babel/helper-module-imports@^7.0.0", "@babel/helper-module-imports@^7.12.13", "@babel/helper-module-imports@^7.15.4", "@babel/helper-module-imports@^7.16.0", "@babel/helper-module-imports@^7.7.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.16.0.tgz#90538e60b672ecf1b448f5f4f5433d37e79a3ec3" + integrity sha512-kkH7sWzKPq0xt3H1n+ghb4xEMP8k0U7XV3kkB+ZGy69kDk2ySFW1qPi06sjKzFY3t1j6XbJSqr4mF9L7CYVyhg== dependencies: - "@babel/types" "^7.15.4" + "@babel/types" "^7.16.0" -"@babel/helper-hoist-variables@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.10.4.tgz#d49b001d1d5a68ca5e6604dda01a6297f7c9381e" - integrity sha512-wljroF5PgCk2juF69kanHVs6vrLwIPNp6DLD+Lrl3hoQ3PpPPikaDRNFA+0t81NOoMt2DL6WW/mdU8k4k6ZzuA== +"@babel/helper-module-transforms@^7.12.1", "@babel/helper-module-transforms@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.16.0.tgz#1c82a8dd4cb34577502ebd2909699b194c3e9bb5" + integrity sha512-My4cr9ATcaBbmaEa8M0dZNA74cfI6gitvUAskgDtAFmAqyFKDSHQo5YstxPbN+lzHl2D9l/YOEFqb2mtUh4gfA== dependencies: - "@babel/types" "^7.10.4" - -"@babel/helper-hoist-variables@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.15.4.tgz#09993a3259c0e918f99d104261dfdfc033f178df" - integrity sha512-VTy085egb3jUGVK9ycIxQiPbquesq0HUQ+tPO0uv5mPEBZipk+5FkRKiWq5apuyTE9FUrjENB0rCf8y+n+UuhA== - dependencies: - "@babel/types" "^7.15.4" - -"@babel/helper-member-expression-to-functions@^7.13.0": - version "7.13.0" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.13.0.tgz#6aa4bb678e0f8c22f58cdb79451d30494461b091" - integrity sha512-yvRf8Ivk62JwisqV1rFRMxiSMDGnN6KH1/mDMmIrij4jztpQNRoHqqMG3U6apYbGRPJpgPalhva9Yd06HlUxJQ== - dependencies: - "@babel/types" "^7.13.0" - -"@babel/helper-member-expression-to-functions@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.15.4.tgz#bfd34dc9bba9824a4658b0317ec2fd571a51e6ef" - integrity sha512-cokOMkxC/BTyNP1AlY25HuBWM32iCEsLPI4BHDpJCHHm1FU2E7dKWWIXJgQgSFiu4lp8q3bL1BIKwqkSUviqtA== - dependencies: - "@babel/types" "^7.15.4" - -"@babel/helper-module-imports@^7.0.0", "@babel/helper-module-imports@^7.12.1", "@babel/helper-module-imports@^7.12.5", "@babel/helper-module-imports@^7.7.0": - version "7.13.12" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.13.12.tgz#c6a369a6f3621cb25da014078684da9196b61977" - integrity sha512-4cVvR2/1B693IuOvSI20xqqa/+bl7lqAMR59R4iu39R9aOX8/JoYY1sFaNvUMyMBGnHdwvJgUrzNLoUZxXypxA== - dependencies: - "@babel/types" "^7.13.12" - -"@babel/helper-module-imports@^7.12.13", "@babel/helper-module-imports@^7.14.5", "@babel/helper-module-imports@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.15.4.tgz#e18007d230632dea19b47853b984476e7b4e103f" - integrity sha512-jeAHZbzUwdW/xHgHQ3QmWR4Jg6j15q4w/gCfwZvtqOxoo5DKtLHk8Bsf4c5RZRC7NmLEs+ohkdq8jFefuvIxAA== - dependencies: - "@babel/types" "^7.15.4" - -"@babel/helper-module-transforms@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.12.1.tgz#7954fec71f5b32c48e4b303b437c34453fd7247c" - integrity sha512-QQzehgFAZ2bbISiCpmVGfiGux8YVFXQ0abBic2Envhej22DVXV9nCFaS5hIQbkyo1AdGb+gNME2TSh3hYJVV/w== - dependencies: - "@babel/helper-module-imports" "^7.12.1" - "@babel/helper-replace-supers" "^7.12.1" - "@babel/helper-simple-access" "^7.12.1" - "@babel/helper-split-export-declaration" "^7.11.0" - "@babel/helper-validator-identifier" "^7.10.4" - "@babel/template" "^7.10.4" - "@babel/traverse" "^7.12.1" - "@babel/types" "^7.12.1" - lodash "^4.17.19" - -"@babel/helper-module-transforms@^7.14.5", "@babel/helper-module-transforms@^7.15.4": - version "7.15.7" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.15.7.tgz#7da80c8cbc1f02655d83f8b79d25866afe50d226" - integrity sha512-ZNqjjQG/AuFfekFTY+7nY4RgBSklgTu970c7Rj3m/JOhIu5KPBUuTA9AY6zaKcUvk4g6EbDXdBnhi35FAssdSw== - dependencies: - "@babel/helper-module-imports" "^7.15.4" - "@babel/helper-replace-supers" "^7.15.4" - "@babel/helper-simple-access" "^7.15.4" - "@babel/helper-split-export-declaration" "^7.15.4" - "@babel/helper-validator-identifier" "^7.15.7" - "@babel/template" "^7.15.4" - "@babel/traverse" "^7.15.4" - "@babel/types" "^7.15.6" - -"@babel/helper-module-transforms@^7.15.8": - version "7.15.8" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.15.8.tgz#d8c0e75a87a52e374a8f25f855174786a09498b2" - integrity sha512-DfAfA6PfpG8t4S6npwzLvTUpp0sS7JrcuaMiy1Y5645laRJIp/LiLGIBbQKaXSInK8tiGNI7FL7L8UvB8gdUZg== - dependencies: - "@babel/helper-module-imports" "^7.15.4" - "@babel/helper-replace-supers" "^7.15.4" - "@babel/helper-simple-access" "^7.15.4" - "@babel/helper-split-export-declaration" "^7.15.4" + "@babel/helper-module-imports" "^7.16.0" + "@babel/helper-replace-supers" "^7.16.0" + "@babel/helper-simple-access" "^7.16.0" + "@babel/helper-split-export-declaration" "^7.16.0" "@babel/helper-validator-identifier" "^7.15.7" - "@babel/template" "^7.15.4" - "@babel/traverse" "^7.15.4" - "@babel/types" "^7.15.6" - -"@babel/helper-optimise-call-expression@^7.10.4", "@babel/helper-optimise-call-expression@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.12.13.tgz#5c02d171b4c8615b1e7163f888c1c81c30a2aaea" - integrity sha512-BdWQhoVJkp6nVjB7nkFWcn43dkprYauqtk++Py2eaf/GRDFm5BxRqEIZCiHlZUGAVmtwKcsVL1dC68WmzeFmiA== - dependencies: - "@babel/types" "^7.12.13" + "@babel/template" "^7.16.0" + "@babel/traverse" "^7.16.0" + "@babel/types" "^7.16.0" -"@babel/helper-optimise-call-expression@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.15.4.tgz#f310a5121a3b9cc52d9ab19122bd729822dee171" - integrity sha512-E/z9rfbAOt1vDW1DR7k4SzhzotVV5+qMciWV6LaG1g4jeFrkDlJedjtV4h0i4Q/ITnUu+Pk08M7fczsB9GXBDw== +"@babel/helper-optimise-call-expression@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.0.tgz#cecdb145d70c54096b1564f8e9f10cd7d193b338" + integrity sha512-SuI467Gi2V8fkofm2JPnZzB/SUuXoJA5zXe/xzyPP2M04686RzFKFHPK6HDVN6JvWBIEW8tt9hPR7fXdn2Lgpw== dependencies: - "@babel/types" "^7.15.4" + "@babel/types" "^7.16.0" "@babel/helper-plugin-utils@7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz#2f75a831269d4f677de49986dff59927533cf375" integrity sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg== -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.13.0", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": - version "7.13.0" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.13.0.tgz#806526ce125aed03373bc416a828321e3a6a33af" - integrity sha512-ZPafIPSwzUlAoWT8DKs1W2VyF2gOWthGd5NGFMsBcMMol+ZhK+EQY/e6V96poa6PA/Bh+C9plWN0hXO1uB8AfQ== - -"@babel/helper-plugin-utils@^7.14.5": +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.13.0", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz#5ac822ce97eec46741ab70a517971e443a70c5a9" integrity sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ== -"@babel/helper-regex@^7.10.4": - version "7.10.5" - resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.10.5.tgz#32dfbb79899073c415557053a19bd055aae50ae0" - integrity sha512-68kdUAzDrljqBrio7DYAEgCoJHxppJOERHOgOrDN7WjOzP0ZQ1LsSDRXcemzVZaLvjaJsJEESb6qt+znNuENDg== +"@babel/helper-remap-async-to-generator@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.16.0.tgz#d5aa3b086e13a5fe05238ff40c3a5a0c2dab3ead" + integrity sha512-MLM1IOMe9aQBqMWxcRw8dcb9jlM86NIw7KA0Wri91Xkfied+dE0QuBFSBjMNvqzmS0OSIDsMNC24dBEkPUi7ew== dependencies: - lodash "^4.17.19" + "@babel/helper-annotate-as-pure" "^7.16.0" + "@babel/helper-wrap-function" "^7.16.0" + "@babel/types" "^7.16.0" -"@babel/helper-remap-async-to-generator@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.12.1.tgz#8c4dbbf916314f6047dc05e6a2217074238347fd" - integrity sha512-9d0KQCRM8clMPcDwo8SevNs+/9a8yWVVmaE80FGJcEP8N1qToREmWEGnBn8BUlJhYRFz6fqxeRL1sl5Ogsed7A== +"@babel/helper-replace-supers@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.16.0.tgz#73055e8d3cf9bcba8ddb55cad93fedc860f68f17" + integrity sha512-TQxuQfSCdoha7cpRNJvfaYxxxzmbxXw/+6cS7V02eeDYyhxderSoMVALvwupA54/pZcOTtVeJ0xccp1nGWladA== dependencies: - "@babel/helper-annotate-as-pure" "^7.10.4" - "@babel/helper-wrap-function" "^7.10.4" - "@babel/types" "^7.12.1" + "@babel/helper-member-expression-to-functions" "^7.16.0" + "@babel/helper-optimise-call-expression" "^7.16.0" + "@babel/traverse" "^7.16.0" + "@babel/types" "^7.16.0" -"@babel/helper-remap-async-to-generator@^7.14.5", "@babel/helper-remap-async-to-generator@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.15.4.tgz#2637c0731e4c90fbf58ac58b50b2b5a192fc970f" - integrity sha512-v53MxgvMK/HCwckJ1bZrq6dNKlmwlyRNYM6ypaRTdXWGOE2c1/SCa6dL/HimhPulGhZKw9W0QhREM583F/t0vQ== +"@babel/helper-simple-access@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.16.0.tgz#21d6a27620e383e37534cf6c10bba019a6f90517" + integrity sha512-o1rjBT/gppAqKsYfUdfHq5Rk03lMQrkPHG1OWzHWpLgVXRH4HnMM9Et9CVdIqwkCQlobnGHEJMsgWP/jE1zUiw== dependencies: - "@babel/helper-annotate-as-pure" "^7.15.4" - "@babel/helper-wrap-function" "^7.15.4" - "@babel/types" "^7.15.4" + "@babel/types" "^7.16.0" -"@babel/helper-replace-supers@^7.12.1", "@babel/helper-replace-supers@^7.13.0": - version "7.13.0" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.13.0.tgz#6034b7b51943094cb41627848cb219cb02be1d24" - integrity sha512-Segd5me1+Pz+rmN/NFBOplMbZG3SqRJOBlY+mA0SxAv6rjj7zJqr1AVr3SfzUVTLCv7ZLU5FycOM/SBGuLPbZw== +"@babel/helper-skip-transparent-expression-wrappers@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.16.0.tgz#0ee3388070147c3ae051e487eca3ebb0e2e8bb09" + integrity sha512-+il1gTy0oHwUsBQZyJvukbB4vPMdcYBrFHa0Uc4AizLxbq6BOYC51Rv4tWocX9BLBDLZ4kc6qUFpQ6HRgL+3zw== dependencies: - "@babel/helper-member-expression-to-functions" "^7.13.0" - "@babel/helper-optimise-call-expression" "^7.12.13" - "@babel/traverse" "^7.13.0" - "@babel/types" "^7.13.0" + "@babel/types" "^7.16.0" -"@babel/helper-replace-supers@^7.14.5", "@babel/helper-replace-supers@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.15.4.tgz#52a8ab26ba918c7f6dee28628b07071ac7b7347a" - integrity sha512-/ztT6khaXF37MS47fufrKvIsiQkx1LBRvSJNzRqmbyeZnTwU9qBxXYLaaT/6KaxfKhjs2Wy8kG8ZdsFUuWBjzw== +"@babel/helper-split-export-declaration@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.0.tgz#29672f43663e936df370aaeb22beddb3baec7438" + integrity sha512-0YMMRpuDFNGTHNRiiqJX19GjNXA4H0E8jZ2ibccfSxaCogbm3am5WN/2nQNj0YnQwGWM1J06GOcQ2qnh3+0paw== dependencies: - "@babel/helper-member-expression-to-functions" "^7.15.4" - "@babel/helper-optimise-call-expression" "^7.15.4" - "@babel/traverse" "^7.15.4" - "@babel/types" "^7.15.4" + "@babel/types" "^7.16.0" -"@babel/helper-simple-access@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.12.1.tgz#32427e5aa61547d38eb1e6eaf5fd1426fdad9136" - integrity sha512-OxBp7pMrjVewSSC8fXDFrHrBcJATOOFssZwv16F3/6Xtc138GHybBfPbm9kfiqQHKhYQrlamWILwlDCeyMFEaA== - dependencies: - "@babel/types" "^7.12.1" - -"@babel/helper-simple-access@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.15.4.tgz#ac368905abf1de8e9781434b635d8f8674bcc13b" - integrity sha512-UzazrDoIVOZZcTeHHEPYrr1MvTR/K+wgLg6MY6e1CJyaRhbibftF6fR2KU2sFRtI/nERUZR9fBd6aKgBlIBaPg== - dependencies: - "@babel/types" "^7.15.4" - -"@babel/helper-skip-transparent-expression-wrappers@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.12.1.tgz#462dc63a7e435ade8468385c63d2b84cce4b3cbf" - integrity sha512-Mf5AUuhG1/OCChOJ/HcADmvcHM42WJockombn8ATJG3OnyiSxBK/Mm5x78BQWvmtXZKHgbjdGL2kin/HOLlZGA== - dependencies: - "@babel/types" "^7.12.1" - -"@babel/helper-skip-transparent-expression-wrappers@^7.14.5", "@babel/helper-skip-transparent-expression-wrappers@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.15.4.tgz#707dbdba1f4ad0fa34f9114fc8197aec7d5da2eb" - integrity sha512-BMRLsdh+D1/aap19TycS4eD1qELGrCBJwzaY9IE8LrpJtJb+H7rQkPIdsfgnMtLBA6DJls7X9z93Z4U8h7xw0A== - dependencies: - "@babel/types" "^7.15.4" - -"@babel/helper-split-export-declaration@^7.10.4", "@babel/helper-split-export-declaration@^7.11.0", "@babel/helper-split-export-declaration@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.13.tgz#e9430be00baf3e88b0e13e6f9d4eaf2136372b05" - integrity sha512-tCJDltF83htUtXx5NLcaDqRmknv652ZWCHyoTETf1CXYJdPC7nohZohjUgieXhv0hTJdRf2FjDueFehdNucpzg== - dependencies: - "@babel/types" "^7.12.13" - -"@babel/helper-split-export-declaration@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.15.4.tgz#aecab92dcdbef6a10aa3b62ab204b085f776e257" - integrity sha512-HsFqhLDZ08DxCpBdEVtKmywj6PQbwnF6HHybur0MAnkAKnlS6uHkwnmRIkElB2Owpfb4xL4NwDmDLFubueDXsw== - dependencies: - "@babel/types" "^7.15.4" - -"@babel/helper-validator-identifier@^7.10.4", "@babel/helper-validator-identifier@^7.12.11", "@babel/helper-validator-identifier@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.5.tgz#d0f0e277c512e0c938277faa85a3968c9a44c0e8" - integrity sha512-5lsetuxCLilmVGyiLEfoHBRX8UCFD+1m2x3Rj97WrW3V7H3u4RWRXA4evMjImCsin2J2YT0QaVDGf+z8ondbAg== - -"@babel/helper-validator-identifier@^7.14.9", "@babel/helper-validator-identifier@^7.15.7": +"@babel/helper-validator-identifier@^7.15.7": version "7.15.7" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz#220df993bfe904a4a6b02ab4f3385a5ebf6e2389" integrity sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w== -"@babel/helper-validator-option@^7.12.1", "@babel/helper-validator-option@^7.12.11": - version "7.12.11" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.12.11.tgz#d66cb8b7a3e7fe4c6962b32020a131ecf0847f4f" - integrity sha512-TBFCyj939mFSdeX7U7DDj32WtzYY7fDcalgq8v3fBZMNOJQNn7nOYzMaUCiPxPYfCup69mtIpqlKgMZLvQ8Xhw== - "@babel/helper-validator-option@^7.14.5": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz#6e72a1fff18d5dfcb878e1e62f1a021c4b72d5a3" integrity sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow== -"@babel/helper-wrap-function@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.10.4.tgz#8a6f701eab0ff39f765b5a1cfef409990e624b87" - integrity sha512-6py45WvEF0MhiLrdxtRjKjufwLL1/ob2qDJgg5JgNdojBAZSAKnAjkyOCNug6n+OBl4VW76XjvgSFTdaMcW0Ug== - dependencies: - "@babel/helper-function-name" "^7.10.4" - "@babel/template" "^7.10.4" - "@babel/traverse" "^7.10.4" - "@babel/types" "^7.10.4" - -"@babel/helper-wrap-function@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.15.4.tgz#6f754b2446cfaf3d612523e6ab8d79c27c3a3de7" - integrity sha512-Y2o+H/hRV5W8QhIfTpRIBwl57y8PrZt6JM3V8FOo5qarjshHItyH5lXlpMfBfmBefOqSCpKZs/6Dxqp0E/U+uw== - dependencies: - "@babel/helper-function-name" "^7.15.4" - "@babel/template" "^7.15.4" - "@babel/traverse" "^7.15.4" - "@babel/types" "^7.15.4" - -"@babel/helpers@^7.12.5", "@babel/helpers@^7.4.4": - version "7.12.5" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.12.5.tgz#1a1ba4a768d9b58310eda516c449913fe647116e" - integrity sha512-lgKGMQlKqA8meJqKsW6rUnc4MdUk35Ln0ATDqdM1a/UpARODdI4j5Y5lVfUScnSNkJcdCRAaWkspykNoFg9sJA== - dependencies: - "@babel/template" "^7.10.4" - "@babel/traverse" "^7.12.5" - "@babel/types" "^7.12.5" - -"@babel/helpers@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.15.4.tgz#5f40f02050a3027121a3cf48d497c05c555eaf43" - integrity sha512-V45u6dqEJ3w2rlryYYXf6i9rQ5YMNu4FLS6ngs8ikblhu2VdR1AqAd6aJjBzmf2Qzh6KOLqKHxEN9+TFbAkAVQ== - dependencies: - "@babel/template" "^7.15.4" - "@babel/traverse" "^7.15.4" - "@babel/types" "^7.15.4" - -"@babel/highlight@^7.10.4", "@babel/highlight@^7.12.13": - version "7.13.8" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.13.8.tgz#10b2dac78526424dfc1f47650d0e415dfd9dc481" - integrity sha512-4vrIhfJyfNf+lCtXC2ck1rKSzDwciqF7IWFhXXrSOUC2O5DrVp+w4c6ed4AllTxhTkUP5x2tYj41VaxdVMMRDw== - dependencies: - "@babel/helper-validator-identifier" "^7.12.11" - chalk "^2.0.0" - js-tokens "^4.0.0" +"@babel/helper-wrap-function@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.16.0.tgz#b3cf318afce774dfe75b86767cd6d68f3482e57c" + integrity sha512-VVMGzYY3vkWgCJML+qVLvGIam902mJW0FvT7Avj1zEe0Gn7D93aWdLblYARTxEw+6DhZmtzhBM2zv0ekE5zg1g== + dependencies: + "@babel/helper-function-name" "^7.16.0" + "@babel/template" "^7.16.0" + "@babel/traverse" "^7.16.0" + "@babel/types" "^7.16.0" -"@babel/highlight@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.14.5.tgz#6861a52f03966405001f6aa534a01a24d99e8cd9" - integrity sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg== +"@babel/helpers@^7.12.5", "@babel/helpers@^7.16.0", "@babel/helpers@^7.4.4": + version "7.16.3" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.16.3.tgz#27fc64f40b996e7074dc73128c3e5c3e7f55c43c" + integrity sha512-Xn8IhDlBPhvYTvgewPKawhADichOsbkZuzN7qz2BusOM0brChsyXMDJvldWaYMMUNiCQdQzNEioXTp3sC8Nt8w== + dependencies: + "@babel/template" "^7.16.0" + "@babel/traverse" "^7.16.3" + "@babel/types" "^7.16.0" + +"@babel/highlight@^7.10.4", "@babel/highlight@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.16.0.tgz#6ceb32b2ca4b8f5f361fb7fd821e3fddf4a1725a" + integrity sha512-t8MH41kUQylBtu2+4IQA3atqevA2lRgqA2wyVB/YiWmsDSuylZZuXOUy9ric30hfzauEFfdsuk/eXTRrGrfd0g== dependencies: - "@babel/helper-validator-identifier" "^7.14.5" + "@babel/helper-validator-identifier" "^7.15.7" chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.12.10", "@babel/parser@^7.12.13", "@babel/parser@^7.12.3", "@babel/parser@^7.12.7", "@babel/parser@^7.13.0", "@babel/parser@^7.4.5": - version "7.13.9" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.13.9.tgz#ca34cb95e1c2dd126863a84465ae8ef66114be99" - integrity sha512-nEUfRiARCcaVo3ny3ZQjURjHQZUo/JkEw7rLlSZy/psWGnvwXFtPcr6jb7Yb41DVW5LTe6KRq9LGleRNsg1Frw== - -"@babel/parser@^7.15.4": - version "7.15.7" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.15.7.tgz#0c3ed4a2eb07b165dfa85b3cc45c727334c4edae" - integrity sha512-rycZXvQ+xS9QyIcJ9HXeDWf1uxqlbVFAUq0Rq0dbc50Zb/+wUe/ehyfzGfm9KZZF0kBejYgxltBXocP+gKdL2g== - -"@babel/parser@^7.15.8": - version "7.15.8" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.15.8.tgz#7bacdcbe71bdc3ff936d510c15dcea7cf0b99016" - integrity sha512-BRYa3wcQnjS/nqI8Ac94pYYpJfojHVvVXJ97+IDCImX4Jc8W8Xv1+47enbruk+q1etOpsQNwnfFcNGw+gtPGxA== +"@babel/parser@^7.1.0", "@babel/parser@^7.12.3", "@babel/parser@^7.12.7", "@babel/parser@^7.14.7", "@babel/parser@^7.16.0", "@babel/parser@^7.16.3", "@babel/parser@^7.4.5": + version "7.16.3" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.16.3.tgz#271bafcb811080905a119222edbc17909c82261d" + integrity sha512-dcNwU1O4sx57ClvLBVFbEgx0UZWfd0JQX5X6fxFRCLHelFBGXFfSz6Y0FAq2PEwUqlqLkdVjVr4VASEOuUnLJw== -"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.15.4.tgz#dbdeabb1e80f622d9f0b583efb2999605e0a567e" - integrity sha512-eBnpsl9tlhPhpI10kU06JHnrYXwg3+V6CaP2idsCXNef0aeslpqyITXQ74Vfk5uHgY7IG7XP0yIH8b42KSzHog== +"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.16.0": + version "7.16.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.16.2.tgz#2977fca9b212db153c195674e57cfab807733183" + integrity sha512-h37CvpLSf8gb2lIJ2CgC3t+EjFbi0t8qS7LCS1xcJIlEXE4czlofwaW7W1HA8zpgOCzI9C1nmoqNR1zWkk0pQg== dependencies: "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-skip-transparent-expression-wrappers" "^7.15.4" - "@babel/plugin-proposal-optional-chaining" "^7.14.5" -"@babel/plugin-proposal-async-generator-functions@^7.12.1", "@babel/plugin-proposal-async-generator-functions@^7.2.0": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.12.1.tgz#dc6c1170e27d8aca99ff65f4925bd06b1c90550e" - integrity sha512-d+/o30tJxFxrA1lhzJqiUcEJdI6jKlNregCv5bASeGf2Q4MXmnwH7viDo7nhx1/ohf09oaH8j1GVYG/e3Yqk6A== +"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.16.0.tgz#358972eaab006f5eb0826183b0c93cbcaf13e1e2" + integrity sha512-4tcFwwicpWTrpl9qjf7UsoosaArgImF85AxqCRZlgc3IQDvkUHjJpruXAL58Wmj+T6fypWTC/BakfEkwIL/pwA== dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/helper-remap-async-to-generator" "^7.12.1" - "@babel/plugin-syntax-async-generators" "^7.8.0" + "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" + "@babel/plugin-proposal-optional-chaining" "^7.16.0" -"@babel/plugin-proposal-async-generator-functions@^7.15.8": - version "7.15.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.15.8.tgz#a3100f785fab4357987c4223ab1b02b599048403" - integrity sha512-2Z5F2R2ibINTc63mY7FLqGfEbmofrHU9FitJW1Q7aPaKFhiPvSq6QEt/BoWN5oME3GVyjcRuNNSRbb9LC0CSWA== +"@babel/plugin-proposal-async-generator-functions@^7.16.0", "@babel/plugin-proposal-async-generator-functions@^7.2.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.16.0.tgz#11425d47a60364352f668ad5fbc1d6596b2c5caf" + integrity sha512-nyYmIo7ZqKsY6P4lnVmBlxp9B3a96CscbLotlsNuktMHahkDwoPYEjXrZHU0Tj844Z9f1IthVxQln57mhkcExw== dependencies: "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-remap-async-to-generator" "^7.15.4" + "@babel/helper-remap-async-to-generator" "^7.16.0" "@babel/plugin-syntax-async-generators" "^7.8.4" "@babel/plugin-proposal-class-properties@7.3.0": @@ -677,28 +382,20 @@ "@babel/helper-create-class-features-plugin" "^7.3.0" "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-proposal-class-properties@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.12.1.tgz#a082ff541f2a29a4821065b8add9346c0c16e5de" - integrity sha512-cKp3dlQsFsEs5CWKnN7BnSHOd0EOW8EKpEjkoz1pO2E5KzIDNV9Ros1b0CnmbVgAGXJubOYVBOGCT1OmJwOI7w== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.12.1" - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-proposal-class-properties@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.14.5.tgz#40d1ee140c5b1e31a350f4f5eed945096559b42e" - integrity sha512-q/PLpv5Ko4dVc1LYMpCY7RVAAO4uk55qPwrIuJ5QJ8c6cVuAmhu7I/49JOppXL6gXf7ZHzpRVEUZdYoPLM04Gg== +"@babel/plugin-proposal-class-properties@^7.12.1", "@babel/plugin-proposal-class-properties@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.16.0.tgz#c029618267ddebc7280fa286e0f8ca2a278a2d1a" + integrity sha512-mCF3HcuZSY9Fcx56Lbn+CGdT44ioBMMvjNVldpKtj8tpniETdLjnxdHI1+sDWXIM1nNt+EanJOZ3IG9lzVjs7A== dependencies: - "@babel/helper-create-class-features-plugin" "^7.14.5" + "@babel/helper-create-class-features-plugin" "^7.16.0" "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-proposal-class-static-block@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.15.4.tgz#3e7ca6128453c089e8b477a99f970c63fc1cb8d7" - integrity sha512-M682XWrrLNk3chXCjoPUQWOyYsB93B9z3mRyjtqqYJWDf2mfCdIYgDrA11cgNVhAQieaq6F2fn2f3wI0U4aTjA== +"@babel/plugin-proposal-class-static-block@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.16.0.tgz#5296942c564d8144c83eea347d0aa8a0b89170e7" + integrity sha512-mAy3sdcY9sKAkf3lQbDiv3olOfiLqI51c9DR9b19uMoR2Z6r5pmGl7dfNFqEvqOyqbf1ta4lknK4gc5PJn3mfA== dependencies: - "@babel/helper-create-class-features-plugin" "^7.15.4" + "@babel/helper-create-class-features-plugin" "^7.16.0" "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-class-static-block" "^7.14.5" @@ -711,18 +408,10 @@ "@babel/helper-plugin-utils" "^7.13.0" "@babel/plugin-syntax-decorators" "^7.12.13" -"@babel/plugin-proposal-dynamic-import@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.12.1.tgz#43eb5c2a3487ecd98c5c8ea8b5fdb69a2749b2dc" - integrity sha512-a4rhUSZFuq5W8/OO8H7BL5zspjnc1FLd9hlOxIK/f7qG4a0qsqk8uvF/ywgBA8/OmjsapjpvaEOYItfGG1qIvQ== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-syntax-dynamic-import" "^7.8.0" - -"@babel/plugin-proposal-dynamic-import@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.14.5.tgz#0c6617df461c0c1f8fff3b47cd59772360101d2c" - integrity sha512-ExjiNYc3HDN5PXJx+bwC50GIx/KKanX2HiggnIUAYedbARdImiCU4RhhHfdf0Kd7JNXGpsBBBCOm+bBVy3Gb0g== +"@babel/plugin-proposal-dynamic-import@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.16.0.tgz#783eca61d50526202f9b296095453977e88659f1" + integrity sha512-QGSA6ExWk95jFQgwz5GQ2Dr95cf7eI7TKutIXXTb7B1gCLTCz5hTjFTQGfLFBBiC5WSNi7udNwWsqbbMh1c4yQ== dependencies: "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-dynamic-import" "^7.8.3" @@ -735,87 +424,47 @@ "@babel/helper-plugin-utils" "^7.12.13" "@babel/plugin-syntax-export-default-from" "^7.12.13" -"@babel/plugin-proposal-export-namespace-from@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.12.1.tgz#8b9b8f376b2d88f5dd774e4d24a5cc2e3679b6d4" - integrity sha512-6CThGf0irEkzujYS5LQcjBx8j/4aQGiVv7J9+2f7pGfxqyKh3WnmVJYW3hdrQjyksErMGBPQrCnHfOtna+WLbw== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-syntax-export-namespace-from" "^7.8.3" - -"@babel/plugin-proposal-export-namespace-from@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.14.5.tgz#dbad244310ce6ccd083072167d8cea83a52faf76" - integrity sha512-g5POA32bXPMmSBu5Dx/iZGLGnKmKPc5AiY7qfZgurzrCYgIztDlHFbznSNCoQuv57YQLnQfaDi7dxCtLDIdXdA== +"@babel/plugin-proposal-export-namespace-from@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.16.0.tgz#9c01dee40b9d6b847b656aaf4a3976a71740f222" + integrity sha512-CjI4nxM/D+5wCnhD11MHB1AwRSAYeDT+h8gCdcVJZ/OK7+wRzFsf7PFPWVpVpNRkHMmMkQWAHpTq+15IXQ1diA== dependencies: "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-export-namespace-from" "^7.8.3" -"@babel/plugin-proposal-json-strings@^7.12.1", "@babel/plugin-proposal-json-strings@^7.2.0": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.12.1.tgz#d45423b517714eedd5621a9dfdc03fa9f4eb241c" - integrity sha512-GoLDUi6U9ZLzlSda2Df++VSqDJg3CG+dR0+iWsv6XRw1rEq+zwt4DirM9yrxW6XWaTpmai1cWJLMfM8qQJf+yw== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-syntax-json-strings" "^7.8.0" - -"@babel/plugin-proposal-json-strings@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.14.5.tgz#38de60db362e83a3d8c944ac858ddf9f0c2239eb" - integrity sha512-NSq2fczJYKVRIsUJyNxrVUMhB27zb7N7pOFGQOhBKJrChbGcgEAqyZrmZswkPk18VMurEeJAaICbfm57vUeTbQ== +"@babel/plugin-proposal-json-strings@^7.16.0", "@babel/plugin-proposal-json-strings@^7.2.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.16.0.tgz#cae35a95ed1d2a7fa29c4dc41540b84a72e9ab25" + integrity sha512-kouIPuiv8mSi5JkEhzApg5Gn6hFyKPnlkO0a9YSzqRurH8wYzSlf6RJdzluAsbqecdW5pBvDJDfyDIUR/vLxvg== dependencies: "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-json-strings" "^7.8.3" -"@babel/plugin-proposal-logical-assignment-operators@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.12.1.tgz#f2c490d36e1b3c9659241034a5d2cd50263a2751" - integrity sha512-k8ZmVv0JU+4gcUGeCDZOGd0lCIamU/sMtIiX3UWnUc5yzgq6YUGyEolNYD+MLYKfSzgECPcqetVcJP9Afe/aCA== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" - -"@babel/plugin-proposal-logical-assignment-operators@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.14.5.tgz#6e6229c2a99b02ab2915f82571e0cc646a40c738" - integrity sha512-YGn2AvZAo9TwyhlLvCCWxD90Xq8xJ4aSgaX3G5D/8DW94L8aaT+dS5cSP+Z06+rCJERGSr9GxMBZ601xoc2taw== +"@babel/plugin-proposal-logical-assignment-operators@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.16.0.tgz#a711b8ceb3ffddd3ef88d3a49e86dbd3cc7db3fd" + integrity sha512-pbW0fE30sVTYXXm9lpVQQ/Vc+iTeQKiXlaNRZPPN2A2VdlWyAtsUrsQ3xydSlDW00TFMK7a8m3cDTkBF5WnV3Q== dependencies: "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" -"@babel/plugin-proposal-nullish-coalescing-operator@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.12.1.tgz#3ed4fff31c015e7f3f1467f190dbe545cd7b046c" - integrity sha512-nZY0ESiaQDI1y96+jk6VxMOaL4LPo/QDHBqL+SF3/vl6dHkTwHlOI8L4ZwuRBHgakRBw5zsVylel7QPbbGuYgg== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" - -"@babel/plugin-proposal-nullish-coalescing-operator@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.14.5.tgz#ee38589ce00e2cc59b299ec3ea406fcd3a0fdaf6" - integrity sha512-gun/SOnMqjSb98Nkaq2rTKMwervfdAoz6NphdY0vTfuzMfryj+tDGb2n6UkDKwez+Y8PZDhE3D143v6Gepp4Hg== +"@babel/plugin-proposal-nullish-coalescing-operator@^7.12.1", "@babel/plugin-proposal-nullish-coalescing-operator@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.16.0.tgz#44e1cce08fe2427482cf446a91bb451528ed0596" + integrity sha512-3bnHA8CAFm7cG93v8loghDYyQ8r97Qydf63BeYiGgYbjKKB/XP53W15wfRC7dvKfoiJ34f6Rbyyx2btExc8XsQ== dependencies: "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" -"@babel/plugin-proposal-numeric-separator@^7.12.7": - version "7.12.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.12.7.tgz#8bf253de8139099fea193b297d23a9d406ef056b" - integrity sha512-8c+uy0qmnRTeukiGsjLGy6uVs/TFjJchGXUeBqlG4VWYOdJWkhhVPdQ3uHwbmalfJwv2JsV0qffXP4asRfL2SQ== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-syntax-numeric-separator" "^7.10.4" - -"@babel/plugin-proposal-numeric-separator@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.14.5.tgz#83631bf33d9a51df184c2102a069ac0c58c05f18" - integrity sha512-yiclALKe0vyZRZE0pS6RXgjUOt87GWv6FYa5zqj15PvhOGFO69R5DusPlgK/1K5dVnCtegTiWu9UaBSrLLJJBg== +"@babel/plugin-proposal-numeric-separator@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.16.0.tgz#5d418e4fbbf8b9b7d03125d3a52730433a373734" + integrity sha512-FAhE2I6mjispy+vwwd6xWPyEx3NYFS13pikDBWUAFGZvq6POGs5eNchw8+1CYoEgBl9n11I3NkzD7ghn25PQ9Q== dependencies: "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-numeric-separator" "^7.10.4" -"@babel/plugin-proposal-object-rest-spread@7.12.1", "@babel/plugin-proposal-object-rest-spread@^7.12.1", "@babel/plugin-proposal-object-rest-spread@^7.4.4": +"@babel/plugin-proposal-object-rest-spread@7.12.1": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.12.1.tgz#def9bd03cea0f9b72283dac0ec22d289c7691069" integrity sha512-s6SowJIjzlhx8o7lsFx5zmY4At6CTtDvgNQDdPzkBQucle58A6b/TTeEBYtyDgmcXjUTM+vE8YOGHZzzbc/ioA== @@ -832,94 +481,61 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-syntax-object-rest-spread" "^7.2.0" -"@babel/plugin-proposal-object-rest-spread@^7.15.6": - version "7.15.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.15.6.tgz#ef68050c8703d07b25af402cb96cf7f34a68ed11" - integrity sha512-qtOHo7A1Vt+O23qEAX+GdBpqaIuD3i9VRrWgCJeq7WO6H2d14EK3q11urj5Te2MAeK97nMiIdRpwd/ST4JFbNg== +"@babel/plugin-proposal-object-rest-spread@^7.12.1", "@babel/plugin-proposal-object-rest-spread@^7.16.0", "@babel/plugin-proposal-object-rest-spread@^7.4.4": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.16.0.tgz#5fb32f6d924d6e6712810362a60e12a2609872e6" + integrity sha512-LU/+jp89efe5HuWJLmMmFG0+xbz+I2rSI7iLc1AlaeSMDMOGzWlc5yJrMN1d04osXN4sSfpo4O+azkBNBes0jg== dependencies: - "@babel/compat-data" "^7.15.0" - "@babel/helper-compilation-targets" "^7.15.4" + "@babel/compat-data" "^7.16.0" + "@babel/helper-compilation-targets" "^7.16.0" "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-object-rest-spread" "^7.8.3" - "@babel/plugin-transform-parameters" "^7.15.4" + "@babel/plugin-transform-parameters" "^7.16.0" -"@babel/plugin-proposal-optional-catch-binding@^7.12.1", "@babel/plugin-proposal-optional-catch-binding@^7.2.0": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.12.1.tgz#ccc2421af64d3aae50b558a71cede929a5ab2942" - integrity sha512-hFvIjgprh9mMw5v42sJWLI1lzU5L2sznP805zeT6rySVRA0Y18StRhDqhSxlap0oVgItRsB6WSROp4YnJTJz0g== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" - -"@babel/plugin-proposal-optional-catch-binding@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.14.5.tgz#939dd6eddeff3a67fdf7b3f044b5347262598c3c" - integrity sha512-3Oyiixm0ur7bzO5ybNcZFlmVsygSIQgdOa7cTfOYCMY+wEPAYhZAJxi3mixKFCTCKUhQXuCTtQ1MzrpL3WT8ZQ== +"@babel/plugin-proposal-optional-catch-binding@^7.16.0", "@babel/plugin-proposal-optional-catch-binding@^7.2.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.16.0.tgz#5910085811ab4c28b00d6ebffa4ab0274d1e5f16" + integrity sha512-kicDo0A/5J0nrsCPbn89mTG3Bm4XgYi0CZtvex9Oyw7gGZE3HXGD0zpQNH+mo+tEfbo8wbmMvJftOwpmPy7aVw== dependencies: "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" -"@babel/plugin-proposal-optional-chaining@^7.12.1", "@babel/plugin-proposal-optional-chaining@^7.12.7": - version "7.12.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.12.7.tgz#e02f0ea1b5dc59d401ec16fb824679f683d3303c" - integrity sha512-4ovylXZ0PWmwoOvhU2vhnzVNnm88/Sm9nx7V8BPgMvAzn5zDou3/Awy0EjglyubVHasJj+XCEkr/r1X3P5elCA== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/helper-skip-transparent-expression-wrappers" "^7.12.1" - "@babel/plugin-syntax-optional-chaining" "^7.8.0" - -"@babel/plugin-proposal-optional-chaining@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.14.5.tgz#fa83651e60a360e3f13797eef00b8d519695b603" - integrity sha512-ycz+VOzo2UbWNI1rQXxIuMOzrDdHGrI23fRiz/Si2R4kv2XZQ1BK8ccdHwehMKBlcH/joGW/tzrUmo67gbJHlQ== +"@babel/plugin-proposal-optional-chaining@^7.12.1", "@babel/plugin-proposal-optional-chaining@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.16.0.tgz#56dbc3970825683608e9efb55ea82c2a2d6c8dc0" + integrity sha512-Y4rFpkZODfHrVo70Uaj6cC1JJOt3Pp0MdWSwIKtb8z1/lsjl9AmnB7ErRFV+QNGIfcY1Eruc2UMx5KaRnXjMyg== dependencies: "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-skip-transparent-expression-wrappers" "^7.14.5" + "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" "@babel/plugin-syntax-optional-chaining" "^7.8.3" -"@babel/plugin-proposal-private-methods@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.12.1.tgz#86814f6e7a21374c980c10d38b4493e703f4a389" - integrity sha512-mwZ1phvH7/NHK6Kf8LP7MYDogGV+DKB1mryFOEwx5EBNQrosvIczzZFTUmWaeujd5xT6G1ELYWUz3CutMhjE1w== +"@babel/plugin-proposal-private-methods@^7.12.1", "@babel/plugin-proposal-private-methods@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.16.0.tgz#b4dafb9c717e4301c5776b30d080d6383c89aff6" + integrity sha512-IvHmcTHDFztQGnn6aWq4t12QaBXTKr1whF/dgp9kz84X6GUcwq9utj7z2wFCUfeOup/QKnOlt2k0zxkGFx9ubg== dependencies: - "@babel/helper-create-class-features-plugin" "^7.12.1" - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-proposal-private-methods@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.14.5.tgz#37446495996b2945f30f5be5b60d5e2aa4f5792d" - integrity sha512-838DkdUA1u+QTCplatfq4B7+1lnDa/+QMI89x5WZHBcnNv+47N8QEj2k9I2MUU9xIv8XJ4XvPCviM/Dj7Uwt9g== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.14.5" + "@babel/helper-create-class-features-plugin" "^7.16.0" "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-proposal-private-property-in-object@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.15.4.tgz#55c5e3b4d0261fd44fe637e3f624cfb0f484e3e5" - integrity sha512-X0UTixkLf0PCCffxgu5/1RQyGGbgZuKoI+vXP4iSbJSYwPb7hu06omsFGBvQ9lJEvwgrxHdS8B5nbfcd8GyUNA== +"@babel/plugin-proposal-private-property-in-object@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.16.0.tgz#69e935b2c5c79d2488112d886f0c4e2790fee76f" + integrity sha512-3jQUr/HBbMVZmi72LpjQwlZ55i1queL8KcDTQEkAHihttJnAPrcvG9ZNXIfsd2ugpizZo595egYV6xy+pv4Ofw== dependencies: - "@babel/helper-annotate-as-pure" "^7.15.4" - "@babel/helper-create-class-features-plugin" "^7.15.4" + "@babel/helper-annotate-as-pure" "^7.16.0" + "@babel/helper-create-class-features-plugin" "^7.16.0" "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-private-property-in-object" "^7.14.5" -"@babel/plugin-proposal-unicode-property-regex@^7.12.1", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.12.1.tgz#2a183958d417765b9eae334f47758e5d6a82e072" - integrity sha512-MYq+l+PvHuw/rKUz1at/vb6nCnQ2gmJBNaM62z0OgH7B2W1D9pvkpYtlti9bGtizNIU1K3zm4bZF9F91efVY0w== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.12.1" - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-proposal-unicode-property-regex@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.14.5.tgz#0f95ee0e757a5d647f378daa0eca7e93faa8bbe8" - integrity sha512-6axIeOU5LnY471KenAB9vI8I5j7NQ2d652hIYwVyRfgaZT5UpiqFKCuVXCDMSrU+3VFafnu2c5m3lrWIlr6A5Q== +"@babel/plugin-proposal-unicode-property-regex@^7.16.0", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.16.0.tgz#890482dfc5ea378e42e19a71e709728cabf18612" + integrity sha512-ti7IdM54NXv29cA4+bNNKEMS4jLMCbJgl+Drv+FgYy0erJLAxNAIXcNjNjrRZEcWq0xJHsNVwQezskMFpF8N9g== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.14.5" + "@babel/helper-create-regexp-features-plugin" "^7.16.0" "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-syntax-async-generators@^7.2.0", "@babel/plugin-syntax-async-generators@^7.8.0", "@babel/plugin-syntax-async-generators@^7.8.4": +"@babel/plugin-syntax-async-generators@^7.2.0", "@babel/plugin-syntax-async-generators@^7.8.4": version "7.8.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== @@ -933,14 +549,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-class-properties@^7.12.1", "@babel/plugin-syntax-class-properties@^7.8.3": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.1.tgz#bcb297c5366e79bebadef509549cd93b04f19978" - integrity sha512-U40A76x5gTwmESz+qiqssqmeEsKvcSyvtgktrm0uzcARAmM9I1jR221f6Oq+GmHrcD+LvZDag1UTOTe2fL3TeA== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-syntax-class-properties@^7.12.13": +"@babel/plugin-syntax-class-properties@^7.12.13", "@babel/plugin-syntax-class-properties@^7.8.3": version "7.12.13" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== @@ -961,7 +570,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.12.13" -"@babel/plugin-syntax-dynamic-import@^7.8.0", "@babel/plugin-syntax-dynamic-import@^7.8.3": +"@babel/plugin-syntax-dynamic-import@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ== @@ -996,7 +605,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-syntax-json-strings@^7.2.0", "@babel/plugin-syntax-json-strings@^7.8.0", "@babel/plugin-syntax-json-strings@^7.8.3": +"@babel/plugin-syntax-json-strings@^7.2.0", "@babel/plugin-syntax-json-strings@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== @@ -1010,17 +619,10 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-syntax-jsx@^7.10.4", "@babel/plugin-syntax-jsx@^7.12.1", "@babel/plugin-syntax-jsx@^7.2.0": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.12.13.tgz#044fb81ebad6698fe62c478875575bcbb9b70f15" - integrity sha512-d4HM23Q1K7oq/SLNmG6mRt85l2csmQ0cHRaxRXjKW0YFdEXqlZ5kzFQKH5Uc3rDJECgu+yCRgPkG04Mm98R/1g== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-syntax-jsx@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.14.5.tgz#000e2e25d8673cce49300517a3eda44c263e4201" - integrity sha512-ohuFIsOMXJnbOMRfX7/w7LocdR6R7whhuRD4ax8IipLcLPlZGJKkBxgHp++U4N/vKyU16/YDQr2f5seajD3jIw== +"@babel/plugin-syntax-jsx@^7.10.4", "@babel/plugin-syntax-jsx@^7.12.1", "@babel/plugin-syntax-jsx@^7.16.0", "@babel/plugin-syntax-jsx@^7.2.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.16.0.tgz#f9624394317365a9a88c82358d3f8471154698f1" + integrity sha512-8zv2+xiPHwly31RK4RmnEYY5zziuF3O7W2kIDW+07ewWDh6Oi0dRq8kwvulRkFgt6DB97RlKs5c1y068iPlCUg== dependencies: "@babel/helper-plugin-utils" "^7.14.5" @@ -1031,7 +633,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.0", "@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": +"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== @@ -1052,14 +654,14 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-optional-catch-binding@^7.2.0", "@babel/plugin-syntax-optional-catch-binding@^7.8.0", "@babel/plugin-syntax-optional-catch-binding@^7.8.3": +"@babel/plugin-syntax-optional-catch-binding@^7.2.0", "@babel/plugin-syntax-optional-catch-binding@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-optional-chaining@^7.8.0", "@babel/plugin-syntax-optional-chaining@^7.8.3": +"@babel/plugin-syntax-optional-chaining@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== @@ -1073,193 +675,98 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-syntax-top-level-await@^7.12.1", "@babel/plugin-syntax-top-level-await@^7.8.3": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.12.1.tgz#dd6c0b357ac1bb142d98537450a319625d13d2a0" - integrity sha512-i7ooMZFS+a/Om0crxZodrTzNEPJHZrlMVGMTEpFAj6rYY/bKCddB0Dk/YxfPuYXOopuhKk/e1jV6h+WUU9XN3A== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-syntax-top-level-await@^7.14.5": +"@babel/plugin-syntax-top-level-await@^7.14.5", "@babel/plugin-syntax-top-level-await@^7.8.3": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-syntax-typescript@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.12.1.tgz#460ba9d77077653803c3dd2e673f76d66b4029e5" - integrity sha512-UZNEcCY+4Dp9yYRCAHrHDU+9ZXLYaY9MgBXSRLkB9WjYFRR6quJBumfVrEkUxrePPBwFcpWfNKXqVRQQtm7mMA== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-syntax-typescript@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.14.5.tgz#b82c6ce471b165b5ce420cf92914d6fb46225716" - integrity sha512-u6OXzDaIXjEstBRRoBCQ/uKQKlbuaeE5in0RvWdA4pN6AhqxTIwUsnHPU1CFZA/amYObMsuWhYfRl3Ch90HD0Q== +"@babel/plugin-syntax-typescript@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.16.0.tgz#2feeb13d9334cc582ea9111d3506f773174179bb" + integrity sha512-Xv6mEXqVdaqCBfJFyeab0fH2DnUoMsDmhamxsSi4j8nLd4Vtw213WMJr55xxqipC/YVWyPY3K0blJncPYji+dQ== dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-arrow-functions@^7.12.1", "@babel/plugin-transform-arrow-functions@^7.2.0": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.12.1.tgz#8083ffc86ac8e777fbe24b5967c4b2521f3cb2b3" - integrity sha512-5QB50qyN44fzzz4/qxDPQMBCTHgxg3n0xRBLJUmBlLoU/sFvxVWGZF/ZUfMVDQuJUKXaBhbupxIzIfZ6Fwk/0A== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-arrow-functions@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.14.5.tgz#f7187d9588a768dd080bf4c9ffe117ea62f7862a" - integrity sha512-KOnO0l4+tD5IfOdi4x8C1XmEIRWUjNRV8wc6K2vz/3e8yAOoZZvsRXRRIF/yo/MAOFb4QjtAw9xSxMXbSMRy8A== +"@babel/plugin-transform-arrow-functions@^7.12.1", "@babel/plugin-transform-arrow-functions@^7.16.0", "@babel/plugin-transform-arrow-functions@^7.2.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.16.0.tgz#951706f8b449c834ed07bd474c0924c944b95a8e" + integrity sha512-vIFb5250Rbh7roWARvCLvIJ/PtAU5Lhv7BtZ1u24COwpI9Ypjsh+bZcKk6rlIyalK+r0jOc1XQ8I4ovNxNrWrA== dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-async-to-generator@^7.12.1", "@babel/plugin-transform-async-to-generator@^7.4.4": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.12.1.tgz#3849a49cc2a22e9743cbd6b52926d30337229af1" - integrity sha512-SDtqoEcarK1DFlRJ1hHRY5HvJUj5kX4qmtpMAm2QnhOlyuMC4TMdCRgW6WXpv93rZeYNeLP22y8Aq2dbcDRM1A== +"@babel/plugin-transform-async-to-generator@^7.16.0", "@babel/plugin-transform-async-to-generator@^7.4.4": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.16.0.tgz#df12637f9630ddfa0ef9d7a11bc414d629d38604" + integrity sha512-PbIr7G9kR8tdH6g8Wouir5uVjklETk91GMVSUq+VaOgiinbCkBP6Q7NN/suM/QutZkMJMvcyAriogcYAdhg8Gw== dependencies: - "@babel/helper-module-imports" "^7.12.1" - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/helper-remap-async-to-generator" "^7.12.1" - -"@babel/plugin-transform-async-to-generator@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.14.5.tgz#72c789084d8f2094acb945633943ef8443d39e67" - integrity sha512-szkbzQ0mNk0rpu76fzDdqSyPu0MuvpXgC+6rz5rpMb5OIRxdmHfQxrktL8CYolL2d8luMCZTR0DpIMIdL27IjA== - dependencies: - "@babel/helper-module-imports" "^7.14.5" + "@babel/helper-module-imports" "^7.16.0" "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-remap-async-to-generator" "^7.14.5" + "@babel/helper-remap-async-to-generator" "^7.16.0" -"@babel/plugin-transform-block-scoped-functions@^7.12.1", "@babel/plugin-transform-block-scoped-functions@^7.2.0": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.12.1.tgz#f2a1a365bde2b7112e0a6ded9067fdd7c07905d9" - integrity sha512-5OpxfuYnSgPalRpo8EWGPzIYf0lHBWORCkj5M0oLBwHdlux9Ri36QqGW3/LR13RSVOAoUUMzoPI/jpE4ABcHoA== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-block-scoped-functions@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.14.5.tgz#e48641d999d4bc157a67ef336aeb54bc44fd3ad4" - integrity sha512-dtqWqdWZ5NqBX3KzsVCWfQI3A53Ft5pWFCT2eCVUftWZgjc5DpDponbIF1+c+7cSGk2wN0YK7HGL/ezfRbpKBQ== +"@babel/plugin-transform-block-scoped-functions@^7.16.0", "@babel/plugin-transform-block-scoped-functions@^7.2.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.16.0.tgz#c618763233ad02847805abcac4c345ce9de7145d" + integrity sha512-V14As3haUOP4ZWrLJ3VVx5rCnrYhMSHN/jX7z6FAt5hjRkLsb0snPCmJwSOML5oxkKO4FNoNv7V5hw/y2bjuvg== dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-block-scoping@^7.12.1", "@babel/plugin-transform-block-scoping@^7.12.11", "@babel/plugin-transform-block-scoping@^7.4.4": - version "7.12.12" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.12.12.tgz#d93a567a152c22aea3b1929bb118d1d0a175cdca" - integrity sha512-VOEPQ/ExOVqbukuP7BYJtI5ZxxsmegTwzZ04j1aF0dkSypGo9XpDHuOrABsJu+ie+penpSJheDJ11x1BEZNiyQ== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-block-scoping@^7.15.3": - version "7.15.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.15.3.tgz#94c81a6e2fc230bcce6ef537ac96a1e4d2b3afaf" - integrity sha512-nBAzfZwZb4DkaGtOes1Up1nOAp9TDRRFw4XBzBBSG9QK7KVFmYzgj9o9sbPv7TX5ofL4Auq4wZnxCoPnI/lz2Q== +"@babel/plugin-transform-block-scoping@^7.12.1", "@babel/plugin-transform-block-scoping@^7.16.0", "@babel/plugin-transform-block-scoping@^7.4.4": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.16.0.tgz#bcf433fb482fe8c3d3b4e8a66b1c4a8e77d37c16" + integrity sha512-27n3l67/R3UrXfizlvHGuTwsRIFyce3D/6a37GRxn28iyTPvNXaW4XvznexRh1zUNLPjbLL22Id0XQElV94ruw== dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-classes@^7.12.1", "@babel/plugin-transform-classes@^7.4.4": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.12.1.tgz#65e650fcaddd3d88ddce67c0f834a3d436a32db6" - integrity sha512-/74xkA7bVdzQTBeSUhLLJgYIcxw/dpEpCdRDiHgPJ3Mv6uC11UhjpOhl72CgqbBCmt1qtssCyB2xnJm1+PFjog== +"@babel/plugin-transform-classes@^7.12.1", "@babel/plugin-transform-classes@^7.16.0", "@babel/plugin-transform-classes@^7.4.4": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.16.0.tgz#54cf5ff0b2242c6573d753cd4bfc7077a8b282f5" + integrity sha512-HUxMvy6GtAdd+GKBNYDWCIA776byUQH8zjnfjxwT1P1ARv/wFu8eBDpmXQcLS/IwRtrxIReGiplOwMeyO7nsDQ== dependencies: - "@babel/helper-annotate-as-pure" "^7.10.4" - "@babel/helper-define-map" "^7.10.4" - "@babel/helper-function-name" "^7.10.4" - "@babel/helper-optimise-call-expression" "^7.10.4" - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/helper-replace-supers" "^7.12.1" - "@babel/helper-split-export-declaration" "^7.10.4" - globals "^11.1.0" - -"@babel/plugin-transform-classes@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.15.4.tgz#50aee17aaf7f332ae44e3bce4c2e10534d5d3bf1" - integrity sha512-Yjvhex8GzBmmPQUvpXRPWQ9WnxXgAFuZSrqOK/eJlOGIXwvv8H3UEdUigl1gb/bnjTrln+e8bkZUYCBt/xYlBg== - dependencies: - "@babel/helper-annotate-as-pure" "^7.15.4" - "@babel/helper-function-name" "^7.15.4" - "@babel/helper-optimise-call-expression" "^7.15.4" + "@babel/helper-annotate-as-pure" "^7.16.0" + "@babel/helper-function-name" "^7.16.0" + "@babel/helper-optimise-call-expression" "^7.16.0" "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-replace-supers" "^7.15.4" - "@babel/helper-split-export-declaration" "^7.15.4" + "@babel/helper-replace-supers" "^7.16.0" + "@babel/helper-split-export-declaration" "^7.16.0" globals "^11.1.0" -"@babel/plugin-transform-computed-properties@^7.12.1", "@babel/plugin-transform-computed-properties@^7.2.0": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.12.1.tgz#d68cf6c9b7f838a8a4144badbe97541ea0904852" - integrity sha512-vVUOYpPWB7BkgUWPo4C44mUQHpTZXakEqFjbv8rQMg7TC6S6ZhGZ3otQcRH6u7+adSlE5i0sp63eMC/XGffrzg== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-computed-properties@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.14.5.tgz#1b9d78987420d11223d41195461cc43b974b204f" - integrity sha512-pWM+E4283UxaVzLb8UBXv4EIxMovU4zxT1OPnpHJcmnvyY9QbPPTKZfEj31EUvG3/EQRbYAGaYEUZ4yWOBC2xg== +"@babel/plugin-transform-computed-properties@^7.16.0", "@babel/plugin-transform-computed-properties@^7.2.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.16.0.tgz#e0c385507d21e1b0b076d66bed6d5231b85110b7" + integrity sha512-63l1dRXday6S8V3WFY5mXJwcRAnPYxvFfTlt67bwV1rTyVTM5zrp0DBBb13Kl7+ehkCVwIZPumPpFP/4u70+Tw== dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-destructuring@^7.12.1", "@babel/plugin-transform-destructuring@^7.4.4": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.12.1.tgz#b9a570fe0d0a8d460116413cb4f97e8e08b2f847" - integrity sha512-fRMYFKuzi/rSiYb2uRLiUENJOKq4Gnl+6qOv5f8z0TZXg3llUwUhsNNwrwaT/6dUhJTzNpBr+CUvEWBtfNY1cw== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-destructuring@^7.14.7": - version "7.14.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.14.7.tgz#0ad58ed37e23e22084d109f185260835e5557576" - integrity sha512-0mDE99nK+kVh3xlc5vKwB6wnP9ecuSj+zQCa/n0voENtP/zymdT4HH6QEb65wjjcbqr1Jb/7z9Qp7TF5FtwYGw== +"@babel/plugin-transform-destructuring@^7.12.1", "@babel/plugin-transform-destructuring@^7.16.0", "@babel/plugin-transform-destructuring@^7.4.4": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.16.0.tgz#ad3d7e74584ad5ea4eadb1e6642146c590dee33c" + integrity sha512-Q7tBUwjxLTsHEoqktemHBMtb3NYwyJPTJdM+wDwb0g8PZ3kQUIzNvwD5lPaqW/p54TXBc/MXZu9Jr7tbUEUM8Q== dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-dotall-regex@^7.12.1", "@babel/plugin-transform-dotall-regex@^7.4.4": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.12.1.tgz#a1d16c14862817b6409c0a678d6f9373ca9cd975" - integrity sha512-B2pXeRKoLszfEW7J4Hg9LoFaWEbr/kzo3teWHmtFCszjRNa/b40f9mfeqZsIDLLt/FjwQ6pz/Gdlwy85xNckBA== +"@babel/plugin-transform-dotall-regex@^7.16.0", "@babel/plugin-transform-dotall-regex@^7.4.4": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.16.0.tgz#50bab00c1084b6162d0a58a818031cf57798e06f" + integrity sha512-FXlDZfQeLILfJlC6I1qyEwcHK5UpRCFkaoVyA1nk9A1L1Yu583YO4un2KsLBsu3IJb4CUbctZks8tD9xPQubLw== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.12.1" - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-dotall-regex@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.14.5.tgz#2f6bf76e46bdf8043b4e7e16cf24532629ba0c7a" - integrity sha512-loGlnBdj02MDsFaHhAIJzh7euK89lBrGIdM9EAtHFo6xKygCUGuuWe07o1oZVk287amtW1n0808sQM99aZt3gw== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.14.5" + "@babel/helper-create-regexp-features-plugin" "^7.16.0" "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-duplicate-keys@^7.12.1", "@babel/plugin-transform-duplicate-keys@^7.2.0": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.12.1.tgz#745661baba295ac06e686822797a69fbaa2ca228" - integrity sha512-iRght0T0HztAb/CazveUpUQrZY+aGKKaWXMJ4uf9YJtqxSUe09j3wteztCUDRHs+SRAL7yMuFqUsLoAKKzgXjw== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-duplicate-keys@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.14.5.tgz#365a4844881bdf1501e3a9f0270e7f0f91177954" - integrity sha512-iJjbI53huKbPDAsJ8EmVmvCKeeq21bAze4fu9GBQtSLqfvzj2oRuHVx4ZkDwEhg1htQ+5OBZh/Ab0XDf5iBZ7A== +"@babel/plugin-transform-duplicate-keys@^7.16.0", "@babel/plugin-transform-duplicate-keys@^7.2.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.16.0.tgz#8bc2e21813e3e89e5e5bf3b60aa5fc458575a176" + integrity sha512-LIe2kcHKAZOJDNxujvmp6z3mfN6V9lJxubU4fJIGoQCkKe3Ec2OcbdlYP+vW++4MpxwG0d1wSDOJtQW5kLnkZQ== dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-exponentiation-operator@^7.12.1", "@babel/plugin-transform-exponentiation-operator@^7.2.0": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.12.1.tgz#b0f2ed356ba1be1428ecaf128ff8a24f02830ae0" - integrity sha512-7tqwy2bv48q+c1EHbXK0Zx3KXd2RVQp6OC7PbwFNt/dPTAV3Lu5sWtWuAj8owr5wqtWnqHfl2/mJlUmqkChKug== - dependencies: - "@babel/helper-builder-binary-assignment-operator-visitor" "^7.10.4" - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-exponentiation-operator@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.14.5.tgz#5154b8dd6a3dfe6d90923d61724bd3deeb90b493" - integrity sha512-jFazJhMBc9D27o9jDnIE5ZErI0R0m7PbKXVq77FFvqFbzvTMuv8jaAwLZ5PviOLSFttqKIW0/wxNSDbjLk0tYA== +"@babel/plugin-transform-exponentiation-operator@^7.16.0", "@babel/plugin-transform-exponentiation-operator@^7.2.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.16.0.tgz#a180cd2881e3533cef9d3901e48dad0fbeff4be4" + integrity sha512-OwYEvzFI38hXklsrbNivzpO3fh87skzx8Pnqi4LoSYeav0xHlueSoCJrSgTPfnbyzopo5b3YVAJkFIcUpK2wsw== dependencies: - "@babel/helper-builder-binary-assignment-operator-visitor" "^7.14.5" + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.16.0" "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-transform-flow-strip-types@^7.12.13": @@ -1270,239 +777,122 @@ "@babel/helper-plugin-utils" "^7.13.0" "@babel/plugin-syntax-flow" "^7.12.13" -"@babel/plugin-transform-for-of@^7.12.1", "@babel/plugin-transform-for-of@^7.4.4": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.12.1.tgz#07640f28867ed16f9511c99c888291f560921cfa" - integrity sha512-Zaeq10naAsuHo7heQvyV0ptj4dlZJwZgNAtBYBnu5nNKJoW62m0zKcIEyVECrUKErkUkg6ajMy4ZfnVZciSBhg== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-for-of@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.15.4.tgz#25c62cce2718cfb29715f416e75d5263fb36a8c2" - integrity sha512-DRTY9fA751AFBDh2oxydvVm4SYevs5ILTWLs6xKXps4Re/KG5nfUkr+TdHCrRWB8C69TlzVgA9b3RmGWmgN9LA== +"@babel/plugin-transform-for-of@^7.12.1", "@babel/plugin-transform-for-of@^7.16.0", "@babel/plugin-transform-for-of@^7.4.4": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.16.0.tgz#f7abaced155260e2461359bbc7c7248aca5e6bd2" + integrity sha512-5QKUw2kO+GVmKr2wMYSATCTTnHyscl6sxFRAY+rvN7h7WB0lcG0o4NoV6ZQU32OZGVsYUsfLGgPQpDFdkfjlJQ== dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-function-name@^7.12.1", "@babel/plugin-transform-function-name@^7.4.4": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.12.1.tgz#2ec76258c70fe08c6d7da154003a480620eba667" - integrity sha512-JF3UgJUILoFrFMEnOJLJkRHSk6LUSXLmEFsA23aR2O5CSLUxbeUX1IZ1YQ7Sn0aXb601Ncwjx73a+FVqgcljVw== - dependencies: - "@babel/helper-function-name" "^7.10.4" - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-function-name@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.14.5.tgz#e81c65ecb900746d7f31802f6bed1f52d915d6f2" - integrity sha512-vbO6kv0fIzZ1GpmGQuvbwwm+O4Cbm2NrPzwlup9+/3fdkuzo1YqOZcXw26+YUJB84Ja7j9yURWposEHLYwxUfQ== +"@babel/plugin-transform-function-name@^7.16.0", "@babel/plugin-transform-function-name@^7.4.4": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.16.0.tgz#02e3699c284c6262236599f751065c5d5f1f400e" + integrity sha512-lBzMle9jcOXtSOXUpc7tvvTpENu/NuekNJVova5lCCWCV9/U1ho2HH2y0p6mBg8fPm/syEAbfaaemYGOHCY3mg== dependencies: - "@babel/helper-function-name" "^7.14.5" + "@babel/helper-function-name" "^7.16.0" "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-literals@^7.12.1", "@babel/plugin-transform-literals@^7.2.0": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.12.1.tgz#d73b803a26b37017ddf9d3bb8f4dc58bfb806f57" - integrity sha512-+PxVGA+2Ag6uGgL0A5f+9rklOnnMccwEBzwYFL3EUaKuiyVnUipyXncFcfjSkbimLrODoqki1U9XxZzTvfN7IQ== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-literals@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.14.5.tgz#41d06c7ff5d4d09e3cf4587bd3ecf3930c730f78" - integrity sha512-ql33+epql2F49bi8aHXxvLURHkxJbSmMKl9J5yHqg4PLtdE6Uc48CH1GS6TQvZ86eoB/ApZXwm7jlA+B3kra7A== +"@babel/plugin-transform-literals@^7.16.0", "@babel/plugin-transform-literals@^7.2.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.16.0.tgz#79711e670ffceb31bd298229d50f3621f7980cac" + integrity sha512-gQDlsSF1iv9RU04clgXqRjrPyyoJMTclFt3K1cjLmTKikc0s/6vE3hlDeEVC71wLTRu72Fq7650kABrdTc2wMQ== dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-member-expression-literals@^7.12.1", "@babel/plugin-transform-member-expression-literals@^7.2.0": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.12.1.tgz#496038602daf1514a64d43d8e17cbb2755e0c3ad" - integrity sha512-1sxePl6z9ad0gFMB9KqmYofk34flq62aqMt9NqliS/7hPEpURUCMbyHXrMPlo282iY7nAvUB1aQd5mg79UD9Jg== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-member-expression-literals@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.14.5.tgz#b39cd5212a2bf235a617d320ec2b48bcc091b8a7" - integrity sha512-WkNXxH1VXVTKarWFqmso83xl+2V3Eo28YY5utIkbsmXoItO8Q3aZxN4BTS2k0hz9dGUloHK26mJMyQEYfkn/+Q== +"@babel/plugin-transform-member-expression-literals@^7.16.0", "@babel/plugin-transform-member-expression-literals@^7.2.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.16.0.tgz#5251b4cce01eaf8314403d21aedb269d79f5e64b" + integrity sha512-WRpw5HL4Jhnxw8QARzRvwojp9MIE7Tdk3ez6vRyUk1MwgjJN0aNpRoXainLR5SgxmoXx/vsXGZ6OthP6t/RbUg== dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-modules-amd@^7.12.1", "@babel/plugin-transform-modules-amd@^7.2.0": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.12.1.tgz#3154300b026185666eebb0c0ed7f8415fefcf6f9" - integrity sha512-tDW8hMkzad5oDtzsB70HIQQRBiTKrhfgwC/KkJeGsaNFTdWhKNt/BiE8c5yj19XiGyrxpbkOfH87qkNg1YGlOQ== - dependencies: - "@babel/helper-module-transforms" "^7.12.1" - "@babel/helper-plugin-utils" "^7.10.4" - babel-plugin-dynamic-import-node "^2.3.3" - -"@babel/plugin-transform-modules-amd@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.14.5.tgz#4fd9ce7e3411cb8b83848480b7041d83004858f7" - integrity sha512-3lpOU8Vxmp3roC4vzFpSdEpGUWSMsHFreTWOMMLzel2gNGfHE5UWIh/LN6ghHs2xurUp4jRFYMUIZhuFbody1g== +"@babel/plugin-transform-modules-amd@^7.16.0", "@babel/plugin-transform-modules-amd@^7.2.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.16.0.tgz#09abd41e18dcf4fd479c598c1cef7bd39eb1337e" + integrity sha512-rWFhWbCJ9Wdmzln1NmSCqn7P0RAD+ogXG/bd9Kg5c7PKWkJtkiXmYsMBeXjDlzHpVTJ4I/hnjs45zX4dEv81xw== dependencies: - "@babel/helper-module-transforms" "^7.14.5" + "@babel/helper-module-transforms" "^7.16.0" "@babel/helper-plugin-utils" "^7.14.5" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-commonjs@^7.12.1", "@babel/plugin-transform-modules-commonjs@^7.4.4": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.12.1.tgz#fa403124542636c786cf9b460a0ffbb48a86e648" - integrity sha512-dY789wq6l0uLY8py9c1B48V8mVL5gZh/+PQ5ZPrylPYsnAvnEMjqsUXkuoDVPeVK+0VyGar+D08107LzDQ6pag== +"@babel/plugin-transform-modules-commonjs@^7.16.0", "@babel/plugin-transform-modules-commonjs@^7.4.4": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.16.0.tgz#add58e638c8ddc4875bd9a9ecb5c594613f6c922" + integrity sha512-Dzi+NWqyEotgzk/sb7kgQPJQf7AJkQBWsVp1N6JWc1lBVo0vkElUnGdr1PzUBmfsCCN5OOFya3RtpeHk15oLKQ== dependencies: - "@babel/helper-module-transforms" "^7.12.1" - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/helper-simple-access" "^7.12.1" - babel-plugin-dynamic-import-node "^2.3.3" - -"@babel/plugin-transform-modules-commonjs@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.15.4.tgz#8201101240eabb5a76c08ef61b2954f767b6b4c1" - integrity sha512-qg4DPhwG8hKp4BbVDvX1s8cohM8a6Bvptu4l6Iingq5rW+yRUAhe/YRup/YcW2zCOlrysEWVhftIcKzrEZv3sA== - dependencies: - "@babel/helper-module-transforms" "^7.15.4" + "@babel/helper-module-transforms" "^7.16.0" "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-simple-access" "^7.15.4" - babel-plugin-dynamic-import-node "^2.3.3" - -"@babel/plugin-transform-modules-systemjs@^7.12.1", "@babel/plugin-transform-modules-systemjs@^7.4.4": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.12.1.tgz#663fea620d593c93f214a464cd399bf6dc683086" - integrity sha512-Hn7cVvOavVh8yvW6fLwveFqSnd7rbQN3zJvoPNyNaQSvgfKmDBO9U1YL9+PCXGRlZD9tNdWTy5ACKqMuzyn32Q== - dependencies: - "@babel/helper-hoist-variables" "^7.10.4" - "@babel/helper-module-transforms" "^7.12.1" - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/helper-validator-identifier" "^7.10.4" + "@babel/helper-simple-access" "^7.16.0" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-systemjs@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.15.4.tgz#b42890c7349a78c827719f1d2d0cd38c7d268132" - integrity sha512-fJUnlQrl/mezMneR72CKCgtOoahqGJNVKpompKwzv3BrEXdlPspTcyxrZ1XmDTIr9PpULrgEQo3qNKp6dW7ssw== +"@babel/plugin-transform-modules-systemjs@^7.16.0", "@babel/plugin-transform-modules-systemjs@^7.4.4": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.16.0.tgz#a92cf240afeb605f4ca16670453024425e421ea4" + integrity sha512-yuGBaHS3lF1m/5R+6fjIke64ii5luRUg97N2wr+z1sF0V+sNSXPxXDdEEL/iYLszsN5VKxVB1IPfEqhzVpiqvg== dependencies: - "@babel/helper-hoist-variables" "^7.15.4" - "@babel/helper-module-transforms" "^7.15.4" + "@babel/helper-hoist-variables" "^7.16.0" + "@babel/helper-module-transforms" "^7.16.0" "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-validator-identifier" "^7.14.9" + "@babel/helper-validator-identifier" "^7.15.7" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-umd@^7.12.1", "@babel/plugin-transform-modules-umd@^7.2.0": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.12.1.tgz#eb5a218d6b1c68f3d6217b8fa2cc82fec6547902" - integrity sha512-aEIubCS0KHKM0zUos5fIoQm+AZUMt1ZvMpqz0/H5qAQ7vWylr9+PLYurT+Ic7ID/bKLd4q8hDovaG3Zch2uz5Q== - dependencies: - "@babel/helper-module-transforms" "^7.12.1" - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-modules-umd@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.14.5.tgz#fb662dfee697cce274a7cda525190a79096aa6e0" - integrity sha512-RfPGoagSngC06LsGUYyM9QWSXZ8MysEjDJTAea1lqRjNECE3y0qIJF/qbvJxc4oA4s99HumIMdXOrd+TdKaAAA== +"@babel/plugin-transform-modules-umd@^7.16.0", "@babel/plugin-transform-modules-umd@^7.2.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.16.0.tgz#195f26c2ad6d6a391b70880effce18ce625e06a7" + integrity sha512-nx4f6no57himWiHhxDM5pjwhae5vLpTK2zCnDH8+wNLJy0TVER/LJRHl2bkt6w9Aad2sPD5iNNoUpY3X9sTGDg== dependencies: - "@babel/helper-module-transforms" "^7.14.5" + "@babel/helper-module-transforms" "^7.16.0" "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-named-capturing-groups-regex@^7.12.1", "@babel/plugin-transform-named-capturing-groups-regex@^7.4.5": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.12.1.tgz#b407f5c96be0d9f5f88467497fa82b30ac3e8753" - integrity sha512-tB43uQ62RHcoDp9v2Nsf+dSM8sbNodbEicbQNA53zHz8pWUhsgHSJCGpt7daXxRydjb0KnfmB+ChXOv3oADp1Q== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.12.1" - -"@babel/plugin-transform-named-capturing-groups-regex@^7.14.9": - version "7.14.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.14.9.tgz#c68f5c5d12d2ebaba3762e57c2c4f6347a46e7b2" - integrity sha512-l666wCVYO75mlAtGFfyFwnWmIXQm3kSH0C3IRnJqWcZbWkoihyAdDhFm2ZWaxWTqvBvhVFfJjMRQ0ez4oN1yYA== +"@babel/plugin-transform-named-capturing-groups-regex@^7.16.0", "@babel/plugin-transform-named-capturing-groups-regex@^7.4.5": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.16.0.tgz#d3db61cc5d5b97986559967cd5ea83e5c32096ca" + integrity sha512-LogN88uO+7EhxWc8WZuQ8vxdSyVGxhkh8WTC3tzlT8LccMuQdA81e9SGV6zY7kY2LjDhhDOFdQVxdGwPyBCnvg== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.14.5" + "@babel/helper-create-regexp-features-plugin" "^7.16.0" -"@babel/plugin-transform-new-target@^7.12.1", "@babel/plugin-transform-new-target@^7.4.4": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.12.1.tgz#80073f02ee1bb2d365c3416490e085c95759dec0" - integrity sha512-+eW/VLcUL5L9IvJH7rT1sT0CzkdUTvPrXC2PXTn/7z7tXLBuKvezYbGdxD5WMRoyvyaujOq2fWoKl869heKjhw== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-new-target@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.14.5.tgz#31bdae8b925dc84076ebfcd2a9940143aed7dbf8" - integrity sha512-Nx054zovz6IIRWEB49RDRuXGI4Gy0GMgqG0cII9L3MxqgXz/+rgII+RU58qpo4g7tNEx1jG7rRVH4ihZoP4esQ== +"@babel/plugin-transform-new-target@^7.16.0", "@babel/plugin-transform-new-target@^7.4.4": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.16.0.tgz#af823ab576f752215a49937779a41ca65825ab35" + integrity sha512-fhjrDEYv2DBsGN/P6rlqakwRwIp7rBGLPbrKxwh7oVt5NNkIhZVOY2GRV+ULLsQri1bDqwDWnU3vhlmx5B2aCw== dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-object-super@^7.12.1", "@babel/plugin-transform-object-super@^7.2.0": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.12.1.tgz#4ea08696b8d2e65841d0c7706482b048bed1066e" - integrity sha512-AvypiGJH9hsquNUn+RXVcBdeE3KHPZexWRdimhuV59cSoOt5kFBmqlByorAeUlGG2CJWd0U+4ZtNKga/TB0cAw== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/helper-replace-supers" "^7.12.1" - -"@babel/plugin-transform-object-super@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.14.5.tgz#d0b5faeac9e98597a161a9cf78c527ed934cdc45" - integrity sha512-MKfOBWzK0pZIrav9z/hkRqIk/2bTv9qvxHzPQc12RcVkMOzpIKnFCNYJip00ssKWYkd8Sf5g0Wr7pqJ+cmtuFg== +"@babel/plugin-transform-object-super@^7.16.0", "@babel/plugin-transform-object-super@^7.2.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.16.0.tgz#fb20d5806dc6491a06296ac14ea8e8d6fedda72b" + integrity sha512-fds+puedQHn4cPLshoHcR1DTMN0q1V9ou0mUjm8whx9pGcNvDrVVrgw+KJzzCaiTdaYhldtrUps8DWVMgrSEyg== dependencies: "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-replace-supers" "^7.14.5" + "@babel/helper-replace-supers" "^7.16.0" -"@babel/plugin-transform-parameters@^7.12.1", "@babel/plugin-transform-parameters@^7.4.4": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.12.1.tgz#d2e963b038771650c922eff593799c96d853255d" - integrity sha512-xq9C5EQhdPK23ZeCdMxl8bbRnAgHFrw5EOC3KJUsSylZqdkCaFEXxGSBuTSObOpiiHHNyb82es8M1QYgfQGfNg== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-parameters@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.15.4.tgz#5f2285cc3160bf48c8502432716b48504d29ed62" - integrity sha512-9WB/GUTO6lvJU3XQsSr6J/WKvBC2hcs4Pew8YxZagi6GkTdniyqp8On5kqdK8MN0LMeu0mGbhPN+O049NV/9FQ== +"@babel/plugin-transform-parameters@^7.12.1", "@babel/plugin-transform-parameters@^7.16.0", "@babel/plugin-transform-parameters@^7.4.4": + version "7.16.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.16.3.tgz#fa9e4c874ee5223f891ee6fa8d737f4766d31d15" + integrity sha512-3MaDpJrOXT1MZ/WCmkOFo7EtmVVC8H4EUZVrHvFOsmwkk4lOjQj8rzv8JKUZV4YoQKeoIgk07GO+acPU9IMu/w== dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-property-literals@^7.12.1", "@babel/plugin-transform-property-literals@^7.2.0": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.12.1.tgz#41bc81200d730abb4456ab8b3fbd5537b59adecd" - integrity sha512-6MTCR/mZ1MQS+AwZLplX4cEySjCpnIF26ToWo942nqn8hXSm7McaHQNeGx/pt7suI1TWOWMfa/NgBhiqSnX0cQ== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-property-literals@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.14.5.tgz#0ddbaa1f83db3606f1cdf4846fa1dfb473458b34" - integrity sha512-r1uilDthkgXW8Z1vJz2dKYLV1tuw2xsbrp3MrZmD99Wh9vsfKoob+JTgri5VUb/JqyKRXotlOtwgu4stIYCmnw== +"@babel/plugin-transform-property-literals@^7.16.0", "@babel/plugin-transform-property-literals@^7.2.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.16.0.tgz#a95c552189a96a00059f6776dc4e00e3690c78d1" + integrity sha512-XLldD4V8+pOqX2hwfWhgwXzGdnDOThxaNTgqagOcpBgIxbUvpgU2FMvo5E1RyHbk756WYgdbS0T8y0Cj9FKkWQ== dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-react-display-name@^7.0.0", "@babel/plugin-transform-react-display-name@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.12.1.tgz#1cbcd0c3b1d6648c55374a22fc9b6b7e5341c00d" - integrity sha512-cAzB+UzBIrekfYxyLlFqf/OagTvHLcVBb5vpouzkYkBclRPraiygVnafvAoipErZLI8ANv8Ecn6E/m5qPXD26w== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-react-display-name@^7.14.5": - version "7.15.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.15.1.tgz#6aaac6099f1fcf6589d35ae6be1b6e10c8c602b9" - integrity sha512-yQZ/i/pUCJAHI/LbtZr413S3VT26qNrEm0M5RRxQJA947/YNYwbZbBaXGDrq6CG5QsZycI1VIP6d7pQaBfP+8Q== +"@babel/plugin-transform-react-display-name@^7.0.0", "@babel/plugin-transform-react-display-name@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.16.0.tgz#9a0ad8aa8e8790883a7bd2736f66229a58125676" + integrity sha512-FJFdJAqaCpndL+pIf0aeD/qlQwT7QXOvR6Cc8JPvNhKJBi2zc/DPc4g05Y3fbD/0iWAMQFGij4+Xw+4L/BMpTg== dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-react-jsx-development@^7.12.7": - version "7.12.12" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.12.12.tgz#bccca33108fe99d95d7f9e82046bfe762e71f4e7" - integrity sha512-i1AxnKxHeMxUaWVXQOSIco4tvVvvCxMSfeBMnMM06mpaJt3g+MpxYQQrDfojUQldP1xxraPSJYSMEljoWM/dCg== +"@babel/plugin-transform-react-jsx-development@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.16.0.tgz#1cb52874678d23ab11d0d16488d54730807303ef" + integrity sha512-qq65iSqBRq0Hr3wq57YG2AmW0H6wgTnIzpffTphrUWUgLCOK+zf1f7G0vuOiXrp7dU1qq+fQBoqZ3wCDAkhFzw== dependencies: - "@babel/plugin-transform-react-jsx" "^7.12.12" - -"@babel/plugin-transform-react-jsx-development@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.14.5.tgz#1a6c73e2f7ed2c42eebc3d2ad60b0c7494fcb9af" - integrity sha512-rdwG/9jC6QybWxVe2UVOa7q6cnTpw8JRRHOxntG/h6g/guAOe6AhtQHJuJh5FwmnXIT1bdm5vC2/5huV8ZOorQ== - dependencies: - "@babel/plugin-transform-react-jsx" "^7.14.5" + "@babel/plugin-transform-react-jsx" "^7.16.0" "@babel/plugin-transform-react-jsx-self@^7.0.0": version "7.10.4" @@ -1520,69 +910,36 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-jsx" "^7.10.4" -"@babel/plugin-transform-react-jsx@^7.0.0", "@babel/plugin-transform-react-jsx@^7.12.1", "@babel/plugin-transform-react-jsx@^7.12.10", "@babel/plugin-transform-react-jsx@^7.12.12": - version "7.12.12" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.12.12.tgz#b0da51ffe5f34b9a900e9f1f5fb814f9e512d25e" - integrity sha512-JDWGuzGNWscYcq8oJVCtSE61a5+XAOos+V0HrxnDieUus4UMnBEosDnY1VJqU5iZ4pA04QY7l0+JvHL1hZEfsw== +"@babel/plugin-transform-react-jsx@^7.0.0", "@babel/plugin-transform-react-jsx@^7.12.1", "@babel/plugin-transform-react-jsx@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.16.0.tgz#55b797d4960c3de04e07ad1c0476e2bc6a4889f1" + integrity sha512-rqDgIbukZ44pqq7NIRPGPGNklshPkvlmvqjdx3OZcGPk4zGIenYkxDTvl3LsSL8gqcc3ZzGmXPE6hR/u/voNOw== dependencies: - "@babel/helper-annotate-as-pure" "^7.12.10" - "@babel/helper-module-imports" "^7.12.5" - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-syntax-jsx" "^7.12.1" - "@babel/types" "^7.12.12" - -"@babel/plugin-transform-react-jsx@^7.14.5": - version "7.14.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.14.9.tgz#3314b2163033abac5200a869c4de242cd50a914c" - integrity sha512-30PeETvS+AeD1f58i1OVyoDlVYQhap/K20ZrMjLmmzmC2AYR/G43D4sdJAaDAqCD3MYpSWbmrz3kES158QSLjw== - dependencies: - "@babel/helper-annotate-as-pure" "^7.14.5" - "@babel/helper-module-imports" "^7.14.5" + "@babel/helper-annotate-as-pure" "^7.16.0" + "@babel/helper-module-imports" "^7.16.0" "@babel/helper-plugin-utils" "^7.14.5" - "@babel/plugin-syntax-jsx" "^7.14.5" - "@babel/types" "^7.14.9" + "@babel/plugin-syntax-jsx" "^7.16.0" + "@babel/types" "^7.16.0" -"@babel/plugin-transform-react-pure-annotations@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.12.1.tgz#05d46f0ab4d1339ac59adf20a1462c91b37a1a42" - integrity sha512-RqeaHiwZtphSIUZ5I85PEH19LOSzxfuEazoY7/pWASCAIBuATQzpSVD+eT6MebeeZT2F4eSL0u4vw6n4Nm0Mjg== +"@babel/plugin-transform-react-pure-annotations@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.16.0.tgz#23db6ddf558d8abde41b8ad9d59f48ad5532ccab" + integrity sha512-NC/Bj2MG+t8Ef5Pdpo34Ay74X4Rt804h5y81PwOpfPtmAK3i6CizmQqwyBQzIepz1Yt8wNr2Z2L7Lu3qBMfZMA== dependencies: - "@babel/helper-annotate-as-pure" "^7.10.4" - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-react-pure-annotations@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.14.5.tgz#18de612b84021e3a9802cbc212c9d9f46d0d11fc" - integrity sha512-3X4HpBJimNxW4rhUy/SONPyNQHp5YRr0HhJdT2OH1BRp0of7u3Dkirc7x9FRJMKMqTBI079VZ1hzv7Ouuz///g== - dependencies: - "@babel/helper-annotate-as-pure" "^7.14.5" + "@babel/helper-annotate-as-pure" "^7.16.0" "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-regenerator@^7.12.1", "@babel/plugin-transform-regenerator@^7.4.5": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.12.1.tgz#5f0a28d842f6462281f06a964e88ba8d7ab49753" - integrity sha512-gYrHqs5itw6i4PflFX3OdBPMQdPbF4bj2REIUxlMRUFk0/ZOAIpDFuViuxPjUL7YC8UPnf+XG7/utJvqXdPKng== - dependencies: - regenerator-transform "^0.14.2" - -"@babel/plugin-transform-regenerator@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.14.5.tgz#9676fd5707ed28f522727c5b3c0aa8544440b04f" - integrity sha512-NVIY1W3ITDP5xQl50NgTKlZ0GrotKtLna08/uGY6ErQt6VEQZXla86x/CTddm5gZdcr+5GSsvMeTmWA5Ii6pkg== +"@babel/plugin-transform-regenerator@^7.16.0", "@babel/plugin-transform-regenerator@^7.4.5": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.16.0.tgz#eaee422c84b0232d03aea7db99c97deeaf6125a4" + integrity sha512-JAvGxgKuwS2PihiSFaDrp94XOzzTUeDeOQlcKzVAyaPap7BnZXK/lvMDiubkPTdotPKOIZq9xWXWnggUMYiExg== dependencies: regenerator-transform "^0.14.2" -"@babel/plugin-transform-reserved-words@^7.12.1", "@babel/plugin-transform-reserved-words@^7.2.0": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.12.1.tgz#6fdfc8cc7edcc42b36a7c12188c6787c873adcd8" - integrity sha512-pOnUfhyPKvZpVyBHhSBoX8vfA09b7r00Pmm1sH+29ae2hMTKVmSp4Ztsr8KBKjLjx17H0eJqaRC3bR2iThM54A== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-reserved-words@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.14.5.tgz#c44589b661cfdbef8d4300dcc7469dffa92f8304" - integrity sha512-cv4F2rv1nD4qdexOGsRQXJrOcyb5CrgjUH9PKrrtyhSDBNWGxd0UIitjyJiWagS+EbUGjG++22mGH1Pub8D6Vg== +"@babel/plugin-transform-reserved-words@^7.16.0", "@babel/plugin-transform-reserved-words@^7.2.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.16.0.tgz#fff4b9dcb19e12619394bda172d14f2d04c0379c" + integrity sha512-Dgs8NNCehHSvXdhEhln8u/TtJxfVwGYCgP2OOr5Z3Ar+B+zXicEOKNTyc+eca2cuEOMtjW6m9P9ijOt8QdqWkg== dependencies: "@babel/helper-plugin-utils" "^7.14.5" @@ -1596,136 +953,76 @@ resolve "^1.8.1" semver "^5.5.1" -"@babel/plugin-transform-runtime@^7.15.8": - version "7.15.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.15.8.tgz#9d15b1e94e1c7f6344f65a8d573597d93c6cd886" - integrity sha512-+6zsde91jMzzvkzuEA3k63zCw+tm/GvuuabkpisgbDMTPQsIMHllE3XczJFFtEHLjjhKQFZmGQVRdELetlWpVw== +"@babel/plugin-transform-runtime@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.16.0.tgz#3fe0da36c2f0834bef7c4d3e7f2b2db0ee0c8909" + integrity sha512-zlPf1/XFn5+vWdve3AAhf+Sxl+MVa5VlwTwWgnLx23u4GlatSRQJ3Eoo9vllf0a9il3woQsT4SK+5Z7c06h8ag== dependencies: - "@babel/helper-module-imports" "^7.15.4" + "@babel/helper-module-imports" "^7.16.0" "@babel/helper-plugin-utils" "^7.14.5" - babel-plugin-polyfill-corejs2 "^0.2.2" - babel-plugin-polyfill-corejs3 "^0.2.5" - babel-plugin-polyfill-regenerator "^0.2.2" + babel-plugin-polyfill-corejs2 "^0.2.3" + babel-plugin-polyfill-corejs3 "^0.3.0" + babel-plugin-polyfill-regenerator "^0.2.3" semver "^6.3.0" -"@babel/plugin-transform-shorthand-properties@^7.12.1", "@babel/plugin-transform-shorthand-properties@^7.2.0": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.12.1.tgz#0bf9cac5550fce0cfdf043420f661d645fdc75e3" - integrity sha512-GFZS3c/MhX1OusqB1MZ1ct2xRzX5ppQh2JU1h2Pnfk88HtFTM+TWQqJNfwkmxtPQtb/s1tk87oENfXJlx7rSDw== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-shorthand-properties@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.14.5.tgz#97f13855f1409338d8cadcbaca670ad79e091a58" - integrity sha512-xLucks6T1VmGsTB+GWK5Pl9Jl5+nRXD1uoFdA5TSO6xtiNjtXTjKkmPdFXVLGlK5A2/or/wQMKfmQ2Y0XJfn5g== +"@babel/plugin-transform-shorthand-properties@^7.12.1", "@babel/plugin-transform-shorthand-properties@^7.16.0", "@babel/plugin-transform-shorthand-properties@^7.2.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.16.0.tgz#090372e3141f7cc324ed70b3daf5379df2fa384d" + integrity sha512-iVb1mTcD8fuhSv3k99+5tlXu5N0v8/DPm2mO3WACLG6al1CGZH7v09HJyUb1TtYl/Z+KrM6pHSIJdZxP5A+xow== dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-spread@^7.12.1", "@babel/plugin-transform-spread@^7.2.0": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.12.1.tgz#527f9f311be4ec7fdc2b79bb89f7bf884b3e1e1e" - integrity sha512-vuLp8CP0BE18zVYjsEBZ5xoCecMK6LBMMxYzJnh01rxQRvhNhH1csMMmBfNo5tGpGO+NhdSNW2mzIvBu3K1fng== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/helper-skip-transparent-expression-wrappers" "^7.12.1" - -"@babel/plugin-transform-spread@^7.15.8": - version "7.15.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.15.8.tgz#79d5aa27f68d700449b2da07691dfa32d2f6d468" - integrity sha512-/daZ8s2tNaRekl9YJa9X4bzjpeRZLt122cpgFnQPLGUe61PH8zMEBmYqKkW5xF5JUEh5buEGXJoQpqBmIbpmEQ== +"@babel/plugin-transform-spread@^7.12.1", "@babel/plugin-transform-spread@^7.16.0", "@babel/plugin-transform-spread@^7.2.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.16.0.tgz#d21ca099bbd53ab307a8621e019a7bd0f40cdcfb" + integrity sha512-Ao4MSYRaLAQczZVp9/7E7QHsCuK92yHRrmVNRe/SlEJjhzivq0BSn8mEraimL8wizHZ3fuaHxKH0iwzI13GyGg== dependencies: "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-skip-transparent-expression-wrappers" "^7.15.4" - -"@babel/plugin-transform-sticky-regex@^7.12.7", "@babel/plugin-transform-sticky-regex@^7.2.0": - version "7.12.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.12.7.tgz#560224613ab23987453948ed21d0b0b193fa7fad" - integrity sha512-VEiqZL5N/QvDbdjfYQBhruN0HYjSPjC4XkeqW4ny/jNtH9gcbgaqBIXYEZCNnESMAGs0/K/R7oFGMhOyu/eIxg== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" -"@babel/plugin-transform-sticky-regex@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.14.5.tgz#5b617542675e8b7761294381f3c28c633f40aeb9" - integrity sha512-Z7F7GyvEMzIIbwnziAZmnSNpdijdr4dWt+FJNBnBLz5mwDFkqIXU9wmBcWWad3QeJF5hMTkRe4dAq2sUZiG+8A== +"@babel/plugin-transform-sticky-regex@^7.16.0", "@babel/plugin-transform-sticky-regex@^7.2.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.16.0.tgz#c35ea31a02d86be485f6aa510184b677a91738fd" + integrity sha512-/ntT2NljR9foobKk4E/YyOSwcGUXtYWv5tinMK/3RkypyNBNdhHUaq6Orw5DWq9ZcNlS03BIlEALFeQgeVAo4Q== dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-template-literals@^7.12.1", "@babel/plugin-transform-template-literals@^7.4.4": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.12.1.tgz#b43ece6ed9a79c0c71119f576d299ef09d942843" - integrity sha512-b4Zx3KHi+taXB1dVRBhVJtEPi9h1THCeKmae2qP0YdUHIFhVjtpqqNfxeVAa1xeHVhAy4SbHxEwx5cltAu5apw== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-template-literals@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.14.5.tgz#a5f2bc233937d8453885dc736bdd8d9ffabf3d93" - integrity sha512-22btZeURqiepOfuy/VkFr+zStqlujWaarpMErvay7goJS6BWwdd6BY9zQyDLDa4x2S3VugxFb162IZ4m/S/+Gg== +"@babel/plugin-transform-template-literals@^7.12.1", "@babel/plugin-transform-template-literals@^7.16.0", "@babel/plugin-transform-template-literals@^7.4.4": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.16.0.tgz#a8eced3a8e7b8e2d40ec4ec4548a45912630d302" + integrity sha512-Rd4Ic89hA/f7xUSJQk5PnC+4so50vBoBfxjdQAdvngwidM8jYIBVxBZ/sARxD4e0yMXRbJVDrYf7dyRtIIKT6Q== dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-typeof-symbol@^7.12.10", "@babel/plugin-transform-typeof-symbol@^7.2.0": - version "7.12.10" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.12.10.tgz#de01c4c8f96580bd00f183072b0d0ecdcf0dec4b" - integrity sha512-JQ6H8Rnsogh//ijxspCjc21YPd3VLVoYtAwv3zQmqAt8YGYUtdo5usNhdl4b9/Vir2kPFZl6n1h0PfUz4hJhaA== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-typeof-symbol@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.14.5.tgz#39af2739e989a2bd291bf6b53f16981423d457d4" - integrity sha512-lXzLD30ffCWseTbMQzrvDWqljvZlHkXU+CnseMhkMNqU1sASnCsz3tSzAaH3vCUXb9PHeUb90ZT1BdFTm1xxJw== +"@babel/plugin-transform-typeof-symbol@^7.16.0", "@babel/plugin-transform-typeof-symbol@^7.2.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.16.0.tgz#8b19a244c6f8c9d668dca6a6f754ad6ead1128f2" + integrity sha512-++V2L8Bdf4vcaHi2raILnptTBjGEFxn5315YU+e8+EqXIucA+q349qWngCLpUYqqv233suJ6NOienIVUpS9cqg== dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-typescript@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.12.1.tgz#d92cc0af504d510e26a754a7dbc2e5c8cd9c7ab4" - integrity sha512-VrsBByqAIntM+EYMqSm59SiMEf7qkmI9dqMt6RbD/wlwueWmYcI0FFK5Fj47pP6DRZm+3teXjosKlwcZJ5lIMw== +"@babel/plugin-transform-typescript@^7.16.0": + version "7.16.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.16.1.tgz#cc0670b2822b0338355bc1b3d2246a42b8166409" + integrity sha512-NO4XoryBng06jjw/qWEU2LhcLJr1tWkhpMam/H4eas/CDKMX/b2/Ylb6EI256Y7+FVPCawwSM1rrJNOpDiz+Lg== dependencies: - "@babel/helper-create-class-features-plugin" "^7.12.1" - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-syntax-typescript" "^7.12.1" - -"@babel/plugin-transform-typescript@^7.15.0": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.15.4.tgz#db7a062dcf8be5fc096bc0eeb40a13fbfa1fa251" - integrity sha512-sM1/FEjwYjXvMwu1PJStH11kJ154zd/lpY56NQJ5qH2D0mabMv1CAy/kdvS9RP4Xgfj9fBBA3JiSLdDHgXdzOA== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.15.4" + "@babel/helper-create-class-features-plugin" "^7.16.0" "@babel/helper-plugin-utils" "^7.14.5" - "@babel/plugin-syntax-typescript" "^7.14.5" + "@babel/plugin-syntax-typescript" "^7.16.0" -"@babel/plugin-transform-unicode-escapes@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.12.1.tgz#5232b9f81ccb07070b7c3c36c67a1b78f1845709" - integrity sha512-I8gNHJLIc7GdApm7wkVnStWssPNbSRMPtgHdmH3sRM1zopz09UWPS4x5V4n1yz/MIWTVnJ9sp6IkuXdWM4w+2Q== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-unicode-escapes@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.14.5.tgz#9d4bd2a681e3c5d7acf4f57fa9e51175d91d0c6b" - integrity sha512-crTo4jATEOjxj7bt9lbYXcBAM3LZaUrbP2uUdxb6WIorLmjNKSpHfIybgY4B8SRpbf8tEVIWH3Vtm7ayCrKocA== +"@babel/plugin-transform-unicode-escapes@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.16.0.tgz#1a354064b4c45663a32334f46fa0cf6100b5b1f3" + integrity sha512-VFi4dhgJM7Bpk8lRc5CMaRGlKZ29W9C3geZjt9beuzSUrlJxsNwX7ReLwaL6WEvsOf2EQkyIJEPtF8EXjB/g2A== dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-unicode-regex@^7.12.1", "@babel/plugin-transform-unicode-regex@^7.4.4": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.12.1.tgz#cc9661f61390db5c65e3febaccefd5c6ac3faecb" - integrity sha512-SqH4ClNngh/zGwHZOOQMTD+e8FGWexILV+ePMyiDJttAWRh5dhDL8rcl5lSgU3Huiq6Zn6pWTMvdPAb21Dwdyg== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.12.1" - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-unicode-regex@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.14.5.tgz#4cd09b6c8425dd81255c7ceb3fb1836e7414382e" - integrity sha512-UygduJpC5kHeCiRw/xDVzC+wj8VaYSoKl5JNVmbP7MadpNinAm3SvZCxZ42H37KZBKztz46YC73i9yV34d0Tzw== +"@babel/plugin-transform-unicode-regex@^7.16.0", "@babel/plugin-transform-unicode-regex@^7.4.4": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.16.0.tgz#293b80950177c8c85aede87cef280259fb995402" + integrity sha512-jHLK4LxhHjvCeZDWyA9c+P9XH1sOxRd1RO9xMtDVRAOND/PczPqizEtVdx4TQF/wyPaewqpT+tgQFYMnN/P94A== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.14.5" + "@babel/helper-create-regexp-features-plugin" "^7.16.0" "@babel/helper-plugin-utils" "^7.14.5" "@babel/preset-env@7.4.5": @@ -1782,103 +1079,32 @@ js-levenshtein "^1.1.3" semver "^5.5.0" -"@babel/preset-env@^7.12.1": - version "7.12.11" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.12.11.tgz#55d5f7981487365c93dbbc84507b1c7215e857f9" - integrity sha512-j8Tb+KKIXKYlDBQyIOy4BLxzv1NUOwlHfZ74rvW+Z0Gp4/cI2IMDPBWAgWceGcE7aep9oL/0K9mlzlMGxA8yNw== +"@babel/preset-env@^7.12.1", "@babel/preset-env@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.16.0.tgz#97228393d217560d6a1c6c56f0adb9d12bca67f5" + integrity sha512-cdTu/W0IrviamtnZiTfixPfIncr2M1VqRrkjzZWlr1B4TVYimCFK5jkyOdP4qw2MrlKHi+b3ORj6x8GoCew8Dg== dependencies: - "@babel/compat-data" "^7.12.7" - "@babel/helper-compilation-targets" "^7.12.5" - "@babel/helper-module-imports" "^7.12.5" - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/helper-validator-option" "^7.12.11" - "@babel/plugin-proposal-async-generator-functions" "^7.12.1" - "@babel/plugin-proposal-class-properties" "^7.12.1" - "@babel/plugin-proposal-dynamic-import" "^7.12.1" - "@babel/plugin-proposal-export-namespace-from" "^7.12.1" - "@babel/plugin-proposal-json-strings" "^7.12.1" - "@babel/plugin-proposal-logical-assignment-operators" "^7.12.1" - "@babel/plugin-proposal-nullish-coalescing-operator" "^7.12.1" - "@babel/plugin-proposal-numeric-separator" "^7.12.7" - "@babel/plugin-proposal-object-rest-spread" "^7.12.1" - "@babel/plugin-proposal-optional-catch-binding" "^7.12.1" - "@babel/plugin-proposal-optional-chaining" "^7.12.7" - "@babel/plugin-proposal-private-methods" "^7.12.1" - "@babel/plugin-proposal-unicode-property-regex" "^7.12.1" - "@babel/plugin-syntax-async-generators" "^7.8.0" - "@babel/plugin-syntax-class-properties" "^7.12.1" - "@babel/plugin-syntax-dynamic-import" "^7.8.0" - "@babel/plugin-syntax-export-namespace-from" "^7.8.3" - "@babel/plugin-syntax-json-strings" "^7.8.0" - "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" - "@babel/plugin-syntax-numeric-separator" "^7.10.4" - "@babel/plugin-syntax-object-rest-spread" "^7.8.0" - "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" - "@babel/plugin-syntax-optional-chaining" "^7.8.0" - "@babel/plugin-syntax-top-level-await" "^7.12.1" - "@babel/plugin-transform-arrow-functions" "^7.12.1" - "@babel/plugin-transform-async-to-generator" "^7.12.1" - "@babel/plugin-transform-block-scoped-functions" "^7.12.1" - "@babel/plugin-transform-block-scoping" "^7.12.11" - "@babel/plugin-transform-classes" "^7.12.1" - "@babel/plugin-transform-computed-properties" "^7.12.1" - "@babel/plugin-transform-destructuring" "^7.12.1" - "@babel/plugin-transform-dotall-regex" "^7.12.1" - "@babel/plugin-transform-duplicate-keys" "^7.12.1" - "@babel/plugin-transform-exponentiation-operator" "^7.12.1" - "@babel/plugin-transform-for-of" "^7.12.1" - "@babel/plugin-transform-function-name" "^7.12.1" - "@babel/plugin-transform-literals" "^7.12.1" - "@babel/plugin-transform-member-expression-literals" "^7.12.1" - "@babel/plugin-transform-modules-amd" "^7.12.1" - "@babel/plugin-transform-modules-commonjs" "^7.12.1" - "@babel/plugin-transform-modules-systemjs" "^7.12.1" - "@babel/plugin-transform-modules-umd" "^7.12.1" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.12.1" - "@babel/plugin-transform-new-target" "^7.12.1" - "@babel/plugin-transform-object-super" "^7.12.1" - "@babel/plugin-transform-parameters" "^7.12.1" - "@babel/plugin-transform-property-literals" "^7.12.1" - "@babel/plugin-transform-regenerator" "^7.12.1" - "@babel/plugin-transform-reserved-words" "^7.12.1" - "@babel/plugin-transform-shorthand-properties" "^7.12.1" - "@babel/plugin-transform-spread" "^7.12.1" - "@babel/plugin-transform-sticky-regex" "^7.12.7" - "@babel/plugin-transform-template-literals" "^7.12.1" - "@babel/plugin-transform-typeof-symbol" "^7.12.10" - "@babel/plugin-transform-unicode-escapes" "^7.12.1" - "@babel/plugin-transform-unicode-regex" "^7.12.1" - "@babel/preset-modules" "^0.1.3" - "@babel/types" "^7.12.11" - core-js-compat "^3.8.0" - semver "^5.5.0" - -"@babel/preset-env@^7.15.8": - version "7.15.8" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.15.8.tgz#f527ce5bcb121cd199f6b502bf23e420b3ff8dba" - integrity sha512-rCC0wH8husJgY4FPbHsiYyiLxSY8oMDJH7Rl6RQMknbN9oDDHhM9RDFvnGM2MgkbUJzSQB4gtuwygY5mCqGSsA== - dependencies: - "@babel/compat-data" "^7.15.0" - "@babel/helper-compilation-targets" "^7.15.4" + "@babel/compat-data" "^7.16.0" + "@babel/helper-compilation-targets" "^7.16.0" "@babel/helper-plugin-utils" "^7.14.5" "@babel/helper-validator-option" "^7.14.5" - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.15.4" - "@babel/plugin-proposal-async-generator-functions" "^7.15.8" - "@babel/plugin-proposal-class-properties" "^7.14.5" - "@babel/plugin-proposal-class-static-block" "^7.15.4" - "@babel/plugin-proposal-dynamic-import" "^7.14.5" - "@babel/plugin-proposal-export-namespace-from" "^7.14.5" - "@babel/plugin-proposal-json-strings" "^7.14.5" - "@babel/plugin-proposal-logical-assignment-operators" "^7.14.5" - "@babel/plugin-proposal-nullish-coalescing-operator" "^7.14.5" - "@babel/plugin-proposal-numeric-separator" "^7.14.5" - "@babel/plugin-proposal-object-rest-spread" "^7.15.6" - "@babel/plugin-proposal-optional-catch-binding" "^7.14.5" - "@babel/plugin-proposal-optional-chaining" "^7.14.5" - "@babel/plugin-proposal-private-methods" "^7.14.5" - "@babel/plugin-proposal-private-property-in-object" "^7.15.4" - "@babel/plugin-proposal-unicode-property-regex" "^7.14.5" + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.16.0" + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.16.0" + "@babel/plugin-proposal-async-generator-functions" "^7.16.0" + "@babel/plugin-proposal-class-properties" "^7.16.0" + "@babel/plugin-proposal-class-static-block" "^7.16.0" + "@babel/plugin-proposal-dynamic-import" "^7.16.0" + "@babel/plugin-proposal-export-namespace-from" "^7.16.0" + "@babel/plugin-proposal-json-strings" "^7.16.0" + "@babel/plugin-proposal-logical-assignment-operators" "^7.16.0" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.16.0" + "@babel/plugin-proposal-numeric-separator" "^7.16.0" + "@babel/plugin-proposal-object-rest-spread" "^7.16.0" + "@babel/plugin-proposal-optional-catch-binding" "^7.16.0" + "@babel/plugin-proposal-optional-chaining" "^7.16.0" + "@babel/plugin-proposal-private-methods" "^7.16.0" + "@babel/plugin-proposal-private-property-in-object" "^7.16.0" + "@babel/plugin-proposal-unicode-property-regex" "^7.16.0" "@babel/plugin-syntax-async-generators" "^7.8.4" "@babel/plugin-syntax-class-properties" "^7.12.13" "@babel/plugin-syntax-class-static-block" "^7.14.5" @@ -1893,44 +1119,44 @@ "@babel/plugin-syntax-optional-chaining" "^7.8.3" "@babel/plugin-syntax-private-property-in-object" "^7.14.5" "@babel/plugin-syntax-top-level-await" "^7.14.5" - "@babel/plugin-transform-arrow-functions" "^7.14.5" - "@babel/plugin-transform-async-to-generator" "^7.14.5" - "@babel/plugin-transform-block-scoped-functions" "^7.14.5" - "@babel/plugin-transform-block-scoping" "^7.15.3" - "@babel/plugin-transform-classes" "^7.15.4" - "@babel/plugin-transform-computed-properties" "^7.14.5" - "@babel/plugin-transform-destructuring" "^7.14.7" - "@babel/plugin-transform-dotall-regex" "^7.14.5" - "@babel/plugin-transform-duplicate-keys" "^7.14.5" - "@babel/plugin-transform-exponentiation-operator" "^7.14.5" - "@babel/plugin-transform-for-of" "^7.15.4" - "@babel/plugin-transform-function-name" "^7.14.5" - "@babel/plugin-transform-literals" "^7.14.5" - "@babel/plugin-transform-member-expression-literals" "^7.14.5" - "@babel/plugin-transform-modules-amd" "^7.14.5" - "@babel/plugin-transform-modules-commonjs" "^7.15.4" - "@babel/plugin-transform-modules-systemjs" "^7.15.4" - "@babel/plugin-transform-modules-umd" "^7.14.5" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.14.9" - "@babel/plugin-transform-new-target" "^7.14.5" - "@babel/plugin-transform-object-super" "^7.14.5" - "@babel/plugin-transform-parameters" "^7.15.4" - "@babel/plugin-transform-property-literals" "^7.14.5" - "@babel/plugin-transform-regenerator" "^7.14.5" - "@babel/plugin-transform-reserved-words" "^7.14.5" - "@babel/plugin-transform-shorthand-properties" "^7.14.5" - "@babel/plugin-transform-spread" "^7.15.8" - "@babel/plugin-transform-sticky-regex" "^7.14.5" - "@babel/plugin-transform-template-literals" "^7.14.5" - "@babel/plugin-transform-typeof-symbol" "^7.14.5" - "@babel/plugin-transform-unicode-escapes" "^7.14.5" - "@babel/plugin-transform-unicode-regex" "^7.14.5" - "@babel/preset-modules" "^0.1.4" - "@babel/types" "^7.15.6" - babel-plugin-polyfill-corejs2 "^0.2.2" - babel-plugin-polyfill-corejs3 "^0.2.5" - babel-plugin-polyfill-regenerator "^0.2.2" - core-js-compat "^3.16.0" + "@babel/plugin-transform-arrow-functions" "^7.16.0" + "@babel/plugin-transform-async-to-generator" "^7.16.0" + "@babel/plugin-transform-block-scoped-functions" "^7.16.0" + "@babel/plugin-transform-block-scoping" "^7.16.0" + "@babel/plugin-transform-classes" "^7.16.0" + "@babel/plugin-transform-computed-properties" "^7.16.0" + "@babel/plugin-transform-destructuring" "^7.16.0" + "@babel/plugin-transform-dotall-regex" "^7.16.0" + "@babel/plugin-transform-duplicate-keys" "^7.16.0" + "@babel/plugin-transform-exponentiation-operator" "^7.16.0" + "@babel/plugin-transform-for-of" "^7.16.0" + "@babel/plugin-transform-function-name" "^7.16.0" + "@babel/plugin-transform-literals" "^7.16.0" + "@babel/plugin-transform-member-expression-literals" "^7.16.0" + "@babel/plugin-transform-modules-amd" "^7.16.0" + "@babel/plugin-transform-modules-commonjs" "^7.16.0" + "@babel/plugin-transform-modules-systemjs" "^7.16.0" + "@babel/plugin-transform-modules-umd" "^7.16.0" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.16.0" + "@babel/plugin-transform-new-target" "^7.16.0" + "@babel/plugin-transform-object-super" "^7.16.0" + "@babel/plugin-transform-parameters" "^7.16.0" + "@babel/plugin-transform-property-literals" "^7.16.0" + "@babel/plugin-transform-regenerator" "^7.16.0" + "@babel/plugin-transform-reserved-words" "^7.16.0" + "@babel/plugin-transform-shorthand-properties" "^7.16.0" + "@babel/plugin-transform-spread" "^7.16.0" + "@babel/plugin-transform-sticky-regex" "^7.16.0" + "@babel/plugin-transform-template-literals" "^7.16.0" + "@babel/plugin-transform-typeof-symbol" "^7.16.0" + "@babel/plugin-transform-unicode-escapes" "^7.16.0" + "@babel/plugin-transform-unicode-regex" "^7.16.0" + "@babel/preset-modules" "^0.1.5" + "@babel/types" "^7.16.0" + babel-plugin-polyfill-corejs2 "^0.2.3" + babel-plugin-polyfill-corejs3 "^0.3.0" + babel-plugin-polyfill-regenerator "^0.2.3" + core-js-compat "^3.19.0" semver "^6.3.0" "@babel/preset-flow@^7.12.1": @@ -1941,21 +1167,10 @@ "@babel/helper-plugin-utils" "^7.12.13" "@babel/plugin-transform-flow-strip-types" "^7.12.13" -"@babel/preset-modules@^0.1.3": - version "0.1.3" - resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.3.tgz#13242b53b5ef8c883c3cf7dddd55b36ce80fbc72" - integrity sha512-Ra3JXOHBq2xd56xSF7lMKXdjBn3T772Y1Wet3yWnkDly9zHvJki029tAFzvAAK5cf4YV3yoxuP61crYRol6SVg== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-proposal-unicode-property-regex" "^7.4.4" - "@babel/plugin-transform-dotall-regex" "^7.4.4" - "@babel/types" "^7.4.4" - esutils "^2.0.2" - -"@babel/preset-modules@^0.1.4": - version "0.1.4" - resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.4.tgz#362f2b68c662842970fdb5e254ffc8fc1c2e415e" - integrity sha512-J36NhwnfdzpmH41M1DrnkkgAqhZaqr/NBdPfQ677mLzlaXo+oDiv1deyCDtgAhz8p328otdob0Du7+xgHGZbKg== +"@babel/preset-modules@^0.1.5": + version "0.1.5" + resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.5.tgz#ef939d6e7f268827e1841638dc6ff95515e115d9" + integrity sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA== dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-proposal-unicode-property-regex" "^7.4.4" @@ -1974,62 +1189,42 @@ "@babel/plugin-transform-react-jsx-self" "^7.0.0" "@babel/plugin-transform-react-jsx-source" "^7.0.0" -"@babel/preset-react@^7.12.1": - version "7.12.10" - resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.12.10.tgz#4fed65f296cbb0f5fb09de6be8cddc85cc909be9" - integrity sha512-vtQNjaHRl4DUpp+t+g4wvTHsLQuye+n0H/wsXIZRn69oz/fvNC7gQ4IK73zGJBaxvHoxElDvnYCthMcT7uzFoQ== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-transform-react-display-name" "^7.12.1" - "@babel/plugin-transform-react-jsx" "^7.12.10" - "@babel/plugin-transform-react-jsx-development" "^7.12.7" - "@babel/plugin-transform-react-pure-annotations" "^7.12.1" - -"@babel/preset-react@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.14.5.tgz#0fbb769513f899c2c56f3a882fa79673c2d4ab3c" - integrity sha512-XFxBkjyObLvBaAvkx1Ie95Iaq4S/GUEIrejyrntQ/VCMKUYvKLoyKxOBzJ2kjA3b6rC9/KL6KXfDC2GqvLiNqQ== +"@babel/preset-react@^7.12.1", "@babel/preset-react@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.16.0.tgz#f71d3e8dff5218478011df037fad52660ee6d82a" + integrity sha512-d31IFW2bLRB28uL1WoElyro8RH5l6531XfxMtCeCmp6RVAF1uTfxxUA0LH1tXl+psZdwfmIbwoG4U5VwgbhtLw== dependencies: "@babel/helper-plugin-utils" "^7.14.5" "@babel/helper-validator-option" "^7.14.5" - "@babel/plugin-transform-react-display-name" "^7.14.5" - "@babel/plugin-transform-react-jsx" "^7.14.5" - "@babel/plugin-transform-react-jsx-development" "^7.14.5" - "@babel/plugin-transform-react-pure-annotations" "^7.14.5" + "@babel/plugin-transform-react-display-name" "^7.16.0" + "@babel/plugin-transform-react-jsx" "^7.16.0" + "@babel/plugin-transform-react-jsx-development" "^7.16.0" + "@babel/plugin-transform-react-pure-annotations" "^7.16.0" -"@babel/preset-typescript@^7.12.1": - version "7.12.7" - resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.12.7.tgz#fc7df8199d6aae747896f1e6c61fc872056632a3" - integrity sha512-nOoIqIqBmHBSEgBXWR4Dv/XBehtIFcw9PqZw6rFYuKrzsZmOQm3PR5siLBnKZFEsDb03IegG8nSjU/iXXXYRmw== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/helper-validator-option" "^7.12.1" - "@babel/plugin-transform-typescript" "^7.12.1" - -"@babel/preset-typescript@^7.15.0": - version "7.15.0" - resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.15.0.tgz#e8fca638a1a0f64f14e1119f7fe4500277840945" - integrity sha512-lt0Y/8V3y06Wq/8H/u0WakrqciZ7Fz7mwPDHWUJAXlABL5hiUG42BNlRXiELNjeWjO5rWmnNKlx+yzJvxezHow== +"@babel/preset-typescript@^7.12.1", "@babel/preset-typescript@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.16.0.tgz#b0b4f105b855fb3d631ec036cdc9d1ffd1fa5eac" + integrity sha512-txegdrZYgO9DlPbv+9QOVpMnKbOtezsLHWsnsRF4AjbSIsVaujrq1qg8HK0mxQpWv0jnejt0yEoW1uWpvbrDTg== dependencies: "@babel/helper-plugin-utils" "^7.14.5" "@babel/helper-validator-option" "^7.14.5" - "@babel/plugin-transform-typescript" "^7.15.0" + "@babel/plugin-transform-typescript" "^7.16.0" "@babel/register@^7.12.1": - version "7.12.10" - resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.12.10.tgz#19b87143f17128af4dbe7af54c735663b3999f60" - integrity sha512-EvX/BvMMJRAA3jZgILWgbsrHwBQvllC5T8B29McyME8DvkdOxk4ujESfrMvME8IHSDvWXrmMXxPvA/lx2gqPLQ== + version "7.15.3" + resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.15.3.tgz#6b40a549e06ec06c885b2ec42c3dd711f55fe752" + integrity sha512-mj4IY1ZJkorClxKTImccn4T81+UKTo4Ux0+OFSV9hME1ooqS9UV+pJ6BjD0qXPK4T3XW/KNa79XByjeEMZz+fw== dependencies: + clone-deep "^4.0.1" find-cache-dir "^2.0.0" - lodash "^4.17.19" make-dir "^2.1.0" pirates "^4.0.0" source-map-support "^0.5.16" -"@babel/register@^7.15.3": - version "7.15.3" - resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.15.3.tgz#6b40a549e06ec06c885b2ec42c3dd711f55fe752" - integrity sha512-mj4IY1ZJkorClxKTImccn4T81+UKTo4Ux0+OFSV9hME1ooqS9UV+pJ6BjD0qXPK4T3XW/KNa79XByjeEMZz+fw== +"@babel/register@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.16.0.tgz#f5d2aa14df37cf7146b9759f7c53818360f24ec6" + integrity sha512-lzl4yfs0zVXnooeLE0AAfYaT7F3SPA8yB2Bj4W1BiZwLbMS3MZH35ZvCWSRHvneUugwuM+Wsnrj7h0F7UmU3NQ== dependencies: clone-deep "^4.0.1" find-cache-dir "^2.0.0" @@ -2059,74 +1254,43 @@ dependencies: regenerator-runtime "^0.12.0" -"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.14.0", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.2", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.14.5.tgz#665450911c6031af38f81db530f387ec04cd9a98" - integrity sha512-121rumjddw9c3NCQ55KGkyE1h/nzWhU/owjhw0l4mQrkzz4x9SGS1X8gFLraHwX7td3Yo4QTL+qj0NcIzN87BA== +"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.14.0", "@babel/runtime@^7.16.3", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.2", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": + version "7.16.3" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.16.3.tgz#b86f0db02a04187a3c17caa77de69840165d42d5" + integrity sha512-WBwekcqacdY2e9AF/Q7WLFUWmdJGJTkbjqTjoMDgXkVZ3ZRUvOPsLb5KdwISoQVsbP+DQzVZW4Zhci0DvpbNTQ== dependencies: regenerator-runtime "^0.13.4" -"@babel/runtime@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.15.4.tgz#fd17d16bfdf878e6dd02d19753a39fa8a8d9c84a" - integrity sha512-99catp6bHCaxr4sJ/DbTGgHS4+Rs2RVd2g7iOap6SLGPDknRK9ztKNsE/Fg6QhSeh1FGE5f6gHGQmvvn3I3xhw== - dependencies: - regenerator-runtime "^0.13.4" - -"@babel/template@^7.10.4", "@babel/template@^7.12.13", "@babel/template@^7.12.7", "@babel/template@^7.3.3", "@babel/template@^7.4.4": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.12.13.tgz#530265be8a2589dbb37523844c5bcb55947fb327" - integrity sha512-/7xxiGA57xMo/P2GVvdEumr8ONhFOhfgq2ihK3h1e6THqzTAkHbkXgB0xI9yeTfIUoH3+oAeHhqm/I43OTbbjA== - dependencies: - "@babel/code-frame" "^7.12.13" - "@babel/parser" "^7.12.13" - "@babel/types" "^7.12.13" - -"@babel/template@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.15.4.tgz#51898d35dcf3faa670c4ee6afcfd517ee139f194" - integrity sha512-UgBAfEa1oGuYgDIPM2G+aHa4Nlo9Lh6mGD2bDBGMTbYnc38vulXPuC1MGjYILIEmlwl6Rd+BPR9ee3gm20CBtg== - dependencies: - "@babel/code-frame" "^7.14.5" - "@babel/parser" "^7.15.4" - "@babel/types" "^7.15.4" - -"@babel/traverse@^7.1.0", "@babel/traverse@^7.10.4", "@babel/traverse@^7.12.1", "@babel/traverse@^7.12.10", "@babel/traverse@^7.12.5", "@babel/traverse@^7.12.9", "@babel/traverse@^7.13.0", "@babel/traverse@^7.4.5": - version "7.13.0" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.13.0.tgz#6d95752475f86ee7ded06536de309a65fc8966cc" - integrity sha512-xys5xi5JEhzC3RzEmSGrs/b3pJW/o87SypZ+G/PhaE7uqVQNv/jlmVIBXuoh5atqQ434LfXV+sf23Oxj0bchJQ== - dependencies: - "@babel/code-frame" "^7.12.13" - "@babel/generator" "^7.13.0" - "@babel/helper-function-name" "^7.12.13" - "@babel/helper-split-export-declaration" "^7.12.13" - "@babel/parser" "^7.13.0" - "@babel/types" "^7.13.0" - debug "^4.1.0" - globals "^11.1.0" - lodash "^4.17.19" - -"@babel/traverse@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.15.4.tgz#ff8510367a144bfbff552d9e18e28f3e2889c22d" - integrity sha512-W6lQD8l4rUbQR/vYgSuCAE75ADyyQvOpFVsvPPdkhf6lATXAsQIG9YdtOcu8BB1dZ0LKu+Zo3c1wEcbKeuhdlA== - dependencies: - "@babel/code-frame" "^7.14.5" - "@babel/generator" "^7.15.4" - "@babel/helper-function-name" "^7.15.4" - "@babel/helper-hoist-variables" "^7.15.4" - "@babel/helper-split-export-declaration" "^7.15.4" - "@babel/parser" "^7.15.4" - "@babel/types" "^7.15.4" +"@babel/template@^7.12.7", "@babel/template@^7.16.0", "@babel/template@^7.3.3", "@babel/template@^7.4.4": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.16.0.tgz#d16a35ebf4cd74e202083356fab21dd89363ddd6" + integrity sha512-MnZdpFD/ZdYhXwiunMqqgyZyucaYsbL0IrjoGjaVhGilz+x8YB++kRfygSOIj1yOtWKPlx7NBp+9I1RQSgsd5A== + dependencies: + "@babel/code-frame" "^7.16.0" + "@babel/parser" "^7.16.0" + "@babel/types" "^7.16.0" + +"@babel/traverse@^7.1.0", "@babel/traverse@^7.12.9", "@babel/traverse@^7.13.0", "@babel/traverse@^7.16.0", "@babel/traverse@^7.16.3", "@babel/traverse@^7.4.5": + version "7.16.3" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.16.3.tgz#f63e8a938cc1b780f66d9ed3c54f532ca2d14787" + integrity sha512-eolumr1vVMjqevCpwVO99yN/LoGL0EyHiLO5I043aYQvwOJ9eR5UsZSClHVCzfhBduMAsSzgA/6AyqPjNayJag== + dependencies: + "@babel/code-frame" "^7.16.0" + "@babel/generator" "^7.16.0" + "@babel/helper-function-name" "^7.16.0" + "@babel/helper-hoist-variables" "^7.16.0" + "@babel/helper-split-export-declaration" "^7.16.0" + "@babel/parser" "^7.16.3" + "@babel/types" "^7.16.0" debug "^4.1.0" globals "^11.1.0" -"@babel/types@^7.0.0", "@babel/types@^7.10.4", "@babel/types@^7.10.5", "@babel/types@^7.12.1", "@babel/types@^7.12.10", "@babel/types@^7.12.11", "@babel/types@^7.12.12", "@babel/types@^7.12.13", "@babel/types@^7.12.5", "@babel/types@^7.12.7", "@babel/types@^7.13.0", "@babel/types@^7.13.12", "@babel/types@^7.14.5", "@babel/types@^7.14.9", "@babel/types@^7.15.4", "@babel/types@^7.15.6", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4": - version "7.15.6" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.15.6.tgz#99abdc48218b2881c058dd0a7ab05b99c9be758f" - integrity sha512-BPU+7QhqNjmWyDO0/vitH/CuhpV8ZmK1wpKva8nuyNF5MJfuRNWMc+hc14+u9xT93kvykMdncrJT19h74uB1Ig== +"@babel/types@^7.0.0", "@babel/types@^7.12.7", "@babel/types@^7.16.0", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.16.0.tgz#db3b313804f96aadd0b776c4823e127ad67289ba" + integrity sha512-PJgg/k3SdLsGb3hhisFvtLOw5ts113klrpLuIPtCJIU+BB24fqq6lf8RWqKJEjzqXR9AEH1rIb5XTqwBHB+kQg== dependencies: - "@babel/helper-validator-identifier" "^7.14.9" + "@babel/helper-validator-identifier" "^7.15.7" to-fast-properties "^2.0.0" "@base2/pretty-print-object@1.0.0": @@ -8934,6 +8098,17 @@ babel-plugin-istanbul@^6.0.0: istanbul-lib-instrument "^4.0.0" test-exclude "^6.0.0" +babel-plugin-istanbul@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz#fa88ec59232fd9b4e36dbbc540a8ec9a9b47da73" + integrity sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@istanbuljs/load-nyc-config" "^1.0.0" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-instrument "^5.0.4" + test-exclude "^6.0.0" + babel-plugin-jest-hoist@^26.6.2: version "26.6.2" resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-26.6.2.tgz#8185bd030348d254c6d7dd974355e6a28b21e62d" @@ -9032,29 +8207,29 @@ babel-plugin-named-asset-import@^0.3.1: resolved "https://registry.yarnpkg.com/babel-plugin-named-asset-import/-/babel-plugin-named-asset-import-0.3.3.tgz#9ba2f3ac4dc78b042651654f07e847adfe50667c" integrity sha512-1XDRysF4894BUdMChT+2HHbtJYiO7zx5Be7U6bT8dISy7OdyETMGIAQBMPQCsY1YRf0xcubwnKKaDr5bk15JTA== -babel-plugin-polyfill-corejs2@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.2.2.tgz#e9124785e6fd94f94b618a7954e5693053bf5327" - integrity sha512-kISrENsJ0z5dNPq5eRvcctITNHYXWOA4DUZRFYCz3jYCcvTb/A546LIddmoGNMVYg2U38OyFeNosQwI9ENTqIQ== +babel-plugin-polyfill-corejs2@^0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.2.3.tgz#6ed8e30981b062f8fe6aca8873a37ebcc8cc1c0f" + integrity sha512-NDZ0auNRzmAfE1oDDPW2JhzIMXUk+FFe2ICejmt5T4ocKgiQx3e0VCRx9NCAidcMtL2RUZaWtXnmjTCkx0tcbA== dependencies: "@babel/compat-data" "^7.13.11" - "@babel/helper-define-polyfill-provider" "^0.2.2" + "@babel/helper-define-polyfill-provider" "^0.2.4" semver "^6.1.1" -babel-plugin-polyfill-corejs3@^0.2.5: - version "0.2.5" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.2.5.tgz#2779846a16a1652244ae268b1e906ada107faf92" - integrity sha512-ninF5MQNwAX9Z7c9ED+H2pGt1mXdP4TqzlHKyPIYmJIYz0N+++uwdM7RnJukklhzJ54Q84vA4ZJkgs7lu5vqcw== +babel-plugin-polyfill-corejs3@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.3.0.tgz#fa7ca3d1ee9ddc6193600ffb632c9785d54918af" + integrity sha512-JLwi9vloVdXLjzACL80j24bG6/T1gYxwowG44dg6HN/7aTPdyPbJJidf6ajoA3RPHHtW0j9KMrSOLpIZpAnPpg== dependencies: - "@babel/helper-define-polyfill-provider" "^0.2.2" - core-js-compat "^3.16.2" + "@babel/helper-define-polyfill-provider" "^0.2.4" + core-js-compat "^3.18.0" -babel-plugin-polyfill-regenerator@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.2.2.tgz#b310c8d642acada348c1fa3b3e6ce0e851bee077" - integrity sha512-Goy5ghsc21HgPDFtzRkSirpZVW35meGoTmTOb2bxqdl60ghub4xOidgNTHaZfQ2FaxQsKmwvXtOAkcIS4SMBWg== +babel-plugin-polyfill-regenerator@^0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.2.3.tgz#2e9808f5027c4336c994992b48a4262580cb8d6d" + integrity sha512-JVE78oRZPKFIeUqFGrSORNzQnrDwZR16oiWeGM8ZyjBn2XAT5OjP+wXx5ESuo33nUsFUEJYjtklnsKbxW5L+7g== dependencies: - "@babel/helper-define-polyfill-provider" "^0.2.2" + "@babel/helper-define-polyfill-provider" "^0.2.4" babel-plugin-react-docgen@^4.2.1: version "4.2.1" @@ -9080,13 +8255,13 @@ babel-plugin-require-context-hook@^1.0.0: babel-plugin-syntax-jsx "^6.18.0" lodash "^4.17.11" -babel-plugin-styled-components@^1.13.2: - version "1.13.2" - resolved "https://registry.yarnpkg.com/babel-plugin-styled-components/-/babel-plugin-styled-components-1.13.2.tgz#ebe0e6deff51d7f93fceda1819e9b96aeb88278d" - integrity sha512-Vb1R3d4g+MUfPQPVDMCGjm3cDocJEUTR7Xq7QS95JWWeksN1wdFRYpD2kulDgI3Huuaf1CZd+NK4KQmqUFh5dA== +babel-plugin-styled-components@^1.13.3: + version "1.13.3" + resolved "https://registry.yarnpkg.com/babel-plugin-styled-components/-/babel-plugin-styled-components-1.13.3.tgz#1f1cb3927d4afa1e324695c78f690900e3d075bc" + integrity sha512-meGStRGv+VuKA/q0/jXxrPNWEm4LPfYIqxooDTdmh8kFsP/Ph7jJG5rUPwUPX3QHUvggwdbgdGpo88P/rRYsVw== dependencies: - "@babel/helper-annotate-as-pure" "^7.0.0" - "@babel/helper-module-imports" "^7.0.0" + "@babel/helper-annotate-as-pure" "^7.15.4" + "@babel/helper-module-imports" "^7.15.4" babel-plugin-syntax-jsx "^6.18.0" lodash "^4.17.11" @@ -9845,7 +9020,7 @@ browserslist@4.14.2: escalade "^3.0.2" node-releases "^1.1.61" -browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.14.5, browserslist@^4.16.1, browserslist@^4.16.6, browserslist@^4.17.1, browserslist@^4.6.0, browserslist@^4.8.5: +browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.17.1, browserslist@^4.6.0, browserslist@^4.8.5: version "4.17.1" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.17.1.tgz#a98d104f54af441290b7d592626dd541fa642eb9" integrity sha512-aLD0ZMDSnF4lUt4ZDNgqi5BUn9BZ7YdQdI/cYlILrhdSSZJLU9aNZoD5/NBmM4SK34APB2e83MOsRt1EnkuyaQ== @@ -9856,6 +9031,17 @@ browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.14.5, browserslist@^4 nanocolors "^0.1.5" node-releases "^1.1.76" +browserslist@^4.17.5, browserslist@^4.17.6: + version "4.18.1" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.18.1.tgz#60d3920f25b6860eb917c6c7b185576f4d8b017f" + integrity sha512-8ScCzdpPwR2wQh8IT82CA2VgDwjHyqMovPBZSNH54+tm4Jk2pCuv90gmAdH6J84OCRWi0b4gMe6O6XPXuJnjgQ== + dependencies: + caniuse-lite "^1.0.30001280" + electron-to-chromium "^1.3.896" + escalade "^3.1.1" + node-releases "^2.0.1" + picocolors "^1.0.0" + bser@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/bser/-/bser-2.0.0.tgz#9ac78d3ed5d915804fd87acb158bc797147a1719" @@ -10188,10 +9374,10 @@ caniuse-api@^3.0.0: lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001097, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001125, caniuse-lite@^1.0.30001259: - version "1.0.30001261" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001261.tgz#96d89813c076ea061209a4e040d8dcf0c66a1d01" - integrity sha512-vM8D9Uvp7bHIN0fZ2KQ4wnmYFpJo/Etb4Vwsuc+ka0tfGDHvOPrFm6S/7CCNLSOkAUjenT2HnUPESdOIL91FaA== +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001097, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001125, caniuse-lite@^1.0.30001259, caniuse-lite@^1.0.30001280: + version "1.0.30001280" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001280.tgz#066a506046ba4be34cde5f74a08db7a396718fb7" + integrity sha512-kFXwYvHe5rix25uwueBxC569o53J6TpnGu0BEEn+6Lhl2vsnAumRFWEBhDft1fwyo6m1r4i+RqA4+163FpeFcA== capture-exit@^2.0.0: version "2.0.0" @@ -11238,7 +10424,7 @@ core-js-compat@^3.1.1: browserslist "^4.8.5" semver "7.0.0" -core-js-compat@^3.16.0, core-js-compat@^3.16.2: +core-js-compat@^3.18.0: version "3.18.1" resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.18.1.tgz#01942a0877caf9c6e5007c027183cf0bdae6a191" integrity sha512-XJMYx58zo4W0kLPmIingVZA10+7TuKrMLPt83+EzDmxFJQUMcTVVmQ+n5JP4r6Z14qSzhQBRi3NSWoeVyKKXUg== @@ -11246,12 +10432,12 @@ core-js-compat@^3.16.0, core-js-compat@^3.16.2: browserslist "^4.17.1" semver "7.0.0" -core-js-compat@^3.8.0: - version "3.8.3" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.8.3.tgz#9123fb6b9cad30f0651332dc77deba48ef9b0b3f" - integrity sha512-1sCb0wBXnBIL16pfFG1Gkvei6UzvKyTNYpiC41yrdjEv0UoJoq9E/abTMzyYJ6JpTkAj15dLjbqifIzEBDVvog== +core-js-compat@^3.19.0: + version "3.19.1" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.19.1.tgz#fe598f1a9bf37310d77c3813968e9f7c7bb99476" + integrity sha512-Q/VJ7jAF/y68+aUsQJ/afPOewdsGkDtcMb40J8MbuWKlK3Y+wtHq8bTHKPj2WKWLIqmS5JhHs4CzHtz6pT2W6g== dependencies: - browserslist "^4.16.1" + browserslist "^4.17.6" semver "7.0.0" core-js-pure@^3.0.0, core-js-pure@^3.0.1: @@ -13316,6 +12502,11 @@ electron-to-chromium@^1.3.846: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.853.tgz#f3ed1d31f092cb3a17af188bca6c6a3ec91c3e82" integrity sha512-W4U8n+U8I5/SUaFcqZgbKRmYZwcyEIQVBDf+j5QQK6xChjXnQD+wj248eGR9X4u+dDmDR//8vIfbu4PrdBBIoQ== +electron-to-chromium@^1.3.896: + version "1.3.899" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.899.tgz#4d7d040e73def3d5f5bd6b8a21049025dce6fce0" + integrity sha512-w16Dtd2zl7VZ4N4Db+FIa7n36sgPGCKjrKvUUmp5ialsikvcQLjcJR9RWnlYNxIyEHLdHaoIZEqKsPxU9MdyBg== + elegant-spinner@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/elegant-spinner/-/elegant-spinner-1.0.1.tgz#db043521c95d7e303fd8f345bedc3349cfb0729e" @@ -17813,6 +17004,11 @@ istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.0.0-alpha.1: resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz#f5944a37c70b550b02a78a5c3b2055b280cec8ec" integrity sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg== +istanbul-lib-coverage@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz#189e7909d0a39fa5a3dfad5b03f71947770191d3" + integrity sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw== + istanbul-lib-hook@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz#8f84c9434888cc6b1d0a9d7092a76d239ebf0cc6" @@ -17843,6 +17039,17 @@ istanbul-lib-instrument@^4.0.0, istanbul-lib-instrument@^4.0.3: istanbul-lib-coverage "^3.0.0" semver "^6.3.0" +istanbul-lib-instrument@^5.0.4: + version "5.1.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.1.0.tgz#7b49198b657b27a730b8e9cb601f1e1bff24c59a" + integrity sha512-czwUz525rkOFDJxfKK6mYfIs9zBKILyrZQxjz3ABhjQXhbhFsSbo1HW/BFcsDnfJYJWA6thRR5/TUY2qs5W99Q== + dependencies: + "@babel/core" "^7.12.3" + "@babel/parser" "^7.14.7" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-coverage "^3.2.0" + semver "^6.3.0" + istanbul-lib-processinfo@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.2.tgz#e1426514662244b2f25df728e8fd1ba35fe53b9c" @@ -21228,6 +20435,11 @@ node-releases@^1.1.76: resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.76.tgz#df245b062b0cafbd5282ab6792f7dccc2d97f36e" integrity sha512-9/IECtNr8dXNmPWmFXepT0/7o5eolGesHUa3mtr0KlgnCvnZxwh2qensKL42JJY2vQKC3nIBXetFAqR+PW1CmA== +node-releases@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.1.tgz#3d1d395f204f1f2f29a54358b9fb678765ad2fc5" + integrity sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA== + node-sass@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-6.0.1.tgz#cad1ccd0ce63e35c7181f545d8b986f3a9a887fe" @@ -22458,6 +21670,11 @@ phin@^2.9.1: resolved "https://registry.yarnpkg.com/phin/-/phin-2.9.3.tgz#f9b6ac10a035636fb65dfc576aaaa17b8743125c" integrity sha512-CzFr90qM24ju5f88quFC/6qohjC144rehe5n6DH900lgXmUe86+xCKc10ev56gRKC4/BkHUoG4uSiQgBiIXwDA== +picocolors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" + integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== + picomatch@^2.0.4, picomatch@^2.2.1: version "2.2.2" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" From 96ec161569d7227a34b67e2ef5479f302e170f81 Mon Sep 17 00:00:00 2001 From: Spencer Date: Tue, 16 Nov 2021 15:41:59 -0800 Subject: [PATCH 057/148] [kbn/pm] sort package.json in bootstrap (#118805) --- .buildkite/scripts/common/util.sh | 2 + package.json | 47 +- packages/kbn-pm/dist/index.js | 2640 ++++++++++------- packages/kbn-pm/src/commands/bootstrap.ts | 3 + .../kbn-pm/src/utils/sort_package_json.ts | 47 + yarn.lock | 53 +- 6 files changed, 1766 insertions(+), 1026 deletions(-) create mode 100644 packages/kbn-pm/src/utils/sort_package_json.ts diff --git a/.buildkite/scripts/common/util.sh b/.buildkite/scripts/common/util.sh index 0e5fb1c40eb6f..4a81506200cfa 100755 --- a/.buildkite/scripts/common/util.sh +++ b/.buildkite/scripts/common/util.sh @@ -16,12 +16,14 @@ is_pr() { verify_no_git_changes() { RED='\033[0;31m' + YELLOW='\033[0;33m' C_RESET='\033[0m' # Reset color GIT_CHANGES="$(git ls-files --modified -- . ':!:.bazelrc')" if [ "$GIT_CHANGES" ]; then echo -e "\n${RED}ERROR: '$1' caused changes to the following files:${C_RESET}\n" echo -e "$GIT_CHANGES\n" + echo -e "\n${YELLOW}TO FIX: Run '$1' locally, commit the changes and push to your branch${C_RESET}\n" exit 1 fi } diff --git a/package.json b/package.json index fcc4b773dddad..70cd6aba11c2a 100644 --- a/package.json +++ b/package.json @@ -37,44 +37,47 @@ }, "author": "Rashid Khan ", "scripts": { + "backport-skip-ci": "backport --prDescription \"[skip-ci]\"", "bazel": "bazel", - "preinstall": "node ./preinstall_check", - "kbn": "node scripts/kbn", - "es": "node scripts/es", - "test:jest": "node scripts/jest", - "test:jest_integration": "node scripts/jest_integration", - "test:ftr": "node scripts/functional_tests", - "test:ftr:server": "node scripts/functional_tests_server", - "test:ftr:runner": "node scripts/functional_test_runner", - "checkLicenses": "node scripts/check_licenses --dev", "build": "node scripts/build --all-platforms", "build:apidocs": "node scripts/build_api_docs", - "start": "node scripts/kibana --dev", + "build:types": "rm -rf ./target/types && tsc --p tsconfig.types.json", + "checkLicenses": "node scripts/check_licenses --dev", + "cover:functional:merge": "nyc report --temp-dir target/kibana-coverage/functional --report-dir target/coverage/report/functional --reporter=json-summary", + "cover:report": "nyc report --temp-dir target/kibana-coverage/functional --report-dir target/coverage/report --reporter=lcov && open ./target/coverage/report/lcov-report/index.html", "debug": "node --nolazy --inspect scripts/kibana --dev", "debug-break": "node --nolazy --inspect-brk scripts/kibana --dev", + "docs:acceptApiChanges": "node --max-old-space-size=6144 scripts/check_published_api_changes.js --accept", + "es": "node scripts/es", + "preinstall": "node ./preinstall_check", + "postinstall": "node scripts/kbn patch_native_modules", + "kbn": "node scripts/kbn", "lint": "yarn run lint:es && yarn run lint:style", "lint:es": "node scripts/eslint", "lint:style": "node scripts/stylelint", "makelogs": "node scripts/makelogs", - "build:types": "rm -rf ./target/types && tsc --p tsconfig.types.json", - "docs:acceptApiChanges": "node --max-old-space-size=6144 scripts/check_published_api_changes.js --accept", "spec_to_console": "node scripts/spec_to_console", - "backport-skip-ci": "backport --prDescription \"[skip-ci]\"", + "start": "node scripts/kibana --dev", "storybook": "node scripts/storybook", - "cover:report": "nyc report --temp-dir target/kibana-coverage/functional --report-dir target/coverage/report --reporter=lcov && open ./target/coverage/report/lcov-report/index.html", - "cover:functional:merge": "nyc report --temp-dir target/kibana-coverage/functional --report-dir target/coverage/report/functional --reporter=json-summary", - "postinstall": "node scripts/kbn patch_native_modules" + "test:ftr": "node scripts/functional_tests", + "test:ftr:runner": "node scripts/functional_test_runner", + "test:ftr:server": "node scripts/functional_tests_server", + "test:jest": "node scripts/jest", + "test:jest_integration": "node scripts/jest_integration" }, "repository": { "type": "git", "url": "https://github.com/elastic/kibana.git" }, + "engines": { + "node": "16.13.0", + "yarn": "^1.21.1" + }, "resolutions": { "**/@types/node": "16.10.2", "**/chokidar": "^3.4.3", "**/deepmerge": "^4.2.2", "**/fast-deep-equal": "^3.1.1", - "globby/fast-glob": "3.2.5", "**/hoist-non-react-statics": "^3.3.2", "**/isomorphic-fetch/node-fetch": "^2.6.1", "**/istanbul-instrumenter-loader/schema-utils": "1.0.0", @@ -85,11 +88,8 @@ "**/react-syntax-highlighter/**/highlight.js": "^10.4.1", "**/trim": "1.0.1", "**/typescript": "4.1.3", - "**/underscore": "^1.13.1" - }, - "engines": { - "node": "16.13.0", - "yarn": "^1.21.1" + "**/underscore": "^1.13.1", + "globby/fast-glob": "3.2.5" }, "dependencies": { "@babel/runtime": "^7.16.3", @@ -792,6 +792,7 @@ "shelljs": "^0.8.4", "simple-git": "1.116.0", "sinon": "^7.4.2", + "sort-package-json": "^1.53.1", "spawn-sync": "^1.0.15", "string-replace-loader": "^2.2.0", "strong-log-transformer": "^2.1.0", @@ -828,4 +829,4 @@ "yargs": "^15.4.1", "zlib": "^1.0.5" } -} +} \ No newline at end of file diff --git a/packages/kbn-pm/dist/index.js b/packages/kbn-pm/dist/index.js index e73f46a0504a6..ab8b9766f28d0 100644 --- a/packages/kbn-pm/dist/index.js +++ b/packages/kbn-pm/dist/index.js @@ -94,7 +94,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var _cli__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "run", function() { return _cli__WEBPACK_IMPORTED_MODULE_0__["run"]; }); -/* harmony import */ var _production__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(561); +/* harmony import */ var _production__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(569); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "buildBazelProductionProjects", function() { return _production__WEBPACK_IMPORTED_MODULE_1__["buildBazelProductionProjects"]; }); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "buildNonBazelProductionProjects", function() { return _production__WEBPACK_IMPORTED_MODULE_1__["buildNonBazelProductionProjects"]; }); @@ -108,7 +108,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var _utils_package_json__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(349); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "transformDependencies", function() { return _utils_package_json__WEBPACK_IMPORTED_MODULE_4__["transformDependencies"]; }); -/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(560); +/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(568); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "getProjectPaths", function() { return _config__WEBPACK_IMPORTED_MODULE_5__["getProjectPaths"]; }); /* @@ -141,7 +141,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var _kbn_dev_utils_tooling_log__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(5); /* harmony import */ var _kbn_dev_utils_tooling_log__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_kbn_dev_utils_tooling_log__WEBPACK_IMPORTED_MODULE_3__); /* harmony import */ var _commands__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(129); -/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(555); +/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(563); /* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(220); /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one @@ -8811,12 +8811,12 @@ exports.ToolingLogCollectingWriter = ToolingLogCollectingWriter; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "commands", function() { return commands; }); /* harmony import */ var _bootstrap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(130); -/* harmony import */ var _build__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(525); -/* harmony import */ var _clean__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(526); -/* harmony import */ var _reset__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(550); -/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(551); -/* harmony import */ var _watch__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(553); -/* harmony import */ var _patch_native_modules__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(554); +/* harmony import */ var _build__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(533); +/* harmony import */ var _clean__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(534); +/* harmony import */ var _reset__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(558); +/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(559); +/* harmony import */ var _watch__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(561); +/* harmony import */ var _patch_native_modules__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(562); /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License @@ -8857,8 +8857,9 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var _utils_link_project_executables__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(230); /* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(346); /* harmony import */ var _utils_yarn_lock__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(414); -/* harmony import */ var _utils_validate_dependencies__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(417); -/* harmony import */ var _utils_bazel__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(419); +/* harmony import */ var _utils_sort_package_json__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(417); +/* harmony import */ var _utils_validate_dependencies__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(425); +/* harmony import */ var _utils_bazel__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(427); function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } @@ -8881,6 +8882,7 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.definePrope + const BootstrapCommand = { description: 'Install dependencies and crosslink projects', name: 'bootstrap', @@ -8905,12 +8907,12 @@ const BootstrapCommand = { // if the `.yarn-integrity` file is not found which // will be indicated by the return of yarnIntegrityFileExists. - const forceInstall = !!options && options['force-install'] === true || !(await Object(_utils_bazel__WEBPACK_IMPORTED_MODULE_8__["yarnIntegrityFileExists"])(Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(kibanaProjectPath, 'node_modules'))); // Ensure we have a `node_modules/.yarn-integrity` file as we depend on it + const forceInstall = !!options && options['force-install'] === true || !(await Object(_utils_bazel__WEBPACK_IMPORTED_MODULE_9__["yarnIntegrityFileExists"])(Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(kibanaProjectPath, 'node_modules'))); // Ensure we have a `node_modules/.yarn-integrity` file as we depend on it // for bazel to know it has to re-install the node_modules after a reset or a clean - await Object(_utils_bazel__WEBPACK_IMPORTED_MODULE_8__["ensureYarnIntegrityFileExists"])(Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(kibanaProjectPath, 'node_modules')); // Install bazel machinery tools if needed + await Object(_utils_bazel__WEBPACK_IMPORTED_MODULE_9__["ensureYarnIntegrityFileExists"])(Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(kibanaProjectPath, 'node_modules')); // Install bazel machinery tools if needed - await Object(_utils_bazel__WEBPACK_IMPORTED_MODULE_8__["installBazelTools"])(rootPath); // Bootstrap process for Bazel packages + await Object(_utils_bazel__WEBPACK_IMPORTED_MODULE_9__["installBazelTools"])(rootPath); // Bootstrap process for Bazel packages // Bazel is now managing dependencies so yarn install // will happen as part of this // @@ -8922,7 +8924,7 @@ const BootstrapCommand = { if (forceInstall) { const forceInstallStartTime = Date.now(); - await Object(_utils_bazel__WEBPACK_IMPORTED_MODULE_8__["runBazel"])(['run', '@nodejs//:yarn'], runOffline); + await Object(_utils_bazel__WEBPACK_IMPORTED_MODULE_9__["runBazel"])(['run', '@nodejs//:yarn'], runOffline); timings.push({ id: 'force install dependencies', ms: Date.now() - forceInstallStartTime @@ -8931,7 +8933,7 @@ const BootstrapCommand = { const packageStartTime = Date.now(); - await Object(_utils_bazel__WEBPACK_IMPORTED_MODULE_8__["runBazel"])(['build', '//packages:build', '--show_result=1'], runOffline); + await Object(_utils_bazel__WEBPACK_IMPORTED_MODULE_9__["runBazel"])(['build', '//packages:build', '--show_result=1'], runOffline); timings.push({ id: 'build packages', ms: Date.now() - packageStartTime @@ -8956,10 +8958,11 @@ const BootstrapCommand = { } } + await Object(_utils_sort_package_json__WEBPACK_IMPORTED_MODULE_7__["sortPackageJson"])(kbn); const yarnLock = await Object(_utils_yarn_lock__WEBPACK_IMPORTED_MODULE_6__["readYarnLock"])(kbn); if (options.validate) { - await Object(_utils_validate_dependencies__WEBPACK_IMPORTED_MODULE_7__["validateDependencies"])(kbn, yarnLock); + await Object(_utils_validate_dependencies__WEBPACK_IMPORTED_MODULE_8__["validateDependencies"])(kbn, yarnLock); } // Assure all kbn projects with bin defined scripts // copy those scripts into the top level node_modules folder // @@ -53490,6 +53493,649 @@ module.exports = require("buffer"); /* 417 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "sortPackageJson", function() { return sortPackageJson; }); +/* harmony import */ var fs_promises__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(418); +/* harmony import */ var fs_promises__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(fs_promises__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var sort_package_json__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(419); +/* harmony import */ var sort_package_json__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(sort_package_json__WEBPACK_IMPORTED_MODULE_1__); +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + + +async function sortPackageJson(kbn) { + const packageJsonPath = kbn.getAbsolute('package.json'); + const packageJson = await fs_promises__WEBPACK_IMPORTED_MODULE_0___default.a.readFile(packageJsonPath, 'utf-8'); + await fs_promises__WEBPACK_IMPORTED_MODULE_0___default.a.writeFile(packageJsonPath, JSON.stringify(sort_package_json__WEBPACK_IMPORTED_MODULE_1___default()(JSON.parse(packageJson), { + // top level keys in the order they were written when this was implemented + sortOrder: ['name', 'description', 'keywords', 'private', 'version', 'branch', 'types', 'tsdocMetadata', 'build', 'homepage', 'bugs', 'kibana', 'author', 'scripts', 'repository', 'engines', 'resolutions'] + }), null, 2)); +} + +/***/ }), +/* 418 */ +/***/ (function(module, exports) { + +module.exports = require("fs/promises"); + +/***/ }), +/* 419 */ +/***/ (function(module, exports, __webpack_require__) { + +const sortObjectKeys = __webpack_require__(420) +const detectIndent = __webpack_require__(421) +const detectNewline = __webpack_require__(422).graceful +const gitHooks = __webpack_require__(423) +const isPlainObject = __webpack_require__(424) + +const hasOwnProperty = (object, property) => + Object.prototype.hasOwnProperty.call(object, property) +const pipe = (fns) => (x, ...args) => + fns.reduce((result, fn) => fn(result, ...args), x) +const onArray = (fn) => (x) => (Array.isArray(x) ? fn(x) : x) +const onStringArray = (fn) => (x) => + Array.isArray(x) && x.every((item) => typeof item === 'string') ? fn(x) : x +const uniq = onStringArray((xs) => xs.filter((x, i) => i === xs.indexOf(x))) +const sortArray = onStringArray((array) => [...array].sort()) +const uniqAndSortArray = pipe([uniq, sortArray]) +const onObject = (fn) => (x, ...args) => (isPlainObject(x) ? fn(x, ...args) : x) +const sortObjectBy = (comparator, deep) => { + const over = onObject((object) => { + object = sortObjectKeys(object, comparator) + if (deep) { + for (const [key, value] of Object.entries(object)) { + object[key] = over(value) + } + } + return object + }) + + return over +} +const sortObject = sortObjectBy() +const sortURLObject = sortObjectBy(['type', 'url']) +const sortPeopleObject = sortObjectBy(['name', 'email', 'url']) +const sortDirectories = sortObjectBy([ + 'lib', + 'bin', + 'man', + 'doc', + 'example', + 'test', +]) +const overProperty = (property, over) => (object, ...args) => + hasOwnProperty(object, property) + ? Object.assign(object, { [property]: over(object[property], ...args) }) + : object +const sortGitHooks = sortObjectBy(gitHooks) + +// https://github.com/eslint/eslint/blob/acc0e47572a9390292b4e313b4a4bf360d236358/conf/config-schema.js +const eslintBaseConfigProperties = [ + // `files` and `excludedFiles` are only on `overrides[]` + // for easier sort `overrides[]`, + // add them to here, so we don't need sort `overrides[]` twice + 'files', + 'excludedFiles', + // baseConfig + 'env', + 'parser', + 'parserOptions', + 'settings', + 'plugins', + 'extends', + 'rules', + 'overrides', + 'globals', + 'processor', + 'noInlineConfig', + 'reportUnusedDisableDirectives', +] +const sortEslintConfig = onObject( + pipe([ + sortObjectBy(eslintBaseConfigProperties), + overProperty('env', sortObject), + overProperty('globals', sortObject), + overProperty( + 'overrides', + onArray((overrides) => overrides.map(sortEslintConfig)), + ), + overProperty('parserOptions', sortObject), + overProperty( + 'rules', + sortObjectBy( + (rule1, rule2) => + rule1.split('/').length - rule2.split('/').length || + rule1.localeCompare(rule2), + ), + ), + overProperty('settings', sortObject), + ]), +) +const sortVSCodeBadgeObject = sortObjectBy(['description', 'url', 'href']) + +const sortPrettierConfig = onObject( + pipe([ + // sort keys alphabetically, but put `overrides` at bottom + (config) => + sortObjectKeys(config, [ + ...Object.keys(config) + .filter((key) => key !== 'overrides') + .sort(), + 'overrides', + ]), + // if `config.overrides` exists + overProperty( + 'overrides', + // and `config.overrides` is an array + onArray((overrides) => + overrides.map( + pipe([ + // sort `config.overrides[]` alphabetically + sortObject, + // sort `config.overrides[].options` alphabetically + overProperty('options', sortObject), + ]), + ), + ), + ), + ]), +) + +// See https://docs.npmjs.com/misc/scripts +const defaultNpmScripts = new Set([ + 'install', + 'pack', + 'prepare', + 'publish', + 'restart', + 'shrinkwrap', + 'start', + 'stop', + 'test', + 'uninstall', + 'version', +]) + +const hasDevDependency = (dependency, packageJson) => { + return ( + 'devDependencies' in packageJson && + !!packageJson.devDependencies[dependency] + ) +} + +const sortScripts = onObject((scripts, packageJson) => { + const names = Object.keys(scripts) + const prefixable = new Set() + + const keys = names.map((name) => { + const omitted = name.replace(/^(?:pre|post)/, '') + if (defaultNpmScripts.has(omitted) || names.includes(omitted)) { + prefixable.add(omitted) + return omitted + } + return name + }) + + if (!hasDevDependency('npm-run-all', packageJson)) { + keys.sort() + } + + const order = keys.reduce( + (order, key) => + order.concat( + prefixable.has(key) ? [`pre${key}`, key, `post${key}`] : [key], + ), + [], + ) + + return sortObjectKeys(scripts, order) +}) + +// fields marked `vscode` are for `Visual Studio Code extension manifest` only +// https://code.visualstudio.com/api/references/extension-manifest +// Supported fields: +// publisher, displayName, categories, galleryBanner, preview, contributes, +// activationEvents, badges, markdown, qna, extensionPack, +// extensionDependencies, icon + +// field.key{string}: field name +// field.over{function}: sort field subKey +const fields = [ + { key: '$schema' }, + { key: 'name' }, + /* vscode */ { key: 'displayName' }, + { key: 'version' }, + { key: 'private' }, + { key: 'description' }, + /* vscode */ { key: 'categories', over: uniq }, + { key: 'keywords', over: uniq }, + { key: 'homepage' }, + { key: 'bugs', over: sortObjectBy(['url', 'email']) }, + { key: 'repository', over: sortURLObject }, + { key: 'funding', over: sortURLObject }, + { key: 'license', over: sortURLObject }, + /* vscode */ { key: 'qna' }, + { key: 'author', over: sortPeopleObject }, + { + key: 'maintainers', + over: onArray((maintainers) => maintainers.map(sortPeopleObject)), + }, + { + key: 'contributors', + over: onArray((contributors) => contributors.map(sortPeopleObject)), + }, + /* vscode */ { key: 'publisher' }, + { key: 'sideEffects' }, + { key: 'type' }, + { key: 'imports' }, + { key: 'exports' }, + { key: 'main' }, + { key: 'umd:main' }, + { key: 'jsdelivr' }, + { key: 'unpkg' }, + { key: 'module' }, + { key: 'source' }, + { key: 'jsnext:main' }, + { key: 'browser' }, + { key: 'types' }, + { key: 'typesVersions' }, + { key: 'typings' }, + { key: 'style' }, + { key: 'example' }, + { key: 'examplestyle' }, + { key: 'assets' }, + { key: 'bin', over: sortObject }, + { key: 'man' }, + { key: 'directories', over: sortDirectories }, + { key: 'files', over: uniq }, + { key: 'workspaces' }, + // node-pre-gyp https://www.npmjs.com/package/node-pre-gyp#1-add-new-entries-to-your-packagejson + { + key: 'binary', + over: sortObjectBy([ + 'module_name', + 'module_path', + 'remote_path', + 'package_name', + 'host', + ]), + }, + { key: 'scripts', over: sortScripts }, + { key: 'betterScripts', over: sortScripts }, + /* vscode */ { key: 'contributes', over: sortObject }, + /* vscode */ { key: 'activationEvents', over: uniq }, + { key: 'husky', over: overProperty('hooks', sortGitHooks) }, + { key: 'simple-git-hooks', over: sortGitHooks }, + { key: 'pre-commit' }, + { key: 'commitlint', over: sortObject }, + { key: 'lint-staged' }, + { key: 'config', over: sortObject }, + { key: 'nodemonConfig', over: sortObject }, + { key: 'browserify', over: sortObject }, + { key: 'babel', over: sortObject }, + { key: 'browserslist' }, + { key: 'xo', over: sortObject }, + { key: 'prettier', over: sortPrettierConfig }, + { key: 'eslintConfig', over: sortEslintConfig }, + { key: 'eslintIgnore' }, + { key: 'npmpkgjsonlint', over: sortObject }, + { key: 'npmPackageJsonLintConfig', over: sortObject }, + { key: 'npmpackagejsonlint', over: sortObject }, + { key: 'release', over: sortObject }, + { key: 'remarkConfig', over: sortObject }, + { key: 'stylelint' }, + { key: 'ava', over: sortObject }, + { key: 'jest', over: sortObject }, + { key: 'mocha', over: sortObject }, + { key: 'nyc', over: sortObject }, + { key: 'c8', over: sortObject }, + { key: 'tap', over: sortObject }, + { key: 'resolutions', over: sortObject }, + { key: 'dependencies', over: sortObject }, + { key: 'devDependencies', over: sortObject }, + { key: 'dependenciesMeta', over: sortObjectBy(undefined, true) }, + { key: 'peerDependencies', over: sortObject }, + // TODO: only sort depth = 2 + { key: 'peerDependenciesMeta', over: sortObjectBy(undefined, true) }, + { key: 'optionalDependencies', over: sortObject }, + { key: 'bundledDependencies', over: uniqAndSortArray }, + { key: 'bundleDependencies', over: uniqAndSortArray }, + /* vscode */ { key: 'extensionPack', over: uniqAndSortArray }, + /* vscode */ { key: 'extensionDependencies', over: uniqAndSortArray }, + { key: 'flat' }, + { key: 'engines', over: sortObject }, + { key: 'engineStrict', over: sortObject }, + { key: 'languageName' }, + { key: 'os' }, + { key: 'cpu' }, + { key: 'preferGlobal', over: sortObject }, + { key: 'publishConfig', over: sortObject }, + /* vscode */ { key: 'icon' }, + /* vscode */ { + key: 'badges', + over: onArray((badge) => badge.map(sortVSCodeBadgeObject)), + }, + /* vscode */ { key: 'galleryBanner', over: sortObject }, + /* vscode */ { key: 'preview' }, + /* vscode */ { key: 'markdown' }, +] + +const defaultSortOrder = fields.map(({ key }) => key) +const overFields = pipe( + fields.reduce((fns, { key, over }) => { + if (over) { + fns.push(overProperty(key, over)) + } + return fns + }, []), +) + +function editStringJSON(json, over) { + if (typeof json === 'string') { + const { indent } = detectIndent(json) + const endCharacters = json.slice(-1) === '\n' ? '\n' : '' + const newline = detectNewline(json) + json = JSON.parse(json) + + let result = JSON.stringify(over(json), null, indent) + endCharacters + if (newline === '\r\n') { + result = result.replace(/\n/g, newline) + } + return result + } + + return over(json) +} + +const isPrivateKey = (key) => key[0] === '_' +const partition = (array, predicate) => + array.reduce( + (result, value) => { + result[predicate(value) ? 0 : 1].push(value) + return result + }, + [[], []], + ) +function sortPackageJson(jsonIsh, options = {}) { + return editStringJSON( + jsonIsh, + onObject((json) => { + let sortOrder = options.sortOrder ? options.sortOrder : defaultSortOrder + + if (Array.isArray(sortOrder)) { + const keys = Object.keys(json) + const [privateKeys, publicKeys] = partition(keys, isPrivateKey) + sortOrder = [ + ...sortOrder, + ...defaultSortOrder, + ...publicKeys.sort(), + ...privateKeys.sort(), + ] + } + + return overFields(sortObjectKeys(json, sortOrder), json) + }), + ) +} + +module.exports = sortPackageJson +module.exports.sortPackageJson = sortPackageJson +module.exports.sortOrder = defaultSortOrder +module.exports.default = sortPackageJson + + +/***/ }), +/* 420 */ +/***/ (function(module, exports) { + +module.exports = function sortObjectByKeyNameList(object, sortWith) { + var keys; + var sortFn; + + if (typeof sortWith === 'function') { + sortFn = sortWith; + } else { + keys = sortWith; + } + + var objectKeys = Object.keys(object); + return (keys || []).concat(objectKeys.sort(sortFn)).reduce(function(total, key) { + if (objectKeys.indexOf(key) !== -1) { + total[key] = object[key]; + } + return total; + }, Object.create(null)); +} + + +/***/ }), +/* 421 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +// Detect either spaces or tabs but not both to properly handle tabs for indentation and spaces for alignment +const INDENT_REGEX = /^(?:( )+|\t+)/; + +const INDENT_TYPE_SPACE = 'space'; +const INDENT_TYPE_TAB = 'tab'; + +// Make a Map that counts how many indents/unindents have occurred for a given size and how many lines follow a given indentation. +// The key is a concatenation of the indentation type (s = space and t = tab) and the size of the indents/unindents. +// +// indents = { +// t3: [1, 0], +// t4: [1, 5], +// s5: [1, 0], +// s12: [1, 0], +// } +function makeIndentsMap(string, ignoreSingleSpaces) { + const indents = new Map(); + + // Remember the size of previous line's indentation + let previousSize = 0; + let previousIndentType; + + // Indents key (ident type + size of the indents/unindents) + let key; + + for (const line of string.split(/\n/g)) { + if (!line) { + // Ignore empty lines + continue; + } + + let indent; + let indentType; + let weight; + let entry; + const matches = line.match(INDENT_REGEX); + + if (matches === null) { + previousSize = 0; + previousIndentType = ''; + } else { + indent = matches[0].length; + + if (matches[1]) { + indentType = INDENT_TYPE_SPACE; + } else { + indentType = INDENT_TYPE_TAB; + } + + // Ignore single space unless it's the only indent detected to prevent common false positives + if (ignoreSingleSpaces && indentType === INDENT_TYPE_SPACE && indent === 1) { + continue; + } + + if (indentType !== previousIndentType) { + previousSize = 0; + } + + previousIndentType = indentType; + + weight = 0; + + const indentDifference = indent - previousSize; + previousSize = indent; + + // Previous line have same indent? + if (indentDifference === 0) { + weight++; + // We use the key from previous loop + } else { + const absoluteIndentDifference = indentDifference > 0 ? indentDifference : -indentDifference; + key = encodeIndentsKey(indentType, absoluteIndentDifference); + } + + // Update the stats + entry = indents.get(key); + + if (entry === undefined) { + entry = [1, 0]; // Init + } else { + entry = [++entry[0], entry[1] + weight]; + } + + indents.set(key, entry); + } + } + + return indents; +} + +// Encode the indent type and amount as a string (e.g. 's4') for use as a compound key in the indents Map. +function encodeIndentsKey(indentType, indentAmount) { + const typeCharacter = indentType === INDENT_TYPE_SPACE ? 's' : 't'; + return typeCharacter + String(indentAmount); +} + +// Extract the indent type and amount from a key of the indents Map. +function decodeIndentsKey(indentsKey) { + const keyHasTypeSpace = indentsKey[0] === 's'; + const type = keyHasTypeSpace ? INDENT_TYPE_SPACE : INDENT_TYPE_TAB; + + const amount = Number(indentsKey.slice(1)); + + return {type, amount}; +} + +// Return the key (e.g. 's4') from the indents Map that represents the most common indent, +// or return undefined if there are no indents. +function getMostUsedKey(indents) { + let result; + let maxUsed = 0; + let maxWeight = 0; + + for (const [key, [usedCount, weight]] of indents) { + if (usedCount > maxUsed || (usedCount === maxUsed && weight > maxWeight)) { + maxUsed = usedCount; + maxWeight = weight; + result = key; + } + } + + return result; +} + +function makeIndentString(type, amount) { + const indentCharacter = type === INDENT_TYPE_SPACE ? ' ' : '\t'; + return indentCharacter.repeat(amount); +} + +module.exports = string => { + if (typeof string !== 'string') { + throw new TypeError('Expected a string'); + } + + // Identify indents while skipping single space indents to avoid common edge cases (e.g. code comments) + // If no indents are identified, run again and include all indents for comprehensive detection + let indents = makeIndentsMap(string, true); + if (indents.size === 0) { + indents = makeIndentsMap(string, false); + } + + const keyOfMostUsedIndent = getMostUsedKey(indents); + + let type; + let amount = 0; + let indent = ''; + + if (keyOfMostUsedIndent !== undefined) { + ({type, amount} = decodeIndentsKey(keyOfMostUsedIndent)); + indent = makeIndentString(type, amount); + } + + return { + amount, + type, + indent + }; +}; + + +/***/ }), +/* 422 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +const detectNewline = string => { + if (typeof string !== 'string') { + throw new TypeError('Expected a string'); + } + + const newlines = string.match(/(?:\r?\n)/g) || []; + + if (newlines.length === 0) { + return; + } + + const crlf = newlines.filter(newline => newline === '\r\n').length; + const lf = newlines.length - crlf; + + return crlf > lf ? '\r\n' : '\n'; +}; + +module.exports = detectNewline; +module.exports.graceful = string => (typeof string === 'string' && detectNewline(string)) || '\n'; + + +/***/ }), +/* 423 */ +/***/ (function(module) { + +module.exports = JSON.parse("[\"applypatch-msg\",\"pre-applypatch\",\"post-applypatch\",\"pre-commit\",\"pre-merge-commit\",\"prepare-commit-msg\",\"commit-msg\",\"post-commit\",\"pre-rebase\",\"post-checkout\",\"post-merge\",\"pre-push\",\"pre-receive\",\"update\",\"post-receive\",\"post-update\",\"push-to-checkout\",\"pre-auto-gc\",\"post-rewrite\",\"sendemail-validate\",\"fsmonitor-watchman\",\"p4-pre-submit\",\"post-index-change\"]"); + +/***/ }), +/* 424 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +module.exports = value => { + if (Object.prototype.toString.call(value) !== '[object Object]') { + return false; + } + + const prototype = Object.getPrototypeOf(value); + return prototype === null || prototype === Object.prototype; +}; + + +/***/ }), +/* 425 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "validateDependencies", function() { return validateDependencies; }); @@ -53504,7 +54150,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var _fs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(231); /* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(220); /* harmony import */ var _package_json__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(349); -/* harmony import */ var _projects_tree__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(418); +/* harmony import */ var _projects_tree__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(426); /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License @@ -53685,7 +54331,7 @@ function getDevOnlyProductionDepsTree(kbn, projectName) { } /***/ }), -/* 418 */ +/* 426 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -53827,27 +54473,27 @@ function addProjectToTree(tree, pathParts, project) { } /***/ }), -/* 419 */ +/* 427 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); -/* harmony import */ var _yarn_integrity__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(420); +/* harmony import */ var _yarn_integrity__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(428); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "yarnIntegrityFileExists", function() { return _yarn_integrity__WEBPACK_IMPORTED_MODULE_0__["yarnIntegrityFileExists"]; }); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "ensureYarnIntegrityFileExists", function() { return _yarn_integrity__WEBPACK_IMPORTED_MODULE_0__["ensureYarnIntegrityFileExists"]; }); -/* harmony import */ var _get_cache_folders__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(421); +/* harmony import */ var _get_cache_folders__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(429); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "getBazelDiskCacheFolder", function() { return _get_cache_folders__WEBPACK_IMPORTED_MODULE_1__["getBazelDiskCacheFolder"]; }); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "getBazelRepositoryCacheFolder", function() { return _get_cache_folders__WEBPACK_IMPORTED_MODULE_1__["getBazelRepositoryCacheFolder"]; }); -/* harmony import */ var _install_tools__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(422); +/* harmony import */ var _install_tools__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(430); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "isBazelBinAvailable", function() { return _install_tools__WEBPACK_IMPORTED_MODULE_2__["isBazelBinAvailable"]; }); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "installBazelTools", function() { return _install_tools__WEBPACK_IMPORTED_MODULE_2__["installBazelTools"]; }); -/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(423); +/* harmony import */ var _run__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(431); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "runBazel", function() { return _run__WEBPACK_IMPORTED_MODULE_3__["runBazel"]; }); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "runIBazel", function() { return _run__WEBPACK_IMPORTED_MODULE_3__["runIBazel"]; }); @@ -53865,7 +54511,7 @@ __webpack_require__.r(__webpack_exports__); /***/ }), -/* 420 */ +/* 428 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -53912,7 +54558,7 @@ async function ensureYarnIntegrityFileExists(nodeModulesPath) { } /***/ }), -/* 421 */ +/* 429 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -53949,7 +54595,7 @@ async function getBazelRepositoryCacheFolder() { } /***/ }), -/* 422 */ +/* 430 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -54068,7 +54714,7 @@ async function installBazelTools(repoRootPath) { } /***/ }), -/* 423 */ +/* 431 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -54078,8 +54724,8 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(114); /* harmony import */ var chalk__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(chalk__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var rxjs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(9); -/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(424); -/* harmony import */ var _kbn_dev_utils_stdio__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(522); +/* harmony import */ var rxjs_operators__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(432); +/* harmony import */ var _kbn_dev_utils_stdio__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(530); /* harmony import */ var _kbn_dev_utils_stdio__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_kbn_dev_utils_stdio__WEBPACK_IMPORTED_MODULE_3__); /* harmony import */ var _child_process__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(221); /* harmony import */ var _log__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(220); @@ -54145,141 +54791,141 @@ async function runIBazel(bazelArgs, offline = false, runOpts = {}) { } /***/ }), -/* 424 */ +/* 432 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); -/* harmony import */ var _internal_operators_audit__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(425); +/* harmony import */ var _internal_operators_audit__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(433); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "audit", function() { return _internal_operators_audit__WEBPACK_IMPORTED_MODULE_0__["audit"]; }); -/* harmony import */ var _internal_operators_auditTime__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(426); +/* harmony import */ var _internal_operators_auditTime__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(434); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "auditTime", function() { return _internal_operators_auditTime__WEBPACK_IMPORTED_MODULE_1__["auditTime"]; }); -/* harmony import */ var _internal_operators_buffer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(427); +/* harmony import */ var _internal_operators_buffer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(435); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "buffer", function() { return _internal_operators_buffer__WEBPACK_IMPORTED_MODULE_2__["buffer"]; }); -/* harmony import */ var _internal_operators_bufferCount__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(428); +/* harmony import */ var _internal_operators_bufferCount__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(436); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "bufferCount", function() { return _internal_operators_bufferCount__WEBPACK_IMPORTED_MODULE_3__["bufferCount"]; }); -/* harmony import */ var _internal_operators_bufferTime__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(429); +/* harmony import */ var _internal_operators_bufferTime__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(437); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "bufferTime", function() { return _internal_operators_bufferTime__WEBPACK_IMPORTED_MODULE_4__["bufferTime"]; }); -/* harmony import */ var _internal_operators_bufferToggle__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(430); +/* harmony import */ var _internal_operators_bufferToggle__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(438); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "bufferToggle", function() { return _internal_operators_bufferToggle__WEBPACK_IMPORTED_MODULE_5__["bufferToggle"]; }); -/* harmony import */ var _internal_operators_bufferWhen__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(431); +/* harmony import */ var _internal_operators_bufferWhen__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(439); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "bufferWhen", function() { return _internal_operators_bufferWhen__WEBPACK_IMPORTED_MODULE_6__["bufferWhen"]; }); -/* harmony import */ var _internal_operators_catchError__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(432); +/* harmony import */ var _internal_operators_catchError__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(440); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "catchError", function() { return _internal_operators_catchError__WEBPACK_IMPORTED_MODULE_7__["catchError"]; }); -/* harmony import */ var _internal_operators_combineAll__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(433); +/* harmony import */ var _internal_operators_combineAll__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(441); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "combineAll", function() { return _internal_operators_combineAll__WEBPACK_IMPORTED_MODULE_8__["combineAll"]; }); -/* harmony import */ var _internal_operators_combineLatest__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(434); +/* harmony import */ var _internal_operators_combineLatest__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(442); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "combineLatest", function() { return _internal_operators_combineLatest__WEBPACK_IMPORTED_MODULE_9__["combineLatest"]; }); -/* harmony import */ var _internal_operators_concat__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(435); +/* harmony import */ var _internal_operators_concat__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(443); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "concat", function() { return _internal_operators_concat__WEBPACK_IMPORTED_MODULE_10__["concat"]; }); /* harmony import */ var _internal_operators_concatAll__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(81); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "concatAll", function() { return _internal_operators_concatAll__WEBPACK_IMPORTED_MODULE_11__["concatAll"]; }); -/* harmony import */ var _internal_operators_concatMap__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(436); +/* harmony import */ var _internal_operators_concatMap__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(444); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "concatMap", function() { return _internal_operators_concatMap__WEBPACK_IMPORTED_MODULE_12__["concatMap"]; }); -/* harmony import */ var _internal_operators_concatMapTo__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(437); +/* harmony import */ var _internal_operators_concatMapTo__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(445); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "concatMapTo", function() { return _internal_operators_concatMapTo__WEBPACK_IMPORTED_MODULE_13__["concatMapTo"]; }); -/* harmony import */ var _internal_operators_count__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(438); +/* harmony import */ var _internal_operators_count__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(446); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "count", function() { return _internal_operators_count__WEBPACK_IMPORTED_MODULE_14__["count"]; }); -/* harmony import */ var _internal_operators_debounce__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(439); +/* harmony import */ var _internal_operators_debounce__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(447); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "debounce", function() { return _internal_operators_debounce__WEBPACK_IMPORTED_MODULE_15__["debounce"]; }); -/* harmony import */ var _internal_operators_debounceTime__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(440); +/* harmony import */ var _internal_operators_debounceTime__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(448); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "debounceTime", function() { return _internal_operators_debounceTime__WEBPACK_IMPORTED_MODULE_16__["debounceTime"]; }); -/* harmony import */ var _internal_operators_defaultIfEmpty__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(441); +/* harmony import */ var _internal_operators_defaultIfEmpty__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(449); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "defaultIfEmpty", function() { return _internal_operators_defaultIfEmpty__WEBPACK_IMPORTED_MODULE_17__["defaultIfEmpty"]; }); -/* harmony import */ var _internal_operators_delay__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(442); +/* harmony import */ var _internal_operators_delay__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(450); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "delay", function() { return _internal_operators_delay__WEBPACK_IMPORTED_MODULE_18__["delay"]; }); -/* harmony import */ var _internal_operators_delayWhen__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(444); +/* harmony import */ var _internal_operators_delayWhen__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(452); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "delayWhen", function() { return _internal_operators_delayWhen__WEBPACK_IMPORTED_MODULE_19__["delayWhen"]; }); -/* harmony import */ var _internal_operators_dematerialize__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(445); +/* harmony import */ var _internal_operators_dematerialize__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(453); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "dematerialize", function() { return _internal_operators_dematerialize__WEBPACK_IMPORTED_MODULE_20__["dematerialize"]; }); -/* harmony import */ var _internal_operators_distinct__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(446); +/* harmony import */ var _internal_operators_distinct__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(454); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "distinct", function() { return _internal_operators_distinct__WEBPACK_IMPORTED_MODULE_21__["distinct"]; }); -/* harmony import */ var _internal_operators_distinctUntilChanged__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(447); +/* harmony import */ var _internal_operators_distinctUntilChanged__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(455); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "distinctUntilChanged", function() { return _internal_operators_distinctUntilChanged__WEBPACK_IMPORTED_MODULE_22__["distinctUntilChanged"]; }); -/* harmony import */ var _internal_operators_distinctUntilKeyChanged__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(448); +/* harmony import */ var _internal_operators_distinctUntilKeyChanged__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(456); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "distinctUntilKeyChanged", function() { return _internal_operators_distinctUntilKeyChanged__WEBPACK_IMPORTED_MODULE_23__["distinctUntilKeyChanged"]; }); -/* harmony import */ var _internal_operators_elementAt__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(449); +/* harmony import */ var _internal_operators_elementAt__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(457); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "elementAt", function() { return _internal_operators_elementAt__WEBPACK_IMPORTED_MODULE_24__["elementAt"]; }); -/* harmony import */ var _internal_operators_endWith__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(452); +/* harmony import */ var _internal_operators_endWith__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(460); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "endWith", function() { return _internal_operators_endWith__WEBPACK_IMPORTED_MODULE_25__["endWith"]; }); -/* harmony import */ var _internal_operators_every__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(453); +/* harmony import */ var _internal_operators_every__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(461); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "every", function() { return _internal_operators_every__WEBPACK_IMPORTED_MODULE_26__["every"]; }); -/* harmony import */ var _internal_operators_exhaust__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(454); +/* harmony import */ var _internal_operators_exhaust__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(462); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "exhaust", function() { return _internal_operators_exhaust__WEBPACK_IMPORTED_MODULE_27__["exhaust"]; }); -/* harmony import */ var _internal_operators_exhaustMap__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(455); +/* harmony import */ var _internal_operators_exhaustMap__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(463); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "exhaustMap", function() { return _internal_operators_exhaustMap__WEBPACK_IMPORTED_MODULE_28__["exhaustMap"]; }); -/* harmony import */ var _internal_operators_expand__WEBPACK_IMPORTED_MODULE_29__ = __webpack_require__(456); +/* harmony import */ var _internal_operators_expand__WEBPACK_IMPORTED_MODULE_29__ = __webpack_require__(464); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "expand", function() { return _internal_operators_expand__WEBPACK_IMPORTED_MODULE_29__["expand"]; }); /* harmony import */ var _internal_operators_filter__WEBPACK_IMPORTED_MODULE_30__ = __webpack_require__(106); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "filter", function() { return _internal_operators_filter__WEBPACK_IMPORTED_MODULE_30__["filter"]; }); -/* harmony import */ var _internal_operators_finalize__WEBPACK_IMPORTED_MODULE_31__ = __webpack_require__(457); +/* harmony import */ var _internal_operators_finalize__WEBPACK_IMPORTED_MODULE_31__ = __webpack_require__(465); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "finalize", function() { return _internal_operators_finalize__WEBPACK_IMPORTED_MODULE_31__["finalize"]; }); -/* harmony import */ var _internal_operators_find__WEBPACK_IMPORTED_MODULE_32__ = __webpack_require__(458); +/* harmony import */ var _internal_operators_find__WEBPACK_IMPORTED_MODULE_32__ = __webpack_require__(466); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "find", function() { return _internal_operators_find__WEBPACK_IMPORTED_MODULE_32__["find"]; }); -/* harmony import */ var _internal_operators_findIndex__WEBPACK_IMPORTED_MODULE_33__ = __webpack_require__(459); +/* harmony import */ var _internal_operators_findIndex__WEBPACK_IMPORTED_MODULE_33__ = __webpack_require__(467); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "findIndex", function() { return _internal_operators_findIndex__WEBPACK_IMPORTED_MODULE_33__["findIndex"]; }); -/* harmony import */ var _internal_operators_first__WEBPACK_IMPORTED_MODULE_34__ = __webpack_require__(460); +/* harmony import */ var _internal_operators_first__WEBPACK_IMPORTED_MODULE_34__ = __webpack_require__(468); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "first", function() { return _internal_operators_first__WEBPACK_IMPORTED_MODULE_34__["first"]; }); /* harmony import */ var _internal_operators_groupBy__WEBPACK_IMPORTED_MODULE_35__ = __webpack_require__(32); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "groupBy", function() { return _internal_operators_groupBy__WEBPACK_IMPORTED_MODULE_35__["groupBy"]; }); -/* harmony import */ var _internal_operators_ignoreElements__WEBPACK_IMPORTED_MODULE_36__ = __webpack_require__(461); +/* harmony import */ var _internal_operators_ignoreElements__WEBPACK_IMPORTED_MODULE_36__ = __webpack_require__(469); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "ignoreElements", function() { return _internal_operators_ignoreElements__WEBPACK_IMPORTED_MODULE_36__["ignoreElements"]; }); -/* harmony import */ var _internal_operators_isEmpty__WEBPACK_IMPORTED_MODULE_37__ = __webpack_require__(462); +/* harmony import */ var _internal_operators_isEmpty__WEBPACK_IMPORTED_MODULE_37__ = __webpack_require__(470); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "isEmpty", function() { return _internal_operators_isEmpty__WEBPACK_IMPORTED_MODULE_37__["isEmpty"]; }); -/* harmony import */ var _internal_operators_last__WEBPACK_IMPORTED_MODULE_38__ = __webpack_require__(463); +/* harmony import */ var _internal_operators_last__WEBPACK_IMPORTED_MODULE_38__ = __webpack_require__(471); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "last", function() { return _internal_operators_last__WEBPACK_IMPORTED_MODULE_38__["last"]; }); /* harmony import */ var _internal_operators_map__WEBPACK_IMPORTED_MODULE_39__ = __webpack_require__(67); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "map", function() { return _internal_operators_map__WEBPACK_IMPORTED_MODULE_39__["map"]; }); -/* harmony import */ var _internal_operators_mapTo__WEBPACK_IMPORTED_MODULE_40__ = __webpack_require__(465); +/* harmony import */ var _internal_operators_mapTo__WEBPACK_IMPORTED_MODULE_40__ = __webpack_require__(473); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "mapTo", function() { return _internal_operators_mapTo__WEBPACK_IMPORTED_MODULE_40__["mapTo"]; }); -/* harmony import */ var _internal_operators_materialize__WEBPACK_IMPORTED_MODULE_41__ = __webpack_require__(466); +/* harmony import */ var _internal_operators_materialize__WEBPACK_IMPORTED_MODULE_41__ = __webpack_require__(474); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "materialize", function() { return _internal_operators_materialize__WEBPACK_IMPORTED_MODULE_41__["materialize"]; }); -/* harmony import */ var _internal_operators_max__WEBPACK_IMPORTED_MODULE_42__ = __webpack_require__(467); +/* harmony import */ var _internal_operators_max__WEBPACK_IMPORTED_MODULE_42__ = __webpack_require__(475); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "max", function() { return _internal_operators_max__WEBPACK_IMPORTED_MODULE_42__["max"]; }); -/* harmony import */ var _internal_operators_merge__WEBPACK_IMPORTED_MODULE_43__ = __webpack_require__(470); +/* harmony import */ var _internal_operators_merge__WEBPACK_IMPORTED_MODULE_43__ = __webpack_require__(478); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "merge", function() { return _internal_operators_merge__WEBPACK_IMPORTED_MODULE_43__["merge"]; }); /* harmony import */ var _internal_operators_mergeAll__WEBPACK_IMPORTED_MODULE_44__ = __webpack_require__(82); @@ -54290,175 +54936,175 @@ __webpack_require__.r(__webpack_exports__); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "flatMap", function() { return _internal_operators_mergeMap__WEBPACK_IMPORTED_MODULE_45__["flatMap"]; }); -/* harmony import */ var _internal_operators_mergeMapTo__WEBPACK_IMPORTED_MODULE_46__ = __webpack_require__(471); +/* harmony import */ var _internal_operators_mergeMapTo__WEBPACK_IMPORTED_MODULE_46__ = __webpack_require__(479); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "mergeMapTo", function() { return _internal_operators_mergeMapTo__WEBPACK_IMPORTED_MODULE_46__["mergeMapTo"]; }); -/* harmony import */ var _internal_operators_mergeScan__WEBPACK_IMPORTED_MODULE_47__ = __webpack_require__(472); +/* harmony import */ var _internal_operators_mergeScan__WEBPACK_IMPORTED_MODULE_47__ = __webpack_require__(480); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "mergeScan", function() { return _internal_operators_mergeScan__WEBPACK_IMPORTED_MODULE_47__["mergeScan"]; }); -/* harmony import */ var _internal_operators_min__WEBPACK_IMPORTED_MODULE_48__ = __webpack_require__(473); +/* harmony import */ var _internal_operators_min__WEBPACK_IMPORTED_MODULE_48__ = __webpack_require__(481); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "min", function() { return _internal_operators_min__WEBPACK_IMPORTED_MODULE_48__["min"]; }); -/* harmony import */ var _internal_operators_multicast__WEBPACK_IMPORTED_MODULE_49__ = __webpack_require__(474); +/* harmony import */ var _internal_operators_multicast__WEBPACK_IMPORTED_MODULE_49__ = __webpack_require__(482); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "multicast", function() { return _internal_operators_multicast__WEBPACK_IMPORTED_MODULE_49__["multicast"]; }); /* harmony import */ var _internal_operators_observeOn__WEBPACK_IMPORTED_MODULE_50__ = __webpack_require__(42); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "observeOn", function() { return _internal_operators_observeOn__WEBPACK_IMPORTED_MODULE_50__["observeOn"]; }); -/* harmony import */ var _internal_operators_onErrorResumeNext__WEBPACK_IMPORTED_MODULE_51__ = __webpack_require__(475); +/* harmony import */ var _internal_operators_onErrorResumeNext__WEBPACK_IMPORTED_MODULE_51__ = __webpack_require__(483); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "onErrorResumeNext", function() { return _internal_operators_onErrorResumeNext__WEBPACK_IMPORTED_MODULE_51__["onErrorResumeNext"]; }); -/* harmony import */ var _internal_operators_pairwise__WEBPACK_IMPORTED_MODULE_52__ = __webpack_require__(476); +/* harmony import */ var _internal_operators_pairwise__WEBPACK_IMPORTED_MODULE_52__ = __webpack_require__(484); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "pairwise", function() { return _internal_operators_pairwise__WEBPACK_IMPORTED_MODULE_52__["pairwise"]; }); -/* harmony import */ var _internal_operators_partition__WEBPACK_IMPORTED_MODULE_53__ = __webpack_require__(477); +/* harmony import */ var _internal_operators_partition__WEBPACK_IMPORTED_MODULE_53__ = __webpack_require__(485); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "partition", function() { return _internal_operators_partition__WEBPACK_IMPORTED_MODULE_53__["partition"]; }); -/* harmony import */ var _internal_operators_pluck__WEBPACK_IMPORTED_MODULE_54__ = __webpack_require__(478); +/* harmony import */ var _internal_operators_pluck__WEBPACK_IMPORTED_MODULE_54__ = __webpack_require__(486); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "pluck", function() { return _internal_operators_pluck__WEBPACK_IMPORTED_MODULE_54__["pluck"]; }); -/* harmony import */ var _internal_operators_publish__WEBPACK_IMPORTED_MODULE_55__ = __webpack_require__(479); +/* harmony import */ var _internal_operators_publish__WEBPACK_IMPORTED_MODULE_55__ = __webpack_require__(487); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "publish", function() { return _internal_operators_publish__WEBPACK_IMPORTED_MODULE_55__["publish"]; }); -/* harmony import */ var _internal_operators_publishBehavior__WEBPACK_IMPORTED_MODULE_56__ = __webpack_require__(480); +/* harmony import */ var _internal_operators_publishBehavior__WEBPACK_IMPORTED_MODULE_56__ = __webpack_require__(488); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "publishBehavior", function() { return _internal_operators_publishBehavior__WEBPACK_IMPORTED_MODULE_56__["publishBehavior"]; }); -/* harmony import */ var _internal_operators_publishLast__WEBPACK_IMPORTED_MODULE_57__ = __webpack_require__(481); +/* harmony import */ var _internal_operators_publishLast__WEBPACK_IMPORTED_MODULE_57__ = __webpack_require__(489); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "publishLast", function() { return _internal_operators_publishLast__WEBPACK_IMPORTED_MODULE_57__["publishLast"]; }); -/* harmony import */ var _internal_operators_publishReplay__WEBPACK_IMPORTED_MODULE_58__ = __webpack_require__(482); +/* harmony import */ var _internal_operators_publishReplay__WEBPACK_IMPORTED_MODULE_58__ = __webpack_require__(490); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "publishReplay", function() { return _internal_operators_publishReplay__WEBPACK_IMPORTED_MODULE_58__["publishReplay"]; }); -/* harmony import */ var _internal_operators_race__WEBPACK_IMPORTED_MODULE_59__ = __webpack_require__(483); +/* harmony import */ var _internal_operators_race__WEBPACK_IMPORTED_MODULE_59__ = __webpack_require__(491); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "race", function() { return _internal_operators_race__WEBPACK_IMPORTED_MODULE_59__["race"]; }); -/* harmony import */ var _internal_operators_reduce__WEBPACK_IMPORTED_MODULE_60__ = __webpack_require__(468); +/* harmony import */ var _internal_operators_reduce__WEBPACK_IMPORTED_MODULE_60__ = __webpack_require__(476); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "reduce", function() { return _internal_operators_reduce__WEBPACK_IMPORTED_MODULE_60__["reduce"]; }); -/* harmony import */ var _internal_operators_repeat__WEBPACK_IMPORTED_MODULE_61__ = __webpack_require__(484); +/* harmony import */ var _internal_operators_repeat__WEBPACK_IMPORTED_MODULE_61__ = __webpack_require__(492); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "repeat", function() { return _internal_operators_repeat__WEBPACK_IMPORTED_MODULE_61__["repeat"]; }); -/* harmony import */ var _internal_operators_repeatWhen__WEBPACK_IMPORTED_MODULE_62__ = __webpack_require__(485); +/* harmony import */ var _internal_operators_repeatWhen__WEBPACK_IMPORTED_MODULE_62__ = __webpack_require__(493); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "repeatWhen", function() { return _internal_operators_repeatWhen__WEBPACK_IMPORTED_MODULE_62__["repeatWhen"]; }); -/* harmony import */ var _internal_operators_retry__WEBPACK_IMPORTED_MODULE_63__ = __webpack_require__(486); +/* harmony import */ var _internal_operators_retry__WEBPACK_IMPORTED_MODULE_63__ = __webpack_require__(494); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "retry", function() { return _internal_operators_retry__WEBPACK_IMPORTED_MODULE_63__["retry"]; }); -/* harmony import */ var _internal_operators_retryWhen__WEBPACK_IMPORTED_MODULE_64__ = __webpack_require__(487); +/* harmony import */ var _internal_operators_retryWhen__WEBPACK_IMPORTED_MODULE_64__ = __webpack_require__(495); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "retryWhen", function() { return _internal_operators_retryWhen__WEBPACK_IMPORTED_MODULE_64__["retryWhen"]; }); /* harmony import */ var _internal_operators_refCount__WEBPACK_IMPORTED_MODULE_65__ = __webpack_require__(31); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "refCount", function() { return _internal_operators_refCount__WEBPACK_IMPORTED_MODULE_65__["refCount"]; }); -/* harmony import */ var _internal_operators_sample__WEBPACK_IMPORTED_MODULE_66__ = __webpack_require__(488); +/* harmony import */ var _internal_operators_sample__WEBPACK_IMPORTED_MODULE_66__ = __webpack_require__(496); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "sample", function() { return _internal_operators_sample__WEBPACK_IMPORTED_MODULE_66__["sample"]; }); -/* harmony import */ var _internal_operators_sampleTime__WEBPACK_IMPORTED_MODULE_67__ = __webpack_require__(489); +/* harmony import */ var _internal_operators_sampleTime__WEBPACK_IMPORTED_MODULE_67__ = __webpack_require__(497); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "sampleTime", function() { return _internal_operators_sampleTime__WEBPACK_IMPORTED_MODULE_67__["sampleTime"]; }); -/* harmony import */ var _internal_operators_scan__WEBPACK_IMPORTED_MODULE_68__ = __webpack_require__(469); +/* harmony import */ var _internal_operators_scan__WEBPACK_IMPORTED_MODULE_68__ = __webpack_require__(477); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "scan", function() { return _internal_operators_scan__WEBPACK_IMPORTED_MODULE_68__["scan"]; }); -/* harmony import */ var _internal_operators_sequenceEqual__WEBPACK_IMPORTED_MODULE_69__ = __webpack_require__(490); +/* harmony import */ var _internal_operators_sequenceEqual__WEBPACK_IMPORTED_MODULE_69__ = __webpack_require__(498); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "sequenceEqual", function() { return _internal_operators_sequenceEqual__WEBPACK_IMPORTED_MODULE_69__["sequenceEqual"]; }); -/* harmony import */ var _internal_operators_share__WEBPACK_IMPORTED_MODULE_70__ = __webpack_require__(491); +/* harmony import */ var _internal_operators_share__WEBPACK_IMPORTED_MODULE_70__ = __webpack_require__(499); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "share", function() { return _internal_operators_share__WEBPACK_IMPORTED_MODULE_70__["share"]; }); -/* harmony import */ var _internal_operators_shareReplay__WEBPACK_IMPORTED_MODULE_71__ = __webpack_require__(492); +/* harmony import */ var _internal_operators_shareReplay__WEBPACK_IMPORTED_MODULE_71__ = __webpack_require__(500); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "shareReplay", function() { return _internal_operators_shareReplay__WEBPACK_IMPORTED_MODULE_71__["shareReplay"]; }); -/* harmony import */ var _internal_operators_single__WEBPACK_IMPORTED_MODULE_72__ = __webpack_require__(493); +/* harmony import */ var _internal_operators_single__WEBPACK_IMPORTED_MODULE_72__ = __webpack_require__(501); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "single", function() { return _internal_operators_single__WEBPACK_IMPORTED_MODULE_72__["single"]; }); -/* harmony import */ var _internal_operators_skip__WEBPACK_IMPORTED_MODULE_73__ = __webpack_require__(494); +/* harmony import */ var _internal_operators_skip__WEBPACK_IMPORTED_MODULE_73__ = __webpack_require__(502); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "skip", function() { return _internal_operators_skip__WEBPACK_IMPORTED_MODULE_73__["skip"]; }); -/* harmony import */ var _internal_operators_skipLast__WEBPACK_IMPORTED_MODULE_74__ = __webpack_require__(495); +/* harmony import */ var _internal_operators_skipLast__WEBPACK_IMPORTED_MODULE_74__ = __webpack_require__(503); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "skipLast", function() { return _internal_operators_skipLast__WEBPACK_IMPORTED_MODULE_74__["skipLast"]; }); -/* harmony import */ var _internal_operators_skipUntil__WEBPACK_IMPORTED_MODULE_75__ = __webpack_require__(496); +/* harmony import */ var _internal_operators_skipUntil__WEBPACK_IMPORTED_MODULE_75__ = __webpack_require__(504); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "skipUntil", function() { return _internal_operators_skipUntil__WEBPACK_IMPORTED_MODULE_75__["skipUntil"]; }); -/* harmony import */ var _internal_operators_skipWhile__WEBPACK_IMPORTED_MODULE_76__ = __webpack_require__(497); +/* harmony import */ var _internal_operators_skipWhile__WEBPACK_IMPORTED_MODULE_76__ = __webpack_require__(505); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "skipWhile", function() { return _internal_operators_skipWhile__WEBPACK_IMPORTED_MODULE_76__["skipWhile"]; }); -/* harmony import */ var _internal_operators_startWith__WEBPACK_IMPORTED_MODULE_77__ = __webpack_require__(498); +/* harmony import */ var _internal_operators_startWith__WEBPACK_IMPORTED_MODULE_77__ = __webpack_require__(506); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "startWith", function() { return _internal_operators_startWith__WEBPACK_IMPORTED_MODULE_77__["startWith"]; }); -/* harmony import */ var _internal_operators_subscribeOn__WEBPACK_IMPORTED_MODULE_78__ = __webpack_require__(499); +/* harmony import */ var _internal_operators_subscribeOn__WEBPACK_IMPORTED_MODULE_78__ = __webpack_require__(507); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "subscribeOn", function() { return _internal_operators_subscribeOn__WEBPACK_IMPORTED_MODULE_78__["subscribeOn"]; }); -/* harmony import */ var _internal_operators_switchAll__WEBPACK_IMPORTED_MODULE_79__ = __webpack_require__(501); +/* harmony import */ var _internal_operators_switchAll__WEBPACK_IMPORTED_MODULE_79__ = __webpack_require__(509); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "switchAll", function() { return _internal_operators_switchAll__WEBPACK_IMPORTED_MODULE_79__["switchAll"]; }); -/* harmony import */ var _internal_operators_switchMap__WEBPACK_IMPORTED_MODULE_80__ = __webpack_require__(502); +/* harmony import */ var _internal_operators_switchMap__WEBPACK_IMPORTED_MODULE_80__ = __webpack_require__(510); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "switchMap", function() { return _internal_operators_switchMap__WEBPACK_IMPORTED_MODULE_80__["switchMap"]; }); -/* harmony import */ var _internal_operators_switchMapTo__WEBPACK_IMPORTED_MODULE_81__ = __webpack_require__(503); +/* harmony import */ var _internal_operators_switchMapTo__WEBPACK_IMPORTED_MODULE_81__ = __webpack_require__(511); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "switchMapTo", function() { return _internal_operators_switchMapTo__WEBPACK_IMPORTED_MODULE_81__["switchMapTo"]; }); -/* harmony import */ var _internal_operators_take__WEBPACK_IMPORTED_MODULE_82__ = __webpack_require__(451); +/* harmony import */ var _internal_operators_take__WEBPACK_IMPORTED_MODULE_82__ = __webpack_require__(459); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "take", function() { return _internal_operators_take__WEBPACK_IMPORTED_MODULE_82__["take"]; }); -/* harmony import */ var _internal_operators_takeLast__WEBPACK_IMPORTED_MODULE_83__ = __webpack_require__(464); +/* harmony import */ var _internal_operators_takeLast__WEBPACK_IMPORTED_MODULE_83__ = __webpack_require__(472); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "takeLast", function() { return _internal_operators_takeLast__WEBPACK_IMPORTED_MODULE_83__["takeLast"]; }); -/* harmony import */ var _internal_operators_takeUntil__WEBPACK_IMPORTED_MODULE_84__ = __webpack_require__(504); +/* harmony import */ var _internal_operators_takeUntil__WEBPACK_IMPORTED_MODULE_84__ = __webpack_require__(512); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "takeUntil", function() { return _internal_operators_takeUntil__WEBPACK_IMPORTED_MODULE_84__["takeUntil"]; }); -/* harmony import */ var _internal_operators_takeWhile__WEBPACK_IMPORTED_MODULE_85__ = __webpack_require__(505); +/* harmony import */ var _internal_operators_takeWhile__WEBPACK_IMPORTED_MODULE_85__ = __webpack_require__(513); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "takeWhile", function() { return _internal_operators_takeWhile__WEBPACK_IMPORTED_MODULE_85__["takeWhile"]; }); -/* harmony import */ var _internal_operators_tap__WEBPACK_IMPORTED_MODULE_86__ = __webpack_require__(506); +/* harmony import */ var _internal_operators_tap__WEBPACK_IMPORTED_MODULE_86__ = __webpack_require__(514); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "tap", function() { return _internal_operators_tap__WEBPACK_IMPORTED_MODULE_86__["tap"]; }); -/* harmony import */ var _internal_operators_throttle__WEBPACK_IMPORTED_MODULE_87__ = __webpack_require__(507); +/* harmony import */ var _internal_operators_throttle__WEBPACK_IMPORTED_MODULE_87__ = __webpack_require__(515); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "throttle", function() { return _internal_operators_throttle__WEBPACK_IMPORTED_MODULE_87__["throttle"]; }); -/* harmony import */ var _internal_operators_throttleTime__WEBPACK_IMPORTED_MODULE_88__ = __webpack_require__(508); +/* harmony import */ var _internal_operators_throttleTime__WEBPACK_IMPORTED_MODULE_88__ = __webpack_require__(516); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "throttleTime", function() { return _internal_operators_throttleTime__WEBPACK_IMPORTED_MODULE_88__["throttleTime"]; }); -/* harmony import */ var _internal_operators_throwIfEmpty__WEBPACK_IMPORTED_MODULE_89__ = __webpack_require__(450); +/* harmony import */ var _internal_operators_throwIfEmpty__WEBPACK_IMPORTED_MODULE_89__ = __webpack_require__(458); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "throwIfEmpty", function() { return _internal_operators_throwIfEmpty__WEBPACK_IMPORTED_MODULE_89__["throwIfEmpty"]; }); -/* harmony import */ var _internal_operators_timeInterval__WEBPACK_IMPORTED_MODULE_90__ = __webpack_require__(509); +/* harmony import */ var _internal_operators_timeInterval__WEBPACK_IMPORTED_MODULE_90__ = __webpack_require__(517); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "timeInterval", function() { return _internal_operators_timeInterval__WEBPACK_IMPORTED_MODULE_90__["timeInterval"]; }); -/* harmony import */ var _internal_operators_timeout__WEBPACK_IMPORTED_MODULE_91__ = __webpack_require__(510); +/* harmony import */ var _internal_operators_timeout__WEBPACK_IMPORTED_MODULE_91__ = __webpack_require__(518); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "timeout", function() { return _internal_operators_timeout__WEBPACK_IMPORTED_MODULE_91__["timeout"]; }); -/* harmony import */ var _internal_operators_timeoutWith__WEBPACK_IMPORTED_MODULE_92__ = __webpack_require__(511); +/* harmony import */ var _internal_operators_timeoutWith__WEBPACK_IMPORTED_MODULE_92__ = __webpack_require__(519); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "timeoutWith", function() { return _internal_operators_timeoutWith__WEBPACK_IMPORTED_MODULE_92__["timeoutWith"]; }); -/* harmony import */ var _internal_operators_timestamp__WEBPACK_IMPORTED_MODULE_93__ = __webpack_require__(512); +/* harmony import */ var _internal_operators_timestamp__WEBPACK_IMPORTED_MODULE_93__ = __webpack_require__(520); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "timestamp", function() { return _internal_operators_timestamp__WEBPACK_IMPORTED_MODULE_93__["timestamp"]; }); -/* harmony import */ var _internal_operators_toArray__WEBPACK_IMPORTED_MODULE_94__ = __webpack_require__(513); +/* harmony import */ var _internal_operators_toArray__WEBPACK_IMPORTED_MODULE_94__ = __webpack_require__(521); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "toArray", function() { return _internal_operators_toArray__WEBPACK_IMPORTED_MODULE_94__["toArray"]; }); -/* harmony import */ var _internal_operators_window__WEBPACK_IMPORTED_MODULE_95__ = __webpack_require__(514); +/* harmony import */ var _internal_operators_window__WEBPACK_IMPORTED_MODULE_95__ = __webpack_require__(522); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "window", function() { return _internal_operators_window__WEBPACK_IMPORTED_MODULE_95__["window"]; }); -/* harmony import */ var _internal_operators_windowCount__WEBPACK_IMPORTED_MODULE_96__ = __webpack_require__(515); +/* harmony import */ var _internal_operators_windowCount__WEBPACK_IMPORTED_MODULE_96__ = __webpack_require__(523); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "windowCount", function() { return _internal_operators_windowCount__WEBPACK_IMPORTED_MODULE_96__["windowCount"]; }); -/* harmony import */ var _internal_operators_windowTime__WEBPACK_IMPORTED_MODULE_97__ = __webpack_require__(516); +/* harmony import */ var _internal_operators_windowTime__WEBPACK_IMPORTED_MODULE_97__ = __webpack_require__(524); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "windowTime", function() { return _internal_operators_windowTime__WEBPACK_IMPORTED_MODULE_97__["windowTime"]; }); -/* harmony import */ var _internal_operators_windowToggle__WEBPACK_IMPORTED_MODULE_98__ = __webpack_require__(517); +/* harmony import */ var _internal_operators_windowToggle__WEBPACK_IMPORTED_MODULE_98__ = __webpack_require__(525); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "windowToggle", function() { return _internal_operators_windowToggle__WEBPACK_IMPORTED_MODULE_98__["windowToggle"]; }); -/* harmony import */ var _internal_operators_windowWhen__WEBPACK_IMPORTED_MODULE_99__ = __webpack_require__(518); +/* harmony import */ var _internal_operators_windowWhen__WEBPACK_IMPORTED_MODULE_99__ = __webpack_require__(526); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "windowWhen", function() { return _internal_operators_windowWhen__WEBPACK_IMPORTED_MODULE_99__["windowWhen"]; }); -/* harmony import */ var _internal_operators_withLatestFrom__WEBPACK_IMPORTED_MODULE_100__ = __webpack_require__(519); +/* harmony import */ var _internal_operators_withLatestFrom__WEBPACK_IMPORTED_MODULE_100__ = __webpack_require__(527); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "withLatestFrom", function() { return _internal_operators_withLatestFrom__WEBPACK_IMPORTED_MODULE_100__["withLatestFrom"]; }); -/* harmony import */ var _internal_operators_zip__WEBPACK_IMPORTED_MODULE_101__ = __webpack_require__(520); +/* harmony import */ var _internal_operators_zip__WEBPACK_IMPORTED_MODULE_101__ = __webpack_require__(528); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "zip", function() { return _internal_operators_zip__WEBPACK_IMPORTED_MODULE_101__["zip"]; }); -/* harmony import */ var _internal_operators_zipAll__WEBPACK_IMPORTED_MODULE_102__ = __webpack_require__(521); +/* harmony import */ var _internal_operators_zipAll__WEBPACK_IMPORTED_MODULE_102__ = __webpack_require__(529); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "zipAll", function() { return _internal_operators_zipAll__WEBPACK_IMPORTED_MODULE_102__["zipAll"]; }); /** PURE_IMPORTS_START PURE_IMPORTS_END */ @@ -54569,7 +55215,7 @@ __webpack_require__.r(__webpack_exports__); /***/ }), -/* 425 */ +/* 433 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -54648,14 +55294,14 @@ var AuditSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 426 */ +/* 434 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "auditTime", function() { return auditTime; }); /* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(56); -/* harmony import */ var _audit__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(425); +/* harmony import */ var _audit__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(433); /* harmony import */ var _observable_timer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(109); /** PURE_IMPORTS_START _scheduler_async,_audit,_observable_timer PURE_IMPORTS_END */ @@ -54671,7 +55317,7 @@ function auditTime(duration, scheduler) { /***/ }), -/* 427 */ +/* 435 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -54718,7 +55364,7 @@ var BufferSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 428 */ +/* 436 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -54819,7 +55465,7 @@ var BufferSkipCountSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 429 */ +/* 437 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -54980,7 +55626,7 @@ function dispatchBufferClose(arg) { /***/ }), -/* 430 */ +/* 438 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -55099,7 +55745,7 @@ var BufferToggleSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 431 */ +/* 439 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -55192,7 +55838,7 @@ var BufferWhenSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 432 */ +/* 440 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -55252,7 +55898,7 @@ var CatchSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 433 */ +/* 441 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -55268,7 +55914,7 @@ function combineAll(project) { /***/ }), -/* 434 */ +/* 442 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -55300,7 +55946,7 @@ function combineLatest() { /***/ }), -/* 435 */ +/* 443 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -55320,7 +55966,7 @@ function concat() { /***/ }), -/* 436 */ +/* 444 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -55336,13 +55982,13 @@ function concatMap(project, resultSelector) { /***/ }), -/* 437 */ +/* 445 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "concatMapTo", function() { return concatMapTo; }); -/* harmony import */ var _concatMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(436); +/* harmony import */ var _concatMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(444); /** PURE_IMPORTS_START _concatMap PURE_IMPORTS_END */ function concatMapTo(innerObservable, resultSelector) { @@ -55352,7 +55998,7 @@ function concatMapTo(innerObservable, resultSelector) { /***/ }), -/* 438 */ +/* 446 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -55417,7 +56063,7 @@ var CountSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 439 */ +/* 447 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -55502,7 +56148,7 @@ var DebounceSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 440 */ +/* 448 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -55578,7 +56224,7 @@ function dispatchNext(subscriber) { /***/ }), -/* 441 */ +/* 449 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -55628,7 +56274,7 @@ var DefaultIfEmptySubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 442 */ +/* 450 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -55636,7 +56282,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "delay", function() { return delay; }); /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); /* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(56); -/* harmony import */ var _util_isDate__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(443); +/* harmony import */ var _util_isDate__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(451); /* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(12); /* harmony import */ var _Notification__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(43); /** PURE_IMPORTS_START tslib,_scheduler_async,_util_isDate,_Subscriber,_Notification PURE_IMPORTS_END */ @@ -55735,7 +56381,7 @@ var DelayMessage = /*@__PURE__*/ (function () { /***/ }), -/* 443 */ +/* 451 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -55749,7 +56395,7 @@ function isDate(value) { /***/ }), -/* 444 */ +/* 452 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -55895,7 +56541,7 @@ var SubscriptionDelaySubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 445 */ +/* 453 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -55933,7 +56579,7 @@ var DeMaterializeSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 446 */ +/* 454 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -56009,7 +56655,7 @@ var DistinctSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 447 */ +/* 455 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -56080,13 +56726,13 @@ var DistinctUntilChangedSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 448 */ +/* 456 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "distinctUntilKeyChanged", function() { return distinctUntilKeyChanged; }); -/* harmony import */ var _distinctUntilChanged__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(447); +/* harmony import */ var _distinctUntilChanged__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(455); /** PURE_IMPORTS_START _distinctUntilChanged PURE_IMPORTS_END */ function distinctUntilKeyChanged(key, compare) { @@ -56096,7 +56742,7 @@ function distinctUntilKeyChanged(key, compare) { /***/ }), -/* 449 */ +/* 457 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -56104,9 +56750,9 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "elementAt", function() { return elementAt; }); /* harmony import */ var _util_ArgumentOutOfRangeError__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(63); /* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(106); -/* harmony import */ var _throwIfEmpty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(450); -/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(441); -/* harmony import */ var _take__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(451); +/* harmony import */ var _throwIfEmpty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(458); +/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(449); +/* harmony import */ var _take__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(459); /** PURE_IMPORTS_START _util_ArgumentOutOfRangeError,_filter,_throwIfEmpty,_defaultIfEmpty,_take PURE_IMPORTS_END */ @@ -56128,7 +56774,7 @@ function elementAt(index, defaultValue) { /***/ }), -/* 450 */ +/* 458 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -56194,7 +56840,7 @@ function defaultErrorFactory() { /***/ }), -/* 451 */ +/* 459 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -56256,7 +56902,7 @@ var TakeSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 452 */ +/* 460 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -56278,7 +56924,7 @@ function endWith() { /***/ }), -/* 453 */ +/* 461 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -56340,7 +56986,7 @@ var EverySubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 454 */ +/* 462 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -56394,7 +57040,7 @@ var SwitchFirstSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 455 */ +/* 463 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -56488,7 +57134,7 @@ var ExhaustMapSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 456 */ +/* 464 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -56600,7 +57246,7 @@ var ExpandSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 457 */ +/* 465 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -56638,7 +57284,7 @@ var FinallySubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 458 */ +/* 466 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -56710,13 +57356,13 @@ var FindValueSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 459 */ +/* 467 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "findIndex", function() { return findIndex; }); -/* harmony import */ var _operators_find__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(458); +/* harmony import */ var _operators_find__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(466); /** PURE_IMPORTS_START _operators_find PURE_IMPORTS_END */ function findIndex(predicate, thisArg) { @@ -56726,7 +57372,7 @@ function findIndex(predicate, thisArg) { /***/ }), -/* 460 */ +/* 468 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -56734,9 +57380,9 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "first", function() { return first; }); /* harmony import */ var _util_EmptyError__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(64); /* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(106); -/* harmony import */ var _take__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(451); -/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(441); -/* harmony import */ var _throwIfEmpty__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(450); +/* harmony import */ var _take__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(459); +/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(449); +/* harmony import */ var _throwIfEmpty__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(458); /* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(26); /** PURE_IMPORTS_START _util_EmptyError,_filter,_take,_defaultIfEmpty,_throwIfEmpty,_util_identity PURE_IMPORTS_END */ @@ -56753,7 +57399,7 @@ function first(predicate, defaultValue) { /***/ }), -/* 461 */ +/* 469 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -56790,7 +57436,7 @@ var IgnoreElementsSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 462 */ +/* 470 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -56834,7 +57480,7 @@ var IsEmptySubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 463 */ +/* 471 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -56842,9 +57488,9 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "last", function() { return last; }); /* harmony import */ var _util_EmptyError__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(64); /* harmony import */ var _filter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(106); -/* harmony import */ var _takeLast__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(464); -/* harmony import */ var _throwIfEmpty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(450); -/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(441); +/* harmony import */ var _takeLast__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(472); +/* harmony import */ var _throwIfEmpty__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(458); +/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(449); /* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(26); /** PURE_IMPORTS_START _util_EmptyError,_filter,_takeLast,_throwIfEmpty,_defaultIfEmpty,_util_identity PURE_IMPORTS_END */ @@ -56861,7 +57507,7 @@ function last(predicate, defaultValue) { /***/ }), -/* 464 */ +/* 472 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -56938,7 +57584,7 @@ var TakeLastSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 465 */ +/* 473 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -56977,7 +57623,7 @@ var MapToSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 466 */ +/* 474 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -57027,13 +57673,13 @@ var MaterializeSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 467 */ +/* 475 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "max", function() { return max; }); -/* harmony import */ var _reduce__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(468); +/* harmony import */ var _reduce__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(476); /** PURE_IMPORTS_START _reduce PURE_IMPORTS_END */ function max(comparer) { @@ -57046,15 +57692,15 @@ function max(comparer) { /***/ }), -/* 468 */ +/* 476 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "reduce", function() { return reduce; }); -/* harmony import */ var _scan__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(469); -/* harmony import */ var _takeLast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(464); -/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(441); +/* harmony import */ var _scan__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(477); +/* harmony import */ var _takeLast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(472); +/* harmony import */ var _defaultIfEmpty__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(449); /* harmony import */ var _util_pipe__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(25); /** PURE_IMPORTS_START _scan,_takeLast,_defaultIfEmpty,_util_pipe PURE_IMPORTS_END */ @@ -57075,7 +57721,7 @@ function reduce(accumulator, seed) { /***/ }), -/* 469 */ +/* 477 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -57157,7 +57803,7 @@ var ScanSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 470 */ +/* 478 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -57177,7 +57823,7 @@ function merge() { /***/ }), -/* 471 */ +/* 479 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -57202,7 +57848,7 @@ function mergeMapTo(innerObservable, resultSelector, concurrent) { /***/ }), -/* 472 */ +/* 480 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -57311,13 +57957,13 @@ var MergeScanSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 473 */ +/* 481 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "min", function() { return min; }); -/* harmony import */ var _reduce__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(468); +/* harmony import */ var _reduce__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(476); /** PURE_IMPORTS_START _reduce PURE_IMPORTS_END */ function min(comparer) { @@ -57330,7 +57976,7 @@ function min(comparer) { /***/ }), -/* 474 */ +/* 482 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -57379,7 +58025,7 @@ var MulticastOperator = /*@__PURE__*/ (function () { /***/ }), -/* 475 */ +/* 483 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -57469,7 +58115,7 @@ var OnErrorResumeNextSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 476 */ +/* 484 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -57517,7 +58163,7 @@ var PairwiseSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 477 */ +/* 485 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -57540,7 +58186,7 @@ function partition(predicate, thisArg) { /***/ }), -/* 478 */ +/* 486 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -57580,14 +58226,14 @@ function plucker(props, length) { /***/ }), -/* 479 */ +/* 487 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "publish", function() { return publish; }); /* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(28); -/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(474); +/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(482); /** PURE_IMPORTS_START _Subject,_multicast PURE_IMPORTS_END */ @@ -57600,14 +58246,14 @@ function publish(selector) { /***/ }), -/* 480 */ +/* 488 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "publishBehavior", function() { return publishBehavior; }); /* harmony import */ var _BehaviorSubject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(33); -/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(474); +/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(482); /** PURE_IMPORTS_START _BehaviorSubject,_multicast PURE_IMPORTS_END */ @@ -57618,14 +58264,14 @@ function publishBehavior(value) { /***/ }), -/* 481 */ +/* 489 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "publishLast", function() { return publishLast; }); /* harmony import */ var _AsyncSubject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(51); -/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(474); +/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(482); /** PURE_IMPORTS_START _AsyncSubject,_multicast PURE_IMPORTS_END */ @@ -57636,14 +58282,14 @@ function publishLast() { /***/ }), -/* 482 */ +/* 490 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "publishReplay", function() { return publishReplay; }); /* harmony import */ var _ReplaySubject__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(34); -/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(474); +/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(482); /** PURE_IMPORTS_START _ReplaySubject,_multicast PURE_IMPORTS_END */ @@ -57659,7 +58305,7 @@ function publishReplay(bufferSize, windowTime, selectorOrScheduler, scheduler) { /***/ }), -/* 483 */ +/* 491 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -57686,7 +58332,7 @@ function race() { /***/ }), -/* 484 */ +/* 492 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -57751,7 +58397,7 @@ var RepeatSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 485 */ +/* 493 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -57845,7 +58491,7 @@ var RepeatWhenSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 486 */ +/* 494 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -57898,7 +58544,7 @@ var RetrySubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 487 */ +/* 495 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -57984,7 +58630,7 @@ var RetryWhenSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 488 */ +/* 496 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -58039,7 +58685,7 @@ var SampleSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 489 */ +/* 497 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -58099,7 +58745,7 @@ function dispatchNotification(state) { /***/ }), -/* 490 */ +/* 498 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -58222,13 +58868,13 @@ var SequenceEqualCompareToSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 491 */ +/* 499 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "share", function() { return share; }); -/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(474); +/* harmony import */ var _multicast__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(482); /* harmony import */ var _refCount__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(31); /* harmony import */ var _Subject__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(28); /** PURE_IMPORTS_START _multicast,_refCount,_Subject PURE_IMPORTS_END */ @@ -58245,7 +58891,7 @@ function share() { /***/ }), -/* 492 */ +/* 500 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -58314,7 +58960,7 @@ function shareReplayOperator(_a) { /***/ }), -/* 493 */ +/* 501 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -58394,7 +59040,7 @@ var SingleSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 494 */ +/* 502 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -58436,7 +59082,7 @@ var SkipSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 495 */ +/* 503 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -58498,7 +59144,7 @@ var SkipLastSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 496 */ +/* 504 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -58555,7 +59201,7 @@ var SkipUntilSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 497 */ +/* 505 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -58611,7 +59257,7 @@ var SkipWhileSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 498 */ +/* 506 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -58640,13 +59286,13 @@ function startWith() { /***/ }), -/* 499 */ +/* 507 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "subscribeOn", function() { return subscribeOn; }); -/* harmony import */ var _observable_SubscribeOnObservable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(500); +/* harmony import */ var _observable_SubscribeOnObservable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(508); /** PURE_IMPORTS_START _observable_SubscribeOnObservable PURE_IMPORTS_END */ function subscribeOn(scheduler, delay) { @@ -58671,7 +59317,7 @@ var SubscribeOnOperator = /*@__PURE__*/ (function () { /***/ }), -/* 500 */ +/* 508 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -58735,13 +59381,13 @@ var SubscribeOnObservable = /*@__PURE__*/ (function (_super) { /***/ }), -/* 501 */ +/* 509 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "switchAll", function() { return switchAll; }); -/* harmony import */ var _switchMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(502); +/* harmony import */ var _switchMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(510); /* harmony import */ var _util_identity__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(26); /** PURE_IMPORTS_START _switchMap,_util_identity PURE_IMPORTS_END */ @@ -58753,7 +59399,7 @@ function switchAll() { /***/ }), -/* 502 */ +/* 510 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -58841,13 +59487,13 @@ var SwitchMapSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 503 */ +/* 511 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "switchMapTo", function() { return switchMapTo; }); -/* harmony import */ var _switchMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(502); +/* harmony import */ var _switchMap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(510); /** PURE_IMPORTS_START _switchMap PURE_IMPORTS_END */ function switchMapTo(innerObservable, resultSelector) { @@ -58857,7 +59503,7 @@ function switchMapTo(innerObservable, resultSelector) { /***/ }), -/* 504 */ +/* 512 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -58905,7 +59551,7 @@ var TakeUntilSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 505 */ +/* 513 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -58973,7 +59619,7 @@ var TakeWhileSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 506 */ +/* 514 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -59061,7 +59707,7 @@ var TapSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 507 */ +/* 515 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -59163,7 +59809,7 @@ var ThrottleSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 508 */ +/* 516 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -59172,7 +59818,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); /* harmony import */ var _Subscriber__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(12); /* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(56); -/* harmony import */ var _throttle__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(507); +/* harmony import */ var _throttle__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(515); /** PURE_IMPORTS_START tslib,_Subscriber,_scheduler_async,_throttle PURE_IMPORTS_END */ @@ -59261,7 +59907,7 @@ function dispatchNext(arg) { /***/ }), -/* 509 */ +/* 517 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -59269,7 +59915,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "timeInterval", function() { return timeInterval; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TimeInterval", function() { return TimeInterval; }); /* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(56); -/* harmony import */ var _scan__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(469); +/* harmony import */ var _scan__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(477); /* harmony import */ var _observable_defer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(92); /* harmony import */ var _map__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(67); /** PURE_IMPORTS_START _scheduler_async,_scan,_observable_defer,_map PURE_IMPORTS_END */ @@ -59305,7 +59951,7 @@ var TimeInterval = /*@__PURE__*/ (function () { /***/ }), -/* 510 */ +/* 518 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -59313,7 +59959,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "timeout", function() { return timeout; }); /* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(56); /* harmony import */ var _util_TimeoutError__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(65); -/* harmony import */ var _timeoutWith__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(511); +/* harmony import */ var _timeoutWith__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(519); /* harmony import */ var _observable_throwError__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(50); /** PURE_IMPORTS_START _scheduler_async,_util_TimeoutError,_timeoutWith,_observable_throwError PURE_IMPORTS_END */ @@ -59330,7 +59976,7 @@ function timeout(due, scheduler) { /***/ }), -/* 511 */ +/* 519 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -59338,7 +59984,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "timeoutWith", function() { return timeoutWith; }); /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); /* harmony import */ var _scheduler_async__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(56); -/* harmony import */ var _util_isDate__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(443); +/* harmony import */ var _util_isDate__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(451); /* harmony import */ var _innerSubscribe__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(91); /** PURE_IMPORTS_START tslib,_scheduler_async,_util_isDate,_innerSubscribe PURE_IMPORTS_END */ @@ -59409,7 +60055,7 @@ var TimeoutWithSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 512 */ +/* 520 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -59439,13 +60085,13 @@ var Timestamp = /*@__PURE__*/ (function () { /***/ }), -/* 513 */ +/* 521 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "toArray", function() { return toArray; }); -/* harmony import */ var _reduce__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(468); +/* harmony import */ var _reduce__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(476); /** PURE_IMPORTS_START _reduce PURE_IMPORTS_END */ function toArrayReducer(arr, item, index) { @@ -59462,7 +60108,7 @@ function toArray() { /***/ }), -/* 514 */ +/* 522 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -59540,7 +60186,7 @@ var WindowSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 515 */ +/* 523 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -59630,7 +60276,7 @@ var WindowCountSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 516 */ +/* 524 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -59800,7 +60446,7 @@ function dispatchWindowClose(state) { /***/ }), -/* 517 */ +/* 525 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -59943,7 +60589,7 @@ var WindowToggleSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 518 */ +/* 526 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -60040,7 +60686,7 @@ var WindowSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 519 */ +/* 527 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -60135,7 +60781,7 @@ var WithLatestFromSubscriber = /*@__PURE__*/ (function (_super) { /***/ }), -/* 520 */ +/* 528 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -60157,7 +60803,7 @@ function zip() { /***/ }), -/* 521 */ +/* 529 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -60173,7 +60819,7 @@ function zipAll(project) { /***/ }), -/* 522 */ +/* 530 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -60183,7 +60829,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); -var _observe_lines = __webpack_require__(523); +var _observe_lines = __webpack_require__(531); Object.keys(_observe_lines).forEach(function (key) { if (key === "default" || key === "__esModule") return; @@ -60196,7 +60842,7 @@ Object.keys(_observe_lines).forEach(function (key) { }); }); -var _observe_readable = __webpack_require__(524); +var _observe_readable = __webpack_require__(532); Object.keys(_observe_readable).forEach(function (key) { if (key === "default" || key === "__esModule") return; @@ -60210,7 +60856,7 @@ Object.keys(_observe_readable).forEach(function (key) { }); /***/ }), -/* 523 */ +/* 531 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -60223,9 +60869,9 @@ exports.observeLines = observeLines; var Rx = _interopRequireWildcard(__webpack_require__(9)); -var _operators = __webpack_require__(424); +var _operators = __webpack_require__(432); -var _observe_readable = __webpack_require__(524); +var _observe_readable = __webpack_require__(532); function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } @@ -60288,7 +60934,7 @@ function observeLines(readable) { } /***/ }), -/* 524 */ +/* 532 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -60301,7 +60947,7 @@ exports.observeReadable = observeReadable; var Rx = _interopRequireWildcard(__webpack_require__(9)); -var _operators = __webpack_require__(424); +var _operators = __webpack_require__(432); function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } @@ -60325,13 +60971,13 @@ function observeReadable(readable) { } /***/ }), -/* 525 */ +/* 533 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "BuildCommand", function() { return BuildCommand; }); -/* harmony import */ var _utils_bazel__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(419); +/* harmony import */ var _utils_bazel__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(427); /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License @@ -60359,7 +61005,7 @@ const BuildCommand = { }; /***/ }), -/* 526 */ +/* 534 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -60369,11 +61015,11 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var dedent__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(dedent__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(240); /* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(del__WEBPACK_IMPORTED_MODULE_1__); -/* harmony import */ var ora__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(527); +/* harmony import */ var ora__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(535); /* harmony import */ var ora__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(ora__WEBPACK_IMPORTED_MODULE_2__); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(4); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_3__); -/* harmony import */ var _utils_bazel__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(419); +/* harmony import */ var _utils_bazel__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(427); /* harmony import */ var _utils_fs__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(231); /* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(220); /* @@ -60476,20 +61122,20 @@ const CleanCommand = { }; /***/ }), -/* 527 */ +/* 535 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const readline = __webpack_require__(528); -const chalk = __webpack_require__(529); -const cliCursor = __webpack_require__(532); -const cliSpinners = __webpack_require__(534); -const logSymbols = __webpack_require__(536); -const stripAnsi = __webpack_require__(542); -const wcwidth = __webpack_require__(544); -const isInteractive = __webpack_require__(548); -const MuteStream = __webpack_require__(549); +const readline = __webpack_require__(536); +const chalk = __webpack_require__(537); +const cliCursor = __webpack_require__(540); +const cliSpinners = __webpack_require__(542); +const logSymbols = __webpack_require__(544); +const stripAnsi = __webpack_require__(550); +const wcwidth = __webpack_require__(552); +const isInteractive = __webpack_require__(556); +const MuteStream = __webpack_require__(557); const TEXT = Symbol('text'); const PREFIX_TEXT = Symbol('prefixText'); @@ -60842,13 +61488,13 @@ module.exports.promise = (action, options) => { /***/ }), -/* 528 */ +/* 536 */ /***/ (function(module, exports) { module.exports = require("readline"); /***/ }), -/* 529 */ +/* 537 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -60858,7 +61504,7 @@ const {stdout: stdoutColor, stderr: stderrColor} = __webpack_require__(121); const { stringReplaceAll, stringEncaseCRLFWithFirstIndex -} = __webpack_require__(530); +} = __webpack_require__(538); // `supportsColor.level` → `ansiStyles.color[name]` mapping const levelMapping = [ @@ -61059,7 +61705,7 @@ const chalkTag = (chalk, ...strings) => { } if (template === undefined) { - template = __webpack_require__(531); + template = __webpack_require__(539); } return template(chalk, parts.join('')); @@ -61088,7 +61734,7 @@ module.exports = chalk; /***/ }), -/* 530 */ +/* 538 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -61134,7 +61780,7 @@ module.exports = { /***/ }), -/* 531 */ +/* 539 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -61275,12 +61921,12 @@ module.exports = (chalk, temporary) => { /***/ }), -/* 532 */ +/* 540 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const restoreCursor = __webpack_require__(533); +const restoreCursor = __webpack_require__(541); let isHidden = false; @@ -61317,7 +61963,7 @@ exports.toggle = (force, writableStream) => { /***/ }), -/* 533 */ +/* 541 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -61333,13 +61979,13 @@ module.exports = onetime(() => { /***/ }), -/* 534 */ +/* 542 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const spinners = Object.assign({}, __webpack_require__(535)); +const spinners = Object.assign({}, __webpack_require__(543)); const spinnersList = Object.keys(spinners); @@ -61357,18 +62003,18 @@ module.exports.default = spinners; /***/ }), -/* 535 */ +/* 543 */ /***/ (function(module) { module.exports = JSON.parse("{\"dots\":{\"interval\":80,\"frames\":[\"⠋\",\"⠙\",\"⠹\",\"⠸\",\"⠼\",\"⠴\",\"⠦\",\"⠧\",\"⠇\",\"⠏\"]},\"dots2\":{\"interval\":80,\"frames\":[\"⣾\",\"⣽\",\"⣻\",\"⢿\",\"⡿\",\"⣟\",\"⣯\",\"⣷\"]},\"dots3\":{\"interval\":80,\"frames\":[\"⠋\",\"⠙\",\"⠚\",\"⠞\",\"⠖\",\"⠦\",\"⠴\",\"⠲\",\"⠳\",\"⠓\"]},\"dots4\":{\"interval\":80,\"frames\":[\"⠄\",\"⠆\",\"⠇\",\"⠋\",\"⠙\",\"⠸\",\"⠰\",\"⠠\",\"⠰\",\"⠸\",\"⠙\",\"⠋\",\"⠇\",\"⠆\"]},\"dots5\":{\"interval\":80,\"frames\":[\"⠋\",\"⠙\",\"⠚\",\"⠒\",\"⠂\",\"⠂\",\"⠒\",\"⠲\",\"⠴\",\"⠦\",\"⠖\",\"⠒\",\"⠐\",\"⠐\",\"⠒\",\"⠓\",\"⠋\"]},\"dots6\":{\"interval\":80,\"frames\":[\"⠁\",\"⠉\",\"⠙\",\"⠚\",\"⠒\",\"⠂\",\"⠂\",\"⠒\",\"⠲\",\"⠴\",\"⠤\",\"⠄\",\"⠄\",\"⠤\",\"⠴\",\"⠲\",\"⠒\",\"⠂\",\"⠂\",\"⠒\",\"⠚\",\"⠙\",\"⠉\",\"⠁\"]},\"dots7\":{\"interval\":80,\"frames\":[\"⠈\",\"⠉\",\"⠋\",\"⠓\",\"⠒\",\"⠐\",\"⠐\",\"⠒\",\"⠖\",\"⠦\",\"⠤\",\"⠠\",\"⠠\",\"⠤\",\"⠦\",\"⠖\",\"⠒\",\"⠐\",\"⠐\",\"⠒\",\"⠓\",\"⠋\",\"⠉\",\"⠈\"]},\"dots8\":{\"interval\":80,\"frames\":[\"⠁\",\"⠁\",\"⠉\",\"⠙\",\"⠚\",\"⠒\",\"⠂\",\"⠂\",\"⠒\",\"⠲\",\"⠴\",\"⠤\",\"⠄\",\"⠄\",\"⠤\",\"⠠\",\"⠠\",\"⠤\",\"⠦\",\"⠖\",\"⠒\",\"⠐\",\"⠐\",\"⠒\",\"⠓\",\"⠋\",\"⠉\",\"⠈\",\"⠈\"]},\"dots9\":{\"interval\":80,\"frames\":[\"⢹\",\"⢺\",\"⢼\",\"⣸\",\"⣇\",\"⡧\",\"⡗\",\"⡏\"]},\"dots10\":{\"interval\":80,\"frames\":[\"⢄\",\"⢂\",\"⢁\",\"⡁\",\"⡈\",\"⡐\",\"⡠\"]},\"dots11\":{\"interval\":100,\"frames\":[\"⠁\",\"⠂\",\"⠄\",\"⡀\",\"⢀\",\"⠠\",\"⠐\",\"⠈\"]},\"dots12\":{\"interval\":80,\"frames\":[\"⢀⠀\",\"⡀⠀\",\"⠄⠀\",\"⢂⠀\",\"⡂⠀\",\"⠅⠀\",\"⢃⠀\",\"⡃⠀\",\"⠍⠀\",\"⢋⠀\",\"⡋⠀\",\"⠍⠁\",\"⢋⠁\",\"⡋⠁\",\"⠍⠉\",\"⠋⠉\",\"⠋⠉\",\"⠉⠙\",\"⠉⠙\",\"⠉⠩\",\"⠈⢙\",\"⠈⡙\",\"⢈⠩\",\"⡀⢙\",\"⠄⡙\",\"⢂⠩\",\"⡂⢘\",\"⠅⡘\",\"⢃⠨\",\"⡃⢐\",\"⠍⡐\",\"⢋⠠\",\"⡋⢀\",\"⠍⡁\",\"⢋⠁\",\"⡋⠁\",\"⠍⠉\",\"⠋⠉\",\"⠋⠉\",\"⠉⠙\",\"⠉⠙\",\"⠉⠩\",\"⠈⢙\",\"⠈⡙\",\"⠈⠩\",\"⠀⢙\",\"⠀⡙\",\"⠀⠩\",\"⠀⢘\",\"⠀⡘\",\"⠀⠨\",\"⠀⢐\",\"⠀⡐\",\"⠀⠠\",\"⠀⢀\",\"⠀⡀\"]},\"dots8Bit\":{\"interval\":80,\"frames\":[\"⠀\",\"⠁\",\"⠂\",\"⠃\",\"⠄\",\"⠅\",\"⠆\",\"⠇\",\"⡀\",\"⡁\",\"⡂\",\"⡃\",\"⡄\",\"⡅\",\"⡆\",\"⡇\",\"⠈\",\"⠉\",\"⠊\",\"⠋\",\"⠌\",\"⠍\",\"⠎\",\"⠏\",\"⡈\",\"⡉\",\"⡊\",\"⡋\",\"⡌\",\"⡍\",\"⡎\",\"⡏\",\"⠐\",\"⠑\",\"⠒\",\"⠓\",\"⠔\",\"⠕\",\"⠖\",\"⠗\",\"⡐\",\"⡑\",\"⡒\",\"⡓\",\"⡔\",\"⡕\",\"⡖\",\"⡗\",\"⠘\",\"⠙\",\"⠚\",\"⠛\",\"⠜\",\"⠝\",\"⠞\",\"⠟\",\"⡘\",\"⡙\",\"⡚\",\"⡛\",\"⡜\",\"⡝\",\"⡞\",\"⡟\",\"⠠\",\"⠡\",\"⠢\",\"⠣\",\"⠤\",\"⠥\",\"⠦\",\"⠧\",\"⡠\",\"⡡\",\"⡢\",\"⡣\",\"⡤\",\"⡥\",\"⡦\",\"⡧\",\"⠨\",\"⠩\",\"⠪\",\"⠫\",\"⠬\",\"⠭\",\"⠮\",\"⠯\",\"⡨\",\"⡩\",\"⡪\",\"⡫\",\"⡬\",\"⡭\",\"⡮\",\"⡯\",\"⠰\",\"⠱\",\"⠲\",\"⠳\",\"⠴\",\"⠵\",\"⠶\",\"⠷\",\"⡰\",\"⡱\",\"⡲\",\"⡳\",\"⡴\",\"⡵\",\"⡶\",\"⡷\",\"⠸\",\"⠹\",\"⠺\",\"⠻\",\"⠼\",\"⠽\",\"⠾\",\"⠿\",\"⡸\",\"⡹\",\"⡺\",\"⡻\",\"⡼\",\"⡽\",\"⡾\",\"⡿\",\"⢀\",\"⢁\",\"⢂\",\"⢃\",\"⢄\",\"⢅\",\"⢆\",\"⢇\",\"⣀\",\"⣁\",\"⣂\",\"⣃\",\"⣄\",\"⣅\",\"⣆\",\"⣇\",\"⢈\",\"⢉\",\"⢊\",\"⢋\",\"⢌\",\"⢍\",\"⢎\",\"⢏\",\"⣈\",\"⣉\",\"⣊\",\"⣋\",\"⣌\",\"⣍\",\"⣎\",\"⣏\",\"⢐\",\"⢑\",\"⢒\",\"⢓\",\"⢔\",\"⢕\",\"⢖\",\"⢗\",\"⣐\",\"⣑\",\"⣒\",\"⣓\",\"⣔\",\"⣕\",\"⣖\",\"⣗\",\"⢘\",\"⢙\",\"⢚\",\"⢛\",\"⢜\",\"⢝\",\"⢞\",\"⢟\",\"⣘\",\"⣙\",\"⣚\",\"⣛\",\"⣜\",\"⣝\",\"⣞\",\"⣟\",\"⢠\",\"⢡\",\"⢢\",\"⢣\",\"⢤\",\"⢥\",\"⢦\",\"⢧\",\"⣠\",\"⣡\",\"⣢\",\"⣣\",\"⣤\",\"⣥\",\"⣦\",\"⣧\",\"⢨\",\"⢩\",\"⢪\",\"⢫\",\"⢬\",\"⢭\",\"⢮\",\"⢯\",\"⣨\",\"⣩\",\"⣪\",\"⣫\",\"⣬\",\"⣭\",\"⣮\",\"⣯\",\"⢰\",\"⢱\",\"⢲\",\"⢳\",\"⢴\",\"⢵\",\"⢶\",\"⢷\",\"⣰\",\"⣱\",\"⣲\",\"⣳\",\"⣴\",\"⣵\",\"⣶\",\"⣷\",\"⢸\",\"⢹\",\"⢺\",\"⢻\",\"⢼\",\"⢽\",\"⢾\",\"⢿\",\"⣸\",\"⣹\",\"⣺\",\"⣻\",\"⣼\",\"⣽\",\"⣾\",\"⣿\"]},\"line\":{\"interval\":130,\"frames\":[\"-\",\"\\\\\",\"|\",\"/\"]},\"line2\":{\"interval\":100,\"frames\":[\"⠂\",\"-\",\"–\",\"—\",\"–\",\"-\"]},\"pipe\":{\"interval\":100,\"frames\":[\"┤\",\"┘\",\"┴\",\"└\",\"├\",\"┌\",\"┬\",\"┐\"]},\"simpleDots\":{\"interval\":400,\"frames\":[\". \",\".. \",\"...\",\" \"]},\"simpleDotsScrolling\":{\"interval\":200,\"frames\":[\". \",\".. \",\"...\",\" ..\",\" .\",\" \"]},\"star\":{\"interval\":70,\"frames\":[\"✶\",\"✸\",\"✹\",\"✺\",\"✹\",\"✷\"]},\"star2\":{\"interval\":80,\"frames\":[\"+\",\"x\",\"*\"]},\"flip\":{\"interval\":70,\"frames\":[\"_\",\"_\",\"_\",\"-\",\"`\",\"`\",\"'\",\"´\",\"-\",\"_\",\"_\",\"_\"]},\"hamburger\":{\"interval\":100,\"frames\":[\"☱\",\"☲\",\"☴\"]},\"growVertical\":{\"interval\":120,\"frames\":[\"▁\",\"▃\",\"▄\",\"▅\",\"▆\",\"▇\",\"▆\",\"▅\",\"▄\",\"▃\"]},\"growHorizontal\":{\"interval\":120,\"frames\":[\"▏\",\"▎\",\"▍\",\"▌\",\"▋\",\"▊\",\"▉\",\"▊\",\"▋\",\"▌\",\"▍\",\"▎\"]},\"balloon\":{\"interval\":140,\"frames\":[\" \",\".\",\"o\",\"O\",\"@\",\"*\",\" \"]},\"balloon2\":{\"interval\":120,\"frames\":[\".\",\"o\",\"O\",\"°\",\"O\",\"o\",\".\"]},\"noise\":{\"interval\":100,\"frames\":[\"▓\",\"▒\",\"░\"]},\"bounce\":{\"interval\":120,\"frames\":[\"⠁\",\"⠂\",\"⠄\",\"⠂\"]},\"boxBounce\":{\"interval\":120,\"frames\":[\"▖\",\"▘\",\"▝\",\"▗\"]},\"boxBounce2\":{\"interval\":100,\"frames\":[\"▌\",\"▀\",\"▐\",\"▄\"]},\"triangle\":{\"interval\":50,\"frames\":[\"◢\",\"◣\",\"◤\",\"◥\"]},\"arc\":{\"interval\":100,\"frames\":[\"◜\",\"◠\",\"◝\",\"◞\",\"◡\",\"◟\"]},\"circle\":{\"interval\":120,\"frames\":[\"◡\",\"⊙\",\"◠\"]},\"squareCorners\":{\"interval\":180,\"frames\":[\"◰\",\"◳\",\"◲\",\"◱\"]},\"circleQuarters\":{\"interval\":120,\"frames\":[\"◴\",\"◷\",\"◶\",\"◵\"]},\"circleHalves\":{\"interval\":50,\"frames\":[\"◐\",\"◓\",\"◑\",\"◒\"]},\"squish\":{\"interval\":100,\"frames\":[\"╫\",\"╪\"]},\"toggle\":{\"interval\":250,\"frames\":[\"⊶\",\"⊷\"]},\"toggle2\":{\"interval\":80,\"frames\":[\"▫\",\"▪\"]},\"toggle3\":{\"interval\":120,\"frames\":[\"□\",\"■\"]},\"toggle4\":{\"interval\":100,\"frames\":[\"■\",\"□\",\"▪\",\"▫\"]},\"toggle5\":{\"interval\":100,\"frames\":[\"▮\",\"▯\"]},\"toggle6\":{\"interval\":300,\"frames\":[\"ဝ\",\"၀\"]},\"toggle7\":{\"interval\":80,\"frames\":[\"⦾\",\"⦿\"]},\"toggle8\":{\"interval\":100,\"frames\":[\"◍\",\"◌\"]},\"toggle9\":{\"interval\":100,\"frames\":[\"◉\",\"◎\"]},\"toggle10\":{\"interval\":100,\"frames\":[\"㊂\",\"㊀\",\"㊁\"]},\"toggle11\":{\"interval\":50,\"frames\":[\"⧇\",\"⧆\"]},\"toggle12\":{\"interval\":120,\"frames\":[\"☗\",\"☖\"]},\"toggle13\":{\"interval\":80,\"frames\":[\"=\",\"*\",\"-\"]},\"arrow\":{\"interval\":100,\"frames\":[\"←\",\"↖\",\"↑\",\"↗\",\"→\",\"↘\",\"↓\",\"↙\"]},\"arrow2\":{\"interval\":80,\"frames\":[\"⬆️ \",\"↗️ \",\"➡️ \",\"↘️ \",\"⬇️ \",\"↙️ \",\"⬅️ \",\"↖️ \"]},\"arrow3\":{\"interval\":120,\"frames\":[\"▹▹▹▹▹\",\"▸▹▹▹▹\",\"▹▸▹▹▹\",\"▹▹▸▹▹\",\"▹▹▹▸▹\",\"▹▹▹▹▸\"]},\"bouncingBar\":{\"interval\":80,\"frames\":[\"[ ]\",\"[= ]\",\"[== ]\",\"[=== ]\",\"[ ===]\",\"[ ==]\",\"[ =]\",\"[ ]\",\"[ =]\",\"[ ==]\",\"[ ===]\",\"[====]\",\"[=== ]\",\"[== ]\",\"[= ]\"]},\"bouncingBall\":{\"interval\":80,\"frames\":[\"( ● )\",\"( ● )\",\"( ● )\",\"( ● )\",\"( ●)\",\"( ● )\",\"( ● )\",\"( ● )\",\"( ● )\",\"(● )\"]},\"smiley\":{\"interval\":200,\"frames\":[\"😄 \",\"😝 \"]},\"monkey\":{\"interval\":300,\"frames\":[\"🙈 \",\"🙈 \",\"🙉 \",\"🙊 \"]},\"hearts\":{\"interval\":100,\"frames\":[\"💛 \",\"💙 \",\"💜 \",\"💚 \",\"❤️ \"]},\"clock\":{\"interval\":100,\"frames\":[\"🕛 \",\"🕐 \",\"🕑 \",\"🕒 \",\"🕓 \",\"🕔 \",\"🕕 \",\"🕖 \",\"🕗 \",\"🕘 \",\"🕙 \",\"🕚 \"]},\"earth\":{\"interval\":180,\"frames\":[\"🌍 \",\"🌎 \",\"🌏 \"]},\"material\":{\"interval\":17,\"frames\":[\"█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁\",\"██▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁\",\"███▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁\",\"████▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁\",\"██████▁▁▁▁▁▁▁▁▁▁▁▁▁▁\",\"██████▁▁▁▁▁▁▁▁▁▁▁▁▁▁\",\"███████▁▁▁▁▁▁▁▁▁▁▁▁▁\",\"████████▁▁▁▁▁▁▁▁▁▁▁▁\",\"█████████▁▁▁▁▁▁▁▁▁▁▁\",\"█████████▁▁▁▁▁▁▁▁▁▁▁\",\"██████████▁▁▁▁▁▁▁▁▁▁\",\"███████████▁▁▁▁▁▁▁▁▁\",\"█████████████▁▁▁▁▁▁▁\",\"██████████████▁▁▁▁▁▁\",\"██████████████▁▁▁▁▁▁\",\"▁██████████████▁▁▁▁▁\",\"▁██████████████▁▁▁▁▁\",\"▁██████████████▁▁▁▁▁\",\"▁▁██████████████▁▁▁▁\",\"▁▁▁██████████████▁▁▁\",\"▁▁▁▁█████████████▁▁▁\",\"▁▁▁▁██████████████▁▁\",\"▁▁▁▁██████████████▁▁\",\"▁▁▁▁▁██████████████▁\",\"▁▁▁▁▁██████████████▁\",\"▁▁▁▁▁██████████████▁\",\"▁▁▁▁▁▁██████████████\",\"▁▁▁▁▁▁██████████████\",\"▁▁▁▁▁▁▁█████████████\",\"▁▁▁▁▁▁▁█████████████\",\"▁▁▁▁▁▁▁▁████████████\",\"▁▁▁▁▁▁▁▁████████████\",\"▁▁▁▁▁▁▁▁▁███████████\",\"▁▁▁▁▁▁▁▁▁███████████\",\"▁▁▁▁▁▁▁▁▁▁██████████\",\"▁▁▁▁▁▁▁▁▁▁██████████\",\"▁▁▁▁▁▁▁▁▁▁▁▁████████\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁███████\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁██████\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█████\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█████\",\"█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁████\",\"██▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁███\",\"██▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁███\",\"███▁▁▁▁▁▁▁▁▁▁▁▁▁▁███\",\"████▁▁▁▁▁▁▁▁▁▁▁▁▁▁██\",\"█████▁▁▁▁▁▁▁▁▁▁▁▁▁▁█\",\"█████▁▁▁▁▁▁▁▁▁▁▁▁▁▁█\",\"██████▁▁▁▁▁▁▁▁▁▁▁▁▁█\",\"████████▁▁▁▁▁▁▁▁▁▁▁▁\",\"█████████▁▁▁▁▁▁▁▁▁▁▁\",\"█████████▁▁▁▁▁▁▁▁▁▁▁\",\"█████████▁▁▁▁▁▁▁▁▁▁▁\",\"█████████▁▁▁▁▁▁▁▁▁▁▁\",\"███████████▁▁▁▁▁▁▁▁▁\",\"████████████▁▁▁▁▁▁▁▁\",\"████████████▁▁▁▁▁▁▁▁\",\"██████████████▁▁▁▁▁▁\",\"██████████████▁▁▁▁▁▁\",\"▁██████████████▁▁▁▁▁\",\"▁██████████████▁▁▁▁▁\",\"▁▁▁█████████████▁▁▁▁\",\"▁▁▁▁▁████████████▁▁▁\",\"▁▁▁▁▁████████████▁▁▁\",\"▁▁▁▁▁▁███████████▁▁▁\",\"▁▁▁▁▁▁▁▁█████████▁▁▁\",\"▁▁▁▁▁▁▁▁█████████▁▁▁\",\"▁▁▁▁▁▁▁▁▁█████████▁▁\",\"▁▁▁▁▁▁▁▁▁█████████▁▁\",\"▁▁▁▁▁▁▁▁▁▁█████████▁\",\"▁▁▁▁▁▁▁▁▁▁▁████████▁\",\"▁▁▁▁▁▁▁▁▁▁▁████████▁\",\"▁▁▁▁▁▁▁▁▁▁▁▁███████▁\",\"▁▁▁▁▁▁▁▁▁▁▁▁███████▁\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁███████\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁███████\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█████\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁████\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁████\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁████\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁███\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁███\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁██\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁██\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁██\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁\",\"▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁\"]},\"moon\":{\"interval\":80,\"frames\":[\"🌑 \",\"🌒 \",\"🌓 \",\"🌔 \",\"🌕 \",\"🌖 \",\"🌗 \",\"🌘 \"]},\"runner\":{\"interval\":140,\"frames\":[\"🚶 \",\"🏃 \"]},\"pong\":{\"interval\":80,\"frames\":[\"▐⠂ ▌\",\"▐⠈ ▌\",\"▐ ⠂ ▌\",\"▐ ⠠ ▌\",\"▐ ⡀ ▌\",\"▐ ⠠ ▌\",\"▐ ⠂ ▌\",\"▐ ⠈ ▌\",\"▐ ⠂ ▌\",\"▐ ⠠ ▌\",\"▐ ⡀ ▌\",\"▐ ⠠ ▌\",\"▐ ⠂ ▌\",\"▐ ⠈ ▌\",\"▐ ⠂▌\",\"▐ ⠠▌\",\"▐ ⡀▌\",\"▐ ⠠ ▌\",\"▐ ⠂ ▌\",\"▐ ⠈ ▌\",\"▐ ⠂ ▌\",\"▐ ⠠ ▌\",\"▐ ⡀ ▌\",\"▐ ⠠ ▌\",\"▐ ⠂ ▌\",\"▐ ⠈ ▌\",\"▐ ⠂ ▌\",\"▐ ⠠ ▌\",\"▐ ⡀ ▌\",\"▐⠠ ▌\"]},\"shark\":{\"interval\":120,\"frames\":[\"▐|\\\\____________▌\",\"▐_|\\\\___________▌\",\"▐__|\\\\__________▌\",\"▐___|\\\\_________▌\",\"▐____|\\\\________▌\",\"▐_____|\\\\_______▌\",\"▐______|\\\\______▌\",\"▐_______|\\\\_____▌\",\"▐________|\\\\____▌\",\"▐_________|\\\\___▌\",\"▐__________|\\\\__▌\",\"▐___________|\\\\_▌\",\"▐____________|\\\\▌\",\"▐____________/|▌\",\"▐___________/|_▌\",\"▐__________/|__▌\",\"▐_________/|___▌\",\"▐________/|____▌\",\"▐_______/|_____▌\",\"▐______/|______▌\",\"▐_____/|_______▌\",\"▐____/|________▌\",\"▐___/|_________▌\",\"▐__/|__________▌\",\"▐_/|___________▌\",\"▐/|____________▌\"]},\"dqpb\":{\"interval\":100,\"frames\":[\"d\",\"q\",\"p\",\"b\"]},\"weather\":{\"interval\":100,\"frames\":[\"☀️ \",\"☀️ \",\"☀️ \",\"🌤 \",\"⛅️ \",\"🌥 \",\"☁️ \",\"🌧 \",\"🌨 \",\"🌧 \",\"🌨 \",\"🌧 \",\"🌨 \",\"⛈ \",\"🌨 \",\"🌧 \",\"🌨 \",\"☁️ \",\"🌥 \",\"⛅️ \",\"🌤 \",\"☀️ \",\"☀️ \"]},\"christmas\":{\"interval\":400,\"frames\":[\"🌲\",\"🎄\"]},\"grenade\":{\"interval\":80,\"frames\":[\"، \",\"′ \",\" ´ \",\" ‾ \",\" ⸌\",\" ⸊\",\" |\",\" ⁎\",\" ⁕\",\" ෴ \",\" ⁓\",\" \",\" \",\" \"]},\"point\":{\"interval\":125,\"frames\":[\"∙∙∙\",\"●∙∙\",\"∙●∙\",\"∙∙●\",\"∙∙∙\"]},\"layer\":{\"interval\":150,\"frames\":[\"-\",\"=\",\"≡\"]},\"betaWave\":{\"interval\":80,\"frames\":[\"ρββββββ\",\"βρβββββ\",\"ββρββββ\",\"βββρβββ\",\"ββββρββ\",\"βββββρβ\",\"ββββββρ\"]},\"aesthetic\":{\"interval\":80,\"frames\":[\"▰▱▱▱▱▱▱\",\"▰▰▱▱▱▱▱\",\"▰▰▰▱▱▱▱\",\"▰▰▰▰▱▱▱\",\"▰▰▰▰▰▱▱\",\"▰▰▰▰▰▰▱\",\"▰▰▰▰▰▰▰\",\"▰▱▱▱▱▱▱\"]}}"); /***/ }), -/* 536 */ +/* 544 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const chalk = __webpack_require__(537); +const chalk = __webpack_require__(545); const isSupported = process.platform !== 'win32' || process.env.CI || process.env.TERM === 'xterm-256color'; @@ -61390,16 +62036,16 @@ module.exports = isSupported ? main : fallbacks; /***/ }), -/* 537 */ +/* 545 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const escapeStringRegexp = __webpack_require__(363); -const ansiStyles = __webpack_require__(538); -const stdoutColor = __webpack_require__(539).stdout; +const ansiStyles = __webpack_require__(546); +const stdoutColor = __webpack_require__(547).stdout; -const template = __webpack_require__(541); +const template = __webpack_require__(549); const isSimpleWindowsTerm = process.platform === 'win32' && !(process.env.TERM || '').toLowerCase().startsWith('xterm'); @@ -61625,7 +62271,7 @@ module.exports.default = module.exports; // For TypeScript /***/ }), -/* 538 */ +/* 546 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -61798,13 +62444,13 @@ Object.defineProperty(module, 'exports', { /* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(116)(module))) /***/ }), -/* 539 */ +/* 547 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const os = __webpack_require__(122); -const hasFlag = __webpack_require__(540); +const hasFlag = __webpack_require__(548); const env = process.env; @@ -61936,7 +62582,7 @@ module.exports = { /***/ }), -/* 540 */ +/* 548 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -61951,7 +62597,7 @@ module.exports = (flag, argv) => { /***/ }), -/* 541 */ +/* 549 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -62086,18 +62732,18 @@ module.exports = (chalk, tmp) => { /***/ }), -/* 542 */ +/* 550 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const ansiRegex = __webpack_require__(543); +const ansiRegex = __webpack_require__(551); module.exports = string => typeof string === 'string' ? string.replace(ansiRegex(), '') : string; /***/ }), -/* 543 */ +/* 551 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -62114,14 +62760,14 @@ module.exports = ({onlyFirst = false} = {}) => { /***/ }), -/* 544 */ +/* 552 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var defaults = __webpack_require__(545) -var combining = __webpack_require__(547) +var defaults = __webpack_require__(553) +var combining = __webpack_require__(555) var DEFAULTS = { nul: 0, @@ -62220,10 +62866,10 @@ function bisearch(ucs) { /***/ }), -/* 545 */ +/* 553 */ /***/ (function(module, exports, __webpack_require__) { -var clone = __webpack_require__(546); +var clone = __webpack_require__(554); module.exports = function(options, defaults) { options = options || {}; @@ -62238,7 +62884,7 @@ module.exports = function(options, defaults) { }; /***/ }), -/* 546 */ +/* 554 */ /***/ (function(module, exports, __webpack_require__) { var clone = (function() { @@ -62410,7 +63056,7 @@ if ( true && module.exports) { /***/ }), -/* 547 */ +/* 555 */ /***/ (function(module, exports) { module.exports = [ @@ -62466,7 +63112,7 @@ module.exports = [ /***/ }), -/* 548 */ +/* 556 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -62482,7 +63128,7 @@ module.exports = ({stream = process.stdout} = {}) => { /***/ }), -/* 549 */ +/* 557 */ /***/ (function(module, exports, __webpack_require__) { var Stream = __webpack_require__(173) @@ -62633,7 +63279,7 @@ MuteStream.prototype.close = proxy('close') /***/ }), -/* 550 */ +/* 558 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -62643,11 +63289,11 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var dedent__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(dedent__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(240); /* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(del__WEBPACK_IMPORTED_MODULE_1__); -/* harmony import */ var ora__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(527); +/* harmony import */ var ora__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(535); /* harmony import */ var ora__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(ora__WEBPACK_IMPORTED_MODULE_2__); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(4); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_3__); -/* harmony import */ var _utils_bazel__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(419); +/* harmony import */ var _utils_bazel__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(427); /* harmony import */ var _utils_fs__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(231); /* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(220); /* @@ -62756,7 +63402,7 @@ const ResetCommand = { }; /***/ }), -/* 551 */ +/* 559 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -62766,7 +63412,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var dedent__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(dedent__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _utils_errors__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(347); /* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(220); -/* harmony import */ var _utils_parallelize__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(552); +/* harmony import */ var _utils_parallelize__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(560); /* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(346); /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one @@ -62825,7 +63471,7 @@ const RunCommand = { }; /***/ }), -/* 552 */ +/* 560 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -62880,13 +63526,13 @@ async function parallelize(items, fn, concurrency = 4) { } /***/ }), -/* 553 */ +/* 561 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "WatchCommand", function() { return WatchCommand; }); -/* harmony import */ var _utils_bazel__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(419); +/* harmony import */ var _utils_bazel__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(427); /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License @@ -62917,7 +63563,7 @@ const WatchCommand = { }; /***/ }), -/* 554 */ +/* 562 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -62997,7 +63643,7 @@ const PatchNativeModulesCommand = { }; /***/ }), -/* 555 */ +/* 563 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -63008,8 +63654,8 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var _utils_errors__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(347); /* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(220); /* harmony import */ var _utils_projects__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(346); -/* harmony import */ var _utils_projects_tree__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(418); -/* harmony import */ var _utils_kibana__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(556); +/* harmony import */ var _utils_projects_tree__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(426); +/* harmony import */ var _utils_kibana__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(564); function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } @@ -63128,7 +63774,7 @@ function toArray(value) { } /***/ }), -/* 556 */ +/* 564 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -63138,13 +63784,13 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(132); /* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_1__); -/* harmony import */ var multimatch__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(557); +/* harmony import */ var multimatch__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(565); /* harmony import */ var multimatch__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(multimatch__WEBPACK_IMPORTED_MODULE_2__); /* harmony import */ var is_path_inside__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(339); /* harmony import */ var is_path_inside__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(is_path_inside__WEBPACK_IMPORTED_MODULE_3__); /* harmony import */ var _yarn_lock__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(414); /* harmony import */ var _projects__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(346); -/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(560); +/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(568); function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } @@ -63308,15 +63954,15 @@ class Kibana { } /***/ }), -/* 557 */ +/* 565 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const minimatch = __webpack_require__(247); const arrayUnion = __webpack_require__(242); -const arrayDiffer = __webpack_require__(558); -const arrify = __webpack_require__(559); +const arrayDiffer = __webpack_require__(566); +const arrify = __webpack_require__(567); module.exports = (list, patterns, options = {}) => { list = arrify(list); @@ -63340,7 +63986,7 @@ module.exports = (list, patterns, options = {}) => { /***/ }), -/* 558 */ +/* 566 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -63355,7 +64001,7 @@ module.exports = arrayDiffer; /***/ }), -/* 559 */ +/* 567 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -63385,7 +64031,7 @@ module.exports = arrify; /***/ }), -/* 560 */ +/* 568 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -63445,15 +64091,15 @@ function getProjectPaths({ } /***/ }), -/* 561 */ +/* 569 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); -/* harmony import */ var _build_bazel_production_projects__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(562); +/* harmony import */ var _build_bazel_production_projects__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(570); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "buildBazelProductionProjects", function() { return _build_bazel_production_projects__WEBPACK_IMPORTED_MODULE_0__["buildBazelProductionProjects"]; }); -/* harmony import */ var _build_non_bazel_production_projects__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(809); +/* harmony import */ var _build_non_bazel_production_projects__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(817); /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "buildNonBazelProductionProjects", function() { return _build_non_bazel_production_projects__WEBPACK_IMPORTED_MODULE_1__["buildNonBazelProductionProjects"]; }); /* @@ -63467,20 +64113,20 @@ __webpack_require__.r(__webpack_exports__); /***/ }), -/* 562 */ +/* 570 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "buildBazelProductionProjects", function() { return buildBazelProductionProjects; }); -/* harmony import */ var cpy__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(563); +/* harmony import */ var cpy__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(571); /* harmony import */ var cpy__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(cpy__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var globby__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(775); +/* harmony import */ var globby__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(783); /* harmony import */ var globby__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(globby__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(4); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_2__); -/* harmony import */ var _build_non_bazel_production_projects__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(809); -/* harmony import */ var _utils_bazel__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(419); +/* harmony import */ var _build_non_bazel_production_projects__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(817); +/* harmony import */ var _utils_bazel__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(427); /* harmony import */ var _utils_fs__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(231); /* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(220); /* harmony import */ var _utils_package_json__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(349); @@ -63574,7 +64220,7 @@ async function applyCorrectPermissions(project, kibanaRoot, buildRoot) { } /***/ }), -/* 563 */ +/* 571 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -63582,14 +64228,14 @@ async function applyCorrectPermissions(project, kibanaRoot, buildRoot) { const EventEmitter = __webpack_require__(164); const path = __webpack_require__(4); const os = __webpack_require__(122); -const pMap = __webpack_require__(564); -const arrify = __webpack_require__(559); -const globby = __webpack_require__(567); -const hasGlob = __webpack_require__(759); -const cpFile = __webpack_require__(761); -const junk = __webpack_require__(771); -const pFilter = __webpack_require__(772); -const CpyError = __webpack_require__(774); +const pMap = __webpack_require__(572); +const arrify = __webpack_require__(567); +const globby = __webpack_require__(575); +const hasGlob = __webpack_require__(767); +const cpFile = __webpack_require__(769); +const junk = __webpack_require__(779); +const pFilter = __webpack_require__(780); +const CpyError = __webpack_require__(782); const defaultOptions = { ignoreJunk: true @@ -63740,12 +64386,12 @@ module.exports = (source, destination, { /***/ }), -/* 564 */ +/* 572 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const AggregateError = __webpack_require__(565); +const AggregateError = __webpack_require__(573); module.exports = async ( iterable, @@ -63828,12 +64474,12 @@ module.exports = async ( /***/ }), -/* 565 */ +/* 573 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const indentString = __webpack_require__(566); +const indentString = __webpack_require__(574); const cleanStack = __webpack_require__(344); const cleanInternalStack = stack => stack.replace(/\s+at .*aggregate-error\/index.js:\d+:\d+\)?/g, ''); @@ -63882,7 +64528,7 @@ module.exports = AggregateError; /***/ }), -/* 566 */ +/* 574 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -63924,17 +64570,17 @@ module.exports = (string, count = 1, options) => { /***/ }), -/* 567 */ +/* 575 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const fs = __webpack_require__(132); -const arrayUnion = __webpack_require__(568); +const arrayUnion = __webpack_require__(576); const glob = __webpack_require__(244); -const fastGlob = __webpack_require__(570); -const dirGlob = __webpack_require__(753); -const gitignore = __webpack_require__(756); +const fastGlob = __webpack_require__(578); +const dirGlob = __webpack_require__(761); +const gitignore = __webpack_require__(764); const DEFAULT_FILTER = () => false; @@ -64079,12 +64725,12 @@ module.exports.gitignore = gitignore; /***/ }), -/* 568 */ +/* 576 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var arrayUniq = __webpack_require__(569); +var arrayUniq = __webpack_require__(577); module.exports = function () { return arrayUniq([].concat.apply([], arguments)); @@ -64092,7 +64738,7 @@ module.exports = function () { /***/ }), -/* 569 */ +/* 577 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -64161,10 +64807,10 @@ if ('Set' in global) { /***/ }), -/* 570 */ +/* 578 */ /***/ (function(module, exports, __webpack_require__) { -const pkg = __webpack_require__(571); +const pkg = __webpack_require__(579); module.exports = pkg.async; module.exports.default = pkg.async; @@ -64177,19 +64823,19 @@ module.exports.generateTasks = pkg.generateTasks; /***/ }), -/* 571 */ +/* 579 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var optionsManager = __webpack_require__(572); -var taskManager = __webpack_require__(573); -var reader_async_1 = __webpack_require__(724); -var reader_stream_1 = __webpack_require__(748); -var reader_sync_1 = __webpack_require__(749); -var arrayUtils = __webpack_require__(751); -var streamUtils = __webpack_require__(752); +var optionsManager = __webpack_require__(580); +var taskManager = __webpack_require__(581); +var reader_async_1 = __webpack_require__(732); +var reader_stream_1 = __webpack_require__(756); +var reader_sync_1 = __webpack_require__(757); +var arrayUtils = __webpack_require__(759); +var streamUtils = __webpack_require__(760); /** * Synchronous API. */ @@ -64255,7 +64901,7 @@ function isString(source) { /***/ }), -/* 572 */ +/* 580 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -64293,13 +64939,13 @@ exports.prepare = prepare; /***/ }), -/* 573 */ +/* 581 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var patternUtils = __webpack_require__(574); +var patternUtils = __webpack_require__(582); /** * Generate tasks based on parent directory of each pattern. */ @@ -64390,16 +65036,16 @@ exports.convertPatternGroupToTask = convertPatternGroupToTask; /***/ }), -/* 574 */ +/* 582 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var path = __webpack_require__(4); -var globParent = __webpack_require__(575); +var globParent = __webpack_require__(583); var isGlob = __webpack_require__(266); -var micromatch = __webpack_require__(578); +var micromatch = __webpack_require__(586); var GLOBSTAR = '**'; /** * Return true for static pattern. @@ -64545,15 +65191,15 @@ exports.matchAny = matchAny; /***/ }), -/* 575 */ +/* 583 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var path = __webpack_require__(4); -var isglob = __webpack_require__(576); -var pathDirname = __webpack_require__(577); +var isglob = __webpack_require__(584); +var pathDirname = __webpack_require__(585); var isWin32 = __webpack_require__(122).platform() === 'win32'; module.exports = function globParent(str) { @@ -64576,7 +65222,7 @@ module.exports = function globParent(str) { /***/ }), -/* 576 */ +/* 584 */ /***/ (function(module, exports, __webpack_require__) { /*! @@ -64607,7 +65253,7 @@ module.exports = function isGlob(str) { /***/ }), -/* 577 */ +/* 585 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -64757,7 +65403,7 @@ module.exports.win32 = win32; /***/ }), -/* 578 */ +/* 586 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -64768,18 +65414,18 @@ module.exports.win32 = win32; */ var util = __webpack_require__(113); -var braces = __webpack_require__(579); -var toRegex = __webpack_require__(580); -var extend = __webpack_require__(692); +var braces = __webpack_require__(587); +var toRegex = __webpack_require__(588); +var extend = __webpack_require__(700); /** * Local dependencies */ -var compilers = __webpack_require__(694); -var parsers = __webpack_require__(720); -var cache = __webpack_require__(721); -var utils = __webpack_require__(722); +var compilers = __webpack_require__(702); +var parsers = __webpack_require__(728); +var cache = __webpack_require__(729); +var utils = __webpack_require__(730); var MAX_LENGTH = 1024 * 64; /** @@ -65641,7 +66287,7 @@ module.exports = micromatch; /***/ }), -/* 579 */ +/* 587 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -65651,18 +66297,18 @@ module.exports = micromatch; * Module dependencies */ -var toRegex = __webpack_require__(580); -var unique = __webpack_require__(600); -var extend = __webpack_require__(601); +var toRegex = __webpack_require__(588); +var unique = __webpack_require__(608); +var extend = __webpack_require__(609); /** * Local dependencies */ -var compilers = __webpack_require__(603); -var parsers = __webpack_require__(618); -var Braces = __webpack_require__(623); -var utils = __webpack_require__(604); +var compilers = __webpack_require__(611); +var parsers = __webpack_require__(626); +var Braces = __webpack_require__(631); +var utils = __webpack_require__(612); var MAX_LENGTH = 1024 * 64; var cache = {}; @@ -65966,16 +66612,16 @@ module.exports = braces; /***/ }), -/* 580 */ +/* 588 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var safe = __webpack_require__(581); -var define = __webpack_require__(587); -var extend = __webpack_require__(593); -var not = __webpack_require__(597); +var safe = __webpack_require__(589); +var define = __webpack_require__(595); +var extend = __webpack_require__(601); +var not = __webpack_require__(605); var MAX_LENGTH = 1024 * 64; /** @@ -66128,10 +66774,10 @@ module.exports.makeRe = makeRe; /***/ }), -/* 581 */ +/* 589 */ /***/ (function(module, exports, __webpack_require__) { -var parse = __webpack_require__(582); +var parse = __webpack_require__(590); var types = parse.types; module.exports = function (re, opts) { @@ -66177,13 +66823,13 @@ function isRegExp (x) { /***/ }), -/* 582 */ +/* 590 */ /***/ (function(module, exports, __webpack_require__) { -var util = __webpack_require__(583); -var types = __webpack_require__(584); -var sets = __webpack_require__(585); -var positions = __webpack_require__(586); +var util = __webpack_require__(591); +var types = __webpack_require__(592); +var sets = __webpack_require__(593); +var positions = __webpack_require__(594); module.exports = function(regexpStr) { @@ -66465,11 +67111,11 @@ module.exports.types = types; /***/ }), -/* 583 */ +/* 591 */ /***/ (function(module, exports, __webpack_require__) { -var types = __webpack_require__(584); -var sets = __webpack_require__(585); +var types = __webpack_require__(592); +var sets = __webpack_require__(593); // All of these are private and only used by randexp. @@ -66582,7 +67228,7 @@ exports.error = function(regexp, msg) { /***/ }), -/* 584 */ +/* 592 */ /***/ (function(module, exports) { module.exports = { @@ -66598,10 +67244,10 @@ module.exports = { /***/ }), -/* 585 */ +/* 593 */ /***/ (function(module, exports, __webpack_require__) { -var types = __webpack_require__(584); +var types = __webpack_require__(592); var INTS = function() { return [{ type: types.RANGE , from: 48, to: 57 }]; @@ -66686,10 +67332,10 @@ exports.anyChar = function() { /***/ }), -/* 586 */ +/* 594 */ /***/ (function(module, exports, __webpack_require__) { -var types = __webpack_require__(584); +var types = __webpack_require__(592); exports.wordBoundary = function() { return { type: types.POSITION, value: 'b' }; @@ -66709,7 +67355,7 @@ exports.end = function() { /***/ }), -/* 587 */ +/* 595 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -66722,8 +67368,8 @@ exports.end = function() { -var isobject = __webpack_require__(588); -var isDescriptor = __webpack_require__(589); +var isobject = __webpack_require__(596); +var isDescriptor = __webpack_require__(597); var define = (typeof Reflect !== 'undefined' && Reflect.defineProperty) ? Reflect.defineProperty : Object.defineProperty; @@ -66754,7 +67400,7 @@ module.exports = function defineProperty(obj, key, val) { /***/ }), -/* 588 */ +/* 596 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -66773,7 +67419,7 @@ module.exports = function isObject(val) { /***/ }), -/* 589 */ +/* 597 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -66786,9 +67432,9 @@ module.exports = function isObject(val) { -var typeOf = __webpack_require__(590); -var isAccessor = __webpack_require__(591); -var isData = __webpack_require__(592); +var typeOf = __webpack_require__(598); +var isAccessor = __webpack_require__(599); +var isData = __webpack_require__(600); module.exports = function isDescriptor(obj, key) { if (typeOf(obj) !== 'object') { @@ -66802,7 +67448,7 @@ module.exports = function isDescriptor(obj, key) { /***/ }), -/* 590 */ +/* 598 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -66937,7 +67583,7 @@ function isBuffer(val) { /***/ }), -/* 591 */ +/* 599 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -66950,7 +67596,7 @@ function isBuffer(val) { -var typeOf = __webpack_require__(590); +var typeOf = __webpack_require__(598); // accessor descriptor properties var accessor = { @@ -67013,7 +67659,7 @@ module.exports = isAccessorDescriptor; /***/ }), -/* 592 */ +/* 600 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -67026,7 +67672,7 @@ module.exports = isAccessorDescriptor; -var typeOf = __webpack_require__(590); +var typeOf = __webpack_require__(598); module.exports = function isDataDescriptor(obj, prop) { // data descriptor properties @@ -67069,14 +67715,14 @@ module.exports = function isDataDescriptor(obj, prop) { /***/ }), -/* 593 */ +/* 601 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isExtendable = __webpack_require__(594); -var assignSymbols = __webpack_require__(596); +var isExtendable = __webpack_require__(602); +var assignSymbols = __webpack_require__(604); module.exports = Object.assign || function(obj/*, objects*/) { if (obj === null || typeof obj === 'undefined') { @@ -67136,7 +67782,7 @@ function isEnum(obj, key) { /***/ }), -/* 594 */ +/* 602 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -67149,7 +67795,7 @@ function isEnum(obj, key) { -var isPlainObject = __webpack_require__(595); +var isPlainObject = __webpack_require__(603); module.exports = function isExtendable(val) { return isPlainObject(val) || typeof val === 'function' || Array.isArray(val); @@ -67157,7 +67803,7 @@ module.exports = function isExtendable(val) { /***/ }), -/* 595 */ +/* 603 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -67170,7 +67816,7 @@ module.exports = function isExtendable(val) { -var isObject = __webpack_require__(588); +var isObject = __webpack_require__(596); function isObjectObject(o) { return isObject(o) === true @@ -67201,7 +67847,7 @@ module.exports = function isPlainObject(o) { /***/ }), -/* 596 */ +/* 604 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -67248,14 +67894,14 @@ module.exports = function(receiver, objects) { /***/ }), -/* 597 */ +/* 605 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var extend = __webpack_require__(598); -var safe = __webpack_require__(581); +var extend = __webpack_require__(606); +var safe = __webpack_require__(589); /** * The main export is a function that takes a `pattern` string and an `options` object. @@ -67327,14 +67973,14 @@ module.exports = toRegex; /***/ }), -/* 598 */ +/* 606 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isExtendable = __webpack_require__(599); -var assignSymbols = __webpack_require__(596); +var isExtendable = __webpack_require__(607); +var assignSymbols = __webpack_require__(604); module.exports = Object.assign || function(obj/*, objects*/) { if (obj === null || typeof obj === 'undefined') { @@ -67394,7 +68040,7 @@ function isEnum(obj, key) { /***/ }), -/* 599 */ +/* 607 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -67407,7 +68053,7 @@ function isEnum(obj, key) { -var isPlainObject = __webpack_require__(595); +var isPlainObject = __webpack_require__(603); module.exports = function isExtendable(val) { return isPlainObject(val) || typeof val === 'function' || Array.isArray(val); @@ -67415,7 +68061,7 @@ module.exports = function isExtendable(val) { /***/ }), -/* 600 */ +/* 608 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -67465,13 +68111,13 @@ module.exports.immutable = function uniqueImmutable(arr) { /***/ }), -/* 601 */ +/* 609 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isObject = __webpack_require__(602); +var isObject = __webpack_require__(610); module.exports = function extend(o/*, objects*/) { if (!isObject(o)) { o = {}; } @@ -67505,7 +68151,7 @@ function hasOwn(obj, key) { /***/ }), -/* 602 */ +/* 610 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -67525,13 +68171,13 @@ module.exports = function isExtendable(val) { /***/ }), -/* 603 */ +/* 611 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var utils = __webpack_require__(604); +var utils = __webpack_require__(612); module.exports = function(braces, options) { braces.compiler @@ -67814,25 +68460,25 @@ function hasQueue(node) { /***/ }), -/* 604 */ +/* 612 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var splitString = __webpack_require__(605); +var splitString = __webpack_require__(613); var utils = module.exports; /** * Module dependencies */ -utils.extend = __webpack_require__(601); -utils.flatten = __webpack_require__(608); -utils.isObject = __webpack_require__(588); -utils.fillRange = __webpack_require__(609); -utils.repeat = __webpack_require__(617); -utils.unique = __webpack_require__(600); +utils.extend = __webpack_require__(609); +utils.flatten = __webpack_require__(616); +utils.isObject = __webpack_require__(596); +utils.fillRange = __webpack_require__(617); +utils.repeat = __webpack_require__(625); +utils.unique = __webpack_require__(608); utils.define = function(obj, key, val) { Object.defineProperty(obj, key, { @@ -68164,7 +68810,7 @@ utils.escapeRegex = function(str) { /***/ }), -/* 605 */ +/* 613 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -68177,7 +68823,7 @@ utils.escapeRegex = function(str) { -var extend = __webpack_require__(606); +var extend = __webpack_require__(614); module.exports = function(str, options, fn) { if (typeof str !== 'string') { @@ -68342,14 +68988,14 @@ function keepEscaping(opts, str, idx) { /***/ }), -/* 606 */ +/* 614 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isExtendable = __webpack_require__(607); -var assignSymbols = __webpack_require__(596); +var isExtendable = __webpack_require__(615); +var assignSymbols = __webpack_require__(604); module.exports = Object.assign || function(obj/*, objects*/) { if (obj === null || typeof obj === 'undefined') { @@ -68409,7 +69055,7 @@ function isEnum(obj, key) { /***/ }), -/* 607 */ +/* 615 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -68422,7 +69068,7 @@ function isEnum(obj, key) { -var isPlainObject = __webpack_require__(595); +var isPlainObject = __webpack_require__(603); module.exports = function isExtendable(val) { return isPlainObject(val) || typeof val === 'function' || Array.isArray(val); @@ -68430,7 +69076,7 @@ module.exports = function isExtendable(val) { /***/ }), -/* 608 */ +/* 616 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -68459,7 +69105,7 @@ function flat(arr, res) { /***/ }), -/* 609 */ +/* 617 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -68473,10 +69119,10 @@ function flat(arr, res) { var util = __webpack_require__(113); -var isNumber = __webpack_require__(610); -var extend = __webpack_require__(613); -var repeat = __webpack_require__(615); -var toRegex = __webpack_require__(616); +var isNumber = __webpack_require__(618); +var extend = __webpack_require__(621); +var repeat = __webpack_require__(623); +var toRegex = __webpack_require__(624); /** * Return a range of numbers or letters. @@ -68674,7 +69320,7 @@ module.exports = fillRange; /***/ }), -/* 610 */ +/* 618 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -68687,7 +69333,7 @@ module.exports = fillRange; -var typeOf = __webpack_require__(611); +var typeOf = __webpack_require__(619); module.exports = function isNumber(num) { var type = typeOf(num); @@ -68703,10 +69349,10 @@ module.exports = function isNumber(num) { /***/ }), -/* 611 */ +/* 619 */ /***/ (function(module, exports, __webpack_require__) { -var isBuffer = __webpack_require__(612); +var isBuffer = __webpack_require__(620); var toString = Object.prototype.toString; /** @@ -68825,7 +69471,7 @@ module.exports = function kindOf(val) { /***/ }), -/* 612 */ +/* 620 */ /***/ (function(module, exports) { /*! @@ -68852,13 +69498,13 @@ function isSlowBuffer (obj) { /***/ }), -/* 613 */ +/* 621 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isObject = __webpack_require__(614); +var isObject = __webpack_require__(622); module.exports = function extend(o/*, objects*/) { if (!isObject(o)) { o = {}; } @@ -68892,7 +69538,7 @@ function hasOwn(obj, key) { /***/ }), -/* 614 */ +/* 622 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -68912,7 +69558,7 @@ module.exports = function isExtendable(val) { /***/ }), -/* 615 */ +/* 623 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -68989,7 +69635,7 @@ function repeat(str, num) { /***/ }), -/* 616 */ +/* 624 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -69002,8 +69648,8 @@ function repeat(str, num) { -var repeat = __webpack_require__(615); -var isNumber = __webpack_require__(610); +var repeat = __webpack_require__(623); +var isNumber = __webpack_require__(618); var cache = {}; function toRegexRange(min, max, options) { @@ -69290,7 +69936,7 @@ module.exports = toRegexRange; /***/ }), -/* 617 */ +/* 625 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -69315,14 +69961,14 @@ module.exports = function repeat(ele, num) { /***/ }), -/* 618 */ +/* 626 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var Node = __webpack_require__(619); -var utils = __webpack_require__(604); +var Node = __webpack_require__(627); +var utils = __webpack_require__(612); /** * Braces parsers @@ -69682,15 +70328,15 @@ function concatNodes(pos, node, parent, options) { /***/ }), -/* 619 */ +/* 627 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isObject = __webpack_require__(588); -var define = __webpack_require__(620); -var utils = __webpack_require__(621); +var isObject = __webpack_require__(596); +var define = __webpack_require__(628); +var utils = __webpack_require__(629); var ownNames; /** @@ -70181,7 +70827,7 @@ exports = module.exports = Node; /***/ }), -/* 620 */ +/* 628 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -70194,7 +70840,7 @@ exports = module.exports = Node; -var isDescriptor = __webpack_require__(589); +var isDescriptor = __webpack_require__(597); module.exports = function defineProperty(obj, prop, val) { if (typeof obj !== 'object' && typeof obj !== 'function') { @@ -70219,13 +70865,13 @@ module.exports = function defineProperty(obj, prop, val) { /***/ }), -/* 621 */ +/* 629 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var typeOf = __webpack_require__(622); +var typeOf = __webpack_require__(630); var utils = module.exports; /** @@ -71245,10 +71891,10 @@ function assert(val, message) { /***/ }), -/* 622 */ +/* 630 */ /***/ (function(module, exports, __webpack_require__) { -var isBuffer = __webpack_require__(612); +var isBuffer = __webpack_require__(620); var toString = Object.prototype.toString; /** @@ -71367,17 +72013,17 @@ module.exports = function kindOf(val) { /***/ }), -/* 623 */ +/* 631 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var extend = __webpack_require__(601); -var Snapdragon = __webpack_require__(624); -var compilers = __webpack_require__(603); -var parsers = __webpack_require__(618); -var utils = __webpack_require__(604); +var extend = __webpack_require__(609); +var Snapdragon = __webpack_require__(632); +var compilers = __webpack_require__(611); +var parsers = __webpack_require__(626); +var utils = __webpack_require__(612); /** * Customize Snapdragon parser and renderer @@ -71478,17 +72124,17 @@ module.exports = Braces; /***/ }), -/* 624 */ +/* 632 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var Base = __webpack_require__(625); -var define = __webpack_require__(655); -var Compiler = __webpack_require__(666); -var Parser = __webpack_require__(689); -var utils = __webpack_require__(669); +var Base = __webpack_require__(633); +var define = __webpack_require__(663); +var Compiler = __webpack_require__(674); +var Parser = __webpack_require__(697); +var utils = __webpack_require__(677); var regexCache = {}; var cache = {}; @@ -71659,20 +72305,20 @@ module.exports.Parser = Parser; /***/ }), -/* 625 */ +/* 633 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var util = __webpack_require__(113); -var define = __webpack_require__(626); -var CacheBase = __webpack_require__(627); -var Emitter = __webpack_require__(628); -var isObject = __webpack_require__(588); -var merge = __webpack_require__(649); -var pascal = __webpack_require__(652); -var cu = __webpack_require__(653); +var define = __webpack_require__(634); +var CacheBase = __webpack_require__(635); +var Emitter = __webpack_require__(636); +var isObject = __webpack_require__(596); +var merge = __webpack_require__(657); +var pascal = __webpack_require__(660); +var cu = __webpack_require__(661); /** * Optionally define a custom `cache` namespace to use. @@ -72101,7 +72747,7 @@ module.exports.namespace = namespace; /***/ }), -/* 626 */ +/* 634 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -72114,7 +72760,7 @@ module.exports.namespace = namespace; -var isDescriptor = __webpack_require__(589); +var isDescriptor = __webpack_require__(597); module.exports = function defineProperty(obj, prop, val) { if (typeof obj !== 'object' && typeof obj !== 'function') { @@ -72139,21 +72785,21 @@ module.exports = function defineProperty(obj, prop, val) { /***/ }), -/* 627 */ +/* 635 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isObject = __webpack_require__(588); -var Emitter = __webpack_require__(628); -var visit = __webpack_require__(629); -var toPath = __webpack_require__(632); -var union = __webpack_require__(634); -var del = __webpack_require__(640); -var get = __webpack_require__(637); -var has = __webpack_require__(645); -var set = __webpack_require__(648); +var isObject = __webpack_require__(596); +var Emitter = __webpack_require__(636); +var visit = __webpack_require__(637); +var toPath = __webpack_require__(640); +var union = __webpack_require__(642); +var del = __webpack_require__(648); +var get = __webpack_require__(645); +var has = __webpack_require__(653); +var set = __webpack_require__(656); /** * Create a `Cache` constructor that when instantiated will @@ -72407,7 +73053,7 @@ module.exports.namespace = namespace; /***/ }), -/* 628 */ +/* 636 */ /***/ (function(module, exports, __webpack_require__) { @@ -72576,7 +73222,7 @@ Emitter.prototype.hasListeners = function(event){ /***/ }), -/* 629 */ +/* 637 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -72589,8 +73235,8 @@ Emitter.prototype.hasListeners = function(event){ -var visit = __webpack_require__(630); -var mapVisit = __webpack_require__(631); +var visit = __webpack_require__(638); +var mapVisit = __webpack_require__(639); module.exports = function(collection, method, val) { var result; @@ -72613,7 +73259,7 @@ module.exports = function(collection, method, val) { /***/ }), -/* 630 */ +/* 638 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -72626,7 +73272,7 @@ module.exports = function(collection, method, val) { -var isObject = __webpack_require__(588); +var isObject = __webpack_require__(596); module.exports = function visit(thisArg, method, target, val) { if (!isObject(thisArg) && typeof thisArg !== 'function') { @@ -72653,14 +73299,14 @@ module.exports = function visit(thisArg, method, target, val) { /***/ }), -/* 631 */ +/* 639 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var util = __webpack_require__(113); -var visit = __webpack_require__(630); +var visit = __webpack_require__(638); /** * Map `visit` over an array of objects. @@ -72697,7 +73343,7 @@ function isObject(val) { /***/ }), -/* 632 */ +/* 640 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -72710,7 +73356,7 @@ function isObject(val) { -var typeOf = __webpack_require__(633); +var typeOf = __webpack_require__(641); module.exports = function toPath(args) { if (typeOf(args) !== 'arguments') { @@ -72737,10 +73383,10 @@ function filter(arr) { /***/ }), -/* 633 */ +/* 641 */ /***/ (function(module, exports, __webpack_require__) { -var isBuffer = __webpack_require__(612); +var isBuffer = __webpack_require__(620); var toString = Object.prototype.toString; /** @@ -72859,16 +73505,16 @@ module.exports = function kindOf(val) { /***/ }), -/* 634 */ +/* 642 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isObject = __webpack_require__(635); -var union = __webpack_require__(636); -var get = __webpack_require__(637); -var set = __webpack_require__(638); +var isObject = __webpack_require__(643); +var union = __webpack_require__(644); +var get = __webpack_require__(645); +var set = __webpack_require__(646); module.exports = function unionValue(obj, prop, value) { if (!isObject(obj)) { @@ -72896,7 +73542,7 @@ function arrayify(val) { /***/ }), -/* 635 */ +/* 643 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -72916,7 +73562,7 @@ module.exports = function isExtendable(val) { /***/ }), -/* 636 */ +/* 644 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -72952,7 +73598,7 @@ module.exports = function union(init) { /***/ }), -/* 637 */ +/* 645 */ /***/ (function(module, exports) { /*! @@ -73008,7 +73654,7 @@ function toString(val) { /***/ }), -/* 638 */ +/* 646 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -73021,10 +73667,10 @@ function toString(val) { -var split = __webpack_require__(605); -var extend = __webpack_require__(639); -var isPlainObject = __webpack_require__(595); -var isObject = __webpack_require__(635); +var split = __webpack_require__(613); +var extend = __webpack_require__(647); +var isPlainObject = __webpack_require__(603); +var isObject = __webpack_require__(643); module.exports = function(obj, prop, val) { if (!isObject(obj)) { @@ -73070,13 +73716,13 @@ function isValidKey(key) { /***/ }), -/* 639 */ +/* 647 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isObject = __webpack_require__(635); +var isObject = __webpack_require__(643); module.exports = function extend(o/*, objects*/) { if (!isObject(o)) { o = {}; } @@ -73110,7 +73756,7 @@ function hasOwn(obj, key) { /***/ }), -/* 640 */ +/* 648 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -73123,8 +73769,8 @@ function hasOwn(obj, key) { -var isObject = __webpack_require__(588); -var has = __webpack_require__(641); +var isObject = __webpack_require__(596); +var has = __webpack_require__(649); module.exports = function unset(obj, prop) { if (!isObject(obj)) { @@ -73149,7 +73795,7 @@ module.exports = function unset(obj, prop) { /***/ }), -/* 641 */ +/* 649 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -73162,9 +73808,9 @@ module.exports = function unset(obj, prop) { -var isObject = __webpack_require__(642); -var hasValues = __webpack_require__(644); -var get = __webpack_require__(637); +var isObject = __webpack_require__(650); +var hasValues = __webpack_require__(652); +var get = __webpack_require__(645); module.exports = function(obj, prop, noZero) { if (isObject(obj)) { @@ -73175,7 +73821,7 @@ module.exports = function(obj, prop, noZero) { /***/ }), -/* 642 */ +/* 650 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -73188,7 +73834,7 @@ module.exports = function(obj, prop, noZero) { -var isArray = __webpack_require__(643); +var isArray = __webpack_require__(651); module.exports = function isObject(val) { return val != null && typeof val === 'object' && isArray(val) === false; @@ -73196,7 +73842,7 @@ module.exports = function isObject(val) { /***/ }), -/* 643 */ +/* 651 */ /***/ (function(module, exports) { var toString = {}.toString; @@ -73207,7 +73853,7 @@ module.exports = Array.isArray || function (arr) { /***/ }), -/* 644 */ +/* 652 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -73250,7 +73896,7 @@ module.exports = function hasValue(o, noZero) { /***/ }), -/* 645 */ +/* 653 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -73263,9 +73909,9 @@ module.exports = function hasValue(o, noZero) { -var isObject = __webpack_require__(588); -var hasValues = __webpack_require__(646); -var get = __webpack_require__(637); +var isObject = __webpack_require__(596); +var hasValues = __webpack_require__(654); +var get = __webpack_require__(645); module.exports = function(val, prop) { return hasValues(isObject(val) && prop ? get(val, prop) : val); @@ -73273,7 +73919,7 @@ module.exports = function(val, prop) { /***/ }), -/* 646 */ +/* 654 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -73286,8 +73932,8 @@ module.exports = function(val, prop) { -var typeOf = __webpack_require__(647); -var isNumber = __webpack_require__(610); +var typeOf = __webpack_require__(655); +var isNumber = __webpack_require__(618); module.exports = function hasValue(val) { // is-number checks for NaN and other edge cases @@ -73340,10 +73986,10 @@ module.exports = function hasValue(val) { /***/ }), -/* 647 */ +/* 655 */ /***/ (function(module, exports, __webpack_require__) { -var isBuffer = __webpack_require__(612); +var isBuffer = __webpack_require__(620); var toString = Object.prototype.toString; /** @@ -73465,7 +74111,7 @@ module.exports = function kindOf(val) { /***/ }), -/* 648 */ +/* 656 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -73478,10 +74124,10 @@ module.exports = function kindOf(val) { -var split = __webpack_require__(605); -var extend = __webpack_require__(639); -var isPlainObject = __webpack_require__(595); -var isObject = __webpack_require__(635); +var split = __webpack_require__(613); +var extend = __webpack_require__(647); +var isPlainObject = __webpack_require__(603); +var isObject = __webpack_require__(643); module.exports = function(obj, prop, val) { if (!isObject(obj)) { @@ -73527,14 +74173,14 @@ function isValidKey(key) { /***/ }), -/* 649 */ +/* 657 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isExtendable = __webpack_require__(650); -var forIn = __webpack_require__(651); +var isExtendable = __webpack_require__(658); +var forIn = __webpack_require__(659); function mixinDeep(target, objects) { var len = arguments.length, i = 0; @@ -73598,7 +74244,7 @@ module.exports = mixinDeep; /***/ }), -/* 650 */ +/* 658 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -73611,7 +74257,7 @@ module.exports = mixinDeep; -var isPlainObject = __webpack_require__(595); +var isPlainObject = __webpack_require__(603); module.exports = function isExtendable(val) { return isPlainObject(val) || typeof val === 'function' || Array.isArray(val); @@ -73619,7 +74265,7 @@ module.exports = function isExtendable(val) { /***/ }), -/* 651 */ +/* 659 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -73642,7 +74288,7 @@ module.exports = function forIn(obj, fn, thisArg) { /***/ }), -/* 652 */ +/* 660 */ /***/ (function(module, exports) { /*! @@ -73669,14 +74315,14 @@ module.exports = pascalcase; /***/ }), -/* 653 */ +/* 661 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var util = __webpack_require__(113); -var utils = __webpack_require__(654); +var utils = __webpack_require__(662); /** * Expose class utils @@ -74041,7 +74687,7 @@ cu.bubble = function(Parent, events) { /***/ }), -/* 654 */ +/* 662 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -74055,10 +74701,10 @@ var utils = {}; * Lazily required module dependencies */ -utils.union = __webpack_require__(636); -utils.define = __webpack_require__(655); -utils.isObj = __webpack_require__(588); -utils.staticExtend = __webpack_require__(662); +utils.union = __webpack_require__(644); +utils.define = __webpack_require__(663); +utils.isObj = __webpack_require__(596); +utils.staticExtend = __webpack_require__(670); /** @@ -74069,7 +74715,7 @@ module.exports = utils; /***/ }), -/* 655 */ +/* 663 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -74082,7 +74728,7 @@ module.exports = utils; -var isDescriptor = __webpack_require__(656); +var isDescriptor = __webpack_require__(664); module.exports = function defineProperty(obj, prop, val) { if (typeof obj !== 'object' && typeof obj !== 'function') { @@ -74107,7 +74753,7 @@ module.exports = function defineProperty(obj, prop, val) { /***/ }), -/* 656 */ +/* 664 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -74120,9 +74766,9 @@ module.exports = function defineProperty(obj, prop, val) { -var typeOf = __webpack_require__(657); -var isAccessor = __webpack_require__(658); -var isData = __webpack_require__(660); +var typeOf = __webpack_require__(665); +var isAccessor = __webpack_require__(666); +var isData = __webpack_require__(668); module.exports = function isDescriptor(obj, key) { if (typeOf(obj) !== 'object') { @@ -74136,7 +74782,7 @@ module.exports = function isDescriptor(obj, key) { /***/ }), -/* 657 */ +/* 665 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -74289,7 +74935,7 @@ function isBuffer(val) { /***/ }), -/* 658 */ +/* 666 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -74302,7 +74948,7 @@ function isBuffer(val) { -var typeOf = __webpack_require__(659); +var typeOf = __webpack_require__(667); // accessor descriptor properties var accessor = { @@ -74365,10 +75011,10 @@ module.exports = isAccessorDescriptor; /***/ }), -/* 659 */ +/* 667 */ /***/ (function(module, exports, __webpack_require__) { -var isBuffer = __webpack_require__(612); +var isBuffer = __webpack_require__(620); var toString = Object.prototype.toString; /** @@ -74487,7 +75133,7 @@ module.exports = function kindOf(val) { /***/ }), -/* 660 */ +/* 668 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -74500,7 +75146,7 @@ module.exports = function kindOf(val) { -var typeOf = __webpack_require__(661); +var typeOf = __webpack_require__(669); // data descriptor properties var data = { @@ -74549,10 +75195,10 @@ module.exports = isDataDescriptor; /***/ }), -/* 661 */ +/* 669 */ /***/ (function(module, exports, __webpack_require__) { -var isBuffer = __webpack_require__(612); +var isBuffer = __webpack_require__(620); var toString = Object.prototype.toString; /** @@ -74671,7 +75317,7 @@ module.exports = function kindOf(val) { /***/ }), -/* 662 */ +/* 670 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -74684,8 +75330,8 @@ module.exports = function kindOf(val) { -var copy = __webpack_require__(663); -var define = __webpack_require__(655); +var copy = __webpack_require__(671); +var define = __webpack_require__(663); var util = __webpack_require__(113); /** @@ -74768,15 +75414,15 @@ module.exports = extend; /***/ }), -/* 663 */ +/* 671 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var typeOf = __webpack_require__(664); -var copyDescriptor = __webpack_require__(665); -var define = __webpack_require__(655); +var typeOf = __webpack_require__(672); +var copyDescriptor = __webpack_require__(673); +var define = __webpack_require__(663); /** * Copy static properties, prototype properties, and descriptors from one object to another. @@ -74949,10 +75595,10 @@ module.exports.has = has; /***/ }), -/* 664 */ +/* 672 */ /***/ (function(module, exports, __webpack_require__) { -var isBuffer = __webpack_require__(612); +var isBuffer = __webpack_require__(620); var toString = Object.prototype.toString; /** @@ -75071,7 +75717,7 @@ module.exports = function kindOf(val) { /***/ }), -/* 665 */ +/* 673 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -75159,16 +75805,16 @@ function isObject(val) { /***/ }), -/* 666 */ +/* 674 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var use = __webpack_require__(667); -var define = __webpack_require__(655); +var use = __webpack_require__(675); +var define = __webpack_require__(663); var debug = __webpack_require__(205)('snapdragon:compiler'); -var utils = __webpack_require__(669); +var utils = __webpack_require__(677); /** * Create a new `Compiler` with the given `options`. @@ -75322,7 +75968,7 @@ Compiler.prototype = { // source map support if (opts.sourcemap) { - var sourcemaps = __webpack_require__(688); + var sourcemaps = __webpack_require__(696); sourcemaps(this); this.mapVisit(this.ast.nodes); this.applySourceMaps(); @@ -75343,7 +75989,7 @@ module.exports = Compiler; /***/ }), -/* 667 */ +/* 675 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -75356,7 +76002,7 @@ module.exports = Compiler; -var utils = __webpack_require__(668); +var utils = __webpack_require__(676); module.exports = function base(app, opts) { if (!utils.isObject(app) && typeof app !== 'function') { @@ -75471,7 +76117,7 @@ module.exports = function base(app, opts) { /***/ }), -/* 668 */ +/* 676 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -75485,8 +76131,8 @@ var utils = {}; * Lazily required module dependencies */ -utils.define = __webpack_require__(655); -utils.isObject = __webpack_require__(588); +utils.define = __webpack_require__(663); +utils.isObject = __webpack_require__(596); utils.isString = function(val) { @@ -75501,7 +76147,7 @@ module.exports = utils; /***/ }), -/* 669 */ +/* 677 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -75511,9 +76157,9 @@ module.exports = utils; * Module dependencies */ -exports.extend = __webpack_require__(639); -exports.SourceMap = __webpack_require__(670); -exports.sourceMapResolve = __webpack_require__(681); +exports.extend = __webpack_require__(647); +exports.SourceMap = __webpack_require__(678); +exports.sourceMapResolve = __webpack_require__(689); /** * Convert backslash in the given string to forward slashes @@ -75556,7 +76202,7 @@ exports.last = function(arr, n) { /***/ }), -/* 670 */ +/* 678 */ /***/ (function(module, exports, __webpack_require__) { /* @@ -75564,13 +76210,13 @@ exports.last = function(arr, n) { * Licensed under the New BSD license. See LICENSE.txt or: * http://opensource.org/licenses/BSD-3-Clause */ -exports.SourceMapGenerator = __webpack_require__(671).SourceMapGenerator; -exports.SourceMapConsumer = __webpack_require__(677).SourceMapConsumer; -exports.SourceNode = __webpack_require__(680).SourceNode; +exports.SourceMapGenerator = __webpack_require__(679).SourceMapGenerator; +exports.SourceMapConsumer = __webpack_require__(685).SourceMapConsumer; +exports.SourceNode = __webpack_require__(688).SourceNode; /***/ }), -/* 671 */ +/* 679 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -75580,10 +76226,10 @@ exports.SourceNode = __webpack_require__(680).SourceNode; * http://opensource.org/licenses/BSD-3-Clause */ -var base64VLQ = __webpack_require__(672); -var util = __webpack_require__(674); -var ArraySet = __webpack_require__(675).ArraySet; -var MappingList = __webpack_require__(676).MappingList; +var base64VLQ = __webpack_require__(680); +var util = __webpack_require__(682); +var ArraySet = __webpack_require__(683).ArraySet; +var MappingList = __webpack_require__(684).MappingList; /** * An instance of the SourceMapGenerator represents a source map which is @@ -75992,7 +76638,7 @@ exports.SourceMapGenerator = SourceMapGenerator; /***/ }), -/* 672 */ +/* 680 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -76032,7 +76678,7 @@ exports.SourceMapGenerator = SourceMapGenerator; * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -var base64 = __webpack_require__(673); +var base64 = __webpack_require__(681); // A single base 64 digit can contain 6 bits of data. For the base 64 variable // length quantities we use in the source map spec, the first bit is the sign, @@ -76138,7 +76784,7 @@ exports.decode = function base64VLQ_decode(aStr, aIndex, aOutParam) { /***/ }), -/* 673 */ +/* 681 */ /***/ (function(module, exports) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -76211,7 +76857,7 @@ exports.decode = function (charCode) { /***/ }), -/* 674 */ +/* 682 */ /***/ (function(module, exports) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -76634,7 +77280,7 @@ exports.compareByGeneratedPositionsInflated = compareByGeneratedPositionsInflate /***/ }), -/* 675 */ +/* 683 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -76644,7 +77290,7 @@ exports.compareByGeneratedPositionsInflated = compareByGeneratedPositionsInflate * http://opensource.org/licenses/BSD-3-Clause */ -var util = __webpack_require__(674); +var util = __webpack_require__(682); var has = Object.prototype.hasOwnProperty; var hasNativeMap = typeof Map !== "undefined"; @@ -76761,7 +77407,7 @@ exports.ArraySet = ArraySet; /***/ }), -/* 676 */ +/* 684 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -76771,7 +77417,7 @@ exports.ArraySet = ArraySet; * http://opensource.org/licenses/BSD-3-Clause */ -var util = __webpack_require__(674); +var util = __webpack_require__(682); /** * Determine whether mappingB is after mappingA with respect to generated @@ -76846,7 +77492,7 @@ exports.MappingList = MappingList; /***/ }), -/* 677 */ +/* 685 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -76856,11 +77502,11 @@ exports.MappingList = MappingList; * http://opensource.org/licenses/BSD-3-Clause */ -var util = __webpack_require__(674); -var binarySearch = __webpack_require__(678); -var ArraySet = __webpack_require__(675).ArraySet; -var base64VLQ = __webpack_require__(672); -var quickSort = __webpack_require__(679).quickSort; +var util = __webpack_require__(682); +var binarySearch = __webpack_require__(686); +var ArraySet = __webpack_require__(683).ArraySet; +var base64VLQ = __webpack_require__(680); +var quickSort = __webpack_require__(687).quickSort; function SourceMapConsumer(aSourceMap) { var sourceMap = aSourceMap; @@ -77934,7 +78580,7 @@ exports.IndexedSourceMapConsumer = IndexedSourceMapConsumer; /***/ }), -/* 678 */ +/* 686 */ /***/ (function(module, exports) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -78051,7 +78697,7 @@ exports.search = function search(aNeedle, aHaystack, aCompare, aBias) { /***/ }), -/* 679 */ +/* 687 */ /***/ (function(module, exports) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -78171,7 +78817,7 @@ exports.quickSort = function (ary, comparator) { /***/ }), -/* 680 */ +/* 688 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -78181,8 +78827,8 @@ exports.quickSort = function (ary, comparator) { * http://opensource.org/licenses/BSD-3-Clause */ -var SourceMapGenerator = __webpack_require__(671).SourceMapGenerator; -var util = __webpack_require__(674); +var SourceMapGenerator = __webpack_require__(679).SourceMapGenerator; +var util = __webpack_require__(682); // Matches a Windows-style `\r\n` newline or a `\n` newline used by all other // operating systems these days (capturing the result). @@ -78590,17 +79236,17 @@ exports.SourceNode = SourceNode; /***/ }), -/* 681 */ +/* 689 */ /***/ (function(module, exports, __webpack_require__) { // Copyright 2014, 2015, 2016, 2017 Simon Lydell // X11 (“MIT”) Licensed. (See LICENSE.) -var sourceMappingURL = __webpack_require__(682) -var resolveUrl = __webpack_require__(683) -var decodeUriComponent = __webpack_require__(684) -var urix = __webpack_require__(686) -var atob = __webpack_require__(687) +var sourceMappingURL = __webpack_require__(690) +var resolveUrl = __webpack_require__(691) +var decodeUriComponent = __webpack_require__(692) +var urix = __webpack_require__(694) +var atob = __webpack_require__(695) @@ -78898,7 +79544,7 @@ module.exports = { /***/ }), -/* 682 */ +/* 690 */ /***/ (function(module, exports, __webpack_require__) { var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_RESULT__;// Copyright 2014 Simon Lydell @@ -78961,7 +79607,7 @@ void (function(root, factory) { /***/ }), -/* 683 */ +/* 691 */ /***/ (function(module, exports, __webpack_require__) { // Copyright 2014 Simon Lydell @@ -78979,13 +79625,13 @@ module.exports = resolveUrl /***/ }), -/* 684 */ +/* 692 */ /***/ (function(module, exports, __webpack_require__) { // Copyright 2017 Simon Lydell // X11 (“MIT”) Licensed. (See LICENSE.) -var decodeUriComponent = __webpack_require__(685) +var decodeUriComponent = __webpack_require__(693) function customDecodeUriComponent(string) { // `decodeUriComponent` turns `+` into ` `, but that's not wanted. @@ -78996,7 +79642,7 @@ module.exports = customDecodeUriComponent /***/ }), -/* 685 */ +/* 693 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -79097,7 +79743,7 @@ module.exports = function (encodedURI) { /***/ }), -/* 686 */ +/* 694 */ /***/ (function(module, exports, __webpack_require__) { // Copyright 2014 Simon Lydell @@ -79120,7 +79766,7 @@ module.exports = urix /***/ }), -/* 687 */ +/* 695 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -79134,7 +79780,7 @@ module.exports = atob.atob = atob; /***/ }), -/* 688 */ +/* 696 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -79142,8 +79788,8 @@ module.exports = atob.atob = atob; var fs = __webpack_require__(132); var path = __webpack_require__(4); -var define = __webpack_require__(655); -var utils = __webpack_require__(669); +var define = __webpack_require__(663); +var utils = __webpack_require__(677); /** * Expose `mixin()`. @@ -79286,19 +79932,19 @@ exports.comment = function(node) { /***/ }), -/* 689 */ +/* 697 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var use = __webpack_require__(667); +var use = __webpack_require__(675); var util = __webpack_require__(113); -var Cache = __webpack_require__(690); -var define = __webpack_require__(655); +var Cache = __webpack_require__(698); +var define = __webpack_require__(663); var debug = __webpack_require__(205)('snapdragon:parser'); -var Position = __webpack_require__(691); -var utils = __webpack_require__(669); +var Position = __webpack_require__(699); +var utils = __webpack_require__(677); /** * Create a new `Parser` with the given `input` and `options`. @@ -79826,7 +80472,7 @@ module.exports = Parser; /***/ }), -/* 690 */ +/* 698 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -79933,13 +80579,13 @@ MapCache.prototype.del = function mapDelete(key) { /***/ }), -/* 691 */ +/* 699 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var define = __webpack_require__(655); +var define = __webpack_require__(663); /** * Store position for a node @@ -79954,14 +80600,14 @@ module.exports = function Position(start, parser) { /***/ }), -/* 692 */ +/* 700 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isExtendable = __webpack_require__(693); -var assignSymbols = __webpack_require__(596); +var isExtendable = __webpack_require__(701); +var assignSymbols = __webpack_require__(604); module.exports = Object.assign || function(obj/*, objects*/) { if (obj === null || typeof obj === 'undefined') { @@ -80021,7 +80667,7 @@ function isEnum(obj, key) { /***/ }), -/* 693 */ +/* 701 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -80034,7 +80680,7 @@ function isEnum(obj, key) { -var isPlainObject = __webpack_require__(595); +var isPlainObject = __webpack_require__(603); module.exports = function isExtendable(val) { return isPlainObject(val) || typeof val === 'function' || Array.isArray(val); @@ -80042,14 +80688,14 @@ module.exports = function isExtendable(val) { /***/ }), -/* 694 */ +/* 702 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var nanomatch = __webpack_require__(695); -var extglob = __webpack_require__(709); +var nanomatch = __webpack_require__(703); +var extglob = __webpack_require__(717); module.exports = function(snapdragon) { var compilers = snapdragon.compiler.compilers; @@ -80126,7 +80772,7 @@ function escapeExtglobs(compiler) { /***/ }), -/* 695 */ +/* 703 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -80137,17 +80783,17 @@ function escapeExtglobs(compiler) { */ var util = __webpack_require__(113); -var toRegex = __webpack_require__(580); -var extend = __webpack_require__(696); +var toRegex = __webpack_require__(588); +var extend = __webpack_require__(704); /** * Local dependencies */ -var compilers = __webpack_require__(698); -var parsers = __webpack_require__(699); -var cache = __webpack_require__(702); -var utils = __webpack_require__(704); +var compilers = __webpack_require__(706); +var parsers = __webpack_require__(707); +var cache = __webpack_require__(710); +var utils = __webpack_require__(712); var MAX_LENGTH = 1024 * 64; /** @@ -80971,14 +81617,14 @@ module.exports = nanomatch; /***/ }), -/* 696 */ +/* 704 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isExtendable = __webpack_require__(697); -var assignSymbols = __webpack_require__(596); +var isExtendable = __webpack_require__(705); +var assignSymbols = __webpack_require__(604); module.exports = Object.assign || function(obj/*, objects*/) { if (obj === null || typeof obj === 'undefined') { @@ -81038,7 +81684,7 @@ function isEnum(obj, key) { /***/ }), -/* 697 */ +/* 705 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -81051,7 +81697,7 @@ function isEnum(obj, key) { -var isPlainObject = __webpack_require__(595); +var isPlainObject = __webpack_require__(603); module.exports = function isExtendable(val) { return isPlainObject(val) || typeof val === 'function' || Array.isArray(val); @@ -81059,7 +81705,7 @@ module.exports = function isExtendable(val) { /***/ }), -/* 698 */ +/* 706 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -81405,15 +82051,15 @@ module.exports = function(nanomatch, options) { /***/ }), -/* 699 */ +/* 707 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var regexNot = __webpack_require__(597); -var toRegex = __webpack_require__(580); -var isOdd = __webpack_require__(700); +var regexNot = __webpack_require__(605); +var toRegex = __webpack_require__(588); +var isOdd = __webpack_require__(708); /** * Characters to use in negation regex (we want to "not" match @@ -81799,7 +82445,7 @@ module.exports.not = NOT_REGEX; /***/ }), -/* 700 */ +/* 708 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -81812,7 +82458,7 @@ module.exports.not = NOT_REGEX; -var isNumber = __webpack_require__(701); +var isNumber = __webpack_require__(709); module.exports = function isOdd(i) { if (!isNumber(i)) { @@ -81826,7 +82472,7 @@ module.exports = function isOdd(i) { /***/ }), -/* 701 */ +/* 709 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -81854,14 +82500,14 @@ module.exports = function isNumber(num) { /***/ }), -/* 702 */ +/* 710 */ /***/ (function(module, exports, __webpack_require__) { -module.exports = new (__webpack_require__(703))(); +module.exports = new (__webpack_require__(711))(); /***/ }), -/* 703 */ +/* 711 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -81874,7 +82520,7 @@ module.exports = new (__webpack_require__(703))(); -var MapCache = __webpack_require__(690); +var MapCache = __webpack_require__(698); /** * Create a new `FragmentCache` with an optional object to use for `caches`. @@ -81996,7 +82642,7 @@ exports = module.exports = FragmentCache; /***/ }), -/* 704 */ +/* 712 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -82009,14 +82655,14 @@ var path = __webpack_require__(4); * Module dependencies */ -var isWindows = __webpack_require__(705)(); -var Snapdragon = __webpack_require__(624); -utils.define = __webpack_require__(706); -utils.diff = __webpack_require__(707); -utils.extend = __webpack_require__(696); -utils.pick = __webpack_require__(708); -utils.typeOf = __webpack_require__(590); -utils.unique = __webpack_require__(600); +var isWindows = __webpack_require__(713)(); +var Snapdragon = __webpack_require__(632); +utils.define = __webpack_require__(714); +utils.diff = __webpack_require__(715); +utils.extend = __webpack_require__(704); +utils.pick = __webpack_require__(716); +utils.typeOf = __webpack_require__(598); +utils.unique = __webpack_require__(608); /** * Returns true if the given value is effectively an empty string @@ -82382,7 +83028,7 @@ utils.unixify = function(options) { /***/ }), -/* 705 */ +/* 713 */ /***/ (function(module, exports, __webpack_require__) { var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*! @@ -82410,7 +83056,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ /***/ }), -/* 706 */ +/* 714 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -82423,8 +83069,8 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ -var isobject = __webpack_require__(588); -var isDescriptor = __webpack_require__(589); +var isobject = __webpack_require__(596); +var isDescriptor = __webpack_require__(597); var define = (typeof Reflect !== 'undefined' && Reflect.defineProperty) ? Reflect.defineProperty : Object.defineProperty; @@ -82455,7 +83101,7 @@ module.exports = function defineProperty(obj, key, val) { /***/ }), -/* 707 */ +/* 715 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -82509,7 +83155,7 @@ function diffArray(one, two) { /***/ }), -/* 708 */ +/* 716 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -82522,7 +83168,7 @@ function diffArray(one, two) { -var isObject = __webpack_require__(588); +var isObject = __webpack_require__(596); module.exports = function pick(obj, keys) { if (!isObject(obj) && typeof obj !== 'function') { @@ -82551,7 +83197,7 @@ module.exports = function pick(obj, keys) { /***/ }), -/* 709 */ +/* 717 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -82561,18 +83207,18 @@ module.exports = function pick(obj, keys) { * Module dependencies */ -var extend = __webpack_require__(639); -var unique = __webpack_require__(600); -var toRegex = __webpack_require__(580); +var extend = __webpack_require__(647); +var unique = __webpack_require__(608); +var toRegex = __webpack_require__(588); /** * Local dependencies */ -var compilers = __webpack_require__(710); -var parsers = __webpack_require__(716); -var Extglob = __webpack_require__(719); -var utils = __webpack_require__(718); +var compilers = __webpack_require__(718); +var parsers = __webpack_require__(724); +var Extglob = __webpack_require__(727); +var utils = __webpack_require__(726); var MAX_LENGTH = 1024 * 64; /** @@ -82889,13 +83535,13 @@ module.exports = extglob; /***/ }), -/* 710 */ +/* 718 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var brackets = __webpack_require__(711); +var brackets = __webpack_require__(719); /** * Extglob compilers @@ -83065,7 +83711,7 @@ module.exports = function(extglob) { /***/ }), -/* 711 */ +/* 719 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -83075,17 +83721,17 @@ module.exports = function(extglob) { * Local dependencies */ -var compilers = __webpack_require__(712); -var parsers = __webpack_require__(714); +var compilers = __webpack_require__(720); +var parsers = __webpack_require__(722); /** * Module dependencies */ var debug = __webpack_require__(205)('expand-brackets'); -var extend = __webpack_require__(639); -var Snapdragon = __webpack_require__(624); -var toRegex = __webpack_require__(580); +var extend = __webpack_require__(647); +var Snapdragon = __webpack_require__(632); +var toRegex = __webpack_require__(588); /** * Parses the given POSIX character class `pattern` and returns a @@ -83283,13 +83929,13 @@ module.exports = brackets; /***/ }), -/* 712 */ +/* 720 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var posix = __webpack_require__(713); +var posix = __webpack_require__(721); module.exports = function(brackets) { brackets.compiler @@ -83377,7 +84023,7 @@ module.exports = function(brackets) { /***/ }), -/* 713 */ +/* 721 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -83406,14 +84052,14 @@ module.exports = { /***/ }), -/* 714 */ +/* 722 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var utils = __webpack_require__(715); -var define = __webpack_require__(655); +var utils = __webpack_require__(723); +var define = __webpack_require__(663); /** * Text regex @@ -83632,14 +84278,14 @@ module.exports.TEXT_REGEX = TEXT_REGEX; /***/ }), -/* 715 */ +/* 723 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var toRegex = __webpack_require__(580); -var regexNot = __webpack_require__(597); +var toRegex = __webpack_require__(588); +var regexNot = __webpack_require__(605); var cached; /** @@ -83673,15 +84319,15 @@ exports.createRegex = function(pattern, include) { /***/ }), -/* 716 */ +/* 724 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var brackets = __webpack_require__(711); -var define = __webpack_require__(717); -var utils = __webpack_require__(718); +var brackets = __webpack_require__(719); +var define = __webpack_require__(725); +var utils = __webpack_require__(726); /** * Characters to use in text regex (we want to "not" match @@ -83836,7 +84482,7 @@ module.exports = parsers; /***/ }), -/* 717 */ +/* 725 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -83849,7 +84495,7 @@ module.exports = parsers; -var isDescriptor = __webpack_require__(589); +var isDescriptor = __webpack_require__(597); module.exports = function defineProperty(obj, prop, val) { if (typeof obj !== 'object' && typeof obj !== 'function') { @@ -83874,14 +84520,14 @@ module.exports = function defineProperty(obj, prop, val) { /***/ }), -/* 718 */ +/* 726 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var regex = __webpack_require__(597); -var Cache = __webpack_require__(703); +var regex = __webpack_require__(605); +var Cache = __webpack_require__(711); /** * Utils @@ -83950,7 +84596,7 @@ utils.createRegex = function(str) { /***/ }), -/* 719 */ +/* 727 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -83960,16 +84606,16 @@ utils.createRegex = function(str) { * Module dependencies */ -var Snapdragon = __webpack_require__(624); -var define = __webpack_require__(717); -var extend = __webpack_require__(639); +var Snapdragon = __webpack_require__(632); +var define = __webpack_require__(725); +var extend = __webpack_require__(647); /** * Local dependencies */ -var compilers = __webpack_require__(710); -var parsers = __webpack_require__(716); +var compilers = __webpack_require__(718); +var parsers = __webpack_require__(724); /** * Customize Snapdragon parser and renderer @@ -84035,16 +84681,16 @@ module.exports = Extglob; /***/ }), -/* 720 */ +/* 728 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var extglob = __webpack_require__(709); -var nanomatch = __webpack_require__(695); -var regexNot = __webpack_require__(597); -var toRegex = __webpack_require__(580); +var extglob = __webpack_require__(717); +var nanomatch = __webpack_require__(703); +var regexNot = __webpack_require__(605); +var toRegex = __webpack_require__(588); var not; /** @@ -84125,14 +84771,14 @@ function textRegex(pattern) { /***/ }), -/* 721 */ +/* 729 */ /***/ (function(module, exports, __webpack_require__) { -module.exports = new (__webpack_require__(703))(); +module.exports = new (__webpack_require__(711))(); /***/ }), -/* 722 */ +/* 730 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -84145,13 +84791,13 @@ var path = __webpack_require__(4); * Module dependencies */ -var Snapdragon = __webpack_require__(624); -utils.define = __webpack_require__(723); -utils.diff = __webpack_require__(707); -utils.extend = __webpack_require__(692); -utils.pick = __webpack_require__(708); -utils.typeOf = __webpack_require__(590); -utils.unique = __webpack_require__(600); +var Snapdragon = __webpack_require__(632); +utils.define = __webpack_require__(731); +utils.diff = __webpack_require__(715); +utils.extend = __webpack_require__(700); +utils.pick = __webpack_require__(716); +utils.typeOf = __webpack_require__(598); +utils.unique = __webpack_require__(608); /** * Returns true if the platform is windows, or `path.sep` is `\\`. @@ -84448,7 +85094,7 @@ utils.unixify = function(options) { /***/ }), -/* 723 */ +/* 731 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -84461,8 +85107,8 @@ utils.unixify = function(options) { -var isobject = __webpack_require__(588); -var isDescriptor = __webpack_require__(589); +var isobject = __webpack_require__(596); +var isDescriptor = __webpack_require__(597); var define = (typeof Reflect !== 'undefined' && Reflect.defineProperty) ? Reflect.defineProperty : Object.defineProperty; @@ -84493,7 +85139,7 @@ module.exports = function defineProperty(obj, key, val) { /***/ }), -/* 724 */ +/* 732 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -84512,9 +85158,9 @@ var __extends = (this && this.__extends) || (function () { }; })(); Object.defineProperty(exports, "__esModule", { value: true }); -var readdir = __webpack_require__(725); -var reader_1 = __webpack_require__(738); -var fs_stream_1 = __webpack_require__(742); +var readdir = __webpack_require__(733); +var reader_1 = __webpack_require__(746); +var fs_stream_1 = __webpack_require__(750); var ReaderAsync = /** @class */ (function (_super) { __extends(ReaderAsync, _super); function ReaderAsync() { @@ -84575,15 +85221,15 @@ exports.default = ReaderAsync; /***/ }), -/* 725 */ +/* 733 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const readdirSync = __webpack_require__(726); -const readdirAsync = __webpack_require__(734); -const readdirStream = __webpack_require__(737); +const readdirSync = __webpack_require__(734); +const readdirAsync = __webpack_require__(742); +const readdirStream = __webpack_require__(745); module.exports = exports = readdirAsyncPath; exports.readdir = exports.readdirAsync = exports.async = readdirAsyncPath; @@ -84667,7 +85313,7 @@ function readdirStreamStat (dir, options) { /***/ }), -/* 726 */ +/* 734 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -84675,11 +85321,11 @@ function readdirStreamStat (dir, options) { module.exports = readdirSync; -const DirectoryReader = __webpack_require__(727); +const DirectoryReader = __webpack_require__(735); let syncFacade = { - fs: __webpack_require__(732), - forEach: __webpack_require__(733), + fs: __webpack_require__(740), + forEach: __webpack_require__(741), sync: true }; @@ -84708,7 +85354,7 @@ function readdirSync (dir, options, internalOptions) { /***/ }), -/* 727 */ +/* 735 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -84717,9 +85363,9 @@ function readdirSync (dir, options, internalOptions) { const Readable = __webpack_require__(173).Readable; const EventEmitter = __webpack_require__(164).EventEmitter; const path = __webpack_require__(4); -const normalizeOptions = __webpack_require__(728); -const stat = __webpack_require__(730); -const call = __webpack_require__(731); +const normalizeOptions = __webpack_require__(736); +const stat = __webpack_require__(738); +const call = __webpack_require__(739); /** * Asynchronously reads the contents of a directory and streams the results @@ -85095,14 +85741,14 @@ module.exports = DirectoryReader; /***/ }), -/* 728 */ +/* 736 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(4); -const globToRegExp = __webpack_require__(729); +const globToRegExp = __webpack_require__(737); module.exports = normalizeOptions; @@ -85279,7 +85925,7 @@ function normalizeOptions (options, internalOptions) { /***/ }), -/* 729 */ +/* 737 */ /***/ (function(module, exports) { module.exports = function (glob, opts) { @@ -85416,13 +86062,13 @@ module.exports = function (glob, opts) { /***/ }), -/* 730 */ +/* 738 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const call = __webpack_require__(731); +const call = __webpack_require__(739); module.exports = stat; @@ -85497,7 +86143,7 @@ function symlinkStat (fs, path, lstats, callback) { /***/ }), -/* 731 */ +/* 739 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -85558,14 +86204,14 @@ function callOnce (fn) { /***/ }), -/* 732 */ +/* 740 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const fs = __webpack_require__(132); -const call = __webpack_require__(731); +const call = __webpack_require__(739); /** * A facade around {@link fs.readdirSync} that allows it to be called @@ -85629,7 +86275,7 @@ exports.lstat = function (path, callback) { /***/ }), -/* 733 */ +/* 741 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -85658,7 +86304,7 @@ function syncForEach (array, iterator, done) { /***/ }), -/* 734 */ +/* 742 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -85666,12 +86312,12 @@ function syncForEach (array, iterator, done) { module.exports = readdirAsync; -const maybe = __webpack_require__(735); -const DirectoryReader = __webpack_require__(727); +const maybe = __webpack_require__(743); +const DirectoryReader = __webpack_require__(735); let asyncFacade = { fs: __webpack_require__(132), - forEach: __webpack_require__(736), + forEach: __webpack_require__(744), async: true }; @@ -85713,7 +86359,7 @@ function readdirAsync (dir, options, callback, internalOptions) { /***/ }), -/* 735 */ +/* 743 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -85740,7 +86386,7 @@ module.exports = function maybe (cb, promise) { /***/ }), -/* 736 */ +/* 744 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -85776,7 +86422,7 @@ function asyncForEach (array, iterator, done) { /***/ }), -/* 737 */ +/* 745 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -85784,11 +86430,11 @@ function asyncForEach (array, iterator, done) { module.exports = readdirStream; -const DirectoryReader = __webpack_require__(727); +const DirectoryReader = __webpack_require__(735); let streamFacade = { fs: __webpack_require__(132), - forEach: __webpack_require__(736), + forEach: __webpack_require__(744), async: true }; @@ -85808,16 +86454,16 @@ function readdirStream (dir, options, internalOptions) { /***/ }), -/* 738 */ +/* 746 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var path = __webpack_require__(4); -var deep_1 = __webpack_require__(739); -var entry_1 = __webpack_require__(741); -var pathUtil = __webpack_require__(740); +var deep_1 = __webpack_require__(747); +var entry_1 = __webpack_require__(749); +var pathUtil = __webpack_require__(748); var Reader = /** @class */ (function () { function Reader(options) { this.options = options; @@ -85883,14 +86529,14 @@ exports.default = Reader; /***/ }), -/* 739 */ +/* 747 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var pathUtils = __webpack_require__(740); -var patternUtils = __webpack_require__(574); +var pathUtils = __webpack_require__(748); +var patternUtils = __webpack_require__(582); var DeepFilter = /** @class */ (function () { function DeepFilter(options, micromatchOptions) { this.options = options; @@ -85973,7 +86619,7 @@ exports.default = DeepFilter; /***/ }), -/* 740 */ +/* 748 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -86004,14 +86650,14 @@ exports.makeAbsolute = makeAbsolute; /***/ }), -/* 741 */ +/* 749 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var pathUtils = __webpack_require__(740); -var patternUtils = __webpack_require__(574); +var pathUtils = __webpack_require__(748); +var patternUtils = __webpack_require__(582); var EntryFilter = /** @class */ (function () { function EntryFilter(options, micromatchOptions) { this.options = options; @@ -86096,7 +86742,7 @@ exports.default = EntryFilter; /***/ }), -/* 742 */ +/* 750 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -86116,8 +86762,8 @@ var __extends = (this && this.__extends) || (function () { })(); Object.defineProperty(exports, "__esModule", { value: true }); var stream = __webpack_require__(173); -var fsStat = __webpack_require__(743); -var fs_1 = __webpack_require__(747); +var fsStat = __webpack_require__(751); +var fs_1 = __webpack_require__(755); var FileSystemStream = /** @class */ (function (_super) { __extends(FileSystemStream, _super); function FileSystemStream() { @@ -86167,14 +86813,14 @@ exports.default = FileSystemStream; /***/ }), -/* 743 */ +/* 751 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const optionsManager = __webpack_require__(744); -const statProvider = __webpack_require__(746); +const optionsManager = __webpack_require__(752); +const statProvider = __webpack_require__(754); /** * Asynchronous API. */ @@ -86205,13 +86851,13 @@ exports.statSync = statSync; /***/ }), -/* 744 */ +/* 752 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const fsAdapter = __webpack_require__(745); +const fsAdapter = __webpack_require__(753); function prepare(opts) { const options = Object.assign({ fs: fsAdapter.getFileSystemAdapter(opts ? opts.fs : undefined), @@ -86224,7 +86870,7 @@ exports.prepare = prepare; /***/ }), -/* 745 */ +/* 753 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -86247,7 +86893,7 @@ exports.getFileSystemAdapter = getFileSystemAdapter; /***/ }), -/* 746 */ +/* 754 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -86299,7 +86945,7 @@ exports.isFollowedSymlink = isFollowedSymlink; /***/ }), -/* 747 */ +/* 755 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -86330,7 +86976,7 @@ exports.default = FileSystem; /***/ }), -/* 748 */ +/* 756 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -86350,9 +86996,9 @@ var __extends = (this && this.__extends) || (function () { })(); Object.defineProperty(exports, "__esModule", { value: true }); var stream = __webpack_require__(173); -var readdir = __webpack_require__(725); -var reader_1 = __webpack_require__(738); -var fs_stream_1 = __webpack_require__(742); +var readdir = __webpack_require__(733); +var reader_1 = __webpack_require__(746); +var fs_stream_1 = __webpack_require__(750); var TransformStream = /** @class */ (function (_super) { __extends(TransformStream, _super); function TransformStream(reader) { @@ -86420,7 +87066,7 @@ exports.default = ReaderStream; /***/ }), -/* 749 */ +/* 757 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -86439,9 +87085,9 @@ var __extends = (this && this.__extends) || (function () { }; })(); Object.defineProperty(exports, "__esModule", { value: true }); -var readdir = __webpack_require__(725); -var reader_1 = __webpack_require__(738); -var fs_sync_1 = __webpack_require__(750); +var readdir = __webpack_require__(733); +var reader_1 = __webpack_require__(746); +var fs_sync_1 = __webpack_require__(758); var ReaderSync = /** @class */ (function (_super) { __extends(ReaderSync, _super); function ReaderSync() { @@ -86501,7 +87147,7 @@ exports.default = ReaderSync; /***/ }), -/* 750 */ +/* 758 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -86520,8 +87166,8 @@ var __extends = (this && this.__extends) || (function () { }; })(); Object.defineProperty(exports, "__esModule", { value: true }); -var fsStat = __webpack_require__(743); -var fs_1 = __webpack_require__(747); +var fsStat = __webpack_require__(751); +var fs_1 = __webpack_require__(755); var FileSystemSync = /** @class */ (function (_super) { __extends(FileSystemSync, _super); function FileSystemSync() { @@ -86567,7 +87213,7 @@ exports.default = FileSystemSync; /***/ }), -/* 751 */ +/* 759 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -86583,7 +87229,7 @@ exports.flatten = flatten; /***/ }), -/* 752 */ +/* 760 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -86604,13 +87250,13 @@ exports.merge = merge; /***/ }), -/* 753 */ +/* 761 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(4); -const pathType = __webpack_require__(754); +const pathType = __webpack_require__(762); const getExtensions = extensions => extensions.length > 1 ? `{${extensions.join(',')}}` : extensions[0]; @@ -86676,13 +87322,13 @@ module.exports.sync = (input, opts) => { /***/ }), -/* 754 */ +/* 762 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const fs = __webpack_require__(132); -const pify = __webpack_require__(755); +const pify = __webpack_require__(763); function type(fn, fn2, fp) { if (typeof fp !== 'string') { @@ -86725,7 +87371,7 @@ exports.symlinkSync = typeSync.bind(null, 'lstatSync', 'isSymbolicLink'); /***/ }), -/* 755 */ +/* 763 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -86816,17 +87462,17 @@ module.exports = (obj, opts) => { /***/ }), -/* 756 */ +/* 764 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const fs = __webpack_require__(132); const path = __webpack_require__(4); -const fastGlob = __webpack_require__(570); -const gitIgnore = __webpack_require__(757); +const fastGlob = __webpack_require__(578); +const gitIgnore = __webpack_require__(765); const pify = __webpack_require__(410); -const slash = __webpack_require__(758); +const slash = __webpack_require__(766); const DEFAULT_IGNORE = [ '**/node_modules/**', @@ -86924,7 +87570,7 @@ module.exports.sync = options => { /***/ }), -/* 757 */ +/* 765 */ /***/ (function(module, exports) { // A simple implementation of make-array @@ -87393,7 +88039,7 @@ module.exports = options => new IgnoreBase(options) /***/ }), -/* 758 */ +/* 766 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -87411,7 +88057,7 @@ module.exports = input => { /***/ }), -/* 759 */ +/* 767 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -87424,7 +88070,7 @@ module.exports = input => { -var isGlob = __webpack_require__(760); +var isGlob = __webpack_require__(768); module.exports = function hasGlob(val) { if (val == null) return false; @@ -87444,7 +88090,7 @@ module.exports = function hasGlob(val) { /***/ }), -/* 760 */ +/* 768 */ /***/ (function(module, exports, __webpack_require__) { /*! @@ -87475,17 +88121,17 @@ module.exports = function isGlob(str) { /***/ }), -/* 761 */ +/* 769 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(4); const {constants: fsConstants} = __webpack_require__(132); -const pEvent = __webpack_require__(762); -const CpFileError = __webpack_require__(765); -const fs = __webpack_require__(767); -const ProgressEmitter = __webpack_require__(770); +const pEvent = __webpack_require__(770); +const CpFileError = __webpack_require__(773); +const fs = __webpack_require__(775); +const ProgressEmitter = __webpack_require__(778); const cpFileAsync = async (source, destination, options, progressEmitter) => { let readError; @@ -87599,12 +88245,12 @@ module.exports.sync = (source, destination, options) => { /***/ }), -/* 762 */ +/* 770 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const pTimeout = __webpack_require__(763); +const pTimeout = __webpack_require__(771); const symbolAsyncIterator = Symbol.asyncIterator || '@@asyncIterator'; @@ -87895,12 +88541,12 @@ module.exports.iterator = (emitter, event, options) => { /***/ }), -/* 763 */ +/* 771 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const pFinally = __webpack_require__(764); +const pFinally = __webpack_require__(772); class TimeoutError extends Error { constructor(message) { @@ -87946,7 +88592,7 @@ module.exports.TimeoutError = TimeoutError; /***/ }), -/* 764 */ +/* 772 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -87968,12 +88614,12 @@ module.exports = (promise, onFinally) => { /***/ }), -/* 765 */ +/* 773 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const NestedError = __webpack_require__(766); +const NestedError = __webpack_require__(774); class CpFileError extends NestedError { constructor(message, nested) { @@ -87987,7 +88633,7 @@ module.exports = CpFileError; /***/ }), -/* 766 */ +/* 774 */ /***/ (function(module, exports, __webpack_require__) { var inherits = __webpack_require__(113).inherits; @@ -88043,16 +88689,16 @@ module.exports = NestedError; /***/ }), -/* 767 */ +/* 775 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const {promisify} = __webpack_require__(113); const fs = __webpack_require__(233); -const makeDir = __webpack_require__(768); -const pEvent = __webpack_require__(762); -const CpFileError = __webpack_require__(765); +const makeDir = __webpack_require__(776); +const pEvent = __webpack_require__(770); +const CpFileError = __webpack_require__(773); const stat = promisify(fs.stat); const lstat = promisify(fs.lstat); @@ -88149,7 +88795,7 @@ exports.copyFileSync = (source, destination, flags) => { /***/ }), -/* 768 */ +/* 776 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -88157,7 +88803,7 @@ exports.copyFileSync = (source, destination, flags) => { const fs = __webpack_require__(132); const path = __webpack_require__(4); const {promisify} = __webpack_require__(113); -const semver = __webpack_require__(769); +const semver = __webpack_require__(777); const useNativeRecursiveOption = semver.satisfies(process.version, '>=10.12.0'); @@ -88312,7 +88958,7 @@ module.exports.sync = (input, options) => { /***/ }), -/* 769 */ +/* 777 */ /***/ (function(module, exports) { exports = module.exports = SemVer @@ -89914,7 +90560,7 @@ function coerce (version, options) { /***/ }), -/* 770 */ +/* 778 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -89955,7 +90601,7 @@ module.exports = ProgressEmitter; /***/ }), -/* 771 */ +/* 779 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -90001,12 +90647,12 @@ exports.default = module.exports; /***/ }), -/* 772 */ +/* 780 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const pMap = __webpack_require__(773); +const pMap = __webpack_require__(781); const pFilter = async (iterable, filterer, options) => { const values = await pMap( @@ -90023,7 +90669,7 @@ module.exports.default = pFilter; /***/ }), -/* 773 */ +/* 781 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -90102,12 +90748,12 @@ module.exports.default = pMap; /***/ }), -/* 774 */ +/* 782 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const NestedError = __webpack_require__(766); +const NestedError = __webpack_require__(774); class CpyError extends NestedError { constructor(message, nested) { @@ -90121,7 +90767,7 @@ module.exports = CpyError; /***/ }), -/* 775 */ +/* 783 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -90129,10 +90775,10 @@ module.exports = CpyError; const fs = __webpack_require__(132); const arrayUnion = __webpack_require__(242); const merge2 = __webpack_require__(243); -const fastGlob = __webpack_require__(776); +const fastGlob = __webpack_require__(784); const dirGlob = __webpack_require__(332); -const gitignore = __webpack_require__(807); -const {FilterStream, UniqueStream} = __webpack_require__(808); +const gitignore = __webpack_require__(815); +const {FilterStream, UniqueStream} = __webpack_require__(816); const DEFAULT_FILTER = () => false; @@ -90309,17 +90955,17 @@ module.exports.gitignore = gitignore; /***/ }), -/* 776 */ +/* 784 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const taskManager = __webpack_require__(777); -const async_1 = __webpack_require__(793); -const stream_1 = __webpack_require__(803); -const sync_1 = __webpack_require__(804); -const settings_1 = __webpack_require__(806); -const utils = __webpack_require__(778); +const taskManager = __webpack_require__(785); +const async_1 = __webpack_require__(801); +const stream_1 = __webpack_require__(811); +const sync_1 = __webpack_require__(812); +const settings_1 = __webpack_require__(814); +const utils = __webpack_require__(786); async function FastGlob(source, options) { assertPatternsInput(source); const works = getWorks(source, async_1.default, options); @@ -90383,14 +91029,14 @@ module.exports = FastGlob; /***/ }), -/* 777 */ +/* 785 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.convertPatternGroupToTask = exports.convertPatternGroupsToTasks = exports.groupPatternsByBaseDirectory = exports.getNegativePatternsAsPositive = exports.getPositivePatterns = exports.convertPatternsToTasks = exports.generate = void 0; -const utils = __webpack_require__(778); +const utils = __webpack_require__(786); function generate(patterns, settings) { const positivePatterns = getPositivePatterns(patterns); const negativePatterns = getNegativePatternsAsPositive(patterns, settings.ignore); @@ -90455,31 +91101,31 @@ exports.convertPatternGroupToTask = convertPatternGroupToTask; /***/ }), -/* 778 */ +/* 786 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.string = exports.stream = exports.pattern = exports.path = exports.fs = exports.errno = exports.array = void 0; -const array = __webpack_require__(779); +const array = __webpack_require__(787); exports.array = array; -const errno = __webpack_require__(780); +const errno = __webpack_require__(788); exports.errno = errno; -const fs = __webpack_require__(781); +const fs = __webpack_require__(789); exports.fs = fs; -const path = __webpack_require__(782); +const path = __webpack_require__(790); exports.path = path; -const pattern = __webpack_require__(783); +const pattern = __webpack_require__(791); exports.pattern = pattern; -const stream = __webpack_require__(791); +const stream = __webpack_require__(799); exports.stream = stream; -const string = __webpack_require__(792); +const string = __webpack_require__(800); exports.string = string; /***/ }), -/* 779 */ +/* 787 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -90508,7 +91154,7 @@ exports.splitWhen = splitWhen; /***/ }), -/* 780 */ +/* 788 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -90522,7 +91168,7 @@ exports.isEnoentCodeError = isEnoentCodeError; /***/ }), -/* 781 */ +/* 789 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -90548,7 +91194,7 @@ exports.createDirentFromStats = createDirentFromStats; /***/ }), -/* 782 */ +/* 790 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -90588,7 +91234,7 @@ exports.removeLeadingDotSegment = removeLeadingDotSegment; /***/ }), -/* 783 */ +/* 791 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -90597,7 +91243,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.matchAny = exports.convertPatternsToRe = exports.makeRe = exports.getPatternParts = exports.expandBraceExpansion = exports.expandPatternsWithBraceExpansion = exports.isAffectDepthOfReadingPattern = exports.endsWithSlashGlobStar = exports.hasGlobStar = exports.getBaseDirectory = exports.getPositivePatterns = exports.getNegativePatterns = exports.isPositivePattern = exports.isNegativePattern = exports.convertToNegativePattern = exports.convertToPositivePattern = exports.isDynamicPattern = exports.isStaticPattern = void 0; const path = __webpack_require__(4); const globParent = __webpack_require__(265); -const micromatch = __webpack_require__(784); +const micromatch = __webpack_require__(792); const picomatch = __webpack_require__(285); const GLOBSTAR = '**'; const ESCAPE_SYMBOL = '\\'; @@ -90727,7 +91373,7 @@ exports.matchAny = matchAny; /***/ }), -/* 784 */ +/* 792 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -90735,8 +91381,8 @@ exports.matchAny = matchAny; const util = __webpack_require__(113); const braces = __webpack_require__(269); -const picomatch = __webpack_require__(785); -const utils = __webpack_require__(788); +const picomatch = __webpack_require__(793); +const utils = __webpack_require__(796); const isEmptyString = val => val === '' || val === './'; /** @@ -91201,27 +91847,27 @@ module.exports = micromatch; /***/ }), -/* 785 */ +/* 793 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -module.exports = __webpack_require__(786); +module.exports = __webpack_require__(794); /***/ }), -/* 786 */ +/* 794 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(4); -const scan = __webpack_require__(787); -const parse = __webpack_require__(790); -const utils = __webpack_require__(788); -const constants = __webpack_require__(789); +const scan = __webpack_require__(795); +const parse = __webpack_require__(798); +const utils = __webpack_require__(796); +const constants = __webpack_require__(797); const isObject = val => val && typeof val === 'object' && !Array.isArray(val); /** @@ -91560,13 +92206,13 @@ module.exports = picomatch; /***/ }), -/* 787 */ +/* 795 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const utils = __webpack_require__(788); +const utils = __webpack_require__(796); const { CHAR_ASTERISK, /* * */ CHAR_AT, /* @ */ @@ -91583,7 +92229,7 @@ const { CHAR_RIGHT_CURLY_BRACE, /* } */ CHAR_RIGHT_PARENTHESES, /* ) */ CHAR_RIGHT_SQUARE_BRACKET /* ] */ -} = __webpack_require__(789); +} = __webpack_require__(797); const isPathSeparator = code => { return code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH; @@ -91958,7 +92604,7 @@ module.exports = scan; /***/ }), -/* 788 */ +/* 796 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -91971,7 +92617,7 @@ const { REGEX_REMOVE_BACKSLASH, REGEX_SPECIAL_CHARS, REGEX_SPECIAL_CHARS_GLOBAL -} = __webpack_require__(789); +} = __webpack_require__(797); exports.isObject = val => val !== null && typeof val === 'object' && !Array.isArray(val); exports.hasRegexChars = str => REGEX_SPECIAL_CHARS.test(str); @@ -92029,7 +92675,7 @@ exports.wrapOutput = (input, state = {}, options = {}) => { /***/ }), -/* 789 */ +/* 797 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -92215,14 +92861,14 @@ module.exports = { /***/ }), -/* 790 */ +/* 798 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const constants = __webpack_require__(789); -const utils = __webpack_require__(788); +const constants = __webpack_require__(797); +const utils = __webpack_require__(796); /** * Constants @@ -93306,7 +93952,7 @@ module.exports = parse; /***/ }), -/* 791 */ +/* 799 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -93330,7 +93976,7 @@ function propagateCloseEventToSources(streams) { /***/ }), -/* 792 */ +/* 800 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -93348,14 +93994,14 @@ exports.isEmpty = isEmpty; /***/ }), -/* 793 */ +/* 801 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const stream_1 = __webpack_require__(794); -const provider_1 = __webpack_require__(796); +const stream_1 = __webpack_require__(802); +const provider_1 = __webpack_require__(804); class ProviderAsync extends provider_1.default { constructor() { super(...arguments); @@ -93383,7 +94029,7 @@ exports.default = ProviderAsync; /***/ }), -/* 794 */ +/* 802 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -93392,7 +94038,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); const stream_1 = __webpack_require__(173); const fsStat = __webpack_require__(295); const fsWalk = __webpack_require__(300); -const reader_1 = __webpack_require__(795); +const reader_1 = __webpack_require__(803); class ReaderStream extends reader_1.default { constructor() { super(...arguments); @@ -93445,7 +94091,7 @@ exports.default = ReaderStream; /***/ }), -/* 795 */ +/* 803 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -93453,7 +94099,7 @@ exports.default = ReaderStream; Object.defineProperty(exports, "__esModule", { value: true }); const path = __webpack_require__(4); const fsStat = __webpack_require__(295); -const utils = __webpack_require__(778); +const utils = __webpack_require__(786); class Reader { constructor(_settings) { this._settings = _settings; @@ -93485,17 +94131,17 @@ exports.default = Reader; /***/ }), -/* 796 */ +/* 804 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const path = __webpack_require__(4); -const deep_1 = __webpack_require__(797); -const entry_1 = __webpack_require__(800); -const error_1 = __webpack_require__(801); -const entry_2 = __webpack_require__(802); +const deep_1 = __webpack_require__(805); +const entry_1 = __webpack_require__(808); +const error_1 = __webpack_require__(809); +const entry_2 = __webpack_require__(810); class Provider { constructor(_settings) { this._settings = _settings; @@ -93540,14 +94186,14 @@ exports.default = Provider; /***/ }), -/* 797 */ +/* 805 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const utils = __webpack_require__(778); -const partial_1 = __webpack_require__(798); +const utils = __webpack_require__(786); +const partial_1 = __webpack_require__(806); class DeepFilter { constructor(_settings, _micromatchOptions) { this._settings = _settings; @@ -93609,13 +94255,13 @@ exports.default = DeepFilter; /***/ }), -/* 798 */ +/* 806 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const matcher_1 = __webpack_require__(799); +const matcher_1 = __webpack_require__(807); class PartialMatcher extends matcher_1.default { match(filepath) { const parts = filepath.split('/'); @@ -93654,13 +94300,13 @@ exports.default = PartialMatcher; /***/ }), -/* 799 */ +/* 807 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const utils = __webpack_require__(778); +const utils = __webpack_require__(786); class Matcher { constructor(_patterns, _settings, _micromatchOptions) { this._patterns = _patterns; @@ -93711,13 +94357,13 @@ exports.default = Matcher; /***/ }), -/* 800 */ +/* 808 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const utils = __webpack_require__(778); +const utils = __webpack_require__(786); class EntryFilter { constructor(_settings, _micromatchOptions) { this._settings = _settings; @@ -93774,13 +94420,13 @@ exports.default = EntryFilter; /***/ }), -/* 801 */ +/* 809 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const utils = __webpack_require__(778); +const utils = __webpack_require__(786); class ErrorFilter { constructor(_settings) { this._settings = _settings; @@ -93796,13 +94442,13 @@ exports.default = ErrorFilter; /***/ }), -/* 802 */ +/* 810 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const utils = __webpack_require__(778); +const utils = __webpack_require__(786); class EntryTransformer { constructor(_settings) { this._settings = _settings; @@ -93829,15 +94475,15 @@ exports.default = EntryTransformer; /***/ }), -/* 803 */ +/* 811 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const stream_1 = __webpack_require__(173); -const stream_2 = __webpack_require__(794); -const provider_1 = __webpack_require__(796); +const stream_2 = __webpack_require__(802); +const provider_1 = __webpack_require__(804); class ProviderStream extends provider_1.default { constructor() { super(...arguments); @@ -93867,14 +94513,14 @@ exports.default = ProviderStream; /***/ }), -/* 804 */ +/* 812 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const sync_1 = __webpack_require__(805); -const provider_1 = __webpack_require__(796); +const sync_1 = __webpack_require__(813); +const provider_1 = __webpack_require__(804); class ProviderSync extends provider_1.default { constructor() { super(...arguments); @@ -93897,7 +94543,7 @@ exports.default = ProviderSync; /***/ }), -/* 805 */ +/* 813 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -93905,7 +94551,7 @@ exports.default = ProviderSync; Object.defineProperty(exports, "__esModule", { value: true }); const fsStat = __webpack_require__(295); const fsWalk = __webpack_require__(300); -const reader_1 = __webpack_require__(795); +const reader_1 = __webpack_require__(803); class ReaderSync extends reader_1.default { constructor() { super(...arguments); @@ -93947,7 +94593,7 @@ exports.default = ReaderSync; /***/ }), -/* 806 */ +/* 814 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -94011,7 +94657,7 @@ exports.default = Settings; /***/ }), -/* 807 */ +/* 815 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -94019,7 +94665,7 @@ exports.default = Settings; const {promisify} = __webpack_require__(113); const fs = __webpack_require__(132); const path = __webpack_require__(4); -const fastGlob = __webpack_require__(776); +const fastGlob = __webpack_require__(784); const gitIgnore = __webpack_require__(335); const slash = __webpack_require__(336); @@ -94138,7 +94784,7 @@ module.exports.sync = options => { /***/ }), -/* 808 */ +/* 816 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -94191,7 +94837,7 @@ module.exports = { /***/ }), -/* 809 */ +/* 817 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; @@ -94199,13 +94845,13 @@ __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "buildNonBazelProductionProjects", function() { return buildNonBazelProductionProjects; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getProductionProjects", function() { return getProductionProjects; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "buildProject", function() { return buildProject; }); -/* harmony import */ var cpy__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(563); +/* harmony import */ var cpy__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(571); /* harmony import */ var cpy__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(cpy__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(240); /* harmony import */ var del__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(del__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(4); /* harmony import */ var path__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_2__); -/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(560); +/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(568); /* harmony import */ var _utils_fs__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(231); /* harmony import */ var _utils_log__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(220); /* harmony import */ var _utils_package_json__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(349); diff --git a/packages/kbn-pm/src/commands/bootstrap.ts b/packages/kbn-pm/src/commands/bootstrap.ts index 95eeeb329da3d..12034a9f4a094 100644 --- a/packages/kbn-pm/src/commands/bootstrap.ts +++ b/packages/kbn-pm/src/commands/bootstrap.ts @@ -15,6 +15,7 @@ import { linkProjectExecutables } from '../utils/link_project_executables'; import { getNonBazelProjectsOnly, topologicallyBatchProjects } from '../utils/projects'; import { ICommand } from './'; import { readYarnLock } from '../utils/yarn_lock'; +import { sortPackageJson } from '../utils/sort_package_json'; import { validateDependencies } from '../utils/validate_dependencies'; import { ensureYarnIntegrityFileExists, @@ -107,6 +108,8 @@ export const BootstrapCommand: ICommand = { } } + await sortPackageJson(kbn); + const yarnLock = await readYarnLock(kbn); if (options.validate) { diff --git a/packages/kbn-pm/src/utils/sort_package_json.ts b/packages/kbn-pm/src/utils/sort_package_json.ts new file mode 100644 index 0000000000000..0abab6f0f89b4 --- /dev/null +++ b/packages/kbn-pm/src/utils/sort_package_json.ts @@ -0,0 +1,47 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import Fs from 'fs/promises'; + +import sorter from 'sort-package-json'; + +import { Kibana } from './kibana'; + +export async function sortPackageJson(kbn: Kibana) { + const packageJsonPath = kbn.getAbsolute('package.json'); + const packageJson = await Fs.readFile(packageJsonPath, 'utf-8'); + await Fs.writeFile( + packageJsonPath, + JSON.stringify( + sorter(JSON.parse(packageJson), { + // top level keys in the order they were written when this was implemented + sortOrder: [ + 'name', + 'description', + 'keywords', + 'private', + 'version', + 'branch', + 'types', + 'tsdocMetadata', + 'build', + 'homepage', + 'bugs', + 'kibana', + 'author', + 'scripts', + 'repository', + 'engines', + 'resolutions', + ], + }), + null, + 2 + ) + ); +} diff --git a/yarn.lock b/yarn.lock index d1770613f0f6d..4a73df1ef0500 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11932,6 +11932,11 @@ detect-indent@^5.0.0: resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-5.0.0.tgz#3871cc0a6a002e8c3e5b3cf7f336264675f06b9d" integrity sha1-OHHMCmoALow+Wzz38zYmRnXwa50= +detect-indent@^6.0.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-6.1.0.tgz#592485ebbbf6b3b1ab2be175c8393d04ca0d57e6" + integrity sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA== + detect-libc@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" @@ -11942,7 +11947,7 @@ detect-newline@2.X: resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-2.1.0.tgz#f41f1c10be4b00e87b5f13da680759f2c5bfd3e2" integrity sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I= -detect-newline@^3.0.0: +detect-newline@3.1.0, detect-newline@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== @@ -14691,6 +14696,11 @@ gifwrap@^0.9.2: image-q "^1.1.1" omggif "^1.0.10" +git-hooks-list@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/git-hooks-list/-/git-hooks-list-1.0.3.tgz#be5baaf78203ce342f2f844a9d2b03dba1b45156" + integrity sha512-Y7wLWcrLUXwk2noSka166byGCvhMtDRpgHdzCno1UQv/n/Hegp++a2xBWJL1lJarnKD3SWaljD+0z1ztqxuKyQ== + github-from-package@0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce" @@ -14904,6 +14914,20 @@ globalthis@^1.0.0: dependencies: define-properties "^1.1.3" +globby@10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-10.0.0.tgz#abfcd0630037ae174a88590132c2f6804e291072" + integrity sha512-3LifW9M4joGZasyYPz2A1U74zbC/45fvpXUvO/9KbSa+VV0aGZarWkfdgKyR9sExNP0t0x0ss/UMJpNpcaTspw== + dependencies: + "@types/glob" "^7.1.1" + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.0.3" + glob "^7.1.3" + ignore "^5.1.1" + merge2 "^1.2.3" + slash "^3.0.0" + globby@11.0.1: version "11.0.1" resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.1.tgz#9a2bf107a068f3ffeabc49ad702c79ede8cfd357" @@ -16718,16 +16742,16 @@ is-path-inside@^3.0.1, is-path-inside@^3.0.2: resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.2.tgz#f5220fc82a3e233757291dddc9c5877f2a1f3017" integrity sha512-/2UGPSgmtqwo1ktx8NDHjuPwZWmHhO+gj0f93EkhLB5RgW9RZevWYYlIkS6zePc6U2WpOdQYIwHe9YC4DWEBVg== +is-plain-obj@2.1.0, is-plain-obj@^2.0.0, is-plain-obj@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" + integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== + is-plain-obj@^1.0.0, is-plain-obj@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= -is-plain-obj@^2.0.0, is-plain-obj@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" - integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== - is-plain-object@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-3.0.0.tgz#47bfc5da1b5d50d64110806c199359482e75a928" @@ -25588,6 +25612,23 @@ sort-keys@^2.0.0: dependencies: is-plain-obj "^1.0.0" +sort-object-keys@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/sort-object-keys/-/sort-object-keys-1.1.3.tgz#bff833fe85cab147b34742e45863453c1e190b45" + integrity sha512-855pvK+VkU7PaKYPc+Jjnmt4EzejQHyhhF33q31qG8x7maDzkeFhAAThdCYay11CISO+qAMwjOBP+fPZe0IPyg== + +sort-package-json@^1.53.1: + version "1.53.1" + resolved "https://registry.yarnpkg.com/sort-package-json/-/sort-package-json-1.53.1.tgz#8f2672b06314cf04d9a6bcefc75a5f38d600b811" + integrity sha512-ltLORrQuuPMpy23YkWCA8fO7zBOxM4P1j9LcGxci4K2Fk8jmSyCA/ATU6CFyy8qR2HQRx4RBYWzoi78FU/Anuw== + dependencies: + detect-indent "^6.0.0" + detect-newline "3.1.0" + git-hooks-list "1.0.3" + globby "10.0.0" + is-plain-obj "2.1.0" + sort-object-keys "^1.1.3" + source-list-map@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" From 1f263b8db1018fd097635fe134b99b79b6bfcb14 Mon Sep 17 00:00:00 2001 From: Matthew Kime Date: Tue, 16 Nov 2021 20:31:55 -0600 Subject: [PATCH 058/148] [data views] copy fixes (#117967) * rollup fixes * copy fixes * Update x-pack/plugins/rollup/server/plugin.ts Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> * Update form_schema.ts Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../index_pattern_editor/public/components/form_schema.ts | 2 +- .../index_pattern_table/index_pattern_table.tsx | 2 +- x-pack/plugins/rollup/server/plugin.ts | 8 ++++---- x-pack/plugins/translations/translations/ja-JP.json | 2 -- x-pack/plugins/translations/translations/zh-CN.json | 2 -- 5 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/plugins/index_pattern_editor/public/components/form_schema.ts b/src/plugins/index_pattern_editor/public/components/form_schema.ts index 826c9db6a8271..a6df0c4206d2a 100644 --- a/src/plugins/index_pattern_editor/public/components/form_schema.ts +++ b/src/plugins/index_pattern_editor/public/components/form_schema.ts @@ -18,7 +18,7 @@ export const schema = { defaultValue: '', helpText: i18n.translate('indexPatternEditor.validations.titleHelpText', { defaultMessage: - 'Use an asterisk (*) to match multiple characters. Spaces and the characters , /, ?, ", <, >, | are not allowed.', + 'Enter an index pattern that matches one or more data sources. Use an asterisk (*) to match multiple characters. Spaces and the characters , /, ?, ", <, >, | are not allowed.', }), validations: [ { diff --git a/src/plugins/index_pattern_management/public/components/index_pattern_table/index_pattern_table.tsx b/src/plugins/index_pattern_management/public/components/index_pattern_table/index_pattern_table.tsx index e8ce4b468f22f..7c3a2c6eb0e34 100644 --- a/src/plugins/index_pattern_management/public/components/index_pattern_table/index_pattern_table.tsx +++ b/src/plugins/index_pattern_management/public/components/index_pattern_table/index_pattern_table.tsx @@ -47,7 +47,7 @@ const search = { }; const title = i18n.translate('indexPatternManagement.dataViewTable.title', { - defaultMessage: 'Data views', + defaultMessage: 'Data Views', }); const securityDataView = i18n.translate( diff --git a/x-pack/plugins/rollup/server/plugin.ts b/x-pack/plugins/rollup/server/plugin.ts index 88da9a3eb87b1..93b216f05d37e 100644 --- a/x-pack/plugins/rollup/server/plugin.ts +++ b/x-pack/plugins/rollup/server/plugin.ts @@ -76,12 +76,12 @@ export class RollupPlugin implements Plugin { uiSettings.register({ [CONFIG_ROLLUPS]: { - name: i18n.translate('xpack.rollupJobs.rollupIndexPatternsTitle', { - defaultMessage: 'Enable rollup index patterns', + name: i18n.translate('xpack.rollupJobs.rollupDataViewsTitle', { + defaultMessage: 'Enable rollup data views', }), value: true, - description: i18n.translate('xpack.rollupJobs.rollupIndexPatternsDescription', { - defaultMessage: `Enable the creation of index patterns which capture rollup indices, + description: i18n.translate('xpack.rollupJobs.rollupDataViewsDescription', { + defaultMessage: `Enable the creation of data views that capture rollup indices, which in turn enable visualizations based on rollup data.`, }), category: ['rollups'], diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 64e03b9f1efee..bf23a7631bdf1 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -19338,8 +19338,6 @@ "xpack.rollupJobs.licenseCheckErrorMessage": "ライセンス確認失敗", "xpack.rollupJobs.listBreadcrumbTitle": "ロールアップジョブ", "xpack.rollupJobs.refreshAction.errorTitle": "ロールアップジョブの更新中にエラーが発生", - "xpack.rollupJobs.rollupIndexPatternsDescription": "ロールアップインデックスを捕捉するインデックスパターンの作成を有効にします。\n それによりロールアップデータに基づくビジュアライゼーションが可能になります。", - "xpack.rollupJobs.rollupIndexPatternsTitle": "ロールアップインデックスパターンを有効にする", "xpack.rollupJobs.rollupJobsDocsLinkText": "ロールアップジョブドキュメント", "xpack.rollupJobs.startJobsAction.errorTitle": "ロールアップジョブの開始中にエラーが発生", "xpack.rollupJobs.stopJobsAction.errorTitle": "ロールアップジョブの停止中にエラーが発生", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 626eca1befeea..acc1705de5ba8 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -19619,8 +19619,6 @@ "xpack.rollupJobs.licenseCheckErrorMessage": "许可证检查失败", "xpack.rollupJobs.listBreadcrumbTitle": "汇总/打包作业", "xpack.rollupJobs.refreshAction.errorTitle": "刷新汇总/打包作业时出错", - "xpack.rollupJobs.rollupIndexPatternsDescription": "启用用于捕获汇总/打包索引的索引模式的创建,\n 汇总/打包索引反过来基于汇总/打包数据启用可视化。", - "xpack.rollupJobs.rollupIndexPatternsTitle": "启用汇总索引模式", "xpack.rollupJobs.rollupJobsDocsLinkText": "汇总/打包作业文档", "xpack.rollupJobs.startJobsAction.errorTitle": "启动汇总/打包作业时出错", "xpack.rollupJobs.stopJobsAction.errorTitle": "停止汇总/打包作业时出错", From 908470912f2685a0f4f3be7f07a50a48cdb832da Mon Sep 17 00:00:00 2001 From: Spencer Date: Tue, 16 Nov 2021 20:02:51 -0800 Subject: [PATCH 059/148] [ci] validate bootstrap changes at beginning of checks (#118822) * [ci] validate bootstrap changes at beginning of checks * make package.json invalid * Revert "make package.json invalid" This reverts commit e4e9ecfcdd5fbf6295b72b57eee6cf8588b184d5. --- .buildkite/scripts/bootstrap.sh | 8 ++++---- .buildkite/scripts/steps/checks.sh | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.buildkite/scripts/bootstrap.sh b/.buildkite/scripts/bootstrap.sh index 272cd0a086170..d4e8434fe6df8 100755 --- a/.buildkite/scripts/bootstrap.sh +++ b/.buildkite/scripts/bootstrap.sh @@ -18,6 +18,10 @@ if ! yarn kbn bootstrap; then yarn kbn bootstrap fi +if [[ "$DISABLE_BOOTSTRAP_VALIDATION" != "true" ]]; then + verify_no_git_changes 'yarn kbn bootstrap' +fi + ### ### upload ts-refs-cache artifacts as quickly as possible so they are available for download ### @@ -27,7 +31,3 @@ if [[ "${BUILD_TS_REFS_CACHE_CAPTURE:-}" == "true" ]]; then gsutil cp "*.zip" 'gs://kibana-ci-ts-refs-cache/' cd "$KIBANA_DIR" fi - -if [[ "$DISABLE_BOOTSTRAP_VALIDATION" != "true" ]]; then - verify_no_git_changes 'yarn kbn bootstrap' -fi diff --git a/.buildkite/scripts/steps/checks.sh b/.buildkite/scripts/steps/checks.sh index 0d4bc829ead79..9e335fc3cdea3 100755 --- a/.buildkite/scripts/steps/checks.sh +++ b/.buildkite/scripts/steps/checks.sh @@ -2,6 +2,7 @@ set -euo pipefail +export DISABLE_BOOTSTRAP_VALIDATION=false .buildkite/scripts/bootstrap.sh .buildkite/scripts/steps/checks/commit/commit.sh From 3d58e1d1804cd2d916a1a3253aeb4e0d2ac42e4b Mon Sep 17 00:00:00 2001 From: Yaroslav Kuznietsov Date: Wed, 17 Nov 2021 08:37:17 +0200 Subject: [PATCH 060/148] [Canvas] Fixed Image Repeat element not updating (#118701) --- .../canvas_plugin_src/uis/arguments/datacolumn/index.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/datacolumn/index.js b/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/datacolumn/index.js index bc77f347530b7..5008aa42e802a 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/datacolumn/index.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/datacolumn/index.js @@ -28,7 +28,9 @@ const getMathValue = (argValue, columns) => { const matchedCol = columns.find(({ name }) => argValue === name); const val = matchedCol ? maybeQuoteValue(matchedCol.name) : argValue; const mathValue = getFormObject(val); - return { ...mathValue, column: mathValue.column || '' }; + + const validColumn = columns.some(({ name }) => mathValue.column === name); + return { ...mathValue, column: validColumn ? mathValue.column : '' }; } catch (e) { return { error: e.message }; } From e5b005af56622910f4cd42a8cf6e30eab3540b21 Mon Sep 17 00:00:00 2001 From: Milton Hultgren Date: Wed, 17 Nov 2021 09:34:28 +0100 Subject: [PATCH 061/148] [Metrics UI] Add retry.try to some Home Page tests (#118712) --- .../test/functional/apps/infra/home_page.ts | 74 ++++++++++--------- 1 file changed, 41 insertions(+), 33 deletions(-) diff --git a/x-pack/test/functional/apps/infra/home_page.ts b/x-pack/test/functional/apps/infra/home_page.ts index 5046fa3ba90af..dfb5ba1cba4fd 100644 --- a/x-pack/test/functional/apps/infra/home_page.ts +++ b/x-pack/test/functional/apps/infra/home_page.ts @@ -14,6 +14,7 @@ const DATE_WITHOUT_DATA = DATES.metricsAndLogs.hosts.withoutData; export default ({ getPageObjects, getService }: FtrProviderContext) => { const esArchiver = getService('esArchiver'); + const retry = getService('retry'); const pageObjects = getPageObjects(['common', 'infraHome', 'infraSavedViews']); describe('Home page', function () { @@ -60,15 +61,17 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await pageObjects.infraHome.goToTime(DATE_WITH_DATA); await pageObjects.infraHome.getWaffleMap(); await pageObjects.infraHome.sortNodesBy('value'); - const nodesWithValue = await pageObjects.infraHome.getNodesWithValues(); - expect(nodesWithValue).to.eql([ - { name: 'demo-stack-apache-01', value: 1.4, color: '#6092c0' }, - { name: 'demo-stack-mysql-01', value: 1.2, color: '#82a7cd' }, - { name: 'demo-stack-nginx-01', value: 1.1, color: '#93b1d3' }, - { name: 'demo-stack-redis-01', value: 1, color: '#a2bcd9' }, - { name: 'demo-stack-haproxy-01', value: 0.8, color: '#c2d2e6' }, - { name: 'demo-stack-client-01', value: 0.6, color: '#f0f4f9' }, - ]); + await retry.try(async () => { + const nodesWithValue = await pageObjects.infraHome.getNodesWithValues(); + expect(nodesWithValue).to.eql([ + { name: 'demo-stack-apache-01', value: 1.4, color: '#6092c0' }, + { name: 'demo-stack-mysql-01', value: 1.2, color: '#82a7cd' }, + { name: 'demo-stack-nginx-01', value: 1.1, color: '#93b1d3' }, + { name: 'demo-stack-redis-01', value: 1, color: '#a2bcd9' }, + { name: 'demo-stack-haproxy-01', value: 0.8, color: '#c2d2e6' }, + { name: 'demo-stack-client-01', value: 0.6, color: '#f0f4f9' }, + ]); + }); }); it('sort nodes by ascending value', async () => { @@ -76,15 +79,17 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await pageObjects.infraHome.getWaffleMap(); await pageObjects.infraHome.sortNodesBy('value'); await pageObjects.infraHome.toggleReverseSort(); - const nodesWithValue = await pageObjects.infraHome.getNodesWithValues(); - expect(nodesWithValue).to.eql([ - { name: 'demo-stack-client-01', value: 0.6, color: '#f0f4f9' }, - { name: 'demo-stack-haproxy-01', value: 0.8, color: '#c2d2e6' }, - { name: 'demo-stack-redis-01', value: 1, color: '#a2bcd9' }, - { name: 'demo-stack-nginx-01', value: 1.1, color: '#93b1d3' }, - { name: 'demo-stack-mysql-01', value: 1.2, color: '#82a7cd' }, - { name: 'demo-stack-apache-01', value: 1.4, color: '#6092c0' }, - ]); + await retry.try(async () => { + const nodesWithValue = await pageObjects.infraHome.getNodesWithValues(); + expect(nodesWithValue).to.eql([ + { name: 'demo-stack-client-01', value: 0.6, color: '#f0f4f9' }, + { name: 'demo-stack-haproxy-01', value: 0.8, color: '#c2d2e6' }, + { name: 'demo-stack-redis-01', value: 1, color: '#a2bcd9' }, + { name: 'demo-stack-nginx-01', value: 1.1, color: '#93b1d3' }, + { name: 'demo-stack-mysql-01', value: 1.2, color: '#82a7cd' }, + { name: 'demo-stack-apache-01', value: 1.4, color: '#6092c0' }, + ]); + }); }); it('group nodes by custom field', async () => { @@ -98,27 +103,30 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await pageObjects.infraHome.goToTime(DATE_WITH_DATA); await pageObjects.infraHome.getWaffleMap(); await pageObjects.infraHome.enterSearchTerm('host.name: "demo-stack-apache-01"'); - const nodesWithValue = await pageObjects.infraHome.getNodesWithValues(); - expect(nodesWithValue).to.eql([ - { name: 'demo-stack-apache-01', value: 1.4, color: '#6092c0' }, - ]); + await retry.try(async () => { + const nodesWithValue = await pageObjects.infraHome.getNodesWithValues(); + expect(nodesWithValue).to.eql([ + { name: 'demo-stack-apache-01', value: 1.4, color: '#6092c0' }, + ]); + }); await pageObjects.infraHome.clearSearchTerm(); }); - // Tracked in https://github.com/elastic/kibana/issues/118481 - it.skip('change color palette', async () => { + it('change color palette', async () => { await pageObjects.infraHome.openLegendControls(); await pageObjects.infraHome.changePalette('temperature'); await pageObjects.infraHome.applyLegendControls(); - const nodesWithValue = await pageObjects.infraHome.getNodesWithValues(); - expect(nodesWithValue).to.eql([ - { name: 'demo-stack-client-01', value: 0.6, color: '#6092c0' }, - { name: 'demo-stack-haproxy-01', value: 0.8, color: '#b5c9df' }, - { name: 'demo-stack-redis-01', value: 1, color: '#f1d9b9' }, - { name: 'demo-stack-nginx-01', value: 1.1, color: '#eec096' }, - { name: 'demo-stack-mysql-01', value: 1.2, color: '#eba47a' }, - { name: 'demo-stack-apache-01', value: 1.4, color: '#e7664c' }, - ]); + await retry.try(async () => { + const nodesWithValue = await pageObjects.infraHome.getNodesWithValues(); + expect(nodesWithValue).to.eql([ + { name: 'demo-stack-client-01', value: 0.6, color: '#6092c0' }, + { name: 'demo-stack-haproxy-01', value: 0.8, color: '#b5c9df' }, + { name: 'demo-stack-redis-01', value: 1, color: '#f1d9b9' }, + { name: 'demo-stack-nginx-01', value: 1.1, color: '#eec096' }, + { name: 'demo-stack-mysql-01', value: 1.2, color: '#eba47a' }, + { name: 'demo-stack-apache-01', value: 1.4, color: '#e7664c' }, + ]); + }); }); it('toggle the timeline', async () => { From 8232b70646c105bfdf1fd2c0307e24615722ad43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20S=C3=A1nchez?= Date: Wed, 17 Nov 2021 10:01:41 +0100 Subject: [PATCH 062/148] [Security Solution] [Endpoint] Set page index to 0 when changing page size (#118169) * Set page index to 0 when changing page size * Change page index depending on page size without losing the current results * PR suggestions to avoid NaN values * use constants instead of hardcoded values Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../paginated_content/paginated_content.tsx | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/security_solution/public/management/components/paginated_content/paginated_content.tsx b/x-pack/plugins/security_solution/public/management/components/paginated_content/paginated_content.tsx index 0a6b66afebc32..b01dc15a06443 100644 --- a/x-pack/plugins/security_solution/public/management/components/paginated_content/paginated_content.tsx +++ b/x-pack/plugins/security_solution/public/management/components/paginated_content/paginated_content.tsx @@ -34,6 +34,7 @@ import { FormattedMessage } from '@kbn/i18n/react'; import { v4 as generateUUI } from 'uuid'; import { useTestIdGenerator } from '../hooks/use_test_id_generator'; import { MaybeImmutable } from '../../../../common/endpoint/types'; +import { MANAGEMENT_DEFAULT_PAGE, MANAGEMENT_DEFAULT_PAGE_SIZE } from '../../common/constants'; // eslint-disable-next-line @typescript-eslint/no-explicit-any type ComponentWithAnyProps = ComponentType; @@ -164,14 +165,26 @@ export const PaginatedContent = memo( const handleItemsPerPageChange: EuiTablePaginationProps['onChangeItemsPerPage'] = useCallback( (pageSize) => { - onChange({ pageSize, pageIndex: pagination?.pageIndex || 0 }); + if (pagination?.pageIndex) { + const pageIndex = Math.floor( + ((pagination?.pageIndex ?? MANAGEMENT_DEFAULT_PAGE) * + (pagination?.pageSize ?? MANAGEMENT_DEFAULT_PAGE_SIZE)) / + pageSize + ); + onChange({ + pageSize, + pageIndex: isNaN(pageIndex) ? MANAGEMENT_DEFAULT_PAGE : pageIndex, + }); + } else { + onChange({ pageSize, pageIndex: MANAGEMENT_DEFAULT_PAGE }); + } }, - [onChange, pagination?.pageIndex] + [onChange, pagination] ); const handlePageChange: EuiTablePaginationProps['onChangePage'] = useCallback( (pageIndex) => { - onChange({ pageIndex, pageSize: pagination?.pageSize || 10 }); + onChange({ pageIndex, pageSize: pagination?.pageSize || MANAGEMENT_DEFAULT_PAGE_SIZE }); }, [onChange, pagination?.pageSize] ); From deed64cc79f4189c74de91c65709162dff2e1625 Mon Sep 17 00:00:00 2001 From: vladpro25 <91911546+vladpro25@users.noreply.github.com> Date: Wed, 17 Nov 2021 11:16:12 +0200 Subject: [PATCH 063/148] [Console] Fixes Autocomplete/Suggestion for geo_* queries. (#115348) * Autostuggestion for geo_* added... * Autostuggestion for geo_* added * Fixes Autocomplete/Suggestion for geo_* queries Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../server/lib/spec_definitions/js/filter.ts | 4 -- .../lib/spec_definitions/js/query/dsl.ts | 54 ++++++++++++++++++- 2 files changed, 52 insertions(+), 6 deletions(-) diff --git a/src/plugins/console/server/lib/spec_definitions/js/filter.ts b/src/plugins/console/server/lib/spec_definitions/js/filter.ts index ce76864399430..79ce387ea1423 100644 --- a/src/plugins/console/server/lib/spec_definitions/js/filter.ts +++ b/src/plugins/console/server/lib/spec_definitions/js/filter.ts @@ -79,16 +79,12 @@ filters.geo_bounding_box = { filters.geo_distance = { __template: { distance: 100, - distance_unit: 'km', FIELD: { lat: 40.73, lon: -74.1, }, }, distance: 100, - distance_unit: { - __one_of: ['km', 'miles'], - }, distance_type: { __one_of: ['arc', 'plane'], }, diff --git a/src/plugins/console/server/lib/spec_definitions/js/query/dsl.ts b/src/plugins/console/server/lib/spec_definitions/js/query/dsl.ts index 1a9998d2d704a..50da221c7e6bb 100644 --- a/src/plugins/console/server/lib/spec_definitions/js/query/dsl.ts +++ b/src/plugins/console/server/lib/spec_definitions/js/query/dsl.ts @@ -652,11 +652,61 @@ export const query = (specService: SpecDefinitionsService) => { }, geo_shape: { __template: { - location: {}, - relation: 'within', + FIELD: { + shape: { + type: 'envelope', + coordinates: [ + [-45, 45], + [45, -45], + ], + }, + relation: 'within', + }, }, __scope_link: '.filter.geo_shape', }, + geo_bounding_box: { + __template: { + FIELD: { + top_left: { + lat: 40.73, + lon: -74.1, + }, + bottom_right: { + lat: 40.717, + lon: -73.99, + }, + }, + }, + __scope_link: '.filter.geo_bounding_box', + }, + geo_distance: { + __template: { + distance: 100, + FIELD: { + lat: 40.73, + lon: -74.1, + }, + }, + __scope_link: '.filter.geo_distance', + }, + geo_polygon: { + __template: { + FIELD: { + points: [ + { + lat: 40.73, + lon: -74.1, + }, + { + lat: 40.83, + lon: -75.1, + }, + ], + }, + }, + __scope_link: '.filter.geo_polygon', + }, // js hint gets confused here /* jshint -W015 */ function_score: _.defaults( From ef018bb0e6006cf28f20b8e60dc459fb687d85da Mon Sep 17 00:00:00 2001 From: Abdul Wahab Zahid Date: Wed, 17 Nov 2021 10:29:47 +0100 Subject: [PATCH 064/148] [Exploratory View] Make series editor header sticky (#118223) * Make exploratory view series editor section header sticky when scrolled so that Apply Changes button is always in view. (#118223) (#117131) --- .../exploratory_view/exploratory_view.tsx | 58 ++++++++-------- .../series_editor/series_editor.tsx | 69 ++++++++++++------- 2 files changed, 75 insertions(+), 52 deletions(-) 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 index ceb87429f9de4..6ffb49560722a 100644 --- 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 @@ -102,11 +102,7 @@ export function ExploratoryView({ chartTimeRange={chartTimeRangeContext} /> - + {(EuiResizablePanel, EuiResizableButton, { togglePanel }) => { collapseFn.current = (id, direction) => togglePanel?.(id, { direction }); @@ -134,20 +130,13 @@ export function ExploratoryView({ mode={'main'} id="seriesPanel" color="subdued" + className="paddingTopSmall" > - {hiddenPanel === 'chartPanel' ? ( - onChange('chartPanel')} iconType="arrowDown"> - {SHOW_CHART_LABEL} - - ) : ( - onChange('chartPanel')} - iconType="arrowUp" - color="text" - > - {HIDE_CHART_LABEL} - - )} + onChange('chartPanel')} + /> + ); }} - + {hiddenPanel === 'seriesPanel' && ( onChange('seriesPanel')} iconType="arrowUp"> {PREVIEW_LABEL} @@ -180,6 +169,14 @@ const LensWrapper = styled.div<{ height: string }>` height: 100%; } `; + +const ResizableContainer = styled(EuiResizableContainer)` + height: 100%; + &&& .paddingTopSmall { + padding-top: 8px; + } +`; + const Wrapper = styled(EuiPanel)` max-width: 1800px; min-width: 800px; @@ -197,15 +194,22 @@ const ShowPreview = styled(EuiButtonEmpty)` position: absolute; bottom: 34px; `; -const HideChart = styled(EuiButtonEmpty)` - position: absolute; - top: -35px; - right: 50px; -`; -const ShowChart = styled(EuiButtonEmpty)` + +const ChartToggle = styled(({ isCollapsed, ...rest }) => ( + + {isCollapsed ? SHOW_CHART_LABEL : HIDE_CHART_LABEL} + +))` + &:focus, + &:focus:enabled { + background: none; + } position: absolute; - top: -10px; - right: 50px; + top: -30px; + right: 0; `; const HIDE_CHART_LABEL = i18n.translate('xpack.observability.overview.exploratoryView.hideChart', { 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 index 0402dcc4d990a..15040592686e0 100644 --- 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 @@ -7,9 +7,9 @@ import React, { useEffect, useState } from 'react'; import { i18n } from '@kbn/i18n'; -import { EuiSpacer, EuiFormRow, EuiFlexItem, EuiFlexGroup, EuiHorizontalRule } from '@elastic/eui'; +import { EuiSpacer, EuiFormRow, EuiFlexItem, EuiFlexGroup } from '@elastic/eui'; import { rgba } from 'polished'; -import { euiStyled } from './../../../../../../../../src/plugins/kibana_react/common'; +import { euiStyled } from '../../../../../../../../src/plugins/kibana_react/common'; import { AppDataType, ReportViewType, BuilderItem } from '../types'; import { SeriesContextValue, useSeriesStorage } from '../hooks/use_series_storage'; import { IndexPatternState, useAppIndexPatternContext } from '../hooks/use_app_index_pattern'; @@ -115,23 +115,25 @@ export const SeriesEditor = React.memo(function () { return ( -
    - - - - - - - - setItemIdToExpandedRowMap({})} /> - - - - + + + + + + + + + + setItemIdToExpandedRowMap({})} /> + + + + {editorItems.map((item) => (
    ))} - -
    +
    ); }); @@ -185,6 +186,28 @@ const Wrapper = euiStyled.div` } `; +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.paddingSizes.m} 0; +`; + export const LOADING_VIEW = i18n.translate( 'xpack.observability.expView.seriesBuilder.loadingView', { @@ -199,10 +222,6 @@ export const SELECT_REPORT_TYPE = i18n.translate( } ); -export const RESET_LABEL = i18n.translate('xpack.observability.expView.seriesBuilder.reset', { - defaultMessage: 'Reset', -}); - export const REPORT_TYPE_LABEL = i18n.translate( 'xpack.observability.expView.seriesBuilder.reportType', { From 04d57627207a6d6674df706cd48f56f11049f698 Mon Sep 17 00:00:00 2001 From: Pierre Gayvallet Date: Wed, 17 Nov 2021 10:37:29 +0100 Subject: [PATCH 065/148] Add wrapper and utilities around `EuiThemeProvider` (#117368) * draft implementation * refactor and do not use COLOR_MODES_STANDARD * plug CoreThemeProvider to rendering service * plug CoreThemeProvider to toast service * plug CoreThemeProvider to overlay service * adapt tests * adapt application tests * adapt core apps * fix tests and snapshots * fix types * fix setup mock * fix more types * add theme support to `toMountPoint` * add theme start to public API * fix integration test * self-review, first batch * self-review, second batch * add tests for core theme provider * add theme service tests * add more tests * add test for to_mount_point * update generated doc * fix type in story file * fix type in fleet story context * use proper theme$ for devtool's mount * update generated doc * review comments * introduce CoreContextProvider Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- ...a-plugin-core-public.appmountparameters.md | 1 + ...n-core-public.appmountparameters.theme_.md | 33 + .../kibana-plugin-core-public.coresetup.md | 1 + ...bana-plugin-core-public.coresetup.theme.md | 13 + .../kibana-plugin-core-public.corestart.md | 1 + ...bana-plugin-core-public.corestart.theme.md | 13 + ...a-plugin-core-public.coretheme.darkmode.md | 13 + .../kibana-plugin-core-public.coretheme.md | 20 + .../core/public/kibana-plugin-core-public.md | 3 + ...na-plugin-core-public.themeservicesetup.md | 19 + ...in-core-public.themeservicesetup.theme_.md | 11 + ...na-plugin-core-public.themeservicestart.md | 19 + ...in-core-public.themeservicestart.theme_.md | 11 + ...e-server.eventloopdelaysmonitor.collect.md | 2 + ...ugin-core-server.eventloopdelaysmonitor.md | 2 +- ...na-plugin-core-server.intervalhistogram.md | 2 +- .../core/server/kibana-plugin-core-server.md | 2 +- .../application_service.test.ts.snap | 6 + .../application/application_service.mock.ts | 17 + .../application/application_service.test.ts | 19 +- .../application/application_service.tsx | 5 +- .../application_service.test.tsx | 7 +- .../integration_tests/router.test.tsx | 18 + src/core/public/application/types.ts | 24 + .../application/ui/app_container.test.tsx | 61 +- .../public/application/ui/app_container.tsx | 6 + src/core/public/application/ui/app_router.tsx | 7 +- .../core_app/errors/error_application.test.ts | 14 +- .../core_app/errors/error_application.tsx | 7 +- .../public/core_app/status/render_app.tsx | 10 +- src/core/public/core_system.test.mocks.ts | 7 + src/core/public/core_system.test.ts | 24 + src/core/public/core_system.ts | 16 +- src/core/public/index.ts | 7 + .../injected_metadata_service.mock.ts | 2 + .../injected_metadata_service.ts | 13 + src/core/public/mocks.ts | 5 + .../notifications/notifications_service.ts | 16 +- .../toasts_service.test.tsx.snap | 18 +- .../toasts/toasts_service.test.tsx | 10 +- .../notifications/toasts/toasts_service.tsx | 9 +- .../flyout_service.test.tsx.snap | 148 ++- .../overlays/flyout/flyout_service.test.tsx | 8 +- .../public/overlays/flyout/flyout_service.tsx | 10 +- .../__snapshots__/modal_service.test.tsx.snap | 1076 ++++++++++++++++- .../overlays/modal/modal_service.test.tsx | 8 +- .../public/overlays/modal/modal_service.tsx | 15 +- src/core/public/overlays/overlay_service.ts | 8 +- src/core/public/plugins/plugin_context.ts | 2 + .../public/plugins/plugins_service.test.ts | 3 + src/core/public/public.api.md | 25 +- .../rendering/rendering_service.test.tsx | 10 + .../public/rendering/rendering_service.tsx | 18 +- .../public/theme/convert_core_theme.test.ts | 19 + src/core/public/theme/convert_core_theme.ts | 24 + .../public/theme/core_theme_provider.test.tsx | 85 ++ src/core/public/theme/core_theme_provider.tsx | 36 + src/core/public/theme/index.ts | 11 + src/core/public/theme/theme_service.mock.ts | 61 + src/core/public/theme/theme_service.test.ts | 50 + src/core/public/theme/theme_service.ts | 44 + src/core/public/theme/types.ts | 33 + .../public/utils/core_context_provider.tsx | 28 + src/core/public/utils/index.ts | 1 + .../rendering_service.test.ts.snap | 32 + src/core/server/rendering/index.ts | 10 +- .../server/rendering/rendering_service.tsx | 4 + src/core/server/rendering/types.ts | 63 +- src/plugins/dev_tools/public/application.tsx | 9 +- src/plugins/dev_tools/public/plugin.ts | 4 +- src/plugins/kibana_react/public/index.ts | 2 + .../kibana_react/public/theme/index.ts | 11 + .../theme/kibana_theme_provider.test.tsx | 85 ++ .../public/theme/kibana_theme_provider.tsx | 28 + .../kibana_react/public/theme/types.ts | 11 + .../kibana_react/public/theme/utils.test.ts | 19 + .../kibana_react/public/theme/utils.ts | 15 + .../public/theme/wrap_with_theme.tsx | 19 + src/plugins/kibana_react/public/util/index.ts | 1 + .../public/util/to_mount_point.test.tsx | 72 ++ .../public/util/to_mount_point.tsx | 16 +- .../management_section/mount_section.tsx | 71 +- .../plugins/fleet/storybook/context/index.tsx | 4 + .../pages/overview/overview.stories.tsx | 19 +- .../account_management_app.test.ts | 3 +- .../access_agreement_app.test.ts | 3 +- .../logged_out/logged_out_app.test.ts | 3 +- .../authentication/login/login_app.test.ts | 3 +- .../authentication/logout/logout_app.test.ts | 3 +- .../overwritten_session_app.test.ts | 3 +- 90 files changed, 2567 insertions(+), 163 deletions(-) create mode 100644 docs/development/core/public/kibana-plugin-core-public.appmountparameters.theme_.md create mode 100644 docs/development/core/public/kibana-plugin-core-public.coresetup.theme.md create mode 100644 docs/development/core/public/kibana-plugin-core-public.corestart.theme.md create mode 100644 docs/development/core/public/kibana-plugin-core-public.coretheme.darkmode.md create mode 100644 docs/development/core/public/kibana-plugin-core-public.coretheme.md create mode 100644 docs/development/core/public/kibana-plugin-core-public.themeservicesetup.md create mode 100644 docs/development/core/public/kibana-plugin-core-public.themeservicesetup.theme_.md create mode 100644 docs/development/core/public/kibana-plugin-core-public.themeservicestart.md create mode 100644 docs/development/core/public/kibana-plugin-core-public.themeservicestart.theme_.md create mode 100644 src/core/public/theme/convert_core_theme.test.ts create mode 100644 src/core/public/theme/convert_core_theme.ts create mode 100644 src/core/public/theme/core_theme_provider.test.tsx create mode 100644 src/core/public/theme/core_theme_provider.tsx create mode 100644 src/core/public/theme/index.ts create mode 100644 src/core/public/theme/theme_service.mock.ts create mode 100644 src/core/public/theme/theme_service.test.ts create mode 100644 src/core/public/theme/theme_service.ts create mode 100644 src/core/public/theme/types.ts create mode 100644 src/core/public/utils/core_context_provider.tsx create mode 100644 src/plugins/kibana_react/public/theme/index.ts create mode 100644 src/plugins/kibana_react/public/theme/kibana_theme_provider.test.tsx create mode 100644 src/plugins/kibana_react/public/theme/kibana_theme_provider.tsx create mode 100644 src/plugins/kibana_react/public/theme/types.ts create mode 100644 src/plugins/kibana_react/public/theme/utils.test.ts create mode 100644 src/plugins/kibana_react/public/theme/utils.ts create mode 100644 src/plugins/kibana_react/public/theme/wrap_with_theme.tsx create mode 100644 src/plugins/kibana_react/public/util/to_mount_point.test.tsx diff --git a/docs/development/core/public/kibana-plugin-core-public.appmountparameters.md b/docs/development/core/public/kibana-plugin-core-public.appmountparameters.md index d32faa55a5f86..4608767651d2a 100644 --- a/docs/development/core/public/kibana-plugin-core-public.appmountparameters.md +++ b/docs/development/core/public/kibana-plugin-core-public.appmountparameters.md @@ -20,4 +20,5 @@ export interface AppMountParameters | [history](./kibana-plugin-core-public.appmountparameters.history.md) | ScopedHistory<HistoryLocationState> | A scoped history instance for your application. Should be used to wire up your applications Router. | | [onAppLeave](./kibana-plugin-core-public.appmountparameters.onappleave.md) | (handler: AppLeaveHandler) => void | A function that can be used to register a handler that will be called when the user is leaving the current application, allowing to prompt a confirmation message before actually changing the page.This will be called either when the user goes to another application, or when trying to close the tab or manually changing the url. | | [setHeaderActionMenu](./kibana-plugin-core-public.appmountparameters.setheaderactionmenu.md) | (menuMount: MountPoint \| undefined) => void | A function that can be used to set the mount point used to populate the application action container in the chrome header.Calling the handler multiple time will erase the current content of the action menu with the mount from the latest call. Calling the handler with undefined will unmount the current mount point. Calling the handler after the application has been unmounted will have no effect. | +| [theme$](./kibana-plugin-core-public.appmountparameters.theme_.md) | Observable<CoreTheme> | An observable emitting [Core's theme](./kibana-plugin-core-public.coretheme.md). Should be used when mounting the application to include theme information. | diff --git a/docs/development/core/public/kibana-plugin-core-public.appmountparameters.theme_.md b/docs/development/core/public/kibana-plugin-core-public.appmountparameters.theme_.md new file mode 100644 index 0000000000000..dd105e937a3a8 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.appmountparameters.theme_.md @@ -0,0 +1,33 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [AppMountParameters](./kibana-plugin-core-public.appmountparameters.md) > [theme$](./kibana-plugin-core-public.appmountparameters.theme_.md) + +## AppMountParameters.theme$ property + +An observable emitting [Core's theme](./kibana-plugin-core-public.coretheme.md). Should be used when mounting the application to include theme information. + +Signature: + +```typescript +theme$: Observable; +``` + +## Example + +When mounting a react application: + +```ts +// application.tsx +import React from 'react'; +import ReactDOM from 'react-dom'; + +import { AppMountParameters } from 'src/core/public'; +import { wrapWithTheme } from 'src/plugins/kibana_react'; +import { MyApp } from './app'; + +export renderApp = ({ element, theme$ }: AppMountParameters) => { + ReactDOM.render(wrapWithTheme(, theme$), element); + return () => ReactDOM.unmountComponentAtNode(element); +} +``` + diff --git a/docs/development/core/public/kibana-plugin-core-public.coresetup.md b/docs/development/core/public/kibana-plugin-core-public.coresetup.md index 18af0c7ea5855..9488b8a26b867 100644 --- a/docs/development/core/public/kibana-plugin-core-public.coresetup.md +++ b/docs/development/core/public/kibana-plugin-core-public.coresetup.md @@ -22,5 +22,6 @@ export interface CoreSetup + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [CoreSetup](./kibana-plugin-core-public.coresetup.md) > [theme](./kibana-plugin-core-public.coresetup.theme.md) + +## CoreSetup.theme property + +[ThemeServiceSetup](./kibana-plugin-core-public.themeservicesetup.md) + +Signature: + +```typescript +theme: ThemeServiceSetup; +``` diff --git a/docs/development/core/public/kibana-plugin-core-public.corestart.md b/docs/development/core/public/kibana-plugin-core-public.corestart.md index e0f6a68782410..ae67696e12501 100644 --- a/docs/development/core/public/kibana-plugin-core-public.corestart.md +++ b/docs/development/core/public/kibana-plugin-core-public.corestart.md @@ -27,5 +27,6 @@ export interface CoreStart | [notifications](./kibana-plugin-core-public.corestart.notifications.md) | NotificationsStart | [NotificationsStart](./kibana-plugin-core-public.notificationsstart.md) | | [overlays](./kibana-plugin-core-public.corestart.overlays.md) | OverlayStart | [OverlayStart](./kibana-plugin-core-public.overlaystart.md) | | [savedObjects](./kibana-plugin-core-public.corestart.savedobjects.md) | SavedObjectsStart | [SavedObjectsStart](./kibana-plugin-core-public.savedobjectsstart.md) | +| [theme](./kibana-plugin-core-public.corestart.theme.md) | ThemeServiceStart | [ThemeServiceStart](./kibana-plugin-core-public.themeservicestart.md) | | [uiSettings](./kibana-plugin-core-public.corestart.uisettings.md) | IUiSettingsClient | [IUiSettingsClient](./kibana-plugin-core-public.iuisettingsclient.md) | diff --git a/docs/development/core/public/kibana-plugin-core-public.corestart.theme.md b/docs/development/core/public/kibana-plugin-core-public.corestart.theme.md new file mode 100644 index 0000000000000..306ab211798fe --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.corestart.theme.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [CoreStart](./kibana-plugin-core-public.corestart.md) > [theme](./kibana-plugin-core-public.corestart.theme.md) + +## CoreStart.theme property + +[ThemeServiceStart](./kibana-plugin-core-public.themeservicestart.md) + +Signature: + +```typescript +theme: ThemeServiceStart; +``` diff --git a/docs/development/core/public/kibana-plugin-core-public.coretheme.darkmode.md b/docs/development/core/public/kibana-plugin-core-public.coretheme.darkmode.md new file mode 100644 index 0000000000000..d62f9486e66ee --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.coretheme.darkmode.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [CoreTheme](./kibana-plugin-core-public.coretheme.md) > [darkMode](./kibana-plugin-core-public.coretheme.darkmode.md) + +## CoreTheme.darkMode property + +is dark mode enabled or not + +Signature: + +```typescript +readonly darkMode: boolean; +``` diff --git a/docs/development/core/public/kibana-plugin-core-public.coretheme.md b/docs/development/core/public/kibana-plugin-core-public.coretheme.md new file mode 100644 index 0000000000000..552113b8d2c47 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.coretheme.md @@ -0,0 +1,20 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [CoreTheme](./kibana-plugin-core-public.coretheme.md) + +## CoreTheme interface + +Contains all the required information to apply Kibana's theme at the various levels it can be used. + +Signature: + +```typescript +export interface CoreTheme +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [darkMode](./kibana-plugin-core-public.coretheme.darkmode.md) | boolean | is dark mode enabled or not | + diff --git a/docs/development/core/public/kibana-plugin-core-public.md b/docs/development/core/public/kibana-plugin-core-public.md index dee77e8994155..b51f5ed833fd3 100644 --- a/docs/development/core/public/kibana-plugin-core-public.md +++ b/docs/development/core/public/kibana-plugin-core-public.md @@ -58,6 +58,7 @@ The plugin integrates with the core system via lifecycle events: `setup` | [ChromeUserBanner](./kibana-plugin-core-public.chromeuserbanner.md) | | | [CoreSetup](./kibana-plugin-core-public.coresetup.md) | Core services exposed to the Plugin setup lifecycle | | [CoreStart](./kibana-plugin-core-public.corestart.md) | Core services exposed to the Plugin start lifecycle | +| [CoreTheme](./kibana-plugin-core-public.coretheme.md) | Contains all the required information to apply Kibana's theme at the various levels it can be used. | | [DeprecationsServiceStart](./kibana-plugin-core-public.deprecationsservicestart.md) | DeprecationsService provides methods to fetch domain deprecation details from the Kibana server. | | [DocLinksStart](./kibana-plugin-core-public.doclinksstart.md) | | | [ErrorToastOptions](./kibana-plugin-core-public.errortoastoptions.md) | Options available for [IToasts](./kibana-plugin-core-public.itoasts.md) error APIs. | @@ -131,6 +132,8 @@ The plugin integrates with the core system via lifecycle events: `setup` | [SavedObjectsResolveResponse](./kibana-plugin-core-public.savedobjectsresolveresponse.md) | | | [SavedObjectsStart](./kibana-plugin-core-public.savedobjectsstart.md) | | | [SavedObjectsUpdateOptions](./kibana-plugin-core-public.savedobjectsupdateoptions.md) | | +| [ThemeServiceSetup](./kibana-plugin-core-public.themeservicesetup.md) | | +| [ThemeServiceStart](./kibana-plugin-core-public.themeservicestart.md) | | | [ToastOptions](./kibana-plugin-core-public.toastoptions.md) | Options available for [IToasts](./kibana-plugin-core-public.itoasts.md) APIs. | | [UiSettingsParams](./kibana-plugin-core-public.uisettingsparams.md) | UiSettings parameters defined by the plugins. | | [UiSettingsState](./kibana-plugin-core-public.uisettingsstate.md) | | diff --git a/docs/development/core/public/kibana-plugin-core-public.themeservicesetup.md b/docs/development/core/public/kibana-plugin-core-public.themeservicesetup.md new file mode 100644 index 0000000000000..f372ed9b22efb --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.themeservicesetup.md @@ -0,0 +1,19 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [ThemeServiceSetup](./kibana-plugin-core-public.themeservicesetup.md) + +## ThemeServiceSetup interface + + +Signature: + +```typescript +export interface ThemeServiceSetup +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [theme$](./kibana-plugin-core-public.themeservicesetup.theme_.md) | Observable<CoreTheme> | | + diff --git a/docs/development/core/public/kibana-plugin-core-public.themeservicesetup.theme_.md b/docs/development/core/public/kibana-plugin-core-public.themeservicesetup.theme_.md new file mode 100644 index 0000000000000..e043d32a69629 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.themeservicesetup.theme_.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [ThemeServiceSetup](./kibana-plugin-core-public.themeservicesetup.md) > [theme$](./kibana-plugin-core-public.themeservicesetup.theme_.md) + +## ThemeServiceSetup.theme$ property + +Signature: + +```typescript +theme$: Observable; +``` diff --git a/docs/development/core/public/kibana-plugin-core-public.themeservicestart.md b/docs/development/core/public/kibana-plugin-core-public.themeservicestart.md new file mode 100644 index 0000000000000..85122b31e4f29 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.themeservicestart.md @@ -0,0 +1,19 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [ThemeServiceStart](./kibana-plugin-core-public.themeservicestart.md) + +## ThemeServiceStart interface + + +Signature: + +```typescript +export interface ThemeServiceStart +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [theme$](./kibana-plugin-core-public.themeservicestart.theme_.md) | Observable<CoreTheme> | | + diff --git a/docs/development/core/public/kibana-plugin-core-public.themeservicestart.theme_.md b/docs/development/core/public/kibana-plugin-core-public.themeservicestart.theme_.md new file mode 100644 index 0000000000000..416f1b1de6ede --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.themeservicestart.theme_.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [ThemeServiceStart](./kibana-plugin-core-public.themeservicestart.md) > [theme$](./kibana-plugin-core-public.themeservicestart.theme_.md) + +## ThemeServiceStart.theme$ property + +Signature: + +```typescript +theme$: Observable; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.eventloopdelaysmonitor.collect.md b/docs/development/core/server/kibana-plugin-core-server.eventloopdelaysmonitor.collect.md index 36cb2d2d20944..ff9c57787f71d 100644 --- a/docs/development/core/server/kibana-plugin-core-server.eventloopdelaysmonitor.collect.md +++ b/docs/development/core/server/kibana-plugin-core-server.eventloopdelaysmonitor.collect.md @@ -6,6 +6,8 @@ Collect gathers event loop delays metrics from nodejs perf\_hooks.monitorEventLoopDelay the histogram calculations start from the last time `reset` was called or this EventLoopDelaysMonitor instance was created. +Returns metrics in milliseconds. + Signature: ```typescript diff --git a/docs/development/core/server/kibana-plugin-core-server.eventloopdelaysmonitor.md b/docs/development/core/server/kibana-plugin-core-server.eventloopdelaysmonitor.md index 21bbd8b48840c..e5d35547d3bdb 100644 --- a/docs/development/core/server/kibana-plugin-core-server.eventloopdelaysmonitor.md +++ b/docs/development/core/server/kibana-plugin-core-server.eventloopdelaysmonitor.md @@ -20,7 +20,7 @@ export declare class EventLoopDelaysMonitor | Method | Modifiers | Description | | --- | --- | --- | -| [collect()](./kibana-plugin-core-server.eventloopdelaysmonitor.collect.md) | | Collect gathers event loop delays metrics from nodejs perf\_hooks.monitorEventLoopDelay the histogram calculations start from the last time reset was called or this EventLoopDelaysMonitor instance was created. | +| [collect()](./kibana-plugin-core-server.eventloopdelaysmonitor.collect.md) | | Collect gathers event loop delays metrics from nodejs perf\_hooks.monitorEventLoopDelay the histogram calculations start from the last time reset was called or this EventLoopDelaysMonitor instance was created.Returns metrics in milliseconds. | | [reset()](./kibana-plugin-core-server.eventloopdelaysmonitor.reset.md) | | Resets the collected histogram data. | | [stop()](./kibana-plugin-core-server.eventloopdelaysmonitor.stop.md) | | Disables updating the interval timer for collecting new data points. | diff --git a/docs/development/core/server/kibana-plugin-core-server.intervalhistogram.md b/docs/development/core/server/kibana-plugin-core-server.intervalhistogram.md index 39f2d570cd259..56a87a1577e98 100644 --- a/docs/development/core/server/kibana-plugin-core-server.intervalhistogram.md +++ b/docs/development/core/server/kibana-plugin-core-server.intervalhistogram.md @@ -4,7 +4,7 @@ ## IntervalHistogram interface -an IntervalHistogram object that samples and reports the event loop delay over time. The delays will be reported in nanoseconds. +an IntervalHistogram object that samples and reports the event loop delay over time. The delays will be reported in milliseconds. Signature: diff --git a/docs/development/core/server/kibana-plugin-core-server.md b/docs/development/core/server/kibana-plugin-core-server.md index 2eed71cc6ecea..17c2ab736044e 100644 --- a/docs/development/core/server/kibana-plugin-core-server.md +++ b/docs/development/core/server/kibana-plugin-core-server.md @@ -101,7 +101,7 @@ The plugin integrates with the core system via lifecycle events: `setup` | [IExternalUrlPolicy](./kibana-plugin-core-server.iexternalurlpolicy.md) | A policy describing whether access to an external destination is allowed. | | [IKibanaResponse](./kibana-plugin-core-server.ikibanaresponse.md) | A response data object, expected to returned as a result of [RequestHandler](./kibana-plugin-core-server.requesthandler.md) execution | | [IKibanaSocket](./kibana-plugin-core-server.ikibanasocket.md) | A tiny abstraction for TCP socket. | -| [IntervalHistogram](./kibana-plugin-core-server.intervalhistogram.md) | an IntervalHistogram object that samples and reports the event loop delay over time. The delays will be reported in nanoseconds. | +| [IntervalHistogram](./kibana-plugin-core-server.intervalhistogram.md) | an IntervalHistogram object that samples and reports the event loop delay over time. The delays will be reported in milliseconds. | | [IRenderOptions](./kibana-plugin-core-server.irenderoptions.md) | | | [IRouter](./kibana-plugin-core-server.irouter.md) | Registers route handlers for specified resource path and method. See [RouteConfig](./kibana-plugin-core-server.routeconfig.md) and [RequestHandler](./kibana-plugin-core-server.requesthandler.md) for more information about arguments to route registrations. | | [ISavedObjectsPointInTimeFinder](./kibana-plugin-core-server.isavedobjectspointintimefinder.md) | | diff --git a/src/core/public/application/__snapshots__/application_service.test.ts.snap b/src/core/public/application/__snapshots__/application_service.test.ts.snap index a6c9eb27e338a..17de9503bd533 100644 --- a/src/core/public/application/__snapshots__/application_service.test.ts.snap +++ b/src/core/public/application/__snapshots__/application_service.test.ts.snap @@ -83,5 +83,11 @@ exports[`#start() getComponent returns renderable JSX tree 1`] = ` setAppActionMenu={[Function]} setAppLeaveHandler={[Function]} setIsMounting={[Function]} + theme$={ + Observable { + "_isScalar": false, + "_subscribe": [Function], + } + } /> `; diff --git a/src/core/public/application/application_service.mock.ts b/src/core/public/application/application_service.mock.ts index 3799624800c99..6319d7caebf36 100644 --- a/src/core/public/application/application_service.mock.ts +++ b/src/core/public/application/application_service.mock.ts @@ -11,12 +11,15 @@ import { BehaviorSubject, Subject } from 'rxjs'; import type { MountPoint } from '../types'; import { capabilitiesServiceMock } from './capabilities/capabilities_service.mock'; +import { themeServiceMock } from '../theme/theme_service.mock'; +import { scopedHistoryMock } from './scoped_history.mock'; import { ApplicationSetup, InternalApplicationStart, ApplicationStart, InternalApplicationSetup, PublicAppInfo, + AppMountParameters, } from './types'; import { ApplicationServiceContract } from './test_types'; @@ -81,6 +84,19 @@ const createInternalStartContractMock = (): jest.Mocked) => { + const mock: AppMountParameters = { + element: document.createElement('div'), + history: scopedHistoryMock.create(), + appBasePath: '/app', + onAppLeave: jest.fn(), + setHeaderActionMenu: jest.fn(), + theme$: themeServiceMock.createTheme$(), + ...parts, + }; + return mock; +}; + const createMock = (): jest.Mocked => ({ setup: jest.fn().mockReturnValue(createInternalSetupContractMock()), start: jest.fn().mockReturnValue(createInternalStartContractMock()), @@ -93,4 +109,5 @@ export const applicationServiceMock = { createStartContract: createStartContractMock, createInternalSetupContract: createInternalSetupContractMock, createInternalStartContract: createInternalStartContractMock, + createAppMountParameters: createAppMountParametersMock, }; diff --git a/src/core/public/application/application_service.test.ts b/src/core/public/application/application_service.test.ts index f348936d26795..ccb0b220e0243 100644 --- a/src/core/public/application/application_service.test.ts +++ b/src/core/public/application/application_service.test.ts @@ -19,6 +19,7 @@ import { mount, shallow } from 'enzyme'; import { httpServiceMock } from '../http/http_service.mock'; import { overlayServiceMock } from '../overlays/overlay_service.mock'; +import { themeServiceMock } from '../theme/theme_service.mock'; import { MockLifecycle } from './test_types'; import { ApplicationService } from './application_service'; import { App, AppDeepLink, AppNavLinkStatus, AppStatus, AppUpdater, PublicAppInfo } from './types'; @@ -44,7 +45,11 @@ describe('#setup()', () => { http, redirectTo: jest.fn(), }; - startDeps = { http, overlays: overlayServiceMock.createStartContract() }; + startDeps = { + http, + overlays: overlayServiceMock.createStartContract(), + theme: themeServiceMock.createStartContract(), + }; service = new ApplicationService(); }); @@ -454,7 +459,11 @@ describe('#start()', () => { http, redirectTo: jest.fn(), }; - startDeps = { http, overlays: overlayServiceMock.createStartContract() }; + startDeps = { + http, + overlays: overlayServiceMock.createStartContract(), + theme: themeServiceMock.createStartContract(), + }; service = new ApplicationService(); }); @@ -1124,7 +1133,11 @@ describe('#stop()', () => { setupDeps = { http, }; - startDeps = { http, overlays: overlayServiceMock.createStartContract() }; + startDeps = { + http, + overlays: overlayServiceMock.createStartContract(), + theme: themeServiceMock.createStartContract(), + }; service = new ApplicationService(); }); diff --git a/src/core/public/application/application_service.tsx b/src/core/public/application/application_service.tsx index 3ba0d78cf15fd..9f5470a2d248e 100644 --- a/src/core/public/application/application_service.tsx +++ b/src/core/public/application/application_service.tsx @@ -15,6 +15,7 @@ import { MountPoint } from '../types'; import { HttpSetup, HttpStart } from '../http'; import { OverlayStart } from '../overlays'; import { PluginOpaqueId } from '../plugins'; +import type { ThemeServiceStart } from '../theme'; import { AppRouter } from './ui'; import { Capabilities, CapabilitiesService } from './capabilities'; import { @@ -44,6 +45,7 @@ interface SetupDeps { interface StartDeps { http: HttpStart; + theme: ThemeServiceStart; overlays: OverlayStart; } @@ -191,7 +193,7 @@ export class ApplicationService { }; } - public async start({ http, overlays }: StartDeps): Promise { + public async start({ http, overlays, theme }: StartDeps): Promise { if (!this.redirectTo) { throw new Error('ApplicationService#setup() must be invoked before start.'); } @@ -314,6 +316,7 @@ export class ApplicationService { return ( { http, history: history as any, }; - startDeps = { http, overlays: overlayServiceMock.createStartContract() }; + startDeps = { + http, + overlays: overlayServiceMock.createStartContract(), + theme: themeServiceMock.createStartContract(), + }; service = new ApplicationService(); }); diff --git a/src/core/public/application/integration_tests/router.test.tsx b/src/core/public/application/integration_tests/router.test.tsx index 2543d22ee6d31..e627c8ee09a38 100644 --- a/src/core/public/application/integration_tests/router.test.tsx +++ b/src/core/public/application/integration_tests/router.test.tsx @@ -10,6 +10,7 @@ import React from 'react'; import { BehaviorSubject } from 'rxjs'; import { createMemoryHistory, History, createHashHistory } from 'history'; +import { themeServiceMock } from '../../theme/theme_service.mock'; import { AppRouter, AppNotFound } from '../ui'; import { MockedMounterMap, MockedMounterTuple } from '../test_types'; import { createRenderer, createAppMounter, getUnmounter } from './utils'; @@ -19,6 +20,7 @@ describe('AppRouter', () => { let mounters: MockedMounterMap; let globalHistory: History; let update: ReturnType; + let theme$: ReturnType; let scopedAppHistory: History; const navigate = (path: string) => { @@ -49,6 +51,7 @@ describe('AppRouter', () => { setAppLeaveHandler={noop} setAppActionMenu={noop} setIsMounting={noop} + theme$={theme$} /> ); @@ -85,10 +88,25 @@ describe('AppRouter', () => { appRoute: '/app/my-app/app6', }), ] as MockedMounterTuple[]); + theme$ = themeServiceMock.createTheme$(); globalHistory = createMemoryHistory(); update = createMountersRenderer(); }); + it('calls mount handler with the correct parameters', async () => { + const app1 = mounters.get('app1')!; + + await navigate('/app/app1'); + + expect(app1.mounter.mount).toHaveBeenCalledTimes(1); + expect(app1.mounter.mount).toHaveBeenCalledWith( + expect.objectContaining({ + appBasePath: '/app/app1', + theme$, + }) + ); + }); + it('calls mount handler and returned unmount function when navigating between apps', async () => { const app1 = mounters.get('app1')!; const app2 = mounters.get('app2')!; diff --git a/src/core/public/application/types.ts b/src/core/public/application/types.ts index 94930f55b8b2c..9c3294086efcc 100644 --- a/src/core/public/application/types.ts +++ b/src/core/public/application/types.ts @@ -11,6 +11,7 @@ import { History } from 'history'; import { RecursiveReadonly } from '@kbn/utility-types'; import { MountPoint } from '../types'; +import { CoreTheme } from '../theme'; import { Capabilities } from './capabilities'; import { PluginOpaqueId } from '../plugins'; import { AppCategory } from '../../types'; @@ -520,6 +521,29 @@ export interface AppMountParameters { * ``` */ setHeaderActionMenu: (menuMount: MountPoint | undefined) => void; + + /** + * An observable emitting {@link CoreTheme | Core's theme}. + * Should be used when mounting the application to include theme information. + * + * @example + * When mounting a react application: + * ```ts + * // application.tsx + * import React from 'react'; + * import ReactDOM from 'react-dom'; + * + * import { AppMountParameters } from 'src/core/public'; + * import { wrapWithTheme } from 'src/plugins/kibana_react'; + * import { MyApp } from './app'; + * + * export renderApp = ({ element, theme$ }: AppMountParameters) => { + * ReactDOM.render(wrapWithTheme(, theme$), element); + * return () => ReactDOM.unmountComponentAtNode(element); + * } + * ``` + */ + theme$: Observable; } /** diff --git a/src/core/public/application/ui/app_container.test.tsx b/src/core/public/application/ui/app_container.test.tsx index 4c056e748f06e..9fc07530a0095 100644 --- a/src/core/public/application/ui/app_container.test.tsx +++ b/src/core/public/application/ui/app_container.test.tsx @@ -8,8 +8,9 @@ import React from 'react'; import { act } from 'react-dom/test-utils'; -import { mount } from 'enzyme'; +import { mountWithIntl } from '@kbn/test/jest'; +import { themeServiceMock } from '../../theme/theme_service.mock'; import { AppContainer } from './app_container'; import { Mounter, AppMountParameters, AppStatus } from '../types'; import { createMemoryHistory } from 'history'; @@ -20,6 +21,7 @@ describe('AppContainer', () => { const setAppLeaveHandler = jest.fn(); const setAppActionMenu = jest.fn(); const setIsMounting = jest.fn(); + const theme$ = themeServiceMock.createTheme$(); beforeEach(() => { setAppLeaveHandler.mockClear(); @@ -59,11 +61,59 @@ describe('AppContainer', () => { }, }); + it('should call the `mount` function with the correct parameters', async () => { + const mounter: Mounter = { + appBasePath: '/base-path', + appRoute: '/some-route', + unmountBeforeMounting: false, + exactRoute: false, + deepLinkPaths: {}, + mount: jest.fn().mockImplementation(({ element }) => { + const container = document.createElement('div'); + container.innerHTML = 'some-content'; + element.appendChild(container); + return () => container.remove(); + }), + }; + + const wrapper = mountWithIntl( + + // Create a history using the appPath as the current location + new ScopedHistory(createMemoryHistory({ initialEntries: [appPath] }), appPath) + } + theme$={theme$} + /> + ); + + await act(async () => { + await flushPromises(); + wrapper.update(); + }); + + expect(mounter.mount).toHaveBeenCalledTimes(1); + expect(mounter.mount).toHaveBeenCalledWith({ + appBasePath: '/base-path', + history: expect.any(ScopedHistory), + element: expect.any(HTMLElement), + theme$, + onAppLeave: expect.any(Function), + setHeaderActionMenu: expect.any(Function), + }); + }); + it('should hide the "not found" page before mounting the route', async () => { const [waitPromise, resolvePromise] = createResolver(); const mounter = createMounter(waitPromise); - const wrapper = mount( + const wrapper = mountWithIntl( { // Create a history using the appPath as the current location new ScopedHistory(createMemoryHistory({ initialEntries: [appPath] }), appPath) } + theme$={theme$} /> ); @@ -104,7 +155,7 @@ describe('AppContainer', () => { const [waitPromise, resolvePromise] = createResolver(); const mounter = createMounter(waitPromise); - const wrapper = mount( + const wrapper = mountWithIntl( { // Create a history using the appPath as the current location new ScopedHistory(createMemoryHistory({ initialEntries: [appPath] }), appPath) } + theme$={theme$} /> ); @@ -147,7 +199,7 @@ describe('AppContainer', () => { }, }; - const wrapper = mount( + const wrapper = mountWithIntl( { // Create a history using the appPath as the current location new ScopedHistory(createMemoryHistory({ initialEntries: [appPath] }), appPath) } + theme$={theme$} /> ); diff --git a/src/core/public/application/ui/app_container.tsx b/src/core/public/application/ui/app_container.tsx index 0312c707e1049..764a8e0485104 100644 --- a/src/core/public/application/ui/app_container.tsx +++ b/src/core/public/application/ui/app_container.tsx @@ -7,6 +7,7 @@ */ import './app_container.scss'; +import { Observable } from 'rxjs'; import React, { Fragment, FunctionComponent, @@ -19,6 +20,7 @@ import { EuiLoadingElastic } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import type { MountPoint } from '../../types'; +import { CoreTheme } from '../../theme'; import { AppLeaveHandler, AppStatus, AppUnmount, Mounter } from '../types'; import { AppNotFound } from './app_not_found_screen'; import { ScopedHistory } from '../scoped_history'; @@ -29,6 +31,7 @@ interface Props { appPath: string; appId: string; mounter?: Mounter; + theme$: Observable; appStatus: AppStatus; setAppLeaveHandler: (appId: string, handler: AppLeaveHandler) => void; setAppActionMenu: (appId: string, mount: MountPoint | undefined) => void; @@ -45,6 +48,7 @@ export const AppContainer: FunctionComponent = ({ createScopedHistory, appStatus, setIsMounting, + theme$, }: Props) => { const [showSpinner, setShowSpinner] = useState(true); const [appNotFound, setAppNotFound] = useState(false); @@ -77,6 +81,7 @@ export const AppContainer: FunctionComponent = ({ appBasePath: mounter.appBasePath, history: createScopedHistory(appPath), element: elementRef.current!, + theme$, onAppLeave: (handler) => setAppLeaveHandler(appId, handler), setHeaderActionMenu: (menuMount) => setAppActionMenu(appId, menuMount), })) || null; @@ -104,6 +109,7 @@ export const AppContainer: FunctionComponent = ({ setAppActionMenu, appPath, setIsMounting, + theme$, ]); return ( diff --git a/src/core/public/application/ui/app_router.tsx b/src/core/public/application/ui/app_router.tsx index 8b74930b07462..0d398cfed12e4 100644 --- a/src/core/public/application/ui/app_router.tsx +++ b/src/core/public/application/ui/app_router.tsx @@ -13,6 +13,7 @@ import { Observable } from 'rxjs'; import useObservable from 'react-use/lib/useObservable'; import type { MountPoint } from '../../types'; +import { CoreTheme } from '../../theme'; import { AppLeaveHandler, AppStatus, Mounter } from '../types'; import { AppContainer } from './app_container'; import { ScopedHistory } from '../scoped_history'; @@ -20,6 +21,7 @@ import { ScopedHistory } from '../scoped_history'; interface Props { mounters: Map; history: History; + theme$: Observable; appStatuses$: Observable>; setAppLeaveHandler: (appId: string, handler: AppLeaveHandler) => void; setAppActionMenu: (appId: string, mount: MountPoint | undefined) => void; @@ -33,6 +35,7 @@ interface Params { export const AppRouter: FunctionComponent = ({ history, mounters, + theme$, setAppLeaveHandler, setAppActionMenu, appStatuses$, @@ -57,7 +60,7 @@ export const AppRouter: FunctionComponent = ({ appPath={path} appStatus={appStatuses.get(appId) ?? AppStatus.inaccessible} createScopedHistory={createScopedHistory} - {...{ appId, mounter, setAppLeaveHandler, setAppActionMenu, setIsMounting }} + {...{ appId, mounter, setAppLeaveHandler, setAppActionMenu, setIsMounting, theme$ }} /> )} /> @@ -79,7 +82,7 @@ export const AppRouter: FunctionComponent = ({ appId={id ?? appId} appStatus={appStatuses.get(appId) ?? AppStatus.inaccessible} createScopedHistory={createScopedHistory} - {...{ mounter, setAppLeaveHandler, setAppActionMenu, setIsMounting }} + {...{ mounter, setAppLeaveHandler, setAppActionMenu, setIsMounting, theme$ }} /> ); }} diff --git a/src/core/public/core_app/errors/error_application.test.ts b/src/core/public/core_app/errors/error_application.test.ts index 769790cabe2e3..1e12c2db6f8d1 100644 --- a/src/core/public/core_app/errors/error_application.test.ts +++ b/src/core/public/core_app/errors/error_application.test.ts @@ -10,6 +10,8 @@ import { act } from 'react-dom/test-utils'; import { History, createMemoryHistory } from 'history'; import { IBasePath } from '../../http'; import { BasePath } from '../../http/base_path'; +import { ScopedHistory } from '../../application/scoped_history'; +import { applicationServiceMock } from '../../application/application_service.mock'; import { renderApp } from './error_application'; @@ -17,13 +19,21 @@ describe('renderApp', () => { let basePath: IBasePath; let element: HTMLDivElement; let history: History; - let unmount: any; + let unmount: () => void; beforeEach(() => { basePath = new BasePath(); element = document.createElement('div'); history = createMemoryHistory(); - unmount = renderApp({ element, history } as any, { basePath }); + unmount = renderApp( + applicationServiceMock.createAppMountParameters({ + element, + history: new ScopedHistory(history, '/'), + }), + { + basePath, + } + ); }); afterEach(() => unmount()); diff --git a/src/core/public/core_app/errors/error_application.tsx b/src/core/public/core_app/errors/error_application.tsx index 8b8f3b999dc11..c04f6fd5b5408 100644 --- a/src/core/public/core_app/errors/error_application.tsx +++ b/src/core/public/core_app/errors/error_application.tsx @@ -16,6 +16,7 @@ import { EuiEmptyPrompt, EuiPage, EuiPageBody, EuiPageContent } from '@elastic/e import { UrlOverflowUi } from './url_overflow_ui'; import { IBasePath } from '../../http'; import { AppMountParameters } from '../../application'; +import { CoreThemeProvider } from '../../theme'; interface Props { title?: string; @@ -77,10 +78,12 @@ interface Deps { * Renders UI for displaying error messages. * @internal */ -export const renderApp = ({ element, history }: AppMountParameters, { basePath }: Deps) => { +export const renderApp = ({ element, history, theme$ }: AppMountParameters, { basePath }: Deps) => { ReactDOM.render( - + + + , element ); diff --git a/src/core/public/core_app/status/render_app.tsx b/src/core/public/core_app/status/render_app.tsx index 5e688238eca48..97398af6c9cf3 100644 --- a/src/core/public/core_app/status/render_app.tsx +++ b/src/core/public/core_app/status/render_app.tsx @@ -12,6 +12,7 @@ import { I18nProvider } from '@kbn/i18n/react'; import type { AppMountParameters } from '../../application'; import type { HttpSetup } from '../../http'; import type { NotificationsSetup } from '../../notifications'; +import { CoreThemeProvider } from '../../theme'; import { StatusApp } from './status_app'; interface Deps { @@ -19,10 +20,15 @@ interface Deps { notifications: NotificationsSetup; } -export const renderApp = ({ element }: AppMountParameters, { http, notifications }: Deps) => { +export const renderApp = ( + { element, theme$ }: AppMountParameters, + { http, notifications }: Deps +) => { ReactDOM.render( - + + + , element ); diff --git a/src/core/public/core_system.test.mocks.ts b/src/core/public/core_system.test.mocks.ts index afb8aec31cccd..6eddf08cd2ae1 100644 --- a/src/core/public/core_system.test.mocks.ts +++ b/src/core/public/core_system.test.mocks.ts @@ -20,6 +20,7 @@ import { docLinksServiceMock } from './doc_links/doc_links_service.mock'; import { renderingServiceMock } from './rendering/rendering_service.mock'; import { integrationsServiceMock } from './integrations/integrations_service.mock'; import { coreAppMock } from './core_app/core_app.mock'; +import { themeServiceMock } from './theme/theme_service.mock'; export const MockInjectedMetadataService = injectedMetadataServiceMock.create(); export const InjectedMetadataServiceConstructor = jest @@ -116,3 +117,9 @@ export const CoreAppConstructor = jest.fn().mockImplementation(() => MockCoreApp jest.doMock('./core_app', () => ({ CoreApp: CoreAppConstructor, })); + +export const MockThemeService = themeServiceMock.create(); +export const ThemeServiceConstructor = jest.fn().mockImplementation(() => MockThemeService); +jest.doMock('./theme', () => ({ + ThemeService: ThemeServiceConstructor, +})); diff --git a/src/core/public/core_system.test.ts b/src/core/public/core_system.test.ts index 8ead0f50785bd..74e8782d33739 100644 --- a/src/core/public/core_system.test.ts +++ b/src/core/public/core_system.test.ts @@ -32,6 +32,8 @@ import { MockIntegrationsService, CoreAppConstructor, MockCoreApp, + MockThemeService, + ThemeServiceConstructor, } from './core_system.test.mocks'; import { CoreSystem } from './core_system'; @@ -77,6 +79,7 @@ describe('constructor', () => { expect(RenderingServiceConstructor).toHaveBeenCalledTimes(1); expect(IntegrationsServiceConstructor).toHaveBeenCalledTimes(1); expect(CoreAppConstructor).toHaveBeenCalledTimes(1); + expect(ThemeServiceConstructor).toHaveBeenCalledTimes(1); }); it('passes injectedMetadata param to InjectedMetadataService', () => { @@ -182,6 +185,11 @@ describe('#setup()', () => { await setupCore(); expect(MockCoreApp.setup).toHaveBeenCalledTimes(1); }); + + it('calls theme#setup()', async () => { + await setupCore(); + expect(MockThemeService.setup).toHaveBeenCalledTimes(1); + }); }); describe('#start()', () => { @@ -235,6 +243,7 @@ describe('#start()', () => { expect(MockNotificationsService.start).toHaveBeenCalledWith({ i18n: expect.any(Object), overlays: expect.any(Object), + theme: expect.any(Object), targetDomElement: expect.any(HTMLElement), }); }); @@ -256,6 +265,8 @@ describe('#start()', () => { application: expect.any(Object), chrome: expect.any(Object), overlays: expect.any(Object), + i18n: expect.any(Object), + theme: expect.any(Object), targetDomElement: expect.any(HTMLElement), }); }); @@ -269,6 +280,11 @@ describe('#start()', () => { await startCore(); expect(MockCoreApp.start).toHaveBeenCalledTimes(1); }); + + it('calls theme#start()', async () => { + await startCore(); + expect(MockThemeService.start).toHaveBeenCalledTimes(1); + }); }); describe('#stop()', () => { @@ -327,6 +343,14 @@ describe('#stop()', () => { expect(MockCoreApp.stop).toHaveBeenCalled(); }); + it('calls theme.stop()', () => { + const coreSystem = createCoreSystem(); + + expect(MockThemeService.stop).not.toHaveBeenCalled(); + coreSystem.stop(); + expect(MockThemeService.stop).toHaveBeenCalled(); + }); + it('clears the rootDomElement', async () => { const rootDomElement = document.createElement('div'); const coreSystem = createCoreSystem({ diff --git a/src/core/public/core_system.ts b/src/core/public/core_system.ts index e5dcd8f817a0a..3d3331d54792b 100644 --- a/src/core/public/core_system.ts +++ b/src/core/public/core_system.ts @@ -28,6 +28,7 @@ import { RenderingService } from './rendering'; import { SavedObjectsService } from './saved_objects'; import { IntegrationsService } from './integrations'; import { DeprecationsService } from './deprecations'; +import { ThemeService } from './theme'; import { CoreApp } from './core_app'; import type { InternalApplicationSetup, InternalApplicationStart } from './application/types'; @@ -83,6 +84,7 @@ export class CoreSystem { private readonly integrations: IntegrationsService; private readonly coreApp: CoreApp; private readonly deprecations: DeprecationsService; + private readonly theme: ThemeService; private readonly rootDomElement: HTMLElement; private readonly coreContext: CoreContext; private fatalErrorsSetup: FatalErrorsSetup | null = null; @@ -104,6 +106,7 @@ export class CoreSystem { this.stop(); }); + this.theme = new ThemeService(); this.notifications = new NotificationsService(); this.http = new HttpService(); this.savedObjects = new SavedObjectsService(); @@ -137,6 +140,7 @@ export class CoreSystem { const http = this.http.setup({ injectedMetadata, fatalErrors: this.fatalErrorsSetup }); const uiSettings = this.uiSettings.setup({ http, injectedMetadata }); const notifications = this.notifications.setup({ uiSettings }); + const theme = this.theme.setup({ injectedMetadata }); const application = this.application.setup({ http }); this.coreApp.setup({ application, http, injectedMetadata, notifications }); @@ -147,6 +151,7 @@ export class CoreSystem { http, injectedMetadata, notifications, + theme, uiSettings, }; @@ -174,6 +179,7 @@ export class CoreSystem { const savedObjects = await this.savedObjects.start({ http }); const i18n = await this.i18n.start(); const fatalErrors = await this.fatalErrors.start(); + const theme = this.theme.start(); await this.integrations.start({ uiSettings }); const coreUiTargetDomElement = document.createElement('div'); @@ -184,15 +190,17 @@ export class CoreSystem { const overlays = this.overlay.start({ i18n, - targetDomElement: overlayTargetDomElement, + theme, uiSettings, + targetDomElement: overlayTargetDomElement, }); const notifications = await this.notifications.start({ i18n, overlays, + theme, targetDomElement: notificationsTargetDomElement, }); - const application = await this.application.start({ http, overlays }); + const application = await this.application.start({ http, theme, overlays }); const chrome = await this.chrome.start({ application, docLinks, @@ -209,6 +217,7 @@ export class CoreSystem { chrome, docLinks, http, + theme, savedObjects, i18n, injectedMetadata, @@ -231,7 +240,9 @@ export class CoreSystem { this.rendering.start({ application, chrome, + i18n, overlays, + theme, targetDomElement: coreUiTargetDomElement, }); @@ -260,6 +271,7 @@ export class CoreSystem { this.i18n.stop(); this.application.stop(); this.deprecations.stop(); + this.theme.stop(); this.rootDomElement.textContent = ''; } } diff --git a/src/core/public/index.ts b/src/core/public/index.ts index 40326d9c67606..ded7db9c6f892 100644 --- a/src/core/public/index.ts +++ b/src/core/public/index.ts @@ -64,6 +64,7 @@ import { ApplicationSetup, Capabilities, ApplicationStart } from './application' import { DocLinksStart } from './doc_links'; import { SavedObjectsStart } from './saved_objects'; import { DeprecationsServiceStart } from './deprecations'; +import type { ThemeServiceSetup, ThemeServiceStart } from './theme'; export type { PackageInfo, @@ -185,6 +186,8 @@ export type { ErrorToastOptions, } from './notifications'; +export type { ThemeServiceSetup, ThemeServiceStart, CoreTheme } from './theme'; + export type { DeprecationsServiceStart, ResolveDeprecationResponse } from './deprecations'; export type { MountPoint, UnmountCallback, PublicUiSettingsParams } from './types'; @@ -227,6 +230,8 @@ export interface CoreSetup unknown; }; + /** {@link ThemeServiceSetup} */ + theme: ThemeServiceSetup; /** {@link StartServicesAccessor} */ getStartServices: StartServicesAccessor; } @@ -275,6 +280,8 @@ export interface CoreStart { fatalErrors: FatalErrorsStart; /** {@link DeprecationsServiceStart} */ deprecations: DeprecationsServiceStart; + /** {@link ThemeServiceStart} */ + theme: ThemeServiceStart; /** * exposed temporarily until https://github.com/elastic/kibana/issues/41990 done * use *only* to retrieve config values. There is no way to set injected values diff --git a/src/core/public/injected_metadata/injected_metadata_service.mock.ts b/src/core/public/injected_metadata/injected_metadata_service.mock.ts index d6dfec4b96d8a..dc8fe63724411 100644 --- a/src/core/public/injected_metadata/injected_metadata_service.mock.ts +++ b/src/core/public/injected_metadata/injected_metadata_service.mock.ts @@ -20,6 +20,7 @@ const createSetupContractMock = () => { getExternalUrlConfig: jest.fn(), getAnonymousStatusPage: jest.fn(), getLegacyMetadata: jest.fn(), + getTheme: jest.fn(), getPlugins: jest.fn(), getInjectedVar: jest.fn(), getInjectedVars: jest.fn(), @@ -41,6 +42,7 @@ const createSetupContractMock = () => { }, } as any); setupContract.getPlugins.mockReturnValue([]); + setupContract.getTheme.mockReturnValue({ darkMode: false, version: 'v8' }); return setupContract; }; diff --git a/src/core/public/injected_metadata/injected_metadata_service.ts b/src/core/public/injected_metadata/injected_metadata_service.ts index 341fc6105bedf..bfda6d3f334ee 100644 --- a/src/core/public/injected_metadata/injected_metadata_service.ts +++ b/src/core/public/injected_metadata/injected_metadata_service.ts @@ -8,6 +8,7 @@ import { get } from 'lodash'; import { deepFreeze } from '@kbn/std'; +import type { ThemeVersion } from '@kbn/ui-shared-deps-npm'; import { DiscoveredPlugin, PluginName } from '../../server'; import { EnvironmentMode, @@ -45,6 +46,10 @@ export interface InjectedMetadataParams { vars: { [key: string]: unknown; }; + theme: { + darkMode: boolean; + version: ThemeVersion; + }; env: { mode: Readonly; packageInfo: Readonly; @@ -132,6 +137,10 @@ export class InjectedMetadataService { getKibanaBranch: () => { return this.state.branch; }, + + getTheme: () => { + return this.state.theme; + }, }; } } @@ -154,6 +163,10 @@ export interface InjectedMetadataSetup { getExternalUrlConfig: () => { policy: IExternalUrlPolicy[]; }; + getTheme: () => { + darkMode: boolean; + version: ThemeVersion; + }; /** * An array of frontend plugins in topological order. */ diff --git a/src/core/public/mocks.ts b/src/core/public/mocks.ts index 39d2dc3d5c497..f11839129be64 100644 --- a/src/core/public/mocks.ts +++ b/src/core/public/mocks.ts @@ -25,6 +25,7 @@ import { uiSettingsServiceMock } from './ui_settings/ui_settings_service.mock'; import { savedObjectsServiceMock } from './saved_objects/saved_objects_service.mock'; import { injectedMetadataServiceMock } from './injected_metadata/injected_metadata_service.mock'; import { deprecationsServiceMock } from './deprecations/deprecations_service.mock'; +import { themeServiceMock } from './theme/theme_service.mock'; export { chromeServiceMock } from './chrome/chrome_service.mock'; export { docLinksServiceMock } from './doc_links/doc_links_service.mock'; @@ -39,6 +40,7 @@ export { savedObjectsServiceMock } from './saved_objects/saved_objects_service.m export { scopedHistoryMock } from './application/scoped_history.mock'; export { applicationServiceMock } from './application/application_service.mock'; export { deprecationsServiceMock } from './deprecations/deprecations_service.mock'; +export { themeServiceMock } from './theme/theme_service.mock'; function createCoreSetupMock({ basePath = '', @@ -63,6 +65,7 @@ function createCoreSetupMock({ injectedMetadata: { getInjectedVar: injectedMetadataServiceMock.createSetupContract().getInjectedVar, }, + theme: themeServiceMock.createSetupContract(), }; return mock; @@ -80,6 +83,7 @@ function createCoreStartMock({ basePath = '' } = {}) { uiSettings: uiSettingsServiceMock.createStartContract(), savedObjects: savedObjectsServiceMock.createStartContract(), deprecations: deprecationsServiceMock.createStartContract(), + theme: themeServiceMock.createStartContract(), injectedMetadata: { getInjectedVar: injectedMetadataServiceMock.createStartContract().getInjectedVar, }, @@ -156,6 +160,7 @@ function createAppMountParametersMock(appBasePath = '') { appBasePath, element: document.createElement('div'), history, + theme$: themeServiceMock.createTheme$(), onAppLeave: jest.fn(), setHeaderActionMenu: jest.fn(), }; diff --git a/src/core/public/notifications/notifications_service.ts b/src/core/public/notifications/notifications_service.ts index a6eec50582e18..383fa2d1914cc 100644 --- a/src/core/public/notifications/notifications_service.ts +++ b/src/core/public/notifications/notifications_service.ts @@ -10,6 +10,7 @@ import { i18n } from '@kbn/i18n'; import { Subscription } from 'rxjs'; import { I18nStart } from '../i18n'; +import { ThemeServiceStart } from '../theme'; import { ToastsService, ToastsSetup, ToastsStart } from './toasts'; import { IUiSettingsClient } from '../ui_settings'; import { OverlayStart } from '../overlays'; @@ -21,6 +22,7 @@ interface SetupDeps { interface StartDeps { i18n: I18nStart; overlays: OverlayStart; + theme: ThemeServiceStart; targetDomElement: HTMLElement; } @@ -49,13 +51,23 @@ export class NotificationsService { return notificationSetup; } - public start({ i18n: i18nDep, overlays, targetDomElement }: StartDeps): NotificationsStart { + public start({ + i18n: i18nDep, + overlays, + theme, + targetDomElement, + }: StartDeps): NotificationsStart { this.targetDomElement = targetDomElement; const toastsContainer = document.createElement('div'); targetDomElement.appendChild(toastsContainer); return { - toasts: this.toasts.start({ i18n: i18nDep, overlays, targetDomElement: toastsContainer }), + toasts: this.toasts.start({ + i18n: i18nDep, + overlays, + theme, + targetDomElement: toastsContainer, + }), }; } diff --git a/src/core/public/notifications/toasts/__snapshots__/toasts_service.test.tsx.snap b/src/core/public/notifications/toasts/__snapshots__/toasts_service.test.tsx.snap index 75d456dd87f78..6e453ed8e48f5 100644 --- a/src/core/public/notifications/toasts/__snapshots__/toasts_service.test.tsx.snap +++ b/src/core/public/notifications/toasts/__snapshots__/toasts_service.test.tsx.snap @@ -3,7 +3,21 @@ exports[`#start() renders the GlobalToastList into the targetDomElement param 1`] = ` Array [ Array [ - + - , + ,
    , diff --git a/src/core/public/notifications/toasts/toasts_service.test.tsx b/src/core/public/notifications/toasts/toasts_service.test.tsx index 8099d4bfabae3..6c7394433b9ed 100644 --- a/src/core/public/notifications/toasts/toasts_service.test.tsx +++ b/src/core/public/notifications/toasts/toasts_service.test.tsx @@ -11,6 +11,7 @@ import { mockReactDomRender, mockReactDomUnmount } from './toasts_service.test.m import { ToastsService } from './toasts_service'; import { ToastsApi } from './toasts_api'; import { overlayServiceMock } from '../../overlays/overlay_service.mock'; +import { themeServiceMock } from '../../theme/theme_service.mock'; import { uiSettingsServiceMock } from '../../ui_settings/ui_settings_service.mock'; const mockI18n: any = { @@ -20,6 +21,7 @@ const mockI18n: any = { }; const mockOverlays = overlayServiceMock.createStartContract(); +const mockTheme = themeServiceMock.createStartContract(); describe('#setup()', () => { it('returns a ToastsApi', () => { @@ -39,7 +41,7 @@ describe('#start()', () => { expect(mockReactDomRender).not.toHaveBeenCalled(); toasts.setup({ uiSettings: uiSettingsServiceMock.createSetupContract() }); - toasts.start({ i18n: mockI18n, targetDomElement, overlays: mockOverlays }); + toasts.start({ i18n: mockI18n, theme: mockTheme, targetDomElement, overlays: mockOverlays }); expect(mockReactDomRender.mock.calls).toMatchSnapshot(); }); @@ -51,7 +53,7 @@ describe('#start()', () => { toasts.setup({ uiSettings: uiSettingsServiceMock.createSetupContract() }) ).toBeInstanceOf(ToastsApi); expect( - toasts.start({ i18n: mockI18n, targetDomElement, overlays: mockOverlays }) + toasts.start({ i18n: mockI18n, theme: mockTheme, targetDomElement, overlays: mockOverlays }) ).toBeInstanceOf(ToastsApi); }); }); @@ -63,7 +65,7 @@ describe('#stop()', () => { const toasts = new ToastsService(); toasts.setup({ uiSettings: uiSettingsServiceMock.createSetupContract() }); - toasts.start({ i18n: mockI18n, targetDomElement, overlays: mockOverlays }); + toasts.start({ i18n: mockI18n, theme: mockTheme, targetDomElement, overlays: mockOverlays }); expect(mockReactDomUnmount).not.toHaveBeenCalled(); toasts.stop(); @@ -82,7 +84,7 @@ describe('#stop()', () => { const toasts = new ToastsService(); toasts.setup({ uiSettings: uiSettingsServiceMock.createSetupContract() }); - toasts.start({ i18n: mockI18n, targetDomElement, overlays: mockOverlays }); + toasts.start({ i18n: mockI18n, theme: mockTheme, targetDomElement, overlays: mockOverlays }); toasts.stop(); expect(targetDomElement.childNodes).toHaveLength(0); }); diff --git a/src/core/public/notifications/toasts/toasts_service.tsx b/src/core/public/notifications/toasts/toasts_service.tsx index d50850841555f..1592c9abcc565 100644 --- a/src/core/public/notifications/toasts/toasts_service.tsx +++ b/src/core/public/notifications/toasts/toasts_service.tsx @@ -14,6 +14,8 @@ import { IUiSettingsClient } from '../../ui_settings'; import { GlobalToastList } from './global_toast_list'; import { ToastsApi, IToasts } from './toasts_api'; import { OverlayStart } from '../../overlays'; +import { ThemeServiceStart } from '../../theme'; +import { CoreContextProvider } from '../../utils'; interface SetupDeps { uiSettings: IUiSettingsClient; @@ -22,6 +24,7 @@ interface SetupDeps { interface StartDeps { i18n: I18nStart; overlays: OverlayStart; + theme: ThemeServiceStart; targetDomElement: HTMLElement; } @@ -46,17 +49,17 @@ export class ToastsService { return this.api!; } - public start({ i18n, overlays, targetDomElement }: StartDeps) { + public start({ i18n, overlays, theme, targetDomElement }: StartDeps) { this.api!.start({ overlays, i18n }); this.targetDomElement = targetDomElement; render( - + this.api!.remove(toastId)} toasts$={this.api!.get$()} /> - , + , targetDomElement ); diff --git a/src/core/public/overlays/flyout/__snapshots__/flyout_service.test.tsx.snap b/src/core/public/overlays/flyout/__snapshots__/flyout_service.test.tsx.snap index fbd09f3096854..145847c39a0b5 100644 --- a/src/core/public/overlays/flyout/__snapshots__/flyout_service.test.tsx.snap +++ b/src/core/public/overlays/flyout/__snapshots__/flyout_service.test.tsx.snap @@ -11,7 +11,21 @@ Array [ exports[`FlyoutService openFlyout() renders a flyout to the DOM 1`] = ` Array [ Array [ - + @@ -20,7 +34,7 @@ Array [ mount={[Function]} /> - , + ,
    , ], ] @@ -31,7 +45,68 @@ exports[`FlyoutService openFlyout() renders a flyout to the DOM 2`] = `"
    + + + + + , + }, + Object {}, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": + + + + , + }, + ], + }, + } + } + theme={ + Object { + "theme$": Observable { + "_isScalar": false, + "_subscribe": [Function], + }, + } + } + > @@ -40,11 +115,72 @@ Array [ mount={[Function]} /> - , + ,
    , ], Array [ - + + + + + , + }, + Object {}, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": + + + + , + }, + ], + }, + } + } + theme={ + Object { + "theme$": Observable { + "_isScalar": false, + "_subscribe": [Function], + }, + } + } + > @@ -53,7 +189,7 @@ Array [ mount={[Function]} /> - , + ,
    , ], ] diff --git a/src/core/public/overlays/flyout/flyout_service.test.tsx b/src/core/public/overlays/flyout/flyout_service.test.tsx index 0da7e14949e6e..563e1e02f2f26 100644 --- a/src/core/public/overlays/flyout/flyout_service.test.tsx +++ b/src/core/public/overlays/flyout/flyout_service.test.tsx @@ -10,10 +10,12 @@ import { mockReactDomRender, mockReactDomUnmount } from '../overlay.test.mocks'; import { mount } from 'enzyme'; import { i18nServiceMock } from '../../i18n/i18n_service.mock'; +import { themeServiceMock } from '../../theme/theme_service.mock'; import { FlyoutService, OverlayFlyoutStart } from './flyout_service'; import { OverlayRef } from '../types'; const i18nMock = i18nServiceMock.createStartContract(); +const themeMock = themeServiceMock.createStartContract(); beforeEach(() => { mockReactDomRender.mockClear(); @@ -29,7 +31,11 @@ const mountText = (text: string) => (container: HTMLElement) => { const getServiceStart = () => { const service = new FlyoutService(); - return service.start({ i18n: i18nMock, targetDomElement: document.createElement('div') }); + return service.start({ + i18n: i18nMock, + theme: themeMock, + targetDomElement: document.createElement('div'), + }); }; describe('FlyoutService', () => { diff --git a/src/core/public/overlays/flyout/flyout_service.tsx b/src/core/public/overlays/flyout/flyout_service.tsx index 79047738da4dd..600e1e0e97b25 100644 --- a/src/core/public/overlays/flyout/flyout_service.tsx +++ b/src/core/public/overlays/flyout/flyout_service.tsx @@ -13,9 +13,10 @@ import React from 'react'; import { render, unmountComponentAtNode } from 'react-dom'; import { Subject } from 'rxjs'; import { I18nStart } from '../../i18n'; +import { ThemeServiceStart } from '../../theme'; import { MountPoint } from '../../types'; import { OverlayRef } from '../types'; -import { MountWrapper } from '../../utils'; +import { MountWrapper, CoreContextProvider } from '../../utils'; /** * A FlyoutRef is a reference to an opened flyout panel. It offers methods to @@ -96,6 +97,7 @@ export interface OverlayFlyoutOpenOptions { interface StartDeps { i18n: I18nStart; + theme: ThemeServiceStart; targetDomElement: Element; } @@ -104,7 +106,7 @@ export class FlyoutService { private activeFlyout: FlyoutRef | null = null; private targetDomElement: Element | null = null; - public start({ i18n, targetDomElement }: StartDeps): OverlayFlyoutStart { + public start({ i18n, theme, targetDomElement }: StartDeps): OverlayFlyoutStart { this.targetDomElement = targetDomElement; return { @@ -135,11 +137,11 @@ export class FlyoutService { }; render( - + - , + , this.targetDomElement ); diff --git a/src/core/public/overlays/modal/__snapshots__/modal_service.test.tsx.snap b/src/core/public/overlays/modal/__snapshots__/modal_service.test.tsx.snap index 9c39776fcea5c..31309a0cd3629 100644 --- a/src/core/public/overlays/modal/__snapshots__/modal_service.test.tsx.snap +++ b/src/core/public/overlays/modal/__snapshots__/modal_service.test.tsx.snap @@ -11,7 +11,68 @@ Array [ exports[`ModalService openConfirm() renders a mountpoint confirm message 1`] = ` Array [ Array [ - + + + + + , + }, + Object {}, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": + + + + , + }, + ], + }, + } + } + theme={ + Object { + "theme$": Observable { + "_isScalar": false, + "_subscribe": [Function], + }, + } + } + > - , + ,
    , ], ] @@ -34,7 +95,116 @@ exports[`ModalService openConfirm() renders a mountpoint confirm message 2`] = ` exports[`ModalService openConfirm() renders a string confirm message 1`] = ` Array [ Array [ - + + + + + , + }, + Object {}, + ], + Array [ + Object { + "children": + + + + , + }, + Object {}, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": + + + + , + }, + Object { + "type": "return", + "value": + + + + , + }, + ], + }, + } + } + theme={ + Object { + "theme$": Observable { + "_isScalar": false, + "_subscribe": [Function], + }, + } + } + > Some message - , + ,
    , ], ] @@ -54,7 +224,158 @@ exports[`ModalService openConfirm() renders a string confirm message 2`] = `" + + + + + , + }, + Object {}, + ], + Array [ + Object { + "children": + + + + , + }, + Object {}, + ], + Array [ + Object { + "children": + + Some message + + , + }, + Object {}, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": + + + + , + }, + Object { + "type": "return", + "value": + + + + , + }, + Object { + "type": "return", + "value": + + Some message + + , + }, + ], + }, + } + } + theme={ + Object { + "theme$": Observable { + "_isScalar": false, + "_subscribe": [Function], + }, + } + } + > confirm 1 - , + ,
    , ], Array [ - + + + + + , + }, + Object {}, + ], + Array [ + Object { + "children": + + + + , + }, + Object {}, + ], + Array [ + Object { + "children": + + Some message + + , + }, + Object {}, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": + + + + , + }, + Object { + "type": "return", + "value": + + + + , + }, + Object { + "type": "return", + "value": + + Some message + + , + }, + ], + }, + } + } + theme={ + Object { + "theme$": Observable { + "_isScalar": false, + "_subscribe": [Function], + }, + } + } + > some confirm - , + ,
    , ], ] @@ -85,7 +557,158 @@ Array [ exports[`ModalService openConfirm() with a currently active modal replaces the current modal with the new confirm 1`] = ` Array [ Array [ - + + + + + , + }, + Object {}, + ], + Array [ + Object { + "children": + + + + , + }, + Object {}, + ], + Array [ + Object { + "children": + + Some message + + , + }, + Object {}, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": + + + + , + }, + Object { + "type": "return", + "value": + + + + , + }, + Object { + "type": "return", + "value": + + Some message + + , + }, + ], + }, + } + } + theme={ + Object { + "theme$": Observable { + "_isScalar": false, + "_subscribe": [Function], + }, + } + } + > @@ -94,11 +717,162 @@ Array [ mount={[Function]} /> - , + ,
    , ], Array [ - + + + + + , + }, + Object {}, + ], + Array [ + Object { + "children": + + + + , + }, + Object {}, + ], + Array [ + Object { + "children": + + Some message + + , + }, + Object {}, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": + + + + , + }, + Object { + "type": "return", + "value": + + + + , + }, + Object { + "type": "return", + "value": + + Some message + + , + }, + ], + }, + } + } + theme={ + Object { + "theme$": Observable { + "_isScalar": false, + "_subscribe": [Function], + }, + } + } + > some confirm - , + ,
    , ], ] @@ -116,7 +890,21 @@ Array [ exports[`ModalService openModal() renders a modal to the DOM 1`] = ` Array [ Array [ - + @@ -125,7 +913,7 @@ Array [ mount={[Function]} /> - , + ,
    , ], ] @@ -136,7 +924,68 @@ exports[`ModalService openModal() renders a modal to the DOM 2`] = `"
    + + + + + , + }, + Object {}, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": + + + + , + }, + ], + }, + } + } + theme={ + Object { + "theme$": Observable { + "_isScalar": false, + "_subscribe": [Function], + }, + } + } + > confirm 1 - , + ,
    , ], Array [ - + + + + + , + }, + Object {}, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": + + + + , + }, + ], + }, + } + } + theme={ + Object { + "theme$": Observable { + "_isScalar": false, + "_subscribe": [Function], + }, + } + } + > some confirm - , + ,
    , ], ] @@ -167,7 +1077,68 @@ Array [ exports[`ModalService openModal() with a currently active modal replaces the current modal with a new one 1`] = ` Array [ Array [ - + + + + + , + }, + Object {}, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": + + + + , + }, + ], + }, + } + } + theme={ + Object { + "theme$": Observable { + "_isScalar": false, + "_subscribe": [Function], + }, + } + } + > @@ -176,11 +1147,72 @@ Array [ mount={[Function]} /> - , + ,
    , ], Array [ - + + + + + , + }, + Object {}, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": + + + + , + }, + ], + }, + } + } + theme={ + Object { + "theme$": Observable { + "_isScalar": false, + "_subscribe": [Function], + }, + } + } + > @@ -189,7 +1221,7 @@ Array [ mount={[Function]} /> - , + ,
    , ], ] diff --git a/src/core/public/overlays/modal/modal_service.test.tsx b/src/core/public/overlays/modal/modal_service.test.tsx index e0a78082570c7..cd3c0d0525657 100644 --- a/src/core/public/overlays/modal/modal_service.test.tsx +++ b/src/core/public/overlays/modal/modal_service.test.tsx @@ -11,11 +11,13 @@ import { mockReactDomRender, mockReactDomUnmount } from '../overlay.test.mocks'; import React from 'react'; import { mount } from 'enzyme'; import { i18nServiceMock } from '../../i18n/i18n_service.mock'; +import { themeServiceMock } from '../../theme/theme_service.mock'; import { ModalService, OverlayModalStart } from './modal_service'; import { mountReactNode } from '../../utils'; import { OverlayRef } from '../types'; const i18nMock = i18nServiceMock.createStartContract(); +const themeMock = themeServiceMock.createStartContract(); beforeEach(() => { mockReactDomRender.mockClear(); @@ -24,7 +26,11 @@ beforeEach(() => { const getServiceStart = () => { const service = new ModalService(); - return service.start({ i18n: i18nMock, targetDomElement: document.createElement('div') }); + return service.start({ + i18n: i18nMock, + theme: themeMock, + targetDomElement: document.createElement('div'), + }); }; describe('ModalService', () => { diff --git a/src/core/public/overlays/modal/modal_service.tsx b/src/core/public/overlays/modal/modal_service.tsx index 7e4aee94c958e..f509146452934 100644 --- a/src/core/public/overlays/modal/modal_service.tsx +++ b/src/core/public/overlays/modal/modal_service.tsx @@ -14,9 +14,10 @@ import React from 'react'; import { render, unmountComponentAtNode } from 'react-dom'; import { Subject } from 'rxjs'; import { I18nStart } from '../../i18n'; +import { ThemeServiceStart } from '../../theme'; import { MountPoint } from '../../types'; import { OverlayRef } from '../types'; -import { MountWrapper } from '../../utils'; +import { MountWrapper, CoreContextProvider } from '../../utils'; /** * A ModalRef is a reference to an opened modal. It offers methods to @@ -84,6 +85,7 @@ export interface OverlayModalStart { * @return {@link OverlayRef} A reference to the opened modal. */ open(mount: MountPoint, options?: OverlayModalOpenOptions): OverlayRef; + /** * Opens a confirmation modal with the given text or mountpoint as a message. * Returns a Promise resolving to `true` if user confirmed or `false` otherwise. @@ -106,6 +108,7 @@ export interface OverlayModalOpenOptions { interface StartDeps { i18n: I18nStart; + theme: ThemeServiceStart; targetDomElement: Element; } @@ -114,7 +117,7 @@ export class ModalService { private activeModal: ModalRef | null = null; private targetDomElement: Element | null = null; - public start({ i18n, targetDomElement }: StartDeps): OverlayModalStart { + public start({ i18n, theme, targetDomElement }: StartDeps): OverlayModalStart { this.targetDomElement = targetDomElement; return { @@ -137,11 +140,11 @@ export class ModalService { this.activeModal = modal; render( - + modal.close()}> - , + , targetDomElement ); @@ -197,9 +200,9 @@ export class ModalService { }; render( - + - , + , targetDomElement ); }); diff --git a/src/core/public/overlays/overlay_service.ts b/src/core/public/overlays/overlay_service.ts index f62b49fa5efa4..8d4a5f5f58b56 100644 --- a/src/core/public/overlays/overlay_service.ts +++ b/src/core/public/overlays/overlay_service.ts @@ -8,12 +8,14 @@ import { I18nStart } from '../i18n'; import { IUiSettingsClient } from '../ui_settings'; +import { ThemeServiceStart } from '../theme'; import { OverlayBannersStart, OverlayBannersService } from './banners'; import { FlyoutService, OverlayFlyoutStart } from './flyout'; import { ModalService, OverlayModalStart } from './modal'; interface StartDeps { i18n: I18nStart; + theme: ThemeServiceStart; targetDomElement: HTMLElement; uiSettings: IUiSettingsClient; } @@ -24,16 +26,16 @@ export class OverlayService { private modalService = new ModalService(); private flyoutService = new FlyoutService(); - public start({ i18n, targetDomElement, uiSettings }: StartDeps): OverlayStart { + public start({ i18n, targetDomElement, uiSettings, theme }: StartDeps): OverlayStart { const flyoutElement = document.createElement('div'); targetDomElement.appendChild(flyoutElement); - const flyouts = this.flyoutService.start({ i18n, targetDomElement: flyoutElement }); + const flyouts = this.flyoutService.start({ i18n, theme, targetDomElement: flyoutElement }); const banners = this.bannersService.start({ i18n, uiSettings }); const modalElement = document.createElement('div'); targetDomElement.appendChild(modalElement); - const modals = this.modalService.start({ i18n, targetDomElement: modalElement }); + const modals = this.modalService.start({ i18n, theme, targetDomElement: modalElement }); return { banners, diff --git a/src/core/public/plugins/plugin_context.ts b/src/core/public/plugins/plugin_context.ts index f87f07d553e0c..345aea4b6cac8 100644 --- a/src/core/public/plugins/plugin_context.ts +++ b/src/core/public/plugins/plugin_context.ts @@ -94,6 +94,7 @@ export function createPluginSetupContext< injectedMetadata: { getInjectedVar: deps.injectedMetadata.getInjectedVar, }, + theme: deps.theme, getStartServices: () => plugin.startDependencies, }; } @@ -140,5 +141,6 @@ export function createPluginStartContext< }, fatalErrors: deps.fatalErrors, deprecations: deps.deprecations, + theme: deps.theme, }; } diff --git a/src/core/public/plugins/plugins_service.test.ts b/src/core/public/plugins/plugins_service.test.ts index 6bed958009419..c4e3b7990ba32 100644 --- a/src/core/public/plugins/plugins_service.test.ts +++ b/src/core/public/plugins/plugins_service.test.ts @@ -35,6 +35,7 @@ import { CoreSetup, CoreStart, PluginInitializerContext } from '..'; import { docLinksServiceMock } from '../doc_links/doc_links_service.mock'; import { savedObjectsServiceMock } from '../saved_objects/saved_objects_service.mock'; import { deprecationsServiceMock } from '../deprecations/deprecations_service.mock'; +import { themeServiceMock } from '../theme/theme_service.mock'; export let mockPluginInitializers: Map; @@ -88,6 +89,7 @@ describe('PluginsService', () => { injectedMetadata: injectedMetadataServiceMock.createStartContract(), notifications: notificationServiceMock.createSetupContract(), uiSettings: uiSettingsServiceMock.createSetupContract(), + theme: themeServiceMock.createSetupContract(), }; mockSetupContext = { ...mockSetupDeps, @@ -108,6 +110,7 @@ describe('PluginsService', () => { savedObjects: savedObjectsServiceMock.createStartContract(), fatalErrors: fatalErrorsServiceMock.createStartContract(), deprecations: deprecationsServiceMock.createStartContract(), + theme: themeServiceMock.createStartContract(), }; mockStartContext = { ...mockStartDeps, diff --git a/src/core/public/public.api.md b/src/core/public/public.api.md index 593a02a16c15a..d1a164a2ab13d 100644 --- a/src/core/public/public.api.md +++ b/src/core/public/public.api.md @@ -41,6 +41,7 @@ import { RecursiveReadonly } from '@kbn/utility-types'; import { Request as Request_2 } from '@hapi/hapi'; import * as Rx from 'rxjs'; import { SchemaTypeError } from '@kbn/config-schema'; +import type { ThemeVersion } from '@kbn/ui-shared-deps-npm'; import type { TransportRequestOptions } from '@elastic/elasticsearch'; import type { TransportRequestParams } from '@elastic/elasticsearch'; import type { TransportResult } from '@elastic/elasticsearch'; @@ -170,6 +171,7 @@ export interface AppMountParameters { // @deprecated onAppLeave: (handler: AppLeaveHandler) => void; setHeaderActionMenu: (menuMount: MountPoint | undefined) => void; + theme$: Observable; } // @public @@ -407,6 +409,8 @@ export interface CoreSetup; @@ -1668,6 +1679,18 @@ export class SimpleSavedObject { // @public export type StartServicesAccessor = () => Promise<[CoreStart, TPluginsStart, TStart]>; +// @public (undocumented) +export interface ThemeServiceSetup { + // (undocumented) + theme$: Observable; +} + +// @public (undocumented) +export interface ThemeServiceStart { + // (undocumented) + theme$: Observable; +} + // Warning: (ae-missing-release-tag) "Toast" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -1764,6 +1787,6 @@ export interface UserProvidedValues { // Warnings were encountered during analysis: // -// src/core/public/core_system.ts:168:21 - (ae-forgotten-export) The symbol "InternalApplicationStart" needs to be exported by the entry point index.d.ts +// src/core/public/core_system.ts:173:21 - (ae-forgotten-export) The symbol "InternalApplicationStart" needs to be exported by the entry point index.d.ts ``` diff --git a/src/core/public/rendering/rendering_service.test.tsx b/src/core/public/rendering/rendering_service.test.tsx index bdca628b295c6..7736b146543b3 100644 --- a/src/core/public/rendering/rendering_service.test.tsx +++ b/src/core/public/rendering/rendering_service.test.tsx @@ -13,12 +13,16 @@ import { RenderingService } from './rendering_service'; import { applicationServiceMock } from '../application/application_service.mock'; import { chromeServiceMock } from '../chrome/chrome_service.mock'; import { overlayServiceMock } from '../overlays/overlay_service.mock'; +import { themeServiceMock } from '../theme/theme_service.mock'; +import { i18nServiceMock } from '../i18n/i18n_service.mock'; import { BehaviorSubject } from 'rxjs'; describe('RenderingService#start', () => { let application: ReturnType; let chrome: ReturnType; let overlays: ReturnType; + let i18n: ReturnType; + let theme: ReturnType; let targetDomElement: HTMLDivElement; let rendering: RenderingService; @@ -32,6 +36,10 @@ describe('RenderingService#start', () => { overlays = overlayServiceMock.createStartContract(); overlays.banners.getComponent.mockReturnValue(
    I'm a banner!
    ); + theme = themeServiceMock.createStartContract(); + + i18n = i18nServiceMock.createStartContract(); + targetDomElement = document.createElement('div'); rendering = new RenderingService(); @@ -42,6 +50,8 @@ describe('RenderingService#start', () => { application, chrome, overlays, + i18n, + theme, targetDomElement, }); }; diff --git a/src/core/public/rendering/rendering_service.tsx b/src/core/public/rendering/rendering_service.tsx index d3f91851370d5..7c84146d1aa86 100644 --- a/src/core/public/rendering/rendering_service.tsx +++ b/src/core/public/rendering/rendering_service.tsx @@ -8,12 +8,14 @@ import React from 'react'; import ReactDOM from 'react-dom'; -import { I18nProvider } from '@kbn/i18n/react'; import { pairwise, startWith } from 'rxjs/operators'; -import { InternalChromeStart } from '../chrome'; -import { InternalApplicationStart } from '../application'; -import { OverlayStart } from '../overlays'; +import type { InternalChromeStart } from '../chrome'; +import type { InternalApplicationStart } from '../application'; +import type { OverlayStart } from '../overlays'; +import type { ThemeServiceStart } from '../theme'; +import type { I18nStart } from '../i18n'; +import { CoreContextProvider } from '../utils'; import { AppWrapper } from './app_containers'; interface StartDeps { @@ -21,6 +23,8 @@ interface StartDeps { chrome: InternalChromeStart; overlays: OverlayStart; targetDomElement: HTMLDivElement; + theme: ThemeServiceStart; + i18n: I18nStart; } /** @@ -32,7 +36,7 @@ interface StartDeps { * @internal */ export class RenderingService { - start({ application, chrome, overlays, targetDomElement }: StartDeps) { + start({ application, chrome, overlays, theme, i18n, targetDomElement }: StartDeps) { const chromeHeader = chrome.getHeaderComponent(); const appComponent = application.getComponent(); const bannerComponent = overlays.banners.getComponent(); @@ -47,7 +51,7 @@ export class RenderingService { }); ReactDOM.render( - + <> {/* Fixed headers */} {chromeHeader} @@ -64,7 +68,7 @@ export class RenderingService { {appComponent} - , + , targetDomElement ); } diff --git a/src/core/public/theme/convert_core_theme.test.ts b/src/core/public/theme/convert_core_theme.test.ts new file mode 100644 index 0000000000000..4e8473c0c45d5 --- /dev/null +++ b/src/core/public/theme/convert_core_theme.test.ts @@ -0,0 +1,19 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { convertCoreTheme } from './convert_core_theme'; + +describe('convertCoreTheme', () => { + it('returns the correct `colorMode` when `darkMode` is enabled', () => { + expect(convertCoreTheme({ darkMode: true }).colorMode).toEqual('DARK'); + }); + + it('returns the correct `colorMode` when `darkMode` is disabled', () => { + expect(convertCoreTheme({ darkMode: false }).colorMode).toEqual('LIGHT'); + }); +}); diff --git a/src/core/public/theme/convert_core_theme.ts b/src/core/public/theme/convert_core_theme.ts new file mode 100644 index 0000000000000..78acef40764b6 --- /dev/null +++ b/src/core/public/theme/convert_core_theme.ts @@ -0,0 +1,24 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { EuiThemeSystem, EuiThemeColorMode } from '@elastic/eui'; +import type { CoreTheme } from './types'; + +/** @internal */ +export interface EuiTheme { + colorMode: EuiThemeColorMode; + euiThemeSystem?: EuiThemeSystem; +} + +/** @internal */ +export const convertCoreTheme = (coreTheme: CoreTheme): EuiTheme => { + const { darkMode } = coreTheme; + return { + colorMode: darkMode ? 'DARK' : 'LIGHT', + }; +}; diff --git a/src/core/public/theme/core_theme_provider.test.tsx b/src/core/public/theme/core_theme_provider.test.tsx new file mode 100644 index 0000000000000..baa354f10f428 --- /dev/null +++ b/src/core/public/theme/core_theme_provider.test.tsx @@ -0,0 +1,85 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React, { FC, useEffect } from 'react'; +import { act } from 'react-dom/test-utils'; +import type { ReactWrapper } from 'enzyme'; +import { of, BehaviorSubject } from 'rxjs'; +import { useEuiTheme } from '@elastic/eui'; +import { mountWithIntl } from '@kbn/test/jest'; +import { CoreThemeProvider } from './core_theme_provider'; +import type { CoreTheme } from './types'; + +describe('CoreThemeProvider', () => { + let euiTheme: ReturnType | undefined; + + beforeEach(() => { + euiTheme = undefined; + }); + + const flushPromises = async () => { + await new Promise(async (resolve, reject) => { + try { + setImmediate(() => resolve()); + } catch (error) { + reject(error); + } + }); + }; + + const InnerComponent: FC = () => { + const theme = useEuiTheme(); + useEffect(() => { + euiTheme = theme; + }, [theme]); + return
    foo
    ; + }; + + const refresh = async (wrapper: ReactWrapper) => { + await act(async () => { + await flushPromises(); + wrapper.update(); + }); + }; + + it('exposes the EUI theme provider', async () => { + const coreTheme: CoreTheme = { darkMode: true }; + + const wrapper = mountWithIntl( + + + + ); + + await refresh(wrapper); + + expect(euiTheme!.colorMode).toEqual('DARK'); + }); + + it('propagates changes of the coreTheme observable', async () => { + const coreTheme$ = new BehaviorSubject({ darkMode: true }); + + const wrapper = mountWithIntl( + + + + ); + + await refresh(wrapper); + + expect(euiTheme!.colorMode).toEqual('DARK'); + + await act(async () => { + coreTheme$.next({ darkMode: false }); + }); + + await refresh(wrapper); + + expect(euiTheme!.colorMode).toEqual('LIGHT'); + }); +}); diff --git a/src/core/public/theme/core_theme_provider.tsx b/src/core/public/theme/core_theme_provider.tsx new file mode 100644 index 0000000000000..9f40cbd5393b8 --- /dev/null +++ b/src/core/public/theme/core_theme_provider.tsx @@ -0,0 +1,36 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React, { FC, useMemo } from 'react'; +import { Observable } from 'rxjs'; +import useObservable from 'react-use/lib/useObservable'; +import { EuiThemeProvider } from '@elastic/eui'; +import { CoreTheme } from './types'; +import { convertCoreTheme } from './convert_core_theme'; + +const defaultTheme: CoreTheme = { + darkMode: false, +}; + +interface CoreThemeProviderProps { + theme$: Observable; +} + +/** + * Wrapper around `EuiThemeProvider` converting (and exposing) core's theme to EUI theme. + * @internal Only meant to be used within core for internal usages of EUI/React + */ +export const CoreThemeProvider: FC = ({ theme$, children }) => { + const coreTheme = useObservable(theme$, defaultTheme); + const euiTheme = useMemo(() => convertCoreTheme(coreTheme), [coreTheme]); + return ( + + {children} + + ); +}; diff --git a/src/core/public/theme/index.ts b/src/core/public/theme/index.ts new file mode 100644 index 0000000000000..1e2d07c8152cc --- /dev/null +++ b/src/core/public/theme/index.ts @@ -0,0 +1,11 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export { ThemeService } from './theme_service'; +export type { CoreTheme, ThemeServiceSetup, ThemeServiceStart } from './types'; +export { CoreThemeProvider } from './core_theme_provider'; diff --git a/src/core/public/theme/theme_service.mock.ts b/src/core/public/theme/theme_service.mock.ts new file mode 100644 index 0000000000000..86abcabf126ba --- /dev/null +++ b/src/core/public/theme/theme_service.mock.ts @@ -0,0 +1,61 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { of } from 'rxjs'; +import type { PublicMethodsOf } from '@kbn/utility-types'; +import type { ThemeServiceSetup, ThemeServiceStart, CoreTheme } from './types'; +import type { ThemeService } from './theme_service'; + +const mockTheme: CoreTheme = { + darkMode: false, +}; + +const createThemeMock = (): CoreTheme => { + return { ...mockTheme }; +}; + +const createTheme$Mock = () => { + return of(createThemeMock()); +}; + +const createThemeSetupMock = () => { + const setupMock: jest.Mocked = { + theme$: createTheme$Mock(), + }; + return setupMock; +}; + +const createThemeStartMock = () => { + const startMock: jest.Mocked = { + theme$: createTheme$Mock(), + }; + return startMock; +}; + +type ThemeServiceContract = PublicMethodsOf; + +const createServiceMock = () => { + const mocked: jest.Mocked = { + setup: jest.fn(), + start: jest.fn(), + stop: jest.fn(), + }; + + mocked.setup.mockReturnValue(createThemeSetupMock()); + mocked.start.mockReturnValue(createThemeStartMock()); + + return mocked; +}; + +export const themeServiceMock = { + create: createServiceMock, + createSetupContract: createThemeSetupMock, + createStartContract: createThemeStartMock, + createTheme: createThemeMock, + createTheme$: createTheme$Mock, +}; diff --git a/src/core/public/theme/theme_service.test.ts b/src/core/public/theme/theme_service.test.ts new file mode 100644 index 0000000000000..d38ef98735a3d --- /dev/null +++ b/src/core/public/theme/theme_service.test.ts @@ -0,0 +1,50 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { take } from 'rxjs/operators'; +import { injectedMetadataServiceMock } from '../injected_metadata/injected_metadata_service.mock'; +import { ThemeService } from './theme_service'; + +describe('ThemeService', () => { + let themeService: ThemeService; + let injectedMetadata: ReturnType; + + beforeEach(() => { + themeService = new ThemeService(); + injectedMetadata = injectedMetadataServiceMock.createSetupContract(); + }); + + describe('#setup', () => { + it('exposes a `theme$` observable with the values provided by the injected metadata', async () => { + injectedMetadata.getTheme.mockReturnValue({ version: 'v8', darkMode: true }); + const { theme$ } = themeService.setup({ injectedMetadata }); + const theme = await theme$.pipe(take(1)).toPromise(); + expect(theme).toEqual({ + darkMode: true, + }); + }); + }); + + describe('#start', () => { + it('throws if called before `#setup`', () => { + expect(() => { + themeService.start(); + }).toThrowErrorMatchingInlineSnapshot(`"setup must be called before start"`); + }); + + it('exposes a `theme$` observable with the values provided by the injected metadata', async () => { + injectedMetadata.getTheme.mockReturnValue({ version: 'v8', darkMode: true }); + themeService.setup({ injectedMetadata }); + const { theme$ } = themeService.start(); + const theme = await theme$.pipe(take(1)).toPromise(); + expect(theme).toEqual({ + darkMode: true, + }); + }); + }); +}); diff --git a/src/core/public/theme/theme_service.ts b/src/core/public/theme/theme_service.ts new file mode 100644 index 0000000000000..fc67ac4a595eb --- /dev/null +++ b/src/core/public/theme/theme_service.ts @@ -0,0 +1,44 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { Subject, Observable, of } from 'rxjs'; +import { shareReplay, takeUntil } from 'rxjs/operators'; +import { InjectedMetadataSetup } from '../injected_metadata'; +import type { CoreTheme, ThemeServiceSetup, ThemeServiceStart } from './types'; + +interface SetupDeps { + injectedMetadata: InjectedMetadataSetup; +} + +export class ThemeService { + private theme$?: Observable; + private stop$ = new Subject(); + + public setup({ injectedMetadata }: SetupDeps): ThemeServiceSetup { + const theme = injectedMetadata.getTheme(); + this.theme$ = of({ darkMode: theme.darkMode }); + + return { + theme$: this.theme$.pipe(takeUntil(this.stop$), shareReplay(1)), + }; + } + + public start(): ThemeServiceStart { + if (!this.theme$) { + throw new Error('setup must be called before start'); + } + + return { + theme$: this.theme$.pipe(takeUntil(this.stop$), shareReplay(1)), + }; + } + + public stop() { + this.stop$.next(); + } +} diff --git a/src/core/public/theme/types.ts b/src/core/public/theme/types.ts new file mode 100644 index 0000000000000..5f8672f3c902c --- /dev/null +++ b/src/core/public/theme/types.ts @@ -0,0 +1,33 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { Observable } from 'rxjs'; + +/** + * Contains all the required information to apply Kibana's theme at the various levels it can be used. + * + * @public + */ +export interface CoreTheme { + /** is dark mode enabled or not */ + readonly darkMode: boolean; +} + +/** + * @public + */ +export interface ThemeServiceSetup { + theme$: Observable; +} + +/** + * @public + */ +export interface ThemeServiceStart { + theme$: Observable; +} diff --git a/src/core/public/utils/core_context_provider.tsx b/src/core/public/utils/core_context_provider.tsx new file mode 100644 index 0000000000000..df070d26747d8 --- /dev/null +++ b/src/core/public/utils/core_context_provider.tsx @@ -0,0 +1,28 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React, { FC } from 'react'; +import { CoreThemeProvider } from '../theme/core_theme_provider'; +import type { ThemeServiceStart } from '../theme'; +import type { I18nStart } from '../i18n'; + +interface CoreContextProviderProps { + theme: ThemeServiceStart; + i18n: I18nStart; +} + +/** + * utility component exposing all the context providers required by core when integrating with react + **/ +export const CoreContextProvider: FC = ({ i18n, theme, children }) => { + return ( + + {children} + + ); +}; diff --git a/src/core/public/utils/index.ts b/src/core/public/utils/index.ts index dfb76b3ff05cc..d28a8dcc37501 100644 --- a/src/core/public/utils/index.ts +++ b/src/core/public/utils/index.ts @@ -8,3 +8,4 @@ export { Sha256 } from './crypto'; export { MountWrapper, mountReactNode } from './mount'; +export { CoreContextProvider } from './core_context_provider'; diff --git a/src/core/server/rendering/__snapshots__/rendering_service.test.ts.snap b/src/core/server/rendering/__snapshots__/rendering_service.test.ts.snap index 5ea65cd8d0c73..4abf24911808c 100644 --- a/src/core/server/rendering/__snapshots__/rendering_service.test.ts.snap +++ b/src/core/server/rendering/__snapshots__/rendering_service.test.ts.snap @@ -45,6 +45,10 @@ Object { }, "publicBaseUrl": "http://myhost.com/mock-server-basepath", "serverBasePath": "/mock-server-basepath", + "theme": Object { + "darkMode": "theme:darkMode", + "version": "v8", + }, "uiPlugins": Array [], "vars": Object {}, "version": Any, @@ -100,6 +104,10 @@ Object { }, "publicBaseUrl": "http://myhost.com/mock-server-basepath", "serverBasePath": "/mock-server-basepath", + "theme": Object { + "darkMode": "theme:darkMode", + "version": "v8", + }, "uiPlugins": Array [], "vars": Object {}, "version": Any, @@ -151,6 +159,10 @@ Object { }, "publicBaseUrl": "http://myhost.com/mock-server-basepath", "serverBasePath": "/mock-server-basepath", + "theme": Object { + "darkMode": "theme:darkMode", + "version": "v8", + }, "uiPlugins": Array [], "vars": Object {}, "version": Any, @@ -202,6 +214,10 @@ Object { }, "publicBaseUrl": "http://myhost.com/mock-server-basepath", "serverBasePath": "/mock-server-basepath", + "theme": Object { + "darkMode": "theme:darkMode", + "version": "v8", + }, "uiPlugins": Array [], "vars": Object {}, "version": Any, @@ -253,6 +269,10 @@ Object { }, "publicBaseUrl": "http://myhost.com/mock-server-basepath", "serverBasePath": "/mock-server-basepath", + "theme": Object { + "darkMode": "theme:darkMode", + "version": "v8", + }, "uiPlugins": Array [], "vars": Object {}, "version": Any, @@ -308,6 +328,10 @@ Object { }, "publicBaseUrl": "http://myhost.com/mock-server-basepath", "serverBasePath": "/mock-server-basepath", + "theme": Object { + "darkMode": "theme:darkMode", + "version": "v8", + }, "uiPlugins": Array [], "vars": Object {}, "version": Any, @@ -359,6 +383,10 @@ Object { }, "publicBaseUrl": "http://myhost.com/mock-server-basepath", "serverBasePath": "/mock-server-basepath", + "theme": Object { + "darkMode": "theme:darkMode", + "version": "v8", + }, "uiPlugins": Array [], "vars": Object {}, "version": Any, @@ -410,6 +438,10 @@ Object { }, "publicBaseUrl": "http://myhost.com/mock-server-basepath", "serverBasePath": "/mock-server-basepath", + "theme": Object { + "darkMode": "theme:darkMode", + "version": "v8", + }, "uiPlugins": Array [], "vars": Object {}, "version": Any, diff --git a/src/core/server/rendering/index.ts b/src/core/server/rendering/index.ts index b89ffd6519ab6..ce38cfab16de0 100644 --- a/src/core/server/rendering/index.ts +++ b/src/core/server/rendering/index.ts @@ -7,4 +7,12 @@ */ export { RenderingService } from './rendering_service'; -export * from './types'; +export type { + InjectedMetadata, + InternalRenderingServicePreboot, + InternalRenderingServiceSetup, + IRenderOptions, + RenderingMetadata, + RenderingPrebootDeps, + RenderingSetupDeps, +} from './types'; diff --git a/src/core/server/rendering/rendering_service.tsx b/src/core/server/rendering/rendering_service.tsx index b1c6971d3c42b..bcce7fb258758 100644 --- a/src/core/server/rendering/rendering_service.tsx +++ b/src/core/server/rendering/rendering_service.tsx @@ -124,6 +124,10 @@ export class RenderingService { i18n: { translationsUrl: `${basePath}/translations/${i18n.getLocale()}.json`, }, + theme: { + darkMode, + version: themeVersion, + }, csp: { warnLegacyBrowsers: http.csp.warnLegacyBrowsers }, externalUrl: http.externalUrl, vars: vars ?? {}, diff --git a/src/core/server/rendering/types.ts b/src/core/server/rendering/types.ts index ca6bab0dff1f8..0cd4fe3547304 100644 --- a/src/core/server/rendering/types.ts +++ b/src/core/server/rendering/types.ts @@ -27,34 +27,41 @@ export interface RenderingMetadata { darkMode: boolean; themeVersion: ThemeVersion; stylesheetPaths: string[]; - injectedMetadata: { - version: string; - buildNumber: number; - branch: string; - basePath: string; - serverBasePath: string; - publicBaseUrl?: string; - env: { - mode: EnvironmentMode; - packageInfo: PackageInfo; - }; - anonymousStatusPage: boolean; - i18n: { - translationsUrl: string; - }; - csp: Pick; - externalUrl: { policy: IExternalUrlPolicy[] }; - vars: Record; - uiPlugins: Array<{ - id: string; - plugin: DiscoveredPlugin; - config?: Record; - }>; - legacyMetadata: { - uiSettings: { - defaults: Record; - user: Record>; - }; + injectedMetadata: InjectedMetadata; +} + +/** @internal */ +export interface InjectedMetadata { + version: string; + buildNumber: number; + branch: string; + basePath: string; + serverBasePath: string; + publicBaseUrl?: string; + env: { + mode: EnvironmentMode; + packageInfo: PackageInfo; + }; + anonymousStatusPage: boolean; + i18n: { + translationsUrl: string; + }; + theme: { + darkMode: boolean; + version: ThemeVersion; + }; + csp: Pick; + externalUrl: { policy: IExternalUrlPolicy[] }; + vars: Record; + uiPlugins: Array<{ + id: string; + plugin: DiscoveredPlugin; + config?: Record; + }>; + legacyMetadata: { + uiSettings: { + defaults: Record; + user: Record>; }; }; } diff --git a/src/plugins/dev_tools/public/application.tsx b/src/plugins/dev_tools/public/application.tsx index 510dabf3b32d4..1eb4a5f4e99e8 100644 --- a/src/plugins/dev_tools/public/application.tsx +++ b/src/plugins/dev_tools/public/application.tsx @@ -7,6 +7,7 @@ */ import React, { useEffect, useRef } from 'react'; +import { Observable } from 'rxjs'; import ReactDOM from 'react-dom'; import { HashRouter as Router, Switch, Route, Redirect } from 'react-router-dom'; import { EuiTab, EuiTabs, EuiToolTip } from '@elastic/eui'; @@ -14,7 +15,7 @@ import { I18nProvider } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; import { euiThemeVars } from '@kbn/ui-shared-deps-src/theme'; -import { ApplicationStart, ChromeStart, ScopedHistory } from 'src/core/public'; +import { ApplicationStart, ChromeStart, ScopedHistory, CoreTheme } from 'src/core/public'; import { DevToolApp } from './dev_tool'; @@ -22,6 +23,7 @@ interface DevToolsWrapperProps { devTools: readonly DevToolApp[]; activeDevTool: DevToolApp; updateRoute: (newRoute: string) => void; + theme$: Observable; } interface MountedDevToolDescriptor { @@ -30,7 +32,7 @@ interface MountedDevToolDescriptor { unmountHandler: () => void; } -function DevToolsWrapper({ devTools, activeDevTool, updateRoute }: DevToolsWrapperProps) { +function DevToolsWrapper({ devTools, activeDevTool, updateRoute, theme$ }: DevToolsWrapperProps) { const mountedTool = useRef(null); useEffect( @@ -84,6 +86,7 @@ function DevToolsWrapper({ devTools, activeDevTool, updateRoute }: DevToolsWrapp setHeaderActionMenu: () => undefined, // TODO: adapt to use Core's ScopedHistory history: {} as any, + theme$, }; const unmountHandler = await activeDevTool.mount(params); @@ -148,6 +151,7 @@ export function renderApp( application: ApplicationStart, chrome: ChromeStart, history: ScopedHistory, + theme$: Observable, devTools: readonly DevToolApp[] ) { if (redirectOnMissingCapabilities(application)) { @@ -175,6 +179,7 @@ export function renderApp( updateRoute={props.history.push} activeDevTool={devTool} devTools={devTools} + theme$={theme$} /> )} /> diff --git a/src/plugins/dev_tools/public/plugin.ts b/src/plugins/dev_tools/public/plugin.ts index 5ccf614533164..e45e73c4b1b40 100644 --- a/src/plugins/dev_tools/public/plugin.ts +++ b/src/plugins/dev_tools/public/plugin.ts @@ -53,14 +53,14 @@ export class DevToolsPlugin implements Plugin { order: 9010, category: DEFAULT_APP_CATEGORIES.management, mount: async (params: AppMountParameters) => { - const { element, history } = params; + const { element, history, theme$ } = params; element.classList.add('devAppWrapper'); const [core] = await getStartServices(); const { application, chrome } = core; const { renderApp } = await import('./application'); - return renderApp(element, application, chrome, history, this.getSortedDevTools()); + return renderApp(element, application, chrome, history, theme$, this.getSortedDevTools()); }, }); diff --git a/src/plugins/kibana_react/public/index.ts b/src/plugins/kibana_react/public/index.ts index 46f8599b996a2..2b39a6aa0e1fb 100644 --- a/src/plugins/kibana_react/public/index.ts +++ b/src/plugins/kibana_react/public/index.ts @@ -27,7 +27,9 @@ export * from './notifications'; export { Markdown, MarkdownSimple } from './markdown'; export { reactToUiComponent, uiToReactComponent } from './adapters'; export { toMountPoint, MountPointPortal } from './util'; +export type { ToMountPointOptions } from './util'; export { RedirectAppLinks } from './app_links'; +export { wrapWithTheme, KibanaThemeProvider } from './theme'; /** dummy plugin, we just want kibanaReact to have its own bundle */ export function plugin() { diff --git a/src/plugins/kibana_react/public/theme/index.ts b/src/plugins/kibana_react/public/theme/index.ts new file mode 100644 index 0000000000000..56e374946034e --- /dev/null +++ b/src/plugins/kibana_react/public/theme/index.ts @@ -0,0 +1,11 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export { wrapWithTheme } from './wrap_with_theme'; +export { KibanaThemeProvider } from './kibana_theme_provider'; +export type { EuiTheme } from './types'; diff --git a/src/plugins/kibana_react/public/theme/kibana_theme_provider.test.tsx b/src/plugins/kibana_react/public/theme/kibana_theme_provider.test.tsx new file mode 100644 index 0000000000000..f2d1484e4bb56 --- /dev/null +++ b/src/plugins/kibana_react/public/theme/kibana_theme_provider.test.tsx @@ -0,0 +1,85 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React, { FC, useEffect } from 'react'; +import { act } from 'react-dom/test-utils'; +import type { ReactWrapper } from 'enzyme'; +import { of, BehaviorSubject } from 'rxjs'; +import { useEuiTheme } from '@elastic/eui'; +import { mountWithIntl } from '@kbn/test/jest'; +import type { CoreTheme } from 'src/core/public'; +import { KibanaThemeProvider } from './kibana_theme_provider'; + +describe('KibanaThemeProvider', () => { + let euiTheme: ReturnType | undefined; + + beforeEach(() => { + euiTheme = undefined; + }); + + const flushPromises = async () => { + await new Promise(async (resolve, reject) => { + try { + setImmediate(() => resolve()); + } catch (error) { + reject(error); + } + }); + }; + + const InnerComponent: FC = () => { + const theme = useEuiTheme(); + useEffect(() => { + euiTheme = theme; + }, [theme]); + return
    foo
    ; + }; + + const refresh = async (wrapper: ReactWrapper) => { + await act(async () => { + await flushPromises(); + wrapper.update(); + }); + }; + + it('exposes the EUI theme provider', async () => { + const coreTheme: CoreTheme = { darkMode: true }; + + const wrapper = mountWithIntl( + + + + ); + + await refresh(wrapper); + + expect(euiTheme!.colorMode).toEqual('DARK'); + }); + + it('propagates changes of the coreTheme observable', async () => { + const coreTheme$ = new BehaviorSubject({ darkMode: true }); + + const wrapper = mountWithIntl( + + + + ); + + await refresh(wrapper); + + expect(euiTheme!.colorMode).toEqual('DARK'); + + await act(async () => { + coreTheme$.next({ darkMode: false }); + }); + + await refresh(wrapper); + + expect(euiTheme!.colorMode).toEqual('LIGHT'); + }); +}); diff --git a/src/plugins/kibana_react/public/theme/kibana_theme_provider.tsx b/src/plugins/kibana_react/public/theme/kibana_theme_provider.tsx new file mode 100644 index 0000000000000..bd5d8c2ea8453 --- /dev/null +++ b/src/plugins/kibana_react/public/theme/kibana_theme_provider.tsx @@ -0,0 +1,28 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React, { FC, useMemo } from 'react'; +import useObservable from 'react-use/lib/useObservable'; +import { Observable } from 'rxjs'; +import { EuiThemeProvider } from '@elastic/eui'; +import type { CoreTheme } from '../../../../core/public'; +import { getColorMode } from './utils'; + +interface KibanaThemeProviderProps { + theme$: Observable; +} + +const defaultTheme: CoreTheme = { + darkMode: false, +}; + +export const KibanaThemeProvider: FC = ({ theme$, children }) => { + const theme = useObservable(theme$, defaultTheme); + const colorMode = useMemo(() => getColorMode(theme), [theme]); + return {children}; +}; diff --git a/src/plugins/kibana_react/public/theme/types.ts b/src/plugins/kibana_react/public/theme/types.ts new file mode 100644 index 0000000000000..4da25b7f4890a --- /dev/null +++ b/src/plugins/kibana_react/public/theme/types.ts @@ -0,0 +1,11 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { useEuiTheme } from '@elastic/eui'; + +export type EuiTheme = ReturnType; diff --git a/src/plugins/kibana_react/public/theme/utils.test.ts b/src/plugins/kibana_react/public/theme/utils.test.ts new file mode 100644 index 0000000000000..57b37f4fb2f62 --- /dev/null +++ b/src/plugins/kibana_react/public/theme/utils.test.ts @@ -0,0 +1,19 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { getColorMode } from './utils'; + +describe('getColorMode', () => { + it('returns the correct `colorMode` when `darkMode` is enabled', () => { + expect(getColorMode({ darkMode: true })).toEqual('DARK'); + }); + + it('returns the correct `colorMode` when `darkMode` is disabled', () => { + expect(getColorMode({ darkMode: false })).toEqual('LIGHT'); + }); +}); diff --git a/src/plugins/kibana_react/public/theme/utils.ts b/src/plugins/kibana_react/public/theme/utils.ts new file mode 100644 index 0000000000000..e85bc78333255 --- /dev/null +++ b/src/plugins/kibana_react/public/theme/utils.ts @@ -0,0 +1,15 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { EuiThemeColorMode } from '@elastic/eui/src/services/theme/types'; +import type { CoreTheme } from '../../../../core/public'; + +export const getColorMode = (theme: CoreTheme): EuiThemeColorMode => { + // COLOR_MODES_STANDARD is not exported from eui + return theme.darkMode ? 'DARK' : 'LIGHT'; +}; diff --git a/src/plugins/kibana_react/public/theme/wrap_with_theme.tsx b/src/plugins/kibana_react/public/theme/wrap_with_theme.tsx new file mode 100644 index 0000000000000..b07b93653c3e5 --- /dev/null +++ b/src/plugins/kibana_react/public/theme/wrap_with_theme.tsx @@ -0,0 +1,19 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React from 'react'; +import { Observable } from 'rxjs'; +import type { CoreTheme } from '../../../../core/public'; +import { KibanaThemeProvider } from './kibana_theme_provider'; + +export const wrapWithTheme = ( + node: React.ReactNode, + theme$: Observable +): React.ReactElement => { + return {node}; +}; diff --git a/src/plugins/kibana_react/public/util/index.ts b/src/plugins/kibana_react/public/util/index.ts index e4d6ffc83f7bf..0deada2d02c78 100644 --- a/src/plugins/kibana_react/public/util/index.ts +++ b/src/plugins/kibana_react/public/util/index.ts @@ -7,5 +7,6 @@ */ export { toMountPoint } from './to_mount_point'; +export type { ToMountPointOptions } from './to_mount_point'; export { MountPointPortal } from './mount_point_portal'; export { useIfMounted } from './utils'; diff --git a/src/plugins/kibana_react/public/util/to_mount_point.test.tsx b/src/plugins/kibana_react/public/util/to_mount_point.test.tsx new file mode 100644 index 0000000000000..7f5bd0789cb12 --- /dev/null +++ b/src/plugins/kibana_react/public/util/to_mount_point.test.tsx @@ -0,0 +1,72 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React, { FC, useEffect } from 'react'; +import { act } from 'react-dom/test-utils'; +import { of, BehaviorSubject } from 'rxjs'; +import { useEuiTheme } from '@elastic/eui'; +import type { CoreTheme } from 'src/core/public'; +import { toMountPoint } from './to_mount_point'; + +describe('toMountPoint', () => { + let euiTheme: ReturnType | undefined; + + beforeEach(() => { + euiTheme = undefined; + }); + + const InnerComponent: FC = () => { + const theme = useEuiTheme(); + useEffect(() => { + euiTheme = theme; + }, [theme]); + return
    foo
    ; + }; + + const flushPromises = async () => { + await new Promise(async (resolve, reject) => { + try { + setTimeout(() => resolve(), 20); + } catch (error) { + reject(error); + } + }); + }; + + it('exposes the euiTheme when `theme$` is provided', async () => { + const theme$ = of({ darkMode: true }); + const mount = toMountPoint(, { theme$ }); + + const targetEl = document.createElement('div'); + mount(targetEl); + + await flushPromises(); + + expect(euiTheme!.colorMode).toEqual('DARK'); + }); + + it('propagates changes of the theme$ observable', async () => { + const theme$ = new BehaviorSubject({ darkMode: true }); + + const mount = toMountPoint(, { theme$ }); + + const targetEl = document.createElement('div'); + mount(targetEl); + + await flushPromises(); + + expect(euiTheme!.colorMode).toEqual('DARK'); + + await act(async () => { + theme$.next({ darkMode: false }); + }); + await flushPromises(); + + expect(euiTheme!.colorMode).toEqual('LIGHT'); + }); +}); diff --git a/src/plugins/kibana_react/public/util/to_mount_point.tsx b/src/plugins/kibana_react/public/util/to_mount_point.tsx index 8ebc73d04feb2..b43894be31c8d 100644 --- a/src/plugins/kibana_react/public/util/to_mount_point.tsx +++ b/src/plugins/kibana_react/public/util/to_mount_point.tsx @@ -8,17 +8,27 @@ import React from 'react'; import ReactDOM from 'react-dom'; +import { Observable } from 'rxjs'; import { I18nProvider } from '@kbn/i18n/react'; -import { MountPoint } from 'kibana/public'; +import type { MountPoint, CoreTheme } from 'kibana/public'; +import { KibanaThemeProvider } from '../theme'; + +export interface ToMountPointOptions { + theme$?: Observable; +} /** * MountPoint converter for react nodes. * * @param node to get a mount point for */ -export const toMountPoint = (node: React.ReactNode): MountPoint => { +export const toMountPoint = ( + node: React.ReactNode, + { theme$ }: ToMountPointOptions = {} +): MountPoint => { + const content = theme$ ? {node} : node; const mount = (element: HTMLElement) => { - ReactDOM.render({node}, element); + ReactDOM.render({content}, element); return () => ReactDOM.unmountComponentAtNode(element); }; // only used for tests and snapshots serialization diff --git a/src/plugins/saved_objects_management/public/management_section/mount_section.tsx b/src/plugins/saved_objects_management/public/management_section/mount_section.tsx index cbebc72b20c5a..948c75cd1ef9b 100644 --- a/src/plugins/saved_objects_management/public/management_section/mount_section.tsx +++ b/src/plugins/saved_objects_management/public/management_section/mount_section.tsx @@ -13,6 +13,7 @@ import { I18nProvider } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; import { EuiLoadingSpinner } from '@elastic/eui'; import { CoreSetup } from 'src/core/public'; +import { wrapWithTheme } from '../../../kibana_react/public'; import { ManagementAppMountParams } from '../../../management/public'; import type { SavedObjectManagementTypeInfo } from '../../common/types'; import { StartDependencies, SavedObjectsManagementPluginStart } from '../plugin'; @@ -36,6 +37,7 @@ export const mountManagementSection = async ({ core, mountParams }: MountParams) await core.getStartServices(); const { capabilities } = coreStart.application; const { element, history, setBreadcrumbs } = mountParams; + const { theme$ } = core.theme; if (!allowedObjectTypes) { allowedObjectTypes = await getAllowedTypes(coreStart.http); @@ -54,39 +56,42 @@ export const mountManagementSection = async ({ core, mountParams }: MountParams) }; ReactDOM.render( - - - - - - }> - - - - - - - }> - - - - - - - , + wrapWithTheme( + + + + + + }> + + + + + + + }> + + + + + + + , + theme$ + ), element ); diff --git a/x-pack/plugins/fleet/storybook/context/index.tsx b/x-pack/plugins/fleet/storybook/context/index.tsx index 76425540c2fbc..ae18f393970f7 100644 --- a/x-pack/plugins/fleet/storybook/context/index.tsx +++ b/x-pack/plugins/fleet/storybook/context/index.tsx @@ -7,6 +7,7 @@ import React, { useEffect, useMemo, useCallback } from 'react'; +import { EMPTY } from 'rxjs'; import type { StoryContext } from '@storybook/react'; import { createBrowserHistory } from 'history'; @@ -69,6 +70,9 @@ export const StorybookContext: React.FC<{ storyContext?: StoryContext }> = ({ notifications: getNotifications(), share: getShare(), uiSettings: getUiSettings(), + theme: { + theme$: EMPTY, + }, }), [isCloudEnabled] ); diff --git a/x-pack/plugins/observability/public/pages/overview/overview.stories.tsx b/x-pack/plugins/observability/public/pages/overview/overview.stories.tsx index 506b919b16416..6549e892cab12 100644 --- a/x-pack/plugins/observability/public/pages/overview/overview.stories.tsx +++ b/x-pack/plugins/observability/public/pages/overview/overview.stories.tsx @@ -41,14 +41,20 @@ const sampleAPMIndices = { transaction: 'apm-*' } as ApmIndicesConfig; const withCore = makeDecorator({ name: 'withCore', parameterName: 'core', - wrapper: (storyFn, context, { options }) => { + wrapper: (storyFn, context, { options: { theme, ...options } }) => { unregisterAll(); const KibanaReactContext = createKibanaReactContext({ application: { getUrlForApp: () => '' }, - chrome: { docTitle: { change: () => {} } }, + chrome: { + docTitle: { + change: () => {}, + }, + }, uiSettings: { get: () => [] }, - usageCollection: { reportUiCounter: () => {} }, + usageCollection: { + reportUiCounter: () => {}, + }, } as unknown as Partial); return ( @@ -66,7 +72,12 @@ const withCore = makeDecorator({ plugins: { data: { query: { - timefilter: { timefilter: { setTime: () => {}, getTime: () => ({}) } }, + timefilter: { + timefilter: { + setTime: () => {}, + getTime: () => ({}), + }, + }, }, }, } as unknown as ObservabilityPublicPluginsStart, diff --git a/x-pack/plugins/security/public/account_management/account_management_app.test.ts b/x-pack/plugins/security/public/account_management/account_management_app.test.ts index 2dfc7fac90a29..d3a4c36ba6b93 100644 --- a/x-pack/plugins/security/public/account_management/account_management_app.test.ts +++ b/x-pack/plugins/security/public/account_management/account_management_app.test.ts @@ -9,7 +9,7 @@ jest.mock('./account_management_page'); import type { AppMount } from 'src/core/public'; import { AppNavLinkStatus } from 'src/core/public'; -import { coreMock, scopedHistoryMock } from 'src/core/public/mocks'; +import { coreMock, scopedHistoryMock, themeServiceMock } from 'src/core/public/mocks'; import { UserAPIClient } from '../management'; import { securityMock } from '../mocks'; @@ -58,6 +58,7 @@ describe('accountManagementApp', () => { onAppLeave: jest.fn(), setHeaderActionMenu: jest.fn(), history: scopedHistoryMock.create(), + theme$: themeServiceMock.createTheme$(), }); expect(coreStartMock.chrome.setBreadcrumbs).toHaveBeenCalledTimes(1); diff --git a/x-pack/plugins/security/public/authentication/access_agreement/access_agreement_app.test.ts b/x-pack/plugins/security/public/authentication/access_agreement/access_agreement_app.test.ts index fc3565adf5caf..f192f298009f7 100644 --- a/x-pack/plugins/security/public/authentication/access_agreement/access_agreement_app.test.ts +++ b/x-pack/plugins/security/public/authentication/access_agreement/access_agreement_app.test.ts @@ -8,7 +8,7 @@ jest.mock('./access_agreement_page'); import type { AppMount } from 'src/core/public'; -import { coreMock, scopedHistoryMock } from 'src/core/public/mocks'; +import { coreMock, scopedHistoryMock, themeServiceMock } from 'src/core/public/mocks'; import { accessAgreementApp } from './access_agreement_app'; @@ -51,6 +51,7 @@ describe('accessAgreementApp', () => { onAppLeave: jest.fn(), setHeaderActionMenu: jest.fn(), history: scopedHistoryMock.create(), + theme$: themeServiceMock.createTheme$(), }); const mockRenderApp = jest.requireMock('./access_agreement_page').renderAccessAgreementPage; diff --git a/x-pack/plugins/security/public/authentication/logged_out/logged_out_app.test.ts b/x-pack/plugins/security/public/authentication/logged_out/logged_out_app.test.ts index 6c6071e9af7ee..a88195c6fe8a6 100644 --- a/x-pack/plugins/security/public/authentication/logged_out/logged_out_app.test.ts +++ b/x-pack/plugins/security/public/authentication/logged_out/logged_out_app.test.ts @@ -8,7 +8,7 @@ jest.mock('./logged_out_page'); import type { AppMount } from 'src/core/public'; -import { coreMock, scopedHistoryMock } from 'src/core/public/mocks'; +import { coreMock, scopedHistoryMock, themeServiceMock } from 'src/core/public/mocks'; import { loggedOutApp } from './logged_out_app'; @@ -49,6 +49,7 @@ describe('loggedOutApp', () => { onAppLeave: jest.fn(), setHeaderActionMenu: jest.fn(), history: scopedHistoryMock.create(), + theme$: themeServiceMock.createTheme$(), }); const mockRenderApp = jest.requireMock('./logged_out_page').renderLoggedOutPage; diff --git a/x-pack/plugins/security/public/authentication/login/login_app.test.ts b/x-pack/plugins/security/public/authentication/login/login_app.test.ts index 2ee759c99f740..5406494067d0e 100644 --- a/x-pack/plugins/security/public/authentication/login/login_app.test.ts +++ b/x-pack/plugins/security/public/authentication/login/login_app.test.ts @@ -8,7 +8,7 @@ jest.mock('./login_page'); import type { AppMount } from 'src/core/public'; -import { coreMock, scopedHistoryMock } from 'src/core/public/mocks'; +import { coreMock, scopedHistoryMock, themeServiceMock } from 'src/core/public/mocks'; import { loginApp } from './login_app'; @@ -54,6 +54,7 @@ describe('loginApp', () => { onAppLeave: jest.fn(), setHeaderActionMenu: jest.fn(), history: scopedHistoryMock.create(), + theme$: themeServiceMock.createTheme$(), }); const mockRenderApp = jest.requireMock('./login_page').renderLoginPage; diff --git a/x-pack/plugins/security/public/authentication/logout/logout_app.test.ts b/x-pack/plugins/security/public/authentication/logout/logout_app.test.ts index 8fcccdf916e93..f60dcfb3e7abe 100644 --- a/x-pack/plugins/security/public/authentication/logout/logout_app.test.ts +++ b/x-pack/plugins/security/public/authentication/logout/logout_app.test.ts @@ -6,7 +6,7 @@ */ import type { AppMount } from 'src/core/public'; -import { coreMock, scopedHistoryMock } from 'src/core/public/mocks'; +import { coreMock, scopedHistoryMock, themeServiceMock } from 'src/core/public/mocks'; import { logoutApp } from './logout_app'; @@ -55,6 +55,7 @@ describe('logoutApp', () => { onAppLeave: jest.fn(), setHeaderActionMenu: jest.fn(), history: scopedHistoryMock.create(), + theme$: themeServiceMock.createTheme$(), }); expect(window.sessionStorage.clear).toHaveBeenCalledTimes(1); diff --git a/x-pack/plugins/security/public/authentication/overwritten_session/overwritten_session_app.test.ts b/x-pack/plugins/security/public/authentication/overwritten_session/overwritten_session_app.test.ts index 37a46a0dcad8a..95497bdc1fb54 100644 --- a/x-pack/plugins/security/public/authentication/overwritten_session/overwritten_session_app.test.ts +++ b/x-pack/plugins/security/public/authentication/overwritten_session/overwritten_session_app.test.ts @@ -8,7 +8,7 @@ jest.mock('./overwritten_session_page'); import type { AppMount } from 'src/core/public'; -import { coreMock, scopedHistoryMock } from 'src/core/public/mocks'; +import { coreMock, scopedHistoryMock, themeServiceMock } from 'src/core/public/mocks'; import { securityMock } from '../../mocks'; import { overwrittenSessionApp } from './overwritten_session_app'; @@ -56,6 +56,7 @@ describe('overwrittenSessionApp', () => { onAppLeave: jest.fn(), setHeaderActionMenu: jest.fn(), history: scopedHistoryMock.create(), + theme$: themeServiceMock.createTheme$(), }); const mockRenderApp = jest.requireMock( From 1b0c062966d6b1050fba13fb9ae0fd8532c5bc48 Mon Sep 17 00:00:00 2001 From: Julia Bardi <90178898+juliaElastic@users.noreply.github.com> Date: Wed, 17 Nov 2021 11:14:37 +0100 Subject: [PATCH 066/148] [Fleet] remove internal params when querying registry (#118693) * removed internal param * fixed tests * fixed tests --- .../plugins/fleet/server/services/epm/archive/validation.ts | 1 - x-pack/plugins/fleet/server/services/epm/packages/get.ts | 6 +----- .../plugins/fleet/server/services/epm/packages/install.ts | 3 +-- x-pack/plugins/fleet/server/services/epm/registry/index.ts | 4 +--- .../apis/epm/__snapshots__/install_by_upload.snap | 1 - .../fleet_api_integration/apis/epm/install_remove_assets.ts | 1 - x-pack/test/fleet_api_integration/apis/epm/update_assets.ts | 1 - 7 files changed, 3 insertions(+), 14 deletions(-) diff --git a/x-pack/plugins/fleet/server/services/epm/archive/validation.ts b/x-pack/plugins/fleet/server/services/epm/archive/validation.ts index a46a26738bdab..8d20d88c7a9aa 100644 --- a/x-pack/plugins/fleet/server/services/epm/archive/validation.ts +++ b/x-pack/plugins/fleet/server/services/epm/archive/validation.ts @@ -61,7 +61,6 @@ const optionalArchivePackageProps: readonly OptionalPackageProp[] = [ 'readme', 'assets', 'data_streams', - 'internal', 'license', 'type', 'categories', diff --git a/x-pack/plugins/fleet/server/services/epm/packages/get.ts b/x-pack/plugins/fleet/server/services/epm/packages/get.ts index b6a1850fed5b8..83bb8125e077e 100644 --- a/x-pack/plugins/fleet/server/services/epm/packages/get.ts +++ b/x-pack/plugins/fleet/server/services/epm/packages/get.ts @@ -54,15 +54,11 @@ export async function getPackages( }); // get the installed packages const packageSavedObjects = await getPackageSavedObjects(savedObjectsClient); - // filter out any internal packages - const savedObjectsVisible = packageSavedObjects.saved_objects.filter( - (o) => !o.attributes.internal - ); const packageList = registryItems .map((item) => createInstallableFrom( item, - savedObjectsVisible.find(({ id }) => id === item.name) + packageSavedObjects.saved_objects.find(({ id }) => id === item.name) ) ) .sort(sortByName); diff --git a/x-pack/plugins/fleet/server/services/epm/packages/install.ts b/x-pack/plugins/fleet/server/services/epm/packages/install.ts index 42f4663dc21e3..5b86c944feb39 100644 --- a/x-pack/plugins/fleet/server/services/epm/packages/install.ts +++ b/x-pack/plugins/fleet/server/services/epm/packages/install.ts @@ -530,7 +530,7 @@ export async function createInstallation(options: { installSource: InstallSource; }) { const { savedObjectsClient, packageInfo, installSource } = options; - const { internal = false, name: pkgName, version: pkgVersion } = packageInfo; + const { name: pkgName, version: pkgVersion } = packageInfo; const removable = !isUnremovablePackage(pkgName); const toSaveESIndexPatterns = generateESIndexPatterns(packageInfo.data_streams); @@ -549,7 +549,6 @@ export async function createInstallation(options: { es_index_patterns: toSaveESIndexPatterns, name: pkgName, version: pkgVersion, - internal, removable, install_version: pkgVersion, install_status: 'installing', diff --git a/x-pack/plugins/fleet/server/services/epm/registry/index.ts b/x-pack/plugins/fleet/server/services/epm/registry/index.ts index 85a52763b7fb7..ff829eca5ec18 100644 --- a/x-pack/plugins/fleet/server/services/epm/registry/index.ts +++ b/x-pack/plugins/fleet/server/services/epm/registry/index.ts @@ -96,9 +96,7 @@ export async function fetchList(params?: SearchParams): Promise { const registryUrl = getRegistryUrl(); - const url = new URL( - `${registryUrl}/search?package=${packageName}&internal=true&experimental=true` - ); + const url = new URL(`${registryUrl}/search?package=${packageName}&experimental=true`); setKibanaVersion(url); diff --git a/x-pack/test/fleet_api_integration/apis/epm/__snapshots__/install_by_upload.snap b/x-pack/test/fleet_api_integration/apis/epm/__snapshots__/install_by_upload.snap index 98dc4c2630743..04d189b5d59b2 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/__snapshots__/install_by_upload.snap +++ b/x-pack/test/fleet_api_integration/apis/epm/__snapshots__/install_by_upload.snap @@ -446,7 +446,6 @@ Object { "type": "search", }, ], - "internal": false, "keep_policies_up_to_date": false, "name": "apache", "package_assets": Array [ diff --git a/x-pack/test/fleet_api_integration/apis/epm/install_remove_assets.ts b/x-pack/test/fleet_api_integration/apis/epm/install_remove_assets.ts index 699b60a14b911..f3f036107fc22 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/install_remove_assets.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/install_remove_assets.ts @@ -668,7 +668,6 @@ const expectAssetsInstalled = ({ ], name: 'all_assets', version: '0.1.0', - internal: false, removable: true, install_version: '0.1.0', install_status: 'installed', diff --git a/x-pack/test/fleet_api_integration/apis/epm/update_assets.ts b/x-pack/test/fleet_api_integration/apis/epm/update_assets.ts index 4ae42ce179219..d55f6aad53aa2 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/update_assets.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/update_assets.ts @@ -457,7 +457,6 @@ export default function (providerContext: FtrProviderContext) { ], name: 'all_assets', version: '0.2.0', - internal: false, removable: true, install_version: '0.2.0', install_status: 'installed', From dfbe896f4bb6547e696ae8ca1cb4e3b90931318a Mon Sep 17 00:00:00 2001 From: Dmitry Tomashevich <39378793+Dmitriynj@users.noreply.github.com> Date: Wed, 17 Nov 2021 14:25:35 +0300 Subject: [PATCH 067/148] [Discover] Fix saved search embeddable pagination (#117507) * [Discover] fix saved search embeddable pagination * [Discover] fix linting error Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../components/pager/tool_bar_pagination.tsx | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/plugins/discover/public/components/doc_table/components/pager/tool_bar_pagination.tsx b/src/plugins/discover/public/components/doc_table/components/pager/tool_bar_pagination.tsx index ccdb620e0ab85..ae5d2fa32ea65 100644 --- a/src/plugins/discover/public/components/doc_table/components/pager/tool_bar_pagination.tsx +++ b/src/plugins/discover/public/components/doc_table/components/pager/tool_bar_pagination.tsx @@ -18,6 +18,7 @@ import { } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; +import { euiLightVars } from '@kbn/ui-shared-deps-src/theme'; interface ToolBarPaginationProps { pageSize: number; @@ -27,6 +28,11 @@ interface ToolBarPaginationProps { onPageSizeChange: (size: number) => void; } +const TOOL_BAR_PAGINATION_STYLES = { + marginLeft: 'auto', + marginRight: euiLightVars.euiSizeL, +}; + export const ToolBarPagination = ({ pageSize, pageCount, @@ -61,12 +67,7 @@ export const ToolBarPagination = ({ )); return ( - + - + Date: Wed, 17 Nov 2021 07:02:24 -0500 Subject: [PATCH 068/148] [Security Solution] Enhancement endpoint flyout UI fixes (#117987) * initial UI changes for font size and deprecated dependency * remove euitext wrapper * Remove unused dependency * Remove import * Add text break word * inline policy, version and icon * Allign icon in the out_of_date component * Remove unncessary wrapper * Replace style attributes with className Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../view/components/out_of_date.tsx | 10 +- .../components/endpoint_details_tabs.tsx | 3 +- .../view/details/components/flyout_header.tsx | 2 +- .../view/details/endpoint_details_content.tsx | 193 ++++++++++-------- 4 files changed, 122 insertions(+), 86 deletions(-) diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/components/out_of_date.tsx b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/components/out_of_date.tsx index 0546c57b38268..d65cfc0cd397b 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/components/out_of_date.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/components/out_of_date.tsx @@ -11,8 +11,14 @@ import { FormattedMessage } from '@kbn/i18n/react'; export const OutOfDate = React.memo<{ style?: React.CSSProperties }>(({ style, ...otherProps }) => { return ( - - + + ); diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/components/endpoint_details_tabs.tsx b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/components/endpoint_details_tabs.tsx index adae21b55a637..4c0e1b799a6be 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/components/endpoint_details_tabs.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/components/endpoint_details_tabs.tsx @@ -6,7 +6,7 @@ */ import React, { memo, useMemo } from 'react'; -import { EuiTab, EuiTabs, EuiFlyoutBody, EuiSpacer } from '@elastic/eui'; +import { EuiTab, EuiTabs, EuiFlyoutBody } from '@elastic/eui'; import { EndpointIndexUIQueryParams } from '../../../types'; import { EndpointDetailsFlyoutHeader } from './flyout_header'; @@ -68,7 +68,6 @@ export const EndpointDetailsFlyoutTabs = memo( return ( <> - {renderTabs} diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/components/flyout_header.tsx b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/components/flyout_header.tsx index f791c0d6adf17..3c8cdf6bf3183 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/components/flyout_header.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/components/flyout_header.tsx @@ -28,7 +28,7 @@ export const EndpointDetailsFlyoutHeader = memo( ) : ( - +

    { + return ( + +
    {children}
    +
    + ); +}; + export const EndpointDetailsContent = memo( ({ details, @@ -70,83 +77,96 @@ export const EndpointDetailsContent = memo( const detailsResults = useMemo(() => { return [ { - title: i18n.translate('xpack.securitySolution.endpoint.details.os', { - defaultMessage: 'OS', - }), - description: {details.host.os.full}, + title: ( + + + + ), + description: {details.host.os.full}, }, { - title: i18n.translate('xpack.securitySolution.endpoint.details.agentStatus', { - defaultMessage: 'Agent Status', - }), + title: ( + + + + ), description: , }, { - title: i18n.translate('xpack.securitySolution.endpoint.details.lastSeen', { - defaultMessage: 'Last Seen', - }), + title: ( + + + + ), description: ( - - {' '} - + + ), }, { - title: i18n.translate('xpack.securitySolution.endpoint.details.policy', { - defaultMessage: 'Policy', - }), + title: ( + + + + ), description: ( - - - - - {details.Endpoint.policy.applied.name} - + + + {details.Endpoint.policy.applied.name} + + {details.Endpoint.policy.applied.endpoint_policy_version && ( + + - - - {details.Endpoint.policy.applied.endpoint_policy_version && ( - - - - - - )} - {isPolicyOutOfDate(details.Endpoint.policy.applied, policyInfo) && ( - - - - )} - - + )} + {isPolicyOutOfDate(details.Endpoint.policy.applied, policyInfo) && } + ), }, { - title: i18n.translate('xpack.securitySolution.endpoint.details.policyStatus', { - defaultMessage: 'Policy Status', - }), + title: ( + + + + ), description: ( - + {details.agent.version}, + title: ( + + + + ), + description: {details.agent.version}, }, { - title: i18n.translate('xpack.securitySolution.endpoint.details.ipAddress', { - defaultMessage: 'IP Address', - }), + title: ( + + + + ), description: ( - - - {details.host.ip.map((ip: string, index: number) => ( - - ))} - - + + {details.host.ip.map((ip: string, index: number) => ( + + {ip} + + ))} + ), }, ]; }, [details, hostStatus, policyStatus, policyStatusClickHandler, policyInfo]); return ( - <> - + + - + ); } ); From 31e9ce7e1ff75492393345c8f60d827e86ac4712 Mon Sep 17 00:00:00 2001 From: Aleh Zasypkin Date: Wed, 17 Nov 2021 13:26:12 +0100 Subject: [PATCH 069/148] Adjust user management functional tests to work in Cloud. (#118315) --- x-pack/test/functional/apps/security/users.ts | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/x-pack/test/functional/apps/security/users.ts b/x-pack/test/functional/apps/security/users.ts index 444cf42752607..b2bef848b18e2 100644 --- a/x-pack/test/functional/apps/security/users.ts +++ b/x-pack/test/functional/apps/security/users.ts @@ -19,6 +19,10 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const toasts = getService('toasts'); const browser = getService('browser'); + function isCloudEnvironment() { + return config.get('servers.elasticsearch.hostname') !== 'localhost'; + } + describe('users', function () { const optionalUser: UserFormValues = { username: 'OptionalUser', @@ -37,7 +41,11 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const users = keyBy(await PageObjects.security.getElasticsearchUsers(), 'username'); log.info('actualUsers = %j', users); log.info('config = %j', config.get('servers.elasticsearch.hostname')); - if (config.get('servers.elasticsearch.hostname') === 'localhost') { + + // In Cloud default users are defined in file realm, such users aren't exposed through the Users API. + if (isCloudEnvironment()) { + expect(Object.keys(users)).to.eql(['test_user']); + } else { expect(users.elastic.roles).to.eql(['superuser']); expect(users.elastic.reserved).to.be(true); expect(users.elastic.deprecated).to.be(false); @@ -49,9 +57,6 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { expect(users.kibana.roles).to.eql(['kibana_system']); expect(users.kibana.reserved).to.be(true); expect(users.kibana.deprecated).to.be(true); - } else { - expect(users.anonymous.roles).to.eql(['anonymous']); - expect(users.anonymous.reserved).to.be(true); } }); From 0c4b58dfda77fe0108a71373c0c4c458f5a60693 Mon Sep 17 00:00:00 2001 From: Gloria Hornero Date: Wed, 17 Nov 2021 13:36:58 +0100 Subject: [PATCH 070/148] adds improvements and fixes to the import timeline test for the upgrade path (#118849) --- .../cypress/screens/timeline.ts | 9 ++- .../import_timeline.spec.ts | 69 ++++++++++--------- 2 files changed, 44 insertions(+), 34 deletions(-) diff --git a/x-pack/plugins/security_solution/cypress/screens/timeline.ts b/x-pack/plugins/security_solution/cypress/screens/timeline.ts index a37cd5e22ca07..845662fe051b5 100644 --- a/x-pack/plugins/security_solution/cypress/screens/timeline.ts +++ b/x-pack/plugins/security_solution/cypress/screens/timeline.ts @@ -24,7 +24,8 @@ export const SELECT_CASE = (id: string) => { return `[data-test-subj="cases-table-row-select-${id}"]`; }; -export const CELL = '[data-test-subj="statefulCell"]'; +export const CORRELATION_EVENT_TABLE_CELL = + '[data-test-subj="eql-events-table"] [data-test-subj="statefulCell"]'; export const CLOSE_TIMELINE_BTN = '[data-test-subj="close-timeline"]'; @@ -104,6 +105,9 @@ export const OPEN_TIMELINE_TEMPLATE_ICON = export const PIN_EVENT = '[data-test-subj="pin"]'; +export const PINNED_EVENT_TABLE_CELL = + '[data-test-subj="pinned-events-table"] [data-test-subj="statefulCell"]'; + export const PINNED_TAB_BUTTON = '[data-test-subj="timelineTabs-pinned"]'; export const PROCESS_KPI = '[data-test-subj="siem-timeline-process-kpi"'; @@ -120,6 +124,9 @@ export const SEARCH_OR_FILTER_CONTAINER = export const INDICATOR_MATCH_ROW_RENDER = '[data-test-subj="threat-match-row"]'; +export const QUERY_EVENT_TABLE_CELL = + '[data-test-subj="query-events-table"] [data-test-subj="statefulCell"]'; + export const QUERY_TAB_BUTTON = '[data-test-subj="timelineTabs-query"]'; export const SERVER_SIDE_EVENT_COUNT = '[data-test-subj="server-side-event-count"]'; diff --git a/x-pack/plugins/security_solution/cypress/upgrade_integration/import_timeline.spec.ts b/x-pack/plugins/security_solution/cypress/upgrade_integration/import_timeline.spec.ts index 464c42d9fc220..f3b3f14e9c260 100644 --- a/x-pack/plugins/security_solution/cypress/upgrade_integration/import_timeline.spec.ts +++ b/x-pack/plugins/security_solution/cypress/upgrade_integration/import_timeline.spec.ts @@ -6,7 +6,7 @@ */ import { - CELL, + CORRELATION_EVENT_TABLE_CELL, DATA_PROVIDERS, DATE_PICKER_END, DATE_PICKER_START, @@ -17,8 +17,10 @@ import { NOTE_DESCRIPTION, NOTE_PREVIEW, NOTES_TAB_BUTTON, + PINNED_EVENT_TABLE_CELL, PINNED_TAB_BUTTON, PROCESS_KPI, + QUERY_EVENT_TABLE_CELL, SOURCE_IP_KPI, TIMELINE_CORRELATION_TAB, TIMELINE_CORRELATION_INPUT, @@ -62,7 +64,7 @@ const timelineDetails = { }; const detectionAlert = { - timestamp: 'Oct 7, 2021 @ 11:14:10.888', + timestamp: 'Nov 17, 2021 @ 09:36:25.499', message: '—', eventCategory: 'file', eventAction: 'initial_scan', @@ -73,7 +75,7 @@ const detectionAlert = { }; const event = { - timestamp: 'Oct 6, 2021 @ 17:09:29.438', + timestamp: 'Nov 4, 2021 @ 11:09:29.438', message: '—', eventCategory: 'file', eventAction: 'initial_scan', @@ -98,7 +100,7 @@ describe('Import timeline after upgrade', () => { cy.readFile(`cypress/fixtures/${timeline}`).then((file) => { const timelineJson = JSON.parse(file); const regex = new RegExp( - `\\S${timelineJson.globalNotes[0].createdBy}added a note\\d* \\w* ago${timelineJson.globalNotes[0].createdBy} added a note${timelineJson.globalNotes[0].note}` + `\\S${timelineJson.globalNotes[0].createdBy}added a note\\S*\\s?(\\S*)?\\s?(\\S*)?${timelineJson.globalNotes[0].createdBy} added a note${timelineJson.globalNotes[0].note}` ); cy.get(TIMELINE_NAME).should('have.text', timelineJson.title); @@ -147,30 +149,31 @@ describe('Import timeline after upgrade', () => { cy.get(NOTES_TAB_BUTTON).should('have.text', timelineDetails.notesTab); cy.get(PINNED_TAB_BUTTON).should('have.text', timelineDetails.pinnedTab); - cy.get(CELL).eq(0).should('contain', detectionAlert.timestamp); - cy.get(CELL).eq(1).should('contain', detectionAlert.message); - cy.get(CELL).eq(2).should('contain', detectionAlert.eventCategory); - cy.get(CELL).eq(3).should('contain', detectionAlert.eventAction); - cy.get(CELL).eq(4).should('contain', detectionAlert.hostName); - cy.get(CELL).eq(5).should('contain', detectionAlert.sourceIp); - cy.get(CELL).eq(6).should('contain', detectionAlert.destinationIp); - cy.get(CELL).eq(7).should('contain', detectionAlert.userName); - - cy.get(CELL).eq(8).should('contain', event.timestamp); - cy.get(CELL).eq(9).should('contain', event.message); - cy.get(CELL).eq(10).should('contain', event.eventCategory); - cy.get(CELL).eq(11).should('contain', event.eventAction); - cy.get(CELL).eq(12).should('contain', event.hostName); - cy.get(CELL).eq(13).should('contain', event.sourceIp); - cy.get(CELL).eq(14).should('contain', event.destinationIp); - cy.get(CELL).eq(15).should('contain', event.userName); + cy.get(QUERY_EVENT_TABLE_CELL).eq(0).should('contain', detectionAlert.timestamp); + cy.get(QUERY_EVENT_TABLE_CELL).eq(1).should('contain', detectionAlert.message); + cy.get(QUERY_EVENT_TABLE_CELL).eq(2).should('contain', detectionAlert.eventCategory); + cy.get(QUERY_EVENT_TABLE_CELL).eq(3).should('contain', detectionAlert.eventAction); + cy.get(QUERY_EVENT_TABLE_CELL).eq(4).should('contain', detectionAlert.hostName); + cy.get(QUERY_EVENT_TABLE_CELL).eq(5).should('contain', detectionAlert.sourceIp); + cy.get(QUERY_EVENT_TABLE_CELL).eq(6).should('contain', detectionAlert.destinationIp); + cy.get(QUERY_EVENT_TABLE_CELL).eq(7).should('contain', detectionAlert.userName); + + cy.get(QUERY_EVENT_TABLE_CELL).eq(8).should('contain', event.timestamp); + cy.get(QUERY_EVENT_TABLE_CELL).eq(9).should('contain', event.message); + cy.get(QUERY_EVENT_TABLE_CELL).eq(10).should('contain', event.eventCategory); + cy.get(QUERY_EVENT_TABLE_CELL).eq(11).should('contain', event.eventAction); + cy.get(QUERY_EVENT_TABLE_CELL).eq(12).should('contain', event.hostName); + cy.get(QUERY_EVENT_TABLE_CELL).eq(13).should('contain', event.sourceIp); + cy.get(QUERY_EVENT_TABLE_CELL).eq(14).should('contain', event.destinationIp); + cy.get(QUERY_EVENT_TABLE_CELL).eq(15).should('contain', event.userName); }); }); - it('Displays the correct timeline details inside the query tab', () => { + it('Displays the correct timeline details inside the correlation tab', () => { goToCorrelationTab(); cy.get(TIMELINE_CORRELATION_INPUT).should('be.empty'); + cy.get(CORRELATION_EVENT_TABLE_CELL).should('not.exist'); }); it('Displays the correct timeline details inside the notes tab', () => { @@ -179,27 +182,27 @@ describe('Import timeline after upgrade', () => { cy.readFile(`cypress/fixtures/${timeline}`).then((file) => { const timelineJson = JSON.parse(file); const descriptionRegex = new RegExp( - `\\S${username}added description\\d* \\w* ago${timelineJson.description}` + `\\S${username}added description\\S*\\s?(\\S*)?\\s?(\\S*)?${timelineJson.description}` ); const noteRegex = new RegExp( - `\\S${timelineJson.globalNotes[0].createdBy}added a note\\d* \\w* ago${timelineJson.globalNotes[0].createdBy} added a note${timelineJson.globalNotes[0].note}` + `\\S${timelineJson.globalNotes[0].createdBy}added a note\\S*\\s?(\\S*)?\\s?(\\S*)?${timelineJson.globalNotes[0].createdBy} added a note${timelineJson.globalNotes[0].note}` ); cy.get(NOTE_DESCRIPTION).invoke('text').should('match', descriptionRegex); - cy.get(NOTE_PREVIEW).invoke('text').should('match', noteRegex); + cy.get(NOTE_PREVIEW).last().invoke('text').should('match', noteRegex); }); }); it('Displays the correct timeline details inside the pinned tab', () => { goToPinnedTab(); - cy.get(CELL).eq(0).should('contain', detectionAlert.timestamp); - cy.get(CELL).eq(1).should('contain', detectionAlert.message); - cy.get(CELL).eq(2).should('contain', detectionAlert.eventCategory); - cy.get(CELL).eq(3).should('contain', detectionAlert.eventAction); - cy.get(CELL).eq(4).should('contain', detectionAlert.hostName); - cy.get(CELL).eq(5).should('contain', detectionAlert.sourceIp); - cy.get(CELL).eq(6).should('contain', detectionAlert.destinationIp); - cy.get(CELL).eq(7).should('contain', detectionAlert.userName); + cy.get(PINNED_EVENT_TABLE_CELL).eq(0).should('contain', detectionAlert.timestamp); + cy.get(PINNED_EVENT_TABLE_CELL).eq(1).should('contain', detectionAlert.message); + cy.get(PINNED_EVENT_TABLE_CELL).eq(2).should('contain', detectionAlert.eventCategory); + cy.get(PINNED_EVENT_TABLE_CELL).eq(3).should('contain', detectionAlert.eventAction); + cy.get(PINNED_EVENT_TABLE_CELL).eq(4).should('contain', detectionAlert.hostName); + cy.get(PINNED_EVENT_TABLE_CELL).eq(5).should('contain', detectionAlert.sourceIp); + cy.get(PINNED_EVENT_TABLE_CELL).eq(6).should('contain', detectionAlert.destinationIp); + cy.get(PINNED_EVENT_TABLE_CELL).eq(7).should('contain', detectionAlert.userName); }); }); From 2d9bbe56fee2c0e3623e4ad1a4a6f14a32783ba7 Mon Sep 17 00:00:00 2001 From: Tiago Costa Date: Wed, 17 Nov 2021 12:52:27 +0000 Subject: [PATCH 071/148] skip flaky suite (#116065) --- .../functional/apps/monitoring/elasticsearch/nodes_mb.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/x-pack/test/functional/apps/monitoring/elasticsearch/nodes_mb.js b/x-pack/test/functional/apps/monitoring/elasticsearch/nodes_mb.js index ed94a91327170..320b392740586 100644 --- a/x-pack/test/functional/apps/monitoring/elasticsearch/nodes_mb.js +++ b/x-pack/test/functional/apps/monitoring/elasticsearch/nodes_mb.js @@ -17,7 +17,8 @@ export default function ({ getService, getPageObjects }) { // FF issue: https://github.com/elastic/kibana/issues/35551 this.tags(['skipFirefox']); - describe('with offline node', () => { + // FLAKY: https://github.com/elastic/kibana/issues/116065 + describe.skip('with offline node', () => { const { setup, tearDown } = getLifecycleMethods(getService, getPageObjects); before(async () => { @@ -53,8 +54,7 @@ export default function ({ getService, getPageObjects }) { }); }); - // FLAKY: https://github.com/elastic/kibana/issues/116065 - describe.skip('skipCloud', function () { + describe('skipCloud', function () { // TODO: https://github.com/elastic/stack-monitoring/issues/31 this.tags(['skipCloud']); From 053b157a3d00ed8a0816b063c949556800fcca47 Mon Sep 17 00:00:00 2001 From: Rudolf Meijering Date: Wed, 17 Nov 2021 13:52:57 +0100 Subject: [PATCH 072/148] Unskip clone tests (#118440) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../actions/integration_tests/actions.test.ts | 207 ++++++++++-------- 1 file changed, 117 insertions(+), 90 deletions(-) diff --git a/src/core/server/saved_objects/migrations/actions/integration_tests/actions.test.ts b/src/core/server/saved_objects/migrations/actions/integration_tests/actions.test.ts index 1b6a668fe57fd..a32ff72375e8a 100644 --- a/src/core/server/saved_objects/migrations/actions/integration_tests/actions.test.ts +++ b/src/core/server/saved_objects/migrations/actions/integration_tests/actions.test.ts @@ -292,8 +292,7 @@ describe('migration actions', () => { }); }); - // FAILED ES PROMOTION: https://github.com/elastic/kibana/issues/117856 - describe.skip('cloneIndex', () => { + describe('cloneIndex', () => { afterAll(async () => { try { await client.indices.delete({ index: 'clone_*' }); @@ -375,14 +374,14 @@ describe('migration actions', () => { expect.assertions(1); const task = cloneIndex({ client, source: 'no_such_index', target: 'clone_target_3' }); await expect(task()).resolves.toMatchInlineSnapshot(` - Object { - "_tag": "Left", - "left": Object { - "index": "no_such_index", - "type": "index_not_found_exception", - }, - } - `); + Object { + "_tag": "Left", + "left": Object { + "index": "no_such_index", + "type": "index_not_found_exception", + }, + } + `); }); it('resolves left with a retryable_es_client_error if clone target already exists but takes longer than the specified timeout before turning yellow', async () => { // Create a red index @@ -407,7 +406,7 @@ describe('migration actions', () => { client, source: 'existing_index_with_write_block', target: 'clone_red_index', - timeout: '0s', + timeout: '1s', })(); await expect(cloneIndexPromise).resolves.toMatchInlineSnapshot(` @@ -419,6 +418,34 @@ describe('migration actions', () => { }, } `); + + // Now that we know timeouts work, make the index yellow again and call cloneIndex a second time to verify that it completes + + await client.indices.putSettings({ + index: 'clone_red_index', + body: { + // Enable all shard allocation so that the index status goes yellow + routing: { allocation: { enable: 'all' } }, + }, + }); + + // Call clone even though the index already exists with yellow state + const cloneIndexPromise2 = cloneIndex({ + client, + source: 'existing_index_with_write_block', + target: 'clone_red_index', + timeout: '30s', + })(); + + await expect(cloneIndexPromise2).resolves.toMatchInlineSnapshot(` + Object { + "_tag": "Right", + "right": Object { + "acknowledged": true, + "shardsAcknowledged": true, + }, + } + `); }); }); @@ -436,11 +463,11 @@ describe('migration actions', () => { })()) as Either.Right; const task = waitForReindexTask({ client, taskId: res.right.taskId, timeout: '10s' }); await expect(task()).resolves.toMatchInlineSnapshot(` - Object { - "_tag": "Right", - "right": "reindex_succeeded", - } - `); + Object { + "_tag": "Right", + "right": "reindex_succeeded", + } + `); const results = ( (await searchForOutdatedDocuments(client, { @@ -476,11 +503,11 @@ describe('migration actions', () => { })()) as Either.Right; const task = waitForReindexTask({ client, taskId: res.right.taskId, timeout: '10s' }); await expect(task()).resolves.toMatchInlineSnapshot(` - Object { - "_tag": "Right", - "right": "reindex_succeeded", - } - `); + Object { + "_tag": "Right", + "right": "reindex_succeeded", + } + `); const results = ( (await searchForOutdatedDocuments(client, { @@ -509,11 +536,11 @@ describe('migration actions', () => { })()) as Either.Right; const task = waitForReindexTask({ client, taskId: res.right.taskId, timeout: '10s' }); await expect(task()).resolves.toMatchInlineSnapshot(` - Object { - "_tag": "Right", - "right": "reindex_succeeded", - } - `); + Object { + "_tag": "Right", + "right": "reindex_succeeded", + } + `); const results = ( (await searchForOutdatedDocuments(client, { batchSize: 1000, @@ -544,11 +571,11 @@ describe('migration actions', () => { })()) as Either.Right; let task = waitForReindexTask({ client, taskId: res.right.taskId, timeout: '10s' }); await expect(task()).resolves.toMatchInlineSnapshot(` - Object { - "_tag": "Right", - "right": "reindex_succeeded", - } - `); + Object { + "_tag": "Right", + "right": "reindex_succeeded", + } + `); // reindex without a script res = (await reindex({ @@ -561,11 +588,11 @@ describe('migration actions', () => { })()) as Either.Right; task = waitForReindexTask({ client, taskId: res.right.taskId, timeout: '10s' }); await expect(task()).resolves.toMatchInlineSnapshot(` - Object { - "_tag": "Right", - "right": "reindex_succeeded", - } - `); + Object { + "_tag": "Right", + "right": "reindex_succeeded", + } + `); // Assert that documents weren't overridden by the second, unscripted reindex const results = ( @@ -620,11 +647,11 @@ describe('migration actions', () => { })()) as Either.Right; const task = waitForReindexTask({ client, taskId: res.right.taskId, timeout: '10s' }); await expect(task()).resolves.toMatchInlineSnapshot(` - Object { - "_tag": "Right", - "right": "reindex_succeeded", - } - `); + Object { + "_tag": "Right", + "right": "reindex_succeeded", + } + `); // Assert that existing documents weren't overridden, but that missing // documents were added by the reindex const results = ( @@ -677,13 +704,13 @@ describe('migration actions', () => { const task = waitForReindexTask({ client, taskId: reindexTaskId, timeout: '10s' }); await expect(task()).resolves.toMatchInlineSnapshot(` - Object { - "_tag": "Left", - "left": Object { - "type": "incompatible_mapping_exception", - }, - } - `); + Object { + "_tag": "Left", + "left": Object { + "type": "incompatible_mapping_exception", + }, + } + `); }); it('resolves left incompatible_mapping_exception if all reindex failures are due to a mapper_parsing_exception', async () => { expect.assertions(1); @@ -716,13 +743,13 @@ describe('migration actions', () => { const task = waitForReindexTask({ client, taskId: reindexTaskId, timeout: '10s' }); await expect(task()).resolves.toMatchInlineSnapshot(` - Object { - "_tag": "Left", - "left": Object { - "type": "incompatible_mapping_exception", - }, - } - `); + Object { + "_tag": "Left", + "left": Object { + "type": "incompatible_mapping_exception", + }, + } + `); }); it('resolves left index_not_found_exception if source index does not exist', async () => { expect.assertions(1); @@ -738,14 +765,14 @@ describe('migration actions', () => { })()) as Either.Right; const task = waitForReindexTask({ client, taskId: res.right.taskId, timeout: '10s' }); await expect(task()).resolves.toMatchInlineSnapshot(` - Object { - "_tag": "Left", - "left": Object { - "index": "no_such_index", - "type": "index_not_found_exception", - }, - } - `); + Object { + "_tag": "Left", + "left": Object { + "index": "no_such_index", + "type": "index_not_found_exception", + }, + } + `); }); it('resolves left target_index_had_write_block if all failures are due to a write block', async () => { expect.assertions(1); @@ -761,13 +788,13 @@ describe('migration actions', () => { const task = waitForReindexTask({ client, taskId: res.right.taskId, timeout: '10s' }); await expect(task()).resolves.toMatchInlineSnapshot(` - Object { - "_tag": "Left", - "left": Object { - "type": "target_index_had_write_block", - }, - } - `); + Object { + "_tag": "Left", + "left": Object { + "type": "target_index_had_write_block", + }, + } + `); }); it('resolves left if requireAlias=true and the target is not an alias', async () => { expect.assertions(1); @@ -783,14 +810,14 @@ describe('migration actions', () => { const task = waitForReindexTask({ client, taskId: res.right.taskId, timeout: '10s' }); await expect(task()).resolves.toMatchInlineSnapshot(` - Object { - "_tag": "Left", - "left": Object { - "index": "existing_index_with_write_block", - "type": "index_not_found_exception", - }, - } - `); + Object { + "_tag": "Left", + "left": Object { + "index": "existing_index_with_write_block", + "type": "index_not_found_exception", + }, + } + `); }); it('resolves left wait_for_task_completion_timeout when the task does not finish within the timeout', async () => { await waitForIndexStatusYellow({ @@ -841,11 +868,11 @@ describe('migration actions', () => { targetIndex: 'reindex_target_7', }); await expect(task()).resolves.toMatchInlineSnapshot(` - Object { - "_tag": "Right", - "right": "verify_reindex_succeeded", - } - `); + Object { + "_tag": "Right", + "right": "verify_reindex_succeeded", + } + `); }); it('resolves left if source and target indices have different amount of documents', async () => { expect.assertions(1); @@ -855,13 +882,13 @@ describe('migration actions', () => { targetIndex: 'existing_index_2', }); await expect(task()).resolves.toMatchInlineSnapshot(` - Object { - "_tag": "Left", - "left": Object { - "type": "verify_reindex_failed", - }, - } - `); + Object { + "_tag": "Left", + "left": Object { + "type": "verify_reindex_failed", + }, + } + `); }); it('rejects if source or target index does not exist', async () => { expect.assertions(2); From de4c5d7a787205e790afed3a15445df97038af41 Mon Sep 17 00:00:00 2001 From: Joe Portner <5295965+jportner@users.noreply.github.com> Date: Wed, 17 Nov 2021 08:48:53 -0500 Subject: [PATCH 073/148] Update broadcast-channel and @types/node-forge packages (#118857) --- package.json | 4 ++-- yarn.lock | 38 ++++++++++++++++++++------------------ 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/package.json b/package.json index 70cd6aba11c2a..da8d75668708f 100644 --- a/package.json +++ b/package.json @@ -192,7 +192,7 @@ "axios": "^0.21.1", "base64-js": "^1.3.1", "brace": "0.11.1", - "broadcast-channel": "^4.2.0", + "broadcast-channel": "^4.5.0", "chalk": "^4.1.0", "cheerio": "^1.0.0-rc.10", "chokidar": "^3.4.3", @@ -571,7 +571,7 @@ "@types/nock": "^10.0.3", "@types/node": "16.10.2", "@types/node-fetch": "^2.5.7", - "@types/node-forge": "^0.10.5", + "@types/node-forge": "^0.10.10", "@types/nodemailer": "^6.4.0", "@types/normalize-path": "^3.0.0", "@types/object-hash": "^1.3.0", diff --git a/yarn.lock b/yarn.lock index 4a73df1ef0500..60a1c1dcf17ce 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1254,7 +1254,7 @@ dependencies: regenerator-runtime "^0.12.0" -"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.14.0", "@babel/runtime@^7.16.3", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.2", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": +"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.14.0", "@babel/runtime@^7.16.0", "@babel/runtime@^7.16.3", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.2", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": version "7.16.3" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.16.3.tgz#b86f0db02a04187a3c17caa77de69840165d42d5" integrity sha512-WBwekcqacdY2e9AF/Q7WLFUWmdJGJTkbjqTjoMDgXkVZ3ZRUvOPsLb5KdwISoQVsbP+DQzVZW4Zhci0DvpbNTQ== @@ -5853,10 +5853,10 @@ "@types/node" "*" form-data "^3.0.0" -"@types/node-forge@^0.10.5": - version "0.10.5" - resolved "https://registry.yarnpkg.com/@types/node-forge/-/node-forge-0.10.5.tgz#f79925c88202817a7ec0958c3a9d3a915d362b4f" - integrity sha512-P+Q+MPSDr0RgIzv5h0gJuJDCm1e4RaSu/EMJZTUS4ZzboWH2uX/T7TiqAAcEFTHzCKtgMRqCgTVTX9SD72fMTQ== +"@types/node-forge@^0.10.10": + version "0.10.10" + resolved "https://registry.yarnpkg.com/@types/node-forge/-/node-forge-0.10.10.tgz#07ffccf0f7f3ebb97de67446555912803be50e7b" + integrity sha512-iixn5bedlE9fm/5mN7fPpXraXlxCVrnNWHZekys8c5fknridLVWGnNRqlaWpenwaijIuB3bNI0lEOm+JD6hZUA== dependencies: "@types/node" "*" @@ -8773,19 +8773,18 @@ broadcast-channel@^3.4.1: rimraf "3.0.2" unload "2.2.0" -broadcast-channel@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/broadcast-channel/-/broadcast-channel-4.2.0.tgz#9ca93a23a31036266c2c9b0f8f55bd21594b8f82" - integrity sha512-XX9yNnIy/v2T+HR5EKIH7ziM2mYTefsrzZ2lkCmFZxwCDG7Ns7HLIooUXA114sCeFRJ4MEXEgdMapxfPDh9Xkg== +broadcast-channel@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/broadcast-channel/-/broadcast-channel-4.5.0.tgz#d4717c493e219908fcb7f2f9078fe0baf95b77c1" + integrity sha512-jp+VPlQ1HyR0CM3uIYUrdpXupBvhTMFRkjR6mEmt5W4HaGDPFEzrO2Jqvi2PZ6zCC4zwLeco7CC5EUJPrVH8Tw== dependencies: - "@babel/runtime" "^7.7.2" + "@babel/runtime" "^7.16.0" detect-node "^2.1.0" - js-sha3 "0.8.0" microseconds "0.2.0" nano-time "1.0.0" oblivious-set "1.0.0" rimraf "3.0.2" - unload "2.2.0" + unload "2.3.1" brorand@^1.0.1, brorand@^1.1.0: version "1.1.0" @@ -11952,12 +11951,7 @@ detect-newline@3.1.0, detect-newline@^3.0.0: resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== -detect-node@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.4.tgz#014ee8f8f669c5c58023da64b8179c083a28c46c" - integrity sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw== - -detect-node@^2.1.0: +detect-node@2.1.0, detect-node@^2.0.4, detect-node@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.1.0.tgz#c9c70775a49c3d03bc2c06d9a73be550f978f8b1" integrity sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g== @@ -28216,6 +28210,14 @@ unload@2.2.0: "@babel/runtime" "^7.6.2" detect-node "^2.0.4" +unload@2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/unload/-/unload-2.3.1.tgz#9d16862d372a5ce5cb630ad1309c2fd6e35dacfe" + integrity sha512-MUZEiDqvAN9AIDRbbBnVYVvfcR6DrjCqeU2YQMmliFZl9uaBUjTkhuDQkBiyAy8ad5bx1TXVbqZ3gg7namsWjA== + dependencies: + "@babel/runtime" "^7.6.2" + detect-node "2.1.0" + unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" From ac0f2a320adba8e25fc1b570e98d43d7850d7598 Mon Sep 17 00:00:00 2001 From: Corey Robertson Date: Wed, 17 Nov 2021 09:00:47 -0500 Subject: [PATCH 074/148] [Canvas] Fix group layering (#114346) * Fix group layering * Fixes incorrect z-layers for elements at 90deg Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../workpad_page/integration_utils.js | 34 ++++++++++++++++++- .../canvas/public/lib/aeroelastic/geometry.js | 8 ++++- 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/canvas/public/components/workpad_page/integration_utils.js b/x-pack/plugins/canvas/public/components/workpad_page/integration_utils.js index 9e0627b2c089d..8228593cd4f3a 100644 --- a/x-pack/plugins/canvas/public/components/workpad_page/integration_utils.js +++ b/x-pack/plugins/canvas/public/components/workpad_page/integration_utils.js @@ -75,8 +75,40 @@ const missingParentCheck = (groups) => { }; export const shapesForNodes = (nodes) => { + // For a group, it's z-layer should be the same as the highest of it's children + // So we cache every nodes layer in this array so when we get to a group + // we can refer back to all of the elements and figure out the appropriate layer + // for the group + const nodeLayers = nodes.map(() => null); + + const getNodeLayer = (nodeIndex) => { + if (nodeLayers[nodeIndex]) { + return nodeLayers[nodeIndex]; + } + + const node = nodes[nodeIndex]; + const thisId = node.id; + + const childrenIndexesOfThisNode = nodes + .map((n, i) => [n, i]) + .filter(([node]) => node.position.parent === thisId) + .map(([, index]) => index); + + if (childrenIndexesOfThisNode.length === 0) { + nodeLayers[nodeIndex] = nodeIndex; + } else { + const layer = Math.max(...childrenIndexesOfThisNode.map(getNodeLayer)); + nodeLayers[nodeIndex] = layer; + } + + return nodeLayers[nodeIndex]; + }; + const rawShapes = nodes - .map(elementToShape) + .map((node, index) => { + const layer = getNodeLayer(index); + return elementToShape(node, layer); + }) // filtering to eliminate residual element of a possible group that had been deleted in Redux .filter((d, i, a) => !isGroupId(d.id) || a.find((s) => s.parent === d.id)) .filter(dedupe); diff --git a/x-pack/plugins/canvas/public/lib/aeroelastic/geometry.js b/x-pack/plugins/canvas/public/lib/aeroelastic/geometry.js index 9fff28142a052..883fc20e853a0 100644 --- a/x-pack/plugins/canvas/public/lib/aeroelastic/geometry.js +++ b/x-pack/plugins/canvas/public/lib/aeroelastic/geometry.js @@ -73,7 +73,13 @@ const planeTuple = (transformMatrix, x, y) => { const x0 = rightPoint[0] - centerPoint[0]; const y0 = rightPoint[1] - centerPoint[1]; const x1 = upPoint[0] - centerPoint[0]; - const y1 = upPoint[1] - centerPoint[1]; + // If the shape is rotated so it's straight up or down (90 deg or -90 deg) then + // y1 is going to be zero here and cause divide by zero issues further down. + // The resulting planeVector accounts for this, but it's returning something incorrect that causes z + // to be calculated incorrectly. + // So instead we're going to set y1 to almost zero so we don't have to worry abou the divide by zeros + // and we still end up with an almost correct planeVector + const y1 = upPoint[1] - centerPoint[1] || 0.00000000001; const rightSlope = y1 ? rightPoint[2] - centerPoint[2] : 0; // handle degenerate case: y1 === 0 (infinite slope) const upSlope = y1 ? upPoint[2] - centerPoint[2] : 0; // handle degenerate case: y1 === 0 (infinite slope) const inverseProjection = invert(transformMatrix); From d8af33a2262977568a7160628a481a0b801080d0 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Wed, 17 Nov 2021 09:12:17 -0500 Subject: [PATCH 075/148] [Maps] Use maximum grid_precision for super fine grid-resolution (#118625) --- x-pack/plugins/maps/server/mvt/get_grid_tile.ts | 2 +- .../api_integration/apis/maps/get_grid_tile.js | 12 ++++++------ .../functional/apps/maps/mvt_geotile_grid.js | 16 ++++++++-------- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/x-pack/plugins/maps/server/mvt/get_grid_tile.ts b/x-pack/plugins/maps/server/mvt/get_grid_tile.ts index cfc894d512450..86abff86081a6 100644 --- a/x-pack/plugins/maps/server/mvt/get_grid_tile.ts +++ b/x-pack/plugins/maps/server/mvt/get_grid_tile.ts @@ -38,7 +38,7 @@ export async function getEsGridTile({ const path = `/${encodeURIComponent(index)}/_mvt/${geometryFieldName}/${z}/${x}/${y}`; const body = { size: 0, // no hits - grid_precision: 7, + grid_precision: 8, exact_bounds: false, extent: 4096, // full resolution, query: requestBody.query, diff --git a/x-pack/test/api_integration/apis/maps/get_grid_tile.js b/x-pack/test/api_integration/apis/maps/get_grid_tile.js index d19c5f20ecd30..a757e7487a4ac 100644 --- a/x-pack/test/api_integration/apis/maps/get_grid_tile.js +++ b/x-pack/test/api_integration/apis/maps/get_grid_tile.js @@ -37,7 +37,7 @@ export default function ({ getService }) { expect(clusterFeature.id).to.be(undefined); expect(clusterFeature.properties).to.eql({ _count: 1, - _key: '10/258/404', + _key: '11/517/809', 'avg_of_bytes.value': 9252, }); expect(clusterFeature.loadGeometry()).to.eql([[{ x: 87, y: 667 }]]); @@ -97,16 +97,16 @@ export default function ({ getService }) { expect(gridFeature.id).to.be(undefined); expect(gridFeature.properties).to.eql({ _count: 1, - _key: '10/258/404', + _key: '11/517/809', 'avg_of_bytes.value': 9252, }); expect(gridFeature.loadGeometry()).to.eql([ [ - { x: 64, y: 672 }, + { x: 80, y: 672 }, { x: 96, y: 672 }, - { x: 96, y: 640 }, - { x: 64, y: 640 }, - { x: 64, y: 672 }, + { x: 96, y: 656 }, + { x: 80, y: 656 }, + { x: 80, y: 672 }, ], ]); diff --git a/x-pack/test/functional/apps/maps/mvt_geotile_grid.js b/x-pack/test/functional/apps/maps/mvt_geotile_grid.js index ffda75f8bf98a..929942714ab2e 100644 --- a/x-pack/test/functional/apps/maps/mvt_geotile_grid.js +++ b/x-pack/test/functional/apps/maps/mvt_geotile_grid.js @@ -98,7 +98,7 @@ export default function ({ getPageObjects, getService }) { 'case', ['==', ['get', '_count'], null], 0, - ['max', ['min', ['to-number', ['get', '_count']], 10], 1], + ['max', ['min', ['to-number', ['get', '_count']], 8], 1], ], 0, ], @@ -106,19 +106,19 @@ export default function ({ getPageObjects, getService }) { 'rgba(0,0,0,0)', 1, '#ecf1f7', - 2.125, + 1.875, '#d9e3ef', - 3.25, + 2.75, '#c5d5e7', - 4.375, + 3.625, '#b2c7df', - 5.5, + 4.5, '#9eb9d8', - 6.625, + 5.375, '#8bacd0', - 7.75, + 6.25, '#769fc8', - 8.875, + 7.125, '#6092c0', ], 'fill-opacity': 0.75, From c983bd94ddaccd69091a0663b85c0ecab88ca855 Mon Sep 17 00:00:00 2001 From: Andrew Tate Date: Wed, 17 Nov 2021 08:26:47 -0600 Subject: [PATCH 076/148] [Lens] Prevent KQL Popovers From Stacking (#118258) --- .../filters/filter_popover.test.tsx | 88 ++++++++++++++----- .../definitions/filters/filter_popover.tsx | 54 +++++++----- .../definitions/filters/filters.tsx | 29 ++++-- 3 files changed, 116 insertions(+), 55 deletions(-) diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/filter_popover.test.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/filter_popover.test.tsx index 1c2e64735ca16..a204c1ec590a4 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/filter_popover.test.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/filter_popover.test.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import React, { MouseEventHandler } from 'react'; +import React from 'react'; import { shallow, mount } from 'enzyme'; import { act } from 'react-dom/test-utils'; import { EuiPopover, EuiLink } from '@elastic/eui'; @@ -20,19 +20,6 @@ jest.mock('.', () => ({ defaultLabel: 'label', })); -const defaultProps = { - filter: { - input: { query: 'bytes >= 1', language: 'kuery' }, - label: 'More than one', - id: '1', - }, - setFilter: jest.fn(), - indexPattern: createMockedIndexPattern(), - Button: ({ onClick }: { onClick: MouseEventHandler }) => ( - trigger - ), - initiallyOpen: true, -}; jest.mock('../../../../../../../../src/plugins/data/public', () => ({ QueryStringInput: () => { return 'QueryStringInput'; @@ -40,6 +27,67 @@ jest.mock('../../../../../../../../src/plugins/data/public', () => ({ })); describe('filter popover', () => { + let defaultProps: Parameters[0]; + let mockOnClick: jest.Mock; + + beforeEach(() => { + mockOnClick = jest.fn(); + + defaultProps = { + filter: { + input: { query: 'bytes >= 1', language: 'kuery' }, + label: 'More than one', + id: '1', + }, + setFilter: jest.fn(), + indexPattern: createMockedIndexPattern(), + Button: () => trigger, + isOpen: true, + triggerClose: () => {}, + }; + }); + + describe('interactions', () => { + it('should open/close according to isOpen', () => { + const instance = mount(); + + expect(instance.find(EuiPopover).prop('isOpen')).toEqual(true); + + instance.setProps({ ...defaultProps, isOpen: false }); + instance.update(); + + expect(instance.find(EuiPopover).prop('isOpen')).toEqual(false); + }); + + it('should report click event', () => { + const instance = mount(); + + expect(mockOnClick).not.toHaveBeenCalled(); + + instance.find(EuiPopover).find('button').simulate('click', {}); + + expect(mockOnClick).toHaveBeenCalledTimes(1); + }); + + it('should trigger close', () => { + const props = { ...defaultProps, triggerClose: jest.fn() }; + const instance = mount(); + expect(instance.find(EuiPopover).prop('isOpen')).toEqual(true); + + // Trigger from EuiPopover + act(() => { + instance.find(EuiPopover).prop('closePopover')!(); + }); + expect(props.triggerClose).toHaveBeenCalledTimes(1); + + // Trigger from submit + act(() => { + instance.find(LabelInput).prop('onSubmit')!(); + }); + expect(props.triggerClose).toHaveBeenCalledTimes(2); + }); + }); + it('passes correct props to QueryStringInput', () => { const instance = mount(); instance.update(); @@ -52,16 +100,7 @@ describe('filter popover', () => { }) ); }); - it('should be open if is open by creation', () => { - const instance = mount(); - instance.update(); - expect(instance.find(EuiPopover).prop('isOpen')).toEqual(true); - act(() => { - instance.find(EuiPopover).prop('closePopover')!(); - }); - instance.update(); - expect(instance.find(EuiPopover).prop('isOpen')).toEqual(false); - }); + it('should call setFilter when modifying QueryInput', () => { const setFilter = jest.fn(); const instance = shallow(); @@ -78,6 +117,7 @@ describe('filter popover', () => { id: '1', }); }); + it('should call setFilter when modifying LabelInput', () => { const setFilter = jest.fn(); const instance = shallow(); diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/filter_popover.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/filter_popover.tsx index bfb0cffece57c..cf95ae2dfd0e8 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/filter_popover.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/filter_popover.tsx @@ -7,7 +7,7 @@ import './filter_popover.scss'; -import React, { MouseEventHandler, useEffect, useState } from 'react'; +import React from 'react'; import { EuiPopover, EuiSpacer } from '@elastic/eui'; import { FilterValue, defaultLabel, isQueryValid } from '.'; import { IndexPattern } from '../../../types'; @@ -20,28 +20,40 @@ export const FilterPopover = ({ setFilter, indexPattern, Button, - initiallyOpen, + isOpen, + triggerClose, }: { filter: FilterValue; setFilter: Function; indexPattern: IndexPattern; - Button: React.FunctionComponent<{ onClick: MouseEventHandler }>; - initiallyOpen: boolean; + Button: React.FunctionComponent; + isOpen: boolean; + triggerClose: () => void; }) => { - const [isPopoverOpen, setIsPopoverOpen] = useState(false); const inputRef = React.useRef(); - // set popover open on start to work around EUI bug - useEffect(() => { - setIsPopoverOpen(initiallyOpen); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); + // The following code is to prevent an keypress + // from propagating. + // + // TODO - It looks like EUI should be handling this + // (see https://github.com/elastic/eui/commit/ad97583b0d644690379f72c7a20879cfadb16e7a) + const popoverRef = React.useRef(null); + let panelElement: HTMLDivElement; + const panelRefCallback = (element: HTMLDivElement) => { + const listener = (event: KeyboardEvent) => { + if (event.key === 'Escape') { + event.stopPropagation(); + panelElement.removeEventListener('keydown', listener); + popoverRef.current?.closePopover(); + } + }; - const closePopover = () => { - if (isPopoverOpen) { - setIsPopoverOpen(false); + if (element) { + panelElement = element; + panelElement.addEventListener('keydown', listener); } }; + // End handling code const setFilterLabel = (label: string) => setFilter({ ...filter, label }); const setFilterQuery = (input: Query) => setFilter({ ...filter, input }); @@ -58,19 +70,15 @@ export const FilterPopover = ({ return ( closePopover()} - button={ - + +

    +
    +
    +
    +
    +`; + +exports[`Storyshots components/WorkpadFilters/FiltersGroupComponent empty group 1`] = ` +
    +
    +
    +
    + + +
    +
    +
    +
    +
    +`; diff --git a/x-pack/plugins/canvas/public/components/workpad_filters/__stories__/__snapshots__/workpad_filters.component.stories.storyshot b/x-pack/plugins/canvas/public/components/workpad_filters/__stories__/__snapshots__/workpad_filters.component.stories.storyshot new file mode 100644 index 0000000000000..31e473f527e06 --- /dev/null +++ b/x-pack/plugins/canvas/public/components/workpad_filters/__stories__/__snapshots__/workpad_filters.component.stories.storyshot @@ -0,0 +1,706 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Storyshots components/WorkpadFilters/WorkpadFiltersComponent Empty filters groups 1`] = ` +
    +
    +
    +
    +
    +
    +
    +
    + Group by +
    +
    +
    +
    +
    +
    + +
    + + +
    +
    +
    +
    +
    +
    +
    +
    +
    +`; + +exports[`Storyshots components/WorkpadFilters/WorkpadFiltersComponent Filters groups without group name 1`] = ` +
    +
    +
    +
    +
    +
    +
    +
    + Group by +
    +
    +
    +
    +
    +
    + +
    + + +
    +
    +
    +
    +
    +
    +
    +
    +
    + + +
    +
    +
    +
    +
    +
    +
    +`; + +exports[`Storyshots components/WorkpadFilters/WorkpadFiltersComponent Filters groups without name 1`] = ` +
    +
    +
    +
    +
    +
    +
    +
    + Group by +
    +
    +
    +
    +
    +
    + +
    + + +
    +
    +
    +
    +
    +
    +
    +
    +
    + + +
    +
    +
    +
    +
    +
    +
    +`; + +exports[`Storyshots components/WorkpadFilters/WorkpadFiltersComponent Filters groups without name and filters 1`] = ` +
    +
    +
    +
    +
    +
    +
    +
    + Group by +
    +
    +
    +
    +
    +
    + +
    + + +
    +
    +
    +
    +
    +
    +
    +
    +
    + + +
    +
    +
    +
    +
    +
    +
    +`; + +exports[`Storyshots components/WorkpadFilters/WorkpadFiltersComponent default 1`] = ` +
    +
    +
    +
    +
    +
    +
    +
    + Group by +
    +
    +
    +
    +
    +
    + +
    + + +
    +
    +
    +
    +
    +
    +
    +
    +
    + + +
    +
    +
    +
    +
    +
    +
    + + +
    +
    +
    +
    +
    +
    +
    +`; diff --git a/x-pack/plugins/canvas/public/components/workpad_filters/__stories__/elements.ts b/x-pack/plugins/canvas/public/components/workpad_filters/__stories__/elements.ts new file mode 100644 index 0000000000000..9eacfb54a411f --- /dev/null +++ b/x-pack/plugins/canvas/public/components/workpad_filters/__stories__/elements.ts @@ -0,0 +1,66 @@ +/* + * 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 moment from 'moment'; +import { CanvasElement } from '../../../../types'; + +const timeFormat = 'MM.dd.YYYY HH:mm'; + +const generatePosition = (n: number): CanvasElement['position'] => ({ + left: n, + top: n, + width: n, + height: n, + angle: n, + parent: null, +}); + +const time1 = { + from: moment('1.01.2021 8:15', timeFormat).format(), + to: moment('2.01.2021 17:22', timeFormat).format(), +}; +const group1 = 'Group 1'; + +const time2 = { + from: moment('1.10.2021 12:20', timeFormat).format(), + to: moment('2.10.2021 12:33', timeFormat).format(), +}; +const group2 = 'Group 2'; + +const element1: CanvasElement = { + id: '1', + position: generatePosition(1), + type: 'element', + expression: '', + filter: `timefilter column="@timestamp" from="${time1.from}" to="${time1.to}" filterGroup="${group1}"`, +}; + +const element2: CanvasElement = { + id: '2', + position: generatePosition(2), + type: 'element', + expression: '', + filter: `exactly value="machine-learning" column="project1" filterGroup="${group1}"`, +}; + +const element3: CanvasElement = { + id: '3', + position: generatePosition(3), + type: 'element', + expression: '', + filter: `timefilter column="@timestamp" from="${time2.from}" to="${time2.to}"`, +}; + +const element4: CanvasElement = { + id: '4', + position: generatePosition(4), + type: 'element', + expression: '', + filter: `exactly value="kibana" column="project2" filterGroup="${group2}"`, +}; + +export const elements = [element1, element2, element3, element4]; diff --git a/x-pack/plugins/canvas/public/components/workpad_filters/__stories__/filter.component.stories.tsx b/x-pack/plugins/canvas/public/components/workpad_filters/__stories__/filter.component.stories.tsx new file mode 100644 index 0000000000000..2f80ffed5abf9 --- /dev/null +++ b/x-pack/plugins/canvas/public/components/workpad_filters/__stories__/filter.component.stories.tsx @@ -0,0 +1,53 @@ +/* + * 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 { EuiText, EuiTextColor } from '@elastic/eui'; +import { storiesOf } from '@storybook/react'; +import React, { FC } from 'react'; +import { FormattedFilterViewInstance } from '../../../../types'; +import { Filter } from '../filter.component'; + +const filter: FormattedFilterViewInstance = { + type: { + label: 'Type', + formattedValue: 'exactly', + }, + column: { + label: 'Column', + formattedValue: 'project', + }, + value: { + label: 'Value', + formattedValue: 'kibana', + }, + filterGroup: { + label: 'Filter group', + formattedValue: 'Group 1', + }, +}; + +const component: FC = ({ value }) => ( + + +

    {value}

    +
    +
    +); + +storiesOf('components/WorkpadFilters/FilterComponent', module) + .add('default', () => ) + .add('with component field', () => ( + + )) + .add('with custom filter fields', () => ( + + )); diff --git a/x-pack/plugins/canvas/public/components/workpad_filters/__stories__/filters_group.component.stories.tsx b/x-pack/plugins/canvas/public/components/workpad_filters/__stories__/filters_group.component.stories.tsx new file mode 100644 index 0000000000000..bdeb963dc8832 --- /dev/null +++ b/x-pack/plugins/canvas/public/components/workpad_filters/__stories__/filters_group.component.stories.tsx @@ -0,0 +1,47 @@ +/* + * 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 { storiesOf } from '@storybook/react'; +import React from 'react'; +import moment from 'moment'; +import { FiltersGroup } from '../filters_group.component'; +import { FiltersGroup as FiltersGroupType } from '../types'; + +const timeFormat = 'MM.dd.YYYY HH:mm'; + +const filtersGroup: FiltersGroupType = { + name: 'Group 1', + filters: [ + { type: 'exactly', column: 'project', value: 'kibana', filterGroup: 'Group 1' }, + { + type: 'time', + column: '@timestamp', + value: { + from: moment('1.01.2021 8:15', timeFormat).format(), + to: moment('2.01.2021 17:22', timeFormat).format(), + }, + filterGroup: 'Group 1', + }, + { type: 'exactly', column: 'country', value: 'US', filterGroup: 'Group 1' }, + { + type: 'time', + column: 'time', + value: { + from: moment('05.21.2021 10:50', timeFormat).format(), + to: moment('05.22.2021 4:40', timeFormat).format(), + }, + filterGroup: 'Group 1', + }, + ], +}; + +storiesOf('components/WorkpadFilters/FiltersGroupComponent', module) + .addDecorator((story) =>
    {story()}
    ) + .add('default', () => ) + .add('empty group', () => ( + + )); diff --git a/x-pack/plugins/canvas/public/components/workpad_filters/__stories__/workpad_filters.component.stories.tsx b/x-pack/plugins/canvas/public/components/workpad_filters/__stories__/workpad_filters.component.stories.tsx new file mode 100644 index 0000000000000..8dc062886a12e --- /dev/null +++ b/x-pack/plugins/canvas/public/components/workpad_filters/__stories__/workpad_filters.component.stories.tsx @@ -0,0 +1,95 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { storiesOf } from '@storybook/react'; +import { action } from '@storybook/addon-actions'; +import React from 'react'; +import moment from 'moment'; +import { WorkpadFilters } from '../workpad_filters.component'; +import { FiltersGroup as FiltersGroupType } from '../types'; +import { Filter } from '../../../../types'; + +const timeFormat = 'MM.dd.YYYY HH:mm'; + +const filters: Filter[] = [ + { type: 'exactly', column: 'project', value: 'kibana', filterGroup: 'Group 1' }, + { + type: 'time', + column: '@timestamp', + value: { + from: moment('1.01.2021 8:15', timeFormat).format(), + to: moment('2.01.2021 17:22', timeFormat).format(), + }, + filterGroup: 'Group 1', + }, + { type: 'exactly', column: 'country', value: 'US', filterGroup: 'Group 2' }, + { + type: 'time', + column: 'time', + value: { + from: moment('05.21.2021 10:50', timeFormat).format(), + to: moment('05.22.2021 4:40', timeFormat).format(), + }, + filterGroup: 'Group 2', + }, +]; + +const filtersGroups: FiltersGroupType[] = [ + { + name: filters[0].filterGroup, + filters: [filters[0], filters[1]], + }, + { + name: filters[2].filterGroup, + filters: [filters[2], filters[3]], + }, +]; + +storiesOf('components/WorkpadFilters/WorkpadFiltersComponent', module) + .addDecorator((story) => ( +
    +
    +
    {story()}
    +
    +
    + )) + .add('default', () => ( + + )) + .add('Filters groups without name', () => ( + ((acc, group) => [...acc, ...group.filters], []), + }, + ]} + groupFiltersByField={'column'} + onGroupByChange={action('onGroupByChange')} + /> + )) + .add('Filters groups without group name', () => ( + ((acc, group) => [...acc, ...group.filters], []), + }, + ]} + groupFiltersByField={'filterGroup'} + onGroupByChange={action('onGroupByChange')} + /> + )) + .add('Filters groups without name and filters', () => ( + + )) + .add('Empty filters groups', () => ( + + )); diff --git a/x-pack/plugins/canvas/public/components/workpad_filters/__stories__/workpad_filters.stories.tsx b/x-pack/plugins/canvas/public/components/workpad_filters/__stories__/workpad_filters.stories.tsx new file mode 100644 index 0000000000000..b97043bf83304 --- /dev/null +++ b/x-pack/plugins/canvas/public/components/workpad_filters/__stories__/workpad_filters.stories.tsx @@ -0,0 +1,23 @@ +/* + * 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 { storiesOf } from '@storybook/react'; +import React from 'react'; +import { reduxDecorator } from '../../../../storybook'; +import { WorkpadFilters } from '../workpad_filters'; +import { elements } from './elements'; + +storiesOf('components/WorkpadFilters/WorkpadFilters', module) + .addDecorator((story) => ( +
    +
    +
    {story()}
    +
    +
    + )) + .addDecorator(reduxDecorator({ elements })) + .add('redux: default', () => ); diff --git a/x-pack/plugins/canvas/public/components/workpad_filters/filter.component.tsx b/x-pack/plugins/canvas/public/components/workpad_filters/filter.component.tsx new file mode 100644 index 0000000000000..bec6bec090d62 --- /dev/null +++ b/x-pack/plugins/canvas/public/components/workpad_filters/filter.component.tsx @@ -0,0 +1,64 @@ +/* + * 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, { FC } from 'react'; +import { EuiDescriptionList, EuiPanel, EuiText } from '@elastic/eui'; +import { FormattedFilterViewInstance } from '../../../types'; + +interface Props { + filter: FormattedFilterViewInstance; + updateFilter?: (value: any) => void; +} + +type CustomComponentProps = Omit & { value: string }; + +const titleStyle = { + width: '30%', +}; + +const descriptionStyle = { + width: '70%', +}; + +const renderElement = ( + Component: FC< + Omit & { onChange?: CustomComponentProps['updateFilter'] } + >, + { updateFilter, ...props }: CustomComponentProps +) => { + return ; +}; + +export const Filter: FC = ({ filter, ...restProps }) => { + const filterView = Object.values(filter).map((filterValue) => { + const description = filterValue.component + ? renderElement(filterValue.component, { value: filterValue.formattedValue, ...restProps }) + : filterValue.formattedValue; + + return { + title: ( + +

    {filterValue.label}

    +
    + ), + description: {description}, + }; + }); + + return ( + + + + ); +}; diff --git a/x-pack/plugins/canvas/public/components/workpad_filters/filter_views/default_filter.ts b/x-pack/plugins/canvas/public/components/workpad_filters/filter_views/default_filter.ts new file mode 100644 index 0000000000000..b2686fb660535 --- /dev/null +++ b/x-pack/plugins/canvas/public/components/workpad_filters/filter_views/default_filter.ts @@ -0,0 +1,39 @@ +/* + * 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 { FilterViewSpec } from '../../../../types'; +import { formatByKey } from '../utils'; + +const strings = { + getTypeLabel: () => + i18n.translate('xpack.canvas.workpadFilters.defaultFilter.type', { + defaultMessage: 'Type', + }), + getColumnLabel: () => + i18n.translate('xpack.canvas.workpadFilters.defaultFilter.column', { + defaultMessage: 'Column', + }), + getFilterGroupLabel: () => + i18n.translate('xpack.canvas.workpadFilters.defaultFilter.filterGroup', { + defaultMessage: 'Filter group', + }), + getValueLabel: () => + i18n.translate('xpack.canvas.workpadFilters.defaultFilter.value', { + defaultMessage: 'Value', + }), +}; + +export const defaultFilter: FilterViewSpec = { + name: 'default', + view: { + column: { label: strings.getColumnLabel() }, + value: { label: strings.getValueLabel() }, + type: { label: strings.getTypeLabel(), formatter: formatByKey('type') }, + filterGroup: { label: strings.getFilterGroupLabel() }, + }, +}; diff --git a/x-pack/plugins/canvas/public/components/workpad_filters/filter_views/index.ts b/x-pack/plugins/canvas/public/components/workpad_filters/filter_views/index.ts new file mode 100644 index 0000000000000..98fad36c0015a --- /dev/null +++ b/x-pack/plugins/canvas/public/components/workpad_filters/filter_views/index.ts @@ -0,0 +1,15 @@ +/* + * 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 { FilterViewSpec } from '../../../../types'; +import { defaultFilter } from './default_filter'; +import { timeFilter } from './time_filter'; + +export const filterViews: Record> = { + [defaultFilter.name]: defaultFilter, + [timeFilter.name]: timeFilter, +}; diff --git a/x-pack/plugins/canvas/public/components/workpad_filters/filter_views/time_filter.ts b/x-pack/plugins/canvas/public/components/workpad_filters/filter_views/time_filter.ts new file mode 100644 index 0000000000000..1dc02f61d05f7 --- /dev/null +++ b/x-pack/plugins/canvas/public/components/workpad_filters/filter_views/time_filter.ts @@ -0,0 +1,68 @@ +/* + * 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 dateMath from '@elastic/datemath'; +import { i18n } from '@kbn/i18n'; +import { FilterType, FilterViewSpec, SimpleFilterViewField } from '../../../../types'; +import { formatByKey } from '../utils'; +import { defaultFilter } from './default_filter'; + +export interface TimeFilterValue { + to: string; + from: string; +} + +const strings = { + getFromLabel: () => + i18n.translate('xpack.canvas.workpadFilters.timeFilter.from', { + defaultMessage: 'From', + }), + getToLabel: () => + i18n.translate('xpack.canvas.workpadFilters.timeFilter.to', { + defaultMessage: 'To', + }), + getInvalidDateLabel: (date: string) => + i18n.translate('xpack.canvas.workpadFilters.timeFilter.invalidDate', { + defaultMessage: 'Invalid date: {date}', + values: { + date, + }, + }), +}; + +const { column, type, filterGroup } = defaultFilter.view; + +const formatTime = (str: string, roundUp: boolean) => { + const moment = dateMath.parse(str, { roundUp }); + if (!moment || !moment.isValid()) { + return strings.getInvalidDateLabel(str); + } + + return moment.format('YYYY-MM-DD HH:mm:ss'); +}; + +export const timeFilter: FilterViewSpec = { + name: FilterType.time, + view: { + column, + value: ({ to, from }) => ({ + from: { + label: strings.getFromLabel(), + formatter: () => formatTime(from, false), + }, + to: { + label: strings.getToLabel(), + formatter: () => formatTime(to, true), + }, + }), + type: { + label: (type as SimpleFilterViewField).label, + formatter: formatByKey('type'), + }, + filterGroup, + }, +}; diff --git a/x-pack/plugins/canvas/public/components/workpad_filters/filters_group.component.tsx b/x-pack/plugins/canvas/public/components/workpad_filters/filters_group.component.tsx new file mode 100644 index 0000000000000..8ceb60fe7866f --- /dev/null +++ b/x-pack/plugins/canvas/public/components/workpad_filters/filters_group.component.tsx @@ -0,0 +1,50 @@ +/* + * 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 { EuiAccordion } from '@elastic/eui'; +import React, { FC } from 'react'; +import { FormattedFilterViewInstance } from '../../../types'; +import { createFilledFilterView } from '../../lib/filter'; +import { Filter } from './filter.component'; +import { filterViews } from './filter_views'; +import { FiltersGroup as FiltersGroupType } from './types'; + +interface Props { + filtersGroup: FiltersGroupType; + id: string | number; +} + +const panelStyle = { + paddingTop: '15px', +}; + +export const FiltersGroup: FC = ({ filtersGroup, id }) => { + const { name, filters: groupFilters } = filtersGroup; + + const filledFilterViews: FormattedFilterViewInstance[] = groupFilters.map((filter) => { + const filterView = filterViews[filter.type] ?? filterViews.default; + return createFilledFilterView(filterView.view, filter); + }); + + const filtersComponents = filledFilterViews.map((filter, index) => ( + + )); + + return ( +
    + +
    {filtersComponents}
    +
    +
    + ); +}; diff --git a/x-pack/plugins/canvas/public/components/workpad_filters/hooks/index.ts b/x-pack/plugins/canvas/public/components/workpad_filters/hooks/index.ts new file mode 100644 index 0000000000000..62f2a28130bfa --- /dev/null +++ b/x-pack/plugins/canvas/public/components/workpad_filters/hooks/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export { useCanvasFilters } from './use_canvas_filters'; diff --git a/x-pack/plugins/canvas/public/components/workpad_filters/hooks/use_canvas_filters.ts b/x-pack/plugins/canvas/public/components/workpad_filters/hooks/use_canvas_filters.ts new file mode 100644 index 0000000000000..ce8e90def5aad --- /dev/null +++ b/x-pack/plugins/canvas/public/components/workpad_filters/hooks/use_canvas_filters.ts @@ -0,0 +1,23 @@ +/* + * 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 { fromExpression } from '@kbn/interpreter/common'; +import { shallowEqual, useSelector } from 'react-redux'; +import { State } from '../../../../types'; +import { adaptCanvasFilter } from '../../../lib/filter_adapters'; +import { getGlobalFilters } from '../../../state/selectors/workpad'; + +const extractExpressionAST = (filtersExpressions: string[]) => + fromExpression(filtersExpressions.join(' | ')); + +export function useCanvasFilters() { + const filterExpressions = useSelector((state: State) => getGlobalFilters(state), shallowEqual); + const expression = extractExpressionAST(filterExpressions); + const filters = expression.chain.map(adaptCanvasFilter); + + return filters; +} diff --git a/x-pack/plugins/canvas/public/components/workpad_filters/index.tsx b/x-pack/plugins/canvas/public/components/workpad_filters/index.tsx new file mode 100644 index 0000000000000..684d5e09c18fc --- /dev/null +++ b/x-pack/plugins/canvas/public/components/workpad_filters/index.tsx @@ -0,0 +1,9 @@ +/* + * 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 { WorkpadFilters } from './workpad_filters'; +export { WorkpadFilters as WorkpadFiltersComponent } from './workpad_filters.component'; diff --git a/x-pack/plugins/canvas/public/components/workpad_filters/types.ts b/x-pack/plugins/canvas/public/components/workpad_filters/types.ts new file mode 100644 index 0000000000000..4733c18da9be5 --- /dev/null +++ b/x-pack/plugins/canvas/public/components/workpad_filters/types.ts @@ -0,0 +1,13 @@ +/* + * 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 { Filter } from '../../../types'; + +export interface FiltersGroup { + name: string | null; + filters: Filter[]; +} diff --git a/x-pack/plugins/canvas/public/components/workpad_filters/utils.ts b/x-pack/plugins/canvas/public/components/workpad_filters/utils.ts new file mode 100644 index 0000000000000..cc5836112db8a --- /dev/null +++ b/x-pack/plugins/canvas/public/components/workpad_filters/utils.ts @@ -0,0 +1,42 @@ +/* + * 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 { FilterField } from '../../../types'; + +const strings = { + getBlankLabel: () => + i18n.translate('xpack.canvas.workpadFilters.filter.blankTypeLabel', { + defaultMessage: '(Blank)', + }), + getExactlyFilterTypeLabel: () => + i18n.translate('xpack.canvas.workpadFilters.defaultFilter.typeLabel', { + defaultMessage: 'Dropdown', + }), + getTimeFilterTypeLabel: () => + i18n.translate('xpack.canvas.workpadFilters.timeFilter.typeLabel', { + defaultMessage: 'Time', + }), + getWithoutGroupLabel: () => + i18n.translate('xpack.canvas.workpadFilters.filters_group.withoutGroup', { + defaultMessage: 'Without group', + }), +}; + +const formatType = (type: unknown) => { + const types: Record = { + exactly: strings.getExactlyFilterTypeLabel(), + time: strings.getTimeFilterTypeLabel(), + }; + return typeof type === 'string' ? types[type] ?? type : null; +}; + +const formatters: Partial string | null>> = { + type: formatType, +}; + +export const formatByKey = (key: FilterField) => formatters[key]; diff --git a/x-pack/plugins/canvas/public/components/workpad_filters/workpad_filters.component.tsx b/x-pack/plugins/canvas/public/components/workpad_filters/workpad_filters.component.tsx new file mode 100644 index 0000000000000..e3504f906fb3a --- /dev/null +++ b/x-pack/plugins/canvas/public/components/workpad_filters/workpad_filters.component.tsx @@ -0,0 +1,98 @@ +/* + * 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, { FC, Fragment } from 'react'; +import { EuiFlexGroup, EuiFlexItem, EuiSelect, EuiText } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { identity } from 'lodash'; +import { FiltersGroup as FiltersGroupType } from './types'; +import { FiltersGroup } from './filters_group.component'; +import { FilterField } from '../../../types'; +import { formatByKey } from './utils'; + +interface Props { + filtersGroups: FiltersGroupType[]; + groupFiltersByField?: FilterField; + onGroupByChange: (groupBy: FilterField) => void; +} + +const strings = { + getGroupBySelectLabel: () => + i18n.translate('xpack.canvas.workpadFilters.groupBySelect', { + defaultMessage: 'Group by', + }), + getGroupByFilterGroupLabel: () => + i18n.translate('xpack.canvas.workpadFilters.groupByFilterGroup', { + defaultMessage: 'Filter group', + }), + getGroupByFilterTypeLabel: () => + i18n.translate('xpack.canvas.workpadFilters.groupByFilterType', { + defaultMessage: 'Filter type', + }), + getGroupByColumnLabel: () => + i18n.translate('xpack.canvas.workpadFilters.groupByColumn', { + defaultMessage: 'Column', + }), + getWithoutGroupLabel: () => + i18n.translate('xpack.canvas.workpadFilters.filters_group.withoutGroup', { + defaultMessage: 'Without group', + }), + getBlankValueLabel: () => + i18n.translate('xpack.canvas.workpadFilters.filters_group.blankValue', { + defaultMessage: '(Blank)', + }), +}; + +const groupByOptions: Array<{ value: FilterField; text: string }> = [ + { value: 'filterGroup', text: strings.getGroupByFilterGroupLabel() }, + { value: 'type', text: strings.getGroupByFilterTypeLabel() }, + { value: 'column', text: strings.getGroupByColumnLabel() }, +]; + +export const WorkpadFilters: FC = ({ + filtersGroups, + onGroupByChange, + groupFiltersByField, +}) => { + const groupedByFilterGroupField = groupFiltersByField === 'filterGroup'; + const formatter = groupFiltersByField ? formatByKey(groupFiltersByField) ?? identity : identity; + + const preparedFilterGroups = filtersGroups.map((filterGroup) => ({ + ...filterGroup, + name: + formatter(filterGroup.name) ?? + (groupedByFilterGroupField ? strings.getWithoutGroupLabel() : strings.getBlankValueLabel()), + })); + + const filtersGroupsComponents = preparedFilterGroups.map((filtersGroup, index) => { + return ; + }); + + return ( + +
    + + + +
    {strings.getGroupBySelectLabel()}
    +
    +
    + + onGroupByChange(e.target.value as FilterField)} + aria-label="Use aria labels when no actual label is in use" + /> + +
    +
    + {filtersGroupsComponents} +
    + ); +}; diff --git a/x-pack/plugins/canvas/public/components/workpad_filters/workpad_filters.tsx b/x-pack/plugins/canvas/public/components/workpad_filters/workpad_filters.tsx new file mode 100644 index 0000000000000..c04fe543804b4 --- /dev/null +++ b/x-pack/plugins/canvas/public/components/workpad_filters/workpad_filters.tsx @@ -0,0 +1,44 @@ +/* + * 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, { FC, useCallback } from 'react'; +import { useDispatch, useSelector } from 'react-redux'; +import { State, FilterField } from '../../../types'; +import { groupFiltersBy } from '../../lib/filter'; +import { setGroupFiltersByOption } from '../../state/actions/sidebar'; +import { getGroupFiltersByOption } from '../../state/selectors/sidebar'; +import { useCanvasFilters } from './hooks'; +import { WorkpadFilters as Component } from './workpad_filters.component'; + +export const WorkpadFilters: FC = () => { + const groupFiltersByField: FilterField = useSelector((state: State) => + getGroupFiltersByOption(state) + ); + + const dispatch = useDispatch(); + + const onGroupByChange = useCallback( + (groupByOption: FilterField) => { + dispatch(setGroupFiltersByOption(groupByOption)); + }, + [dispatch] + ); + + const canvasFilters = useCanvasFilters(); + + const filtersGroups = groupFiltersByField + ? groupFiltersBy(canvasFilters, groupFiltersByField) + : []; + + return ( + + ); +}; diff --git a/x-pack/plugins/canvas/public/lib/filter.test.ts b/x-pack/plugins/canvas/public/lib/filter.test.ts new file mode 100644 index 0000000000000..497f75b91650f --- /dev/null +++ b/x-pack/plugins/canvas/public/lib/filter.test.ts @@ -0,0 +1,282 @@ +/* + * 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 { FC } from 'react'; +import { + Filter as FilterType, + FilterViewInstance, + FlattenFilterViewInstance, + SimpleFilterViewField, +} from '../../types'; +import { + defaultFormatter, + formatFilterView, + flattenFilterView, + createFilledFilterView, + groupFiltersBy, +} from './filter'; + +const formatterFactory = (value: unknown) => () => JSON.stringify(value); +const fc: FC = () => null; + +const simpleFilterValue: FilterType = { + type: 'exactly', + column: 'project', + value: 'kibana', + filterGroup: 'someGroup', +}; + +const filterWithNestedValue: FilterType = { + type: 'exactlyNested' as any, + column: 'project', + value: { nestedField1: 'nestedField1', nestedField2: 'nestedField2' }, + filterGroup: 'someGroup', +}; + +const simpleFilterView: FilterViewInstance = { + type: { label: 'label' }, + column: { label: 'column' }, + value: { label: 'value' }, + filterGroup: { label: 'filterGroup' }, +}; + +const nestedFilterView: FilterViewInstance = { + type: { label: 'label' }, + column: { label: 'column' }, + value: (value: unknown) => ({ + nested: { + label: 'nested', + formatter: formatterFactory(value), + }, + }), + filterGroup: { label: 'filterGroup' }, +}; + +describe('defaultFormatter', () => { + it('returns string when passed not null/undefined/falsy/emtpy value', () => { + expect(defaultFormatter(10)).toBe('10'); + expect(defaultFormatter('10')).toBe('10'); + const objToFormat = { field: 10 }; + expect(defaultFormatter(objToFormat)).toBe(objToFormat.toString()); + const arrToFormat = [10, 20]; + expect(defaultFormatter(arrToFormat)).toBe(arrToFormat.toString()); + }); + + it("returns '-' when passed null/undefined/falsy/emtpy value", () => { + const empty = '-'; + expect(defaultFormatter(null)).toBe(empty); + expect(defaultFormatter(undefined)).toBe(empty); + expect(defaultFormatter('')).toBe(empty); + expect(defaultFormatter(false)).toBe(empty); + }); +}); + +describe('flattenFilterView returns fn which', () => { + it('returns the same filter view if it expects all fiends to be simple values', () => { + const flattenFn = flattenFilterView(simpleFilterValue); + expect(flattenFn(simpleFilterView)).toEqual(simpleFilterView); + }); + + it('returns the same filter view if filterValue is empty object', () => { + const flattenFn = flattenFilterView({} as any); + expect(flattenFn(simpleFilterView)).toEqual(simpleFilterView); + }); + + it('returns empty filter view if filter view is empty object', () => { + const flattenFn = flattenFilterView(simpleFilterValue); + expect(flattenFn({} as any)).toEqual({}); + }); + + it('returns single nesting filter view if it expects some fields to be nested objects', () => { + const flattenFn = flattenFilterView(filterWithNestedValue); + const { value, ...restExpectedFields } = nestedFilterView; + const flattenFilterViewRes = flattenFn(nestedFilterView); + + expect(flattenFilterViewRes).toEqual({ + ...restExpectedFields, + nested: { + label: 'nested', + formatter: expect.any(Function), + }, + }); + expect(flattenFilterViewRes.nested.formatter?.()).toBe( + formatterFactory(filterWithNestedValue.value)() + ); + }); + + it('returns single nesting filter view if filterValue is empty object', () => { + const flattenFn = flattenFilterView({} as any); + const { value, ...rest } = nestedFilterView; + expect(flattenFn(nestedFilterView)).toEqual({ + ...rest, + nested: { + label: 'nested', + formatter: expect.any(Function), + }, + }); + }); +}); + +describe('formatFilterView returns fn which', () => { + const simpleFlattenFilterView: FlattenFilterViewInstance = { + type: { label: 'label' }, + value: { label: 'value' }, + column: { label: 'column' }, + filterGroup: { label: 'filterGroup' }, + nestedField: { label: 'nestedField', formatter: () => 'null' }, + }; + + it('returns formatted filter view with any passed keys', () => { + const formatFn = formatFilterView(simpleFilterValue); + expect(formatFn(simpleFlattenFilterView)).toEqual({ + type: { label: 'label', formattedValue: simpleFilterValue.type }, + value: { label: 'value', formattedValue: simpleFilterValue.value }, + column: { label: 'column', formattedValue: simpleFilterValue.column }, + filterGroup: { label: 'filterGroup', formattedValue: simpleFilterValue.filterGroup }, + nestedField: { label: 'nestedField', formattedValue: 'null' }, + }); + }); + + it("returns formatted filter view with formattedValue = '-' ", () => { + const formatFn = formatFilterView({} as any); + expect(formatFn(simpleFlattenFilterView)).toEqual({ + type: { label: 'label', formattedValue: '-' }, + value: { label: 'value', formattedValue: '-' }, + column: { label: 'column', formattedValue: '-' }, + filterGroup: { label: 'filterGroup', formattedValue: '-' }, + nestedField: { label: 'nestedField', formattedValue: 'null' }, + }); + }); + + it('returns emtpy object when filter view is empty object', () => { + const formatFn = formatFilterView(simpleFilterValue); + expect(formatFn({} as any)).toEqual({}); + }); + + it('returns filter view fields with component property if defined at filter view', () => { + const flattenFilterViewWithComponent: FlattenFilterViewInstance = { + ...simpleFlattenFilterView, + nestedField: { + ...simpleFlattenFilterView.nestedField, + component: fc, + }, + }; + + const formatFn = formatFilterView(simpleFilterValue); + expect(formatFn(flattenFilterViewWithComponent)).toEqual({ + type: { label: 'label', formattedValue: simpleFilterValue.type }, + value: { label: 'value', formattedValue: simpleFilterValue.value }, + column: { label: 'column', formattedValue: simpleFilterValue.column }, + filterGroup: { label: 'filterGroup', formattedValue: simpleFilterValue.filterGroup }, + nestedField: { label: 'nestedField', formattedValue: 'null', component: fc }, + }); + }); +}); + +describe('createFilledFilterView', () => { + it('returns simple filter view with formattedValue and components', () => { + const simpleFilterValueWithComponent = { + ...simpleFilterView, + value: { + ...(simpleFilterView.value as SimpleFilterViewField), + component: fc, + }, + }; + + expect(createFilledFilterView(simpleFilterValueWithComponent, simpleFilterValue)).toEqual({ + type: { label: 'label', formattedValue: simpleFilterValue.type }, + value: { label: 'value', formattedValue: simpleFilterValue.value, component: fc }, + column: { label: 'column', formattedValue: simpleFilterValue.column }, + filterGroup: { label: 'filterGroup', formattedValue: simpleFilterValue.filterGroup }, + }); + }); + + it('returns nested filter view with formattedValue and components', () => { + const nestedFilterViewWithComponent = { + ...nestedFilterView, + value: (value: unknown) => ({ + nested: { + label: 'nested', + formatter: formatterFactory(value), + component: fc, + }, + }), + }; + + expect(createFilledFilterView(nestedFilterViewWithComponent, filterWithNestedValue)).toEqual({ + type: { label: 'label', formattedValue: filterWithNestedValue.type }, + column: { label: 'column', formattedValue: filterWithNestedValue.column }, + filterGroup: { label: 'filterGroup', formattedValue: filterWithNestedValue.filterGroup }, + nested: { + label: 'nested', + formattedValue: formatterFactory(filterWithNestedValue.value)(), + component: fc, + }, + }); + }); +}); + +describe('groupFiltersBy', () => { + const filters: FilterType[] = [ + { type: 'exactly', column: 'project', value: 'kibana', filterGroup: 'someGroup' }, + { + type: 'time', + column: '@timestamp', + value: { from: 'some time', to: 'some time' }, + filterGroup: 'someGroup2', + }, + { type: 'exactly', column: 'country', value: 'US', filterGroup: 'someGroup2' }, + { + type: 'time', + column: 'time', + value: { from: 'some time', to: 'some time' }, + filterGroup: null, + }, + ]; + + it('groups by type', () => { + const grouped = groupFiltersBy(filters, 'type'); + expect(grouped).toEqual([ + { name: 'exactly', filters: [filters[0], filters[2]] }, + { name: 'time', filters: [filters[1], filters[3]] }, + ]); + }); + + it('groups by column', () => { + const grouped = groupFiltersBy(filters, 'column'); + expect(grouped).toEqual([ + { name: 'project', filters: [filters[0]] }, + { name: '@timestamp', filters: [filters[1]] }, + { name: 'country', filters: [filters[2]] }, + { name: 'time', filters: [filters[3]] }, + ]); + }); + + it('groups by filterGroup', () => { + const grouped = groupFiltersBy(filters, 'filterGroup'); + expect(grouped).toEqual([ + { name: 'someGroup', filters: [filters[0]] }, + { name: 'someGroup2', filters: [filters[1], filters[2]] }, + { name: null, filters: [filters[3]] }, + ]); + }); + + it('groups by field on empty array', () => { + const grouped = groupFiltersBy([], 'filterGroup'); + expect(grouped).toEqual([]); + }); + + it('groups by empty field', () => { + const filtersWithoutGroups = filters.map(({ filterGroup, ...rest }) => ({ + ...rest, + filterGroup: null, + })); + + const grouped = groupFiltersBy(filtersWithoutGroups, 'filterGroup'); + expect(grouped).toEqual([{ name: null, filters: filtersWithoutGroups }]); + }); +}); diff --git a/x-pack/plugins/canvas/public/lib/filter.ts b/x-pack/plugins/canvas/public/lib/filter.ts new file mode 100644 index 0000000000000..ae75822e4a7c9 --- /dev/null +++ b/x-pack/plugins/canvas/public/lib/filter.ts @@ -0,0 +1,55 @@ +/* + * 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 { flowRight, groupBy } from 'lodash'; +import { + Filter as FilterType, + FilterField, + FilterViewInstance, + FlattenFilterViewInstance, +} from '../../types/filters'; + +export const defaultFormatter = (value: unknown) => (value || null ? `${value}` : '-'); + +export const formatFilterView = + (filterValue: FilterType) => (filterView: FlattenFilterViewInstance) => { + const filterViewKeys = Object.keys(filterView) as Array; + return filterViewKeys.reduce( + (acc, key) => ({ + ...acc, + [key]: { + label: filterView[key].label, + formattedValue: (filterView[key].formatter ?? defaultFormatter)(filterValue[key]), + component: filterView[key].component, + }, + }), + {} + ); + }; + +export const flattenFilterView = (filterValue: FilterType) => (filterView: FilterViewInstance) => { + const filterViewKeys = Object.keys(filterView) as Array; + return filterViewKeys.reduce((acc, key) => { + const filterField = filterView[key]; + if (typeof filterField === 'function') { + const val = filterField(filterValue[key]); + return { ...acc, ...val }; + } + return { ...acc, [key]: filterField }; + }, {}); +}; + +export const createFilledFilterView = (filterView: FilterViewInstance, filter: FilterType) => + flowRight(formatFilterView(filter), flattenFilterView(filter))(filterView); + +export const groupFiltersBy = (filters: FilterType[], groupByField: FilterField) => { + const groupedFilters = groupBy(filters, (filter) => filter[groupByField]); + return Object.keys(groupedFilters).map((key) => ({ + name: groupedFilters[key]?.[0]?.[groupByField] ? key : null, + filters: groupedFilters[key], + })); +}; diff --git a/x-pack/plugins/canvas/public/lib/filter_adapters.test.ts b/x-pack/plugins/canvas/public/lib/filter_adapters.test.ts new file mode 100644 index 0000000000000..5061e47a44347 --- /dev/null +++ b/x-pack/plugins/canvas/public/lib/filter_adapters.test.ts @@ -0,0 +1,59 @@ +/* + * 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 { ExpressionFunctionAST } from '@kbn/interpreter/common'; +import { adaptCanvasFilter } from './filter_adapters'; + +describe('adaptCanvasFilter', () => { + const filterAST: ExpressionFunctionAST = { + type: 'function', + function: 'exactly', + arguments: { + type: ['exactly'], + column: ['project'], + filterGroup: [], + value: ['kibana'], + }, + }; + + it('returns filter when AST arguments consists of arrays with one element', () => { + const resultFilter = { type: 'exactly', column: 'project', filterGroup: null, value: 'kibana' }; + + const filter = adaptCanvasFilter(filterAST); + expect(filter).toEqual(resultFilter); + }); + + it('returns filter with all additional fields stored on value field', () => { + const { value, ...rest } = filterAST.arguments; + const additionalArguments = { value1: ['value1'], value2: ['value2'] }; + const newFilterAST = { ...filterAST, arguments: { ...rest, ...additionalArguments } }; + + const resultFilter = { + type: 'exactly', + column: 'project', + filterGroup: null, + value: { value1: 'value1', value2: 'value2' }, + }; + + const filter = adaptCanvasFilter(newFilterAST); + expect(filter).toEqual(resultFilter); + }); + + it('returns filter if args are empty', () => { + const { arguments: args, ...rest } = filterAST; + + const resultFilter = { + type: 'exactly', + column: null, + filterGroup: null, + value: null, + }; + + const filter = adaptCanvasFilter({ ...rest, arguments: {} }); + expect(filter).toEqual(resultFilter); + }); +}); diff --git a/x-pack/plugins/canvas/public/lib/filter_adapters.ts b/x-pack/plugins/canvas/public/lib/filter_adapters.ts new file mode 100644 index 0000000000000..478b0a5302631 --- /dev/null +++ b/x-pack/plugins/canvas/public/lib/filter_adapters.ts @@ -0,0 +1,48 @@ +/* + * 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 { ExpressionFunctionAST } from '@kbn/interpreter/common'; +import { identity } from 'lodash'; +import { ExpressionAstArgument, Filter, FilterType } from '../../types'; + +const functionToFilter: Record = { + timefilter: FilterType.time, + exactly: FilterType.exactly, +}; + +const defaultFormatter = (arg: ExpressionAstArgument) => arg.toString(); + +const argToValue = ( + arg: ExpressionAstArgument[], + formatter: (arg: ExpressionAstArgument) => string | null = defaultFormatter +) => (arg?.[0] ? formatter(arg[0]) : null); + +const convertFunctionToFilterType = (func: string) => functionToFilter[func] ?? FilterType.exactly; + +const collectArgs = (args: ExpressionFunctionAST['arguments']) => { + const argsKeys = Object.keys(args); + + if (!argsKeys.length) { + return null; + } + + return argsKeys.reduce>( + (acc, key) => ({ ...acc, [key]: argToValue(args[key], identity) }), + {} + ); +}; + +export function adaptCanvasFilter(filter: ExpressionFunctionAST): Filter { + const { function: type, arguments: args } = filter; + const { column, filterGroup, value: valueArg, type: typeArg, ...rest } = args ?? {}; + return { + type: convertFunctionToFilterType(type), + column: argToValue(column), + filterGroup: argToValue(filterGroup), + value: argToValue(valueArg) ?? collectArgs(rest), + }; +} diff --git a/x-pack/plugins/canvas/public/state/actions/sidebar.ts b/x-pack/plugins/canvas/public/state/actions/sidebar.ts new file mode 100644 index 0000000000000..309cb43fcd936 --- /dev/null +++ b/x-pack/plugins/canvas/public/state/actions/sidebar.ts @@ -0,0 +1,16 @@ +/* + * 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 { createAction } from 'redux-actions'; +import { FilterField } from '../../../types'; + +export type SetGroupFiltersByOptionPayload = FilterField; +export const SetGroupFiltersByOptionType = 'setGroupFiltersByOption'; + +export const setGroupFiltersByOption = createAction( + SetGroupFiltersByOptionType +); diff --git a/x-pack/plugins/canvas/public/state/defaults.js b/x-pack/plugins/canvas/public/state/defaults.js index a245d515a32d9..40e8425c98ff0 100644 --- a/x-pack/plugins/canvas/public/state/defaults.js +++ b/x-pack/plugins/canvas/public/state/defaults.js @@ -6,7 +6,7 @@ */ import { getId } from '../lib/get_id'; -import { DEFAULT_WORKPAD_CSS } from '../../common/lib/constants'; +import { DEFAULT_WORKPAD_CSS, DEFAULT_GROUP_BY_FIELD } from '../../common/lib/constants'; export const getDefaultElement = () => { return { @@ -86,3 +86,7 @@ export const getDefaultWorkpad = () => { isWriteable: true, }; }; + +export const getDefaultSidebar = () => ({ + groupFiltersByOption: DEFAULT_GROUP_BY_FIELD, +}); diff --git a/x-pack/plugins/canvas/public/state/initial_state.js b/x-pack/plugins/canvas/public/state/initial_state.js index c652cc573abe9..d676b27c7a906 100644 --- a/x-pack/plugins/canvas/public/state/initial_state.js +++ b/x-pack/plugins/canvas/public/state/initial_state.js @@ -7,7 +7,7 @@ import { get } from 'lodash'; import { pluginServices } from '../services'; -import { getDefaultWorkpad } from './defaults'; +import { getDefaultWorkpad, getDefaultSidebar } from './defaults'; export const getInitialState = (path) => { const platformService = pluginServices.getServices().platform; @@ -40,6 +40,7 @@ export const getInitialState = (path) => { // In there will live an object with a status (string), value (any), and error (Error) property. // If the state is 'error', the error property will be the error object, the value will not change // See the resolved_args reducer for more information. + sidebar: getDefaultSidebar(), }, persistent: { schemaVersion: 2, diff --git a/x-pack/plugins/canvas/public/state/reducers/index.js b/x-pack/plugins/canvas/public/state/reducers/index.js index 5a901fc3bb294..a07de70d9a005 100644 --- a/x-pack/plugins/canvas/public/state/reducers/index.js +++ b/x-pack/plugins/canvas/public/state/reducers/index.js @@ -18,12 +18,13 @@ import { elementsReducer } from './elements'; import { assetsReducer } from './assets'; import { historyReducer } from './history'; import { embeddableReducer } from './embeddable'; +import { sidebarReducer } from './sidebar'; export function getRootReducer(initialState) { return combineReducers({ assets: assetsReducer, app: appReducer, - transient: reduceReducers(transientReducer, resolvedArgsReducer), + transient: reduceReducers(transientReducer, resolvedArgsReducer, sidebarReducer), persistent: reduceReducers( historyReducer, combineReducers({ diff --git a/x-pack/plugins/canvas/public/state/reducers/sidebar.ts b/x-pack/plugins/canvas/public/state/reducers/sidebar.ts new file mode 100644 index 0000000000000..55697b17c09e0 --- /dev/null +++ b/x-pack/plugins/canvas/public/state/reducers/sidebar.ts @@ -0,0 +1,22 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { handleActions } from 'redux-actions'; +import { State } from '../../../types'; +import { SetGroupFiltersByOptionType, SetGroupFiltersByOptionPayload } from '../actions/sidebar'; + +export const sidebarReducer = handleActions( + { + [SetGroupFiltersByOptionType]: (transientState, { payload }) => { + return { + ...transientState, + sidebar: { ...transientState.sidebar, groupFiltersByOption: payload }, + }; + }, + }, + {} as State['transient'] +); diff --git a/x-pack/plugins/canvas/public/state/selectors/sidebar.ts b/x-pack/plugins/canvas/public/state/selectors/sidebar.ts new file mode 100644 index 0000000000000..637264a200b9a --- /dev/null +++ b/x-pack/plugins/canvas/public/state/selectors/sidebar.ts @@ -0,0 +1,13 @@ +/* + * 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 { DEFAULT_GROUP_BY_FIELD } from '../../../common/lib'; +import { FilterField, State } from '../../../types'; + +export const getGroupFiltersByOption = (state: State): FilterField => { + return state.transient.sidebar.groupFiltersByOption ?? DEFAULT_GROUP_BY_FIELD; +}; diff --git a/x-pack/plugins/canvas/types/canvas.ts b/x-pack/plugins/canvas/types/canvas.ts index 0868054d0a489..efb121b2948af 100644 --- a/x-pack/plugins/canvas/types/canvas.ts +++ b/x-pack/plugins/canvas/types/canvas.ts @@ -6,6 +6,7 @@ */ import { ElementPosition } from './elements'; +import { FilterField } from './filters'; export interface CanvasAsset { '@created': string; @@ -44,6 +45,10 @@ export interface CanvasVariable { type: 'boolean' | 'number' | 'string'; } +export interface Sidebar { + groupFiltersByOption?: FilterField; +} + export interface CanvasWorkpad { '@created': string; '@timestamp': string; diff --git a/x-pack/plugins/canvas/types/filters.ts b/x-pack/plugins/canvas/types/filters.ts index 942e4259d780e..8529b37e40b1b 100644 --- a/x-pack/plugins/canvas/types/filters.ts +++ b/x-pack/plugins/canvas/types/filters.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { FC } from 'react'; import { ExpressionValueFilter } from '.'; export enum FilterType { @@ -31,3 +32,41 @@ export type CanvasExactlyFilter = ExpressionValueFilter & { }; export type CanvasFilter = CanvasTimeFilter | CanvasExactlyFilter | CanvasLuceneFilter; + +export interface Filter { + type: keyof typeof FilterType; + column: string | null; + value: unknown; + filterGroup: string | null; +} + +export type ComplexFilterViewField = ( + value: FilterValue +) => Record; + +export interface SimpleFilterViewField { + label: string; + formatter?: (value?: unknown) => string | null; + component?: FC; +} + +export interface FormattedFilterViewField { + label: string; + formattedValue: string; + component?: FC; +} + +export type FilterViewInstance = Record< + keyof Filter, + SimpleFilterViewField | ComplexFilterViewField +>; + +export interface FilterViewSpec { + name: string; + view: FilterViewInstance; +} + +export type FlattenFilterViewInstance = Record; +export type FormattedFilterViewInstance = Record; + +export type FilterField = 'column' | 'type' | 'filterGroup'; diff --git a/x-pack/plugins/canvas/types/state.ts b/x-pack/plugins/canvas/types/state.ts index a3c770f12f225..b283de1386f55 100644 --- a/x-pack/plugins/canvas/types/state.ts +++ b/x-pack/plugins/canvas/types/state.ts @@ -18,7 +18,7 @@ import { } from 'src/plugins/expressions'; import { Datasource, Model, Transform, View } from '../public/expression_types'; import { AssetType } from './assets'; -import { CanvasWorkpad } from './canvas'; +import { CanvasWorkpad, Sidebar } from './canvas'; export enum AppStateKeys { FULLSCREEN = '__fullscreen', @@ -75,7 +75,7 @@ export interface ResolvedArgType { expressionContext: ExpressionContext; } -interface TransientState { +export interface TransientState { canUserWrite: boolean; zoomScale: number; elementStats: ElementStatsType; @@ -90,6 +90,7 @@ interface TransientState { interval: number; }; inFlight: boolean; + sidebar: Sidebar; } interface PersistentState { diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 1a5335ef93e72..af76ea0e98276 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -8115,7 +8115,6 @@ "xpack.canvas.workpadConfig.pageSizeBadgeOnClickAriaLabel": "ページサイズを {sizeName} に設定", "xpack.canvas.workpadConfig.swapDimensionsAriaLabel": "ページの幅と高さを入れ替えます", "xpack.canvas.workpadConfig.swapDimensionsTooltip": "ページの幅と高さを入れ替える", - "xpack.canvas.workpadConfig.title": "ワークパッドの設定", "xpack.canvas.workpadConfig.USLetterButtonLabel": "US レター", "xpack.canvas.workpadConfig.widthLabel": "幅", "xpack.canvas.workpadCreate.createButtonLabel": "ワークパッドを作成", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 529b692e3552e..91513909af9c7 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -8178,7 +8178,6 @@ "xpack.canvas.workpadConfig.pageSizeBadgeOnClickAriaLabel": "将页面大小设置为 {sizeName}", "xpack.canvas.workpadConfig.swapDimensionsAriaLabel": "交换页面的宽和高", "xpack.canvas.workpadConfig.swapDimensionsTooltip": "交换宽高", - "xpack.canvas.workpadConfig.title": "Workpad 设置", "xpack.canvas.workpadConfig.USLetterButtonLabel": "美国信函", "xpack.canvas.workpadConfig.widthLabel": "宽", "xpack.canvas.workpadCreate.createButtonLabel": "创建 Workpad", From 8a16b849f26653ef7958f86f8d16e5047fe4fc5f Mon Sep 17 00:00:00 2001 From: Mikhail Shustov Date: Thu, 18 Nov 2021 09:30:36 +0100 Subject: [PATCH 101/148] Don't enable RUM agent if APM is run with contextPropagationOnly (#118685) * do not enable RUM agent when nodejs is run in contextPropagationOnly mode * move shouldInstrumentClient to apm-config package --- packages/kbn-apm-config-loader/src/index.ts | 1 + .../src/rum_agent_configuration.test.ts | 27 +++++++++++++++++++ .../src/rum_agent_configuration.ts | 14 ++++++++++ .../get_apm_config.test.mocks.ts | 2 ++ .../http_resources/get_apm_config.test.ts | 14 +++++----- .../server/http_resources/get_apm_config.ts | 4 +-- 6 files changed, 53 insertions(+), 9 deletions(-) create mode 100644 packages/kbn-apm-config-loader/src/rum_agent_configuration.test.ts create mode 100644 packages/kbn-apm-config-loader/src/rum_agent_configuration.ts diff --git a/packages/kbn-apm-config-loader/src/index.ts b/packages/kbn-apm-config-loader/src/index.ts index b16f6dcfd418f..381eb895b7eec 100644 --- a/packages/kbn-apm-config-loader/src/index.ts +++ b/packages/kbn-apm-config-loader/src/index.ts @@ -8,4 +8,5 @@ export { getConfiguration } from './config_loader'; export { initApm } from './init_apm'; +export { shouldInstrumentClient } from './rum_agent_configuration'; export type { ApmConfiguration } from './config'; diff --git a/packages/kbn-apm-config-loader/src/rum_agent_configuration.test.ts b/packages/kbn-apm-config-loader/src/rum_agent_configuration.test.ts new file mode 100644 index 0000000000000..be4619578b5a4 --- /dev/null +++ b/packages/kbn-apm-config-loader/src/rum_agent_configuration.test.ts @@ -0,0 +1,27 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ +import { shouldInstrumentClient } from './rum_agent_configuration'; +describe('shouldInstrumentClient', () => { + it('returns false if apm is disabled', () => { + expect(shouldInstrumentClient({ active: false })).toBe(false); + }); + + it('returns false if apm is enabled with contextPropagationOnly: true', () => { + expect(shouldInstrumentClient({ active: true, contextPropagationOnly: true })).toBe(false); + }); + + it('returns false if apm is enabled with disableSend: true', () => { + expect(shouldInstrumentClient({ active: true, disableSend: true })).toBe(false); + }); + + it('returns true if apm is enabled', () => { + expect(shouldInstrumentClient({ active: true })).toBe(true); + expect(shouldInstrumentClient({ active: true, contextPropagationOnly: false })).toBe(true); + expect(shouldInstrumentClient({ active: true, disableSend: false })).toBe(true); + }); +}); diff --git a/packages/kbn-apm-config-loader/src/rum_agent_configuration.ts b/packages/kbn-apm-config-loader/src/rum_agent_configuration.ts new file mode 100644 index 0000000000000..5a73c95e21135 --- /dev/null +++ b/packages/kbn-apm-config-loader/src/rum_agent_configuration.ts @@ -0,0 +1,14 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ +import type { AgentConfigOptions } from 'elastic-apm-node'; + +export function shouldInstrumentClient(config?: AgentConfigOptions): boolean { + return Boolean( + config?.active === true && config.contextPropagationOnly !== true && config.disableSend !== true + ); +} diff --git a/src/core/server/http_resources/get_apm_config.test.mocks.ts b/src/core/server/http_resources/get_apm_config.test.mocks.ts index 8c3fa180a04f0..03d1a2575ba53 100644 --- a/src/core/server/http_resources/get_apm_config.test.mocks.ts +++ b/src/core/server/http_resources/get_apm_config.test.mocks.ts @@ -7,8 +7,10 @@ */ export const getConfigurationMock = jest.fn(); +export const shouldInstrumentClientMock = jest.fn(() => true); jest.doMock('@kbn/apm-config-loader', () => ({ getConfiguration: getConfigurationMock, + shouldInstrumentClient: shouldInstrumentClientMock, })); export const agentMock = {} as Record; diff --git a/src/core/server/http_resources/get_apm_config.test.ts b/src/core/server/http_resources/get_apm_config.test.ts index bd867375f46d6..9552a91da97b1 100644 --- a/src/core/server/http_resources/get_apm_config.test.ts +++ b/src/core/server/http_resources/get_apm_config.test.ts @@ -6,7 +6,11 @@ * Side Public License, v 1. */ -import { getConfigurationMock, agentMock } from './get_apm_config.test.mocks'; +import { + getConfigurationMock, + agentMock, + shouldInstrumentClientMock, +} from './get_apm_config.test.mocks'; import { getApmConfig } from './get_apm_config'; const defaultApmConfig = { @@ -17,6 +21,7 @@ const defaultApmConfig = { describe('getApmConfig', () => { beforeEach(() => { getConfigurationMock.mockReturnValue(defaultApmConfig); + shouldInstrumentClientMock.mockReturnValue(true); }); afterEach(() => { @@ -25,12 +30,7 @@ describe('getApmConfig', () => { }); it('returns null if apm is disabled', () => { - getConfigurationMock.mockReturnValue({ - active: false, - }); - expect(getApmConfig('/path')).toBeNull(); - - getConfigurationMock.mockReturnValue(undefined); + shouldInstrumentClientMock.mockReturnValue(false); expect(getApmConfig('/path')).toBeNull(); }); diff --git a/src/core/server/http_resources/get_apm_config.ts b/src/core/server/http_resources/get_apm_config.ts index 6ea172b162d28..3e7be65f96652 100644 --- a/src/core/server/http_resources/get_apm_config.ts +++ b/src/core/server/http_resources/get_apm_config.ts @@ -7,11 +7,11 @@ */ import agent from 'elastic-apm-node'; -import { getConfiguration } from '@kbn/apm-config-loader'; +import { getConfiguration, shouldInstrumentClient } from '@kbn/apm-config-loader'; export const getApmConfig = (requestPath: string) => { const baseConfig = getConfiguration('kibana-frontend'); - if (!baseConfig?.active) { + if (!shouldInstrumentClient(baseConfig)) { return null; } From e4621fddf92cfde2fe065ae4789db5241edf438c Mon Sep 17 00:00:00 2001 From: vladpro25 <91911546+vladpro25@users.noreply.github.com> Date: Thu, 18 Nov 2021 10:32:00 +0200 Subject: [PATCH 102/148] [Console] Add overrides for request parameters for Logstash PUT Pipeline API (#116450) * Autostuggestion for geo_* added... * Autostuggestion for geo_* added * Add overrides for request parameters for Logstash PUT Pipeline API * Add overrides for request parameters for Logstash PUT Pipeline API * Add overrides for request parameters for Logstash PUT Pipeline API * Add overrides for request parameters for Logstash PUT Pipeline API Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../json/overrides/logstash.put_pipeline.json | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 src/plugins/console/server/lib/spec_definitions/json/overrides/logstash.put_pipeline.json diff --git a/src/plugins/console/server/lib/spec_definitions/json/overrides/logstash.put_pipeline.json b/src/plugins/console/server/lib/spec_definitions/json/overrides/logstash.put_pipeline.json new file mode 100644 index 0000000000000..224def4d5bf13 --- /dev/null +++ b/src/plugins/console/server/lib/spec_definitions/json/overrides/logstash.put_pipeline.json @@ -0,0 +1,66 @@ +{ + "logstash.put_pipeline": { + "data_autocomplete_rules": { + "__template": { + "last_modified": "", + "pipeline": "", + "pipeline_metadata": {}, + "pipeline_settings": {}, + "username": "" + }, + "last_modified": "", + "pipeline_metadata": {}, + "username": "", + "pipeline": "", + "pipeline_settings": { + "pipeline.id": "main", + "pipeline.workers": 0, + "pipeline.batch.size": 125, + "pipeline.batch.delay": 50, + "pipeline.unsafe_shutdown": false, + "pipeline.plugin_classloaders": false, + "pipeline.ordered": "auto", + "pipeline.ecs_compatibility": "disabled", + "pipeline.separate_logs": false, + "queue.type": "memory", + "queue.page_capacity": "64mb", + "queue.max_events": 0, + "queue.max_bytes": "1024mb", + "queue.checkpoint.acks": 1024, + "queue.checkpoint.writes": 1024, + "queue.checkpoint.retry": false, + "queue.max_bytes.number": 0, + "queue.max_bytes.units": "", + "queue.drain": false, + "api.enabled": true, + "api.environment": "production", + "api.http.host": "127.0.0.1", + "api.http.port": "9600-9700", + "api.ssl.enabled": false, + "api.ssl.keystore.path": "", + "api.ssl.keystore.password": "", + "api.auth.type": "none", + "api.auth.basic.username": "", + "api.auth.basic.password": "", + "log.level": "info", + "log.format": "plain", + "path.logs": "LOGSTASH_HOME/logs", + "path.plugins": "PATH/logstash/TYPE/NAME.rb", + "path.queue": "path.data/queue", + "path.data": "LOGSTASH_HOME/data", + "path.config": "/usr/share/logstash/pipeline", + "path.dead_letter_queue": "path.data/dead_letter_queue", + "dead_letter_queue.max_bytes": "1024mb", + "dead_letter_queue.enable": false, + "config.support_escapes": false, + "config.debug": false, + "config.reload.interval": "3s", + "config.reload.automatic": false, + "config.test_and_exit": false, + "config.string": "", + "node.name": "" + }, + "description": "" + } + } +} \ No newline at end of file From 3ec4503be704b60f8c8335b1fce53016e815ae39 Mon Sep 17 00:00:00 2001 From: Pierre Gayvallet Date: Thu, 18 Nov 2021 09:36:24 +0100 Subject: [PATCH 103/148] add `theme$` to `ManagementAppMountParams` (#118852) * add `theme$` to `ManagementAppMountParams` * fix tests * fix more test usages Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- src/plugins/management/public/application.tsx | 9 +++++++-- .../components/management_app/management_app.tsx | 4 +++- .../components/management_app/management_router.tsx | 11 ++++++++++- .../management_app_wrapper/management_app_wrapper.tsx | 4 +++- src/plugins/management/public/types.ts | 4 +++- .../api_keys/api_keys_management_app.test.tsx | 3 ++- .../role_mappings_management_app.test.tsx | 3 ++- .../management/roles/roles_management_app.test.tsx | 3 ++- .../management/users/users_management_app.test.tsx | 3 ++- .../public/management/spaces_management_app.test.tsx | 3 ++- 10 files changed, 36 insertions(+), 11 deletions(-) diff --git a/src/plugins/management/public/application.tsx b/src/plugins/management/public/application.tsx index 8e3e7da41c394..3e2c4f7c04e40 100644 --- a/src/plugins/management/public/application.tsx +++ b/src/plugins/management/public/application.tsx @@ -13,11 +13,16 @@ import { AppMountParameters } from 'kibana/public'; import { ManagementApp, ManagementAppDependencies } from './components/management_app'; export const renderApp = async ( - { history, appBasePath, element }: AppMountParameters, + { history, appBasePath, element, theme$ }: AppMountParameters, dependencies: ManagementAppDependencies ) => { ReactDOM.render( - , + , element ); diff --git a/src/plugins/management/public/components/management_app/management_app.tsx b/src/plugins/management/public/components/management_app/management_app.tsx index 23d0a29083747..ac9739cc54578 100644 --- a/src/plugins/management/public/components/management_app/management_app.tsx +++ b/src/plugins/management/public/components/management_app/management_app.tsx @@ -25,6 +25,7 @@ import { SectionsServiceStart } from '../../types'; interface ManagementAppProps { appBasePath: string; history: AppMountParameters['history']; + theme$: AppMountParameters['theme$']; dependencies: ManagementAppDependencies; } @@ -34,7 +35,7 @@ export interface ManagementAppDependencies { setBreadcrumbs: (newBreadcrumbs: ChromeBreadcrumb[]) => void; } -export const ManagementApp = ({ dependencies, history }: ManagementAppProps) => { +export const ManagementApp = ({ dependencies, history, theme$ }: ManagementAppProps) => { const { setBreadcrumbs } = dependencies; const [selectedId, setSelectedId] = useState(''); const [sections, setSections] = useState(); @@ -93,6 +94,7 @@ export const ManagementApp = ({ dependencies, history }: ManagementAppProps) => > void; onAppMounted: (id: string) => void; @@ -23,7 +24,14 @@ interface ManagementRouterProps { } export const ManagementRouter = memo( - ({ dependencies, history, setBreadcrumbs, onAppMounted, sections }: ManagementRouterProps) => ( + ({ + dependencies, + history, + setBreadcrumbs, + onAppMounted, + sections, + theme$, + }: ManagementRouterProps) => ( {sections.map((section) => @@ -38,6 +46,7 @@ export const ManagementRouter = memo( setBreadcrumbs={setBreadcrumbs} onAppMounted={onAppMounted} history={history} + theme$={theme$} /> )} /> diff --git a/src/plugins/management/public/components/management_app_wrapper/management_app_wrapper.tsx b/src/plugins/management/public/components/management_app_wrapper/management_app_wrapper.tsx index 72bfe609c141a..57de84ec5aec6 100644 --- a/src/plugins/management/public/components/management_app_wrapper/management_app_wrapper.tsx +++ b/src/plugins/management/public/components/management_app_wrapper/management_app_wrapper.tsx @@ -19,6 +19,7 @@ interface ManagementSectionWrapperProps { setBreadcrumbs: (crumbs?: ChromeBreadcrumb[], history?: ScopedHistory) => void; onAppMounted: (id: string) => void; history: AppMountParameters['history']; + theme$: AppMountParameters['theme$']; } export class ManagementAppWrapper extends Component { @@ -26,7 +27,7 @@ export class ManagementAppWrapper extends Component(); componentDidMount() { - const { setBreadcrumbs, app, onAppMounted, history } = this.props; + const { setBreadcrumbs, app, onAppMounted, history, theme$ } = this.props; const { mount, basePath } = app; const appHistory = history.createSubHistory(app.basePath); @@ -35,6 +36,7 @@ export class ManagementAppWrapper extends Component setBreadcrumbs(crumbs, appHistory), element: this.mountElementRef.current!, history: appHistory, + theme$, }); onAppMounted(app.id); diff --git a/src/plugins/management/public/types.ts b/src/plugins/management/public/types.ts index 6a165c812b474..87b336928db91 100644 --- a/src/plugins/management/public/types.ts +++ b/src/plugins/management/public/types.ts @@ -6,10 +6,11 @@ * Side Public License, v 1. */ +import { Observable } from 'rxjs'; import { ScopedHistory, Capabilities } from 'kibana/public'; import type { LocatorPublic } from 'src/plugins/share/common'; import { ManagementSection, RegisterManagementSectionArgs } from './utils'; -import { ChromeBreadcrumb } from '../../../core/public/'; +import { ChromeBreadcrumb, CoreTheme } from '../../../core/public/'; import type { ManagementAppLocatorParams } from '../common/locator'; export interface ManagementSetup { @@ -63,6 +64,7 @@ export interface ManagementAppMountParams { element: HTMLElement; // element the section should render into setBreadcrumbs: (crumbs: ChromeBreadcrumb[]) => void; history: ScopedHistory; + theme$: Observable; } export interface CreateManagementItemArgs { diff --git a/x-pack/plugins/security/public/management/api_keys/api_keys_management_app.test.tsx b/x-pack/plugins/security/public/management/api_keys/api_keys_management_app.test.tsx index 922fd59c56d1b..83fe807f9a3c6 100644 --- a/x-pack/plugins/security/public/management/api_keys/api_keys_management_app.test.tsx +++ b/x-pack/plugins/security/public/management/api_keys/api_keys_management_app.test.tsx @@ -11,7 +11,7 @@ jest.mock('./api_keys_grid', () => ({ import { act } from '@testing-library/react'; -import { coreMock, scopedHistoryMock } from 'src/core/public/mocks'; +import { coreMock, scopedHistoryMock, themeServiceMock } from 'src/core/public/mocks'; import type { Unmount } from 'src/plugins/management/public/types'; import { securityMock } from '../../mocks'; @@ -52,6 +52,7 @@ describe('apiKeysManagementApp', () => { element: container, setBreadcrumbs, history: scopedHistoryMock.create(), + theme$: themeServiceMock.createTheme$(), }); }); diff --git a/x-pack/plugins/security/public/management/role_mappings/role_mappings_management_app.test.tsx b/x-pack/plugins/security/public/management/role_mappings/role_mappings_management_app.test.tsx index 892c7940675d3..3b7e96ffabd1e 100644 --- a/x-pack/plugins/security/public/management/role_mappings/role_mappings_management_app.test.tsx +++ b/x-pack/plugins/security/public/management/role_mappings/role_mappings_management_app.test.tsx @@ -8,7 +8,7 @@ import { act } from '@testing-library/react'; import { noop } from 'lodash'; -import { coreMock, scopedHistoryMock } from 'src/core/public/mocks'; +import { coreMock, scopedHistoryMock, themeServiceMock } from 'src/core/public/mocks'; import type { Unmount } from 'src/plugins/management/public/types'; import { roleMappingsManagementApp } from './role_mappings_management_app'; @@ -46,6 +46,7 @@ async function mountApp(basePath: string, pathname: string) { element: container, setBreadcrumbs, history: scopedHistoryMock.create({ pathname }), + theme$: themeServiceMock.createTheme$(), }); }); diff --git a/x-pack/plugins/security/public/management/roles/roles_management_app.test.tsx b/x-pack/plugins/security/public/management/roles/roles_management_app.test.tsx index faab47a858d67..007c3e306372e 100644 --- a/x-pack/plugins/security/public/management/roles/roles_management_app.test.tsx +++ b/x-pack/plugins/security/public/management/roles/roles_management_app.test.tsx @@ -8,7 +8,7 @@ import { act } from '@testing-library/react'; import { noop } from 'lodash'; -import { coreMock, scopedHistoryMock } from 'src/core/public/mocks'; +import { coreMock, scopedHistoryMock, themeServiceMock } from 'src/core/public/mocks'; import type { Unmount } from 'src/plugins/management/public/types'; import { featuresPluginMock } from '../../../../features/public/mocks'; @@ -48,6 +48,7 @@ async function mountApp(basePath: string, pathname: string) { element: container, setBreadcrumbs, history: scopedHistoryMock.create({ pathname }), + theme$: themeServiceMock.createTheme$(), }); }); diff --git a/x-pack/plugins/security/public/management/users/users_management_app.test.tsx b/x-pack/plugins/security/public/management/users/users_management_app.test.tsx index f25fb211cb9de..84a6e82bf12ae 100644 --- a/x-pack/plugins/security/public/management/users/users_management_app.test.tsx +++ b/x-pack/plugins/security/public/management/users/users_management_app.test.tsx @@ -8,7 +8,7 @@ import { act } from '@testing-library/react'; import { noop } from 'lodash'; -import { coreMock, scopedHistoryMock } from 'src/core/public/mocks'; +import { coreMock, scopedHistoryMock, themeServiceMock } from 'src/core/public/mocks'; import type { Unmount } from 'src/plugins/management/public/types'; import { securityMock } from '../../mocks'; @@ -33,6 +33,7 @@ describe('usersManagementApp', () => { element, setBreadcrumbs, history, + theme$: themeServiceMock.createTheme$(), }); }); diff --git a/x-pack/plugins/spaces/public/management/spaces_management_app.test.tsx b/x-pack/plugins/spaces/public/management/spaces_management_app.test.tsx index aefff7fb3c76a..2c64f559602cc 100644 --- a/x-pack/plugins/spaces/public/management/spaces_management_app.test.tsx +++ b/x-pack/plugins/spaces/public/management/spaces_management_app.test.tsx @@ -18,7 +18,7 @@ jest.mock('./edit_space', () => ({ }, })); -import { coreMock, scopedHistoryMock } from 'src/core/public/mocks'; +import { coreMock, scopedHistoryMock, themeServiceMock } from 'src/core/public/mocks'; import { featuresPluginMock } from '../../../features/public/mocks'; import type { PluginsStart } from '../plugin'; @@ -51,6 +51,7 @@ async function mountApp(basePath: string, pathname: string, spaceId?: string) { element: container, setBreadcrumbs, history: scopedHistoryMock.create({ pathname }), + theme$: themeServiceMock.createTheme$(), }); return { unmount, container, setBreadcrumbs, docTitle: coreStart.chrome.docTitle }; From 279d093277d0fbd37aedd6b26d2a72fb7d4b2268 Mon Sep 17 00:00:00 2001 From: Lisa Cawley Date: Thu, 18 Nov 2021 00:36:46 -0800 Subject: [PATCH 104/148] Fixes index pattern link in doc link service (#118748) --- src/core/public/doc_links/doc_links_service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/public/doc_links/doc_links_service.ts b/src/core/public/doc_links/doc_links_service.ts index a9330ce499cac..6b6ceeddee68e 100644 --- a/src/core/public/doc_links/doc_links_service.ts +++ b/src/core/public/doc_links/doc_links_service.ts @@ -156,7 +156,7 @@ export class DocLinksService { luceneExpressions: `${ELASTICSEARCH_DOCS}modules-scripting-expression.html`, }, indexPatterns: { - introduction: `${KIBANA_DOCS}index-patterns.html`, + introduction: `${KIBANA_DOCS}data-views.html`, fieldFormattersNumber: `${KIBANA_DOCS}numeral.html`, fieldFormattersString: `${KIBANA_DOCS}field-formatters-string.html`, runtimeFields: `${KIBANA_DOCS}managing-data-views.html#runtime-fields`, From b68e8c9e4a5d563df9959c2347ba79ec956593b0 Mon Sep 17 00:00:00 2001 From: Shahzad Date: Thu, 18 Nov 2021 10:53:47 +0100 Subject: [PATCH 105/148] [Exploratory view] Update discover dependency (#117500) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../build_filters/query_string_filter.ts | 1 + x-pack/plugins/observability/kibana.json | 1 + .../exploratory_view/configurations/utils.ts | 67 +++++++++++++++---- .../hooks/use_discover_link.tsx | 56 ++++++++-------- .../columns/report_definition_field.tsx | 4 +- .../series_editor/columns/series_actions.tsx | 7 +- 6 files changed, 93 insertions(+), 43 deletions(-) diff --git a/packages/kbn-es-query/src/filters/build_filters/query_string_filter.ts b/packages/kbn-es-query/src/filters/build_filters/query_string_filter.ts index a18347c77cfc9..69f10efd97d66 100644 --- a/packages/kbn-es-query/src/filters/build_filters/query_string_filter.ts +++ b/packages/kbn-es-query/src/filters/build_filters/query_string_filter.ts @@ -16,6 +16,7 @@ export type QueryStringFilter = Filter & { query?: { query_string?: { query: string; + fields?: string[]; }; }; }; diff --git a/x-pack/plugins/observability/kibana.json b/x-pack/plugins/observability/kibana.json index 822e0cf9efe7c..343e16f4a4095 100644 --- a/x-pack/plugins/observability/kibana.json +++ b/x-pack/plugins/observability/kibana.json @@ -11,6 +11,7 @@ "observability" ], "optionalPlugins": [ + "discover", "embeddable", "home", "lens", 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 index 56e6cb5210356..7eab266ea35d1 100644 --- 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 @@ -5,10 +5,15 @@ * 2.0. */ import rison, { RisonValue } from 'rison-node'; +import { buildQueryFilter } from '@kbn/es-query'; import type { ReportViewType, SeriesUrl, UrlFilter } from '../types'; import type { AllSeries, AllShortSeries } from '../hooks/use_series_storage'; import { IndexPattern } from '../../../../../../../../src/plugins/data/common'; -import { esFilters, ExistsFilter } from '../../../../../../../../src/plugins/data/public'; +import { + esFilters, + ExistsFilter, + PhraseFilter, +} from '../../../../../../../../src/plugins/data/public'; import { URL_KEYS } from './constants/url_constants'; import { PersistableFilter } from '../../../../../../lens/common'; @@ -64,9 +69,32 @@ export function buildPhraseFilter(field: string, value: string, indexPattern: In return []; } +export function getQueryFilter(field: string, value: string[], indexPattern: IndexPattern) { + const fieldMeta = indexPattern?.fields.find((fieldT) => fieldT.name === field); + if (fieldMeta && indexPattern.id) { + return value.map((val) => + buildQueryFilter( + { + query_string: { + fields: [field], + query: `*${val}*`, + }, + }, + indexPattern.id!, + '' + ) + ); + } + + return []; +} + export function buildPhrasesFilter(field: string, value: string[], indexPattern: IndexPattern) { const fieldMeta = indexPattern?.fields.find((fieldT) => fieldT.name === field); if (fieldMeta) { + if (value.length === 1) { + return [esFilters.buildPhraseFilter(fieldMeta, value[0], indexPattern)]; + } return [esFilters.buildPhrasesFilter(fieldMeta, value, indexPattern)]; } return []; @@ -80,7 +108,7 @@ export function buildExistsFilter(field: string, indexPattern: IndexPattern) { return []; } -type FiltersType = PersistableFilter[] | ExistsFilter[]; +type FiltersType = Array; export function urlFilterToPersistedFilter({ urlFilters, @@ -88,23 +116,36 @@ export function urlFilterToPersistedFilter({ indexPattern, }: { urlFilters: UrlFilter[]; - initFilters: FiltersType; + initFilters?: FiltersType; indexPattern: IndexPattern; }) { const parsedFilters: FiltersType = initFilters ? [...initFilters] : []; - urlFilters.forEach(({ field, values = [], notValues = [] }) => { - if (values?.length > 0) { - const filter = buildPhrasesFilter(field, values, indexPattern); - parsedFilters.push(...filter); - } + urlFilters.forEach( + ({ field, values = [], notValues = [], wildcards = [], notWildcards = ([] = []) }) => { + if (values.length > 0) { + const filter = buildPhrasesFilter(field, values, indexPattern); + parsedFilters.push(...filter); + } + + if (notValues.length > 0) { + const filter = buildPhrasesFilter(field, notValues, indexPattern)[0]; + filter.meta.negate = true; + parsedFilters.push(filter); + } - if (notValues?.length > 0) { - const filter = buildPhrasesFilter(field, notValues, indexPattern)[0]; - filter.meta.negate = true; - parsedFilters.push(filter); + if (wildcards.length > 0) { + const filter = getQueryFilter(field, wildcards, indexPattern); + parsedFilters.push(...filter); + } + + if (notWildcards.length > 0) { + const filter = getQueryFilter(field, notWildcards, indexPattern)[0]; + filter.meta.negate = true; + parsedFilters.push(filter); + } } - }); + ); return parsedFilters; } 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 index 4f19a8131f669..03396ffef9d8d 100644 --- 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 @@ -9,7 +9,7 @@ import { useCallback, useEffect, useState } from 'react'; import { useKibana } from '../../../../utils/kibana_react'; import { SeriesConfig, SeriesUrl } from '../types'; import { useAppIndexPatternContext } from './use_app_index_pattern'; -import { buildExistsFilter, buildPhraseFilter, buildPhrasesFilter } from '../configurations/utils'; +import { buildExistsFilter, urlFilterToPersistedFilter } from '../configurations/utils'; import { getFiltersFromDefs } from './use_lens_attributes'; import { RECORDS_FIELD, RECORDS_PERCENTAGE_FIELD } from '../configurations/constants'; @@ -32,42 +32,42 @@ export const useDiscoverLink = ({ series, seriesConfig }: UseDiscoverLink) => { useEffect(() => { const indexPattern = indexPatterns?.[series.dataType]; - const definitions = series.reportDefinitions ?? {}; - const filters = [...(seriesConfig?.baseFilters ?? [])]; + if (indexPattern) { + const definitions = series.reportDefinitions ?? {}; - const definitionFilters = getFiltersFromDefs(definitions); + const urlFilters = (series.filters ?? []).concat(getFiltersFromDefs(definitions)); - definitionFilters.forEach(({ field, values = [] }) => { - if (values.length > 1) { - filters.push(buildPhrasesFilter(field, values, indexPattern)[0]); - } else { - filters.push(buildPhraseFilter(field, values[0], indexPattern)[0]); - } - }); + const filters = urlFilterToPersistedFilter({ + indexPattern, + urlFilters, + initFilters: seriesConfig?.baseFilters, + }); - const selectedMetricField = series.selectedMetricField; + const selectedMetricField = series.selectedMetricField; - if ( - selectedMetricField && - selectedMetricField !== RECORDS_FIELD && - selectedMetricField !== RECORDS_PERCENTAGE_FIELD - ) { - filters.push(buildExistsFilter(selectedMetricField, indexPattern)[0]); - } + if ( + selectedMetricField && + selectedMetricField !== RECORDS_FIELD && + selectedMetricField !== RECORDS_PERCENTAGE_FIELD + ) { + filters.push(buildExistsFilter(selectedMetricField, indexPattern)[0]); + } - const getDiscoverUrl = async () => { - if (!urlGenerator?.createUrl) return; + const getDiscoverUrl = async () => { + if (!urlGenerator?.createUrl) return; - const newUrl = await urlGenerator.createUrl({ - filters, - indexPatternId: indexPattern?.id, - }); - setDiscoverUrl(newUrl); - }; - getDiscoverUrl(); + const newUrl = await urlGenerator.createUrl({ + filters, + indexPatternId: indexPattern?.id, + }); + setDiscoverUrl(newUrl); + }; + getDiscoverUrl(); + } }, [ indexPatterns, series.dataType, + series.filters, series.reportDefinitions, series.selectedMetricField, seriesConfig?.baseFilters, 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 index f3e0eb767d336..2808dfae83527 100644 --- 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 @@ -66,7 +66,9 @@ export function ReportDefinitionField({ const values = selectedReportDefinitions?.[fieldT]; if (!values.includes(ALL_VALUES_SELECTED)) { const valueFilter = buildPhrasesFilter(fieldT, values, indexPattern)[0]; - filtersN.push(valueFilter.query); + if (valueFilter.query) { + filtersN.push(valueFilter.query); + } } } }); 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 index c1462ce74b426..640e928b8ab98 100644 --- 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 @@ -12,6 +12,7 @@ import { RemoveSeries } from './remove_series'; import { useSeriesStorage } from '../../hooks/use_series_storage'; import { SeriesConfig, SeriesUrl } from '../../types'; import { useDiscoverLink } from '../../hooks/use_discover_link'; +import { useAppIndexPatternContext } from '../../hooks/use_app_index_pattern'; interface Props { seriesId: number; @@ -25,6 +26,10 @@ export function SeriesActions({ seriesId, series, seriesConfig, onEditClick }: P const { href: discoverHref } = useDiscoverLink({ series, seriesConfig }); + const { indexPatterns } = useAppIndexPatternContext(); + + const indexPattern = indexPatterns?.[series.dataType]; + const copySeries = () => { let copySeriesId: string = `${series.name}-copy`; if (allSeries.find(({ name }) => name === copySeriesId)) { @@ -63,7 +68,7 @@ export function SeriesActions({ seriesId, series, seriesConfig, onEditClick }: P color="text" target="_blank" href={discoverHref} - isDisabled={!series.dataType || !series.selectedMetricField} + isDisabled={!series.dataType || !series.selectedMetricField || !indexPattern} /> From f1125821f55fc24e9985eb1732fe4cf1a9c33dcd Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 18 Nov 2021 05:48:41 -0500 Subject: [PATCH 106/148] Update dependency @elastic/charts to v39.0.2 (#118895) Co-authored-by: Renovate Bot --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index d1639068c1cd4..ca2cb27076c7a 100644 --- a/package.json +++ b/package.json @@ -99,7 +99,7 @@ "@elastic/apm-rum": "^5.9.1", "@elastic/apm-rum-react": "^1.3.1", "@elastic/apm-synthtrace": "link:bazel-bin/packages/elastic-apm-synthtrace", - "@elastic/charts": "39.0.1", + "@elastic/charts": "39.0.2", "@elastic/datemath": "link:bazel-bin/packages/elastic-datemath", "@elastic/elasticsearch": "npm:@elastic/elasticsearch-canary@^8.0.0-canary.35", "@elastic/ems-client": "8.0.0", diff --git a/yarn.lock b/yarn.lock index 9f661aca62673..de6ee06e53975 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1623,10 +1623,10 @@ dependencies: object-hash "^1.3.0" -"@elastic/charts@39.0.1": - version "39.0.1" - resolved "https://registry.yarnpkg.com/@elastic/charts/-/charts-39.0.1.tgz#7891d6efb3a12eb73fcb57d9a1f71565c22f4501" - integrity sha512-k64+vrfRkP7Gn8+T0Vtdev/DKpy6G+M9H6OFQcf1fgXAd7qOnTXVaN4Ru+BRTPylTFwxf9pqHraz8Ayi+3VpjA== +"@elastic/charts@39.0.2": + version "39.0.2" + resolved "https://registry.yarnpkg.com/@elastic/charts/-/charts-39.0.2.tgz#5533fc57c4ceed4c5ae826cd9a13c55cc03c55e5" + integrity sha512-jjdZSV6PGKsjA2qDAwEw+SjHWq5/Rm9FQk9lrmxrX+0rc7TlsPyr840RT1BAfkDDoo8+o3WWbfg+r61Y0FQ1Pg== dependencies: "@popperjs/core" "^2.4.0" chroma-js "^2.1.0" From 3004e762b3b8751ea6728258ec06a4101195391e Mon Sep 17 00:00:00 2001 From: Tiago Costa Date: Thu, 18 Nov 2021 12:45:39 +0000 Subject: [PATCH 107/148] skip flaky suites (#118921) --- x-pack/test/examples/search_examples/search_session_example.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/examples/search_examples/search_session_example.ts b/x-pack/test/examples/search_examples/search_session_example.ts index ab96a7767baff..e6261f69e14f6 100644 --- a/x-pack/test/examples/search_examples/search_session_example.ts +++ b/x-pack/test/examples/search_examples/search_session_example.ts @@ -15,7 +15,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const es = getService('es'); const searchSessions = getService('searchSessions'); - describe('Search session example', () => { + // FLAKY: https://github.com/elastic/kibana/issues/118921 + describe.skip('Search session example', () => { const appId = 'searchExamples'; before(async function () { From f7d7a344e358d0d24ae05f43bebe3a0296d2a839 Mon Sep 17 00:00:00 2001 From: Kate Patticha Date: Thu, 18 Nov 2021 13:48:04 +0100 Subject: [PATCH 108/148] [APM] Improve server file structure by colocating files related to the route (#118649) * [APM] Improve server file structure by colocate files related to the route * [APM] co-locate the rest of files * Fix unit test * Remove obsolete code * Fix broken paths in tests --- .../plugins/apm/server/deprecations/index.ts | 2 +- .../collect_data_telemetry/index.ts | 2 +- .../collect_data_telemetry/tasks.test.ts | 2 +- .../apm/server/lib/apm_telemetry/index.ts | 2 +- .../create_apm_event_client/index.ts | 2 +- .../unpack_processor_events.test.ts | 2 +- .../unpack_processor_events.ts | 2 +- .../server/lib/helpers/setup_request.test.ts | 6 +- .../apm/server/lib/helpers/setup_request.ts | 2 +- x-pack/plugins/apm/server/plugin.ts | 10 ++-- .../projections/rum_page_load_transactions.ts | 4 +- .../alerts/action_variables.ts | 0 .../alerts/alerting_es_client.ts | 0 .../chart_preview/get_transaction_duration.ts | 6 +- .../get_transaction_error_count.ts | 4 +- .../get_transaction_error_rate.ts | 8 +-- .../alerts/register_apm_alerts.ts | 0 .../register_error_count_alert_type.test.ts | 0 .../alerts/register_error_count_alert_type.ts | 2 +- ...er_transaction_duration_alert_type.test.ts | 0 ...egister_transaction_duration_alert_type.ts | 4 +- ...action_duration_anomaly_alert_type.test.ts | 0 ...transaction_duration_anomaly_alert_type.ts | 0 ..._transaction_error_rate_alert_type.test.ts | 0 ...ister_transaction_error_rate_alert_type.ts | 4 +- .../alerts/{chart_preview.ts => route.ts} | 6 +- .../alerts/test_utils/index.ts | 0 .../get_global_apm_server_route_repository.ts | 46 +++++++------- .../field_stats/get_boolean_field_stats.ts | 0 .../field_stats/get_field_stats.test.ts | 0 .../queries/field_stats/get_fields_stats.ts | 0 .../field_stats/get_keyword_field_stats.ts | 0 .../field_stats/get_numeric_field_stats.ts | 0 .../correlations/queries/get_filters.ts | 0 .../queries/get_query_with_params.test.ts | 0 .../queries/get_query_with_params.ts | 0 .../queries/get_request_base.test.ts | 0 .../correlations/queries/get_request_base.ts | 0 .../correlations/queries/index.ts | 0 .../queries/query_correlation.test.ts | 0 .../correlations/queries/query_correlation.ts | 0 .../query_correlation_with_histogram.test.ts | 0 .../query_correlation_with_histogram.ts | 0 .../queries/query_failure_correlation.ts | 0 .../queries/query_field_candidates.test.ts | 0 .../queries/query_field_candidates.ts | 0 .../queries/query_field_value_pairs.test.ts | 0 .../queries/query_field_value_pairs.ts | 0 .../queries/query_fractions.test.ts | 0 .../correlations/queries/query_fractions.ts | 0 .../queries/query_histogram.test.ts | 0 .../correlations/queries/query_histogram.ts | 0 .../query_histogram_range_steps.test.ts | 0 .../queries/query_histogram_range_steps.ts | 0 .../correlations/queries/query_p_values.ts | 0 .../queries/query_percentiles.test.ts | 0 .../correlations/queries/query_percentiles.ts | 0 .../correlations/queries/query_ranges.test.ts | 0 .../correlations/queries/query_ranges.ts | 0 .../queries/query_significant_correlations.ts | 0 .../route.ts} | 16 ++--- .../compute_expectations_and_ranges.test.ts | 0 .../utils/compute_expectations_and_ranges.ts | 0 .../correlations/utils/field_stats_utils.ts | 0 .../correlations/utils/index.ts | 0 .../utils/split_all_settled_promises.ts | 0 .../data_view/create_static_data_view.test.ts | 4 +- .../data_view/create_static_data_view.ts | 4 +- .../data_view/get_apm_data_view_title.test.ts | 0 .../data_view/get_apm_data_view_title.ts | 0 .../data_view/get_dynamic_data_view.ts | 0 .../{data_view.ts => data_view/route.ts} | 10 ++-- .../get_all_environments.test.ts.snap | 0 .../get_environments.test.ts.snap | 0 .../environments/get_all_environments.test.ts | 0 .../environments/get_all_environments.ts | 4 +- .../environments/get_environments.test.ts | 0 .../environments/get_environments.ts | 4 +- .../route.ts} | 14 ++--- .../errors/__snapshots__/queries.test.ts.snap | 0 .../__snapshots__/get_buckets.test.ts.snap | 0 .../__snapshots__/queries.test.ts.snap | 0 .../errors/distribution/get_buckets.test.ts | 0 .../errors/distribution/get_buckets.ts | 2 +- .../errors/distribution/get_distribution.ts | 2 +- .../errors/distribution/queries.test.ts | 0 .../errors/get_error_group_sample.ts | 2 +- .../errors/get_error_groups.ts | 4 +- .../{lib => routes}/errors/queries.test.ts | 0 .../routes/{errors.ts => errors/route.ts} | 14 ++--- .../event_metadata/get_event_metadata.ts | 2 +- .../route.ts} | 10 ++-- .../route.ts} | 10 ++-- .../fleet/create_cloud_apm_package_policy.ts | 2 +- .../{lib => routes}/fleet/get_agents.ts | 2 +- .../fleet/get_apm_package_policies.ts | 2 +- .../get_apm_package_policy_definition.test.ts | 0 .../get_apm_package_policy_definition.ts | 0 .../fleet/get_cloud_apm_package_policy.ts | 0 .../get_unsupported_apm_server_schema.test.ts | 0 .../get_unsupported_apm_server_schema.ts | 0 .../{lib => routes}/fleet/is_superuser.ts | 0 .../fleet/merge_package_policy_with_apm.ts | 2 +- .../fleet/register_fleet_policy_callbacks.ts | 2 +- .../routes/{fleet.ts => fleet/route.ts} | 22 +++---- .../{lib => routes}/fleet/source_maps.test.ts | 0 .../{lib => routes}/fleet/source_maps.ts | 2 +- ...c_agent_configs_to_apm_package_policies.ts | 6 +- .../get_overall_latency_distribution.ts | 0 .../get_percentile_threshold_value.ts | 0 .../route.ts} | 10 ++-- .../latency_distribution}/types.ts | 2 +- .../__snapshots__/queries.test.ts.snap | 0 .../metrics/by_agent/default.ts | 2 +- .../gc/fetch_and_transform_gc_metrics.test.ts | 2 +- .../java/gc/fetch_and_transform_gc_metrics.ts | 6 +- .../by_agent/java/gc/get_gc_rate_chart.ts | 2 +- .../by_agent/java/gc/get_gc_time_chart.ts | 2 +- .../by_agent/java/heap_memory/index.ts | 2 +- .../metrics/by_agent/java/index.ts | 2 +- .../by_agent/java/non_heap_memory/index.ts | 2 +- .../by_agent/java/thread_count/index.ts | 2 +- .../metrics/by_agent/shared/cpu/index.ts | 2 +- .../metrics/by_agent/shared/memory/index.ts | 2 +- .../metrics/fetch_and_transform_metrics.ts | 6 +- .../get_metrics_chart_data_by_agent.ts | 2 +- .../{lib => routes}/metrics/queries.test.ts | 0 .../routes/{metrics.ts => metrics/route.ts} | 10 ++-- .../server/{lib => routes}/metrics/types.ts | 0 .../get_service_count.ts | 4 +- .../get_transactions_per_minute.ts | 6 +- .../observability_overview/has_data.ts | 2 +- .../route.ts} | 18 +++--- .../__snapshots__/queries.test.ts.snap | 0 .../rum_client/get_client_metrics.ts | 2 +- .../rum_client/get_js_errors.ts | 2 +- .../rum_client/get_long_task_metrics.ts | 2 +- .../rum_client/get_page_load_distribution.ts | 2 +- .../rum_client/get_page_view_trends.ts | 2 +- .../rum_client/get_pl_dist_breakdown.ts | 2 +- .../rum_client/get_rum_services.ts | 2 +- .../rum_client/get_url_search.ts | 2 +- .../rum_client/get_visitor_breakdown.ts | 2 +- .../rum_client/get_web_core_vitals.ts | 2 +- .../rum_client/has_rum_data.ts | 2 +- .../rum_client/queries.test.ts | 0 .../{rum_client.ts => rum_client/route.ts} | 34 +++++------ .../ui_filters/get_es_filter.test.ts | 0 .../rum_client/ui_filters/get_es_filter.ts | 0 .../fetch_service_paths_from_trace_ids.ts | 2 +- .../service_map/get_service_anomalies.ts | 4 +- .../service_map/get_service_map.ts | 4 +- .../get_service_map_backend_node_info.ts | 4 +- .../get_service_map_from_trace_ids.test.ts | 0 .../get_service_map_from_trace_ids.ts | 2 +- .../get_service_map_service_node_info.test.ts | 4 +- .../get_service_map_service_node_info.ts | 6 +- .../service_map/get_trace_sample_ids.ts | 2 +- .../service_map/group_resource_nodes.test.ts | 0 .../service_map/group_resource_nodes.ts | 0 .../group_resource_nodes_grouped.json | 0 .../group_resource_nodes_pregrouped.json | 0 .../{service_map.ts => service_map/route.ts} | 22 +++---- .../transform_service_map_responses.test.ts | 0 .../transform_service_map_responses.ts | 0 .../__snapshots__/queries.test.ts.snap | 0 .../service_nodes/get_service_nodes.ts} | 2 +- .../service_nodes/queries.test.ts | 2 +- .../route.ts} | 12 ++-- .../__snapshots__/queries.test.ts.snap | 0 .../__fixtures__/multiple_versions.json | 0 .../annotations/__fixtures__/no_versions.json | 0 .../annotations/__fixtures__/one_version.json | 0 .../__fixtures__/versions_first_seen.json | 0 .../get_derived_service_annotations.ts | 4 +- .../annotations/get_stored_annotations.ts | 0 .../services/annotations/index.test.ts | 0 .../services/annotations/index.ts | 2 +- .../services/get_service_agent.ts | 2 +- .../services/get_service_alerts.ts | 0 .../services/get_service_dependencies.ts | 6 +- .../get_service_dependencies_breakdown.ts | 4 +- ...service_error_group_detailed_statistics.ts | 4 +- ...get_service_error_group_main_statistics.ts | 4 +- .../get_service_error_groups/index.ts | 6 +- .../services/get_service_infrastructure.ts | 2 +- .../get_service_instance_metadata_details.ts | 4 +- .../detailed_statistics.ts | 2 +- ...vice_instances_system_metric_statistics.ts | 4 +- ...ervice_instances_transaction_statistics.ts | 10 ++-- .../get_service_instances/main_statistics.ts | 2 +- .../services/get_service_metadata_details.ts | 4 +- .../services/get_service_metadata_icons.ts | 4 +- .../services/get_service_node_metadata.ts | 2 +- ...e_transaction_group_detailed_statistics.ts | 10 ++-- .../get_service_transaction_groups.ts | 10 ++-- .../services/get_service_transaction_types.ts | 4 +- .../get_services/get_health_statuses.ts | 2 +- .../get_services/get_legacy_data_status.ts | 2 +- .../get_service_transaction_stats.ts | 6 +- .../get_services_from_metric_documents.ts | 2 +- .../get_services/get_services_items.ts | 2 +- .../services/get_services/index.ts | 2 +- .../get_services/merge_service_stats.test.ts | 0 .../get_services/merge_service_stats.ts | 0 ...service_transaction_detailed_statistics.ts | 10 ++-- .../get_services_detailed_statistics/index.ts | 2 +- .../services/get_throughput.ts | 4 +- .../get_service_profiling_statistics.ts | 4 +- .../get_service_profiling_timeline.ts | 4 +- .../{lib => routes}/services/queries.test.ts | 0 .../routes/{services.ts => services/route.ts} | 60 +++++++++---------- .../__snapshots__/queries.test.ts.snap | 0 .../convert_settings_to_string.ts | 0 .../create_agent_config_index.ts | 0 .../create_or_update_configuration.ts | 4 +- .../delete_configuration.ts | 2 +- .../find_exact_configuration.ts | 2 +- .../get_agent_name_by_service.ts | 2 +- .../get_existing_environments_for_service.ts | 2 +- .../get_environments/index.ts | 2 +- .../agent_configuration/get_service_names.ts | 4 +- .../list_configurations.ts | 2 +- .../mark_applied_by_agent.ts | 2 +- .../agent_configuration/queries.test.ts | 0 .../route.ts} | 32 +++++----- .../search_configurations.ts | 2 +- .../route.ts} | 26 ++++---- .../settings/apm_indices/get_apm_indices.ts | 2 +- .../{apm_indices.ts => apm_indices/route.ts} | 13 ++-- .../apm_indices/save_apm_indices.test.ts | 0 .../settings/apm_indices/save_apm_indices.ts | 0 .../get_transaction.test.ts.snap | 0 .../list_custom_links.test.ts.snap | 0 .../custom_link/create_custom_link_index.ts | 0 .../create_or_update_custom_link.test.ts | 2 +- .../create_or_update_custom_link.ts | 4 +- .../settings/custom_link/custom_link_types.ts | 0 .../custom_link/delete_custom_link.ts | 2 +- .../custom_link/get_transaction.test.ts | 2 +- .../settings/custom_link/get_transaction.ts | 2 +- .../settings/custom_link/helper.test.ts | 0 .../settings/custom_link/helper.ts | 0 .../custom_link/list_custom_links.test.ts | 2 +- .../settings/custom_link/list_custom_links.ts | 2 +- .../{custom_link.ts => custom_link/route.ts} | 27 ++++----- .../{source_maps.ts => source_maps/route.ts} | 10 ++-- .../suggestions/get_suggestions.ts | 4 +- .../{suggestions.ts => suggestions/route.ts} | 12 ++-- .../traces/__snapshots__/queries.test.ts.snap | 0 .../{lib => routes}/traces/get_trace_items.ts | 2 +- .../{lib => routes}/traces/queries.test.ts | 0 .../routes/{traces.ts => traces/route.ts} | 18 +++--- .../__snapshots__/queries.test.ts.snap | 0 .../transactions/breakdown/constants.ts | 0 .../transactions/breakdown/index.test.ts | 2 +- .../transactions/breakdown/index.ts | 4 +- .../breakdown/mock_responses/data.json | 0 .../breakdown/mock_responses/no_data.json | 0 .../{lib => routes}/transactions/constants.ts | 0 .../transactions/get_anomaly_data/fetcher.ts | 2 +- .../transactions/get_anomaly_data/index.ts | 4 +- .../transactions/get_latency_charts/index.ts | 4 +- .../transactions/get_transaction/index.ts | 2 +- .../get_transaction_by_trace/index.ts | 2 +- .../transactions/queries.test.ts | 0 .../route.ts} | 26 ++++---- .../trace_samples/get_trace_samples/index.ts | 2 +- .../transactions/trace_samples/index.ts | 2 +- x-pack/plugins/apm/server/tutorial/index.ts | 4 +- x-pack/plugins/apm/server/types.ts | 2 +- .../plugins/apm/server/utils/test_helpers.tsx | 2 +- .../metrics_charts/metrics_charts.spec.ts | 2 +- .../settings/agent_configuration.spec.ts | 2 +- 274 files changed, 449 insertions(+), 455 deletions(-) rename x-pack/plugins/apm/server/{lib => routes}/alerts/action_variables.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/alerts/alerting_es_client.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/alerts/chart_preview/get_transaction_duration.ts (94%) rename x-pack/plugins/apm/server/{lib => routes}/alerts/chart_preview/get_transaction_error_count.ts (93%) rename x-pack/plugins/apm/server/{lib => routes}/alerts/chart_preview/get_transaction_error_rate.ts (91%) rename x-pack/plugins/apm/server/{lib => routes}/alerts/register_apm_alerts.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/alerts/register_error_count_alert_type.test.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/alerts/register_error_count_alert_type.ts (98%) rename x-pack/plugins/apm/server/{lib => routes}/alerts/register_transaction_duration_alert_type.test.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/alerts/register_transaction_duration_alert_type.ts (98%) rename x-pack/plugins/apm/server/{lib => routes}/alerts/register_transaction_duration_anomaly_alert_type.test.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/alerts/register_transaction_duration_anomaly_alert_type.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/alerts/register_transaction_error_rate_alert_type.test.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/alerts/register_transaction_error_rate_alert_type.ts (97%) rename x-pack/plugins/apm/server/routes/alerts/{chart_preview.ts => route.ts} (89%) rename x-pack/plugins/apm/server/{lib => routes}/alerts/test_utils/index.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/correlations/queries/field_stats/get_boolean_field_stats.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/correlations/queries/field_stats/get_field_stats.test.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/correlations/queries/field_stats/get_fields_stats.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/correlations/queries/field_stats/get_keyword_field_stats.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/correlations/queries/field_stats/get_numeric_field_stats.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/correlations/queries/get_filters.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/correlations/queries/get_query_with_params.test.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/correlations/queries/get_query_with_params.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/correlations/queries/get_request_base.test.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/correlations/queries/get_request_base.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/correlations/queries/index.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/correlations/queries/query_correlation.test.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/correlations/queries/query_correlation.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/correlations/queries/query_correlation_with_histogram.test.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/correlations/queries/query_correlation_with_histogram.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/correlations/queries/query_failure_correlation.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/correlations/queries/query_field_candidates.test.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/correlations/queries/query_field_candidates.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/correlations/queries/query_field_value_pairs.test.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/correlations/queries/query_field_value_pairs.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/correlations/queries/query_fractions.test.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/correlations/queries/query_fractions.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/correlations/queries/query_histogram.test.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/correlations/queries/query_histogram.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/correlations/queries/query_histogram_range_steps.test.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/correlations/queries/query_histogram_range_steps.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/correlations/queries/query_p_values.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/correlations/queries/query_percentiles.test.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/correlations/queries/query_percentiles.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/correlations/queries/query_ranges.test.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/correlations/queries/query_ranges.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/correlations/queries/query_significant_correlations.ts (100%) rename x-pack/plugins/apm/server/routes/{correlations.ts => correlations/route.ts} (92%) rename x-pack/plugins/apm/server/{lib => routes}/correlations/utils/compute_expectations_and_ranges.test.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/correlations/utils/compute_expectations_and_ranges.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/correlations/utils/field_stats_utils.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/correlations/utils/index.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/correlations/utils/split_all_settled_promises.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/data_view/create_static_data_view.test.ts (96%) rename x-pack/plugins/apm/server/{lib => routes}/data_view/create_static_data_view.ts (95%) rename x-pack/plugins/apm/server/{lib => routes}/data_view/get_apm_data_view_title.test.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/data_view/get_apm_data_view_title.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/data_view/get_dynamic_data_view.ts (100%) rename x-pack/plugins/apm/server/routes/{data_view.ts => data_view/route.ts} (78%) rename x-pack/plugins/apm/server/{lib => routes}/environments/__snapshots__/get_all_environments.test.ts.snap (100%) rename x-pack/plugins/apm/server/{lib => routes}/environments/__snapshots__/get_environments.test.ts.snap (100%) rename x-pack/plugins/apm/server/{lib => routes}/environments/get_all_environments.test.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/environments/get_all_environments.ts (93%) rename x-pack/plugins/apm/server/{lib => routes}/environments/get_environments.test.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/environments/get_environments.ts (93%) rename x-pack/plugins/apm/server/routes/{environments.ts => environments/route.ts} (72%) rename x-pack/plugins/apm/server/{lib => routes}/errors/__snapshots__/queries.test.ts.snap (100%) rename x-pack/plugins/apm/server/{lib => routes}/errors/distribution/__snapshots__/get_buckets.test.ts.snap (100%) rename x-pack/plugins/apm/server/{lib => routes}/errors/distribution/__snapshots__/queries.test.ts.snap (100%) rename x-pack/plugins/apm/server/{lib => routes}/errors/distribution/get_buckets.test.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/errors/distribution/get_buckets.ts (96%) rename x-pack/plugins/apm/server/{lib => routes}/errors/distribution/get_distribution.ts (96%) rename x-pack/plugins/apm/server/{lib => routes}/errors/distribution/queries.test.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/errors/get_error_group_sample.ts (97%) rename x-pack/plugins/apm/server/{lib => routes}/errors/get_error_groups.ts (96%) rename x-pack/plugins/apm/server/{lib => routes}/errors/queries.test.ts (100%) rename x-pack/plugins/apm/server/routes/{errors.ts => errors/route.ts} (86%) rename x-pack/plugins/apm/server/{lib => routes}/event_metadata/get_event_metadata.ts (93%) rename x-pack/plugins/apm/server/routes/{event_metadata.ts => event_metadata/route.ts} (72%) rename x-pack/plugins/apm/server/routes/{fallback_to_transactions.ts => fallback_to_transactions/route.ts} (70%) rename x-pack/plugins/apm/server/{lib => routes}/fleet/create_cloud_apm_package_policy.ts (97%) rename x-pack/plugins/apm/server/{lib => routes}/fleet/get_agents.ts (89%) rename x-pack/plugins/apm/server/{lib => routes}/fleet/get_apm_package_policies.ts (89%) rename x-pack/plugins/apm/server/{lib => routes}/fleet/get_apm_package_policy_definition.test.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/fleet/get_apm_package_policy_definition.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/fleet/get_cloud_apm_package_policy.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/fleet/get_unsupported_apm_server_schema.test.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/fleet/get_unsupported_apm_server_schema.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/fleet/is_superuser.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/fleet/merge_package_policy_with_apm.ts (95%) rename x-pack/plugins/apm/server/{lib => routes}/fleet/register_fleet_policy_callbacks.ts (98%) rename x-pack/plugins/apm/server/routes/{fleet.ts => fleet/route.ts} (89%) rename x-pack/plugins/apm/server/{lib => routes}/fleet/source_maps.test.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/fleet/source_maps.ts (98%) rename x-pack/plugins/apm/server/{lib => routes}/fleet/sync_agent_configs_to_apm_package_policies.ts (90%) rename x-pack/plugins/apm/server/{lib/latency => routes/latency_distribution}/get_overall_latency_distribution.ts (100%) rename x-pack/plugins/apm/server/{lib/latency => routes/latency_distribution}/get_percentile_threshold_value.ts (100%) rename x-pack/plugins/apm/server/routes/{latency_distribution.ts => latency_distribution/route.ts} (80%) rename x-pack/plugins/apm/server/{lib/latency => routes/latency_distribution}/types.ts (92%) rename x-pack/plugins/apm/server/{lib => routes}/metrics/__snapshots__/queries.test.ts.snap (100%) rename x-pack/plugins/apm/server/{lib => routes}/metrics/by_agent/default.ts (92%) rename x-pack/plugins/apm/server/{lib => routes}/metrics/by_agent/java/gc/fetch_and_transform_gc_metrics.test.ts (98%) rename x-pack/plugins/apm/server/{lib => routes}/metrics/by_agent/java/gc/fetch_and_transform_gc_metrics.ts (95%) rename x-pack/plugins/apm/server/{lib => routes}/metrics/by_agent/java/gc/get_gc_rate_chart.ts (95%) rename x-pack/plugins/apm/server/{lib => routes}/metrics/by_agent/java/gc/get_gc_time_chart.ts (95%) rename x-pack/plugins/apm/server/{lib => routes}/metrics/by_agent/java/heap_memory/index.ts (97%) rename x-pack/plugins/apm/server/{lib => routes}/metrics/by_agent/java/index.ts (95%) rename x-pack/plugins/apm/server/{lib => routes}/metrics/by_agent/java/non_heap_memory/index.ts (97%) rename x-pack/plugins/apm/server/{lib => routes}/metrics/by_agent/java/thread_count/index.ts (96%) rename x-pack/plugins/apm/server/{lib => routes}/metrics/by_agent/shared/cpu/index.ts (97%) rename x-pack/plugins/apm/server/{lib => routes}/metrics/by_agent/shared/memory/index.ts (98%) rename x-pack/plugins/apm/server/{lib => routes}/metrics/fetch_and_transform_metrics.ts (94%) rename x-pack/plugins/apm/server/{lib => routes}/metrics/get_metrics_chart_data_by_agent.ts (95%) rename x-pack/plugins/apm/server/{lib => routes}/metrics/queries.test.ts (100%) rename x-pack/plugins/apm/server/routes/{metrics.ts => metrics/route.ts} (76%) rename x-pack/plugins/apm/server/{lib => routes}/metrics/types.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/observability_overview/get_service_count.ts (90%) rename x-pack/plugins/apm/server/{lib => routes}/observability_overview/get_transactions_per_minute.ts (93%) rename x-pack/plugins/apm/server/{lib => routes}/observability_overview/has_data.ts (94%) rename x-pack/plugins/apm/server/routes/{observability_overview.ts => observability_overview/route.ts} (74%) rename x-pack/plugins/apm/server/{lib => routes}/rum_client/__snapshots__/queries.test.ts.snap (100%) rename x-pack/plugins/apm/server/{lib => routes}/rum_client/get_client_metrics.ts (98%) rename x-pack/plugins/apm/server/{lib => routes}/rum_client/get_js_errors.ts (98%) rename x-pack/plugins/apm/server/{lib => routes}/rum_client/get_long_task_metrics.ts (97%) rename x-pack/plugins/apm/server/{lib => routes}/rum_client/get_page_load_distribution.ts (99%) rename x-pack/plugins/apm/server/{lib => routes}/rum_client/get_page_view_trends.ts (98%) rename x-pack/plugins/apm/server/{lib => routes}/rum_client/get_pl_dist_breakdown.ts (98%) rename x-pack/plugins/apm/server/{lib => routes}/rum_client/get_rum_services.ts (96%) rename x-pack/plugins/apm/server/{lib => routes}/rum_client/get_url_search.ts (97%) rename x-pack/plugins/apm/server/{lib => routes}/rum_client/get_visitor_breakdown.ts (97%) rename x-pack/plugins/apm/server/{lib => routes}/rum_client/get_web_core_vitals.ts (98%) rename x-pack/plugins/apm/server/{lib => routes}/rum_client/has_rum_data.ts (97%) rename x-pack/plugins/apm/server/{lib => routes}/rum_client/queries.test.ts (100%) rename x-pack/plugins/apm/server/routes/{rum_client.ts => rum_client/route.ts} (87%) rename x-pack/plugins/apm/server/{lib => routes}/rum_client/ui_filters/get_es_filter.test.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/rum_client/ui_filters/get_es_filter.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/service_map/fetch_service_paths_from_trace_ids.ts (99%) rename x-pack/plugins/apm/server/{lib => routes}/service_map/get_service_anomalies.ts (97%) rename x-pack/plugins/apm/server/{lib => routes}/service_map/get_service_map.ts (97%) rename x-pack/plugins/apm/server/{lib => routes}/service_map/get_service_map_backend_node_info.ts (95%) rename x-pack/plugins/apm/server/{lib => routes}/service_map/get_service_map_from_trace_ids.test.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/service_map/get_service_map_from_trace_ids.ts (96%) rename x-pack/plugins/apm/server/{lib => routes}/service_map/get_service_map_service_node_info.test.ts (95%) rename x-pack/plugins/apm/server/{lib => routes}/service_map/get_service_map_service_node_info.ts (97%) rename x-pack/plugins/apm/server/{lib => routes}/service_map/get_trace_sample_ids.ts (98%) rename x-pack/plugins/apm/server/{lib => routes}/service_map/group_resource_nodes.test.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/service_map/group_resource_nodes.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/service_map/mock_responses/group_resource_nodes_grouped.json (100%) rename x-pack/plugins/apm/server/{lib => routes}/service_map/mock_responses/group_resource_nodes_pregrouped.json (100%) rename x-pack/plugins/apm/server/routes/{service_map.ts => service_map/route.ts} (81%) rename x-pack/plugins/apm/server/{lib => routes}/service_map/transform_service_map_responses.test.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/service_map/transform_service_map_responses.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/service_nodes/__snapshots__/queries.test.ts.snap (100%) rename x-pack/plugins/apm/server/{lib/service_nodes/index.ts => routes/service_nodes/get_service_nodes.ts} (98%) rename x-pack/plugins/apm/server/{lib => routes}/service_nodes/queries.test.ts (96%) rename x-pack/plugins/apm/server/routes/{service_nodes.ts => service_nodes/route.ts} (72%) rename x-pack/plugins/apm/server/{lib => routes}/services/__snapshots__/queries.test.ts.snap (100%) rename x-pack/plugins/apm/server/{lib => routes}/services/annotations/__fixtures__/multiple_versions.json (100%) rename x-pack/plugins/apm/server/{lib => routes}/services/annotations/__fixtures__/no_versions.json (100%) rename x-pack/plugins/apm/server/{lib => routes}/services/annotations/__fixtures__/one_version.json (100%) rename x-pack/plugins/apm/server/{lib => routes}/services/annotations/__fixtures__/versions_first_seen.json (100%) rename x-pack/plugins/apm/server/{lib => routes}/services/annotations/get_derived_service_annotations.ts (96%) rename x-pack/plugins/apm/server/{lib => routes}/services/annotations/get_stored_annotations.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/services/annotations/index.test.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/services/annotations/index.ts (96%) rename x-pack/plugins/apm/server/{lib => routes}/services/get_service_agent.ts (97%) rename x-pack/plugins/apm/server/{lib => routes}/services/get_service_alerts.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/services/get_service_dependencies.ts (77%) rename x-pack/plugins/apm/server/{lib => routes}/services/get_service_dependencies_breakdown.ts (90%) rename x-pack/plugins/apm/server/{lib => routes}/services/get_service_error_groups/get_service_error_group_detailed_statistics.ts (97%) rename x-pack/plugins/apm/server/{lib => routes}/services/get_service_error_groups/get_service_error_group_main_statistics.ts (95%) rename x-pack/plugins/apm/server/{lib => routes}/services/get_service_error_groups/index.ts (96%) rename x-pack/plugins/apm/server/{lib => routes}/services/get_service_infrastructure.ts (96%) rename x-pack/plugins/apm/server/{lib => routes}/services/get_service_instance_metadata_details.ts (97%) rename x-pack/plugins/apm/server/{lib => routes}/services/get_service_instances/detailed_statistics.ts (98%) rename x-pack/plugins/apm/server/{lib => routes}/services/get_service_instances/get_service_instances_system_metric_statistics.ts (97%) rename x-pack/plugins/apm/server/{lib => routes}/services/get_service_instances/get_service_instances_transaction_statistics.ts (94%) rename x-pack/plugins/apm/server/{lib => routes}/services/get_service_instances/main_statistics.ts (96%) rename x-pack/plugins/apm/server/{lib => routes}/services/get_service_metadata_details.ts (96%) rename x-pack/plugins/apm/server/{lib => routes}/services/get_service_metadata_icons.ts (94%) rename x-pack/plugins/apm/server/{lib => routes}/services/get_service_node_metadata.ts (97%) rename x-pack/plugins/apm/server/{lib => routes}/services/get_service_transaction_group_detailed_statistics.ts (95%) rename x-pack/plugins/apm/server/{lib => routes}/services/get_service_transaction_groups.ts (92%) rename x-pack/plugins/apm/server/{lib => routes}/services/get_service_transaction_types.ts (94%) rename x-pack/plugins/apm/server/{lib => routes}/services/get_services/get_health_statuses.ts (92%) rename x-pack/plugins/apm/server/{lib => routes}/services/get_services/get_legacy_data_status.ts (95%) rename x-pack/plugins/apm/server/{lib => routes}/services/get_services/get_service_transaction_stats.ts (95%) rename x-pack/plugins/apm/server/{lib => routes}/services/get_services/get_services_from_metric_documents.ts (97%) rename x-pack/plugins/apm/server/{lib => routes}/services/get_services/get_services_items.ts (96%) rename x-pack/plugins/apm/server/{lib => routes}/services/get_services/index.ts (95%) rename x-pack/plugins/apm/server/{lib => routes}/services/get_services/merge_service_stats.test.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/services/get_services/merge_service_stats.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/services/get_services_detailed_statistics/get_service_transaction_detailed_statistics.ts (92%) rename x-pack/plugins/apm/server/{lib => routes}/services/get_services_detailed_statistics/index.ts (95%) rename x-pack/plugins/apm/server/{lib => routes}/services/get_throughput.ts (96%) rename x-pack/plugins/apm/server/{lib => routes}/services/profiling/get_service_profiling_statistics.ts (97%) rename x-pack/plugins/apm/server/{lib => routes}/services/profiling/get_service_profiling_timeline.ts (96%) rename x-pack/plugins/apm/server/{lib => routes}/services/queries.test.ts (100%) rename x-pack/plugins/apm/server/routes/{services.ts => services/route.ts} (89%) rename x-pack/plugins/apm/server/{lib => routes}/settings/agent_configuration/__snapshots__/queries.test.ts.snap (100%) rename x-pack/plugins/apm/server/{lib => routes}/settings/agent_configuration/convert_settings_to_string.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/settings/agent_configuration/create_agent_config_index.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/settings/agent_configuration/create_or_update_configuration.ts (89%) rename x-pack/plugins/apm/server/{lib => routes}/settings/agent_configuration/delete_configuration.ts (91%) rename x-pack/plugins/apm/server/{lib => routes}/settings/agent_configuration/find_exact_configuration.ts (96%) rename x-pack/plugins/apm/server/{lib => routes}/settings/agent_configuration/get_agent_name_by_service.ts (95%) rename x-pack/plugins/apm/server/{lib => routes}/settings/agent_configuration/get_environments/get_existing_environments_for_service.ts (95%) rename x-pack/plugins/apm/server/{lib => routes}/settings/agent_configuration/get_environments/index.ts (95%) rename x-pack/plugins/apm/server/{lib => routes}/settings/agent_configuration/get_service_names.ts (90%) rename x-pack/plugins/apm/server/{lib => routes}/settings/agent_configuration/list_configurations.ts (93%) rename x-pack/plugins/apm/server/{lib => routes}/settings/agent_configuration/mark_applied_by_agent.ts (93%) rename x-pack/plugins/apm/server/{lib => routes}/settings/agent_configuration/queries.test.ts (100%) rename x-pack/plugins/apm/server/routes/settings/{agent_configuration.ts => agent_configuration/route.ts} (86%) rename x-pack/plugins/apm/server/{lib => routes}/settings/agent_configuration/search_configurations.ts (97%) rename x-pack/plugins/apm/server/routes/settings/{anomaly_detection.ts => anomaly_detection/route.ts} (74%) rename x-pack/plugins/apm/server/{lib => routes}/settings/apm_indices/get_apm_indices.ts (97%) rename x-pack/plugins/apm/server/routes/settings/{apm_indices.ts => apm_indices/route.ts} (82%) rename x-pack/plugins/apm/server/{lib => routes}/settings/apm_indices/save_apm_indices.test.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/settings/apm_indices/save_apm_indices.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/settings/custom_link/__snapshots__/get_transaction.test.ts.snap (100%) rename x-pack/plugins/apm/server/{lib => routes}/settings/custom_link/__snapshots__/list_custom_links.test.ts.snap (100%) rename x-pack/plugins/apm/server/{lib => routes}/settings/custom_link/create_custom_link_index.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/settings/custom_link/create_or_update_custom_link.test.ts (97%) rename x-pack/plugins/apm/server/{lib => routes}/settings/custom_link/create_or_update_custom_link.ts (86%) rename x-pack/plugins/apm/server/{lib => routes}/settings/custom_link/custom_link_types.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/settings/custom_link/delete_custom_link.ts (90%) rename x-pack/plugins/apm/server/{lib => routes}/settings/custom_link/get_transaction.test.ts (95%) rename x-pack/plugins/apm/server/{lib => routes}/settings/custom_link/get_transaction.ts (95%) rename x-pack/plugins/apm/server/{lib => routes}/settings/custom_link/helper.test.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/settings/custom_link/helper.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/settings/custom_link/list_custom_links.test.ts (94%) rename x-pack/plugins/apm/server/{lib => routes}/settings/custom_link/list_custom_links.ts (96%) rename x-pack/plugins/apm/server/routes/settings/{custom_link.ts => custom_link/route.ts} (79%) rename x-pack/plugins/apm/server/routes/{source_maps.ts => source_maps/route.ts} (91%) rename x-pack/plugins/apm/server/{lib => routes}/suggestions/get_suggestions.ts (87%) rename x-pack/plugins/apm/server/routes/{suggestions.ts => suggestions/route.ts} (72%) rename x-pack/plugins/apm/server/{lib => routes}/traces/__snapshots__/queries.test.ts.snap (100%) rename x-pack/plugins/apm/server/{lib => routes}/traces/get_trace_items.ts (97%) rename x-pack/plugins/apm/server/{lib => routes}/traces/queries.test.ts (100%) rename x-pack/plugins/apm/server/routes/{traces.ts => traces/route.ts} (79%) rename x-pack/plugins/apm/server/{lib => routes}/transactions/__snapshots__/queries.test.ts.snap (100%) rename x-pack/plugins/apm/server/{lib => routes}/transactions/breakdown/constants.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/transactions/breakdown/index.test.ts (97%) rename x-pack/plugins/apm/server/{lib => routes}/transactions/breakdown/index.ts (97%) rename x-pack/plugins/apm/server/{lib => routes}/transactions/breakdown/mock_responses/data.json (100%) rename x-pack/plugins/apm/server/{lib => routes}/transactions/breakdown/mock_responses/no_data.json (100%) rename x-pack/plugins/apm/server/{lib => routes}/transactions/constants.ts (100%) rename x-pack/plugins/apm/server/{lib => routes}/transactions/get_anomaly_data/fetcher.ts (97%) rename x-pack/plugins/apm/server/{lib => routes}/transactions/get_anomaly_data/index.ts (97%) rename x-pack/plugins/apm/server/{lib => routes}/transactions/get_latency_charts/index.ts (97%) rename x-pack/plugins/apm/server/{lib => routes}/transactions/get_transaction/index.ts (95%) rename x-pack/plugins/apm/server/{lib => routes}/transactions/get_transaction_by_trace/index.ts (95%) rename x-pack/plugins/apm/server/{lib => routes}/transactions/queries.test.ts (100%) rename x-pack/plugins/apm/server/routes/{transactions.ts => transactions/route.ts} (90%) rename x-pack/plugins/apm/server/{lib => routes}/transactions/trace_samples/get_trace_samples/index.ts (97%) rename x-pack/plugins/apm/server/{lib => routes}/transactions/trace_samples/index.ts (95%) diff --git a/x-pack/plugins/apm/server/deprecations/index.ts b/x-pack/plugins/apm/server/deprecations/index.ts index 39e282e76d9a6..92955fa0c6d0b 100644 --- a/x-pack/plugins/apm/server/deprecations/index.ts +++ b/x-pack/plugins/apm/server/deprecations/index.ts @@ -9,7 +9,7 @@ import { GetDeprecationsContext, DeprecationsDetails } from 'src/core/server'; import { i18n } from '@kbn/i18n'; import { isEmpty } from 'lodash'; import { CloudSetup } from '../../../cloud/server'; -import { getCloudAgentPolicy } from '../lib/fleet/get_cloud_apm_package_policy'; +import { getCloudAgentPolicy } from '../routes/fleet/get_cloud_apm_package_policy'; import { APMRouteHandlerResources } from '../'; export function getDeprecations({ diff --git a/x-pack/plugins/apm/server/lib/apm_telemetry/collect_data_telemetry/index.ts b/x-pack/plugins/apm/server/lib/apm_telemetry/collect_data_telemetry/index.ts index 9b5820767690f..8aee60357ba73 100644 --- a/x-pack/plugins/apm/server/lib/apm_telemetry/collect_data_telemetry/index.ts +++ b/x-pack/plugins/apm/server/lib/apm_telemetry/collect_data_telemetry/index.ts @@ -12,7 +12,7 @@ import { ESSearchRequest, ESSearchResponse, } from '../../../../../../../src/core/types/elasticsearch'; -import { ApmIndicesConfig } from '../../settings/apm_indices/get_apm_indices'; +import { ApmIndicesConfig } from '../../../routes/settings/apm_indices/get_apm_indices'; import { tasks } from './tasks'; import { APMDataTelemetry } from '../types'; diff --git a/x-pack/plugins/apm/server/lib/apm_telemetry/collect_data_telemetry/tasks.test.ts b/x-pack/plugins/apm/server/lib/apm_telemetry/collect_data_telemetry/tasks.test.ts index 1e697ebdcae06..b69aa1e6e0196 100644 --- a/x-pack/plugins/apm/server/lib/apm_telemetry/collect_data_telemetry/tasks.test.ts +++ b/x-pack/plugins/apm/server/lib/apm_telemetry/collect_data_telemetry/tasks.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { ApmIndicesConfig } from '../../settings/apm_indices/get_apm_indices'; +import { ApmIndicesConfig } from '../../../routes/settings/apm_indices/get_apm_indices'; import { tasks } from './tasks'; import { SERVICE_NAME, diff --git a/x-pack/plugins/apm/server/lib/apm_telemetry/index.ts b/x-pack/plugins/apm/server/lib/apm_telemetry/index.ts index 88ef1203bae9f..bdbb1fe1dbcd3 100644 --- a/x-pack/plugins/apm/server/lib/apm_telemetry/index.ts +++ b/x-pack/plugins/apm/server/lib/apm_telemetry/index.ts @@ -24,7 +24,7 @@ import { APM_TELEMETRY_SAVED_OBJECT_TYPE, } from '../../../common/apm_saved_object_constants'; import { getInternalSavedObjectsClient } from '../helpers/get_internal_saved_objects_client'; -import { getApmIndices } from '../settings/apm_indices/get_apm_indices'; +import { getApmIndices } from '../../routes/settings/apm_indices/get_apm_indices'; import { collectDataTelemetry, CollectTelemetryParams, diff --git a/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_apm_event_client/index.ts b/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_apm_event_client/index.ts index a45d314c33719..6c9a0cb45e273 100644 --- a/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_apm_event_client/index.ts +++ b/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_apm_event_client/index.ts @@ -26,7 +26,7 @@ import { APMError } from '../../../../../typings/es_schemas/ui/apm_error'; import { Metric } from '../../../../../typings/es_schemas/ui/metric'; import { Span } from '../../../../../typings/es_schemas/ui/span'; import { Transaction } from '../../../../../typings/es_schemas/ui/transaction'; -import { ApmIndicesConfig } from '../../../settings/apm_indices/get_apm_indices'; +import { ApmIndicesConfig } from '../../../../routes/settings/apm_indices/get_apm_indices'; import { callAsyncWithDebug, getDebugBody, diff --git a/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_apm_event_client/unpack_processor_events.test.ts b/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_apm_event_client/unpack_processor_events.test.ts index 5ef3786e9bde4..d3f0fca0bb259 100644 --- a/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_apm_event_client/unpack_processor_events.test.ts +++ b/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_apm_event_client/unpack_processor_events.test.ts @@ -6,7 +6,7 @@ */ import { APMEventESSearchRequest } from '.'; -import { ApmIndicesConfig } from '../../../settings/apm_indices/get_apm_indices'; +import { ApmIndicesConfig } from '../../../../routes/settings/apm_indices/get_apm_indices'; import { unpackProcessorEvents } from './unpack_processor_events'; describe('unpackProcessorEvents', () => { diff --git a/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_apm_event_client/unpack_processor_events.ts b/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_apm_event_client/unpack_processor_events.ts index 582fe0374c5ca..e62720e9fbd0c 100644 --- a/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_apm_event_client/unpack_processor_events.ts +++ b/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_apm_event_client/unpack_processor_events.ts @@ -13,7 +13,7 @@ import { ESFilter, } from '../../../../../../../../src/core/types/elasticsearch'; import { APMEventESSearchRequest, APMEventESTermsEnumRequest } from '.'; -import { ApmIndicesConfig } from '../../../settings/apm_indices/get_apm_indices'; +import { ApmIndicesConfig } from '../../../../routes/settings/apm_indices/get_apm_indices'; const processorEventIndexMap = { [ProcessorEvent.transaction]: 'transaction', diff --git a/x-pack/plugins/apm/server/lib/helpers/setup_request.test.ts b/x-pack/plugins/apm/server/lib/helpers/setup_request.test.ts index 7b3201095106e..ffcbe01b7f043 100644 --- a/x-pack/plugins/apm/server/lib/helpers/setup_request.test.ts +++ b/x-pack/plugins/apm/server/lib/helpers/setup_request.test.ts @@ -10,10 +10,10 @@ import { APMConfig } from '../..'; import { APMRouteHandlerResources } from '../../routes/typings'; import { ProcessorEvent } from '../../../common/processor_event'; import { PROCESSOR_EVENT } from '../../../common/elasticsearch_fieldnames'; -import { getApmIndices } from '../settings/apm_indices/get_apm_indices'; +import { getApmIndices } from '../../routes/settings/apm_indices/get_apm_indices'; import { PromiseReturnType } from '../../../../observability/typings/common'; -jest.mock('../settings/apm_indices/get_apm_indices', () => ({ +jest.mock('../../routes/settings/apm_indices/get_apm_indices', () => ({ getApmIndices: async () => ({ sourcemap: 'apm-*', @@ -26,7 +26,7 @@ jest.mock('../settings/apm_indices/get_apm_indices', () => ({ } as PromiseReturnType), })); -jest.mock('../data_view/get_dynamic_data_view', () => ({ +jest.mock('../../routes/data_view/get_dynamic_data_view', () => ({ getDynamicDataView: async () => { return; }, diff --git a/x-pack/plugins/apm/server/lib/helpers/setup_request.ts b/x-pack/plugins/apm/server/lib/helpers/setup_request.ts index a0d908c68d84d..85fb94dd765b0 100644 --- a/x-pack/plugins/apm/server/lib/helpers/setup_request.ts +++ b/x-pack/plugins/apm/server/lib/helpers/setup_request.ts @@ -13,7 +13,7 @@ import { APMRouteHandlerResources } from '../../routes/typings'; import { ApmIndicesConfig, getApmIndices, -} from '../settings/apm_indices/get_apm_indices'; +} from '../../routes/settings/apm_indices/get_apm_indices'; import { APMEventClient, createApmEventClient, diff --git a/x-pack/plugins/apm/server/plugin.ts b/x-pack/plugins/apm/server/plugin.ts index b273fc867e5a8..9ece2c507847e 100644 --- a/x-pack/plugins/apm/server/plugin.ts +++ b/x-pack/plugins/apm/server/plugin.ts @@ -20,14 +20,14 @@ import { Dataset } from '../../rule_registry/server'; import { APMConfig, APM_SERVER_FEATURE_ID } from '.'; import { UI_SETTINGS } from '../../../../src/plugins/data/common'; import { APM_FEATURE, registerFeaturesUsage } from './feature'; -import { registerApmAlerts } from './lib/alerts/register_apm_alerts'; -import { registerFleetPolicyCallbacks } from './lib/fleet/register_fleet_policy_callbacks'; +import { registerApmAlerts } from './routes/alerts/register_apm_alerts'; +import { registerFleetPolicyCallbacks } from './routes/fleet/register_fleet_policy_callbacks'; import { createApmTelemetry } from './lib/apm_telemetry'; import { createApmEventClient } from './lib/helpers/create_es_client/create_apm_event_client'; import { getInternalSavedObjectsClient } from './lib/helpers/get_internal_saved_objects_client'; -import { createApmAgentConfigurationIndex } from './lib/settings/agent_configuration/create_agent_config_index'; -import { getApmIndices } from './lib/settings/apm_indices/get_apm_indices'; -import { createApmCustomLinkIndex } from './lib/settings/custom_link/create_custom_link_index'; +import { createApmAgentConfigurationIndex } from './routes/settings/agent_configuration/create_agent_config_index'; +import { getApmIndices } from './routes/settings/apm_indices/get_apm_indices'; +import { createApmCustomLinkIndex } from './routes/settings/custom_link/create_custom_link_index'; import { apmIndices, apmTelemetry, apmServerSettings } from './saved_objects'; import type { ApmPluginRequestHandlerContext, diff --git a/x-pack/plugins/apm/server/projections/rum_page_load_transactions.ts b/x-pack/plugins/apm/server/projections/rum_page_load_transactions.ts index 6265ee71c27e1..e3e98cc3c1773 100644 --- a/x-pack/plugins/apm/server/projections/rum_page_load_transactions.ts +++ b/x-pack/plugins/apm/server/projections/rum_page_load_transactions.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { SetupUX } from '../routes/rum_client'; +import { SetupUX } from '../routes/rum_client/route'; import { AGENT_NAME, TRANSACTION_TYPE, @@ -14,7 +14,7 @@ import { import { rangeQuery } from '../../../observability/server'; import { ProcessorEvent } from '../../common/processor_event'; import { TRANSACTION_PAGE_LOAD } from '../../common/transaction_types'; -import { getEsFilter } from '../lib/rum_client/ui_filters/get_es_filter'; +import { getEsFilter } from '../routes/rum_client/ui_filters/get_es_filter'; export function getRumPageLoadTransactionsProjection({ setup, diff --git a/x-pack/plugins/apm/server/lib/alerts/action_variables.ts b/x-pack/plugins/apm/server/routes/alerts/action_variables.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/alerts/action_variables.ts rename to x-pack/plugins/apm/server/routes/alerts/action_variables.ts diff --git a/x-pack/plugins/apm/server/lib/alerts/alerting_es_client.ts b/x-pack/plugins/apm/server/routes/alerts/alerting_es_client.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/alerts/alerting_es_client.ts rename to x-pack/plugins/apm/server/routes/alerts/alerting_es_client.ts diff --git a/x-pack/plugins/apm/server/lib/alerts/chart_preview/get_transaction_duration.ts b/x-pack/plugins/apm/server/routes/alerts/chart_preview/get_transaction_duration.ts similarity index 94% rename from x-pack/plugins/apm/server/lib/alerts/chart_preview/get_transaction_duration.ts rename to x-pack/plugins/apm/server/routes/alerts/chart_preview/get_transaction_duration.ts index 693502d7629e8..0338f78a0a892 100644 --- a/x-pack/plugins/apm/server/lib/alerts/chart_preview/get_transaction_duration.ts +++ b/x-pack/plugins/apm/server/routes/alerts/chart_preview/get_transaction_duration.ts @@ -12,14 +12,14 @@ import { TRANSACTION_TYPE, } from '../../../../common/elasticsearch_fieldnames'; import { environmentQuery } from '../../../../common/utils/environment_query'; -import { AlertParams } from '../../../routes/alerts/chart_preview'; +import { AlertParams } from '../route'; import { getSearchAggregatedTransactions, getDocumentTypeFilterForTransactions, getTransactionDurationFieldForTransactions, getProcessorEventForTransactions, -} from '../../helpers/transactions'; -import { Setup } from '../../helpers/setup_request'; +} from '../../../lib/helpers/transactions'; +import { Setup } from '../../../lib/helpers/setup_request'; export async function getTransactionDurationChartPreview({ alertParams, diff --git a/x-pack/plugins/apm/server/lib/alerts/chart_preview/get_transaction_error_count.ts b/x-pack/plugins/apm/server/routes/alerts/chart_preview/get_transaction_error_count.ts similarity index 93% rename from x-pack/plugins/apm/server/lib/alerts/chart_preview/get_transaction_error_count.ts rename to x-pack/plugins/apm/server/routes/alerts/chart_preview/get_transaction_error_count.ts index 0e1fa74199f60..708acd6d7f8ea 100644 --- a/x-pack/plugins/apm/server/lib/alerts/chart_preview/get_transaction_error_count.ts +++ b/x-pack/plugins/apm/server/routes/alerts/chart_preview/get_transaction_error_count.ts @@ -7,10 +7,10 @@ import { SERVICE_NAME } from '../../../../common/elasticsearch_fieldnames'; import { ProcessorEvent } from '../../../../common/processor_event'; -import { AlertParams } from '../../../routes/alerts/chart_preview'; +import { AlertParams } from '../route'; import { rangeQuery, termQuery } from '../../../../../observability/server'; import { environmentQuery } from '../../../../common/utils/environment_query'; -import { Setup } from '../../helpers/setup_request'; +import { Setup } from '../../../lib/helpers/setup_request'; export async function getTransactionErrorCountChartPreview({ setup, diff --git a/x-pack/plugins/apm/server/lib/alerts/chart_preview/get_transaction_error_rate.ts b/x-pack/plugins/apm/server/routes/alerts/chart_preview/get_transaction_error_rate.ts similarity index 91% rename from x-pack/plugins/apm/server/lib/alerts/chart_preview/get_transaction_error_rate.ts rename to x-pack/plugins/apm/server/routes/alerts/chart_preview/get_transaction_error_rate.ts index e2bfaf29f83cb..cf3380c105ac8 100644 --- a/x-pack/plugins/apm/server/lib/alerts/chart_preview/get_transaction_error_rate.ts +++ b/x-pack/plugins/apm/server/routes/alerts/chart_preview/get_transaction_error_rate.ts @@ -11,17 +11,17 @@ import { TRANSACTION_TYPE, } from '../../../../common/elasticsearch_fieldnames'; import { environmentQuery } from '../../../../common/utils/environment_query'; -import { AlertParams } from '../../../routes/alerts/chart_preview'; +import { AlertParams } from '../route'; import { getSearchAggregatedTransactions, getDocumentTypeFilterForTransactions, getProcessorEventForTransactions, -} from '../../helpers/transactions'; -import { Setup } from '../../helpers/setup_request'; +} from '../../../lib/helpers/transactions'; +import { Setup } from '../../../lib/helpers/setup_request'; import { calculateFailedTransactionRate, getOutcomeAggregation, -} from '../../helpers/transaction_error_rate'; +} from '../../../lib/helpers/transaction_error_rate'; export async function getTransactionErrorRateChartPreview({ setup, diff --git a/x-pack/plugins/apm/server/lib/alerts/register_apm_alerts.ts b/x-pack/plugins/apm/server/routes/alerts/register_apm_alerts.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/alerts/register_apm_alerts.ts rename to x-pack/plugins/apm/server/routes/alerts/register_apm_alerts.ts diff --git a/x-pack/plugins/apm/server/lib/alerts/register_error_count_alert_type.test.ts b/x-pack/plugins/apm/server/routes/alerts/register_error_count_alert_type.test.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/alerts/register_error_count_alert_type.test.ts rename to x-pack/plugins/apm/server/routes/alerts/register_error_count_alert_type.test.ts diff --git a/x-pack/plugins/apm/server/lib/alerts/register_error_count_alert_type.ts b/x-pack/plugins/apm/server/routes/alerts/register_error_count_alert_type.ts similarity index 98% rename from x-pack/plugins/apm/server/lib/alerts/register_error_count_alert_type.ts rename to x-pack/plugins/apm/server/routes/alerts/register_error_count_alert_type.ts index 723f52cb1eeda..2dacb5ca1e895 100644 --- a/x-pack/plugins/apm/server/lib/alerts/register_error_count_alert_type.ts +++ b/x-pack/plugins/apm/server/routes/alerts/register_error_count_alert_type.ts @@ -31,7 +31,7 @@ import { } from '../../../common/elasticsearch_fieldnames'; import { ProcessorEvent } from '../../../common/processor_event'; import { environmentQuery } from '../../../common/utils/environment_query'; -import { getApmIndices } from '../settings/apm_indices/get_apm_indices'; +import { getApmIndices } from '../../routes/settings/apm_indices/get_apm_indices'; import { apmActionVariables } from './action_variables'; import { alertingEsClient } from './alerting_es_client'; import { RegisterRuleDependencies } from './register_apm_alerts'; diff --git a/x-pack/plugins/apm/server/lib/alerts/register_transaction_duration_alert_type.test.ts b/x-pack/plugins/apm/server/routes/alerts/register_transaction_duration_alert_type.test.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/alerts/register_transaction_duration_alert_type.test.ts rename to x-pack/plugins/apm/server/routes/alerts/register_transaction_duration_alert_type.test.ts diff --git a/x-pack/plugins/apm/server/lib/alerts/register_transaction_duration_alert_type.ts b/x-pack/plugins/apm/server/routes/alerts/register_transaction_duration_alert_type.ts similarity index 98% rename from x-pack/plugins/apm/server/lib/alerts/register_transaction_duration_alert_type.ts rename to x-pack/plugins/apm/server/routes/alerts/register_transaction_duration_alert_type.ts index 4e68ca6b52248..1e39b02655ada 100644 --- a/x-pack/plugins/apm/server/lib/alerts/register_transaction_duration_alert_type.ts +++ b/x-pack/plugins/apm/server/routes/alerts/register_transaction_duration_alert_type.ts @@ -37,8 +37,8 @@ import { getDurationFormatter } from '../../../common/utils/formatters'; import { getDocumentTypeFilterForTransactions, getTransactionDurationFieldForTransactions, -} from '../helpers/transactions'; -import { getApmIndices } from '../settings/apm_indices/get_apm_indices'; +} from '../../lib/helpers/transactions'; +import { getApmIndices } from '../../routes/settings/apm_indices/get_apm_indices'; import { apmActionVariables } from './action_variables'; import { alertingEsClient } from './alerting_es_client'; import { RegisterRuleDependencies } from './register_apm_alerts'; diff --git a/x-pack/plugins/apm/server/lib/alerts/register_transaction_duration_anomaly_alert_type.test.ts b/x-pack/plugins/apm/server/routes/alerts/register_transaction_duration_anomaly_alert_type.test.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/alerts/register_transaction_duration_anomaly_alert_type.test.ts rename to x-pack/plugins/apm/server/routes/alerts/register_transaction_duration_anomaly_alert_type.test.ts diff --git a/x-pack/plugins/apm/server/lib/alerts/register_transaction_duration_anomaly_alert_type.ts b/x-pack/plugins/apm/server/routes/alerts/register_transaction_duration_anomaly_alert_type.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/alerts/register_transaction_duration_anomaly_alert_type.ts rename to x-pack/plugins/apm/server/routes/alerts/register_transaction_duration_anomaly_alert_type.ts diff --git a/x-pack/plugins/apm/server/lib/alerts/register_transaction_error_rate_alert_type.test.ts b/x-pack/plugins/apm/server/routes/alerts/register_transaction_error_rate_alert_type.test.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/alerts/register_transaction_error_rate_alert_type.test.ts rename to x-pack/plugins/apm/server/routes/alerts/register_transaction_error_rate_alert_type.test.ts diff --git a/x-pack/plugins/apm/server/lib/alerts/register_transaction_error_rate_alert_type.ts b/x-pack/plugins/apm/server/routes/alerts/register_transaction_error_rate_alert_type.ts similarity index 97% rename from x-pack/plugins/apm/server/lib/alerts/register_transaction_error_rate_alert_type.ts rename to x-pack/plugins/apm/server/routes/alerts/register_transaction_error_rate_alert_type.ts index cf5b45d901228..f196b718968da 100644 --- a/x-pack/plugins/apm/server/lib/alerts/register_transaction_error_rate_alert_type.ts +++ b/x-pack/plugins/apm/server/routes/alerts/register_transaction_error_rate_alert_type.ts @@ -35,12 +35,12 @@ import { EventOutcome } from '../../../common/event_outcome'; import { ProcessorEvent } from '../../../common/processor_event'; import { asDecimalOrInteger } from '../../../common/utils/formatters'; import { environmentQuery } from '../../../common/utils/environment_query'; -import { getApmIndices } from '../settings/apm_indices/get_apm_indices'; +import { getApmIndices } from '../../routes/settings/apm_indices/get_apm_indices'; import { apmActionVariables } from './action_variables'; import { alertingEsClient } from './alerting_es_client'; import { RegisterRuleDependencies } from './register_apm_alerts'; import { SearchAggregatedTransactionSetting } from '../../../common/aggregated_transactions'; -import { getDocumentTypeFilterForTransactions } from '../helpers/transactions'; +import { getDocumentTypeFilterForTransactions } from '../../lib/helpers/transactions'; import { asPercent } from '../../../../observability/common/utils/formatters'; import { termQuery } from '../../../../observability/server'; diff --git a/x-pack/plugins/apm/server/routes/alerts/chart_preview.ts b/x-pack/plugins/apm/server/routes/alerts/route.ts similarity index 89% rename from x-pack/plugins/apm/server/routes/alerts/chart_preview.ts rename to x-pack/plugins/apm/server/routes/alerts/route.ts index cae35c7f06a85..49baeda8d3a47 100644 --- a/x-pack/plugins/apm/server/routes/alerts/chart_preview.ts +++ b/x-pack/plugins/apm/server/routes/alerts/route.ts @@ -6,9 +6,9 @@ */ import * as t from 'io-ts'; -import { getTransactionDurationChartPreview } from '../../lib/alerts/chart_preview/get_transaction_duration'; -import { getTransactionErrorCountChartPreview } from '../../lib/alerts/chart_preview/get_transaction_error_count'; -import { getTransactionErrorRateChartPreview } from '../../lib/alerts/chart_preview/get_transaction_error_rate'; +import { getTransactionDurationChartPreview } from './chart_preview/get_transaction_duration'; +import { getTransactionErrorCountChartPreview } from './chart_preview/get_transaction_error_count'; +import { getTransactionErrorRateChartPreview } from './chart_preview/get_transaction_error_rate'; import { setupRequest } from '../../lib/helpers/setup_request'; import { createApmServerRoute } from '../apm_routes/create_apm_server_route'; import { createApmServerRouteRepository } from '../apm_routes/create_apm_server_route_repository'; diff --git a/x-pack/plugins/apm/server/lib/alerts/test_utils/index.ts b/x-pack/plugins/apm/server/routes/alerts/test_utils/index.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/alerts/test_utils/index.ts rename to x-pack/plugins/apm/server/routes/alerts/test_utils/index.ts diff --git a/x-pack/plugins/apm/server/routes/apm_routes/get_global_apm_server_route_repository.ts b/x-pack/plugins/apm/server/routes/apm_routes/get_global_apm_server_route_repository.ts index fa8bc1e54ebfb..ee4c9d1c8cfa5 100644 --- a/x-pack/plugins/apm/server/routes/apm_routes/get_global_apm_server_route_repository.ts +++ b/x-pack/plugins/apm/server/routes/apm_routes/get_global_apm_server_route_repository.ts @@ -10,33 +10,33 @@ import type { EndpointOf, } from '@kbn/server-route-repository'; import { PickByValue } from 'utility-types'; -import { correlationsRouteRepository } from '../correlations'; -import { alertsChartPreviewRouteRepository } from '../alerts/chart_preview'; +import { correlationsRouteRepository } from '../correlations/route'; +import { alertsChartPreviewRouteRepository } from '../alerts/route'; import { backendsRouteRepository } from '../backends/route'; import { createApmServerRouteRepository } from '../apm_routes/create_apm_server_route_repository'; -import { environmentsRouteRepository } from '../environments'; -import { errorsRouteRepository } from '../errors'; -import { apmFleetRouteRepository } from '../fleet'; -import { dataViewRouteRepository } from '../data_view'; -import { latencyDistributionRouteRepository } from '../latency_distribution'; -import { metricsRouteRepository } from '../metrics'; -import { observabilityOverviewRouteRepository } from '../observability_overview'; -import { rumRouteRepository } from '../rum_client'; -import { fallbackToTransactionsRouteRepository } from '../fallback_to_transactions'; -import { serviceRouteRepository } from '../services'; -import { serviceMapRouteRepository } from '../service_map'; -import { serviceNodeRouteRepository } from '../service_nodes'; -import { agentConfigurationRouteRepository } from '../settings/agent_configuration'; -import { anomalyDetectionRouteRepository } from '../settings/anomaly_detection'; -import { apmIndicesRouteRepository } from '../settings/apm_indices'; -import { customLinkRouteRepository } from '../settings/custom_link'; -import { sourceMapsRouteRepository } from '../source_maps'; -import { traceRouteRepository } from '../traces'; -import { transactionRouteRepository } from '../transactions'; +import { environmentsRouteRepository } from '../environments/route'; +import { errorsRouteRepository } from '../errors/route'; +import { apmFleetRouteRepository } from '../fleet/route'; +import { dataViewRouteRepository } from '../data_view/route'; +import { latencyDistributionRouteRepository } from '../latency_distribution/route'; +import { metricsRouteRepository } from '../metrics/route'; +import { observabilityOverviewRouteRepository } from '../observability_overview/route'; +import { rumRouteRepository } from '../rum_client/route'; +import { fallbackToTransactionsRouteRepository } from '../fallback_to_transactions/route'; +import { serviceRouteRepository } from '../services/route'; +import { serviceMapRouteRepository } from '../service_map/route'; +import { serviceNodeRouteRepository } from '../service_nodes/route'; +import { agentConfigurationRouteRepository } from '../settings/agent_configuration/route'; +import { anomalyDetectionRouteRepository } from '../settings/anomaly_detection/route'; +import { apmIndicesRouteRepository } from '../settings/apm_indices/route'; +import { customLinkRouteRepository } from '../settings/custom_link/route'; +import { sourceMapsRouteRepository } from '../source_maps/route'; +import { traceRouteRepository } from '../traces/route'; +import { transactionRouteRepository } from '../transactions/route'; import { APMRouteHandlerResources } from '../typings'; import { historicalDataRouteRepository } from '../historical_data'; -import { eventMetadataRouteRepository } from '../event_metadata'; -import { suggestionsRouteRepository } from '../suggestions'; +import { eventMetadataRouteRepository } from '../event_metadata/route'; +import { suggestionsRouteRepository } from '../suggestions/route'; const getTypedGlobalApmServerRouteRepository = () => { const repository = createApmServerRouteRepository() diff --git a/x-pack/plugins/apm/server/lib/correlations/queries/field_stats/get_boolean_field_stats.ts b/x-pack/plugins/apm/server/routes/correlations/queries/field_stats/get_boolean_field_stats.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/correlations/queries/field_stats/get_boolean_field_stats.ts rename to x-pack/plugins/apm/server/routes/correlations/queries/field_stats/get_boolean_field_stats.ts diff --git a/x-pack/plugins/apm/server/lib/correlations/queries/field_stats/get_field_stats.test.ts b/x-pack/plugins/apm/server/routes/correlations/queries/field_stats/get_field_stats.test.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/correlations/queries/field_stats/get_field_stats.test.ts rename to x-pack/plugins/apm/server/routes/correlations/queries/field_stats/get_field_stats.test.ts diff --git a/x-pack/plugins/apm/server/lib/correlations/queries/field_stats/get_fields_stats.ts b/x-pack/plugins/apm/server/routes/correlations/queries/field_stats/get_fields_stats.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/correlations/queries/field_stats/get_fields_stats.ts rename to x-pack/plugins/apm/server/routes/correlations/queries/field_stats/get_fields_stats.ts diff --git a/x-pack/plugins/apm/server/lib/correlations/queries/field_stats/get_keyword_field_stats.ts b/x-pack/plugins/apm/server/routes/correlations/queries/field_stats/get_keyword_field_stats.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/correlations/queries/field_stats/get_keyword_field_stats.ts rename to x-pack/plugins/apm/server/routes/correlations/queries/field_stats/get_keyword_field_stats.ts diff --git a/x-pack/plugins/apm/server/lib/correlations/queries/field_stats/get_numeric_field_stats.ts b/x-pack/plugins/apm/server/routes/correlations/queries/field_stats/get_numeric_field_stats.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/correlations/queries/field_stats/get_numeric_field_stats.ts rename to x-pack/plugins/apm/server/routes/correlations/queries/field_stats/get_numeric_field_stats.ts diff --git a/x-pack/plugins/apm/server/lib/correlations/queries/get_filters.ts b/x-pack/plugins/apm/server/routes/correlations/queries/get_filters.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/correlations/queries/get_filters.ts rename to x-pack/plugins/apm/server/routes/correlations/queries/get_filters.ts diff --git a/x-pack/plugins/apm/server/lib/correlations/queries/get_query_with_params.test.ts b/x-pack/plugins/apm/server/routes/correlations/queries/get_query_with_params.test.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/correlations/queries/get_query_with_params.test.ts rename to x-pack/plugins/apm/server/routes/correlations/queries/get_query_with_params.test.ts diff --git a/x-pack/plugins/apm/server/lib/correlations/queries/get_query_with_params.ts b/x-pack/plugins/apm/server/routes/correlations/queries/get_query_with_params.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/correlations/queries/get_query_with_params.ts rename to x-pack/plugins/apm/server/routes/correlations/queries/get_query_with_params.ts diff --git a/x-pack/plugins/apm/server/lib/correlations/queries/get_request_base.test.ts b/x-pack/plugins/apm/server/routes/correlations/queries/get_request_base.test.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/correlations/queries/get_request_base.test.ts rename to x-pack/plugins/apm/server/routes/correlations/queries/get_request_base.test.ts diff --git a/x-pack/plugins/apm/server/lib/correlations/queries/get_request_base.ts b/x-pack/plugins/apm/server/routes/correlations/queries/get_request_base.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/correlations/queries/get_request_base.ts rename to x-pack/plugins/apm/server/routes/correlations/queries/get_request_base.ts diff --git a/x-pack/plugins/apm/server/lib/correlations/queries/index.ts b/x-pack/plugins/apm/server/routes/correlations/queries/index.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/correlations/queries/index.ts rename to x-pack/plugins/apm/server/routes/correlations/queries/index.ts diff --git a/x-pack/plugins/apm/server/lib/correlations/queries/query_correlation.test.ts b/x-pack/plugins/apm/server/routes/correlations/queries/query_correlation.test.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/correlations/queries/query_correlation.test.ts rename to x-pack/plugins/apm/server/routes/correlations/queries/query_correlation.test.ts diff --git a/x-pack/plugins/apm/server/lib/correlations/queries/query_correlation.ts b/x-pack/plugins/apm/server/routes/correlations/queries/query_correlation.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/correlations/queries/query_correlation.ts rename to x-pack/plugins/apm/server/routes/correlations/queries/query_correlation.ts diff --git a/x-pack/plugins/apm/server/lib/correlations/queries/query_correlation_with_histogram.test.ts b/x-pack/plugins/apm/server/routes/correlations/queries/query_correlation_with_histogram.test.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/correlations/queries/query_correlation_with_histogram.test.ts rename to x-pack/plugins/apm/server/routes/correlations/queries/query_correlation_with_histogram.test.ts diff --git a/x-pack/plugins/apm/server/lib/correlations/queries/query_correlation_with_histogram.ts b/x-pack/plugins/apm/server/routes/correlations/queries/query_correlation_with_histogram.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/correlations/queries/query_correlation_with_histogram.ts rename to x-pack/plugins/apm/server/routes/correlations/queries/query_correlation_with_histogram.ts diff --git a/x-pack/plugins/apm/server/lib/correlations/queries/query_failure_correlation.ts b/x-pack/plugins/apm/server/routes/correlations/queries/query_failure_correlation.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/correlations/queries/query_failure_correlation.ts rename to x-pack/plugins/apm/server/routes/correlations/queries/query_failure_correlation.ts diff --git a/x-pack/plugins/apm/server/lib/correlations/queries/query_field_candidates.test.ts b/x-pack/plugins/apm/server/routes/correlations/queries/query_field_candidates.test.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/correlations/queries/query_field_candidates.test.ts rename to x-pack/plugins/apm/server/routes/correlations/queries/query_field_candidates.test.ts diff --git a/x-pack/plugins/apm/server/lib/correlations/queries/query_field_candidates.ts b/x-pack/plugins/apm/server/routes/correlations/queries/query_field_candidates.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/correlations/queries/query_field_candidates.ts rename to x-pack/plugins/apm/server/routes/correlations/queries/query_field_candidates.ts diff --git a/x-pack/plugins/apm/server/lib/correlations/queries/query_field_value_pairs.test.ts b/x-pack/plugins/apm/server/routes/correlations/queries/query_field_value_pairs.test.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/correlations/queries/query_field_value_pairs.test.ts rename to x-pack/plugins/apm/server/routes/correlations/queries/query_field_value_pairs.test.ts diff --git a/x-pack/plugins/apm/server/lib/correlations/queries/query_field_value_pairs.ts b/x-pack/plugins/apm/server/routes/correlations/queries/query_field_value_pairs.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/correlations/queries/query_field_value_pairs.ts rename to x-pack/plugins/apm/server/routes/correlations/queries/query_field_value_pairs.ts diff --git a/x-pack/plugins/apm/server/lib/correlations/queries/query_fractions.test.ts b/x-pack/plugins/apm/server/routes/correlations/queries/query_fractions.test.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/correlations/queries/query_fractions.test.ts rename to x-pack/plugins/apm/server/routes/correlations/queries/query_fractions.test.ts diff --git a/x-pack/plugins/apm/server/lib/correlations/queries/query_fractions.ts b/x-pack/plugins/apm/server/routes/correlations/queries/query_fractions.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/correlations/queries/query_fractions.ts rename to x-pack/plugins/apm/server/routes/correlations/queries/query_fractions.ts diff --git a/x-pack/plugins/apm/server/lib/correlations/queries/query_histogram.test.ts b/x-pack/plugins/apm/server/routes/correlations/queries/query_histogram.test.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/correlations/queries/query_histogram.test.ts rename to x-pack/plugins/apm/server/routes/correlations/queries/query_histogram.test.ts diff --git a/x-pack/plugins/apm/server/lib/correlations/queries/query_histogram.ts b/x-pack/plugins/apm/server/routes/correlations/queries/query_histogram.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/correlations/queries/query_histogram.ts rename to x-pack/plugins/apm/server/routes/correlations/queries/query_histogram.ts diff --git a/x-pack/plugins/apm/server/lib/correlations/queries/query_histogram_range_steps.test.ts b/x-pack/plugins/apm/server/routes/correlations/queries/query_histogram_range_steps.test.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/correlations/queries/query_histogram_range_steps.test.ts rename to x-pack/plugins/apm/server/routes/correlations/queries/query_histogram_range_steps.test.ts diff --git a/x-pack/plugins/apm/server/lib/correlations/queries/query_histogram_range_steps.ts b/x-pack/plugins/apm/server/routes/correlations/queries/query_histogram_range_steps.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/correlations/queries/query_histogram_range_steps.ts rename to x-pack/plugins/apm/server/routes/correlations/queries/query_histogram_range_steps.ts diff --git a/x-pack/plugins/apm/server/lib/correlations/queries/query_p_values.ts b/x-pack/plugins/apm/server/routes/correlations/queries/query_p_values.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/correlations/queries/query_p_values.ts rename to x-pack/plugins/apm/server/routes/correlations/queries/query_p_values.ts diff --git a/x-pack/plugins/apm/server/lib/correlations/queries/query_percentiles.test.ts b/x-pack/plugins/apm/server/routes/correlations/queries/query_percentiles.test.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/correlations/queries/query_percentiles.test.ts rename to x-pack/plugins/apm/server/routes/correlations/queries/query_percentiles.test.ts diff --git a/x-pack/plugins/apm/server/lib/correlations/queries/query_percentiles.ts b/x-pack/plugins/apm/server/routes/correlations/queries/query_percentiles.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/correlations/queries/query_percentiles.ts rename to x-pack/plugins/apm/server/routes/correlations/queries/query_percentiles.ts diff --git a/x-pack/plugins/apm/server/lib/correlations/queries/query_ranges.test.ts b/x-pack/plugins/apm/server/routes/correlations/queries/query_ranges.test.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/correlations/queries/query_ranges.test.ts rename to x-pack/plugins/apm/server/routes/correlations/queries/query_ranges.test.ts diff --git a/x-pack/plugins/apm/server/lib/correlations/queries/query_ranges.ts b/x-pack/plugins/apm/server/routes/correlations/queries/query_ranges.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/correlations/queries/query_ranges.ts rename to x-pack/plugins/apm/server/routes/correlations/queries/query_ranges.ts diff --git a/x-pack/plugins/apm/server/lib/correlations/queries/query_significant_correlations.ts b/x-pack/plugins/apm/server/routes/correlations/queries/query_significant_correlations.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/correlations/queries/query_significant_correlations.ts rename to x-pack/plugins/apm/server/routes/correlations/queries/query_significant_correlations.ts diff --git a/x-pack/plugins/apm/server/routes/correlations.ts b/x-pack/plugins/apm/server/routes/correlations/route.ts similarity index 92% rename from x-pack/plugins/apm/server/routes/correlations.ts rename to x-pack/plugins/apm/server/routes/correlations/route.ts index f6ca064b4385f..b02a6fbc6b7a6 100644 --- a/x-pack/plugins/apm/server/routes/correlations.ts +++ b/x-pack/plugins/apm/server/routes/correlations/route.ts @@ -11,22 +11,22 @@ import Boom from '@hapi/boom'; import { i18n } from '@kbn/i18n'; import { toNumberRt } from '@kbn/io-ts-utils/to_number_rt'; -import { isActivePlatinumLicense } from '../../common/license_check'; +import { isActivePlatinumLicense } from '../../../common/license_check'; -import { setupRequest } from '../lib/helpers/setup_request'; +import { setupRequest } from '../../lib/helpers/setup_request'; import { fetchPValues, fetchSignificantCorrelations, fetchTransactionDurationFieldCandidates, fetchTransactionDurationFieldValuePairs, -} from '../lib/correlations/queries'; -import { fetchFieldsStats } from '../lib/correlations/queries/field_stats/get_fields_stats'; +} from './queries'; +import { fetchFieldsStats } from './queries/field_stats/get_fields_stats'; -import { withApmSpan } from '../utils/with_apm_span'; +import { withApmSpan } from '../../utils/with_apm_span'; -import { createApmServerRoute } from './apm_routes/create_apm_server_route'; -import { createApmServerRouteRepository } from './apm_routes/create_apm_server_route_repository'; -import { environmentRt, kueryRt, rangeRt } from './default_api_types'; +import { createApmServerRoute } from '../apm_routes/create_apm_server_route'; +import { createApmServerRouteRepository } from '../apm_routes/create_apm_server_route_repository'; +import { environmentRt, kueryRt, rangeRt } from '../default_api_types'; const INVALID_LICENSE = i18n.translate('xpack.apm.correlations.license.text', { defaultMessage: diff --git a/x-pack/plugins/apm/server/lib/correlations/utils/compute_expectations_and_ranges.test.ts b/x-pack/plugins/apm/server/routes/correlations/utils/compute_expectations_and_ranges.test.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/correlations/utils/compute_expectations_and_ranges.test.ts rename to x-pack/plugins/apm/server/routes/correlations/utils/compute_expectations_and_ranges.test.ts diff --git a/x-pack/plugins/apm/server/lib/correlations/utils/compute_expectations_and_ranges.ts b/x-pack/plugins/apm/server/routes/correlations/utils/compute_expectations_and_ranges.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/correlations/utils/compute_expectations_and_ranges.ts rename to x-pack/plugins/apm/server/routes/correlations/utils/compute_expectations_and_ranges.ts diff --git a/x-pack/plugins/apm/server/lib/correlations/utils/field_stats_utils.ts b/x-pack/plugins/apm/server/routes/correlations/utils/field_stats_utils.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/correlations/utils/field_stats_utils.ts rename to x-pack/plugins/apm/server/routes/correlations/utils/field_stats_utils.ts diff --git a/x-pack/plugins/apm/server/lib/correlations/utils/index.ts b/x-pack/plugins/apm/server/routes/correlations/utils/index.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/correlations/utils/index.ts rename to x-pack/plugins/apm/server/routes/correlations/utils/index.ts diff --git a/x-pack/plugins/apm/server/lib/correlations/utils/split_all_settled_promises.ts b/x-pack/plugins/apm/server/routes/correlations/utils/split_all_settled_promises.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/correlations/utils/split_all_settled_promises.ts rename to x-pack/plugins/apm/server/routes/correlations/utils/split_all_settled_promises.ts diff --git a/x-pack/plugins/apm/server/lib/data_view/create_static_data_view.test.ts b/x-pack/plugins/apm/server/routes/data_view/create_static_data_view.test.ts similarity index 96% rename from x-pack/plugins/apm/server/lib/data_view/create_static_data_view.test.ts rename to x-pack/plugins/apm/server/routes/data_view/create_static_data_view.test.ts index 77b9f0ffd4ad0..7d345b5e3bec1 100644 --- a/x-pack/plugins/apm/server/lib/data_view/create_static_data_view.test.ts +++ b/x-pack/plugins/apm/server/routes/data_view/create_static_data_view.test.ts @@ -6,9 +6,9 @@ */ import { createStaticDataView } from './create_static_data_view'; -import { Setup } from '../helpers/setup_request'; +import { Setup } from '../../lib/helpers/setup_request'; import * as HistoricalAgentData from '../../routes/historical_data/has_historical_agent_data'; -import { InternalSavedObjectsClient } from '../helpers/get_internal_saved_objects_client'; +import { InternalSavedObjectsClient } from '../../lib/helpers/get_internal_saved_objects_client'; import { APMConfig } from '../..'; function getMockSavedObjectsClient(existingDataViewTitle: string) { diff --git a/x-pack/plugins/apm/server/lib/data_view/create_static_data_view.ts b/x-pack/plugins/apm/server/routes/data_view/create_static_data_view.ts similarity index 95% rename from x-pack/plugins/apm/server/lib/data_view/create_static_data_view.ts rename to x-pack/plugins/apm/server/routes/data_view/create_static_data_view.ts index 521d290b9ca22..13639d2efcbfe 100644 --- a/x-pack/plugins/apm/server/lib/data_view/create_static_data_view.ts +++ b/x-pack/plugins/apm/server/routes/data_view/create_static_data_view.ts @@ -9,9 +9,9 @@ import { SavedObjectsErrorHelpers } from '../../../../../../src/core/server'; import { APM_STATIC_INDEX_PATTERN_ID } from '../../../common/index_pattern_constants'; import apmDataView from '../../tutorial/index_pattern.json'; import { hasHistoricalAgentData } from '../../routes/historical_data/has_historical_agent_data'; -import { Setup } from '../helpers/setup_request'; +import { Setup } from '../../lib/helpers/setup_request'; import { APMRouteHandlerResources } from '../../routes/typings'; -import { InternalSavedObjectsClient } from '../helpers/get_internal_saved_objects_client.js'; +import { InternalSavedObjectsClient } from '../../lib/helpers/get_internal_saved_objects_client.js'; import { withApmSpan } from '../../utils/with_apm_span'; import { getApmDataViewTitle } from './get_apm_data_view_title'; diff --git a/x-pack/plugins/apm/server/lib/data_view/get_apm_data_view_title.test.ts b/x-pack/plugins/apm/server/routes/data_view/get_apm_data_view_title.test.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/data_view/get_apm_data_view_title.test.ts rename to x-pack/plugins/apm/server/routes/data_view/get_apm_data_view_title.test.ts diff --git a/x-pack/plugins/apm/server/lib/data_view/get_apm_data_view_title.ts b/x-pack/plugins/apm/server/routes/data_view/get_apm_data_view_title.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/data_view/get_apm_data_view_title.ts rename to x-pack/plugins/apm/server/routes/data_view/get_apm_data_view_title.ts diff --git a/x-pack/plugins/apm/server/lib/data_view/get_dynamic_data_view.ts b/x-pack/plugins/apm/server/routes/data_view/get_dynamic_data_view.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/data_view/get_dynamic_data_view.ts rename to x-pack/plugins/apm/server/routes/data_view/get_dynamic_data_view.ts diff --git a/x-pack/plugins/apm/server/routes/data_view.ts b/x-pack/plugins/apm/server/routes/data_view/route.ts similarity index 78% rename from x-pack/plugins/apm/server/routes/data_view.ts rename to x-pack/plugins/apm/server/routes/data_view/route.ts index 3590ef9db9bd0..4e1c0ca050a09 100644 --- a/x-pack/plugins/apm/server/routes/data_view.ts +++ b/x-pack/plugins/apm/server/routes/data_view/route.ts @@ -5,11 +5,11 @@ * 2.0. */ -import { createStaticDataView } from '../lib/data_view/create_static_data_view'; -import { createApmServerRouteRepository } from './apm_routes/create_apm_server_route_repository'; -import { setupRequest } from '../lib/helpers/setup_request'; -import { getDynamicDataView } from '../lib/data_view/get_dynamic_data_view'; -import { createApmServerRoute } from './apm_routes/create_apm_server_route'; +import { createStaticDataView } from './create_static_data_view'; +import { createApmServerRouteRepository } from '../apm_routes/create_apm_server_route_repository'; +import { setupRequest } from '../../lib/helpers/setup_request'; +import { getDynamicDataView } from './get_dynamic_data_view'; +import { createApmServerRoute } from '../apm_routes/create_apm_server_route'; const staticDataViewRoute = createApmServerRoute({ endpoint: 'POST /internal/apm/data_view/static', diff --git a/x-pack/plugins/apm/server/lib/environments/__snapshots__/get_all_environments.test.ts.snap b/x-pack/plugins/apm/server/routes/environments/__snapshots__/get_all_environments.test.ts.snap similarity index 100% rename from x-pack/plugins/apm/server/lib/environments/__snapshots__/get_all_environments.test.ts.snap rename to x-pack/plugins/apm/server/routes/environments/__snapshots__/get_all_environments.test.ts.snap diff --git a/x-pack/plugins/apm/server/lib/environments/__snapshots__/get_environments.test.ts.snap b/x-pack/plugins/apm/server/routes/environments/__snapshots__/get_environments.test.ts.snap similarity index 100% rename from x-pack/plugins/apm/server/lib/environments/__snapshots__/get_environments.test.ts.snap rename to x-pack/plugins/apm/server/routes/environments/__snapshots__/get_environments.test.ts.snap diff --git a/x-pack/plugins/apm/server/lib/environments/get_all_environments.test.ts b/x-pack/plugins/apm/server/routes/environments/get_all_environments.test.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/environments/get_all_environments.test.ts rename to x-pack/plugins/apm/server/routes/environments/get_all_environments.test.ts diff --git a/x-pack/plugins/apm/server/lib/environments/get_all_environments.ts b/x-pack/plugins/apm/server/routes/environments/get_all_environments.ts similarity index 93% rename from x-pack/plugins/apm/server/lib/environments/get_all_environments.ts rename to x-pack/plugins/apm/server/routes/environments/get_all_environments.ts index 7bdb21b9fda78..f479fd185b889 100644 --- a/x-pack/plugins/apm/server/lib/environments/get_all_environments.ts +++ b/x-pack/plugins/apm/server/routes/environments/get_all_environments.ts @@ -7,13 +7,13 @@ import { termQuery } from '../../../../observability/server'; import { ProcessorEvent } from '../../../common/processor_event'; -import { Setup } from '../helpers/setup_request'; +import { Setup } from '../../lib/helpers/setup_request'; import { SERVICE_NAME, SERVICE_ENVIRONMENT, } from '../../../common/elasticsearch_fieldnames'; import { ENVIRONMENT_NOT_DEFINED } from '../../../common/environment_filter_values'; -import { getProcessorEventForTransactions } from '../helpers/transactions'; +import { getProcessorEventForTransactions } from '../../lib/helpers/transactions'; /** * This is used for getting *all* environments, and does not filter by range. diff --git a/x-pack/plugins/apm/server/lib/environments/get_environments.test.ts b/x-pack/plugins/apm/server/routes/environments/get_environments.test.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/environments/get_environments.test.ts rename to x-pack/plugins/apm/server/routes/environments/get_environments.test.ts diff --git a/x-pack/plugins/apm/server/lib/environments/get_environments.ts b/x-pack/plugins/apm/server/routes/environments/get_environments.ts similarity index 93% rename from x-pack/plugins/apm/server/lib/environments/get_environments.ts rename to x-pack/plugins/apm/server/routes/environments/get_environments.ts index cd5caab6d2587..34ac9cb18d796 100644 --- a/x-pack/plugins/apm/server/lib/environments/get_environments.ts +++ b/x-pack/plugins/apm/server/routes/environments/get_environments.ts @@ -12,8 +12,8 @@ import { import { ENVIRONMENT_NOT_DEFINED } from '../../../common/environment_filter_values'; import { ProcessorEvent } from '../../../common/processor_event'; import { rangeQuery, termQuery } from '../../../../observability/server'; -import { getProcessorEventForTransactions } from '../helpers/transactions'; -import { Setup } from '../helpers/setup_request'; +import { getProcessorEventForTransactions } from '../../lib/helpers/transactions'; +import { Setup } from '../../lib/helpers/setup_request'; /** * This is used for getting the list of environments for the environments selector, diff --git a/x-pack/plugins/apm/server/routes/environments.ts b/x-pack/plugins/apm/server/routes/environments/route.ts similarity index 72% rename from x-pack/plugins/apm/server/routes/environments.ts rename to x-pack/plugins/apm/server/routes/environments/route.ts index 38328a63a411e..6c980187cd331 100644 --- a/x-pack/plugins/apm/server/routes/environments.ts +++ b/x-pack/plugins/apm/server/routes/environments/route.ts @@ -6,13 +6,13 @@ */ import * as t from 'io-ts'; -import { maxSuggestions } from '../../../observability/common'; -import { getSearchAggregatedTransactions } from '../lib/helpers/transactions'; -import { setupRequest } from '../lib/helpers/setup_request'; -import { getEnvironments } from '../lib/environments/get_environments'; -import { rangeRt } from './default_api_types'; -import { createApmServerRoute } from './apm_routes/create_apm_server_route'; -import { createApmServerRouteRepository } from './apm_routes/create_apm_server_route_repository'; +import { maxSuggestions } from '../../../../observability/common'; +import { getSearchAggregatedTransactions } from '../../lib/helpers/transactions'; +import { setupRequest } from '../../lib/helpers/setup_request'; +import { getEnvironments } from './get_environments'; +import { rangeRt } from '../default_api_types'; +import { createApmServerRoute } from '../apm_routes/create_apm_server_route'; +import { createApmServerRouteRepository } from '../apm_routes/create_apm_server_route_repository'; const environmentsRoute = createApmServerRoute({ endpoint: 'GET /internal/apm/environments', diff --git a/x-pack/plugins/apm/server/lib/errors/__snapshots__/queries.test.ts.snap b/x-pack/plugins/apm/server/routes/errors/__snapshots__/queries.test.ts.snap similarity index 100% rename from x-pack/plugins/apm/server/lib/errors/__snapshots__/queries.test.ts.snap rename to x-pack/plugins/apm/server/routes/errors/__snapshots__/queries.test.ts.snap diff --git a/x-pack/plugins/apm/server/lib/errors/distribution/__snapshots__/get_buckets.test.ts.snap b/x-pack/plugins/apm/server/routes/errors/distribution/__snapshots__/get_buckets.test.ts.snap similarity index 100% rename from x-pack/plugins/apm/server/lib/errors/distribution/__snapshots__/get_buckets.test.ts.snap rename to x-pack/plugins/apm/server/routes/errors/distribution/__snapshots__/get_buckets.test.ts.snap diff --git a/x-pack/plugins/apm/server/lib/errors/distribution/__snapshots__/queries.test.ts.snap b/x-pack/plugins/apm/server/routes/errors/distribution/__snapshots__/queries.test.ts.snap similarity index 100% rename from x-pack/plugins/apm/server/lib/errors/distribution/__snapshots__/queries.test.ts.snap rename to x-pack/plugins/apm/server/routes/errors/distribution/__snapshots__/queries.test.ts.snap diff --git a/x-pack/plugins/apm/server/lib/errors/distribution/get_buckets.test.ts b/x-pack/plugins/apm/server/routes/errors/distribution/get_buckets.test.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/errors/distribution/get_buckets.test.ts rename to x-pack/plugins/apm/server/routes/errors/distribution/get_buckets.test.ts diff --git a/x-pack/plugins/apm/server/lib/errors/distribution/get_buckets.ts b/x-pack/plugins/apm/server/routes/errors/distribution/get_buckets.ts similarity index 96% rename from x-pack/plugins/apm/server/lib/errors/distribution/get_buckets.ts rename to x-pack/plugins/apm/server/routes/errors/distribution/get_buckets.ts index 625089e99d360..dd2dd3bc9ff3e 100644 --- a/x-pack/plugins/apm/server/lib/errors/distribution/get_buckets.ts +++ b/x-pack/plugins/apm/server/routes/errors/distribution/get_buckets.ts @@ -16,7 +16,7 @@ import { termQuery, } from '../../../../../observability/server'; import { environmentQuery } from '../../../../common/utils/environment_query'; -import { Setup } from '../../helpers/setup_request'; +import { Setup } from '../../../lib/helpers/setup_request'; export async function getBuckets({ environment, diff --git a/x-pack/plugins/apm/server/lib/errors/distribution/get_distribution.ts b/x-pack/plugins/apm/server/routes/errors/distribution/get_distribution.ts similarity index 96% rename from x-pack/plugins/apm/server/lib/errors/distribution/get_distribution.ts rename to x-pack/plugins/apm/server/routes/errors/distribution/get_distribution.ts index 7d5cbe9f95584..9e7221b7cd939 100644 --- a/x-pack/plugins/apm/server/lib/errors/distribution/get_distribution.ts +++ b/x-pack/plugins/apm/server/routes/errors/distribution/get_distribution.ts @@ -6,7 +6,7 @@ */ import { offsetPreviousPeriodCoordinates } from '../../../../common/utils/offset_previous_period_coordinate'; -import { Setup } from '../../helpers/setup_request'; +import { Setup } from '../../../lib/helpers/setup_request'; import { BUCKET_TARGET_COUNT } from '../../transactions/constants'; import { getBuckets } from './get_buckets'; diff --git a/x-pack/plugins/apm/server/lib/errors/distribution/queries.test.ts b/x-pack/plugins/apm/server/routes/errors/distribution/queries.test.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/errors/distribution/queries.test.ts rename to x-pack/plugins/apm/server/routes/errors/distribution/queries.test.ts diff --git a/x-pack/plugins/apm/server/lib/errors/get_error_group_sample.ts b/x-pack/plugins/apm/server/routes/errors/get_error_group_sample.ts similarity index 97% rename from x-pack/plugins/apm/server/lib/errors/get_error_group_sample.ts rename to x-pack/plugins/apm/server/routes/errors/get_error_group_sample.ts index 35c3ce999a9ff..2c5073fb5dc66 100644 --- a/x-pack/plugins/apm/server/lib/errors/get_error_group_sample.ts +++ b/x-pack/plugins/apm/server/routes/errors/get_error_group_sample.ts @@ -14,7 +14,7 @@ import { import { ProcessorEvent } from '../../../common/processor_event'; import { rangeQuery, kqlQuery } from '../../../../observability/server'; import { environmentQuery } from '../../../common/utils/environment_query'; -import { Setup } from '../helpers/setup_request'; +import { Setup } from '../../lib/helpers/setup_request'; import { getTransaction } from '../transactions/get_transaction'; export async function getErrorGroupSample({ diff --git a/x-pack/plugins/apm/server/lib/errors/get_error_groups.ts b/x-pack/plugins/apm/server/routes/errors/get_error_groups.ts similarity index 96% rename from x-pack/plugins/apm/server/lib/errors/get_error_groups.ts rename to x-pack/plugins/apm/server/routes/errors/get_error_groups.ts index 4d4c935d20e76..b26f3f4e7b4fe 100644 --- a/x-pack/plugins/apm/server/lib/errors/get_error_groups.ts +++ b/x-pack/plugins/apm/server/routes/errors/get_error_groups.ts @@ -18,8 +18,8 @@ import { ERROR_LOG_MESSAGE, SERVICE_NAME, } from '../../../common/elasticsearch_fieldnames'; -import { getErrorName } from '../helpers/get_error_name'; -import { Setup } from '../helpers/setup_request'; +import { getErrorName } from '../../lib/helpers/get_error_name'; +import { Setup } from '../../lib/helpers/setup_request'; export async function getErrorGroups({ environment, diff --git a/x-pack/plugins/apm/server/lib/errors/queries.test.ts b/x-pack/plugins/apm/server/routes/errors/queries.test.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/errors/queries.test.ts rename to x-pack/plugins/apm/server/routes/errors/queries.test.ts diff --git a/x-pack/plugins/apm/server/routes/errors.ts b/x-pack/plugins/apm/server/routes/errors/route.ts similarity index 86% rename from x-pack/plugins/apm/server/routes/errors.ts rename to x-pack/plugins/apm/server/routes/errors/route.ts index 02df03f108083..602fed89be93c 100644 --- a/x-pack/plugins/apm/server/routes/errors.ts +++ b/x-pack/plugins/apm/server/routes/errors/route.ts @@ -6,18 +6,18 @@ */ import * as t from 'io-ts'; -import { createApmServerRoute } from './apm_routes/create_apm_server_route'; -import { getErrorDistribution } from '../lib/errors/distribution/get_distribution'; -import { getErrorGroupSample } from '../lib/errors/get_error_group_sample'; -import { getErrorGroups } from '../lib/errors/get_error_groups'; -import { setupRequest } from '../lib/helpers/setup_request'; +import { createApmServerRoute } from '../apm_routes/create_apm_server_route'; +import { getErrorDistribution } from './distribution/get_distribution'; +import { getErrorGroupSample } from './get_error_group_sample'; +import { getErrorGroups } from './get_error_groups'; +import { setupRequest } from '../../lib/helpers/setup_request'; import { environmentRt, kueryRt, rangeRt, comparisonRangeRt, -} from './default_api_types'; -import { createApmServerRouteRepository } from './apm_routes/create_apm_server_route_repository'; +} from '../default_api_types'; +import { createApmServerRouteRepository } from '../apm_routes/create_apm_server_route_repository'; const errorsRoute = createApmServerRoute({ endpoint: 'GET /internal/apm/services/{serviceName}/errors', diff --git a/x-pack/plugins/apm/server/lib/event_metadata/get_event_metadata.ts b/x-pack/plugins/apm/server/routes/event_metadata/get_event_metadata.ts similarity index 93% rename from x-pack/plugins/apm/server/lib/event_metadata/get_event_metadata.ts rename to x-pack/plugins/apm/server/routes/event_metadata/get_event_metadata.ts index b9e0dee52a42e..006c87a3dac20 100644 --- a/x-pack/plugins/apm/server/lib/event_metadata/get_event_metadata.ts +++ b/x-pack/plugins/apm/server/routes/event_metadata/get_event_metadata.ts @@ -12,7 +12,7 @@ import { TRANSACTION_ID, } from '../../../common/elasticsearch_fieldnames'; import { ProcessorEvent } from '../../../common/processor_event'; -import type { APMEventClient } from '../helpers/create_es_client/create_apm_event_client'; +import type { APMEventClient } from '../../lib/helpers/create_es_client/create_apm_event_client'; export async function getEventMetadata({ apmEventClient, diff --git a/x-pack/plugins/apm/server/routes/event_metadata.ts b/x-pack/plugins/apm/server/routes/event_metadata/route.ts similarity index 72% rename from x-pack/plugins/apm/server/routes/event_metadata.ts rename to x-pack/plugins/apm/server/routes/event_metadata/route.ts index 3a40e445007ee..3140372aa69de 100644 --- a/x-pack/plugins/apm/server/routes/event_metadata.ts +++ b/x-pack/plugins/apm/server/routes/event_metadata/route.ts @@ -6,11 +6,11 @@ */ import * as t from 'io-ts'; -import { createApmServerRouteRepository } from './apm_routes/create_apm_server_route_repository'; -import { createApmServerRoute } from './apm_routes/create_apm_server_route'; -import { getEventMetadata } from '../lib/event_metadata/get_event_metadata'; -import { processorEventRt } from '../../common/processor_event'; -import { setupRequest } from '../lib/helpers/setup_request'; +import { createApmServerRouteRepository } from '../apm_routes/create_apm_server_route_repository'; +import { createApmServerRoute } from '../apm_routes/create_apm_server_route'; +import { getEventMetadata } from './get_event_metadata'; +import { processorEventRt } from '../../../common/processor_event'; +import { setupRequest } from '../../lib/helpers/setup_request'; const eventMetadataRoute = createApmServerRoute({ endpoint: 'GET /internal/apm/event_metadata/{processorEvent}/{id}', diff --git a/x-pack/plugins/apm/server/routes/fallback_to_transactions.ts b/x-pack/plugins/apm/server/routes/fallback_to_transactions/route.ts similarity index 70% rename from x-pack/plugins/apm/server/routes/fallback_to_transactions.ts rename to x-pack/plugins/apm/server/routes/fallback_to_transactions/route.ts index 53e3ebae0d4ff..77b5aeeac6ee8 100644 --- a/x-pack/plugins/apm/server/routes/fallback_to_transactions.ts +++ b/x-pack/plugins/apm/server/routes/fallback_to_transactions/route.ts @@ -6,11 +6,11 @@ */ import * as t from 'io-ts'; -import { getIsUsingTransactionEvents } from '../lib/helpers/transactions/get_is_using_transaction_events'; -import { setupRequest } from '../lib/helpers/setup_request'; -import { createApmServerRoute } from './apm_routes/create_apm_server_route'; -import { createApmServerRouteRepository } from './apm_routes/create_apm_server_route_repository'; -import { kueryRt, rangeRt } from './default_api_types'; +import { getIsUsingTransactionEvents } from '../../lib/helpers/transactions/get_is_using_transaction_events'; +import { setupRequest } from '../../lib/helpers/setup_request'; +import { createApmServerRoute } from '../apm_routes/create_apm_server_route'; +import { createApmServerRouteRepository } from '../apm_routes/create_apm_server_route_repository'; +import { kueryRt, rangeRt } from '../default_api_types'; const fallbackToTransactionsRoute = createApmServerRoute({ endpoint: 'GET /internal/apm/fallback_to_transactions', diff --git a/x-pack/plugins/apm/server/lib/fleet/create_cloud_apm_package_policy.ts b/x-pack/plugins/apm/server/routes/fleet/create_cloud_apm_package_policy.ts similarity index 97% rename from x-pack/plugins/apm/server/lib/fleet/create_cloud_apm_package_policy.ts rename to x-pack/plugins/apm/server/routes/fleet/create_cloud_apm_package_policy.ts index 6726865c6c3a5..a3c7bfd079a4c 100644 --- a/x-pack/plugins/apm/server/lib/fleet/create_cloud_apm_package_policy.ts +++ b/x-pack/plugins/apm/server/routes/fleet/create_cloud_apm_package_policy.ts @@ -20,7 +20,7 @@ import { APMPluginStartDependencies, } from '../../types'; import { getApmPackagePolicyDefinition } from './get_apm_package_policy_definition'; -import { Setup } from '../helpers/setup_request'; +import { Setup } from '../../lib/helpers/setup_request'; import { mergePackagePolicyWithApm } from './merge_package_policy_with_apm'; export async function createCloudApmPackgePolicy({ diff --git a/x-pack/plugins/apm/server/lib/fleet/get_agents.ts b/x-pack/plugins/apm/server/routes/fleet/get_agents.ts similarity index 89% rename from x-pack/plugins/apm/server/lib/fleet/get_agents.ts rename to x-pack/plugins/apm/server/routes/fleet/get_agents.ts index 86a6294e96b09..bcfe42428dbe2 100644 --- a/x-pack/plugins/apm/server/lib/fleet/get_agents.ts +++ b/x-pack/plugins/apm/server/routes/fleet/get_agents.ts @@ -11,7 +11,7 @@ import { SavedObjectsClientContract, } from 'kibana/server'; import { APMPluginStartDependencies } from '../../types'; -import { getInternalSavedObjectsClient } from '../helpers/get_internal_saved_objects_client'; +import { getInternalSavedObjectsClient } from '../../lib/helpers/get_internal_saved_objects_client'; export async function getFleetAgents({ policyIds, diff --git a/x-pack/plugins/apm/server/lib/fleet/get_apm_package_policies.ts b/x-pack/plugins/apm/server/routes/fleet/get_apm_package_policies.ts similarity index 89% rename from x-pack/plugins/apm/server/lib/fleet/get_apm_package_policies.ts rename to x-pack/plugins/apm/server/routes/fleet/get_apm_package_policies.ts index 5128339368f46..89ab9df051f70 100644 --- a/x-pack/plugins/apm/server/lib/fleet/get_apm_package_policies.ts +++ b/x-pack/plugins/apm/server/routes/fleet/get_apm_package_policies.ts @@ -11,7 +11,7 @@ import { SavedObjectsClientContract, } from 'kibana/server'; import { APMPluginStartDependencies } from '../../types'; -import { getInternalSavedObjectsClient } from '../helpers/get_internal_saved_objects_client'; +import { getInternalSavedObjectsClient } from '../../lib/helpers/get_internal_saved_objects_client'; export async function getApmPackgePolicies({ core, diff --git a/x-pack/plugins/apm/server/lib/fleet/get_apm_package_policy_definition.test.ts b/x-pack/plugins/apm/server/routes/fleet/get_apm_package_policy_definition.test.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/fleet/get_apm_package_policy_definition.test.ts rename to x-pack/plugins/apm/server/routes/fleet/get_apm_package_policy_definition.test.ts diff --git a/x-pack/plugins/apm/server/lib/fleet/get_apm_package_policy_definition.ts b/x-pack/plugins/apm/server/routes/fleet/get_apm_package_policy_definition.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/fleet/get_apm_package_policy_definition.ts rename to x-pack/plugins/apm/server/routes/fleet/get_apm_package_policy_definition.ts diff --git a/x-pack/plugins/apm/server/lib/fleet/get_cloud_apm_package_policy.ts b/x-pack/plugins/apm/server/routes/fleet/get_cloud_apm_package_policy.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/fleet/get_cloud_apm_package_policy.ts rename to x-pack/plugins/apm/server/routes/fleet/get_cloud_apm_package_policy.ts diff --git a/x-pack/plugins/apm/server/lib/fleet/get_unsupported_apm_server_schema.test.ts b/x-pack/plugins/apm/server/routes/fleet/get_unsupported_apm_server_schema.test.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/fleet/get_unsupported_apm_server_schema.test.ts rename to x-pack/plugins/apm/server/routes/fleet/get_unsupported_apm_server_schema.test.ts diff --git a/x-pack/plugins/apm/server/lib/fleet/get_unsupported_apm_server_schema.ts b/x-pack/plugins/apm/server/routes/fleet/get_unsupported_apm_server_schema.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/fleet/get_unsupported_apm_server_schema.ts rename to x-pack/plugins/apm/server/routes/fleet/get_unsupported_apm_server_schema.ts diff --git a/x-pack/plugins/apm/server/lib/fleet/is_superuser.ts b/x-pack/plugins/apm/server/routes/fleet/is_superuser.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/fleet/is_superuser.ts rename to x-pack/plugins/apm/server/routes/fleet/is_superuser.ts diff --git a/x-pack/plugins/apm/server/lib/fleet/merge_package_policy_with_apm.ts b/x-pack/plugins/apm/server/routes/fleet/merge_package_policy_with_apm.ts similarity index 95% rename from x-pack/plugins/apm/server/lib/fleet/merge_package_policy_with_apm.ts rename to x-pack/plugins/apm/server/routes/fleet/merge_package_policy_with_apm.ts index fd3e3db700fd0..5442185decde3 100644 --- a/x-pack/plugins/apm/server/lib/fleet/merge_package_policy_with_apm.ts +++ b/x-pack/plugins/apm/server/routes/fleet/merge_package_policy_with_apm.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { Setup } from '../helpers/setup_request'; +import { Setup } from '../../lib/helpers/setup_request'; import { APMPluginStartDependencies } from '../../types'; import { listConfigurations } from '../settings/agent_configuration/list_configurations'; import { diff --git a/x-pack/plugins/apm/server/lib/fleet/register_fleet_policy_callbacks.ts b/x-pack/plugins/apm/server/routes/fleet/register_fleet_policy_callbacks.ts similarity index 98% rename from x-pack/plugins/apm/server/lib/fleet/register_fleet_policy_callbacks.ts rename to x-pack/plugins/apm/server/routes/fleet/register_fleet_policy_callbacks.ts index 6fcd0433e2e83..06e55c7fdcca8 100644 --- a/x-pack/plugins/apm/server/lib/fleet/register_fleet_policy_callbacks.ts +++ b/x-pack/plugins/apm/server/routes/fleet/register_fleet_policy_callbacks.ts @@ -17,7 +17,7 @@ import { import { AgentConfiguration } from '../../../common/agent_configuration/configuration_types'; import { AGENT_NAME } from '../../../common/elasticsearch_fieldnames'; import { APMPluginStartDependencies } from '../../types'; -import { setupRequest } from '../helpers/setup_request'; +import { setupRequest } from '../../lib/helpers/setup_request'; import { mergePackagePolicyWithApm } from './merge_package_policy_with_apm'; export async function registerFleetPolicyCallbacks({ diff --git a/x-pack/plugins/apm/server/routes/fleet.ts b/x-pack/plugins/apm/server/routes/fleet/route.ts similarity index 89% rename from x-pack/plugins/apm/server/routes/fleet.ts rename to x-pack/plugins/apm/server/routes/fleet/route.ts index a6e0cb09d894a..e9e7f2254bcfe 100644 --- a/x-pack/plugins/apm/server/routes/fleet.ts +++ b/x-pack/plugins/apm/server/routes/fleet/route.ts @@ -12,20 +12,20 @@ import { keyBy } from 'lodash'; import { APM_SERVER_SCHEMA_SAVED_OBJECT_ID, APM_SERVER_SCHEMA_SAVED_OBJECT_TYPE, -} from '../../common/apm_saved_object_constants'; -import { createCloudApmPackgePolicy } from '../lib/fleet/create_cloud_apm_package_policy'; -import { getFleetAgents } from '../lib/fleet/get_agents'; -import { getApmPackgePolicies } from '../lib/fleet/get_apm_package_policies'; +} from '../../../common/apm_saved_object_constants'; +import { createCloudApmPackgePolicy } from './create_cloud_apm_package_policy'; +import { getFleetAgents } from './get_agents'; +import { getApmPackgePolicies } from './get_apm_package_policies'; import { getApmPackagePolicy, getCloudAgentPolicy, -} from '../lib/fleet/get_cloud_apm_package_policy'; -import { getUnsupportedApmServerSchema } from '../lib/fleet/get_unsupported_apm_server_schema'; -import { isSuperuser } from '../lib/fleet/is_superuser'; -import { getInternalSavedObjectsClient } from '../lib/helpers/get_internal_saved_objects_client'; -import { setupRequest } from '../lib/helpers/setup_request'; -import { createApmServerRoute } from './apm_routes/create_apm_server_route'; -import { createApmServerRouteRepository } from './apm_routes/create_apm_server_route_repository'; +} from './get_cloud_apm_package_policy'; +import { getUnsupportedApmServerSchema } from './get_unsupported_apm_server_schema'; +import { isSuperuser } from './is_superuser'; +import { getInternalSavedObjectsClient } from '../../lib/helpers/get_internal_saved_objects_client'; +import { setupRequest } from '../../lib/helpers/setup_request'; +import { createApmServerRoute } from '../apm_routes/create_apm_server_route'; +import { createApmServerRouteRepository } from '../apm_routes/create_apm_server_route_repository'; const hasFleetDataRoute = createApmServerRoute({ endpoint: 'GET /internal/apm/fleet/has_data', diff --git a/x-pack/plugins/apm/server/lib/fleet/source_maps.test.ts b/x-pack/plugins/apm/server/routes/fleet/source_maps.test.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/fleet/source_maps.test.ts rename to x-pack/plugins/apm/server/routes/fleet/source_maps.test.ts diff --git a/x-pack/plugins/apm/server/lib/fleet/source_maps.ts b/x-pack/plugins/apm/server/routes/fleet/source_maps.ts similarity index 98% rename from x-pack/plugins/apm/server/lib/fleet/source_maps.ts rename to x-pack/plugins/apm/server/routes/fleet/source_maps.ts index 8c11f80f21191..1d70076a828dd 100644 --- a/x-pack/plugins/apm/server/lib/fleet/source_maps.ts +++ b/x-pack/plugins/apm/server/routes/fleet/source_maps.ts @@ -13,7 +13,7 @@ import { import { promisify } from 'util'; import { unzip } from 'zlib'; import { Artifact } from '../../../../fleet/server'; -import { SourceMap } from '../../routes/source_maps'; +import { SourceMap } from '../source_maps/route'; import { APMPluginStartDependencies } from '../../types'; import { getApmPackgePolicies } from './get_apm_package_policies'; import { APM_SERVER, PackagePolicy } from './register_fleet_policy_callbacks'; diff --git a/x-pack/plugins/apm/server/lib/fleet/sync_agent_configs_to_apm_package_policies.ts b/x-pack/plugins/apm/server/routes/fleet/sync_agent_configs_to_apm_package_policies.ts similarity index 90% rename from x-pack/plugins/apm/server/lib/fleet/sync_agent_configs_to_apm_package_policies.ts rename to x-pack/plugins/apm/server/routes/fleet/sync_agent_configs_to_apm_package_policies.ts index 5f3a3f74598a1..c3660eee0afae 100644 --- a/x-pack/plugins/apm/server/lib/fleet/sync_agent_configs_to_apm_package_policies.ts +++ b/x-pack/plugins/apm/server/routes/fleet/sync_agent_configs_to_apm_package_policies.ts @@ -10,10 +10,10 @@ import { CoreStart, SavedObjectsClientContract, } from 'kibana/server'; -import { TelemetryUsageCounter } from '../../routes/typings'; +import { TelemetryUsageCounter } from '../typings'; import { APMPluginStartDependencies } from '../../types'; -import { getInternalSavedObjectsClient } from '../helpers/get_internal_saved_objects_client'; -import { Setup } from '../helpers/setup_request'; +import { getInternalSavedObjectsClient } from '../../lib/helpers/get_internal_saved_objects_client'; +import { Setup } from '../../lib/helpers/setup_request'; import { listConfigurations } from '../settings/agent_configuration/list_configurations'; import { getApmPackgePolicies } from './get_apm_package_policies'; import { getPackagePolicyWithAgentConfigurations } from './register_fleet_policy_callbacks'; diff --git a/x-pack/plugins/apm/server/lib/latency/get_overall_latency_distribution.ts b/x-pack/plugins/apm/server/routes/latency_distribution/get_overall_latency_distribution.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/latency/get_overall_latency_distribution.ts rename to x-pack/plugins/apm/server/routes/latency_distribution/get_overall_latency_distribution.ts diff --git a/x-pack/plugins/apm/server/lib/latency/get_percentile_threshold_value.ts b/x-pack/plugins/apm/server/routes/latency_distribution/get_percentile_threshold_value.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/latency/get_percentile_threshold_value.ts rename to x-pack/plugins/apm/server/routes/latency_distribution/get_percentile_threshold_value.ts diff --git a/x-pack/plugins/apm/server/routes/latency_distribution.ts b/x-pack/plugins/apm/server/routes/latency_distribution/route.ts similarity index 80% rename from x-pack/plugins/apm/server/routes/latency_distribution.ts rename to x-pack/plugins/apm/server/routes/latency_distribution/route.ts index 826898784835e..f30e98dd8c7b8 100644 --- a/x-pack/plugins/apm/server/routes/latency_distribution.ts +++ b/x-pack/plugins/apm/server/routes/latency_distribution/route.ts @@ -7,11 +7,11 @@ import * as t from 'io-ts'; import { toNumberRt } from '@kbn/io-ts-utils/to_number_rt'; -import { getOverallLatencyDistribution } from '../lib/latency/get_overall_latency_distribution'; -import { setupRequest } from '../lib/helpers/setup_request'; -import { createApmServerRoute } from './apm_routes/create_apm_server_route'; -import { createApmServerRouteRepository } from './apm_routes/create_apm_server_route_repository'; -import { environmentRt, kueryRt, rangeRt } from './default_api_types'; +import { getOverallLatencyDistribution } from './get_overall_latency_distribution'; +import { setupRequest } from '../../lib/helpers/setup_request'; +import { createApmServerRoute } from '../apm_routes/create_apm_server_route'; +import { createApmServerRouteRepository } from '../apm_routes/create_apm_server_route_repository'; +import { environmentRt, kueryRt, rangeRt } from '../default_api_types'; const latencyOverallDistributionRoute = createApmServerRoute({ endpoint: 'POST /internal/apm/latency/overall_distribution', diff --git a/x-pack/plugins/apm/server/lib/latency/types.ts b/x-pack/plugins/apm/server/routes/latency_distribution/types.ts similarity index 92% rename from x-pack/plugins/apm/server/lib/latency/types.ts rename to x-pack/plugins/apm/server/routes/latency_distribution/types.ts index 17c036f44f088..d2eb9cde0bf3b 100644 --- a/x-pack/plugins/apm/server/lib/latency/types.ts +++ b/x-pack/plugins/apm/server/routes/latency_distribution/types.ts @@ -10,7 +10,7 @@ import type { CorrelationsClientParams, } from '../../../common/correlations/types'; -import { Setup } from '../helpers/setup_request'; +import { Setup } from '../../lib/helpers/setup_request'; export interface OverallLatencyDistributionOptions extends CorrelationsClientParams { diff --git a/x-pack/plugins/apm/server/lib/metrics/__snapshots__/queries.test.ts.snap b/x-pack/plugins/apm/server/routes/metrics/__snapshots__/queries.test.ts.snap similarity index 100% rename from x-pack/plugins/apm/server/lib/metrics/__snapshots__/queries.test.ts.snap rename to x-pack/plugins/apm/server/routes/metrics/__snapshots__/queries.test.ts.snap diff --git a/x-pack/plugins/apm/server/lib/metrics/by_agent/default.ts b/x-pack/plugins/apm/server/routes/metrics/by_agent/default.ts similarity index 92% rename from x-pack/plugins/apm/server/lib/metrics/by_agent/default.ts rename to x-pack/plugins/apm/server/routes/metrics/by_agent/default.ts index 54e10bd8adde0..b4e95d5217daa 100644 --- a/x-pack/plugins/apm/server/lib/metrics/by_agent/default.ts +++ b/x-pack/plugins/apm/server/routes/metrics/by_agent/default.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { Setup } from '../../helpers/setup_request'; +import { Setup } from '../../../lib/helpers/setup_request'; import { getCPUChartData } from './shared/cpu'; import { getMemoryChartData } from './shared/memory'; diff --git a/x-pack/plugins/apm/server/lib/metrics/by_agent/java/gc/fetch_and_transform_gc_metrics.test.ts b/x-pack/plugins/apm/server/routes/metrics/by_agent/java/gc/fetch_and_transform_gc_metrics.test.ts similarity index 98% rename from x-pack/plugins/apm/server/lib/metrics/by_agent/java/gc/fetch_and_transform_gc_metrics.test.ts rename to x-pack/plugins/apm/server/routes/metrics/by_agent/java/gc/fetch_and_transform_gc_metrics.test.ts index c22c326473e2c..8b3fcbfe5ce88 100644 --- a/x-pack/plugins/apm/server/lib/metrics/by_agent/java/gc/fetch_and_transform_gc_metrics.test.ts +++ b/x-pack/plugins/apm/server/routes/metrics/by_agent/java/gc/fetch_and_transform_gc_metrics.test.ts @@ -9,7 +9,7 @@ import { METRIC_JAVA_GC_COUNT, METRIC_JAVA_GC_TIME, } from '../../../../../../common/elasticsearch_fieldnames'; -import { Setup } from '../../../../helpers/setup_request'; +import { Setup } from '../../../../../lib/helpers/setup_request'; import { ChartBase } from '../../../types'; import { fetchAndTransformGcMetrics } from './fetch_and_transform_gc_metrics'; diff --git a/x-pack/plugins/apm/server/lib/metrics/by_agent/java/gc/fetch_and_transform_gc_metrics.ts b/x-pack/plugins/apm/server/routes/metrics/by_agent/java/gc/fetch_and_transform_gc_metrics.ts similarity index 95% rename from x-pack/plugins/apm/server/lib/metrics/by_agent/java/gc/fetch_and_transform_gc_metrics.ts rename to x-pack/plugins/apm/server/routes/metrics/by_agent/java/gc/fetch_and_transform_gc_metrics.ts index 2d4cf2f70ab5f..790fcf5720745 100644 --- a/x-pack/plugins/apm/server/lib/metrics/by_agent/java/gc/fetch_and_transform_gc_metrics.ts +++ b/x-pack/plugins/apm/server/routes/metrics/by_agent/java/gc/fetch_and_transform_gc_metrics.ts @@ -8,8 +8,8 @@ import { sum, round } from 'lodash'; import { euiLightVars as theme } from '@kbn/ui-shared-deps-src/theme'; import { isFiniteNumber } from '../../../../../../common/utils/is_finite_number'; -import { Setup } from '../../../../helpers/setup_request'; -import { getMetricsDateHistogramParams } from '../../../../helpers/metrics'; +import { Setup } from '../../../../../lib/helpers/setup_request'; +import { getMetricsDateHistogramParams } from '../../../../../lib/helpers/metrics'; import { ChartBase } from '../../../types'; import { @@ -19,7 +19,7 @@ import { METRIC_JAVA_GC_TIME, SERVICE_NAME, } from '../../../../../../common/elasticsearch_fieldnames'; -import { getBucketSize } from '../../../../helpers/get_bucket_size'; +import { getBucketSize } from '../../../../../lib/helpers/get_bucket_size'; import { getVizColorForIndex } from '../../../../../../common/viz_colors'; import { JAVA_AGENT_NAMES } from '../../../../../../common/agent_name'; import { diff --git a/x-pack/plugins/apm/server/lib/metrics/by_agent/java/gc/get_gc_rate_chart.ts b/x-pack/plugins/apm/server/routes/metrics/by_agent/java/gc/get_gc_rate_chart.ts similarity index 95% rename from x-pack/plugins/apm/server/lib/metrics/by_agent/java/gc/get_gc_rate_chart.ts rename to x-pack/plugins/apm/server/routes/metrics/by_agent/java/gc/get_gc_rate_chart.ts index 22dcb3e0f08ff..a22f7df915617 100644 --- a/x-pack/plugins/apm/server/lib/metrics/by_agent/java/gc/get_gc_rate_chart.ts +++ b/x-pack/plugins/apm/server/routes/metrics/by_agent/java/gc/get_gc_rate_chart.ts @@ -8,7 +8,7 @@ import { euiLightVars as theme } from '@kbn/ui-shared-deps-src/theme'; import { i18n } from '@kbn/i18n'; import { METRIC_JAVA_GC_COUNT } from '../../../../../../common/elasticsearch_fieldnames'; -import { Setup } from '../../../../helpers/setup_request'; +import { Setup } from '../../../../../lib/helpers/setup_request'; import { fetchAndTransformGcMetrics } from './fetch_and_transform_gc_metrics'; import { ChartBase } from '../../../types'; diff --git a/x-pack/plugins/apm/server/lib/metrics/by_agent/java/gc/get_gc_time_chart.ts b/x-pack/plugins/apm/server/routes/metrics/by_agent/java/gc/get_gc_time_chart.ts similarity index 95% rename from x-pack/plugins/apm/server/lib/metrics/by_agent/java/gc/get_gc_time_chart.ts rename to x-pack/plugins/apm/server/routes/metrics/by_agent/java/gc/get_gc_time_chart.ts index 4b85ad94f6494..596d871b916f9 100644 --- a/x-pack/plugins/apm/server/lib/metrics/by_agent/java/gc/get_gc_time_chart.ts +++ b/x-pack/plugins/apm/server/routes/metrics/by_agent/java/gc/get_gc_time_chart.ts @@ -8,7 +8,7 @@ import { euiLightVars as theme } from '@kbn/ui-shared-deps-src/theme'; import { i18n } from '@kbn/i18n'; import { METRIC_JAVA_GC_TIME } from '../../../../../../common/elasticsearch_fieldnames'; -import { Setup } from '../../../../helpers/setup_request'; +import { Setup } from '../../../../../lib/helpers/setup_request'; import { fetchAndTransformGcMetrics } from './fetch_and_transform_gc_metrics'; import { ChartBase } from '../../../types'; diff --git a/x-pack/plugins/apm/server/lib/metrics/by_agent/java/heap_memory/index.ts b/x-pack/plugins/apm/server/routes/metrics/by_agent/java/heap_memory/index.ts similarity index 97% rename from x-pack/plugins/apm/server/lib/metrics/by_agent/java/heap_memory/index.ts rename to x-pack/plugins/apm/server/routes/metrics/by_agent/java/heap_memory/index.ts index a872a3af76d7e..cde28e77e38ca 100644 --- a/x-pack/plugins/apm/server/lib/metrics/by_agent/java/heap_memory/index.ts +++ b/x-pack/plugins/apm/server/routes/metrics/by_agent/java/heap_memory/index.ts @@ -13,7 +13,7 @@ import { METRIC_JAVA_HEAP_MEMORY_USED, AGENT_NAME, } from '../../../../../../common/elasticsearch_fieldnames'; -import { Setup } from '../../../../helpers/setup_request'; +import { Setup } from '../../../../../lib/helpers/setup_request'; import { fetchAndTransformMetrics } from '../../../fetch_and_transform_metrics'; import { ChartBase } from '../../../types'; import { JAVA_AGENT_NAMES } from '../../../../../../common/agent_name'; diff --git a/x-pack/plugins/apm/server/lib/metrics/by_agent/java/index.ts b/x-pack/plugins/apm/server/routes/metrics/by_agent/java/index.ts similarity index 95% rename from x-pack/plugins/apm/server/lib/metrics/by_agent/java/index.ts rename to x-pack/plugins/apm/server/routes/metrics/by_agent/java/index.ts index 9039bb19ebb78..5250884ed5e44 100644 --- a/x-pack/plugins/apm/server/lib/metrics/by_agent/java/index.ts +++ b/x-pack/plugins/apm/server/routes/metrics/by_agent/java/index.ts @@ -7,7 +7,7 @@ import { withApmSpan } from '../../../../utils/with_apm_span'; import { getHeapMemoryChart } from './heap_memory'; -import { Setup } from '../../../helpers/setup_request'; +import { Setup } from '../../../../lib/helpers/setup_request'; import { getNonHeapMemoryChart } from './non_heap_memory'; import { getThreadCountChart } from './thread_count'; import { getCPUChartData } from '../shared/cpu'; diff --git a/x-pack/plugins/apm/server/lib/metrics/by_agent/java/non_heap_memory/index.ts b/x-pack/plugins/apm/server/routes/metrics/by_agent/java/non_heap_memory/index.ts similarity index 97% rename from x-pack/plugins/apm/server/lib/metrics/by_agent/java/non_heap_memory/index.ts rename to x-pack/plugins/apm/server/routes/metrics/by_agent/java/non_heap_memory/index.ts index 9fa758cb4dbd8..ffcce74ee6766 100644 --- a/x-pack/plugins/apm/server/lib/metrics/by_agent/java/non_heap_memory/index.ts +++ b/x-pack/plugins/apm/server/routes/metrics/by_agent/java/non_heap_memory/index.ts @@ -13,7 +13,7 @@ import { METRIC_JAVA_NON_HEAP_MEMORY_USED, AGENT_NAME, } from '../../../../../../common/elasticsearch_fieldnames'; -import { Setup } from '../../../../helpers/setup_request'; +import { Setup } from '../../../../../lib/helpers/setup_request'; import { ChartBase } from '../../../types'; import { fetchAndTransformMetrics } from '../../../fetch_and_transform_metrics'; import { JAVA_AGENT_NAMES } from '../../../../../../common/agent_name'; diff --git a/x-pack/plugins/apm/server/lib/metrics/by_agent/java/thread_count/index.ts b/x-pack/plugins/apm/server/routes/metrics/by_agent/java/thread_count/index.ts similarity index 96% rename from x-pack/plugins/apm/server/lib/metrics/by_agent/java/thread_count/index.ts rename to x-pack/plugins/apm/server/routes/metrics/by_agent/java/thread_count/index.ts index 306666d27cd1c..699812ffc8463 100644 --- a/x-pack/plugins/apm/server/lib/metrics/by_agent/java/thread_count/index.ts +++ b/x-pack/plugins/apm/server/routes/metrics/by_agent/java/thread_count/index.ts @@ -11,7 +11,7 @@ import { METRIC_JAVA_THREAD_COUNT, AGENT_NAME, } from '../../../../../../common/elasticsearch_fieldnames'; -import { Setup } from '../../../../helpers/setup_request'; +import { Setup } from '../../../../../lib/helpers/setup_request'; import { ChartBase } from '../../../types'; import { fetchAndTransformMetrics } from '../../../fetch_and_transform_metrics'; import { JAVA_AGENT_NAMES } from '../../../../../../common/agent_name'; diff --git a/x-pack/plugins/apm/server/lib/metrics/by_agent/shared/cpu/index.ts b/x-pack/plugins/apm/server/routes/metrics/by_agent/shared/cpu/index.ts similarity index 97% rename from x-pack/plugins/apm/server/lib/metrics/by_agent/shared/cpu/index.ts rename to x-pack/plugins/apm/server/routes/metrics/by_agent/shared/cpu/index.ts index 0911081b20324..95c39d4bd55cc 100644 --- a/x-pack/plugins/apm/server/lib/metrics/by_agent/shared/cpu/index.ts +++ b/x-pack/plugins/apm/server/routes/metrics/by_agent/shared/cpu/index.ts @@ -11,7 +11,7 @@ import { METRIC_SYSTEM_CPU_PERCENT, METRIC_PROCESS_CPU_PERCENT, } from '../../../../../../common/elasticsearch_fieldnames'; -import { Setup } from '../../../../helpers/setup_request'; +import { Setup } from '../../../../../lib/helpers/setup_request'; import { ChartBase } from '../../../types'; import { fetchAndTransformMetrics } from '../../../fetch_and_transform_metrics'; diff --git a/x-pack/plugins/apm/server/lib/metrics/by_agent/shared/memory/index.ts b/x-pack/plugins/apm/server/routes/metrics/by_agent/shared/memory/index.ts similarity index 98% rename from x-pack/plugins/apm/server/lib/metrics/by_agent/shared/memory/index.ts rename to x-pack/plugins/apm/server/routes/metrics/by_agent/shared/memory/index.ts index 828ee28260471..d0e84211ef455 100644 --- a/x-pack/plugins/apm/server/lib/metrics/by_agent/shared/memory/index.ts +++ b/x-pack/plugins/apm/server/routes/metrics/by_agent/shared/memory/index.ts @@ -13,7 +13,7 @@ import { METRIC_SYSTEM_FREE_MEMORY, METRIC_SYSTEM_TOTAL_MEMORY, } from '../../../../../../common/elasticsearch_fieldnames'; -import { Setup } from '../../../../helpers/setup_request'; +import { Setup } from '../../../../../lib/helpers/setup_request'; import { fetchAndTransformMetrics } from '../../../fetch_and_transform_metrics'; import { ChartBase } from '../../../types'; diff --git a/x-pack/plugins/apm/server/lib/metrics/fetch_and_transform_metrics.ts b/x-pack/plugins/apm/server/routes/metrics/fetch_and_transform_metrics.ts similarity index 94% rename from x-pack/plugins/apm/server/lib/metrics/fetch_and_transform_metrics.ts rename to x-pack/plugins/apm/server/routes/metrics/fetch_and_transform_metrics.ts index 0a24179ed9fc6..e607ae08e0b23 100644 --- a/x-pack/plugins/apm/server/lib/metrics/fetch_and_transform_metrics.ts +++ b/x-pack/plugins/apm/server/routes/metrics/fetch_and_transform_metrics.ts @@ -10,8 +10,9 @@ import { euiLightVars as theme } from '@kbn/ui-shared-deps-src/theme'; import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/types'; import { getVizColorForIndex } from '../../../common/viz_colors'; import { AggregationOptionsByType } from '../../../../../../src/core/types/elasticsearch'; -import { getMetricsDateHistogramParams } from '../helpers/metrics'; -import { Setup } from '../helpers/setup_request'; +import { APMEventESSearchRequest } from '../../lib/helpers/create_es_client/create_apm_event_client'; +import { getMetricsDateHistogramParams } from '../../lib/helpers/metrics'; +import { Setup } from '../../lib/helpers/setup_request'; import { ChartBase } from './types'; import { environmentQuery, @@ -20,7 +21,6 @@ import { import { kqlQuery, rangeQuery } from '../../../../observability/server'; import { ProcessorEvent } from '../../../common/processor_event'; import { SERVICE_NAME } from '../../../common/elasticsearch_fieldnames'; -import { APMEventESSearchRequest } from '../helpers/create_es_client/create_apm_event_client'; import { PromiseReturnType } from '../../../../observability/typings/common'; type MetricsAggregationMap = Unionize<{ diff --git a/x-pack/plugins/apm/server/lib/metrics/get_metrics_chart_data_by_agent.ts b/x-pack/plugins/apm/server/routes/metrics/get_metrics_chart_data_by_agent.ts similarity index 95% rename from x-pack/plugins/apm/server/lib/metrics/get_metrics_chart_data_by_agent.ts rename to x-pack/plugins/apm/server/routes/metrics/get_metrics_chart_data_by_agent.ts index 611bb8196032c..c6927417687da 100644 --- a/x-pack/plugins/apm/server/lib/metrics/get_metrics_chart_data_by_agent.ts +++ b/x-pack/plugins/apm/server/routes/metrics/get_metrics_chart_data_by_agent.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { Setup } from '../helpers/setup_request'; +import { Setup } from '../../lib/helpers/setup_request'; import { getJavaMetricsCharts } from './by_agent/java'; import { getDefaultMetricsCharts } from './by_agent/default'; import { isJavaAgentName } from '../../../common/agent_name'; diff --git a/x-pack/plugins/apm/server/lib/metrics/queries.test.ts b/x-pack/plugins/apm/server/routes/metrics/queries.test.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/metrics/queries.test.ts rename to x-pack/plugins/apm/server/routes/metrics/queries.test.ts diff --git a/x-pack/plugins/apm/server/routes/metrics.ts b/x-pack/plugins/apm/server/routes/metrics/route.ts similarity index 76% rename from x-pack/plugins/apm/server/routes/metrics.ts rename to x-pack/plugins/apm/server/routes/metrics/route.ts index 36a504859797a..4e15188827e9b 100644 --- a/x-pack/plugins/apm/server/routes/metrics.ts +++ b/x-pack/plugins/apm/server/routes/metrics/route.ts @@ -6,11 +6,11 @@ */ import * as t from 'io-ts'; -import { setupRequest } from '../lib/helpers/setup_request'; -import { getMetricsChartDataByAgent } from '../lib/metrics/get_metrics_chart_data_by_agent'; -import { createApmServerRoute } from './apm_routes/create_apm_server_route'; -import { createApmServerRouteRepository } from './apm_routes/create_apm_server_route_repository'; -import { environmentRt, kueryRt, rangeRt } from './default_api_types'; +import { setupRequest } from '../../lib/helpers/setup_request'; +import { getMetricsChartDataByAgent } from './get_metrics_chart_data_by_agent'; +import { createApmServerRoute } from '../apm_routes/create_apm_server_route'; +import { createApmServerRouteRepository } from '../apm_routes/create_apm_server_route_repository'; +import { environmentRt, kueryRt, rangeRt } from '../default_api_types'; const metricsChartsRoute = createApmServerRoute({ endpoint: 'GET /internal/apm/services/{serviceName}/metrics/charts', diff --git a/x-pack/plugins/apm/server/lib/metrics/types.ts b/x-pack/plugins/apm/server/routes/metrics/types.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/metrics/types.ts rename to x-pack/plugins/apm/server/routes/metrics/types.ts diff --git a/x-pack/plugins/apm/server/lib/observability_overview/get_service_count.ts b/x-pack/plugins/apm/server/routes/observability_overview/get_service_count.ts similarity index 90% rename from x-pack/plugins/apm/server/lib/observability_overview/get_service_count.ts rename to x-pack/plugins/apm/server/routes/observability_overview/get_service_count.ts index 3eb11f668115d..74b70e5fa7d60 100644 --- a/x-pack/plugins/apm/server/lib/observability_overview/get_service_count.ts +++ b/x-pack/plugins/apm/server/routes/observability_overview/get_service_count.ts @@ -8,8 +8,8 @@ import { ProcessorEvent } from '../../../common/processor_event'; import { rangeQuery } from '../../../../observability/server'; import { SERVICE_NAME } from '../../../common/elasticsearch_fieldnames'; -import { Setup } from '../helpers/setup_request'; -import { getProcessorEventForTransactions } from '../helpers/transactions'; +import { Setup } from '../../lib/helpers/setup_request'; +import { getProcessorEventForTransactions } from '../../lib/helpers/transactions'; export async function getServiceCount({ setup, diff --git a/x-pack/plugins/apm/server/lib/observability_overview/get_transactions_per_minute.ts b/x-pack/plugins/apm/server/routes/observability_overview/get_transactions_per_minute.ts similarity index 93% rename from x-pack/plugins/apm/server/lib/observability_overview/get_transactions_per_minute.ts rename to x-pack/plugins/apm/server/routes/observability_overview/get_transactions_per_minute.ts index de4d6dec4e1fe..83e51d7d638fe 100644 --- a/x-pack/plugins/apm/server/lib/observability_overview/get_transactions_per_minute.ts +++ b/x-pack/plugins/apm/server/routes/observability_overview/get_transactions_per_minute.ts @@ -11,12 +11,12 @@ import { } from '../../../common/transaction_types'; import { TRANSACTION_TYPE } from '../../../common/elasticsearch_fieldnames'; import { rangeQuery } from '../../../../observability/server'; -import { Setup } from '../helpers/setup_request'; +import { Setup } from '../../lib/helpers/setup_request'; import { getDocumentTypeFilterForTransactions, getProcessorEventForTransactions, -} from '../helpers/transactions'; -import { calculateThroughputWithRange } from '../helpers/calculate_throughput'; +} from '../../lib/helpers/transactions'; +import { calculateThroughputWithRange } from '../../lib/helpers/calculate_throughput'; export async function getTransactionsPerMinute({ setup, diff --git a/x-pack/plugins/apm/server/lib/observability_overview/has_data.ts b/x-pack/plugins/apm/server/routes/observability_overview/has_data.ts similarity index 94% rename from x-pack/plugins/apm/server/lib/observability_overview/has_data.ts rename to x-pack/plugins/apm/server/routes/observability_overview/has_data.ts index f09b67ec98dfb..9f98af055e696 100644 --- a/x-pack/plugins/apm/server/lib/observability_overview/has_data.ts +++ b/x-pack/plugins/apm/server/routes/observability_overview/has_data.ts @@ -6,7 +6,7 @@ */ import { ProcessorEvent } from '../../../common/processor_event'; -import { Setup } from '../helpers/setup_request'; +import { Setup } from '../../lib/helpers/setup_request'; export async function getHasData({ setup }: { setup: Setup }) { const { apmEventClient } = setup; diff --git a/x-pack/plugins/apm/server/routes/observability_overview.ts b/x-pack/plugins/apm/server/routes/observability_overview/route.ts similarity index 74% rename from x-pack/plugins/apm/server/routes/observability_overview.ts rename to x-pack/plugins/apm/server/routes/observability_overview/route.ts index 2df3212d8da70..c99586638c3de 100644 --- a/x-pack/plugins/apm/server/routes/observability_overview.ts +++ b/x-pack/plugins/apm/server/routes/observability_overview/route.ts @@ -7,15 +7,15 @@ import * as t from 'io-ts'; import { toNumberRt } from '@kbn/io-ts-utils/to_number_rt'; -import { setupRequest } from '../lib/helpers/setup_request'; -import { getServiceCount } from '../lib/observability_overview/get_service_count'; -import { getTransactionsPerMinute } from '../lib/observability_overview/get_transactions_per_minute'; -import { getHasData } from '../lib/observability_overview/has_data'; -import { rangeRt } from './default_api_types'; -import { getSearchAggregatedTransactions } from '../lib/helpers/transactions'; -import { withApmSpan } from '../utils/with_apm_span'; -import { createApmServerRouteRepository } from './apm_routes/create_apm_server_route_repository'; -import { createApmServerRoute } from './apm_routes/create_apm_server_route'; +import { setupRequest } from '../../lib/helpers/setup_request'; +import { getServiceCount } from './get_service_count'; +import { getTransactionsPerMinute } from './get_transactions_per_minute'; +import { getHasData } from './has_data'; +import { rangeRt } from '../default_api_types'; +import { getSearchAggregatedTransactions } from '../../lib/helpers/transactions'; +import { withApmSpan } from '../../utils/with_apm_span'; +import { createApmServerRouteRepository } from '../apm_routes/create_apm_server_route_repository'; +import { createApmServerRoute } from '../apm_routes/create_apm_server_route'; const observabilityOverviewHasDataRoute = createApmServerRoute({ endpoint: 'GET /internal/apm/observability_overview/has_data', diff --git a/x-pack/plugins/apm/server/lib/rum_client/__snapshots__/queries.test.ts.snap b/x-pack/plugins/apm/server/routes/rum_client/__snapshots__/queries.test.ts.snap similarity index 100% rename from x-pack/plugins/apm/server/lib/rum_client/__snapshots__/queries.test.ts.snap rename to x-pack/plugins/apm/server/routes/rum_client/__snapshots__/queries.test.ts.snap diff --git a/x-pack/plugins/apm/server/lib/rum_client/get_client_metrics.ts b/x-pack/plugins/apm/server/routes/rum_client/get_client_metrics.ts similarity index 98% rename from x-pack/plugins/apm/server/lib/rum_client/get_client_metrics.ts rename to x-pack/plugins/apm/server/routes/rum_client/get_client_metrics.ts index 206fc134a0c87..40352db9f18a6 100644 --- a/x-pack/plugins/apm/server/lib/rum_client/get_client_metrics.ts +++ b/x-pack/plugins/apm/server/routes/rum_client/get_client_metrics.ts @@ -7,7 +7,7 @@ import { getRumPageLoadTransactionsProjection } from '../../projections/rum_page_load_transactions'; import { mergeProjection } from '../../projections/util/merge_projection'; -import { SetupUX } from '../../routes/rum_client'; +import { SetupUX } from './route'; import { TRANSACTION_TIME_TO_FIRST_BYTE, TRANSACTION_DURATION, diff --git a/x-pack/plugins/apm/server/lib/rum_client/get_js_errors.ts b/x-pack/plugins/apm/server/routes/rum_client/get_js_errors.ts similarity index 98% rename from x-pack/plugins/apm/server/lib/rum_client/get_js_errors.ts rename to x-pack/plugins/apm/server/routes/rum_client/get_js_errors.ts index dca575b42cf0a..a0f7c0940b812 100644 --- a/x-pack/plugins/apm/server/lib/rum_client/get_js_errors.ts +++ b/x-pack/plugins/apm/server/routes/rum_client/get_js_errors.ts @@ -6,7 +6,7 @@ */ import { mergeProjection } from '../../projections/util/merge_projection'; -import { SetupUX } from '../../routes/rum_client'; +import { SetupUX } from './route'; import { getRumErrorsProjection } from '../../projections/rum_page_load_transactions'; import { ERROR_EXC_MESSAGE, diff --git a/x-pack/plugins/apm/server/lib/rum_client/get_long_task_metrics.ts b/x-pack/plugins/apm/server/routes/rum_client/get_long_task_metrics.ts similarity index 97% rename from x-pack/plugins/apm/server/lib/rum_client/get_long_task_metrics.ts rename to x-pack/plugins/apm/server/routes/rum_client/get_long_task_metrics.ts index d5cc78e2f3062..29ef955e19aa4 100644 --- a/x-pack/plugins/apm/server/lib/rum_client/get_long_task_metrics.ts +++ b/x-pack/plugins/apm/server/routes/rum_client/get_long_task_metrics.ts @@ -7,7 +7,7 @@ import { getRumPageLoadTransactionsProjection } from '../../projections/rum_page_load_transactions'; import { mergeProjection } from '../../projections/util/merge_projection'; -import { SetupUX } from '../../routes/rum_client'; +import { SetupUX } from './route'; const LONG_TASK_SUM_FIELD = 'transaction.experience.longtask.sum'; const LONG_TASK_COUNT_FIELD = 'transaction.experience.longtask.count'; diff --git a/x-pack/plugins/apm/server/lib/rum_client/get_page_load_distribution.ts b/x-pack/plugins/apm/server/routes/rum_client/get_page_load_distribution.ts similarity index 99% rename from x-pack/plugins/apm/server/lib/rum_client/get_page_load_distribution.ts rename to x-pack/plugins/apm/server/routes/rum_client/get_page_load_distribution.ts index e551b4a34746c..27c8c4668ce9b 100644 --- a/x-pack/plugins/apm/server/lib/rum_client/get_page_load_distribution.ts +++ b/x-pack/plugins/apm/server/routes/rum_client/get_page_load_distribution.ts @@ -8,7 +8,7 @@ import { TRANSACTION_DURATION } from '../../../common/elasticsearch_fieldnames'; import { getRumPageLoadTransactionsProjection } from '../../projections/rum_page_load_transactions'; import { mergeProjection } from '../../projections/util/merge_projection'; -import { SetupUX } from '../../routes/rum_client'; +import { SetupUX } from './route'; export const MICRO_TO_SEC = 1000000; diff --git a/x-pack/plugins/apm/server/lib/rum_client/get_page_view_trends.ts b/x-pack/plugins/apm/server/routes/rum_client/get_page_view_trends.ts similarity index 98% rename from x-pack/plugins/apm/server/lib/rum_client/get_page_view_trends.ts rename to x-pack/plugins/apm/server/routes/rum_client/get_page_view_trends.ts index 87766aae43272..6bcc7f66d1dfd 100644 --- a/x-pack/plugins/apm/server/lib/rum_client/get_page_view_trends.ts +++ b/x-pack/plugins/apm/server/routes/rum_client/get_page_view_trends.ts @@ -7,7 +7,7 @@ import { getRumPageLoadTransactionsProjection } from '../../projections/rum_page_load_transactions'; import { mergeProjection } from '../../projections/util/merge_projection'; -import { SetupUX } from '../../routes/rum_client'; +import { SetupUX } from './route'; import { BreakdownItem } from '../../../typings/ui_filters'; export async function getPageViewTrends({ diff --git a/x-pack/plugins/apm/server/lib/rum_client/get_pl_dist_breakdown.ts b/x-pack/plugins/apm/server/routes/rum_client/get_pl_dist_breakdown.ts similarity index 98% rename from x-pack/plugins/apm/server/lib/rum_client/get_pl_dist_breakdown.ts rename to x-pack/plugins/apm/server/routes/rum_client/get_pl_dist_breakdown.ts index 298f2a3b7ddf0..d6a67b57fa98f 100644 --- a/x-pack/plugins/apm/server/lib/rum_client/get_pl_dist_breakdown.ts +++ b/x-pack/plugins/apm/server/routes/rum_client/get_pl_dist_breakdown.ts @@ -8,7 +8,7 @@ import { getRumPageLoadTransactionsProjection } from '../../projections/rum_page_load_transactions'; import { ProcessorEvent } from '../../../common/processor_event'; import { mergeProjection } from '../../projections/util/merge_projection'; -import { SetupUX } from '../../routes/rum_client'; +import { SetupUX } from './route'; import { CLIENT_GEO_COUNTRY_ISO_CODE, USER_AGENT_DEVICE, diff --git a/x-pack/plugins/apm/server/lib/rum_client/get_rum_services.ts b/x-pack/plugins/apm/server/routes/rum_client/get_rum_services.ts similarity index 96% rename from x-pack/plugins/apm/server/lib/rum_client/get_rum_services.ts rename to x-pack/plugins/apm/server/routes/rum_client/get_rum_services.ts index 1929f7e3ed994..e62b54f00d212 100644 --- a/x-pack/plugins/apm/server/lib/rum_client/get_rum_services.ts +++ b/x-pack/plugins/apm/server/routes/rum_client/get_rum_services.ts @@ -5,7 +5,7 @@ * 2.0. */ import { SERVICE_NAME } from '../../../common/elasticsearch_fieldnames'; -import { SetupUX } from '../../routes/rum_client'; +import { SetupUX } from './route'; import { getRumPageLoadTransactionsProjection } from '../../projections/rum_page_load_transactions'; import { mergeProjection } from '../../projections/util/merge_projection'; diff --git a/x-pack/plugins/apm/server/lib/rum_client/get_url_search.ts b/x-pack/plugins/apm/server/routes/rum_client/get_url_search.ts similarity index 97% rename from x-pack/plugins/apm/server/lib/rum_client/get_url_search.ts rename to x-pack/plugins/apm/server/routes/rum_client/get_url_search.ts index 515df78f87bd8..0ffb836402f61 100644 --- a/x-pack/plugins/apm/server/lib/rum_client/get_url_search.ts +++ b/x-pack/plugins/apm/server/routes/rum_client/get_url_search.ts @@ -6,7 +6,7 @@ */ import { mergeProjection } from '../../projections/util/merge_projection'; -import { SetupUX } from '../../routes/rum_client'; +import { SetupUX } from './route'; import { getRumPageLoadTransactionsProjection } from '../../projections/rum_page_load_transactions'; import { TRANSACTION_DURATION, diff --git a/x-pack/plugins/apm/server/lib/rum_client/get_visitor_breakdown.ts b/x-pack/plugins/apm/server/routes/rum_client/get_visitor_breakdown.ts similarity index 97% rename from x-pack/plugins/apm/server/lib/rum_client/get_visitor_breakdown.ts rename to x-pack/plugins/apm/server/routes/rum_client/get_visitor_breakdown.ts index ed0a4e90a4cb7..d7447889db849 100644 --- a/x-pack/plugins/apm/server/lib/rum_client/get_visitor_breakdown.ts +++ b/x-pack/plugins/apm/server/routes/rum_client/get_visitor_breakdown.ts @@ -7,7 +7,7 @@ import { getRumPageLoadTransactionsProjection } from '../../projections/rum_page_load_transactions'; import { mergeProjection } from '../../projections/util/merge_projection'; -import { SetupUX } from '../../routes/rum_client'; +import { SetupUX } from './route'; import { USER_AGENT_NAME, USER_AGENT_OS, diff --git a/x-pack/plugins/apm/server/lib/rum_client/get_web_core_vitals.ts b/x-pack/plugins/apm/server/routes/rum_client/get_web_core_vitals.ts similarity index 98% rename from x-pack/plugins/apm/server/lib/rum_client/get_web_core_vitals.ts rename to x-pack/plugins/apm/server/routes/rum_client/get_web_core_vitals.ts index 6dfa3abe117df..6a3b3a1c7b1c8 100644 --- a/x-pack/plugins/apm/server/lib/rum_client/get_web_core_vitals.ts +++ b/x-pack/plugins/apm/server/routes/rum_client/get_web_core_vitals.ts @@ -7,7 +7,7 @@ import { getRumPageLoadTransactionsProjection } from '../../projections/rum_page_load_transactions'; import { mergeProjection } from '../../projections/util/merge_projection'; -import { SetupUX } from '../../routes/rum_client'; +import { SetupUX } from './route'; import { CLS_FIELD, FCP_FIELD, diff --git a/x-pack/plugins/apm/server/lib/rum_client/has_rum_data.ts b/x-pack/plugins/apm/server/routes/rum_client/has_rum_data.ts similarity index 97% rename from x-pack/plugins/apm/server/lib/rum_client/has_rum_data.ts rename to x-pack/plugins/apm/server/routes/rum_client/has_rum_data.ts index ba35ac5c5c89c..6cb3bc069e072 100644 --- a/x-pack/plugins/apm/server/lib/rum_client/has_rum_data.ts +++ b/x-pack/plugins/apm/server/routes/rum_client/has_rum_data.ts @@ -6,7 +6,7 @@ */ import moment from 'moment'; -import { SetupUX } from '../../routes/rum_client'; +import { SetupUX } from './route'; import { SERVICE_NAME, TRANSACTION_TYPE, diff --git a/x-pack/plugins/apm/server/lib/rum_client/queries.test.ts b/x-pack/plugins/apm/server/routes/rum_client/queries.test.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/rum_client/queries.test.ts rename to x-pack/plugins/apm/server/routes/rum_client/queries.test.ts diff --git a/x-pack/plugins/apm/server/routes/rum_client.ts b/x-pack/plugins/apm/server/routes/rum_client/route.ts similarity index 87% rename from x-pack/plugins/apm/server/routes/rum_client.ts rename to x-pack/plugins/apm/server/routes/rum_client/route.ts index e84a281a7ce1b..482dcc0799ed0 100644 --- a/x-pack/plugins/apm/server/routes/rum_client.ts +++ b/x-pack/plugins/apm/server/routes/rum_client/route.ts @@ -7,23 +7,23 @@ import * as t from 'io-ts'; import { Logger } from 'kibana/server'; import { isoToEpochRt } from '@kbn/io-ts-utils/iso_to_epoch_rt'; -import { setupRequest, Setup } from '../lib/helpers/setup_request'; -import { getClientMetrics } from '../lib/rum_client/get_client_metrics'; -import { getJSErrors } from '../lib/rum_client/get_js_errors'; -import { getLongTaskMetrics } from '../lib/rum_client/get_long_task_metrics'; -import { getPageLoadDistribution } from '../lib/rum_client/get_page_load_distribution'; -import { getPageViewTrends } from '../lib/rum_client/get_page_view_trends'; -import { getPageLoadDistBreakdown } from '../lib/rum_client/get_pl_dist_breakdown'; -import { getRumServices } from '../lib/rum_client/get_rum_services'; -import { getUrlSearch } from '../lib/rum_client/get_url_search'; -import { getVisitorBreakdown } from '../lib/rum_client/get_visitor_breakdown'; -import { getWebCoreVitals } from '../lib/rum_client/get_web_core_vitals'; -import { hasRumData } from '../lib/rum_client/has_rum_data'; -import { createApmServerRoute } from './apm_routes/create_apm_server_route'; -import { createApmServerRouteRepository } from './apm_routes/create_apm_server_route_repository'; -import { rangeRt } from './default_api_types'; -import { UxUIFilters } from '../../typings/ui_filters'; -import { APMRouteHandlerResources } from '../routes/typings'; +import { setupRequest, Setup } from '../../lib/helpers/setup_request'; +import { getClientMetrics } from './get_client_metrics'; +import { getJSErrors } from './get_js_errors'; +import { getLongTaskMetrics } from './get_long_task_metrics'; +import { getPageLoadDistribution } from './get_page_load_distribution'; +import { getPageViewTrends } from './get_page_view_trends'; +import { getPageLoadDistBreakdown } from './get_pl_dist_breakdown'; +import { getRumServices } from './get_rum_services'; +import { getUrlSearch } from './get_url_search'; +import { getVisitorBreakdown } from './get_visitor_breakdown'; +import { getWebCoreVitals } from './get_web_core_vitals'; +import { hasRumData } from './has_rum_data'; +import { createApmServerRoute } from '../apm_routes/create_apm_server_route'; +import { createApmServerRouteRepository } from '../apm_routes/create_apm_server_route_repository'; +import { rangeRt } from '../default_api_types'; +import { UxUIFilters } from '../../../typings/ui_filters'; +import { APMRouteHandlerResources } from '../typings'; export type SetupUX = Setup & { uiFilters: UxUIFilters; diff --git a/x-pack/plugins/apm/server/lib/rum_client/ui_filters/get_es_filter.test.ts b/x-pack/plugins/apm/server/routes/rum_client/ui_filters/get_es_filter.test.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/rum_client/ui_filters/get_es_filter.test.ts rename to x-pack/plugins/apm/server/routes/rum_client/ui_filters/get_es_filter.test.ts diff --git a/x-pack/plugins/apm/server/lib/rum_client/ui_filters/get_es_filter.ts b/x-pack/plugins/apm/server/routes/rum_client/ui_filters/get_es_filter.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/rum_client/ui_filters/get_es_filter.ts rename to x-pack/plugins/apm/server/routes/rum_client/ui_filters/get_es_filter.ts diff --git a/x-pack/plugins/apm/server/lib/service_map/fetch_service_paths_from_trace_ids.ts b/x-pack/plugins/apm/server/routes/service_map/fetch_service_paths_from_trace_ids.ts similarity index 99% rename from x-pack/plugins/apm/server/lib/service_map/fetch_service_paths_from_trace_ids.ts rename to x-pack/plugins/apm/server/routes/service_map/fetch_service_paths_from_trace_ids.ts index 2f725b61942cd..b3bd4d1510180 100644 --- a/x-pack/plugins/apm/server/lib/service_map/fetch_service_paths_from_trace_ids.ts +++ b/x-pack/plugins/apm/server/routes/service_map/fetch_service_paths_from_trace_ids.ts @@ -13,7 +13,7 @@ import { ExternalConnectionNode, ServiceConnectionNode, } from '../../../common/service_map'; -import { Setup } from '../helpers/setup_request'; +import { Setup } from '../../lib/helpers/setup_request'; export async function fetchServicePathsFromTraceIds( setup: Setup, diff --git a/x-pack/plugins/apm/server/lib/service_map/get_service_anomalies.ts b/x-pack/plugins/apm/server/routes/service_map/get_service_anomalies.ts similarity index 97% rename from x-pack/plugins/apm/server/lib/service_map/get_service_anomalies.ts rename to x-pack/plugins/apm/server/routes/service_map/get_service_anomalies.ts index 2aa2f5c6eead5..65c022b7175de 100644 --- a/x-pack/plugins/apm/server/lib/service_map/get_service_anomalies.ts +++ b/x-pack/plugins/apm/server/routes/service_map/get_service_anomalies.ts @@ -20,8 +20,8 @@ import { } from '../../../common/transaction_types'; import { rangeQuery } from '../../../../observability/server'; import { withApmSpan } from '../../utils/with_apm_span'; -import { getMlJobsWithAPMGroup } from '../anomaly_detection/get_ml_jobs_with_apm_group'; -import { Setup } from '../helpers/setup_request'; +import { getMlJobsWithAPMGroup } from '../../lib/anomaly_detection/get_ml_jobs_with_apm_group'; +import { Setup } from '../../lib/helpers/setup_request'; import { apmMlAnomalyQuery } from '../../../common/anomaly_detection/apm_ml_anomaly_query'; import { ApmMlDetectorIndex } from '../../../common/anomaly_detection/apm_ml_detectors'; diff --git a/x-pack/plugins/apm/server/lib/service_map/get_service_map.ts b/x-pack/plugins/apm/server/routes/service_map/get_service_map.ts similarity index 97% rename from x-pack/plugins/apm/server/lib/service_map/get_service_map.ts rename to x-pack/plugins/apm/server/routes/service_map/get_service_map.ts index 9f94bdd9275c0..d7eb101f77e38 100644 --- a/x-pack/plugins/apm/server/lib/service_map/get_service_map.ts +++ b/x-pack/plugins/apm/server/routes/service_map/get_service_map.ts @@ -17,7 +17,7 @@ import { } from '../../../common/elasticsearch_fieldnames'; import { environmentQuery } from '../../../common/utils/environment_query'; import { withApmSpan } from '../../utils/with_apm_span'; -import { Setup } from '../helpers/setup_request'; +import { Setup } from '../../lib/helpers/setup_request'; import { DEFAULT_ANOMALIES, getServiceAnomalies, @@ -26,7 +26,7 @@ import { getServiceMapFromTraceIds } from './get_service_map_from_trace_ids'; import { getTraceSampleIds } from './get_trace_sample_ids'; import { transformServiceMapResponses } from './transform_service_map_responses'; import { ENVIRONMENT_ALL } from '../../../common/environment_filter_values'; -import { getProcessorEventForTransactions } from '../helpers/transactions'; +import { getProcessorEventForTransactions } from '../../lib/helpers/transactions'; export interface IEnvOptions { setup: Setup; diff --git a/x-pack/plugins/apm/server/lib/service_map/get_service_map_backend_node_info.ts b/x-pack/plugins/apm/server/routes/service_map/get_service_map_backend_node_info.ts similarity index 95% rename from x-pack/plugins/apm/server/lib/service_map/get_service_map_backend_node_info.ts rename to x-pack/plugins/apm/server/routes/service_map/get_service_map_backend_node_info.ts index c8242731e756c..3866bac88ef44 100644 --- a/x-pack/plugins/apm/server/lib/service_map/get_service_map_backend_node_info.ts +++ b/x-pack/plugins/apm/server/routes/service_map/get_service_map_backend_node_info.ts @@ -16,8 +16,8 @@ import { EventOutcome } from '../../../common/event_outcome'; import { ProcessorEvent } from '../../../common/processor_event'; import { environmentQuery } from '../../../common/utils/environment_query'; import { withApmSpan } from '../../utils/with_apm_span'; -import { calculateThroughput } from '../helpers/calculate_throughput'; -import { Setup } from '../helpers/setup_request'; +import { calculateThroughput } from '../../lib/helpers/calculate_throughput'; +import { Setup } from '../../lib/helpers/setup_request'; interface Options { setup: Setup; diff --git a/x-pack/plugins/apm/server/lib/service_map/get_service_map_from_trace_ids.test.ts b/x-pack/plugins/apm/server/routes/service_map/get_service_map_from_trace_ids.test.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/service_map/get_service_map_from_trace_ids.test.ts rename to x-pack/plugins/apm/server/routes/service_map/get_service_map_from_trace_ids.test.ts diff --git a/x-pack/plugins/apm/server/lib/service_map/get_service_map_from_trace_ids.ts b/x-pack/plugins/apm/server/routes/service_map/get_service_map_from_trace_ids.ts similarity index 96% rename from x-pack/plugins/apm/server/lib/service_map/get_service_map_from_trace_ids.ts rename to x-pack/plugins/apm/server/routes/service_map/get_service_map_from_trace_ids.ts index e77e127aebb42..6a61a514881b0 100644 --- a/x-pack/plugins/apm/server/lib/service_map/get_service_map_from_trace_ids.ts +++ b/x-pack/plugins/apm/server/routes/service_map/get_service_map_from_trace_ids.ts @@ -7,7 +7,7 @@ import { find, uniqBy } from 'lodash'; import { Connection, ConnectionNode } from '../../../common/service_map'; -import { Setup } from '../helpers/setup_request'; +import { Setup } from '../../lib/helpers/setup_request'; import { fetchServicePathsFromTraceIds } from './fetch_service_paths_from_trace_ids'; export function getConnections({ diff --git a/x-pack/plugins/apm/server/lib/service_map/get_service_map_service_node_info.test.ts b/x-pack/plugins/apm/server/routes/service_map/get_service_map_service_node_info.test.ts similarity index 95% rename from x-pack/plugins/apm/server/lib/service_map/get_service_map_service_node_info.test.ts rename to x-pack/plugins/apm/server/routes/service_map/get_service_map_service_node_info.test.ts index e064d97bb7aee..9f65481d07489 100644 --- a/x-pack/plugins/apm/server/lib/service_map/get_service_map_service_node_info.test.ts +++ b/x-pack/plugins/apm/server/routes/service_map/get_service_map_service_node_info.test.ts @@ -6,8 +6,8 @@ */ import { getServiceMapServiceNodeInfo } from './get_service_map_service_node_info'; -import { Setup } from '../helpers/setup_request'; -import * as getErrorRateModule from '../transaction_groups/get_error_rate'; +import { Setup } from '../../lib/helpers/setup_request'; +import * as getErrorRateModule from '../../lib/transaction_groups/get_error_rate'; import { ENVIRONMENT_ALL } from '../../../common/environment_filter_values'; describe('getServiceMapServiceNodeInfo', () => { diff --git a/x-pack/plugins/apm/server/lib/service_map/get_service_map_service_node_info.ts b/x-pack/plugins/apm/server/routes/service_map/get_service_map_service_node_info.ts similarity index 97% rename from x-pack/plugins/apm/server/lib/service_map/get_service_map_service_node_info.ts rename to x-pack/plugins/apm/server/routes/service_map/get_service_map_service_node_info.ts index 2f089adf70c1c..d6eb7729effaf 100644 --- a/x-pack/plugins/apm/server/lib/service_map/get_service_map_service_node_info.ts +++ b/x-pack/plugins/apm/server/routes/service_map/get_service_map_service_node_info.ts @@ -26,13 +26,13 @@ import { getDocumentTypeFilterForTransactions, getTransactionDurationFieldForTransactions, getProcessorEventForTransactions, -} from '../helpers/transactions'; -import { Setup } from '../helpers/setup_request'; +} from '../../lib/helpers/transactions'; +import { Setup } from '../../lib/helpers/setup_request'; import { percentCgroupMemoryUsedScript, percentSystemMemoryUsedScript, } from '../metrics/by_agent/shared/memory'; -import { getErrorRate } from '../transaction_groups/get_error_rate'; +import { getErrorRate } from '../../lib/transaction_groups/get_error_rate'; interface Options { setup: Setup; diff --git a/x-pack/plugins/apm/server/lib/service_map/get_trace_sample_ids.ts b/x-pack/plugins/apm/server/routes/service_map/get_trace_sample_ids.ts similarity index 98% rename from x-pack/plugins/apm/server/lib/service_map/get_trace_sample_ids.ts rename to x-pack/plugins/apm/server/routes/service_map/get_trace_sample_ids.ts index 7e16e69498e7c..af24953833a27 100644 --- a/x-pack/plugins/apm/server/lib/service_map/get_trace_sample_ids.ts +++ b/x-pack/plugins/apm/server/routes/service_map/get_trace_sample_ids.ts @@ -18,7 +18,7 @@ import { ProcessorEvent } from '../../../common/processor_event'; import { SERVICE_MAP_TIMEOUT_ERROR } from '../../../common/service_map'; import { rangeQuery } from '../../../../observability/server'; import { environmentQuery } from '../../../common/utils/environment_query'; -import { Setup } from '../helpers/setup_request'; +import { Setup } from '../../lib/helpers/setup_request'; const MAX_TRACES_TO_INSPECT = 1000; diff --git a/x-pack/plugins/apm/server/lib/service_map/group_resource_nodes.test.ts b/x-pack/plugins/apm/server/routes/service_map/group_resource_nodes.test.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/service_map/group_resource_nodes.test.ts rename to x-pack/plugins/apm/server/routes/service_map/group_resource_nodes.test.ts diff --git a/x-pack/plugins/apm/server/lib/service_map/group_resource_nodes.ts b/x-pack/plugins/apm/server/routes/service_map/group_resource_nodes.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/service_map/group_resource_nodes.ts rename to x-pack/plugins/apm/server/routes/service_map/group_resource_nodes.ts diff --git a/x-pack/plugins/apm/server/lib/service_map/mock_responses/group_resource_nodes_grouped.json b/x-pack/plugins/apm/server/routes/service_map/mock_responses/group_resource_nodes_grouped.json similarity index 100% rename from x-pack/plugins/apm/server/lib/service_map/mock_responses/group_resource_nodes_grouped.json rename to x-pack/plugins/apm/server/routes/service_map/mock_responses/group_resource_nodes_grouped.json diff --git a/x-pack/plugins/apm/server/lib/service_map/mock_responses/group_resource_nodes_pregrouped.json b/x-pack/plugins/apm/server/routes/service_map/mock_responses/group_resource_nodes_pregrouped.json similarity index 100% rename from x-pack/plugins/apm/server/lib/service_map/mock_responses/group_resource_nodes_pregrouped.json rename to x-pack/plugins/apm/server/routes/service_map/mock_responses/group_resource_nodes_pregrouped.json diff --git a/x-pack/plugins/apm/server/routes/service_map.ts b/x-pack/plugins/apm/server/routes/service_map/route.ts similarity index 81% rename from x-pack/plugins/apm/server/routes/service_map.ts rename to x-pack/plugins/apm/server/routes/service_map/route.ts index e75b4ec832d82..97d0c01ed6a44 100644 --- a/x-pack/plugins/apm/server/routes/service_map.ts +++ b/x-pack/plugins/apm/server/routes/service_map/route.ts @@ -7,17 +7,17 @@ import Boom from '@hapi/boom'; import * as t from 'io-ts'; -import { isActivePlatinumLicense } from '../../common/license_check'; -import { invalidLicenseMessage } from '../../common/service_map'; -import { notifyFeatureUsage } from '../feature'; -import { getSearchAggregatedTransactions } from '../lib/helpers/transactions'; -import { setupRequest } from '../lib/helpers/setup_request'; -import { getServiceMap } from '../lib/service_map/get_service_map'; -import { getServiceMapBackendNodeInfo } from '../lib/service_map/get_service_map_backend_node_info'; -import { getServiceMapServiceNodeInfo } from '../lib/service_map/get_service_map_service_node_info'; -import { createApmServerRoute } from './apm_routes/create_apm_server_route'; -import { createApmServerRouteRepository } from './apm_routes/create_apm_server_route_repository'; -import { environmentRt, rangeRt } from './default_api_types'; +import { isActivePlatinumLicense } from '../../../common/license_check'; +import { invalidLicenseMessage } from '../../../common/service_map'; +import { notifyFeatureUsage } from '../../feature'; +import { getSearchAggregatedTransactions } from '../../lib/helpers/transactions'; +import { setupRequest } from '../../lib/helpers/setup_request'; +import { getServiceMap } from './get_service_map'; +import { getServiceMapBackendNodeInfo } from './get_service_map_backend_node_info'; +import { getServiceMapServiceNodeInfo } from './get_service_map_service_node_info'; +import { createApmServerRoute } from '../apm_routes/create_apm_server_route'; +import { createApmServerRouteRepository } from '../apm_routes/create_apm_server_route_repository'; +import { environmentRt, rangeRt } from '../default_api_types'; const serviceMapRoute = createApmServerRoute({ endpoint: 'GET /internal/apm/service-map', diff --git a/x-pack/plugins/apm/server/lib/service_map/transform_service_map_responses.test.ts b/x-pack/plugins/apm/server/routes/service_map/transform_service_map_responses.test.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/service_map/transform_service_map_responses.test.ts rename to x-pack/plugins/apm/server/routes/service_map/transform_service_map_responses.test.ts diff --git a/x-pack/plugins/apm/server/lib/service_map/transform_service_map_responses.ts b/x-pack/plugins/apm/server/routes/service_map/transform_service_map_responses.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/service_map/transform_service_map_responses.ts rename to x-pack/plugins/apm/server/routes/service_map/transform_service_map_responses.ts diff --git a/x-pack/plugins/apm/server/lib/service_nodes/__snapshots__/queries.test.ts.snap b/x-pack/plugins/apm/server/routes/service_nodes/__snapshots__/queries.test.ts.snap similarity index 100% rename from x-pack/plugins/apm/server/lib/service_nodes/__snapshots__/queries.test.ts.snap rename to x-pack/plugins/apm/server/routes/service_nodes/__snapshots__/queries.test.ts.snap diff --git a/x-pack/plugins/apm/server/lib/service_nodes/index.ts b/x-pack/plugins/apm/server/routes/service_nodes/get_service_nodes.ts similarity index 98% rename from x-pack/plugins/apm/server/lib/service_nodes/index.ts rename to x-pack/plugins/apm/server/routes/service_nodes/get_service_nodes.ts index 541fbb79c9e50..ebd56cb9768ce 100644 --- a/x-pack/plugins/apm/server/lib/service_nodes/index.ts +++ b/x-pack/plugins/apm/server/routes/service_nodes/get_service_nodes.ts @@ -21,7 +21,7 @@ import { import { ProcessorEvent } from '../../../common/processor_event'; import { kqlQuery, rangeQuery } from '../../../../observability/server'; import { environmentQuery } from '../../../common/utils/environment_query'; -import { Setup } from '../helpers/setup_request'; +import { Setup } from '../../lib/helpers/setup_request'; const getServiceNodes = async ({ kuery, diff --git a/x-pack/plugins/apm/server/lib/service_nodes/queries.test.ts b/x-pack/plugins/apm/server/routes/service_nodes/queries.test.ts similarity index 96% rename from x-pack/plugins/apm/server/lib/service_nodes/queries.test.ts rename to x-pack/plugins/apm/server/routes/service_nodes/queries.test.ts index f8bc3879d5794..470be6142aaed 100644 --- a/x-pack/plugins/apm/server/lib/service_nodes/queries.test.ts +++ b/x-pack/plugins/apm/server/routes/service_nodes/queries.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { getServiceNodes } from './'; +import { getServiceNodes } from './get_service_nodes'; import { SearchParamsMock, inspectSearchParams, diff --git a/x-pack/plugins/apm/server/routes/service_nodes.ts b/x-pack/plugins/apm/server/routes/service_nodes/route.ts similarity index 72% rename from x-pack/plugins/apm/server/routes/service_nodes.ts rename to x-pack/plugins/apm/server/routes/service_nodes/route.ts index 61d58bfa3cf38..027a907dd2659 100644 --- a/x-pack/plugins/apm/server/routes/service_nodes.ts +++ b/x-pack/plugins/apm/server/routes/service_nodes/route.ts @@ -6,12 +6,12 @@ */ import * as t from 'io-ts'; -import { createApmServerRouteRepository } from './apm_routes/create_apm_server_route_repository'; -import { createApmServerRoute } from './apm_routes/create_apm_server_route'; -import { setupRequest } from '../lib/helpers/setup_request'; -import { getServiceNodes } from '../lib/service_nodes'; -import { rangeRt, kueryRt } from './default_api_types'; -import { environmentRt } from '../../common/environment_rt'; +import { createApmServerRouteRepository } from '../apm_routes/create_apm_server_route_repository'; +import { createApmServerRoute } from '../apm_routes/create_apm_server_route'; +import { setupRequest } from '../../lib/helpers/setup_request'; +import { getServiceNodes } from './get_service_nodes'; +import { rangeRt, kueryRt } from '../default_api_types'; +import { environmentRt } from '../../../common/environment_rt'; const serviceNodesRoute = createApmServerRoute({ endpoint: 'GET /internal/apm/services/{serviceName}/serviceNodes', diff --git a/x-pack/plugins/apm/server/lib/services/__snapshots__/queries.test.ts.snap b/x-pack/plugins/apm/server/routes/services/__snapshots__/queries.test.ts.snap similarity index 100% rename from x-pack/plugins/apm/server/lib/services/__snapshots__/queries.test.ts.snap rename to x-pack/plugins/apm/server/routes/services/__snapshots__/queries.test.ts.snap diff --git a/x-pack/plugins/apm/server/lib/services/annotations/__fixtures__/multiple_versions.json b/x-pack/plugins/apm/server/routes/services/annotations/__fixtures__/multiple_versions.json similarity index 100% rename from x-pack/plugins/apm/server/lib/services/annotations/__fixtures__/multiple_versions.json rename to x-pack/plugins/apm/server/routes/services/annotations/__fixtures__/multiple_versions.json diff --git a/x-pack/plugins/apm/server/lib/services/annotations/__fixtures__/no_versions.json b/x-pack/plugins/apm/server/routes/services/annotations/__fixtures__/no_versions.json similarity index 100% rename from x-pack/plugins/apm/server/lib/services/annotations/__fixtures__/no_versions.json rename to x-pack/plugins/apm/server/routes/services/annotations/__fixtures__/no_versions.json diff --git a/x-pack/plugins/apm/server/lib/services/annotations/__fixtures__/one_version.json b/x-pack/plugins/apm/server/routes/services/annotations/__fixtures__/one_version.json similarity index 100% rename from x-pack/plugins/apm/server/lib/services/annotations/__fixtures__/one_version.json rename to x-pack/plugins/apm/server/routes/services/annotations/__fixtures__/one_version.json diff --git a/x-pack/plugins/apm/server/lib/services/annotations/__fixtures__/versions_first_seen.json b/x-pack/plugins/apm/server/routes/services/annotations/__fixtures__/versions_first_seen.json similarity index 100% rename from x-pack/plugins/apm/server/lib/services/annotations/__fixtures__/versions_first_seen.json rename to x-pack/plugins/apm/server/routes/services/annotations/__fixtures__/versions_first_seen.json diff --git a/x-pack/plugins/apm/server/lib/services/annotations/get_derived_service_annotations.ts b/x-pack/plugins/apm/server/routes/services/annotations/get_derived_service_annotations.ts similarity index 96% rename from x-pack/plugins/apm/server/lib/services/annotations/get_derived_service_annotations.ts rename to x-pack/plugins/apm/server/routes/services/annotations/get_derived_service_annotations.ts index 22b37e33a26e2..523775de170e7 100644 --- a/x-pack/plugins/apm/server/lib/services/annotations/get_derived_service_annotations.ts +++ b/x-pack/plugins/apm/server/routes/services/annotations/get_derived_service_annotations.ts @@ -17,8 +17,8 @@ import { environmentQuery } from '../../../../common/utils/environment_query'; import { getDocumentTypeFilterForTransactions, getProcessorEventForTransactions, -} from '../../helpers/transactions'; -import { Setup } from '../../helpers/setup_request'; +} from '../../../lib/helpers/transactions'; +import { Setup } from '../../../lib/helpers/setup_request'; export async function getDerivedServiceAnnotations({ setup, diff --git a/x-pack/plugins/apm/server/lib/services/annotations/get_stored_annotations.ts b/x-pack/plugins/apm/server/routes/services/annotations/get_stored_annotations.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/services/annotations/get_stored_annotations.ts rename to x-pack/plugins/apm/server/routes/services/annotations/get_stored_annotations.ts diff --git a/x-pack/plugins/apm/server/lib/services/annotations/index.test.ts b/x-pack/plugins/apm/server/routes/services/annotations/index.test.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/services/annotations/index.test.ts rename to x-pack/plugins/apm/server/routes/services/annotations/index.test.ts diff --git a/x-pack/plugins/apm/server/lib/services/annotations/index.ts b/x-pack/plugins/apm/server/routes/services/annotations/index.ts similarity index 96% rename from x-pack/plugins/apm/server/lib/services/annotations/index.ts rename to x-pack/plugins/apm/server/routes/services/annotations/index.ts index 677530522f6ca..488a4ce6e4c20 100644 --- a/x-pack/plugins/apm/server/lib/services/annotations/index.ts +++ b/x-pack/plugins/apm/server/routes/services/annotations/index.ts @@ -8,7 +8,7 @@ import { ElasticsearchClient, Logger } from 'kibana/server'; import { ScopedAnnotationsClient } from '../../../../../observability/server'; import { getDerivedServiceAnnotations } from './get_derived_service_annotations'; -import { Setup } from '../../helpers/setup_request'; +import { Setup } from '../../../lib/helpers/setup_request'; import { getStoredAnnotations } from './get_stored_annotations'; export async function getServiceAnnotations({ diff --git a/x-pack/plugins/apm/server/lib/services/get_service_agent.ts b/x-pack/plugins/apm/server/routes/services/get_service_agent.ts similarity index 97% rename from x-pack/plugins/apm/server/lib/services/get_service_agent.ts rename to x-pack/plugins/apm/server/routes/services/get_service_agent.ts index dc3fee20fdf68..8117729eb9b59 100644 --- a/x-pack/plugins/apm/server/lib/services/get_service_agent.ts +++ b/x-pack/plugins/apm/server/routes/services/get_service_agent.ts @@ -12,7 +12,7 @@ import { SERVICE_RUNTIME_NAME, } from '../../../common/elasticsearch_fieldnames'; import { rangeQuery } from '../../../../observability/server'; -import { Setup } from '../helpers/setup_request'; +import { Setup } from '../../lib/helpers/setup_request'; interface ServiceAgent { agent?: { diff --git a/x-pack/plugins/apm/server/lib/services/get_service_alerts.ts b/x-pack/plugins/apm/server/routes/services/get_service_alerts.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/services/get_service_alerts.ts rename to x-pack/plugins/apm/server/routes/services/get_service_alerts.ts diff --git a/x-pack/plugins/apm/server/lib/services/get_service_dependencies.ts b/x-pack/plugins/apm/server/routes/services/get_service_dependencies.ts similarity index 77% rename from x-pack/plugins/apm/server/lib/services/get_service_dependencies.ts rename to x-pack/plugins/apm/server/routes/services/get_service_dependencies.ts index d4472d495230a..cf60502e9861b 100644 --- a/x-pack/plugins/apm/server/lib/services/get_service_dependencies.ts +++ b/x-pack/plugins/apm/server/routes/services/get_service_dependencies.ts @@ -7,9 +7,9 @@ import { SERVICE_NAME } from '../../../common/elasticsearch_fieldnames'; import { environmentQuery } from '../../../common/utils/environment_query'; -import { getConnectionStats } from '../connections/get_connection_stats'; -import { getConnectionStatsItemsWithRelativeImpact } from '../connections/get_connection_stats/get_connection_stats_items_with_relative_impact'; -import { Setup } from '../helpers/setup_request'; +import { getConnectionStats } from '../../lib/connections/get_connection_stats'; +import { getConnectionStatsItemsWithRelativeImpact } from '../../lib/connections/get_connection_stats/get_connection_stats_items_with_relative_impact'; +import { Setup } from '../../lib/helpers/setup_request'; export async function getServiceDependencies({ setup, diff --git a/x-pack/plugins/apm/server/lib/services/get_service_dependencies_breakdown.ts b/x-pack/plugins/apm/server/routes/services/get_service_dependencies_breakdown.ts similarity index 90% rename from x-pack/plugins/apm/server/lib/services/get_service_dependencies_breakdown.ts rename to x-pack/plugins/apm/server/routes/services/get_service_dependencies_breakdown.ts index c0e1af40d98db..a0b8eb1768d6f 100644 --- a/x-pack/plugins/apm/server/lib/services/get_service_dependencies_breakdown.ts +++ b/x-pack/plugins/apm/server/routes/services/get_service_dependencies_breakdown.ts @@ -9,8 +9,8 @@ import { getNodeName } from '../../../common/connections'; import { kqlQuery } from '../../../../observability/server'; import { SERVICE_NAME } from '../../../common/elasticsearch_fieldnames'; import { environmentQuery } from '../../../common/utils/environment_query'; -import { Setup } from '../helpers/setup_request'; -import { getConnectionStats } from '../connections/get_connection_stats'; +import { Setup } from '../../lib/helpers/setup_request'; +import { getConnectionStats } from '../../lib/connections/get_connection_stats'; export async function getServiceDependenciesBreakdown({ setup, diff --git a/x-pack/plugins/apm/server/lib/services/get_service_error_groups/get_service_error_group_detailed_statistics.ts b/x-pack/plugins/apm/server/routes/services/get_service_error_groups/get_service_error_group_detailed_statistics.ts similarity index 97% rename from x-pack/plugins/apm/server/lib/services/get_service_error_groups/get_service_error_group_detailed_statistics.ts rename to x-pack/plugins/apm/server/routes/services/get_service_error_groups/get_service_error_group_detailed_statistics.ts index 9a0b6155fe84d..17c538d0fd7ea 100644 --- a/x-pack/plugins/apm/server/lib/services/get_service_error_groups/get_service_error_group_detailed_statistics.ts +++ b/x-pack/plugins/apm/server/routes/services/get_service_error_groups/get_service_error_group_detailed_statistics.ts @@ -15,8 +15,8 @@ import { import { ProcessorEvent } from '../../../../common/processor_event'; import { rangeQuery, kqlQuery } from '../../../../../observability/server'; import { environmentQuery } from '../../../../common/utils/environment_query'; -import { getBucketSize } from '../../helpers/get_bucket_size'; -import { Setup } from '../../helpers/setup_request'; +import { getBucketSize } from '../../../lib/helpers/get_bucket_size'; +import { Setup } from '../../../lib/helpers/setup_request'; export async function getServiceErrorGroupDetailedStatistics({ kuery, diff --git a/x-pack/plugins/apm/server/lib/services/get_service_error_groups/get_service_error_group_main_statistics.ts b/x-pack/plugins/apm/server/routes/services/get_service_error_groups/get_service_error_group_main_statistics.ts similarity index 95% rename from x-pack/plugins/apm/server/lib/services/get_service_error_groups/get_service_error_group_main_statistics.ts rename to x-pack/plugins/apm/server/routes/services/get_service_error_groups/get_service_error_group_main_statistics.ts index 1a25b18f81aac..8d174abb1bed5 100644 --- a/x-pack/plugins/apm/server/lib/services/get_service_error_groups/get_service_error_group_main_statistics.ts +++ b/x-pack/plugins/apm/server/routes/services/get_service_error_groups/get_service_error_group_main_statistics.ts @@ -15,8 +15,8 @@ import { } from '../../../../common/elasticsearch_fieldnames'; import { ProcessorEvent } from '../../../../common/processor_event'; import { environmentQuery } from '../../../../common/utils/environment_query'; -import { getErrorName } from '../../helpers/get_error_name'; -import { Setup } from '../../helpers/setup_request'; +import { getErrorName } from '../../../lib/helpers/get_error_name'; +import { Setup } from '../../../lib/helpers/setup_request'; export async function getServiceErrorGroupMainStatistics({ kuery, diff --git a/x-pack/plugins/apm/server/lib/services/get_service_error_groups/index.ts b/x-pack/plugins/apm/server/routes/services/get_service_error_groups/index.ts similarity index 96% rename from x-pack/plugins/apm/server/lib/services/get_service_error_groups/index.ts rename to x-pack/plugins/apm/server/routes/services/get_service_error_groups/index.ts index 83cb38da6e0a3..1a853231bb09a 100644 --- a/x-pack/plugins/apm/server/lib/services/get_service_error_groups/index.ts +++ b/x-pack/plugins/apm/server/routes/services/get_service_error_groups/index.ts @@ -19,9 +19,9 @@ import { import { ProcessorEvent } from '../../../../common/processor_event'; import { environmentQuery } from '../../../../common/utils/environment_query'; import { withApmSpan } from '../../../utils/with_apm_span'; -import { getBucketSize } from '../../helpers/get_bucket_size'; -import { getErrorName } from '../../helpers/get_error_name'; -import { Setup } from '../../helpers/setup_request'; +import { getBucketSize } from '../../../lib/helpers/get_bucket_size'; +import { getErrorName } from '../../../lib/helpers/get_error_name'; +import { Setup } from '../../../lib/helpers/setup_request'; export type ServiceErrorGroupItem = ValuesType< PromiseReturnType diff --git a/x-pack/plugins/apm/server/lib/services/get_service_infrastructure.ts b/x-pack/plugins/apm/server/routes/services/get_service_infrastructure.ts similarity index 96% rename from x-pack/plugins/apm/server/lib/services/get_service_infrastructure.ts rename to x-pack/plugins/apm/server/routes/services/get_service_infrastructure.ts index 09946187b90a2..cda0beb6b2d70 100644 --- a/x-pack/plugins/apm/server/lib/services/get_service_infrastructure.ts +++ b/x-pack/plugins/apm/server/routes/services/get_service_infrastructure.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { Setup } from '../helpers/setup_request'; +import { Setup } from '../../lib/helpers/setup_request'; import { rangeQuery, kqlQuery } from '../../../../observability/server'; import { environmentQuery } from '../../../common/utils/environment_query'; import { ProcessorEvent } from '../../../common/processor_event'; diff --git a/x-pack/plugins/apm/server/lib/services/get_service_instance_metadata_details.ts b/x-pack/plugins/apm/server/routes/services/get_service_instance_metadata_details.ts similarity index 97% rename from x-pack/plugins/apm/server/lib/services/get_service_instance_metadata_details.ts rename to x-pack/plugins/apm/server/routes/services/get_service_instance_metadata_details.ts index d349ca3ce0399..957d655b98e5d 100644 --- a/x-pack/plugins/apm/server/lib/services/get_service_instance_metadata_details.ts +++ b/x-pack/plugins/apm/server/routes/services/get_service_instance_metadata_details.ts @@ -12,12 +12,12 @@ import { SERVICE_NODE_NAME, } from '../../../common/elasticsearch_fieldnames'; import { rangeQuery } from '../../../../observability/server'; -import { Setup } from '../helpers/setup_request'; +import { Setup } from '../../lib/helpers/setup_request'; import { maybe } from '../../../common/utils/maybe'; import { getDocumentTypeFilterForTransactions, getProcessorEventForTransactions, -} from '../helpers/transactions'; +} from '../../lib/helpers/transactions'; export async function getServiceInstanceMetadataDetails({ serviceName, diff --git a/x-pack/plugins/apm/server/lib/services/get_service_instances/detailed_statistics.ts b/x-pack/plugins/apm/server/routes/services/get_service_instances/detailed_statistics.ts similarity index 98% rename from x-pack/plugins/apm/server/lib/services/get_service_instances/detailed_statistics.ts rename to x-pack/plugins/apm/server/routes/services/get_service_instances/detailed_statistics.ts index fd6f0f6d03c66..10393e3434779 100644 --- a/x-pack/plugins/apm/server/lib/services/get_service_instances/detailed_statistics.ts +++ b/x-pack/plugins/apm/server/routes/services/get_service_instances/detailed_statistics.ts @@ -11,7 +11,7 @@ import { Coordinate } from '../../../../typings/timeseries'; import { LatencyAggregationType } from '../../../../common/latency_aggregation_types'; import { joinByKey } from '../../../../common/utils/join_by_key'; import { withApmSpan } from '../../../utils/with_apm_span'; -import { Setup } from '../../helpers/setup_request'; +import { Setup } from '../../../lib/helpers/setup_request'; import { getServiceInstancesSystemMetricStatistics } from './get_service_instances_system_metric_statistics'; import { getServiceInstancesTransactionStatistics } from './get_service_instances_transaction_statistics'; diff --git a/x-pack/plugins/apm/server/lib/services/get_service_instances/get_service_instances_system_metric_statistics.ts b/x-pack/plugins/apm/server/routes/services/get_service_instances/get_service_instances_system_metric_statistics.ts similarity index 97% rename from x-pack/plugins/apm/server/lib/services/get_service_instances/get_service_instances_system_metric_statistics.ts rename to x-pack/plugins/apm/server/routes/services/get_service_instances/get_service_instances_system_metric_statistics.ts index 61e89ed8ca5e3..11fcbd8ce6561 100644 --- a/x-pack/plugins/apm/server/lib/services/get_service_instances/get_service_instances_system_metric_statistics.ts +++ b/x-pack/plugins/apm/server/routes/services/get_service_instances/get_service_instances_system_metric_statistics.ts @@ -19,8 +19,8 @@ import { SERVICE_NODE_NAME_MISSING } from '../../../../common/service_nodes'; import { Coordinate } from '../../../../typings/timeseries'; import { kqlQuery, rangeQuery } from '../../../../../observability/server'; import { environmentQuery } from '../../../../common/utils/environment_query'; -import { getBucketSize } from '../../helpers/get_bucket_size'; -import { Setup } from '../../helpers/setup_request'; +import { getBucketSize } from '../../../lib/helpers/get_bucket_size'; +import { Setup } from '../../../lib/helpers/setup_request'; import { percentCgroupMemoryUsedScript, percentSystemMemoryUsedScript, diff --git a/x-pack/plugins/apm/server/lib/services/get_service_instances/get_service_instances_transaction_statistics.ts b/x-pack/plugins/apm/server/routes/services/get_service_instances/get_service_instances_transaction_statistics.ts similarity index 94% rename from x-pack/plugins/apm/server/lib/services/get_service_instances/get_service_instances_transaction_statistics.ts rename to x-pack/plugins/apm/server/routes/services/get_service_instances/get_service_instances_transaction_statistics.ts index b0f64036a1845..166e8d61142ea 100644 --- a/x-pack/plugins/apm/server/lib/services/get_service_instances/get_service_instances_transaction_statistics.ts +++ b/x-pack/plugins/apm/server/routes/services/get_service_instances/get_service_instances_transaction_statistics.ts @@ -20,14 +20,14 @@ import { getDocumentTypeFilterForTransactions, getTransactionDurationFieldForTransactions, getProcessorEventForTransactions, -} from '../../helpers/transactions'; -import { calculateThroughput } from '../../helpers/calculate_throughput'; -import { getBucketSizeForAggregatedTransactions } from '../../helpers/get_bucket_size_for_aggregated_transactions'; +} from '../../../lib/helpers/transactions'; +import { calculateThroughput } from '../../../lib/helpers/calculate_throughput'; +import { getBucketSizeForAggregatedTransactions } from '../../../lib/helpers/get_bucket_size_for_aggregated_transactions'; import { getLatencyAggregation, getLatencyValue, -} from '../../helpers/latency_aggregation_type'; -import { Setup } from '../../helpers/setup_request'; +} from '../../../lib/helpers/latency_aggregation_type'; +import { Setup } from '../../../lib/helpers/setup_request'; interface ServiceInstanceTransactionPrimaryStatistics { serviceNodeName: string; diff --git a/x-pack/plugins/apm/server/lib/services/get_service_instances/main_statistics.ts b/x-pack/plugins/apm/server/routes/services/get_service_instances/main_statistics.ts similarity index 96% rename from x-pack/plugins/apm/server/lib/services/get_service_instances/main_statistics.ts rename to x-pack/plugins/apm/server/routes/services/get_service_instances/main_statistics.ts index ea34693bceb30..a064c71496de9 100644 --- a/x-pack/plugins/apm/server/lib/services/get_service_instances/main_statistics.ts +++ b/x-pack/plugins/apm/server/routes/services/get_service_instances/main_statistics.ts @@ -8,7 +8,7 @@ import { LatencyAggregationType } from '../../../../common/latency_aggregation_types'; import { joinByKey } from '../../../../common/utils/join_by_key'; import { withApmSpan } from '../../../utils/with_apm_span'; -import { Setup } from '../../helpers/setup_request'; +import { Setup } from '../../../lib/helpers/setup_request'; import { getServiceInstancesSystemMetricStatistics } from './get_service_instances_system_metric_statistics'; import { getServiceInstancesTransactionStatistics } from './get_service_instances_transaction_statistics'; diff --git a/x-pack/plugins/apm/server/lib/services/get_service_metadata_details.ts b/x-pack/plugins/apm/server/routes/services/get_service_metadata_details.ts similarity index 96% rename from x-pack/plugins/apm/server/lib/services/get_service_metadata_details.ts rename to x-pack/plugins/apm/server/routes/services/get_service_metadata_details.ts index e2852a51b0c06..b7ce68a0de578 100644 --- a/x-pack/plugins/apm/server/lib/services/get_service_metadata_details.ts +++ b/x-pack/plugins/apm/server/routes/services/get_service_metadata_details.ts @@ -22,8 +22,8 @@ import { import { ContainerType } from '../../../common/service_metadata'; import { rangeQuery } from '../../../../observability/server'; import { TransactionRaw } from '../../../typings/es_schemas/raw/transaction_raw'; -import { getProcessorEventForTransactions } from '../helpers/transactions'; -import { Setup } from '../helpers/setup_request'; +import { getProcessorEventForTransactions } from '../../lib/helpers/transactions'; +import { Setup } from '../../lib/helpers/setup_request'; import { should } from './get_service_metadata_icons'; type ServiceMetadataDetailsRaw = Pick< diff --git a/x-pack/plugins/apm/server/lib/services/get_service_metadata_icons.ts b/x-pack/plugins/apm/server/routes/services/get_service_metadata_icons.ts similarity index 94% rename from x-pack/plugins/apm/server/lib/services/get_service_metadata_icons.ts rename to x-pack/plugins/apm/server/routes/services/get_service_metadata_icons.ts index 2c93a298cb134..ca97e9d58f060 100644 --- a/x-pack/plugins/apm/server/lib/services/get_service_metadata_icons.ts +++ b/x-pack/plugins/apm/server/routes/services/get_service_metadata_icons.ts @@ -18,8 +18,8 @@ import { import { ContainerType } from '../../../common/service_metadata'; import { rangeQuery } from '../../../../observability/server'; import { TransactionRaw } from '../../../typings/es_schemas/raw/transaction_raw'; -import { getProcessorEventForTransactions } from '../helpers/transactions'; -import { Setup } from '../helpers/setup_request'; +import { getProcessorEventForTransactions } from '../../lib/helpers/transactions'; +import { Setup } from '../../lib/helpers/setup_request'; type ServiceMetadataIconsRaw = Pick< TransactionRaw, diff --git a/x-pack/plugins/apm/server/lib/services/get_service_node_metadata.ts b/x-pack/plugins/apm/server/routes/services/get_service_node_metadata.ts similarity index 97% rename from x-pack/plugins/apm/server/lib/services/get_service_node_metadata.ts rename to x-pack/plugins/apm/server/routes/services/get_service_node_metadata.ts index ab0fa91529917..89e0e42e95914 100644 --- a/x-pack/plugins/apm/server/lib/services/get_service_node_metadata.ts +++ b/x-pack/plugins/apm/server/routes/services/get_service_node_metadata.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { Setup } from '../helpers/setup_request'; +import { Setup } from '../../lib/helpers/setup_request'; import { HOST_NAME, CONTAINER_ID, diff --git a/x-pack/plugins/apm/server/lib/services/get_service_transaction_group_detailed_statistics.ts b/x-pack/plugins/apm/server/routes/services/get_service_transaction_group_detailed_statistics.ts similarity index 95% rename from x-pack/plugins/apm/server/lib/services/get_service_transaction_group_detailed_statistics.ts rename to x-pack/plugins/apm/server/routes/services/get_service_transaction_group_detailed_statistics.ts index 35256e6a7ecd6..70f77c26fdbf9 100644 --- a/x-pack/plugins/apm/server/lib/services/get_service_transaction_group_detailed_statistics.ts +++ b/x-pack/plugins/apm/server/routes/services/get_service_transaction_group_detailed_statistics.ts @@ -22,14 +22,14 @@ import { getDocumentTypeFilterForTransactions, getTransactionDurationFieldForTransactions, getProcessorEventForTransactions, -} from '../helpers/transactions'; -import { getBucketSizeForAggregatedTransactions } from '../helpers/get_bucket_size_for_aggregated_transactions'; +} from '../../lib/helpers/transactions'; +import { getBucketSizeForAggregatedTransactions } from '../../lib/helpers/get_bucket_size_for_aggregated_transactions'; import { getLatencyAggregation, getLatencyValue, -} from '../helpers/latency_aggregation_type'; -import { Setup } from '../helpers/setup_request'; -import { calculateFailedTransactionRate } from '../helpers/transaction_error_rate'; +} from '../../lib/helpers/latency_aggregation_type'; +import { Setup } from '../../lib/helpers/setup_request'; +import { calculateFailedTransactionRate } from '../../lib/helpers/transaction_error_rate'; export async function getServiceTransactionGroupDetailedStatistics({ environment, diff --git a/x-pack/plugins/apm/server/lib/services/get_service_transaction_groups.ts b/x-pack/plugins/apm/server/routes/services/get_service_transaction_groups.ts similarity index 92% rename from x-pack/plugins/apm/server/lib/services/get_service_transaction_groups.ts rename to x-pack/plugins/apm/server/routes/services/get_service_transaction_groups.ts index 7f624693a3b9c..711d6964221bd 100644 --- a/x-pack/plugins/apm/server/lib/services/get_service_transaction_groups.ts +++ b/x-pack/plugins/apm/server/routes/services/get_service_transaction_groups.ts @@ -19,14 +19,14 @@ import { getDocumentTypeFilterForTransactions, getTransactionDurationFieldForTransactions, getProcessorEventForTransactions, -} from '../helpers/transactions'; -import { calculateThroughput } from '../helpers/calculate_throughput'; +} from '../../lib/helpers/transactions'; +import { calculateThroughput } from '../../lib/helpers/calculate_throughput'; import { getLatencyAggregation, getLatencyValue, -} from '../helpers/latency_aggregation_type'; -import { Setup } from '../helpers/setup_request'; -import { calculateFailedTransactionRate } from '../helpers/transaction_error_rate'; +} from '../../lib/helpers/latency_aggregation_type'; +import { Setup } from '../../lib/helpers/setup_request'; +import { calculateFailedTransactionRate } from '../../lib/helpers/transaction_error_rate'; export type ServiceOverviewTransactionGroupSortField = | 'name' diff --git a/x-pack/plugins/apm/server/lib/services/get_service_transaction_types.ts b/x-pack/plugins/apm/server/routes/services/get_service_transaction_types.ts similarity index 94% rename from x-pack/plugins/apm/server/lib/services/get_service_transaction_types.ts rename to x-pack/plugins/apm/server/routes/services/get_service_transaction_types.ts index 1c2d1c9207bc3..a3761df72156e 100644 --- a/x-pack/plugins/apm/server/lib/services/get_service_transaction_types.ts +++ b/x-pack/plugins/apm/server/routes/services/get_service_transaction_types.ts @@ -10,11 +10,11 @@ import { TRANSACTION_TYPE, } from '../../../common/elasticsearch_fieldnames'; import { rangeQuery } from '../../../../observability/server'; -import { Setup } from '../helpers/setup_request'; +import { Setup } from '../../lib/helpers/setup_request'; import { getDocumentTypeFilterForTransactions, getProcessorEventForTransactions, -} from '../helpers/transactions'; +} from '../../lib/helpers/transactions'; export async function getServiceTransactionTypes({ setup, diff --git a/x-pack/plugins/apm/server/lib/services/get_services/get_health_statuses.ts b/x-pack/plugins/apm/server/routes/services/get_services/get_health_statuses.ts similarity index 92% rename from x-pack/plugins/apm/server/lib/services/get_services/get_health_statuses.ts rename to x-pack/plugins/apm/server/routes/services/get_services/get_health_statuses.ts index af6d0d9613b35..65fb04b821ffa 100644 --- a/x-pack/plugins/apm/server/lib/services/get_services/get_health_statuses.ts +++ b/x-pack/plugins/apm/server/routes/services/get_services/get_health_statuses.ts @@ -7,7 +7,7 @@ import { getSeverity } from '../../../../common/anomaly_detection'; import { getServiceHealthStatus } from '../../../../common/service_health_status'; -import { getServiceAnomalies } from '../../service_map/get_service_anomalies'; +import { getServiceAnomalies } from '../../../routes/service_map/get_service_anomalies'; import { ServicesItemsSetup } from './get_services_items'; interface AggregationParams { diff --git a/x-pack/plugins/apm/server/lib/services/get_services/get_legacy_data_status.ts b/x-pack/plugins/apm/server/routes/services/get_services/get_legacy_data_status.ts similarity index 95% rename from x-pack/plugins/apm/server/lib/services/get_services/get_legacy_data_status.ts rename to x-pack/plugins/apm/server/routes/services/get_services/get_legacy_data_status.ts index 5b94bb2314258..7275e34786e36 100644 --- a/x-pack/plugins/apm/server/lib/services/get_services/get_legacy_data_status.ts +++ b/x-pack/plugins/apm/server/routes/services/get_services/get_legacy_data_status.ts @@ -8,7 +8,7 @@ import { rangeQuery } from '../../../../../observability/server'; import { ProcessorEvent } from '../../../../common/processor_event'; import { OBSERVER_VERSION_MAJOR } from '../../../../common/elasticsearch_fieldnames'; -import { Setup } from '../../helpers/setup_request'; +import { Setup } from '../../../lib/helpers/setup_request'; // returns true if 6.x data is found export async function getLegacyDataStatus( diff --git a/x-pack/plugins/apm/server/lib/services/get_services/get_service_transaction_stats.ts b/x-pack/plugins/apm/server/routes/services/get_services/get_service_transaction_stats.ts similarity index 95% rename from x-pack/plugins/apm/server/lib/services/get_services/get_service_transaction_stats.ts rename to x-pack/plugins/apm/server/routes/services/get_services/get_service_transaction_stats.ts index 36903f9ca229f..3eaa8053b6709 100644 --- a/x-pack/plugins/apm/server/lib/services/get_services/get_service_transaction_stats.ts +++ b/x-pack/plugins/apm/server/routes/services/get_services/get_service_transaction_stats.ts @@ -22,12 +22,12 @@ import { getDocumentTypeFilterForTransactions, getTransactionDurationFieldForTransactions, getProcessorEventForTransactions, -} from '../../helpers/transactions'; -import { calculateThroughput } from '../../helpers/calculate_throughput'; +} from '../../../lib/helpers/transactions'; +import { calculateThroughput } from '../../../lib/helpers/calculate_throughput'; import { calculateFailedTransactionRate, getOutcomeAggregation, -} from '../../helpers/transaction_error_rate'; +} from '../../../lib/helpers/transaction_error_rate'; import { ServicesItemsSetup } from './get_services_items'; interface AggregationParams { diff --git a/x-pack/plugins/apm/server/lib/services/get_services/get_services_from_metric_documents.ts b/x-pack/plugins/apm/server/routes/services/get_services/get_services_from_metric_documents.ts similarity index 97% rename from x-pack/plugins/apm/server/lib/services/get_services/get_services_from_metric_documents.ts rename to x-pack/plugins/apm/server/routes/services/get_services/get_services_from_metric_documents.ts index cffd106d13348..055d82a807815 100644 --- a/x-pack/plugins/apm/server/lib/services/get_services/get_services_from_metric_documents.ts +++ b/x-pack/plugins/apm/server/routes/services/get_services/get_services_from_metric_documents.ts @@ -14,7 +14,7 @@ import { import { kqlQuery, rangeQuery } from '../../../../../observability/server'; import { environmentQuery } from '../../../../common/utils/environment_query'; import { ProcessorEvent } from '../../../../common/processor_event'; -import { Setup } from '../../helpers/setup_request'; +import { Setup } from '../../../lib/helpers/setup_request'; export async function getServicesFromMetricDocuments({ environment, diff --git a/x-pack/plugins/apm/server/lib/services/get_services/get_services_items.ts b/x-pack/plugins/apm/server/routes/services/get_services/get_services_items.ts similarity index 96% rename from x-pack/plugins/apm/server/lib/services/get_services/get_services_items.ts rename to x-pack/plugins/apm/server/routes/services/get_services/get_services_items.ts index 47f1f6e7e6430..db3377b6710c5 100644 --- a/x-pack/plugins/apm/server/lib/services/get_services/get_services_items.ts +++ b/x-pack/plugins/apm/server/routes/services/get_services/get_services_items.ts @@ -7,7 +7,7 @@ import { Logger } from '@kbn/logging'; import { withApmSpan } from '../../../utils/with_apm_span'; -import { Setup } from '../../helpers/setup_request'; +import { Setup } from '../../../lib/helpers/setup_request'; import { getHealthStatuses } from './get_health_statuses'; import { getServicesFromMetricDocuments } from './get_services_from_metric_documents'; import { getServiceTransactionStats } from './get_service_transaction_stats'; diff --git a/x-pack/plugins/apm/server/lib/services/get_services/index.ts b/x-pack/plugins/apm/server/routes/services/get_services/index.ts similarity index 95% rename from x-pack/plugins/apm/server/lib/services/get_services/index.ts rename to x-pack/plugins/apm/server/routes/services/get_services/index.ts index d6a940bc14b5f..9d1670fe84582 100644 --- a/x-pack/plugins/apm/server/lib/services/get_services/index.ts +++ b/x-pack/plugins/apm/server/routes/services/get_services/index.ts @@ -7,7 +7,7 @@ import { Logger } from '@kbn/logging'; import { withApmSpan } from '../../../utils/with_apm_span'; -import { Setup } from '../../helpers/setup_request'; +import { Setup } from '../../../lib/helpers/setup_request'; import { getLegacyDataStatus } from './get_legacy_data_status'; import { getServicesItems } from './get_services_items'; diff --git a/x-pack/plugins/apm/server/lib/services/get_services/merge_service_stats.test.ts b/x-pack/plugins/apm/server/routes/services/get_services/merge_service_stats.test.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/services/get_services/merge_service_stats.test.ts rename to x-pack/plugins/apm/server/routes/services/get_services/merge_service_stats.test.ts diff --git a/x-pack/plugins/apm/server/lib/services/get_services/merge_service_stats.ts b/x-pack/plugins/apm/server/routes/services/get_services/merge_service_stats.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/services/get_services/merge_service_stats.ts rename to x-pack/plugins/apm/server/routes/services/get_services/merge_service_stats.ts diff --git a/x-pack/plugins/apm/server/lib/services/get_services_detailed_statistics/get_service_transaction_detailed_statistics.ts b/x-pack/plugins/apm/server/routes/services/get_services_detailed_statistics/get_service_transaction_detailed_statistics.ts similarity index 92% rename from x-pack/plugins/apm/server/lib/services/get_services_detailed_statistics/get_service_transaction_detailed_statistics.ts rename to x-pack/plugins/apm/server/routes/services/get_services_detailed_statistics/get_service_transaction_detailed_statistics.ts index ea153a5ddcd4c..95f2c6f400de9 100644 --- a/x-pack/plugins/apm/server/lib/services/get_services_detailed_statistics/get_service_transaction_detailed_statistics.ts +++ b/x-pack/plugins/apm/server/routes/services/get_services_detailed_statistics/get_service_transaction_detailed_statistics.ts @@ -21,14 +21,14 @@ import { getDocumentTypeFilterForTransactions, getTransactionDurationFieldForTransactions, getProcessorEventForTransactions, -} from '../../helpers/transactions'; -import { calculateThroughput } from '../../helpers/calculate_throughput'; -import { getBucketSizeForAggregatedTransactions } from '../../helpers/get_bucket_size_for_aggregated_transactions'; -import { Setup } from '../../helpers/setup_request'; +} from '../../../lib/helpers/transactions'; +import { calculateThroughput } from '../../../lib/helpers/calculate_throughput'; +import { getBucketSizeForAggregatedTransactions } from '../../../lib/helpers/get_bucket_size_for_aggregated_transactions'; +import { Setup } from '../../../lib/helpers/setup_request'; import { calculateFailedTransactionRate, getOutcomeAggregation, -} from '../../helpers/transaction_error_rate'; +} from '../../../lib/helpers/transaction_error_rate'; export async function getServiceTransactionDetailedStatistics({ serviceNames, diff --git a/x-pack/plugins/apm/server/lib/services/get_services_detailed_statistics/index.ts b/x-pack/plugins/apm/server/routes/services/get_services_detailed_statistics/index.ts similarity index 95% rename from x-pack/plugins/apm/server/lib/services/get_services_detailed_statistics/index.ts rename to x-pack/plugins/apm/server/routes/services/get_services_detailed_statistics/index.ts index e2f2ee226ab1e..228add10184ba 100644 --- a/x-pack/plugins/apm/server/lib/services/get_services_detailed_statistics/index.ts +++ b/x-pack/plugins/apm/server/routes/services/get_services_detailed_statistics/index.ts @@ -6,7 +6,7 @@ */ import { withApmSpan } from '../../../utils/with_apm_span'; -import { Setup } from '../../helpers/setup_request'; +import { Setup } from '../../../lib/helpers/setup_request'; import { getServiceTransactionDetailedStatistics } from './get_service_transaction_detailed_statistics'; export async function getServicesDetailedStatistics({ diff --git a/x-pack/plugins/apm/server/lib/services/get_throughput.ts b/x-pack/plugins/apm/server/routes/services/get_throughput.ts similarity index 96% rename from x-pack/plugins/apm/server/lib/services/get_throughput.ts rename to x-pack/plugins/apm/server/routes/services/get_throughput.ts index 3161066ebadf9..4a0366cc2f6ae 100644 --- a/x-pack/plugins/apm/server/lib/services/get_throughput.ts +++ b/x-pack/plugins/apm/server/routes/services/get_throughput.ts @@ -20,8 +20,8 @@ import { environmentQuery } from '../../../common/utils/environment_query'; import { getDocumentTypeFilterForTransactions, getProcessorEventForTransactions, -} from '../helpers/transactions'; -import { Setup } from '../helpers/setup_request'; +} from '../../lib/helpers/transactions'; +import { Setup } from '../../lib/helpers/setup_request'; interface Options { environment: string; diff --git a/x-pack/plugins/apm/server/lib/services/profiling/get_service_profiling_statistics.ts b/x-pack/plugins/apm/server/routes/services/profiling/get_service_profiling_statistics.ts similarity index 97% rename from x-pack/plugins/apm/server/lib/services/profiling/get_service_profiling_statistics.ts rename to x-pack/plugins/apm/server/routes/services/profiling/get_service_profiling_statistics.ts index 0b96a6bd3d456..009d974e33721 100644 --- a/x-pack/plugins/apm/server/lib/services/profiling/get_service_profiling_statistics.ts +++ b/x-pack/plugins/apm/server/routes/services/profiling/get_service_profiling_statistics.ts @@ -23,8 +23,8 @@ import { } from '../../../../common/elasticsearch_fieldnames'; import { rangeQuery, kqlQuery } from '../../../../../observability/server'; import { environmentQuery } from '../../../../common/utils/environment_query'; -import { APMEventClient } from '../../helpers/create_es_client/create_apm_event_client'; -import { Setup } from '../../helpers/setup_request'; +import { APMEventClient } from '../../../lib/helpers/create_es_client/create_apm_event_client'; +import { Setup } from '../../../lib/helpers/setup_request'; import { withApmSpan } from '../../../utils/with_apm_span'; const MAX_STACK_IDS = 10000; diff --git a/x-pack/plugins/apm/server/lib/services/profiling/get_service_profiling_timeline.ts b/x-pack/plugins/apm/server/routes/services/profiling/get_service_profiling_timeline.ts similarity index 96% rename from x-pack/plugins/apm/server/lib/services/profiling/get_service_profiling_timeline.ts rename to x-pack/plugins/apm/server/routes/services/profiling/get_service_profiling_timeline.ts index ce1580fc48290..47df939467d0e 100644 --- a/x-pack/plugins/apm/server/lib/services/profiling/get_service_profiling_timeline.ts +++ b/x-pack/plugins/apm/server/routes/services/profiling/get_service_profiling_timeline.ts @@ -14,8 +14,8 @@ import { getValueTypeConfig, ProfilingValueType, } from '../../../../common/profiling'; -import { Setup } from '../../helpers/setup_request'; -import { getBucketSize } from '../../helpers/get_bucket_size'; +import { Setup } from '../../../lib/helpers/setup_request'; +import { getBucketSize } from '../../../lib/helpers/get_bucket_size'; import { environmentQuery } from '../../../../common/utils/environment_query'; import { kqlQuery, rangeQuery } from '../../../../../observability/server'; diff --git a/x-pack/plugins/apm/server/lib/services/queries.test.ts b/x-pack/plugins/apm/server/routes/services/queries.test.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/services/queries.test.ts rename to x-pack/plugins/apm/server/routes/services/queries.test.ts diff --git a/x-pack/plugins/apm/server/routes/services.ts b/x-pack/plugins/apm/server/routes/services/route.ts similarity index 89% rename from x-pack/plugins/apm/server/routes/services.ts rename to x-pack/plugins/apm/server/routes/services/route.ts index cb557f56d8165..d395be4c6adce 100644 --- a/x-pack/plugins/apm/server/routes/services.ts +++ b/x-pack/plugins/apm/server/routes/services/route.ts @@ -11,42 +11,42 @@ import { isoToEpochRt } from '@kbn/io-ts-utils/iso_to_epoch_rt'; import { toNumberRt } from '@kbn/io-ts-utils/to_number_rt'; import * as t from 'io-ts'; import { uniq } from 'lodash'; -import { latencyAggregationTypeRt } from '../../common/latency_aggregation_types'; -import { ProfilingValueType } from '../../common/profiling'; -import { getSearchAggregatedTransactions } from '../lib/helpers/transactions'; -import { setupRequest } from '../lib/helpers/setup_request'; -import { getServiceAnnotations } from '../lib/services/annotations'; -import { getServices } from '../lib/services/get_services'; -import { getServiceAgent } from '../lib/services/get_service_agent'; -import { getServiceAlerts } from '../lib/services/get_service_alerts'; -import { getServiceDependencies } from '../lib/services/get_service_dependencies'; -import { getServiceInstanceMetadataDetails } from '../lib/services/get_service_instance_metadata_details'; -import { getServiceErrorGroupPeriods } from '../lib/services/get_service_error_groups/get_service_error_group_detailed_statistics'; -import { getServiceErrorGroupMainStatistics } from '../lib/services/get_service_error_groups/get_service_error_group_main_statistics'; -import { getServiceInstancesDetailedStatisticsPeriods } from '../lib/services/get_service_instances/detailed_statistics'; -import { getServiceInstancesMainStatistics } from '../lib/services/get_service_instances/main_statistics'; -import { getServiceMetadataDetails } from '../lib/services/get_service_metadata_details'; -import { getServiceMetadataIcons } from '../lib/services/get_service_metadata_icons'; -import { getServiceNodeMetadata } from '../lib/services/get_service_node_metadata'; -import { getServiceTransactionTypes } from '../lib/services/get_service_transaction_types'; -import { getThroughput } from '../lib/services/get_throughput'; -import { getServiceProfilingStatistics } from '../lib/services/profiling/get_service_profiling_statistics'; -import { getServiceProfilingTimeline } from '../lib/services/profiling/get_service_profiling_timeline'; -import { getServiceInfrastructure } from '../lib/services/get_service_infrastructure'; -import { withApmSpan } from '../utils/with_apm_span'; -import { createApmServerRoute } from './apm_routes/create_apm_server_route'; -import { createApmServerRouteRepository } from './apm_routes/create_apm_server_route_repository'; +import { latencyAggregationTypeRt } from '../../../common/latency_aggregation_types'; +import { ProfilingValueType } from '../../../common/profiling'; +import { getSearchAggregatedTransactions } from '../../lib/helpers/transactions'; +import { setupRequest } from '../../lib/helpers/setup_request'; +import { getServiceAnnotations } from './annotations'; +import { getServices } from './get_services'; +import { getServiceAgent } from './get_service_agent'; +import { getServiceAlerts } from './get_service_alerts'; +import { getServiceDependencies } from './get_service_dependencies'; +import { getServiceInstanceMetadataDetails } from './get_service_instance_metadata_details'; +import { getServiceErrorGroupPeriods } from './get_service_error_groups/get_service_error_group_detailed_statistics'; +import { getServiceErrorGroupMainStatistics } from './get_service_error_groups/get_service_error_group_main_statistics'; +import { getServiceInstancesDetailedStatisticsPeriods } from './get_service_instances/detailed_statistics'; +import { getServiceInstancesMainStatistics } from './get_service_instances/main_statistics'; +import { getServiceMetadataDetails } from './get_service_metadata_details'; +import { getServiceMetadataIcons } from './get_service_metadata_icons'; +import { getServiceNodeMetadata } from './get_service_node_metadata'; +import { getServiceTransactionTypes } from './get_service_transaction_types'; +import { getThroughput } from './get_throughput'; +import { getServiceProfilingStatistics } from './profiling/get_service_profiling_statistics'; +import { getServiceProfilingTimeline } from './profiling/get_service_profiling_timeline'; +import { getServiceInfrastructure } from './get_service_infrastructure'; +import { withApmSpan } from '../../utils/with_apm_span'; +import { createApmServerRoute } from '../apm_routes/create_apm_server_route'; +import { createApmServerRouteRepository } from '../apm_routes/create_apm_server_route_repository'; import { comparisonRangeRt, environmentRt, kueryRt, offsetRt, rangeRt, -} from './default_api_types'; -import { offsetPreviousPeriodCoordinates } from '../../common/utils/offset_previous_period_coordinate'; -import { getServicesDetailedStatistics } from '../lib/services/get_services_detailed_statistics'; -import { getServiceDependenciesBreakdown } from '../lib/services/get_service_dependencies_breakdown'; -import { getBucketSizeForAggregatedTransactions } from '../lib/helpers/get_bucket_size_for_aggregated_transactions'; +} from '../default_api_types'; +import { offsetPreviousPeriodCoordinates } from '../../../common/utils/offset_previous_period_coordinate'; +import { getServicesDetailedStatistics } from './get_services_detailed_statistics'; +import { getServiceDependenciesBreakdown } from './get_service_dependencies_breakdown'; +import { getBucketSizeForAggregatedTransactions } from '../../lib/helpers/get_bucket_size_for_aggregated_transactions'; const servicesRoute = createApmServerRoute({ endpoint: 'GET /internal/apm/services', diff --git a/x-pack/plugins/apm/server/lib/settings/agent_configuration/__snapshots__/queries.test.ts.snap b/x-pack/plugins/apm/server/routes/settings/agent_configuration/__snapshots__/queries.test.ts.snap similarity index 100% rename from x-pack/plugins/apm/server/lib/settings/agent_configuration/__snapshots__/queries.test.ts.snap rename to x-pack/plugins/apm/server/routes/settings/agent_configuration/__snapshots__/queries.test.ts.snap diff --git a/x-pack/plugins/apm/server/lib/settings/agent_configuration/convert_settings_to_string.ts b/x-pack/plugins/apm/server/routes/settings/agent_configuration/convert_settings_to_string.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/settings/agent_configuration/convert_settings_to_string.ts rename to x-pack/plugins/apm/server/routes/settings/agent_configuration/convert_settings_to_string.ts diff --git a/x-pack/plugins/apm/server/lib/settings/agent_configuration/create_agent_config_index.ts b/x-pack/plugins/apm/server/routes/settings/agent_configuration/create_agent_config_index.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/settings/agent_configuration/create_agent_config_index.ts rename to x-pack/plugins/apm/server/routes/settings/agent_configuration/create_agent_config_index.ts diff --git a/x-pack/plugins/apm/server/lib/settings/agent_configuration/create_or_update_configuration.ts b/x-pack/plugins/apm/server/routes/settings/agent_configuration/create_or_update_configuration.ts similarity index 89% rename from x-pack/plugins/apm/server/lib/settings/agent_configuration/create_or_update_configuration.ts rename to x-pack/plugins/apm/server/routes/settings/agent_configuration/create_or_update_configuration.ts index c112c3be3362b..07a9f79829306 100644 --- a/x-pack/plugins/apm/server/lib/settings/agent_configuration/create_or_update_configuration.ts +++ b/x-pack/plugins/apm/server/routes/settings/agent_configuration/create_or_update_configuration.ts @@ -6,12 +6,12 @@ */ import hash from 'object-hash'; -import { Setup } from '../../helpers/setup_request'; +import { Setup } from '../../../lib/helpers/setup_request'; import { AgentConfiguration, AgentConfigurationIntake, } from '../../../../common/agent_configuration/configuration_types'; -import { APMIndexDocumentParams } from '../../helpers/create_es_client/create_internal_es_client'; +import { APMIndexDocumentParams } from '../../../lib/helpers/create_es_client/create_internal_es_client'; export function createOrUpdateConfiguration({ configurationId, diff --git a/x-pack/plugins/apm/server/lib/settings/agent_configuration/delete_configuration.ts b/x-pack/plugins/apm/server/routes/settings/agent_configuration/delete_configuration.ts similarity index 91% rename from x-pack/plugins/apm/server/lib/settings/agent_configuration/delete_configuration.ts rename to x-pack/plugins/apm/server/routes/settings/agent_configuration/delete_configuration.ts index 125c97730a6fa..5ac8437b15786 100644 --- a/x-pack/plugins/apm/server/lib/settings/agent_configuration/delete_configuration.ts +++ b/x-pack/plugins/apm/server/routes/settings/agent_configuration/delete_configuration.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { Setup } from '../../helpers/setup_request'; +import { Setup } from '../../../lib/helpers/setup_request'; export async function deleteConfiguration({ configurationId, diff --git a/x-pack/plugins/apm/server/lib/settings/agent_configuration/find_exact_configuration.ts b/x-pack/plugins/apm/server/routes/settings/agent_configuration/find_exact_configuration.ts similarity index 96% rename from x-pack/plugins/apm/server/lib/settings/agent_configuration/find_exact_configuration.ts rename to x-pack/plugins/apm/server/routes/settings/agent_configuration/find_exact_configuration.ts index 90f82442f9bfa..ac95f36107994 100644 --- a/x-pack/plugins/apm/server/lib/settings/agent_configuration/find_exact_configuration.ts +++ b/x-pack/plugins/apm/server/routes/settings/agent_configuration/find_exact_configuration.ts @@ -11,7 +11,7 @@ import { SERVICE_ENVIRONMENT, SERVICE_NAME, } from '../../../../common/elasticsearch_fieldnames'; -import { Setup } from '../../helpers/setup_request'; +import { Setup } from '../../../lib/helpers/setup_request'; import { convertConfigSettingsToString } from './convert_settings_to_string'; export async function findExactConfiguration({ diff --git a/x-pack/plugins/apm/server/lib/settings/agent_configuration/get_agent_name_by_service.ts b/x-pack/plugins/apm/server/routes/settings/agent_configuration/get_agent_name_by_service.ts similarity index 95% rename from x-pack/plugins/apm/server/lib/settings/agent_configuration/get_agent_name_by_service.ts rename to x-pack/plugins/apm/server/routes/settings/agent_configuration/get_agent_name_by_service.ts index 6ea3e2a578050..d16af2d95d22a 100644 --- a/x-pack/plugins/apm/server/lib/settings/agent_configuration/get_agent_name_by_service.ts +++ b/x-pack/plugins/apm/server/routes/settings/agent_configuration/get_agent_name_by_service.ts @@ -6,7 +6,7 @@ */ import { ProcessorEvent } from '../../../../common/processor_event'; -import { Setup } from '../../helpers/setup_request'; +import { Setup } from '../../../lib/helpers/setup_request'; import { SERVICE_NAME } from '../../../../common/elasticsearch_fieldnames'; import { AGENT_NAME } from '../../../../common/elasticsearch_fieldnames'; diff --git a/x-pack/plugins/apm/server/lib/settings/agent_configuration/get_environments/get_existing_environments_for_service.ts b/x-pack/plugins/apm/server/routes/settings/agent_configuration/get_environments/get_existing_environments_for_service.ts similarity index 95% rename from x-pack/plugins/apm/server/lib/settings/agent_configuration/get_environments/get_existing_environments_for_service.ts rename to x-pack/plugins/apm/server/routes/settings/agent_configuration/get_environments/get_existing_environments_for_service.ts index 4fd351f8708a2..a3925c060a1c5 100644 --- a/x-pack/plugins/apm/server/lib/settings/agent_configuration/get_environments/get_existing_environments_for_service.ts +++ b/x-pack/plugins/apm/server/routes/settings/agent_configuration/get_environments/get_existing_environments_for_service.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { Setup } from '../../../helpers/setup_request'; +import { Setup } from '../../../../lib/helpers/setup_request'; import { SERVICE_NAME, SERVICE_ENVIRONMENT, diff --git a/x-pack/plugins/apm/server/lib/settings/agent_configuration/get_environments/index.ts b/x-pack/plugins/apm/server/routes/settings/agent_configuration/get_environments/index.ts similarity index 95% rename from x-pack/plugins/apm/server/lib/settings/agent_configuration/get_environments/index.ts rename to x-pack/plugins/apm/server/routes/settings/agent_configuration/get_environments/index.ts index a22c1d35dc663..46ab82152caad 100644 --- a/x-pack/plugins/apm/server/lib/settings/agent_configuration/get_environments/index.ts +++ b/x-pack/plugins/apm/server/routes/settings/agent_configuration/get_environments/index.ts @@ -7,7 +7,7 @@ import { withApmSpan } from '../../../../utils/with_apm_span'; import { getAllEnvironments } from '../../../environments/get_all_environments'; -import { Setup } from '../../../helpers/setup_request'; +import { Setup } from '../../../../lib/helpers/setup_request'; import { getExistingEnvironmentsForService } from './get_existing_environments_for_service'; import { ALL_OPTION_VALUE } from '../../../../../common/agent_configuration/all_option'; diff --git a/x-pack/plugins/apm/server/lib/settings/agent_configuration/get_service_names.ts b/x-pack/plugins/apm/server/routes/settings/agent_configuration/get_service_names.ts similarity index 90% rename from x-pack/plugins/apm/server/lib/settings/agent_configuration/get_service_names.ts rename to x-pack/plugins/apm/server/routes/settings/agent_configuration/get_service_names.ts index fc5167159b98d..18e359c5b9425 100644 --- a/x-pack/plugins/apm/server/lib/settings/agent_configuration/get_service_names.ts +++ b/x-pack/plugins/apm/server/routes/settings/agent_configuration/get_service_names.ts @@ -6,10 +6,10 @@ */ import { ProcessorEvent } from '../../../../common/processor_event'; -import { Setup } from '../../helpers/setup_request'; +import { Setup } from '../../../lib/helpers/setup_request'; import { SERVICE_NAME } from '../../../../common/elasticsearch_fieldnames'; import { ALL_OPTION_VALUE } from '../../../../common/agent_configuration/all_option'; -import { getProcessorEventForTransactions } from '../../helpers/transactions'; +import { getProcessorEventForTransactions } from '../../../lib/helpers/transactions'; export async function getServiceNames({ setup, diff --git a/x-pack/plugins/apm/server/lib/settings/agent_configuration/list_configurations.ts b/x-pack/plugins/apm/server/routes/settings/agent_configuration/list_configurations.ts similarity index 93% rename from x-pack/plugins/apm/server/lib/settings/agent_configuration/list_configurations.ts rename to x-pack/plugins/apm/server/routes/settings/agent_configuration/list_configurations.ts index 098888c23ccbc..bc105106cb5e4 100644 --- a/x-pack/plugins/apm/server/lib/settings/agent_configuration/list_configurations.ts +++ b/x-pack/plugins/apm/server/routes/settings/agent_configuration/list_configurations.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { Setup } from '../../helpers/setup_request'; +import { Setup } from '../../../lib/helpers/setup_request'; import { AgentConfiguration } from '../../../../common/agent_configuration/configuration_types'; import { convertConfigSettingsToString } from './convert_settings_to_string'; diff --git a/x-pack/plugins/apm/server/lib/settings/agent_configuration/mark_applied_by_agent.ts b/x-pack/plugins/apm/server/routes/settings/agent_configuration/mark_applied_by_agent.ts similarity index 93% rename from x-pack/plugins/apm/server/lib/settings/agent_configuration/mark_applied_by_agent.ts rename to x-pack/plugins/apm/server/routes/settings/agent_configuration/mark_applied_by_agent.ts index 5fa4993921570..78e0ce68624a6 100644 --- a/x-pack/plugins/apm/server/lib/settings/agent_configuration/mark_applied_by_agent.ts +++ b/x-pack/plugins/apm/server/routes/settings/agent_configuration/mark_applied_by_agent.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { Setup } from '../../helpers/setup_request'; +import { Setup } from '../../../lib/helpers/setup_request'; import { AgentConfiguration } from '../../../../common/agent_configuration/configuration_types'; // We're not wrapping this function with a span as it is not blocking the request diff --git a/x-pack/plugins/apm/server/lib/settings/agent_configuration/queries.test.ts b/x-pack/plugins/apm/server/routes/settings/agent_configuration/queries.test.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/settings/agent_configuration/queries.test.ts rename to x-pack/plugins/apm/server/routes/settings/agent_configuration/queries.test.ts diff --git a/x-pack/plugins/apm/server/routes/settings/agent_configuration.ts b/x-pack/plugins/apm/server/routes/settings/agent_configuration/route.ts similarity index 86% rename from x-pack/plugins/apm/server/routes/settings/agent_configuration.ts rename to x-pack/plugins/apm/server/routes/settings/agent_configuration/route.ts index 563fa40c6c0d9..1122c2095ed3d 100644 --- a/x-pack/plugins/apm/server/routes/settings/agent_configuration.ts +++ b/x-pack/plugins/apm/server/routes/settings/agent_configuration/route.ts @@ -8,25 +8,25 @@ import * as t from 'io-ts'; import Boom from '@hapi/boom'; import { toBooleanRt } from '@kbn/io-ts-utils/to_boolean_rt'; -import { maxSuggestions } from '../../../../observability/common'; -import { setupRequest } from '../../lib/helpers/setup_request'; -import { getServiceNames } from '../../lib/settings/agent_configuration/get_service_names'; -import { createOrUpdateConfiguration } from '../../lib/settings/agent_configuration/create_or_update_configuration'; -import { searchConfigurations } from '../../lib/settings/agent_configuration/search_configurations'; -import { findExactConfiguration } from '../../lib/settings/agent_configuration/find_exact_configuration'; -import { listConfigurations } from '../../lib/settings/agent_configuration/list_configurations'; -import { getEnvironments } from '../../lib/settings/agent_configuration/get_environments'; -import { deleteConfiguration } from '../../lib/settings/agent_configuration/delete_configuration'; -import { createApmServerRoute } from '../apm_routes/create_apm_server_route'; -import { getAgentNameByService } from '../../lib/settings/agent_configuration/get_agent_name_by_service'; -import { markAppliedByAgent } from '../../lib/settings/agent_configuration/mark_applied_by_agent'; +import { maxSuggestions } from '../../../../../observability/common'; +import { setupRequest } from '../../../lib/helpers/setup_request'; +import { getServiceNames } from './get_service_names'; +import { createOrUpdateConfiguration } from './create_or_update_configuration'; +import { searchConfigurations } from './search_configurations'; +import { findExactConfiguration } from './find_exact_configuration'; +import { listConfigurations } from './list_configurations'; +import { getEnvironments } from './get_environments'; +import { deleteConfiguration } from './delete_configuration'; +import { createApmServerRoute } from '../../apm_routes/create_apm_server_route'; +import { getAgentNameByService } from './get_agent_name_by_service'; +import { markAppliedByAgent } from './mark_applied_by_agent'; import { serviceRt, agentConfigurationIntakeRt, -} from '../../../common/agent_configuration/runtime_types/agent_configuration_intake_rt'; -import { getSearchAggregatedTransactions } from '../../lib/helpers/transactions'; -import { createApmServerRouteRepository } from '../apm_routes/create_apm_server_route_repository'; -import { syncAgentConfigsToApmPackagePolicies } from '../../lib/fleet/sync_agent_configs_to_apm_package_policies'; +} from '../../../../common/agent_configuration/runtime_types/agent_configuration_intake_rt'; +import { getSearchAggregatedTransactions } from '../../../lib/helpers/transactions'; +import { createApmServerRouteRepository } from '../../apm_routes/create_apm_server_route_repository'; +import { syncAgentConfigsToApmPackagePolicies } from '../../fleet/sync_agent_configs_to_apm_package_policies'; // get list of configurations const agentConfigurationRoute = createApmServerRoute({ diff --git a/x-pack/plugins/apm/server/lib/settings/agent_configuration/search_configurations.ts b/x-pack/plugins/apm/server/routes/settings/agent_configuration/search_configurations.ts similarity index 97% rename from x-pack/plugins/apm/server/lib/settings/agent_configuration/search_configurations.ts rename to x-pack/plugins/apm/server/routes/settings/agent_configuration/search_configurations.ts index 1e37ae9108573..194e1eff4e657 100644 --- a/x-pack/plugins/apm/server/lib/settings/agent_configuration/search_configurations.ts +++ b/x-pack/plugins/apm/server/routes/settings/agent_configuration/search_configurations.ts @@ -10,7 +10,7 @@ import { SERVICE_NAME, SERVICE_ENVIRONMENT, } from '../../../../common/elasticsearch_fieldnames'; -import { Setup } from '../../helpers/setup_request'; +import { Setup } from '../../../lib/helpers/setup_request'; import { AgentConfiguration } from '../../../../common/agent_configuration/configuration_types'; import { convertConfigSettingsToString } from './convert_settings_to_string'; diff --git a/x-pack/plugins/apm/server/routes/settings/anomaly_detection.ts b/x-pack/plugins/apm/server/routes/settings/anomaly_detection/route.ts similarity index 74% rename from x-pack/plugins/apm/server/routes/settings/anomaly_detection.ts rename to x-pack/plugins/apm/server/routes/settings/anomaly_detection/route.ts index e8b2ef5e119cd..a924a9214977d 100644 --- a/x-pack/plugins/apm/server/routes/settings/anomaly_detection.ts +++ b/x-pack/plugins/apm/server/routes/settings/anomaly_detection/route.ts @@ -7,19 +7,19 @@ import * as t from 'io-ts'; import Boom from '@hapi/boom'; -import { maxSuggestions } from '../../../../observability/common'; -import { isActivePlatinumLicense } from '../../../common/license_check'; -import { ML_ERRORS } from '../../../common/anomaly_detection'; -import { createApmServerRoute } from '../apm_routes/create_apm_server_route'; -import { getAnomalyDetectionJobs } from '../../lib/anomaly_detection/get_anomaly_detection_jobs'; -import { createAnomalyDetectionJobs } from '../../lib/anomaly_detection/create_anomaly_detection_jobs'; -import { setupRequest } from '../../lib/helpers/setup_request'; -import { getAllEnvironments } from '../../lib/environments/get_all_environments'; -import { hasLegacyJobs } from '../../lib/anomaly_detection/has_legacy_jobs'; -import { getSearchAggregatedTransactions } from '../../lib/helpers/transactions'; -import { notifyFeatureUsage } from '../../feature'; -import { withApmSpan } from '../../utils/with_apm_span'; -import { createApmServerRouteRepository } from '../apm_routes/create_apm_server_route_repository'; +import { maxSuggestions } from '../../../../../observability/common'; +import { isActivePlatinumLicense } from '../../../../common/license_check'; +import { ML_ERRORS } from '../../../../common/anomaly_detection'; +import { createApmServerRoute } from '../../apm_routes/create_apm_server_route'; +import { getAnomalyDetectionJobs } from '../../../lib/anomaly_detection/get_anomaly_detection_jobs'; +import { createAnomalyDetectionJobs } from '../../../lib/anomaly_detection/create_anomaly_detection_jobs'; +import { setupRequest } from '../../../lib/helpers/setup_request'; +import { getAllEnvironments } from '../../environments/get_all_environments'; +import { hasLegacyJobs } from '../../../lib/anomaly_detection/has_legacy_jobs'; +import { getSearchAggregatedTransactions } from '../../../lib/helpers/transactions'; +import { notifyFeatureUsage } from '../../../feature'; +import { withApmSpan } from '../../../utils/with_apm_span'; +import { createApmServerRouteRepository } from '../../apm_routes/create_apm_server_route_repository'; // get ML anomaly detection jobs for each environment const anomalyDetectionJobsRoute = createApmServerRoute({ diff --git a/x-pack/plugins/apm/server/lib/settings/apm_indices/get_apm_indices.ts b/x-pack/plugins/apm/server/routes/settings/apm_indices/get_apm_indices.ts similarity index 97% rename from x-pack/plugins/apm/server/lib/settings/apm_indices/get_apm_indices.ts rename to x-pack/plugins/apm/server/routes/settings/apm_indices/get_apm_indices.ts index a37720cbc3790..6b917919bade5 100644 --- a/x-pack/plugins/apm/server/lib/settings/apm_indices/get_apm_indices.ts +++ b/x-pack/plugins/apm/server/routes/settings/apm_indices/get_apm_indices.ts @@ -12,7 +12,7 @@ import { APM_INDICES_SAVED_OBJECT_ID, } from '../../../../common/apm_saved_object_constants'; import { APMConfig } from '../../..'; -import { APMRouteHandlerResources } from '../../../routes/typings'; +import { APMRouteHandlerResources } from '../../typings'; import { withApmSpan } from '../../../utils/with_apm_span'; import { ApmIndicesConfig } from '../../../../../observability/common/typings'; diff --git a/x-pack/plugins/apm/server/routes/settings/apm_indices.ts b/x-pack/plugins/apm/server/routes/settings/apm_indices/route.ts similarity index 82% rename from x-pack/plugins/apm/server/routes/settings/apm_indices.ts rename to x-pack/plugins/apm/server/routes/settings/apm_indices/route.ts index ed99f0c8862f0..485ff8af88843 100644 --- a/x-pack/plugins/apm/server/routes/settings/apm_indices.ts +++ b/x-pack/plugins/apm/server/routes/settings/apm_indices/route.ts @@ -6,14 +6,11 @@ */ import * as t from 'io-ts'; -import { createApmServerRouteRepository } from '../apm_routes/create_apm_server_route_repository'; -import { createApmServerRoute } from '../apm_routes/create_apm_server_route'; -import { - getApmIndices, - getApmIndexSettings, -} from '../../lib/settings/apm_indices/get_apm_indices'; -import { saveApmIndices } from '../../lib/settings/apm_indices/save_apm_indices'; -import { APMConfig } from '../..'; +import { createApmServerRouteRepository } from '../../apm_routes/create_apm_server_route_repository'; +import { createApmServerRoute } from '../../apm_routes/create_apm_server_route'; +import { getApmIndices, getApmIndexSettings } from './get_apm_indices'; +import { saveApmIndices } from './save_apm_indices'; +import { APMConfig } from '../../../'; // get list of apm indices and values const apmIndexSettingsRoute = createApmServerRoute({ diff --git a/x-pack/plugins/apm/server/lib/settings/apm_indices/save_apm_indices.test.ts b/x-pack/plugins/apm/server/routes/settings/apm_indices/save_apm_indices.test.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/settings/apm_indices/save_apm_indices.test.ts rename to x-pack/plugins/apm/server/routes/settings/apm_indices/save_apm_indices.test.ts diff --git a/x-pack/plugins/apm/server/lib/settings/apm_indices/save_apm_indices.ts b/x-pack/plugins/apm/server/routes/settings/apm_indices/save_apm_indices.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/settings/apm_indices/save_apm_indices.ts rename to x-pack/plugins/apm/server/routes/settings/apm_indices/save_apm_indices.ts diff --git a/x-pack/plugins/apm/server/lib/settings/custom_link/__snapshots__/get_transaction.test.ts.snap b/x-pack/plugins/apm/server/routes/settings/custom_link/__snapshots__/get_transaction.test.ts.snap similarity index 100% rename from x-pack/plugins/apm/server/lib/settings/custom_link/__snapshots__/get_transaction.test.ts.snap rename to x-pack/plugins/apm/server/routes/settings/custom_link/__snapshots__/get_transaction.test.ts.snap diff --git a/x-pack/plugins/apm/server/lib/settings/custom_link/__snapshots__/list_custom_links.test.ts.snap b/x-pack/plugins/apm/server/routes/settings/custom_link/__snapshots__/list_custom_links.test.ts.snap similarity index 100% rename from x-pack/plugins/apm/server/lib/settings/custom_link/__snapshots__/list_custom_links.test.ts.snap rename to x-pack/plugins/apm/server/routes/settings/custom_link/__snapshots__/list_custom_links.test.ts.snap diff --git a/x-pack/plugins/apm/server/lib/settings/custom_link/create_custom_link_index.ts b/x-pack/plugins/apm/server/routes/settings/custom_link/create_custom_link_index.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/settings/custom_link/create_custom_link_index.ts rename to x-pack/plugins/apm/server/routes/settings/custom_link/create_custom_link_index.ts diff --git a/x-pack/plugins/apm/server/lib/settings/custom_link/create_or_update_custom_link.test.ts b/x-pack/plugins/apm/server/routes/settings/custom_link/create_or_update_custom_link.test.ts similarity index 97% rename from x-pack/plugins/apm/server/lib/settings/custom_link/create_or_update_custom_link.test.ts rename to x-pack/plugins/apm/server/routes/settings/custom_link/create_or_update_custom_link.test.ts index 1cec38ad4af69..7690210ac0123 100644 --- a/x-pack/plugins/apm/server/lib/settings/custom_link/create_or_update_custom_link.test.ts +++ b/x-pack/plugins/apm/server/routes/settings/custom_link/create_or_update_custom_link.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { Setup } from '../../helpers/setup_request'; +import { Setup } from '../../../lib/helpers/setup_request'; import { mockNow } from '../../../utils/test_helpers'; import { CustomLink } from '../../../../common/custom_link/custom_link_types'; import { createOrUpdateCustomLink } from './create_or_update_custom_link'; diff --git a/x-pack/plugins/apm/server/lib/settings/custom_link/create_or_update_custom_link.ts b/x-pack/plugins/apm/server/routes/settings/custom_link/create_or_update_custom_link.ts similarity index 86% rename from x-pack/plugins/apm/server/lib/settings/custom_link/create_or_update_custom_link.ts rename to x-pack/plugins/apm/server/routes/settings/custom_link/create_or_update_custom_link.ts index 8f14e87fe183b..6431390936763 100644 --- a/x-pack/plugins/apm/server/lib/settings/custom_link/create_or_update_custom_link.ts +++ b/x-pack/plugins/apm/server/routes/settings/custom_link/create_or_update_custom_link.ts @@ -9,9 +9,9 @@ import { CustomLink, CustomLinkES, } from '../../../../common/custom_link/custom_link_types'; -import { Setup } from '../../helpers/setup_request'; +import { Setup } from '../../../lib/helpers/setup_request'; import { toESFormat } from './helper'; -import { APMIndexDocumentParams } from '../../helpers/create_es_client/create_internal_es_client'; +import { APMIndexDocumentParams } from '../../../lib/helpers/create_es_client/create_internal_es_client'; export function createOrUpdateCustomLink({ customLinkId, diff --git a/x-pack/plugins/apm/server/lib/settings/custom_link/custom_link_types.ts b/x-pack/plugins/apm/server/routes/settings/custom_link/custom_link_types.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/settings/custom_link/custom_link_types.ts rename to x-pack/plugins/apm/server/routes/settings/custom_link/custom_link_types.ts diff --git a/x-pack/plugins/apm/server/lib/settings/custom_link/delete_custom_link.ts b/x-pack/plugins/apm/server/routes/settings/custom_link/delete_custom_link.ts similarity index 90% rename from x-pack/plugins/apm/server/lib/settings/custom_link/delete_custom_link.ts rename to x-pack/plugins/apm/server/routes/settings/custom_link/delete_custom_link.ts index bf7cfb33d87ac..6366bbcfd9f07 100644 --- a/x-pack/plugins/apm/server/lib/settings/custom_link/delete_custom_link.ts +++ b/x-pack/plugins/apm/server/routes/settings/custom_link/delete_custom_link.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { Setup } from '../../helpers/setup_request'; +import { Setup } from '../../../lib/helpers/setup_request'; export function deleteCustomLink({ customLinkId, diff --git a/x-pack/plugins/apm/server/lib/settings/custom_link/get_transaction.test.ts b/x-pack/plugins/apm/server/routes/settings/custom_link/get_transaction.test.ts similarity index 95% rename from x-pack/plugins/apm/server/lib/settings/custom_link/get_transaction.test.ts rename to x-pack/plugins/apm/server/routes/settings/custom_link/get_transaction.test.ts index 03d0120b0043b..e6ba932ca58d6 100644 --- a/x-pack/plugins/apm/server/lib/settings/custom_link/get_transaction.test.ts +++ b/x-pack/plugins/apm/server/routes/settings/custom_link/get_transaction.test.ts @@ -10,7 +10,7 @@ import { SearchParamsMock, } from '../../../utils/test_helpers'; import { getTransaction } from './get_transaction'; -import { Setup } from '../../helpers/setup_request'; +import { Setup } from '../../../lib/helpers/setup_request'; import { SERVICE_NAME, TRANSACTION_TYPE, diff --git a/x-pack/plugins/apm/server/lib/settings/custom_link/get_transaction.ts b/x-pack/plugins/apm/server/routes/settings/custom_link/get_transaction.ts similarity index 95% rename from x-pack/plugins/apm/server/lib/settings/custom_link/get_transaction.ts rename to x-pack/plugins/apm/server/routes/settings/custom_link/get_transaction.ts index 1c3d1465527ba..88d2ae9f339ac 100644 --- a/x-pack/plugins/apm/server/lib/settings/custom_link/get_transaction.ts +++ b/x-pack/plugins/apm/server/routes/settings/custom_link/get_transaction.ts @@ -7,7 +7,7 @@ import * as t from 'io-ts'; import { compact } from 'lodash'; -import { Setup } from '../../helpers/setup_request'; +import { Setup } from '../../../lib/helpers/setup_request'; import { ProcessorEvent } from '../../../../common/processor_event'; import { filterOptionsRt } from './custom_link_types'; import { splitFilterValueByComma } from './helper'; diff --git a/x-pack/plugins/apm/server/lib/settings/custom_link/helper.test.ts b/x-pack/plugins/apm/server/routes/settings/custom_link/helper.test.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/settings/custom_link/helper.test.ts rename to x-pack/plugins/apm/server/routes/settings/custom_link/helper.test.ts diff --git a/x-pack/plugins/apm/server/lib/settings/custom_link/helper.ts b/x-pack/plugins/apm/server/routes/settings/custom_link/helper.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/settings/custom_link/helper.ts rename to x-pack/plugins/apm/server/routes/settings/custom_link/helper.ts diff --git a/x-pack/plugins/apm/server/lib/settings/custom_link/list_custom_links.test.ts b/x-pack/plugins/apm/server/routes/settings/custom_link/list_custom_links.test.ts similarity index 94% rename from x-pack/plugins/apm/server/lib/settings/custom_link/list_custom_links.test.ts rename to x-pack/plugins/apm/server/routes/settings/custom_link/list_custom_links.test.ts index 844f886c21a46..8ea4061e46cf2 100644 --- a/x-pack/plugins/apm/server/lib/settings/custom_link/list_custom_links.test.ts +++ b/x-pack/plugins/apm/server/routes/settings/custom_link/list_custom_links.test.ts @@ -10,7 +10,7 @@ import { inspectSearchParams, SearchParamsMock, } from '../../../utils/test_helpers'; -import { Setup } from '../../helpers/setup_request'; +import { Setup } from '../../../lib/helpers/setup_request'; import { SERVICE_NAME, TRANSACTION_NAME, diff --git a/x-pack/plugins/apm/server/lib/settings/custom_link/list_custom_links.ts b/x-pack/plugins/apm/server/routes/settings/custom_link/list_custom_links.ts similarity index 96% rename from x-pack/plugins/apm/server/lib/settings/custom_link/list_custom_links.ts rename to x-pack/plugins/apm/server/routes/settings/custom_link/list_custom_links.ts index 633545e16acfd..a64d958dabd09 100644 --- a/x-pack/plugins/apm/server/lib/settings/custom_link/list_custom_links.ts +++ b/x-pack/plugins/apm/server/routes/settings/custom_link/list_custom_links.ts @@ -11,7 +11,7 @@ import { CustomLink, CustomLinkES, } from '../../../../common/custom_link/custom_link_types'; -import { Setup } from '../../helpers/setup_request'; +import { Setup } from '../../../lib/helpers/setup_request'; import { fromESFormat } from './helper'; import { filterOptionsRt } from './custom_link_types'; diff --git a/x-pack/plugins/apm/server/routes/settings/custom_link.ts b/x-pack/plugins/apm/server/routes/settings/custom_link/route.ts similarity index 79% rename from x-pack/plugins/apm/server/routes/settings/custom_link.ts rename to x-pack/plugins/apm/server/routes/settings/custom_link/route.ts index 044b56c3c273d..42232581f1af3 100644 --- a/x-pack/plugins/apm/server/routes/settings/custom_link.ts +++ b/x-pack/plugins/apm/server/routes/settings/custom_link/route.ts @@ -8,21 +8,18 @@ import Boom from '@hapi/boom'; import * as t from 'io-ts'; import { pick } from 'lodash'; -import { isActiveGoldLicense } from '../../../common/license_check'; -import { INVALID_LICENSE } from '../../../common/custom_link'; -import { FILTER_OPTIONS } from '../../../common/custom_link/custom_link_filter_options'; -import { notifyFeatureUsage } from '../../feature'; -import { setupRequest } from '../../lib/helpers/setup_request'; -import { createOrUpdateCustomLink } from '../../lib/settings/custom_link/create_or_update_custom_link'; -import { - filterOptionsRt, - payloadRt, -} from '../../lib/settings/custom_link/custom_link_types'; -import { deleteCustomLink } from '../../lib/settings/custom_link/delete_custom_link'; -import { getTransaction } from '../../lib/settings/custom_link/get_transaction'; -import { listCustomLinks } from '../../lib/settings/custom_link/list_custom_links'; -import { createApmServerRoute } from '../apm_routes/create_apm_server_route'; -import { createApmServerRouteRepository } from '../apm_routes/create_apm_server_route_repository'; +import { isActiveGoldLicense } from '../../../../common/license_check'; +import { INVALID_LICENSE } from '../../../../common/custom_link'; +import { FILTER_OPTIONS } from '../../../../common/custom_link/custom_link_filter_options'; +import { notifyFeatureUsage } from '../../../feature'; +import { setupRequest } from '../../../lib/helpers/setup_request'; +import { createOrUpdateCustomLink } from './create_or_update_custom_link'; +import { filterOptionsRt, payloadRt } from './custom_link_types'; +import { deleteCustomLink } from './delete_custom_link'; +import { getTransaction } from './get_transaction'; +import { listCustomLinks } from './list_custom_links'; +import { createApmServerRoute } from '../../apm_routes/create_apm_server_route'; +import { createApmServerRouteRepository } from '../../apm_routes/create_apm_server_route_repository'; const customLinkTransactionRoute = createApmServerRoute({ endpoint: 'GET /internal/apm/settings/custom_links/transaction', diff --git a/x-pack/plugins/apm/server/routes/source_maps.ts b/x-pack/plugins/apm/server/routes/source_maps/route.ts similarity index 91% rename from x-pack/plugins/apm/server/routes/source_maps.ts rename to x-pack/plugins/apm/server/routes/source_maps/route.ts index 602a3a725eac4..b0b7eb5134fcf 100644 --- a/x-pack/plugins/apm/server/routes/source_maps.ts +++ b/x-pack/plugins/apm/server/routes/source_maps/route.ts @@ -14,11 +14,11 @@ import { listArtifacts, updateSourceMapsOnFleetPolicies, getCleanedBundleFilePath, -} from '../lib/fleet/source_maps'; -import { getInternalSavedObjectsClient } from '../lib/helpers/get_internal_saved_objects_client'; -import { createApmServerRoute } from './apm_routes/create_apm_server_route'; -import { createApmServerRouteRepository } from './apm_routes/create_apm_server_route_repository'; -import { stringFromBufferRt } from '../utils/string_from_buffer_rt'; +} from '../fleet/source_maps'; +import { getInternalSavedObjectsClient } from '../../lib/helpers/get_internal_saved_objects_client'; +import { createApmServerRoute } from '../apm_routes/create_apm_server_route'; +import { createApmServerRouteRepository } from '../apm_routes/create_apm_server_route_repository'; +import { stringFromBufferRt } from '../../utils/string_from_buffer_rt'; export const sourceMapRt = t.intersection([ t.type({ diff --git a/x-pack/plugins/apm/server/lib/suggestions/get_suggestions.ts b/x-pack/plugins/apm/server/routes/suggestions/get_suggestions.ts similarity index 87% rename from x-pack/plugins/apm/server/lib/suggestions/get_suggestions.ts rename to x-pack/plugins/apm/server/routes/suggestions/get_suggestions.ts index 5ea28debc4437..624bf2bb4c018 100644 --- a/x-pack/plugins/apm/server/lib/suggestions/get_suggestions.ts +++ b/x-pack/plugins/apm/server/routes/suggestions/get_suggestions.ts @@ -6,8 +6,8 @@ */ import { ProcessorEvent } from '../../../common/processor_event'; -import { getProcessorEventForTransactions } from '../helpers/transactions'; -import { Setup } from '../helpers/setup_request'; +import { getProcessorEventForTransactions } from '../../lib/helpers/transactions'; +import { Setup } from '../../lib/helpers/setup_request'; export async function getSuggestions({ field, diff --git a/x-pack/plugins/apm/server/routes/suggestions.ts b/x-pack/plugins/apm/server/routes/suggestions/route.ts similarity index 72% rename from x-pack/plugins/apm/server/routes/suggestions.ts rename to x-pack/plugins/apm/server/routes/suggestions/route.ts index 9b8952d09d162..de3636c2c1502 100644 --- a/x-pack/plugins/apm/server/routes/suggestions.ts +++ b/x-pack/plugins/apm/server/routes/suggestions/route.ts @@ -6,12 +6,12 @@ */ import * as t from 'io-ts'; -import { maxSuggestions } from '../../../observability/common'; -import { getSuggestions } from '../lib/suggestions/get_suggestions'; -import { getSearchAggregatedTransactions } from '../lib/helpers/transactions'; -import { setupRequest } from '../lib/helpers/setup_request'; -import { createApmServerRoute } from './apm_routes/create_apm_server_route'; -import { createApmServerRouteRepository } from './apm_routes/create_apm_server_route_repository'; +import { maxSuggestions } from '../../../../observability/common'; +import { getSuggestions } from '../suggestions/get_suggestions'; +import { getSearchAggregatedTransactions } from '../../lib/helpers/transactions'; +import { setupRequest } from '../../lib/helpers/setup_request'; +import { createApmServerRoute } from '../apm_routes/create_apm_server_route'; +import { createApmServerRouteRepository } from '../apm_routes/create_apm_server_route_repository'; const suggestionsRoute = createApmServerRoute({ endpoint: 'GET /internal/apm/suggestions', diff --git a/x-pack/plugins/apm/server/lib/traces/__snapshots__/queries.test.ts.snap b/x-pack/plugins/apm/server/routes/traces/__snapshots__/queries.test.ts.snap similarity index 100% rename from x-pack/plugins/apm/server/lib/traces/__snapshots__/queries.test.ts.snap rename to x-pack/plugins/apm/server/routes/traces/__snapshots__/queries.test.ts.snap diff --git a/x-pack/plugins/apm/server/lib/traces/get_trace_items.ts b/x-pack/plugins/apm/server/routes/traces/get_trace_items.ts similarity index 97% rename from x-pack/plugins/apm/server/lib/traces/get_trace_items.ts rename to x-pack/plugins/apm/server/routes/traces/get_trace_items.ts index 55204786b8e67..419c3e44d68a6 100644 --- a/x-pack/plugins/apm/server/lib/traces/get_trace_items.ts +++ b/x-pack/plugins/apm/server/routes/traces/get_trace_items.ts @@ -15,7 +15,7 @@ import { ERROR_LOG_LEVEL, } from '../../../common/elasticsearch_fieldnames'; import { rangeQuery } from '../../../../observability/server'; -import { Setup } from '../helpers/setup_request'; +import { Setup } from '../../lib/helpers/setup_request'; export async function getTraceItems( traceId: string, diff --git a/x-pack/plugins/apm/server/lib/traces/queries.test.ts b/x-pack/plugins/apm/server/routes/traces/queries.test.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/traces/queries.test.ts rename to x-pack/plugins/apm/server/routes/traces/queries.test.ts diff --git a/x-pack/plugins/apm/server/routes/traces.ts b/x-pack/plugins/apm/server/routes/traces/route.ts similarity index 79% rename from x-pack/plugins/apm/server/routes/traces.ts rename to x-pack/plugins/apm/server/routes/traces/route.ts index 5fdac470a81ed..24b5faeedfc00 100644 --- a/x-pack/plugins/apm/server/routes/traces.ts +++ b/x-pack/plugins/apm/server/routes/traces/route.ts @@ -6,15 +6,15 @@ */ import * as t from 'io-ts'; -import { setupRequest } from '../lib/helpers/setup_request'; -import { getTraceItems } from '../lib/traces/get_trace_items'; -import { getTopTransactionGroupList } from '../lib/transaction_groups'; -import { createApmServerRoute } from './apm_routes/create_apm_server_route'; -import { environmentRt, kueryRt, rangeRt } from './default_api_types'; -import { getSearchAggregatedTransactions } from '../lib/helpers/transactions'; -import { getRootTransactionByTraceId } from '../lib/transactions/get_transaction_by_trace'; -import { createApmServerRouteRepository } from './apm_routes/create_apm_server_route_repository'; -import { getTransaction } from '../lib/transactions/get_transaction'; +import { setupRequest } from '../../lib/helpers/setup_request'; +import { getTraceItems } from './get_trace_items'; +import { getTopTransactionGroupList } from '../../lib/transaction_groups'; +import { createApmServerRoute } from '../apm_routes/create_apm_server_route'; +import { environmentRt, kueryRt, rangeRt } from '../default_api_types'; +import { getSearchAggregatedTransactions } from '../../lib/helpers/transactions'; +import { getRootTransactionByTraceId } from '../transactions/get_transaction_by_trace'; +import { createApmServerRouteRepository } from '../apm_routes/create_apm_server_route_repository'; +import { getTransaction } from '../transactions/get_transaction'; const tracesRoute = createApmServerRoute({ endpoint: 'GET /internal/apm/traces', diff --git a/x-pack/plugins/apm/server/lib/transactions/__snapshots__/queries.test.ts.snap b/x-pack/plugins/apm/server/routes/transactions/__snapshots__/queries.test.ts.snap similarity index 100% rename from x-pack/plugins/apm/server/lib/transactions/__snapshots__/queries.test.ts.snap rename to x-pack/plugins/apm/server/routes/transactions/__snapshots__/queries.test.ts.snap diff --git a/x-pack/plugins/apm/server/lib/transactions/breakdown/constants.ts b/x-pack/plugins/apm/server/routes/transactions/breakdown/constants.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/transactions/breakdown/constants.ts rename to x-pack/plugins/apm/server/routes/transactions/breakdown/constants.ts diff --git a/x-pack/plugins/apm/server/lib/transactions/breakdown/index.test.ts b/x-pack/plugins/apm/server/routes/transactions/breakdown/index.test.ts similarity index 97% rename from x-pack/plugins/apm/server/lib/transactions/breakdown/index.test.ts rename to x-pack/plugins/apm/server/routes/transactions/breakdown/index.test.ts index 41d4c60fd72b4..1d2602dcafc75 100644 --- a/x-pack/plugins/apm/server/lib/transactions/breakdown/index.test.ts +++ b/x-pack/plugins/apm/server/routes/transactions/breakdown/index.test.ts @@ -11,7 +11,7 @@ import noDataResponse from './mock_responses/no_data.json'; import dataResponse from './mock_responses/data.json'; import { APMConfig } from '../../..'; import { ENVIRONMENT_ALL } from '../../../../common/environment_filter_values'; -import { ApmIndicesConfig } from '../../settings/apm_indices/get_apm_indices'; +import { ApmIndicesConfig } from '../../../routes/settings/apm_indices/get_apm_indices'; const mockIndices: ApmIndicesConfig = { sourcemap: 'myIndex', diff --git a/x-pack/plugins/apm/server/lib/transactions/breakdown/index.ts b/x-pack/plugins/apm/server/routes/transactions/breakdown/index.ts similarity index 97% rename from x-pack/plugins/apm/server/lib/transactions/breakdown/index.ts rename to x-pack/plugins/apm/server/routes/transactions/breakdown/index.ts index a5c11776c70b0..2c3bca8443db0 100644 --- a/x-pack/plugins/apm/server/lib/transactions/breakdown/index.ts +++ b/x-pack/plugins/apm/server/routes/transactions/breakdown/index.ts @@ -17,10 +17,10 @@ import { TRANSACTION_NAME, TRANSACTION_BREAKDOWN_COUNT, } from '../../../../common/elasticsearch_fieldnames'; -import { Setup } from '../../helpers/setup_request'; +import { Setup } from '../../../lib/helpers/setup_request'; import { rangeQuery, kqlQuery } from '../../../../../observability/server'; import { environmentQuery } from '../../../../common/utils/environment_query'; -import { getMetricsDateHistogramParams } from '../../helpers/metrics'; +import { getMetricsDateHistogramParams } from '../../../lib/helpers/metrics'; import { MAX_KPIS } from './constants'; import { getVizColorForIndex } from '../../../../common/viz_colors'; diff --git a/x-pack/plugins/apm/server/lib/transactions/breakdown/mock_responses/data.json b/x-pack/plugins/apm/server/routes/transactions/breakdown/mock_responses/data.json similarity index 100% rename from x-pack/plugins/apm/server/lib/transactions/breakdown/mock_responses/data.json rename to x-pack/plugins/apm/server/routes/transactions/breakdown/mock_responses/data.json diff --git a/x-pack/plugins/apm/server/lib/transactions/breakdown/mock_responses/no_data.json b/x-pack/plugins/apm/server/routes/transactions/breakdown/mock_responses/no_data.json similarity index 100% rename from x-pack/plugins/apm/server/lib/transactions/breakdown/mock_responses/no_data.json rename to x-pack/plugins/apm/server/routes/transactions/breakdown/mock_responses/no_data.json diff --git a/x-pack/plugins/apm/server/lib/transactions/constants.ts b/x-pack/plugins/apm/server/routes/transactions/constants.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/transactions/constants.ts rename to x-pack/plugins/apm/server/routes/transactions/constants.ts diff --git a/x-pack/plugins/apm/server/lib/transactions/get_anomaly_data/fetcher.ts b/x-pack/plugins/apm/server/routes/transactions/get_anomaly_data/fetcher.ts similarity index 97% rename from x-pack/plugins/apm/server/lib/transactions/get_anomaly_data/fetcher.ts rename to x-pack/plugins/apm/server/routes/transactions/get_anomaly_data/fetcher.ts index dd723f24abe1b..704bc751e5772 100644 --- a/x-pack/plugins/apm/server/lib/transactions/get_anomaly_data/fetcher.ts +++ b/x-pack/plugins/apm/server/routes/transactions/get_anomaly_data/fetcher.ts @@ -11,7 +11,7 @@ import { PromiseReturnType } from '../../../../../observability/typings/common'; import { rangeQuery } from '../../../../../observability/server'; import { asMutableArray } from '../../../../common/utils/as_mutable_array'; import { withApmSpan } from '../../../utils/with_apm_span'; -import { Setup } from '../../helpers/setup_request'; +import { Setup } from '../../../lib/helpers/setup_request'; import { apmMlAnomalyQuery } from '../../../../common/anomaly_detection/apm_ml_anomaly_query'; import { ApmMlDetectorIndex } from '../../../../common/anomaly_detection/apm_ml_detectors'; diff --git a/x-pack/plugins/apm/server/lib/transactions/get_anomaly_data/index.ts b/x-pack/plugins/apm/server/routes/transactions/get_anomaly_data/index.ts similarity index 97% rename from x-pack/plugins/apm/server/lib/transactions/get_anomaly_data/index.ts rename to x-pack/plugins/apm/server/routes/transactions/get_anomaly_data/index.ts index c1123182586b7..0cdbe1774504a 100644 --- a/x-pack/plugins/apm/server/lib/transactions/get_anomaly_data/index.ts +++ b/x-pack/plugins/apm/server/routes/transactions/get_anomaly_data/index.ts @@ -10,8 +10,8 @@ import { Logger } from 'src/core/server'; import { isFiniteNumber } from '../../../../common/utils/is_finite_number'; import { maybe } from '../../../../common/utils/maybe'; import { ENVIRONMENT_ALL } from '../../../../common/environment_filter_values'; -import { getBucketSize } from '../../helpers/get_bucket_size'; -import { Setup } from '../../helpers/setup_request'; +import { getBucketSize } from '../../../lib/helpers/get_bucket_size'; +import { Setup } from '../../../lib/helpers/setup_request'; import { anomalySeriesFetcher } from './fetcher'; import { getMLJobIds } from '../../service_map/get_service_anomalies'; import { ANOMALY_THRESHOLD } from '../../../../common/ml_constants'; diff --git a/x-pack/plugins/apm/server/lib/transactions/get_latency_charts/index.ts b/x-pack/plugins/apm/server/routes/transactions/get_latency_charts/index.ts similarity index 97% rename from x-pack/plugins/apm/server/lib/transactions/get_latency_charts/index.ts rename to x-pack/plugins/apm/server/routes/transactions/get_latency_charts/index.ts index 4612d399b54a1..5375da3606f18 100644 --- a/x-pack/plugins/apm/server/lib/transactions/get_latency_charts/index.ts +++ b/x-pack/plugins/apm/server/routes/transactions/get_latency_charts/index.ts @@ -25,11 +25,11 @@ import { getProcessorEventForTransactions, } from '../../../lib/helpers/transactions'; import { Setup } from '../../../lib/helpers/setup_request'; -import { getBucketSizeForAggregatedTransactions } from '../../helpers/get_bucket_size_for_aggregated_transactions'; +import { getBucketSizeForAggregatedTransactions } from '../../../lib/helpers/get_bucket_size_for_aggregated_transactions'; import { getLatencyAggregation, getLatencyValue, -} from '../../helpers/latency_aggregation_type'; +} from '../../../lib/helpers/latency_aggregation_type'; export type LatencyChartsSearchResponse = PromiseReturnType< typeof searchLatency >; diff --git a/x-pack/plugins/apm/server/lib/transactions/get_transaction/index.ts b/x-pack/plugins/apm/server/routes/transactions/get_transaction/index.ts similarity index 95% rename from x-pack/plugins/apm/server/lib/transactions/get_transaction/index.ts rename to x-pack/plugins/apm/server/routes/transactions/get_transaction/index.ts index 6d0bbcdb55ca4..0522fb3a1899d 100644 --- a/x-pack/plugins/apm/server/lib/transactions/get_transaction/index.ts +++ b/x-pack/plugins/apm/server/routes/transactions/get_transaction/index.ts @@ -10,7 +10,7 @@ import { TRANSACTION_ID, } from '../../../../common/elasticsearch_fieldnames'; import { rangeQuery, termQuery } from '../../../../../observability/server'; -import { Setup } from '../../helpers/setup_request'; +import { Setup } from '../../../lib/helpers/setup_request'; import { ProcessorEvent } from '../../../../common/processor_event'; import { asMutableArray } from '../../../../common/utils/as_mutable_array'; diff --git a/x-pack/plugins/apm/server/lib/transactions/get_transaction_by_trace/index.ts b/x-pack/plugins/apm/server/routes/transactions/get_transaction_by_trace/index.ts similarity index 95% rename from x-pack/plugins/apm/server/lib/transactions/get_transaction_by_trace/index.ts rename to x-pack/plugins/apm/server/routes/transactions/get_transaction_by_trace/index.ts index 568ce16e7aedc..d9c6a64bdbcc6 100644 --- a/x-pack/plugins/apm/server/lib/transactions/get_transaction_by_trace/index.ts +++ b/x-pack/plugins/apm/server/routes/transactions/get_transaction_by_trace/index.ts @@ -9,7 +9,7 @@ import { TRACE_ID, PARENT_ID, } from '../../../../common/elasticsearch_fieldnames'; -import { Setup } from '../../helpers/setup_request'; +import { Setup } from '../../../lib/helpers/setup_request'; import { ProcessorEvent } from '../../../../common/processor_event'; export async function getRootTransactionByTraceId( diff --git a/x-pack/plugins/apm/server/lib/transactions/queries.test.ts b/x-pack/plugins/apm/server/routes/transactions/queries.test.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/transactions/queries.test.ts rename to x-pack/plugins/apm/server/routes/transactions/queries.test.ts diff --git a/x-pack/plugins/apm/server/routes/transactions.ts b/x-pack/plugins/apm/server/routes/transactions/route.ts similarity index 90% rename from x-pack/plugins/apm/server/routes/transactions.ts rename to x-pack/plugins/apm/server/routes/transactions/route.ts index c0d83bac6e8e4..5b3f4e4f3bd4c 100644 --- a/x-pack/plugins/apm/server/routes/transactions.ts +++ b/x-pack/plugins/apm/server/routes/transactions/route.ts @@ -11,24 +11,24 @@ import * as t from 'io-ts'; import { LatencyAggregationType, latencyAggregationTypeRt, -} from '../../common/latency_aggregation_types'; -import { getSearchAggregatedTransactions } from '../lib/helpers/transactions'; -import { setupRequest } from '../lib/helpers/setup_request'; -import { getServiceTransactionGroups } from '../lib/services/get_service_transaction_groups'; -import { getServiceTransactionGroupDetailedStatisticsPeriods } from '../lib/services/get_service_transaction_group_detailed_statistics'; -import { getTransactionBreakdown } from '../lib/transactions/breakdown'; -import { getTransactionTraceSamples } from '../lib/transactions/trace_samples'; -import { getAnomalySeries } from '../lib/transactions/get_anomaly_data'; -import { getLatencyPeriods } from '../lib/transactions/get_latency_charts'; -import { getErrorRatePeriods } from '../lib/transaction_groups/get_error_rate'; -import { createApmServerRoute } from './apm_routes/create_apm_server_route'; -import { createApmServerRouteRepository } from './apm_routes/create_apm_server_route_repository'; +} from '../../../common/latency_aggregation_types'; +import { getSearchAggregatedTransactions } from '../../lib/helpers/transactions'; +import { setupRequest } from '../../lib/helpers/setup_request'; +import { getServiceTransactionGroups } from '../services/get_service_transaction_groups'; +import { getServiceTransactionGroupDetailedStatisticsPeriods } from '../services/get_service_transaction_group_detailed_statistics'; +import { getTransactionBreakdown } from './breakdown'; +import { getTransactionTraceSamples } from './trace_samples'; +import { getAnomalySeries } from './get_anomaly_data'; +import { getLatencyPeriods } from './get_latency_charts'; +import { getErrorRatePeriods } from '../../lib/transaction_groups/get_error_rate'; +import { createApmServerRoute } from '../apm_routes/create_apm_server_route'; +import { createApmServerRouteRepository } from '../apm_routes/create_apm_server_route_repository'; import { comparisonRangeRt, environmentRt, kueryRt, rangeRt, -} from './default_api_types'; +} from '../default_api_types'; const transactionGroupsMainStatisticsRoute = createApmServerRoute({ endpoint: diff --git a/x-pack/plugins/apm/server/lib/transactions/trace_samples/get_trace_samples/index.ts b/x-pack/plugins/apm/server/routes/transactions/trace_samples/get_trace_samples/index.ts similarity index 97% rename from x-pack/plugins/apm/server/lib/transactions/trace_samples/get_trace_samples/index.ts rename to x-pack/plugins/apm/server/routes/transactions/trace_samples/get_trace_samples/index.ts index 9b96cf19c516d..d4ceafd9f6306 100644 --- a/x-pack/plugins/apm/server/lib/transactions/trace_samples/get_trace_samples/index.ts +++ b/x-pack/plugins/apm/server/routes/transactions/trace_samples/get_trace_samples/index.ts @@ -17,7 +17,7 @@ import { import { ProcessorEvent } from '../../../../../common/processor_event'; import { rangeQuery, kqlQuery } from '../../../../../../observability/server'; import { environmentQuery } from '../../../../../common/utils/environment_query'; -import { Setup } from '../../../helpers/setup_request'; +import { Setup } from '../../../../lib/helpers/setup_request'; const TRACE_SAMPLES_SIZE = 500; diff --git a/x-pack/plugins/apm/server/lib/transactions/trace_samples/index.ts b/x-pack/plugins/apm/server/routes/transactions/trace_samples/index.ts similarity index 95% rename from x-pack/plugins/apm/server/lib/transactions/trace_samples/index.ts rename to x-pack/plugins/apm/server/routes/transactions/trace_samples/index.ts index e422be417438b..89bae10db5e87 100644 --- a/x-pack/plugins/apm/server/lib/transactions/trace_samples/index.ts +++ b/x-pack/plugins/apm/server/routes/transactions/trace_samples/index.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { Setup } from '../../helpers/setup_request'; +import { Setup } from '../../../lib/helpers/setup_request'; import { getTraceSamples } from './get_trace_samples'; import { withApmSpan } from '../../../utils/with_apm_span'; diff --git a/x-pack/plugins/apm/server/tutorial/index.ts b/x-pack/plugins/apm/server/tutorial/index.ts index f04b794091ff2..5d3ff8636df4d 100644 --- a/x-pack/plugins/apm/server/tutorial/index.ts +++ b/x-pack/plugins/apm/server/tutorial/index.ts @@ -14,8 +14,8 @@ import { } from '../../../../../src/plugins/home/server'; import { CloudSetup } from '../../../cloud/server'; import { APM_STATIC_INDEX_PATTERN_ID } from '../../common/index_pattern_constants'; -import { getApmDataViewTitle } from '../lib/data_view/get_apm_data_view_title'; -import { ApmIndicesConfig } from '../lib/settings/apm_indices/get_apm_indices'; +import { getApmDataViewTitle } from '../routes/data_view/get_apm_data_view_title'; +import { ApmIndicesConfig } from '../routes/settings/apm_indices/get_apm_indices'; import { createElasticCloudInstructions } from './envs/elastic_cloud'; import { onPremInstructions } from './envs/on_prem'; import apmDataView from './index_pattern.json'; diff --git a/x-pack/plugins/apm/server/types.ts b/x-pack/plugins/apm/server/types.ts index c686c42beb6ef..02aae547407e5 100644 --- a/x-pack/plugins/apm/server/types.ts +++ b/x-pack/plugins/apm/server/types.ts @@ -47,7 +47,7 @@ import { FleetStartContract as FleetPluginStart, } from '../../fleet/server'; import { APMConfig } from '.'; -import { getApmIndices } from './lib/settings/apm_indices/get_apm_indices'; +import { getApmIndices } from './routes/settings/apm_indices/get_apm_indices'; import { createApmEventClient } from './lib/helpers/create_es_client/create_apm_event_client'; import { ApmPluginRequestHandlerContext } from './routes/typings'; diff --git a/x-pack/plugins/apm/server/utils/test_helpers.tsx b/x-pack/plugins/apm/server/utils/test_helpers.tsx index 0e1b9f2ba8051..19644b5bc87f8 100644 --- a/x-pack/plugins/apm/server/utils/test_helpers.tsx +++ b/x-pack/plugins/apm/server/utils/test_helpers.tsx @@ -12,7 +12,7 @@ import { ESSearchResponse, } from '../../../../../src/core/types/elasticsearch'; import { UxUIFilters } from '../../typings/ui_filters'; -import { ApmIndicesConfig } from '../lib/settings/apm_indices/get_apm_indices'; +import { ApmIndicesConfig } from '../routes/settings/apm_indices/get_apm_indices'; interface Options { mockResponse?: ( diff --git a/x-pack/test/apm_api_integration/tests/metrics_charts/metrics_charts.spec.ts b/x-pack/test/apm_api_integration/tests/metrics_charts/metrics_charts.spec.ts index d70ee347d4c2d..beaaae24fb220 100644 --- a/x-pack/test/apm_api_integration/tests/metrics_charts/metrics_charts.spec.ts +++ b/x-pack/test/apm_api_integration/tests/metrics_charts/metrics_charts.spec.ts @@ -7,7 +7,7 @@ import expect from '@kbn/expect'; import { first } from 'lodash'; -import { GenericMetricsChart } from '../../../../plugins/apm/server/lib/metrics/fetch_and_transform_metrics'; +import { GenericMetricsChart } from '../../../../plugins/apm/server/routes/metrics/fetch_and_transform_metrics'; import { SupertestReturnType } from '../../common/apm_api_supertest'; import { FtrProviderContext } from '../../common/ftr_provider_context'; diff --git a/x-pack/test/apm_api_integration/tests/settings/agent_configuration.spec.ts b/x-pack/test/apm_api_integration/tests/settings/agent_configuration.spec.ts index df504ec7444d7..cea718c2c69d5 100644 --- a/x-pack/test/apm_api_integration/tests/settings/agent_configuration.spec.ts +++ b/x-pack/test/apm_api_integration/tests/settings/agent_configuration.spec.ts @@ -10,7 +10,7 @@ import { inspect } from 'util'; import expect from '@kbn/expect'; import { omit, orderBy } from 'lodash'; import { AgentConfigurationIntake } from '../../../../plugins/apm/common/agent_configuration/configuration_types'; -import { AgentConfigSearchParams } from '../../../../plugins/apm/server/routes/settings/agent_configuration'; +import { AgentConfigSearchParams } from '../../../../plugins/apm/server/routes/settings/agent_configuration/route'; import { FtrProviderContext } from '../../common/ftr_provider_context'; From fc8816265bb73b51ec64124a7d24f6c777debcbb Mon Sep 17 00:00:00 2001 From: "Devin W. Hurley" Date: Thu, 18 Nov 2021 09:12:41 -0500 Subject: [PATCH 109/148] [Security Solution] [Platform] optionally include legacy id when resolving a rule (#118946) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../server/rules_client/rules_client.ts | 5 +- .../server/rules_client/tests/resolve.test.ts | 74 +++++++++++++++++++ 2 files changed, 78 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/alerting/server/rules_client/rules_client.ts b/x-pack/plugins/alerting/server/rules_client/rules_client.ts index e10af37e0936b..37e9bcbfa3a8f 100644 --- a/x-pack/plugins/alerting/server/rules_client/rules_client.ts +++ b/x-pack/plugins/alerting/server/rules_client/rules_client.ts @@ -450,8 +450,10 @@ export class RulesClient { public async resolve({ id, + includeLegacyId, }: { id: string; + includeLegacyId?: boolean; }): Promise> { const { saved_object: result, ...resolveResponse } = await this.unsecuredSavedObjectsClient.resolve('alert', id); @@ -483,7 +485,8 @@ export class RulesClient { result.id, result.attributes.alertTypeId, result.attributes, - result.references + result.references, + includeLegacyId ); return { diff --git a/x-pack/plugins/alerting/server/rules_client/tests/resolve.test.ts b/x-pack/plugins/alerting/server/rules_client/tests/resolve.test.ts index 537d890217cfb..8102dcedbd780 100644 --- a/x-pack/plugins/alerting/server/rules_client/tests/resolve.test.ts +++ b/x-pack/plugins/alerting/server/rules_client/tests/resolve.test.ts @@ -125,6 +125,80 @@ describe('resolve()', () => { `); }); + test('calls saved objects client with id and includeLegacyId params', async () => { + const rulesClient = new RulesClient(rulesClientParams); + unsecuredSavedObjectsClient.resolve.mockResolvedValueOnce({ + saved_object: { + id: '1', + type: 'alert', + attributes: { + legacyId: 'some-legacy-id', + alertTypeId: '123', + schedule: { interval: '10s' }, + params: { + bar: true, + }, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + actions: [ + { + group: 'default', + actionRef: 'action_0', + params: { + foo: true, + }, + }, + ], + notifyWhen: 'onActiveAlert', + }, + references: [ + { + name: 'action_0', + type: 'action', + id: '1', + }, + ], + }, + outcome: 'aliasMatch', + alias_target_id: '2', + }); + const result = await rulesClient.resolve({ id: '1', includeLegacyId: true }); + expect(result).toMatchInlineSnapshot(` + Object { + "actions": Array [ + Object { + "group": "default", + "id": "1", + "params": Object { + "foo": true, + }, + }, + ], + "alertTypeId": "123", + "alias_target_id": "2", + "createdAt": 2019-02-12T21:01:22.479Z, + "id": "1", + "legacyId": "some-legacy-id", + "notifyWhen": "onActiveAlert", + "outcome": "aliasMatch", + "params": Object { + "bar": true, + }, + "schedule": Object { + "interval": "10s", + }, + "updatedAt": 2019-02-12T21:01:22.479Z, + } + `); + expect(unsecuredSavedObjectsClient.resolve).toHaveBeenCalledTimes(1); + expect(unsecuredSavedObjectsClient.resolve.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + "alert", + "1", + ] + `); + }); + test('should call useSavedObjectReferences.injectReferences if defined for rule type', async () => { const injectReferencesFn = jest.fn().mockReturnValue({ bar: true, From 32587fb93d7f4045f992239731c39f7510519d0a Mon Sep 17 00:00:00 2001 From: Steph Milovic Date: Thu, 18 Nov 2021 07:30:27 -0700 Subject: [PATCH 110/148] [Security Solution] Update timeline when sourcerer updates (#118958) --- .../components/timeline/index.test.tsx | 60 +++++++++++++++---- .../timelines/components/timeline/index.tsx | 43 ++++++++++++- 2 files changed, 89 insertions(+), 14 deletions(-) diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/index.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/index.test.tsx index bb1281c0eff2e..f5ceebf9cdb11 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/index.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/index.test.tsx @@ -13,18 +13,26 @@ import { DragDropContextWrapper } from '../../../common/components/drag_and_drop import '../../../common/mock/match_media'; import { mockBrowserFields, mockDocValueFields } from '../../../common/containers/source/mock'; import { TimelineId } from '../../../../common/types/timeline'; -import { mockIndexNames, mockIndexPattern, TestProviders } from '../../../common/mock'; +import { + mockGlobalState, + mockIndexNames, + mockIndexPattern, + TestProviders, +} from '../../../common/mock'; import { StatefulTimeline, Props as StatefulTimelineOwnProps } from './index'; import { useTimelineEvents } from '../../containers/index'; import { DefaultCellRenderer } from './cell_rendering/default_cell_renderer'; import { SELECTOR_TIMELINE_GLOBAL_CONTAINER } from './styles'; import { defaultRowRenderers } from './body/renderers'; +import { useSourcererDataView } from '../../../common/containers/sourcerer'; jest.mock('../../containers/index', () => ({ useTimelineEvents: jest.fn(), })); +jest.mock('./tabs_content'); + jest.mock('../../../common/lib/kibana'); jest.mock('../../../common/components/url_state/normalize_time_range.ts'); jest.mock('@kbn/i18n/react', () => { @@ -54,21 +62,29 @@ jest.mock('react-router-dom', () => { useHistory: jest.fn(), }; }); -jest.mock('../../../common/containers/sourcerer', () => { - const originalModule = jest.requireActual('../../../common/containers/sourcerer'); +const mockDispatch = jest.fn(); + +jest.mock('react-redux', () => { + const actual = jest.requireActual('react-redux'); return { - ...originalModule, - useSourcererDataView: jest.fn().mockReturnValue({ - browserFields: mockBrowserFields, - docValueFields: mockDocValueFields, - loading: false, - indexPattern: mockIndexPattern, - pageInfo: { activePage: 0, querySize: 0 }, - selectedPatterns: mockIndexNames, - }), + ...actual, + useDispatch: () => mockDispatch, }; }); + +const mockUseSourcererDataView: jest.Mock = useSourcererDataView as jest.Mock; +jest.mock('../../../common/containers/sourcerer'); +const mockDataView = { + dataViewId: mockGlobalState.timeline.timelineById.test?.dataViewId, + browserFields: mockBrowserFields, + docValueFields: mockDocValueFields, + loading: false, + indexPattern: mockIndexPattern, + pageInfo: { activePage: 0, querySize: 0 }, + selectedPatterns: mockGlobalState.timeline.timelineById.test?.indexNames, +}; +mockUseSourcererDataView.mockReturnValue(mockDataView); describe('StatefulTimeline', () => { const props: StatefulTimelineOwnProps = { renderCellValue: DefaultCellRenderer, @@ -77,6 +93,7 @@ describe('StatefulTimeline', () => { }; beforeEach(() => { + jest.clearAllMocks(); (useTimelineEvents as jest.Mock).mockReturnValue([ false, { @@ -97,6 +114,25 @@ describe('StatefulTimeline', () => { ); expect(wrapper.find('[data-test-subj="timeline"]')).toBeTruthy(); + expect(mockDispatch).toBeCalledTimes(1); + }); + + test('data view updates, updates timeline', () => { + mockUseSourcererDataView.mockReturnValue({ ...mockDataView, selectedPatterns: mockIndexNames }); + mount( + + + + ); + expect(mockDispatch).toBeCalledTimes(2); + expect(mockDispatch).toHaveBeenNthCalledWith(2, { + payload: { + id: 'test', + dataViewId: mockDataView.dataViewId, + indexNames: mockIndexNames, + }, + type: 'x-pack/security_solution/local/timeline/UPDATE_DATA_VIEW', + }); }); test(`it add attribute data-timeline-id in ${SELECTOR_TIMELINE_GLOBAL_CONTAINER}`, () => { diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/index.tsx index 48f9274fa563f..12bd3113f3ea7 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/index.tsx @@ -64,9 +64,16 @@ const StatefulTimelineComponent: React.FC = ({ const getTimeline = useMemo(() => timelineSelectors.getTimelineByIdSelector(), []); const { dataViewId, selectedPatterns } = useSourcererDataView(SourcererScopeName.timeline); - const { graphEventId, savedObjectId, timelineType, description } = useDeepEqualSelector((state) => + const { + dataViewId: dataViewIdCurrent, + indexNames: selectedPatternsCurrent, + graphEventId, + savedObjectId, + timelineType, + description, + } = useDeepEqualSelector((state) => pick( - ['graphEventId', 'savedObjectId', 'timelineType', 'description'], + ['indexNames', 'dataViewId', 'graphEventId', 'savedObjectId', 'timelineType', 'description'], getTimeline(state, timelineId) ?? timelineDefaults ) ); @@ -88,6 +95,38 @@ const StatefulTimelineComponent: React.FC = ({ // eslint-disable-next-line react-hooks/exhaustive-deps }, []); + const onDataViewChange = useCallback(() => { + if ( + // initial state will get set on create + (dataViewIdCurrent === '' && selectedPatternsCurrent.length === 0) || + // don't update if no change + (dataViewIdCurrent === dataViewId && + selectedPatternsCurrent.sort().join() === selectedPatterns.sort().join()) + ) { + return; + } + + dispatch( + timelineActions.updateDataView({ + id: timelineId, + dataViewId, + indexNames: selectedPatterns, + }) + ); + }, [ + dataViewId, + dataViewIdCurrent, + dispatch, + selectedPatterns, + selectedPatternsCurrent, + timelineId, + ]); + + useEffect(() => { + onDataViewChange(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [dataViewId, selectedPatterns]); + const onSkipFocusBeforeEventsTable = useCallback(() => { const exitFullScreenButton = containerElement.current?.querySelector( EXIT_FULL_SCREEN_CLASS_NAME From 5e90ec95f846e4864622e9bf282a87f72daa9b76 Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Thu, 18 Nov 2021 15:30:44 +0100 Subject: [PATCH 111/148] Lens tests: heatmap fix (#119010) --- .../shared_components/coloring/palette_panel_container.tsx | 1 + x-pack/test/functional/page_objects/lens_page.ts | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/lens/public/shared_components/coloring/palette_panel_container.tsx b/x-pack/plugins/lens/public/shared_components/coloring/palette_panel_container.tsx index b546ffe5fb6fb..abcd714b3af97 100644 --- a/x-pack/plugins/lens/public/shared_components/coloring/palette_panel_container.tsx +++ b/x-pack/plugins/lens/public/shared_components/coloring/palette_panel_container.tsx @@ -56,6 +56,7 @@ export function PalettePanelContainer({
    diff --git a/x-pack/test/functional/page_objects/lens_page.ts b/x-pack/test/functional/page_objects/lens_page.ts index 5b7136a8d677b..10a46207b5338 100644 --- a/x-pack/test/functional/page_objects/lens_page.ts +++ b/x-pack/test/functional/page_objects/lens_page.ts @@ -872,7 +872,12 @@ export function LensPageProvider({ getService, getPageObjects }: FtrProviderCont }, async openPalettePanel(chartType: string) { - await testSubjects.click(`${chartType}_dynamicColoring_trigger`); + await retry.try(async () => { + await testSubjects.click(`${chartType}_dynamicColoring_trigger`); + // wait for the UI to settle + await PageObjects.common.sleep(100); + await testSubjects.existOrFail('lns-indexPattern-PalettePanelContainer', { timeout: 2500 }); + }); }, async closePalettePanel() { From 12104d54c44327e52026d24a363caee09e89f551 Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Thu, 18 Nov 2021 15:30:56 +0100 Subject: [PATCH 112/148] Lens tests: increase window height to avoid scrolling (#119003) --- x-pack/test/functional/apps/lens/index.ts | 2 +- x-pack/test/functional/page_objects/lens_page.ts | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/x-pack/test/functional/apps/lens/index.ts b/x-pack/test/functional/apps/lens/index.ts index e63aadf3451d7..72442be7645fa 100644 --- a/x-pack/test/functional/apps/lens/index.ts +++ b/x-pack/test/functional/apps/lens/index.ts @@ -17,7 +17,7 @@ export default function ({ getService, loadTestFile, getPageObjects }: FtrProvid describe('lens app', () => { before(async () => { log.debug('Starting lens before method'); - await browser.setWindowSize(1280, 800); + await browser.setWindowSize(1280, 1200); await esArchiver.load('x-pack/test/functional/es_archives/logstash_functional'); // changing the timepicker default here saves us from having to set it in Discover (~8s) await PageObjects.timePicker.setDefaultAbsoluteRangeViaUiSettings(); diff --git a/x-pack/test/functional/page_objects/lens_page.ts b/x-pack/test/functional/page_objects/lens_page.ts index 10a46207b5338..78b9762e3889a 100644 --- a/x-pack/test/functional/page_objects/lens_page.ts +++ b/x-pack/test/functional/page_objects/lens_page.ts @@ -20,8 +20,6 @@ export function LensPageProvider({ getService, getPageObjects }: FtrProviderCont const browser = getService('browser'); const dashboardAddPanel = getService('dashboardAddPanel'); - const FORMULA_TAB_HEIGHT = 40; - const PageObjects = getPageObjects([ 'common', 'header', @@ -133,7 +131,7 @@ export function LensPageProvider({ getService, getPageObjects }: FtrProviderCont : `lns-indexPatternDimension-${opts.operation}`; async function getAriaPressed() { const operationSelectorContainer = await testSubjects.find(operationSelector); - await testSubjects.click(operationSelector, undefined, FORMULA_TAB_HEIGHT); + await testSubjects.click(operationSelector); const ariaPressed = await operationSelectorContainer.getAttribute('aria-pressed'); return ariaPressed; } From 8377a870c68d0b50b65f20b50ce1dc239bcb0d7e Mon Sep 17 00:00:00 2001 From: Andrew Tate Date: Thu, 18 Nov 2021 09:02:57 -0600 Subject: [PATCH 113/148] reset filter state whenever split_mode changed (#118953) --- .../application/components/splits/filter.js | 14 +++++++++++--- .../application/components/splits/filters.js | 13 ++++++++++--- .../public/application/components/splits/terms.js | 15 ++++++++++++++- 3 files changed, 35 insertions(+), 7 deletions(-) diff --git a/src/plugins/vis_types/timeseries/public/application/components/splits/filter.js b/src/plugins/vis_types/timeseries/public/application/components/splits/filter.js index 6324fff859d44..a53dc291fb6f0 100644 --- a/src/plugins/vis_types/timeseries/public/application/components/splits/filter.js +++ b/src/plugins/vis_types/timeseries/public/application/components/splits/filter.js @@ -6,7 +6,6 @@ * Side Public License, v 1. */ -import { createSelectHandler } from '../lib/create_select_handler'; import { GroupBySelect } from './group_by_select'; import PropTypes from 'prop-types'; import React from 'react'; @@ -15,12 +14,16 @@ import { FormattedMessage } from '@kbn/i18n/react'; import { getDefaultQueryLanguage } from '../lib/get_default_query_language'; import { QueryBarWrapper } from '../query_bar_wrapper'; +const RESET_STATE = { + filter: undefined, +}; + export const SplitByFilter = (props) => { const { onChange, uiRestrictions, indexPattern } = props; const defaults = { filter: { language: getDefaultQueryLanguage(), query: '' } }; const model = { ...defaults, ...props.model }; const htmlId = htmlIdGenerator(); - const handleSelectChange = createSelectHandler(onChange); + return ( @@ -35,7 +38,12 @@ export const SplitByFilter = (props) => { > { + onChange({ + split_mode: newSplitMode, + ...RESET_STATE, + }); + }} uiRestrictions={uiRestrictions} /> diff --git a/src/plugins/vis_types/timeseries/public/application/components/splits/filters.js b/src/plugins/vis_types/timeseries/public/application/components/splits/filters.js index 8c91d057ae341..edb1ce5927939 100644 --- a/src/plugins/vis_types/timeseries/public/application/components/splits/filters.js +++ b/src/plugins/vis_types/timeseries/public/application/components/splits/filters.js @@ -6,7 +6,6 @@ * Side Public License, v 1. */ -import { createSelectHandler } from '../lib/create_select_handler'; import { GroupBySelect } from './group_by_select'; import { FilterItems } from './filter_items'; import PropTypes from 'prop-types'; @@ -14,10 +13,13 @@ import React from 'react'; import { htmlIdGenerator, EuiFlexGroup, EuiFlexItem, EuiFormRow } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; +const RESET_STATE = { + split_filters: undefined, +}; + export const SplitByFilters = (props) => { const { onChange, model, uiRestrictions, indexPattern } = props; const htmlId = htmlIdGenerator(); - const handleSelectChange = createSelectHandler(onChange); return (
    @@ -33,7 +35,12 @@ export const SplitByFilters = (props) => { > { + onChange({ + split_mode: newSplitMode, + ...RESET_STATE, + }); + }} uiRestrictions={uiRestrictions} /> diff --git a/src/plugins/vis_types/timeseries/public/application/components/splits/terms.js b/src/plugins/vis_types/timeseries/public/application/components/splits/terms.js index b32af037533f7..8a85c9826e937 100644 --- a/src/plugins/vis_types/timeseries/public/application/components/splits/terms.js +++ b/src/plugins/vis_types/timeseries/public/application/components/splits/terms.js @@ -30,6 +30,14 @@ import { STACKED_OPTIONS } from '../../visualizations/constants'; import { getIndexPatternKey } from '../../../../common/index_patterns_utils'; const DEFAULTS = { terms_direction: 'desc', terms_size: 10, terms_order_by: '_count' }; +const RESET_STATE = { + terms_field: undefined, + terms_include: undefined, + terms_exclude: undefined, + terms_direction: undefined, + terms_size: undefined, + terms_order_by: undefined, +}; export const SplitByTermsUI = ({ onChange, @@ -106,7 +114,12 @@ export const SplitByTermsUI = ({ > { + onChange({ + split_mode: newSplitMode, + ...RESET_STATE, + }); + }} uiRestrictions={uiRestrictions} /> From 4d3d95afe9bab1eb2703345cf42cbd086906bd39 Mon Sep 17 00:00:00 2001 From: vladpro25 <91911546+vladpro25@users.noreply.github.com> Date: Thu, 18 Nov 2021 17:50:56 +0200 Subject: [PATCH 114/148] Autocomplete for t_test aggregation (#117782) * Autocomplete for t_test aggregation * Update aggregations.ts * Update aggregations.ts Co-authored-by: Alexey Antonov Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../lib/spec_definitions/js/aggregations.ts | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/plugins/console/server/lib/spec_definitions/js/aggregations.ts b/src/plugins/console/server/lib/spec_definitions/js/aggregations.ts index dfa263f2f1e65..d912b6d64c7a8 100644 --- a/src/plugins/console/server/lib/spec_definitions/js/aggregations.ts +++ b/src/plugins/console/server/lib/spec_definitions/js/aggregations.ts @@ -79,6 +79,26 @@ const rules = { }, }, }, + t_test: { + a: { + field: '{field}', + filter: { __scope_link: 'GLOBAL.filter' }, + }, + b: { + field: '{field}', + filter: { __scope_link: 'GLOBAL.filter' }, + }, + type: { __one_of: ['paired', 'homoscedastic', 'heteroscedastic'] }, + __template: { + a: { + field: '', + }, + b: { + field: '', + }, + type: '', + }, + }, adjacency_matrix: { filters: {}, }, From 617be5160ae779d5549c5ec5c60438fea7de2cee Mon Sep 17 00:00:00 2001 From: Ignacio Rivas Date: Thu, 18 Nov 2021 16:52:03 +0100 Subject: [PATCH 115/148] [Dev Tools] Change breadcrumbs and docTitle when toggling between apps (#117857) --- src/plugins/dev_tools/public/application.tsx | 64 +++++++++++-------- .../dev_tools/public/constants/texts.ts | 17 +++++ src/plugins/dev_tools/public/dev_tool.ts | 17 +++-- src/plugins/dev_tools/public/index.scss | 4 ++ src/plugins/dev_tools/public/plugin.ts | 22 ++++++- .../dev_tools/public/services/breadcrumb.ts | 32 ++++++++++ .../dev_tools/public/services/doc_title.ts | 31 +++++++++ .../dev_tools/public/services/index.ts | 10 +++ src/plugins/dev_tools/tsconfig.json | 3 +- x-pack/plugins/painless_lab/public/plugin.tsx | 26 ++------ .../painless_lab/public/styles/_index.scss | 4 -- .../translations/translations/ja-JP.json | 4 -- .../translations/translations/zh-CN.json | 4 -- .../functional/apps/dev_tools/breadcrumbs.ts | 54 ++++++++++++++++ .../test/functional/apps/dev_tools/index.ts | 3 +- 15 files changed, 228 insertions(+), 67 deletions(-) create mode 100644 src/plugins/dev_tools/public/constants/texts.ts create mode 100644 src/plugins/dev_tools/public/services/breadcrumb.ts create mode 100644 src/plugins/dev_tools/public/services/doc_title.ts create mode 100644 src/plugins/dev_tools/public/services/index.ts create mode 100644 x-pack/test/functional/apps/dev_tools/breadcrumbs.ts diff --git a/src/plugins/dev_tools/public/application.tsx b/src/plugins/dev_tools/public/application.tsx index 1eb4a5f4e99e8..9351cdcdf54bf 100644 --- a/src/plugins/dev_tools/public/application.tsx +++ b/src/plugins/dev_tools/public/application.tsx @@ -10,20 +10,27 @@ import React, { useEffect, useRef } from 'react'; import { Observable } from 'rxjs'; import ReactDOM from 'react-dom'; import { HashRouter as Router, Switch, Route, Redirect } from 'react-router-dom'; -import { EuiTab, EuiTabs, EuiToolTip } from '@elastic/eui'; +import { EuiTab, EuiTabs, EuiToolTip, EuiBetaBadge } from '@elastic/eui'; import { I18nProvider } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; import { euiThemeVars } from '@kbn/ui-shared-deps-src/theme'; import { ApplicationStart, ChromeStart, ScopedHistory, CoreTheme } from 'src/core/public'; +import type { DocTitleService, BreadcrumbService } from './services'; import { DevToolApp } from './dev_tool'; +export interface AppServices { + docTitleService: DocTitleService; + breadcrumbService: BreadcrumbService; +} + interface DevToolsWrapperProps { devTools: readonly DevToolApp[]; activeDevTool: DevToolApp; updateRoute: (newRoute: string) => void; theme$: Observable; + appServices: AppServices; } interface MountedDevToolDescriptor { @@ -32,7 +39,14 @@ interface MountedDevToolDescriptor { unmountHandler: () => void; } -function DevToolsWrapper({ devTools, activeDevTool, updateRoute, theme$ }: DevToolsWrapperProps) { +function DevToolsWrapper({ + devTools, + activeDevTool, + updateRoute, + theme$, + appServices, +}: DevToolsWrapperProps) { + const { docTitleService, breadcrumbService } = appServices; const mountedTool = useRef(null); useEffect( @@ -44,6 +58,11 @@ function DevToolsWrapper({ devTools, activeDevTool, updateRoute, theme$ }: DevTo [] ); + useEffect(() => { + docTitleService.setTitle(activeDevTool.title); + breadcrumbService.setBreadcrumbs(activeDevTool.title); + }, [activeDevTool, docTitleService, breadcrumbService]); + return (
    @@ -59,7 +78,21 @@ function DevToolsWrapper({ devTools, activeDevTool, updateRoute, theme$ }: DevTo }} > - {currentDevTool.title} + + {currentDevTool.title}{' '} + {currentDevTool.isBeta && ( + + )} + ))} @@ -127,40 +160,20 @@ function setBadge(application: ApplicationStart, chrome: ChromeStart) { }); } -function setTitle(chrome: ChromeStart) { - chrome.docTitle.change( - i18n.translate('devTools.pageTitle', { - defaultMessage: 'Dev Tools', - }) - ); -} - -function setBreadcrumbs(chrome: ChromeStart) { - chrome.setBreadcrumbs([ - { - text: i18n.translate('devTools.k7BreadcrumbsDevToolsLabel', { - defaultMessage: 'Dev Tools', - }), - href: '#/', - }, - ]); -} - export function renderApp( element: HTMLElement, application: ApplicationStart, chrome: ChromeStart, history: ScopedHistory, theme$: Observable, - devTools: readonly DevToolApp[] + devTools: readonly DevToolApp[], + appServices: AppServices ) { if (redirectOnMissingCapabilities(application)) { return () => {}; } setBadge(application, chrome); - setBreadcrumbs(chrome); - setTitle(chrome); ReactDOM.render( @@ -180,6 +193,7 @@ export function renderApp( activeDevTool={devTool} devTools={devTools} theme$={theme$} + appServices={appServices} /> )} /> diff --git a/src/plugins/dev_tools/public/constants/texts.ts b/src/plugins/dev_tools/public/constants/texts.ts new file mode 100644 index 0000000000000..12f27c5904efd --- /dev/null +++ b/src/plugins/dev_tools/public/constants/texts.ts @@ -0,0 +1,17 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { i18n } from '@kbn/i18n'; + +export const i18Texts = { + breadcrumbs: { + home: i18n.translate('devTools.breadcrumb.homeLabel', { + defaultMessage: 'Dev Tools', + }), + }, +}; diff --git a/src/plugins/dev_tools/public/dev_tool.ts b/src/plugins/dev_tools/public/dev_tool.ts index 8adfd4c76482d..a2e32d43a60c7 100644 --- a/src/plugins/dev_tools/public/dev_tool.ts +++ b/src/plugins/dev_tools/public/dev_tool.ts @@ -6,7 +6,6 @@ * Side Public License, v 1. */ -import { ReactNode } from 'react'; import { AppMount } from 'src/core/public'; /** @@ -29,9 +28,14 @@ export class DevToolApp { * This will be used as a label in the tab above the actual tool. * May also be a ReactNode. */ - public readonly title: ReactNode; + public readonly title: string; public readonly mount: AppMount; + /** + * Mark the navigation tab as beta. + */ + public readonly isBeta?: boolean; + /** * Flag indicating to disable the tab of this dev tool. Navigating to a * disabled dev tool will be treated as the navigation to an unknown route @@ -57,12 +61,13 @@ export class DevToolApp { constructor( id: string, - title: ReactNode, + title: string, mount: AppMount, enableRouting: boolean, order: number, toolTipContent = '', - disabled = false + disabled = false, + isBeta?: boolean ) { this.id = id; this.title = title; @@ -71,6 +76,7 @@ export class DevToolApp { this.order = order; this.tooltipContent = toolTipContent; this.disabled = disabled; + this.isBeta = isBeta; } public enable() { @@ -94,5 +100,6 @@ export const createDevToolApp = ({ order, tooltipContent, disabled, + isBeta, }: CreateDevToolArgs) => - new DevToolApp(id, title, mount, enableRouting, order, tooltipContent, disabled); + new DevToolApp(id, title, mount, enableRouting, order, tooltipContent, disabled, isBeta); diff --git a/src/plugins/dev_tools/public/index.scss b/src/plugins/dev_tools/public/index.scss index 4bec602ea42db..a00084972c0ea 100644 --- a/src/plugins/dev_tools/public/index.scss +++ b/src/plugins/dev_tools/public/index.scss @@ -21,3 +21,7 @@ flex-direction: column; flex-grow: 1; } + +.devApp__tabBeta { + vertical-align: middle; +} diff --git a/src/plugins/dev_tools/public/plugin.ts b/src/plugins/dev_tools/public/plugin.ts index e45e73c4b1b40..1876bf278513e 100644 --- a/src/plugins/dev_tools/public/plugin.ts +++ b/src/plugins/dev_tools/public/plugin.ts @@ -15,6 +15,7 @@ import { sortBy } from 'lodash'; import { AppNavLinkStatus, DEFAULT_APP_CATEGORIES } from '../../../core/public'; import { UrlForwardingSetup } from '../../url_forwarding/public'; import { CreateDevToolArgs, DevToolApp, createDevToolApp } from './dev_tool'; +import { DocTitleService, BreadcrumbService } from './services'; import './index.scss'; @@ -36,6 +37,9 @@ export class DevToolsPlugin implements Plugin { private readonly devTools = new Map(); private appStateUpdater = new BehaviorSubject(() => ({})); + private breadcrumbService = new BreadcrumbService(); + private docTitleService = new DocTitleService(); + private getSortedDevTools(): readonly DevToolApp[] { return sortBy([...this.devTools.values()], 'order'); } @@ -59,8 +63,24 @@ export class DevToolsPlugin implements Plugin { const [core] = await getStartServices(); const { application, chrome } = core; + this.docTitleService.setup(chrome.docTitle.change); + this.breadcrumbService.setup(chrome.setBreadcrumbs); + + const appServices = { + breadcrumbService: this.breadcrumbService, + docTitleService: this.docTitleService, + }; + const { renderApp } = await import('./application'); - return renderApp(element, application, chrome, history, theme$, this.getSortedDevTools()); + return renderApp( + element, + application, + chrome, + history, + theme$, + this.getSortedDevTools(), + appServices + ); }, }); diff --git a/src/plugins/dev_tools/public/services/breadcrumb.ts b/src/plugins/dev_tools/public/services/breadcrumb.ts new file mode 100644 index 0000000000000..c12aa7e8ceef2 --- /dev/null +++ b/src/plugins/dev_tools/public/services/breadcrumb.ts @@ -0,0 +1,32 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { ManagementAppMountParams } from '../../../management/public'; +import { i18Texts } from '../constants/texts'; + +export type SetBreadcrumbs = ManagementAppMountParams['setBreadcrumbs']; + +export class BreadcrumbService { + private setBreadcrumbsHandler?: SetBreadcrumbs; + + public setup(setBreadcrumbsHandler: SetBreadcrumbs): void { + this.setBreadcrumbsHandler = setBreadcrumbsHandler; + } + + public setBreadcrumbs(page: string): void { + if (!this.setBreadcrumbsHandler) { + throw new Error('Breadcrumb service has not been initialized'); + } + + if (!page || page === 'home') { + this.setBreadcrumbsHandler([{ text: i18Texts.breadcrumbs.home }]); + } else { + this.setBreadcrumbsHandler([{ text: i18Texts.breadcrumbs.home, href: '#/' }, { text: page }]); + } + } +} diff --git a/src/plugins/dev_tools/public/services/doc_title.ts b/src/plugins/dev_tools/public/services/doc_title.ts new file mode 100644 index 0000000000000..abe9b1ece6b24 --- /dev/null +++ b/src/plugins/dev_tools/public/services/doc_title.ts @@ -0,0 +1,31 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { i18Texts } from '../constants/texts'; + +type ChangeDocTitleHandler = (newTitle: string | string[]) => void; + +export class DocTitleService { + private changeDocTitleHandler: ChangeDocTitleHandler = () => {}; + + public setup(_changeDocTitleHandler: ChangeDocTitleHandler): void { + this.changeDocTitleHandler = _changeDocTitleHandler; + } + + public setTitle(page: string): void { + if (!this.changeDocTitleHandler) { + throw new Error('DocTitle service has not been initialized'); + } + + if (!page || page === 'home') { + this.changeDocTitleHandler(i18Texts.breadcrumbs.home); + } else { + this.changeDocTitleHandler(`${page} - ${i18Texts.breadcrumbs.home}`); + } + } +} diff --git a/src/plugins/dev_tools/public/services/index.ts b/src/plugins/dev_tools/public/services/index.ts new file mode 100644 index 0000000000000..283ec44e41097 --- /dev/null +++ b/src/plugins/dev_tools/public/services/index.ts @@ -0,0 +1,10 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export { DocTitleService } from './doc_title'; +export { BreadcrumbService } from './breadcrumb'; diff --git a/src/plugins/dev_tools/tsconfig.json b/src/plugins/dev_tools/tsconfig.json index bbb33ac5b2f99..df16711f6ea50 100644 --- a/src/plugins/dev_tools/tsconfig.json +++ b/src/plugins/dev_tools/tsconfig.json @@ -9,6 +9,7 @@ "include": ["public/**/*"], "references": [ { "path": "../../core/tsconfig.json" }, - { "path": "../url_forwarding/tsconfig.json" } + { "path": "../url_forwarding/tsconfig.json" }, + { "path": "../../../src/plugins/management/tsconfig.json" } ] } diff --git a/x-pack/plugins/painless_lab/public/plugin.tsx b/x-pack/plugins/painless_lab/public/plugin.tsx index 118adae22dc50..793947b9803c9 100644 --- a/x-pack/plugins/painless_lab/public/plugin.tsx +++ b/x-pack/plugins/painless_lab/public/plugin.tsx @@ -5,9 +5,7 @@ * 2.0. */ -import React from 'react'; import { first } from 'rxjs/operators'; -import { EuiBetaBadge, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { Plugin, CoreSetup } from 'src/core/public'; @@ -46,26 +44,10 @@ export class PainlessLabUIPlugin implements Plugin - - {i18n.translate('xpack.painlessLab.displayName', { - defaultMessage: 'Painless Lab', - })} - - - - - - - ) as any, + isBeta: true, + title: i18n.translate('xpack.painlessLab.displayName', { + defaultMessage: 'Painless Lab', + }), enableRouting: false, disabled: false, mount: async ({ element }) => { diff --git a/x-pack/plugins/painless_lab/public/styles/_index.scss b/x-pack/plugins/painless_lab/public/styles/_index.scss index 78182787a63b6..4844fe443e56f 100644 --- a/x-pack/plugins/painless_lab/public/styles/_index.scss +++ b/x-pack/plugins/painless_lab/public/styles/_index.scss @@ -34,10 +34,6 @@ $bottomBarHeight: $euiSize * 3; } } -.painlessLab__betaLabelContainer { - line-height: 0; -} - // adding dev tool top bar + bottom bar height to the body offset $bodyOffset: $euiHeaderHeightCompensation + $bottomBarHeight; diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index af76ea0e98276..c02cec2b26106 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -2280,8 +2280,6 @@ "devTools.badge.readOnly.text": "読み取り専用", "devTools.badge.readOnly.tooltip": "を保存できませんでした", "devTools.devToolsTitle": "開発ツール", - "devTools.k7BreadcrumbsDevToolsLabel": "開発ツール", - "devTools.pageTitle": "開発ツール", "discover.advancedSettings.context.defaultSizeText": "コンテキストビューに表示される周りのエントリーの数", "discover.advancedSettings.context.defaultSizeTitle": "コンテキストサイズ", "discover.advancedSettings.context.sizeStepText": "コンテキストサイズを増減させる際の最低単位です", @@ -18798,8 +18796,6 @@ "xpack.painlessLab.contextScoreLabel": "スコア", "xpack.painlessLab.contextTabLabel": "コンテキスト", "xpack.painlessLab.displayName": "Painless Lab", - "xpack.painlessLab.displayNameBetaLabel": "ベータ", - "xpack.painlessLab.displayNameBetaTooltipText": "この機能は将来のリリースで大幅に変更される可能性があります", "xpack.painlessLab.documentFieldLabel": "サンプルドキュメント(JSON)", "xpack.painlessLab.documentFieldTooltipText": "スクリプトでこのドキュメントのフィールドにアクセスできます", "xpack.painlessLab.flyoutDocLink": "API ドキュメンテーション", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 91513909af9c7..879e57fae4eb6 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -2302,8 +2302,6 @@ "devTools.badge.readOnly.text": "只读", "devTools.badge.readOnly.tooltip": "无法保存", "devTools.devToolsTitle": "开发工具", - "devTools.k7BreadcrumbsDevToolsLabel": "开发工具", - "devTools.pageTitle": "开发工具", "discover.advancedSettings.context.defaultSizeText": "要在上下文视图中显示的周围条目数目", "discover.advancedSettings.context.defaultSizeTitle": "上下文大小", "discover.advancedSettings.context.sizeStepText": "递增或递减上下文大小的步进大小", @@ -19072,8 +19070,6 @@ "xpack.painlessLab.contextScoreLabel": "分数", "xpack.painlessLab.contextTabLabel": "上下文", "xpack.painlessLab.displayName": "Painless 实验室", - "xpack.painlessLab.displayNameBetaLabel": "公测版", - "xpack.painlessLab.displayNameBetaTooltipText": "此功能在未来的版本中可能会变化很大", "xpack.painlessLab.documentFieldLabel": "样例文档 (JSON)", "xpack.painlessLab.documentFieldTooltipText": "您的脚本可以访问此文档的字段", "xpack.painlessLab.flyoutDocLink": "API 文档", diff --git a/x-pack/test/functional/apps/dev_tools/breadcrumbs.ts b/x-pack/test/functional/apps/dev_tools/breadcrumbs.ts new file mode 100644 index 0000000000000..c41e75c45fd43 --- /dev/null +++ b/x-pack/test/functional/apps/dev_tools/breadcrumbs.ts @@ -0,0 +1,54 @@ +/* + * 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 expect from '@kbn/expect'; +import { FtrProviderContext } from '../../ftr_provider_context'; + +export default function ({ getPageObjects, getService }: FtrProviderContext) { + const PageObjects = getPageObjects(['common']); + const testSubjects = getService('testSubjects'); + const security = getService('security'); + + describe('Breadcrumbs', () => { + before(async () => { + await security.testUser.setRoles(['global_devtools_read']); + await PageObjects.common.navigateToApp('searchProfiler'); + }); + + after(async () => { + await security.testUser.restoreDefaults(); + }); + + it('Sets the right breadcrumbs when navigating to console app', async () => { + await PageObjects.common.navigateToApp('dev_tools'); + + const lastBreadcrumbdcrumb = await testSubjects.getVisibleText('breadcrumb last'); + expect(lastBreadcrumbdcrumb).to.be('Console'); + }); + + it('Sets the right breadcrumbs when navigating to grok debugger app', async () => { + await PageObjects.common.navigateToApp('grokDebugger'); + + const lastBreadcrumb = await testSubjects.getVisibleText('breadcrumb last'); + expect(lastBreadcrumb).to.be('Grok Debugger'); + }); + + it('Sets the right breadcrumbs when navigating to search profiler app', async () => { + await PageObjects.common.navigateToApp('searchProfiler'); + + const lastBreadcrumb = await testSubjects.getVisibleText('breadcrumb last'); + expect(lastBreadcrumb).to.be('Search Profiler'); + }); + + it('Sets the right breadcrumbs when navigating to painless lab app', async () => { + await PageObjects.common.navigateToApp('painlessLab'); + + const lastBreadcrumb = await testSubjects.getVisibleText('breadcrumb last'); + expect(lastBreadcrumb).to.be('Painless Lab'); + }); + }); +} diff --git a/x-pack/test/functional/apps/dev_tools/index.ts b/x-pack/test/functional/apps/dev_tools/index.ts index 87904a5ab8cb8..4f0e9290cc25e 100644 --- a/x-pack/test/functional/apps/dev_tools/index.ts +++ b/x-pack/test/functional/apps/dev_tools/index.ts @@ -8,9 +8,10 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { - describe('console', function () { + describe('Dev Tools', function () { this.tags('ciGroup13'); + loadTestFile(require.resolve('./breadcrumbs')); loadTestFile(require.resolve('./feature_controls')); loadTestFile(require.resolve('./searchprofiler_editor')); }); From a578beaff5cbd1e39e3ac3fa662d1edaa1eb9817 Mon Sep 17 00:00:00 2001 From: Adam Locke Date: Thu, 18 Nov 2021 11:41:56 -0500 Subject: [PATCH 116/148] [DOCS] Update Kibana install docs for security ON by default Beta (#118770) * [DOCS] Update install docs for security ON by default * Incorporating reviewer feedback and expanding RPM + Debian steps * Update Debian and RPM enrollment token process --- docs/setup/install/auto-enroll.asciidoc | 21 ++++++++++++++++ docs/setup/install/deb.asciidoc | 24 +++++++++++++++++++ docs/setup/install/rpm.asciidoc | 24 +++++++++++++++++++ .../install/start-es-and-enroll.asciidoc | 16 +++++++++++++ docs/setup/install/systemd.asciidoc | 8 +++---- docs/setup/install/targz-running.asciidoc | 2 ++ docs/setup/install/targz.asciidoc | 2 ++ docs/setup/install/windows-running.asciidoc | 2 ++ docs/setup/install/windows.asciidoc | 3 +++ 9 files changed, 98 insertions(+), 4 deletions(-) create mode 100644 docs/setup/install/auto-enroll.asciidoc create mode 100644 docs/setup/install/start-es-and-enroll.asciidoc diff --git a/docs/setup/install/auto-enroll.asciidoc b/docs/setup/install/auto-enroll.asciidoc new file mode 100644 index 0000000000000..0f9f9e2d8a929 --- /dev/null +++ b/docs/setup/install/auto-enroll.asciidoc @@ -0,0 +1,21 @@ +[role="exclude"] + +If this is the first time you're starting {kib}, this command generates a +unique link in your terminal to enroll your {kib} instance with {es}. + +. In your terminal, click the generated link to open {kib} in your browser. + +. In your browser, paste the enrollment token that was generated in the terminal +when you started {es}, and then click the button to connect your {kib} instance with {es}. + +. Log in to {kib} as the `elastic` user with the password that was +generated when you started {es}. + +[NOTE] +==== +If you need to reset the password for the `elastic` user or other +built-in users, run the {ref}/reset-password.html[`elasticsearch-reset-password`] tool. To generate new enrollment tokens for +{kib} or {es} nodes, run the +{ref}/create-enrollment-token.html[`elasticsearch-create-enrollment-token`] tool. +These tools are available in the {es} `bin` directory. +==== \ No newline at end of file diff --git a/docs/setup/install/deb.asciidoc b/docs/setup/install/deb.asciidoc index a229426185200..3f600d7c2bdbc 100644 --- a/docs/setup/install/deb.asciidoc +++ b/docs/setup/install/deb.asciidoc @@ -122,6 +122,30 @@ sudo dpkg -i kibana-{version}-amd64.deb endif::[] +[[deb-enroll]] +==== Start {es} and generate an enrollment token for {kib} +++++ +Generate an enrollment token +++++ + +When you start {es} for the first time, the following security configuration +occurs automatically: + +* Authentication and authorization are enabled, and a password is generated for the `elastic` built-in superuser. +* Certificates and keys for TLS are generated for the transport and HTTP layer, and TLS is enabled and configured with these keys and certificates. + +The password and certificate and keys are output to your terminal. + +You can then generate an enrollment token for {kib} with the +{ref}/create-enrollment-token.html[`elasticsearch-create-enrollment-token`] tool: + +[source,sh] +---- +bin/elasticsearch-create-enrollment-token -s kibana +---- + +Start {kib} and enter the enrollment token to securely connect {kib} with {es}. + [[deb-running-systemd]] include::systemd.asciidoc[] diff --git a/docs/setup/install/rpm.asciidoc b/docs/setup/install/rpm.asciidoc index a87d2f89b6ddb..329af9af0ccf7 100644 --- a/docs/setup/install/rpm.asciidoc +++ b/docs/setup/install/rpm.asciidoc @@ -115,6 +115,30 @@ sudo rpm --install kibana-{version}-x86_64.rpm endif::[] +[[rpm-enroll]] +==== Start {es} and generate an enrollment token for {kib} +++++ +Generate an enrollment token +++++ + +When you start {es} for the first time, the following security configuration +occurs automatically: + +* Authentication and authorization are enabled, and a password is generated for the `elastic` built-in superuser. +* Certificates and keys for TLS are generated for the transport and HTTP layer, and TLS is enabled and configured with these keys and certificates. + +The password and certificate and keys are output to your terminal. + +You can then generate an enrollment token for {kib} with the +{ref}/create-enrollment-token.html[`elasticsearch-create-enrollment-token`] tool: + +[source,sh] +---- +bin/elasticsearch-create-enrollment-token -s kibana +---- + +Start {kib} and enter the enrollment token to securely connect {kib} with {es}. + [[rpm-running-systemd]] include::systemd.asciidoc[] diff --git a/docs/setup/install/start-es-and-enroll.asciidoc b/docs/setup/install/start-es-and-enroll.asciidoc new file mode 100644 index 0000000000000..25541ec4aa993 --- /dev/null +++ b/docs/setup/install/start-es-and-enroll.asciidoc @@ -0,0 +1,16 @@ +==== Start {es} and generate an enrollment token for {kib} +++++ +Generate an enrollment token +++++ + +When you start {es} for the first time, the following security configuration +occurs automatically: + +* {ref}/configuring-stack-security.html#stack-security-certificates[Certificates and keys] for TLS are +generated for the transport and HTTP layers. +* The TLS configuration settings are written to `elasticsearch.yml`. +* A password is generated for the `elastic` user. +* An enrollment token is generated for {kib}. + +You can then start {kib} and enter the enrollment token to securely connect +{kib} with {es}. The enrollment token is valid for 30 minutes. \ No newline at end of file diff --git a/docs/setup/install/systemd.asciidoc b/docs/setup/install/systemd.asciidoc index 6fcb82217affc..125626e314241 100644 --- a/docs/setup/install/systemd.asciidoc +++ b/docs/setup/install/systemd.asciidoc @@ -1,6 +1,6 @@ ==== Run {kib} with `systemd` -To configure Kibana to start automatically when the system boots up, +To configure {kib} to start automatically when the system starts, run the following commands: [source,sh] @@ -9,7 +9,7 @@ sudo /bin/systemctl daemon-reload sudo /bin/systemctl enable kibana.service -------------------------------------------------- -Kibana can be started and stopped as follows: +{kib} can be started and stopped as follows: [source,sh] -------------------------------------------- @@ -17,6 +17,6 @@ sudo systemctl start kibana.service sudo systemctl stop kibana.service -------------------------------------------- -These commands provide no feedback as to whether Kibana was started +These commands provide no feedback as to whether {kib} was started successfully or not. Log information can be accessed via -`journalctl -u kibana.service`. +`journalctl -u kibana.service`. \ No newline at end of file diff --git a/docs/setup/install/targz-running.asciidoc b/docs/setup/install/targz-running.asciidoc index d3813d9811b13..40a2626cdd73a 100644 --- a/docs/setup/install/targz-running.asciidoc +++ b/docs/setup/install/targz-running.asciidoc @@ -9,3 +9,5 @@ Kibana can be started from the command line as follows: By default, Kibana runs in the foreground, prints its logs to the standard output (`stdout`), and can be stopped by pressing *Ctrl-C*. + +include::auto-enroll.asciidoc[] diff --git a/docs/setup/install/targz.asciidoc b/docs/setup/install/targz.asciidoc index 104ac335b5232..d9849811a7455 100644 --- a/docs/setup/install/targz.asciidoc +++ b/docs/setup/install/targz.asciidoc @@ -90,6 +90,8 @@ cd kibana-{version}/ <2> endif::[] +[[targz-enroll]] +include::start-es-and-enroll.asciidoc[] [[targz-running]] include::targz-running.asciidoc[] diff --git a/docs/setup/install/windows-running.asciidoc b/docs/setup/install/windows-running.asciidoc index 832284edc8f39..aabde22d66d16 100644 --- a/docs/setup/install/windows-running.asciidoc +++ b/docs/setup/install/windows-running.asciidoc @@ -9,3 +9,5 @@ Kibana can be started from the command line as follows: By default, Kibana runs in the foreground, prints its logs to `STDOUT`, and can be stopped by pressing *Ctrl-C*. + +include::auto-enroll.asciidoc[] \ No newline at end of file diff --git a/docs/setup/install/windows.asciidoc b/docs/setup/install/windows.asciidoc index 4138fc1886a6c..352a327e61195 100644 --- a/docs/setup/install/windows.asciidoc +++ b/docs/setup/install/windows.asciidoc @@ -40,6 +40,9 @@ CD c:\kibana-{version}-windows-x86_64 endif::[] +[[windows-enroll]] +include::start-es-and-enroll.asciidoc[] + [[windows-running]] include::windows-running.asciidoc[] From d370050b5e836bf6d8b4020ccebfac059fed11f0 Mon Sep 17 00:00:00 2001 From: vladpro25 <91911546+vladpro25@users.noreply.github.com> Date: Thu, 18 Nov 2021 19:24:33 +0200 Subject: [PATCH 117/148] Add Autocompletion for boxplot aggregation in Kibana Dev tools (#117024) * Add autocompletion for boxplot aggregation * Update aggregations.ts * Add Autocompletion for boxplot aggregation in Kibana Dev tools Co-authored-by: Alexey Antonov Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../server/lib/spec_definitions/js/aggregations.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/plugins/console/server/lib/spec_definitions/js/aggregations.ts b/src/plugins/console/server/lib/spec_definitions/js/aggregations.ts index d912b6d64c7a8..fc9e66e17685c 100644 --- a/src/plugins/console/server/lib/spec_definitions/js/aggregations.ts +++ b/src/plugins/console/server/lib/spec_definitions/js/aggregations.ts @@ -79,6 +79,14 @@ const rules = { }, }, }, + boxplot: { + __template: { + field: '', + }, + field: '{field}', + compression: 100, + missing: 0, + }, t_test: { a: { field: '{field}', From eb7f525b2ec0a73021c385311f75d79588e74500 Mon Sep 17 00:00:00 2001 From: Chenhui Wang <54903978+wangch079@users.noreply.github.com> Date: Fri, 19 Nov 2021 02:04:19 +0800 Subject: [PATCH 118/148] Add DLP option for Dropbox/GitHub/GitHub Enterprise Server (#118992) * Add DLP option for Dropbox/GitHub/GitHub Enterprise Server * commit using @elastic.co Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../workplace_search/views/content_sources/source_data.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_data.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_data.tsx index 3ff21566cf916..687461296ac9e 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_data.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_data.tsx @@ -180,6 +180,7 @@ export const staticSourceData = [ FeatureIds.SyncedItems, FeatureIds.GlobalAccessPermissions, ], + basicOrgContextExcludedFeatures: [FeatureIds.DocumentLevelPermissions], platinumOrgContext: [FeatureIds.SyncFrequency, FeatureIds.SyncedItems], platinumPrivateContext: [ FeatureIds.Private, @@ -215,6 +216,7 @@ export const staticSourceData = [ FeatureIds.SyncedItems, FeatureIds.GlobalAccessPermissions, ], + basicOrgContextExcludedFeatures: [FeatureIds.DocumentLevelPermissions], platinumOrgContext: [FeatureIds.SyncFrequency, FeatureIds.SyncedItems], platinumPrivateContext: [ FeatureIds.Private, @@ -256,6 +258,7 @@ export const staticSourceData = [ FeatureIds.SyncedItems, FeatureIds.GlobalAccessPermissions, ], + basicOrgContextExcludedFeatures: [FeatureIds.DocumentLevelPermissions], platinumOrgContext: [FeatureIds.SyncFrequency, FeatureIds.SyncedItems], platinumPrivateContext: [ FeatureIds.Private, From 769e490a5bd4816c80737b208bc7e6bc7e6d9297 Mon Sep 17 00:00:00 2001 From: Yuliia Naumenko Date: Thu, 18 Nov 2021 10:14:03 -0800 Subject: [PATCH 119/148] [Alerting][Docs] Fix rule types categorization (#118285) * [Alerting][Docs] Fix rule types categorization * fixed links * fixed separator * Apply suggestions from code review Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> * fixed due to comments * fixed due to comments * fixed due to comments * Apply suggestions from code review Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> * fixed due to comments * Update docs/user/alerting/rule-types.asciidoc Co-authored-by: ymao1 * fixed due to comments Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> Co-authored-by: ymao1 --- .../alerting-getting-started.asciidoc | 4 +- docs/user/alerting/rule-types.asciidoc | 54 +++++++++++++------ 2 files changed, 39 insertions(+), 19 deletions(-) diff --git a/docs/user/alerting/alerting-getting-started.asciidoc b/docs/user/alerting/alerting-getting-started.asciidoc index b53788b518fa0..80ad1bb630f53 100644 --- a/docs/user/alerting/alerting-getting-started.asciidoc +++ b/docs/user/alerting/alerting-getting-started.asciidoc @@ -24,7 +24,7 @@ This section describes all of these elements and how they operate together. [float] === Rules -A rule specifies a background task that runs on the {kib} server to check for specific conditions. {kib} provides two types of rules: stack rules that are built into {kib} and domain rules that are registered by Kibana apps. Refer to <> for more information. +A rule specifies a background task that runs on the {kib} server to check for specific conditions. {kib} provides two types of rules: stack rules that are built into {kib} and the rules that are registered by Kibana apps. Refer to <> for more information. A rule consists of three main parts: @@ -53,7 +53,7 @@ to control the details of the conditions to detect. For example, an <> lets you specify the index to query, an aggregation field, and a time window, but the details of the underlying {es} query are hidden. -See <> and <> for the types of rules provided by {kib} and how they express their conditions. +See <> for the rules provided by {kib} and how they express their conditions. [float] [[alerting-concepts-scheduling]] diff --git a/docs/user/alerting/rule-types.asciidoc b/docs/user/alerting/rule-types.asciidoc index ab2349f2fb102..324347f3b2648 100644 --- a/docs/user/alerting/rule-types.asciidoc +++ b/docs/user/alerting/rule-types.asciidoc @@ -2,7 +2,8 @@ [[rule-types]] == Rule types -A rule is a set of <>, <>, and <> that enable notifications. {kib} provides two types of rules: rules specific to the Elastic Stack and rules specific to a domain. +A rule is a set of <>, <>, and <> that enable notifications. {kib} provides rules built into the Elastic Stack and rules registered by one of the {kib} apps. +You can create most rules types in < Rules and Connectors>>. For information on creating security rules, refer to {security-guide}/rules-ui-create.html[Create a detection rule]. [NOTE] ============================================== @@ -15,45 +16,64 @@ see {subscriptions}[the subscription page]. [[stack-rules]] === Stack rules -<> are built into {kib}. To access the *Stack Rules* feature and create and edit rules, users require the `all` privilege. See <> for more information. +<> are built into {kib}. To access the *Stack Rules* feature and create and edit rules, users require the `all` privilege. See <> for more information. [cols="2*<"] |=== -| <> -| Aggregate field values from documents using {es} queries, compare them to threshold values, and schedule actions to run when the thresholds are met. - | <> | Run a user-configured {es} query, compare the number of matches to a configured threshold, and schedule actions to run when the threshold condition is met. -| {ref}/transform-alerts.html[{transform-cap} rules] beta:[] +| <> +| Aggregate field values from documents using {es} queries, compare them to threshold values, and schedule actions to run when the thresholds are met. + +| {ref}/transform-alerts.html[{transform-cap} rules] | beta:[] Run scheduled checks on a {ctransform} to check its health. If a {ctransform} meets the conditions, an alert is created and the associated action is triggered. +| <> +| Run an {es} query to determine if any documents are currently contained in any boundaries from a specified boundary index and generate alerts when a rule's conditions are met. + |=== [float] -[[domain-specific-rules]] -=== Domain rules +[[observability-rules]] +=== Observability rules -Domain rules are registered by *Observability*, *Security*, <> and <>. +Observability rules are categorized into APM and User Experience, Logs, Metrics, Stack Monitoring, and Uptime. [cols="2*<"] |=== -| {observability-guide}/create-alerts.html[Observability rules] -| Detect complex conditions in the *Logs*, *Metrics*, and *Uptime* apps. -| {security-guide}/prebuilt-rules.html[Security rules] -| Detect suspicious source events with pre-built or custom rules and create alerts when a rule’s conditions are met. +| <> +| Detect complex conditions in *APM* data and trigger built-in actions when the conditions are met. -| <> -| Run an {es} query to determine if any documents are currently contained in any boundaries from a specified boundary index and generate alerts when a rule's conditions are met. +| {observability-guide}/create-alerts.html[Logs rules] +| Detect complex conditions in the *Logs* app. -| {ml-docs}/ml-configuring-alerts.html[{ml-cap} rules] beta:[] -| beta:[] Run scheduled checks on an {anomaly-job} to detect anomalies with certain conditions. If an anomaly meets the conditions, an alert is created and the associated action is triggered. +| {observability-guide}/create-alerts.html[Metrics rules] +| Detect complex conditions in the *Metrics* app. + +| <> +| Provide {kib} Alerting rules out-of-the box to notify you of potential issues in the Elastic Stack. + +| {observability-guide}/create-alerts.html[Uptime rules] +| Detect complex conditions in the *Uptime* app. |=== +[float] +[[ml-rules]] +=== Machine learning rules + +beta:[] {ml-docs}/ml-configuring-alerts.html[{ml-cap} rules] run scheduled checks on an {anomaly-job} to detect anomalies with certain conditions. If an anomaly meets the conditions, an alert is created and the associated action is triggered. + +[float] +[[security-rules]] +=== Security rules + +Security rules detect suspicious source events with pre-built or custom rules and create alerts when a rule’s conditions are met. For more information, refer to {security-guide}/prebuilt-rules.html[Security rules]. + include::rule-types/index-threshold.asciidoc[] include::rule-types/es-query.asciidoc[] include::rule-types/geo-rule-types.asciidoc[] From cd8c648012f1b51d897e287a9667f19bda6bcddc Mon Sep 17 00:00:00 2001 From: Greg Thompson Date: Thu, 18 Nov 2021 12:29:51 -0600 Subject: [PATCH 120/148] Upgrade EUI to v41.0.0 (#117242) * eui to v41.0.0 * update eui i18n tokens * sass tokens * EuiLoadingKibana * EuiCodeEditor * subdued * betaBadgeProps * EuiCodeEditor null-loader * src secondary -> success * [enterprise_search] Deprecate 'secondary' color prop * [apm] Deprecate 'secondary' color prop * [canvas] Deprecate 'secondary' color prop * [cases] Deprecate 'secondary' color prop * [cross_cluster_replication] Deprecate 'secondary' color prop * [data_enhanced] Deprecate 'secondary' color prop * [data_visualizer] Deprecate 'secondary' color prop * [fleet] Deprecate 'secondary' color prop * [index_management] Deprecate 'secondary' color prop * [infra] Deprecate 'secondary' color prop * [ingest_pipelines] Deprecate 'secondary' color prop * [maps] Deprecate 'secondary' color prop * [ml] Deprecate 'secondary' color prop * [monitoring] Deprecate 'secondary' color prop * [observability] Deprecate 'secondary' color prop NB: conditional became `type === 'success' ? 'success' : type` after find&replace, which felt fairly redundant, so I simplified it * [osquery] Deprecate 'secondary' color prop * [painless_lab] Deprecate 'secondary' color prop * [remote_clusters] Deprecate 'secondary' color prop * [rollup] Deprecate 'secondary' color prop * [security] Deprecate 'secondary' color prop * [security_solution] Deprecate 'secondary' color prop NB: several conditional became `type === 'success' ? 'success' : type` after find&replace, which felt fairly redundant, so I simplified them * [snapshot_restore] Deprecate 'secondary' color prop * [spaces] Deprecate 'secondary' color prop * [transform] Deprecate 'secondary' color prop * [triggers_actions_ui] Deprecate 'secondary' color prop * [uptime] Deprecate 'secondary' color prop * [watcher] Deprecate 'secondary' color prop * [infra] replace ambiguous 'secondary' color - GaugesSectionVis doesn't appear to use the color property but it's required by the SeriesOverrides types, so changing it just in case * [examples] Deprecate 'secondary' color prop * [uptime] deprecate 'subdued' prop on EuiButtonIcon * revert EuiKeyPadMenuItem betaBadge props * mobileOptions * examples/ updates * fix brace import * fix type exports * update expressions_explorer requiredBundles * remove make_id mocks * snapshot updates * fix import :facepalm: * Fix `ReferenceError: ace is not defined` Jest failures * Remove unused brace import (?) - Assuming here, as no code editor is actually being used in this file * Fix failing Jest test due to EuiCodeEditor moving to es_ui_shared plugin + minor cleanup of `jest.mock()`s * Fix failing Jest test due to snapshot update * Fix failing `TypeError: Cannot read properties of undefined (reading 'euiBorderRadius')` Jest test - since this is being mount()'d, EuiThemeProvider as a wrapper is needed to prevent the failure * access uiSettings * Move react-ace dependency into kbn-ui-shared-deps-npm * Revert App Search shenanigans - caused local unsaved changes shenanigans, somehow * secondary -> success Co-authored-by: Constance Chen Co-authored-by: Chandler Prall Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Constance Chen --- examples/expressions_explorer/kibana.json | 2 +- examples/expressions_explorer/public/app.tsx | 69 ++++++++++--------- .../public/editor/expression_editor.tsx | 18 +++-- .../expressions_explorer/public/plugin.tsx | 1 + .../public/todo/todo.tsx | 6 +- package.json | 2 +- packages/kbn-ui-shared-deps-npm/BUILD.bazel | 1 + .../kbn-ui-shared-deps-npm/webpack.config.js | 1 + .../__snapshots__/server_status.test.tsx.snap | 4 +- .../__snapshots__/status_table.test.tsx.snap | 2 +- .../status/components/server_status.test.tsx | 2 +- .../status/components/status_table.test.tsx | 2 +- .../core_app/status/lib/load_status.test.ts | 6 +- .../public/core_app/status/lib/load_status.ts | 2 +- .../__snapshots__/i18n_service.test.tsx.snap | 4 -- src/core/public/i18n/i18n_eui_mapping.tsx | 16 ----- src/core/server/status/legacy_status.test.ts | 4 +- src/core/server/status/legacy_status.ts | 4 +- .../routes/integration_tests/status.test.ts | 8 +-- src/dev/license_checker/config.ts | 2 +- .../management_app/components/field/field.tsx | 1 + .../management_app/components/form/form.tsx | 2 +- .../static/components/legend_toggle.tsx | 2 +- .../network_request_status_bar.tsx | 2 +- .../application/top_nav/dashboard_top_nav.tsx | 2 +- .../data/public/ui/typeahead/_suggestion.scss | 2 +- .../sidebar/discover_field_bucket.tsx | 2 +- .../sidebar/string_progress_bar.tsx | 4 +- .../discover_grid_expand_button.tsx | 2 +- .../components/code_editor/code_editor.tsx | 4 +- .../static/forms/components/index.ts | 3 +- .../__snapshots__/synopsis.test.js.snap | 24 +++++-- .../components/_solutions_section.scss | 2 +- .../components/sample_data_set_card.js | 2 +- .../public/application/components/synopsis.js | 2 +- .../table/__snapshots__/table.test.tsx.snap | 2 +- .../components/table/table.tsx | 2 +- .../requests/components/request_selector.tsx | 2 +- .../public/components/_overview.scss | 2 +- .../__snapshots__/synopsis.test.js.snap | 24 +++++-- .../public/components/synopsis/synopsis.js | 2 +- .../public/code_editor/editor_theme.ts | 6 +- .../elastic_agent_card.test.tsx.snap | 26 ++++++- .../no_data_card/elastic_agent_card.tsx | 2 +- .../no_data_card/no_data_card.tsx | 2 +- .../component/control_group_component.tsx | 2 +- .../options_list_popover_component.tsx | 2 +- .../components/labs/project_list_item.scss | 2 +- .../components/labs/project_list_item.tsx | 2 +- .../agg_based_selection.tsx | 2 +- .../group_selection/group_selection.tsx | 4 +- .../public/components/view_alert.tsx | 4 +- .../public/components/view_astros_alert.tsx | 4 +- .../drilldowns_without_embeddable_example.tsx | 2 +- ...thout_embeddable_single_button_example.tsx | 2 +- .../PercentileAnnotations.tsx | 2 +- .../URLFilter/URLSearch/render_option.tsx | 2 +- .../SettingsPage/SettingsPage.tsx | 2 +- .../service_map/Popover/service_contents.tsx | 2 +- .../shared/charts/breakdown_chart/index.tsx | 2 +- .../shared/charts/timeseries_chart.tsx | 2 +- .../shared/license_prompt/index.tsx | 14 ++-- .../tutorial_fleet_instructions/index.tsx | 2 +- .../components/arg_form/arg_simple_form.tsx | 2 +- .../asset_manager.stories.storyshot | 4 +- .../asset_manager/asset_manager.component.tsx | 2 +- .../datasource_component.stories.storyshot | 2 +- .../components/datasource/datasource.scss | 2 +- .../datasource/datasource_component.js | 8 +-- .../workpad_table_tools.component.tsx | 2 +- .../components/page_manager/page_manager.scss | 2 +- .../__snapshots__/edit_var.stories.storyshot | 8 +-- .../public/components/var_config/edit_var.tsx | 2 +- .../filter.component.stories.storyshot | 2 +- .../__stories__/filter.component.stories.tsx | 2 +- .../footer/settings/settings.test.tsx | 1 - .../shareable_runtime/webpack.config.js | 1 - .../canvas/storybook/storyshots.test.tsx | 3 - .../components/edit_connector/index.tsx | 2 +- .../components/header_page/editable_title.tsx | 2 +- .../public/components/tag_list/index.tsx | 2 +- .../callout/callout.test.tsx | 2 +- .../use_push_to_service/callout/callout.tsx | 2 +- .../user_action_tree/user_action_markdown.tsx | 2 +- .../components/auto_follow_pattern_form.js | 6 +- .../follower_index_form.js | 6 +- .../auto_follow_pattern_table.js | 4 +- .../components/detail_panel/detail_panel.js | 1 + .../follower_indices_table.js | 4 +- .../sessions_mgmt/components/status.test.tsx | 2 +- .../sessions_mgmt/components/status.tsx | 4 +- .../search_session_indicator.tsx | 4 +- .../field_data_expanded_row/ip_content.tsx | 2 +- .../keyword_content.tsx | 2 +- .../number_content.tsx | 2 +- .../components/top_values/top_values.tsx | 2 +- .../components/json_editor/json_editor.tsx | 8 ++- .../public/application/shared_imports.ts | 3 + .../components/api_logs/utils.test.ts | 2 +- .../app_search/components/api_logs/utils.ts | 2 +- .../credentials/credentials_flyout/footer.tsx | 2 +- .../curation_result_panel.scss | 2 +- .../engine_creation/engine_creation.tsx | 2 +- .../components/engines/engines_overview.tsx | 4 +- .../meta_engine_creation.tsx | 2 +- .../components/schema/views/schema.tsx | 2 +- .../shared/role_mapping/user_flyout.test.tsx | 2 +- .../shared/role_mapping/user_flyout.tsx | 2 +- .../content_sources/components/overview.tsx | 2 +- .../workplace_search/views/groups/groups.tsx | 2 +- .../views/overview/onboarding_card.tsx | 2 +- .../step_configure_package.tsx | 2 +- .../agents/components/agent_health.tsx | 2 +- .../sections/agents/services/agent_status.tsx | 4 +- .../legacy_settings_form/confirm_modal.tsx | 2 +- .../guidance_panel/_guidance_panel.scss | 2 +- .../component_template_list/table.tsx | 2 +- .../component_templates_list_item.tsx | 2 +- .../data_stream_table/data_stream_table.tsx | 2 +- .../index_list/index_table/index_table.js | 2 +- .../home/template_list/template_list.tsx | 2 +- .../common/inventory_models/host/layout.tsx | 10 +-- .../inventory/components/expression.tsx | 2 +- .../alerting/inventory/components/metric.tsx | 2 +- .../expression_editor/criterion.tsx | 4 +- .../components/expression_editor/editor.tsx | 2 +- .../components/expression_row.tsx | 2 +- .../setup_flyout/module_list_card.tsx | 2 +- .../single_metric_comparison.tsx | 4 +- .../tabs/processes/processes_table.tsx | 2 +- .../tabs/processes/state_badge.tsx | 2 +- .../node_details/tabs/properties/table.tsx | 2 +- .../pipeline_processors_editor_item.tsx | 2 +- .../tab_documents/add_document_form.tsx | 4 +- .../pipeline_form/pipeline_form.tsx | 2 +- .../sections/pipelines_list/table.tsx | 2 +- x-pack/plugins/logstash/kibana.json | 2 +- .../pipeline_editor/pipeline_editor.js | 2 +- .../dynamic_color_property.test.tsx.snap | 2 +- .../dynamic_icon_property.test.tsx.snap | 2 +- .../properties/dynamic_color_property.tsx | 2 +- .../properties/dynamic_icon_property.tsx | 2 +- .../tooltip_selector/tooltip_selector.tsx | 2 +- .../layer_wizard_select.test.tsx.snap | 10 +++ .../flyout_body/layer_wizard_select.tsx | 2 +- .../timeslider/timeslider.tsx | 2 +- .../import_jobs_flyout/import_jobs_flyout.tsx | 2 +- .../job_map/components/cytoscape_options.tsx | 2 +- .../explorer/anomaly_context_menu.tsx | 2 +- .../application/explorer/anomaly_timeline.tsx | 2 +- .../ml_job_editor/ml_job_editor.tsx | 8 ++- .../new_job/recognize/components/job_item.tsx | 8 +-- .../recognize/components/kibana_objects.tsx | 2 +- .../_timeseriesexplorer.scss | 2 +- x-pack/plugins/ml/shared_imports.ts | 3 + .../__snapshots__/shard.test.js.snap | 2 +- .../shard_allocation/components/shard.js | 2 +- .../shard_allocation/shard_allocation.js | 2 +- .../__snapshots__/tooltip.test.js.snap | 10 +-- .../public/components/setup_mode/tooltip.js | 2 +- .../summary_status/summary_status.test.js | 1 - .../app/cases/callout/callout.test.tsx | 2 +- .../components/app/cases/callout/callout.tsx | 2 +- .../field_value_selection.test.tsx | 20 +++--- .../action_results/services/agent_status.tsx | 4 +- .../plugins/osquery/public/editor/index.tsx | 3 +- .../plugins/osquery/public/shared_imports.ts | 3 + .../components/output_pane/output_pane.tsx | 2 +- .../remote_cluster_form.tsx | 6 +- .../remote_cluster_list.js | 4 +- .../sections/job_create/job_create.js | 4 +- .../job_create/navigation/navigation.js | 2 +- .../job_create/steps/step_logistics.js | 2 +- .../public/extend_index_management/index.ts | 2 +- .../api_keys_grid/api_keys_grid_page.tsx | 2 +- .../management/badges/enabled_badge.tsx | 2 +- .../rule_editor_panel/json_rule_editor.tsx | 1 + .../role_mappings_grid_page.tsx | 2 +- .../cases/components/callout/callout.test.tsx | 2 +- .../cases/components/callout/callout.tsx | 6 +- .../callouts/callout_dismiss_button.tsx | 2 +- .../components/header_page/editable_title.tsx | 2 +- .../__snapshots__/index.test.tsx.snap | 4 +- .../item_details_card/index.stories.tsx | 4 +- .../item_details_card/index.test.tsx | 4 +- .../__snapshots__/index.test.tsx.snap | 16 +++-- .../components/paginated_table/index.mock.tsx | 8 +-- .../components/paginated_table/index.tsx | 4 +- .../__snapshots__/index.test.tsx.snap | 2 +- .../components/progress_inline/index.tsx | 2 +- .../description_step/ml_job_description.tsx | 2 +- .../authentications_table/index.tsx | 18 ++--- .../hosts/components/hosts_table/columns.tsx | 8 +-- .../uncommon_process_table/index.tsx | 12 ++-- .../endpoint_hosts/view/host_constants.ts | 6 +- .../policy/view/policy_forms/locked_card.tsx | 8 ++- .../components/network_dns_table/columns.tsx | 10 +-- .../network/components/tls_table/columns.tsx | 10 +-- .../components/users_table/columns.tsx | 10 +-- .../open_timeline/note_previews/index.tsx | 2 +- .../components/timeline/footer/index.tsx | 2 +- .../components/host_rules_table/columns.tsx | 8 +-- .../components/host_tactics_table/columns.tsx | 8 +-- .../components/risk_score_table/columns.tsx | 4 +- .../components/policy_form/policy_form.tsx | 2 +- .../components/repository_form/step_two.tsx | 2 +- .../restore_snapshot_form.tsx | 2 +- .../policy_details/policy_details.tsx | 2 +- .../policy_list/policy_table/policy_table.tsx | 2 +- .../repository_details/repository_details.tsx | 2 - .../type_details/default_details.tsx | 1 + .../repository_table/repository_table.tsx | 2 +- .../copy_to_space_flyout_footer.tsx | 2 +- .../components/share_mode_control.tsx | 2 +- .../alert_types/es_query/expression.test.tsx | 31 +++------ .../alert_types/es_query/expression.tsx | 5 +- .../t_grid/event_rendered_view/index.tsx | 8 +-- .../refresh_transform_list_button.tsx | 2 +- .../translations/translations/ja-JP.json | 4 -- .../translations/translations/zh-CN.json | 4 -- .../json_editor_with_message_variables.tsx | 6 +- .../connector_add_flyout.tsx | 4 +- .../connector_add_modal.tsx | 2 +- .../connector_edit_flyout.tsx | 4 +- .../sections/alert_form/alert_add_footer.tsx | 2 +- .../sections/alert_form/alert_edit.tsx | 2 +- .../components/flyout_frame/flyout_frame.tsx | 2 +- .../es_deprecations/es_deprecations_table.tsx | 6 +- .../common/charts/monitor_bar_series.tsx | 2 +- .../monitor/ping_list/columns/ping_status.tsx | 2 +- .../monitor/ping_list/ping_redirects.tsx | 4 +- .../__snapshots__/tag_label.test.tsx.snap | 2 +- .../availability_reporting/tag_label.tsx | 2 +- .../components/middle_truncated_text.tsx | 2 +- .../alerts/alert_expression_popover.tsx | 4 +- .../components/overview/alerts/alert_tls.tsx | 2 +- .../down_number_select.test.tsx.snap | 2 +- .../time_expression_select.test.tsx.snap | 4 +- .../filters_expression_select.tsx | 2 +- .../settings_message_expression_popover.tsx | 2 +- .../columns/monitor_status_column.tsx | 2 +- .../monitor_status_row.tsx | 2 +- .../application/components/watch_status.tsx | 2 +- .../json_watch_edit/json_watch_edit_form.tsx | 2 +- .../threshold_watch_edit.tsx | 10 +-- yarn.lock | 9 ++- 246 files changed, 524 insertions(+), 474 deletions(-) diff --git a/examples/expressions_explorer/kibana.json b/examples/expressions_explorer/kibana.json index 770ce91143d99..dea706d024941 100644 --- a/examples/expressions_explorer/kibana.json +++ b/examples/expressions_explorer/kibana.json @@ -10,5 +10,5 @@ }, "requiredPlugins": ["expressions", "inspector", "uiActions", "developerExamples"], "optionalPlugins": [], - "requiredBundles": [] + "requiredBundles": ["kibanaReact"] } diff --git a/examples/expressions_explorer/public/app.tsx b/examples/expressions_explorer/public/app.tsx index 260c529650bdb..631b60f4dc566 100644 --- a/examples/expressions_explorer/public/app.tsx +++ b/examples/expressions_explorer/public/app.tsx @@ -18,7 +18,7 @@ import { EuiText, EuiLink, } from '@elastic/eui'; -import { AppMountParameters } from '../../../src/core/public'; +import { AppMountParameters, IUiSettingsClient } from '../../../src/core/public'; import { ExpressionsStart } from '../../../src/plugins/expressions/public'; import { Start as InspectorStart } from '../../../src/plugins/inspector/public'; import { RunExpressionsExample } from './run_expressions'; @@ -26,53 +26,58 @@ import { RenderExpressionsExample } from './render_expressions'; import { ActionsExpressionsExample } from './actions_and_expressions'; import { UiActionsStart } from '../../../src/plugins/ui_actions/public'; import { ActionsExpressionsExample2 } from './actions_and_expressions2'; +import { createKibanaReactContext } from '../../../src/plugins/kibana_react/public'; interface Props { expressions: ExpressionsStart; inspector: InspectorStart; actions: UiActionsStart; + uiSettings: IUiSettingsClient; } -const ExpressionsExplorer = ({ expressions, inspector, actions }: Props) => { +const ExpressionsExplorer = ({ expressions, inspector, actions, uiSettings }: Props) => { + const { Provider: KibanaReactContextProvider } = createKibanaReactContext({ uiSettings }); return ( - - - Expressions Explorer - - - -

    - There are a couple of ways to run the expressions. Below some of the options are - demonstrated. You can read more about it{' '} - - here - -

    -
    + + + + Expressions Explorer + + + +

    + There are a couple of ways to run the expressions. Below some of the options are + demonstrated. You can read more about it{' '} + + here + +

    +
    - + - + - + - + - + - + - + - -
    -
    -
    -
    + +
    +
    +
    +
    + ); }; diff --git a/examples/expressions_explorer/public/editor/expression_editor.tsx b/examples/expressions_explorer/public/editor/expression_editor.tsx index 16370c2ece281..79c5a296981db 100644 --- a/examples/expressions_explorer/public/editor/expression_editor.tsx +++ b/examples/expressions_explorer/public/editor/expression_editor.tsx @@ -7,7 +7,7 @@ */ import React from 'react'; -import { EuiCodeEditor } from '@elastic/eui'; +import { CodeEditor } from '../../../../src/plugins/kibana_react/public'; interface Props { value: string; @@ -16,19 +16,17 @@ interface Props { export function ExpressionEditor({ value, onChange }: Props) { return ( - {}} aria-label="Code Editor" /> ); diff --git a/examples/expressions_explorer/public/plugin.tsx b/examples/expressions_explorer/public/plugin.tsx index 329dcfbb11d45..07f0526c3461d 100644 --- a/examples/expressions_explorer/public/plugin.tsx +++ b/examples/expressions_explorer/public/plugin.tsx @@ -59,6 +59,7 @@ export class ExpressionsExplorerPlugin implements Plugin = ({ filter, stateContainer }) => { <>
    - + All - + Completed @@ -76,7 +76,7 @@ const TodoApp: React.FC = ({ filter, stateContainer }) => { to={{ ...location, pathname: '/not-completed' }} data-test-subj={'filterLinkNotCompleted'} > - + Not Completed diff --git a/package.json b/package.json index ca2cb27076c7a..c15bb092f17d8 100644 --- a/package.json +++ b/package.json @@ -103,7 +103,7 @@ "@elastic/datemath": "link:bazel-bin/packages/elastic-datemath", "@elastic/elasticsearch": "npm:@elastic/elasticsearch-canary@^8.0.0-canary.35", "@elastic/ems-client": "8.0.0", - "@elastic/eui": "40.1.0", + "@elastic/eui": "41.0.0", "@elastic/filesaver": "1.1.2", "@elastic/maki": "6.3.0", "@elastic/node-crypto": "1.2.1", diff --git a/packages/kbn-ui-shared-deps-npm/BUILD.bazel b/packages/kbn-ui-shared-deps-npm/BUILD.bazel index 416a4d4799b7b..490aa91f30680 100644 --- a/packages/kbn-ui-shared-deps-npm/BUILD.bazel +++ b/packages/kbn-ui-shared-deps-npm/BUILD.bazel @@ -46,6 +46,7 @@ RUNTIME_DEPS = [ "@npm//moment-timezone", "@npm//moment", "@npm//raw-loader", + "@npm//react-ace", "@npm//react-dom", "@npm//react-intl", "@npm//react-is", diff --git a/packages/kbn-ui-shared-deps-npm/webpack.config.js b/packages/kbn-ui-shared-deps-npm/webpack.config.js index 80043bd0857ee..a6e7180e88123 100644 --- a/packages/kbn-ui-shared-deps-npm/webpack.config.js +++ b/packages/kbn-ui-shared-deps-npm/webpack.config.js @@ -82,6 +82,7 @@ module.exports = (_, argv) => { 'moment-timezone/moment-timezone', 'moment-timezone/data/packed/latest.json', 'moment', + 'react-ace', 'react-beautiful-dnd', 'react-dom', 'react-dom/server', diff --git a/src/core/public/core_app/status/components/__snapshots__/server_status.test.tsx.snap b/src/core/public/core_app/status/components/__snapshots__/server_status.test.tsx.snap index 0ed784ef680f7..7682a848b0b17 100644 --- a/src/core/public/core_app/status/components/__snapshots__/server_status.test.tsx.snap +++ b/src/core/public/core_app/status/components/__snapshots__/server_status.test.tsx.snap @@ -3,7 +3,7 @@ exports[`ServerStatus renders correctly for green state 2`] = ` @@ -36,7 +36,7 @@ exports[`ServerStatus renders correctly for green state 2`] = ` exports[`ServerStatus renders correctly for red state 2`] = ` diff --git a/src/core/public/core_app/status/components/__snapshots__/status_table.test.tsx.snap b/src/core/public/core_app/status/components/__snapshots__/status_table.test.tsx.snap index 5b0e831286aad..c30637ed85a57 100644 --- a/src/core/public/core_app/status/components/__snapshots__/status_table.test.tsx.snap +++ b/src/core/public/core_app/status/components/__snapshots__/status_table.test.tsx.snap @@ -30,7 +30,7 @@ exports[`StatusTable renders when statuses is provided 1`] = ` "id": "available", "message": "Ready", "title": "green", - "uiColor": "secondary", + "uiColor": "success", }, }, ] diff --git a/src/core/public/core_app/status/components/server_status.test.tsx b/src/core/public/core_app/status/components/server_status.test.tsx index 3aa41827ff40f..e4fa84d317dd6 100644 --- a/src/core/public/core_app/status/components/server_status.test.tsx +++ b/src/core/public/core_app/status/components/server_status.test.tsx @@ -14,7 +14,7 @@ import { FormattedStatus } from '../lib'; const getStatus = (parts: Partial = {}): FormattedStatus['state'] => ({ id: 'available', title: 'Green', - uiColor: 'secondary', + uiColor: 'success', message: '', ...parts, }); diff --git a/src/core/public/core_app/status/components/status_table.test.tsx b/src/core/public/core_app/status/components/status_table.test.tsx index af7d33bee5ed6..3cb5d1126ef31 100644 --- a/src/core/public/core_app/status/components/status_table.test.tsx +++ b/src/core/public/core_app/status/components/status_table.test.tsx @@ -12,7 +12,7 @@ import { StatusTable } from './status_table'; const state = { id: 'available' as const, - uiColor: 'secondary', + uiColor: 'success', message: 'Ready', title: 'green', }; diff --git a/src/core/public/core_app/status/lib/load_status.test.ts b/src/core/public/core_app/status/lib/load_status.test.ts index 73c697c3d55aa..b6e7ba9b91e97 100644 --- a/src/core/public/core_app/status/lib/load_status.test.ts +++ b/src/core/public/core_app/status/lib/load_status.test.ts @@ -174,7 +174,7 @@ describe('response processing', () => { id: 'available', title: 'Green', message: 'Elasticsearch is available', - uiColor: 'secondary', + uiColor: 'success', }, }, { @@ -183,12 +183,12 @@ describe('response processing', () => { id: 'available', title: 'Green', message: 'SavedObjects service has completed migrations and is available', - uiColor: 'secondary', + uiColor: 'success', }, }, { id: 'plugin:1', - state: { id: 'available', title: 'Green', message: 'Ready', uiColor: 'secondary' }, + state: { id: 'available', title: 'Green', message: 'Ready', uiColor: 'success' }, }, { id: 'plugin:2', diff --git a/src/core/public/core_app/status/lib/load_status.ts b/src/core/public/core_app/status/lib/load_status.ts index e65764771f0fc..0baa67d4e793c 100644 --- a/src/core/public/core_app/status/lib/load_status.ts +++ b/src/core/public/core_app/status/lib/load_status.ts @@ -128,7 +128,7 @@ const STATUS_LEVEL_UI_ATTRS: Record = { title: i18n.translate('core.status.greenTitle', { defaultMessage: 'Green', }), - uiColor: 'secondary', + uiColor: 'success', }, }; diff --git a/src/core/public/i18n/__snapshots__/i18n_service.test.tsx.snap b/src/core/public/i18n/__snapshots__/i18n_service.test.tsx.snap index 197714df7f207..e93ef34c38025 100644 --- a/src/core/public/i18n/__snapshots__/i18n_service.test.tsx.snap +++ b/src/core/public/i18n/__snapshots__/i18n_service.test.tsx.snap @@ -26,10 +26,6 @@ exports[`#start() returns \`Context\` component 1`] = ` "euiCodeBlock.copyButton": "Copy", "euiCodeBlock.fullscreenCollapse": "Collapse", "euiCodeBlock.fullscreenExpand": "Expand", - "euiCodeEditor.startEditing": "Press Enter to start editing.", - "euiCodeEditor.startInteracting": "Press Enter to start interacting with the code.", - "euiCodeEditor.stopEditing": "When you're done, press Escape to stop editing.", - "euiCodeEditor.stopInteracting": "When you're done, press Escape to stop interacting with the code.", "euiCollapsedItemActions.allActions": "All actions", "euiColorPicker.alphaLabel": "Alpha channel (opacity) value", "euiColorPicker.closeLabel": "Press the down key to open a popover containing color options", diff --git a/src/core/public/i18n/i18n_eui_mapping.tsx b/src/core/public/i18n/i18n_eui_mapping.tsx index f28add25056ee..79180575129ea 100644 --- a/src/core/public/i18n/i18n_eui_mapping.tsx +++ b/src/core/public/i18n/i18n_eui_mapping.tsx @@ -127,22 +127,6 @@ export const getEuiContextMapping = (): EuiTokensObject => { defaultMessage: 'Expand', description: 'ARIA label for a button that enters fullscreen view', }), - 'euiCodeEditor.startEditing': i18n.translate('core.euiCodeEditor.startEditing', { - defaultMessage: 'Press Enter to start editing.', - description: 'Screen reader text to prompt editing', - }), - 'euiCodeEditor.startInteracting': i18n.translate('core.euiCodeEditor.startInteracting', { - defaultMessage: 'Press Enter to start interacting with the code.', - description: 'Screen reader text to prompt interaction', - }), - 'euiCodeEditor.stopEditing': i18n.translate('core.euiCodeEditor.stopEditing', { - defaultMessage: "When you're done, press Escape to stop editing.", - description: 'Screen reader text to describe ending editing', - }), - 'euiCodeEditor.stopInteracting': i18n.translate('core.euiCodeEditor.stopInteracting', { - defaultMessage: "When you're done, press Escape to stop interacting with the code.", - description: 'Screen reader text to describe ending interactions', - }), 'euiCollapsedItemActions.allActions': i18n.translate( 'core.euiCollapsedItemActions.allActions', { diff --git a/src/core/server/status/legacy_status.test.ts b/src/core/server/status/legacy_status.test.ts index 8f1193cfcbd33..61c356e514e5f 100644 --- a/src/core/server/status/legacy_status.test.ts +++ b/src/core/server/status/legacy_status.test.ts @@ -37,7 +37,7 @@ describe('calculateLegacyStatus', () => { title: 'Green', nickname: 'Looking good', icon: 'success', - uiColor: 'secondary', + uiColor: 'success', since: expect.any(String), }); }); @@ -80,7 +80,7 @@ describe('calculateLegacyStatus', () => { message: 'Available', since: expect.any(String), state: 'green', - uiColor: 'secondary', + uiColor: 'success', }, { icon: 'danger', diff --git a/src/core/server/status/legacy_status.ts b/src/core/server/status/legacy_status.ts index 1b3d139b1345e..654427781ba9e 100644 --- a/src/core/server/status/legacy_status.ts +++ b/src/core/server/status/legacy_status.ts @@ -37,7 +37,7 @@ interface LegacyStatusOverall { type LegacyStatusState = 'green' | 'yellow' | 'red'; type LegacyStatusIcon = 'danger' | 'warning' | 'success'; -type LegacyStatusUiColor = 'secondary' | 'warning' | 'danger'; +type LegacyStatusUiColor = 'success' | 'warning' | 'danger'; interface LegacyStateAttr { id: LegacyStatusState; @@ -141,7 +141,7 @@ const STATUS_LEVEL_LEGACY_ATTRS = deepFreeze>({ defaultMessage: 'Green', }), icon: 'success', - uiColor: 'secondary', + uiColor: 'success', nickname: 'Looking good', }, }); diff --git a/src/core/server/status/routes/integration_tests/status.test.ts b/src/core/server/status/routes/integration_tests/status.test.ts index df840f5d7c059..df203675725a8 100644 --- a/src/core/server/status/routes/integration_tests/status.test.ts +++ b/src/core/server/status/routes/integration_tests/status.test.ts @@ -164,7 +164,7 @@ describe('GET /api/status', () => { since: expect.any(String), state: 'green', title: 'Green', - uiColor: 'secondary', + uiColor: 'success', }, statuses: [ { @@ -173,7 +173,7 @@ describe('GET /api/status', () => { message: 'Service is working', since: expect.any(String), state: 'green', - uiColor: 'secondary', + uiColor: 'success', }, { icon: 'success', @@ -181,7 +181,7 @@ describe('GET /api/status', () => { message: 'Service is working', since: expect.any(String), state: 'green', - uiColor: 'secondary', + uiColor: 'success', }, { icon: 'success', @@ -189,7 +189,7 @@ describe('GET /api/status', () => { message: 'a is available', since: expect.any(String), state: 'green', - uiColor: 'secondary', + uiColor: 'success', }, { icon: 'warning', diff --git a/src/dev/license_checker/config.ts b/src/dev/license_checker/config.ts index f23456bbaca07..078786abb8c64 100644 --- a/src/dev/license_checker/config.ts +++ b/src/dev/license_checker/config.ts @@ -75,6 +75,6 @@ export const LICENSE_OVERRIDES = { 'jsts@1.6.2': ['Eclipse Distribution License - v 1.0'], // cf. https://github.com/bjornharrtell/jsts '@mapbox/jsonlint-lines-primitives@2.0.2': ['MIT'], // license in readme https://github.com/tmcw/jsonlint '@elastic/ems-client@8.0.0': ['Elastic License 2.0'], - '@elastic/eui@40.1.0': ['SSPL-1.0 OR Elastic License 2.0'], + '@elastic/eui@41.0.0': ['SSPL-1.0 OR Elastic License 2.0'], 'language-subtag-registry@0.3.21': ['CC-BY-4.0'], // retired ODC‑By license https://github.com/mattcg/language-subtag-registry }; diff --git a/src/plugins/advanced_settings/public/management_app/components/field/field.tsx b/src/plugins/advanced_settings/public/management_app/components/field/field.tsx index 745452a31ff9c..5e4d047b2c701 100644 --- a/src/plugins/advanced_settings/public/management_app/components/field/field.tsx +++ b/src/plugins/advanced_settings/public/management_app/components/field/field.tsx @@ -8,6 +8,7 @@ import React, { PureComponent, Fragment } from 'react'; import classNames from 'classnames'; +import 'react-ace'; import 'brace/theme/textmate'; import 'brace/mode/markdown'; import 'brace/mode/json'; diff --git a/src/plugins/advanced_settings/public/management_app/components/form/form.tsx b/src/plugins/advanced_settings/public/management_app/components/form/form.tsx index 0b08a317e87c9..2356cc7690c7c 100644 --- a/src/plugins/advanced_settings/public/management_app/components/form/form.tsx +++ b/src/plugins/advanced_settings/public/management_app/components/form/form.tsx @@ -368,7 +368,7 @@ export class Form extends PureComponent { { } if (statusCode <= 299) { - return 'secondary'; + return 'success'; } if (statusCode <= 399) { diff --git a/src/plugins/dashboard/public/application/top_nav/dashboard_top_nav.tsx b/src/plugins/dashboard/public/application/top_nav/dashboard_top_nav.tsx index 8391edd30d8ee..8e24e9ea595dc 100644 --- a/src/plugins/dashboard/public/application/top_nav/dashboard_top_nav.tsx +++ b/src/plugins/dashboard/public/application/top_nav/dashboard_top_nav.tsx @@ -502,7 +502,7 @@ export function DashboardTopNav({ { 'data-test-subj': 'dashboardUnsavedChangesBadge', badgeText: unsavedChangesBadge.getUnsavedChangedBadgeText(), - color: 'secondary', + color: 'success', }, ] : undefined; diff --git a/src/plugins/data/public/ui/typeahead/_suggestion.scss b/src/plugins/data/public/ui/typeahead/_suggestion.scss index 67ff17d017053..345c7493dc293 100644 --- a/src/plugins/data/public/ui/typeahead/_suggestion.scss +++ b/src/plugins/data/public/ui/typeahead/_suggestion.scss @@ -1,7 +1,7 @@ // These are the various types in the dropdown, they each get a color $kbnTypeaheadTypes: ( field: $euiColorWarning, - value: $euiColorSecondary, + value: $euiColorSuccess, operator: $euiColorPrimary, conjunction: $euiColorVis3, ); diff --git a/src/plugins/discover/public/application/main/components/sidebar/discover_field_bucket.tsx b/src/plugins/discover/public/application/main/components/sidebar/discover_field_bucket.tsx index 9b0134bf19406..54c5bccaf6041 100644 --- a/src/plugins/discover/public/application/main/components/sidebar/discover_field_bucket.tsx +++ b/src/plugins/discover/public/application/main/components/sidebar/discover_field_bucket.tsx @@ -55,7 +55,7 @@ export function DiscoverFieldBucket({ field, bucket, onAddFilter }: Props) { - + {bucket.percent}% diff --git a/src/plugins/discover/public/application/main/components/sidebar/string_progress_bar.tsx b/src/plugins/discover/public/application/main/components/sidebar/string_progress_bar.tsx index a3f6c70c23a6e..34bcbfcaf113e 100644 --- a/src/plugins/discover/public/application/main/components/sidebar/string_progress_bar.tsx +++ b/src/plugins/discover/public/application/main/components/sidebar/string_progress_bar.tsx @@ -18,7 +18,5 @@ interface Props { export function StringFieldProgressBar({ value, percent, count }: Props) { const ariaLabel = `${value}: ${count} (${percent}%)`; - return ( - - ); + return ; } diff --git a/src/plugins/discover/public/components/discover_grid/discover_grid_expand_button.tsx b/src/plugins/discover/public/components/discover_grid/discover_grid_expand_button.tsx index 3453a535f98dd..372fe03666d03 100644 --- a/src/plugins/discover/public/components/discover_grid/discover_grid_expand_button.tsx +++ b/src/plugins/discover/public/components/discover_grid/discover_grid_expand_button.tsx @@ -50,7 +50,7 @@ export const ExpandButton = ({ rowIndex, setCellProps }: EuiDataGridCellValueEle aria-label={buttonLabel} data-test-subj="docTableExpandToggleColumn" onClick={() => setExpanded(isCurrentRowExpanded ? undefined : current)} - color={isCurrentRowExpanded ? 'primary' : 'subdued'} + color={isCurrentRowExpanded ? 'primary' : 'text'} iconType={isCurrentRowExpanded ? 'minimize' : 'expand'} isSelected={isCurrentRowExpanded} /> diff --git a/src/plugins/es_ui_shared/public/components/code_editor/code_editor.tsx b/src/plugins/es_ui_shared/public/components/code_editor/code_editor.tsx index 6299b473f68df..5f172d010b836 100644 --- a/src/plugins/es_ui_shared/public/components/code_editor/code_editor.tsx +++ b/src/plugins/es_ui_shared/public/components/code_editor/code_editor.tsx @@ -9,9 +9,7 @@ import React, { Component, AriaAttributes } from 'react'; import classNames from 'classnames'; import AceEditor, { IAceEditorProps } from 'react-ace'; -import { EuiI18n } from '@elastic/eui'; -// @ts-ignore -import { htmlIdGenerator, keys } from '@elastic/eui/lib/services'; +import { EuiI18n, htmlIdGenerator, keys } from '@elastic/eui'; import './_index.scss'; diff --git a/src/plugins/es_ui_shared/static/forms/components/index.ts b/src/plugins/es_ui_shared/static/forms/components/index.ts index 95b92d205c8cd..7dc1ce16a6824 100644 --- a/src/plugins/es_ui_shared/static/forms/components/index.ts +++ b/src/plugins/es_ui_shared/static/forms/components/index.ts @@ -9,7 +9,7 @@ /* @TODO -The brace/mode/json import below is loaded eagerly - before this plugin is explicitly loaded by users. This makes +The react-ace and brace/mode/json imports below are loaded eagerly - before this plugin is explicitly loaded by users. This makes the brace JSON mode, used for JSON syntax highlighting and grammar checking, available across all of Kibana plugins. This is not ideal because we are loading JS that is not necessary for Kibana to start, but the alternative @@ -19,6 +19,7 @@ EuiCodeEditor (for instance, explicitly). Importing here is a way of preventing a more sophisticated solution to this problem since we want to, eventually, migrate all code editors over to Monaco. Once that is done, we should remove this import. */ +import 'react-ace'; import 'brace/mode/json'; export * from './field'; diff --git a/src/plugins/home/public/application/components/__snapshots__/synopsis.test.js.snap b/src/plugins/home/public/application/components/__snapshots__/synopsis.test.js.snap index 8e04e70ed92b6..68bb6022d093b 100644 --- a/src/plugins/home/public/application/components/__snapshots__/synopsis.test.js.snap +++ b/src/plugins/home/public/application/components/__snapshots__/synopsis.test.js.snap @@ -2,7 +2,11 @@ exports[`props iconType 1`] = ` diff --git a/src/plugins/home/public/application/components/synopsis.js b/src/plugins/home/public/application/components/synopsis.js index b450ec8d15d2a..73113c48107d2 100644 --- a/src/plugins/home/public/application/components/synopsis.js +++ b/src/plugins/home/public/application/components/synopsis.js @@ -22,7 +22,7 @@ export function Synopsis({ id, description, iconUrl, iconType, title, url, onCli return ( `; exports[`Table should render the boolean template (true) 1`] = ` `; diff --git a/src/plugins/index_pattern_management/public/components/edit_index_pattern/indexed_fields_table/components/table/table.tsx b/src/plugins/index_pattern_management/public/components/edit_index_pattern/indexed_fields_table/components/table/table.tsx index e3e59a4093334..aed985f062cd9 100644 --- a/src/plugins/index_pattern_management/public/components/edit_index_pattern/indexed_fields_table/components/table/table.tsx +++ b/src/plugins/index_pattern_management/public/components/edit_index_pattern/indexed_fields_table/components/table/table.tsx @@ -225,7 +225,7 @@ export const renderFieldName = (field: IndexedFieldItem, timeFieldName?: string) export class Table extends PureComponent { renderBooleanTemplate(value: string, arialLabel: string) { - return value ? : ; + return value ? : ; } renderFieldType(type: string, isConflict: boolean) { diff --git a/src/plugins/inspector/public/views/requests/components/request_selector.tsx b/src/plugins/inspector/public/views/requests/components/request_selector.tsx index 04fac0bd93b7e..539abd3d14372 100644 --- a/src/plugins/inspector/public/views/requests/components/request_selector.tsx +++ b/src/plugins/inspector/public/views/requests/components/request_selector.tsx @@ -114,7 +114,7 @@ export class RequestSelector extends Component { } > ); diff --git a/src/plugins/kibana_react/public/code_editor/editor_theme.ts b/src/plugins/kibana_react/public/code_editor/editor_theme.ts index 6c2727b123de8..517fe4cf61a08 100644 --- a/src/plugins/kibana_react/public/code_editor/editor_theme.ts +++ b/src/plugins/kibana_react/public/code_editor/editor_theme.ts @@ -35,7 +35,7 @@ export function createTheme( { token: 'strong', fontStyle: 'bold' }, { token: 'variable', foreground: euiTheme.euiColorPrimary }, - { token: 'variable.predefined', foreground: euiTheme.euiColorSecondary }, + { token: 'variable.predefined', foreground: euiTheme.euiColorSuccess }, { token: 'constant', foreground: euiTheme.euiColorAccent }, { token: 'comment', foreground: euiTheme.euiColorMediumShade }, { token: 'number', foreground: euiTheme.euiColorAccent }, @@ -52,7 +52,7 @@ export function createTheme( { token: 'tag.id.jade', foreground: euiTheme.euiColorPrimary }, { token: 'tag.class.jade', foreground: euiTheme.euiColorPrimary }, { token: 'meta.scss', foreground: euiTheme.euiColorAccent }, - { token: 'metatag', foreground: euiTheme.euiColorSecondary }, + { token: 'metatag', foreground: euiTheme.euiColorSuccess }, { token: 'metatag.content.html', foreground: euiTheme.euiColorDanger }, { token: 'metatag.html', foreground: euiTheme.euiColorMediumShade }, { token: 'metatag.xml', foreground: euiTheme.euiColorMediumShade }, @@ -63,7 +63,7 @@ export function createTheme( { token: 'string.value.json', foreground: euiTheme.euiColorPrimary }, { token: 'attribute.name', foreground: euiTheme.euiColorDanger }, - { token: 'attribute.name.css', foreground: euiTheme.euiColorSecondary }, + { token: 'attribute.name.css', foreground: euiTheme.euiColorSuccess }, { token: 'attribute.value', foreground: euiTheme.euiColorPrimary }, { token: 'attribute.value.number', foreground: euiTheme.euiColorWarning }, { token: 'attribute.value.unit', foreground: euiTheme.euiColorWarning }, diff --git a/src/plugins/kibana_react/public/page_template/no_data_page/no_data_card/__snapshots__/elastic_agent_card.test.tsx.snap b/src/plugins/kibana_react/public/page_template/no_data_page/no_data_card/__snapshots__/elastic_agent_card.test.tsx.snap index 8e1d0cb92e006..f6dcf46b27d8c 100644 --- a/src/plugins/kibana_react/public/page_template/no_data_page/no_data_card/__snapshots__/elastic_agent_card.test.tsx.snap +++ b/src/plugins/kibana_react/public/page_template/no_data_page/no_data_card/__snapshots__/elastic_agent_card.test.tsx.snap @@ -13,6 +13,11 @@ exports[`ElasticAgentCard props button 1`] = ` } > = ({ description={i18n.translate('kibana-react.noDataPage.elasticAgentCard.description', { defaultMessage: `Use Elastic Agent for a simple, unified way to collect data from your machines.`, })} - betaBadgeLabel={recommended ? NO_DATA_RECOMMENDED : undefined} + betaBadgeProps={{ label: recommended ? NO_DATA_RECOMMENDED : undefined }} footer={footer} layout={layout as 'vertical' | undefined} {...cardRest} diff --git a/src/plugins/kibana_react/public/page_template/no_data_page/no_data_card/no_data_card.tsx b/src/plugins/kibana_react/public/page_template/no_data_page/no_data_card/no_data_card.tsx index 9cc38cc5f6038..2d7335a1740a0 100644 --- a/src/plugins/kibana_react/public/page_template/no_data_page/no_data_card/no_data_card.tsx +++ b/src/plugins/kibana_react/public/page_template/no_data_page/no_data_card/no_data_card.tsx @@ -33,7 +33,7 @@ export const NoDataCard: FunctionComponent = ({ description={i18n.translate('kibana-react.noDataPage.noDataCard.description', { defaultMessage: `Proceed without collecting data`, })} - betaBadgeLabel={recommended ? NO_DATA_RECOMMENDED : undefined} + betaBadgeProps={{ label: recommended ? NO_DATA_RECOMMENDED : undefined }} footer={footer} layout={layout as 'vertical' | undefined} {...cardRest} diff --git a/src/plugins/presentation_util/public/components/controls/control_group/component/control_group_component.tsx b/src/plugins/presentation_util/public/components/controls/control_group/component/control_group_component.tsx index 22b97b6f6b0da..9b5e5588373db 100644 --- a/src/plugins/presentation_util/public/components/controls/control_group/component/control_group_component.tsx +++ b/src/plugins/presentation_util/public/components/controls/control_group/component/control_group_component.tsx @@ -174,7 +174,7 @@ export const ControlGroup = () => { { const flyoutInstance = openFlyout( diff --git a/src/plugins/presentation_util/public/components/controls/control_types/options_list/options_list_popover_component.tsx b/src/plugins/presentation_util/public/components/controls/control_types/options_list/options_list_popover_component.tsx index 90f92e30c32c9..a84d0460e9299 100644 --- a/src/plugins/presentation_util/public/components/controls/control_types/options_list/options_list_popover_component.tsx +++ b/src/plugins/presentation_util/public/components/controls/control_types/options_list/options_list_popover_component.tsx @@ -92,7 +92,7 @@ export const OptionsListPopover = ({ size="s" iconType="list" aria-pressed={showOnlySelected} - color={showOnlySelected ? 'primary' : 'subdued'} + color={showOnlySelected ? 'primary' : 'text'} display={showOnlySelected ? 'base' : 'empty'} aria-label={OptionsListStrings.popover.getClearAllSelectionsButtonTitle()} onClick={() => setShowOnlySelected(!showOnlySelected)} diff --git a/src/plugins/presentation_util/public/components/labs/project_list_item.scss b/src/plugins/presentation_util/public/components/labs/project_list_item.scss index 898770f7811a1..75c0018989fa0 100644 --- a/src/plugins/presentation_util/public/components/labs/project_list_item.scss +++ b/src/plugins/presentation_util/public/components/labs/project_list_item.scss @@ -10,7 +10,7 @@ left: 4px; bottom: $euiSizeL; width: 4px; - background: $euiColorSecondary; + background: $euiColorSuccess; content: ''; } diff --git a/src/plugins/presentation_util/public/components/labs/project_list_item.tsx b/src/plugins/presentation_util/public/components/labs/project_list_item.tsx index 994059c9789ec..909e8434f77f1 100644 --- a/src/plugins/presentation_util/public/components/labs/project_list_item.tsx +++ b/src/plugins/presentation_util/public/components/labs/project_list_item.tsx @@ -58,7 +58,7 @@ export const ProjectListItem = ({ project, onStatusChange }: Props) => { content={strings.getOverriddenIconTipLabel()} position="top" type="dot" - color="secondary" + color="success" /> ) : null} diff --git a/src/plugins/visualizations/public/wizard/agg_based_selection/agg_based_selection.tsx b/src/plugins/visualizations/public/wizard/agg_based_selection/agg_based_selection.tsx index ff3b05f0bd994..acbe226155397 100644 --- a/src/plugins/visualizations/public/wizard/agg_based_selection/agg_based_selection.tsx +++ b/src/plugins/visualizations/public/wizard/agg_based_selection/agg_based_selection.tsx @@ -137,7 +137,7 @@ class AggBasedSelection extends React.Component} + icon={} className="aggBasedDialog__card" /> diff --git a/src/plugins/visualizations/public/wizard/group_selection/group_selection.tsx b/src/plugins/visualizations/public/wizard/group_selection/group_selection.tsx index b28d980424ebf..3866bce796c22 100644 --- a/src/plugins/visualizations/public/wizard/group_selection/group_selection.tsx +++ b/src/plugins/visualizations/public/wizard/group_selection/group_selection.tsx @@ -110,7 +110,7 @@ function GroupSelection(props: GroupSelectionProps) { 'Use our classic visualize library to create charts based on aggregations.', } )} - icon={} + icon={} className="visNewVisDialog__groupsCard" > { } layout="horizontal" - icon={} + icon={} className="visNewVisDialog__groupsCard" /> diff --git a/x-pack/examples/alerting_example/public/components/view_alert.tsx b/x-pack/examples/alerting_example/public/components/view_alert.tsx index 5f3581871e2bd..0269654806c51 100644 --- a/x-pack/examples/alerting_example/public/components/view_alert.tsx +++ b/x-pack/examples/alerting_example/public/components/view_alert.tsx @@ -9,7 +9,7 @@ import React, { useState, useEffect, Fragment } from 'react'; import { EuiText, - EuiLoadingKibana, + EuiLoadingLogo, EuiCallOut, EuiTextColor, EuiDescriptionList, @@ -106,6 +106,6 @@ export const ViewAlertPage = withRouter(({ http, id }: Props) => { )} ) : ( - + ); }); diff --git a/x-pack/examples/alerting_example/public/components/view_astros_alert.tsx b/x-pack/examples/alerting_example/public/components/view_astros_alert.tsx index 1bab422c2bcf0..44ca8f624c197 100644 --- a/x-pack/examples/alerting_example/public/components/view_astros_alert.tsx +++ b/x-pack/examples/alerting_example/public/components/view_astros_alert.tsx @@ -9,7 +9,7 @@ import React, { useState, useEffect, Fragment } from 'react'; import { EuiText, - EuiLoadingKibana, + EuiLoadingLogo, EuiCallOut, EuiTextColor, EuiDescriptionList, @@ -114,6 +114,6 @@ export const ViewPeopleInSpaceAlertPage = withRouter(({ http, id }: Props) => { )} ) : ( - + ); }); diff --git a/x-pack/examples/ui_actions_enhanced_examples/public/containers/drilldowns_without_embeddable_example/drilldowns_without_embeddable_example.tsx b/x-pack/examples/ui_actions_enhanced_examples/public/containers/drilldowns_without_embeddable_example/drilldowns_without_embeddable_example.tsx index a0e1f38543c29..0941c1e2c8148 100644 --- a/x-pack/examples/ui_actions_enhanced_examples/public/containers/drilldowns_without_embeddable_example/drilldowns_without_embeddable_example.tsx +++ b/x-pack/examples/ui_actions_enhanced_examples/public/containers/drilldowns_without_embeddable_example/drilldowns_without_embeddable_example.tsx @@ -101,7 +101,7 @@ export const DrilldownsWithoutEmbeddableExample: React.FC = () => { {openManagerButton} { = { line: { strokeWidth: 1, - stroke: euiLightVars.euiColorSecondary, + stroke: euiLightVars.euiColorSuccess, opacity: 1, }, }; diff --git a/x-pack/plugins/apm/public/components/app/RumDashboard/URLFilter/URLSearch/render_option.tsx b/x-pack/plugins/apm/public/components/app/RumDashboard/URLFilter/URLSearch/render_option.tsx index 4a4d8e9d3e191..3293760ef7128 100644 --- a/x-pack/plugins/apm/public/components/app/RumDashboard/URLFilter/URLSearch/render_option.tsx +++ b/x-pack/plugins/apm/public/components/app/RumDashboard/URLFilter/URLSearch/render_option.tsx @@ -11,7 +11,7 @@ import styled from 'styled-components'; import { euiLightVars } from '@kbn/ui-shared-deps-src/theme'; const StyledSpan = styled.span` - color: ${euiLightVars.euiColorSecondaryText}; + color: ${euiLightVars.euiColorSuccessText}; font-weight: 500; :not(:last-of-type)::after { content: '•'; diff --git a/x-pack/plugins/apm/public/components/app/Settings/agent_configurations/AgentConfigurationCreateEdit/SettingsPage/SettingsPage.tsx b/x-pack/plugins/apm/public/components/app/Settings/agent_configurations/AgentConfigurationCreateEdit/SettingsPage/SettingsPage.tsx index 7623e467aaa2d..8789bbd772319 100644 --- a/x-pack/plugins/apm/public/components/app/Settings/agent_configurations/AgentConfigurationCreateEdit/SettingsPage/SettingsPage.tsx +++ b/x-pack/plugins/apm/public/components/app/Settings/agent_configurations/AgentConfigurationCreateEdit/SettingsPage/SettingsPage.tsx @@ -224,7 +224,7 @@ export function SettingsPage({ fill isLoading={isSaving} isDisabled={!isFormValid} - color="secondary" + color="success" iconType="check" > {i18n.translate( diff --git a/x-pack/plugins/apm/public/components/app/service_map/Popover/service_contents.tsx b/x-pack/plugins/apm/public/components/app/service_map/Popover/service_contents.tsx index f320123ce0723..5c41a1b4db7e6 100644 --- a/x-pack/plugins/apm/public/components/app/service_map/Popover/service_contents.tsx +++ b/x-pack/plugins/apm/public/components/app/service_map/Popover/service_contents.tsx @@ -97,7 +97,7 @@ export function ServiceContents({ - + {i18n.translate('xpack.apm.serviceMap.focusMapButtonText', { defaultMessage: 'Focus map', })} diff --git a/x-pack/plugins/apm/public/components/shared/charts/breakdown_chart/index.tsx b/x-pack/plugins/apm/public/components/shared/charts/breakdown_chart/index.tsx index 7f7c163ff1ea1..78bfd8911c351 100644 --- a/x-pack/plugins/apm/public/components/shared/charts/breakdown_chart/index.tsx +++ b/x-pack/plugins/apm/public/components/shared/charts/breakdown_chart/index.tsx @@ -81,7 +81,7 @@ export function BreakdownChart({ const xFormatter = niceTimeFormatter([min, max]); - const annotationColor = theme.eui.euiColorSecondary; + const annotationColor = theme.eui.euiColorSuccess; const isEmpty = isTimeseriesEmpty(timeseries); diff --git a/x-pack/plugins/apm/public/components/shared/charts/timeseries_chart.tsx b/x-pack/plugins/apm/public/components/shared/charts/timeseries_chart.tsx index bcdfff2678cda..29ef524508b02 100644 --- a/x-pack/plugins/apm/public/components/shared/charts/timeseries_chart.tsx +++ b/x-pack/plugins/apm/public/components/shared/charts/timeseries_chart.tsx @@ -105,7 +105,7 @@ export function TimeseriesChart({ const xFormatter = niceTimeFormatter([min, max]); const isEmpty = isTimeseriesEmpty(timeseries); - const annotationColor = theme.eui.euiColorSecondary; + const annotationColor = theme.eui.euiColorSuccess; const allSeries = [...timeseries, ...(anomalyTimeseries?.boundaries ?? [])]; const xDomain = isEmpty ? { min: 0, max: 1 } : { min, max }; diff --git a/x-pack/plugins/apm/public/components/shared/license_prompt/index.tsx b/x-pack/plugins/apm/public/components/shared/license_prompt/index.tsx index 0950cff5127fc..5d643614ba4d3 100644 --- a/x-pack/plugins/apm/public/components/shared/license_prompt/index.tsx +++ b/x-pack/plugins/apm/public/components/shared/license_prompt/index.tsx @@ -27,21 +27,19 @@ export function LicensePrompt({ {i18n.translate( diff --git a/x-pack/plugins/canvas/public/components/arg_form/arg_simple_form.tsx b/x-pack/plugins/canvas/public/components/arg_form/arg_simple_form.tsx index 84b87373c1c5a..df73c149a9111 100644 --- a/x-pack/plugins/canvas/public/components/arg_form/arg_simple_form.tsx +++ b/x-pack/plugins/canvas/public/components/arg_form/arg_simple_form.tsx @@ -52,7 +52,7 @@ export const ArgSimpleForm: React.FunctionComponent = ({ {!required && ( = (props) => { diff --git a/x-pack/plugins/canvas/public/components/datasource/__stories__/__snapshots__/datasource_component.stories.storyshot b/x-pack/plugins/canvas/public/components/datasource/__stories__/__snapshots__/datasource_component.stories.storyshot index 6e665f48b3e9a..7a34ee2b5aaad 100644 --- a/x-pack/plugins/canvas/public/components/datasource/__stories__/__snapshots__/datasource_component.stories.storyshot +++ b/x-pack/plugins/canvas/public/components/datasource/__stories__/__snapshots__/datasource_component.stories.storyshot @@ -118,7 +118,7 @@ exports[`Storyshots components/datasource/DatasourceComponent simple datasource className="euiFlexItem euiFlexItem--flexGrowZero" >
    ); diff --git a/x-pack/plugins/index_management/public/application/sections/home/data_stream_list/data_stream_table/data_stream_table.tsx b/x-pack/plugins/index_management/public/application/sections/home/data_stream_list/data_stream_table/data_stream_table.tsx index aa6ed7ae910f8..cbfe133b2909d 100644 --- a/x-pack/plugins/index_management/public/application/sections/home/data_stream_list/data_stream_table/data_stream_table.tsx +++ b/x-pack/plugins/index_management/public/application/sections/home/data_stream_list/data_stream_table/data_stream_table.tsx @@ -183,7 +183,7 @@ export const DataStreamTable: React.FunctionComponent = ({ ) : undefined, toolsRight: [ { loadIndices(); }} diff --git a/x-pack/plugins/index_management/public/application/sections/home/template_list/template_list.tsx b/x-pack/plugins/index_management/public/application/sections/home/template_list/template_list.tsx index 57f18134be5d6..2df312771ca12 100644 --- a/x-pack/plugins/index_management/public/application/sections/home/template_list/template_list.tsx +++ b/x-pack/plugins/index_management/public/application/sections/home/template_list/template_list.tsx @@ -162,7 +162,7 @@ export const TemplateList: React.FunctionComponent = (props) => { } )} iconSize="s" - color={'subdued'} + color="text" iconType={'crossInACircleFilled'} onClick={toggleWarningThreshold} /> diff --git a/x-pack/plugins/infra/public/alerting/inventory/components/metric.tsx b/x-pack/plugins/infra/public/alerting/inventory/components/metric.tsx index 7f8bcd6ae419b..3d9116905fb25 100644 --- a/x-pack/plugins/infra/public/alerting/inventory/components/metric.tsx +++ b/x-pack/plugins/infra/public/alerting/inventory/components/metric.tsx @@ -186,7 +186,7 @@ export const MetricExpression = ({ onClick={() => { setPopoverOpen(true); }} - color={errors.metric?.length ? 'danger' : 'secondary'} + color={errors.metric?.length ? 'danger' : 'success'} /> } isOpen={popoverOpen} diff --git a/x-pack/plugins/infra/public/alerting/log_threshold/components/expression_editor/criterion.tsx b/x-pack/plugins/infra/public/alerting/log_threshold/components/expression_editor/criterion.tsx index 47ba580c272bd..3dd092fa48b99 100644 --- a/x-pack/plugins/infra/public/alerting/log_threshold/components/expression_editor/criterion.tsx +++ b/x-pack/plugins/infra/public/alerting/log_threshold/components/expression_editor/criterion.tsx @@ -176,7 +176,7 @@ export const Criterion: React.FC = ({ uppercase={true} value={criterion.field ?? 'a chosen field'} isActive={isFieldPopoverOpen} - color={errors.field.length === 0 ? 'secondary' : 'danger'} + color={errors.field.length === 0 ? 'success' : 'danger'} onClick={(e) => { e.stopPropagation(); setIsFieldPopoverOpen(!isFieldPopoverOpen); @@ -227,7 +227,7 @@ export const Criterion: React.FC = ({ isActive={isComparatorPopoverOpen} color={ errors.comparator.length === 0 && errors.value.length === 0 - ? 'secondary' + ? 'success' : 'danger' } onClick={(e) => { diff --git a/x-pack/plugins/infra/public/alerting/log_threshold/components/expression_editor/editor.tsx b/x-pack/plugins/infra/public/alerting/log_threshold/components/expression_editor/editor.tsx index 2664a0d6aa2b0..02b827d5915dd 100644 --- a/x-pack/plugins/infra/public/alerting/log_threshold/components/expression_editor/editor.tsx +++ b/x-pack/plugins/infra/public/alerting/log_threshold/components/expression_editor/editor.tsx @@ -339,7 +339,7 @@ export default ExpressionEditor; // components. export const ExpressionLike = ({ text }: { text: string }) => { return ( -
    +
    {text}
    ); diff --git a/x-pack/plugins/infra/public/alerting/metric_threshold/components/expression_row.tsx b/x-pack/plugins/infra/public/alerting/metric_threshold/components/expression_row.tsx index 4dd191313261b..b4472b90efdb2 100644 --- a/x-pack/plugins/infra/public/alerting/metric_threshold/components/expression_row.tsx +++ b/x-pack/plugins/infra/public/alerting/metric_threshold/components/expression_row.tsx @@ -276,7 +276,7 @@ export const ExpressionRow: React.FC = (props) => { } )} iconSize="s" - color={'subdued'} + color="text" iconType={'crossInACircleFilled'} onClick={toggleWarningThreshold} /> diff --git a/x-pack/plugins/infra/public/components/logging/log_analysis_setup/setup_flyout/module_list_card.tsx b/x-pack/plugins/infra/public/components/logging/log_analysis_setup/setup_flyout/module_list_card.tsx index 5931e1cbe49ee..4424410f552c6 100644 --- a/x-pack/plugins/infra/public/components/logging/log_analysis_setup/setup_flyout/module_list_card.tsx +++ b/x-pack/plugins/infra/public/components/logging/log_analysis_setup/setup_flyout/module_list_card.tsx @@ -65,7 +65,7 @@ export const LogAnalysisModuleListCard: React.FC<{ moduleStatus.type === 'required' ? ( ) : ( - + ); const moduleSetupButton = diff --git a/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/single_metric_comparison.tsx b/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/single_metric_comparison.tsx index 8eed47c1a833e..fe9297b9409c7 100644 --- a/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/single_metric_comparison.tsx +++ b/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/single_metric_comparison.tsx @@ -29,14 +29,14 @@ export const SingleMetricComparison: React.FunctionComponent<{ return ( - {formatPercentage(changeFactor)} + {formatPercentage(changeFactor)} ); } else if (changeFactor > 0 && !Number.isFinite(changeFactor)) { return ( - {newCategoryTrendLabel} + {newCategoryTrendLabel} ); } diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/node_details/tabs/processes/processes_table.tsx b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/node_details/tabs/processes/processes_table.tsx index 427f67ec7a211..8c51fbf9d805b 100644 --- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/node_details/tabs/processes/processes_table.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/node_details/tabs/processes/processes_table.tsx @@ -202,7 +202,7 @@ const ProcessesTableBody = ({ items, currentTime }: TableBodyProps) => ( const cells = columns.map((column) => ( diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/node_details/tabs/processes/state_badge.tsx b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/node_details/tabs/processes/state_badge.tsx index c354ddcd55d71..47049c7d9c893 100644 --- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/node_details/tabs/processes/state_badge.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/node_details/tabs/processes/state_badge.tsx @@ -12,7 +12,7 @@ import { STATE_NAMES } from './states'; export const StateBadge = ({ state }: { state: string }) => { switch (state) { case 'running': - return {STATE_NAMES.running}; + return {STATE_NAMES.running}; case 'sleeping': return {STATE_NAMES.sleeping}; case 'dead': diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/node_details/tabs/properties/table.tsx b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/node_details/tabs/properties/table.tsx index 053e50ff87049..996e90c03f3db 100644 --- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/node_details/tabs/properties/table.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/node_details/tabs/properties/table.tsx @@ -65,7 +65,7 @@ export const Table = (props: Props) => { )} > = memo( const disabled = isEditorNotInIdleMode && !isMovingThisProcessor; const moveButton = ( = ({ onAddDocuments }) => - + - + {i18nTexts.addDocumentSuccessMessage} diff --git a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_form/pipeline_form.tsx b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_form/pipeline_form.tsx index 02fd7ec65957d..eeda40c96418c 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_form/pipeline_form.tsx +++ b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_form/pipeline_form.tsx @@ -138,7 +138,7 @@ export const PipelineForm: React.FunctionComponent = ({ = ({ diff --git a/x-pack/plugins/logstash/kibana.json b/x-pack/plugins/logstash/kibana.json index 2ff4aac9ba55b..48391c9bc68c4 100644 --- a/x-pack/plugins/logstash/kibana.json +++ b/x-pack/plugins/logstash/kibana.json @@ -11,5 +11,5 @@ "optionalPlugins": ["home", "monitoring", "security"], "server": true, "ui": true, - "requiredBundles": ["home"] + "requiredBundles": ["esUiShared", "home"] } diff --git a/x-pack/plugins/logstash/public/application/components/pipeline_editor/pipeline_editor.js b/x-pack/plugins/logstash/public/application/components/pipeline_editor/pipeline_editor.js index 334c7d0322a84..9d5f3b2d4af06 100644 --- a/x-pack/plugins/logstash/public/application/components/pipeline_editor/pipeline_editor.js +++ b/x-pack/plugins/logstash/public/application/components/pipeline_editor/pipeline_editor.js @@ -15,10 +15,10 @@ import 'brace/theme/github'; import { isEmpty } from 'lodash'; import { TOOLTIPS } from '../../../../common/constants/tooltips'; +import { EuiCodeEditor } from '../../../../../../../src/plugins/es_ui_shared/public'; import { EuiButton, EuiButtonEmpty, - EuiCodeEditor, EuiFlexGroup, EuiFieldNumber, EuiFlexItem, diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/__snapshots__/dynamic_color_property.test.tsx.snap b/x-pack/plugins/maps/public/classes/styles/vector/properties/__snapshots__/dynamic_color_property.test.tsx.snap index 58af4d009e43a..dba9fa59dd424 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/properties/__snapshots__/dynamic_color_property.test.tsx.snap +++ b/x-pack/plugins/maps/public/classes/styles/vector/properties/__snapshots__/dynamic_color_property.test.tsx.snap @@ -91,7 +91,7 @@ exports[`renderLegendDetailRow categorical Should render categorical legend with isPointsOnly={true} label={ Other diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/__snapshots__/dynamic_icon_property.test.tsx.snap b/x-pack/plugins/maps/public/classes/styles/vector/properties/__snapshots__/dynamic_icon_property.test.tsx.snap index 11a4fafda29e1..a3f23536326aa 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/properties/__snapshots__/dynamic_icon_property.test.tsx.snap +++ b/x-pack/plugins/maps/public/classes/styles/vector/properties/__snapshots__/dynamic_icon_property.test.tsx.snap @@ -71,7 +71,7 @@ exports[`renderLegendDetailRow Should render categorical legend with breaks 1`] isPointsOnly={true} label={ Other diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_color_property.tsx b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_color_property.tsx index cfb5d54720ce7..03800fa03827e 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_color_property.tsx +++ b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_color_property.tsx @@ -425,7 +425,7 @@ export class DynamicColorProperty extends DynamicStyleProperty{getOtherCategoryLabel()}, + label: {getOtherCategoryLabel()}, symbolId, }); } diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_icon_property.tsx b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_icon_property.tsx index 15672bda941be..b5d5e90efa45f 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_icon_property.tsx +++ b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_icon_property.tsx @@ -129,7 +129,7 @@ export class DynamicIconProperty extends DynamicStyleProperty{getOtherCategoryLabel()}, + label: {getOtherCategoryLabel()}, symbolId: fallbackSymbolId, }); } diff --git a/x-pack/plugins/maps/public/components/tooltip_selector/tooltip_selector.tsx b/x-pack/plugins/maps/public/components/tooltip_selector/tooltip_selector.tsx index dc3ad26b48e84..1a4c8e36b3457 100644 --- a/x-pack/plugins/maps/public/components/tooltip_selector/tooltip_selector.tsx +++ b/x-pack/plugins/maps/public/components/tooltip_selector/tooltip_selector.tsx @@ -217,7 +217,7 @@ export class TooltipSelector extends Component { { { = ({ isDisabled }) => { aria-label={i18n.translate('xpack.ml.importExport.importFlyout.deleteButtonAria', { defaultMessage: 'Delete', })} - color={deleteDisabled ? 'subdued' : 'danger'} + color={deleteDisabled ? 'text' : 'danger'} disabled={deleteDisabled} onClick={() => deleteJob(index)} /> diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/job_map/components/cytoscape_options.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/job_map/components/cytoscape_options.tsx index 4cd76b4e410c7..b7dc4d617427d 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/job_map/components/cytoscape_options.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/job_map/components/cytoscape_options.tsx @@ -65,7 +65,7 @@ function borderColorForNode(el: cytoscape.NodeSingular, theme: EuiThemeType) { switch (type) { case JOB_MAP_NODE_TYPES.ANALYTICS: - return theme.euiColorSecondary; + return theme.euiColorSuccess; case JOB_MAP_NODE_TYPES.TRANSFORM: return theme.euiColorVis1; case JOB_MAP_NODE_TYPES.INDEX: diff --git a/x-pack/plugins/ml/public/application/explorer/anomaly_context_menu.tsx b/x-pack/plugins/ml/public/application/explorer/anomaly_context_menu.tsx index d40e9cae1a04f..c32745f8bce8c 100644 --- a/x-pack/plugins/ml/public/application/explorer/anomaly_context_menu.tsx +++ b/x-pack/plugins/ml/public/application/explorer/anomaly_context_menu.tsx @@ -75,7 +75,7 @@ export const AnomalyContextMenu: FC = ({ aria-label={i18n.translate('xpack.ml.explorer.anomalies.actionsAriaLabel', { defaultMessage: 'Actions', })} - color="subdued" + color="text" iconType="boxesHorizontal" onClick={setIsMenuOpen.bind(null, !isMenuOpen)} data-test-subj="mlExplorerAnomalyPanelMenu" diff --git a/x-pack/plugins/ml/public/application/explorer/anomaly_timeline.tsx b/x-pack/plugins/ml/public/application/explorer/anomaly_timeline.tsx index 6091ab22692af..c8006292f8e09 100644 --- a/x-pack/plugins/ml/public/application/explorer/anomaly_timeline.tsx +++ b/x-pack/plugins/ml/public/application/explorer/anomaly_timeline.tsx @@ -184,7 +184,7 @@ export const AnomalyTimeline: FC = React.memo( aria-label={i18n.translate('xpack.ml.explorer.swimlaneActions', { defaultMessage: 'Actions', })} - color="subdued" + color="text" iconType="boxesHorizontal" onClick={setIsMenuOpen.bind(null, !isMenuOpen)} data-test-subj="mlAnomalyTimelinePanelMenu" diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/ml_job_editor/ml_job_editor.tsx b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/ml_job_editor/ml_job_editor.tsx index 96708e83dd8be..9ee583ba2d3e7 100644 --- a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/ml_job_editor/ml_job_editor.tsx +++ b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/ml_job_editor/ml_job_editor.tsx @@ -7,8 +7,12 @@ import React, { FC } from 'react'; -import { EuiCodeEditor, EuiCodeEditorProps } from '@elastic/eui'; -import { expandLiteralStrings, XJsonMode } from '../../../../../../shared_imports'; +import { + expandLiteralStrings, + XJsonMode, + EuiCodeEditor, + EuiCodeEditorProps, +} from '../../../../../../shared_imports'; export const ML_EDITOR_MODE = { TEXT: 'text', JSON: 'json', XJSON: new XJsonMode() }; diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/recognize/components/job_item.tsx b/x-pack/plugins/ml/public/application/jobs/new_job/recognize/components/job_item.tsx index 39d3eb634e9ce..53ffa593830e0 100644 --- a/x-pack/plugins/ml/public/application/jobs/new_job/recognize/components/job_item.tsx +++ b/x-pack/plugins/ml/public/application/jobs/new_job/recognize/components/job_item.tsx @@ -53,7 +53,7 @@ export const JobItem: FC = memo( - + {jobPrefix} {id} @@ -118,7 +118,7 @@ export const JobItem: FC = memo( = memo( = memo( - + {title} {success === false && error !== undefined && ( diff --git a/x-pack/plugins/ml/public/application/timeseriesexplorer/_timeseriesexplorer.scss b/x-pack/plugins/ml/public/application/timeseriesexplorer/_timeseriesexplorer.scss index cfd521c882fb7..63cb8a57adba6 100644 --- a/x-pack/plugins/ml/public/application/timeseriesexplorer/_timeseriesexplorer.scss +++ b/x-pack/plugins/ml/public/application/timeseriesexplorer/_timeseriesexplorer.scss @@ -10,7 +10,7 @@ } .entity-count-text { - color: $euiColorSecondary; + color: $euiColorSuccess; font-size: $euiFontSizeS; } } diff --git a/x-pack/plugins/ml/shared_imports.ts b/x-pack/plugins/ml/shared_imports.ts index 255a1e3c20d60..e70410c99a8f4 100644 --- a/x-pack/plugins/ml/shared_imports.ts +++ b/x-pack/plugins/ml/shared_imports.ts @@ -5,6 +5,9 @@ * 2.0. */ +export { EuiCodeEditor } from '../../../src/plugins/es_ui_shared/public'; +export type { EuiCodeEditorProps } from '../../../src/plugins/es_ui_shared/public'; + import { XJson } from '../../../src/plugins/es_ui_shared/public'; const { collapseLiteralStrings, expandLiteralStrings } = XJson; diff --git a/x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/components/__snapshots__/shard.test.js.snap b/x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/components/__snapshots__/shard.test.js.snap index dcad0937066d5..5c0294ffdc8d8 100644 --- a/x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/components/__snapshots__/shard.test.js.snap +++ b/x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/components/__snapshots__/shard.test.js.snap @@ -27,7 +27,7 @@ exports[`Shard should show for assigned replica shards 1`] = ` onMouseLeave={[Function]} > 0 diff --git a/x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/components/shard.js b/x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/components/shard.js index a81e1f8db5ec8..6676b71b4bf13 100644 --- a/x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/components/shard.js +++ b/x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/components/shard.js @@ -39,7 +39,7 @@ function getColor(classes) { } if (classList.includes('replica')) { - return 'secondary'; + return 'success'; } } diff --git a/x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/shard_allocation.js b/x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/shard_allocation.js index 7ca24853a9ccb..1c9021aeedf74 100644 --- a/x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/shard_allocation.js +++ b/x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/shard_allocation.js @@ -24,7 +24,7 @@ export const ShardAllocation = (props) => { label: i18n.translate('xpack.monitoring.elasticsearch.shardAllocation.replicaLabel', { defaultMessage: 'Replica', }), - color: 'secondary', + color: 'success', }, { label: i18n.translate('xpack.monitoring.elasticsearch.shardAllocation.relocatingLabel', { diff --git a/x-pack/plugins/monitoring/public/components/setup_mode/__snapshots__/tooltip.test.js.snap b/x-pack/plugins/monitoring/public/components/setup_mode/__snapshots__/tooltip.test.js.snap index 2a3a27cbc7c12..2edd5c1ab0cf2 100644 --- a/x-pack/plugins/monitoring/public/components/setup_mode/__snapshots__/tooltip.test.js.snap +++ b/x-pack/plugins/monitoring/public/components/setup_mode/__snapshots__/tooltip.test.js.snap @@ -127,7 +127,7 @@ exports[`setupMode SetupModeTooltip allMonitoredByMetricbeat should render for a position="top" > () => `generated-id`); describe('Summary Status Component', () => { it('should render metrics in a summary bar', () => { diff --git a/x-pack/plugins/observability/public/components/app/cases/callout/callout.test.tsx b/x-pack/plugins/observability/public/components/app/cases/callout/callout.test.tsx index 25d32d0cae884..6f48d429071ca 100644 --- a/x-pack/plugins/observability/public/components/app/cases/callout/callout.test.tsx +++ b/x-pack/plugins/observability/public/components/app/cases/callout/callout.test.tsx @@ -60,7 +60,7 @@ describe('Callout', () => { const className = wrapper.find(`button[data-test-subj="calloutDismiss-md5-hex"]`).first().prop('className') ?? ''; - expect(className.includes('euiButton--secondary')).toBeTruthy(); + expect(className.includes('euiButton--success')).toBeTruthy(); }); it('transform the button color correctly - warning', () => { diff --git a/x-pack/plugins/observability/public/components/app/cases/callout/callout.tsx b/x-pack/plugins/observability/public/components/app/cases/callout/callout.tsx index 15bd250c6ceb6..25c9643a22af9 100644 --- a/x-pack/plugins/observability/public/components/app/cases/callout/callout.tsx +++ b/x-pack/plugins/observability/public/components/app/cases/callout/callout.tsx @@ -39,7 +39,7 @@ function CallOutComponent({ {i18n.DISMISS_CALLOUT} diff --git a/x-pack/plugins/observability/public/components/shared/field_value_suggestions/field_value_selection.test.tsx b/x-pack/plugins/observability/public/components/shared/field_value_suggestions/field_value_selection.test.tsx index c142e50400e5f..3b9f6264c773a 100644 --- a/x-pack/plugins/observability/public/components/shared/field_value_suggestions/field_value_selection.test.tsx +++ b/x-pack/plugins/observability/public/components/shared/field_value_suggestions/field_value_selection.test.tsx @@ -9,6 +9,7 @@ import React from 'react'; import { mount, render } from 'enzyme'; import { FieldValueSelection } from './field_value_selection'; import { EuiButton, EuiSelectableList } from '@elastic/eui'; +import { EuiThemeProvider } from '../../../../../../../src/plugins/kibana_react/common'; const values = [ { label: 'elastic co frontend', count: 1 }, @@ -32,16 +33,19 @@ describe('FieldValueSelection', () => { expect(btn.text()).toBe('Service name'); }); + it('renders a list on click', async () => { const wrapper = mount( - {}} - selectedValue={[]} - loading={false} - setQuery={() => {}} - /> + + {}} + selectedValue={[]} + loading={false} + setQuery={() => {}} + /> + ); const btn = wrapper.find(EuiButton); diff --git a/x-pack/plugins/osquery/public/action_results/services/agent_status.tsx b/x-pack/plugins/osquery/public/action_results/services/agent_status.tsx index 39a033f49ec90..1a2c9f370bc31 100644 --- a/x-pack/plugins/osquery/public/action_results/services/agent_status.tsx +++ b/x-pack/plugins/osquery/public/action_results/services/agent_status.tsx @@ -14,7 +14,7 @@ const visColors = euiPaletteColorBlindBehindText(); const colorToHexMap = { default: '#d3dae6', primary: visColors[1], - secondary: visColors[0], + success: visColors[0], accent: visColors[2], warning: visColors[5], danger: visColors[9], @@ -25,7 +25,7 @@ export const AGENT_STATUSES: ActionAgentStatus[] = ['success', 'pending', 'faile export function getColorForAgentStatus(agentStatus: ActionAgentStatus): string { switch (agentStatus) { case 'success': - return colorToHexMap.secondary; + return colorToHexMap.success; case 'pending': return colorToHexMap.default; case 'failed': diff --git a/x-pack/plugins/osquery/public/editor/index.tsx b/x-pack/plugins/osquery/public/editor/index.tsx index 7d6823acec2cd..df78d45d0cc93 100644 --- a/x-pack/plugins/osquery/public/editor/index.tsx +++ b/x-pack/plugins/osquery/public/editor/index.tsx @@ -6,10 +6,11 @@ */ import React, { useEffect, useState } from 'react'; -import { EuiCodeEditor } from '@elastic/eui'; import useDebounce from 'react-use/lib/useDebounce'; import 'brace/theme/tomorrow'; +import { EuiCodeEditor } from '../shared_imports'; + import './osquery_mode.ts'; const EDITOR_SET_OPTIONS = { diff --git a/x-pack/plugins/osquery/public/shared_imports.ts b/x-pack/plugins/osquery/public/shared_imports.ts index 227a276c41f18..c0f9d35ba51a8 100644 --- a/x-pack/plugins/osquery/public/shared_imports.ts +++ b/x-pack/plugins/osquery/public/shared_imports.ts @@ -40,3 +40,6 @@ export { } from '../../../../src/plugins/es_ui_shared/static/forms/components'; export { fieldValidators } from '../../../../src/plugins/es_ui_shared/static/forms/helpers'; export type { ERROR_CODE } from '../../../../src/plugins/es_ui_shared/static/forms/helpers/field_validators/types'; + +export { EuiCodeEditor } from '../../../../src/plugins/es_ui_shared/public'; +export type { EuiCodeEditorProps } from '../../../../src/plugins/es_ui_shared/public'; diff --git a/x-pack/plugins/painless_lab/public/application/components/output_pane/output_pane.tsx b/x-pack/plugins/painless_lab/public/application/components/output_pane/output_pane.tsx index 258c6bcdb1beb..8391ccbbe7ef4 100644 --- a/x-pack/plugins/painless_lab/public/application/components/output_pane/output_pane.tsx +++ b/x-pack/plugins/painless_lab/public/application/components/output_pane/output_pane.tsx @@ -34,7 +34,7 @@ export const OutputPane: FunctionComponent = ({ isLoading, response }) => ) : response && response.error ? ( ) : ( - + )} diff --git a/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/remote_cluster_form.tsx b/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/remote_cluster_form.tsx index 766f12fedc81c..fdcbf220331d7 100644 --- a/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/remote_cluster_form.tsx +++ b/x-pack/plugins/remote_clusters/public/application/sections/components/remote_cluster_form/remote_cluster_form.tsx @@ -20,7 +20,7 @@ import { EuiForm, EuiFormRow, EuiLink, - EuiLoadingKibana, + EuiLoadingLogo, EuiLoadingSpinner, EuiOverlayMask, EuiSpacer, @@ -348,7 +348,7 @@ export class RemoteClusterForm extends Component { { if (this.props.isSaving) { return ( - + ); } diff --git a/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_list/remote_cluster_list.js b/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_list/remote_cluster_list.js index b94ae8f7edbc0..b6881aa02e0b9 100644 --- a/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_list/remote_cluster_list.js +++ b/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_list/remote_cluster_list.js @@ -13,7 +13,7 @@ import { EuiButton, EuiButtonEmpty, EuiEmptyPrompt, - EuiLoadingKibana, + EuiLoadingLogo, EuiOverlayMask, EuiPageContent, EuiSpacer, @@ -80,7 +80,7 @@ export class RemoteClusterList extends Component { if (isCopyingCluster || isRemovingCluster) { return ( - + ); } diff --git a/x-pack/plugins/rollup/public/crud_app/sections/job_create/job_create.js b/x-pack/plugins/rollup/public/crud_app/sections/job_create/job_create.js index 6f22345dc1cec..22d6f74c0aee5 100644 --- a/x-pack/plugins/rollup/public/crud_app/sections/job_create/job_create.js +++ b/x-pack/plugins/rollup/public/crud_app/sections/job_create/job_create.js @@ -16,7 +16,7 @@ import { withKibana } from '../../../../../../../src/plugins/kibana_react/public import { EuiCallOut, - EuiLoadingKibana, + EuiLoadingLogo, EuiOverlayMask, EuiPageContentBody, EuiPageHeader, @@ -494,7 +494,7 @@ export class JobCreateUi extends Component { if (isSaving) { savingFeedback = ( - + ); } diff --git a/x-pack/plugins/rollup/public/crud_app/sections/job_create/navigation/navigation.js b/x-pack/plugins/rollup/public/crud_app/sections/job_create/navigation/navigation.js index 6afb864fedbe4..e9c324cd5f87e 100644 --- a/x-pack/plugins/rollup/public/crud_app/sections/job_create/navigation/navigation.js +++ b/x-pack/plugins/rollup/public/crud_app/sections/job_create/navigation/navigation.js @@ -79,7 +79,7 @@ export const Navigation = ({ const saveButton = ( +

    { render: (creation: string, item: ApiKey) => ( {item.id === createdApiKey?.id ? ( - + { return ( - + diff --git a/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/json_rule_editor.tsx b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/json_rule_editor.tsx index 86f7892e49d24..176d66049eade 100644 --- a/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/json_rule_editor.tsx +++ b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/rule_editor_panel/json_rule_editor.tsx @@ -5,6 +5,7 @@ * 2.0. */ +import 'react-ace'; import 'brace/mode/json'; import 'brace/theme/github'; diff --git a/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/role_mappings_grid_page.tsx b/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/role_mappings_grid_page.tsx index 373f3366f36c8..c983f2c704f4a 100644 --- a/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/role_mappings_grid_page.tsx +++ b/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/role_mappings_grid_page.tsx @@ -255,7 +255,7 @@ export class RoleMappingsGridPage extends Component { ) : undefined, toolsRight: ( this.reloadRoleMappings()} data-test-subj="reloadButton" diff --git a/x-pack/plugins/security_solution/public/cases/components/callout/callout.test.tsx b/x-pack/plugins/security_solution/public/cases/components/callout/callout.test.tsx index 0a0caa40a8783..01c581f5401ba 100644 --- a/x-pack/plugins/security_solution/public/cases/components/callout/callout.test.tsx +++ b/x-pack/plugins/security_solution/public/cases/components/callout/callout.test.tsx @@ -60,7 +60,7 @@ describe('Callout', () => { const className = wrapper.find(`button[data-test-subj="callout-dismiss-md5-hex"]`).first().prop('className') ?? ''; - expect(className.includes('euiButton--secondary')).toBeTruthy(); + expect(className.includes('euiButton--success')).toBeTruthy(); }); it('transform the button color correctly - warning', () => { diff --git a/x-pack/plugins/security_solution/public/cases/components/callout/callout.tsx b/x-pack/plugins/security_solution/public/cases/components/callout/callout.tsx index f00fa84c6ff0a..d0493ec7acb9c 100644 --- a/x-pack/plugins/security_solution/public/cases/components/callout/callout.tsx +++ b/x-pack/plugins/security_solution/public/cases/components/callout/callout.tsx @@ -37,11 +37,7 @@ const CallOutComponent = ({ return showCallOut && !isEmpty(messages) ? ( - + {i18n.DISMISS_CALLOUT} diff --git a/x-pack/plugins/security_solution/public/common/components/callouts/callout_dismiss_button.tsx b/x-pack/plugins/security_solution/public/common/components/callouts/callout_dismiss_button.tsx index c657ee243b74b..b00072be6cc5f 100644 --- a/x-pack/plugins/security_solution/public/common/components/callouts/callout_dismiss_button.tsx +++ b/x-pack/plugins/security_solution/public/common/components/callouts/callout_dismiss_button.tsx @@ -23,7 +23,7 @@ export const CallOutDismissButton: FC = ({ onClick = noop, }) => { const { type } = message; - const buttonColor = type === 'success' ? 'secondary' : type; + const buttonColor = type; const buttonText = text ?? i18n.DISMISS_BUTTON; const handleClick = useCallback(() => onClick(message), [onClick, message]); diff --git a/x-pack/plugins/security_solution/public/common/components/header_page/editable_title.tsx b/x-pack/plugins/security_solution/public/common/components/header_page/editable_title.tsx index 487e0fe4981f1..3744297ded56a 100644 --- a/x-pack/plugins/security_solution/public/common/components/header_page/editable_title.tsx +++ b/x-pack/plugins/security_solution/public/common/components/header_page/editable_title.tsx @@ -77,7 +77,7 @@ const EditableTitleComponent: React.FC = ({ - secondary + success { {'primary'} - - {'secondary'} + + {'success'} {'danger'} diff --git a/x-pack/plugins/security_solution/public/common/components/item_details_card/index.test.tsx b/x-pack/plugins/security_solution/public/common/components/item_details_card/index.test.tsx index 12264e28d40c9..7fce50284d0d9 100644 --- a/x-pack/plugins/security_solution/public/common/components/item_details_card/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/item_details_card/index.test.tsx @@ -60,8 +60,8 @@ describe('item_details_card', () => { {'primary'} - - {'secondary'} + + {'success'} {'danger'} diff --git a/x-pack/plugins/security_solution/public/common/components/paginated_table/__snapshots__/index.test.tsx.snap b/x-pack/plugins/security_solution/public/common/components/paginated_table/__snapshots__/index.test.tsx.snap index 3440e5f4488c6..a2fffc32be46d 100644 --- a/x-pack/plugins/security_solution/public/common/components/paginated_table/__snapshots__/index.test.tsx.snap +++ b/x-pack/plugins/security_solution/public/common/components/paginated_table/__snapshots__/index.test.tsx.snap @@ -22,28 +22,36 @@ exports[`Paginated Table Component rendering it renders the default load more ta Array [ Object { "field": "node.host.name", - "hideForMobile": false, + "mobileOptions": Object { + "show": true, + }, "name": "Host", "render": [Function], "truncateText": false, }, Object { "field": "node.host.firstSeen", - "hideForMobile": false, + "mobileOptions": Object { + "show": true, + }, "name": "First seen", "render": [Function], "truncateText": false, }, Object { "field": "node.host.os", - "hideForMobile": false, + "mobileOptions": Object { + "show": true, + }, "name": "OS", "render": [Function], "truncateText": false, }, Object { "field": "node.host.version", - "hideForMobile": false, + "mobileOptions": Object { + "show": true, + }, "name": "Version", "render": [Function], "truncateText": false, diff --git a/x-pack/plugins/security_solution/public/common/components/paginated_table/index.mock.tsx b/x-pack/plugins/security_solution/public/common/components/paginated_table/index.mock.tsx index 070c8a8d53b43..2d728ffa915fc 100644 --- a/x-pack/plugins/security_solution/public/common/components/paginated_table/index.mock.tsx +++ b/x-pack/plugins/security_solution/public/common/components/paginated_table/index.mock.tsx @@ -57,28 +57,28 @@ export const getHostsColumns = (): [ field: 'node.host.name', name: 'Host', truncateText: false, - hideForMobile: false, + mobileOptions: { show: true }, render: (name: string) => getOrEmptyTagFromValue(name), }, { field: 'node.host.firstSeen', name: 'First seen', truncateText: false, - hideForMobile: false, + mobileOptions: { show: true }, render: (firstSeen: string) => getOrEmptyTagFromValue(firstSeen), }, { field: 'node.host.os', name: 'OS', truncateText: false, - hideForMobile: false, + mobileOptions: { show: true }, render: (os: string) => getOrEmptyTagFromValue(os), }, { field: 'node.host.version', name: 'Version', truncateText: false, - hideForMobile: false, + mobileOptions: { show: true }, render: (version: string) => getOrEmptyTagFromValue(version), }, ]; diff --git a/x-pack/plugins/security_solution/public/common/components/paginated_table/index.tsx b/x-pack/plugins/security_solution/public/common/components/paginated_table/index.tsx index f5828c9f65db9..ef49c8e2a5e8c 100644 --- a/x-pack/plugins/security_solution/public/common/components/paginated_table/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/paginated_table/index.tsx @@ -17,6 +17,7 @@ import { EuiLoadingContent, EuiPagination, EuiPopover, + EuiTableRowCellProps, } from '@elastic/eui'; import { noop } from 'lodash/fp'; import React, { FC, memo, useState, useMemo, useEffect, ComponentType } from 'react'; @@ -126,8 +127,7 @@ type Func = (arg: T) => string | number; export interface Columns { align?: string; field?: string; - hideForMobile?: boolean; - isMobileHeader?: boolean; + mobileOptions?: EuiTableRowCellProps['mobileOptions']; name: string | React.ReactNode; render?: (item: T, node: U) => React.ReactNode; sortable?: boolean | Func; diff --git a/x-pack/plugins/security_solution/public/common/components/progress_inline/__snapshots__/index.test.tsx.snap b/x-pack/plugins/security_solution/public/common/components/progress_inline/__snapshots__/index.test.tsx.snap index e1fc1becd0188..bf36bf1afeef3 100644 --- a/x-pack/plugins/security_solution/public/common/components/progress_inline/__snapshots__/index.test.tsx.snap +++ b/x-pack/plugins/security_solution/public/common/components/progress_inline/__snapshots__/index.test.tsx.snap @@ -13,7 +13,7 @@ exports[`ProgressInline it renders 1`] = ` className="siemProgressInline__bar" > diff --git a/x-pack/plugins/security_solution/public/common/components/progress_inline/index.tsx b/x-pack/plugins/security_solution/public/common/components/progress_inline/index.tsx index bbea27f5a705a..7b7e24bf8707b 100644 --- a/x-pack/plugins/security_solution/public/common/components/progress_inline/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/progress_inline/index.tsx @@ -38,7 +38,7 @@ export const ProgressInline = React.memo(

    {children}
    - +
    diff --git a/x-pack/plugins/security_solution/public/detections/components/rules/description_step/ml_job_description.tsx b/x-pack/plugins/security_solution/public/detections/components/rules/description_step/ml_job_description.tsx index 27afe847f7612..4b61504ec997a 100644 --- a/x-pack/plugins/security_solution/public/detections/components/rules/description_step/ml_job_description.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/rules/description_step/ml_job_description.tsx @@ -51,7 +51,7 @@ export const AuditIcon = React.memo(AuditIconComponent); const JobStatusBadgeComponent: React.FC<{ job: MlSummaryJob }> = ({ job }) => { const isStarted = isJobStarted(job.jobState, job.datafeedState); - const color = isStarted ? 'secondary' : 'danger'; + const color = isStarted ? 'success' : 'danger'; const text = isStarted ? ML_JOB_STARTED : ML_JOB_STOPPED; return ( diff --git a/x-pack/plugins/security_solution/public/hosts/components/authentications_table/index.tsx b/x-pack/plugins/security_solution/public/hosts/components/authentications_table/index.tsx index 23e5da28a3559..65357b15036ea 100644 --- a/x-pack/plugins/security_solution/public/hosts/components/authentications_table/index.tsx +++ b/x-pack/plugins/security_solution/public/hosts/components/authentications_table/index.tsx @@ -140,7 +140,7 @@ const getAuthenticationColumns = (): AuthTableColumns => [ { name: i18n.USER, truncateText: false, - hideForMobile: false, + mobileOptions: { show: true }, render: ({ node }) => getRowItemDraggables({ rowItems: node.user.name, @@ -151,7 +151,7 @@ const getAuthenticationColumns = (): AuthTableColumns => [ { name: i18n.SUCCESSES, truncateText: false, - hideForMobile: false, + mobileOptions: { show: true }, render: ({ node }) => { const id = escapeDataProviderId( `authentications-table-${node._id}-node-successes-${node.successes}` @@ -189,7 +189,7 @@ const getAuthenticationColumns = (): AuthTableColumns => [ { name: i18n.FAILURES, truncateText: false, - hideForMobile: false, + mobileOptions: { show: true }, render: ({ node }) => { const id = escapeDataProviderId( `authentications-table-${node._id}-failures-${node.failures}` @@ -227,7 +227,7 @@ const getAuthenticationColumns = (): AuthTableColumns => [ { name: i18n.LAST_SUCCESSFUL_TIME, truncateText: false, - hideForMobile: false, + mobileOptions: { show: true }, render: ({ node }) => has('lastSuccess.timestamp', node) && node.lastSuccess?.timestamp != null ? ( @@ -238,7 +238,7 @@ const getAuthenticationColumns = (): AuthTableColumns => [ { name: i18n.LAST_SUCCESSFUL_SOURCE, truncateText: false, - hideForMobile: false, + mobileOptions: { show: true }, render: ({ node }) => getRowItemDraggables({ rowItems: node.lastSuccess?.source?.ip || null, @@ -250,7 +250,7 @@ const getAuthenticationColumns = (): AuthTableColumns => [ { name: i18n.LAST_SUCCESSFUL_DESTINATION, truncateText: false, - hideForMobile: false, + mobileOptions: { show: true }, render: ({ node }) => getRowItemDraggables({ rowItems: node.lastSuccess?.host?.name ?? null, @@ -262,7 +262,7 @@ const getAuthenticationColumns = (): AuthTableColumns => [ { name: i18n.LAST_FAILED_TIME, truncateText: false, - hideForMobile: false, + mobileOptions: { show: true }, render: ({ node }) => has('lastFailure.timestamp', node) && node.lastFailure?.timestamp != null ? ( @@ -273,7 +273,7 @@ const getAuthenticationColumns = (): AuthTableColumns => [ { name: i18n.LAST_FAILED_SOURCE, truncateText: false, - hideForMobile: false, + mobileOptions: { show: true }, render: ({ node }) => getRowItemDraggables({ rowItems: node.lastFailure?.source?.ip || null, @@ -285,7 +285,7 @@ const getAuthenticationColumns = (): AuthTableColumns => [ { name: i18n.LAST_FAILED_DESTINATION, truncateText: false, - hideForMobile: false, + mobileOptions: { show: true }, render: ({ node }) => getRowItemDraggables({ rowItems: node.lastFailure?.host?.name || null, diff --git a/x-pack/plugins/security_solution/public/hosts/components/hosts_table/columns.tsx b/x-pack/plugins/security_solution/public/hosts/components/hosts_table/columns.tsx index d6c51b2bfe05e..95f88da0a24ac 100644 --- a/x-pack/plugins/security_solution/public/hosts/components/hosts_table/columns.tsx +++ b/x-pack/plugins/security_solution/public/hosts/components/hosts_table/columns.tsx @@ -31,7 +31,7 @@ export const getHostsColumns = (): HostsTableColumns => [ field: 'node.host.name', name: i18n.NAME, truncateText: false, - hideForMobile: false, + mobileOptions: { show: true }, sortable: true, render: (hostName) => { if (hostName != null && hostName.length > 0) { @@ -75,7 +75,7 @@ export const getHostsColumns = (): HostsTableColumns => [ ), truncateText: false, - hideForMobile: false, + mobileOptions: { show: true }, sortable: true, render: (lastSeen: Maybe | undefined) => { if (lastSeen != null && lastSeen.length > 0) { @@ -92,7 +92,7 @@ export const getHostsColumns = (): HostsTableColumns => [ field: 'node.host.os.name', name: i18n.OS, truncateText: false, - hideForMobile: false, + mobileOptions: { show: true }, sortable: false, render: (hostOsName) => { if (hostOsName != null) { @@ -109,7 +109,7 @@ export const getHostsColumns = (): HostsTableColumns => [ field: 'node.host.os.version', name: i18n.VERSION, truncateText: false, - hideForMobile: false, + mobileOptions: { show: true }, sortable: false, render: (hostOsVersion) => { if (hostOsVersion != null) { diff --git a/x-pack/plugins/security_solution/public/hosts/components/uncommon_process_table/index.tsx b/x-pack/plugins/security_solution/public/hosts/components/uncommon_process_table/index.tsx index 0541f2f1d403d..0af27bdb0ba18 100644 --- a/x-pack/plugins/security_solution/public/hosts/components/uncommon_process_table/index.tsx +++ b/x-pack/plugins/security_solution/public/hosts/components/uncommon_process_table/index.tsx @@ -144,7 +144,7 @@ const getUncommonColumns = (): UncommonProcessTableColumns => [ { name: i18n.NAME, truncateText: false, - hideForMobile: false, + mobileOptions: { show: true }, render: ({ node }) => getRowItemDraggables({ rowItems: node.process.name, @@ -157,7 +157,7 @@ const getUncommonColumns = (): UncommonProcessTableColumns => [ align: 'right', name: i18n.NUMBER_OF_HOSTS, truncateText: false, - hideForMobile: false, + mobileOptions: { show: true }, render: ({ node }) => <>{node.hosts != null ? node.hosts.length : getEmptyValue()}, width: '8%', }, @@ -165,14 +165,14 @@ const getUncommonColumns = (): UncommonProcessTableColumns => [ align: 'right', name: i18n.NUMBER_OF_INSTANCES, truncateText: false, - hideForMobile: false, + mobileOptions: { show: true }, render: ({ node }) => defaultToEmptyTag(node.instances), width: '8%', }, { name: i18n.HOSTS, truncateText: false, - hideForMobile: false, + mobileOptions: { show: true }, render: ({ node }) => getRowItemDraggables({ rowItems: getHostNames(node), @@ -185,7 +185,7 @@ const getUncommonColumns = (): UncommonProcessTableColumns => [ { name: i18n.LAST_COMMAND, truncateText: false, - hideForMobile: false, + mobileOptions: { show: true }, render: ({ node }) => getRowItemDraggables({ rowItems: node.process != null ? node.process.args : null, @@ -198,7 +198,7 @@ const getUncommonColumns = (): UncommonProcessTableColumns => [ { name: i18n.LAST_USER, truncateText: false, - hideForMobile: false, + mobileOptions: { show: true }, render: ({ node }) => getRowItemDraggables({ rowItems: node.user != null ? node.user.name : null, diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/host_constants.ts b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/host_constants.ts index 8e0e4fd969c22..8fa4a9388e08e 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/host_constants.ts +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/host_constants.ts @@ -11,7 +11,7 @@ import { HostStatus, HostPolicyResponseActionStatus } from '../../../../../commo export const HOST_STATUS_TO_BADGE_COLOR = Object.freeze<{ [key in HostStatus]: string; }>({ - [HostStatus.HEALTHY]: 'secondary', + [HostStatus.HEALTHY]: 'success', [HostStatus.UNHEALTHY]: 'warning', [HostStatus.UPDATING]: 'primary', [HostStatus.OFFLINE]: 'default', @@ -22,7 +22,7 @@ export const HOST_STATUS_TO_BADGE_COLOR = Object.freeze<{ export const POLICY_STATUS_TO_HEALTH_COLOR = Object.freeze<{ [key in keyof typeof HostPolicyResponseActionStatus]: string; }>({ - success: 'secondary', + success: 'success', warning: 'warning', failure: 'danger', unsupported: 'default', @@ -31,7 +31,7 @@ export const POLICY_STATUS_TO_HEALTH_COLOR = Object.freeze<{ export const POLICY_STATUS_TO_BADGE_COLOR = Object.freeze<{ [key in keyof typeof HostPolicyResponseActionStatus]: string; }>({ - success: 'secondary', + success: 'success', warning: 'warning', failure: 'danger', unsupported: 'default', diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_forms/locked_card.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_forms/locked_card.tsx index 150ae5e82ef55..cd13e2f933526 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_forms/locked_card.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_forms/locked_card.tsx @@ -35,9 +35,11 @@ export const LockedPolicyCard = memo(({ title }: { title: string }) => { } title={ diff --git a/x-pack/plugins/security_solution/public/network/components/network_dns_table/columns.tsx b/x-pack/plugins/security_solution/public/network/components/network_dns_table/columns.tsx index 03c2442982fc9..4dcdc92983168 100644 --- a/x-pack/plugins/security_solution/public/network/components/network_dns_table/columns.tsx +++ b/x-pack/plugins/security_solution/public/network/components/network_dns_table/columns.tsx @@ -34,7 +34,7 @@ export const getNetworkDnsColumns = (): NetworkDnsColumns => [ field: `node.${NetworkDnsFields.dnsName}`, name: i18n.REGISTERED_DOMAIN, truncateText: false, - hideForMobile: false, + mobileOptions: { show: true }, sortable: true, render: (dnsName) => { if (dnsName != null) { @@ -77,7 +77,7 @@ export const getNetworkDnsColumns = (): NetworkDnsColumns => [ name: i18n.TOTAL_QUERIES, sortable: true, truncateText: false, - hideForMobile: false, + mobileOptions: { show: true }, render: (queryCount) => { if (queryCount != null) { return numeral(queryCount).format('0'); @@ -92,7 +92,7 @@ export const getNetworkDnsColumns = (): NetworkDnsColumns => [ name: i18n.UNIQUE_DOMAINS, sortable: true, truncateText: false, - hideForMobile: false, + mobileOptions: { show: true }, render: (uniqueDomains) => { if (uniqueDomains != null) { return numeral(uniqueDomains).format('0'); @@ -107,7 +107,7 @@ export const getNetworkDnsColumns = (): NetworkDnsColumns => [ name: i18n.DNS_BYTES_IN, sortable: true, truncateText: false, - hideForMobile: false, + mobileOptions: { show: true }, render: (dnsBytesIn) => { if (dnsBytesIn != null) { return ; @@ -122,7 +122,7 @@ export const getNetworkDnsColumns = (): NetworkDnsColumns => [ name: i18n.DNS_BYTES_OUT, sortable: true, truncateText: false, - hideForMobile: false, + mobileOptions: { show: true }, render: (dnsBytesOut) => { if (dnsBytesOut != null) { return ; diff --git a/x-pack/plugins/security_solution/public/network/components/tls_table/columns.tsx b/x-pack/plugins/security_solution/public/network/components/tls_table/columns.tsx index 7a45c418a4ff0..6641927082b6b 100644 --- a/x-pack/plugins/security_solution/public/network/components/tls_table/columns.tsx +++ b/x-pack/plugins/security_solution/public/network/components/tls_table/columns.tsx @@ -32,7 +32,7 @@ export const getTlsColumns = (tableId: string): TlsColumns => [ field: 'node', name: i18n.ISSUER, truncateText: false, - hideForMobile: false, + mobileOptions: { show: true }, sortable: false, render: ({ _id, issuers }) => getRowItemDraggables({ @@ -45,7 +45,7 @@ export const getTlsColumns = (tableId: string): TlsColumns => [ field: 'node', name: i18n.SUBJECT, truncateText: false, - hideForMobile: false, + mobileOptions: { show: true }, sortable: false, render: ({ _id, subjects }) => getRowItemDraggables({ @@ -58,7 +58,7 @@ export const getTlsColumns = (tableId: string): TlsColumns => [ field: 'node._id', name: i18n.SHA1_FINGERPRINT, truncateText: false, - hideForMobile: false, + mobileOptions: { show: true }, sortable: true, render: (sha1) => getRowItemDraggable({ @@ -71,7 +71,7 @@ export const getTlsColumns = (tableId: string): TlsColumns => [ field: 'node', name: i18n.JA3_FINGERPRINT, truncateText: false, - hideForMobile: false, + mobileOptions: { show: true }, sortable: false, render: ({ _id, ja3 }) => getRowItemDraggables({ @@ -84,7 +84,7 @@ export const getTlsColumns = (tableId: string): TlsColumns => [ field: 'node', name: i18n.VALID_UNTIL, truncateText: false, - hideForMobile: false, + mobileOptions: { show: true }, sortable: false, render: ({ _id, notAfter }) => getRowItemDraggables({ diff --git a/x-pack/plugins/security_solution/public/network/components/users_table/columns.tsx b/x-pack/plugins/security_solution/public/network/components/users_table/columns.tsx index 473d014686795..4068c616228f2 100644 --- a/x-pack/plugins/security_solution/public/network/components/users_table/columns.tsx +++ b/x-pack/plugins/security_solution/public/network/components/users_table/columns.tsx @@ -28,7 +28,7 @@ export const getUsersColumns = (flowTarget: FlowTarget, tableId: string): UsersC field: 'node.user.name', name: i18n.USER_NAME, truncateText: false, - hideForMobile: false, + mobileOptions: { show: true }, sortable: true, render: (userName) => getRowItemDraggable({ @@ -41,7 +41,7 @@ export const getUsersColumns = (flowTarget: FlowTarget, tableId: string): UsersC field: 'node.user.id', name: i18n.USER_ID, truncateText: false, - hideForMobile: false, + mobileOptions: { show: true }, sortable: false, render: (userIds) => getRowItemDraggables({ @@ -54,7 +54,7 @@ export const getUsersColumns = (flowTarget: FlowTarget, tableId: string): UsersC field: 'node.user.groupName', name: i18n.GROUP_NAME, truncateText: false, - hideForMobile: false, + mobileOptions: { show: true }, sortable: false, render: (groupNames) => getRowItemDraggables({ @@ -67,7 +67,7 @@ export const getUsersColumns = (flowTarget: FlowTarget, tableId: string): UsersC field: 'node.user.groupId', name: i18n.GROUP_ID, truncateText: false, - hideForMobile: false, + mobileOptions: { show: true }, sortable: false, render: (groupId) => getRowItemDraggables({ @@ -81,7 +81,7 @@ export const getUsersColumns = (flowTarget: FlowTarget, tableId: string): UsersC field: 'node.user.count', name: i18n.DOCUMENT_COUNT, truncateText: false, - hideForMobile: false, + mobileOptions: { show: true }, sortable: true, render: (docCount) => defaultToEmptyTag(docCount), }, diff --git a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/note_previews/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/note_previews/index.tsx index 1016a430807be..7693efad0730d 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/note_previews/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/note_previews/index.tsx @@ -66,7 +66,7 @@ const ToggleEventDetailsButtonComponent: React.FC diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/footer/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/footer/index.tsx index 80a682293dbba..c11aaa3b17370 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/footer/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/footer/index.tsx @@ -387,7 +387,7 @@ export const FooterComponent = ({ {i18n.AUTO_REFRESH_ACTIVE}{' '} [ field: `node.${HostRulesFields.ruleName}`, name: i18n.NAME, truncateText: false, - hideForMobile: false, + mobileOptions: { show: true }, render: (ruleName) => { if (ruleName != null && ruleName.length > 0) { const id = escapeDataProviderId(`ueba-table-ruleName-${ruleName}`); @@ -63,7 +63,7 @@ export const getHostRulesColumns = (): HostRulesColumns => [ field: `node.${HostRulesFields.ruleType}`, name: i18n.RULE_TYPE, truncateText: false, - hideForMobile: false, + mobileOptions: { show: true }, render: (ruleType) => { if (ruleType != null && ruleType.length > 0) { const id = escapeDataProviderId(`ueba-table-ruleType-${ruleType}`); @@ -102,7 +102,7 @@ export const getHostRulesColumns = (): HostRulesColumns => [ field: `node.${HostRulesFields.riskScore}`, name: i18n.RISK_SCORE, truncateText: false, - hideForMobile: false, + mobileOptions: { show: true }, render: (riskScore) => { if (riskScore != null) { const id = escapeDataProviderId(`ueba-table-riskScore-${riskScore}`); @@ -141,7 +141,7 @@ export const getHostRulesColumns = (): HostRulesColumns => [ field: `node.${HostRulesFields.hits}`, name: i18n.HITS, truncateText: false, - hideForMobile: false, + mobileOptions: { show: true }, sortable: false, render: (hits) => { if (hits != null) { diff --git a/x-pack/plugins/security_solution/public/ueba/components/host_tactics_table/columns.tsx b/x-pack/plugins/security_solution/public/ueba/components/host_tactics_table/columns.tsx index 19516ad6fcafa..68e1195a9c7eb 100644 --- a/x-pack/plugins/security_solution/public/ueba/components/host_tactics_table/columns.tsx +++ b/x-pack/plugins/security_solution/public/ueba/components/host_tactics_table/columns.tsx @@ -24,7 +24,7 @@ export const getHostTacticsColumns = (): HostTacticsColumns => [ field: `node.${HostTacticsFields.tactic}`, name: i18n.TACTIC, truncateText: false, - hideForMobile: false, + mobileOptions: { show: true }, render: (tactic) => { if (tactic != null && tactic.length > 0) { const id = escapeDataProviderId(`ueba-table-tactic-${tactic}`); @@ -63,7 +63,7 @@ export const getHostTacticsColumns = (): HostTacticsColumns => [ field: `node.${HostTacticsFields.technique}`, name: i18n.TECHNIQUE, truncateText: false, - hideForMobile: false, + mobileOptions: { show: true }, render: (technique) => { if (technique != null && technique.length > 0) { const id = escapeDataProviderId(`ueba-table-technique-${technique}`); @@ -102,7 +102,7 @@ export const getHostTacticsColumns = (): HostTacticsColumns => [ field: `node.${HostTacticsFields.riskScore}`, name: i18n.RISK_SCORE, truncateText: false, - hideForMobile: false, + mobileOptions: { show: true }, render: (riskScore) => { if (riskScore != null) { const id = escapeDataProviderId(`ueba-table-riskScore-${riskScore}`); @@ -141,7 +141,7 @@ export const getHostTacticsColumns = (): HostTacticsColumns => [ field: `node.${HostTacticsFields.hits}`, name: i18n.HITS, truncateText: false, - hideForMobile: false, + mobileOptions: { show: true }, sortable: false, render: (hits) => { if (hits != null) { diff --git a/x-pack/plugins/security_solution/public/ueba/components/risk_score_table/columns.tsx b/x-pack/plugins/security_solution/public/ueba/components/risk_score_table/columns.tsx index b751521001fe5..43512d6717363 100644 --- a/x-pack/plugins/security_solution/public/ueba/components/risk_score_table/columns.tsx +++ b/x-pack/plugins/security_solution/public/ueba/components/risk_score_table/columns.tsx @@ -27,7 +27,7 @@ export const getRiskScoreColumns = (): RiskScoreColumns => [ field: 'node.host_name', name: i18n.NAME, truncateText: false, - hideForMobile: false, + mobileOptions: { show: true }, sortable: true, render: (hostName) => { if (hostName != null && hostName.length > 0) { @@ -63,7 +63,7 @@ export const getRiskScoreColumns = (): RiskScoreColumns => [ field: 'node.risk_keyword', name: i18n.CURRENT_RISK, truncateText: false, - hideForMobile: false, + mobileOptions: { show: true }, sortable: false, render: (riskKeyword) => { if (riskKeyword != null) { diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/policy_form.tsx b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/policy_form.tsx index f3ce07cd732ca..185d3bb90bae5 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/policy_form.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/policy_form.tsx @@ -193,7 +193,7 @@ export const PolicyForm: React.FunctionComponent = ({ savePolicy()} isLoading={isSaving} diff --git a/x-pack/plugins/snapshot_restore/public/application/components/repository_form/step_two.tsx b/x-pack/plugins/snapshot_restore/public/application/components/repository_form/step_two.tsx index 011b8e883316c..a985a6dee0bae 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/repository_form/step_two.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/repository_form/step_two.tsx @@ -143,7 +143,7 @@ export const RepositoryFormStepTwo: React.FunctionComponent = ({ )} = ({ executeRestore()} isLoading={isSaving} diff --git a/x-pack/plugins/snapshot_restore/public/application/sections/home/policy_list/policy_details/policy_details.tsx b/x-pack/plugins/snapshot_restore/public/application/sections/home/policy_list/policy_details/policy_details.tsx index 0a283d406e5aa..33f83ca30c04e 100644 --- a/x-pack/plugins/snapshot_restore/public/application/sections/home/policy_list/policy_details/policy_details.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/sections/home/policy_list/policy_details/policy_details.tsx @@ -307,7 +307,7 @@ export const PolicyDetails: React.FunctionComponent = ({ {policyName}{' '} = ({ toolsRight: [ = ({ toolsRight: [ { data-test-subj={`cts-summary-success-count`} title={summarizedResults.successCount} titleSize="s" - titleColor={initialCopyFinished ? 'secondary' : 'subdued'} + titleColor={initialCopyFinished ? 'success' : 'subdued'} isLoading={!initialCopyFinished} textAlign="center" description={ diff --git a/x-pack/plugins/spaces/public/share_saved_objects_to_space/components/share_mode_control.tsx b/x-pack/plugins/spaces/public/share_saved_objects_to_space/components/share_mode_control.tsx index 2740533e52715..45a2d3f4964b1 100644 --- a/x-pack/plugins/spaces/public/share_saved_objects_to_space/components/share_mode_control.tsx +++ b/x-pack/plugins/spaces/public/share_saved_objects_to_space/components/share_mode_control.tsx @@ -139,7 +139,7 @@ export const ShareModeControl = (props: Props) => { onChange(updatedSpaceIds); }} legend={buttonGroupLegend} - color="secondary" + color="success" isFullWidth={true} isDisabled={!canShareToAllSpaces} /> diff --git a/x-pack/plugins/stack_alerts/public/alert_types/es_query/expression.test.tsx b/x-pack/plugins/stack_alerts/public/alert_types/es_query/expression.test.tsx index 51c2f0471d486..ad624c345272d 100644 --- a/x-pack/plugins/stack_alerts/public/alert_types/es_query/expression.test.tsx +++ b/x-pack/plugins/stack_alerts/public/alert_types/es_query/expression.test.tsx @@ -22,7 +22,6 @@ import { useKibana } from '../../../../../../src/plugins/kibana_react/public'; import { EsQueryAlertParams } from './types'; jest.mock('../../../../../../src/plugins/kibana_react/public'); -jest.mock('../../../../../../src/plugins/es_ui_shared/public'); jest.mock('../../../../../../src/plugins/es_ui_shared/public', () => ({ XJson: { useXJsonMode: jest.fn().mockReturnValue({ @@ -31,26 +30,18 @@ jest.mock('../../../../../../src/plugins/es_ui_shared/public', () => ({ xJson: jest.fn(), }), }, + // Mocking EuiCodeEditor, which uses React Ace under the hood + // eslint-disable-next-line @typescript-eslint/no-explicit-any + EuiCodeEditor: (props: any) => ( + { + props.onChange(syntheticEvent.jsonString); + }} + /> + ), })); -jest.mock(''); -jest.mock('@elastic/eui', () => { - const original = jest.requireActual('@elastic/eui'); - - return { - ...original, - // Mocking EuiCodeEditor, which uses React Ace under the hood - // eslint-disable-next-line @typescript-eslint/no-explicit-any - EuiCodeEditor: (props: any) => ( - { - props.onChange(syntheticEvent.jsonString); - }} - /> - ), - }; -}); jest.mock('../../../../triggers_actions_ui/public', () => { const original = jest.requireActual('../../../../triggers_actions_ui/public'); return { diff --git a/x-pack/plugins/stack_alerts/public/alert_types/es_query/expression.tsx b/x-pack/plugins/stack_alerts/public/alert_types/es_query/expression.tsx index 4cba80a9a541a..b98df85e0b8a0 100644 --- a/x-pack/plugins/stack_alerts/public/alert_types/es_query/expression.tsx +++ b/x-pack/plugins/stack_alerts/public/alert_types/es_query/expression.tsx @@ -9,12 +9,11 @@ import React, { useState, Fragment, useEffect } from 'react'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import 'brace/theme/github'; import { XJsonMode } from '@kbn/ace'; +import 'brace/theme/github'; import { EuiButtonEmpty, - EuiCodeEditor, EuiSpacer, EuiFormRow, EuiCallOut, @@ -25,7 +24,7 @@ import { import { DocLinksStart, HttpSetup } from 'kibana/public'; import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; -import { XJson } from '../../../../../../src/plugins/es_ui_shared/public'; +import { XJson, EuiCodeEditor } from '../../../../../../src/plugins/es_ui_shared/public'; import { useKibana } from '../../../../../../src/plugins/kibana_react/public'; import { getFields, diff --git a/x-pack/plugins/timelines/public/components/t_grid/event_rendered_view/index.tsx b/x-pack/plugins/timelines/public/components/t_grid/event_rendered_view/index.tsx index 6267c9d3a4953..3caa53988c005 100644 --- a/x-pack/plugins/timelines/public/components/t_grid/event_rendered_view/index.tsx +++ b/x-pack/plugins/timelines/public/components/t_grid/event_rendered_view/index.tsx @@ -115,7 +115,7 @@ const EventRenderedViewComponent = ({ field: 'actions', name: ActionTitle, truncateText: false, - hideForMobile: false, + mobileOptions: { show: true }, render: (name: unknown, item: unknown) => { const alertId = get(item, '_id'); const rowIndex = events.findIndex((evt) => evt._id === alertId); @@ -147,7 +147,7 @@ const EventRenderedViewComponent = ({ defaultMessage: 'Timestamp', }), truncateText: false, - hideForMobile: false, + mobileOptions: { show: true }, render: (name: unknown, item: TimelineItem) => { const timestamp = get(item, `ecs.timestamp`); return ; @@ -159,7 +159,7 @@ const EventRenderedViewComponent = ({ defaultMessage: 'Rule', }), truncateText: false, - hideForMobile: false, + mobileOptions: { show: true }, render: (name: unknown, item: TimelineItem) => { const ruleName = get(item, `ecs.signal.rule.name`); /* `ecs.${ALERT_RULE_NAME}`*/ const ruleId = get(item, `ecs.signal.rule.id`); /* `ecs.${ALERT_RULE_ID}`*/ @@ -172,7 +172,7 @@ const EventRenderedViewComponent = ({ defaultMessage: 'Event Summary', }), truncateText: false, - hideForMobile: false, + mobileOptions: { show: true }, render: (name: unknown, item: TimelineItem) => { const ecsData = get(item, 'ecs'); const reason = get(item, `ecs.signal.reason`); /* `ecs.${ALERT_REASON}`*/ diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/refresh_transform_list_button/refresh_transform_list_button.tsx b/x-pack/plugins/transform/public/app/sections/transform_management/components/refresh_transform_list_button/refresh_transform_list_button.tsx index f9f5f79bf4620..183847362851b 100644 --- a/x-pack/plugins/transform/public/app/sections/transform_management/components/refresh_transform_list_button/refresh_transform_list_button.tsx +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/refresh_transform_list_button/refresh_transform_list_button.tsx @@ -19,7 +19,7 @@ export const RefreshTransformListButton: FC = ({ isLoading, }) => ( = ({ {onTestConnector && ( = ({ { @@ -408,7 +408,7 @@ const ConnectorEditFlyout = ({ = ({
    = ({ {filteredDeprecations.length === 0 ? ( - + {i18nTexts.noDeprecationsMessage} diff --git a/x-pack/plugins/uptime/public/components/common/charts/monitor_bar_series.tsx b/x-pack/plugins/uptime/public/components/common/charts/monitor_bar_series.tsx index 08cac07250fea..145ec5f199db4 100644 --- a/x-pack/plugins/uptime/public/components/common/charts/monitor_bar_series.tsx +++ b/x-pack/plugins/uptime/public/components/common/charts/monitor_bar_series.tsx @@ -114,7 +114,7 @@ export const MonitorBarSeries = ({ histogramSeries, minInterval }: MonitorBarSer /> } > - -- + -- ); }; diff --git a/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_status.tsx b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_status.tsx index 3a4ee53f63223..dcf3fdb9163db 100644 --- a/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_status.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/ping_list/columns/ping_status.tsx @@ -50,7 +50,7 @@ export const PingStatusColumn = ({ pingStatus, item }: Props) => {
    {getPingStatusLabel(pingStatus, item)} diff --git a/x-pack/plugins/uptime/public/components/monitor/ping_list/ping_redirects.tsx b/x-pack/plugins/uptime/public/components/monitor/ping_list/ping_redirects.tsx index b1a36b1c0d61b..01e0cb5be2b0f 100644 --- a/x-pack/plugins/uptime/public/components/monitor/ping_list/ping_redirects.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/ping_list/ping_redirects.tsx @@ -37,7 +37,7 @@ export const PingRedirects: React.FC = ({ monitorStatus, showTitle }) => size: 's', target: '_blank', extraAction: { - color: 'subdued', + color: 'text', iconType: 'popout', iconSize: 's', alwaysShow: true, @@ -56,7 +56,7 @@ export const PingRedirects: React.FC = ({ monitorStatus, showTitle }) => size: 's', target: '_blank', extraAction: { - color: 'subdued', + color: 'text', iconType: 'popout', iconSize: 's', 'aria-label': i18n.translate('xpack.uptime.monitorList.redirects.openWindow', { diff --git a/x-pack/plugins/uptime/public/components/monitor/status_details/availability_reporting/__snapshots__/tag_label.test.tsx.snap b/x-pack/plugins/uptime/public/components/monitor/status_details/availability_reporting/__snapshots__/tag_label.test.tsx.snap index 2e55e7024f444..345a8f2786d41 100644 --- a/x-pack/plugins/uptime/public/components/monitor/status_details/availability_reporting/__snapshots__/tag_label.test.tsx.snap +++ b/x-pack/plugins/uptime/public/components/monitor/status_details/availability_reporting/__snapshots__/tag_label.test.tsx.snap @@ -36,7 +36,7 @@ exports[`TagLabel component renders correctly against snapshot 1`] = ` exports[`TagLabel component shallow render correctly against snapshot 1`] = ` US-East diff --git a/x-pack/plugins/uptime/public/components/monitor/status_details/availability_reporting/tag_label.tsx b/x-pack/plugins/uptime/public/components/monitor/status_details/availability_reporting/tag_label.tsx index a53beb60ab410..6bf73b9609e58 100644 --- a/x-pack/plugins/uptime/public/components/monitor/status_details/availability_reporting/tag_label.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/status_details/availability_reporting/tag_label.tsx @@ -23,7 +23,7 @@ const BadgeItem = styled.div` export const TagLabel: React.FC = ({ color, label, status }) => { return ( - {label} + {label} ); }; diff --git a/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/middle_truncated_text.tsx b/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/middle_truncated_text.tsx index 311a496bd58a3..3e3b08f49d705 100644 --- a/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/middle_truncated_text.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/middle_truncated_text.tsx @@ -145,7 +145,7 @@ export const MiddleTruncatedText = ({ { +): 'primary' | 'success' | 'subdued' | 'danger' => { if (isInvalid === true) return 'danger'; if (isEnabled === false) return 'subdued'; - return isOpen ? 'primary' : 'secondary'; + return isOpen ? 'primary' : 'success'; }; export const AlertExpressionPopover: React.FC = ({ diff --git a/x-pack/plugins/uptime/public/components/overview/alerts/alert_tls.tsx b/x-pack/plugins/uptime/public/components/overview/alerts/alert_tls.tsx index e2de834a379b5..f7cd341e04dae 100644 --- a/x-pack/plugins/uptime/public/components/overview/alerts/alert_tls.tsx +++ b/x-pack/plugins/uptime/public/components/overview/alerts/alert_tls.tsx @@ -23,7 +23,7 @@ export const AlertTlsComponent: React.FC = (props) => ( diff --git a/x-pack/plugins/uptime/public/components/overview/alerts/monitor_expressions/__snapshots__/down_number_select.test.tsx.snap b/x-pack/plugins/uptime/public/components/overview/alerts/monitor_expressions/__snapshots__/down_number_select.test.tsx.snap index bf56ebd0de236..f9e169b976d1d 100644 --- a/x-pack/plugins/uptime/public/components/overview/alerts/monitor_expressions/__snapshots__/down_number_select.test.tsx.snap +++ b/x-pack/plugins/uptime/public/components/overview/alerts/monitor_expressions/__snapshots__/down_number_select.test.tsx.snap @@ -10,7 +10,7 @@ exports[`DownNoExpressionSelect component should renders against props 1`] = ` > = button={ setIsOpen(!isOpen)} diff --git a/x-pack/plugins/uptime/public/components/overview/monitor_list/columns/monitor_status_column.tsx b/x-pack/plugins/uptime/public/components/overview/monitor_list/columns/monitor_status_column.tsx index f5581f75b3759..6960bb5632852 100644 --- a/x-pack/plugins/uptime/public/components/overview/monitor_list/columns/monitor_status_column.tsx +++ b/x-pack/plugins/uptime/public/components/overview/monitor_list/columns/monitor_status_column.tsx @@ -162,7 +162,7 @@ export const MonitorListStatusColumn = ({ {getHealthMessage(status)} diff --git a/x-pack/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/monitor_status_row.tsx b/x-pack/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/monitor_status_row.tsx index 03655d11c983d..15e40773ae6df 100644 --- a/x-pack/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/monitor_status_row.tsx +++ b/x-pack/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/monitor_status_row.tsx @@ -23,7 +23,7 @@ interface MonitorStatusRowProps { } export const MonitorStatusRow = ({ locationNames, status }: MonitorStatusRowProps) => { - const color = status === STATUS.UP ? 'secondary' : 'danger'; + const color = status === STATUS.UP ? 'success' : 'danger'; let checkListArray = [...locationNames]; // If un-named location exists, move it to end diff --git a/x-pack/plugins/watcher/public/application/components/watch_status.tsx b/x-pack/plugins/watcher/public/application/components/watch_status.tsx index 5c1fd39b5b486..8c6ea0e01b357 100644 --- a/x-pack/plugins/watcher/public/application/components/watch_status.tsx +++ b/x-pack/plugins/watcher/public/application/components/watch_status.tsx @@ -17,7 +17,7 @@ function StatusIcon({ status }: { status: string }) { case WATCH_STATES.OK: case ACTION_STATES.OK: case ACTION_STATES.ACKNOWLEDGED: - return ; + return ; case ACTION_STATES.THROTTLED: return ; case WATCH_STATES.DISABLED: diff --git a/x-pack/plugins/watcher/public/application/sections/watch_edit/components/json_watch_edit/json_watch_edit_form.tsx b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/json_watch_edit/json_watch_edit_form.tsx index b19d97f67d2e0..c59147d7e7ce6 100644 --- a/x-pack/plugins/watcher/public/application/sections/watch_edit/components/json_watch_edit/json_watch_edit_form.tsx +++ b/x-pack/plugins/watcher/public/application/sections/watch_edit/components/json_watch_edit/json_watch_edit_form.tsx @@ -197,7 +197,7 @@ export const JsonWatchEditForm = () => { { onClick={() => { setAggFieldPopoverOpen(true); }} - color={watch.aggField ? 'secondary' : 'danger'} + color={watch.aggField ? 'success' : 'danger'} /> } isOpen={aggFieldPopoverOpen} @@ -617,7 +617,7 @@ export const ThresholdWatchEdit = ({ pageTitle }: { pageTitle: string }) => { }} color={ watch.groupBy === 'all' || (watch.termSize && watch.termField) - ? 'secondary' + ? 'success' : 'danger' } /> @@ -730,7 +730,7 @@ export const ThresholdWatchEdit = ({ pageTitle }: { pageTitle: string }) => { color={ errors.threshold0.length || (errors.threshold1 && errors.threshold1.length) ? 'danger' - : 'secondary' + : 'success' } /> } @@ -816,7 +816,7 @@ export const ThresholdWatchEdit = ({ pageTitle }: { pageTitle: string }) => { onClick={() => { setWatchDurationPopoverOpen(true); }} - color={watch.timeWindowSize ? 'secondary' : 'danger'} + color={watch.timeWindowSize ? 'success' : 'danger'} /> } isOpen={watchDurationPopoverOpen} @@ -890,7 +890,7 @@ export const ThresholdWatchEdit = ({ pageTitle }: { pageTitle: string }) => { Date: Thu, 18 Nov 2021 13:33:33 -0500 Subject: [PATCH 121/148] [CTI] explicit threat_indicator_path for IM rules (#118821) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../indicator_match_rule.spec.ts | 5 ++ .../security_solution/cypress/objects/rule.ts | 2 + .../cypress/screens/rule_details.ts | 2 + .../rules/step_about_rule/index.test.tsx | 58 ++++++++++++++++ .../rules/step_about_rule/index.tsx | 29 ++++++-- .../rules/step_about_rule/schema.tsx | 30 +++++++++ .../rules/create_rules.mock.ts | 66 +++++++++++++++++++ .../rules/create_rules.test.ts | 36 +++++++++- .../detection_engine/rules/create_rules.ts | 10 ++- 9 files changed, 231 insertions(+), 7 deletions(-) diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_rules/indicator_match_rule.spec.ts b/x-pack/plugins/security_solution/cypress/integration/detection_rules/indicator_match_rule.spec.ts index 378de8f0bc593..ef6db14dba896 100644 --- a/x-pack/plugins/security_solution/cypress/integration/detection_rules/indicator_match_rule.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/detection_rules/indicator_match_rule.spec.ts @@ -40,6 +40,7 @@ import { INDICATOR_INDEX_PATTERNS, INDICATOR_INDEX_QUERY, INDICATOR_MAPPING, + INDICATOR_PREFIX_OVERRIDE, INVESTIGATION_NOTES_MARKDOWN, INVESTIGATION_NOTES_TOGGLE, MITRE_ATTACK_DETAILS, @@ -448,6 +449,10 @@ describe('indicator match', () => { cy.get(ABOUT_DETAILS).within(() => { getDetails(SEVERITY_DETAILS).should('have.text', getNewThreatIndicatorRule().severity); getDetails(RISK_SCORE_DETAILS).should('have.text', getNewThreatIndicatorRule().riskScore); + getDetails(INDICATOR_PREFIX_OVERRIDE).should( + 'have.text', + getNewThreatIndicatorRule().threatIndicatorPath + ); getDetails(REFERENCE_URLS_DETAILS).should((details) => { expect(removeExternalLinkText(details.text())).equal(expectedUrls); }); diff --git a/x-pack/plugins/security_solution/cypress/objects/rule.ts b/x-pack/plugins/security_solution/cypress/objects/rule.ts index 0a9eecf83c7fc..1c81099d43dd5 100644 --- a/x-pack/plugins/security_solution/cypress/objects/rule.ts +++ b/x-pack/plugins/security_solution/cypress/objects/rule.ts @@ -77,6 +77,7 @@ export interface ThreatIndicatorRule extends CustomRule { indicatorIndexPattern: string[]; indicatorMappingField: string; indicatorIndexField: string; + threatIndicatorPath: string; type?: string; atomic?: string; } @@ -405,6 +406,7 @@ export const getNewThreatIndicatorRule = (): ThreatIndicatorRule => ({ atomic: 'a04ac6d98ad989312783d4fe3456c53730b212c79a426fb215708b6c6daa3de3', timeline: getIndicatorMatchTimelineTemplate(), maxSignals: 100, + threatIndicatorPath: 'threat.indicator', }); export const duplicatedRuleName = `${getNewThreatIndicatorRule().name} [Duplicate]`; diff --git a/x-pack/plugins/security_solution/cypress/screens/rule_details.ts b/x-pack/plugins/security_solution/cypress/screens/rule_details.ts index fb1fded1fe8a6..cdad6096ece1f 100644 --- a/x-pack/plugins/security_solution/cypress/screens/rule_details.ts +++ b/x-pack/plugins/security_solution/cypress/screens/rule_details.ts @@ -64,6 +64,8 @@ export const RULE_NAME_OVERRIDE_DETAILS = 'Rule name override'; export const RISK_SCORE_DETAILS = 'Risk score'; +export const INDICATOR_PREFIX_OVERRIDE = 'Indicator prefix override'; + export const RISK_SCORE_OVERRIDE_DETAILS = 'Risk score override'; export const REFERENCE_URLS_DETAILS = 'Reference URLs'; diff --git a/x-pack/plugins/security_solution/public/detections/components/rules/step_about_rule/index.test.tsx b/x-pack/plugins/security_solution/public/detections/components/rules/step_about_rule/index.test.tsx index 9340ca2af1513..01ba47f728e43 100644 --- a/x-pack/plugins/security_solution/public/detections/components/rules/step_about_rule/index.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/rules/step_about_rule/index.test.tsx @@ -20,6 +20,7 @@ import { AboutStepRule, RuleStepsFormHooks, RuleStep, + DefineStepRule, } from '../../../pages/detection_engine/rules/types'; import { fillEmptySeverityMappings } from '../../../pages/detection_engine/rules/helpers'; import { getMockTheme } from '../../../../common/lib/kibana/kibana_react.mock'; @@ -105,6 +106,63 @@ describe.skip('StepAboutRuleComponent', () => { }); }); + it('is invalid if threat match rule and threat_indicator_path is not present', async () => { + const wrapper = mount( + + + + ); + + await act(async () => { + if (!formHook) { + throw new Error('Form hook not set, but tests depend on it'); + } + wrapper + .find('[data-test-subj="detectionEngineStepAboutThreatIndicatorPath"] input') + .first() + .simulate('change', { target: { value: '' } }); + + const result = await formHook(); + expect(result?.isValid).toEqual(false); + }); + }); + + it('is valid if is not a threat match rule and threat_indicator_path is not present', async () => { + const wrapper = mount( + + + + ); + + await act(async () => { + if (!formHook) { + throw new Error('Form hook not set, but tests depend on it'); + } + wrapper + .find('[data-test-subj="detectionEngineStepAboutThreatIndicatorPath"] input') + .first() + .simulate('change', { target: { value: '' } }); + + const result = await formHook(); + expect(result?.isValid).toEqual(true); + }); + }); + it('is invalid if no "name" is present', async () => { const wrapper = mount( diff --git a/x-pack/plugins/security_solution/public/detections/components/rules/step_about_rule/index.tsx b/x-pack/plugins/security_solution/public/detections/components/rules/step_about_rule/index.tsx index 91e428382dc30..5f5b636d6afe1 100644 --- a/x-pack/plugins/security_solution/public/detections/components/rules/step_about_rule/index.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/rules/step_about_rule/index.tsx @@ -6,7 +6,7 @@ */ import { EuiAccordion, EuiFlexItem, EuiSpacer, EuiFormRow } from '@elastic/eui'; -import React, { FC, memo, useCallback, useEffect, useState } from 'react'; +import React, { FC, memo, useCallback, useEffect, useState, useMemo } from 'react'; import styled from 'styled-components'; import { @@ -31,7 +31,7 @@ import { import { defaultRiskScoreBySeverity, severityOptions } from './data'; import { stepAboutDefaultValue } from './default_value'; import { isUrlInvalid } from '../../../../common/utils/validators'; -import { schema } from './schema'; +import { schema as defaultSchema, threatIndicatorPathRequiredSchemaValue } from './schema'; import * as I18n from './translations'; import { StepContentWrapper } from '../step_content_wrapper'; import { NextStep } from '../next_step'; @@ -73,7 +73,28 @@ const StepAboutRuleComponent: FC = ({ onSubmit, setForm, }) => { - const initialState = defaultValues ?? stepAboutDefaultValue; + const isThreatMatchRuleValue = useMemo( + () => isThreatMatchRule(defineRuleData?.ruleType), + [defineRuleData?.ruleType] + ); + + const initialState: AboutStepRule = useMemo( + () => + defaultValues ?? + (isThreatMatchRuleValue + ? { ...stepAboutDefaultValue, threatIndicatorPath: DEFAULT_INDICATOR_SOURCE_PATH } + : stepAboutDefaultValue), + [defaultValues, isThreatMatchRuleValue] + ); + + const schema = useMemo( + () => + isThreatMatchRuleValue + ? { ...defaultSchema, threatIndicatorPath: threatIndicatorPathRequiredSchemaValue } + : defaultSchema, + [isThreatMatchRuleValue] + ); + const [severityValue, setSeverityValue] = useState(initialState.severity.value); const [indexPatternLoading, { indexPatterns }] = useFetchIndex(defineRuleData?.index ?? []); @@ -300,7 +321,7 @@ const StepAboutRuleComponent: FC = ({ /> - {isThreatMatchRule(defineRuleData?.ruleType) && ( + {isThreatMatchRuleValue && ( <> = { labelAppend: OptionalFieldLabel, }, }; + +export const threatIndicatorPathRequiredSchemaValue = { + type: FIELD_TYPES.TEXT, + label: i18n.translate( + 'xpack.securitySolution.detectionEngine.createRule.stepAboutRule.fieldThreatIndicatorPathLabel', + { + defaultMessage: 'Indicator prefix override', + } + ), + helpText: i18n.translate( + 'xpack.securitySolution.detectionEngine.createRule.stepAboutRule.fieldThreatIndicatorPathHelpText', + { + defaultMessage: + 'Specify the document prefix containing your indicator fields. Used for enrichment of indicator match alerts.', + } + ), + validations: [ + { + validator: emptyField( + i18n.translate( + 'xpack.securitySolution.detectionEngine.createRule.stepAboutRule.threatIndicatorPathFieldEmptyError', + { + defaultMessage: 'Indicator prefix override must not be empty', + } + ) + ), + type: VALIDATION_TYPES.FIELD, + }, + ], +}; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/create_rules.mock.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/create_rules.mock.ts index 2c25134cc3760..c3e15b061842e 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/create_rules.mock.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/create_rules.mock.ts @@ -117,3 +117,69 @@ export const getCreateMlRulesOptionsMock = ( exceptionsList: [], actions: [], }); + +export const getCreateThreatMatchRulesOptionsMock = ( + isRuleRegistryEnabled: boolean +): CreateRulesOptions => ({ + actions: [], + anomalyThreshold: undefined, + author: ['Elastic'], + buildingBlockType: undefined, + concurrentSearches: undefined, + description: 'some description', + enabled: true, + eventCategoryOverride: undefined, + exceptionsList: [], + falsePositives: ['false positive 1', 'false positive 2'], + filters: [], + from: 'now-1m', + immutable: false, + index: ['*'], + interval: '5m', + isRuleRegistryEnabled, + itemsPerSearch: undefined, + language: 'kuery', + license: 'Elastic License', + machineLearningJobId: undefined, + maxSignals: 100, + meta: {}, + name: 'Query with a rule id', + note: '# sample markdown', + outputIndex: 'output-1', + query: 'user.name: root or user.name: admin', + references: ['http://www.example.com'], + riskScore: 80, + riskScoreMapping: [], + ruleId: 'rule-1', + ruleNameOverride: undefined, + rulesClient: rulesClientMock.create(), + savedId: 'savedId-123', + severity: 'high', + severityMapping: [], + tags: [], + threat: [], + threatFilters: undefined, + threatIndex: ['filebeat-*'], + threatIndicatorPath: 'threat.indicator', + threatLanguage: 'kuery', + threatMapping: [ + { + entries: [ + { + field: 'file.hash.md5', + type: 'mapping', + value: 'threat.indicator.file.hash.md5', + }, + ], + }, + ], + threatQuery: '*:*', + threshold: undefined, + throttle: null, + timelineId: 'timelineid-123', + timelineTitle: 'timeline-title-123', + timestampOverride: undefined, + to: 'now', + type: 'threat_match', + version: 1, +}); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/create_rules.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/create_rules.test.ts index 0fd708791712a..3d5619ab1306b 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/create_rules.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/create_rules.test.ts @@ -6,7 +6,11 @@ */ import { createRules } from './create_rules'; -import { getCreateMlRulesOptionsMock } from './create_rules.mock'; +import { + getCreateMlRulesOptionsMock, + getCreateThreatMatchRulesOptionsMock, +} from './create_rules.mock'; +import { DEFAULT_INDICATOR_SOURCE_PATH } from '../../../../common/constants'; describe.each([ ['Legacy', false], @@ -44,4 +48,34 @@ describe.each([ }) ); }); + + it('populates a threatIndicatorPath value for threat_match rule if empty', async () => { + const ruleOptions = getCreateThreatMatchRulesOptionsMock(isRuleRegistryEnabled); + delete ruleOptions.threatIndicatorPath; + await createRules(ruleOptions); + expect(ruleOptions.rulesClient.create).toHaveBeenCalledWith( + expect.objectContaining({ + data: expect.objectContaining({ + params: expect.objectContaining({ + threatIndicatorPath: DEFAULT_INDICATOR_SOURCE_PATH, + }), + }), + }) + ); + }); + + it('does not populate a threatIndicatorPath value for other rules if empty', async () => { + const ruleOptions = getCreateMlRulesOptionsMock(isRuleRegistryEnabled); + delete ruleOptions.threatIndicatorPath; + await createRules(ruleOptions); + expect(ruleOptions.rulesClient.create).not.toHaveBeenCalledWith( + expect.objectContaining({ + data: expect.objectContaining({ + params: expect.objectContaining({ + threatIndicatorPath: DEFAULT_INDICATOR_SOURCE_PATH, + }), + }), + }) + ); + }); }); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/create_rules.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/create_rules.ts index 1d0010b38578d..5ff5358fbc4cd 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/create_rules.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/create_rules.ts @@ -13,7 +13,11 @@ import { } from '../../../../common/detection_engine/utils'; import { transformRuleToAlertAction } from '../../../../common/detection_engine/transform_actions'; import { SanitizedAlert } from '../../../../../alerting/common'; -import { NOTIFICATION_THROTTLE_NO_ACTIONS, SERVER_APP_ID } from '../../../../common/constants'; +import { + DEFAULT_INDICATOR_SOURCE_PATH, + NOTIFICATION_THROTTLE_NO_ACTIONS, + SERVER_APP_ID, +} from '../../../../common/constants'; import { CreateRulesOptions } from './types'; import { addTags } from './add_tags'; import { PartialFilter, RuleTypeParams } from '../types'; @@ -115,7 +119,9 @@ export const createRules = async ({ */ threatFilters: threatFilters as PartialFilter[] | undefined, threatIndex, - threatIndicatorPath, + threatIndicatorPath: + threatIndicatorPath ?? + (type === 'threat_match' ? DEFAULT_INDICATOR_SOURCE_PATH : undefined), threatQuery, concurrentSearches, itemsPerSearch, From 324c5872d03cf90337b85f9bce41c251153d4255 Mon Sep 17 00:00:00 2001 From: ymao1 Date: Thu, 18 Nov 2021 14:14:20 -0500 Subject: [PATCH 122/148] [Alerting] Handle errors with scheduled task document during rule disable (#118618) * Catching errors during rule disable * Adding functional test Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../server/rules_client/rules_client.ts | 81 +++++++++-------- .../server/rules_client/tests/disable.test.ts | 59 +++++++++++++ .../spaces_only/tests/alerting/disable.ts | 88 ++++++++++++------- 3 files changed, 159 insertions(+), 69 deletions(-) diff --git a/x-pack/plugins/alerting/server/rules_client/rules_client.ts b/x-pack/plugins/alerting/server/rules_client/rules_client.ts index 37e9bcbfa3a8f..b190737a157ea 100644 --- a/x-pack/plugins/alerting/server/rules_client/rules_client.ts +++ b/x-pack/plugins/alerting/server/rules_client/rules_client.ts @@ -1205,44 +1205,51 @@ export class RulesClient { } if (this.eventLogger && attributes.scheduledTaskId) { - const { state } = taskInstanceToAlertTaskInstance( - await this.taskManager.get(attributes.scheduledTaskId), - attributes as unknown as SanitizedAlert - ); + try { + const { state } = taskInstanceToAlertTaskInstance( + await this.taskManager.get(attributes.scheduledTaskId), + attributes as unknown as SanitizedAlert + ); - const recoveredAlertInstances = mapValues, AlertInstance>( - state.alertInstances ?? {}, - (rawAlertInstance) => new AlertInstance(rawAlertInstance) - ); - const recoveredAlertInstanceIds = Object.keys(recoveredAlertInstances); - - for (const instanceId of recoveredAlertInstanceIds) { - const { group: actionGroup, subgroup: actionSubgroup } = - recoveredAlertInstances[instanceId].getLastScheduledActions() ?? {}; - const instanceState = recoveredAlertInstances[instanceId].getState(); - const message = `instance '${instanceId}' has recovered due to the rule was disabled`; - - const event = createAlertEventLogRecordObject({ - ruleId: id, - ruleName: attributes.name, - ruleType: this.ruleTypeRegistry.get(attributes.alertTypeId), - instanceId, - action: EVENT_LOG_ACTIONS.recoveredInstance, - message, - state: instanceState, - group: actionGroup, - subgroup: actionSubgroup, - namespace: this.namespace, - savedObjects: [ - { - id, - type: 'alert', - typeId: attributes.alertTypeId, - relation: SAVED_OBJECT_REL_PRIMARY, - }, - ], - }); - this.eventLogger.logEvent(event); + const recoveredAlertInstances = mapValues, AlertInstance>( + state.alertInstances ?? {}, + (rawAlertInstance) => new AlertInstance(rawAlertInstance) + ); + const recoveredAlertInstanceIds = Object.keys(recoveredAlertInstances); + + for (const instanceId of recoveredAlertInstanceIds) { + const { group: actionGroup, subgroup: actionSubgroup } = + recoveredAlertInstances[instanceId].getLastScheduledActions() ?? {}; + const instanceState = recoveredAlertInstances[instanceId].getState(); + const message = `instance '${instanceId}' has recovered due to the rule was disabled`; + + const event = createAlertEventLogRecordObject({ + ruleId: id, + ruleName: attributes.name, + ruleType: this.ruleTypeRegistry.get(attributes.alertTypeId), + instanceId, + action: EVENT_LOG_ACTIONS.recoveredInstance, + message, + state: instanceState, + group: actionGroup, + subgroup: actionSubgroup, + namespace: this.namespace, + savedObjects: [ + { + id, + type: 'alert', + typeId: attributes.alertTypeId, + relation: SAVED_OBJECT_REL_PRIMARY, + }, + ], + }); + this.eventLogger.logEvent(event); + } + } catch (error) { + // this should not block the rest of the disable process + this.logger.warn( + `rulesClient.disable('${id}') - Could not write recovery events - ${error.message}` + ); } } try { diff --git a/x-pack/plugins/alerting/server/rules_client/tests/disable.test.ts b/x-pack/plugins/alerting/server/rules_client/tests/disable.test.ts index c518d385dd747..a5b9f1d928e81 100644 --- a/x-pack/plugins/alerting/server/rules_client/tests/disable.test.ts +++ b/x-pack/plugins/alerting/server/rules_client/tests/disable.test.ts @@ -350,6 +350,65 @@ describe('disable()', () => { }); }); + test('disables the rule even if unable to retrieve task manager doc to generate recovery event log events', async () => { + unsecuredSavedObjectsClient.create.mockResolvedValueOnce({ + id: '1', + type: 'api_key_pending_invalidation', + attributes: { + apiKeyId: '123', + createdAt: '2019-02-12T21:01:22.479Z', + }, + references: [], + }); + taskManager.get.mockRejectedValueOnce(new Error('Fail')); + await rulesClient.disable({ id: '1' }); + expect(unsecuredSavedObjectsClient.get).not.toHaveBeenCalled(); + expect(encryptedSavedObjects.getDecryptedAsInternalUser).toHaveBeenCalledWith('alert', '1', { + namespace: 'default', + }); + expect(unsecuredSavedObjectsClient.update).toHaveBeenCalledWith( + 'alert', + '1', + { + consumer: 'myApp', + schedule: { interval: '10s' }, + alertTypeId: 'myType', + enabled: false, + meta: { + versionApiKeyLastmodified: kibanaVersion, + }, + scheduledTaskId: null, + apiKey: null, + apiKeyOwner: null, + updatedAt: '2019-02-12T21:01:22.479Z', + updatedBy: 'elastic', + actions: [ + { + group: 'default', + id: '1', + actionTypeId: '1', + actionRef: '1', + params: { + foo: true, + }, + }, + ], + }, + { + version: '123', + } + ); + expect(taskManager.removeIfExists).toHaveBeenCalledWith('task-123'); + expect( + (unsecuredSavedObjectsClient.create.mock.calls[0][1] as InvalidatePendingApiKey).apiKeyId + ).toBe('123'); + + expect(eventLogger.logEvent).toHaveBeenCalledTimes(0); + expect(rulesClientParams.logger.warn).toHaveBeenCalledWith( + `rulesClient.disable('1') - Could not write recovery events - Fail` + ); + }); + test('falls back when getDecryptedAsInternalUser throws an error', async () => { encryptedSavedObjects.getDecryptedAsInternalUser.mockRejectedValueOnce(new Error('Fail')); unsecuredSavedObjectsClient.create.mockResolvedValueOnce({ diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/disable.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/disable.ts index fa94eed46dc3f..51cb54aa5f9e5 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/disable.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/disable.ts @@ -9,17 +9,17 @@ import expect from '@kbn/expect'; import { Spaces } from '../../scenarios'; import { FtrProviderContext } from '../../../common/ftr_provider_context'; import { - AlertUtils, + AlertUtils as RuleUtils, checkAAD, getUrlPrefix, - getTestAlertData, + getTestAlertData as getTestRuleData, ObjectRemover, getEventLog, } from '../../../common/lib'; import { validateEvent } from './event_log'; // eslint-disable-next-line import/no-default-export -export default function createDisableAlertTests({ getService }: FtrProviderContext) { +export default function createDisableRuleTests({ getService }: FtrProviderContext) { const es = getService('es'); const supertestWithoutAuth = getService('supertestWithoutAuth'); const retry = getService('retry'); @@ -27,7 +27,7 @@ export default function createDisableAlertTests({ getService }: FtrProviderConte describe('disable', () => { const objectRemover = new ObjectRemover(supertestWithoutAuth); - const alertUtils = new AlertUtils({ space: Spaces.space1, supertestWithoutAuth }); + const ruleUtils = new RuleUtils({ space: Spaces.space1, supertestWithoutAuth }); after(() => objectRemover.removeAll()); @@ -38,18 +38,18 @@ export default function createDisableAlertTests({ getService }: FtrProviderConte }); } - it('should handle disable alert request appropriately', async () => { - const { body: createdAlert } = await supertestWithoutAuth + it('should handle disable rule request appropriately', async () => { + const { body: createdRule } = await supertestWithoutAuth .post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`) .set('kbn-xsrf', 'foo') - .send(getTestAlertData({ enabled: true })) + .send(getTestRuleData({ enabled: true })) .expect(200); - objectRemover.add(Spaces.space1.id, createdAlert.id, 'rule', 'alerting'); + objectRemover.add(Spaces.space1.id, createdRule.id, 'rule', 'alerting'); - await alertUtils.disable(createdAlert.id); + await ruleUtils.disable(createdRule.id); try { - await getScheduledTask(createdAlert.scheduledTaskId); + await getScheduledTask(createdRule.scheduled_task_id); throw new Error('Should have removed scheduled task'); } catch (e) { expect(e.meta.statusCode).to.eql(404); @@ -60,27 +60,27 @@ export default function createDisableAlertTests({ getService }: FtrProviderConte supertest: supertestWithoutAuth, spaceId: Spaces.space1.id, type: 'alert', - id: createdAlert.id, + id: createdRule.id, }); }); - it(`shouldn't disable alert from another space`, async () => { - const { body: createdAlert } = await supertestWithoutAuth + it(`shouldn't disable rule from another space`, async () => { + const { body: createdRule } = await supertestWithoutAuth .post(`${getUrlPrefix(Spaces.other.id)}/api/alerting/rule`) .set('kbn-xsrf', 'foo') - .send(getTestAlertData({ enabled: true })) + .send(getTestRuleData({ enabled: true })) .expect(200); - objectRemover.add(Spaces.other.id, createdAlert.id, 'rule', 'alerting'); + objectRemover.add(Spaces.other.id, createdRule.id, 'rule', 'alerting'); - await alertUtils.getDisableRequest(createdAlert.id).expect(404, { + await ruleUtils.getDisableRequest(createdRule.id).expect(404, { statusCode: 404, error: 'Not Found', - message: `Saved object [alert/${createdAlert.id}] not found`, + message: `Saved object [alert/${createdRule.id}] not found`, }); }); - it('should create recovered-instance events for all alert instances', async () => { - const { body: createdAlert } = await supertest + it('should create recovered-instance events for all alerts', async () => { + const { body: createdRule } = await supertest .post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`) .set('kbn-xsrf', 'foo') .send({ @@ -96,12 +96,12 @@ export default function createDisableAlertTests({ getService }: FtrProviderConte notify_when: 'onThrottleInterval', }) .expect(200); - objectRemover.add(Spaces.space1.id, createdAlert.id, 'rule', 'alerting'); + objectRemover.add(Spaces.space1.id, createdRule.id, 'rule', 'alerting'); - // wait for alert to actually execute + // wait for rule to actually execute await retry.try(async () => { const response = await supertest.get( - `${getUrlPrefix(Spaces.space1.id)}/internal/alerting/rule/${createdAlert.id}/state` + `${getUrlPrefix(Spaces.space1.id)}/internal/alerting/rule/${createdRule.id}/state` ); expect(response.status).to.eql(200); @@ -109,8 +109,8 @@ export default function createDisableAlertTests({ getService }: FtrProviderConte expect(response.body.rule_type_state.runCount).to.greaterThan(1); }); - await alertUtils.getDisableRequest(createdAlert.id); - const ruleId = createdAlert.id; + await ruleUtils.getDisableRequest(createdRule.id); + const ruleId = createdRule.id; // wait for the events we're expecting const events = await retry.try(async () => { @@ -140,7 +140,7 @@ export default function createDisableAlertTests({ getService }: FtrProviderConte shouldHaveTask: false, rule: { id: ruleId, - category: createdAlert.rule_type_id, + category: createdRule.rule_type_id, license: 'basic', ruleset: 'alertsFixture', name: 'abc', @@ -148,22 +148,46 @@ export default function createDisableAlertTests({ getService }: FtrProviderConte }); }); + it('should disable rule even if associated task manager document is missing', async () => { + const { body: createdRule } = await supertestWithoutAuth + .post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`) + .set('kbn-xsrf', 'foo') + .send(getTestRuleData({ enabled: true })) + .expect(200); + objectRemover.add(Spaces.space1.id, createdRule.id, 'rule', 'alerting'); + + // manually remove scheduled task + await es.delete({ + id: `task:${createdRule.scheduled_task_id}`, + index: '.kibana_task_manager', + }); + await ruleUtils.disable(createdRule.id); + + // Ensure AAD isn't broken + await checkAAD({ + supertest: supertestWithoutAuth, + spaceId: Spaces.space1.id, + type: 'alert', + id: createdRule.id, + }); + }); + describe('legacy', () => { - it('should handle disable alert request appropriately', async () => { - const { body: createdAlert } = await supertestWithoutAuth + it('should handle disable rule request appropriately', async () => { + const { body: createdRule } = await supertestWithoutAuth .post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`) .set('kbn-xsrf', 'foo') - .send(getTestAlertData({ enabled: true })) + .send(getTestRuleData({ enabled: true })) .expect(200); - objectRemover.add(Spaces.space1.id, createdAlert.id, 'rule', 'alerting'); + objectRemover.add(Spaces.space1.id, createdRule.id, 'rule', 'alerting'); await supertestWithoutAuth - .post(`${getUrlPrefix(Spaces.space1.id)}/api/alerts/alert/${createdAlert.id}/_disable`) + .post(`${getUrlPrefix(Spaces.space1.id)}/api/alerts/alert/${createdRule.id}/_disable`) .set('kbn-xsrf', 'foo') .expect(204); try { - await getScheduledTask(createdAlert.scheduledTaskId); + await getScheduledTask(createdRule.scheduled_task_id); throw new Error('Should have removed scheduled task'); } catch (e) { expect(e.meta.statusCode).to.eql(404); @@ -174,7 +198,7 @@ export default function createDisableAlertTests({ getService }: FtrProviderConte supertest: supertestWithoutAuth, spaceId: Spaces.space1.id, type: 'alert', - id: createdAlert.id, + id: createdRule.id, }); }); }); From bbccf0ed2ea843831a34691d33112bf74f5743fa Mon Sep 17 00:00:00 2001 From: Esteban Beltran Date: Thu, 18 Nov 2021 14:17:15 -0500 Subject: [PATCH 123/148] [Security Solution] Feature/decouple artifact policy selector (#118927) --- .../effected_policy_select.test.tsx | 7 +- .../effected_policy_select.tsx | 67 +++++++++++++------ .../effected_policy_select/index.ts | 0 .../effected_policy_select/test_utils.ts | 0 .../pages/endpoint_hosts/store/middleware.ts | 2 +- .../policy/store/services/ingest.test.ts | 31 +-------- .../pages/policy/store/services/ingest.ts | 25 +------ .../pages/trusted_apps/service/index.ts | 2 +- .../create_trusted_app_form.test.tsx | 2 +- .../components/create_trusted_app_form.tsx | 13 +++- .../view/trusted_apps_page.test.tsx | 2 +- .../management/services/policies.test.ts | 42 ++++++++++++ .../public/management/services/policies.ts | 35 ++++++++++ 13 files changed, 140 insertions(+), 88 deletions(-) rename x-pack/plugins/security_solution/public/management/{pages/trusted_apps/view => }/components/effected_policy_select/effected_policy_select.test.tsx (95%) rename x-pack/plugins/security_solution/public/management/{pages/trusted_apps/view => }/components/effected_policy_select/effected_policy_select.tsx (76%) rename x-pack/plugins/security_solution/public/management/{pages/trusted_apps/view => }/components/effected_policy_select/index.ts (100%) rename x-pack/plugins/security_solution/public/management/{pages/trusted_apps/view => }/components/effected_policy_select/test_utils.ts (100%) create mode 100644 x-pack/plugins/security_solution/public/management/services/policies.test.ts create mode 100644 x-pack/plugins/security_solution/public/management/services/policies.ts diff --git a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/effected_policy_select/effected_policy_select.test.tsx b/x-pack/plugins/security_solution/public/management/components/effected_policy_select/effected_policy_select.test.tsx similarity index 95% rename from x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/effected_policy_select/effected_policy_select.test.tsx rename to x-pack/plugins/security_solution/public/management/components/effected_policy_select/effected_policy_select.test.tsx index 3e48ccc6d9b6d..5eebc2721857f 100644 --- a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/effected_policy_select/effected_policy_select.test.tsx +++ b/x-pack/plugins/security_solution/public/management/components/effected_policy_select/effected_policy_select.test.tsx @@ -5,15 +5,12 @@ * 2.0. */ -import { EndpointDocGenerator } from '../../../../../../../common/endpoint/generate_data'; import { EffectedPolicySelect, EffectedPolicySelectProps } from './effected_policy_select'; -import { - AppContextTestRender, - createAppRootMockRenderer, -} from '../../../../../../common/mock/endpoint'; import React from 'react'; import { forceHTMLElementOffsetWidth } from './test_utils'; import { fireEvent, act } from '@testing-library/react'; +import { EndpointDocGenerator } from '../../../../common/endpoint/generate_data'; +import { AppContextTestRender, createAppRootMockRenderer } from '../../../common/mock/endpoint'; describe('when using EffectedPolicySelect component', () => { const generator = new EndpointDocGenerator('effected-policy-select'); diff --git a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/effected_policy_select/effected_policy_select.tsx b/x-pack/plugins/security_solution/public/management/components/effected_policy_select/effected_policy_select.tsx similarity index 76% rename from x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/effected_policy_select/effected_policy_select.tsx rename to x-pack/plugins/security_solution/public/management/components/effected_policy_select/effected_policy_select.tsx index 07de303c155aa..2249fc89430d2 100644 --- a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/effected_policy_select/effected_policy_select.tsx +++ b/x-pack/plugins/security_solution/public/management/components/effected_policy_select/effected_policy_select.tsx @@ -23,14 +23,27 @@ import { i18n } from '@kbn/i18n'; import { EuiSelectableOption } from '@elastic/eui/src/components/selectable/selectable_option'; import { FormattedMessage } from '@kbn/i18n/react'; import styled from 'styled-components'; -import { PolicyData } from '../../../../../../../common/endpoint/types'; -import { getPolicyDetailPath } from '../../../../../common/routing'; -import { useAppUrl } from '../../../../../../common/lib/kibana/hooks'; -import { LinkToApp } from '../../../../../../common/components/endpoint/link_to_app'; -import { useTestIdGenerator } from '../../../../../components/hooks/use_test_id_generator'; +import { PolicyData } from '../../../../common/endpoint/types'; +import { LinkToApp } from '../../../common/components/endpoint/link_to_app'; +import { getPolicyDetailPath } from '../../common/routing'; +import { useTestIdGenerator } from '../hooks/use_test_id_generator'; +import { useAppUrl } from '../../../common/lib/kibana/hooks'; const NOOP = () => {}; const DEFAULT_LIST_PROPS: EuiSelectableProps['listProps'] = { bordered: true, showIcons: false }; +const SEARCH_PROPS = { className: 'effected-policies-search' }; + +const StyledEuiSelectable = styled.div` + .effected-policies-search { + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + } + .euiSelectableList { + border-top-left-radius: 0; + border-top-right-radius: 0; + border-top-width: 0; + } +`; const EffectivePolicyFormContainer = styled.div` .policy-name .euiSelectableListItem__text { @@ -57,6 +70,7 @@ export type EffectedPolicySelectProps = Omit< options: PolicyData[]; isGlobal: boolean; isPlatinumPlus: boolean; + description?: string; onChange: (selection: EffectedPolicySelection) => void; selected?: PolicyData[]; }; @@ -64,6 +78,7 @@ export const EffectedPolicySelect = memo( ({ isGlobal, isPlatinumPlus, + description, onChange, listProps, options, @@ -79,7 +94,7 @@ export const EffectedPolicySelect = memo( () => [ { id: 'globalPolicy', - label: i18n.translate('xpack.securitySolution.endpoint.trustedAppsByPolicy.global', { + label: i18n.translate('xpack.securitySolution.endpoint.effectedPolicySelect.global', { defaultMessage: 'Global', }), iconType: isGlobal ? 'checkInCircleFilled' : '', @@ -87,7 +102,7 @@ export const EffectedPolicySelect = memo( }, { id: 'perPolicy', - label: i18n.translate('xpack.securitySolution.endpoint.trustedAppsByPolicy.perPolicy', { + label: i18n.translate('xpack.securitySolution.endpoint.effectedPolicySelect.perPolicy', { defaultMessage: 'Per Policy', }), iconType: !isGlobal ? 'checkInCircleFilled' : '', @@ -169,7 +184,7 @@ export const EffectedPolicySelect = memo(

    @@ -179,10 +194,15 @@ export const EffectedPolicySelect = memo(

    - {i18n.translate('xpack.securitySolution.trustedApps.assignmentSectionDescription', { - defaultMessage: - 'Assign this trusted application globally across all policies, or assign it to specific policies.', - })} + {description + ? description + : i18n.translate( + 'xpack.securitySolution.effectedPolicySelect.assignmentSectionDescription', + { + defaultMessage: + 'Assign globally across all policies, or assign it to specific policies.', + } + )}

    @@ -202,16 +222,19 @@ export const EffectedPolicySelect = memo( {!isGlobal && ( - - {...otherSelectableProps} - options={selectableOptions} - listProps={listProps || DEFAULT_LIST_PROPS} - onChange={handleOnPolicySelectChange} - searchable={true} - data-test-subj={getTestId('policiesSelectable')} - > - {listBuilderCallback} - + + + {...otherSelectableProps} + options={selectableOptions} + listProps={listProps || DEFAULT_LIST_PROPS} + onChange={handleOnPolicySelectChange} + searchProps={SEARCH_PROPS} + searchable={true} + data-test-subj={getTestId('policiesSelectable')} + > + {listBuilderCallback} + + )} diff --git a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/effected_policy_select/index.ts b/x-pack/plugins/security_solution/public/management/components/effected_policy_select/index.ts similarity index 100% rename from x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/effected_policy_select/index.ts rename to x-pack/plugins/security_solution/public/management/components/effected_policy_select/index.ts diff --git a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/effected_policy_select/test_utils.ts b/x-pack/plugins/security_solution/public/management/components/effected_policy_select/test_utils.ts similarity index 100% rename from x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/effected_policy_select/test_utils.ts rename to x-pack/plugins/security_solution/public/management/components/effected_policy_select/test_utils.ts diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts index 287f66a48fce8..3f4afe8e4b108 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts @@ -54,7 +54,6 @@ import { TransformStatsResponse, } from '../types'; import { - sendGetEndpointSpecificPackagePolicies, sendGetEndpointSecurityPackage, sendGetAgentPolicyList, sendGetFleetAgentsWithEndpoint, @@ -81,6 +80,7 @@ import { EndpointPackageInfoStateChanged } from './action'; import { fetchPendingActionsByAgentId } from '../../../../common/lib/endpoint_pending_actions'; import { getIsInvalidDateRange } from '../utils'; import { METADATA_TRANSFORM_STATS_URL } from '../../../../../common/constants'; +import { sendGetEndpointSpecificPackagePolicies } from '../../../services/policies'; type EndpointPageStore = ImmutableMiddlewareAPI; diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/store/services/ingest.test.ts b/x-pack/plugins/security_solution/public/management/pages/policy/store/services/ingest.test.ts index b5897d8fd3bc4..ef66c948e1127 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/store/services/ingest.test.ts +++ b/x-pack/plugins/security_solution/public/management/pages/policy/store/services/ingest.test.ts @@ -9,15 +9,9 @@ import { INGEST_API_EPM_PACKAGES, sendGetPackagePolicy, sendGetEndpointSecurityPackage, - sendGetEndpointSpecificPackagePolicies, } from './ingest'; import { httpServiceMock } from '../../../../../../../../../src/core/public/mocks'; -import { - EPM_API_ROUTES, - PACKAGE_POLICY_SAVED_OBJECT_TYPE, - PACKAGE_POLICY_API_ROOT, - PACKAGE_POLICY_API_ROUTES, -} from '../../../../../../../fleet/common'; +import { EPM_API_ROUTES, PACKAGE_POLICY_API_ROOT } from '../../../../../../../fleet/common'; import { policyListApiPathHandlers } from '../test_mock_utils'; describe('ingest service', () => { @@ -27,29 +21,6 @@ describe('ingest service', () => { http = httpServiceMock.createStartContract(); }); - describe('sendGetEndpointSpecificPackagePolicies()', () => { - it('auto adds kuery to api request', async () => { - await sendGetEndpointSpecificPackagePolicies(http); - expect(http.get).toHaveBeenCalledWith(`${PACKAGE_POLICY_API_ROUTES.LIST_PATTERN}`, { - query: { - kuery: `${PACKAGE_POLICY_SAVED_OBJECT_TYPE}.package.name: endpoint`, - }, - }); - }); - it('supports additional KQL to be defined on input for query params', async () => { - await sendGetEndpointSpecificPackagePolicies(http, { - query: { kuery: 'someValueHere', page: 1, perPage: 10 }, - }); - expect(http.get).toHaveBeenCalledWith(`${PACKAGE_POLICY_API_ROUTES.LIST_PATTERN}`, { - query: { - kuery: `someValueHere and ${PACKAGE_POLICY_SAVED_OBJECT_TYPE}.package.name: endpoint`, - perPage: 10, - page: 1, - }, - }); - }); - }); - describe('sendGetPackagePolicy()', () => { it('builds correct API path', async () => { await sendGetPackagePolicy(http, '123'); diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/store/services/ingest.ts b/x-pack/plugins/security_solution/public/management/pages/policy/store/services/ingest.ts index 0375b0c434f18..27b567c3bb38c 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/store/services/ingest.ts +++ b/x-pack/plugins/security_solution/public/management/pages/policy/store/services/ingest.ts @@ -7,17 +7,15 @@ import { HttpFetchOptions, HttpStart } from 'kibana/public'; import { - GetPackagePoliciesRequest, GetAgentStatusResponse, GetAgentsResponse, DeletePackagePoliciesResponse, DeletePackagePoliciesRequest, - PACKAGE_POLICY_SAVED_OBJECT_TYPE, GetPackagesResponse, GetAgentPoliciesRequest, GetAgentPoliciesResponse, } from '../../../../../../../fleet/common'; -import { GetPolicyListResponse, GetPolicyResponse, UpdatePolicyResponse } from '../../types'; +import { GetPolicyResponse, UpdatePolicyResponse } from '../../types'; import { NewPolicyData } from '../../../../../../common/endpoint/types'; const INGEST_API_ROOT = `/api/fleet`; @@ -28,27 +26,6 @@ export const INGEST_API_FLEET_AGENTS = `${INGEST_API_ROOT}/agents`; export const INGEST_API_EPM_PACKAGES = `${INGEST_API_ROOT}/epm/packages`; const INGEST_API_DELETE_PACKAGE_POLICY = `${INGEST_API_PACKAGE_POLICIES}/delete`; -/** - * Retrieves a list of endpoint specific package policies (those created with a `package.name` of - * `endpoint`) from Ingest - * @param http - * @param options - */ -export const sendGetEndpointSpecificPackagePolicies = ( - http: HttpStart, - options: HttpFetchOptions & Partial = {} -): Promise => { - return http.get(INGEST_API_PACKAGE_POLICIES, { - ...options, - query: { - ...options.query, - kuery: `${ - options?.query?.kuery ? `${options.query.kuery} and ` : '' - }${PACKAGE_POLICY_SAVED_OBJECT_TYPE}.package.name: endpoint`, - }, - }); -}; - /** * Retrieves a single package policy based on ID from ingest * @param http diff --git a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/service/index.ts b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/service/index.ts index b59fb6cfdd2f7..2549dd5a2a4dc 100644 --- a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/service/index.ts +++ b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/service/index.ts @@ -35,9 +35,9 @@ import { } from '../../../../../common/endpoint/types'; import { resolvePathVariables } from '../../../../common/utils/resolve_path_variables'; -import { sendGetEndpointSpecificPackagePolicies } from '../../policy/store/services/ingest'; import { toUpdateTrustedApp } from '../../../../../common/endpoint/service/trusted_apps/to_update_trusted_app'; import { isGlobalEffectScope } from '../state/type_guards'; +import { sendGetEndpointSpecificPackagePolicies } from '../../../services/policies'; export interface TrustedAppsService { getTrustedApp(params: GetOneTrustedAppRequestParams): Promise; diff --git a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/create_trusted_app_form.test.tsx b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/create_trusted_app_form.test.tsx index f05d018fe8e9a..23589843c28c3 100644 --- a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/create_trusted_app_form.test.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/create_trusted_app_form.test.tsx @@ -21,10 +21,10 @@ import { import { CreateTrustedAppForm, CreateTrustedAppFormProps } from './create_trusted_app_form'; import { defaultNewTrustedApp } from '../../store/builders'; -import { forceHTMLElementOffsetWidth } from './effected_policy_select/test_utils'; import { EndpointDocGenerator } from '../../../../../../common/endpoint/generate_data'; import { useIsExperimentalFeatureEnabled } from '../../../../../common/hooks/use_experimental_features'; import { licenseService } from '../../../../../common/hooks/use_license'; +import { forceHTMLElementOffsetWidth } from '../../../../components/effected_policy_select/test_utils'; jest.mock('../../../../../common/hooks/use_experimental_features'); const useIsExperimentalFeatureEnabledMock = useIsExperimentalFeatureEnabled as jest.Mock; diff --git a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/create_trusted_app_form.tsx b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/create_trusted_app_form.tsx index da925ddd8a6c1..147529b164ae1 100644 --- a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/create_trusted_app_form.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/create_trusted_app_form.tsx @@ -42,13 +42,13 @@ import { import { defaultConditionEntry } from '../../store/builders'; import { OS_TITLES } from '../translations'; import { LogicalConditionBuilder, LogicalConditionBuilderProps } from './logical_condition'; +import { useTestIdGenerator } from '../../../../components/hooks/use_test_id_generator'; +import { useLicense } from '../../../../../common/hooks/use_license'; import { EffectedPolicySelect, EffectedPolicySelection, EffectedPolicySelectProps, -} from './effected_policy_select'; -import { useTestIdGenerator } from '../../../../components/hooks/use_test_id_generator'; -import { useLicense } from '../../../../../common/hooks/use_license'; +} from '../../../../components/effected_policy_select'; const OPERATING_SYSTEMS: readonly OperatingSystem[] = [ OperatingSystem.MAC, @@ -564,6 +564,13 @@ export const CreateTrustedAppForm = memo( options={policies.options} onChange={handlePolicySelectChange} isLoading={policies?.isLoading} + description={i18n.translate( + 'xpack.securitySolution.trustedApps.assignmentSectionDescription', + { + defaultMessage: + 'Assign this trusted application globally across all policies, or assign it to specific policies.', + } + )} data-test-subj={getTestId('effectedPolicies')} /> diff --git a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/trusted_apps_page.test.tsx b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/trusted_apps_page.test.tsx index 39619379a1ee0..5d78de741e459 100644 --- a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/trusted_apps_page.test.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/trusted_apps_page.test.tsx @@ -30,11 +30,11 @@ import { } from '../../../../../../fleet/common'; import { EndpointDocGenerator } from '../../../../../common/endpoint/generate_data'; import { isFailedResourceState, isLoadedResourceState } from '../state'; -import { forceHTMLElementOffsetWidth } from './components/effected_policy_select/test_utils'; import { toUpdateTrustedApp } from '../../../../../common/endpoint/service/trusted_apps/to_update_trusted_app'; import { useIsExperimentalFeatureEnabled } from '../../../../common/hooks/use_experimental_features'; import { resolvePathVariables } from '../../../../common/utils/resolve_path_variables'; import { licenseService } from '../../../../common/hooks/use_license'; +import { forceHTMLElementOffsetWidth } from '../../../components/effected_policy_select/test_utils'; // TODO: remove this mock when feature flag is removed jest.mock('../../../../common/hooks/use_experimental_features'); diff --git a/x-pack/plugins/security_solution/public/management/services/policies.test.ts b/x-pack/plugins/security_solution/public/management/services/policies.test.ts new file mode 100644 index 0000000000000..0b93dffb71d3c --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/services/policies.test.ts @@ -0,0 +1,42 @@ +/* + * 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 { httpServiceMock } from '../../../../../../src/core/public/mocks'; +import { PACKAGE_POLICY_SAVED_OBJECT_TYPE } from '../../../../fleet/common'; +import { PACKAGE_POLICY_API_ROUTES } from '../../../../fleet/common/constants/routes'; +import { sendGetEndpointSpecificPackagePolicies } from './policies'; + +describe('ingest service', () => { + let http: ReturnType; + + beforeEach(() => { + http = httpServiceMock.createStartContract(); + }); + + describe('sendGetEndpointSpecificPackagePolicies()', () => { + it('auto adds kuery to api request', async () => { + await sendGetEndpointSpecificPackagePolicies(http); + expect(http.get).toHaveBeenCalledWith(`${PACKAGE_POLICY_API_ROUTES.LIST_PATTERN}`, { + query: { + kuery: `${PACKAGE_POLICY_SAVED_OBJECT_TYPE}.package.name: endpoint`, + }, + }); + }); + it('supports additional KQL to be defined on input for query params', async () => { + await sendGetEndpointSpecificPackagePolicies(http, { + query: { kuery: 'someValueHere', page: 1, perPage: 10 }, + }); + expect(http.get).toHaveBeenCalledWith(`${PACKAGE_POLICY_API_ROUTES.LIST_PATTERN}`, { + query: { + kuery: `someValueHere and ${PACKAGE_POLICY_SAVED_OBJECT_TYPE}.package.name: endpoint`, + perPage: 10, + page: 1, + }, + }); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/public/management/services/policies.ts b/x-pack/plugins/security_solution/public/management/services/policies.ts new file mode 100644 index 0000000000000..63810ad499c09 --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/services/policies.ts @@ -0,0 +1,35 @@ +/* + * 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 { HttpFetchOptions, HttpStart } from 'kibana/public'; +import { + GetPackagePoliciesRequest, + PACKAGE_POLICY_SAVED_OBJECT_TYPE, +} from '../../../../fleet/common'; +import { INGEST_API_PACKAGE_POLICIES } from '../pages/policy/store/services/ingest'; +import { GetPolicyListResponse } from '../pages/policy/types'; + +/** + * Retrieves a list of endpoint specific package policies (those created with a `package.name` of + * `endpoint`) from Ingest + * @param http + * @param options + */ +export const sendGetEndpointSpecificPackagePolicies = ( + http: HttpStart, + options: HttpFetchOptions & Partial = {} +): Promise => { + return http.get(INGEST_API_PACKAGE_POLICIES, { + ...options, + query: { + ...options.query, + kuery: `${ + options?.query?.kuery ? `${options.query.kuery} and ` : '' + }${PACKAGE_POLICY_SAVED_OBJECT_TYPE}.package.name: endpoint`, + }, + }); +}; From fcb855b0ecb671beb70f897e13725718c9dd5058 Mon Sep 17 00:00:00 2001 From: Baturalp Gurdin <9674241+suchcodemuchwow@users.noreply.github.com> Date: Thu, 18 Nov 2021 20:28:58 +0100 Subject: [PATCH 124/148] Performance test for login and home page (#117861) - Remove reporting-dashboard test from performance tests and add login page and home page tests to get performance metrics. - Set network latency (KBN_TEST_NETWORK_LATENCY), download throughput (KBN_TEST_DOWNLOAD_THROUGHPUT) and upload throughput (KBN_TEST_UPLOAD_THROUGHPUT) through environment variables and fallback to default 100ms latency for network latency, 5MB for download throughput and 1MB for upload throughput. --- .../services/remote/network_profiles.ts | 34 +++++++++++++++++++ test/functional/services/remote/webdriver.ts | 27 ++++++++++++--- x-pack/test/performance/tests/home.ts | 25 ++++++++++++++ x-pack/test/performance/tests/index.ts | 2 +- .../performance/tests/reporting_dashboard.ts | 2 +- 5 files changed, 83 insertions(+), 7 deletions(-) create mode 100644 test/functional/services/remote/network_profiles.ts create mode 100644 x-pack/test/performance/tests/home.ts diff --git a/test/functional/services/remote/network_profiles.ts b/test/functional/services/remote/network_profiles.ts new file mode 100644 index 0000000000000..c27bafa4f8dcb --- /dev/null +++ b/test/functional/services/remote/network_profiles.ts @@ -0,0 +1,34 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +interface NetworkOptions { + DOWNLOAD: number; + UPLOAD: number; + LATENCY: number; +} + +const sec = 1_000; +const kB = 1024; + +// Download (kb/s) Upload (kb/s) Latency (ms) +// https://gist.github.com/theodorosploumis/fd4086ee58369b68aea6b0782dc96a2e +export const NETWORK_PROFILES: { [key: string]: NetworkOptions } = { + DEFAULT: { DOWNLOAD: 5 * kB * sec, UPLOAD: 1 * kB * sec, LATENCY: 0.1 * sec }, + GPRS: { DOWNLOAD: 0.05 * kB * sec, UPLOAD: 0.02 * kB * sec, LATENCY: 0.5 * sec }, + MOBILE_EDGE: { DOWNLOAD: 0.24 * kB * sec, UPLOAD: 0.2 * kB * sec, LATENCY: 0.84 * sec }, + '2G_REGULAR': { DOWNLOAD: 0.25 * kB * sec, UPLOAD: 0.05 * kB * sec, LATENCY: 0.3 * sec }, + '2G_GOOD': { DOWNLOAD: 0.45 * kB * sec, UPLOAD: 0.15 * kB * sec, LATENCY: 0.15 * sec }, + '3G_SLOW': { DOWNLOAD: 0.78 * kB * sec, UPLOAD: 0.33 * kB * sec, LATENCY: 0.2 * sec }, + '3G_REGULAR': { DOWNLOAD: 0.75 * kB * sec, UPLOAD: 0.25 * kB * sec, LATENCY: 0.1 * sec }, + '3G_GOOD': { DOWNLOAD: 1.5 * kB * sec, UPLOAD: 0.75 * kB * sec, LATENCY: 0.04 * sec }, + '4G_REGULAR': { DOWNLOAD: 4 * kB * sec, UPLOAD: 3 * kB * sec, LATENCY: 0.02 * sec }, + DSL: { DOWNLOAD: 2 * kB * sec, UPLOAD: 1 * kB * sec, LATENCY: 0.005 * sec }, + CABLE_5MBPS: { DOWNLOAD: 5 * kB * sec, UPLOAD: 1 * kB * sec, LATENCY: 0.28 * sec }, + CABLE_8MBPS: { DOWNLOAD: 8 * kB * sec, UPLOAD: 2 * kB * sec, LATENCY: 0.1 * sec }, + WIFI: { DOWNLOAD: 30 * kB * sec, UPLOAD: 15 * kB * sec, LATENCY: 0.002 * sec }, +}; diff --git a/test/functional/services/remote/webdriver.ts b/test/functional/services/remote/webdriver.ts index 9ae848d95473a..84dfdf3c845f7 100644 --- a/test/functional/services/remote/webdriver.ts +++ b/test/functional/services/remote/webdriver.ts @@ -32,6 +32,7 @@ import { createStdoutSocket } from './create_stdout_stream'; import { preventParallelCalls } from './prevent_parallel_calls'; import { Browsers } from './browsers'; +import { NETWORK_PROFILES } from './network_profiles'; const throttleOption: string = process.env.TEST_THROTTLE_NETWORK as string; const headlessBrowser: string = process.env.TEST_BROWSER_HEADLESS as string; @@ -290,14 +291,30 @@ async function attemptToCreateCommand( const { session, consoleLog$ } = await buildDriverInstance(); if (throttleOption === '1' && browserType === 'chrome') { + const { KBN_NETWORK_TEST_PROFILE = 'DEFAULT' } = process.env; + + const profile = + KBN_NETWORK_TEST_PROFILE in Object.keys(NETWORK_PROFILES) + ? KBN_NETWORK_TEST_PROFILE + : 'DEFAULT'; + + const { + DOWNLOAD: downloadThroughput, + UPLOAD: uploadThroughput, + LATENCY: latency, + } = NETWORK_PROFILES[`${profile}`]; + // Only chrome supports this option. - log.debug('NETWORK THROTTLED: 768k down, 256k up, 100ms latency.'); + log.debug( + `NETWORK THROTTLED with profile ${profile}: ${downloadThroughput}kbps down, ${uploadThroughput}kbps up, ${latency} ms latency.` + ); - (session as any).setNetworkConditions({ + // @ts-expect-error + session.setNetworkConditions({ offline: false, - latency: 100, // Additional latency (ms). - download_throughput: 768 * 1024, // These speeds are in bites per second, not kilobytes. - upload_throughput: 256 * 1024, + latency, + download_throughput: downloadThroughput, + upload_throughput: uploadThroughput, }); } diff --git a/x-pack/test/performance/tests/home.ts b/x-pack/test/performance/tests/home.ts new file mode 100644 index 0000000000000..eda690b9b0a19 --- /dev/null +++ b/x-pack/test/performance/tests/home.ts @@ -0,0 +1,25 @@ +/* + * 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 { FtrProviderContext } from '../ftr_provider_context'; + +export default function ({ getService, getPageObjects }: FtrProviderContext) { + const PageObjects = getPageObjects(['common', 'security']); + const testSubjects = getService('testSubjects'); + + describe('Login', () => { + it('login and navigate to homepage', async () => { + await PageObjects.common.navigateToApp('login'); + + await testSubjects.existOrFail('loginSubmit', { timeout: 2000 }); + + await PageObjects.security.login(); + + await testSubjects.existOrFail('homeApp', { timeout: 2000 }); + }); + }); +} diff --git a/x-pack/test/performance/tests/index.ts b/x-pack/test/performance/tests/index.ts index b1023bde688e2..d784fa3031739 100644 --- a/x-pack/test/performance/tests/index.ts +++ b/x-pack/test/performance/tests/index.ts @@ -11,6 +11,6 @@ export default function ({ loadTestFile }: FtrProviderContext) { describe('performance', function () { this.tags('ciGroup8'); - loadTestFile(require.resolve('./reporting_dashboard')); + loadTestFile(require.resolve('./home')); }); } diff --git a/x-pack/test/performance/tests/reporting_dashboard.ts b/x-pack/test/performance/tests/reporting_dashboard.ts index f363f8449df96..93b4010ab27a8 100644 --- a/x-pack/test/performance/tests/reporting_dashboard.ts +++ b/x-pack/test/performance/tests/reporting_dashboard.ts @@ -16,7 +16,7 @@ export default function ({ getService, getPageObject }: FtrProviderContext) { const dashboard = getPageObject('dashboard'); const reporting = getPageObject('reporting'); - describe('reporting dashbaord', () => { + describe('Reporting Dashboard', () => { before(async () => { await kibanaServer.importExport.load( 'x-pack/test/performance/kbn_archives/reporting_dashboard' From 3b1a76061c09347404288a7913178d1420aa3882 Mon Sep 17 00:00:00 2001 From: Esteban Beltran Date: Thu, 18 Nov 2021 14:53:12 -0500 Subject: [PATCH 125/148] [Security Solution] adds host isolation exceptions summary in fleet integration advance tab (#119029) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../fleet_event_filters_card.test.tsx | 8 +- .../components/fleet_event_filters_card.tsx | 4 +- ...et_host_isolation_exceptions_card.test.tsx | 110 +++++++++++++++ .../fleet_host_isolation_exceptions_card.tsx | 130 ++++++++++++++++++ .../fleet_trusted_apps_card.test.tsx | 8 +- .../components/fleet_trusted_apps_card.tsx | 2 +- .../fleet_trusted_apps_card_wrapper.tsx | 4 +- .../components/styled_components.tsx | 2 +- .../index.tsx | 5 +- .../translations/translations/ja-JP.json | 2 - .../translations/translations/zh-CN.json | 2 - 11 files changed, 258 insertions(+), 19 deletions(-) create mode 100644 x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_package_custom_extension/components/fleet_host_isolation_exceptions_card.test.tsx create mode 100644 x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_package_custom_extension/components/fleet_host_isolation_exceptions_card.tsx diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_package_custom_extension/components/fleet_event_filters_card.test.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_package_custom_extension/components/fleet_event_filters_card.test.tsx index 30c95472e4d6d..0981c775e961b 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_package_custom_extension/components/fleet_event_filters_card.test.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_package_custom_extension/components/fleet_event_filters_card.test.tsx @@ -97,8 +97,8 @@ describe('Fleet event filters card', () => { }; }); const component = await renderComponent(); - expect(component.getByText('Event Filters')).not.toBeNull(); - expect(component.getByText('Manage event filters')).not.toBeNull(); + expect(component.getByText('Event filters')).not.toBeNull(); + expect(component.getByText('Manage')).not.toBeNull(); }); it('should render an error toast when api call fails', async () => { expect(addDanger).toBeCalledTimes(0); @@ -109,8 +109,8 @@ describe('Fleet event filters card', () => { }; }); const component = await renderComponent(); - expect(component.getByText('Event Filters')).not.toBeNull(); - expect(component.getByText('Manage event filters')).not.toBeNull(); + expect(component.getByText('Event filters')).not.toBeNull(); + expect(component.getByText('Manage')).not.toBeNull(); await reactTestingLibrary.waitFor(() => expect(addDanger).toBeCalledTimes(1)); }); }); diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_package_custom_extension/components/fleet_event_filters_card.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_package_custom_extension/components/fleet_event_filters_card.tsx index 41768f4be7d2e..7db76fee4efc5 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_package_custom_extension/components/fleet_event_filters_card.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_package_custom_extension/components/fleet_event_filters_card.tsx @@ -95,7 +95,7 @@ export const FleetEventFiltersCard = memo(

    @@ -115,7 +115,7 @@ export const FleetEventFiltersCard = memo( > diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_package_custom_extension/components/fleet_host_isolation_exceptions_card.test.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_package_custom_extension/components/fleet_host_isolation_exceptions_card.test.tsx new file mode 100644 index 0000000000000..ea1937c5a98d5 --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_package_custom_extension/components/fleet_host_isolation_exceptions_card.test.tsx @@ -0,0 +1,110 @@ +/* + * 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 { I18nProvider } from '@kbn/i18n/react'; +import * as reactTestingLibrary from '@testing-library/react'; +import React from 'react'; +import { ThemeProvider } from 'styled-components'; +import { GetExceptionSummaryResponse } from '../../../../../../../../common/endpoint/types'; +import { getMockTheme } from '../../../../../../../../public/common/lib/kibana/kibana_react.mock'; +import { useToasts } from '../../../../../../../common/lib/kibana'; +import { getHostIsolationExceptionSummary } from '../../../../../host_isolation_exceptions/service'; +import { FleetHostIsolationExceptionsCard } from './fleet_host_isolation_exceptions_card'; + +jest.mock('./exception_items_summary'); +jest.mock('../../../../../host_isolation_exceptions/service'); + +jest.mock('../../../../../../../../../../../src/plugins/kibana_react/public', () => { + const originalModule = jest.requireActual( + '../../../../../../../../../../../src/plugins/kibana_react/public' + ); + const useKibana = jest.fn().mockImplementation(() => ({ + services: { + http: {}, + data: {}, + notifications: {}, + application: { + getUrlForApp: jest.fn(), + }, + }, + })); + + return { + ...originalModule, + useKibana, + }; +}); + +jest.mock('../../../../../../../common/lib/kibana'); + +const mockTheme = getMockTheme({ + eui: { + paddingSizes: { m: '2' }, + }, +}); + +const getHostIsolationExceptionSummaryMock = getHostIsolationExceptionSummary as jest.Mock; +const useToastsMock = useToasts as jest.Mock; + +const summary: GetExceptionSummaryResponse = { + windows: 3, + linux: 2, + macos: 2, + total: 7, +}; + +describe('Fleet host isolation exceptions card filters card', () => { + let promise: Promise; + let addDanger: jest.Mock = jest.fn(); + const renderComponent: () => Promise = async () => { + const Wrapper: React.FC = ({ children }) => ( + + {children} + + ); + // @ts-expect-error TS2739 + const component = reactTestingLibrary.render(, { + wrapper: Wrapper, + }); + try { + // @ts-expect-error TS2769 + await reactTestingLibrary.act(() => promise); + } catch (err) { + return component; + } + return component; + }; + beforeAll(() => { + useToastsMock.mockImplementation(() => { + return { + addDanger, + }; + }); + }); + beforeEach(() => { + promise = Promise.resolve(summary); + addDanger = jest.fn(); + }); + afterEach(() => { + getHostIsolationExceptionSummaryMock.mockReset(); + }); + it('should render correctly', async () => { + getHostIsolationExceptionSummaryMock.mockReturnValueOnce(promise); + const component = await renderComponent(); + expect(component.getByText('Host isolation exceptions')).not.toBeNull(); + expect(component.getByText('Manage')).not.toBeNull(); + }); + it('should render an error toast when api call fails', async () => { + expect(addDanger).toBeCalledTimes(0); + promise = Promise.reject(new Error('error test')); + getHostIsolationExceptionSummaryMock.mockReturnValueOnce(promise); + const component = await renderComponent(); + expect(component.getByText('Host isolation exceptions')).not.toBeNull(); + expect(component.getByText('Manage')).not.toBeNull(); + await reactTestingLibrary.waitFor(() => expect(addDanger).toBeCalledTimes(1)); + }); +}); diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_package_custom_extension/components/fleet_host_isolation_exceptions_card.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_package_custom_extension/components/fleet_host_isolation_exceptions_card.tsx new file mode 100644 index 0000000000000..535c0be4736cc --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_package_custom_extension/components/fleet_host_isolation_exceptions_card.tsx @@ -0,0 +1,130 @@ +/* + * 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 { EuiPanel, EuiText } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; +import React, { memo, useEffect, useMemo, useRef, useState } from 'react'; +import { INTEGRATIONS_PLUGIN_ID } from '../../../../../../../../../fleet/common'; +import { + PackageCustomExtensionComponentProps, + pagePathGetters, +} from '../../../../../../../../../fleet/public'; +import { + GetExceptionSummaryResponse, + ListPageRouteState, +} from '../../../../../../../../common/endpoint/types'; +import { useKibana, useToasts } from '../../../../../../../common/lib/kibana'; +import { useAppUrl } from '../../../../../../../common/lib/kibana/hooks'; +import { getHostIsolationExceptionsListPath } from '../../../../../../common/routing'; +import { getHostIsolationExceptionSummary } from '../../../../../host_isolation_exceptions/service'; +import { ExceptionItemsSummary } from './exception_items_summary'; +import { LinkWithIcon } from './link_with_icon'; +import { StyledEuiFlexGridGroup, StyledEuiFlexGridItem } from './styled_components'; + +export const FleetHostIsolationExceptionsCard = memo( + ({ pkgkey }) => { + const { getAppUrl } = useAppUrl(); + const { + services: { http }, + } = useKibana(); + const toasts = useToasts(); + const [stats, setStats] = useState(); + const hostIsolationExceptionsListUrlPath = getHostIsolationExceptionsListPath(); + const isMounted = useRef(); + + useEffect(() => { + isMounted.current = true; + const fetchStats = async () => { + try { + const summary = await getHostIsolationExceptionSummary(http); + if (isMounted.current) { + setStats(summary); + } + } catch (error) { + if (isMounted.current) { + toasts.addDanger( + i18n.translate( + 'xpack.securitySolution.endpoint.fleetCustomExtension.hostIsolationExceptionsSummary.error', + { + defaultMessage: + 'There was an error trying to fetch host isolation exceptions stats: "{error}"', + values: { error }, + } + ) + ); + } + } + }; + fetchStats(); + return () => { + isMounted.current = false; + }; + }, [http, toasts]); + + const hostIsolationExceptionsRouteState = useMemo(() => { + const fleetPackageCustomUrlPath = `#${ + pagePathGetters.integration_details_custom({ pkgkey })[1] + }`; + return { + backButtonLabel: i18n.translate( + 'xpack.securitySolution.endpoint.fleetCustomExtension.hostIsolationExceptionsSummary.backButtonLabel', + { defaultMessage: 'Back to Endpoint Integration' } + ), + onBackButtonNavigateTo: [ + INTEGRATIONS_PLUGIN_ID, + { + path: fleetPackageCustomUrlPath, + }, + ], + backButtonUrl: getAppUrl({ + appId: INTEGRATIONS_PLUGIN_ID, + path: fleetPackageCustomUrlPath, + }), + }; + }, [getAppUrl, pkgkey]); + + return ( + + + + +

    + +

    +
    +
    + + + + + <> + + + + + +
    +
    + ); + } +); + +FleetHostIsolationExceptionsCard.displayName = 'FleetHostIsolationExceptionsCard'; diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_package_custom_extension/components/fleet_trusted_apps_card.test.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_package_custom_extension/components/fleet_trusted_apps_card.test.tsx index c61f109c75a1e..1da2c41324f56 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_package_custom_extension/components/fleet_trusted_apps_card.test.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_package_custom_extension/components/fleet_trusted_apps_card.test.tsx @@ -100,8 +100,8 @@ describe('Fleet trusted apps card', () => { }; }); const component = await renderComponent(); - expect(component.getByText('Trusted Applications')).not.toBeNull(); - expect(component.getByText('Manage trusted applications')).not.toBeNull(); + expect(component.getByText('Trusted applications')).not.toBeNull(); + expect(component.getByText('Manage')).not.toBeNull(); }); it('should render an error toast when api call fails', async () => { expect(addDanger).toBeCalledTimes(0); @@ -112,8 +112,8 @@ describe('Fleet trusted apps card', () => { }; }); const component = await renderComponent(); - expect(component.getByText('Trusted Applications')).not.toBeNull(); - expect(component.getByText('Manage trusted applications')).not.toBeNull(); + expect(component.getByText('Trusted applications')).not.toBeNull(); + expect(component.getByText('Manage')).not.toBeNull(); await reactTestingLibrary.waitFor(() => expect(addDanger).toBeCalledTimes(1)); }); }); diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_package_custom_extension/components/fleet_trusted_apps_card.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_package_custom_extension/components/fleet_trusted_apps_card.tsx index 54b1c37c7093f..680023cc6fd07 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_package_custom_extension/components/fleet_trusted_apps_card.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_package_custom_extension/components/fleet_trusted_apps_card.tsx @@ -72,7 +72,7 @@ export const FleetTrustedAppsCard = memo( const getTitleMessage = () => ( ); diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_package_custom_extension/components/fleet_trusted_apps_card_wrapper.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_package_custom_extension/components/fleet_trusted_apps_card_wrapper.tsx index 5ac79a5dd5d5a..848a0916b1d2e 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_package_custom_extension/components/fleet_trusted_apps_card_wrapper.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_package_custom_extension/components/fleet_trusted_apps_card_wrapper.tsx @@ -59,8 +59,8 @@ export const FleetTrustedAppsCardWrapper = memo ), diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_package_custom_extension/components/styled_components.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_package_custom_extension/components/styled_components.tsx index ad1d823677f22..ce28b4ac6c1cc 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_package_custom_extension/components/styled_components.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_package_custom_extension/components/styled_components.tsx @@ -9,7 +9,7 @@ import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; export const StyledEuiFlexGridGroup = styled(EuiFlexGroup)` display: grid; - grid-template-columns: 25% 45% 30%; + grid-template-columns: 33% 45% 22%; grid-template-areas: 'title summary link'; `; diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_package_custom_extension/index.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_package_custom_extension/index.tsx index 0748a95f63c9f..d53fe308a90ec 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_package_custom_extension/index.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_package_custom_extension/index.tsx @@ -8,8 +8,9 @@ import { EuiSpacer } from '@elastic/eui'; import React, { memo } from 'react'; import { PackageCustomExtensionComponentProps } from '../../../../../../../../fleet/public'; -import { FleetTrustedAppsCardWrapper } from './components/fleet_trusted_apps_card_wrapper'; import { FleetEventFiltersCard } from './components/fleet_event_filters_card'; +import { FleetHostIsolationExceptionsCard } from './components/fleet_host_isolation_exceptions_card'; +import { FleetTrustedAppsCardWrapper } from './components/fleet_trusted_apps_card_wrapper'; export const EndpointPackageCustomExtension = memo( (props) => { @@ -18,6 +19,8 @@ export const EndpointPackageCustomExtension = memo + +
    ); } diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index a41fe672a34d0..9be504204ea6a 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -21413,8 +21413,6 @@ "xpack.securitySolution.endpoint.fleetCustomExtension.exceptionItemsSummary.macos": "Mac", "xpack.securitySolution.endpoint.fleetCustomExtension.exceptionItemsSummary.total": "合計", "xpack.securitySolution.endpoint.fleetCustomExtension.exceptionItemsSummary.windows": "Windows", - "xpack.securitySolution.endpoint.fleetCustomExtension.manageEventFiltersLinkLabel": "イベントフィルターの管理", - "xpack.securitySolution.endpoint.fleetCustomExtension.manageTrustedAppLinkLabel": "信頼できるアプリケーションを管理", "xpack.securitySolution.endpoint.fleetCustomExtension.trustedAppsLabel": "信頼できるアプリケーション", "xpack.securitySolution.endpoint.fleetCustomExtension.trustedAppsSummaryError": "信頼できるアプリ統計情報の取得中にエラーが発生しました:\"{error}\"", "xpack.securitySolution.endpoint.hostIsolation.cancel": "キャンセル", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index f293283fdedf2..095180ca86057 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -21750,8 +21750,6 @@ "xpack.securitySolution.endpoint.fleetCustomExtension.exceptionItemsSummary.macos": "Mac", "xpack.securitySolution.endpoint.fleetCustomExtension.exceptionItemsSummary.total": "合计", "xpack.securitySolution.endpoint.fleetCustomExtension.exceptionItemsSummary.windows": "Windows", - "xpack.securitySolution.endpoint.fleetCustomExtension.manageEventFiltersLinkLabel": "管理事件筛选", - "xpack.securitySolution.endpoint.fleetCustomExtension.manageTrustedAppLinkLabel": "管理受信任的应用程序", "xpack.securitySolution.endpoint.fleetCustomExtension.trustedAppsLabel": "受信任的应用程序", "xpack.securitySolution.endpoint.fleetCustomExtension.trustedAppsSummaryError": "尝试提取受信任应用统计时出错:“{error}”", "xpack.securitySolution.endpoint.hostIsolation.cancel": "取消", From 00cbc6324aaa5de1f07b715b7c6fabab811c2871 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Thu, 18 Nov 2021 14:57:29 -0500 Subject: [PATCH 126/148] [Maps] Propagate http abort requests to Elasticsearch for mvt endpoints (#119043) --- .../plugins/maps/server/mvt/get_grid_tile.ts | 17 +++++++++----- x-pack/plugins/maps/server/mvt/get_tile.ts | 17 +++++++++----- x-pack/plugins/maps/server/mvt/mvt_routes.ts | 22 +++++++++---------- 3 files changed, 34 insertions(+), 22 deletions(-) diff --git a/x-pack/plugins/maps/server/mvt/get_grid_tile.ts b/x-pack/plugins/maps/server/mvt/get_grid_tile.ts index 86abff86081a6..59e3d791fd8a9 100644 --- a/x-pack/plugins/maps/server/mvt/get_grid_tile.ts +++ b/x-pack/plugins/maps/server/mvt/get_grid_tile.ts @@ -23,6 +23,7 @@ export async function getEsGridTile({ z, requestBody = {}, requestType = RENDER_AS.POINT, + abortController, }: { x: number; y: number; @@ -33,6 +34,7 @@ export async function getEsGridTile({ logger: Logger; requestBody: any; requestType: RENDER_AS.GRID | RENDER_AS.POINT; + abortController: AbortController; }): Promise { try { const path = `/${encodeURIComponent(index)}/_mvt/${geometryFieldName}/${z}/${x}/${y}`; @@ -47,11 +49,16 @@ export async function getEsGridTile({ fields: requestBody.fields, runtime_mappings: requestBody.runtime_mappings, }; - const tile = await context.core.elasticsearch.client.asCurrentUser.transport.request({ - method: 'GET', - path, - body, - }); + const tile = await context.core.elasticsearch.client.asCurrentUser.transport.request( + { + method: 'GET', + path, + body, + }, + { + signal: abortController.signal, + } + ); return tile.body as unknown as Buffer; } catch (e) { if (!isAbortError(e)) { diff --git a/x-pack/plugins/maps/server/mvt/get_tile.ts b/x-pack/plugins/maps/server/mvt/get_tile.ts index 0864b373af3f8..478b4343038e3 100644 --- a/x-pack/plugins/maps/server/mvt/get_tile.ts +++ b/x-pack/plugins/maps/server/mvt/get_tile.ts @@ -22,6 +22,7 @@ export async function getEsTile({ y, z, requestBody = {}, + abortController, }: { x: number; y: number; @@ -31,6 +32,7 @@ export async function getEsTile({ context: DataRequestHandlerContext; logger: Logger; requestBody: any; + abortController: AbortController; }): Promise { try { const path = `/${encodeURIComponent(index)}/_mvt/${geometryFieldName}/${z}/${x}/${y}`; @@ -45,11 +47,16 @@ export async function getEsTile({ runtime_mappings: requestBody.runtime_mappings, track_total_hits: requestBody.size + 1, }; - const tile = await context.core.elasticsearch.client.asCurrentUser.transport.request({ - method: 'GET', - path, - body, - }); + const tile = await context.core.elasticsearch.client.asCurrentUser.transport.request( + { + method: 'GET', + path, + body, + }, + { + signal: abortController.signal, + } + ); return tile.body as unknown as Buffer; } catch (e) { if (!isAbortError(e)) { diff --git a/x-pack/plugins/maps/server/mvt/mvt_routes.ts b/x-pack/plugins/maps/server/mvt/mvt_routes.ts index 3c61a47a383d6..317f62e50825e 100644 --- a/x-pack/plugins/maps/server/mvt/mvt_routes.ts +++ b/x-pack/plugins/maps/server/mvt/mvt_routes.ts @@ -10,8 +10,6 @@ import { schema } from '@kbn/config-schema'; import { KibanaRequest, KibanaResponseFactory, Logger } from 'src/core/server'; import { IRouter } from 'src/core/server'; import type { DataRequestHandlerContext } from 'src/plugins/data/server'; -// @ts-ignore not typed -import { AbortController } from 'abortcontroller-polyfill/dist/cjs-ponyfill'; import { MVT_GETTILE_API_PATH, API_ROOT_PATH, @@ -54,11 +52,10 @@ export function initMVTRoutes({ ) => { const { query, params } = request; - // todo - replace with direct abortion of raw transport request - // const abortController = new AbortController(); - // request.events.aborted$.subscribe(() => { - // abortController.abort(); - // }); + const abortController = new AbortController(); + request.events.aborted$.subscribe(() => { + abortController.abort(); + }); const requestBodyDSL = rison.decode(query.requestBody as string); @@ -71,6 +68,7 @@ export function initMVTRoutes({ z: parseInt((params as any).z, 10) as number, index: query.index as string, requestBody: requestBodyDSL as any, + abortController, }); return sendResponse(response, tile); @@ -102,11 +100,10 @@ export function initMVTRoutes({ ) => { const { query, params } = request; - // todo - replace with direct abortion of raw transport request - // const abortController = new AbortController(); - // request.events.aborted$.subscribe(() => { - // abortController.abort(); - // }); + const abortController = new AbortController(); + request.events.aborted$.subscribe(() => { + abortController.abort(); + }); const requestBodyDSL = rison.decode(query.requestBody as string); @@ -120,6 +117,7 @@ export function initMVTRoutes({ index: query.index as string, requestBody: requestBodyDSL as any, requestType: query.requestType as RENDER_AS.POINT | RENDER_AS.GRID, + abortController, }); return sendResponse(response, tile); From 293bde0df1fd3cd3e03528cadfcf492924d83e20 Mon Sep 17 00:00:00 2001 From: "Joey F. Poon" Date: Thu, 18 Nov 2021 14:11:06 -0600 Subject: [PATCH 127/148] [Security Solution] add new GET endpoint metadata list api (#118968) --- .../common/endpoint/types/index.ts | 21 +- .../endpoint/routes/metadata/handlers.ts | 124 +- .../server/endpoint/routes/metadata/index.ts | 44 +- .../endpoint/routes/metadata/metadata.test.ts | 1557 +++++++++++------ .../routes/metadata/query_builders.test.ts | 99 +- .../routes/metadata/query_builders.ts | 44 +- .../routes/metadata/support/agent_status.ts | 2 +- .../endpoint_metadata_service.test.ts | 20 +- .../metadata/endpoint_metadata_service.ts | 10 +- .../server/endpoint/types.ts | 10 - .../apis/metadata.ts | 1123 ++++++++---- 11 files changed, 2088 insertions(+), 966 deletions(-) diff --git a/x-pack/plugins/security_solution/common/endpoint/types/index.ts b/x-pack/plugins/security_solution/common/endpoint/types/index.ts index 2fee3e4c39d1d..2dc4f49919ef7 100644 --- a/x-pack/plugins/security_solution/common/endpoint/types/index.ts +++ b/x-pack/plugins/security_solution/common/endpoint/types/index.ts @@ -177,7 +177,7 @@ export interface ResolverPaginatedEvents { } /** - * Returned by the server via /api/endpoint/metadata + * Returned by the server via POST /api/endpoint/metadata */ export interface HostResultList { /* the hosts restricted by the page size */ @@ -1231,3 +1231,22 @@ export interface ListPageRouteState { /** The label for the button */ backButtonLabel?: string; } + +/** + * REST API standard base response for list types + */ +export interface BaseListResponse { + data: unknown[]; + page: number; + pageSize: number; + total: number; + sort?: string; + sortOrder?: 'asc' | 'desc'; +} + +/** + * Returned by the server via GET /api/endpoint/metadata + */ +export interface MetadataListResponse extends BaseListResponse { + data: HostInfo[]; +} diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/metadata/handlers.ts b/x-pack/plugins/security_solution/server/endpoint/routes/metadata/handlers.ts index 384fde6c7ceac..8b0e5abad228b 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/metadata/handlers.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/metadata/handlers.ts @@ -11,7 +11,6 @@ import { TypeOf } from '@kbn/config-schema'; import { IKibanaResponse, IScopedClusterClient, - KibanaRequest, KibanaResponseFactory, Logger, RequestHandler, @@ -22,6 +21,7 @@ import { HostMetadata, HostResultList, HostStatus, + MetadataListResponse, } from '../../../../common/endpoint/types'; import type { SecuritySolutionRequestHandlerContext } from '../../../types'; @@ -33,7 +33,11 @@ import { import { Agent, PackagePolicy } from '../../../../../fleet/common/types/models'; import { AgentNotFoundError } from '../../../../../fleet/server'; import { EndpointAppContext, HostListQueryResult } from '../../types'; -import { GetMetadataListRequestSchema, GetMetadataRequestSchema } from './index'; +import { + GetMetadataListRequestSchema, + GetMetadataListRequestSchemaV2, + GetMetadataRequestSchema, +} from './index'; import { findAllUnenrolledAgentIds } from './support/unenroll'; import { getAllEndpointPackagePolicies } from './support/endpoint_package_policies'; import { findAgentIdsByStatus } from './support/agent_status'; @@ -125,33 +129,35 @@ export const getMetadataListRequestHandler = function ( context.core.savedObjects.client ); - body = await legacyListMetadataQuery( - context, - request, - endpointAppContext, - logger, - endpointPolicies - ); + const pagingProperties = await getPagingProperties(request, endpointAppContext); + + body = await legacyListMetadataQuery(context, endpointAppContext, logger, endpointPolicies, { + page: pagingProperties.pageIndex, + pageSize: pagingProperties.pageSize, + kuery: request?.body?.filters?.kql || '', + hostStatuses: request?.body?.filters?.host_status || [], + }); return response.ok({ body }); } // Unified index is installed and being used - perform search using new approach try { const pagingProperties = await getPagingProperties(request, endpointAppContext); - const { data, page, total, pageSize } = await endpointMetadataService.getHostMetadataList( + const { data, total } = await endpointMetadataService.getHostMetadataList( context.core.elasticsearch.client.asCurrentUser, { - page: pagingProperties.pageIndex + 1, + page: pagingProperties.pageIndex, pageSize: pagingProperties.pageSize, - filters: request.body?.filters || {}, + hostStatuses: request.body?.filters.host_status || [], + kuery: request.body?.filters.kql || '', } ); body = { hosts: data, - request_page_index: page - 1, total, - request_page_size: pageSize, + request_page_index: pagingProperties.pageIndex * pagingProperties.pageSize, + request_page_size: pagingProperties.pageSize, }; } catch (error) { return errorHandler(logger, response, error); @@ -161,6 +167,83 @@ export const getMetadataListRequestHandler = function ( }; }; +export function getMetadataListRequestHandlerV2( + endpointAppContext: EndpointAppContext, + logger: Logger +): RequestHandler< + unknown, + TypeOf, + unknown, + SecuritySolutionRequestHandlerContext +> { + return async (context, request, response) => { + const endpointMetadataService = endpointAppContext.service.getEndpointMetadataService(); + if (!endpointMetadataService) { + throw new EndpointError('endpoint metadata service not available'); + } + + let doesUnitedIndexExist = false; + let didUnitedIndexError = false; + let body: MetadataListResponse = { + data: [], + total: 0, + page: 0, + pageSize: 0, + }; + + try { + doesUnitedIndexExist = await endpointMetadataService.doesUnitedIndexExist( + context.core.elasticsearch.client.asCurrentUser + ); + } catch (error) { + // for better UX, try legacy query instead of immediately failing on united index error + didUnitedIndexError = true; + } + + // If no unified Index present, then perform a search using the legacy approach + if (!doesUnitedIndexExist || didUnitedIndexError) { + const endpointPolicies = await getAllEndpointPackagePolicies( + endpointAppContext.service.getPackagePolicyService(), + context.core.savedObjects.client + ); + + const legacyResponse = await legacyListMetadataQuery( + context, + endpointAppContext, + logger, + endpointPolicies, + request.query + ); + body = { + data: legacyResponse.hosts, + total: legacyResponse.total, + page: request.query.page, + pageSize: request.query.pageSize, + }; + return response.ok({ body }); + } + + // Unified index is installed and being used - perform search using new approach + try { + const { data, total } = await endpointMetadataService.getHostMetadataList( + context.core.elasticsearch.client.asCurrentUser, + request.query + ); + + body = { + data, + total, + page: request.query.page, + pageSize: request.query.pageSize, + }; + } catch (error) { + return errorHandler(logger, response, error); + } + + return response.ok({ body }); + }; +} + export const getMetadataRequestHandler = function ( endpointAppContext: EndpointAppContext, logger: Logger @@ -420,11 +503,10 @@ export async function enrichHostMetadata( async function legacyListMetadataQuery( context: SecuritySolutionRequestHandlerContext, - // eslint-disable-next-line @typescript-eslint/no-explicit-any - request: KibanaRequest, endpointAppContext: EndpointAppContext, logger: Logger, - endpointPolicies: PackagePolicy[] + endpointPolicies: PackagePolicy[], + queryOptions: TypeOf ): Promise { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const agentService = endpointAppContext.service.getAgentService()!; @@ -447,14 +529,16 @@ async function legacyListMetadataQuery( endpointPolicyIds ); - const statusesToFilter = request?.body?.filters?.host_status ?? []; const statusAgentIds = await findAgentIdsByStatus( agentService, context.core.elasticsearch.client.asCurrentUser, - statusesToFilter + queryOptions.hostStatuses ); - const queryParams = await kibanaRequestToMetadataListESQuery(request, endpointAppContext, { + const queryParams = await kibanaRequestToMetadataListESQuery({ + page: queryOptions.page, + pageSize: queryOptions.pageSize, + kuery: queryOptions.kuery, unenrolledAgentIds, statusAgentIds, }); diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/metadata/index.ts b/x-pack/plugins/security_solution/server/endpoint/routes/metadata/index.ts index d9c3e6c195307..5ea465aa21799 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/metadata/index.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/metadata/index.ts @@ -9,7 +9,12 @@ import { schema } from '@kbn/config-schema'; import { HostStatus } from '../../../../common/endpoint/types'; import { EndpointAppContext } from '../../types'; -import { getLogger, getMetadataListRequestHandler, getMetadataRequestHandler } from './handlers'; +import { + getLogger, + getMetadataListRequestHandler, + getMetadataRequestHandler, + getMetadataListRequestHandlerV2, +} from './handlers'; import type { SecuritySolutionPluginRouter } from '../../../types'; import { HOST_METADATA_GET_ROUTE, @@ -60,27 +65,54 @@ export const GetMetadataListRequestSchema = { ), }; +export const GetMetadataListRequestSchemaV2 = { + query: schema.object({ + page: schema.number({ defaultValue: 0 }), + pageSize: schema.number({ defaultValue: 10, min: 1, max: 10000 }), + kuery: schema.maybe(schema.string()), + hostStatuses: schema.arrayOf( + schema.oneOf([ + schema.literal(HostStatus.HEALTHY.toString()), + schema.literal(HostStatus.OFFLINE.toString()), + schema.literal(HostStatus.UPDATING.toString()), + schema.literal(HostStatus.UNHEALTHY.toString()), + schema.literal(HostStatus.INACTIVE.toString()), + ]), + { defaultValue: [] } + ), + }), +}; + export function registerEndpointRoutes( router: SecuritySolutionPluginRouter, endpointAppContext: EndpointAppContext ) { const logger = getLogger(endpointAppContext); - router.post( + router.get( { - path: `${HOST_METADATA_LIST_ROUTE}`, - validate: GetMetadataListRequestSchema, + path: HOST_METADATA_LIST_ROUTE, + validate: GetMetadataListRequestSchemaV2, options: { authRequired: true, tags: ['access:securitySolution'] }, }, - getMetadataListRequestHandler(endpointAppContext, logger) + getMetadataListRequestHandlerV2(endpointAppContext, logger) ); router.get( { - path: `${HOST_METADATA_GET_ROUTE}`, + path: HOST_METADATA_GET_ROUTE, validate: GetMetadataRequestSchema, options: { authRequired: true, tags: ['access:securitySolution'] }, }, getMetadataRequestHandler(endpointAppContext, logger) ); + + router.post( + { + path: HOST_METADATA_LIST_ROUTE, + validate: GetMetadataListRequestSchema, + options: { authRequired: true, tags: ['access:securitySolution'] }, + }, + getMetadataListRequestHandler(endpointAppContext, logger) + ); } diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/metadata/metadata.test.ts b/x-pack/plugins/security_solution/server/endpoint/routes/metadata/metadata.test.ts index c0be1c7530cb4..c1dfee0252b38 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/metadata/metadata.test.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/metadata/metadata.test.ts @@ -18,7 +18,12 @@ import { loggingSystemMock, savedObjectsClientMock, } from '../../../../../../../src/core/server/mocks'; -import { HostInfo, HostResultList, HostStatus } from '../../../../common/endpoint/types'; +import { + HostInfo, + HostResultList, + HostStatus, + MetadataListResponse, +} from '../../../../common/endpoint/types'; import { parseExperimentalConfigValue } from '../../../../common/experimental_features'; import { registerEndpointRoutes } from './index'; import { @@ -40,6 +45,7 @@ import { } from './support/test_support'; import { PackageService } from '../../../../../fleet/server/services'; import { + HOST_METADATA_GET_ROUTE, HOST_METADATA_LIST_ROUTE, metadataCurrentIndexPattern, metadataTransformPrefix, @@ -64,7 +70,7 @@ class IndexNotFoundException extends Error { } } -describe('test endpoint route', () => { +describe('test endpoint routes', () => { let routerMock: jest.Mocked; let mockResponse: jest.Mocked; let mockClusterClient: ClusterClientMock; @@ -113,552 +119,616 @@ describe('test endpoint route', () => { }); }); - describe('with .metrics-endpoint.metadata_united_default index', () => { - beforeEach(() => { - endpointAppContextService = new EndpointAppContextService(); - mockPackageService = createMockPackageService(); - mockPackageService.getInstallation.mockReturnValue( - Promise.resolve({ - installed_kibana: [], - package_assets: [], - es_index_patterns: {}, - name: '', - version: '', - install_status: 'installed', - install_version: '', - install_started_at: '', - install_source: 'registry', - installed_es: [ - { - id: 'logs-endpoint.events.security', - type: ElasticsearchAssetType.indexTemplate, - }, - { - id: `${metadataTransformPrefix}-0.16.0-dev.0`, - type: ElasticsearchAssetType.transform, - }, - ], - keep_policies_up_to_date: false, - }) - ); - endpointAppContextService.setup(createMockEndpointAppContextServiceSetupContract()); - endpointAppContextService.start({ ...startContract, packageService: mockPackageService }); - mockAgentService = startContract.agentService!; - mockAgentPolicyService = startContract.agentPolicyService!; + describe('POST list endpoints route', () => { + describe('with .metrics-endpoint.metadata_united_default index', () => { + beforeEach(() => { + endpointAppContextService = new EndpointAppContextService(); + mockPackageService = createMockPackageService(); + mockPackageService.getInstallation.mockReturnValue( + Promise.resolve({ + installed_kibana: [], + package_assets: [], + es_index_patterns: {}, + name: '', + version: '', + install_status: 'installed', + install_version: '', + install_started_at: '', + install_source: 'registry', + installed_es: [ + { + id: 'logs-endpoint.events.security', + type: ElasticsearchAssetType.indexTemplate, + }, + { + id: `${metadataTransformPrefix}-0.16.0-dev.0`, + type: ElasticsearchAssetType.transform, + }, + ], + keep_policies_up_to_date: false, + }) + ); + endpointAppContextService.setup(createMockEndpointAppContextServiceSetupContract()); + endpointAppContextService.start({ ...startContract, packageService: mockPackageService }); + mockAgentService = startContract.agentService!; + mockAgentPolicyService = startContract.agentPolicyService!; - registerEndpointRoutes(routerMock, { - logFactory: loggingSystemMock.create(), - service: endpointAppContextService, - config: () => Promise.resolve(createMockConfig()), - experimentalFeatures: parseExperimentalConfigValue(createMockConfig().enableExperimental), + registerEndpointRoutes(routerMock, { + logFactory: loggingSystemMock.create(), + service: endpointAppContextService, + config: () => Promise.resolve(createMockConfig()), + experimentalFeatures: parseExperimentalConfigValue(createMockConfig().enableExperimental), + }); }); - }); - afterEach(() => endpointAppContextService.stop()); + afterEach(() => endpointAppContextService.stop()); - it('should fallback to legacy index if index not found', async () => { - const mockRequest = httpServerMock.createKibanaRequest({}); - const response = legacyMetadataSearchResponseMock( - new EndpointDocGenerator().generateHostMetadata() - ); - (mockScopedClient.asCurrentUser.search as jest.Mock) - .mockImplementationOnce(() => { - throw new IndexNotFoundException(); - }) - .mockImplementationOnce(() => Promise.resolve({ body: response })); - [routeConfig, routeHandler] = routerMock.post.mock.calls.find(([{ path }]) => - path.startsWith(`${HOST_METADATA_LIST_ROUTE}`) - )!; - mockAgentService.getAgentStatusById = jest.fn().mockReturnValue('error'); - mockAgentService.listAgents = jest.fn().mockReturnValue(noUnenrolledAgent); - await routeHandler( - createRouteHandlerContext(mockScopedClient, mockSavedObjectClient), - mockRequest, - mockResponse - ); + it('should fallback to legacy index if index not found', async () => { + const mockRequest = httpServerMock.createKibanaRequest({}); + const response = legacyMetadataSearchResponseMock( + new EndpointDocGenerator().generateHostMetadata() + ); + (mockScopedClient.asCurrentUser.search as jest.Mock) + .mockImplementationOnce(() => { + throw new IndexNotFoundException(); + }) + .mockImplementationOnce(() => Promise.resolve({ body: response })); + [routeConfig, routeHandler] = routerMock.post.mock.calls.find(([{ path }]) => + path.startsWith(HOST_METADATA_LIST_ROUTE) + )!; + mockAgentService.getAgentStatusById = jest.fn().mockReturnValue('error'); + mockAgentService.listAgents = jest.fn().mockReturnValue(noUnenrolledAgent); + await routeHandler( + createRouteHandlerContext(mockScopedClient, mockSavedObjectClient), + mockRequest, + mockResponse + ); - const esSearchMock = mockScopedClient.asCurrentUser.search; - // should be called twice, united index first, then legacy index - expect(esSearchMock).toHaveBeenCalledTimes(2); - expect(esSearchMock.mock.calls[0][0]?.index).toEqual(METADATA_UNITED_INDEX); - expect(esSearchMock.mock.calls[1][0]?.index).toEqual(metadataCurrentIndexPattern); - expect(routeConfig.options).toEqual({ - authRequired: true, - tags: ['access:securitySolution'], + const esSearchMock = mockScopedClient.asCurrentUser.search; + // should be called twice, united index first, then legacy index + expect(esSearchMock).toHaveBeenCalledTimes(2); + expect(esSearchMock.mock.calls[0][0]?.index).toEqual(METADATA_UNITED_INDEX); + expect(esSearchMock.mock.calls[1][0]?.index).toEqual(metadataCurrentIndexPattern); + expect(routeConfig.options).toEqual({ + authRequired: true, + tags: ['access:securitySolution'], + }); + expect(mockResponse.ok).toBeCalled(); + const endpointResultList = mockResponse.ok.mock.calls[0][0]?.body as HostResultList; + expect(endpointResultList.hosts.length).toEqual(1); + expect(endpointResultList.total).toEqual(1); + expect(endpointResultList.request_page_index).toEqual(0); + expect(endpointResultList.request_page_size).toEqual(10); }); - expect(mockResponse.ok).toBeCalled(); - const endpointResultList = mockResponse.ok.mock.calls[0][0]?.body as HostResultList; - expect(endpointResultList.hosts.length).toEqual(1); - expect(endpointResultList.total).toEqual(1); - expect(endpointResultList.request_page_index).toEqual(0); - expect(endpointResultList.request_page_size).toEqual(10); - }); - it('should return expected metadata', async () => { - const mockRequest = httpServerMock.createKibanaRequest({ - body: { - paging_properties: [ - { - page_size: 10, - }, - { - page_index: 0, - }, - ], + it('should return expected metadata', async () => { + const mockRequest = httpServerMock.createKibanaRequest({ + body: { + paging_properties: [ + { + page_size: 10, + }, + { + page_index: 0, + }, + ], - filters: { - kql: 'not host.ip:10.140.73.246', - host_status: ['updating'], + filters: { + kql: 'not host.ip:10.140.73.246', + host_status: ['updating'], + }, }, - }, - }); + }); - mockAgentService.getAgentStatusById = jest.fn().mockReturnValue('error'); - mockAgentService.listAgents = jest.fn().mockReturnValue(noUnenrolledAgent); - mockAgentPolicyService.getByIds = jest.fn().mockResolvedValueOnce([]); - const metadata = new EndpointDocGenerator().generateHostMetadata(); - const esSearchMock = mockScopedClient.asCurrentUser.search as jest.Mock; - esSearchMock.mockResolvedValueOnce({}); - esSearchMock.mockResolvedValueOnce({ - body: unitedMetadataSearchResponseMock(metadata), - }); - [routeConfig, routeHandler] = routerMock.post.mock.calls.find(([{ path }]) => - path.startsWith(`${HOST_METADATA_LIST_ROUTE}`) - )!; + mockAgentService.getAgentStatusById = jest.fn().mockReturnValue('error'); + mockAgentService.listAgents = jest.fn().mockReturnValue(noUnenrolledAgent); + mockAgentPolicyService.getByIds = jest.fn().mockResolvedValueOnce([]); + const metadata = new EndpointDocGenerator().generateHostMetadata(); + const esSearchMock = mockScopedClient.asCurrentUser.search as jest.Mock; + esSearchMock.mockResolvedValueOnce({}); + esSearchMock.mockResolvedValueOnce({ + body: unitedMetadataSearchResponseMock(metadata), + }); + [routeConfig, routeHandler] = routerMock.post.mock.calls.find(([{ path }]) => + path.startsWith(HOST_METADATA_LIST_ROUTE) + )!; - await routeHandler( - createRouteHandlerContext(mockScopedClient, mockSavedObjectClient), - mockRequest, - mockResponse - ); + await routeHandler( + createRouteHandlerContext(mockScopedClient, mockSavedObjectClient), + mockRequest, + mockResponse + ); - expect(esSearchMock).toHaveBeenCalledTimes(2); - expect(esSearchMock.mock.calls[0][0]?.index).toEqual(METADATA_UNITED_INDEX); - expect(esSearchMock.mock.calls[0][0]?.size).toEqual(1); - expect(esSearchMock.mock.calls[1][0]?.index).toEqual(METADATA_UNITED_INDEX); - expect(esSearchMock.mock.calls[1][0]?.body?.query).toEqual({ - bool: { - must: [ - { - bool: { - filter: [ - { - terms: { - 'united.agent.policy_id': [], + expect(esSearchMock).toHaveBeenCalledTimes(2); + expect(esSearchMock.mock.calls[0][0]?.index).toEqual(METADATA_UNITED_INDEX); + expect(esSearchMock.mock.calls[0][0]?.size).toEqual(1); + expect(esSearchMock.mock.calls[1][0]?.index).toEqual(METADATA_UNITED_INDEX); + expect(esSearchMock.mock.calls[1][0]?.body?.query).toEqual({ + bool: { + must: [ + { + bool: { + filter: [ + { + terms: { + 'united.agent.policy_id': [], + }, }, - }, - { - exists: { - field: 'united.endpoint.agent.id', + { + exists: { + field: 'united.endpoint.agent.id', + }, }, - }, - { - exists: { - field: 'united.agent.agent.id', + { + exists: { + field: 'united.agent.agent.id', + }, }, - }, - { - term: { - 'united.agent.active': { - value: true, + { + term: { + 'united.agent.active': { + value: true, + }, }, }, - }, - ], - must_not: { - terms: { - 'agent.id': [ - '00000000-0000-0000-0000-000000000000', - '11111111-1111-1111-1111-111111111111', - ], + ], + must_not: { + terms: { + 'agent.id': [ + '00000000-0000-0000-0000-000000000000', + '11111111-1111-1111-1111-111111111111', + ], + }, }, }, }, - }, - { - bool: { - should: [ - { - bool: { - filter: [ - { + { + bool: { + should: [ + { + bool: { + filter: [ + { + bool: { + should: [ + { + exists: { + field: 'united.agent.upgrade_started_at', + }, + }, + ], + minimum_should_match: 1, + }, + }, + { + bool: { + must_not: { + bool: { + should: [ + { + exists: { + field: 'united.agent.upgraded_at', + }, + }, + ], + minimum_should_match: 1, + }, + }, + }, + }, + ], + }, + }, + { + bool: { + must_not: { bool: { should: [ { exists: { - field: 'united.agent.upgrade_started_at', + field: 'united.agent.last_checkin', }, }, ], minimum_should_match: 1, }, }, - { - bool: { - must_not: { - bool: { - should: [ - { - exists: { - field: 'united.agent.upgraded_at', - }, - }, - ], - minimum_should_match: 1, - }, - }, - }, - }, - ], + }, }, - }, - { - bool: { - must_not: { - bool: { - should: [ - { - exists: { - field: 'united.agent.last_checkin', - }, + { + bool: { + should: [ + { + exists: { + field: 'united.agent.unenrollment_started_at', }, - ], - minimum_should_match: 1, - }, + }, + ], + minimum_should_match: 1, }, }, - }, - { + ], + minimum_should_match: 1, + }, + }, + { + bool: { + must_not: { bool: { should: [ { - exists: { - field: 'united.agent.unenrollment_started_at', + match: { + 'host.ip': '10.140.73.246', }, }, ], minimum_should_match: 1, }, }, - ], - minimum_should_match: 1, - }, - }, - { - bool: { - must_not: { - bool: { - should: [ - { - match: { - 'host.ip': '10.140.73.246', - }, - }, - ], - minimum_should_match: 1, - }, }, }, - }, - ], - }, - }); - expect(routeConfig.options).toEqual({ - authRequired: true, - tags: ['access:securitySolution'], + ], + }, + }); + expect(routeConfig.options).toEqual({ + authRequired: true, + tags: ['access:securitySolution'], + }); + expect(mockResponse.ok).toBeCalled(); + const endpointResultList = mockResponse.ok.mock.calls[0][0]?.body as HostResultList; + expect(endpointResultList.hosts.length).toEqual(1); + expect(endpointResultList.hosts[0].metadata).toEqual(metadata); + expect(endpointResultList.total).toEqual(1); + expect(endpointResultList.request_page_index).toEqual(0); + expect(endpointResultList.request_page_size).toEqual(10); }); - expect(mockResponse.ok).toBeCalled(); - const endpointResultList = mockResponse.ok.mock.calls[0][0]?.body as HostResultList; - expect(endpointResultList.hosts.length).toEqual(1); - expect(endpointResultList.hosts[0].metadata).toEqual(metadata); - expect(endpointResultList.total).toEqual(1); - expect(endpointResultList.request_page_index).toEqual(0); - expect(endpointResultList.request_page_size).toEqual(10); }); - }); - describe('with metrics-endpoint.metadata_current_default index', () => { - beforeEach(() => { - endpointAppContextService = new EndpointAppContextService(); - mockPackageService = createMockPackageService(); - mockPackageService.getInstallation.mockReturnValue( - Promise.resolve({ - installed_kibana: [], - package_assets: [], - es_index_patterns: {}, - name: '', - version: '', - install_status: 'installed', - install_version: '', - install_started_at: '', - install_source: 'registry', - installed_es: [ - { - id: 'logs-endpoint.events.security', - type: ElasticsearchAssetType.indexTemplate, - }, - { - id: `${metadataTransformPrefix}-0.16.0-dev.0`, - type: ElasticsearchAssetType.transform, - }, - ], - keep_policies_up_to_date: false, - }) - ); - endpointAppContextService.setup(createMockEndpointAppContextServiceSetupContract()); - endpointAppContextService.start({ ...startContract, packageService: mockPackageService }); - mockAgentService = startContract.agentService!; + describe('with metrics-endpoint.metadata_current_default index', () => { + beforeEach(() => { + endpointAppContextService = new EndpointAppContextService(); + mockPackageService = createMockPackageService(); + mockPackageService.getInstallation.mockReturnValue( + Promise.resolve({ + installed_kibana: [], + package_assets: [], + es_index_patterns: {}, + name: '', + version: '', + install_status: 'installed', + install_version: '', + install_started_at: '', + install_source: 'registry', + installed_es: [ + { + id: 'logs-endpoint.events.security', + type: ElasticsearchAssetType.indexTemplate, + }, + { + id: `${metadataTransformPrefix}-0.16.0-dev.0`, + type: ElasticsearchAssetType.transform, + }, + ], + keep_policies_up_to_date: false, + }) + ); + endpointAppContextService.setup(createMockEndpointAppContextServiceSetupContract()); + endpointAppContextService.start({ ...startContract, packageService: mockPackageService }); + mockAgentService = startContract.agentService!; - registerEndpointRoutes(routerMock, { - logFactory: loggingSystemMock.create(), - service: endpointAppContextService, - config: () => Promise.resolve(createMockConfig()), - experimentalFeatures: parseExperimentalConfigValue(createMockConfig().enableExperimental), + registerEndpointRoutes(routerMock, { + logFactory: loggingSystemMock.create(), + service: endpointAppContextService, + config: () => Promise.resolve(createMockConfig()), + experimentalFeatures: parseExperimentalConfigValue(createMockConfig().enableExperimental), + }); }); - }); - afterEach(() => endpointAppContextService.stop()); + afterEach(() => endpointAppContextService.stop()); - it('test find the latest of all endpoints', async () => { - const mockRequest = httpServerMock.createKibanaRequest({}); - const response = legacyMetadataSearchResponseMock( - new EndpointDocGenerator().generateHostMetadata() - ); - (mockScopedClient.asCurrentUser.search as jest.Mock) - .mockImplementationOnce(() => { - throw new IndexNotFoundException(); - }) - .mockImplementationOnce(() => Promise.resolve({ body: response })); - [routeConfig, routeHandler] = routerMock.post.mock.calls.find(([{ path }]) => - path.startsWith(`${HOST_METADATA_LIST_ROUTE}`) - )!; - mockAgentService.getAgentStatusById = jest.fn().mockReturnValue('error'); - mockAgentService.listAgents = jest.fn().mockReturnValue(noUnenrolledAgent); - await routeHandler( - createRouteHandlerContext(mockScopedClient, mockSavedObjectClient), - mockRequest, - mockResponse - ); + it('test find the latest of all endpoints', async () => { + const mockRequest = httpServerMock.createKibanaRequest({}); + const response = legacyMetadataSearchResponseMock( + new EndpointDocGenerator().generateHostMetadata() + ); + (mockScopedClient.asCurrentUser.search as jest.Mock) + .mockImplementationOnce(() => { + throw new IndexNotFoundException(); + }) + .mockImplementationOnce(() => Promise.resolve({ body: response })); + [routeConfig, routeHandler] = routerMock.post.mock.calls.find(([{ path }]) => + path.startsWith(HOST_METADATA_LIST_ROUTE) + )!; + mockAgentService.getAgentStatusById = jest.fn().mockReturnValue('error'); + mockAgentService.listAgents = jest.fn().mockReturnValue(noUnenrolledAgent); + await routeHandler( + createRouteHandlerContext(mockScopedClient, mockSavedObjectClient), + mockRequest, + mockResponse + ); - expect(mockScopedClient.asCurrentUser.search).toHaveBeenCalledTimes(2); - expect(routeConfig.options).toEqual({ - authRequired: true, - tags: ['access:securitySolution'], - }); - expect(mockResponse.ok).toBeCalled(); - const endpointResultList = mockResponse.ok.mock.calls[0][0]?.body as HostResultList; - expect(endpointResultList.hosts.length).toEqual(1); - expect(endpointResultList.total).toEqual(1); - expect(endpointResultList.request_page_index).toEqual(0); - expect(endpointResultList.request_page_size).toEqual(10); - }); - - it('test find the latest of all endpoints with paging properties', async () => { - const mockRequest = httpServerMock.createKibanaRequest({ - body: { - paging_properties: [ - { - page_size: 10, - }, - { - page_index: 1, - }, - ], - }, + expect(mockScopedClient.asCurrentUser.search).toHaveBeenCalledTimes(2); + expect(routeConfig.options).toEqual({ + authRequired: true, + tags: ['access:securitySolution'], + }); + expect(mockResponse.ok).toBeCalled(); + const endpointResultList = mockResponse.ok.mock.calls[0][0]?.body as HostResultList; + expect(endpointResultList.hosts.length).toEqual(1); + expect(endpointResultList.total).toEqual(1); + expect(endpointResultList.request_page_index).toEqual(0); + expect(endpointResultList.request_page_size).toEqual(10); }); - mockAgentService.getAgentStatusById = jest.fn().mockReturnValue('error'); - mockAgentService.listAgents = jest.fn().mockReturnValue(noUnenrolledAgent); - (mockScopedClient.asCurrentUser.search as jest.Mock) - .mockImplementationOnce(() => { - throw new IndexNotFoundException(); - }) - .mockImplementationOnce(() => - Promise.resolve({ - body: legacyMetadataSearchResponseMock( - new EndpointDocGenerator().generateHostMetadata() - ), + it('test find the latest of all endpoints with paging properties', async () => { + const mockRequest = httpServerMock.createKibanaRequest({ + body: { + paging_properties: [ + { + page_size: 10, + }, + { + page_index: 1, + }, + ], + }, + }); + + mockAgentService.getAgentStatusById = jest.fn().mockReturnValue('error'); + mockAgentService.listAgents = jest.fn().mockReturnValue(noUnenrolledAgent); + (mockScopedClient.asCurrentUser.search as jest.Mock) + .mockImplementationOnce(() => { + throw new IndexNotFoundException(); }) - ); - [routeConfig, routeHandler] = routerMock.post.mock.calls.find(([{ path }]) => - path.startsWith(`${HOST_METADATA_LIST_ROUTE}`) - )!; + .mockImplementationOnce(() => + Promise.resolve({ + body: legacyMetadataSearchResponseMock( + new EndpointDocGenerator().generateHostMetadata() + ), + }) + ); + [routeConfig, routeHandler] = routerMock.post.mock.calls.find(([{ path }]) => + path.startsWith(HOST_METADATA_LIST_ROUTE) + )!; - await routeHandler( - createRouteHandlerContext(mockScopedClient, mockSavedObjectClient), - mockRequest, - mockResponse - ); - expect(mockScopedClient.asCurrentUser.search).toHaveBeenCalledTimes(2); - expect( - (mockScopedClient.asCurrentUser.search as jest.Mock).mock.calls[1][0]?.body?.query.bool - .must_not - ).toContainEqual({ - terms: { - 'elastic.agent.id': [ - '00000000-0000-0000-0000-000000000000', - '11111111-1111-1111-1111-111111111111', - ], - }, - }); - expect(routeConfig.options).toEqual({ - authRequired: true, - tags: ['access:securitySolution'], + await routeHandler( + createRouteHandlerContext(mockScopedClient, mockSavedObjectClient), + mockRequest, + mockResponse + ); + expect(mockScopedClient.asCurrentUser.search).toHaveBeenCalledTimes(2); + expect( + (mockScopedClient.asCurrentUser.search as jest.Mock).mock.calls[1][0]?.body?.query.bool + .must_not + ).toContainEqual({ + terms: { + 'elastic.agent.id': [ + '00000000-0000-0000-0000-000000000000', + '11111111-1111-1111-1111-111111111111', + ], + }, + }); + expect(routeConfig.options).toEqual({ + authRequired: true, + tags: ['access:securitySolution'], + }); + expect(mockResponse.ok).toBeCalled(); + const endpointResultList = mockResponse.ok.mock.calls[0][0]?.body as HostResultList; + expect(endpointResultList.hosts.length).toEqual(1); + expect(endpointResultList.total).toEqual(1); + expect(endpointResultList.request_page_index).toEqual(10); + expect(endpointResultList.request_page_size).toEqual(10); }); - expect(mockResponse.ok).toBeCalled(); - const endpointResultList = mockResponse.ok.mock.calls[0][0]?.body as HostResultList; - expect(endpointResultList.hosts.length).toEqual(1); - expect(endpointResultList.total).toEqual(1); - expect(endpointResultList.request_page_index).toEqual(10); - expect(endpointResultList.request_page_size).toEqual(10); - }); - it('test find the latest of all endpoints with paging and filters properties', async () => { - const mockRequest = httpServerMock.createKibanaRequest({ - body: { - paging_properties: [ - { - page_size: 10, - }, - { - page_index: 1, - }, - ], + it('test find the latest of all endpoints with paging and filters properties', async () => { + const mockRequest = httpServerMock.createKibanaRequest({ + body: { + paging_properties: [ + { + page_size: 10, + }, + { + page_index: 1, + }, + ], - filters: { kql: 'not host.ip:10.140.73.246' }, - }, - }); + filters: { kql: 'not host.ip:10.140.73.246' }, + }, + }); - mockAgentService.getAgentStatusById = jest.fn().mockReturnValue('error'); - mockAgentService.listAgents = jest.fn().mockReturnValue(noUnenrolledAgent); - (mockScopedClient.asCurrentUser.search as jest.Mock) - .mockImplementationOnce(() => { - throw new IndexNotFoundException(); - }) - .mockImplementationOnce(() => - Promise.resolve({ - body: legacyMetadataSearchResponseMock( - new EndpointDocGenerator().generateHostMetadata() - ), + mockAgentService.getAgentStatusById = jest.fn().mockReturnValue('error'); + mockAgentService.listAgents = jest.fn().mockReturnValue(noUnenrolledAgent); + (mockScopedClient.asCurrentUser.search as jest.Mock) + .mockImplementationOnce(() => { + throw new IndexNotFoundException(); }) - ); - [routeConfig, routeHandler] = routerMock.post.mock.calls.find(([{ path }]) => - path.startsWith(`${HOST_METADATA_LIST_ROUTE}`) - )!; + .mockImplementationOnce(() => + Promise.resolve({ + body: legacyMetadataSearchResponseMock( + new EndpointDocGenerator().generateHostMetadata() + ), + }) + ); + [routeConfig, routeHandler] = routerMock.post.mock.calls.find(([{ path }]) => + path.startsWith(HOST_METADATA_LIST_ROUTE) + )!; - await routeHandler( - createRouteHandlerContext(mockScopedClient, mockSavedObjectClient), - mockRequest, - mockResponse - ); + await routeHandler( + createRouteHandlerContext(mockScopedClient, mockSavedObjectClient), + mockRequest, + mockResponse + ); - expect(mockScopedClient.asCurrentUser.search).toBeCalled(); - expect( - // KQL filter to be passed through - (mockScopedClient.asCurrentUser.search as jest.Mock).mock.calls[1][0]?.body?.query.bool.must - ).toContainEqual({ - bool: { - must_not: { - bool: { - should: [ - { - match: { - 'host.ip': '10.140.73.246', + expect(mockScopedClient.asCurrentUser.search).toBeCalled(); + expect( + // KQL filter to be passed through + (mockScopedClient.asCurrentUser.search as jest.Mock).mock.calls[1][0]?.body?.query.bool + .must + ).toContainEqual({ + bool: { + must_not: { + bool: { + should: [ + { + match: { + 'host.ip': '10.140.73.246', + }, }, - }, - ], - minimum_should_match: 1, - }, - }, - }, - }); - expect( - (mockScopedClient.asCurrentUser.search as jest.Mock).mock.calls[1][0]?.body?.query.bool.must - ).toContainEqual({ - bool: { - must_not: [ - { - terms: { - 'elastic.agent.id': [ - '00000000-0000-0000-0000-000000000000', - '11111111-1111-1111-1111-111111111111', ], + minimum_should_match: 1, }, }, - { - terms: { - // here we DO want to see both schemas are present - // to make this schema-compatible forward and back - 'HostDetails.elastic.agent.id': [ - '00000000-0000-0000-0000-000000000000', - '11111111-1111-1111-1111-111111111111', - ], + }, + }); + expect( + (mockScopedClient.asCurrentUser.search as jest.Mock).mock.calls[1][0]?.body?.query.bool + .must + ).toContainEqual({ + bool: { + must_not: [ + { + terms: { + 'elastic.agent.id': [ + '00000000-0000-0000-0000-000000000000', + '11111111-1111-1111-1111-111111111111', + ], + }, }, - }, - ], - }, - }); - expect(routeConfig.options).toEqual({ - authRequired: true, - tags: ['access:securitySolution'], + { + terms: { + // here we DO want to see both schemas are present + // to make this schema-compatible forward and back + 'HostDetails.elastic.agent.id': [ + '00000000-0000-0000-0000-000000000000', + '11111111-1111-1111-1111-111111111111', + ], + }, + }, + ], + }, + }); + expect(routeConfig.options).toEqual({ + authRequired: true, + tags: ['access:securitySolution'], + }); + expect(mockResponse.ok).toBeCalled(); + const endpointResultList = mockResponse.ok.mock.calls[0][0]?.body as HostResultList; + expect(endpointResultList.hosts.length).toEqual(1); + expect(endpointResultList.total).toEqual(1); + expect(endpointResultList.request_page_index).toEqual(10); + expect(endpointResultList.request_page_size).toEqual(10); }); - expect(mockResponse.ok).toBeCalled(); - const endpointResultList = mockResponse.ok.mock.calls[0][0]?.body as HostResultList; - expect(endpointResultList.hosts.length).toEqual(1); - expect(endpointResultList.total).toEqual(1); - expect(endpointResultList.request_page_index).toEqual(10); - expect(endpointResultList.request_page_size).toEqual(10); }); + }); - describe('Endpoint Details route', () => { - it('should return 404 on no results', async () => { - const mockRequest = httpServerMock.createKibanaRequest({ params: { id: 'BADID' } }); - - (mockScopedClient.asCurrentUser.search as jest.Mock).mockImplementationOnce(() => - Promise.resolve({ body: legacyMetadataSearchResponseMock() }) + describe('GET list endpoints route', () => { + describe('with .metrics-endpoint.metadata_united_default index', () => { + beforeEach(() => { + endpointAppContextService = new EndpointAppContextService(); + mockPackageService = createMockPackageService(); + mockPackageService.getInstallation.mockReturnValue( + Promise.resolve({ + installed_kibana: [], + package_assets: [], + es_index_patterns: {}, + name: '', + version: '', + install_status: 'installed', + install_version: '', + install_started_at: '', + install_source: 'registry', + installed_es: [ + { + id: 'logs-endpoint.events.security', + type: ElasticsearchAssetType.indexTemplate, + }, + { + id: `${metadataTransformPrefix}-0.16.0-dev.0`, + type: ElasticsearchAssetType.transform, + }, + ], + keep_policies_up_to_date: false, + }) ); + endpointAppContextService.setup(createMockEndpointAppContextServiceSetupContract()); + endpointAppContextService.start({ ...startContract, packageService: mockPackageService }); + mockAgentService = startContract.agentService!; + mockAgentPolicyService = startContract.agentPolicyService!; - mockAgentService.getAgentStatusById = jest.fn().mockReturnValue('error'); - mockAgentService.getAgent = jest.fn().mockReturnValue({ - active: true, - } as unknown as Agent); + registerEndpointRoutes(routerMock, { + logFactory: loggingSystemMock.create(), + service: endpointAppContextService, + config: () => Promise.resolve(createMockConfig()), + experimentalFeatures: parseExperimentalConfigValue(createMockConfig().enableExperimental), + }); + }); + + afterEach(() => endpointAppContextService.stop()); + it('should fallback to legacy index if index not found', async () => { + const mockRequest = httpServerMock.createKibanaRequest({ + query: { + page: 0, + pageSize: 10, + }, + }); + const response = legacyMetadataSearchResponseMock( + new EndpointDocGenerator().generateHostMetadata() + ); + (mockScopedClient.asCurrentUser.search as jest.Mock) + .mockImplementationOnce(() => { + throw new IndexNotFoundException(); + }) + .mockImplementationOnce(() => Promise.resolve({ body: response })); [routeConfig, routeHandler] = routerMock.get.mock.calls.find(([{ path }]) => - path.startsWith(`${HOST_METADATA_LIST_ROUTE}`) + path.startsWith(HOST_METADATA_LIST_ROUTE) )!; + mockAgentService.getAgentStatusById = jest.fn().mockReturnValue('error'); + mockAgentService.listAgents = jest.fn().mockReturnValue(noUnenrolledAgent); await routeHandler( createRouteHandlerContext(mockScopedClient, mockSavedObjectClient), mockRequest, mockResponse ); - expect(mockScopedClient.asCurrentUser.search).toHaveBeenCalledTimes(1); + const esSearchMock = mockScopedClient.asCurrentUser.search; + // should be called twice, united index first, then legacy index + expect(esSearchMock).toHaveBeenCalledTimes(2); + expect(esSearchMock.mock.calls[0][0]?.index).toEqual(METADATA_UNITED_INDEX); + expect(esSearchMock.mock.calls[1][0]?.index).toEqual(metadataCurrentIndexPattern); expect(routeConfig.options).toEqual({ authRequired: true, tags: ['access:securitySolution'], }); - expect(mockResponse.notFound).toBeCalled(); - const message = mockResponse.notFound.mock.calls[0][0]?.body; - expect(message).toBeInstanceOf(EndpointHostNotFoundError); + expect(mockResponse.ok).toBeCalled(); + const endpointResultList = mockResponse.ok.mock.calls[0][0]?.body as MetadataListResponse; + expect(endpointResultList.data.length).toEqual(1); + expect(endpointResultList.total).toEqual(1); + expect(endpointResultList.page).toEqual(0); + expect(endpointResultList.pageSize).toEqual(10); }); - it('should return a single endpoint with status healthy', async () => { - const response = legacyMetadataSearchResponseMock( - new EndpointDocGenerator().generateHostMetadata() - ); + it('should return expected metadata', async () => { const mockRequest = httpServerMock.createKibanaRequest({ - params: { id: response.hits.hits[0]._id }, + query: { + page: 0, + pageSize: 10, + hostStatuses: ['updating'], + kuery: 'not host.ip:10.140.73.246', + }, }); - mockAgentService.getAgent = jest - .fn() - .mockReturnValue(agentGenerator.generate({ status: 'online' })); - (mockScopedClient.asCurrentUser.search as jest.Mock).mockImplementationOnce(() => - Promise.resolve({ body: response }) - ); - + mockAgentService.getAgentStatusById = jest.fn().mockReturnValue('error'); + mockAgentService.listAgents = jest.fn().mockReturnValue(noUnenrolledAgent); + mockAgentPolicyService.getByIds = jest.fn().mockResolvedValueOnce([]); + const metadata = new EndpointDocGenerator().generateHostMetadata(); + const esSearchMock = mockScopedClient.asCurrentUser.search as jest.Mock; + esSearchMock.mockResolvedValueOnce({}); + esSearchMock.mockResolvedValueOnce({ + body: unitedMetadataSearchResponseMock(metadata), + }); [routeConfig, routeHandler] = routerMock.get.mock.calls.find(([{ path }]) => - path.startsWith(`${HOST_METADATA_LIST_ROUTE}`) + path.startsWith(HOST_METADATA_LIST_ROUTE) )!; await routeHandler( @@ -667,74 +737,255 @@ describe('test endpoint route', () => { mockResponse ); - expect(mockScopedClient.asCurrentUser.search).toHaveBeenCalledTimes(1); + expect(esSearchMock).toHaveBeenCalledTimes(2); + expect(esSearchMock.mock.calls[0][0]?.index).toEqual(METADATA_UNITED_INDEX); + expect(esSearchMock.mock.calls[0][0]?.size).toEqual(1); + expect(esSearchMock.mock.calls[1][0]?.index).toEqual(METADATA_UNITED_INDEX); + expect(esSearchMock.mock.calls[1][0]?.body?.query).toEqual({ + bool: { + must: [ + { + bool: { + filter: [ + { + terms: { + 'united.agent.policy_id': [], + }, + }, + { + exists: { + field: 'united.endpoint.agent.id', + }, + }, + { + exists: { + field: 'united.agent.agent.id', + }, + }, + { + term: { + 'united.agent.active': { + value: true, + }, + }, + }, + ], + must_not: { + terms: { + 'agent.id': [ + '00000000-0000-0000-0000-000000000000', + '11111111-1111-1111-1111-111111111111', + ], + }, + }, + }, + }, + { + bool: { + should: [ + { + bool: { + filter: [ + { + bool: { + should: [ + { + exists: { + field: 'united.agent.upgrade_started_at', + }, + }, + ], + minimum_should_match: 1, + }, + }, + { + bool: { + must_not: { + bool: { + should: [ + { + exists: { + field: 'united.agent.upgraded_at', + }, + }, + ], + minimum_should_match: 1, + }, + }, + }, + }, + ], + }, + }, + { + bool: { + must_not: { + bool: { + should: [ + { + exists: { + field: 'united.agent.last_checkin', + }, + }, + ], + minimum_should_match: 1, + }, + }, + }, + }, + { + bool: { + should: [ + { + exists: { + field: 'united.agent.unenrollment_started_at', + }, + }, + ], + minimum_should_match: 1, + }, + }, + ], + minimum_should_match: 1, + }, + }, + { + bool: { + must_not: { + bool: { + should: [ + { + match: { + 'host.ip': '10.140.73.246', + }, + }, + ], + minimum_should_match: 1, + }, + }, + }, + }, + ], + }, + }); expect(routeConfig.options).toEqual({ authRequired: true, tags: ['access:securitySolution'], }); expect(mockResponse.ok).toBeCalled(); - const result = mockResponse.ok.mock.calls[0][0]?.body as HostInfo; - expect(result).toHaveProperty('metadata.Endpoint'); - expect(result.host_status).toEqual(HostStatus.HEALTHY); + const endpointResultList = mockResponse.ok.mock.calls[0][0]?.body as MetadataListResponse; + expect(endpointResultList.data.length).toEqual(1); + expect(endpointResultList.data[0].metadata).toEqual(metadata); + expect(endpointResultList.total).toEqual(1); + expect(endpointResultList.page).toEqual(0); + expect(endpointResultList.pageSize).toEqual(10); }); + }); - it('should return a single endpoint with status unhealthy when AgentService throw 404', async () => { - const response = legacyMetadataSearchResponseMock( - new EndpointDocGenerator().generateHostMetadata() + describe('with metrics-endpoint.metadata_current_default index', () => { + beforeEach(() => { + endpointAppContextService = new EndpointAppContextService(); + mockPackageService = createMockPackageService(); + mockPackageService.getInstallation.mockReturnValue( + Promise.resolve({ + installed_kibana: [], + package_assets: [], + es_index_patterns: {}, + name: '', + version: '', + install_status: 'installed', + install_version: '', + install_started_at: '', + install_source: 'registry', + installed_es: [ + { + id: 'logs-endpoint.events.security', + type: ElasticsearchAssetType.indexTemplate, + }, + { + id: `${metadataTransformPrefix}-0.16.0-dev.0`, + type: ElasticsearchAssetType.transform, + }, + ], + keep_policies_up_to_date: false, + }) ); + endpointAppContextService.setup(createMockEndpointAppContextServiceSetupContract()); + endpointAppContextService.start({ ...startContract, packageService: mockPackageService }); + mockAgentService = startContract.agentService!; - const mockRequest = httpServerMock.createKibanaRequest({ - params: { id: response.hits.hits[0]._id }, + registerEndpointRoutes(routerMock, { + logFactory: loggingSystemMock.create(), + service: endpointAppContextService, + config: () => Promise.resolve(createMockConfig()), + experimentalFeatures: parseExperimentalConfigValue(createMockConfig().enableExperimental), }); + }); - mockAgentService.getAgent = jest - .fn() - .mockRejectedValue(new AgentNotFoundError('not found')); + afterEach(() => endpointAppContextService.stop()); - (mockScopedClient.asCurrentUser.search as jest.Mock).mockImplementationOnce(() => - Promise.resolve({ body: response }) + it('test find the latest of all endpoints', async () => { + const mockRequest = httpServerMock.createKibanaRequest({ + query: { + page: 0, + pageSize: 10, + }, + }); + const response = legacyMetadataSearchResponseMock( + new EndpointDocGenerator().generateHostMetadata() ); - + (mockScopedClient.asCurrentUser.search as jest.Mock) + .mockImplementationOnce(() => { + throw new IndexNotFoundException(); + }) + .mockImplementationOnce(() => Promise.resolve({ body: response })); [routeConfig, routeHandler] = routerMock.get.mock.calls.find(([{ path }]) => - path.startsWith(`${HOST_METADATA_LIST_ROUTE}`) + path.startsWith(HOST_METADATA_LIST_ROUTE) )!; - + mockAgentService.getAgentStatusById = jest.fn().mockReturnValue('error'); + mockAgentService.listAgents = jest.fn().mockReturnValue(noUnenrolledAgent); await routeHandler( createRouteHandlerContext(mockScopedClient, mockSavedObjectClient), mockRequest, mockResponse ); - expect(mockScopedClient.asCurrentUser.search).toHaveBeenCalledTimes(1); + expect(mockScopedClient.asCurrentUser.search).toHaveBeenCalledTimes(2); expect(routeConfig.options).toEqual({ authRequired: true, tags: ['access:securitySolution'], }); expect(mockResponse.ok).toBeCalled(); - const result = mockResponse.ok.mock.calls[0][0]?.body as HostInfo; - expect(result.host_status).toEqual(HostStatus.UNHEALTHY); + const endpointResultList = mockResponse.ok.mock.calls[0][0]?.body as MetadataListResponse; + expect(endpointResultList.data.length).toEqual(1); + expect(endpointResultList.total).toEqual(1); + expect(endpointResultList.page).toEqual(0); + expect(endpointResultList.pageSize).toEqual(10); }); - it('should return a single endpoint with status unhealthy when status is not offline, online or enrolling', async () => { - const response = legacyMetadataSearchResponseMock( - new EndpointDocGenerator().generateHostMetadata() - ); - + it('test find the latest of all endpoints with paging properties', async () => { const mockRequest = httpServerMock.createKibanaRequest({ - params: { id: response.hits.hits[0]._id }, + query: { + page: 1, + pageSize: 10, + }, }); - mockAgentService.getAgent = jest.fn().mockReturnValue( - agentGenerator.generate({ - status: 'error', + mockAgentService.getAgentStatusById = jest.fn().mockReturnValue('error'); + mockAgentService.listAgents = jest.fn().mockReturnValue(noUnenrolledAgent); + (mockScopedClient.asCurrentUser.search as jest.Mock) + .mockImplementationOnce(() => { + throw new IndexNotFoundException(); }) - ); - (mockScopedClient.asCurrentUser.search as jest.Mock).mockImplementationOnce(() => - Promise.resolve({ body: response }) - ); - + .mockImplementationOnce(() => + Promise.resolve({ + body: legacyMetadataSearchResponseMock( + new EndpointDocGenerator().generateHostMetadata() + ), + }) + ); [routeConfig, routeHandler] = routerMock.get.mock.calls.find(([{ path }]) => - path.startsWith(`${HOST_METADATA_LIST_ROUTE}`) + path.startsWith(HOST_METADATA_LIST_ROUTE) )!; await routeHandler( @@ -742,34 +993,54 @@ describe('test endpoint route', () => { mockRequest, mockResponse ); - - expect(mockScopedClient.asCurrentUser.search).toHaveBeenCalledTimes(1); + expect(mockScopedClient.asCurrentUser.search).toHaveBeenCalledTimes(2); + expect( + (mockScopedClient.asCurrentUser.search as jest.Mock).mock.calls[1][0]?.body?.query.bool + .must_not + ).toContainEqual({ + terms: { + 'elastic.agent.id': [ + '00000000-0000-0000-0000-000000000000', + '11111111-1111-1111-1111-111111111111', + ], + }, + }); expect(routeConfig.options).toEqual({ authRequired: true, tags: ['access:securitySolution'], }); expect(mockResponse.ok).toBeCalled(); - const result = mockResponse.ok.mock.calls[0][0]?.body as HostInfo; - expect(result.host_status).toEqual(HostStatus.UNHEALTHY); + const endpointResultList = mockResponse.ok.mock.calls[0][0]?.body as MetadataListResponse; + expect(endpointResultList.data.length).toEqual(1); + expect(endpointResultList.total).toEqual(1); + expect(endpointResultList.page).toEqual(1); + expect(endpointResultList.pageSize).toEqual(10); }); - it('should throw error when endpoint agent is not active', async () => { - const response = legacyMetadataSearchResponseMock( - new EndpointDocGenerator().generateHostMetadata() - ); - + it('test find the latest of all endpoints with paging and filters properties', async () => { const mockRequest = httpServerMock.createKibanaRequest({ - params: { id: response.hits.hits[0]._id }, + query: { + page: 1, + pageSize: 10, + kuery: 'not host.ip:10.140.73.246', + }, }); - (mockScopedClient.asCurrentUser.search as jest.Mock).mockImplementationOnce(() => - Promise.resolve({ body: response }) - ); - mockAgentService.getAgent = jest.fn().mockReturnValue({ - active: false, - } as unknown as Agent); + mockAgentService.getAgentStatusById = jest.fn().mockReturnValue('error'); + mockAgentService.listAgents = jest.fn().mockReturnValue(noUnenrolledAgent); + (mockScopedClient.asCurrentUser.search as jest.Mock) + .mockImplementationOnce(() => { + throw new IndexNotFoundException(); + }) + .mockImplementationOnce(() => + Promise.resolve({ + body: legacyMetadataSearchResponseMock( + new EndpointDocGenerator().generateHostMetadata() + ), + }) + ); [routeConfig, routeHandler] = routerMock.get.mock.calls.find(([{ path }]) => - path.startsWith(`${HOST_METADATA_LIST_ROUTE}`) + path.startsWith(HOST_METADATA_LIST_ROUTE) )!; await routeHandler( @@ -778,9 +1049,277 @@ describe('test endpoint route', () => { mockResponse ); - expect(mockScopedClient.asCurrentUser.search).toHaveBeenCalledTimes(1); - expect(mockResponse.badRequest).toBeCalled(); + expect(mockScopedClient.asCurrentUser.search).toBeCalled(); + expect( + // KQL filter to be passed through + (mockScopedClient.asCurrentUser.search as jest.Mock).mock.calls[1][0]?.body?.query.bool + .must + ).toContainEqual({ + bool: { + must_not: { + bool: { + should: [ + { + match: { + 'host.ip': '10.140.73.246', + }, + }, + ], + minimum_should_match: 1, + }, + }, + }, + }); + expect( + (mockScopedClient.asCurrentUser.search as jest.Mock).mock.calls[1][0]?.body?.query.bool + .must + ).toContainEqual({ + bool: { + must_not: [ + { + terms: { + 'elastic.agent.id': [ + '00000000-0000-0000-0000-000000000000', + '11111111-1111-1111-1111-111111111111', + ], + }, + }, + { + terms: { + // here we DO want to see both schemas are present + // to make this schema-compatible forward and back + 'HostDetails.elastic.agent.id': [ + '00000000-0000-0000-0000-000000000000', + '11111111-1111-1111-1111-111111111111', + ], + }, + }, + ], + }, + }); + expect(routeConfig.options).toEqual({ + authRequired: true, + tags: ['access:securitySolution'], + }); + expect(mockResponse.ok).toBeCalled(); + const endpointResultList = mockResponse.ok.mock.calls[0][0]?.body as MetadataListResponse; + expect(endpointResultList.data.length).toEqual(1); + expect(endpointResultList.total).toEqual(1); + expect(endpointResultList.page).toEqual(1); + expect(endpointResultList.pageSize).toEqual(10); + }); + }); + }); + + describe('GET endpoint details route', () => { + beforeEach(() => { + endpointAppContextService = new EndpointAppContextService(); + mockPackageService = createMockPackageService(); + mockPackageService.getInstallation.mockReturnValue( + Promise.resolve({ + installed_kibana: [], + package_assets: [], + es_index_patterns: {}, + name: '', + version: '', + install_status: 'installed', + install_version: '', + install_started_at: '', + install_source: 'registry', + installed_es: [ + { + id: 'logs-endpoint.events.security', + type: ElasticsearchAssetType.indexTemplate, + }, + { + id: `${metadataTransformPrefix}-0.16.0-dev.0`, + type: ElasticsearchAssetType.transform, + }, + ], + keep_policies_up_to_date: false, + }) + ); + endpointAppContextService.setup(createMockEndpointAppContextServiceSetupContract()); + endpointAppContextService.start({ ...startContract, packageService: mockPackageService }); + mockAgentService = startContract.agentService!; + + registerEndpointRoutes(routerMock, { + logFactory: loggingSystemMock.create(), + service: endpointAppContextService, + config: () => Promise.resolve(createMockConfig()), + experimentalFeatures: parseExperimentalConfigValue(createMockConfig().enableExperimental), + }); + }); + + afterEach(() => endpointAppContextService.stop()); + + it('should return 404 on no results', async () => { + const mockRequest = httpServerMock.createKibanaRequest({ params: { id: 'BADID' } }); + + (mockScopedClient.asCurrentUser.search as jest.Mock).mockImplementationOnce(() => + Promise.resolve({ body: legacyMetadataSearchResponseMock() }) + ); + + mockAgentService.getAgentStatusById = jest.fn().mockReturnValue('error'); + mockAgentService.getAgent = jest.fn().mockReturnValue({ + active: true, + } as unknown as Agent); + + [routeConfig, routeHandler] = routerMock.get.mock.calls.find(([{ path }]) => + path.startsWith(HOST_METADATA_GET_ROUTE) + )!; + await routeHandler( + createRouteHandlerContext(mockScopedClient, mockSavedObjectClient), + mockRequest, + mockResponse + ); + + expect(mockScopedClient.asCurrentUser.search).toHaveBeenCalledTimes(1); + expect(routeConfig.options).toEqual({ + authRequired: true, + tags: ['access:securitySolution'], + }); + expect(mockResponse.notFound).toBeCalled(); + const message = mockResponse.notFound.mock.calls[0][0]?.body; + expect(message).toBeInstanceOf(EndpointHostNotFoundError); + }); + + it('should return a single endpoint with status healthy', async () => { + const response = legacyMetadataSearchResponseMock( + new EndpointDocGenerator().generateHostMetadata() + ); + const mockRequest = httpServerMock.createKibanaRequest({ + params: { id: response.hits.hits[0]._id }, }); + + mockAgentService.getAgent = jest + .fn() + .mockReturnValue(agentGenerator.generate({ status: 'online' })); + (mockScopedClient.asCurrentUser.search as jest.Mock).mockImplementationOnce(() => + Promise.resolve({ body: response }) + ); + + [routeConfig, routeHandler] = routerMock.get.mock.calls.find(([{ path }]) => + path.startsWith(HOST_METADATA_GET_ROUTE) + )!; + + await routeHandler( + createRouteHandlerContext(mockScopedClient, mockSavedObjectClient), + mockRequest, + mockResponse + ); + + expect(mockScopedClient.asCurrentUser.search).toHaveBeenCalledTimes(1); + expect(routeConfig.options).toEqual({ + authRequired: true, + tags: ['access:securitySolution'], + }); + expect(mockResponse.ok).toBeCalled(); + const result = mockResponse.ok.mock.calls[0][0]?.body as HostInfo; + expect(result).toHaveProperty('metadata.Endpoint'); + expect(result.host_status).toEqual(HostStatus.HEALTHY); + }); + + it('should return a single endpoint with status unhealthy when AgentService throw 404', async () => { + const response = legacyMetadataSearchResponseMock( + new EndpointDocGenerator().generateHostMetadata() + ); + + const mockRequest = httpServerMock.createKibanaRequest({ + params: { id: response.hits.hits[0]._id }, + }); + + mockAgentService.getAgent = jest.fn().mockRejectedValue(new AgentNotFoundError('not found')); + + (mockScopedClient.asCurrentUser.search as jest.Mock).mockImplementationOnce(() => + Promise.resolve({ body: response }) + ); + + [routeConfig, routeHandler] = routerMock.get.mock.calls.find(([{ path }]) => + path.startsWith(HOST_METADATA_GET_ROUTE) + )!; + + await routeHandler( + createRouteHandlerContext(mockScopedClient, mockSavedObjectClient), + mockRequest, + mockResponse + ); + + expect(mockScopedClient.asCurrentUser.search).toHaveBeenCalledTimes(1); + expect(routeConfig.options).toEqual({ + authRequired: true, + tags: ['access:securitySolution'], + }); + expect(mockResponse.ok).toBeCalled(); + const result = mockResponse.ok.mock.calls[0][0]?.body as HostInfo; + expect(result.host_status).toEqual(HostStatus.UNHEALTHY); + }); + + it('should return a single endpoint with status unhealthy when status is not offline, online or enrolling', async () => { + const response = legacyMetadataSearchResponseMock( + new EndpointDocGenerator().generateHostMetadata() + ); + + const mockRequest = httpServerMock.createKibanaRequest({ + params: { id: response.hits.hits[0]._id }, + }); + + mockAgentService.getAgent = jest.fn().mockReturnValue( + agentGenerator.generate({ + status: 'error', + }) + ); + (mockScopedClient.asCurrentUser.search as jest.Mock).mockImplementationOnce(() => + Promise.resolve({ body: response }) + ); + + [routeConfig, routeHandler] = routerMock.get.mock.calls.find(([{ path }]) => + path.startsWith(HOST_METADATA_GET_ROUTE) + )!; + + await routeHandler( + createRouteHandlerContext(mockScopedClient, mockSavedObjectClient), + mockRequest, + mockResponse + ); + + expect(mockScopedClient.asCurrentUser.search).toHaveBeenCalledTimes(1); + expect(routeConfig.options).toEqual({ + authRequired: true, + tags: ['access:securitySolution'], + }); + expect(mockResponse.ok).toBeCalled(); + const result = mockResponse.ok.mock.calls[0][0]?.body as HostInfo; + expect(result.host_status).toEqual(HostStatus.UNHEALTHY); + }); + + it('should throw error when endpoint agent is not active', async () => { + const response = legacyMetadataSearchResponseMock( + new EndpointDocGenerator().generateHostMetadata() + ); + + const mockRequest = httpServerMock.createKibanaRequest({ + params: { id: response.hits.hits[0]._id }, + }); + (mockScopedClient.asCurrentUser.search as jest.Mock).mockImplementationOnce(() => + Promise.resolve({ body: response }) + ); + mockAgentService.getAgent = jest.fn().mockReturnValue({ + active: false, + } as unknown as Agent); + + [routeConfig, routeHandler] = routerMock.get.mock.calls.find(([{ path }]) => + path.startsWith(HOST_METADATA_GET_ROUTE) + )!; + + await routeHandler( + createRouteHandlerContext(mockScopedClient, mockSavedObjectClient), + mockRequest, + mockResponse + ); + + expect(mockScopedClient.asCurrentUser.search).toHaveBeenCalledTimes(1); + expect(mockResponse.badRequest).toBeCalled(); }); }); }); diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/metadata/query_builders.test.ts b/x-pack/plugins/security_solution/server/endpoint/routes/metadata/query_builders.test.ts index a0cb5aad552d2..0a8f2616c516f 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/metadata/query_builders.test.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/metadata/query_builders.test.ts @@ -5,39 +5,35 @@ * 2.0. */ -import { httpServerMock, loggingSystemMock } from '../../../../../../../src/core/server/mocks'; import { kibanaRequestToMetadataListESQuery, getESQueryHostMetadataByID, buildUnitedIndexQuery, } from './query_builders'; -import { EndpointAppContextService } from '../../endpoint_app_context_services'; -import { createMockConfig } from '../../../lib/detection_engine/routes/__mocks__'; import { metadataCurrentIndexPattern } from '../../../../common/endpoint/constants'; -import { parseExperimentalConfigValue } from '../../../../common/experimental_features'; import { get } from 'lodash'; import { expectedCompleteUnitedIndexQuery } from './query_builders.fixtures'; describe('query builder', () => { describe('MetadataListESQuery', () => { it('queries the correct index', async () => { - const mockRequest = httpServerMock.createKibanaRequest({ body: {} }); - const query = await kibanaRequestToMetadataListESQuery(mockRequest, { - logFactory: loggingSystemMock.create(), - service: new EndpointAppContextService(), - config: () => Promise.resolve(createMockConfig()), - experimentalFeatures: parseExperimentalConfigValue(createMockConfig().enableExperimental), + const query = await kibanaRequestToMetadataListESQuery({ + page: 0, + pageSize: 10, + kuery: '', + unenrolledAgentIds: [], + statusAgentIds: [], }); expect(query.index).toEqual(metadataCurrentIndexPattern); }); it('sorts using *event.created', async () => { - const mockRequest = httpServerMock.createKibanaRequest({ body: {} }); - const query = await kibanaRequestToMetadataListESQuery(mockRequest, { - logFactory: loggingSystemMock.create(), - service: new EndpointAppContextService(), - config: () => Promise.resolve(createMockConfig()), - experimentalFeatures: parseExperimentalConfigValue(createMockConfig().enableExperimental), + const query = await kibanaRequestToMetadataListESQuery({ + page: 0, + pageSize: 10, + kuery: '', + unenrolledAgentIds: [], + statusAgentIds: [], }); expect(query.body.sort).toContainEqual({ 'event.created': { @@ -55,21 +51,13 @@ describe('query builder', () => { it('excludes unenrolled elastic agents when they exist, by default', async () => { const unenrolledElasticAgentId = '1fdca33f-799f-49f4-939c-ea4383c77672'; - const mockRequest = httpServerMock.createKibanaRequest({ - body: {}, + const query = await kibanaRequestToMetadataListESQuery({ + page: 0, + pageSize: 10, + kuery: '', + unenrolledAgentIds: [unenrolledElasticAgentId], + statusAgentIds: [], }); - const query = await kibanaRequestToMetadataListESQuery( - mockRequest, - { - logFactory: loggingSystemMock.create(), - service: new EndpointAppContextService(), - config: () => Promise.resolve(createMockConfig()), - experimentalFeatures: parseExperimentalConfigValue(createMockConfig().enableExperimental), - }, - { - unenrolledAgentIds: [unenrolledElasticAgentId], - } - ); expect(query.body.query).toEqual({ bool: { @@ -100,16 +88,12 @@ describe('query builder', () => { describe('test query builder with kql filter', () => { it('test default query params for all endpoints metadata when body filter is provided', async () => { - const mockRequest = httpServerMock.createKibanaRequest({ - body: { - filters: { kql: 'not host.ip:10.140.73.246' }, - }, - }); - const query = await kibanaRequestToMetadataListESQuery(mockRequest, { - logFactory: loggingSystemMock.create(), - service: new EndpointAppContextService(), - config: () => Promise.resolve(createMockConfig()), - experimentalFeatures: parseExperimentalConfigValue(createMockConfig().enableExperimental), + const query = await kibanaRequestToMetadataListESQuery({ + page: 0, + pageSize: 10, + kuery: 'not host.ip:10.140.73.246', + unenrolledAgentIds: [], + statusAgentIds: [], }); expect(query.body.query.bool.must).toContainEqual({ @@ -135,25 +119,13 @@ describe('query builder', () => { 'and when body filter is provided', async () => { const unenrolledElasticAgentId = '1fdca33f-799f-49f4-939c-ea4383c77672'; - const mockRequest = httpServerMock.createKibanaRequest({ - body: { - filters: { kql: 'not host.ip:10.140.73.246' }, - }, + const query = await kibanaRequestToMetadataListESQuery({ + page: 0, + pageSize: 10, + kuery: 'not host.ip:10.140.73.246', + unenrolledAgentIds: [unenrolledElasticAgentId], + statusAgentIds: [], }); - const query = await kibanaRequestToMetadataListESQuery( - mockRequest, - { - logFactory: loggingSystemMock.create(), - service: new EndpointAppContextService(), - config: () => Promise.resolve(createMockConfig()), - experimentalFeatures: parseExperimentalConfigValue( - createMockConfig().enableExperimental - ), - }, - { - unenrolledAgentIds: [unenrolledElasticAgentId], - } - ); expect(query.body.query.bool.must).toEqual([ { @@ -222,7 +194,10 @@ describe('query builder', () => { describe('buildUnitedIndexQuery', () => { it('correctly builds empty query', async () => { - const query = await buildUnitedIndexQuery({ page: 1, pageSize: 10, filters: {} }, []); + const query = await buildUnitedIndexQuery( + { page: 1, pageSize: 10, hostStatuses: [], kuery: '' }, + [] + ); const expected = { bool: { must_not: { @@ -267,10 +242,8 @@ describe('query builder', () => { { page: 1, pageSize: 10, - filters: { - kql: 'united.endpoint.host.os.name : *', - host_status: ['healthy'], - }, + kuery: 'united.endpoint.host.os.name : *', + hostStatuses: ['healthy'], }, ['test-endpoint-policy-id'] ); diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/metadata/query_builders.ts b/x-pack/plugins/security_solution/server/endpoint/routes/metadata/query_builders.ts index 73325a92a3324..2262028ec43bf 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/metadata/query_builders.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/metadata/query_builders.ts @@ -6,14 +6,16 @@ */ import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { TypeOf } from '@kbn/config-schema'; import { fromKueryExpression, toElasticsearchQuery } from '@kbn/es-query'; import { metadataCurrentIndexPattern, METADATA_UNITED_INDEX, } from '../../../../common/endpoint/constants'; import { KibanaRequest } from '../../../../../../../src/core/server'; -import { EndpointAppContext, GetHostMetadataListQuery } from '../../types'; +import { EndpointAppContext } from '../../types'; import { buildStatusesKuery } from './support/agent_status'; +import { GetMetadataListRequestSchemaV2 } from '.'; /** * 00000000-0000-0000-0000-000000000000 is initial Elastic Agent id sent by Endpoint before policy is configured @@ -25,6 +27,9 @@ const IGNORED_ELASTIC_AGENT_IDS = [ ]; export interface QueryBuilderOptions { + page: number; + pageSize: number; + kuery?: string; unenrolledAgentIds?: string[]; statusAgentIds?: string[]; } @@ -50,26 +55,21 @@ export const MetadataSortMethod: estypes.SearchSortContainer[] = [ ]; export async function kibanaRequestToMetadataListESQuery( - // eslint-disable-next-line @typescript-eslint/no-explicit-any - request: KibanaRequest, - endpointAppContext: EndpointAppContext, - queryBuilderOptions?: QueryBuilderOptions + queryBuilderOptions: QueryBuilderOptions // eslint-disable-next-line @typescript-eslint/no-explicit-any ): Promise> { - const pagingProperties = await getPagingProperties(request, endpointAppContext); - return { body: { query: buildQueryBody( - request, + queryBuilderOptions?.kuery, IGNORED_ELASTIC_AGENT_IDS.concat(queryBuilderOptions?.unenrolledAgentIds ?? []), queryBuilderOptions?.statusAgentIds ), track_total_hits: true, sort: MetadataSortMethod, }, - from: pagingProperties.pageIndex * pagingProperties.pageSize, - size: pagingProperties.pageSize, + from: queryBuilderOptions.page * queryBuilderOptions.pageSize, + size: queryBuilderOptions.pageSize, index: metadataCurrentIndexPattern, }; } @@ -96,8 +96,7 @@ export async function getPagingProperties( } function buildQueryBody( - // eslint-disable-next-line @typescript-eslint/no-explicit-any - request: KibanaRequest, + kuery: string = '', unerolledAgentIds: string[] | undefined, statusAgentIds: string[] | undefined // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -136,8 +135,8 @@ function buildQueryBody( }, }; - if (request?.body?.filters?.kql) { - const kqlQuery = toElasticsearchQuery(fromKueryExpression(request.body.filters.kql)); + if (kuery) { + const kqlQuery = toElasticsearchQuery(fromKueryExpression(kuery)); const q = []; if (filterUnenrolledAgents || filterStatusAgents) { q.push(idFilter); @@ -233,12 +232,17 @@ interface BuildUnitedIndexQueryResponse { size: number; index: string; } + export async function buildUnitedIndexQuery( - { page = 1, pageSize = 10, filters = {} }: GetHostMetadataListQuery, + { + page = 0, + pageSize = 10, + hostStatuses = [], + kuery = '', + }: TypeOf, endpointPolicyIds: string[] = [] ): Promise { - const statusesToFilter = filters?.host_status ?? []; - const statusesKuery = buildStatusesKuery(statusesToFilter); + const statusesKuery = buildStatusesKuery(hostStatuses); const filterIgnoredAgents = { must_not: { terms: { 'agent.id': IGNORED_ELASTIC_AGENT_IDS } }, @@ -272,8 +276,8 @@ export async function buildUnitedIndexQuery( let query: BuildUnitedIndexQueryResponse['body']['query'] = idFilter; - if (statusesKuery || filters?.kql) { - const kqlQuery = toElasticsearchQuery(fromKueryExpression(filters.kql ?? '')); + if (statusesKuery || kuery) { + const kqlQuery = toElasticsearchQuery(fromKueryExpression(kuery ?? '')); const q = []; if (filterIgnoredAgents || filterEndpointPolicyAgents) { @@ -295,7 +299,7 @@ export async function buildUnitedIndexQuery( track_total_hits: true, sort: MetadataSortMethod, }, - from: (page - 1) * pageSize, + from: page * pageSize, size: pageSize, index: METADATA_UNITED_INDEX, }; diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/metadata/support/agent_status.ts b/x-pack/plugins/security_solution/server/endpoint/routes/metadata/support/agent_status.ts index f9e04f4edebee..a7781cb77e8c0 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/metadata/support/agent_status.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/metadata/support/agent_status.ts @@ -36,7 +36,7 @@ export function buildStatusesKuery(statusesToFilter: string[]): string | undefin export async function findAgentIdsByStatus( agentService: AgentService, esClient: ElasticsearchClient, - statuses: string[], + statuses: string[] = [], pageSize: number = 1000 ): Promise { if (!statuses.length) { diff --git a/x-pack/plugins/security_solution/server/endpoint/services/metadata/endpoint_metadata_service.test.ts b/x-pack/plugins/security_solution/server/endpoint/services/metadata/endpoint_metadata_service.test.ts index d3cc7b32bbc1c..5af108304ff9d 100644 --- a/x-pack/plugins/security_solution/server/endpoint/services/metadata/endpoint_metadata_service.test.ts +++ b/x-pack/plugins/security_solution/server/endpoint/services/metadata/endpoint_metadata_service.test.ts @@ -117,7 +117,12 @@ describe('EndpointMetadataService', () => { it('should throw wrapped error if es error', async () => { const esMockResponse = elasticsearchServiceMock.createErrorTransportRequestPromise({}); esClient.search.mockResolvedValue(esMockResponse); - const metadataListResponse = metadataService.getHostMetadataList(esClient); + const metadataListResponse = metadataService.getHostMetadataList(esClient, { + page: 0, + pageSize: 10, + kuery: '', + hostStatuses: [], + }); await expect(metadataListResponse).rejects.toThrow(EndpointError); }); @@ -168,18 +173,16 @@ describe('EndpointMetadataService', () => { } ); - const metadataListResponse = await metadataService.getHostMetadataList(esClient); - const unitedIndexQuery = await buildUnitedIndexQuery( - { page: 1, pageSize: 10, filters: {} }, - packagePolicyIds + const queryOptions = { page: 1, pageSize: 10, kuery: '', hostStatuses: [] }; + const metadataListResponse = await metadataService.getHostMetadataList( + esClient, + queryOptions ); + const unitedIndexQuery = await buildUnitedIndexQuery(queryOptions, packagePolicyIds); expect(esClient.search).toBeCalledWith(unitedIndexQuery); expect(agentPolicyServiceMock.getByIds).toBeCalledWith(expect.anything(), agentPolicyIds); expect(metadataListResponse).toEqual({ - pageSize: 10, - page: 1, - total: 1, data: [ { metadata: endpointMetadataDoc, @@ -202,6 +205,7 @@ describe('EndpointMetadataService', () => { }, }, ], + total: 1, }); }); }); diff --git a/x-pack/plugins/security_solution/server/endpoint/services/metadata/endpoint_metadata_service.ts b/x-pack/plugins/security_solution/server/endpoint/services/metadata/endpoint_metadata_service.ts index be8a6625c111e..832b8b507e5d4 100644 --- a/x-pack/plugins/security_solution/server/endpoint/services/metadata/endpoint_metadata_service.ts +++ b/x-pack/plugins/security_solution/server/endpoint/services/metadata/endpoint_metadata_service.ts @@ -12,12 +12,14 @@ import { SavedObjectsServiceStart, } from 'kibana/server'; +import { TypeOf } from '@kbn/config-schema'; import { TransportResult } from '@elastic/elasticsearch'; import { SearchTotalHits, SearchResponse } from '@elastic/elasticsearch/lib/api/types'; import { HostInfo, HostMetadata, MaybeImmutable, + MetadataListResponse, PolicyData, UnitedAgentMetadata, } from '../../../../common/endpoint/types'; @@ -52,10 +54,10 @@ import { } from '../../utils'; import { EndpointError } from '../../errors'; import { createInternalReadonlySoClient } from '../../utils/create_internal_readonly_so_client'; -import { GetHostMetadataListQuery } from '../../types'; import { METADATA_UNITED_INDEX } from '../../../../common/endpoint/constants'; import { getAllEndpointPackagePolicies } from '../../routes/metadata/support/endpoint_package_policies'; import { getAgentStatus } from '../../../../../fleet/common/services/agent_status'; +import { GetMetadataListRequestSchemaV2 } from '../../routes/metadata'; type AgentPolicyWithPackagePolicies = Omit & { package_policies: PackagePolicy[]; @@ -401,8 +403,8 @@ export class EndpointMetadataService { */ async getHostMetadataList( esClient: ElasticsearchClient, - queryOptions: GetHostMetadataListQuery = {} - ): Promise<{ data: HostInfo[]; total: number; page: number; pageSize: number }> { + queryOptions: TypeOf + ): Promise> { const endpointPolicies = await getAllEndpointPackagePolicies( this.packagePolicyService, this.DANGEROUS_INTERNAL_SO_CLIENT @@ -474,8 +476,6 @@ export class EndpointMetadataService { return { data: hosts, - pageSize: unitedIndexQuery.size, - page: unitedIndexQuery.from + 1, total: (docsCount as unknown as SearchTotalHits).value, }; } diff --git a/x-pack/plugins/security_solution/server/endpoint/types.ts b/x-pack/plugins/security_solution/server/endpoint/types.ts index 919e62785f698..bc52b759b9f0a 100644 --- a/x-pack/plugins/security_solution/server/endpoint/types.ts +++ b/x-pack/plugins/security_solution/server/endpoint/types.ts @@ -7,12 +7,10 @@ import { LoggerFactory } from 'kibana/server'; -import { TypeOf } from '@kbn/config-schema'; import { ConfigType } from '../config'; import { EndpointAppContextService } from './endpoint_app_context_services'; import { HostMetadata } from '../../common/endpoint/types'; import { ExperimentalFeatures } from '../../common/experimental_features'; -import { endpointFilters } from './routes/metadata'; /** * The context for Endpoint apps. @@ -37,11 +35,3 @@ export interface HostQueryResult { resultLength: number; result: HostMetadata | undefined; } - -// FIXME: when new Host Metadata list API is created (and existing one deprecated - 8.0?), move this type out of here and created it from Schema -export interface GetHostMetadataListQuery { - /* page number 1 based - not an index */ - page?: number; - pageSize?: number; - filters?: Partial>; -} diff --git a/x-pack/test/security_solution_endpoint_api_int/apis/metadata.ts b/x-pack/test/security_solution_endpoint_api_int/apis/metadata.ts index 35e316f309d7f..471d00728bac3 100644 --- a/x-pack/test/security_solution_endpoint_api_int/apis/metadata.ts +++ b/x-pack/test/security_solution_endpoint_api_int/apis/metadata.ts @@ -5,6 +5,7 @@ * 2.0. */ +import uuid from 'uuid'; import expect from '@kbn/expect'; import { FtrProviderContext } from '../ftr_provider_context'; import { @@ -31,317 +32,56 @@ import { indexFleetEndpointPolicy } from '../../../plugins/security_solution/com export default function ({ getService }: FtrProviderContext) { const supertest = getService('supertest'); - describe('test metadata api', () => { - describe('with .metrics-endpoint.metadata_united_default index', () => { - const numberOfHostsInFixture = 2; - - before(async () => { - await stopTransform(getService, `${METADATA_UNITED_TRANSFORM}*`); - await deleteAllDocsFromFleetAgents(getService); - await deleteAllDocsFromMetadataDatastream(getService); - await deleteAllDocsFromMetadataCurrentIndex(getService); - await deleteAllDocsFromIndex(getService, METADATA_UNITED_INDEX); - - // generate an endpoint policy and attach id to agents since - // metadata list api filters down to endpoint policies only - const policy = await indexFleetEndpointPolicy( - getService('kibanaServer'), - 'Default', - '1.1.1' - ); - const policyId = policy.integrationPolicies[0].policy_id; - const currentTime = new Date().getTime(); - - await Promise.all([ - bulkIndex(getService, AGENTS_INDEX, generateAgentDocs(currentTime, policyId)), - bulkIndex(getService, METADATA_DATASTREAM, generateMetadataDocs(currentTime)), - ]); - - // wait for latest metadata transform to run - await new Promise((r) => setTimeout(r, 30000)); - await startTransform(getService, METADATA_UNITED_TRANSFORM); - - // wait for united metadata transform to run - await new Promise((r) => setTimeout(r, 15000)); - }); - - after(async () => { - await deleteAllDocsFromFleetAgents(getService); - await deleteAllDocsFromMetadataDatastream(getService); - await deleteAllDocsFromMetadataCurrentIndex(getService); - await stopTransform(getService, `${METADATA_UNITED_TRANSFORM}*`); - await deleteAllDocsFromIndex(getService, METADATA_UNITED_INDEX); - }); - - it('should return one entry for each host with default paging', async () => { - const res = await supertest - .post(HOST_METADATA_LIST_ROUTE) - .set('kbn-xsrf', 'xxx') - .send() - .expect(200); - const { body } = res; - expect(body.total).to.eql(numberOfHostsInFixture); - expect(body.hosts.length).to.eql(numberOfHostsInFixture); - expect(body.request_page_size).to.eql(10); - expect(body.request_page_index).to.eql(0); - }); + describe('test metadata apis', () => { + describe('list endpoints POST route', () => { + describe('with .metrics-endpoint.metadata_united_default index', () => { + const numberOfHostsInFixture = 2; - it('metadata api should return page based on paging properties passed.', async () => { - const { body } = await supertest - .post(HOST_METADATA_LIST_ROUTE) - .set('kbn-xsrf', 'xxx') - .send({ - paging_properties: [ - { - page_size: 1, - }, - { - page_index: 1, - }, - ], - }) - .expect(200); - expect(body.total).to.eql(numberOfHostsInFixture); - expect(body.hosts.length).to.eql(1); - expect(body.request_page_size).to.eql(1); - expect(body.request_page_index).to.eql(1); - }); - - it('metadata api should return accurate total metadata if page index produces no result', async () => { - const { body } = await supertest - .post(HOST_METADATA_LIST_ROUTE) - .set('kbn-xsrf', 'xxx') - .send({ - paging_properties: [ - { - page_size: 10, - }, - { - page_index: 3, - }, - ], - }) - .expect(200); - expect(body.total).to.eql(numberOfHostsInFixture); - expect(body.hosts.length).to.eql(0); - expect(body.request_page_size).to.eql(10); - expect(body.request_page_index).to.eql(30); - }); - - it('metadata api should return 400 when pagingProperties is below boundaries.', async () => { - const { body } = await supertest - .post(HOST_METADATA_LIST_ROUTE) - .set('kbn-xsrf', 'xxx') - .send({ - paging_properties: [ - { - page_size: 0, - }, - { - page_index: 1, - }, - ], - }) - .expect(400); - expect(body.message).to.contain('Value must be equal to or greater than [1]'); - }); - - it('metadata api should return page based on filters passed.', async () => { - const { body } = await supertest - .post(HOST_METADATA_LIST_ROUTE) - .set('kbn-xsrf', 'xxx') - .send({ - filters: { - kql: 'not (united.endpoint.host.ip:10.101.149.26)', - }, - }) - .expect(200); - expect(body.total).to.eql(1); - expect(body.hosts.length).to.eql(1); - expect(body.request_page_size).to.eql(10); - expect(body.request_page_index).to.eql(0); - }); - - it('metadata api should return page based on filters and paging passed.', async () => { - const notIncludedIp = '10.101.149.26'; - const { body } = await supertest - .post(HOST_METADATA_LIST_ROUTE) - .set('kbn-xsrf', 'xxx') - .send({ - paging_properties: [ - { - page_size: 10, - }, - { - page_index: 0, - }, - ], - filters: { - kql: `not (united.endpoint.host.ip:${notIncludedIp})`, - }, - }) - .expect(200); - expect(body.total).to.eql(1); - const resultIps: string[] = [].concat( - ...body.hosts.map((hostInfo: Record) => hostInfo.metadata.host.ip) - ); - expect(resultIps.sort()).to.eql(['10.192.213.130', '10.70.28.129'].sort()); - expect(resultIps).not.include.eql(notIncludedIp); - expect(body.hosts.length).to.eql(1); - expect(body.request_page_size).to.eql(10); - expect(body.request_page_index).to.eql(0); - }); - - it('metadata api should return page based on host.os.Ext.variant filter.', async () => { - const variantValue = 'Windows Pro'; - const { body } = await supertest - .post(HOST_METADATA_LIST_ROUTE) - .set('kbn-xsrf', 'xxx') - .send({ - filters: { - kql: `united.endpoint.host.os.Ext.variant:${variantValue}`, - }, - }) - .expect(200); - expect(body.total).to.eql(2); - const resultOsVariantValue: Set = new Set( - body.hosts.map((hostInfo: Record) => hostInfo.metadata.host.os.Ext.variant) - ); - expect(Array.from(resultOsVariantValue)).to.eql([variantValue]); - expect(body.hosts.length).to.eql(2); - expect(body.request_page_size).to.eql(10); - expect(body.request_page_index).to.eql(0); - }); - - it('metadata api should return the latest event for all the events for an endpoint', async () => { - const targetEndpointIp = '10.101.149.26'; - const { body } = await supertest - .post(HOST_METADATA_LIST_ROUTE) - .set('kbn-xsrf', 'xxx') - .send({ - filters: { - kql: `united.endpoint.host.ip:${targetEndpointIp}`, - }, - }) - .expect(200); - expect(body.total).to.eql(1); - const resultIp: string = body.hosts[0].metadata.host.ip.filter( - (ip: string) => ip === targetEndpointIp - ); - expect(resultIp).to.eql([targetEndpointIp]); - expect(body.hosts.length).to.eql(1); - expect(body.request_page_size).to.eql(10); - expect(body.request_page_index).to.eql(0); - }); - - it('metadata api should return the latest event for all the events where policy status is not success', async () => { - const { body } = await supertest - .post(HOST_METADATA_LIST_ROUTE) - .set('kbn-xsrf', 'xxx') - .send({ - filters: { - kql: `not (united.endpoint.Endpoint.policy.applied.status:success)`, - }, - }) - .expect(200); - const statuses: Set = new Set( - body.hosts.map( - (hostInfo: Record) => hostInfo.metadata.Endpoint.policy.applied.status - ) - ); - expect(statuses.size).to.eql(1); - expect(Array.from(statuses)).to.eql(['failure']); - }); + before(async () => { + await stopTransform(getService, `${METADATA_UNITED_TRANSFORM}*`); + await deleteAllDocsFromFleetAgents(getService); + await deleteAllDocsFromMetadataDatastream(getService); + await deleteAllDocsFromMetadataCurrentIndex(getService); + await deleteAllDocsFromIndex(getService, METADATA_UNITED_INDEX); - it('metadata api should return the endpoint based on the elastic agent id, and status should be healthy', async () => { - const targetEndpointId = 'fc0ff548-feba-41b6-8367-65e8790d0eaf'; - const targetElasticAgentId = '023fa40c-411d-4188-a941-4147bfadd095'; - const { body } = await supertest - .post(HOST_METADATA_LIST_ROUTE) - .set('kbn-xsrf', 'xxx') - .send({ - filters: { - kql: `united.endpoint.elastic.agent.id:${targetElasticAgentId}`, - }, - }) - .expect(200); - expect(body.total).to.eql(1); - const resultHostId: string = body.hosts[0].metadata.host.id; - const resultElasticAgentId: string = body.hosts[0].metadata.elastic.agent.id; - expect(resultHostId).to.eql(targetEndpointId); - expect(resultElasticAgentId).to.eql(targetElasticAgentId); - expect(body.hosts[0].host_status).to.eql('healthy'); - expect(body.hosts.length).to.eql(1); - expect(body.request_page_size).to.eql(10); - expect(body.request_page_index).to.eql(0); - }); + // generate an endpoint policy and attach id to agents since + // metadata list api filters down to endpoint policies only + const policy = await indexFleetEndpointPolicy( + getService('kibanaServer'), + `Default ${uuid.v4()}`, + '1.1.1' + ); + const policyId = policy.integrationPolicies[0].policy_id; + const currentTime = new Date().getTime(); - it('metadata api should return all hosts when filter is empty string', async () => { - const { body } = await supertest - .post(HOST_METADATA_LIST_ROUTE) - .set('kbn-xsrf', 'xxx') - .send({ - filters: { - kql: '', - }, - }) - .expect(200); - expect(body.total).to.eql(numberOfHostsInFixture); - expect(body.hosts.length).to.eql(numberOfHostsInFixture); - expect(body.request_page_size).to.eql(10); - expect(body.request_page_index).to.eql(0); - }); - }); + await Promise.all([ + bulkIndex(getService, AGENTS_INDEX, generateAgentDocs(currentTime, policyId)), + bulkIndex(getService, METADATA_DATASTREAM, generateMetadataDocs(currentTime)), + ]); - describe('with metrics-endpoint.metadata_current_default index', () => { - /** - * The number of host documents in the es archive. - */ - const numberOfHostsInFixture = 3; + // wait for latest metadata transform to run + await new Promise((r) => setTimeout(r, 30000)); + await startTransform(getService, METADATA_UNITED_TRANSFORM); - describe(`POST ${HOST_METADATA_LIST_ROUTE} when index is empty`, () => { - it('metadata api should return empty result when index is empty', async () => { - await stopTransform(getService, `${METADATA_UNITED_TRANSFORM}*`); - await deleteIndex(getService, METADATA_UNITED_INDEX); - await deleteMetadataStream(getService); - await deleteAllDocsFromMetadataDatastream(getService); - await deleteAllDocsFromMetadataCurrentIndex(getService); - const { body } = await supertest - .post(HOST_METADATA_LIST_ROUTE) - .set('kbn-xsrf', 'xxx') - .send() - .expect(200); - expect(body.total).to.eql(0); - expect(body.hosts.length).to.eql(0); - expect(body.request_page_size).to.eql(10); - expect(body.request_page_index).to.eql(0); + // wait for united metadata transform to run + await new Promise((r) => setTimeout(r, 15000)); }); - }); - describe(`POST ${HOST_METADATA_LIST_ROUTE} when index is not empty`, () => { - const timestamp = new Date().getTime(); - before(async () => { - // stop the united transform and delete the index - // otherwise it won't hit metrics-endpoint.metadata_current_default index - await stopTransform(getService, `${METADATA_UNITED_TRANSFORM}*`); - await deleteIndex(getService, METADATA_UNITED_INDEX); - await bulkIndex(getService, METADATA_DATASTREAM, generateMetadataDocs(timestamp)); - // wait for transform - await new Promise((r) => setTimeout(r, 60000)); - }); - // the endpoint uses data streams and es archiver does not support deleting them at the moment so we need - // to do it manually after(async () => { - await deleteMetadataStream(getService); + await deleteAllDocsFromFleetAgents(getService); await deleteAllDocsFromMetadataDatastream(getService); await deleteAllDocsFromMetadataCurrentIndex(getService); + await stopTransform(getService, `${METADATA_UNITED_TRANSFORM}*`); + await deleteAllDocsFromIndex(getService, METADATA_UNITED_INDEX); }); - it('metadata api should return one entry for each host with default paging', async () => { - const { body } = await supertest + + it('should return one entry for each host with default paging', async () => { + const res = await supertest .post(HOST_METADATA_LIST_ROUTE) .set('kbn-xsrf', 'xxx') .send() .expect(200); + const { body } = res; expect(body.total).to.eql(numberOfHostsInFixture); expect(body.hosts.length).to.eql(numberOfHostsInFixture); expect(body.request_page_size).to.eql(10); @@ -369,9 +109,6 @@ export default function ({ getService }: FtrProviderContext) { expect(body.request_page_index).to.eql(1); }); - /* test that when paging properties produces no result, the total should reflect the actual number of metadata - in the index. - */ it('metadata api should return accurate total metadata if page index produces no result', async () => { const { body } = await supertest .post(HOST_METADATA_LIST_ROUTE) @@ -417,18 +154,18 @@ export default function ({ getService }: FtrProviderContext) { .set('kbn-xsrf', 'xxx') .send({ filters: { - kql: 'not (HostDetails.host.ip:10.46.229.234 or host.ip:10.46.229.234)', + kql: 'not (united.endpoint.host.ip:10.101.149.26)', }, }) .expect(200); - expect(body.total).to.eql(2); - expect(body.hosts.length).to.eql(2); + expect(body.total).to.eql(1); + expect(body.hosts.length).to.eql(1); expect(body.request_page_size).to.eql(10); expect(body.request_page_index).to.eql(0); }); it('metadata api should return page based on filters and paging passed.', async () => { - const notIncludedIp = '10.46.229.234'; + const notIncludedIp = '10.101.149.26'; const { body } = await supertest .post(HOST_METADATA_LIST_ROUTE) .set('kbn-xsrf', 'xxx') @@ -442,24 +179,17 @@ export default function ({ getService }: FtrProviderContext) { }, ], filters: { - kql: `not (HostDetails.host.ip:${notIncludedIp} or host.ip:${notIncludedIp})`, + kql: `not (united.endpoint.host.ip:${notIncludedIp})`, }, }) .expect(200); - expect(body.total).to.eql(2); + expect(body.total).to.eql(1); const resultIps: string[] = [].concat( ...body.hosts.map((hostInfo: Record) => hostInfo.metadata.host.ip) ); - expect(resultIps.sort()).to.eql( - [ - '10.192.213.130', - '10.70.28.129', - '10.101.149.26', - '2606:a000:ffc0:39:11ef:37b9:3371:578c', - ].sort() - ); + expect(resultIps.sort()).to.eql(['10.192.213.130', '10.70.28.129'].sort()); expect(resultIps).not.include.eql(notIncludedIp); - expect(body.hosts.length).to.eql(2); + expect(body.hosts.length).to.eql(1); expect(body.request_page_size).to.eql(10); expect(body.request_page_index).to.eql(0); }); @@ -471,7 +201,7 @@ export default function ({ getService }: FtrProviderContext) { .set('kbn-xsrf', 'xxx') .send({ filters: { - kql: `HostDetails.host.os.Ext.variant:${variantValue} or host.os.Ext.variant:${variantValue}`, + kql: `united.endpoint.host.os.Ext.variant:${variantValue}`, }, }) .expect(200); @@ -486,13 +216,13 @@ export default function ({ getService }: FtrProviderContext) { }); it('metadata api should return the latest event for all the events for an endpoint', async () => { - const targetEndpointIp = '10.46.229.234'; + const targetEndpointIp = '10.101.149.26'; const { body } = await supertest .post(HOST_METADATA_LIST_ROUTE) .set('kbn-xsrf', 'xxx') .send({ filters: { - kql: `HostDetails.host.ip:${targetEndpointIp} or host.ip:${targetEndpointIp}`, + kql: `united.endpoint.host.ip:${targetEndpointIp}`, }, }) .expect(200); @@ -501,7 +231,6 @@ export default function ({ getService }: FtrProviderContext) { (ip: string) => ip === targetEndpointIp ); expect(resultIp).to.eql([targetEndpointIp]); - expect(body.hosts[0].metadata.event.created).to.eql(timestamp); expect(body.hosts.length).to.eql(1); expect(body.request_page_size).to.eql(10); expect(body.request_page_index).to.eql(0); @@ -513,7 +242,7 @@ export default function ({ getService }: FtrProviderContext) { .set('kbn-xsrf', 'xxx') .send({ filters: { - kql: `not (HostDetails.Endpoint.policy.applied.status:success or Endpoint.policy.applied.status:success)`, + kql: `not (united.endpoint.Endpoint.policy.applied.status:success)`, }, }) .expect(200); @@ -526,7 +255,7 @@ export default function ({ getService }: FtrProviderContext) { expect(Array.from(statuses)).to.eql(['failure']); }); - it('metadata api should return the endpoint based on the elastic agent id, and status should be unhealthy', async () => { + it('metadata api should return the endpoint based on the elastic agent id, and status should be healthy', async () => { const targetEndpointId = 'fc0ff548-feba-41b6-8367-65e8790d0eaf'; const targetElasticAgentId = '023fa40c-411d-4188-a941-4147bfadd095'; const { body } = await supertest @@ -534,7 +263,7 @@ export default function ({ getService }: FtrProviderContext) { .set('kbn-xsrf', 'xxx') .send({ filters: { - kql: `HostDetails.elastic.agent.id:${targetElasticAgentId} or elastic.agent.id:${targetElasticAgentId}`, + kql: `united.endpoint.elastic.agent.id:${targetElasticAgentId}`, }, }) .expect(200); @@ -543,8 +272,7 @@ export default function ({ getService }: FtrProviderContext) { const resultElasticAgentId: string = body.hosts[0].metadata.elastic.agent.id; expect(resultHostId).to.eql(targetEndpointId); expect(resultElasticAgentId).to.eql(targetElasticAgentId); - expect(body.hosts[0].metadata.event.created).to.eql(timestamp); - expect(body.hosts[0].host_status).to.eql('unhealthy'); + expect(body.hosts[0].host_status).to.eql('healthy'); expect(body.hosts.length).to.eql(1); expect(body.request_page_size).to.eql(10); expect(body.request_page_index).to.eql(0); @@ -566,6 +294,755 @@ export default function ({ getService }: FtrProviderContext) { expect(body.request_page_index).to.eql(0); }); }); + + describe('with metrics-endpoint.metadata_current_default index', () => { + /** + * The number of host documents in the es archive. + */ + const numberOfHostsInFixture = 3; + + describe(`POST ${HOST_METADATA_LIST_ROUTE} when index is empty`, () => { + it('metadata api should return empty result when index is empty', async () => { + await stopTransform(getService, `${METADATA_UNITED_TRANSFORM}*`); + await deleteIndex(getService, METADATA_UNITED_INDEX); + await deleteMetadataStream(getService); + await deleteAllDocsFromMetadataDatastream(getService); + await deleteAllDocsFromMetadataCurrentIndex(getService); + const { body } = await supertest + .post(HOST_METADATA_LIST_ROUTE) + .set('kbn-xsrf', 'xxx') + .send() + .expect(200); + expect(body.total).to.eql(0); + expect(body.hosts.length).to.eql(0); + expect(body.request_page_size).to.eql(10); + expect(body.request_page_index).to.eql(0); + }); + }); + + describe(`POST ${HOST_METADATA_LIST_ROUTE} when index is not empty`, () => { + const timestamp = new Date().getTime(); + before(async () => { + // stop the united transform and delete the index + // otherwise it won't hit metrics-endpoint.metadata_current_default index + await stopTransform(getService, `${METADATA_UNITED_TRANSFORM}*`); + await deleteIndex(getService, METADATA_UNITED_INDEX); + await bulkIndex(getService, METADATA_DATASTREAM, generateMetadataDocs(timestamp)); + // wait for transform + await new Promise((r) => setTimeout(r, 60000)); + }); + // the endpoint uses data streams and es archiver does not support deleting them at the moment so we need + // to do it manually + after(async () => { + await deleteMetadataStream(getService); + await deleteAllDocsFromMetadataDatastream(getService); + await deleteAllDocsFromMetadataCurrentIndex(getService); + }); + it('metadata api should return one entry for each host with default paging', async () => { + const { body } = await supertest + .post(HOST_METADATA_LIST_ROUTE) + .set('kbn-xsrf', 'xxx') + .send() + .expect(200); + expect(body.total).to.eql(numberOfHostsInFixture); + expect(body.hosts.length).to.eql(numberOfHostsInFixture); + expect(body.request_page_size).to.eql(10); + expect(body.request_page_index).to.eql(0); + }); + + it('metadata api should return page based on paging properties passed.', async () => { + const { body } = await supertest + .post(HOST_METADATA_LIST_ROUTE) + .set('kbn-xsrf', 'xxx') + .send({ + paging_properties: [ + { + page_size: 1, + }, + { + page_index: 1, + }, + ], + }) + .expect(200); + expect(body.total).to.eql(numberOfHostsInFixture); + expect(body.hosts.length).to.eql(1); + expect(body.request_page_size).to.eql(1); + expect(body.request_page_index).to.eql(1); + }); + + /* test that when paging properties produces no result, the total should reflect the actual number of metadata + in the index. + */ + it('metadata api should return accurate total metadata if page index produces no result', async () => { + const { body } = await supertest + .post(HOST_METADATA_LIST_ROUTE) + .set('kbn-xsrf', 'xxx') + .send({ + paging_properties: [ + { + page_size: 10, + }, + { + page_index: 3, + }, + ], + }) + .expect(200); + expect(body.total).to.eql(numberOfHostsInFixture); + expect(body.hosts.length).to.eql(0); + expect(body.request_page_size).to.eql(10); + expect(body.request_page_index).to.eql(30); + }); + + it('metadata api should return 400 when pagingProperties is below boundaries.', async () => { + const { body } = await supertest + .post(HOST_METADATA_LIST_ROUTE) + .set('kbn-xsrf', 'xxx') + .send({ + paging_properties: [ + { + page_size: 0, + }, + { + page_index: 1, + }, + ], + }) + .expect(400); + expect(body.message).to.contain('Value must be equal to or greater than [1]'); + }); + + it('metadata api should return page based on filters passed.', async () => { + const { body } = await supertest + .post(HOST_METADATA_LIST_ROUTE) + .set('kbn-xsrf', 'xxx') + .send({ + filters: { + kql: 'not (HostDetails.host.ip:10.46.229.234 or host.ip:10.46.229.234)', + }, + }) + .expect(200); + expect(body.total).to.eql(2); + expect(body.hosts.length).to.eql(2); + expect(body.request_page_size).to.eql(10); + expect(body.request_page_index).to.eql(0); + }); + + it('metadata api should return page based on filters and paging passed.', async () => { + const notIncludedIp = '10.46.229.234'; + const { body } = await supertest + .post(HOST_METADATA_LIST_ROUTE) + .set('kbn-xsrf', 'xxx') + .send({ + paging_properties: [ + { + page_size: 10, + }, + { + page_index: 0, + }, + ], + filters: { + kql: `not (HostDetails.host.ip:${notIncludedIp} or host.ip:${notIncludedIp})`, + }, + }) + .expect(200); + expect(body.total).to.eql(2); + const resultIps: string[] = [].concat( + ...body.hosts.map((hostInfo: Record) => hostInfo.metadata.host.ip) + ); + expect(resultIps.sort()).to.eql( + [ + '10.192.213.130', + '10.70.28.129', + '10.101.149.26', + '2606:a000:ffc0:39:11ef:37b9:3371:578c', + ].sort() + ); + expect(resultIps).not.include.eql(notIncludedIp); + expect(body.hosts.length).to.eql(2); + expect(body.request_page_size).to.eql(10); + expect(body.request_page_index).to.eql(0); + }); + + it('metadata api should return page based on host.os.Ext.variant filter.', async () => { + const variantValue = 'Windows Pro'; + const { body } = await supertest + .post(HOST_METADATA_LIST_ROUTE) + .set('kbn-xsrf', 'xxx') + .send({ + filters: { + kql: `HostDetails.host.os.Ext.variant:${variantValue} or host.os.Ext.variant:${variantValue}`, + }, + }) + .expect(200); + expect(body.total).to.eql(2); + const resultOsVariantValue: Set = new Set( + body.hosts.map( + (hostInfo: Record) => hostInfo.metadata.host.os.Ext.variant + ) + ); + expect(Array.from(resultOsVariantValue)).to.eql([variantValue]); + expect(body.hosts.length).to.eql(2); + expect(body.request_page_size).to.eql(10); + expect(body.request_page_index).to.eql(0); + }); + + it('metadata api should return the latest event for all the events for an endpoint', async () => { + const targetEndpointIp = '10.46.229.234'; + const { body } = await supertest + .post(HOST_METADATA_LIST_ROUTE) + .set('kbn-xsrf', 'xxx') + .send({ + filters: { + kql: `HostDetails.host.ip:${targetEndpointIp} or host.ip:${targetEndpointIp}`, + }, + }) + .expect(200); + expect(body.total).to.eql(1); + const resultIp: string = body.hosts[0].metadata.host.ip.filter( + (ip: string) => ip === targetEndpointIp + ); + expect(resultIp).to.eql([targetEndpointIp]); + expect(body.hosts[0].metadata.event.created).to.eql(timestamp); + expect(body.hosts.length).to.eql(1); + expect(body.request_page_size).to.eql(10); + expect(body.request_page_index).to.eql(0); + }); + + it('metadata api should return the latest event for all the events where policy status is not success', async () => { + const { body } = await supertest + .post(HOST_METADATA_LIST_ROUTE) + .set('kbn-xsrf', 'xxx') + .send({ + filters: { + kql: `not (HostDetails.Endpoint.policy.applied.status:success or Endpoint.policy.applied.status:success)`, + }, + }) + .expect(200); + const statuses: Set = new Set( + body.hosts.map( + (hostInfo: Record) => hostInfo.metadata.Endpoint.policy.applied.status + ) + ); + expect(statuses.size).to.eql(1); + expect(Array.from(statuses)).to.eql(['failure']); + }); + + it('metadata api should return the endpoint based on the elastic agent id, and status should be unhealthy', async () => { + const targetEndpointId = 'fc0ff548-feba-41b6-8367-65e8790d0eaf'; + const targetElasticAgentId = '023fa40c-411d-4188-a941-4147bfadd095'; + const { body } = await supertest + .post(HOST_METADATA_LIST_ROUTE) + .set('kbn-xsrf', 'xxx') + .send({ + filters: { + kql: `HostDetails.elastic.agent.id:${targetElasticAgentId} or elastic.agent.id:${targetElasticAgentId}`, + }, + }) + .expect(200); + expect(body.total).to.eql(1); + const resultHostId: string = body.hosts[0].metadata.host.id; + const resultElasticAgentId: string = body.hosts[0].metadata.elastic.agent.id; + expect(resultHostId).to.eql(targetEndpointId); + expect(resultElasticAgentId).to.eql(targetElasticAgentId); + expect(body.hosts[0].metadata.event.created).to.eql(timestamp); + expect(body.hosts[0].host_status).to.eql('unhealthy'); + expect(body.hosts.length).to.eql(1); + expect(body.request_page_size).to.eql(10); + expect(body.request_page_index).to.eql(0); + }); + + it('metadata api should return all hosts when filter is empty string', async () => { + const { body } = await supertest + .post(HOST_METADATA_LIST_ROUTE) + .set('kbn-xsrf', 'xxx') + .send({ + filters: { + kql: '', + }, + }) + .expect(200); + expect(body.total).to.eql(numberOfHostsInFixture); + expect(body.hosts.length).to.eql(numberOfHostsInFixture); + expect(body.request_page_size).to.eql(10); + expect(body.request_page_index).to.eql(0); + }); + }); + }); + }); + + describe('list endpoints GET route', () => { + describe('with .metrics-endpoint.metadata_united_default index', () => { + const numberOfHostsInFixture = 2; + + before(async () => { + await stopTransform(getService, `${METADATA_UNITED_TRANSFORM}*`); + await deleteAllDocsFromFleetAgents(getService); + await deleteAllDocsFromMetadataDatastream(getService); + await deleteAllDocsFromMetadataCurrentIndex(getService); + await deleteAllDocsFromIndex(getService, METADATA_UNITED_INDEX); + + // generate an endpoint policy and attach id to agents since + // metadata list api filters down to endpoint policies only + const policy = await indexFleetEndpointPolicy( + getService('kibanaServer'), + `Default ${uuid.v4()}`, + '1.1.1' + ); + const policyId = policy.integrationPolicies[0].policy_id; + const currentTime = new Date().getTime(); + + await Promise.all([ + bulkIndex(getService, AGENTS_INDEX, generateAgentDocs(currentTime, policyId)), + bulkIndex(getService, METADATA_DATASTREAM, generateMetadataDocs(currentTime)), + ]); + + // wait for latest metadata transform to run + await new Promise((r) => setTimeout(r, 30000)); + await startTransform(getService, METADATA_UNITED_TRANSFORM); + + // wait for united metadata transform to run + await new Promise((r) => setTimeout(r, 15000)); + }); + + after(async () => { + await deleteAllDocsFromFleetAgents(getService); + await deleteAllDocsFromMetadataDatastream(getService); + await deleteAllDocsFromMetadataCurrentIndex(getService); + await stopTransform(getService, `${METADATA_UNITED_TRANSFORM}*`); + await deleteAllDocsFromIndex(getService, METADATA_UNITED_INDEX); + }); + + it('should return one entry for each host with default paging', async () => { + const res = await supertest + .get(HOST_METADATA_LIST_ROUTE) + .set('kbn-xsrf', 'xxx') + .query({ + page: 0, + pageSize: 10, + }) + .expect(200); + const { body } = res; + expect(body.data.length).to.eql(numberOfHostsInFixture); + expect(body.total).to.eql(numberOfHostsInFixture); + expect(body.page).to.eql(0); + expect(body.pageSize).to.eql(10); + }); + + it('metadata api should return page based on paging properties passed', async () => { + const { body } = await supertest + .get(HOST_METADATA_LIST_ROUTE) + .set('kbn-xsrf', 'xxx') + .query({ + page: 1, + pageSize: 1, + }) + .expect(200); + expect(body.data.length).to.eql(1); + expect(body.total).to.eql(numberOfHostsInFixture); + expect(body.page).to.eql(1); + expect(body.pageSize).to.eql(1); + }); + + it('metadata api should return accurate total metadata if page index produces no result', async () => { + const { body } = await supertest + .get(HOST_METADATA_LIST_ROUTE) + .set('kbn-xsrf', 'xxx') + .query({ + page: 3, + pageSize: 10, + }) + .expect(200); + expect(body.data.length).to.eql(0); + expect(body.total).to.eql(numberOfHostsInFixture); + expect(body.page).to.eql(3); + expect(body.pageSize).to.eql(10); + }); + + it('metadata api should return 400 when pagingProperties is below boundaries.', async () => { + const { body } = await supertest + .get(HOST_METADATA_LIST_ROUTE) + .set('kbn-xsrf', 'xxx') + .query({ + page: 1, + pageSize: 0, + }) + .expect(400); + expect(body.message).to.contain('Value must be equal to or greater than [1]'); + }); + + it('metadata api should return page based on filters passed.', async () => { + const { body } = await supertest + .get(HOST_METADATA_LIST_ROUTE) + .set('kbn-xsrf', 'xxx') + .query({ + kuery: 'not (united.endpoint.host.ip:10.101.149.26)', + }) + .expect(200); + expect(body.data.length).to.eql(1); + expect(body.total).to.eql(1); + expect(body.page).to.eql(0); + expect(body.pageSize).to.eql(10); + }); + + it('metadata api should return page based on filters and paging passed.', async () => { + const notIncludedIp = '10.101.149.26'; + const { body } = await supertest + .get(HOST_METADATA_LIST_ROUTE) + .set('kbn-xsrf', 'xxx') + .query({ + page: 0, + pageSize: 10, + kuery: `not (united.endpoint.host.ip:${notIncludedIp})`, + }) + .expect(200); + expect(body.total).to.eql(1); + const resultIps: string[] = [].concat( + ...body.data.map((hostInfo: Record) => hostInfo.metadata.host.ip) + ); + expect(resultIps.sort()).to.eql(['10.192.213.130', '10.70.28.129'].sort()); + expect(resultIps).not.include.eql(notIncludedIp); + expect(body.data.length).to.eql(1); + expect(body.page).to.eql(0); + expect(body.pageSize).to.eql(10); + }); + + it('metadata api should return page based on host.os.Ext.variant filter.', async () => { + const variantValue = 'Windows Pro'; + const { body } = await supertest + .get(HOST_METADATA_LIST_ROUTE) + .set('kbn-xsrf', 'xxx') + .query({ + kuery: `united.endpoint.host.os.Ext.variant:${variantValue}`, + }) + .expect(200); + expect(body.total).to.eql(2); + const resultOsVariantValue: Set = new Set( + body.data.map((hostInfo: Record) => hostInfo.metadata.host.os.Ext.variant) + ); + expect(Array.from(resultOsVariantValue)).to.eql([variantValue]); + expect(body.data.length).to.eql(2); + expect(body.page).to.eql(0); + expect(body.pageSize).to.eql(10); + }); + + it('metadata api should return the latest event for all the events for an endpoint', async () => { + const targetEndpointIp = '10.101.149.26'; + const { body } = await supertest + .get(HOST_METADATA_LIST_ROUTE) + .set('kbn-xsrf', 'xxx') + .query({ + kuery: `united.endpoint.host.ip:${targetEndpointIp}`, + }) + .expect(200); + expect(body.total).to.eql(1); + const resultIp: string = body.data[0].metadata.host.ip.filter( + (ip: string) => ip === targetEndpointIp + ); + expect(resultIp).to.eql([targetEndpointIp]); + expect(body.data.length).to.eql(1); + expect(body.page).to.eql(0); + expect(body.pageSize).to.eql(10); + }); + + it('metadata api should return the latest event for all the events where policy status is not success', async () => { + const { body } = await supertest + .get(HOST_METADATA_LIST_ROUTE) + .set('kbn-xsrf', 'xxx') + .query({ + kuery: 'not (united.endpoint.Endpoint.policy.applied.status:success)', + }) + .expect(200); + const statuses: Set = new Set( + body.data.map( + (hostInfo: Record) => hostInfo.metadata.Endpoint.policy.applied.status + ) + ); + expect(statuses.size).to.eql(1); + expect(Array.from(statuses)).to.eql(['failure']); + }); + + it('metadata api should return the endpoint based on the elastic agent id, and status should be healthy', async () => { + const targetEndpointId = 'fc0ff548-feba-41b6-8367-65e8790d0eaf'; + const targetElasticAgentId = '023fa40c-411d-4188-a941-4147bfadd095'; + const { body } = await supertest + .get(HOST_METADATA_LIST_ROUTE) + .set('kbn-xsrf', 'xxx') + .query({ + kuery: `united.endpoint.elastic.agent.id:${targetElasticAgentId}`, + }) + .expect(200); + expect(body.total).to.eql(1); + const resultHostId: string = body.data[0].metadata.host.id; + const resultElasticAgentId: string = body.data[0].metadata.elastic.agent.id; + expect(resultHostId).to.eql(targetEndpointId); + expect(resultElasticAgentId).to.eql(targetElasticAgentId); + expect(body.data.length).to.eql(1); + expect(body.data[0].host_status).to.eql('healthy'); + expect(body.page).to.eql(0); + expect(body.pageSize).to.eql(10); + }); + + it('metadata api should return all hosts when filter is empty string', async () => { + const { body } = await supertest + .get(HOST_METADATA_LIST_ROUTE) + .set('kbn-xsrf', 'xxx') + .expect(200); + expect(body.data.length).to.eql(numberOfHostsInFixture); + expect(body.total).to.eql(numberOfHostsInFixture); + expect(body.page).to.eql(0); + expect(body.pageSize).to.eql(10); + }); + }); + + describe('with metrics-endpoint.metadata_current_default index', () => { + /** + * The number of host documents in the es archive. + */ + const numberOfHostsInFixture = 3; + + describe('when index is empty', () => { + it('metadata api should return empty result when index is empty', async () => { + await stopTransform(getService, `${METADATA_UNITED_TRANSFORM}*`); + await deleteIndex(getService, METADATA_UNITED_INDEX); + await deleteMetadataStream(getService); + await deleteAllDocsFromMetadataDatastream(getService); + await deleteAllDocsFromMetadataCurrentIndex(getService); + const { body } = await supertest + .get(HOST_METADATA_LIST_ROUTE) + .set('kbn-xsrf', 'xxx') + .query({ + page: 0, + pageSize: 10, + }) + .expect(200); + expect(body.data.length).to.eql(0); + expect(body.total).to.eql(0); + expect(body.page).to.eql(0); + expect(body.pageSize).to.eql(10); + }); + }); + + describe('when index is not empty', () => { + const timestamp = new Date().getTime(); + before(async () => { + // stop the united transform and delete the index + // otherwise it won't hit metrics-endpoint.metadata_current_default index + await stopTransform(getService, `${METADATA_UNITED_TRANSFORM}*`); + await deleteIndex(getService, METADATA_UNITED_INDEX); + await bulkIndex(getService, METADATA_DATASTREAM, generateMetadataDocs(timestamp)); + // wait for transform + await new Promise((r) => setTimeout(r, 60000)); + }); + // the endpoint uses data streams and es archiver does not support deleting them at the moment so we need + // to do it manually + after(async () => { + await deleteMetadataStream(getService); + await deleteAllDocsFromMetadataDatastream(getService); + await deleteAllDocsFromMetadataCurrentIndex(getService); + }); + + it('metadata api should return one entry for each host with default paging', async () => { + const { body } = await supertest + .get(HOST_METADATA_LIST_ROUTE) + .set('kbn-xsrf', 'xxx') + .query({ + page: 0, + pageSize: 10, + }) + .expect(200); + expect(body.data.length).to.eql(numberOfHostsInFixture); + expect(body.total).to.eql(numberOfHostsInFixture); + expect(body.page).to.eql(0); + expect(body.pageSize).to.eql(10); + }); + + it('metadata api should return page based on paging properties passed.', async () => { + const { body } = await supertest + .get(HOST_METADATA_LIST_ROUTE) + .set('kbn-xsrf', 'xxx') + .query({ + page: 1, + pageSize: 1, + }) + .expect(200); + expect(body.data.length).to.eql(1); + expect(body.total).to.eql(numberOfHostsInFixture); + expect(body.page).to.eql(1); + expect(body.pageSize).to.eql(1); + }); + + /* test that when paging properties produces no result, the total should reflect the actual number of metadata + in the index. + */ + it('metadata api should return accurate total metadata if page index produces no result', async () => { + const { body } = await supertest + .get(HOST_METADATA_LIST_ROUTE) + .set('kbn-xsrf', 'xxx') + .query({ + page: 3, + pageSize: 10, + }) + .expect(200); + expect(body.data.length).to.eql(0); + expect(body.total).to.eql(numberOfHostsInFixture); + expect(body.page).to.eql(3); + expect(body.pageSize).to.eql(10); + }); + + it('metadata api should return 400 when pagingProperties is below boundaries.', async () => { + const { body } = await supertest + .get(HOST_METADATA_LIST_ROUTE) + .set('kbn-xsrf', 'xxx') + .query({ + page: 1, + pageSize: 0, + }) + .expect(400); + expect(body.message).to.contain('Value must be equal to or greater than [1]'); + }); + + it('metadata api should return page based on filters passed.', async () => { + const { body } = await supertest + .get(HOST_METADATA_LIST_ROUTE) + .set('kbn-xsrf', 'xxx') + .query({ + kuery: 'not (HostDetails.host.ip:10.46.229.234 or host.ip:10.46.229.234)', + }) + .expect(200); + expect(body.data.length).to.eql(2); + expect(body.total).to.eql(2); + expect(body.page).to.eql(0); + expect(body.pageSize).to.eql(10); + }); + + it('metadata api should return page based on filters and paging passed.', async () => { + const notIncludedIp = '10.46.229.234'; + const { body } = await supertest + .get(HOST_METADATA_LIST_ROUTE) + .set('kbn-xsrf', 'xxx') + .query({ + page: 0, + pageSize: 10, + kuery: `not (HostDetails.host.ip:${notIncludedIp} or host.ip:${notIncludedIp})`, + }) + .expect(200); + expect(body.data.length).to.eql(2); + expect(body.total).to.eql(2); + const resultIps: string[] = [].concat( + ...body.data.map((hostInfo: Record) => hostInfo.metadata.host.ip) + ); + expect(resultIps.sort()).to.eql( + [ + '10.192.213.130', + '10.70.28.129', + '10.101.149.26', + '2606:a000:ffc0:39:11ef:37b9:3371:578c', + ].sort() + ); + expect(resultIps).not.include.eql(notIncludedIp); + expect(body.page).to.eql(0); + expect(body.pageSize).to.eql(10); + }); + + it('metadata api should return page based on host.os.Ext.variant filter.', async () => { + const variantValue = 'Windows Pro'; + const { body } = await supertest + .get(HOST_METADATA_LIST_ROUTE) + .set('kbn-xsrf', 'xxx') + .query({ + kuery: `HostDetails.host.os.Ext.variant:${variantValue} or host.os.Ext.variant:${variantValue}`, + }) + .expect(200); + expect(body.data.length).to.eql(2); + expect(body.total).to.eql(2); + const resultOsVariantValue: Set = new Set( + body.data.map( + (hostInfo: Record) => hostInfo.metadata.host.os.Ext.variant + ) + ); + expect(Array.from(resultOsVariantValue)).to.eql([variantValue]); + expect(body.page).to.eql(0); + expect(body.pageSize).to.eql(10); + }); + + it('metadata api should return the latest event for all the events for an endpoint', async () => { + const targetEndpointIp = '10.46.229.234'; + const { body } = await supertest + .get(HOST_METADATA_LIST_ROUTE) + .set('kbn-xsrf', 'xxx') + .query({ + kuery: `HostDetails.host.ip:${targetEndpointIp} or host.ip:${targetEndpointIp}`, + }) + .expect(200); + expect(body.data.length).to.eql(1); + expect(body.total).to.eql(1); + const resultIp: string = body.data[0].metadata.host.ip.filter( + (ip: string) => ip === targetEndpointIp + ); + expect(resultIp).to.eql([targetEndpointIp]); + expect(body.data[0].metadata.event.created).to.eql(timestamp); + expect(body.page).to.eql(0); + expect(body.pageSize).to.eql(10); + }); + + it('metadata api should return the latest event for all the events where policy status is not success', async () => { + const { body } = await supertest + .get(HOST_METADATA_LIST_ROUTE) + .set('kbn-xsrf', 'xxx') + .query({ + kuery: + 'not (HostDetails.Endpoint.policy.applied.status:success or Endpoint.policy.applied.status:success)', + }) + .expect(200); + const statuses: Set = new Set( + body.data.map( + (hostInfo: Record) => hostInfo.metadata.Endpoint.policy.applied.status + ) + ); + expect(statuses.size).to.eql(1); + expect(Array.from(statuses)).to.eql(['failure']); + }); + + it('metadata api should return the endpoint based on the elastic agent id, and status should be unhealthy', async () => { + const targetEndpointId = 'fc0ff548-feba-41b6-8367-65e8790d0eaf'; + const targetElasticAgentId = '023fa40c-411d-4188-a941-4147bfadd095'; + const { body } = await supertest + .get(HOST_METADATA_LIST_ROUTE) + .set('kbn-xsrf', 'xxx') + .query({ + kuery: `HostDetails.elastic.agent.id:${targetElasticAgentId} or elastic.agent.id:${targetElasticAgentId}`, + }) + .expect(200); + expect(body.data.length).to.eql(1); + expect(body.total).to.eql(1); + const resultHostId: string = body.data[0].metadata.host.id; + const resultElasticAgentId: string = body.data[0].metadata.elastic.agent.id; + expect(resultHostId).to.eql(targetEndpointId); + expect(resultElasticAgentId).to.eql(targetElasticAgentId); + expect(body.data[0].metadata.event.created).to.eql(timestamp); + expect(body.data[0].host_status).to.eql('unhealthy'); + expect(body.page).to.eql(0); + expect(body.pageSize).to.eql(10); + }); + + it('metadata api should return all hosts when filter is empty string', async () => { + const { body } = await supertest + .get(HOST_METADATA_LIST_ROUTE) + .set('kbn-xsrf', 'xxx') + .query({ + kuery: '', + }) + .expect(200); + expect(body.data.length).to.eql(numberOfHostsInFixture); + expect(body.total).to.eql(numberOfHostsInFixture); + expect(body.page).to.eql(0); + expect(body.pageSize).to.eql(10); + }); + }); + }); }); }); } From 2e4caabcfc3d9998149b8bfd909f770b7e1d268e Mon Sep 17 00:00:00 2001 From: Scotty Bollinger Date: Thu, 18 Nov 2021 14:49:42 -0600 Subject: [PATCH 128/148] [Enterprise Search] Fix bug where non-superusers can lock themselves out (#117405) * Fix bug where non-superusers can lock themselves out * Update name to superuser Co-authored-by: Vadim Yakhin Co-authored-by: Vadim Yakhin Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../shared/role_mapping/constants.ts | 7 ++ .../role_mapping/roles_empty_prompt.test.tsx | 60 ++++++++++++++- .../role_mapping/roles_empty_prompt.tsx | 76 +++++++++++++------ 3 files changed, 116 insertions(+), 27 deletions(-) diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/constants.ts b/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/constants.ts index 0a99b0991f4ed..e94eb39f8cc75 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/constants.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/constants.ts @@ -242,6 +242,13 @@ export const ROLES_DISABLED_NOTE = i18n.translate( } ); +export const RBAC_BUTTON_DISABLED_LABEL = i18n.translate( + 'xpack.enterpriseSearch.roleMapping.rbacButtonDisabledLabel', + { + defaultMessage: 'Enabling RBAC can be performed by a superuser.', + } +); + export const ENABLE_ROLES_BUTTON = i18n.translate( 'xpack.enterpriseSearch.roleMapping.enableRolesButton', { defaultMessage: 'Enable role-based access' } diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/roles_empty_prompt.test.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/roles_empty_prompt.test.tsx index 8331a45849e3a..974c0d17c29f9 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/roles_empty_prompt.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/roles_empty_prompt.test.tsx @@ -5,6 +5,9 @@ * 2.0. */ +import '../../__mocks__/shallow_useeffect.mock'; +import { mockKibanaValues } from '../../__mocks__/kea_logic'; + import React from 'react'; import { shallow } from 'enzyme'; @@ -14,6 +17,18 @@ import { EuiButton, EuiLink, EuiEmptyPrompt } from '@elastic/eui'; import { RolesEmptyPrompt } from './roles_empty_prompt'; describe('RolesEmptyPrompt', () => { + const { + security: { + authc: { getCurrentUser }, + }, + } = mockKibanaValues; + + const mockCurrentUser = (user?: unknown) => + (getCurrentUser as jest.Mock).mockReturnValue(Promise.resolve(user)); + + const mockCurrentUserError = () => + (getCurrentUser as jest.Mock).mockReturnValue(Promise.reject()); + const onEnable = jest.fn(); const props = { @@ -22,15 +37,52 @@ describe('RolesEmptyPrompt', () => { onEnable, }; - it('renders', () => { - const wrapper = shallow(); + const mockUser = { + username: 'elastic', + roles: ['superuser'], + }; + + beforeAll(() => { + mockCurrentUser(); + }); + + it('gets the current user on mount', () => { + shallow(); + + expect(getCurrentUser).toHaveBeenCalled(); + }); + + it('does not render if the getCurrentUser promise returns error', async () => { + mockCurrentUserError(); + const wrapper = await shallow(); + + expect(wrapper.isEmptyRender()).toBe(true); + }); + + it('renders', async () => { + mockCurrentUser(mockUser); + const wrapper = await shallow(); expect(wrapper.find(EuiEmptyPrompt)).toHaveLength(1); expect(wrapper.find(EuiEmptyPrompt).dive().find(EuiLink).prop('href')).toEqual(props.docsLink); }); - it('calls onEnable on change', () => { - const wrapper = shallow(); + it('disables button when non-superuser', async () => { + mockCurrentUser({ + username: 'user', + roles: ['foo'], + }); + const wrapper = await shallow(); + + expect(wrapper.find(EuiEmptyPrompt).dive().find(EuiButton).prop('disabled')).toBe(true); + expect( + wrapper.find(EuiEmptyPrompt).dive().find('[data-test-subj="rbacDisabledLabel"]') + ).toHaveLength(1); + }); + + it('calls onEnable on change', async () => { + mockCurrentUser(mockUser); + const wrapper = await shallow(); const prompt = wrapper.find(EuiEmptyPrompt).dive(); prompt.find(EuiButton).simulate('click'); diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/roles_empty_prompt.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/roles_empty_prompt.tsx index 11d50573c45f6..b325863b54430 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/roles_empty_prompt.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/shared/role_mapping/roles_empty_prompt.tsx @@ -5,13 +5,18 @@ * 2.0. */ -import React from 'react'; +import React, { useState, useEffect } from 'react'; -import { EuiEmptyPrompt, EuiButton, EuiLink, EuiSpacer } from '@elastic/eui'; +import { useValues } from 'kea'; +import { EuiEmptyPrompt, EuiButton, EuiLink, EuiSpacer, EuiText } from '@elastic/eui'; + +import type { AuthenticatedUser } from '../../../../../security/public'; +import { KibanaLogic } from '../kibana/kibana_logic'; import { ProductName } from '../types'; import { + RBAC_BUTTON_DISABLED_LABEL, ROLES_DISABLED_TITLE, ROLES_DISABLED_DESCRIPTION, ROLES_DISABLED_NOTE, @@ -25,24 +30,49 @@ interface Props { onEnable(): void; } -export const RolesEmptyPrompt: React.FC = ({ onEnable, docsLink, productName }) => ( - {ROLES_DISABLED_TITLE}