From 75fe1b643024e6094347c52f610e0d54dfc41c97 Mon Sep 17 00:00:00 2001 From: Shahzad Date: Sun, 13 Sep 2020 19:42:42 +0200 Subject: [PATCH 01/17] update --- .../ImpactfulMetrics/HighTrafficPages.tsx | 130 ++++++++++++++++++ .../ImpactfulMetrics/JSErrors.tsx | 77 +++++++++++ .../RumDashboard/ImpactfulMetrics/index.tsx | 43 ++++++ .../app/RumDashboard/RumDashboard.tsx | 4 + .../app/RumDashboard/translations.ts | 18 +++ .../lib/rum_client/get_high_traffic_pages.ts | 122 ++++++++++++++++ .../server/lib/rum_client/get_js_errors.ts | 67 +++++++++ .../apm/server/projections/rum_overview.ts | 32 ++++- .../apm/server/routes/create_apm_api.ts | 4 + .../plugins/apm/server/routes/rum_client.ts | 51 +++++++ .../apm/typings/elasticsearch/aggregations.ts | 6 + .../apm/typings/elasticsearch/index.ts | 11 ++ 12 files changed, 564 insertions(+), 1 deletion(-) create mode 100644 x-pack/plugins/apm/public/components/app/RumDashboard/ImpactfulMetrics/HighTrafficPages.tsx create mode 100644 x-pack/plugins/apm/public/components/app/RumDashboard/ImpactfulMetrics/JSErrors.tsx create mode 100644 x-pack/plugins/apm/public/components/app/RumDashboard/ImpactfulMetrics/index.tsx create mode 100644 x-pack/plugins/apm/server/lib/rum_client/get_high_traffic_pages.ts create mode 100644 x-pack/plugins/apm/server/lib/rum_client/get_js_errors.ts diff --git a/x-pack/plugins/apm/public/components/app/RumDashboard/ImpactfulMetrics/HighTrafficPages.tsx b/x-pack/plugins/apm/public/components/app/RumDashboard/ImpactfulMetrics/HighTrafficPages.tsx new file mode 100644 index 0000000000000..5c9f3e39d4599 --- /dev/null +++ b/x-pack/plugins/apm/public/components/app/RumDashboard/ImpactfulMetrics/HighTrafficPages.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; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { useCallback, useMemo, useState } from 'react'; +import { EuiDataGrid, EuiSpacer } from '@elastic/eui'; +import { useUrlParams } from '../../../../hooks/useUrlParams'; +import { useFetcher } from '../../../../hooks/useFetcher'; + +export function HighTrafficPages() { + const { urlParams, uiFilters } = useUrlParams(); + + const { start, end, serviceName } = urlParams; + const [sortingColumns, setSortingColumns] = useState([ + { + id: 'percentage', + direction: 'desc', + }, + ]); + const [pagination, setPagination] = useState({ pageIndex: 0, pageSize: 5 }); + + const { data, status } = useFetcher( + (callApmApi) => { + if (start && end && serviceName) { + return callApmApi({ + pathname: '/api/apm/rum-client/high-traffic-pages', + params: { + query: { + start, + end, + pageSize: String(pagination.pageSize), + pageIndex: String(pagination.pageIndex), + uiFilters: JSON.stringify(uiFilters), + sorting: JSON.stringify(sortingColumns), + }, + }, + }); + } + return Promise.resolve(null); + }, + [start, end, serviceName, uiFilters, pagination, sortingColumns] + ); + + const columns = [ + { + id: 'url', + display: 'Url', + displayAsText: 'Url', + defaultSortDirection: 'asc', + }, + { + display: 'Page load duration', + displayAsText: 'Page load duration', + id: 'medianDuration', + align: 'right' as const, + }, + { + display: 'Blocking time', + displayAsText: 'Blocking time', + id: 'medianTbt', + align: 'right' as const, + }, + { + display: '% of total page views', + displayAsText: '% of total page views', + id: 'percentage', + align: 'right' as const, + }, + ]; + + const [visibleColumns, setVisibleColumns] = useState(() => + columns.map(({ id }) => id) + ); + + const onChangeItemsPerPage = useCallback( + (pageSize) => + setPagination((pagination) => ({ + ...pagination, + pageSize, + pageIndex: 0, + })), + [setPagination] + ); + const onChangePage = useCallback( + (pageIndex) => + setPagination((pagination) => ({ ...pagination, pageIndex })), + [setPagination] + ); + + const items = data?.items ?? []; + + const renderCellValue = useMemo(() => { + return ({ rowIndex, columnId, setCellProps }) => { + return items.hasOwnProperty(rowIndex) ? items[rowIndex][columnId] : null; + }; + }, [items]); + + const onSort = useCallback( + (sortingColumns) => { + setSortingColumns(sortingColumns); + }, + [setSortingColumns] + ); + + return ( + <> + + + + ); +} diff --git a/x-pack/plugins/apm/public/components/app/RumDashboard/ImpactfulMetrics/JSErrors.tsx b/x-pack/plugins/apm/public/components/app/RumDashboard/ImpactfulMetrics/JSErrors.tsx new file mode 100644 index 0000000000000..4d8dbecbe6fb2 --- /dev/null +++ b/x-pack/plugins/apm/public/components/app/RumDashboard/ImpactfulMetrics/JSErrors.tsx @@ -0,0 +1,77 @@ +/* + * 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 } from 'react'; +import { EuiBasicTable, EuiSpacer } from '@elastic/eui'; +import { Pagination } from '@elastic/eui/src/components/basic_table/pagination_bar'; +import { useUrlParams } from '../../../../hooks/useUrlParams'; +import { useFetcher } from '../../../../hooks/useFetcher'; + +export function JSErrors() { + const { urlParams, uiFilters } = useUrlParams(); + + const { start, end, serviceName } = urlParams; + + const [pagination, setPagination] = useState({ pageIndex: 0, pageSize: 5 }); + + const { data, status } = useFetcher( + (callApmApi) => { + if (start && end && serviceName) { + return callApmApi({ + pathname: '/api/apm/rum-client/js-errors', + params: { + query: { + start, + end, + uiFilters: JSON.stringify(uiFilters), + pageSize: String(pagination.pageSize), + pageIndex: String(pagination.pageIndex), + }, + }, + }); + } + return Promise.resolve(null); + }, + [start, end, serviceName, uiFilters, pagination] + ); + + const cols = [ + { + field: 'errorMessage', + name: 'Error message', + truncateText: true, + }, + { + name: 'Impacted page loads', + field: 'count', + align: 'right' as const, + }, + ]; + + const onTableChange = ({ page }: Pagination) => { + setPagination({ + ...page, + }); + }; + + return ( + <> + + + + ); +} diff --git a/x-pack/plugins/apm/public/components/app/RumDashboard/ImpactfulMetrics/index.tsx b/x-pack/plugins/apm/public/components/app/RumDashboard/ImpactfulMetrics/index.tsx new file mode 100644 index 0000000000000..e39363a164641 --- /dev/null +++ b/x-pack/plugins/apm/public/components/app/RumDashboard/ImpactfulMetrics/index.tsx @@ -0,0 +1,43 @@ +/* + * 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 { + EuiFlexItem, + EuiPanel, + EuiTitle, + EuiFlexGroup, + EuiSpacer, +} from '@elastic/eui'; +import { JSErrors } from './JSErrors'; +import { I18LABELS } from '../translations'; +import { HighTrafficPages } from './HighTrafficPages'; + +interface Props {} +export function ImpactfulMetrics(props: Props) { + return ( + + +

{I18LABELS.impactfulMetrics}

+
+ + + + +

{I18LABELS.jsErrors}

+
+ +
+ + +

{I18LABELS.highTrafficPages}

+
+ +
+
+
+ ); +} diff --git a/x-pack/plugins/apm/public/components/app/RumDashboard/RumDashboard.tsx b/x-pack/plugins/apm/public/components/app/RumDashboard/RumDashboard.tsx index f05c07e8512ac..2ae7d6f1c93fa 100644 --- a/x-pack/plugins/apm/public/components/app/RumDashboard/RumDashboard.tsx +++ b/x-pack/plugins/apm/public/components/app/RumDashboard/RumDashboard.tsx @@ -18,6 +18,7 @@ import { PageLoadDistribution } from './PageLoadDistribution'; import { I18LABELS } from './translations'; import { VisitorBreakdown } from './VisitorBreakdown'; import { CoreVitals } from './CoreVitals'; +import { ImpactfulMetrics } from './ImpactfulMetrics'; export function RumDashboard() { return ( @@ -70,6 +71,9 @@ export function RumDashboard() { + + + ); } diff --git a/x-pack/plugins/apm/public/components/app/RumDashboard/translations.ts b/x-pack/plugins/apm/public/components/app/RumDashboard/translations.ts index 660ed5a92a0e6..b3ddc812fb850 100644 --- a/x-pack/plugins/apm/public/components/app/RumDashboard/translations.ts +++ b/x-pack/plugins/apm/public/components/app/RumDashboard/translations.ts @@ -37,6 +37,24 @@ export const I18LABELS = { defaultMessage: 'Page load distribution', } ), + impactfulMetrics: i18n.translate( + 'xpack.apm.rum.dashboard.impactfulMetrics.label', + { + defaultMessage: 'Impactful metrics', + } + ), + jsErrors: i18n.translate( + 'xpack.apm.rum.dashboard.impactfulMetrics.jsErrors', + { + defaultMessage: 'Javascript errors', + } + ), + highTrafficPages: i18n.translate( + 'xpack.apm.rum.dashboard.impactfulMetrics.highTrafficPages', + { + defaultMessage: 'High traffic pages', + } + ), resetZoom: i18n.translate('xpack.apm.rum.dashboard.resetZoom.label', { defaultMessage: 'Reset zoom', }), diff --git a/x-pack/plugins/apm/server/lib/rum_client/get_high_traffic_pages.ts b/x-pack/plugins/apm/server/lib/rum_client/get_high_traffic_pages.ts new file mode 100644 index 0000000000000..e8b41e566a2bf --- /dev/null +++ b/x-pack/plugins/apm/server/lib/rum_client/get_high_traffic_pages.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; + * you may not use this file except in compliance with the Elastic License. + */ + +import { getRumOverviewProjection } from '../../projections/rum_overview'; +import { mergeProjection } from '../../projections/util/merge_projection'; +import { + Setup, + SetupTimeRange, + SetupUIFilters, +} from '../helpers/setup_request'; + +const sortFieldMap = { + url: '_key', + medianTbt: 'medianTbt[50.0]', + medianDuration: 'medianDuration[50.0]', + percentage: '_count', +}; + +export async function getHighTrafficPages({ + setup, + pageSize, + pageIndex, + sorting, +}: { + setup: Setup & SetupTimeRange & SetupUIFilters; + pageSize: number; + pageIndex: number; + afterKey?: string; + sorting: string; +}) { + const projection = getRumOverviewProjection({ + setup, + }); + + const sortOptions = JSON.parse(sorting); + + const order: any = {}; + sortOptions.forEach((sortOpt) => { + const sortField = sortFieldMap[sortOpt.id]; + order[sortField] = sortOpt.direction; + }); + + const params = mergeProjection(projection, { + body: { + size: 0, + query: { + bool: { + filter: [...projection.body.query.bool.filter], + }, + }, + aggs: { + totalPageViews: { value_count: { field: 'transaction.type' } }, + total: { + cardinality: { + field: 'url.full', + }, + }, + urls: { + terms: { + field: 'url.full', + size: 1000, + ...(sortOptions.length > 0 ? { order } : {}), + }, + aggs: { + bucket_truncate: { + bucket_sort: { + size: pageSize, + from: pageIndex * pageSize, + }, + }, + medianDuration: { + percentiles: { + field: 'transaction.duration.us', + percents: [50], + }, + }, + medianTbt: { + percentiles: { + field: 'transaction.experience.tbt', + percents: [50], + }, + }, + }, + }, + }, + }, + }); + + const { apmEventClient } = setup; + + const response = await apmEventClient.search(params); + + const { urls, totalPageViews, total } = response.aggregations!; + + return { + total: total.value, + items: urls.buckets.map((bucket) => { + const urlCount = bucket.doc_count; + + const medianDuration = Number( + ((bucket.medianDuration.values['50.0'] ?? 0) / 1000000).toFixed(2) + ); + + const medianTbt = Number( + (bucket.medianTbt.values['50.0'] ?? 0).toFixed(2) + ); + + return { + url: bucket.key, + count: urlCount, + medianDuration, + medianTbt, + percentage: Number( + ((urlCount / totalPageViews.value!) * 100).toFixed(2) + ), + }; + }), + }; +} diff --git a/x-pack/plugins/apm/server/lib/rum_client/get_js_errors.ts b/x-pack/plugins/apm/server/lib/rum_client/get_js_errors.ts new file mode 100644 index 0000000000000..43575106f1fef --- /dev/null +++ b/x-pack/plugins/apm/server/lib/rum_client/get_js_errors.ts @@ -0,0 +1,67 @@ +/* + * 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 { getRumErrorsProjection } from '../../projections/rum_overview'; +import { mergeProjection } from '../../projections/util/merge_projection'; +import { + Setup, + SetupTimeRange, + SetupUIFilters, +} from '../helpers/setup_request'; + +export async function getJSErrors({ + setup, + pageSize, + pageIndex, +}: { + setup: Setup & SetupTimeRange & SetupUIFilters; + pageSize: number; + pageIndex: number; +}) { + const projection = getRumErrorsProjection({ + setup, + }); + + const params = mergeProjection(projection, { + body: { + size: pageSize, + from: pageSize * pageIndex, + query: { + bool: { + filter: [ + ...projection.body.query.bool.filter, + { + term: { + 'service.language.name': 'javascript', + }, + }, + ], + }, + }, + collapse: { + field: 'error.grouping_key', + inner_hits: { + name: 'errorInfo', + size: 0, + }, + }, + }, + }); + + const { apmEventClient } = setup; + + const response = await apmEventClient.search(params); + + return { + total: response.hits.total.value, + items: response.hits.hits.map((hit) => { + return { + errorMessage: hit._source.error.exception[0].message, + count: hit.inner_hits.errorInfo.hits.total.value, + }; + }), + }; +} diff --git a/x-pack/plugins/apm/server/projections/rum_overview.ts b/x-pack/plugins/apm/server/projections/rum_overview.ts index 4588ec2a0451f..f5cd10a17232e 100644 --- a/x-pack/plugins/apm/server/projections/rum_overview.ts +++ b/x-pack/plugins/apm/server/projections/rum_overview.ts @@ -9,7 +9,10 @@ import { SetupTimeRange, SetupUIFilters, } from '../../server/lib/helpers/setup_request'; -import { TRANSACTION_TYPE } from '../../common/elasticsearch_fieldnames'; +import { + AGENT_NAME, + TRANSACTION_TYPE, +} from '../../common/elasticsearch_fieldnames'; import { rangeFilter } from '../../common/utils/range_filter'; import { ProcessorEvent } from '../../common/processor_event'; @@ -45,3 +48,30 @@ export function getRumOverviewProjection({ }, }; } + +export function getRumErrorsProjection({ + setup, +}: { + setup: Setup & SetupTimeRange & SetupUIFilters; +}) { + const { start, end, uiFiltersES } = setup; + + const bool = { + filter: [ + { range: rangeFilter(start, end) }, + { term: { [AGENT_NAME]: 'rum-js' } }, + ...uiFiltersES, + ], + }; + + return { + apm: { + events: [ProcessorEvent.error], + }, + body: { + query: { + bool, + }, + }, + }; +} 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 cf7a02cde975c..9f6843b52db7c 100644 --- a/x-pack/plugins/apm/server/routes/create_apm_api.ts +++ b/x-pack/plugins/apm/server/routes/create_apm_api.ts @@ -78,6 +78,8 @@ import { rumServicesRoute, rumVisitorsBreakdownRoute, rumWebCoreVitals, + rumJSErrors, + rumHighTrafficPages, } from './rum_client'; import { observabilityOverviewHasDataRoute, @@ -174,6 +176,8 @@ const createApmApi = () => { .add(rumServicesRoute) .add(rumVisitorsBreakdownRoute) .add(rumWebCoreVitals) + .add(rumJSErrors) + .add(rumHighTrafficPages) // Observability dashboard .add(observabilityOverviewHasDataRoute) diff --git a/x-pack/plugins/apm/server/routes/rum_client.ts b/x-pack/plugins/apm/server/routes/rum_client.ts index e17791f56eef2..4cd571bbee009 100644 --- a/x-pack/plugins/apm/server/routes/rum_client.ts +++ b/x-pack/plugins/apm/server/routes/rum_client.ts @@ -15,6 +15,8 @@ import { getPageLoadDistBreakdown } from '../lib/rum_client/get_pl_dist_breakdow import { getRumServices } from '../lib/rum_client/get_rum_services'; import { getVisitorBreakdown } from '../lib/rum_client/get_visitor_breakdown'; import { getWebCoreVitals } from '../lib/rum_client/get_web_core_vitals'; +import { getJSErrors } from '../lib/rum_client/get_js_errors'; +import { getHighTrafficPages } from '../lib/rum_client/get_high_traffic_pages'; export const percentileRangeRt = t.partial({ minPercentile: t.string, @@ -130,3 +132,52 @@ export const rumWebCoreVitals = createRoute(() => ({ return getWebCoreVitals({ setup }); }, })); + +export const rumJSErrors = createRoute(() => ({ + path: '/api/apm/rum-client/js-errors', + params: { + query: t.intersection([ + uiFiltersRt, + rangeRt, + t.type({ pageSize: t.string, pageIndex: t.string }), + ]), + }, + handler: async ({ context, request }) => { + const setup = await setupRequest(context, request); + + const { + query: { pageSize, pageIndex }, + } = context.params; + + return getJSErrors({ + setup, + pageSize: Number(pageSize), + pageIndex: Number(pageIndex), + }); + }, +})); + +export const rumHighTrafficPages = createRoute(() => ({ + path: '/api/apm/rum-client/high-traffic-pages', + params: { + query: t.intersection([ + uiFiltersRt, + rangeRt, + t.type({ pageSize: t.string, pageIndex: t.string, sorting: t.string }), + ]), + }, + handler: async ({ context, request }) => { + const setup = await setupRequest(context, request); + + const { + query: { pageSize, pageIndex, sorting }, + } = context.params; + + return getHighTrafficPages({ + setup, + sorting, + pageSize: Number(pageSize), + pageIndex: Number(pageIndex), + }); + }, +})); diff --git a/x-pack/plugins/apm/typings/elasticsearch/aggregations.ts b/x-pack/plugins/apm/typings/elasticsearch/aggregations.ts index 7a7592b248960..117c9de27165b 100644 --- a/x-pack/plugins/apm/typings/elasticsearch/aggregations.ts +++ b/x-pack/plugins/apm/typings/elasticsearch/aggregations.ts @@ -150,6 +150,11 @@ export interface AggregationOptionsByType { keyed?: boolean; hdr?: { number_of_significant_value_digits: number }; } & AggregationSourceOptions; + bucket_sort: { + sort?: SortOptions; + from: number; + size: number; + }; } type AggregationType = keyof AggregationOptionsByType; @@ -325,6 +330,7 @@ interface AggregationResponsePart< ? Array<{ key: number; value: number }> : Record; }; + bucket_sort: undefined; } // Type for debugging purposes. If you see an error in AggregationResponseMap diff --git a/x-pack/plugins/apm/typings/elasticsearch/index.ts b/x-pack/plugins/apm/typings/elasticsearch/index.ts index 064b684cf9aa6..9a05fe631e888 100644 --- a/x-pack/plugins/apm/typings/elasticsearch/index.ts +++ b/x-pack/plugins/apm/typings/elasticsearch/index.ts @@ -7,11 +7,22 @@ import { SearchParams, SearchResponse } from 'elasticsearch'; import { AggregationResponseMap, AggregationInputMap } from './aggregations'; +interface CollapseQuery { + field: string; + inner_hits: { + name: string; + size?: number; + sort?: [{ date: 'asc' | 'desc' }]; + }; + max_concurrent_group_searches?: number; +} + export interface ESSearchBody { query?: any; size?: number; aggs?: AggregationInputMap; track_total_hits?: boolean | number; + collapse?: CollapseQuery; } export type ESSearchRequest = Omit & { From 42bf52ab7ff63b0ed66fd01815d32ba6cbe41335 Mon Sep 17 00:00:00 2001 From: Shahzad Date: Fri, 18 Sep 2020 18:10:09 +0200 Subject: [PATCH 02/17] added js errors table --- .../app/RumDashboard/ClientMetrics/index.tsx | 8 ++ .../RumDashboard/CsmSharedContext/index.tsx | 45 ++++++ .../ImpactfulMetrics/HighTrafficPages.tsx | 130 ------------------ .../ImpactfulMetrics/JSErrors.tsx | 75 ++++++++-- .../RumDashboard/ImpactfulMetrics/index.tsx | 13 +- .../components/app/RumDashboard/RumHome.tsx | 31 +++-- .../app/RumDashboard/translations.ts | 15 ++ .../lib/rum_client/get_high_traffic_pages.ts | 122 ---------------- .../server/lib/rum_client/get_js_errors.ts | 76 +++++++--- .../projections/rum_page_load_transactions.ts | 7 + .../apm/server/routes/create_apm_api.ts | 1 - .../plugins/apm/server/routes/rum_client.ts | 26 ---- 12 files changed, 211 insertions(+), 338 deletions(-) create mode 100644 x-pack/plugins/apm/public/components/app/RumDashboard/CsmSharedContext/index.tsx delete mode 100644 x-pack/plugins/apm/public/components/app/RumDashboard/ImpactfulMetrics/HighTrafficPages.tsx delete mode 100644 x-pack/plugins/apm/server/lib/rum_client/get_high_traffic_pages.ts diff --git a/x-pack/plugins/apm/public/components/app/RumDashboard/ClientMetrics/index.tsx b/x-pack/plugins/apm/public/components/app/RumDashboard/ClientMetrics/index.tsx index 1edfd724dadd7..874b52f993e12 100644 --- a/x-pack/plugins/apm/public/components/app/RumDashboard/ClientMetrics/index.tsx +++ b/x-pack/plugins/apm/public/components/app/RumDashboard/ClientMetrics/index.tsx @@ -6,10 +6,12 @@ import * as React from 'react'; import numeral from '@elastic/numeral'; import styled from 'styled-components'; +import { useContext, useEffect } from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiStat, EuiToolTip } from '@elastic/eui'; import { useFetcher } from '../../../../hooks/useFetcher'; import { useUrlParams } from '../../../../hooks/useUrlParams'; import { I18LABELS } from '../translations'; +import { CsmSharedContext } from '../CsmSharedContext'; const ClFlexGroup = styled(EuiFlexGroup)` flex-direction: row; @@ -40,6 +42,12 @@ export function ClientMetrics() { [start, end, uiFilters] ); + const { setSharedData } = useContext(CsmSharedContext); + + useEffect(() => { + setSharedData({ totalPageViews: data?.pageViews?.value ?? 0 }); + }, [data, setSharedData]); + const STAT_STYLE = { width: '240px' }; return ( diff --git a/x-pack/plugins/apm/public/components/app/RumDashboard/CsmSharedContext/index.tsx b/x-pack/plugins/apm/public/components/app/RumDashboard/CsmSharedContext/index.tsx new file mode 100644 index 0000000000000..e4d148e9189b5 --- /dev/null +++ b/x-pack/plugins/apm/public/components/app/RumDashboard/CsmSharedContext/index.tsx @@ -0,0 +1,45 @@ +/* + * 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, { createContext, useMemo, useState } from 'react'; + +interface SharedData { + totalPageViews: number; +} + +interface Index { + sharedData: SharedData; + setSharedData: (data: SharedData) => void; +} + +const defaultContext: Index = { + sharedData: { totalPageViews: 0 }, + setSharedData: (d) => { + throw new Error( + 'setSharedData was not initialized, set it when you invoke the context' + ); + }, +}; + +export const CsmSharedContext = createContext(defaultContext); + +export function CsmSharedContextProvider({ + children, +}: { + children: React.ReactChildren; +}) { + const [newData, setNewData] = useState({ totalPageViews: 0 }); + + const setSharedData = (data: SharedData) => { + setNewData(data); + }; + + const value = useMemo(() => { + return { sharedData: newData, setSharedData }; + }, [newData]); + + return ; +} diff --git a/x-pack/plugins/apm/public/components/app/RumDashboard/ImpactfulMetrics/HighTrafficPages.tsx b/x-pack/plugins/apm/public/components/app/RumDashboard/ImpactfulMetrics/HighTrafficPages.tsx deleted file mode 100644 index 5c9f3e39d4599..0000000000000 --- a/x-pack/plugins/apm/public/components/app/RumDashboard/ImpactfulMetrics/HighTrafficPages.tsx +++ /dev/null @@ -1,130 +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, { useCallback, useMemo, useState } from 'react'; -import { EuiDataGrid, EuiSpacer } from '@elastic/eui'; -import { useUrlParams } from '../../../../hooks/useUrlParams'; -import { useFetcher } from '../../../../hooks/useFetcher'; - -export function HighTrafficPages() { - const { urlParams, uiFilters } = useUrlParams(); - - const { start, end, serviceName } = urlParams; - const [sortingColumns, setSortingColumns] = useState([ - { - id: 'percentage', - direction: 'desc', - }, - ]); - const [pagination, setPagination] = useState({ pageIndex: 0, pageSize: 5 }); - - const { data, status } = useFetcher( - (callApmApi) => { - if (start && end && serviceName) { - return callApmApi({ - pathname: '/api/apm/rum-client/high-traffic-pages', - params: { - query: { - start, - end, - pageSize: String(pagination.pageSize), - pageIndex: String(pagination.pageIndex), - uiFilters: JSON.stringify(uiFilters), - sorting: JSON.stringify(sortingColumns), - }, - }, - }); - } - return Promise.resolve(null); - }, - [start, end, serviceName, uiFilters, pagination, sortingColumns] - ); - - const columns = [ - { - id: 'url', - display: 'Url', - displayAsText: 'Url', - defaultSortDirection: 'asc', - }, - { - display: 'Page load duration', - displayAsText: 'Page load duration', - id: 'medianDuration', - align: 'right' as const, - }, - { - display: 'Blocking time', - displayAsText: 'Blocking time', - id: 'medianTbt', - align: 'right' as const, - }, - { - display: '% of total page views', - displayAsText: '% of total page views', - id: 'percentage', - align: 'right' as const, - }, - ]; - - const [visibleColumns, setVisibleColumns] = useState(() => - columns.map(({ id }) => id) - ); - - const onChangeItemsPerPage = useCallback( - (pageSize) => - setPagination((pagination) => ({ - ...pagination, - pageSize, - pageIndex: 0, - })), - [setPagination] - ); - const onChangePage = useCallback( - (pageIndex) => - setPagination((pagination) => ({ ...pagination, pageIndex })), - [setPagination] - ); - - const items = data?.items ?? []; - - const renderCellValue = useMemo(() => { - return ({ rowIndex, columnId, setCellProps }) => { - return items.hasOwnProperty(rowIndex) ? items[rowIndex][columnId] : null; - }; - }, [items]); - - const onSort = useCallback( - (sortingColumns) => { - setSortingColumns(sortingColumns); - }, - [setSortingColumns] - ); - - return ( - <> - - - - ); -} diff --git a/x-pack/plugins/apm/public/components/app/RumDashboard/ImpactfulMetrics/JSErrors.tsx b/x-pack/plugins/apm/public/components/app/RumDashboard/ImpactfulMetrics/JSErrors.tsx index 4d8dbecbe6fb2..21cf955f2c742 100644 --- a/x-pack/plugins/apm/public/components/app/RumDashboard/ImpactfulMetrics/JSErrors.tsx +++ b/x-pack/plugins/apm/public/components/app/RumDashboard/ImpactfulMetrics/JSErrors.tsx @@ -4,11 +4,21 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { useState } from 'react'; -import { EuiBasicTable, EuiSpacer } from '@elastic/eui'; -import { Pagination } from '@elastic/eui/src/components/basic_table/pagination_bar'; +import React, { useContext, useState } from 'react'; +import { + EuiBasicTable, + EuiFlexItem, + EuiFlexGroup, + EuiSpacer, + EuiTitle, + EuiStat, + EuiToolTip, +} from '@elastic/eui'; +import numeral from '@elastic/numeral'; import { useUrlParams } from '../../../../hooks/useUrlParams'; import { useFetcher } from '../../../../hooks/useFetcher'; +import { I18LABELS } from '../translations'; +import { CsmSharedContext } from '../CsmSharedContext'; export function JSErrors() { const { urlParams, uiFilters } = useUrlParams(); @@ -38,38 +48,81 @@ export function JSErrors() { [start, end, serviceName, uiFilters, pagination] ); + const { + sharedData: { totalPageViews }, + } = useContext(CsmSharedContext); + + const items = (data?.items ?? []).map(({ errorMessage, count }) => ({ + errorMessage, + percent: ((count / totalPageViews) * 100).toFixed(1) + ' %', + })); + const cols = [ { field: 'errorMessage', - name: 'Error message', - truncateText: true, + name: I18LABELS.errorMessage, }, { - name: 'Impacted page loads', - field: 'count', + name: I18LABELS.impactedPageLoads, + field: 'percent', align: 'right' as const, }, ]; - const onTableChange = ({ page }: Pagination) => { + const onTableChange = ({ + page, + }: { + page: { size: number; index: number }; + }) => { setPagination({ - ...page, + pageIndex: page.index, + pageSize: page.size, }); }; return ( <> + +

{I18LABELS.jsErrors}

+
+ + + + + <>{numeral(data?.totalErrors ?? 0).format('0 a')} + + } + description={I18LABELS.totalErrors} + isLoading={status !== 'success'} + /> + + + + {' '} + diff --git a/x-pack/plugins/apm/public/components/app/RumDashboard/ImpactfulMetrics/index.tsx b/x-pack/plugins/apm/public/components/app/RumDashboard/ImpactfulMetrics/index.tsx index e39363a164641..6a3572243a225 100644 --- a/x-pack/plugins/apm/public/components/app/RumDashboard/ImpactfulMetrics/index.tsx +++ b/x-pack/plugins/apm/public/components/app/RumDashboard/ImpactfulMetrics/index.tsx @@ -14,10 +14,8 @@ import { } from '@elastic/eui'; import { JSErrors } from './JSErrors'; import { I18LABELS } from '../translations'; -import { HighTrafficPages } from './HighTrafficPages'; -interface Props {} -export function ImpactfulMetrics(props: Props) { +export function ImpactfulMetrics() { return ( @@ -26,17 +24,8 @@ export function ImpactfulMetrics(props: Props) { - -

{I18LABELS.jsErrors}

-
- - -

{I18LABELS.highTrafficPages}

-
- -
); diff --git a/x-pack/plugins/apm/public/components/app/RumDashboard/RumHome.tsx b/x-pack/plugins/apm/public/components/app/RumDashboard/RumHome.tsx index 24da5e9ef3897..4c8f418187f75 100644 --- a/x-pack/plugins/apm/public/components/app/RumDashboard/RumHome.tsx +++ b/x-pack/plugins/apm/public/components/app/RumDashboard/RumHome.tsx @@ -9,24 +9,27 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; import { RumOverview } from '../RumDashboard'; import { RumHeader } from './RumHeader'; +import { CsmSharedContextProvider } from './CsmSharedContext'; export function RumHome() { return (
- - - - -

- {i18n.translate('xpack.apm.csm.title', { - defaultMessage: 'Client Side Monitoring', - })} -

-
-
-
-
- + + + + + +

+ {i18n.translate('xpack.apm.csm.title', { + defaultMessage: 'Client Side Monitoring', + })} +

+
+
+
+
+ +
); } diff --git a/x-pack/plugins/apm/public/components/app/RumDashboard/translations.ts b/x-pack/plugins/apm/public/components/app/RumDashboard/translations.ts index c4355c50f086c..106bbc9a38e97 100644 --- a/x-pack/plugins/apm/public/components/app/RumDashboard/translations.ts +++ b/x-pack/plugins/apm/public/components/app/RumDashboard/translations.ts @@ -97,6 +97,21 @@ export const I18LABELS = { defaultMessage: 'Page load duration by region', } ), + totalErrors: i18n.translate('xpack.apm.rum.jsErrors.totalErrors', { + defaultMessage: 'Total errors', + }), + errorRate: i18n.translate('xpack.apm.rum.jsErrors.errorRate', { + defaultMessage: 'Error rate', + }), + errorMessage: i18n.translate('xpack.apm.rum.jsErrors.errorMessage', { + defaultMessage: 'Error message', + }), + impactedPageLoads: i18n.translate( + 'xpack.apm.rum.jsErrors.impactedPageLoads', + { + defaultMessage: 'Impacted page loads', + } + ), }; export const VisitorBreakdownLabel = i18n.translate( diff --git a/x-pack/plugins/apm/server/lib/rum_client/get_high_traffic_pages.ts b/x-pack/plugins/apm/server/lib/rum_client/get_high_traffic_pages.ts deleted file mode 100644 index e8b41e566a2bf..0000000000000 --- a/x-pack/plugins/apm/server/lib/rum_client/get_high_traffic_pages.ts +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { getRumOverviewProjection } from '../../projections/rum_overview'; -import { mergeProjection } from '../../projections/util/merge_projection'; -import { - Setup, - SetupTimeRange, - SetupUIFilters, -} from '../helpers/setup_request'; - -const sortFieldMap = { - url: '_key', - medianTbt: 'medianTbt[50.0]', - medianDuration: 'medianDuration[50.0]', - percentage: '_count', -}; - -export async function getHighTrafficPages({ - setup, - pageSize, - pageIndex, - sorting, -}: { - setup: Setup & SetupTimeRange & SetupUIFilters; - pageSize: number; - pageIndex: number; - afterKey?: string; - sorting: string; -}) { - const projection = getRumOverviewProjection({ - setup, - }); - - const sortOptions = JSON.parse(sorting); - - const order: any = {}; - sortOptions.forEach((sortOpt) => { - const sortField = sortFieldMap[sortOpt.id]; - order[sortField] = sortOpt.direction; - }); - - const params = mergeProjection(projection, { - body: { - size: 0, - query: { - bool: { - filter: [...projection.body.query.bool.filter], - }, - }, - aggs: { - totalPageViews: { value_count: { field: 'transaction.type' } }, - total: { - cardinality: { - field: 'url.full', - }, - }, - urls: { - terms: { - field: 'url.full', - size: 1000, - ...(sortOptions.length > 0 ? { order } : {}), - }, - aggs: { - bucket_truncate: { - bucket_sort: { - size: pageSize, - from: pageIndex * pageSize, - }, - }, - medianDuration: { - percentiles: { - field: 'transaction.duration.us', - percents: [50], - }, - }, - medianTbt: { - percentiles: { - field: 'transaction.experience.tbt', - percents: [50], - }, - }, - }, - }, - }, - }, - }); - - const { apmEventClient } = setup; - - const response = await apmEventClient.search(params); - - const { urls, totalPageViews, total } = response.aggregations!; - - return { - total: total.value, - items: urls.buckets.map((bucket) => { - const urlCount = bucket.doc_count; - - const medianDuration = Number( - ((bucket.medianDuration.values['50.0'] ?? 0) / 1000000).toFixed(2) - ); - - const medianTbt = Number( - (bucket.medianTbt.values['50.0'] ?? 0).toFixed(2) - ); - - return { - url: bucket.key, - count: urlCount, - medianDuration, - medianTbt, - percentage: Number( - ((urlCount / totalPageViews.value!) * 100).toFixed(2) - ), - }; - }), - }; -} diff --git a/x-pack/plugins/apm/server/lib/rum_client/get_js_errors.ts b/x-pack/plugins/apm/server/lib/rum_client/get_js_errors.ts index 43575106f1fef..0540ea4bf09dd 100644 --- a/x-pack/plugins/apm/server/lib/rum_client/get_js_errors.ts +++ b/x-pack/plugins/apm/server/lib/rum_client/get_js_errors.ts @@ -4,13 +4,19 @@ * you may not use this file except in compliance with the Elastic License. */ -import { getRumErrorsProjection } from '../../projections/rum_overview'; import { mergeProjection } from '../../projections/util/merge_projection'; import { Setup, SetupTimeRange, SetupUIFilters, } from '../helpers/setup_request'; +import { getRumErrorsProjection } from '../../projections/rum_page_load_transactions'; +import { + ERROR_EXC_MESSAGE, + ERROR_EXC_TYPE, + ERROR_GROUP_ID, + TRANSACTION_ID, +} from '../../../common/elasticsearch_fieldnames'; export async function getJSErrors({ setup, @@ -27,25 +33,44 @@ export async function getJSErrors({ const params = mergeProjection(projection, { body: { - size: pageSize, - from: pageSize * pageIndex, - query: { - bool: { - filter: [ - ...projection.body.query.bool.filter, - { - term: { - 'service.language.name': 'javascript', + size: 0, + track_total_hits: true, + aggs: { + totalErrorGroups: { + cardinality: { + field: ERROR_GROUP_ID, + }, + }, + totalErrorPages: { + cardinality: { + field: TRANSACTION_ID, + }, + }, + errors: { + terms: { + field: ERROR_GROUP_ID, + size: 500, + }, + aggs: { + bucket_truncate: { + bucket_sort: { + size: pageSize, + from: pageIndex * pageSize, }, }, - ], - }, - }, - collapse: { - field: 'error.grouping_key', - inner_hits: { - name: 'errorInfo', - size: 0, + sample: { + top_hits: { + _source: [ + ERROR_EXC_MESSAGE, + ERROR_EXC_TYPE, + ERROR_GROUP_ID, + '@timestamp', + ], + sort: [{ '@timestamp': 'desc' as const }], + size: 1, + }, + }, + }, }, }, }, @@ -55,12 +80,19 @@ export async function getJSErrors({ const response = await apmEventClient.search(params); + const { totalErrorGroups, totalErrorPages, errors } = + response.aggregations ?? {}; + return { - total: response.hits.total.value, - items: response.hits.hits.map((hit) => { + totalErrorPages: totalErrorPages?.value ?? 0, + totalErrors: response.hits.total.value ?? 0, + totalErrorGroups: totalErrorGroups?.value ?? 0, + items: errors?.buckets.map(({ sample, doc_count: count }) => { return { - errorMessage: hit._source.error.exception[0].message, - count: hit.inner_hits.errorInfo.hits.total.value, + count, + errorMessage: (sample.hits.hits[0]._source as { + error: { exception: Array<{ message: string }> }; + }).error.exception?.[0].message, }; }), }; 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 e7aa5ecc79e9c..bba23a1c9c25d 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 @@ -13,6 +13,7 @@ import { SPAN_TYPE, AGENT_NAME, TRANSACTION_TYPE, + SERVICE_LANGUAGE_NAME, } from '../../common/elasticsearch_fieldnames'; import { rangeFilter } from '../../common/utils/range_filter'; import { ProcessorEvent } from '../../common/processor_event'; @@ -90,6 +91,12 @@ export function getRumErrorsProjection({ filter: [ { range: rangeFilter(start, end) }, { term: { [AGENT_NAME]: 'rum-js' } }, + { term: { [TRANSACTION_TYPE]: TRANSACTION_PAGE_LOAD } }, + { + term: { + [SERVICE_LANGUAGE_NAME]: 'javascript', + }, + }, ...uiFiltersES, ], }; 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 450c9af160eee..be1d443e682e9 100644 --- a/x-pack/plugins/apm/server/routes/create_apm_api.ts +++ b/x-pack/plugins/apm/server/routes/create_apm_api.ts @@ -180,7 +180,6 @@ const createApmApi = () => { .add(rumVisitorsBreakdownRoute) .add(rumWebCoreVitals) .add(rumJSErrors) - .add(rumHighTrafficPages) .add(rumLongTaskMetrics) // Observability dashboard diff --git a/x-pack/plugins/apm/server/routes/rum_client.ts b/x-pack/plugins/apm/server/routes/rum_client.ts index e815e3338c3ed..7103c6578d957 100644 --- a/x-pack/plugins/apm/server/routes/rum_client.ts +++ b/x-pack/plugins/apm/server/routes/rum_client.ts @@ -16,7 +16,6 @@ import { getRumServices } from '../lib/rum_client/get_rum_services'; import { getVisitorBreakdown } from '../lib/rum_client/get_visitor_breakdown'; import { getWebCoreVitals } from '../lib/rum_client/get_web_core_vitals'; import { getJSErrors } from '../lib/rum_client/get_js_errors'; -import { getHighTrafficPages } from '../lib/rum_client/get_high_traffic_pages'; import { getLongTaskMetrics } from '../lib/rum_client/get_long_task_metrics'; export const percentileRangeRt = t.partial({ @@ -169,28 +168,3 @@ export const rumJSErrors = createRoute(() => ({ }); }, })); - -export const rumHighTrafficPages = createRoute(() => ({ - path: '/api/apm/rum-client/high-traffic-pages', - params: { - query: t.intersection([ - uiFiltersRt, - rangeRt, - t.type({ pageSize: t.string, pageIndex: t.string, sorting: t.string }), - ]), - }, - handler: async ({ context, request }) => { - const setup = await setupRequest(context, request); - - const { - query: { pageSize, pageIndex, sorting }, - } = context.params; - - return getHighTrafficPages({ - setup, - sorting, - pageSize: Number(pageSize), - pageIndex: Number(pageIndex), - }); - }, -})); From 1c1327abda97233e98f524162a80239ef94c77cb Mon Sep 17 00:00:00 2001 From: Shahzad Date: Mon, 21 Sep 2020 13:15:31 +0200 Subject: [PATCH 03/17] fix types --- .../components/app/RumDashboard/CsmSharedContext/index.tsx | 6 +++--- .../apm/public/components/app/RumDashboard/RumDashboard.tsx | 1 - x-pack/plugins/apm/server/routes/create_apm_api.ts | 1 - 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/x-pack/plugins/apm/public/components/app/RumDashboard/CsmSharedContext/index.tsx b/x-pack/plugins/apm/public/components/app/RumDashboard/CsmSharedContext/index.tsx index e4d148e9189b5..be961f6bc2af4 100644 --- a/x-pack/plugins/apm/public/components/app/RumDashboard/CsmSharedContext/index.tsx +++ b/x-pack/plugins/apm/public/components/app/RumDashboard/CsmSharedContext/index.tsx @@ -33,13 +33,13 @@ export function CsmSharedContextProvider({ }) { const [newData, setNewData] = useState({ totalPageViews: 0 }); - const setSharedData = (data: SharedData) => { + const setSharedData = React.useCallback((data: SharedData) => { setNewData(data); - }; + }, []); const value = useMemo(() => { return { sharedData: newData, setSharedData }; - }, [newData]); + }, [newData, setSharedData]); return ; } diff --git a/x-pack/plugins/apm/public/components/app/RumDashboard/RumDashboard.tsx b/x-pack/plugins/apm/public/components/app/RumDashboard/RumDashboard.tsx index 00d90ced6ca27..62294c4717314 100644 --- a/x-pack/plugins/apm/public/components/app/RumDashboard/RumDashboard.tsx +++ b/x-pack/plugins/apm/public/components/app/RumDashboard/RumDashboard.tsx @@ -19,7 +19,6 @@ import { I18LABELS } from './translations'; import { VisitorBreakdown } from './VisitorBreakdown'; import { UXMetrics } from './UXMetrics'; import { VisitorBreakdownMap } from './VisitorBreakdownMap'; -import { CoreVitals } from './CoreVitals'; import { ImpactfulMetrics } from './ImpactfulMetrics'; export function RumDashboard() { 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 be1d443e682e9..04ebcedb471b2 100644 --- a/x-pack/plugins/apm/server/routes/create_apm_api.ts +++ b/x-pack/plugins/apm/server/routes/create_apm_api.ts @@ -80,7 +80,6 @@ import { rumVisitorsBreakdownRoute, rumWebCoreVitals, rumJSErrors, - rumHighTrafficPages, rumLongTaskMetrics, } from './rum_client'; import { From 29a007fc525a418e3258cb29b299cce6871439ad Mon Sep 17 00:00:00 2001 From: Shahzad Date: Mon, 21 Sep 2020 13:46:31 +0200 Subject: [PATCH 04/17] fix type --- .../components/app/RumDashboard/CsmSharedContext/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/apm/public/components/app/RumDashboard/CsmSharedContext/index.tsx b/x-pack/plugins/apm/public/components/app/RumDashboard/CsmSharedContext/index.tsx index be961f6bc2af4..3d445104d6d10 100644 --- a/x-pack/plugins/apm/public/components/app/RumDashboard/CsmSharedContext/index.tsx +++ b/x-pack/plugins/apm/public/components/app/RumDashboard/CsmSharedContext/index.tsx @@ -29,7 +29,7 @@ export const CsmSharedContext = createContext(defaultContext); export function CsmSharedContextProvider({ children, }: { - children: React.ReactChildren; + children: JSX.Element[]; }) { const [newData, setNewData] = useState({ totalPageViews: 0 }); From 36e368428c30b86fb469e6ba293b4b320040580c Mon Sep 17 00:00:00 2001 From: Shahzad Date: Mon, 21 Sep 2020 17:06:05 +0200 Subject: [PATCH 05/17] update test --- .../apm/server/lib/rum_client/queries.test.ts | 12 ++++ .../trial/tests/csm/js_errors.ts | 61 +++++++++++++++++++ .../apm_api_integration/trial/tests/index.ts | 1 + 3 files changed, 74 insertions(+) create mode 100644 x-pack/test/apm_api_integration/trial/tests/csm/js_errors.ts diff --git a/x-pack/plugins/apm/server/lib/rum_client/queries.test.ts b/x-pack/plugins/apm/server/lib/rum_client/queries.test.ts index 14cec21cceb79..23d2cb829b8d5 100644 --- a/x-pack/plugins/apm/server/lib/rum_client/queries.test.ts +++ b/x-pack/plugins/apm/server/lib/rum_client/queries.test.ts @@ -14,6 +14,7 @@ import { getPageLoadDistribution } from './get_page_load_distribution'; import { getRumServices } from './get_rum_services'; import { getLongTaskMetrics } from './get_long_task_metrics'; import { getWebCoreVitals } from './get_web_core_vitals'; +import { getJSErrors } from './get_js_errors'; describe('rum client dashboard queries', () => { let mock: SearchParamsMock; @@ -79,4 +80,15 @@ describe('rum client dashboard queries', () => { ); expect(mock.params).toMatchSnapshot(); }); + + it('fetches js errors', async () => { + mock = await inspectSearchParams((setup) => + getJSErrors({ + setup, + pageSize: 5, + pageIndex: 0, + }) + ); + expect(mock.params).toMatchSnapshot(); + }); }); diff --git a/x-pack/test/apm_api_integration/trial/tests/csm/js_errors.ts b/x-pack/test/apm_api_integration/trial/tests/csm/js_errors.ts new file mode 100644 index 0000000000000..0edffe7999a65 --- /dev/null +++ b/x-pack/test/apm_api_integration/trial/tests/csm/js_errors.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; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from '@kbn/expect'; +import { expectSnapshot } from '../../../common/match_snapshot'; +import { FtrProviderContext } from '../../../common/ftr_provider_context'; + +export default function rumJsErrorsApiTests({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + const esArchiver = getService('esArchiver'); + + describe('CSM js errors', () => { + describe('when there is no data', () => { + it('returns no js errors', async () => { + const response = await supertest.get( + '/api/apm/rum-client/js-errors?pageSize=5&pageIndex=0&start=2020-09-07T20%3A35%3A54.654Z&end=2020-09-14T20%3A35%3A54.654Z&uiFilters=%7B%22serviceName%22%3A%5B%22elastic-co-rum-test%22%5D%7D' + ); + + expect(response.status).to.be(200); + expectSnapshot(response.body).toMatchInline(` + Object { + "totalErrorGroups": 0, + "totalErrorPages": 0, + "totalErrors": 0, + } + `); + }); + }); + + describe('when there is data', () => { + before(async () => { + await esArchiver.load('8.0.0'); + await esArchiver.load('rum_8.0.0'); + }); + after(async () => { + await esArchiver.unload('8.0.0'); + await esArchiver.unload('rum_8.0.0'); + }); + + it('returns js errors', async () => { + const response = await supertest.get( + '/api/apm/rum-client/js-errors?pageSize=5&pageIndex=0&start=2020-09-07T20%3A35%3A54.654Z&end=2020-09-16T20%3A35%3A54.654Z&uiFilters=%7B%22serviceName%22%3A%5B%22kibana-frontend-8_0_0%22%5D%7D' + ); + + expect(response.status).to.be(200); + + expectSnapshot(response.body).toMatchInline(` + Object { + "items": Array [], + "totalErrorGroups": 0, + "totalErrorPages": 0, + "totalErrors": 0, + } + `); + }); + }); + }); +} diff --git a/x-pack/test/apm_api_integration/trial/tests/index.ts b/x-pack/test/apm_api_integration/trial/tests/index.ts index ae62253c62d81..98ff66817fba9 100644 --- a/x-pack/test/apm_api_integration/trial/tests/index.ts +++ b/x-pack/test/apm_api_integration/trial/tests/index.ts @@ -35,6 +35,7 @@ export default function observabilityApiIntegrationTests({ loadTestFile }: FtrPr loadTestFile(require.resolve('./csm/csm_services.ts')); loadTestFile(require.resolve('./csm/web_core_vitals.ts')); loadTestFile(require.resolve('./csm/long_task_metrics.ts')); + loadTestFile(require.resolve('./csm/js_errors.ts')); }); }); } From 3440978c9a70b372327258662d468fc55adc3feb Mon Sep 17 00:00:00 2001 From: Shahzad Date: Mon, 21 Sep 2020 20:45:07 +0200 Subject: [PATCH 06/17] update test --- .../__snapshots__/queries.test.ts.snap | 91 +++++++++++++++++++ 1 file changed, 91 insertions(+) diff --git a/x-pack/plugins/apm/server/lib/rum_client/__snapshots__/queries.test.ts.snap b/x-pack/plugins/apm/server/lib/rum_client/__snapshots__/queries.test.ts.snap index ceffb4f4d6654..66cfa954965d2 100644 --- a/x-pack/plugins/apm/server/lib/rum_client/__snapshots__/queries.test.ts.snap +++ b/x-pack/plugins/apm/server/lib/rum_client/__snapshots__/queries.test.ts.snap @@ -72,6 +72,97 @@ Object { } `; +exports[`rum client dashboard queries fetches js errors 1`] = ` +Object { + "apm": Object { + "events": Array [ + "error", + ], + }, + "body": Object { + "aggs": Object { + "errors": Object { + "aggs": Object { + "bucket_truncate": Object { + "bucket_sort": Object { + "from": 0, + "size": 5, + }, + }, + "sample": Object { + "top_hits": Object { + "_source": Array [ + "error.exception.message", + "error.exception.type", + "error.grouping_key", + "@timestamp", + ], + "size": 1, + "sort": Array [ + Object { + "@timestamp": "desc", + }, + ], + }, + }, + }, + "terms": Object { + "field": "error.grouping_key", + "size": 500, + }, + }, + "totalErrorGroups": Object { + "cardinality": Object { + "field": "error.grouping_key", + }, + }, + "totalErrorPages": Object { + "cardinality": Object { + "field": "transaction.id", + }, + }, + }, + "query": Object { + "bool": Object { + "filter": Array [ + Object { + "range": Object { + "@timestamp": Object { + "format": "epoch_millis", + "gte": 1528113600000, + "lte": 1528977600000, + }, + }, + }, + Object { + "term": Object { + "agent.name": "rum-js", + }, + }, + Object { + "term": Object { + "transaction.type": "page-load", + }, + }, + Object { + "term": Object { + "service.language.name": "javascript", + }, + }, + Object { + "term": Object { + "my.custom.ui.filter": "foo-bar", + }, + }, + ], + }, + }, + "size": 0, + "track_total_hits": true, + }, +} +`; + exports[`rum client dashboard queries fetches long task metrics 1`] = ` Object { "apm": Object { From b27daf876ac47879a346f5133f49662f8fbfb03d Mon Sep 17 00:00:00 2001 From: Shahzad Date: Mon, 21 Sep 2020 20:46:02 +0200 Subject: [PATCH 07/17] update test --- x-pack/plugins/apm/e2e/ingest-data/replay.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/apm/e2e/ingest-data/replay.js b/x-pack/plugins/apm/e2e/ingest-data/replay.js index 6bab95635f558..4d941fe8bbb46 100644 --- a/x-pack/plugins/apm/e2e/ingest-data/replay.js +++ b/x-pack/plugins/apm/e2e/ingest-data/replay.js @@ -129,7 +129,7 @@ async function init() { spinner.start(); requestProgress.total = items.length; - const limit = pLimit(20); // number of concurrent requests + const limit = pLimit(10); // number of concurrent requests await Promise.all( items.map(async (item) => { try { From 758eab610a2caeb2ba50026906987993c50fbcba Mon Sep 17 00:00:00 2001 From: Shahzad Date: Tue, 22 Sep 2020 19:07:12 +0200 Subject: [PATCH 08/17] PR feedback --- .../app/RumDashboard/ImpactfulMetrics/JSErrors.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/apm/public/components/app/RumDashboard/ImpactfulMetrics/JSErrors.tsx b/x-pack/plugins/apm/public/components/app/RumDashboard/ImpactfulMetrics/JSErrors.tsx index 21cf955f2c742..b14d8a28d52fa 100644 --- a/x-pack/plugins/apm/public/components/app/RumDashboard/ImpactfulMetrics/JSErrors.tsx +++ b/x-pack/plugins/apm/public/components/app/RumDashboard/ImpactfulMetrics/JSErrors.tsx @@ -15,6 +15,7 @@ import { EuiToolTip, } from '@elastic/eui'; import numeral from '@elastic/numeral'; +import { i18n } from '@kbn/i18n'; import { useUrlParams } from '../../../../hooks/useUrlParams'; import { useFetcher } from '../../../../hooks/useFetcher'; import { I18LABELS } from '../translations'; @@ -54,7 +55,10 @@ export function JSErrors() { const items = (data?.items ?? []).map(({ errorMessage, count }) => ({ errorMessage, - percent: ((count / totalPageViews) * 100).toFixed(1) + ' %', + percent: i18n.translate('xpack.apm.rum.jsErrors.percent', { + defaultMessage: '{pageLoadPercent} %', + values: { pageLoadPercent: ((count / totalPageViews) * 100).toFixed(1) }, + }), })); const cols = [ From ccbbbed874ab65beb4c679535a493e936b27c9e2 Mon Sep 17 00:00:00 2001 From: Shahzad Date: Tue, 22 Sep 2020 20:04:06 +0200 Subject: [PATCH 09/17] improve local --- .../app/RumDashboard/ImpactfulMetrics/JSErrors.tsx | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/x-pack/plugins/apm/public/components/app/RumDashboard/ImpactfulMetrics/JSErrors.tsx b/x-pack/plugins/apm/public/components/app/RumDashboard/ImpactfulMetrics/JSErrors.tsx index b14d8a28d52fa..4b9fd01f8c917 100644 --- a/x-pack/plugins/apm/public/components/app/RumDashboard/ImpactfulMetrics/JSErrors.tsx +++ b/x-pack/plugins/apm/public/components/app/RumDashboard/ImpactfulMetrics/JSErrors.tsx @@ -106,11 +106,15 @@ export function JSErrors() { From a1a0fb70c37195a56061dbc850bd19a5a8f2c650 Mon Sep 17 00:00:00 2001 From: Shahzad Date: Wed, 23 Sep 2020 11:16:48 +0200 Subject: [PATCH 10/17] update i18n --- .../apm/public/components/app/RumDashboard/translations.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/apm/public/components/app/RumDashboard/translations.ts b/x-pack/plugins/apm/public/components/app/RumDashboard/translations.ts index 106bbc9a38e97..042e279655d7e 100644 --- a/x-pack/plugins/apm/public/components/app/RumDashboard/translations.ts +++ b/x-pack/plugins/apm/public/components/app/RumDashboard/translations.ts @@ -46,7 +46,7 @@ export const I18LABELS = { jsErrors: i18n.translate( 'xpack.apm.rum.dashboard.impactfulMetrics.jsErrors', { - defaultMessage: 'Javascript errors', + defaultMessage: 'JavaScript errors', } ), highTrafficPages: i18n.translate( From 895e87b99d02f8d73453ebde02e3d1e094dbcd38 Mon Sep 17 00:00:00 2001 From: Shahzad Date: Wed, 23 Sep 2020 12:29:42 +0200 Subject: [PATCH 11/17] fix i18n --- .../components/app/RumDashboard/ImpactfulMetrics/JSErrors.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/apm/public/components/app/RumDashboard/ImpactfulMetrics/JSErrors.tsx b/x-pack/plugins/apm/public/components/app/RumDashboard/ImpactfulMetrics/JSErrors.tsx index 4b9fd01f8c917..805b328cb1fb0 100644 --- a/x-pack/plugins/apm/public/components/app/RumDashboard/ImpactfulMetrics/JSErrors.tsx +++ b/x-pack/plugins/apm/public/components/app/RumDashboard/ImpactfulMetrics/JSErrors.tsx @@ -106,7 +106,7 @@ export function JSErrors() { Date: Wed, 23 Sep 2020 16:41:37 +0200 Subject: [PATCH 12/17] improve test resiliance --- .../step_definitions/csm/csm_filters.ts | 44 ++++++++++++++----- .../csm/service_name_filter.ts | 8 ++-- x-pack/plugins/apm/e2e/ingest-data/replay.js | 2 +- .../LocalUIFilters/Filter/FilterBadgeList.tsx | 5 ++- .../shared/LocalUIFilters/Filter/index.tsx | 3 +- 5 files changed, 43 insertions(+), 19 deletions(-) diff --git a/x-pack/plugins/apm/e2e/cypress/support/step_definitions/csm/csm_filters.ts b/x-pack/plugins/apm/e2e/cypress/support/step_definitions/csm/csm_filters.ts index c17845fd61468..75974ef9c202c 100644 --- a/x-pack/plugins/apm/e2e/cypress/support/step_definitions/csm/csm_filters.ts +++ b/x-pack/plugins/apm/e2e/cypress/support/step_definitions/csm/csm_filters.ts @@ -14,16 +14,40 @@ When(/^the user filters by "([^"]*)"$/, (filterName) => { cy.get('.euiStat__title-isLoading').should('not.be.visible'); cy.get(`#local-filter-${filterName}`).click(); - if (filterName === 'os') { - cy.get('span.euiSelectableListItem__text', DEFAULT_TIMEOUT) - .contains('Mac OS X') - .click(); - } else { - cy.get('span.euiSelectableListItem__text', DEFAULT_TIMEOUT) - .contains('DE') - .click(); - } - cy.get('[data-cy=applyFilter]').click(); + cy.get(`#local-filter-popover-${filterName}`, DEFAULT_TIMEOUT).within(() => { + if (filterName === 'os') { + const osItem = cy.get('li.euiSelectableListItem', DEFAULT_TIMEOUT).eq(2); + osItem.should('have.text', 'Mac OS X8 '); + osItem.click(); + + // sometimes click doesn't work as expected so we need to retry here + osItem.invoke('attr', 'aria-selected').then((val) => { + if (val === 'false') { + cy.get('li.euiSelectableListItem', DEFAULT_TIMEOUT).eq(2).click(); + } + }); + } else { + const deItem = cy.get('li.euiSelectableListItem', DEFAULT_TIMEOUT).eq(0); + deItem.should('have.text', 'DE28 '); + deItem.click(); + + // sometimes click doesn't work as expected so we need to retry here + deItem.invoke('attr', 'aria-selected').then((val) => { + if (val === 'false') { + cy.get('li.euiSelectableListItem', DEFAULT_TIMEOUT).eq(0).click(); + } + }); + } + cy.get('[data-cy=applyFilter]').click(); + }); + + cy.get(`div#local-filter-values-${filterName}`, DEFAULT_TIMEOUT).within( + () => { + cy.get('span.euiBadge__content') + .eq(0) + .should('have.text', filterName === 'os' ? 'Mac OS X' : 'DE'); + } + ); }); Then(/^it filters the client metrics "([^"]*)"$/, (filterName) => { diff --git a/x-pack/plugins/apm/e2e/cypress/support/step_definitions/csm/service_name_filter.ts b/x-pack/plugins/apm/e2e/cypress/support/step_definitions/csm/service_name_filter.ts index 4169149bc7339..b3899a5649b72 100644 --- a/x-pack/plugins/apm/e2e/cypress/support/step_definitions/csm/service_name_filter.ts +++ b/x-pack/plugins/apm/e2e/cypress/support/step_definitions/csm/service_name_filter.ts @@ -5,15 +5,13 @@ */ import { When, Then } from 'cypress-cucumber-preprocessor/steps'; -import { DEFAULT_TIMEOUT } from '../apm'; import { verifyClientMetrics } from './client_metrics_helper'; +import { DEFAULT_TIMEOUT } from './csm_dashboard'; -When('the user changes the selected service name', (filterName) => { +When('the user changes the selected service name', () => { // wait for all loading to finish cy.get('kbnLoadingIndicator').should('not.be.visible'); - cy.get(`[data-cy=serviceNameFilter]`, { timeout: DEFAULT_TIMEOUT }).select( - 'client' - ); + cy.get(`[data-cy=serviceNameFilter]`, DEFAULT_TIMEOUT).select('client'); }); Then(`it displays relevant client metrics`, () => { diff --git a/x-pack/plugins/apm/e2e/ingest-data/replay.js b/x-pack/plugins/apm/e2e/ingest-data/replay.js index 0cc2a572ad9b4..962926e84e144 100644 --- a/x-pack/plugins/apm/e2e/ingest-data/replay.js +++ b/x-pack/plugins/apm/e2e/ingest-data/replay.js @@ -96,7 +96,7 @@ function setRumAgent(item) { if (item.body) { item.body = item.body.replace( '"name":"client"', - '"name":"opbean-client-rum"' + '"name":"elastic-frontend"' ); } } diff --git a/x-pack/plugins/apm/public/components/shared/LocalUIFilters/Filter/FilterBadgeList.tsx b/x-pack/plugins/apm/public/components/shared/LocalUIFilters/Filter/FilterBadgeList.tsx index ed8d865d2d288..ee240cfef3b21 100644 --- a/x-pack/plugins/apm/public/components/shared/LocalUIFilters/Filter/FilterBadgeList.tsx +++ b/x-pack/plugins/apm/public/components/shared/LocalUIFilters/Filter/FilterBadgeList.tsx @@ -19,6 +19,7 @@ const BadgeText = styled.div` interface Props { value: string[]; onRemove: (val: string) => void; + name: string; } const removeFilterLabel = i18n.translate( @@ -26,9 +27,9 @@ const removeFilterLabel = i18n.translate( { defaultMessage: 'Remove filter' } ); -function FilterBadgeList({ onRemove, value }: Props) { +function FilterBadgeList({ onRemove, value, name }: Props) { return ( - + {value.map((val) => ( {(list, search) => ( - + @@ -159,6 +159,7 @@ function Filter({ name, title, options, onChange, value, showCount }: Props) { {value.length ? ( <> { onChange(value.filter((v) => val !== v)); }} From ec2e075c21a32cbbb6c44fe58d501a8ce8b045b0 Mon Sep 17 00:00:00 2001 From: Shahzad Date: Thu, 24 Sep 2020 12:17:03 +0200 Subject: [PATCH 13/17] improve code ownership --- .github/CODEOWNERS | 1 + .../apm/server/routes/create_apm_api.ts | 30 ++----------- .../apm/server/routes/create_ux_api.ts | 43 +++++++++++++++++++ 3 files changed, 48 insertions(+), 26 deletions(-) create mode 100644 x-pack/plugins/apm/server/routes/create_ux_api.ts diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 8a8cc5c5e448c..8122f0a7a4cfa 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -70,6 +70,7 @@ /x-pack/plugins/apm/public/components/app/RumDashboard @elastic/uptime /x-pack/plugins/apm/server/lib/rum_client @elastic/uptime /x-pack/plugins/apm/server/routes/rum_client.ts @elastic/uptime +/x-pack/plugins/apm/server/routes/create_ux_api.ts @elastic/uptime /x-pack/plugins/apm/server/projections/rum_page_load_transactions.ts @elastic/uptime # Beats 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 b49309a9b302c..cb763832a50f5 100644 --- a/x-pack/plugins/apm/server/routes/create_apm_api.ts +++ b/x-pack/plugins/apm/server/routes/create_apm_api.ts @@ -58,7 +58,6 @@ import { transactionsLocalFiltersRoute, serviceNodesLocalFiltersRoute, uiFiltersEnvironmentsRoute, - rumOverviewLocalFiltersRoute, } from './ui_filters'; import { createApi } from './create_api'; import { serviceMapRoute, serviceMapServiceNodeRoute } from './service_map'; @@ -69,18 +68,6 @@ import { listCustomLinksRoute, customLinkTransactionRoute, } from './settings/custom_link'; -import { - rumClientMetricsRoute, - rumPageViewsTrendRoute, - rumPageLoadDistributionRoute, - rumPageLoadDistBreakdownRoute, - rumServicesRoute, - rumVisitorsBreakdownRoute, - rumWebCoreVitals, - rumJSErrors, - rumUrlSearch, - rumLongTaskMetrics, -} from './rum_client'; import { observabilityOverviewHasDataRoute, observabilityOverviewRoute, @@ -90,6 +77,7 @@ import { createAnomalyDetectionJobsRoute, anomalyDetectionEnvironmentsRoute, } from './settings/anomaly_detection'; +import { createUXAPIRoutes } from './create_ux_api'; const createApmApi = () => { const api = createApi() @@ -166,19 +154,6 @@ const createApmApi = () => { .add(listCustomLinksRoute) .add(customLinkTransactionRoute) - // Rum Overview - .add(rumOverviewLocalFiltersRoute) - .add(rumPageViewsTrendRoute) - .add(rumPageLoadDistributionRoute) - .add(rumPageLoadDistBreakdownRoute) - .add(rumClientMetricsRoute) - .add(rumServicesRoute) - .add(rumVisitorsBreakdownRoute) - .add(rumWebCoreVitals) - .add(rumJSErrors) - .add(rumUrlSearch) - .add(rumLongTaskMetrics) - // Observability dashboard .add(observabilityOverviewHasDataRoute) .add(observabilityOverviewRoute) @@ -188,6 +163,9 @@ const createApmApi = () => { .add(createAnomalyDetectionJobsRoute) .add(anomalyDetectionEnvironmentsRoute); + // User Experience app api routes + createUXAPIRoutes(api); + return api; }; diff --git a/x-pack/plugins/apm/server/routes/create_ux_api.ts b/x-pack/plugins/apm/server/routes/create_ux_api.ts new file mode 100644 index 0000000000000..a02ed260a2873 --- /dev/null +++ b/x-pack/plugins/apm/server/routes/create_ux_api.ts @@ -0,0 +1,43 @@ +/* + * 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. + */ + +/* + * 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 { rumOverviewLocalFiltersRoute } from './ui_filters'; + +import { ServerAPI } from './typings'; +import { + rumClientMetricsRoute, + rumJSErrors, + rumLongTaskMetrics, + rumPageLoadDistBreakdownRoute, + rumPageLoadDistributionRoute, + rumPageViewsTrendRoute, + rumServicesRoute, + rumUrlSearch, + rumVisitorsBreakdownRoute, + rumWebCoreVitals, +} from './rum_client'; + +export const createUXAPIRoutes = (api: ServerAPI<{}>) => { + api + // Rum Overview + .add(rumOverviewLocalFiltersRoute) + .add(rumPageViewsTrendRoute) + .add(rumPageLoadDistributionRoute) + .add(rumPageLoadDistBreakdownRoute) + .add(rumClientMetricsRoute) + .add(rumServicesRoute) + .add(rumVisitorsBreakdownRoute) + .add(rumWebCoreVitals) + .add(rumJSErrors) + .add(rumUrlSearch) + .add(rumLongTaskMetrics); +}; From 866fabe22dfa9728dd7db821a7bd82c63385ee25 Mon Sep 17 00:00:00 2001 From: Shahzad Date: Thu, 24 Sep 2020 13:20:47 +0200 Subject: [PATCH 14/17] revert change --- .github/CODEOWNERS | 1 - .../apm/server/routes/create_apm_api.ts | 32 +++++++++++--- .../apm/server/routes/create_ux_api.ts | 43 ------------------- 3 files changed, 27 insertions(+), 49 deletions(-) delete mode 100644 x-pack/plugins/apm/server/routes/create_ux_api.ts diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 8122f0a7a4cfa..8a8cc5c5e448c 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -70,7 +70,6 @@ /x-pack/plugins/apm/public/components/app/RumDashboard @elastic/uptime /x-pack/plugins/apm/server/lib/rum_client @elastic/uptime /x-pack/plugins/apm/server/routes/rum_client.ts @elastic/uptime -/x-pack/plugins/apm/server/routes/create_ux_api.ts @elastic/uptime /x-pack/plugins/apm/server/projections/rum_page_load_transactions.ts @elastic/uptime # Beats 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 cb763832a50f5..0560b977e708e 100644 --- a/x-pack/plugins/apm/server/routes/create_apm_api.ts +++ b/x-pack/plugins/apm/server/routes/create_apm_api.ts @@ -58,6 +58,7 @@ import { transactionsLocalFiltersRoute, serviceNodesLocalFiltersRoute, uiFiltersEnvironmentsRoute, + rumOverviewLocalFiltersRoute, } from './ui_filters'; import { createApi } from './create_api'; import { serviceMapRoute, serviceMapServiceNodeRoute } from './service_map'; @@ -77,7 +78,18 @@ import { createAnomalyDetectionJobsRoute, anomalyDetectionEnvironmentsRoute, } from './settings/anomaly_detection'; -import { createUXAPIRoutes } from './create_ux_api'; +import { + rumClientMetricsRoute, + rumJSErrors, + rumLongTaskMetrics, + rumPageLoadDistBreakdownRoute, + rumPageLoadDistributionRoute, + rumPageViewsTrendRoute, + rumServicesRoute, + rumUrlSearch, + rumVisitorsBreakdownRoute, + rumWebCoreVitals, +} from './rum_client'; const createApmApi = () => { const api = createApi() @@ -161,10 +173,20 @@ const createApmApi = () => { // Anomaly detection .add(anomalyDetectionJobsRoute) .add(createAnomalyDetectionJobsRoute) - .add(anomalyDetectionEnvironmentsRoute); - - // User Experience app api routes - createUXAPIRoutes(api); + .add(anomalyDetectionEnvironmentsRoute) + + // User Experience app api routes + .add(rumOverviewLocalFiltersRoute) + .add(rumPageViewsTrendRoute) + .add(rumPageLoadDistributionRoute) + .add(rumPageLoadDistBreakdownRoute) + .add(rumClientMetricsRoute) + .add(rumServicesRoute) + .add(rumVisitorsBreakdownRoute) + .add(rumWebCoreVitals) + .add(rumJSErrors) + .add(rumUrlSearch) + .add(rumLongTaskMetrics); return api; }; diff --git a/x-pack/plugins/apm/server/routes/create_ux_api.ts b/x-pack/plugins/apm/server/routes/create_ux_api.ts deleted file mode 100644 index a02ed260a2873..0000000000000 --- a/x-pack/plugins/apm/server/routes/create_ux_api.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. - */ - -/* - * 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 { rumOverviewLocalFiltersRoute } from './ui_filters'; - -import { ServerAPI } from './typings'; -import { - rumClientMetricsRoute, - rumJSErrors, - rumLongTaskMetrics, - rumPageLoadDistBreakdownRoute, - rumPageLoadDistributionRoute, - rumPageViewsTrendRoute, - rumServicesRoute, - rumUrlSearch, - rumVisitorsBreakdownRoute, - rumWebCoreVitals, -} from './rum_client'; - -export const createUXAPIRoutes = (api: ServerAPI<{}>) => { - api - // Rum Overview - .add(rumOverviewLocalFiltersRoute) - .add(rumPageViewsTrendRoute) - .add(rumPageLoadDistributionRoute) - .add(rumPageLoadDistBreakdownRoute) - .add(rumClientMetricsRoute) - .add(rumServicesRoute) - .add(rumVisitorsBreakdownRoute) - .add(rumWebCoreVitals) - .add(rumJSErrors) - .add(rumUrlSearch) - .add(rumLongTaskMetrics); -}; From 8ff79f6da66779915faa1b5857a5066e1619ddd8 Mon Sep 17 00:00:00 2001 From: Shahzad Date: Mon, 28 Sep 2020 12:26:50 +0200 Subject: [PATCH 15/17] revert change --- x-pack/plugins/apm/e2e/ingest-data/replay.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/apm/e2e/ingest-data/replay.js b/x-pack/plugins/apm/e2e/ingest-data/replay.js index 962926e84e144..326cb739e23c6 100644 --- a/x-pack/plugins/apm/e2e/ingest-data/replay.js +++ b/x-pack/plugins/apm/e2e/ingest-data/replay.js @@ -135,7 +135,7 @@ async function init() { spinner.start(); requestProgress.total = items.length; - const limit = pLimit(10); // number of concurrent requests + const limit = pLimit(20); // number of concurrent requests await Promise.all( items.map(async (item) => { try { From 9d6e70ffb35212af63476b273c62534276a679b4 Mon Sep 17 00:00:00 2001 From: Shahzad Date: Mon, 28 Sep 2020 12:39:16 +0200 Subject: [PATCH 16/17] fixed type --- x-pack/plugins/apm/typings/elasticsearch/aggregations.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/apm/typings/elasticsearch/aggregations.ts b/x-pack/plugins/apm/typings/elasticsearch/aggregations.ts index 42ba1b6285fcd..534321201938d 100644 --- a/x-pack/plugins/apm/typings/elasticsearch/aggregations.ts +++ b/x-pack/plugins/apm/typings/elasticsearch/aggregations.ts @@ -155,8 +155,8 @@ export interface AggregationOptionsByType { } & AggregationSourceOptions; bucket_sort: { sort?: SortOptions; - from: number; - size: number; + from?: number; + size?: number; }; } From f80fe402af4a3958cfff43ec25eddfd8c721b0a6 Mon Sep 17 00:00:00 2001 From: Shahzad Date: Mon, 28 Sep 2020 12:46:19 +0200 Subject: [PATCH 17/17] remove unnecessary title for now --- .../app/RumDashboard/ImpactfulMetrics/index.tsx | 12 +----------- .../components/app/RumDashboard/translations.ts | 6 ------ 2 files changed, 1 insertion(+), 17 deletions(-) diff --git a/x-pack/plugins/apm/public/components/app/RumDashboard/ImpactfulMetrics/index.tsx b/x-pack/plugins/apm/public/components/app/RumDashboard/ImpactfulMetrics/index.tsx index 6a3572243a225..34cb6338eb948 100644 --- a/x-pack/plugins/apm/public/components/app/RumDashboard/ImpactfulMetrics/index.tsx +++ b/x-pack/plugins/apm/public/components/app/RumDashboard/ImpactfulMetrics/index.tsx @@ -5,22 +5,12 @@ */ import React from 'react'; -import { - EuiFlexItem, - EuiPanel, - EuiTitle, - EuiFlexGroup, - EuiSpacer, -} from '@elastic/eui'; +import { EuiFlexItem, EuiPanel, EuiFlexGroup, EuiSpacer } from '@elastic/eui'; import { JSErrors } from './JSErrors'; -import { I18LABELS } from '../translations'; export function ImpactfulMetrics() { return ( - -

{I18LABELS.impactfulMetrics}

-
diff --git a/x-pack/plugins/apm/public/components/app/RumDashboard/translations.ts b/x-pack/plugins/apm/public/components/app/RumDashboard/translations.ts index 3a3533f97a370..f92a1d5a5945b 100644 --- a/x-pack/plugins/apm/public/components/app/RumDashboard/translations.ts +++ b/x-pack/plugins/apm/public/components/app/RumDashboard/translations.ts @@ -37,12 +37,6 @@ export const I18LABELS = { defaultMessage: 'Page load distribution', } ), - impactfulMetrics: i18n.translate( - 'xpack.apm.rum.dashboard.impactfulMetrics.label', - { - defaultMessage: 'Impactful metrics', - } - ), jsErrors: i18n.translate( 'xpack.apm.rum.dashboard.impactfulMetrics.jsErrors', {