From a04d81866fe028bfa15aac6e3b5b9f52f7419f32 Mon Sep 17 00:00:00 2001 From: Dario Gieselaar Date: Wed, 28 Aug 2019 17:29:21 +0200 Subject: [PATCH] [7.x] [APM] Persist local UI filter across views (#43988) (#44273) * [APM] Persist local UI filter across views * Migrate remaining links * Add comment clarifying override of EUITab styling * Remove unnecessary check for existence of waterfall.traceRoot --- .../DetailView/StickyErrorProperties.tsx | 12 +- .../List/__test__/List.test.tsx | 9 +- .../app/ErrorGroupOverview/List/index.tsx | 15 ++- .../public/components/app/Home/Home.test.tsx | 8 +- .../app/Home/__snapshots__/Home.test.tsx.snap | 118 ++++++++++++++---- .../apm/public/components/app/Home/index.tsx | 63 +++++++--- .../app/Main/route_config/index.tsx | 29 +++-- .../app/ServiceDetails/ServiceDetailTabs.tsx | 71 ++++++++--- .../components/app/ServiceDetails/index.tsx | 8 +- .../__test__/__snapshots__/List.test.js.snap | 6 +- .../app/ServiceOverview/ServiceList/index.tsx | 8 +- .../components/app/Settings/SettingsList.tsx | 6 +- .../app/TraceOverview/TraceList.tsx | 14 ++- .../Transaction/ErrorCountBadge.tsx | 10 +- .../Waterfall/FlyoutTopLevelProperties.tsx | 18 ++- .../TransactionDetails/Transaction/index.tsx | 13 +- .../app/TransactionOverview/List/index.tsx | 14 ++- .../public/components/shared/EuiTabLink.tsx | 27 ++++ .../HistoryTabs/__test__/HistoryTabs.test.tsx | 85 ------------- .../__snapshots__/HistoryTabs.test.tsx.snap | 52 -------- .../components/shared/HistoryTabs/index.tsx | 76 ----------- .../components/shared/Links/apm/APMLink.tsx | 2 + .../shared/Links/apm/ErrorDetailLink.tsx | 23 ++++ .../shared/Links/apm/ErrorOverviewLink.tsx | 40 ++++++ .../components/shared/Links/apm/HomeLink.tsx | 13 ++ .../shared/Links/apm/MetricOverviewLink.tsx | 34 +++++ .../shared/Links/apm/ServiceOverviewLink.tsx | 25 ++++ .../shared/Links/apm/SettingsLink.tsx | 13 ++ .../shared/Links/apm/TraceOverviewLink.tsx | 31 +++++ .../Links/apm/TransactionDetailLink.tsx | 45 +++++++ .../shared/Links/apm/TransactionLink.tsx | 37 ------ .../Links/apm/TransactionOverviewLink.tsx | 35 ++++++ .../apm/server/lib/errors/get_error_groups.ts | 4 +- 33 files changed, 592 insertions(+), 372 deletions(-) create mode 100644 x-pack/legacy/plugins/apm/public/components/shared/EuiTabLink.tsx delete mode 100644 x-pack/legacy/plugins/apm/public/components/shared/HistoryTabs/__test__/HistoryTabs.test.tsx delete mode 100644 x-pack/legacy/plugins/apm/public/components/shared/HistoryTabs/__test__/__snapshots__/HistoryTabs.test.tsx.snap delete mode 100644 x-pack/legacy/plugins/apm/public/components/shared/HistoryTabs/index.tsx create mode 100644 x-pack/legacy/plugins/apm/public/components/shared/Links/apm/ErrorDetailLink.tsx create mode 100644 x-pack/legacy/plugins/apm/public/components/shared/Links/apm/ErrorOverviewLink.tsx create mode 100644 x-pack/legacy/plugins/apm/public/components/shared/Links/apm/HomeLink.tsx create mode 100644 x-pack/legacy/plugins/apm/public/components/shared/Links/apm/MetricOverviewLink.tsx create mode 100644 x-pack/legacy/plugins/apm/public/components/shared/Links/apm/ServiceOverviewLink.tsx create mode 100644 x-pack/legacy/plugins/apm/public/components/shared/Links/apm/SettingsLink.tsx create mode 100644 x-pack/legacy/plugins/apm/public/components/shared/Links/apm/TraceOverviewLink.tsx create mode 100644 x-pack/legacy/plugins/apm/public/components/shared/Links/apm/TransactionDetailLink.tsx delete mode 100644 x-pack/legacy/plugins/apm/public/components/shared/Links/apm/TransactionLink.tsx create mode 100644 x-pack/legacy/plugins/apm/public/components/shared/Links/apm/TransactionOverviewLink.tsx 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) };