diff --git a/x-pack/legacy/plugins/apm/public/components/app/ErrorGroupDetails/DetailView/StickyErrorProperties.tsx b/x-pack/legacy/plugins/apm/public/components/app/ErrorGroupDetails/DetailView/StickyErrorProperties.tsx
index bdf122ca52c49..38856618cc53d 100644
--- a/x-pack/legacy/plugins/apm/public/components/app/ErrorGroupDetails/DetailView/StickyErrorProperties.tsx
+++ b/x-pack/legacy/plugins/apm/public/components/app/ErrorGroupDetails/DetailView/StickyErrorProperties.tsx
@@ -20,7 +20,7 @@ import { NOT_AVAILABLE_LABEL } from '../../../../../common/i18n';
import { APMError } from '../../../../../typings/es_schemas/ui/APMError';
import { Transaction } from '../../../../../typings/es_schemas/ui/Transaction';
import { StickyProperties } from '../../../shared/StickyProperties';
-import { TransactionLink } from '../../../shared/Links/apm/TransactionLink';
+import { TransactionDetailLink } from '../../../shared/Links/apm/TransactionDetailLink';
import { isRumAgentName } from '../../../../../common/agent_name';
interface Props {
@@ -43,9 +43,15 @@ function TransactionLinkWrapper({
}
return (
-
+
{transaction.transaction.id}
-
+
);
}
diff --git a/x-pack/legacy/plugins/apm/public/components/app/ErrorGroupOverview/List/__test__/List.test.tsx b/x-pack/legacy/plugins/apm/public/components/app/ErrorGroupOverview/List/__test__/List.test.tsx
index 1cc36c3ea047b..68d19a41f33a4 100644
--- a/x-pack/legacy/plugins/apm/public/components/app/ErrorGroupOverview/List/__test__/List.test.tsx
+++ b/x-pack/legacy/plugins/apm/public/components/app/ErrorGroupOverview/List/__test__/List.test.tsx
@@ -6,7 +6,6 @@
import { mount } from 'enzyme';
import React from 'react';
-import { MemoryRouter } from 'react-router-dom';
import { mockMoment, toJson } from '../../../../../utils/testHelpers';
import { ErrorGroupList } from '../index';
import props from './props.json';
@@ -19,7 +18,7 @@ import {
const mockRefreshTimeRange = jest.fn();
const MockUrlParamsProvider: React.FC<{
params?: IUrlParams;
-}> = ({ params = {}, children }) => (
+}> = ({ params = props.urlParams, children }) => (
List', () => {
it('should render empty state', () => {
const storeState = {};
const wrapper = mount(
-
+
- ,
+ ,
storeState
);
@@ -49,7 +48,7 @@ describe('ErrorGroupOverview -> List', () => {
it('should render with data', () => {
const wrapper = mount(
-
+
);
diff --git a/x-pack/legacy/plugins/apm/public/components/app/ErrorGroupOverview/List/index.tsx b/x-pack/legacy/plugins/apm/public/components/app/ErrorGroupOverview/List/index.tsx
index 9fe0119a15164..96a8ad01bb8a1 100644
--- a/x-pack/legacy/plugins/apm/public/components/app/ErrorGroupOverview/List/index.tsx
+++ b/x-pack/legacy/plugins/apm/public/components/app/ErrorGroupOverview/List/index.tsx
@@ -19,11 +19,11 @@ import {
truncate,
unit
} from '../../../../style/variables';
-import { APMLink } from '../../../shared/Links/apm/APMLink';
import { useUrlParams } from '../../../../hooks/useUrlParams';
import { ManagedTable } from '../../../shared/ManagedTable';
+import { ErrorDetailLink } from '../../../shared/Links/apm/ErrorDetailLink';
-const GroupIdLink = styled(APMLink)`
+const GroupIdLink = styled(ErrorDetailLink)`
font-family: ${fontFamilyCode};
`;
@@ -31,7 +31,7 @@ const MessageAndCulpritCell = styled.div`
${truncate('100%')};
`;
-const MessageLink = styled(APMLink)`
+const MessageLink = styled(ErrorDetailLink)`
font-family: ${fontFamilyCode};
font-size: ${fontSizes.large};
${truncate('100%')};
@@ -51,6 +51,10 @@ const ErrorGroupList: React.FC = props => {
urlParams: { serviceName }
} = useUrlParams();
+ if (!serviceName) {
+ throw new Error('Service name is required');
+ }
+
const columns = useMemo(
() => [
{
@@ -62,7 +66,7 @@ const ErrorGroupList: React.FC = props => {
width: px(unit * 6),
render: (groupId: string) => {
return (
-
+
{groupId.slice(0, 5) || NOT_AVAILABLE_LABEL}
);
@@ -86,7 +90,8 @@ const ErrorGroupList: React.FC = props => {
content={message || NOT_AVAILABLE_LABEL}
>
{message || NOT_AVAILABLE_LABEL}
diff --git a/x-pack/legacy/plugins/apm/public/components/app/Home/Home.test.tsx b/x-pack/legacy/plugins/apm/public/components/app/Home/Home.test.tsx
index ee27bd4ff7afb..cc24b56948457 100644
--- a/x-pack/legacy/plugins/apm/public/components/app/Home/Home.test.tsx
+++ b/x-pack/legacy/plugins/apm/public/components/app/Home/Home.test.tsx
@@ -13,7 +13,11 @@ jest.mock('ui/index_patterns');
jest.mock('ui/new_platform');
describe('Home component', () => {
- it('should render', () => {
- expect(shallow()).toMatchSnapshot();
+ it('should render services', () => {
+ expect(shallow()).toMatchSnapshot();
+ });
+
+ it('should render traces', () => {
+ expect(shallow()).toMatchSnapshot();
});
});
diff --git a/x-pack/legacy/plugins/apm/public/components/app/Home/__snapshots__/Home.test.tsx.snap b/x-pack/legacy/plugins/apm/public/components/app/Home/__snapshots__/Home.test.tsx.snap
index 81b97e633d621..530924cce22bb 100644
--- a/x-pack/legacy/plugins/apm/public/components/app/Home/__snapshots__/Home.test.tsx.snap
+++ b/x-pack/legacy/plugins/apm/public/components/app/Home/__snapshots__/Home.test.tsx.snap
@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`Home component should render 1`] = `
+exports[`Home component should render services 1`] = `
-
+
+ Settings
+
+
+
+
+
+
+
+
+
+
+
+ Services
+
+
+
+
+ Traces
+
+
+
+
+
+
+`;
+
+exports[`Home component should render traces 1`] = `
+
+
+
+
+
+
+ APM
+
+
+
+
+
Settings
-
+
-
+
+
+
+ Services
+
+
+
+
+ Traces
+
+
+
+
+
`;
diff --git a/x-pack/legacy/plugins/apm/public/components/app/Home/index.tsx b/x-pack/legacy/plugins/apm/public/components/app/Home/index.tsx
index 4042560859632..b959dd6988e74 100644
--- a/x-pack/legacy/plugins/apm/public/components/app/Home/index.tsx
+++ b/x-pack/legacy/plugins/apm/public/components/app/Home/index.tsx
@@ -8,31 +8,42 @@ import {
EuiFlexGroup,
EuiFlexItem,
EuiTitle,
- EuiButtonEmpty
+ EuiButtonEmpty,
+ EuiTabs,
+ EuiSpacer
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import React from 'react';
+import { $ElementType } from 'utility-types';
import { ApmHeader } from '../../shared/ApmHeader';
-import { HistoryTabs, IHistoryTab } from '../../shared/HistoryTabs';
import { SetupInstructionsLink } from '../../shared/Links/SetupInstructionsLink';
import { ServiceOverview } from '../ServiceOverview';
import { TraceOverview } from '../TraceOverview';
-import { APMLink } from '../../shared/Links/apm/APMLink';
+import { ServiceOverviewLink } from '../../shared/Links/apm/ServiceOverviewLink';
+import { TraceOverviewLink } from '../../shared/Links/apm/TraceOverviewLink';
+import { EuiTabLink } from '../../shared/EuiTabLink';
+import { SettingsLink } from '../../shared/Links/apm/SettingsLink';
-const homeTabs: IHistoryTab[] = [
+const homeTabs = [
{
- path: '/services',
- title: i18n.translate('xpack.apm.home.servicesTabLabel', {
- defaultMessage: 'Services'
- }),
+ link: (
+
+ {i18n.translate('xpack.apm.home.servicesTabLabel', {
+ defaultMessage: 'Services'
+ })}
+
+ ),
render: () => ,
name: 'services'
},
{
- path: '/traces',
- title: i18n.translate('xpack.apm.home.tracesTabLabel', {
- defaultMessage: 'Traces'
- }),
+ link: (
+
+ {i18n.translate('xpack.apm.home.tracesTabLabel', {
+ defaultMessage: 'Traces'
+ })}
+
+ ),
render: () => ,
name: 'traces'
}
@@ -42,7 +53,15 @@ const SETTINGS_LINK_LABEL = i18n.translate('xpack.apm.settingsLinkLabel', {
defaultMessage: 'Settings'
});
-export function Home() {
+interface Props {
+ tab: 'traces' | 'services';
+}
+
+export function Home({ tab }: Props) {
+ const selectedTab = homeTabs.find(
+ homeTab => homeTab.name === tab
+ ) as $ElementType;
+
return (
@@ -53,18 +72,30 @@ export function Home() {
-
+
{SETTINGS_LINK_LABEL}
-
+
-
+
+ {homeTabs.map(homeTab => (
+ null}
+ isSelected={homeTab === selectedTab}
+ key={homeTab.name}
+ >
+ {homeTab.link}
+
+ ))}
+
+
+ {selectedTab.render()}
);
}
diff --git a/x-pack/legacy/plugins/apm/public/components/app/Main/route_config/index.tsx b/x-pack/legacy/plugins/apm/public/components/app/Main/route_config/index.tsx
index 9f19961d1361c..fe208f08ac4ec 100644
--- a/x-pack/legacy/plugins/apm/public/components/app/Main/route_config/index.tsx
+++ b/x-pack/legacy/plugins/apm/public/components/app/Main/route_config/index.tsx
@@ -42,7 +42,7 @@ export const routes: BreadcrumbRoute[] = [
{
exact: true,
path: '/services',
- component: Home,
+ component: () => ,
breadcrumb: i18n.translate('xpack.apm.breadcrumb.servicesTitle', {
defaultMessage: 'Services'
}),
@@ -51,7 +51,7 @@ export const routes: BreadcrumbRoute[] = [
{
exact: true,
path: '/traces',
- component: Home,
+ component: () => ,
breadcrumb: i18n.translate('xpack.apm.breadcrumb.tracesTitle', {
defaultMessage: 'Traces'
}),
@@ -88,7 +88,7 @@ export const routes: BreadcrumbRoute[] = [
{
exact: true,
path: '/services/:serviceName/errors',
- component: ServiceDetails,
+ component: () => ,
breadcrumb: i18n.translate('xpack.apm.breadcrumb.errorsTitle', {
defaultMessage: 'Errors'
}),
@@ -99,12 +99,22 @@ export const routes: BreadcrumbRoute[] = [
{
exact: true,
path: '/services/:serviceName/transactions',
- component: ServiceDetails,
+ component: () => ,
breadcrumb: i18n.translate('xpack.apm.breadcrumb.transactionsTitle', {
defaultMessage: 'Transactions'
}),
name: RouteName.TRANSACTIONS
},
+ // metrics
+ {
+ exact: true,
+ path: '/services/:serviceName/metrics',
+ component: () => ,
+ breadcrumb: i18n.translate('xpack.apm.breadcrumb.metricsTitle', {
+ defaultMessage: 'Metrics'
+ }),
+ name: RouteName.METRICS
+ },
{
exact: true,
path: '/services/:serviceName/transactions/view',
@@ -114,16 +124,5 @@ export const routes: BreadcrumbRoute[] = [
return query.transactionName as string;
},
name: RouteName.TRANSACTION_NAME
- },
-
- // metrics
- {
- exact: true,
- path: '/services/:serviceName/metrics',
- component: ServiceDetails,
- breadcrumb: i18n.translate('xpack.apm.breadcrumb.metricsTitle', {
- defaultMessage: 'Metrics'
- }),
- name: RouteName.METRICS
}
];
diff --git a/x-pack/legacy/plugins/apm/public/components/app/ServiceDetails/ServiceDetailTabs.tsx b/x-pack/legacy/plugins/apm/public/components/app/ServiceDetails/ServiceDetailTabs.tsx
index 00195c6639d3c..c7572e1981d11 100644
--- a/x-pack/legacy/plugins/apm/public/components/app/ServiceDetails/ServiceDetailTabs.tsx
+++ b/x-pack/legacy/plugins/apm/public/components/app/ServiceDetails/ServiceDetailTabs.tsx
@@ -6,20 +6,25 @@
import { i18n } from '@kbn/i18n';
import React from 'react';
-import { IUrlParams } from '../../../context/UrlParamsContext/types';
-import { HistoryTabs } from '../../shared/HistoryTabs';
+import { EuiTabs, EuiSpacer } from '@elastic/eui';
import { ErrorGroupOverview } from '../ErrorGroupOverview';
import { TransactionOverview } from '../TransactionOverview';
import { ServiceMetrics } from '../ServiceMetrics';
import { useFetcher } from '../../../hooks/useFetcher';
import { isRumAgentName } from '../../../../common/agent_name';
import { callApmApi } from '../../../services/rest/callApmApi';
+import { EuiTabLink } from '../../shared/EuiTabLink';
+import { useUrlParams } from '../../../hooks/useUrlParams';
+import { TransactionOverviewLink } from '../../shared/Links/apm/TransactionOverviewLink';
+import { ErrorOverviewLink } from '../../shared/Links/apm/ErrorOverviewLink';
+import { MetricOverviewLink } from '../../shared/Links/apm/MetricOverviewLink';
interface Props {
- urlParams: IUrlParams;
+ tab: 'transactions' | 'errors' | 'metrics';
}
-export function ServiceDetailTabs({ urlParams }: Props) {
+export function ServiceDetailTabs({ tab }: Props) {
+ const { urlParams } = useUrlParams();
const { serviceName, start, end } = urlParams;
const { data: agentName } = useFetcher(() => {
if (serviceName && start && end) {
@@ -33,20 +38,31 @@ export function ServiceDetailTabs({ urlParams }: Props) {
}
}, [serviceName, start, end]);
+ if (!serviceName) {
+ // this never happens, urlParams type is not accurate enough
+ throw new Error('Service name was not defined');
+ }
+
const transactionsTab = {
- title: i18n.translate('xpack.apm.serviceDetails.transactionsTabLabel', {
- defaultMessage: 'Transactions'
- }),
- path: `/services/${serviceName}/transactions`,
+ link: (
+
+ {i18n.translate('xpack.apm.serviceDetails.transactionsTabLabel', {
+ defaultMessage: 'Transactions'
+ })}
+
+ ),
render: () => ,
name: 'transactions'
};
const errorsTab = {
- title: i18n.translate('xpack.apm.serviceDetails.errorsTabLabel', {
- defaultMessage: 'Errors'
- }),
- path: `/services/${serviceName}/errors`,
+ link: (
+
+ {i18n.translate('xpack.apm.serviceDetails.errorsTabLabel', {
+ defaultMessage: 'Errors'
+ })}
+
+ ),
render: () => {
return ;
},
@@ -56,10 +72,13 @@ export function ServiceDetailTabs({ urlParams }: Props) {
const tabs = [transactionsTab, errorsTab];
if (agentName && !isRumAgentName(agentName)) {
const metricsTab = {
- title: i18n.translate('xpack.apm.serviceDetails.metricsTabLabel', {
- defaultMessage: 'Metrics'
- }),
- path: `/services/${serviceName}/metrics`,
+ link: (
+
+ {i18n.translate('xpack.apm.serviceDetails.metricsTabLabel', {
+ defaultMessage: 'Metrics'
+ })}
+
+ ),
render: () => ,
name: 'metrics'
};
@@ -67,5 +86,23 @@ export function ServiceDetailTabs({ urlParams }: Props) {
tabs.push(metricsTab);
}
- return ;
+ const selectedTab = tabs.find(serviceTab => serviceTab.name === tab);
+
+ return (
+ <>
+
+ {tabs.map(serviceTab => (
+ null}
+ isSelected={serviceTab.name === tab}
+ key={serviceTab.name}
+ >
+ {serviceTab.link}
+
+ ))}
+
+
+ {selectedTab ? selectedTab.render() : null}
+ >
+ );
}
diff --git a/x-pack/legacy/plugins/apm/public/components/app/ServiceDetails/index.tsx b/x-pack/legacy/plugins/apm/public/components/app/ServiceDetails/index.tsx
index 3bb1990419ef0..ac7dfd49d4f3d 100644
--- a/x-pack/legacy/plugins/apm/public/components/app/ServiceDetails/index.tsx
+++ b/x-pack/legacy/plugins/apm/public/components/app/ServiceDetails/index.tsx
@@ -11,7 +11,11 @@ import { ServiceDetailTabs } from './ServiceDetailTabs';
import { ServiceIntegrations } from './ServiceIntegrations';
import { useUrlParams } from '../../../hooks/useUrlParams';
-export function ServiceDetails() {
+interface Props {
+ tab: React.ComponentProps['tab'];
+}
+
+export function ServiceDetails({ tab }: Props) {
const { urlParams } = useUrlParams();
const { serviceName } = urlParams;
@@ -30,7 +34,7 @@ export function ServiceDetails() {
-
+
);
}
diff --git a/x-pack/legacy/plugins/apm/public/components/app/ServiceOverview/ServiceList/__test__/__snapshots__/List.test.js.snap b/x-pack/legacy/plugins/apm/public/components/app/ServiceOverview/ServiceList/__test__/__snapshots__/List.test.js.snap
index 0ad8ebcec5369..146f6f58031bb 100644
--- a/x-pack/legacy/plugins/apm/public/components/app/ServiceOverview/ServiceList/__test__/__snapshots__/List.test.js.snap
+++ b/x-pack/legacy/plugins/apm/public/components/app/ServiceOverview/ServiceList/__test__/__snapshots__/List.test.js.snap
@@ -7,11 +7,11 @@ exports[`ServiceOverview -> List should render columns correctly 1`] = `
id="service-name-tooltip"
position="top"
>
-
opbeans-python
-
+
`;
diff --git a/x-pack/legacy/plugins/apm/public/components/app/ServiceOverview/ServiceList/index.tsx b/x-pack/legacy/plugins/apm/public/components/app/ServiceOverview/ServiceList/index.tsx
index 31e05379928ec..f2524ef1c16f4 100644
--- a/x-pack/legacy/plugins/apm/public/components/app/ServiceOverview/ServiceList/index.tsx
+++ b/x-pack/legacy/plugins/apm/public/components/app/ServiceOverview/ServiceList/index.tsx
@@ -12,9 +12,9 @@ import { ServiceListAPIResponse } from '../../../../../server/lib/services/get_s
import { NOT_AVAILABLE_LABEL } from '../../../../../common/i18n';
import { fontSizes, truncate } from '../../../../style/variables';
import { asDecimal, asMillis } from '../../../../utils/formatters';
-import { APMLink } from '../../../shared/Links/apm/APMLink';
import { ManagedTable } from '../../../shared/ManagedTable';
import { EnvironmentBadge } from '../../../shared/EnvironmentBadge';
+import { TransactionOverviewLink } from '../../../shared/Links/apm/TransactionOverviewLink';
interface Props {
items: ServiceListAPIResponse['items'];
@@ -35,7 +35,7 @@ function formatString(value?: string | null) {
return value || NOT_AVAILABLE_LABEL;
}
-const AppLink = styled(APMLink)`
+const AppLink = styled(TransactionOverviewLink)`
font-size: ${fontSizes.large};
${truncate('100%')};
`;
@@ -50,9 +50,7 @@ export const SERVICE_COLUMNS = [
sortable: true,
render: (serviceName: string) => (
-
- {formatString(serviceName)}
-
+ {formatString(serviceName)}
)
},
diff --git a/x-pack/legacy/plugins/apm/public/components/app/Settings/SettingsList.tsx b/x-pack/legacy/plugins/apm/public/components/app/Settings/SettingsList.tsx
index c48a81ffdf590..bc773288b9269 100644
--- a/x-pack/legacy/plugins/apm/public/components/app/Settings/SettingsList.tsx
+++ b/x-pack/legacy/plugins/apm/public/components/app/Settings/SettingsList.tsx
@@ -26,9 +26,9 @@ import { useFetcher } from '../../../hooks/useFetcher';
import { ITableColumn, ManagedTable } from '../../shared/ManagedTable';
import { AgentConfigurationListAPIResponse } from '../../../../server/lib/settings/agent_configuration/list_configurations';
import { AddSettingsFlyout } from './AddSettings/AddSettingFlyout';
-import { APMLink } from '../../shared/Links/apm/APMLink';
import { LoadingStatePrompt } from '../../shared/LoadingStatePrompt';
import { callApmApi } from '../../../services/rest/callApmApi';
+import { HomeLink } from '../../shared/Links/apm/HomeLink';
export type Config = AgentConfigurationListAPIResponse[0];
@@ -200,11 +200,11 @@ export function SettingsList() {
-
+
{RETURN_TO_OVERVIEW_LINK_LABEL}
-
+
diff --git a/x-pack/legacy/plugins/apm/public/components/app/TraceOverview/TraceList.tsx b/x-pack/legacy/plugins/apm/public/components/app/TraceOverview/TraceList.tsx
index b0d494e95b609..1447b2380cd1f 100644
--- a/x-pack/legacy/plugins/apm/public/components/app/TraceOverview/TraceList.tsx
+++ b/x-pack/legacy/plugins/apm/public/components/app/TraceOverview/TraceList.tsx
@@ -13,11 +13,11 @@ import { fontSizes, truncate } from '../../../style/variables';
import { asMillis } from '../../../utils/formatters';
import { EmptyMessage } from '../../shared/EmptyMessage';
import { ImpactBar } from '../../shared/ImpactBar';
-import { TransactionLink } from '../../shared/Links/apm/TransactionLink';
+import { TransactionDetailLink } from '../../shared/Links/apm/TransactionDetailLink';
import { ITableColumn, ManagedTable } from '../../shared/ManagedTable';
import { LoadingStatePrompt } from '../../shared/LoadingStatePrompt';
-const StyledTransactionLink = styled(TransactionLink)`
+const StyledTransactionLink = styled(TransactionDetailLink)`
font-size: ${fontSizes.large};
${truncate('100%')};
`;
@@ -35,9 +35,15 @@ const traceListColumns: Array> = [
}),
width: '40%',
sortable: true,
- render: (name: string, group: ITransactionGroup) => (
+ render: (name: string, { sample }: ITransactionGroup) => (
-
+
{name}
diff --git a/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/Transaction/ErrorCountBadge.tsx b/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/Transaction/ErrorCountBadge.tsx
index f108b2e100114..d50d1e6fe3c5f 100644
--- a/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/Transaction/ErrorCountBadge.tsx
+++ b/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/Transaction/ErrorCountBadge.tsx
@@ -9,10 +9,9 @@ import euiThemeLight from '@elastic/eui/dist/eui_theme_light.json';
import { i18n } from '@kbn/i18n';
import React, { Fragment } from 'react';
import styled from 'styled-components';
-import { idx } from '@kbn/elastic-idx';
import { Transaction } from '../../../../../typings/es_schemas/ui/Transaction';
import { fontSize } from '../../../../style/variables';
-import { APMLink } from '../../../shared/Links/apm/APMLink';
+import { ErrorOverviewLink } from '../../../shared/Links/apm/ErrorOverviewLink';
const LinkLabel = styled.span`
font-size: ${fontSize};
@@ -49,10 +48,11 @@ export const ErrorCountBadge: React.SFC = ({
{errorCount}
);
+ const serviceName = transaction.service.name;
return (
- _.service.name)}/errors`}
+ = ({
) : (
{errorCountBadge}
)}
-
+
);
};
diff --git a/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/Transaction/WaterfallContainer/Waterfall/FlyoutTopLevelProperties.tsx b/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/Transaction/WaterfallContainer/Waterfall/FlyoutTopLevelProperties.tsx
index 9f84d83ae8ff0..d463a96685b2c 100644
--- a/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/Transaction/WaterfallContainer/Waterfall/FlyoutTopLevelProperties.tsx
+++ b/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/Transaction/WaterfallContainer/Waterfall/FlyoutTopLevelProperties.tsx
@@ -11,9 +11,9 @@ import {
TRANSACTION_NAME
} from '../../../../../../../common/elasticsearch_fieldnames';
import { Transaction } from '../../../../../../../typings/es_schemas/ui/Transaction';
-import { APMLink } from '../../../../../shared/Links/apm/APMLink';
-import { TransactionLink } from '../../../../../shared/Links/apm/TransactionLink';
+import { TransactionDetailLink } from '../../../../../shared/Links/apm/TransactionDetailLink';
import { StickyProperties } from '../../../../../shared/StickyProperties';
+import { TransactionOverviewLink } from '../../../../../shared/Links/apm/TransactionOverviewLink';
interface Props {
transaction?: Transaction;
@@ -31,9 +31,9 @@ export function FlyoutTopLevelProperties({ transaction }: Props) {
}),
fieldName: SERVICE_NAME,
val: (
-
+
{transaction.service.name}
-
+
),
width: '50%'
},
@@ -43,9 +43,15 @@ export function FlyoutTopLevelProperties({ transaction }: Props) {
}),
fieldName: TRANSACTION_NAME,
val: (
-
+
{transaction.transaction.name}
-
+
),
width: '50%'
}
diff --git a/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/Transaction/index.tsx b/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/Transaction/index.tsx
index d9e024c5560e9..5df0cb115f430 100644
--- a/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/Transaction/index.tsx
+++ b/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/Transaction/index.tsx
@@ -18,7 +18,7 @@ import { Location } from 'history';
import React from 'react';
import { Transaction as ITransaction } from '../../../../../typings/es_schemas/ui/Transaction';
import { IUrlParams } from '../../../../context/UrlParamsContext/types';
-import { TransactionLink } from '../../../shared/Links/apm/TransactionLink';
+import { TransactionDetailLink } from '../../../shared/Links/apm/TransactionDetailLink';
import { TransactionActionMenu } from '../../../shared/TransactionActionMenu/TransactionActionMenu';
import { StickyTransactionProperties } from './StickyTransactionProperties';
import { TransactionTabs } from './TransactionTabs';
@@ -82,11 +82,18 @@ function MaybeViewTraceLink({
// the user is viewing a zoomed in version of the trace. Link to the full trace
} else {
+ const traceRoot = waterfall.traceRoot;
return (
-
+
{viewFullTraceButtonLabel}
-
+
);
}
diff --git a/x-pack/legacy/plugins/apm/public/components/app/TransactionOverview/List/index.tsx b/x-pack/legacy/plugins/apm/public/components/app/TransactionOverview/List/index.tsx
index 3f6cca5dcb61b..94cf375035260 100644
--- a/x-pack/legacy/plugins/apm/public/components/app/TransactionOverview/List/index.tsx
+++ b/x-pack/legacy/plugins/apm/public/components/app/TransactionOverview/List/index.tsx
@@ -16,9 +16,9 @@ import { ImpactBar } from '../../../shared/ImpactBar';
import { ITableColumn, ManagedTable } from '../../../shared/ManagedTable';
import { LoadingStatePrompt } from '../../../shared/LoadingStatePrompt';
import { EmptyMessage } from '../../../shared/EmptyMessage';
-import { TransactionLink } from '../../../shared/Links/apm/TransactionLink';
+import { TransactionDetailLink } from '../../../shared/Links/apm/TransactionDetailLink';
-const TransactionNameLink = styled(TransactionLink)`
+const TransactionNameLink = styled(TransactionDetailLink)`
${truncate('100%')};
font-family: ${fontFamilyCode};
`;
@@ -38,13 +38,19 @@ export function TransactionList({ items, isLoading }: Props) {
}),
width: '50%',
sortable: true,
- render: (transactionName: string, item: ITransactionGroup) => {
+ render: (transactionName: string, { sample }: ITransactionGroup) => {
return (
-
+
{transactionName || NOT_AVAILABLE_LABEL}
diff --git a/x-pack/legacy/plugins/apm/public/components/shared/EuiTabLink.tsx b/x-pack/legacy/plugins/apm/public/components/shared/EuiTabLink.tsx
new file mode 100644
index 0000000000000..f939b234c16c9
--- /dev/null
+++ b/x-pack/legacy/plugins/apm/public/components/shared/EuiTabLink.tsx
@@ -0,0 +1,27 @@
+/*
+ * 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 styled from 'styled-components';
+import { EuiTab } from '@elastic/eui';
+import theme from '@elastic/eui/dist/eui_theme_light.json';
+import { px, unit } from '../../style/variables';
+
+// We need to remove padding and add it to the link,
+// to prevent the user from clicking in the tab, but outside of the link
+// We also need to override the color here to subdue the color of the link
+// when not selected
+
+const EuiTabLink = styled(EuiTab)`
+ padding: 0;
+ a {
+ display: inline-block;
+ padding: ${px(unit * 0.75)} ${px(unit)};
+ ${({ isSelected }) =>
+ !isSelected ? `color: ${theme.euiTextColor} !important;` : ''}
+ }
+`;
+
+export { EuiTabLink };
diff --git a/x-pack/legacy/plugins/apm/public/components/shared/HistoryTabs/__test__/HistoryTabs.test.tsx b/x-pack/legacy/plugins/apm/public/components/shared/HistoryTabs/__test__/HistoryTabs.test.tsx
deleted file mode 100644
index a29e215eeed48..0000000000000
--- a/x-pack/legacy/plugins/apm/public/components/shared/HistoryTabs/__test__/HistoryTabs.test.tsx
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * 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 { EuiTab } from '@elastic/eui';
-import { shallow, ShallowWrapper } from 'enzyme';
-import React from 'react';
-import { HistoryTabs, HistoryTabsProps, IHistoryTab } from '..';
-import * as hooks from '../../../../hooks/useLocation';
-import { history } from '../../../../utils/history';
-
-type PropsOf = Component extends React.SFC
- ? Props
- : never;
-type EuiTabProps = PropsOf;
-
-describe('HistoryTabs', () => {
- let mockLocation: any;
- let testTabs: IHistoryTab[];
- let testProps: HistoryTabsProps;
-
- beforeEach(() => {
- mockLocation = {
- pathname: ''
- };
-
- jest.spyOn(hooks, 'useLocation').mockImplementation(() => mockLocation);
-
- const Content = (props: { name: string }) => {props.name}
;
-
- testTabs = [
- {
- name: 'one',
- title: 'One',
- path: '/one',
- render: props =>
- },
- {
- name: 'two',
- title: 'Two',
- path: '/two',
- render: () =>
- },
- {
- name: 'three',
- title: 'Three',
- path: '/three',
- render: () =>
- }
- ];
-
- testProps = {
- tabs: testTabs
- } as HistoryTabsProps;
- });
-
- afterEach(() => {
- jest.restoreAllMocks();
- });
-
- it('should render correctly', () => {
- mockLocation.pathname = '/two';
- const wrapper = shallow();
- expect(wrapper).toMatchSnapshot();
-
- const tabs: ShallowWrapper = wrapper.find(EuiTab);
- expect(tabs.at(0).props().isSelected).toEqual(false);
- expect(tabs.at(1).props().isSelected).toEqual(true);
- expect(tabs.at(2).props().isSelected).toEqual(false);
- });
-
- it('should push a new state onto history on tab click', () => {
- const pushSpy = jest.spyOn(history, 'push');
- const wrapper = shallow();
-
- wrapper
- .find(EuiTab)
- .at(2)
- .simulate('click');
-
- expect(pushSpy).toHaveBeenCalledWith({ pathname: '/three', search: '' });
- });
-});
diff --git a/x-pack/legacy/plugins/apm/public/components/shared/HistoryTabs/__test__/__snapshots__/HistoryTabs.test.tsx.snap b/x-pack/legacy/plugins/apm/public/components/shared/HistoryTabs/__test__/__snapshots__/HistoryTabs.test.tsx.snap
deleted file mode 100644
index 67393d2e841e3..0000000000000
--- a/x-pack/legacy/plugins/apm/public/components/shared/HistoryTabs/__test__/__snapshots__/HistoryTabs.test.tsx.snap
+++ /dev/null
@@ -1,52 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`HistoryTabs should render correctly 1`] = `
-
-
-
- One
-
-
- Two
-
-
- Three
-
-
-
-
-
-
-
-`;
diff --git a/x-pack/legacy/plugins/apm/public/components/shared/HistoryTabs/index.tsx b/x-pack/legacy/plugins/apm/public/components/shared/HistoryTabs/index.tsx
deleted file mode 100644
index 78fa47e87a598..0000000000000
--- a/x-pack/legacy/plugins/apm/public/components/shared/HistoryTabs/index.tsx
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * 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 { EuiSpacer, EuiTab, EuiTabs } from '@elastic/eui';
-import React from 'react';
-import { matchPath, Route, RouteComponentProps } from 'react-router-dom';
-import { omit } from 'lodash';
-import { localUIFilterNames } from '../../../../server/lib/ui_filters/local_ui_filters/config';
-import { useLocation } from '../../../hooks/useLocation';
-import { history } from '../../../utils/history';
-import { toQuery, fromQuery } from '../Links/url_helpers';
-
-export interface IHistoryTab {
- path: string;
- routePath?: string;
- title: React.ReactNode;
- name: string;
- render?: (props: RouteComponentProps) => React.ReactNode;
-}
-
-export interface HistoryTabsProps {
- tabs: IHistoryTab[];
-}
-
-function isTabSelected(tab: IHistoryTab, currentPath: string) {
- if (tab.routePath) {
- return !!matchPath(currentPath, { path: tab.routePath, exact: true });
- }
- return currentPath === tab.path;
-}
-
-export function HistoryTabs({ tabs }: HistoryTabsProps) {
- const location = useLocation();
- return (
-
-
- {tabs.map((tab, i) => (
- {
- const persistedQueryParameters = omit(
- toQuery(location.search),
- 'sortField',
- 'sortDirection',
- 'page',
- 'pageSize',
- ...localUIFilterNames
- );
- history.push({
- ...location,
- pathname: tab.path,
- search: fromQuery(persistedQueryParameters)
- });
- }}
- isSelected={isTabSelected(tab, location.pathname)}
- key={tab.name}
- >
- {tab.title}
-
- ))}
-
-
- {tabs.map(tab =>
- tab.render ? (
-
- ) : null
- )}
-
- );
-}
diff --git a/x-pack/legacy/plugins/apm/public/components/shared/Links/apm/APMLink.tsx b/x-pack/legacy/plugins/apm/public/components/shared/Links/apm/APMLink.tsx
index 662ffea88eba4..0312e94d7ee19 100644
--- a/x-pack/legacy/plugins/apm/public/components/shared/Links/apm/APMLink.tsx
+++ b/x-pack/legacy/plugins/apm/public/components/shared/Links/apm/APMLink.tsx
@@ -18,6 +18,8 @@ interface Props extends EuiLinkAnchorProps {
children?: React.ReactNode;
}
+export type APMLinkExtendProps = Omit;
+
export const PERSISTENT_APM_PARAMS = [
'kuery',
'rangeFrom',
diff --git a/x-pack/legacy/plugins/apm/public/components/shared/Links/apm/ErrorDetailLink.tsx b/x-pack/legacy/plugins/apm/public/components/shared/Links/apm/ErrorDetailLink.tsx
new file mode 100644
index 0000000000000..c788da6a0d240
--- /dev/null
+++ b/x-pack/legacy/plugins/apm/public/components/shared/Links/apm/ErrorDetailLink.tsx
@@ -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.
+ */
+import React from 'react';
+import { APMLink, APMLinkExtendProps } from './APMLink';
+
+interface Props extends APMLinkExtendProps {
+ serviceName: string;
+ errorGroupId: string;
+}
+
+const ErrorDetailLink = ({ serviceName, errorGroupId, ...rest }: Props) => {
+ return (
+
+ );
+};
+
+export { ErrorDetailLink };
diff --git a/x-pack/legacy/plugins/apm/public/components/shared/Links/apm/ErrorOverviewLink.tsx b/x-pack/legacy/plugins/apm/public/components/shared/Links/apm/ErrorOverviewLink.tsx
new file mode 100644
index 0000000000000..3c0bf957e03f7
--- /dev/null
+++ b/x-pack/legacy/plugins/apm/public/components/shared/Links/apm/ErrorOverviewLink.tsx
@@ -0,0 +1,40 @@
+/*
+ * 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';
+import { useUrlParams } from '../../../../hooks/useUrlParams';
+import { pickKeys } from '../../../../utils/pickKeys';
+import { APMQueryParams } from '../url_helpers';
+
+interface Props extends APMLinkExtendProps {
+ serviceName: string;
+ query?: APMQueryParams;
+}
+
+const ErrorOverviewLink = ({ serviceName, query, ...rest }: Props) => {
+ const { urlParams } = useUrlParams();
+
+ const persistedFilters = pickKeys(
+ urlParams,
+ 'transactionResult',
+ 'host',
+ 'containerId',
+ 'podName'
+ );
+
+ return (
+
+ );
+};
+
+export { ErrorOverviewLink };
diff --git a/x-pack/legacy/plugins/apm/public/components/shared/Links/apm/HomeLink.tsx b/x-pack/legacy/plugins/apm/public/components/shared/Links/apm/HomeLink.tsx
new file mode 100644
index 0000000000000..92ff3164880e8
--- /dev/null
+++ b/x-pack/legacy/plugins/apm/public/components/shared/Links/apm/HomeLink.tsx
@@ -0,0 +1,13 @@
+/*
+ * 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';
+
+const HomeLink = (props: APMLinkExtendProps) => {
+ return ;
+};
+
+export { HomeLink };
diff --git a/x-pack/legacy/plugins/apm/public/components/shared/Links/apm/MetricOverviewLink.tsx b/x-pack/legacy/plugins/apm/public/components/shared/Links/apm/MetricOverviewLink.tsx
new file mode 100644
index 0000000000000..dd988f3e3720d
--- /dev/null
+++ b/x-pack/legacy/plugins/apm/public/components/shared/Links/apm/MetricOverviewLink.tsx
@@ -0,0 +1,34 @@
+/*
+ * 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';
+import { useUrlParams } from '../../../../hooks/useUrlParams';
+import { pickKeys } from '../../../../utils/pickKeys';
+
+interface Props extends APMLinkExtendProps {
+ serviceName: string;
+}
+
+const MetricOverviewLink = ({ serviceName, ...rest }: Props) => {
+ const { urlParams } = useUrlParams();
+
+ const persistedFilters = pickKeys(
+ urlParams,
+ 'host',
+ 'containerId',
+ 'podName'
+ );
+
+ return (
+
+ );
+};
+
+export { MetricOverviewLink };
diff --git a/x-pack/legacy/plugins/apm/public/components/shared/Links/apm/ServiceOverviewLink.tsx b/x-pack/legacy/plugins/apm/public/components/shared/Links/apm/ServiceOverviewLink.tsx
new file mode 100644
index 0000000000000..101f1602506aa
--- /dev/null
+++ b/x-pack/legacy/plugins/apm/public/components/shared/Links/apm/ServiceOverviewLink.tsx
@@ -0,0 +1,25 @@
+/*
+ * 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';
+import { useUrlParams } from '../../../../hooks/useUrlParams';
+import { pickKeys } from '../../../../utils/pickKeys';
+
+const ServiceOverviewLink = (props: APMLinkExtendProps) => {
+ const { urlParams } = useUrlParams();
+
+ const persistedFilters = pickKeys(urlParams, 'host', 'agentName');
+
+ return ;
+};
+
+export { ServiceOverviewLink };
diff --git a/x-pack/legacy/plugins/apm/public/components/shared/Links/apm/SettingsLink.tsx b/x-pack/legacy/plugins/apm/public/components/shared/Links/apm/SettingsLink.tsx
new file mode 100644
index 0000000000000..8c2b44cf41b82
--- /dev/null
+++ b/x-pack/legacy/plugins/apm/public/components/shared/Links/apm/SettingsLink.tsx
@@ -0,0 +1,13 @@
+/*
+ * 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';
+
+const SettingsLink = (props: APMLinkExtendProps) => {
+ return ;
+};
+
+export { SettingsLink };
diff --git a/x-pack/legacy/plugins/apm/public/components/shared/Links/apm/TraceOverviewLink.tsx b/x-pack/legacy/plugins/apm/public/components/shared/Links/apm/TraceOverviewLink.tsx
new file mode 100644
index 0000000000000..371544c142a2d
--- /dev/null
+++ b/x-pack/legacy/plugins/apm/public/components/shared/Links/apm/TraceOverviewLink.tsx
@@ -0,0 +1,31 @@
+/*
+ * 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';
+import { useUrlParams } from '../../../../hooks/useUrlParams';
+import { pickKeys } from '../../../../utils/pickKeys';
+
+const TraceOverviewLink = (props: APMLinkExtendProps) => {
+ const { urlParams } = useUrlParams();
+
+ const persistedFilters = pickKeys(
+ urlParams,
+ 'transactionResult',
+ 'host',
+ 'containerId',
+ 'podName'
+ );
+
+ return ;
+};
+
+export { TraceOverviewLink };
diff --git a/x-pack/legacy/plugins/apm/public/components/shared/Links/apm/TransactionDetailLink.tsx b/x-pack/legacy/plugins/apm/public/components/shared/Links/apm/TransactionDetailLink.tsx
new file mode 100644
index 0000000000000..a4ac05379615a
--- /dev/null
+++ b/x-pack/legacy/plugins/apm/public/components/shared/Links/apm/TransactionDetailLink.tsx
@@ -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 from 'react';
+import { APMLink, APMLinkExtendProps } from './APMLink';
+import { useUrlParams } from '../../../../hooks/useUrlParams';
+import { pickKeys } from '../../../../utils/pickKeys';
+
+interface Props extends APMLinkExtendProps {
+ serviceName: string;
+ traceId: string;
+ transactionId: string;
+ transactionName: string;
+ transactionType: string;
+}
+
+export const TransactionDetailLink = ({
+ serviceName,
+ traceId,
+ transactionId,
+ transactionName,
+ transactionType,
+ ...rest
+}: Props) => {
+ const { urlParams } = useUrlParams();
+
+ const persistedFilters = pickKeys(urlParams, 'transactionResult');
+
+ return (
+
+ );
+};
diff --git a/x-pack/legacy/plugins/apm/public/components/shared/Links/apm/TransactionLink.tsx b/x-pack/legacy/plugins/apm/public/components/shared/Links/apm/TransactionLink.tsx
deleted file mode 100644
index 6fa2743fc2823..0000000000000
--- a/x-pack/legacy/plugins/apm/public/components/shared/Links/apm/TransactionLink.tsx
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * 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 { Transaction } from '../../../../../typings/es_schemas/ui/Transaction';
-import { APMLink } from './APMLink';
-
-interface TransactionLinkProps {
- transaction: Transaction | undefined;
-}
-
-export const TransactionLink: React.SFC = ({
- transaction,
- children
-}) => {
- if (!transaction) {
- return null;
- }
-
- const serviceName = transaction.service.name;
- const traceId = transaction.trace.id;
- const transactionId = transaction.transaction.id;
- const transactionName = transaction.transaction.name;
- const transactionType = transaction.transaction.type;
-
- return (
-
- {children}
-
- );
-};
diff --git a/x-pack/legacy/plugins/apm/public/components/shared/Links/apm/TransactionOverviewLink.tsx b/x-pack/legacy/plugins/apm/public/components/shared/Links/apm/TransactionOverviewLink.tsx
new file mode 100644
index 0000000000000..d300b259fccb8
--- /dev/null
+++ b/x-pack/legacy/plugins/apm/public/components/shared/Links/apm/TransactionOverviewLink.tsx
@@ -0,0 +1,35 @@
+/*
+ * 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';
+import { useUrlParams } from '../../../../hooks/useUrlParams';
+import { pickKeys } from '../../../../utils/pickKeys';
+
+interface Props extends APMLinkExtendProps {
+ serviceName: string;
+}
+
+const TransactionOverviewLink = ({ serviceName, ...rest }: Props) => {
+ const { urlParams } = useUrlParams();
+
+ const persistedFilters = pickKeys(
+ urlParams,
+ 'transactionResult',
+ 'host',
+ 'containerId',
+ 'podName'
+ );
+
+ return (
+
+ );
+};
+
+export { TransactionOverviewLink };
diff --git a/x-pack/legacy/plugins/apm/server/lib/errors/get_error_groups.ts b/x-pack/legacy/plugins/apm/server/lib/errors/get_error_groups.ts
index 95e88ef0a49cf..f692f94e255fc 100644
--- a/x-pack/legacy/plugins/apm/server/lib/errors/get_error_groups.ts
+++ b/x-pack/legacy/plugins/apm/server/lib/errors/get_error_groups.ts
@@ -112,8 +112,8 @@ export async function getErrorGroups({
return {
message,
occurrenceCount: bucket.doc_count,
- culprit: idx(source, _ => _.error.culprit),
- groupId: idx(source, _ => _.error.grouping_key),
+ culprit: source.error.culprit,
+ groupId: source.error.grouping_key,
latestOccurrenceAt: source['@timestamp'],
handled: idx(source, _ => _.error.exception[0].handled)
};