diff --git a/src/plugins/discover/public/application/angular/get_painless_error.ts b/src/plugins/discover/public/application/angular/get_painless_error.ts index e1e98d9df27b1..162dacd3ac3b7 100644 --- a/src/plugins/discover/public/application/angular/get_painless_error.ts +++ b/src/plugins/discover/public/application/angular/get_painless_error.ts @@ -18,20 +18,77 @@ */ import { i18n } from '@kbn/i18n'; -import { get } from 'lodash'; -export function getPainlessError(error: Error) { - const rootCause: Array<{ lang: string; script: string }> | undefined = get( - error, - 'body.attributes.error.root_cause' - ); - const message: string = get(error, 'body.message'); +interface FailedShards { + shard: number; + index: string; + node: string; + reason: { + type: string; + reason: string; + script_stack: string[]; + script: string; + lang: string; + position: { + offset: number; + start: number; + end: number; + }; + caused_by: { + type: string; + reason: string; + }; + }; +} + +interface EsError { + body: { + statusCode: number; + error: string; + message: string; + attributes?: { + error?: { + root_cause?: [ + { + lang: string; + script: string; + } + ]; + type: string; + reason: string; + caused_by: { + type: string; + reason: string; + phase: string; + grouped: boolean; + failed_shards: FailedShards[]; + }; + }; + }; + }; +} + +export function getCause(error: EsError) { + const cause = error.body?.attributes?.error?.root_cause; + if (cause) { + return cause[0]; + } + + const failedShards = error.body?.attributes?.error?.caused_by?.failed_shards; + + if (failedShards && failedShards[0] && failedShards[0].reason) { + return error.body?.attributes?.error?.caused_by?.failed_shards[0].reason; + } +} + +export function getPainlessError(error: EsError) { + const cause = getCause(error); - if (!rootCause) { + if (!cause) { return; } - const [{ lang, script }] = rootCause; + const { lang, script } = cause; if (lang !== 'painless') { return; @@ -44,6 +101,6 @@ export function getPainlessError(error: Error) { defaultMessage: "Error with Painless scripted field '{script}'.", values: { script }, }), - error: message, + error: error.body?.message, }; } diff --git a/test/accessibility/apps/dashboard_panel.ts b/test/accessibility/apps/dashboard_panel.ts index 03fa76387da1f..1a817ce6b7a1c 100644 --- a/test/accessibility/apps/dashboard_panel.ts +++ b/test/accessibility/apps/dashboard_panel.ts @@ -18,7 +18,6 @@ */ import { FtrProviderContext } from '../ftr_provider_context'; - export default function ({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects(['common', 'dashboard', 'header', 'home', 'settings']); const a11y = getService('a11y'); @@ -31,6 +30,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await PageObjects.common.navigateToUrl('home', '/tutorial_directory/sampleData', { useActualUrl: true, }); + await PageObjects.home.addSampleDataSet('flights'); await PageObjects.common.navigateToApp('dashboard'); await testSubjects.click('dashboardListingTitleLink-[Flights]-Global-Flight-Dashboard'); diff --git a/test/functional/apps/discover/_errors.js b/test/functional/apps/discover/_errors.ts similarity index 92% rename from test/functional/apps/discover/_errors.js rename to test/functional/apps/discover/_errors.ts index 614059dc8ac94..9520d652a65d5 100644 --- a/test/functional/apps/discover/_errors.js +++ b/test/functional/apps/discover/_errors.ts @@ -18,8 +18,9 @@ */ import expect from '@kbn/expect'; +import { FtrProviderContext } from '../../ftr_provider_context'; -export default function ({ getService, getPageObjects }) { +export default function ({ getService, getPageObjects }: FtrProviderContext) { const esArchiver = getService('esArchiver'); const testSubjects = getService('testSubjects'); const PageObjects = getPageObjects(['common', 'discover', 'timePicker']); diff --git a/x-pack/plugins/apm/common/agent_configuration/setting_definitions/__snapshots__/index.test.ts.snap b/x-pack/plugins/apm/common/agent_configuration/setting_definitions/__snapshots__/index.test.ts.snap index 2044053e049f1..2962a5fd2df3b 100644 --- a/x-pack/plugins/apm/common/agent_configuration/setting_definitions/__snapshots__/index.test.ts.snap +++ b/x-pack/plugins/apm/common/agent_configuration/setting_definitions/__snapshots__/index.test.ts.snap @@ -172,7 +172,7 @@ Array [ }, Object { "key": "transaction_max_spans", - "max": 32000, + "max": undefined, "min": 0, "type": "integer", "validationName": "integerRt", diff --git a/x-pack/plugins/apm/common/agent_configuration/setting_definitions/general_settings.ts b/x-pack/plugins/apm/common/agent_configuration/setting_definitions/general_settings.ts index 95892f435e8f9..e777e1fd09d0b 100644 --- a/x-pack/plugins/apm/common/agent_configuration/setting_definitions/general_settings.ts +++ b/x-pack/plugins/apm/common/agent_configuration/setting_definitions/general_settings.ts @@ -177,7 +177,6 @@ export const generalSettings: RawSettingDefinition[] = [ key: 'transaction_max_spans', type: 'integer', min: 0, - max: 32000, defaultValue: '500', label: i18n.translate('xpack.apm.agentConfig.transactionMaxSpans.label', { defaultMessage: 'Transaction max spans', diff --git a/x-pack/plugins/apm/public/components/app/TransactionOverview/ClientSideMonitoringCallout.tsx b/x-pack/plugins/apm/public/components/app/TransactionOverview/ClientSideMonitoringCallout.tsx new file mode 100644 index 0000000000000..b6938b211994d --- /dev/null +++ b/x-pack/plugins/apm/public/components/app/TransactionOverview/ClientSideMonitoringCallout.tsx @@ -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; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { EuiButton, EuiCallOut, EuiSpacer, EuiText } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { useApmPluginContext } from '../../../hooks/useApmPluginContext'; + +export function ClientSideMonitoringCallout() { + const { core } = useApmPluginContext(); + const clientSideMonitoringHref = core.http.basePath.prepend(`/app/csm`); + + return ( + + + {i18n.translate( + 'xpack.apm.transactionOverview.clientSideMonitoring.calloutText', + { + defaultMessage: + 'We are beyond excited to introduce a new experience for analyzing the user experience metrics specifically for your RUM services. It provides insights into the core vitals and visitor breakdown by browser and location. The app is always available in the left sidebar among the other Observability views.', + } + )} + + + + {i18n.translate( + 'xpack.apm.transactionOverview.clientSideMonitoring.linkLabel', + { defaultMessage: 'Take me there' } + )} + + + ); +} diff --git a/x-pack/plugins/apm/public/components/app/TransactionOverview/index.tsx b/x-pack/plugins/apm/public/components/app/TransactionOverview/index.tsx index 3e32b0ec23b13..7c887da6dc5e6 100644 --- a/x-pack/plugins/apm/public/components/app/TransactionOverview/index.tsx +++ b/x-pack/plugins/apm/public/components/app/TransactionOverview/index.tsx @@ -35,6 +35,8 @@ import { LocalUIFilters } from '../../shared/LocalUIFilters'; import { TransactionTypeFilter } from '../../shared/LocalUIFilters/TransactionTypeFilter'; import { TransactionList } from './TransactionList'; import { useRedirect } from './useRedirect'; +import { TRANSACTION_PAGE_LOAD } from '../../../../common/transaction_types'; +import { ClientSideMonitoringCallout } from './ClientSideMonitoringCallout'; function getRedirectLocation({ urlParams, @@ -125,6 +127,12 @@ export function TransactionOverview({ serviceName }: TransactionOverviewProps) { + {transactionType === TRANSACTION_PAGE_LOAD && ( + <> + + + + )} { ); expect(href).toMatchInlineSnapshot( - `"/basepath/app/ml#/timeseriesexplorer?_g=(ml:(jobIds:!(myservicename-mytransactiontype-high_mean_response_time)),refreshInterval:(pause:!t,value:0),time:(from:now/w,to:now-4h))&_a=(mlTimeSeriesExplorer:(entities:(service.name:opbeans-test,transaction.type:request),zoom:(from:now/w,to:now-4h)))"` + `"/basepath/app/ml#/timeseriesexplorer?_g=(ml:(jobIds:!(myservicename-mytransactiontype-high_mean_response_time)),refreshInterval:(pause:!t,value:0),time:(from:now/w,to:now-4h))&_a=(mlTimeSeriesExplorer:(entities:(service.name:opbeans-test,transaction.type:request)))"` ); }); }); diff --git a/x-pack/plugins/apm/public/components/shared/Links/MachineLearningLinks/useTimeSeriesExplorerHref.test.ts b/x-pack/plugins/apm/public/components/shared/Links/MachineLearningLinks/useTimeSeriesExplorerHref.test.ts index 66f3903ba849b..d84f55af993aa 100644 --- a/x-pack/plugins/apm/public/components/shared/Links/MachineLearningLinks/useTimeSeriesExplorerHref.test.ts +++ b/x-pack/plugins/apm/public/components/shared/Links/MachineLearningLinks/useTimeSeriesExplorerHref.test.ts @@ -28,7 +28,7 @@ describe('useTimeSeriesExplorerHref', () => { }); expect(href).toMatchInlineSnapshot( - `"/app/ml#/timeseriesexplorer?_g=(ml:(jobIds:!(apm-production-485b-high_mean_transaction_duration)),refreshInterval:(pause:!t,value:10000),time:(from:'2020-07-29T17:27:29.000Z',to:'2020-07-29T18:45:00.000Z'))&_a=(mlTimeSeriesExplorer:(entities:(service.name:opbeans-java,transaction.type:request),zoom:(from:'2020-07-29T17:27:29.000Z',to:'2020-07-29T18:45:00.000Z')))"` + `"/app/ml#/timeseriesexplorer?_g=(ml:(jobIds:!(apm-production-485b-high_mean_transaction_duration)),refreshInterval:(pause:!t,value:10000),time:(from:'2020-07-29T17:27:29.000Z',to:'2020-07-29T18:45:00.000Z'))&_a=(mlTimeSeriesExplorer:(entities:(service.name:opbeans-java,transaction.type:request)))"` ); }); }); diff --git a/x-pack/plugins/apm/public/components/shared/Links/MachineLearningLinks/useTimeSeriesExplorerHref.ts b/x-pack/plugins/apm/public/components/shared/Links/MachineLearningLinks/useTimeSeriesExplorerHref.ts index 3b60962d797ed..0cb87a4f515b6 100644 --- a/x-pack/plugins/apm/public/components/shared/Links/MachineLearningLinks/useTimeSeriesExplorerHref.ts +++ b/x-pack/plugins/apm/public/components/shared/Links/MachineLearningLinks/useTimeSeriesExplorerHref.ts @@ -39,7 +39,6 @@ export function useTimeSeriesExplorerHref({ 'service.name': serviceName, 'transaction.type': transactionType, }, - zoom: time, }, }), } diff --git a/x-pack/plugins/apm/public/components/shared/charts/TransactionCharts/BrowserLineChart.test.tsx b/x-pack/plugins/apm/public/components/shared/charts/TransactionCharts/BrowserLineChart.test.tsx deleted file mode 100644 index 9f112475a4a78..0000000000000 --- a/x-pack/plugins/apm/public/components/shared/charts/TransactionCharts/BrowserLineChart.test.tsx +++ /dev/null @@ -1,24 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import React from 'react'; -import { shallow } from 'enzyme'; -import { BrowserLineChart } from './BrowserLineChart'; -import { MockApmPluginContextWrapper } from '../../../../context/ApmPluginContext/MockApmPluginContext'; - -describe('BrowserLineChart', () => { - describe('render', () => { - it('renders', () => { - expect(() => - shallow( - - - - ) - ).not.toThrowError(); - }); - }); -}); diff --git a/x-pack/plugins/apm/public/components/shared/charts/TransactionCharts/BrowserLineChart.tsx b/x-pack/plugins/apm/public/components/shared/charts/TransactionCharts/BrowserLineChart.tsx deleted file mode 100644 index 40caf35155918..0000000000000 --- a/x-pack/plugins/apm/public/components/shared/charts/TransactionCharts/BrowserLineChart.tsx +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { EuiTitle } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; -import React from 'react'; -import { useAvgDurationByBrowser } from '../../../../hooks/useAvgDurationByBrowser'; -import { getDurationFormatter } from '../../../../utils/formatters'; -import { - getResponseTimeTickFormatter, - getResponseTimeTooltipFormatter, - getMaxY, -} from './helper'; -import { TransactionLineChart } from './TransactionLineChart'; - -export function BrowserLineChart() { - const { data } = useAvgDurationByBrowser(); - const maxY = getMaxY(data); - const formatter = getDurationFormatter(maxY); - const formatTooltipValue = getResponseTimeTooltipFormatter(formatter); - const tickFormatY = getResponseTimeTickFormatter(formatter); - - return ( - <> - - - {i18n.translate( - 'xpack.apm.metrics.pageLoadCharts.avgPageLoadByBrowser', - { - defaultMessage: 'Avg. page load duration distribution by browser', - } - )} - - - - - ); -} diff --git a/x-pack/plugins/apm/public/components/shared/charts/TransactionCharts/ChoroplethMap/ChoroplethToolTip.tsx b/x-pack/plugins/apm/public/components/shared/charts/TransactionCharts/ChoroplethMap/ChoroplethToolTip.tsx deleted file mode 100644 index 69d4e8109dfbf..0000000000000 --- a/x-pack/plugins/apm/public/components/shared/charts/TransactionCharts/ChoroplethMap/ChoroplethToolTip.tsx +++ /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; - * you may not use this file except in compliance with the Elastic License. - */ - -import React from 'react'; -import { i18n } from '@kbn/i18n'; -import { asDuration, asInteger } from '../../../../../utils/formatters'; -import { fontSizes } from '../../../../../style/variables'; - -export function ChoroplethToolTip({ - name, - value, - docCount, -}: { - name: string; - value: number; - docCount: number; -}) { - return ( -
-
{name}
-
- {i18n.translate( - 'xpack.apm.metrics.durationByCountryMap.RegionMapChart.ToolTip.avgPageLoadDuration', - { - defaultMessage: 'Avg. page load duration:', - } - )} -
-
- {asDuration(value)} -
-
- ( - {i18n.translate( - 'xpack.apm.metrics.durationByCountryMap.RegionMapChart.ToolTip.countPageLoads', - { - values: { docCount: asInteger(docCount) }, - defaultMessage: '{docCount} page loads', - } - )} - ) -
-
- ); -} diff --git a/x-pack/plugins/apm/public/components/shared/charts/TransactionCharts/ChoroplethMap/index.tsx b/x-pack/plugins/apm/public/components/shared/charts/TransactionCharts/ChoroplethMap/index.tsx deleted file mode 100644 index 965cb2ae4f50a..0000000000000 --- a/x-pack/plugins/apm/public/components/shared/charts/TransactionCharts/ChoroplethMap/index.tsx +++ /dev/null @@ -1,270 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import React, { - useState, - useEffect, - useRef, - useCallback, - useMemo, -} from 'react'; -import { Map, NavigationControl, Popup } from 'mapbox-gl'; -import 'mapbox-gl/dist/mapbox-gl.css'; -import { shade, tint } from 'polished'; -import { EuiTheme } from '../../../../../../../observability/public'; -import { useTheme } from '../../../../../hooks/useTheme'; -import { ChoroplethToolTip } from './ChoroplethToolTip'; - -interface ChoroplethItem { - key: string; - value: number; - docCount: number; -} - -interface Tooltip { - name: string; - value: number; - docCount: number; -} - -interface WorldCountryFeatureProperties { - name: string; - iso2: string; - iso3: string; -} - -interface Props { - items: ChoroplethItem[]; -} - -const CHOROPLETH_LAYER_ID = 'choropleth_layer'; -const CHOROPLETH_POLYGONS_SOURCE_ID = 'choropleth_polygons'; -const GEOJSON_KEY_PROPERTY = 'iso2'; -const MAPBOX_STYLE = - 'https://tiles.maps.elastic.co/styles/osm-bright-desaturated/style.json'; -const GEOJSON_SOURCE = - 'https://vector.maps.elastic.co/files/world_countries_v1.geo.json?elastic_tile_service_tos=agree&my_app_name=ems-landing&my_app_version=7.2.0'; - -export function getProgressionColor(scale: number, theme: EuiTheme) { - const baseColor = theme.eui.euiColorPrimary; - const adjustedScale = 0.75 * scale + 0.05; // prevents pure black & white as min/max colors. - if (adjustedScale < 0.5) { - return tint(adjustedScale * 2, baseColor); - } - if (adjustedScale > 0.5) { - return shade(1 - (adjustedScale - 0.5) * 2, baseColor); - } - return baseColor; -} - -const getMin = (items: ChoroplethItem[]) => - Math.min(...items.map((item) => item.value)); - -const getMax = (items: ChoroplethItem[]) => - Math.max(...items.map((item) => item.value)); - -export function ChoroplethMap(props: Props) { - const theme = useTheme(); - const { items } = props; - const containerRef = useRef(null); - const [map, setMap] = useState(null); - const popupRef = useRef(null); - const popupContainerRef = useRef(null); - const [tooltipState, setTooltipState] = useState(null); - const [min, max] = useMemo(() => [getMin(items), getMax(items)], [items]); - - // converts an item value to a scaled value between 0 and 1 - const getValueScale = useCallback( - (value: number) => (value - min) / (max - min), - [max, min] - ); - - const controlScrollZoomOnWheel = useCallback((event: WheelEvent) => { - if (event.ctrlKey || event.metaKey) { - event.preventDefault(); - } else { - event.stopPropagation(); - } - }, []); - - // side effect creates a new mouseover handler referencing new component state - // and replaces the old one stored in `updateTooltipStateOnMousemoveRef` - useEffect(() => { - const updateTooltipStateOnMousemove = (event: mapboxgl.MapMouseEvent) => { - const isMapQueryable = - map && - popupRef.current && - items.length && - map.getLayer(CHOROPLETH_LAYER_ID); - - if (!isMapQueryable) { - return; - } - (popupRef.current as Popup).setLngLat(event.lngLat); - const hoverFeatures = (map as Map).queryRenderedFeatures(event.point, { - layers: [CHOROPLETH_LAYER_ID], - }); - - if (tooltipState && hoverFeatures.length === 0) { - return setTooltipState(null); - } - - const featureProperties = hoverFeatures[0] - .properties as WorldCountryFeatureProperties; - - if (tooltipState && tooltipState.name === featureProperties.name) { - return; - } - - const item = items.find( - ({ key }) => - featureProperties && key === featureProperties[GEOJSON_KEY_PROPERTY] - ); - - if (item) { - return setTooltipState({ - name: featureProperties.name, - value: item.value, - docCount: item.docCount, - }); - } - - setTooltipState(null); - }; - updateTooltipStateOnMousemoveRef.current = updateTooltipStateOnMousemove; - }, [map, items, tooltipState]); - - const updateTooltipStateOnMousemoveRef = useRef( - (_event: mapboxgl.MapMouseEvent & mapboxgl.EventData) => {} - ); - - // initialization side effect, only runs once - useEffect(() => { - if (containerRef.current === null) { - return; - } - - // set up Map object - const mapboxMap = new Map({ - attributionControl: false, - container: containerRef.current, - dragRotate: false, - touchZoomRotate: false, - zoom: 0.85, - center: { lng: 0, lat: 30 }, - style: MAPBOX_STYLE, - }); - - mapboxMap.addControl( - new NavigationControl({ showCompass: false }), - 'top-left' - ); - - // set up Popup object - popupRef.current = new Popup({ - closeButton: false, - closeOnClick: false, - }); - - // always use the current handler which changes with component state - mapboxMap.on('mousemove', (...args) => - updateTooltipStateOnMousemoveRef.current(...args) - ); - mapboxMap.on('mouseout', () => { - setTooltipState(null); - }); - - // only scroll zoom when key is pressed - const canvasElement = mapboxMap.getCanvas(); - canvasElement.addEventListener('wheel', controlScrollZoomOnWheel); - - mapboxMap.on('load', () => { - mapboxMap.addSource(CHOROPLETH_POLYGONS_SOURCE_ID, { - type: 'geojson', - data: GEOJSON_SOURCE, - }); - setMap(mapboxMap); - }); - - // cleanup function called when component unmounts - return () => { - canvasElement.removeEventListener('wheel', controlScrollZoomOnWheel); - }; - }, [controlScrollZoomOnWheel]); - - // side effect replaces choropleth layer with new one on items changes - useEffect(() => { - if (!map) { - return; - } - - // find first symbol layer to place new layer in correct order - const symbolLayer = (map.getStyle().layers || []).find( - ({ type }) => type === 'symbol' - ); - - if (map.getLayer(CHOROPLETH_LAYER_ID)) { - map.removeLayer(CHOROPLETH_LAYER_ID); - } - - if (items.length === 0) { - return; - } - - const stops = items.map(({ key, value }) => [ - key, - getProgressionColor(getValueScale(value), theme), - ]); - - const fillColor: mapboxgl.FillPaint['fill-color'] = { - property: GEOJSON_KEY_PROPERTY, - stops, - type: 'categorical', - default: 'transparent', - }; - - map.addLayer( - { - id: CHOROPLETH_LAYER_ID, - type: 'fill', - source: CHOROPLETH_POLYGONS_SOURCE_ID, - layout: {}, - paint: { - 'fill-opacity': 0.75, - 'fill-color': fillColor, - }, - }, - symbolLayer ? symbolLayer.id : undefined - ); - }, [map, items, theme, getValueScale]); - - // side effect to only render the Popup when hovering a region with a matching item - useEffect(() => { - if (!(popupContainerRef.current && map && popupRef.current)) { - return; - } - if (tooltipState) { - popupRef.current.setDOMContent(popupContainerRef.current).addTo(map); - if (popupContainerRef.current.parentElement) { - popupContainerRef.current.parentElement.style.pointerEvents = 'none'; - } - } else { - popupRef.current.remove(); - } - }, [map, tooltipState]); - - // render map container and tooltip in a hidden container - return ( -
-
-
-
- {tooltipState ? : null} -
-
-
- ); -} diff --git a/x-pack/plugins/apm/public/components/shared/charts/TransactionCharts/DurationByCountryMap/index.tsx b/x-pack/plugins/apm/public/components/shared/charts/TransactionCharts/DurationByCountryMap/index.tsx deleted file mode 100644 index 2dd3d058e98b8..0000000000000 --- a/x-pack/plugins/apm/public/components/shared/charts/TransactionCharts/DurationByCountryMap/index.tsx +++ /dev/null @@ -1,33 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { EuiTitle } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; -import React from 'react'; -import { useAvgDurationByCountry } from '../../../../../hooks/useAvgDurationByCountry'; - -import { ChoroplethMap } from '../ChoroplethMap'; - -export function DurationByCountryMap() { - const { data } = useAvgDurationByCountry(); - - return ( - <> - {' '} - - - {i18n.translate( - 'xpack.apm.metrics.durationByCountryMap.avgPageLoadByCountryLabel', - { - defaultMessage: 'Avg. page load duration distribution by country', - } - )} - - - - - ); -} diff --git a/x-pack/plugins/apm/public/components/shared/charts/TransactionCharts/index.tsx b/x-pack/plugins/apm/public/components/shared/charts/TransactionCharts/index.tsx index 6ba080a07b9d3..30ee0ba3eaa1f 100644 --- a/x-pack/plugins/apm/public/components/shared/charts/TransactionCharts/index.tsx +++ b/x-pack/plugins/apm/public/components/shared/charts/TransactionCharts/index.tsx @@ -26,8 +26,6 @@ import { IUrlParams } from '../../../../context/UrlParamsContext/types'; import { ITransactionChartData } from '../../../../selectors/chartSelectors'; import { asDecimal, tpmUnit } from '../../../../utils/formatters'; import { isValidCoordinateValue } from '../../../../utils/isValidCoordinateValue'; -import { BrowserLineChart } from './BrowserLineChart'; -import { DurationByCountryMap } from './DurationByCountryMap'; import { ErroneousTransactionsRateChart } from '../ErroneousTransactionsRateChart'; import { TransactionBreakdown } from '../../TransactionBreakdown'; import { @@ -120,24 +118,6 @@ export function TransactionCharts({ - - {transactionType === TRANSACTION_PAGE_LOAD && ( - <> - - - - - - - - - - - - - - - )} ); } diff --git a/x-pack/plugins/apm/public/hooks/useAvgDurationByBrowser.test.tsx b/x-pack/plugins/apm/public/hooks/useAvgDurationByBrowser.test.tsx deleted file mode 100644 index bb947e307437e..0000000000000 --- a/x-pack/plugins/apm/public/hooks/useAvgDurationByBrowser.test.tsx +++ /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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { renderHook } from '@testing-library/react-hooks'; -import theme from '@elastic/eui/dist/eui_theme_light.json'; -import * as useFetcherModule from './useFetcher'; -import { useAvgDurationByBrowser } from './useAvgDurationByBrowser'; -import React, { ReactNode } from 'react'; -import { MemoryRouter } from 'react-router-dom'; - -function Wrapper({ children }: { children?: ReactNode }) { - return {children}; -} - -describe('useAvgDurationByBrowser', () => { - it('returns data', () => { - const data = [ - { title: 'Other', data: [{ x: 1572530100000, y: 130010.8947368421 }] }, - ]; - jest.spyOn(useFetcherModule, 'useFetcher').mockReturnValueOnce({ - data, - refetch: () => {}, - status: 'success' as useFetcherModule.FETCH_STATUS, - }); - const { result } = renderHook(() => useAvgDurationByBrowser(), { - wrapper: Wrapper, - }); - - expect(result.current.data).toEqual([ - { - color: theme.euiColorVis0, - data: [{ x: 1572530100000, y: 130010.8947368421 }], - title: 'Other', - type: 'linemark', - }, - ]); - }); -}); diff --git a/x-pack/plugins/apm/public/hooks/useAvgDurationByBrowser.ts b/x-pack/plugins/apm/public/hooks/useAvgDurationByBrowser.ts deleted file mode 100644 index 78dc4210711ef..0000000000000 --- a/x-pack/plugins/apm/public/hooks/useAvgDurationByBrowser.ts +++ /dev/null @@ -1,63 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import theme from '@elastic/eui/dist/eui_theme_light.json'; -import { useParams } from 'react-router-dom'; -import { getVizColorForIndex } from '../../common/viz_colors'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { AvgDurationByBrowserAPIResponse } from '../../server/lib/transactions/avg_duration_by_browser'; -import { TimeSeries } from '../../typings/timeseries'; -import { useFetcher } from './useFetcher'; -import { useUrlParams } from './useUrlParams'; - -function toTimeSeries(data?: AvgDurationByBrowserAPIResponse): TimeSeries[] { - if (!data) { - return []; - } - - return data.map((item, index) => { - return { - ...item, - color: getVizColorForIndex(index, theme), - type: 'linemark', - }; - }); -} - -export function useAvgDurationByBrowser() { - const { serviceName } = useParams<{ serviceName?: string }>(); - const { - urlParams: { start, end, transactionName }, - uiFilters, - } = useUrlParams(); - - const { data, error, status } = useFetcher( - (callApmApi) => { - if (serviceName && start && end) { - return callApmApi({ - pathname: - '/api/apm/services/{serviceName}/transaction_groups/avg_duration_by_browser', - params: { - path: { serviceName }, - query: { - start, - end, - transactionName, - uiFilters: JSON.stringify(uiFilters), - }, - }, - }); - } - }, - [serviceName, start, end, transactionName, uiFilters] - ); - - return { - data: toTimeSeries(data), - status, - error, - }; -} diff --git a/x-pack/plugins/apm/public/hooks/useAvgDurationByCountry.ts b/x-pack/plugins/apm/public/hooks/useAvgDurationByCountry.ts deleted file mode 100644 index 983f949b72961..0000000000000 --- a/x-pack/plugins/apm/public/hooks/useAvgDurationByCountry.ts +++ /dev/null @@ -1,43 +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; - * you may not use this file except in compliance with the Elastic License. - */ -import { useParams } from 'react-router-dom'; -import { useFetcher } from './useFetcher'; -import { useUrlParams } from './useUrlParams'; - -export function useAvgDurationByCountry() { - const { serviceName } = useParams<{ serviceName?: string }>(); - const { - urlParams: { start, end, transactionName }, - uiFilters, - } = useUrlParams(); - - const { data = [], error, status } = useFetcher( - (callApmApi) => { - if (serviceName && start && end) { - return callApmApi({ - pathname: - '/api/apm/services/{serviceName}/transaction_groups/avg_duration_by_country', - params: { - path: { serviceName }, - query: { - start, - end, - uiFilters: JSON.stringify(uiFilters), - transactionName, - }, - }, - }); - } - }, - [serviceName, start, end, uiFilters, transactionName] - ); - - return { - data, - status, - error, - }; -} diff --git a/x-pack/plugins/apm/server/lib/transactions/avg_duration_by_browser/__fixtures__/responses.ts b/x-pack/plugins/apm/server/lib/transactions/avg_duration_by_browser/__fixtures__/responses.ts deleted file mode 100644 index 44878aa6c1f2e..0000000000000 --- a/x-pack/plugins/apm/server/lib/transactions/avg_duration_by_browser/__fixtures__/responses.ts +++ /dev/null @@ -1,76 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { Transaction } from '../../../../../typings/es_schemas/ui/transaction'; -import { APMBaseDoc } from '../../../../../typings/es_schemas/raw/apm_base_doc'; -import { - ESSearchResponse, - ESSearchRequest, -} from '../../../../../typings/elasticsearch'; - -export const response = ({ - hits: { - total: 599, - max_score: 0, - hits: [], - }, - took: 4, - timed_out: false, - _shards: { - total: 1, - successful: 1, - skipped: 0, - failed: 0, - }, - aggregations: { - user_agent_keys: { - buckets: [{ key: 'Firefox' }, { key: 'Other' }], - }, - browsers: { - buckets: [ - { - key_as_string: '2019-10-21T04:38:20.000-05:00', - key: 1571650700000, - doc_count: 0, - user_agent: { - doc_count_error_upper_bound: 0, - sum_other_doc_count: 0, - buckets: [], - }, - }, - { - key_as_string: '2019-10-21T04:40:00.000-05:00', - key: 1571650800000, - doc_count: 1, - user_agent: { - doc_count_error_upper_bound: 0, - sum_other_doc_count: 0, - buckets: [ - { - key: 'Other', - doc_count: 1, - avg_duration: { - value: 860425.0, - }, - }, - { - key: 'Firefox', - doc_count: 10, - avg_duration: { - value: 86425.1, - }, - }, - ], - }, - }, - ], - }, - }, -} as unknown) as ESSearchResponse< - APMBaseDoc | Transaction, - ESSearchRequest, - { restTotalHitsAsInt: false } ->; diff --git a/x-pack/plugins/apm/server/lib/transactions/avg_duration_by_browser/fetcher.test.ts b/x-pack/plugins/apm/server/lib/transactions/avg_duration_by_browser/fetcher.test.ts deleted file mode 100644 index aec124e4f4623..0000000000000 --- a/x-pack/plugins/apm/server/lib/transactions/avg_duration_by_browser/fetcher.test.ts +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { - Setup, - SetupTimeRange, - SetupUIFilters, -} from '../../helpers/setup_request'; -import { fetcher } from './fetcher'; - -describe('fetcher', () => { - it('performs a search', async () => { - const search = jest.fn(); - const setup = ({ - apmEventClient: { search }, - indices: {}, - uiFiltersES: [], - } as unknown) as Setup & SetupTimeRange & SetupUIFilters; - - await fetcher({ - serviceName: 'testServiceName', - setup, - searchAggregatedTransactions: false, - }); - - expect(search).toHaveBeenCalled(); - }); -}); diff --git a/x-pack/plugins/apm/server/lib/transactions/avg_duration_by_browser/fetcher.ts b/x-pack/plugins/apm/server/lib/transactions/avg_duration_by_browser/fetcher.ts deleted file mode 100644 index d40fcaaa02f60..0000000000000 --- a/x-pack/plugins/apm/server/lib/transactions/avg_duration_by_browser/fetcher.ts +++ /dev/null @@ -1,100 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { ESFilter } from '../../../../typings/elasticsearch'; -import { PromiseReturnType } from '../../../../../observability/typings/common'; -import { - SERVICE_NAME, - TRANSACTION_TYPE, - USER_AGENT_NAME, - TRANSACTION_NAME, -} from '../../../../common/elasticsearch_fieldnames'; -import { rangeFilter } from '../../../../common/utils/range_filter'; -import { getBucketSize } from '../../helpers/get_bucket_size'; -import { Options } from '.'; -import { TRANSACTION_PAGE_LOAD } from '../../../../common/transaction_types'; -import { - getDocumentTypeFilterForAggregatedTransactions, - getTransactionDurationFieldForAggregatedTransactions, - getProcessorEventForAggregatedTransactions, -} from '../../helpers/aggregated_transactions'; - -export type ESResponse = PromiseReturnType; - -export function fetcher(options: Options) { - const { end, apmEventClient, start, uiFiltersES } = options.setup; - const { - serviceName, - searchAggregatedTransactions, - transactionName, - } = options; - const { intervalString } = getBucketSize(start, end); - - const transactionNameFilter = transactionName - ? [{ term: { [TRANSACTION_NAME]: transactionName } }] - : []; - - const filter: ESFilter[] = [ - { term: { [SERVICE_NAME]: serviceName } }, - { term: { [TRANSACTION_TYPE]: TRANSACTION_PAGE_LOAD } }, - { range: rangeFilter(start, end) }, - ...getDocumentTypeFilterForAggregatedTransactions( - searchAggregatedTransactions - ), - ...uiFiltersES, - ...transactionNameFilter, - ]; - - const params = { - apm: { - events: [ - getProcessorEventForAggregatedTransactions( - searchAggregatedTransactions - ), - ], - }, - body: { - size: 0, - query: { bool: { filter } }, - aggs: { - user_agent_keys: { - terms: { - field: USER_AGENT_NAME, - }, - }, - browsers: { - date_histogram: { - extended_bounds: { - max: end, - min: start, - }, - field: '@timestamp', - fixed_interval: intervalString, - min_doc_count: 0, - }, - aggs: { - user_agent: { - terms: { - field: USER_AGENT_NAME, - }, - aggs: { - avg_duration: { - avg: { - field: getTransactionDurationFieldForAggregatedTransactions( - searchAggregatedTransactions - ), - }, - }, - }, - }, - }, - }, - }, - }, - }; - - return apmEventClient.search(params); -} diff --git a/x-pack/plugins/apm/server/lib/transactions/avg_duration_by_browser/index.test.ts b/x-pack/plugins/apm/server/lib/transactions/avg_duration_by_browser/index.test.ts deleted file mode 100644 index b8cea3a032268..0000000000000 --- a/x-pack/plugins/apm/server/lib/transactions/avg_duration_by_browser/index.test.ts +++ /dev/null @@ -1,33 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { - getTransactionAvgDurationByBrowser, - Options, - AvgDurationByBrowserAPIResponse, -} from '.'; -import * as transformerModule from './transformer'; -import * as fetcherModule from './fetcher'; -import { response } from './__fixtures__/responses'; - -describe('getAvgDurationByBrowser', () => { - it('returns a transformed response', async () => { - const transformer = jest - .spyOn(transformerModule, 'transformer') - .mockReturnValueOnce(({} as unknown) as AvgDurationByBrowserAPIResponse); - const search = () => {}; - const options = ({ - setup: { client: { search }, indices: {}, uiFiltersES: [] }, - } as unknown) as Options; - jest - .spyOn<{ fetcher: any }, 'fetcher'>(fetcherModule, 'fetcher') - .mockResolvedValueOnce(response); - - await getTransactionAvgDurationByBrowser(options); - - expect(transformer).toHaveBeenCalledWith({ response }); - }); -}); diff --git a/x-pack/plugins/apm/server/lib/transactions/avg_duration_by_browser/index.ts b/x-pack/plugins/apm/server/lib/transactions/avg_duration_by_browser/index.ts deleted file mode 100644 index 2c259edaa26ab..0000000000000 --- a/x-pack/plugins/apm/server/lib/transactions/avg_duration_by_browser/index.ts +++ /dev/null @@ -1,30 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { Coordinate } from '../../../../typings/timeseries'; -import { - Setup, - SetupTimeRange, - SetupUIFilters, -} from '../../helpers/setup_request'; -import { fetcher } from './fetcher'; -import { transformer } from './transformer'; - -export interface Options { - serviceName: string; - setup: Setup & SetupTimeRange & SetupUIFilters; - searchAggregatedTransactions: boolean; - transactionName?: string; -} - -export type AvgDurationByBrowserAPIResponse = Array<{ - data: Coordinate[]; - title: string; -}>; - -export async function getTransactionAvgDurationByBrowser(options: Options) { - return transformer({ response: await fetcher(options) }); -} diff --git a/x-pack/plugins/apm/server/lib/transactions/avg_duration_by_browser/transformer.test.ts b/x-pack/plugins/apm/server/lib/transactions/avg_duration_by_browser/transformer.test.ts deleted file mode 100644 index 91ff2698ea554..0000000000000 --- a/x-pack/plugins/apm/server/lib/transactions/avg_duration_by_browser/transformer.test.ts +++ /dev/null @@ -1,29 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { transformer } from './transformer'; -import { response } from './__fixtures__/responses'; - -describe('transformer', () => { - it('transforms', () => { - expect(transformer({ response })).toEqual([ - { - data: [ - { x: 1571650700000, y: undefined }, - { x: 1571650800000, y: 86425.1 }, - ], - title: 'Firefox', - }, - { - data: [ - { x: 1571650700000, y: undefined }, - { x: 1571650800000, y: 860425.0 }, - ], - title: 'Other', - }, - ]); - }); -}); diff --git a/x-pack/plugins/apm/server/lib/transactions/avg_duration_by_browser/transformer.ts b/x-pack/plugins/apm/server/lib/transactions/avg_duration_by_browser/transformer.ts deleted file mode 100644 index 5234af8cede66..0000000000000 --- a/x-pack/plugins/apm/server/lib/transactions/avg_duration_by_browser/transformer.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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { ESResponse } from './fetcher'; -import { AvgDurationByBrowserAPIResponse } from '.'; -import { Coordinate } from '../../../../typings/timeseries'; - -export function transformer({ - response, -}: { - response: ESResponse; -}): AvgDurationByBrowserAPIResponse { - const allUserAgentKeys = new Set( - (response.aggregations?.user_agent_keys?.buckets ?? []).map(({ key }) => - key.toString() - ) - ); - const buckets = response.aggregations?.browsers?.buckets ?? []; - - const series = buckets.reduce<{ [key: string]: Coordinate[] }>( - (acc, next) => { - const userAgentBuckets = next.user_agent?.buckets ?? []; - const x = next.key; - const seenUserAgentKeys = new Set(); - - userAgentBuckets.map((userAgentBucket) => { - const key = userAgentBucket.key; - const y = userAgentBucket.avg_duration?.value; - - seenUserAgentKeys.add(key.toString()); - acc[key] = (acc[key] || []).concat({ x, y }); - }); - - const emptyUserAgents = new Set( - [...allUserAgentKeys].filter((key) => !seenUserAgentKeys.has(key)) - ); - - // If no user agent requests exist for this bucked, fill in the data with - // undefined - [...emptyUserAgents].map((key) => { - acc[key] = (acc[key] || []).concat({ x, y: undefined }); - }); - - return acc; - }, - {} - ); - - return Object.entries(series).map(([title, data]) => ({ title, data })); -} diff --git a/x-pack/plugins/apm/server/lib/transactions/avg_duration_by_country/index.ts b/x-pack/plugins/apm/server/lib/transactions/avg_duration_by_country/index.ts deleted file mode 100644 index bc1e0af051ace..0000000000000 --- a/x-pack/plugins/apm/server/lib/transactions/avg_duration_by_country/index.ts +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { - CLIENT_GEO_COUNTRY_ISO_CODE, - SERVICE_NAME, - TRANSACTION_TYPE, - TRANSACTION_NAME, -} from '../../../../common/elasticsearch_fieldnames'; -import { - Setup, - SetupTimeRange, - SetupUIFilters, -} from '../../helpers/setup_request'; -import { rangeFilter } from '../../../../common/utils/range_filter'; -import { TRANSACTION_PAGE_LOAD } from '../../../../common/transaction_types'; -import { - getProcessorEventForAggregatedTransactions, - getTransactionDurationFieldForAggregatedTransactions, - getDocumentTypeFilterForAggregatedTransactions, -} from '../../helpers/aggregated_transactions'; - -export async function getTransactionAvgDurationByCountry({ - setup, - serviceName, - transactionName, - searchAggregatedTransactions, -}: { - setup: Setup & SetupTimeRange & SetupUIFilters; - serviceName: string; - transactionName?: string; - searchAggregatedTransactions: boolean; -}) { - const { uiFiltersES, apmEventClient, start, end } = setup; - const transactionNameFilter = transactionName - ? [{ term: { [TRANSACTION_NAME]: transactionName } }] - : []; - const params = { - apm: { - events: [ - getProcessorEventForAggregatedTransactions( - searchAggregatedTransactions - ), - ], - }, - body: { - size: 0, - query: { - bool: { - filter: [ - { term: { [SERVICE_NAME]: serviceName } }, - ...transactionNameFilter, - { term: { [TRANSACTION_TYPE]: TRANSACTION_PAGE_LOAD } }, - { exists: { field: CLIENT_GEO_COUNTRY_ISO_CODE } }, - { range: rangeFilter(start, end) }, - ...uiFiltersES, - ...getDocumentTypeFilterForAggregatedTransactions( - searchAggregatedTransactions - ), - ], - }, - }, - aggs: { - country_code: { - terms: { - field: CLIENT_GEO_COUNTRY_ISO_CODE, - size: 500, - }, - aggs: { - count: { - value_count: { - field: getTransactionDurationFieldForAggregatedTransactions( - searchAggregatedTransactions - ), - }, - }, - avg_duration: { - avg: { - field: getTransactionDurationFieldForAggregatedTransactions( - searchAggregatedTransactions - ), - }, - }, - }, - }, - }, - }, - }; - - const resp = await apmEventClient.search(params); - - if (!resp.aggregations) { - return []; - } - - const buckets = resp.aggregations.country_code.buckets; - const avgDurationsByCountry = buckets.map( - ({ key, count, avg_duration: { value } }) => ({ - key: key as string, - docCount: count.value, - value: value === null ? 0 : value, - }) - ); - - return avgDurationsByCountry; -} diff --git a/x-pack/plugins/apm/server/routes/create_apm_api.ts b/x-pack/plugins/apm/server/routes/create_apm_api.ts index 1230e8aa05c9f..7d9a9ccc167e0 100644 --- a/x-pack/plugins/apm/server/routes/create_apm_api.ts +++ b/x-pack/plugins/apm/server/routes/create_apm_api.ts @@ -46,8 +46,6 @@ import { transactionGroupsChartsRoute, transactionGroupsDistributionRoute, transactionGroupsRoute, - transactionGroupsAvgDurationByCountry, - transactionGroupsAvgDurationByBrowser, transactionSampleForGroupRoute, transactionGroupsErrorRateRoute, } from './transaction_groups'; @@ -139,8 +137,6 @@ const createApmApi = () => { .add(transactionGroupsChartsRoute) .add(transactionGroupsDistributionRoute) .add(transactionGroupsRoute) - .add(transactionGroupsAvgDurationByBrowser) - .add(transactionGroupsAvgDurationByCountry) .add(transactionSampleForGroupRoute) .add(transactionGroupsErrorRateRoute) diff --git a/x-pack/plugins/apm/server/routes/transaction_groups.ts b/x-pack/plugins/apm/server/routes/transaction_groups.ts index 3c512c1fe5278..888c4363f77b9 100644 --- a/x-pack/plugins/apm/server/routes/transaction_groups.ts +++ b/x-pack/plugins/apm/server/routes/transaction_groups.ts @@ -12,8 +12,6 @@ import { getTransactionBreakdown } from '../lib/transactions/breakdown'; import { getTransactionGroupList } from '../lib/transaction_groups'; import { createRoute } from './create_route'; import { uiFiltersRt, rangeRt } from './default_api_types'; -import { getTransactionAvgDurationByBrowser } from '../lib/transactions/avg_duration_by_browser'; -import { getTransactionAvgDurationByCountry } from '../lib/transactions/avg_duration_by_country'; import { getTransactionSampleForGroup } from '../lib/transaction_groups/get_transaction_sample_for_group'; import { getSearchAggregatedTransactions } from '../lib/helpers/aggregated_transactions'; import { getErrorRate } from '../lib/transaction_groups/get_error_rate'; @@ -168,68 +166,6 @@ export const transactionGroupsBreakdownRoute = createRoute(() => ({ }, })); -export const transactionGroupsAvgDurationByBrowser = createRoute(() => ({ - path: `/api/apm/services/{serviceName}/transaction_groups/avg_duration_by_browser`, - params: { - path: t.type({ - serviceName: t.string, - }), - query: t.intersection([ - t.partial({ - transactionName: t.string, - }), - uiFiltersRt, - rangeRt, - ]), - }, - handler: async ({ context, request }) => { - const setup = await setupRequest(context, request); - const { serviceName } = context.params.path; - const { transactionName } = context.params.query; - - const searchAggregatedTransactions = await getSearchAggregatedTransactions( - setup - ); - - return getTransactionAvgDurationByBrowser({ - serviceName, - setup, - searchAggregatedTransactions, - transactionName, - }); - }, -})); - -export const transactionGroupsAvgDurationByCountry = createRoute(() => ({ - path: `/api/apm/services/{serviceName}/transaction_groups/avg_duration_by_country`, - params: { - path: t.type({ - serviceName: t.string, - }), - query: t.intersection([ - uiFiltersRt, - rangeRt, - t.partial({ transactionName: t.string }), - ]), - }, - handler: async ({ context, request }) => { - const setup = await setupRequest(context, request); - const { serviceName } = context.params.path; - const { transactionName } = context.params.query; - - const searchAggregatedTransactions = await getSearchAggregatedTransactions( - setup - ); - - return getTransactionAvgDurationByCountry({ - serviceName, - transactionName, - setup, - searchAggregatedTransactions, - }); - }, -})); - export const transactionSampleForGroupRoute = createRoute(() => ({ path: `/api/apm/transaction_sample`, params: { diff --git a/x-pack/plugins/ingest_manager/server/routes/agent/acks_handlers.ts b/x-pack/plugins/ingest_manager/server/routes/agent/acks_handlers.ts index b0439b30e8973..fb320b01dea97 100644 --- a/x-pack/plugins/ingest_manager/server/routes/agent/acks_handlers.ts +++ b/x-pack/plugins/ingest_manager/server/routes/agent/acks_handlers.ts @@ -10,6 +10,7 @@ import { RequestHandler } from 'kibana/server'; import { AcksService } from '../../services/agents'; import { AgentEvent } from '../../../common/types/models'; import { PostAgentAcksRequest, PostAgentAcksResponse } from '../../../common/types/rest_spec'; +import { defaultIngestErrorHandler } from '../../errors'; export const postAgentAcksHandlerBuilder = function ( ackService: AcksService @@ -43,18 +44,8 @@ export const postAgentAcksHandlerBuilder = function ( }; return response.ok({ body }); - } catch (e) { - if (e.isBoom) { - return response.customError({ - statusCode: e.output.statusCode, - body: { message: e.message }, - }); - } - - return response.customError({ - statusCode: 500, - body: { message: e.message }, - }); + } catch (error) { + return defaultIngestErrorHandler({ error, response }); } }; }; diff --git a/x-pack/plugins/ingest_manager/server/routes/agent/actions_handlers.ts b/x-pack/plugins/ingest_manager/server/routes/agent/actions_handlers.ts index 12a0956b79155..64a7795cc9dac 100644 --- a/x-pack/plugins/ingest_manager/server/routes/agent/actions_handlers.ts +++ b/x-pack/plugins/ingest_manager/server/routes/agent/actions_handlers.ts @@ -11,6 +11,7 @@ import { TypeOf } from '@kbn/config-schema'; import { PostNewAgentActionRequestSchema } from '../../types/rest_spec'; import { ActionsService } from '../../services/agents'; import { PostNewAgentActionResponse } from '../../../common/types/rest_spec'; +import { defaultIngestErrorHandler } from '../../errors'; export const postNewAgentActionHandlerBuilder = function ( actionsService: ActionsService @@ -38,18 +39,8 @@ export const postNewAgentActionHandlerBuilder = function ( }; return response.ok({ body }); - } catch (e) { - if (e.isBoom) { - return response.customError({ - statusCode: e.output.statusCode, - body: { message: e.message }, - }); - } - - return response.customError({ - statusCode: 500, - body: { message: e.message }, - }); + } catch (error) { + return defaultIngestErrorHandler({ error, response }); } }; }; diff --git a/x-pack/plugins/ingest_manager/server/routes/agent/handlers.ts b/x-pack/plugins/ingest_manager/server/routes/agent/handlers.ts index b9789b770eb2e..2ebb7a0667aab 100644 --- a/x-pack/plugins/ingest_manager/server/routes/agent/handlers.ts +++ b/x-pack/plugins/ingest_manager/server/routes/agent/handlers.ts @@ -47,17 +47,14 @@ export const getAgentHandler: RequestHandler= 500) { - logger.error(err); - } - - return response.customError({ - statusCode: err.output.statusCode, - body: { message: err.output.payload.message }, - }); - } - - logger.error(err); - - return response.customError({ - statusCode: 500, - body: { message: err.message }, - }); + } catch (error) { + return defaultIngestErrorHandler({ error, response }); } }; @@ -247,18 +221,8 @@ export const postAgentEnrollHandler: RequestHandler< }; return response.ok({ body }); - } catch (e) { - if (e.isBoom) { - return response.customError({ - statusCode: e.output.statusCode, - body: { message: e.message }, - }); - } - - return response.customError({ - statusCode: 500, - body: { message: e.message }, - }); + } catch (error) { + return defaultIngestErrorHandler({ error, response }); } }; @@ -301,11 +265,8 @@ export const putAgentsReassignHandler: RequestHandler< const body: PutAgentReassignResponse = {}; return response.ok({ body }); - } catch (e) { - return response.customError({ - statusCode: 500, - body: { message: e.message }, - }); + } catch (error) { + return defaultIngestErrorHandler({ error, response }); } }; @@ -324,10 +285,7 @@ export const getAgentStatusForAgentPolicyHandler: RequestHandler< const body: GetAgentStatusResponse = { results }; return response.ok({ body }); - } catch (e) { - return response.customError({ - statusCode: 500, - body: { message: e.message }, - }); + } catch (error) { + return defaultIngestErrorHandler({ error, response }); } }; diff --git a/x-pack/plugins/ingest_manager/server/routes/agent/unenroll_handler.ts b/x-pack/plugins/ingest_manager/server/routes/agent/unenroll_handler.ts index 5df695d248f5b..fa200e912d625 100644 --- a/x-pack/plugins/ingest_manager/server/routes/agent/unenroll_handler.ts +++ b/x-pack/plugins/ingest_manager/server/routes/agent/unenroll_handler.ts @@ -9,6 +9,7 @@ import { TypeOf } from '@kbn/config-schema'; import { PostAgentUnenrollResponse } from '../../../common/types'; import { PostAgentUnenrollRequestSchema } from '../../types'; import * as AgentService from '../../services/agents'; +import { defaultIngestErrorHandler } from '../../errors'; export const postAgentsUnenrollHandler: RequestHandler< TypeOf, @@ -25,10 +26,7 @@ export const postAgentsUnenrollHandler: RequestHandler< const body: PostAgentUnenrollResponse = {}; return response.ok({ body }); - } catch (e) { - return response.customError({ - statusCode: 500, - body: { message: e.message }, - }); + } catch (error) { + return defaultIngestErrorHandler({ error, response }); } }; diff --git a/x-pack/plugins/ingest_manager/server/routes/agent_policy/handlers.ts b/x-pack/plugins/ingest_manager/server/routes/agent_policy/handlers.ts index 7eb3df2346106..311b3bbf7f13b 100644 --- a/x-pack/plugins/ingest_manager/server/routes/agent_policy/handlers.ts +++ b/x-pack/plugins/ingest_manager/server/routes/agent_policy/handlers.ts @@ -32,6 +32,7 @@ import { DeleteAgentPolicyResponse, GetFullAgentPolicyResponse, } from '../../../common'; +import { defaultIngestErrorHandler } from '../../errors'; export const getAgentPoliciesHandler: RequestHandler< undefined, @@ -64,11 +65,8 @@ export const getAgentPoliciesHandler: RequestHandler< ); return response.ok({ body }); - } catch (e) { - return response.customError({ - statusCode: 500, - body: { message: e.message }, - }); + } catch (error) { + return defaultIngestErrorHandler({ error, response }); } }; @@ -91,11 +89,8 @@ export const getOneAgentPolicyHandler: RequestHandler { const soClient = context.core.savedObjects.client; @@ -23,11 +24,8 @@ export const getOutputsHandler: RequestHandler = async (context, request, respon }; return response.ok({ body }); - } catch (e) { - return response.customError({ - statusCode: 500, - body: { message: e.message }, - }); + } catch (error) { + return defaultIngestErrorHandler({ error, response }); } }; @@ -43,17 +41,14 @@ export const getOneOuputHandler: RequestHandler { @@ -19,17 +19,14 @@ export const getSettingsHandler: RequestHandler = async (context, request, respo item: settings, }; return response.ok({ body }); - } catch (e) { - if (e.isBoom && e.output.statusCode === 404) { + } catch (error) { + if (error.isBoom && error.output.statusCode === 404) { return response.notFound({ body: { message: `Setings not found` }, }); } - return response.customError({ - statusCode: 500, - body: { message: e.message }, - }); + return defaultIngestErrorHandler({ error, response }); } }; @@ -49,17 +46,14 @@ export const putSettingsHandler: RequestHandler< item: settings, }; return response.ok({ body }); - } catch (e) { - if (e.isBoom && e.output.statusCode === 404) { + } catch (error) { + if (error.isBoom && error.output.statusCode === 404) { return response.notFound({ body: { message: `Setings not found` }, }); } - return response.customError({ - statusCode: 500, - body: { message: e.message }, - }); + return defaultIngestErrorHandler({ error, response }); } }; diff --git a/x-pack/plugins/security_solution/cypress/integration/alerts.spec.ts b/x-pack/plugins/security_solution/cypress/integration/alerts.spec.ts index 3de57b085a9c6..fdfa042e8fcc9 100644 --- a/x-pack/plugins/security_solution/cypress/integration/alerts.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/alerts.spec.ts @@ -30,7 +30,8 @@ import { loginAndWaitForPage } from '../tasks/login'; import { DETECTIONS_URL } from '../urls/navigation'; -describe('Alerts', () => { +// FLAKY: https://github.com/elastic/kibana/issues/77957 +describe.skip('Alerts', () => { context('Closing alerts', () => { beforeEach(() => { esArchiverLoad('alerts'); diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index c6aca5ed4e369..781f351d7d241 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -499,6 +499,9 @@ "core.ui.securityNavList.label": "セキュリティ", "core.ui.welcomeErrorMessage": "Elasticが正常に読み込まれませんでした。詳細はサーバーアウトプットを確認してください。", "core.ui.welcomeMessage": "Elasticの読み込み中", + "core.status.greenTitle": "緑", + "core.status.redTitle": "赤", + "core.status.yellowTitle": "黄色", "dashboard.actions.toggleExpandPanelMenuItem.expandedDisplayName": "最小化", "dashboard.actions.toggleExpandPanelMenuItem.notExpandedDisplayName": "全画面", "dashboard.addExistingVisualizationLinkText": "既存のユーザーを追加", @@ -2926,9 +2929,6 @@ "savedObjectsManagement.view.viewItemButtonLabel": "{title}を表示", "savedObjectsManagement.view.viewItemTitle": "{title}を表示", "usageCollection.stats.notReadyMessage": "まだ統計が準備できていません。後程再試行してください", - "core.status.greenTitle": "緑", - "core.status.redTitle": "赤", - "core.status.yellowTitle": "黄色", "share.advancedSettings.csv.quoteValuesText": "csvエクスポートに値を引用するかどうかです", "share.advancedSettings.csv.quoteValuesTitle": "CSVの値を引用", "share.advancedSettings.csv.separatorText": "エクスポートされた値をこの文字列で区切ります", @@ -4756,10 +4756,6 @@ "xpack.apm.metadataTable.section.urlLabel": "URL", "xpack.apm.metadataTable.section.userAgentLabel": "ユーザーエージェント", "xpack.apm.metadataTable.section.userLabel": "ユーザー", - "xpack.apm.metrics.durationByCountryMap.avgPageLoadByCountryLabel": "国ごとの平均ページ読み込み時間の分布", - "xpack.apm.metrics.durationByCountryMap.RegionMapChart.ToolTip.avgPageLoadDuration": "平均ページ読み込み時間:", - "xpack.apm.metrics.durationByCountryMap.RegionMapChart.ToolTip.countPageLoads": "{docCount} ページの読み込み", - "xpack.apm.metrics.pageLoadCharts.avgPageLoadByBrowser": "ブラウザごとの平均ページ読み込み時間の分布", "xpack.apm.metrics.plot.noDataLabel": "この時間範囲のデータがありません。", "xpack.apm.metrics.transactionChart.machineLearningLabel": "機械学習:", "xpack.apm.metrics.transactionChart.machineLearningTooltip": "平均期間の周りのストリームには予測バウンドが表示されます。異常スコアが>= 75の場合、注釈が表示されます。", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index bda88b80bbd9d..fd749ba4709ec 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -499,6 +499,9 @@ "core.ui.securityNavList.label": "安全", "core.ui.welcomeErrorMessage": "Elastic 未正确加载。检查服务器输出以了解详情。", "core.ui.welcomeMessage": "正在加载 Elastic", + "core.status.greenTitle": "绿", + "core.status.redTitle": "红", + "core.status.yellowTitle": "黄", "dashboard.actions.toggleExpandPanelMenuItem.expandedDisplayName": "最小化", "dashboard.actions.toggleExpandPanelMenuItem.notExpandedDisplayName": "全屏", "dashboard.addExistingVisualizationLinkText": "将现有", @@ -2927,9 +2930,6 @@ "savedObjectsManagement.view.viewItemButtonLabel": "查看“{title}”", "savedObjectsManagement.view.viewItemTitle": "查看“{title}”", "usageCollection.stats.notReadyMessage": "统计尚未就绪。请稍后重试", - "core.status.greenTitle": "绿", - "core.status.redTitle": "红", - "core.status.yellowTitle": "黄", "share.advancedSettings.csv.quoteValuesText": "在 CSV 导出中是否应使用引号引起值?", "share.advancedSettings.csv.quoteValuesTitle": "使用引号引起 CSV 值", "share.advancedSettings.csv.separatorText": "使用此字符串分隔导出的值", @@ -4758,10 +4758,6 @@ "xpack.apm.metadataTable.section.urlLabel": "URL", "xpack.apm.metadataTable.section.userAgentLabel": "用户代理", "xpack.apm.metadataTable.section.userLabel": "用户", - "xpack.apm.metrics.durationByCountryMap.avgPageLoadByCountryLabel": "页面加载平均时长分布(按国家/地区)", - "xpack.apm.metrics.durationByCountryMap.RegionMapChart.ToolTip.avgPageLoadDuration": "页面加载平均时长:", - "xpack.apm.metrics.durationByCountryMap.RegionMapChart.ToolTip.countPageLoads": "{docCount} 个页面加载", - "xpack.apm.metrics.pageLoadCharts.avgPageLoadByBrowser": "平均页面加载持续时间分布 - 按浏览器", "xpack.apm.metrics.plot.noDataLabel": "此时间范围内没有数据。", "xpack.apm.metrics.transactionChart.machineLearningLabel": "Machine Learning", "xpack.apm.metrics.transactionChart.machineLearningTooltip": "环绕平均持续时间的流显示预期边界。对 ≥ 75 的异常分数显示标注。", diff --git a/x-pack/test/accessibility/apps/dashboard_edit_panel.ts b/x-pack/test/accessibility/apps/dashboard_edit_panel.ts new file mode 100644 index 0000000000000..9c0827e4128cf --- /dev/null +++ b/x-pack/test/accessibility/apps/dashboard_edit_panel.ts @@ -0,0 +1,118 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { FtrProviderContext } from '../ftr_provider_context'; + +export default function ({ getService, getPageObjects }: FtrProviderContext) { + const { dashboard } = getPageObjects(['dashboard']); + const a11y = getService('a11y'); + const dashboardPanelActions = getService('dashboardPanelActions'); + const testSubjects = getService('testSubjects'); + const esArchiver = getService('esArchiver'); + const drilldowns = getService('dashboardDrilldownsManage'); + const kibanaServer = getService('kibanaServer'); + const PageObjects = getPageObjects(['security', 'common']); + const toasts = getService('toasts'); + + describe('Dashboard Edit Panel', () => { + before(async () => { + await esArchiver.load('dashboard/drilldowns'); + await esArchiver.loadIfNeeded('logstash_functional'); + await kibanaServer.uiSettings.replace({ defaultIndex: 'logstash-*' }); + await PageObjects.common.navigateToApp('dashboard'); + await dashboard.loadSavedDashboard(drilldowns.DASHBOARD_WITH_PIE_CHART_NAME); + await testSubjects.click('dashboardEditMode'); + }); + + after(async () => { + await esArchiver.unload('dashboard/drilldowns'); + }); + + // embeddable edit panel + it(' A11y test on dashboard edit panel menu options', async () => { + await testSubjects.click('embeddablePanelToggleMenuIcon'); + await a11y.testAppSnapshot(); + }); + + // clone panel + it(' A11y test on dashboard embeddable clone panel', async () => { + await testSubjects.click('embeddablePanelAction-clonePanel'); + await a11y.testAppSnapshot(); + await toasts.dismissAllToasts(); + await dashboardPanelActions.removePanelByTitle('Visualization PieChart (copy)'); + }); + + // edit dashboard title + it(' A11y test on dashboard embeddable edit dashboard title', async () => { + await testSubjects.click('embeddablePanelToggleMenuIcon'); + await testSubjects.click('embeddablePanelAction-ACTION_CUSTOMIZE_PANEL'); + await a11y.testAppSnapshot(); + await testSubjects.click('customizePanelHideTitle'); + await a11y.testAppSnapshot(); + await testSubjects.click('saveNewTitleButton'); + }); + + // https://github.com/elastic/kibana/issues/77931 + it.skip('A11y test for edit visualization and save', async () => { + await testSubjects.click('embeddablePanelToggleMenuIcon'); + await testSubjects.click('embeddablePanelAction-editPanel'); + await testSubjects.click('visualizesaveAndReturnButton'); + await a11y.testAppSnapshot(); + }); + + // https://github.com/elastic/kibana/issues/77422 + it.skip('A11y test on dashboard embeddable custom time range', async () => { + await testSubjects.click('embeddablePanelToggleMenuIcon'); + await testSubjects.click('embeddablePanelAction-CUSTOM_TIME_RANGE'); + await a11y.testAppSnapshot(); + }); + + // inspector panel + it('A11y test on dashboard embeddable open inspector', async () => { + await testSubjects.click('embeddablePanelToggleMenuIcon'); + await testSubjects.click('embeddablePanelAction-openInspector'); + await a11y.testAppSnapshot(); + await testSubjects.click('euiFlyoutCloseButton'); + }); + + // create drilldown + it('A11y test on dashboard embeddable open flyout and drilldown', async () => { + await testSubjects.click('embeddablePanelToggleMenuIcon'); + await testSubjects.click('embeddablePanelAction-OPEN_FLYOUT_ADD_DRILLDOWN'); + await a11y.testAppSnapshot(); + await testSubjects.click('flyoutCloseButton'); + }); + + // fullscreen + it('A11y test on dashboard embeddable fullscreen', async () => { + await testSubjects.click('embeddablePanelToggleMenuIcon'); + await testSubjects.click('embeddablePanelAction-togglePanel'); + await a11y.testAppSnapshot(); + }); + + // minimize fullscreen panel + it('A11y test on dashboard embeddable fullscreen minimize ', async () => { + await testSubjects.click('embeddablePanelToggleMenuIcon'); + await testSubjects.click('embeddablePanelAction-togglePanel'); + await a11y.testAppSnapshot(); + }); + + // replace panel + it('A11y test on dashboard embeddable replace panel', async () => { + await testSubjects.click('embeddablePanelToggleMenuIcon'); + await testSubjects.click('embeddablePanelAction-replacePanel'); + await a11y.testAppSnapshot(); + await testSubjects.click('euiFlyoutCloseButton'); + }); + + // delete from dashboard + it('A11y test on dashboard embeddable delete panel', async () => { + await testSubjects.click('embeddablePanelToggleMenuIcon'); + await testSubjects.click('embeddablePanelAction-deletePanel'); + await a11y.testAppSnapshot(); + }); + }); +} diff --git a/x-pack/test/accessibility/config.ts b/x-pack/test/accessibility/config.ts index bae7b688fd28c..9382a7186db54 100644 --- a/x-pack/test/accessibility/config.ts +++ b/x-pack/test/accessibility/config.ts @@ -21,6 +21,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { require.resolve('./apps/search_profiler'), require.resolve('./apps/uptime'), require.resolve('./apps/spaces'), + require.resolve('./apps/dashboard_edit_panel'), ], pageObjects, services, diff --git a/x-pack/test/apm_api_integration/basic/tests/index.ts b/x-pack/test/apm_api_integration/basic/tests/index.ts index 8aa509b0899ce..9e1cb1f5872f1 100644 --- a/x-pack/test/apm_api_integration/basic/tests/index.ts +++ b/x-pack/test/apm_api_integration/basic/tests/index.ts @@ -45,7 +45,6 @@ export default function apmApiIntegrationTests({ loadTestFile }: FtrProviderCont loadTestFile(require.resolve('./transaction_groups/transaction_charts')); loadTestFile(require.resolve('./transaction_groups/error_rate')); loadTestFile(require.resolve('./transaction_groups/breakdown')); - loadTestFile(require.resolve('./transaction_groups/avg_duration_by_browser')); }); describe('Observability overview', function () { diff --git a/x-pack/test/apm_api_integration/basic/tests/transaction_groups/__snapshots__/avg_duration_by_browser.snap b/x-pack/test/apm_api_integration/basic/tests/transaction_groups/__snapshots__/avg_duration_by_browser.snap deleted file mode 100644 index ab7b71cdf9e53..0000000000000 --- a/x-pack/test/apm_api_integration/basic/tests/transaction_groups/__snapshots__/avg_duration_by_browser.snap +++ /dev/null @@ -1,438 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Average duration by browser when data is loaded returns the average duration by browser 1`] = ` -Array [ - Object { - "data": Array [ - Object { - "x": 1600159980000, - "y": 1131000, - }, - Object { - "x": 1600160010000, - "y": 617000, - }, - Object { - "x": 1600160040000, - }, - Object { - "x": 1600160070000, - "y": 1963000, - }, - Object { - "x": 1600160100000, - "y": 1190000, - }, - Object { - "x": 1600160130000, - "y": 1697000, - }, - Object { - "x": 1600160160000, - }, - Object { - "x": 1600160190000, - "y": 710000, - }, - Object { - "x": 1600160220000, - "y": 675250, - }, - Object { - "x": 1600160250000, - }, - Object { - "x": 1600160280000, - }, - Object { - "x": 1600160310000, - "y": 1763500, - }, - Object { - "x": 1600160340000, - "y": 539333.3333333334, - }, - Object { - "x": 1600160370000, - }, - Object { - "x": 1600160400000, - }, - Object { - "x": 1600160430000, - "y": 1650000, - }, - Object { - "x": 1600160460000, - "y": 781000, - }, - Object { - "x": 1600160490000, - }, - Object { - "x": 1600160520000, - }, - Object { - "x": 1600160550000, - "y": 1710000, - }, - Object { - "x": 1600160580000, - "y": 718000, - }, - Object { - "x": 1600160610000, - "y": 11912000, - }, - Object { - "x": 1600160640000, - }, - Object { - "x": 1600160670000, - "y": 885000, - }, - Object { - "x": 1600160700000, - "y": 1043000, - }, - Object { - "x": 1600160730000, - "y": 406000, - }, - Object { - "x": 1600160760000, - }, - Object { - "x": 1600160790000, - "y": 1296000, - }, - Object { - "x": 1600160820000, - "y": 570500, - }, - Object { - "x": 1600160850000, - }, - Object { - "x": 1600160880000, - }, - Object { - "x": 1600160910000, - "y": 1110000, - }, - Object { - "x": 1600160940000, - "y": 533500, - }, - Object { - "x": 1600160970000, - "y": 782500, - }, - Object { - "x": 1600161000000, - }, - Object { - "x": 1600161030000, - "y": 1200000, - }, - Object { - "x": 1600161060000, - "y": 522000, - }, - Object { - "x": 1600161090000, - }, - Object { - "x": 1600161120000, - }, - Object { - "x": 1600161150000, - "y": 1006000, - }, - Object { - "x": 1600161180000, - "y": 1203000, - }, - Object { - "x": 1600161210000, - }, - Object { - "x": 1600161240000, - }, - Object { - "x": 1600161270000, - "y": 1908000, - }, - Object { - "x": 1600161300000, - "y": 549000, - }, - Object { - "x": 1600161330000, - "y": 685000, - }, - Object { - "x": 1600161360000, - }, - Object { - "x": 1600161390000, - "y": 2055000, - }, - Object { - "x": 1600161420000, - "y": 699750, - }, - Object { - "x": 1600161450000, - }, - Object { - "x": 1600161480000, - }, - Object { - "x": 1600161510000, - "y": 1557000, - }, - Object { - "x": 1600161540000, - "y": 4993000, - }, - Object { - "x": 1600161570000, - }, - Object { - "x": 1600161600000, - }, - Object { - "x": 1600161630000, - "y": 898000, - }, - Object { - "x": 1600161660000, - "y": 4100500, - }, - Object { - "x": 1600161690000, - }, - Object { - "x": 1600161720000, - }, - Object { - "x": 1600161750000, - "y": 1305000, - }, - Object { - "x": 1600161780000, - }, - ], - "title": "Electron", - }, -] -`; - -exports[`Average duration by browser when data is loaded returns the average duration by browser filtering by transaction name 2`] = ` -Array [ - Object { - "data": Array [ - Object { - "x": 1600159980000, - }, - Object { - "x": 1600160010000, - }, - Object { - "x": 1600160040000, - }, - Object { - "x": 1600160070000, - "y": 1096000, - }, - Object { - "x": 1600160100000, - }, - Object { - "x": 1600160130000, - }, - Object { - "x": 1600160160000, - }, - Object { - "x": 1600160190000, - "y": 710000, - }, - Object { - "x": 1600160220000, - }, - Object { - "x": 1600160250000, - }, - Object { - "x": 1600160280000, - }, - Object { - "x": 1600160310000, - "y": 1108000, - }, - Object { - "x": 1600160340000, - }, - Object { - "x": 1600160370000, - }, - Object { - "x": 1600160400000, - }, - Object { - "x": 1600160430000, - "y": 1221000, - }, - Object { - "x": 1600160460000, - }, - Object { - "x": 1600160490000, - }, - Object { - "x": 1600160520000, - }, - Object { - "x": 1600160550000, - "y": 1325000, - }, - Object { - "x": 1600160580000, - }, - Object { - "x": 1600160610000, - }, - Object { - "x": 1600160640000, - }, - Object { - "x": 1600160670000, - "y": 885000, - }, - Object { - "x": 1600160700000, - }, - Object { - "x": 1600160730000, - }, - Object { - "x": 1600160760000, - }, - Object { - "x": 1600160790000, - "y": 1296000, - }, - Object { - "x": 1600160820000, - }, - Object { - "x": 1600160850000, - }, - Object { - "x": 1600160880000, - }, - Object { - "x": 1600160910000, - "y": 1110000, - }, - Object { - "x": 1600160940000, - }, - Object { - "x": 1600160970000, - }, - Object { - "x": 1600161000000, - }, - Object { - "x": 1600161030000, - "y": 1200000, - }, - Object { - "x": 1600161060000, - }, - Object { - "x": 1600161090000, - }, - Object { - "x": 1600161120000, - }, - Object { - "x": 1600161150000, - "y": 1006000, - }, - Object { - "x": 1600161180000, - }, - Object { - "x": 1600161210000, - }, - Object { - "x": 1600161240000, - }, - Object { - "x": 1600161270000, - "y": 1908000, - }, - Object { - "x": 1600161300000, - }, - Object { - "x": 1600161330000, - }, - Object { - "x": 1600161360000, - }, - Object { - "x": 1600161390000, - "y": 1420000, - }, - Object { - "x": 1600161420000, - }, - Object { - "x": 1600161450000, - }, - Object { - "x": 1600161480000, - }, - Object { - "x": 1600161510000, - "y": 1215000, - }, - Object { - "x": 1600161540000, - }, - Object { - "x": 1600161570000, - }, - Object { - "x": 1600161600000, - }, - Object { - "x": 1600161630000, - "y": 898000, - }, - Object { - "x": 1600161660000, - }, - Object { - "x": 1600161690000, - }, - Object { - "x": 1600161720000, - }, - Object { - "x": 1600161750000, - "y": 1305000, - }, - Object { - "x": 1600161780000, - }, - ], - "title": "Electron", - }, -] -`; diff --git a/x-pack/test/apm_api_integration/basic/tests/transaction_groups/avg_duration_by_browser.ts b/x-pack/test/apm_api_integration/basic/tests/transaction_groups/avg_duration_by_browser.ts deleted file mode 100644 index 087bf1f0655e6..0000000000000 --- a/x-pack/test/apm_api_integration/basic/tests/transaction_groups/avg_duration_by_browser.ts +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ -import expect from '@kbn/expect'; -import archives_metadata from '../../../common/archives_metadata'; -import { expectSnapshot } from '../../../common/match_snapshot'; -import { FtrProviderContext } from '../../../common/ftr_provider_context'; - -export default function ApiTest({ getService }: FtrProviderContext) { - const supertest = getService('supertest'); - const esArchiver = getService('esArchiver'); - - const archiveName = 'apm_8.0.0'; - const metadata = archives_metadata[archiveName]; - - const start = encodeURIComponent(metadata.start); - const end = encodeURIComponent(metadata.end); - const transactionName = '/products'; - const uiFilters = encodeURIComponent(JSON.stringify({})); - - describe('Average duration by browser', () => { - describe('when data is not loaded', () => { - it('handles the empty state', async () => { - const response = await supertest.get( - `/api/apm/services/client/transaction_groups/avg_duration_by_browser?start=${start}&end=${end}&uiFilters=${uiFilters}` - ); - expect(response.status).to.be(200); - expect(response.body).to.eql([]); - }); - }); - - describe('when data is loaded', () => { - before(() => esArchiver.load(archiveName)); - after(() => esArchiver.unload(archiveName)); - - it('returns the average duration by browser', async () => { - const response = await supertest.get( - `/api/apm/services/opbeans-rum/transaction_groups/avg_duration_by_browser?start=${start}&end=${end}&uiFilters=${uiFilters}` - ); - - expect(response.status).to.be(200); - - expect(response.body.length).to.be.greaterThan(0); - - expectSnapshot(response.body).toMatch(); - - expectSnapshot(response.body.length).toMatchInline(`1`); - }); - - it('returns the average duration by browser filtering by transaction name', async () => { - const response = await supertest.get( - `/api/apm/services/opbeans-rum/transaction_groups/avg_duration_by_browser?start=${start}&end=${end}&uiFilters=${uiFilters}&transactionName=${transactionName}` - ); - - expect(response.status).to.be(200); - - expect(response.body.length).to.be.greaterThan(0); - - expectSnapshot(response.body.length).toMatchInline(`1`); - - expectSnapshot(response.body).toMatch(); - }); - }); - }); -} diff --git a/x-pack/test/functional/apps/discover/error_handling.ts b/x-pack/test/functional/apps/discover/error_handling.ts new file mode 100644 index 0000000000000..515e5e293ae28 --- /dev/null +++ b/x-pack/test/functional/apps/discover/error_handling.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; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from '@kbn/expect'; +import { FtrProviderContext } from '../../ftr_provider_context'; + +export default function ({ getService, getPageObjects }: FtrProviderContext) { + const esArchiver = getService('esArchiver'); + const testSubjects = getService('testSubjects'); + const PageObjects = getPageObjects(['common', 'discover', 'timePicker']); + + describe('errors', function describeIndexTests() { + before(async function () { + await esArchiver.loadIfNeeded('logstash_functional'); + await esArchiver.load('invalid_scripted_field'); + await PageObjects.timePicker.setDefaultAbsoluteRangeViaUiSettings(); + await PageObjects.common.navigateToApp('discover'); + }); + + after(async function () { + await esArchiver.unload('invalid_scripted_field'); + }); + // this is the same test as in OSS but it catches different error message issue in different licences + describe('invalid scripted field error', () => { + it('is rendered', async () => { + const isFetchErrorVisible = await testSubjects.exists('discoverFetchError'); + expect(isFetchErrorVisible).to.be(true); + }); + }); + }); +} diff --git a/x-pack/test/functional/apps/discover/index.ts b/x-pack/test/functional/apps/discover/index.ts index 323b728e16454..759225d80fa20 100644 --- a/x-pack/test/functional/apps/discover/index.ts +++ b/x-pack/test/functional/apps/discover/index.ts @@ -13,5 +13,6 @@ export default function ({ loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./preserve_url')); loadTestFile(require.resolve('./async_scripted_fields')); loadTestFile(require.resolve('./reporting')); + loadTestFile(require.resolve('./error_handling')); }); } diff --git a/x-pack/test/functional/es_archives/invalid_scripted_field/data.json.gz b/x-pack/test/functional/es_archives/invalid_scripted_field/data.json.gz new file mode 100644 index 0000000000000..380dd6049179a Binary files /dev/null and b/x-pack/test/functional/es_archives/invalid_scripted_field/data.json.gz differ diff --git a/x-pack/test/functional/es_archives/invalid_scripted_field/mappings.json b/x-pack/test/functional/es_archives/invalid_scripted_field/mappings.json new file mode 100644 index 0000000000000..0024c6943ed1c --- /dev/null +++ b/x-pack/test/functional/es_archives/invalid_scripted_field/mappings.json @@ -0,0 +1,250 @@ +{ + "type": "index", + "value": { + "index": ".kibana", + "mappings": { + "dynamic": "strict", + "properties": { + "config": { + "dynamic": "true", + "properties": { + "buildNum": { + "type": "keyword" + }, + "defaultIndex": { + "fields": { + "keyword": { + "ignore_above": 256, + "type": "keyword" + } + }, + "type": "text" + } + } + }, + "dashboard": { + "properties": { + "description": { + "type": "text" + }, + "hits": { + "type": "integer" + }, + "kibanaSavedObjectMeta": { + "properties": { + "searchSourceJSON": { + "type": "text" + } + } + }, + "optionsJSON": { + "type": "text" + }, + "panelsJSON": { + "type": "text" + }, + "refreshInterval": { + "properties": { + "display": { + "type": "keyword" + }, + "pause": { + "type": "boolean" + }, + "section": { + "type": "integer" + }, + "value": { + "type": "integer" + } + } + }, + "timeFrom": { + "type": "keyword" + }, + "timeRestore": { + "type": "boolean" + }, + "timeTo": { + "type": "keyword" + }, + "title": { + "type": "text" + }, + "uiStateJSON": { + "type": "text" + }, + "version": { + "type": "integer" + } + } + }, + "index-pattern": { + "properties": { + "fieldFormatMap": { + "type": "text" + }, + "fields": { + "type": "text" + }, + "intervalName": { + "type": "keyword" + }, + "notExpandable": { + "type": "boolean" + }, + "sourceFilters": { + "type": "text" + }, + "timeFieldName": { + "type": "keyword" + }, + "title": { + "type": "text" + } + } + }, + "search": { + "properties": { + "columns": { + "type": "keyword" + }, + "description": { + "type": "text" + }, + "hits": { + "type": "integer" + }, + "kibanaSavedObjectMeta": { + "properties": { + "searchSourceJSON": { + "type": "text" + } + } + }, + "sort": { + "type": "keyword" + }, + "title": { + "type": "text" + }, + "version": { + "type": "integer" + } + } + }, + "server": { + "properties": { + "uuid": { + "type": "keyword" + } + } + }, + "timelion-sheet": { + "properties": { + "description": { + "type": "text" + }, + "hits": { + "type": "integer" + }, + "kibanaSavedObjectMeta": { + "properties": { + "searchSourceJSON": { + "type": "text" + } + } + }, + "timelion_chart_height": { + "type": "integer" + }, + "timelion_columns": { + "type": "integer" + }, + "timelion_interval": { + "type": "keyword" + }, + "timelion_other_interval": { + "type": "keyword" + }, + "timelion_rows": { + "type": "integer" + }, + "timelion_sheet": { + "type": "text" + }, + "title": { + "type": "text" + }, + "version": { + "type": "integer" + } + } + }, + "type": { + "type": "keyword" + }, + "updated_at": { + "type": "date" + }, + "url": { + "properties": { + "accessCount": { + "type": "long" + }, + "accessDate": { + "type": "date" + }, + "createDate": { + "type": "date" + }, + "url": { + "fields": { + "keyword": { + "ignore_above": 2048, + "type": "keyword" + } + }, + "type": "text" + } + } + }, + "visualization": { + "properties": { + "description": { + "type": "text" + }, + "kibanaSavedObjectMeta": { + "properties": { + "searchSourceJSON": { + "type": "text" + } + } + }, + "savedSearchId": { + "type": "keyword" + }, + "title": { + "type": "text" + }, + "uiStateJSON": { + "type": "text" + }, + "version": { + "type": "integer" + }, + "visState": { + "type": "text" + } + } + } + } + }, + "settings": { + "index": { + "number_of_replicas": "0", + "number_of_shards": "1" + } + } + } +} \ No newline at end of file diff --git a/x-pack/test/ingest_manager_api_integration/apis/agent_policy/agent_policy.ts b/x-pack/test/ingest_manager_api_integration/apis/agent_policy/agent_policy.ts index 410b0fe093002..71e2bbc4e4c0a 100644 --- a/x-pack/test/ingest_manager_api_integration/apis/agent_policy/agent_policy.ts +++ b/x-pack/test/ingest_manager_api_integration/apis/agent_policy/agent_policy.ts @@ -82,7 +82,7 @@ export default function ({ getService }: FtrProviderContext) { }); }); - it('should return a 500 with invalid source policy', async () => { + it('should return a 404 with invalid source policy', async () => { await supertest .post(`/api/ingest_manager/agent_policies/INVALID_POLICY_ID/copy`) .set('kbn-xsrf', 'xxxx') @@ -90,7 +90,7 @@ export default function ({ getService }: FtrProviderContext) { name: 'Copied policy', description: '', }) - .expect(500); + .expect(404); }); it('should return a 400 with invalid payload', async () => { diff --git a/x-pack/test/security_solution_endpoint/apps/endpoint/policy_details.ts b/x-pack/test/security_solution_endpoint/apps/endpoint/policy_details.ts index 325283f5e3440..9610144d3846d 100644 --- a/x-pack/test/security_solution_endpoint/apps/endpoint/policy_details.ts +++ b/x-pack/test/security_solution_endpoint/apps/endpoint/policy_details.ts @@ -29,7 +29,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { port, }); - describe('When on the Endpoint Policy Details Page', function () { + // FAILING ES PROMOTION: https://github.com/elastic/kibana/issues/72102 + describe.skip('When on the Endpoint Policy Details Page', function () { this.tags(['ciGroup7']); describe('with an invalid policy id', () => {