diff --git a/x-pack/plugins/apm/server/routes/rum_client/__snapshots__/queries.test.ts.snap b/x-pack/plugins/apm/server/routes/rum_client/__snapshots__/queries.test.ts.snap index 6adecb0582ee1..db76ec32f420e 100644 --- a/x-pack/plugins/apm/server/routes/rum_client/__snapshots__/queries.test.ts.snap +++ b/x-pack/plugins/apm/server/routes/rum_client/__snapshots__/queries.test.ts.snap @@ -1,78 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`rum client dashboard queries fetches client metrics 1`] = ` -Object { - "apm": Object { - "events": Array [ - "transaction", - ], - }, - "body": Object { - "aggs": Object { - "hasFetchStartField": Object { - "aggs": Object { - "backEnd": Object { - "percentiles": Object { - "field": "transaction.marks.agent.timeToFirstByte", - "hdr": Object { - "number_of_significant_value_digits": 3, - }, - "percents": Array [ - 50, - ], - }, - }, - "totalPageLoadDuration": Object { - "percentiles": Object { - "field": "transaction.duration.us", - "hdr": Object { - "number_of_significant_value_digits": 3, - }, - "percents": Array [ - 50, - ], - }, - }, - }, - "filter": Object { - "exists": Object { - "field": "transaction.marks.navigationTiming.fetchStart", - }, - }, - }, - }, - "query": Object { - "bool": Object { - "filter": Array [ - Object { - "range": Object { - "@timestamp": Object { - "format": "epoch_millis", - "gte": 0, - "lte": 50000, - }, - }, - }, - Object { - "term": Object { - "transaction.type": "page-load", - }, - }, - Object { - "term": Object { - "service.environment": "staging", - }, - }, - ], - "must_not": Array [], - }, - }, - "size": 0, - "track_total_hits": true, - }, -} -`; - exports[`rum client dashboard queries fetches js errors 1`] = ` Object { "apm": Object { diff --git a/x-pack/plugins/apm/server/routes/rum_client/queries.test.ts b/x-pack/plugins/apm/server/routes/rum_client/queries.test.ts index 12baa775a920c..1dd8e5a727b59 100644 --- a/x-pack/plugins/apm/server/routes/rum_client/queries.test.ts +++ b/x-pack/plugins/apm/server/routes/rum_client/queries.test.ts @@ -9,7 +9,6 @@ import { SearchParamsMock, inspectSearchParams, } from '../../utils/test_helpers'; -import { getClientMetrics } from './get_client_metrics'; import { getPageViewTrends } from './get_page_view_trends'; import { getPageLoadDistribution } from './get_page_load_distribution'; import { getLongTaskMetrics } from './get_long_task_metrics'; @@ -24,20 +23,6 @@ describe('rum client dashboard queries', () => { mock.teardown(); }); - it('fetches client metrics', async () => { - mock = await inspectSearchParams( - (setup) => - getClientMetrics({ - setup, - start: 0, - end: 50000, - }), - { uiFilters: { environment: 'staging' } } - ); - - expect(mock.params).toMatchSnapshot(); - }); - it('fetches page view trends', async () => { mock = await inspectSearchParams( (setup) => diff --git a/x-pack/plugins/apm/server/routes/rum_client/route.ts b/x-pack/plugins/apm/server/routes/rum_client/route.ts index 8807d16afbb66..ac9d8e6f38597 100644 --- a/x-pack/plugins/apm/server/routes/rum_client/route.ts +++ b/x-pack/plugins/apm/server/routes/rum_client/route.ts @@ -8,7 +8,6 @@ import * as t from 'io-ts'; import { Logger } from '@kbn/core/server'; import { isoToEpochRt } from '@kbn/io-ts-utils'; import { setupRequest, Setup } from '../../lib/helpers/setup_request'; -import { getClientMetrics } from './get_client_metrics'; import { getJSErrors } from './get_js_errors'; import { getLongTaskMetrics } from './get_long_task_metrics'; import { getPageLoadDistribution } from './get_page_load_distribution'; @@ -61,36 +60,6 @@ const uxQueryRt = t.intersection([ t.partial({ urlQuery: t.string, percentile: t.string }), ]); -const rumClientMetricsRoute = createApmServerRoute({ - endpoint: 'GET /internal/apm/ux/client-metrics', - params: t.type({ - query: uxQueryRt, - }), - options: { tags: ['access:apm'] }, - handler: async ( - resources - ): Promise<{ - pageViews: { value: number }; - totalPageLoadDuration: { value: number }; - backEnd: { value: number }; - frontEnd: { value: number }; - }> => { - const setup = await setupUXRequest(resources); - - const { - query: { urlQuery, percentile, start, end }, - } = resources.params; - - return getClientMetrics({ - setup, - urlQuery, - percentile: percentile ? Number(percentile) : undefined, - start, - end, - }); - }, -}); - const rumPageLoadDistributionRoute = createApmServerRoute({ endpoint: 'GET /internal/apm/ux/page-load-distribution', params: t.type({ @@ -376,7 +345,6 @@ async function setupUXRequest( } export const rumRouteRepository = { - ...rumClientMetricsRoute, ...rumPageLoadDistributionRoute, ...rumPageLoadDistBreakdownRoute, ...rumPageViewsTrendRoute, diff --git a/x-pack/plugins/ux/common/elasticsearch_fieldnames.ts b/x-pack/plugins/ux/common/elasticsearch_fieldnames.ts index 9bfc0f7596d09..33b4102c478e6 100644 --- a/x-pack/plugins/ux/common/elasticsearch_fieldnames.ts +++ b/x-pack/plugins/ux/common/elasticsearch_fieldnames.ts @@ -13,6 +13,8 @@ export const AGENT = 'agent'; export const AGENT_NAME = 'agent.name'; export const AGENT_VERSION = 'agent.version'; +export const PROCESSOR_EVENT = 'processor.event'; + export const URL_FULL = 'url.full'; export const USER_AGENT_NAME = 'user_agent.name'; diff --git a/x-pack/plugins/ux/public/components/app/rum_dashboard/client_metrics/metrics.tsx b/x-pack/plugins/ux/public/components/app/rum_dashboard/client_metrics/metrics.tsx index f8196db691073..e2d721b5a991e 100644 --- a/x-pack/plugins/ux/public/components/app/rum_dashboard/client_metrics/metrics.tsx +++ b/x-pack/plugins/ux/public/components/app/rum_dashboard/client_metrics/metrics.tsx @@ -16,9 +16,8 @@ import { EuiToolTip, EuiIconTip, } from '@elastic/eui'; -import { useFetcher } from '../../../../hooks/use_fetcher'; +import { useClientMetricsQuery } from '../../../../hooks/use_client_metrics_query'; import { I18LABELS } from '../translations'; -import { useUxQuery } from '../hooks/use_ux_query'; import { formatToSec } from '../ux_metrics/key_ux_metrics'; import { CsmSharedContext } from '../csm_shared_context'; @@ -49,23 +48,7 @@ function PageViewsTotalTitle({ pageViews }: { pageViews?: number }) { } export function Metrics() { - const uxQuery = useUxQuery(); - - const { data, status } = useFetcher( - (callApmApi) => { - if (uxQuery) { - return callApmApi('GET /internal/apm/ux/client-metrics', { - params: { - query: { - ...uxQuery, - }, - }, - }); - } - return Promise.resolve(null); - }, - [uxQuery] - ); + const { data, loading } = useClientMetricsQuery(); const { setSharedData } = useContext(CsmSharedContext); @@ -90,7 +73,7 @@ export function Metrics() { /> } - isLoading={status !== 'success'} + isLoading={!!loading} /> @@ -106,7 +89,7 @@ export function Metrics() { /> } - isLoading={status !== 'success'} + isLoading={!!loading} /> @@ -122,7 +105,7 @@ export function Metrics() { /> } - isLoading={status !== 'success'} + isLoading={!!loading} /> @@ -130,7 +113,7 @@ export function Metrics() { titleSize="l" title={} description={I18LABELS.pageViews} - isLoading={status !== 'success'} + isLoading={!!loading} /> diff --git a/x-pack/plugins/ux/public/hooks/use_client_metrics_query.ts b/x-pack/plugins/ux/public/hooks/use_client_metrics_query.ts new file mode 100644 index 0000000000000..a28e59453b1ee --- /dev/null +++ b/x-pack/plugins/ux/public/hooks/use_client_metrics_query.ts @@ -0,0 +1,59 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { useEsSearch } from '@kbn/observability-plugin/public'; +import { useMemo } from 'react'; +import { useDataView } from '../components/app/rum_dashboard/local_uifilters/use_data_view'; +import { useLegacyUrlParams } from '../context/url_params_context/use_url_params'; +import { callDateMath } from '../services/data/call_date_math'; +import { clientMetricsQuery } from '../services/data/client_metrics_query'; + +export function useClientMetricsQuery() { + const { + rangeId, + urlParams: { start, end, percentile = 50, searchTerm }, + uxUiFilters, + } = useLegacyUrlParams(); + const { dataViewTitle } = useDataView(); + const { data: esQueryResponse, loading } = useEsSearch( + { + index: dataViewTitle, + ...clientMetricsQuery( + callDateMath(start), + callDateMath(end), + percentile, + searchTerm, + uxUiFilters + ), + }, + [start, end, percentile, searchTerm, uxUiFilters, dataViewTitle, rangeId], + { name: 'UxClientMetrics' } + ); + + const data = useMemo(() => { + if (!esQueryResponse) return {}; + + const { + hasFetchStartField: { backEnd, totalPageLoadDuration }, + } = esQueryResponse.aggregations!; + + const pkey = percentile.toFixed(1); + + const totalPageLoadDurationValue = totalPageLoadDuration.values[pkey] ?? 0; + const totalPageLoadDurationValueMs = totalPageLoadDurationValue / 1000; // Microseconds to milliseconds + const backendValue = backEnd.values[pkey] ?? 0; + + return { + pageViews: { value: (esQueryResponse.hits.total as any as number) ?? 0 }, + totalPageLoadDuration: { value: totalPageLoadDurationValueMs }, + backEnd: { value: backendValue }, + frontEnd: { value: totalPageLoadDurationValueMs - backendValue }, + }; + }, [esQueryResponse, percentile]); + + return { data, loading }; +} diff --git a/x-pack/plugins/ux/public/services/data/__snapshots__/client_metrics_query.test.ts.snap b/x-pack/plugins/ux/public/services/data/__snapshots__/client_metrics_query.test.ts.snap new file mode 100644 index 0000000000000..9957c50bf52c9 --- /dev/null +++ b/x-pack/plugins/ux/public/services/data/__snapshots__/client_metrics_query.test.ts.snap @@ -0,0 +1,76 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`clientMetricsQuery fetches client metrics 1`] = ` +Object { + "body": Object { + "aggs": Object { + "hasFetchStartField": Object { + "aggs": Object { + "backEnd": Object { + "percentiles": Object { + "field": "transaction.marks.agent.timeToFirstByte", + "hdr": Object { + "number_of_significant_value_digits": 3, + }, + "percents": Array [ + 50, + ], + }, + }, + "totalPageLoadDuration": Object { + "percentiles": Object { + "field": "transaction.duration.us", + "hdr": Object { + "number_of_significant_value_digits": 3, + }, + "percents": Array [ + 50, + ], + }, + }, + }, + "filter": Object { + "exists": Object { + "field": "transaction.marks.navigationTiming.fetchStart", + }, + }, + }, + }, + "query": Object { + "bool": Object { + "filter": Array [ + Object { + "range": Object { + "@timestamp": Object { + "format": "epoch_millis", + "gte": 0, + "lte": 50000, + }, + }, + }, + Object { + "term": Object { + "transaction.type": "page-load", + }, + }, + Object { + "terms": Object { + "processor.event": Array [ + "transaction", + ], + }, + }, + Object { + "term": Object { + "service.environment": "staging", + }, + }, + ], + "must_not": Array [], + }, + }, + "size": 0, + "track_total_hits": true, + }, +} +`; \ No newline at end of file diff --git a/x-pack/plugins/ux/public/services/data/__snapshots__/service_name_query.test.ts.snap b/x-pack/plugins/ux/public/services/data/__snapshots__/service_name_query.test.ts.snap index 45cebebe8f386..2a3fbbd8b120f 100644 --- a/x-pack/plugins/ux/public/services/data/__snapshots__/service_name_query.test.ts.snap +++ b/x-pack/plugins/ux/public/services/data/__snapshots__/service_name_query.test.ts.snap @@ -28,6 +28,13 @@ Object { "transaction.type": "page-load", }, }, + Object { + "terms": Object { + "processor.event": Array [ + "transaction", + ], + }, + }, Object { "exists": Object { "field": "transaction.marks.navigationTiming.fetchStart", diff --git a/x-pack/plugins/ux/public/services/data/client_metrics_query.test.ts b/x-pack/plugins/ux/public/services/data/client_metrics_query.test.ts new file mode 100644 index 0000000000000..7af6b0c7bcfd3 --- /dev/null +++ b/x-pack/plugins/ux/public/services/data/client_metrics_query.test.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { clientMetricsQuery } from './client_metrics_query'; + +describe('clientMetricsQuery', () => { + it('fetches client metrics', () => { + const query = clientMetricsQuery(0, 50000, 50, '', { + environment: 'staging', + }); + expect(query).toMatchSnapshot(); + }); +}); diff --git a/x-pack/plugins/apm/server/routes/rum_client/get_client_metrics.ts b/x-pack/plugins/ux/public/services/data/client_metrics_query.ts similarity index 55% rename from x-pack/plugins/apm/server/routes/rum_client/get_client_metrics.ts rename to x-pack/plugins/ux/public/services/data/client_metrics_query.ts index 40352db9f18a6..1ab7eacb59855 100644 --- a/x-pack/plugins/apm/server/routes/rum_client/get_client_metrics.ts +++ b/x-pack/plugins/ux/public/services/data/client_metrics_query.ts @@ -5,27 +5,22 @@ * 2.0. */ -import { getRumPageLoadTransactionsProjection } from '../../projections/rum_page_load_transactions'; -import { mergeProjection } from '../../projections/util/merge_projection'; -import { SetupUX } from './route'; +import { mergeProjection } from '../../../common/utils/merge_projection'; +import { SetupUX, UxUIFilters } from '../../../typings/ui_filters'; import { TRANSACTION_TIME_TO_FIRST_BYTE, TRANSACTION_DURATION, } from '../../../common/elasticsearch_fieldnames'; +import { getRumPageLoadTransactionsProjection } from './projections'; -export async function getClientMetrics({ - setup, - urlQuery, - percentile = 50, - start, - end, -}: { - setup: SetupUX; - urlQuery?: string; - percentile?: number; - start: number; - end: number; -}) { +export function clientMetricsQuery( + start: number, + end: number, + percentile: number = 50, + urlQuery?: string, + uiFilters?: UxUIFilters +) { + const setup: SetupUX = { uiFilters: uiFilters ? uiFilters : {} }; const projection = getRumPageLoadTransactionsProjection({ setup, urlQuery, @@ -68,22 +63,5 @@ export async function getClientMetrics({ }, }); - const { apmEventClient } = setup; - const response = await apmEventClient.search('get_client_metrics', params); - const { - hasFetchStartField: { backEnd, totalPageLoadDuration }, - } = response.aggregations!; - - const pkey = percentile.toFixed(1); - - const totalPageLoadDurationValue = totalPageLoadDuration.values[pkey] ?? 0; - const totalPageLoadDurationValueMs = totalPageLoadDurationValue / 1000; // Microseconds to milliseconds - const backendValue = backEnd.values[pkey] ?? 0; - - return { - pageViews: { value: response.hits.total.value ?? 0 }, - totalPageLoadDuration: { value: totalPageLoadDurationValueMs }, - backEnd: { value: backendValue }, - frontEnd: { value: totalPageLoadDurationValueMs - backendValue }, - }; + return params; } diff --git a/x-pack/plugins/ux/public/services/data/projections.ts b/x-pack/plugins/ux/public/services/data/projections.ts index b860e700dc241..84dc4939cc39a 100644 --- a/x-pack/plugins/ux/public/services/data/projections.ts +++ b/x-pack/plugins/ux/public/services/data/projections.ts @@ -4,7 +4,10 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { TRANSACTION_TYPE } from '../../../common/elasticsearch_fieldnames'; +import { + TRANSACTION_TYPE, + PROCESSOR_EVENT, +} from '../../../common/elasticsearch_fieldnames'; import { ProcessorEvent } from '../../../common/processor_event'; import { TRANSACTION_PAGE_LOAD } from '../../../common/transaction_types'; import { SetupUX } from '../../../typings/ui_filters'; @@ -30,6 +33,7 @@ export function getRumPageLoadTransactionsProjection({ filter: [ ...rangeQuery(start, end), { term: { [TRANSACTION_TYPE]: TRANSACTION_PAGE_LOAD } }, + { terms: { [PROCESSOR_EVENT]: [ProcessorEvent.transaction] } }, ...(checkFetchStartFieldExists ? [ { @@ -56,9 +60,6 @@ export function getRumPageLoadTransactionsProjection({ }; return { - apm: { - events: [ProcessorEvent.transaction], - }, body: { query: { bool, diff --git a/x-pack/plugins/ux/public/services/data/service_name_query.ts b/x-pack/plugins/ux/public/services/data/service_name_query.ts index 34dce62f0f587..76eea53629e7e 100644 --- a/x-pack/plugins/ux/public/services/data/service_name_query.ts +++ b/x-pack/plugins/ux/public/services/data/service_name_query.ts @@ -37,6 +37,6 @@ export function serviceNameQuery( }, }, }); - const { apm: _apm, ...rest } = params; - return rest; + + return params; } diff --git a/x-pack/plugins/ux/public/services/data/url_search_query.ts b/x-pack/plugins/ux/public/services/data/url_search_query.ts index aa162e9174c01..e9f01ad6f827e 100644 --- a/x-pack/plugins/ux/public/services/data/url_search_query.ts +++ b/x-pack/plugins/ux/public/services/data/url_search_query.ts @@ -53,6 +53,5 @@ export function urlSearchQuery( }, }, }); - const { apm: _apm, ...rest } = params; - return rest; + return params; }