Skip to content

Commit

Permalink
Service overview tab and route (#81972) (#82046)
Browse files Browse the repository at this point in the history
Placeholder tab and route for service overview page.

Fixes #81718.
  • Loading branch information
smith authored Oct 30, 2020
1 parent 27d7fb8 commit bafc89e
Show file tree
Hide file tree
Showing 5 changed files with 324 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,12 @@ function ServiceDetailsNodes(
return <ServiceDetails {...props} tab="nodes" />;
}

function ServiceDetailsOverview(
props: RouteComponentProps<{ serviceName: string }>
) {
return <ServiceDetails {...props} tab="overview" />;
}

function ServiceDetailsServiceMap(
props: RouteComponentProps<{ serviceName: string }>
) {
Expand Down Expand Up @@ -215,6 +221,14 @@ export const routes: APMRouteDefinition[] = [
`/services/${props.match.params.serviceName}/transactions`
)(props),
} as APMRouteDefinition<{ serviceName: string }>,
{
exact: true,
path: '/services/:serviceName/overview',
breadcrumb: i18n.translate('xpack.apm.breadcrumb.overviewTitle', {
defaultMessage: 'Overview',
}),
component: ServiceDetailsOverview,
} as APMRouteDefinition<{ serviceName: string }>,
// errors
{
exact: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,24 @@ import { ErrorOverviewLink } from '../../shared/Links/apm/ErrorOverviewLink';
import { MetricOverviewLink } from '../../shared/Links/apm/MetricOverviewLink';
import { ServiceMapLink } from '../../shared/Links/apm/ServiceMapLink';
import { ServiceNodeOverviewLink } from '../../shared/Links/apm/ServiceNodeOverviewLink';
import { ServiceOverviewLink } from '../../shared/Links/apm/service_overview_link';
import { TransactionOverviewLink } from '../../shared/Links/apm/TransactionOverviewLink';
import { ErrorGroupOverview } from '../ErrorGroupOverview';
import { ServiceMap } from '../ServiceMap';
import { ServiceMetrics } from '../ServiceMetrics';
import { ServiceNodeOverview } from '../ServiceNodeOverview';
import { ServiceOverview } from '../service_overview';
import { TransactionOverview } from '../TransactionOverview';

interface Props {
serviceName: string;
tab: 'transactions' | 'errors' | 'metrics' | 'nodes' | 'service-map';
tab:
| 'errors'
| 'metrics'
| 'nodes'
| 'overview'
| 'service-map'
| 'transactions';
}

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

const overviewTab = {
link: (
<a title="UNDER CONSTRUCTION" href="#">
<ServiceOverviewLink serviceName={serviceName}>
{i18n.translate('xpack.apm.serviceDetails.overviewTabLabel', {
defaultMessage: 'Overview',
})}
</a>
</ServiceOverviewLink>
),
render: () => <></>,
render: () => <ServiceOverview serviceName={serviceName} />,
name: 'overview',
};

Expand Down
246 changes: 246 additions & 0 deletions x-pack/plugins/apm/public/components/app/service_overview/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,246 @@
/*
* 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 { EuiFlexGroup, EuiFlexItem, EuiPanel, EuiTitle } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import React from 'react';
import styled from 'styled-components';
import { useTrackPageview } from '../../../../../observability/public';
import { ErrorOverviewLink } from '../../shared/Links/apm/ErrorOverviewLink';
import { ServiceMapLink } from '../../shared/Links/apm/ServiceMapLink';
import { TransactionOverviewLink } from '../../shared/Links/apm/TransactionOverviewLink';

const rowHeight = 310;
const latencyChartRowHeight = 230;

const Row = styled(EuiFlexItem)`
height: ${rowHeight}px;
`;

const LatencyChartRow = styled(EuiFlexItem)`
height: ${latencyChartRowHeight}px;
`;

const TableLinkFlexItem = styled(EuiFlexItem)`
& > a {
text-align: right;
}
`;

interface ServiceOverviewProps {
serviceName: string;
}

export function ServiceOverview({ serviceName }: ServiceOverviewProps) {
useTrackPageview({ app: 'apm', path: 'service_overview' });
useTrackPageview({ app: 'apm', path: 'service_overview', delay: 15000 });

return (
<EuiFlexGroup direction="column" gutterSize="s">
<EuiFlexItem>
<EuiFlexGroup
gutterSize="xs"
style={{ marginTop: 16, marginBottom: 8 }}
>
<EuiFlexItem grow={2}>
<EuiPanel>Search bar</EuiPanel>
</EuiFlexItem>
<EuiFlexItem>
<EuiPanel>Comparison picker</EuiPanel>
</EuiFlexItem>
<EuiFlexItem>
<EuiPanel>Date picker</EuiPanel>
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlexItem>
<LatencyChartRow>
<EuiPanel>
<EuiTitle size="xs">
<h2>
{i18n.translate('xpack.apm.serviceOverview.latencyChartTitle', {
defaultMessage: 'Latency',
})}
</h2>
</EuiTitle>
</EuiPanel>
</LatencyChartRow>
<Row>
<EuiFlexGroup gutterSize="s">
<EuiFlexItem grow={4}>
<EuiPanel>
<EuiTitle size="xs">
<h2>
{i18n.translate(
'xpack.apm.serviceOverview.trafficChartTitle',
{
defaultMessage: 'Traffic',
}
)}
</h2>
</EuiTitle>
</EuiPanel>
</EuiFlexItem>
<EuiFlexItem grow={6}>
<EuiPanel>
<EuiFlexGroup justifyContent="spaceBetween">
<EuiFlexItem>
<EuiTitle size="xs">
<h2>
{i18n.translate(
'xpack.apm.serviceOverview.transactionsTableTitle',
{
defaultMessage: 'Transactions',
}
)}
</h2>
</EuiTitle>
</EuiFlexItem>
<TableLinkFlexItem>
<TransactionOverviewLink serviceName={serviceName}>
{i18n.translate(
'xpack.apm.serviceOverview.transactionsTableLinkText',
{
defaultMessage: 'View transactions',
}
)}
</TransactionOverviewLink>
</TableLinkFlexItem>
</EuiFlexGroup>
</EuiPanel>
</EuiFlexItem>
</EuiFlexGroup>
</Row>
<Row>
<EuiFlexGroup gutterSize="s">
<EuiFlexItem grow={4}>
<EuiPanel>
<EuiTitle size="xs">
<h2>
{i18n.translate(
'xpack.apm.serviceOverview.errorRateChartTitle',
{
defaultMessage: 'Error rate',
}
)}
</h2>
</EuiTitle>
</EuiPanel>
</EuiFlexItem>
<EuiFlexItem grow={6}>
<EuiPanel>
<EuiFlexGroup>
<EuiFlexItem>
<EuiTitle size="xs">
<h2>
{i18n.translate(
'xpack.apm.serviceOverview.errorsTableTitle',
{
defaultMessage: 'Errors',
}
)}
</h2>
</EuiTitle>
</EuiFlexItem>
<TableLinkFlexItem>
<ErrorOverviewLink serviceName={serviceName}>
{i18n.translate(
'xpack.apm.serviceOverview.errorsTableLinkText',
{
defaultMessage: 'View errors',
}
)}
</ErrorOverviewLink>
</TableLinkFlexItem>
</EuiFlexGroup>
</EuiPanel>
</EuiFlexItem>
</EuiFlexGroup>
</Row>
<Row>
<EuiFlexGroup gutterSize="s">
<EuiFlexItem grow={4}>
<EuiPanel>
<EuiFlexGroup>
<EuiFlexItem>
<EuiTitle size="xs">
<h2>
{i18n.translate(
'xpack.apm.serviceOverview.averageDurationBySpanTypeChartTitle',
{
defaultMessage: 'Average duration by span type',
}
)}
</h2>
</EuiTitle>
</EuiFlexItem>
</EuiFlexGroup>
</EuiPanel>
</EuiFlexItem>
<EuiFlexItem grow={6}>
<EuiPanel>
<EuiFlexGroup>
<EuiFlexItem>
<EuiTitle size="xs">
<h2>
{i18n.translate(
'xpack.apm.serviceOverview.dependenciesTableTitle',
{
defaultMessage: 'Dependencies',
}
)}
</h2>
</EuiTitle>
</EuiFlexItem>
<TableLinkFlexItem>
<ServiceMapLink serviceName={serviceName}>
{i18n.translate(
'xpack.apm.serviceOverview.dependenciesTableLinkText',
{
defaultMessage: 'View service map',
}
)}
</ServiceMapLink>
</TableLinkFlexItem>
</EuiFlexGroup>
</EuiPanel>
</EuiFlexItem>
</EuiFlexGroup>
</Row>
<Row>
<EuiFlexGroup gutterSize="s">
<EuiFlexItem grow={4}>
<EuiPanel>
<EuiTitle size="xs">
<h2>
{i18n.translate(
'xpack.apm.serviceOverview.instancesLatencyDistributionChartTitle',
{
defaultMessage: 'Instances latency distribution',
}
)}
</h2>
</EuiTitle>
</EuiPanel>
</EuiFlexItem>
<EuiFlexItem grow={6}>
<EuiPanel>
<EuiTitle size="xs">
<h2>
{i18n.translate(
'xpack.apm.serviceOverview.instancesTableTitle',
{
defaultMessage: 'Instances',
}
)}
</h2>
</EuiTitle>
</EuiPanel>
</EuiFlexItem>
</EuiFlexGroup>
</Row>
</EuiFlexGroup>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* 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 { render } from '@testing-library/react';
import React, { ReactNode } from 'react';
import { MemoryRouter } from 'react-router-dom';
import { MockApmPluginContextWrapper } from '../../../context/ApmPluginContext/MockApmPluginContext';
import { ServiceOverview } from './';

function Wrapper({ children }: { children?: ReactNode }) {
return (
<MemoryRouter>
<MockApmPluginContextWrapper>{children}</MockApmPluginContextWrapper>
</MemoryRouter>
);
}

describe('ServiceOverview', () => {
it('renders', () => {
expect(() =>
render(<ServiceOverview serviceName="test service name" />, {
wrapper: Wrapper,
})
).not.toThrowError();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* 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.
*/
/*
* 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 { APMLink, APMLinkExtendProps } from './APMLink';

interface ServiceOverviewLinkProps extends APMLinkExtendProps {
serviceName: string;
}

export function ServiceOverviewLink({
serviceName,
...rest
}: ServiceOverviewLinkProps) {
return <APMLink path={`/services/${serviceName}/overview`} {...rest} />;
}

0 comments on commit bafc89e

Please sign in to comment.