Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[7.x] [RUM Dashboard] Initial version resubmit (#69531) #69669

Merged
merged 1 commit into from
Jun 23, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

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=

[email protected].2:
version "3.9.2"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.2.tgz#64e9c8e9be6ea583c54607677dd4680a1cf35db9"
integrity sha512-q2ktq4n/uLuNNShyayit+DTobV2ApPEo/6so68JaD5ojvc/6GClBipedB9zNWYxRSAlZXAe405Rlijzl6qDiSw==
[email protected].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