diff --git a/x-pack/plugins/apm/e2e/cypress/integration/rum_dashboard.feature b/x-pack/plugins/apm/e2e/cypress/integration/rum_dashboard.feature index bc807d596a272d..c98e3f81b2bc67 100644 --- a/x-pack/plugins/apm/e2e/cypress/integration/rum_dashboard.feature +++ b/x-pack/plugins/apm/e2e/cypress/integration/rum_dashboard.feature @@ -37,3 +37,6 @@ Feature: RUM Dashboard When the user selected the breakdown Then breakdown series should appear in chart + Scenario: Service name filter + When a user changes the selected service name + Then it displays relevant client metrics diff --git a/x-pack/plugins/apm/e2e/cypress/integration/snapshots.js b/x-pack/plugins/apm/e2e/cypress/integration/snapshots.js index acccd86f3e4d7d..ac09e575a46ae2 100644 --- a/x-pack/plugins/apm/e2e/cypress/integration/snapshots.js +++ b/x-pack/plugins/apm/e2e/cypress/integration/snapshots.js @@ -9,17 +9,17 @@ module.exports = { }, "RUM Dashboard": { "Client metrics": { - "1": "62 ", - "2": "0.07 sec", + "1": "55 ", + "2": "0.08 sec", "3": "0.01 sec" }, "Rum page filters (example #1)": { - "1": "15 ", - "2": "0.07 sec", + "1": "8 ", + "2": "0.08 sec", "3": "0.01 sec" }, "Rum page filters (example #2)": { - "1": "35 ", + "1": "28 ", "2": "0.07 sec", "3": "0.01 sec" }, @@ -31,6 +31,11 @@ module.exports = { }, "Page load distribution chart legends": { "1": "Overall" + }, + "Service name filter": { + "1": "7 ", + "2": "0.07 sec", + "3": "0.01 sec" } } } diff --git a/x-pack/plugins/apm/e2e/cypress/support/step_definitions/rum/page_load_dist.ts b/x-pack/plugins/apm/e2e/cypress/support/step_definitions/rum/page_load_dist.ts index 809b22490abd69..89dc3437c3e69f 100644 --- a/x-pack/plugins/apm/e2e/cypress/support/step_definitions/rum/page_load_dist.ts +++ b/x-pack/plugins/apm/e2e/cypress/support/step_definitions/rum/page_load_dist.ts @@ -18,7 +18,9 @@ Given(`a user click page load breakdown filter`, () => { }); When(`the user selected the breakdown`, () => { - cy.get('[data-cy=filter-breakdown-item_Browser]').click(); + cy.get('[data-cy=filter-breakdown-item_Browser]', { + timeout: DEFAULT_TIMEOUT, + }).click(); // click outside popover to close it cy.get('[data-cy=pageLoadDist]').click(); }); diff --git a/x-pack/plugins/apm/e2e/cypress/support/step_definitions/rum/rum_filters.ts b/x-pack/plugins/apm/e2e/cypress/support/step_definitions/rum/rum_filters.ts index 439003351aedbf..2600e5d0733289 100644 --- a/x-pack/plugins/apm/e2e/cypress/support/step_definitions/rum/rum_filters.ts +++ b/x-pack/plugins/apm/e2e/cypress/support/step_definitions/rum/rum_filters.ts @@ -5,6 +5,7 @@ */ import { When, Then } from 'cypress-cucumber-preprocessor/steps'; +import { DEFAULT_TIMEOUT } from './rum_dashboard'; When(/^the user filters by "([^"]*)"$/, (filterName) => { // wait for all loading to finish @@ -13,9 +14,13 @@ When(/^the user filters by "([^"]*)"$/, (filterName) => { cy.get(`#local-filter-${filterName}`).click(); if (filterName === 'os') { - cy.get('button.euiSelectableListItem[title="Mac OS X"]').click(); + cy.get('button.euiSelectableListItem[title="Mac OS X"]', { + timeout: DEFAULT_TIMEOUT, + }).click(); } else { - cy.get('button.euiSelectableListItem[title="DE"]').click(); + cy.get('button.euiSelectableListItem[title="DE"]', { + timeout: DEFAULT_TIMEOUT, + }).click(); } cy.get('[data-cy=applyFilter]').click(); }); diff --git a/x-pack/plugins/apm/e2e/cypress/support/step_definitions/rum/service_name_filter.ts b/x-pack/plugins/apm/e2e/cypress/support/step_definitions/rum/service_name_filter.ts new file mode 100644 index 00000000000000..9a3d7b52674b77 --- /dev/null +++ b/x-pack/plugins/apm/e2e/cypress/support/step_definitions/rum/service_name_filter.ts @@ -0,0 +1,30 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { When, Then } from 'cypress-cucumber-preprocessor/steps'; +import { DEFAULT_TIMEOUT } from '../apm'; + +When('a user changes the selected service name', (filterName) => { + // wait for all loading to finish + cy.get('kbnLoadingIndicator').should('not.be.visible'); + cy.get(`[data-cy=serviceNameFilter]`, { timeout: DEFAULT_TIMEOUT }).select( + 'opbean-client-rum' + ); +}); + +Then(`it displays relevant client metrics`, () => { + const clientMetrics = '[data-cy=client-metrics] .euiStat__title'; + + // wait for all loading to finish + cy.get('kbnLoadingIndicator').should('not.be.visible'); + cy.get('.euiStat__title-isLoading').should('not.be.visible'); + + cy.get(clientMetrics).eq(2).invoke('text').snapshot(); + + cy.get(clientMetrics).eq(1).invoke('text').snapshot(); + + cy.get(clientMetrics).eq(0).invoke('text').snapshot(); +}); diff --git a/x-pack/plugins/apm/e2e/ingest-data/replay.js b/x-pack/plugins/apm/e2e/ingest-data/replay.js index 483cc99df74700..6bab95635f5587 100644 --- a/x-pack/plugins/apm/e2e/ingest-data/replay.js +++ b/x-pack/plugins/apm/e2e/ingest-data/replay.js @@ -69,6 +69,14 @@ function incrementSpinnerCount({ success }) { spinner.text = `Remaining: ${remaining}. Succeeded: ${requestProgress.succeeded}. Failed: ${requestProgress.failed}.`; } let iterIndex = 0; + +function setRumAgent(item) { + item.body = item.body.replace( + '"name":"client"', + '"name":"opbean-client-rum"' + ); +} + async function insertItem(item) { try { const url = `${APM_SERVER_URL}${item.url}`; @@ -78,6 +86,8 @@ async function insertItem(item) { if (item.url === '/intake/v2/rum/events') { if (iterIndex === userAgents.length) { + // set some event agent to opbean + setRumAgent(item); iterIndex = 0; } headers['User-Agent'] = userAgents[iterIndex]; diff --git a/x-pack/plugins/apm/public/components/app/Main/route_config/index.tsx b/x-pack/plugins/apm/public/components/app/Main/route_config/index.tsx index 295f343b411a9b..1625fb4c1409ef 100644 --- a/x-pack/plugins/apm/public/components/app/Main/route_config/index.tsx +++ b/x-pack/plugins/apm/public/components/app/Main/route_config/index.tsx @@ -259,4 +259,13 @@ export const routes: BreadcrumbRoute[] = [ }), name: RouteName.RUM_OVERVIEW, }, + { + exact: true, + path: '/services/:serviceName/rum-overview', + component: () => , + breadcrumb: i18n.translate('xpack.apm.home.rumOverview.title', { + defaultMessage: 'Real User Monitoring', + }), + name: RouteName.RUM_OVERVIEW, + }, ]; diff --git a/x-pack/plugins/apm/public/components/app/RumDashboard/index.tsx b/x-pack/plugins/apm/public/components/app/RumDashboard/index.tsx index c9e475ef15316a..3ddaa66b8de5e5 100644 --- a/x-pack/plugins/apm/public/components/app/RumDashboard/index.tsx +++ b/x-pack/plugins/apm/public/components/app/RumDashboard/index.tsx @@ -11,6 +11,7 @@ import { EuiSpacer, } from '@elastic/eui'; import React, { useMemo } from 'react'; +import { useRouteMatch } from 'react-router-dom'; import { useTrackPageview } from '../../../../../observability/public'; import { LocalUIFilters } from '../../shared/LocalUIFilters'; import { PROJECTION } from '../../../../common/projections/typings'; @@ -37,6 +38,10 @@ export function RumOverview() { urlParams: { start, end }, } = useUrlParams(); + const isRumServiceRoute = useRouteMatch( + '/services/:serviceName/rum-overview' + ); + const { data } = useFetcher( (callApmApi) => { if (start && end) { @@ -61,13 +66,17 @@ export function RumOverview() { - service.serviceName) ?? [] - } - /> - - + {!isRumServiceRoute && ( + <> + service.serviceName) ?? [] + } + /> + + {' '} + + )} diff --git a/x-pack/plugins/apm/public/components/app/ServiceDetails/ServiceDetailTabs.tsx b/x-pack/plugins/apm/public/components/app/ServiceDetails/ServiceDetailTabs.tsx index 81bdbdad805d60..ce60ffa4ba4e36 100644 --- a/x-pack/plugins/apm/public/components/app/ServiceDetails/ServiceDetailTabs.tsx +++ b/x-pack/plugins/apm/public/components/app/ServiceDetails/ServiceDetailTabs.tsx @@ -22,11 +22,17 @@ import { ServiceMap } from '../ServiceMap'; import { ServiceMetrics } from '../ServiceMetrics'; import { ServiceNodeOverview } from '../ServiceNodeOverview'; import { TransactionOverview } from '../TransactionOverview'; -import { RumOverviewLink } from '../../shared/Links/apm/RumOverviewLink'; import { RumOverview } from '../RumDashboard'; +import { RumOverviewLink } from '../../shared/Links/apm/RumOverviewLink'; interface Props { - tab: 'transactions' | 'errors' | 'metrics' | 'nodes' | 'service-map'; + tab: + | 'transactions' + | 'errors' + | 'metrics' + | 'nodes' + | 'service-map' + | 'rum-overview'; } export function ServiceDetailTabs({ tab }: Props) { @@ -115,7 +121,7 @@ export function ServiceDetailTabs({ tab }: Props) { if (isRumAgentName(agentName)) { tabs.push({ link: ( - + {i18n.translate('xpack.apm.home.rumTabLabel', { defaultMessage: 'Real User Monitoring', })} diff --git a/x-pack/plugins/apm/public/components/shared/Links/apm/RumOverviewLink.tsx b/x-pack/plugins/apm/public/components/shared/Links/apm/RumOverviewLink.tsx index abca9817bd69d7..729ed9b10f827d 100644 --- a/x-pack/plugins/apm/public/components/shared/Links/apm/RumOverviewLink.tsx +++ b/x-pack/plugins/apm/public/components/shared/Links/apm/RumOverviewLink.tsx @@ -11,21 +11,17 @@ */ import React from 'react'; import { APMLink, APMLinkExtendProps } from './APMLink'; -import { useUrlParams } from '../../../../hooks/useUrlParams'; -import { pickKeys } from '../../../../../common/utils/pick_keys'; -const RumOverviewLink = (props: APMLinkExtendProps) => { - const { urlParams } = useUrlParams(); +interface RumOverviewLinkProps extends APMLinkExtendProps { + serviceName?: string; +} +export function RumOverviewLink({ + serviceName, + ...rest +}: RumOverviewLinkProps) { + const path = serviceName + ? `/services/${serviceName}/rum-overview` + : '/rum-overview'; - const persistedFilters = pickKeys( - urlParams, - 'transactionResult', - 'host', - 'containerId', - 'podName' - ); - - return ; -}; - -export { RumOverviewLink }; + return ; +} diff --git a/x-pack/plugins/apm/public/components/shared/LocalUIFilters/ServiceNameFilter/index.tsx b/x-pack/plugins/apm/public/components/shared/LocalUIFilters/ServiceNameFilter/index.tsx index e12a4a4831e17b..0bb62bd8efcffd 100644 --- a/x-pack/plugins/apm/public/components/shared/LocalUIFilters/ServiceNameFilter/index.tsx +++ b/x-pack/plugins/apm/public/components/shared/LocalUIFilters/ServiceNameFilter/index.tsx @@ -60,6 +60,7 @@ const ServiceNameFilter = ({ serviceNames }: Props) => {