Skip to content

Commit bafc89e

Browse files
authored
Service overview tab and route (#81972) (#82046)
Placeholder tab and route for service overview page. Fixes #81718.
1 parent 27d7fb8 commit bafc89e

File tree

5 files changed

+324
-4
lines changed

5 files changed

+324
-4
lines changed

x-pack/plugins/apm/public/components/app/Main/route_config/index.tsx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,12 @@ function ServiceDetailsNodes(
9292
return <ServiceDetails {...props} tab="nodes" />;
9393
}
9494

95+
function ServiceDetailsOverview(
96+
props: RouteComponentProps<{ serviceName: string }>
97+
) {
98+
return <ServiceDetails {...props} tab="overview" />;
99+
}
100+
95101
function ServiceDetailsServiceMap(
96102
props: RouteComponentProps<{ serviceName: string }>
97103
) {
@@ -215,6 +221,14 @@ export const routes: APMRouteDefinition[] = [
215221
`/services/${props.match.params.serviceName}/transactions`
216222
)(props),
217223
} as APMRouteDefinition<{ serviceName: string }>,
224+
{
225+
exact: true,
226+
path: '/services/:serviceName/overview',
227+
breadcrumb: i18n.translate('xpack.apm.breadcrumb.overviewTitle', {
228+
defaultMessage: 'Overview',
229+
}),
230+
component: ServiceDetailsOverview,
231+
} as APMRouteDefinition<{ serviceName: string }>,
218232
// errors
219233
{
220234
exact: true,

x-pack/plugins/apm/public/components/app/ServiceDetails/ServiceDetailTabs.tsx

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,24 @@ import { ErrorOverviewLink } from '../../shared/Links/apm/ErrorOverviewLink';
1616
import { MetricOverviewLink } from '../../shared/Links/apm/MetricOverviewLink';
1717
import { ServiceMapLink } from '../../shared/Links/apm/ServiceMapLink';
1818
import { ServiceNodeOverviewLink } from '../../shared/Links/apm/ServiceNodeOverviewLink';
19+
import { ServiceOverviewLink } from '../../shared/Links/apm/service_overview_link';
1920
import { TransactionOverviewLink } from '../../shared/Links/apm/TransactionOverviewLink';
2021
import { ErrorGroupOverview } from '../ErrorGroupOverview';
2122
import { ServiceMap } from '../ServiceMap';
2223
import { ServiceMetrics } from '../ServiceMetrics';
2324
import { ServiceNodeOverview } from '../ServiceNodeOverview';
25+
import { ServiceOverview } from '../service_overview';
2426
import { TransactionOverview } from '../TransactionOverview';
2527

2628
interface Props {
2729
serviceName: string;
28-
tab: 'transactions' | 'errors' | 'metrics' | 'nodes' | 'service-map';
30+
tab:
31+
| 'errors'
32+
| 'metrics'
33+
| 'nodes'
34+
| 'overview'
35+
| 'service-map'
36+
| 'transactions';
2937
}
3038

3139
export function ServiceDetailTabs({ serviceName, tab }: Props) {
@@ -34,13 +42,13 @@ export function ServiceDetailTabs({ serviceName, tab }: Props) {
3442

3543
const overviewTab = {
3644
link: (
37-
<a title="UNDER CONSTRUCTION" href="#">
45+
<ServiceOverviewLink serviceName={serviceName}>
3846
{i18n.translate('xpack.apm.serviceDetails.overviewTabLabel', {
3947
defaultMessage: 'Overview',
4048
})}
41-
</a>
49+
</ServiceOverviewLink>
4250
),
43-
render: () => <></>,
51+
render: () => <ServiceOverview serviceName={serviceName} />,
4452
name: 'overview',
4553
};
4654

Lines changed: 246 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
import { EuiFlexGroup, EuiFlexItem, EuiPanel, EuiTitle } from '@elastic/eui';
8+
import { i18n } from '@kbn/i18n';
9+
import React from 'react';
10+
import styled from 'styled-components';
11+
import { useTrackPageview } from '../../../../../observability/public';
12+
import { ErrorOverviewLink } from '../../shared/Links/apm/ErrorOverviewLink';
13+
import { ServiceMapLink } from '../../shared/Links/apm/ServiceMapLink';
14+
import { TransactionOverviewLink } from '../../shared/Links/apm/TransactionOverviewLink';
15+
16+
const rowHeight = 310;
17+
const latencyChartRowHeight = 230;
18+
19+
const Row = styled(EuiFlexItem)`
20+
height: ${rowHeight}px;
21+
`;
22+
23+
const LatencyChartRow = styled(EuiFlexItem)`
24+
height: ${latencyChartRowHeight}px;
25+
`;
26+
27+
const TableLinkFlexItem = styled(EuiFlexItem)`
28+
& > a {
29+
text-align: right;
30+
}
31+
`;
32+
33+
interface ServiceOverviewProps {
34+
serviceName: string;
35+
}
36+
37+
export function ServiceOverview({ serviceName }: ServiceOverviewProps) {
38+
useTrackPageview({ app: 'apm', path: 'service_overview' });
39+
useTrackPageview({ app: 'apm', path: 'service_overview', delay: 15000 });
40+
41+
return (
42+
<EuiFlexGroup direction="column" gutterSize="s">
43+
<EuiFlexItem>
44+
<EuiFlexGroup
45+
gutterSize="xs"
46+
style={{ marginTop: 16, marginBottom: 8 }}
47+
>
48+
<EuiFlexItem grow={2}>
49+
<EuiPanel>Search bar</EuiPanel>
50+
</EuiFlexItem>
51+
<EuiFlexItem>
52+
<EuiPanel>Comparison picker</EuiPanel>
53+
</EuiFlexItem>
54+
<EuiFlexItem>
55+
<EuiPanel>Date picker</EuiPanel>
56+
</EuiFlexItem>
57+
</EuiFlexGroup>
58+
</EuiFlexItem>
59+
<LatencyChartRow>
60+
<EuiPanel>
61+
<EuiTitle size="xs">
62+
<h2>
63+
{i18n.translate('xpack.apm.serviceOverview.latencyChartTitle', {
64+
defaultMessage: 'Latency',
65+
})}
66+
</h2>
67+
</EuiTitle>
68+
</EuiPanel>
69+
</LatencyChartRow>
70+
<Row>
71+
<EuiFlexGroup gutterSize="s">
72+
<EuiFlexItem grow={4}>
73+
<EuiPanel>
74+
<EuiTitle size="xs">
75+
<h2>
76+
{i18n.translate(
77+
'xpack.apm.serviceOverview.trafficChartTitle',
78+
{
79+
defaultMessage: 'Traffic',
80+
}
81+
)}
82+
</h2>
83+
</EuiTitle>
84+
</EuiPanel>
85+
</EuiFlexItem>
86+
<EuiFlexItem grow={6}>
87+
<EuiPanel>
88+
<EuiFlexGroup justifyContent="spaceBetween">
89+
<EuiFlexItem>
90+
<EuiTitle size="xs">
91+
<h2>
92+
{i18n.translate(
93+
'xpack.apm.serviceOverview.transactionsTableTitle',
94+
{
95+
defaultMessage: 'Transactions',
96+
}
97+
)}
98+
</h2>
99+
</EuiTitle>
100+
</EuiFlexItem>
101+
<TableLinkFlexItem>
102+
<TransactionOverviewLink serviceName={serviceName}>
103+
{i18n.translate(
104+
'xpack.apm.serviceOverview.transactionsTableLinkText',
105+
{
106+
defaultMessage: 'View transactions',
107+
}
108+
)}
109+
</TransactionOverviewLink>
110+
</TableLinkFlexItem>
111+
</EuiFlexGroup>
112+
</EuiPanel>
113+
</EuiFlexItem>
114+
</EuiFlexGroup>
115+
</Row>
116+
<Row>
117+
<EuiFlexGroup gutterSize="s">
118+
<EuiFlexItem grow={4}>
119+
<EuiPanel>
120+
<EuiTitle size="xs">
121+
<h2>
122+
{i18n.translate(
123+
'xpack.apm.serviceOverview.errorRateChartTitle',
124+
{
125+
defaultMessage: 'Error rate',
126+
}
127+
)}
128+
</h2>
129+
</EuiTitle>
130+
</EuiPanel>
131+
</EuiFlexItem>
132+
<EuiFlexItem grow={6}>
133+
<EuiPanel>
134+
<EuiFlexGroup>
135+
<EuiFlexItem>
136+
<EuiTitle size="xs">
137+
<h2>
138+
{i18n.translate(
139+
'xpack.apm.serviceOverview.errorsTableTitle',
140+
{
141+
defaultMessage: 'Errors',
142+
}
143+
)}
144+
</h2>
145+
</EuiTitle>
146+
</EuiFlexItem>
147+
<TableLinkFlexItem>
148+
<ErrorOverviewLink serviceName={serviceName}>
149+
{i18n.translate(
150+
'xpack.apm.serviceOverview.errorsTableLinkText',
151+
{
152+
defaultMessage: 'View errors',
153+
}
154+
)}
155+
</ErrorOverviewLink>
156+
</TableLinkFlexItem>
157+
</EuiFlexGroup>
158+
</EuiPanel>
159+
</EuiFlexItem>
160+
</EuiFlexGroup>
161+
</Row>
162+
<Row>
163+
<EuiFlexGroup gutterSize="s">
164+
<EuiFlexItem grow={4}>
165+
<EuiPanel>
166+
<EuiFlexGroup>
167+
<EuiFlexItem>
168+
<EuiTitle size="xs">
169+
<h2>
170+
{i18n.translate(
171+
'xpack.apm.serviceOverview.averageDurationBySpanTypeChartTitle',
172+
{
173+
defaultMessage: 'Average duration by span type',
174+
}
175+
)}
176+
</h2>
177+
</EuiTitle>
178+
</EuiFlexItem>
179+
</EuiFlexGroup>
180+
</EuiPanel>
181+
</EuiFlexItem>
182+
<EuiFlexItem grow={6}>
183+
<EuiPanel>
184+
<EuiFlexGroup>
185+
<EuiFlexItem>
186+
<EuiTitle size="xs">
187+
<h2>
188+
{i18n.translate(
189+
'xpack.apm.serviceOverview.dependenciesTableTitle',
190+
{
191+
defaultMessage: 'Dependencies',
192+
}
193+
)}
194+
</h2>
195+
</EuiTitle>
196+
</EuiFlexItem>
197+
<TableLinkFlexItem>
198+
<ServiceMapLink serviceName={serviceName}>
199+
{i18n.translate(
200+
'xpack.apm.serviceOverview.dependenciesTableLinkText',
201+
{
202+
defaultMessage: 'View service map',
203+
}
204+
)}
205+
</ServiceMapLink>
206+
</TableLinkFlexItem>
207+
</EuiFlexGroup>
208+
</EuiPanel>
209+
</EuiFlexItem>
210+
</EuiFlexGroup>
211+
</Row>
212+
<Row>
213+
<EuiFlexGroup gutterSize="s">
214+
<EuiFlexItem grow={4}>
215+
<EuiPanel>
216+
<EuiTitle size="xs">
217+
<h2>
218+
{i18n.translate(
219+
'xpack.apm.serviceOverview.instancesLatencyDistributionChartTitle',
220+
{
221+
defaultMessage: 'Instances latency distribution',
222+
}
223+
)}
224+
</h2>
225+
</EuiTitle>
226+
</EuiPanel>
227+
</EuiFlexItem>
228+
<EuiFlexItem grow={6}>
229+
<EuiPanel>
230+
<EuiTitle size="xs">
231+
<h2>
232+
{i18n.translate(
233+
'xpack.apm.serviceOverview.instancesTableTitle',
234+
{
235+
defaultMessage: 'Instances',
236+
}
237+
)}
238+
</h2>
239+
</EuiTitle>
240+
</EuiPanel>
241+
</EuiFlexItem>
242+
</EuiFlexGroup>
243+
</Row>
244+
</EuiFlexGroup>
245+
);
246+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
import { render } from '@testing-library/react';
8+
import React, { ReactNode } from 'react';
9+
import { MemoryRouter } from 'react-router-dom';
10+
import { MockApmPluginContextWrapper } from '../../../context/ApmPluginContext/MockApmPluginContext';
11+
import { ServiceOverview } from './';
12+
13+
function Wrapper({ children }: { children?: ReactNode }) {
14+
return (
15+
<MemoryRouter>
16+
<MockApmPluginContextWrapper>{children}</MockApmPluginContextWrapper>
17+
</MemoryRouter>
18+
);
19+
}
20+
21+
describe('ServiceOverview', () => {
22+
it('renders', () => {
23+
expect(() =>
24+
render(<ServiceOverview serviceName="test service name" />, {
25+
wrapper: Wrapper,
26+
})
27+
).not.toThrowError();
28+
});
29+
});
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
/*
7+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
8+
* or more contributor license agreements. Licensed under the Elastic License;
9+
* you may not use this file except in compliance with the Elastic License.
10+
*/
11+
import React from 'react';
12+
import { APMLink, APMLinkExtendProps } from './APMLink';
13+
14+
interface ServiceOverviewLinkProps extends APMLinkExtendProps {
15+
serviceName: string;
16+
}
17+
18+
export function ServiceOverviewLink({
19+
serviceName,
20+
...rest
21+
}: ServiceOverviewLinkProps) {
22+
return <APMLink path={`/services/${serviceName}/overview`} {...rest} />;
23+
}

0 commit comments

Comments
 (0)