Skip to content

Commit

Permalink
[7.x] [RUM Dashboard] Initial version resubmit (#69531) (#69669)
Browse files Browse the repository at this point in the history
Co-authored-by: Casper Hübertz <casper@formgeist.com>
Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>

Co-authored-by: Casper Hübertz <casper@formgeist.com>
Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
  • Loading branch information
3 people authored Jun 23, 2020
1 parent f8ccb03 commit 188def4
Show file tree
Hide file tree
Showing 59 changed files with 1,553 additions and 48 deletions.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions x-pack/plugins/apm/common/elasticsearch_fieldnames.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,3 +87,9 @@ export const CONTAINER_ID = 'container.id';
export const POD_NAME = 'kubernetes.pod.name';

export const CLIENT_GEO_COUNTRY_ISO_CODE = 'client.geo.country_iso_code';

// RUM Labels
export const TRANSACTION_URL = 'transaction.page.url';
export const CLIENT_GEO = 'client.geo';
export const USER_AGENT_DEVICE = 'user_agent.device.name';
export const USER_AGENT_OS = 'user_agent.os.name';
2 changes: 1 addition & 1 deletion x-pack/plugins/apm/common/projections/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
ERROR_GROUP_ID,
} from '../elasticsearch_fieldnames';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { rangeFilter } from '../../server/lib/helpers/range_filter';
import { rangeFilter } from '../utils/range_filter';

export function getErrorGroupsProjection({
setup,
Expand Down
2 changes: 1 addition & 1 deletion x-pack/plugins/apm/common/projections/metrics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
SERVICE_NODE_NAME,
} from '../elasticsearch_fieldnames';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { rangeFilter } from '../../server/lib/helpers/range_filter';
import { rangeFilter } from '../utils/range_filter';
import { SERVICE_NODE_NAME_MISSING } from '../service_nodes';

function getServiceNodeNameFilters(serviceNodeName?: string) {
Expand Down
46 changes: 46 additions & 0 deletions x-pack/plugins/apm/common/projections/rum_overview.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import {
Setup,
SetupTimeRange,
SetupUIFilters,
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
} from '../../server/lib/helpers/setup_request';
import { PROCESSOR_EVENT, TRANSACTION_TYPE } from '../elasticsearch_fieldnames';
import { rangeFilter } from '../utils/range_filter';

export function getRumOverviewProjection({
setup,
}: {
setup: Setup & SetupTimeRange & SetupUIFilters;
}) {
const { start, end, uiFiltersES, indices } = setup;

const bool = {
filter: [
{ range: rangeFilter(start, end) },
{ term: { [PROCESSOR_EVENT]: 'transaction' } },
{ term: { [TRANSACTION_TYPE]: 'page-load' } },
{
// Adding this filter to cater for some inconsistent rum data
exists: {
field: 'transaction.marks.navigationTiming.fetchStart',
},
},
...uiFiltersES,
],
};

return {
index: indices['apm_oss.transactionIndices'],
body: {
query: {
bool,
},
},
};
}
2 changes: 1 addition & 1 deletion x-pack/plugins/apm/common/projections/services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
} from '../../server/lib/helpers/setup_request';
import { SERVICE_NAME, PROCESSOR_EVENT } from '../elasticsearch_fieldnames';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { rangeFilter } from '../../server/lib/helpers/range_filter';
import { rangeFilter } from '../utils/range_filter';

export function getServicesProjection({
setup,
Expand Down
2 changes: 1 addition & 1 deletion x-pack/plugins/apm/common/projections/transactions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
TRANSACTION_NAME,
} from '../elasticsearch_fieldnames';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { rangeFilter } from '../../server/lib/helpers/range_filter';
import { rangeFilter } from '../utils/range_filter';

export function getTransactionsProjection({
setup,
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/apm/common/projections/typings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,5 @@ export enum PROJECTION {
METRICS = 'metrics',
ERROR_GROUPS = 'errorGroups',
SERVICE_NODES = 'serviceNodes',
RUM_OVERVIEW = 'rumOverview',
}
20 changes: 15 additions & 5 deletions x-pack/plugins/apm/e2e/cypress/integration/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,30 @@

/* eslint-disable import/no-extraneous-dependencies */

const RANGE_FROM = '2020-03-04T12:30:00.000Z';
const RANGE_TO = '2020-03-04T13:00:00.000Z';
const RANGE_FROM = '2020-06-01T14:59:32.686Z';
const RANGE_TO = '2020-06-16T16:59:36.219Z';

const BASE_URL = Cypress.config().baseUrl;

/** The default time in ms to wait for a Cypress command to complete */
export const DEFAULT_TIMEOUT = 60 * 1000;

export function loginAndWaitForPage(url: string) {
export function loginAndWaitForPage(
url: string,
dateRange?: { to: string; from: string }
) {
const username = Cypress.env('elasticsearch_username');
const password = Cypress.env('elasticsearch_password');

cy.log(`Authenticating via ${username} / ${password}`);

const fullUrl = `${BASE_URL}${url}?rangeFrom=${RANGE_FROM}&rangeTo=${RANGE_TO}`;
let rangeFrom = RANGE_FROM;
let rangeTo = RANGE_TO;
if (dateRange) {
rangeFrom = dateRange.from;
rangeTo = dateRange.to;
}

const fullUrl = `${BASE_URL}${url}?rangeFrom=${rangeFrom}&rangeTo=${rangeTo}`;
cy.visit(fullUrl, { auth: { username, password } });

cy.viewport('macbook-15');
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Feature: RUM Dashboard

Scenario: Client metrics
Given a user browses the APM UI application for RUM Data
When the user inspects the real user monitoring tab
Then should redirect to rum dashboard
And should have correct client metrics
23 changes: 15 additions & 8 deletions x-pack/plugins/apm/e2e/cypress/integration/snapshots.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
module.exports = {
APM: {
'Transaction duration charts': {
'1': '350 ms',
'2': '175 ms',
'3': '0 ms',
},
"__version": "4.5.0",
"APM": {
"Transaction duration charts": {
"1": "55 ms",
"2": "28 ms",
"3": "0 ms"
}
},
__version: '4.5.0',
};
"RUM Dashboard": {
"Client metrics": {
"1": "62",
"2": "0.07 sec",
"3": "0.01 sec"
}
}
}
Original file line number Diff line number Diff line change
@@ -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 { Given, When, Then } from 'cypress-cucumber-preprocessor/steps';
import { loginAndWaitForPage } from '../../integration/helpers';

/** The default time in ms to wait for a Cypress command to complete */
export const DEFAULT_TIMEOUT = 60 * 1000;

Given(`a user browses the APM UI application for RUM Data`, () => {
// open service overview page
const RANGE_FROM = 'now-24h';
const RANGE_TO = 'now';
loginAndWaitForPage(`/app/apm#/services`, { from: RANGE_FROM, to: RANGE_TO });
});

When(`the user inspects the real user monitoring tab`, () => {
// click rum tab
cy.get(':contains(Real User Monitoring)', { timeout: DEFAULT_TIMEOUT })
.last()
.click({ force: true });
});

Then(`should redirect to rum dashboard`, () => {
cy.url().should('contain', `/app/apm#/rum-overview`);
});

Then(`should have correct 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();
});
6 changes: 5 additions & 1 deletion x-pack/plugins/apm/e2e/ingest-data/replay.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,11 @@ async function init() {
.split('\n')
.filter((item) => item)
.map((item) => JSON.parse(item))
.filter((item) => item.url === '/intake/v2/events');
.filter((item) => {
return (
item.url === '/intake/v2/events' || item.url === '/intake/v2/rum/events'
);
});

spinner.start();
requestProgress.total = items.length;
Expand Down
2 changes: 1 addition & 1 deletion x-pack/plugins/apm/e2e/run-e2e.sh
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ echo "${bold}Static mock data (logs: ${E2E_DIR}${TMP_DIR}/ingest-data.log)${norm
# Download static data if not already done
if [ ! -e "${TMP_DIR}/events.json" ]; then
echo 'Downloading events.json...'
curl --silent https://storage.googleapis.com/apm-ui-e2e-static-data/events.json --output ${TMP_DIR}/events.json
curl --silent https://storage.googleapis.com/apm-ui-e2e-static-data/2020-06-12.json --output ${TMP_DIR}/events.json
fi

# echo "Deleting existing indices (apm* and .apm*)"
Expand Down
8 changes: 4 additions & 4 deletions x-pack/plugins/apm/e2e/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5561,10 +5561,10 @@ typedarray@^0.0.6:
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=

typescript@3.9.2:
version "3.9.2"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.2.tgz#64e9c8e9be6ea583c54607677dd4680a1cf35db9"
integrity sha512-q2ktq4n/uLuNNShyayit+DTobV2ApPEo/6so68JaD5ojvc/6GClBipedB9zNWYxRSAlZXAe405Rlijzl6qDiSw==
typescript@3.9.5:
version "3.9.5"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.5.tgz#586f0dba300cde8be52dd1ac4f7e1009c1b13f36"
integrity sha512-hSAifV3k+i6lEoCJ2k6R2Z/rp/H3+8sdmcn5NrS3/3kE7+RyZXm9aqvxWqjEXHAd8b0pShatpcdMTvEdvAJltQ==

umd@^3.0.0:
version "3.0.3"
Expand Down
3 changes: 1 addition & 2 deletions x-pack/plugins/apm/public/application/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import {
KibanaContextProvider,
useUiSetting$,
} from '../../../../../src/plugins/kibana_react/public';
import { px, unit, units } from '../style/variables';
import { px, units } from '../style/variables';
import { UpdateBreadcrumbs } from '../components/app/Main/UpdateBreadcrumbs';
import { APMIndicesPermission } from '../components/app/APMIndicesPermission';
import { ScrollToTopOnPathChange } from '../components/app/Main/ScrollToTopOnPathChange';
Expand All @@ -34,7 +34,6 @@ import { ConfigSchema } from '..';
import 'react-vis/dist/style.css';

const MainContainer = styled.div`
min-width: ${px(unit * 50)};
padding: ${px(units.plus)};
height: 100%;
`;
Expand Down
24 changes: 22 additions & 2 deletions x-pack/plugins/apm/public/components/app/Home/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ import { SetupInstructionsLink } from '../../shared/Links/SetupInstructionsLink'
import { ServiceMap } from '../ServiceMap';
import { ServiceOverview } from '../ServiceOverview';
import { TraceOverview } from '../TraceOverview';
import { RumOverview } from '../RumDashboard';
import { RumOverviewLink } from '../../shared/Links/apm/RumOverviewLink';
import { EndUserExperienceLabel } from '../RumDashboard/translations';

function getHomeTabs({
serviceMapEnabled = true,
Expand Down Expand Up @@ -70,14 +73,27 @@ function getHomeTabs({
});
}

homeTabs.push({
link: (
<RumOverviewLink>
{i18n.translate('xpack.apm.home.rumTabLabel', {
defaultMessage: 'Real User Monitoring',
})}
</RumOverviewLink>
),
render: () => <RumOverview />,
name: 'rum-overview',
});

return homeTabs;
}

const SETTINGS_LINK_LABEL = i18n.translate('xpack.apm.settingsLinkLabel', {
defaultMessage: 'Settings',
});

interface Props {
tab: 'traces' | 'services' | 'service-map';
tab: 'traces' | 'services' | 'service-map' | 'rum-overview';
}

export function Home({ tab }: Props) {
Expand All @@ -93,7 +109,11 @@ export function Home({ tab }: Props) {
<EuiFlexGroup alignItems="center">
<EuiFlexItem grow={false}>
<EuiTitle size="l">
<h1>APM</h1>
<h1>
{selectedTab.name === 'rum-overview'
? EndUserExperienceLabel
: 'APM'}
</h1>
</EuiTitle>
</EuiFlexItem>
<EuiFlexItem grow={false}>
Expand Down
Loading

0 comments on commit 188def4

Please sign in to comment.