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

[CSM] Js errors #77919

Merged
merged 28 commits into from
Sep 28, 2020
Merged
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
75fe1b6
update
shahzad31 Sep 13, 2020
bb6ed3e
Merge branch 'master' into impactful-metrics
shahzad31 Sep 14, 2020
e7cc20c
Merge branch 'master' into js-errors
shahzad31 Sep 17, 2020
42bf52a
added js errors table
shahzad31 Sep 18, 2020
601e96d
Merge branch 'master' into js-errors
shahzad31 Sep 18, 2020
cfb3d34
Merge branch 'master' into js-errors
shahzad31 Sep 21, 2020
1c1327a
fix types
shahzad31 Sep 21, 2020
29a007f
fix type
shahzad31 Sep 21, 2020
36e3684
update test
shahzad31 Sep 21, 2020
3440978
update test
shahzad31 Sep 21, 2020
b27daf8
update test
shahzad31 Sep 21, 2020
c32a55e
Merge branch 'master' into js-errors
shahzad31 Sep 22, 2020
758eab6
PR feedback
shahzad31 Sep 22, 2020
ccbbbed
improve local
shahzad31 Sep 22, 2020
f1735b7
Merge branch 'master' into js-errors
shahzad31 Sep 23, 2020
a1a0fb7
update i18n
shahzad31 Sep 23, 2020
222e542
Merge branch 'master' into js-errors
shahzad31 Sep 23, 2020
650d715
Merge branch 'master' into js-errors
shahzad31 Sep 23, 2020
895e87b
fix i18n
shahzad31 Sep 23, 2020
abb4a0c
improve test resiliance
shahzad31 Sep 23, 2020
28fcebc
Merge branch 'master' into js-errors
shahzad31 Sep 24, 2020
ec2e075
improve code ownership
shahzad31 Sep 24, 2020
866fabe
revert change
shahzad31 Sep 24, 2020
96599cf
Merge branch 'master' into js-errors
shahzad31 Sep 24, 2020
504888b
Merge branch 'master' into js-errors
elasticmachine Sep 28, 2020
8ff79f6
revert change
shahzad31 Sep 28, 2020
9d6e70f
fixed type
shahzad31 Sep 28, 2020
f80fe40
remove unnecessary title for now
shahzad31 Sep 28, 2020
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
Original file line number Diff line number Diff line change
Expand Up @@ -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) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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`, () => {
Expand Down
2 changes: 1 addition & 1 deletion x-pack/plugins/apm/e2e/ingest-data/replay.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ function setRumAgent(item) {
if (item.body) {
item.body = item.body.replace(
'"name":"client"',
'"name":"opbean-client-rum"'
'"name":"elastic-frontend"'
);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -45,6 +47,12 @@ export function ClientMetrics() {
[start, end, uiFilters, searchTerm]
);

const { setSharedData } = useContext(CsmSharedContext);

useEffect(() => {
setSharedData({ totalPageViews: data?.pageViews?.value ?? 0 });
}, [data, setSharedData]);

const STAT_STYLE = { width: '240px' };

return (
Expand Down
Original file line number Diff line number Diff line change
@@ -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: JSX.Element[];
}) {
const [newData, setNewData] = useState<SharedData>({ totalPageViews: 0 });

const setSharedData = React.useCallback((data: SharedData) => {
setNewData(data);
}, []);

const value = useMemo(() => {
return { sharedData: newData, setSharedData };
}, [newData, setSharedData]);

return <CsmSharedContext.Provider value={value} children={children} />;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
/*
* 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, { useContext, useState } from 'react';
import {
EuiBasicTable,
EuiFlexItem,
EuiFlexGroup,
EuiSpacer,
EuiTitle,
EuiStat,
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';
import { CsmSharedContext } from '../CsmSharedContext';

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 {
sharedData: { totalPageViews },
} = useContext(CsmSharedContext);

const items = (data?.items ?? []).map(({ errorMessage, count }) => ({
errorMessage,
percent: i18n.translate('xpack.apm.rum.jsErrors.percent', {
defaultMessage: '{pageLoadPercent} %',
values: { pageLoadPercent: ((count / totalPageViews) * 100).toFixed(1) },
}),
}));

const cols = [
{
field: 'errorMessage',
name: I18LABELS.errorMessage,
},
{
name: I18LABELS.impactedPageLoads,
field: 'percent',
align: 'right' as const,
},
];

const onTableChange = ({
page,
}: {
page: { size: number; index: number };
}) => {
setPagination({
pageIndex: page.index,
pageSize: page.size,
});
};

return (
<>
<EuiTitle size="xs">
<h3>{I18LABELS.jsErrors}</h3>
</EuiTitle>
<EuiSpacer size="s" />
<EuiFlexGroup>
<EuiFlexItem grow={false}>
<EuiStat
titleSize="s"
title={
<EuiToolTip content={data?.totalErrors ?? 0}>
<>{numeral(data?.totalErrors ?? 0).format('0 a')}</>
</EuiToolTip>
}
description={I18LABELS.totalErrors}
isLoading={status !== 'success'}
/>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiStat
titleSize="s"
title={i18n.translate('xpack.apm.rum.jsErrors.errorRateValue', {
defaultMessage: '{errorRate} %',
values: {
errorRate: (
((data?.totalErrorPages ?? 0) / totalPageViews) *
100
).toFixed(0),
},
})}
description={I18LABELS.errorRate}
isLoading={status !== 'success'}
/>
</EuiFlexItem>{' '}
</EuiFlexGroup>
<EuiSpacer size="s" />
<EuiBasicTable
loading={status !== 'success'}
responsive={false}
compressed={true}
columns={cols}
items={items}
onChange={onTableChange}
pagination={{
...pagination,
totalItemCount: data?.totalErrorGroups ?? 0,
}}
/>
</>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* 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';

export function ImpactfulMetrics() {
return (
<EuiPanel>
<EuiTitle size="s">
<h3>{I18LABELS.impactfulMetrics}</h3>
</EuiTitle>
<EuiSpacer size="xs" />
<EuiFlexGroup wrap>
<EuiFlexItem style={{ flexBasis: 650 }}>
<JSErrors />
</EuiFlexItem>
</EuiFlexGroup>
</EuiPanel>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { I18LABELS } from './translations';
import { VisitorBreakdown } from './VisitorBreakdown';
import { UXMetrics } from './UXMetrics';
import { VisitorBreakdownMap } from './VisitorBreakdownMap';
import { ImpactfulMetrics } from './ImpactfulMetrics';

export function RumDashboard() {
return (
Expand Down Expand Up @@ -66,6 +67,9 @@ export function RumDashboard() {
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlexItem>
<EuiFlexItem>
<ImpactfulMetrics />
</EuiFlexItem>
</EuiFlexGroup>
);
}
23 changes: 13 additions & 10 deletions x-pack/plugins/apm/public/components/app/RumDashboard/RumHome.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import React from 'react';
import { i18n } from '@kbn/i18n';
import { RumOverview } from '../RumDashboard';
import { RumHeader } from './RumHeader';
import { CsmSharedContextProvider } from './CsmSharedContext';

export const UX_LABEL = i18n.translate('xpack.apm.ux.title', {
defaultMessage: 'User Experience',
Expand All @@ -17,16 +18,18 @@ export const UX_LABEL = i18n.translate('xpack.apm.ux.title', {
export function RumHome() {
return (
<div>
<RumHeader>
<EuiFlexGroup alignItems="center">
<EuiFlexItem grow={false}>
<EuiTitle size="l">
<h1>{UX_LABEL}</h1>
</EuiTitle>
</EuiFlexItem>
</EuiFlexGroup>
</RumHeader>
<RumOverview />
<CsmSharedContextProvider>
<RumHeader>
<EuiFlexGroup alignItems="center">
<EuiFlexItem grow={false}>
<EuiTitle size="l">
<h1>{UX_LABEL}</h1>
</EuiTitle>
</EuiFlexItem>
</EuiFlexGroup>
</RumHeader>
<RumOverview />
</CsmSharedContextProvider>
</div>
);
}
Loading