diff --git a/x-pack/plugins/apm/public/components/app/ErrorGroupDetails/DetailView/index.tsx b/x-pack/plugins/apm/public/components/app/ErrorGroupDetails/DetailView/index.tsx
index cd893c17369889c..da55f274bd77ceb 100644
--- a/x-pack/plugins/apm/public/components/app/ErrorGroupDetails/DetailView/index.tsx
+++ b/x-pack/plugins/apm/public/components/app/ErrorGroupDetails/DetailView/index.tsx
@@ -16,7 +16,6 @@ import {
EuiToolTip,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
-import { Location } from 'history';
import { first } from 'lodash';
import React from 'react';
import { useHistory } from 'react-router-dom';
@@ -58,7 +57,6 @@ const TransactionLinkName = euiStyled.div`
interface Props {
errorGroup: APIReturnType<'GET /api/apm/services/{serviceName}/errors/{groupId}'>;
urlParams: IUrlParams;
- location: Location;
}
// TODO: Move query-string-based tabs into a re-usable component?
@@ -70,7 +68,7 @@ function getCurrentTab(
return selectedTab ? selectedTab : first(tabs) || {};
}
-export function DetailView({ errorGroup, urlParams, location }: Props) {
+export function DetailView({ errorGroup, urlParams }: Props) {
const history = useHistory();
const { transaction, error, occurrencesCount } = errorGroup;
diff --git a/x-pack/plugins/apm/public/components/app/ErrorGroupDetails/index.tsx b/x-pack/plugins/apm/public/components/app/ErrorGroupDetails/index.tsx
index 0e300818327ff5e..a7f11ae4c5726aa 100644
--- a/x-pack/plugins/apm/public/components/app/ErrorGroupDetails/index.tsx
+++ b/x-pack/plugins/apm/public/components/app/ErrorGroupDetails/index.tsx
@@ -16,7 +16,6 @@ import {
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import React, { Fragment } from 'react';
-import { RouteComponentProps } from 'react-router-dom';
import { euiStyled } from '../../../../../../../src/plugins/kibana_react/common';
import { useTrackPageview } from '../../../../../observability/public';
import { NOT_AVAILABLE_LABEL } from '../../../../common/i18n';
@@ -65,43 +64,42 @@ function ErrorGroupHeader({
isUnhandled?: boolean;
}) {
return (
- <>
-
-
+
+
+
+
+ {i18n.translate('xpack.apm.errorGroupDetails.errorGroupTitle', {
+ defaultMessage: 'Error group {errorGroupId}',
+ values: {
+ errorGroupId: getShortGroupId(groupId),
+ },
+ })}
+
+
+
+
+ {isUnhandled && (
-
-
- {i18n.translate('xpack.apm.errorGroupDetails.errorGroupTitle', {
- defaultMessage: 'Error group {errorGroupId}',
- values: {
- errorGroupId: getShortGroupId(groupId),
- },
- })}
-
-
+
+ {i18n.translate('xpack.apm.errorGroupDetails.unhandledLabel', {
+ defaultMessage: 'Unhandled',
+ })}
+
-
- {isUnhandled && (
-
-
- {i18n.translate('xpack.apm.errorGroupDetails.unhandledLabel', {
- defaultMessage: 'Unhandled',
- })}
-
-
- )}
-
- >
+ )}
+
);
}
-type ErrorGroupDetailsProps = RouteComponentProps<{
+interface ErrorGroupDetailsProps {
groupId: string;
serviceName: string;
-}>;
+}
-export function ErrorGroupDetails({ location, match }: ErrorGroupDetailsProps) {
- const { serviceName, groupId } = match.params;
+export function ErrorGroupDetails({
+ serviceName,
+ groupId,
+}: ErrorGroupDetailsProps) {
const { urlParams } = useUrlParams();
const { environment, kuery, start, end } = urlParams;
const { data: errorGroupData } = useFetcher(
@@ -198,11 +196,7 @@ export function ErrorGroupDetails({ location, match }: ErrorGroupDetailsProps) {
{showDetails && (
-
+
)}
>
);
diff --git a/x-pack/plugins/apm/public/components/app/Main/route_config/index.tsx b/x-pack/plugins/apm/public/components/app/Main/route_config/index.tsx
index 6d58b9a2575bb1e..105a86d9f7574af 100644
--- a/x-pack/plugins/apm/public/components/app/Main/route_config/index.tsx
+++ b/x-pack/plugins/apm/public/components/app/Main/route_config/index.tsx
@@ -5,17 +5,14 @@
* 2.0.
*/
-import { isFunction } from 'lodash';
import { i18n } from '@kbn/i18n';
import React from 'react';
import { RouteComponentProps } from 'react-router-dom';
-import { ApmServiceContextProvider } from '../../../../context/apm_service/apm_service_context';
import { getServiceNodeName } from '../../../../../common/service_nodes';
import { APMRouteDefinition } from '../../../../application/routes';
import { toQuery } from '../../../shared/Links/url_helpers';
import { ErrorGroupDetails } from '../../ErrorGroupDetails';
import { useApmPluginContext } from '../../../../context/apm_plugin/use_apm_plugin_context';
-import { ServiceDetails } from '../../service_details';
import { ServiceNodeMetrics } from '../../service_node_metrics';
import { Settings } from '../../Settings';
import { AgentConfigurations } from '../../Settings/AgentConfigurations';
@@ -29,12 +26,19 @@ import {
EditAgentConfigurationRouteHandler,
} from './route_handlers/agent_configuration';
import { enableServiceOverview } from '../../../../../common/ui_settings_keys';
-
-import { renderAsRedirectTo } from '../../../routing/render_as_redirect';
+import { redirectTo } from '../../../routing/render_as_redirect';
import { ApmMainTemplate } from '../../../routing/templates/apm_main_template';
import { serviceInventoryRoutes } from '../../../routing/views/service_inventory';
import { traceOverviewRoute } from '../../../routing/views/trace_overview';
import { serviceMapRoute } from '../../../routing/views/service_map';
+import { ApmServiceTemplate } from '../../../routing/templates/apm_service_template';
+import { ServiceProfiling } from '../../service_profiling';
+import { ErrorGroupOverview } from '../../error_group_overview';
+import { ServiceMap } from '../../service_map';
+import { ServiceNodeOverview } from '../../service_node_overview';
+import { ServiceMetrics } from '../../service_metrics';
+import { ServiceOverview } from '../../service_overview';
+import { TransactionOverview } from '../../transaction_overview';
// These component function definitions are used below with the `component`
// property of the route definitions.
@@ -43,119 +47,207 @@ import { serviceMapRoute } from '../../../routing/views/service_map';
// new component every render. This results in the existing component unmounting
// and the new component mounting instead of just updating the existing component.
-function ServiceDetailsErrors(
+function ServiceDetailsErrorsRouteView(
props: RouteComponentProps<{ serviceName: string }>
) {
- return ;
+ const { serviceName } = props.match.params;
+ return (
+
+
+
+ );
}
-function ServiceDetailsMetrics(
+function ErrorGroupDetailsRouteView(
+ props: RouteComponentProps<{ serviceName: string; groupId: string }>
+) {
+ const { serviceName, groupId } = props.match.params;
+ return (
+
+
+
+ );
+}
+
+function ServiceDetailsMetricsRouteView(
props: RouteComponentProps<{ serviceName: string }>
) {
- return ;
+ const { serviceName } = props.match.params;
+ return (
+
+
+
+ );
}
-function ServiceDetailsNodes(
+function ServiceDetailsNodesRouteView(
props: RouteComponentProps<{ serviceName: string }>
) {
- return ;
+ const { serviceName } = props.match.params;
+ return (
+
+
+
+ );
}
-function ServiceDetailsOverview(
+function ServiceDetailsOverviewRouteView(
props: RouteComponentProps<{ serviceName: string }>
) {
- return ;
+ const { serviceName } = props.match.params;
+ return (
+
+
+
+ );
}
-function ServiceDetailsServiceMap(
+function ServiceDetailsServiceMapRouteView(
props: RouteComponentProps<{ serviceName: string }>
) {
- return ;
+ const { serviceName } = props.match.params;
+ return (
+
+
+
+ );
}
-function ServiceDetailsTransactions(
+function ServiceDetailsTransactionsRouteView(
props: RouteComponentProps<{ serviceName: string }>
) {
- return ;
+ const { serviceName } = props.match.params;
+ return (
+
+
+
+ );
}
-function ServiceDetailsProfiling(
+function ServiceDetailsProfilingRouteView(
props: RouteComponentProps<{ serviceName: string }>
) {
- return ;
+ const { serviceName } = props.match.params;
+ return (
+
+
+
+ );
}
-function SettingsAgentConfiguration(props: RouteComponentProps<{}>) {
+function ServiceNodeMetricsRouteView(
+ props: RouteComponentProps<{
+ serviceName: string;
+ serviceNodeName: string;
+ }>
+) {
+ const { serviceName, serviceNodeName } = props.match.params;
return (
-
-
-
+
+
+
);
}
-function SettingsAnomalyDetection(props: RouteComponentProps<{}>) {
+function TransactionDetailsRouteView(
+ props: RouteComponentProps<{ serviceName: string }>
+) {
+ const { serviceName } = props.match.params;
return (
-
-
-
+
+
+
);
}
-function SettingsApmIndices(props: RouteComponentProps<{}>) {
+function SettingsAgentConfigurationRouteView(props: RouteComponentProps<{}>) {
return (
-
-
-
+
+
+
+
+
);
}
-const SettingsApmIndicesTitle = i18n.translate(
- 'xpack.apm.breadcrumb.settings.indicesTitle',
- { defaultMessage: 'Indices' }
-);
-function SettingsCustomizeUI(props: RouteComponentProps<{}>) {
+function SettingsAnomalyDetectionRouteView(props: RouteComponentProps<{}>) {
return (
-
-
-
+
+
+
+
+
);
}
-function DefaultServicePageRouteHandler(
- props: RouteComponentProps<{ serviceName: string }>
-) {
- const { uiSettings } = useApmPluginContext().core;
- const { serviceName } = props.match.params;
- if (uiSettings.get(enableServiceOverview)) {
- return renderAsRedirectTo(`/services/${serviceName}/overview`)(props);
- }
- return renderAsRedirectTo(`/services/${serviceName}/transactions`)(props);
+function SettingsApmIndicesRouteView(props: RouteComponentProps<{}>) {
+ return (
+
+
+
+
+
+ );
}
+function SettingsCustomizeUI(props: RouteComponentProps<{}>) {
+ return (
+
+
+
+
+
+ );
+}
+
+const SettingsApmIndicesTitle = i18n.translate(
+ 'xpack.apm.views.settings.indices.title',
+ { defaultMessage: 'Indices' }
+);
+
const SettingsAgentConfigurationTitle = i18n.translate(
- 'xpack.apm.breadcrumb.settings.agentConfigurationTitle',
+ 'xpack.apm.views.settings.agentConfiguration.title',
{ defaultMessage: 'Agent Configuration' }
);
const CreateAgentConfigurationTitle = i18n.translate(
- 'xpack.apm.breadcrumb.settings.createAgentConfigurationTitle',
+ 'xpack.apm.views.settings.createAgentConfiguration.title',
{ defaultMessage: 'Create Agent Configuration' }
);
const EditAgentConfigurationTitle = i18n.translate(
- 'xpack.apm.breadcrumb.settings.editAgentConfigurationTitle',
+ 'xpack.apm.views.settings.editAgentConfiguration.title',
{ defaultMessage: 'Edit Agent Configuration' }
);
const SettingsCustomizeUITitle = i18n.translate(
- 'xpack.apm.breadcrumb.settings.customizeUI',
- {
- defaultMessage: 'Customize UI',
- }
+ 'xpack.apm.views.settings.customizeUI.title',
+ { defaultMessage: 'Customize UI' }
);
const SettingsAnomalyDetectionTitle = i18n.translate(
- 'xpack.apm.breadcrumb.settings.anomalyDetection',
- {
- defaultMessage: 'Anomaly detection',
- }
+ 'xpack.apm.views.settings.anomalyDetection.title',
+ { defaultMessage: 'Anomaly detection' }
);
+const SettingsTitle = i18n.translate('xpack.apm.views.listSettings.title', {
+ defaultMessage: 'Settings',
+});
/**
* The array of route definitions to be used when the application
* creates the routes.
@@ -174,57 +266,43 @@ export const routes: APMRouteDefinition[] = [
{
exact: true,
path: '/settings',
- render: renderAsRedirectTo('/settings/agent-configuration'),
- breadcrumb: i18n.translate('xpack.apm.breadcrumb.listSettingsTitle', {
- defaultMessage: 'Settings',
- }),
+ render: redirectTo('/settings/agent-configuration'),
+ breadcrumb: SettingsTitle,
},
{
exact: true,
path: '/settings/agent-configuration',
- component: withApmMainTemplate(SettingsAgentConfiguration, {
- pageTitle: SettingsAgentConfigurationTitle,
- }),
+ component: SettingsAgentConfigurationRouteView,
breadcrumb: SettingsAgentConfigurationTitle,
},
{
exact: true,
path: '/settings/agent-configuration/create',
- component: withApmMainTemplate(CreateAgentConfigurationRouteHandler, {
- pageTitle: CreateAgentConfigurationTitle,
- }),
+ component: CreateAgentConfigurationRouteHandler,
breadcrumb: CreateAgentConfigurationTitle,
},
{
exact: true,
path: '/settings/agent-configuration/edit',
breadcrumb: EditAgentConfigurationTitle,
- component: withApmMainTemplate(EditAgentConfigurationRouteHandler, {
- pageTitle: EditAgentConfigurationTitle,
- }),
+ component: EditAgentConfigurationRouteHandler,
},
{
exact: true,
path: '/settings/apm-indices',
- component: withApmMainTemplate(SettingsApmIndices, {
- pageTitle: SettingsApmIndicesTitle,
- }),
+ component: SettingsApmIndicesRouteView,
breadcrumb: SettingsApmIndicesTitle,
},
{
exact: true,
path: '/settings/customize-ui',
- component: withApmMainTemplate(SettingsCustomizeUI, {
- pageTitle: SettingsCustomizeUITitle,
- }),
+ component: SettingsCustomizeUI,
breadcrumb: SettingsCustomizeUITitle,
},
{
exact: true,
path: '/settings/anomaly-detection',
- component: withApmMainTemplate(SettingsAnomalyDetection, {
- pageTitle: SettingsAnomalyDetectionTitle,
- }),
+ component: SettingsAnomalyDetectionRouteView,
breadcrumb: SettingsAnomalyDetectionTitle,
},
@@ -235,54 +313,43 @@ export const routes: APMRouteDefinition[] = [
exact: true,
path: '/services/:serviceName',
breadcrumb: ({ match }) => match.params.serviceName,
- component: DefaultServicePageRouteHandler,
+ component: RedirectToDefaultServiceRouteView,
},
{
exact: true,
path: '/services/:serviceName/overview',
- breadcrumb: i18n.translate('xpack.apm.breadcrumb.overviewTitle', {
+ breadcrumb: i18n.translate('xpack.apm.views.overview.title', {
defaultMessage: 'Overview',
}),
- component: withApmServiceContext(ServiceDetailsOverview, {
- pageTitle: ({ match }) => match.params.serviceName,
+ component: ServiceDetailsOverviewRouteView,
+ },
+ {
+ exact: true,
+ path: '/services/:serviceName/transactions',
+ component: ServiceDetailsTransactionsRouteView,
+ breadcrumb: i18n.translate('xpack.apm.views.transactions.title', {
+ defaultMessage: 'Transactions',
}),
},
- // errors
{
exact: true,
path: '/services/:serviceName/errors/:groupId',
- component: withApmServiceContext(ErrorGroupDetails, {
- pageTitle: ({ match }) => match.params.serviceName,
- }),
+ component: ErrorGroupDetailsRouteView,
breadcrumb: ({ match }) => match.params.groupId,
},
{
exact: true,
path: '/services/:serviceName/errors',
- component: withApmServiceContext(ServiceDetailsErrors, {
- pageTitle: ({ match }) => match.params.serviceName,
- }),
- breadcrumb: i18n.translate('xpack.apm.breadcrumb.errorsTitle', {
+ component: ServiceDetailsErrorsRouteView,
+ breadcrumb: i18n.translate('xpack.apm.views.errors.title', {
defaultMessage: 'Errors',
}),
},
- {
- exact: true,
- path: '/services/:serviceName/transactions',
- component: withApmServiceContext(ServiceDetailsTransactions, {
- pageTitle: ({ match }) => match.params.serviceName,
- }),
- breadcrumb: i18n.translate('xpack.apm.breadcrumb.transactionsTitle', {
- defaultMessage: 'Transactions',
- }),
- },
{
exact: true,
path: '/services/:serviceName/metrics',
- component: withApmServiceContext(ServiceDetailsMetrics, {
- pageTitle: ({ match }) => match.params.serviceName,
- }),
- breadcrumb: i18n.translate('xpack.apm.breadcrumb.metricsTitle', {
+ component: ServiceDetailsMetricsRouteView,
+ breadcrumb: i18n.translate('xpack.apm.views.metrics.title', {
defaultMessage: 'Metrics',
}),
},
@@ -290,10 +357,8 @@ export const routes: APMRouteDefinition[] = [
{
exact: true,
path: '/services/:serviceName/nodes',
- component: withApmServiceContext(ServiceDetailsNodes, {
- pageTitle: ({ match }) => match.params.serviceName,
- }),
- breadcrumb: i18n.translate('xpack.apm.breadcrumb.nodesTitle', {
+ component: ServiceDetailsNodesRouteView,
+ breadcrumb: i18n.translate('xpack.apm.views.nodes.title', {
defaultMessage: 'JVMs',
}),
},
@@ -301,17 +366,13 @@ export const routes: APMRouteDefinition[] = [
{
exact: true,
path: '/services/:serviceName/nodes/:serviceNodeName/metrics',
- component: withApmServiceContext(ServiceNodeMetrics, {
- pageTitle: ({ match }) => match.params.serviceName,
- }),
+ component: ServiceNodeMetricsRouteView,
breadcrumb: ({ match }) => getServiceNodeName(match.params.serviceNodeName),
},
{
exact: true,
path: '/services/:serviceName/transactions/view',
- component: withApmServiceContext(TransactionDetails, {
- pageTitle: ({ match }) => match.params.serviceName,
- }),
+ component: TransactionDetailsRouteView,
breadcrumb: ({ location }) => {
const query = toQuery(location.search);
return query.transactionName as string;
@@ -320,24 +381,19 @@ export const routes: APMRouteDefinition[] = [
{
exact: true,
path: '/services/:serviceName/profiling',
- component: withApmServiceContext(ServiceDetailsProfiling, {
- pageTitle: ({ match }) => match.params.serviceName,
- }),
- breadcrumb: i18n.translate('xpack.apm.breadcrumb.serviceProfilingTitle', {
+ component: ServiceDetailsProfilingRouteView,
+ breadcrumb: i18n.translate('xpack.apm.views.serviceProfiling.title', {
defaultMessage: 'Profiling',
}),
},
{
exact: true,
path: '/services/:serviceName/service-map',
- component: withApmServiceContext(ServiceDetailsServiceMap, {
- pageTitle: ({ match }) => match.params.serviceName,
- }),
- breadcrumb: i18n.translate('xpack.apm.breadcrumb.serviceMapTitle', {
+ component: ServiceDetailsServiceMapRouteView,
+ breadcrumb: i18n.translate('xpack.apm.views.serviceMap.title', {
defaultMessage: 'Service Map',
}),
},
-
/*
* Utilility routes
*/
@@ -349,53 +405,13 @@ export const routes: APMRouteDefinition[] = [
},
];
-interface Options {
- pageTitle: string | ((props: any) => any);
- environmentSelector?: boolean;
-}
-
-{
- /* */
-}
-
-function withApmServiceContext(
- WrappedComponent: React.ComponentType,
- options: Options
-) {
- return (props: any) => {
- const pageTitle = isFunction(options.pageTitle)
- ? options.pageTitle(props)
- : options.pageTitle;
-
- return (
-
-
-
-
-
- );
- };
-}
-
-function withApmMainTemplate(
- WrappedComponent: React.ComponentType,
- options: Options
+function RedirectToDefaultServiceRouteView(
+ props: RouteComponentProps<{ serviceName: string }>
) {
- return (props: T) => {
- const pageTitle = isFunction(options.pageTitle)
- ? options.pageTitle(props)
- : options.pageTitle;
-
- return (
-
-
-
- );
- };
+ const { uiSettings } = useApmPluginContext().core;
+ const { serviceName } = props.match.params;
+ if (uiSettings.get(enableServiceOverview)) {
+ return redirectTo(`/services/${serviceName}/overview`)(props);
+ }
+ return redirectTo(`/services/${serviceName}/transactions`)(props);
}
diff --git a/x-pack/plugins/apm/public/components/app/error_group_overview/index.tsx b/x-pack/plugins/apm/public/components/app/error_group_overview/index.tsx
index 21aca0d05741d68..62f871bc3f78587 100644
--- a/x-pack/plugins/apm/public/components/app/error_group_overview/index.tsx
+++ b/x-pack/plugins/apm/public/components/app/error_group_overview/index.tsx
@@ -68,42 +68,38 @@ export function ErrorGroupOverview({ serviceName }: ErrorGroupOverviewProps) {
useTrackPageview({ app: 'apm', path: 'error_group_overview', delay: 15000 });
if (!errorDistributionData || !errorGroupListData) {
- return ;
+ return null;
}
return (
- <>
-
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+ Errors
+
+
-
-
-
- Errors
-
-
-
-
-
-
-
- >
+
+
+
+
);
}
diff --git a/x-pack/plugins/apm/public/components/app/service_details/index.tsx b/x-pack/plugins/apm/public/components/app/service_details/index.tsx
deleted file mode 100644
index 9c6db66c377f72f..000000000000000
--- a/x-pack/plugins/apm/public/components/app/service_details/index.tsx
+++ /dev/null
@@ -1,20 +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
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import React from 'react';
-import { RouteComponentProps } from 'react-router-dom';
-import { ServiceDetailTabs } from './service_detail_tabs';
-
-interface Props extends RouteComponentProps<{ serviceName: string }> {
- tab: React.ComponentProps['tab'];
-}
-
-export function ServiceDetails({ match, tab }: Props) {
- const { serviceName } = match.params;
-
- return ;
-}
diff --git a/x-pack/plugins/apm/public/components/app/service_details/service_detail_tabs.tsx b/x-pack/plugins/apm/public/components/app/service_details/service_detail_tabs.tsx
deleted file mode 100644
index 46d62136b4cf41a..000000000000000
--- a/x-pack/plugins/apm/public/components/app/service_details/service_detail_tabs.tsx
+++ /dev/null
@@ -1,213 +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
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import { EuiTab } from '@elastic/eui';
-import { i18n } from '@kbn/i18n';
-import React, { ReactNode } from 'react';
-import { EuiBetaBadge } from '@elastic/eui';
-import { EuiFlexItem } from '@elastic/eui';
-import { EuiFlexGroup } from '@elastic/eui';
-import { EuiTabs } from '@elastic/eui';
-import { isJavaAgentName, isRumAgentName } from '../../../../common/agent_name';
-import { enableServiceOverview } from '../../../../common/ui_settings_keys';
-import { useApmPluginContext } from '../../../context/apm_plugin/use_apm_plugin_context';
-import { useApmServiceContext } from '../../../context/apm_service/use_apm_service_context';
-import { useUrlParams } from '../../../context/url_params_context/use_url_params';
-import { useErrorOverviewHref } from '../../shared/Links/apm/ErrorOverviewLink';
-import { useMetricOverviewHref } from '../../shared/Links/apm/MetricOverviewLink';
-import { useServiceMapHref } from '../../shared/Links/apm/ServiceMapLink';
-import { useServiceNodeOverviewHref } from '../../shared/Links/apm/ServiceNodeOverviewLink';
-import { useServiceOverviewHref } from '../../shared/Links/apm/service_overview_link';
-import { useTransactionsOverviewHref } from '../../shared/Links/apm/transaction_overview_link';
-import { useServiceProfilingHref } from '../../shared/Links/apm/service_profiling_link';
-import { ErrorGroupOverview } from '../error_group_overview';
-import { ServiceMap } from '../service_map';
-import { ServiceNodeOverview } from '../service_node_overview';
-import { ServiceMetrics } from '../service_metrics';
-import { ServiceOverview } from '../service_overview';
-import { TransactionOverview } from '../transaction_overview';
-import { ServiceProfiling } from '../service_profiling';
-import { Correlations } from '../correlations';
-import { euiStyled } from '../../../../../../../src/plugins/kibana_react/common';
-
-interface Tab {
- key: string;
- href: string;
- text: ReactNode;
- hidden?: boolean;
- render: () => ReactNode;
-}
-
-interface Props {
- serviceName: string;
- tab:
- | 'errors'
- | 'metrics'
- | 'nodes'
- | 'overview'
- | 'service-map'
- | 'profiling'
- | 'transactions';
-}
-
-export function ServiceDetailTabs({ serviceName, tab }: Props) {
- const { agentName, transactionType } = useApmServiceContext();
- const {
- core: { uiSettings },
- config,
- } = useApmPluginContext();
- const {
- urlParams: { latencyAggregationType },
- } = useUrlParams();
-
- const overviewTab = {
- key: 'overview',
- href: useServiceOverviewHref({ serviceName, transactionType }),
- text: i18n.translate('xpack.apm.serviceDetails.overviewTabLabel', {
- defaultMessage: 'Overview',
- }),
- render: () => (
-
- ),
- };
-
- const transactionsTab = {
- key: 'transactions',
- href: useTransactionsOverviewHref({
- serviceName,
- latencyAggregationType,
- transactionType,
- }),
- text: i18n.translate('xpack.apm.serviceDetails.transactionsTabLabel', {
- defaultMessage: 'Transactions',
- }),
- render: () => ,
- };
-
- const errorsTab = {
- key: 'errors',
- href: useErrorOverviewHref(serviceName),
- text: i18n.translate('xpack.apm.serviceDetails.errorsTabLabel', {
- defaultMessage: 'Errors',
- }),
- render: () => {
- return ;
- },
- };
-
- const serviceMapTab = {
- key: 'service-map',
- href: useServiceMapHref(serviceName),
- text: i18n.translate('xpack.apm.home.serviceMapTabLabel', {
- defaultMessage: 'Service Map',
- }),
- render: () => ,
- };
-
- const nodesListTab = {
- key: 'nodes',
- href: useServiceNodeOverviewHref(serviceName),
- text: i18n.translate('xpack.apm.serviceDetails.nodesTabLabel', {
- defaultMessage: 'JVMs',
- }),
- render: () => ,
- };
-
- const metricsTab = {
- key: 'metrics',
- href: useMetricOverviewHref(serviceName),
- text: i18n.translate('xpack.apm.serviceDetails.metricsTabLabel', {
- defaultMessage: 'Metrics',
- }),
- render: () =>
- agentName ? (
-
- ) : null,
- };
-
- const profilingTab = {
- key: 'profiling',
- href: useServiceProfilingHref({ serviceName }),
- hidden: !config.profilingEnabled,
- text: (
-
-
- {i18n.translate('xpack.apm.serviceDetails.profilingTabLabel', {
- defaultMessage: 'Profiling',
- })}
-
-
-
-
-
- ),
- render: () => ,
- };
-
- const tabs: Tab[] = [transactionsTab, errorsTab];
-
- if (uiSettings.get(enableServiceOverview)) {
- tabs.unshift(overviewTab);
- }
-
- if (isJavaAgentName(agentName)) {
- tabs.push(nodesListTab);
- } else if (agentName && !isRumAgentName(agentName)) {
- tabs.push(metricsTab);
- }
-
- tabs.push(serviceMapTab, profilingTab);
-
- const selectedTab = tabs.find((serviceTab) => serviceTab.key === tab);
-
- return (
- <>
-
- {tabs
- .filter((t) => !t.hidden)
- .map(({ href, key, text }) => (
-
- {text}
-
- ))}
-
-
-
-
- {selectedTab ? selectedTab.render() : null}
- >
- );
-}
-
-// Since our `EuiTab` components have `APMLink`s inside of them and not just
-// `href`s, we need to override the color of the links inside or they will all
-// be the primary color.
-const StyledTabs = euiStyled(EuiTabs)`
- padding-bottom: ${({ theme }) => `${theme.eui.gutterTypes.gutterMedium}`};
- margin-bottom: ${({ theme }) => `${theme.eui.gutterTypes.gutterMedium}`};
- border-bottom: ${({ theme }) => theme.eui.euiBorderThin};
- background: ${({ theme }) => theme.eui.euiColorEmptyShade};
-`;
diff --git a/x-pack/plugins/apm/public/components/app/service_map/index.tsx b/x-pack/plugins/apm/public/components/app/service_map/index.tsx
index b338d1e4ab03dca..714228d58f9620d 100644
--- a/x-pack/plugins/apm/public/components/app/service_map/index.tsx
+++ b/x-pack/plugins/apm/public/components/app/service_map/index.tsx
@@ -7,7 +7,6 @@
import { EuiFlexGroup, EuiFlexItem, EuiLoadingSpinner } from '@elastic/eui';
import React, { PropsWithChildren, ReactNode } from 'react';
-import { euiStyled } from '../../../../../../../src/plugins/kibana_react/common';
import { isActivePlatinumLicense } from '../../../../common/license_check';
import { useTrackPageview } from '../../../../../observability/public';
import {
@@ -18,7 +17,6 @@ import { FETCH_STATUS, useFetcher } from '../../../hooks/use_fetcher';
import { useLicenseContext } from '../../../context/license/use_license_context';
import { useTheme } from '../../../hooks/use_theme';
import { useUrlParams } from '../../../context/url_params_context/use_url_params';
-import { DatePicker } from '../../shared/DatePicker';
import { LicensePrompt } from '../../shared/license_prompt';
import { Controls } from './Controls';
import { Cytoscape } from './Cytoscape';
@@ -28,31 +26,16 @@ import { EmptyPrompt } from './empty_prompt';
import { Popover } from './Popover';
import { TimeoutPrompt } from './timeout_prompt';
import { useRefDimensions } from './useRefDimensions';
+import { SearchBar } from '../../shared/search_bar';
interface ServiceMapProps {
serviceName?: string;
}
-const ServiceMapDatePickerFlexGroup = euiStyled(EuiFlexGroup)`
- padding: ${({ theme }) => theme.eui.euiSizeM};
- border-bottom: ${({ theme }) => theme.eui.euiBorderThin};
- margin: 0;
-`;
-
-function DatePickerSection() {
- return (
-
-
-
-
-
- );
-}
-
function PromptContainer({ children }: { children: ReactNode }) {
return (
<>
-
+
-
+
+
-
-
-
-
- {data.charts.map((chart) => (
-
-
-
-
-
- ))}
-
-
-
- >
+
+
+ {data.charts.map((chart) => (
+
+
+
+
+
+ ))}
+
+
+
);
}
diff --git a/x-pack/plugins/apm/public/components/app/service_node_metrics/index.tsx b/x-pack/plugins/apm/public/components/app/service_node_metrics/index.tsx
index 6198fa1e6816713..79620cc554264a9 100644
--- a/x-pack/plugins/apm/public/components/app/service_node_metrics/index.tsx
+++ b/x-pack/plugins/apm/public/components/app/service_node_metrics/index.tsx
@@ -18,7 +18,6 @@ import {
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
import React from 'react';
-import { RouteComponentProps } from 'react-router-dom';
import { euiStyled } from '../../../../../../../src/plugins/kibana_react/common';
import { SERVICE_NODE_NAME_MISSING } from '../../../../common/service_nodes';
import { ChartPointerEventContextProvider } from '../../../context/chart_pointer_event/chart_pointer_event_context';
@@ -48,16 +47,18 @@ const MetadataFlexGroup = euiStyled(EuiFlexGroup)`
`${theme.eui.paddingSizes.m} 0 0 ${theme.eui.paddingSizes.m}`};
`;
-type ServiceNodeMetricsProps = RouteComponentProps<{
+interface ServiceNodeMetricsProps {
serviceName: string;
serviceNodeName: string;
-}>;
+}
-export function ServiceNodeMetrics({ match }: ServiceNodeMetricsProps) {
+export function ServiceNodeMetrics({
+ serviceName,
+ serviceNodeName,
+}: ServiceNodeMetricsProps) {
const {
urlParams: { kuery, start, end },
} = useUrlParams();
- const { serviceName, serviceNodeName } = match.params;
const { agentName } = useApmServiceContext();
const { data } = useServiceMetricChartsFetcher({ serviceNodeName });
@@ -167,7 +168,6 @@ export function ServiceNodeMetrics({ match }: ServiceNodeMetricsProps) {
)}
-
{agentName && (
diff --git a/x-pack/plugins/apm/public/components/app/service_node_overview/index.tsx b/x-pack/plugins/apm/public/components/app/service_node_overview/index.tsx
index 25dd4a838daee82..4595dd7cab857c5 100644
--- a/x-pack/plugins/apm/public/components/app/service_node_overview/index.tsx
+++ b/x-pack/plugins/apm/public/components/app/service_node_overview/index.tsx
@@ -143,22 +143,18 @@ function ServiceNodeOverview({ serviceName }: ServiceNodeOverviewProps) {
];
return (
- <>
-
-
-
-
-
- >
+
+
+
);
}
diff --git a/x-pack/plugins/apm/public/components/app/service_overview/index.tsx b/x-pack/plugins/apm/public/components/app/service_overview/index.tsx
index 93172d629eab5a7..43ebe9bebac5ea9 100644
--- a/x-pack/plugins/apm/public/components/app/service_overview/index.tsx
+++ b/x-pack/plugins/apm/public/components/app/service_overview/index.tsx
@@ -10,6 +10,7 @@ import React from 'react';
import { useTrackPageview } from '../../../../../observability/public';
import { isRumAgentName } from '../../../../common/agent_name';
import { AnnotationsContextProvider } from '../../../context/annotations/annotations_context';
+import { useApmServiceContext } from '../../../context/apm_service/use_apm_service_context';
import { ChartPointerEventContextProvider } from '../../../context/chart_pointer_event/chart_pointer_event_context';
import { useBreakPoints } from '../../../hooks/use_break_points';
import { LatencyChart } from '../../shared/charts/latency_chart';
@@ -29,14 +30,12 @@ import { ServiceOverviewTransactionsTable } from './service_overview_transaction
export const chartHeight = 288;
interface ServiceOverviewProps {
- agentName?: string;
serviceName: string;
}
-export function ServiceOverview({
- agentName,
- serviceName,
-}: ServiceOverviewProps) {
+export function ServiceOverview({ serviceName }: ServiceOverviewProps) {
+ const { agentName } = useApmServiceContext();
+
useTrackPageview({ app: 'apm', path: 'service_overview' });
useTrackPageview({ app: 'apm', path: 'service_overview', delay: 15000 });
@@ -49,8 +48,6 @@ export function ServiceOverview({
return (
-
-
diff --git a/x-pack/plugins/apm/public/components/app/service_overview/service_overview_instances_table/intance_details.tsx b/x-pack/plugins/apm/public/components/app/service_overview/service_overview_instances_table/intance_details.tsx
index ba1da7e6dd6eb9c..5c2bbd9e20c59e0 100644
--- a/x-pack/plugins/apm/public/components/app/service_overview/service_overview_instances_table/intance_details.tsx
+++ b/x-pack/plugins/apm/public/components/app/service_overview/service_overview_instances_table/intance_details.tsx
@@ -32,10 +32,7 @@ import { pct } from '../../../../style/variables';
import { getAgentIcon } from '../../../shared/AgentIcon/get_agent_icon';
import { KeyValueFilterList } from '../../../shared/key_value_filter_list';
import { pushNewItemToKueryBar } from '../../../shared/KueryBar/utils';
-import {
- getCloudIcon,
- getContainerIcon,
-} from '../../service_details/service_icons';
+import { getCloudIcon, getContainerIcon } from '../../../shared/service_icons';
import { useInstanceDetailsFetcher } from './use_instance_details_fetcher';
type ServiceInstanceDetails = APIReturnType<'GET /api/apm/services/{serviceName}/service_overview_instances/details/{serviceNodeName}'>;
diff --git a/x-pack/plugins/apm/public/components/app/service_profiling/index.tsx b/x-pack/plugins/apm/public/components/app/service_profiling/index.tsx
index 9d552fc8dad2a6d..e664088c0a2b384 100644
--- a/x-pack/plugins/apm/public/components/app/service_profiling/index.tsx
+++ b/x-pack/plugins/apm/public/components/app/service_profiling/index.tsx
@@ -83,8 +83,6 @@ export function ServiceProfiling({
return (
<>
-
-
diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/WaterfallWithSummmary/TransactionTabs.tsx b/x-pack/plugins/apm/public/components/app/transaction_details/WaterfallWithSummmary/TransactionTabs.tsx
index 7f8ffb62d9e7288..ae58e6f60cf09cb 100644
--- a/x-pack/plugins/apm/public/components/app/transaction_details/WaterfallWithSummmary/TransactionTabs.tsx
+++ b/x-pack/plugins/apm/public/components/app/transaction_details/WaterfallWithSummmary/TransactionTabs.tsx
@@ -7,7 +7,6 @@
import { EuiSpacer, EuiTab, EuiTabs } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
-import { Location } from 'history';
import React from 'react';
import { useHistory } from 'react-router-dom';
import { LogStream } from '../../../../../../infra/public';
@@ -19,7 +18,6 @@ import { WaterfallContainer } from './WaterfallContainer';
import { IWaterfall } from './WaterfallContainer/Waterfall/waterfall_helpers/waterfall_helpers';
interface Props {
- location: Location;
transaction: Transaction;
urlParams: IUrlParams;
waterfall: IWaterfall;
@@ -27,7 +25,6 @@ interface Props {
}
export function TransactionTabs({
- location,
transaction,
urlParams,
waterfall,
@@ -47,9 +44,9 @@ export function TransactionTabs({
{
history.replace({
- ...location,
+ ...history.location,
search: fromQuery({
- ...toQuery(location.search),
+ ...toQuery(history.location.search),
detailTab: key,
}),
});
@@ -66,7 +63,6 @@ export function TransactionTabs({
;
urlParams: IUrlParams;
waterfall: IWaterfall;
exceedsMax: boolean;
}) {
return (
void;
+ toggleFlyout: ({ history }: { history: History }) => void;
}
export function WaterfallFlyout({
waterfallItemId,
waterfall,
- location,
toggleFlyout,
}: Props) {
const history = useHistory();
@@ -52,14 +44,14 @@ export function WaterfallFlyout({
totalDuration={waterfall.duration}
span={currentItem.doc}
parentTransaction={parentTransaction}
- onClose={() => toggleFlyout({ history, location })}
+ onClose={() => toggleFlyout({ history })}
/>
);
case 'transaction':
return (
toggleFlyout({ history, location })}
+ onClose={() => toggleFlyout({ history })}
rootTransactionDuration={
waterfall.rootTransaction?.transaction.duration.us
}
diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/WaterfallWithSummmary/WaterfallContainer/Waterfall/accordion_waterfall.tsx b/x-pack/plugins/apm/public/components/app/transaction_details/WaterfallWithSummmary/WaterfallContainer/Waterfall/accordion_waterfall.tsx
index baced34ad3e56f1..b0721791081fac2 100644
--- a/x-pack/plugins/apm/public/components/app/transaction_details/WaterfallWithSummmary/WaterfallContainer/Waterfall/accordion_waterfall.tsx
+++ b/x-pack/plugins/apm/public/components/app/transaction_details/WaterfallWithSummmary/WaterfallContainer/Waterfall/accordion_waterfall.tsx
@@ -6,7 +6,6 @@
*/
import { EuiAccordion, EuiAccordionProps } from '@elastic/eui';
-import { Location } from 'history';
import { isEmpty } from 'lodash';
import React, { useState } from 'react';
import { euiStyled } from '../../../../../../../../../../src/plugins/kibana_react/common';
@@ -23,7 +22,6 @@ interface AccordionWaterfallProps {
level: number;
duration: IWaterfall['duration'];
waterfallItemId?: string;
- location: Location;
errorsPerTransaction: IWaterfall['errorsPerTransaction'];
childrenByParentId: Record;
onToggleEntryTransaction?: () => void;
@@ -100,7 +98,6 @@ export function AccordionWaterfall(props: AccordionWaterfallProps) {
duration,
childrenByParentId,
waterfallItemId,
- location,
errorsPerTransaction,
timelineMargins,
onClickWaterfallItem,
@@ -160,7 +157,6 @@ export function AccordionWaterfall(props: AccordionWaterfallProps) {
item={child}
level={nextLevel}
waterfallItemId={waterfallItemId}
- location={location}
errorsPerTransaction={errorsPerTransaction}
duration={duration}
childrenByParentId={childrenByParentId}
diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/WaterfallWithSummmary/WaterfallContainer/Waterfall/index.tsx b/x-pack/plugins/apm/public/components/app/transaction_details/WaterfallWithSummmary/WaterfallContainer/Waterfall/index.tsx
index 4be595ac16c6cc5..d7613699221b488 100644
--- a/x-pack/plugins/apm/public/components/app/transaction_details/WaterfallWithSummmary/WaterfallContainer/Waterfall/index.tsx
+++ b/x-pack/plugins/apm/public/components/app/transaction_details/WaterfallWithSummmary/WaterfallContainer/Waterfall/index.tsx
@@ -7,7 +7,7 @@
import { EuiButtonEmpty, EuiCallOut } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
-import { History, Location } from 'history';
+import { History } from 'history';
import React, { useState } from 'react';
import { useHistory } from 'react-router-dom';
import { euiStyled } from '../../../../../../../../../../src/plugins/kibana_react/common';
@@ -40,14 +40,12 @@ const TIMELINE_MARGINS = {
const toggleFlyout = ({
history,
item,
- location,
}: {
history: History;
item?: IWaterfallItem;
- location: Location;
}) => {
history.replace({
- ...location,
+ ...history.location,
search: fromQuery({
...toQuery(location.search),
flyoutDetailTab: undefined,
@@ -63,15 +61,9 @@ const WaterfallItemsContainer = euiStyled.div`
interface Props {
waterfallItemId?: string;
waterfall: IWaterfall;
- location: Location;
exceedsMax: boolean;
}
-export function Waterfall({
- waterfall,
- exceedsMax,
- waterfallItemId,
- location,
-}: Props) {
+export function Waterfall({ waterfall, exceedsMax, waterfallItemId }: Props) {
const history = useHistory();
const [isAccordionOpen, setIsAccordionOpen] = useState(true);
const itemContainerHeight = 58; // TODO: This is a nasty way to calculate the height of the svg element. A better approach should be found
@@ -97,13 +89,12 @@ export function Waterfall({
item={entryWaterfallTransaction}
level={0}
waterfallItemId={waterfallItemId}
- location={location}
errorsPerTransaction={waterfall.errorsPerTransaction}
duration={duration}
childrenByParentId={childrenByParentId}
timelineMargins={TIMELINE_MARGINS}
onClickWaterfallItem={(item: IWaterfallItem) =>
- toggleFlyout({ history, item, location })
+ toggleFlyout({ history, item })
}
onToggleEntryTransaction={() => setIsAccordionOpen((isOpen) => !isOpen)}
/>
@@ -148,7 +139,6 @@ export function Waterfall({
diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/WaterfallWithSummmary/WaterfallContainer/index.tsx b/x-pack/plugins/apm/public/components/app/transaction_details/WaterfallWithSummmary/WaterfallContainer/index.tsx
index 11de1ac85c434d3..817e747551d95c3 100644
--- a/x-pack/plugins/apm/public/components/app/transaction_details/WaterfallWithSummmary/WaterfallContainer/index.tsx
+++ b/x-pack/plugins/apm/public/components/app/transaction_details/WaterfallWithSummmary/WaterfallContainer/index.tsx
@@ -5,7 +5,6 @@
* 2.0.
*/
-import { Location } from 'history';
import React from 'react';
import { keyBy } from 'lodash';
import { useParams } from 'react-router-dom';
@@ -19,13 +18,11 @@ import { WaterfallLegends } from './WaterfallLegends';
interface Props {
urlParams: IUrlParams;
- location: Location;
waterfall: IWaterfall;
exceedsMax: boolean;
}
export function WaterfallContainer({
- location,
urlParams,
waterfall,
exceedsMax,
@@ -84,7 +81,6 @@ export function WaterfallContainer({
;
-
-export function TransactionDetails({
- location,
- match,
-}: TransactionDetailsProps) {
+export function TransactionDetails() {
const { urlParams } = useUrlParams();
const history = useHistory();
const {
@@ -82,10 +77,6 @@ export function TransactionDetails({
return (
<>
-
-
-
-
{transactionName}
@@ -116,7 +107,6 @@ export function TransactionDetails({
-
-
diff --git a/x-pack/plugins/apm/public/components/routing/app_root.tsx b/x-pack/plugins/apm/public/components/routing/app_root.tsx
index f5c72991e34cec5..4f7d810a1557460 100644
--- a/x-pack/plugins/apm/public/components/routing/app_root.tsx
+++ b/x-pack/plugins/apm/public/components/routing/app_root.tsx
@@ -36,49 +36,6 @@ const MainContainer = euiStyled.div`
height: 100%;
`;
-function MountApmHeaderActionMenu() {
- const { setHeaderActionMenu } = useApmPluginContext().appMountParameters;
-
- return (
-
-
-
- );
-}
-
-function ApmThemeProvider({ children }: { children: React.ReactNode }) {
- const [darkMode] = useUiSetting$('theme:darkMode');
-
- return (
- ({
- ...outerTheme,
- eui: darkMode ? euiDarkVars : euiLightVars,
- darkMode,
- })}
- >
- {children}
-
- );
-}
-
-function App() {
- useBreadcrumbs(routes);
-
- return (
-
-
-
-
-
- {routes.map((route, i) => (
-
- ))}
-
-
- );
-}
-
export function ApmAppRoot({
apmPluginContextValue,
pluginsStart,
@@ -100,7 +57,19 @@ export function ApmAppRoot({
-
+
+
+
+
+
+ {routes.map((route, i) => (
+
+ ))}
+
+
@@ -112,3 +81,30 @@ export function ApmAppRoot({
);
}
+
+function MountApmHeaderActionMenu() {
+ useBreadcrumbs(routes);
+ const { setHeaderActionMenu } = useApmPluginContext().appMountParameters;
+
+ return (
+
+
+
+ );
+}
+
+function ApmThemeProvider({ children }: { children: React.ReactNode }) {
+ const [darkMode] = useUiSetting$('theme:darkMode');
+
+ return (
+ ({
+ ...outerTheme,
+ eui: darkMode ? euiDarkVars : euiLightVars,
+ darkMode,
+ })}
+ >
+ {children}
+
+ );
+}
diff --git a/x-pack/plugins/apm/public/components/routing/render_as_redirect.tsx b/x-pack/plugins/apm/public/components/routing/render_as_redirect.tsx
index 6c838bfd4eb1ece..68ff2fce77f1377 100644
--- a/x-pack/plugins/apm/public/components/routing/render_as_redirect.tsx
+++ b/x-pack/plugins/apm/public/components/routing/render_as_redirect.tsx
@@ -12,7 +12,7 @@ import { Redirect, RouteComponentProps } from 'react-router-dom';
* Given a path, redirect to that location, preserving the search and maintaining
* backward-compatibilty with legacy (pre-7.9) hash-based URLs.
*/
-export function renderAsRedirectTo(to: string) {
+export function redirectTo(to: string) {
return ({ location }: RouteComponentProps<{}>) => {
let resolvedUrl: URL | undefined;
diff --git a/x-pack/plugins/apm/public/components/routing/templates/apm_main_template.tsx b/x-pack/plugins/apm/public/components/routing/templates/apm_main_template.tsx
index 4ae5c5755c0e7d1..71bca7a77cd968b 100644
--- a/x-pack/plugins/apm/public/components/routing/templates/apm_main_template.tsx
+++ b/x-pack/plugins/apm/public/components/routing/templates/apm_main_template.tsx
@@ -7,7 +7,6 @@
import React from 'react';
import { useKibana } from '../../../../../../../src/plugins/kibana_react/public';
-
import { ApmPluginStartDeps } from '../../../plugin';
import { EnvironmentFilter } from '../../shared/EnvironmentFilter';
@@ -25,7 +24,7 @@ export function ApmMainTemplate({
environmentSelector = true,
children,
}: {
- pageTitle: string;
+ pageTitle: React.ReactNode;
environmentSelector?: boolean;
children: React.ReactNode;
}) {
diff --git a/x-pack/plugins/apm/public/components/routing/templates/apm_service_template.tsx b/x-pack/plugins/apm/public/components/routing/templates/apm_service_template.tsx
new file mode 100644
index 000000000000000..8e14faf3607ae5a
--- /dev/null
+++ b/x-pack/plugins/apm/public/components/routing/templates/apm_service_template.tsx
@@ -0,0 +1,217 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React from 'react';
+import { i18n } from '@kbn/i18n';
+import {
+ EuiFlexGroup,
+ EuiFlexItem,
+ EuiTitle,
+ EuiTabs,
+ EuiTab,
+ EuiBetaBadge,
+} from '@elastic/eui';
+import { ApmMainTemplate } from './apm_main_template';
+import { ApmServiceContextProvider } from '../../../context/apm_service/apm_service_context';
+import { enableServiceOverview } from '../../../../common/ui_settings_keys';
+import { isJavaAgentName, isRumAgentName } from '../../../../common/agent_name';
+import { ServiceIcons } from '../../shared/service_icons';
+import { useApmPluginContext } from '../../../context/apm_plugin/use_apm_plugin_context';
+import { useApmServiceContext } from '../../../context/apm_service/use_apm_service_context';
+import { useErrorOverviewHref } from '../../shared/Links/apm/ErrorOverviewLink';
+import { useMetricOverviewHref } from '../../shared/Links/apm/MetricOverviewLink';
+import { useServiceMapHref } from '../../shared/Links/apm/ServiceMapLink';
+import { useServiceNodeOverviewHref } from '../../shared/Links/apm/ServiceNodeOverviewLink';
+import { useServiceOverviewHref } from '../../shared/Links/apm/service_overview_link';
+import { useServiceProfilingHref } from '../../shared/Links/apm/service_profiling_link';
+import { useTransactionsOverviewHref } from '../../shared/Links/apm/transaction_overview_link';
+import { useUrlParams } from '../../../context/url_params_context/use_url_params';
+import { Correlations } from '../../app/correlations';
+import { SearchBar } from '../../shared/search_bar';
+
+interface Tab {
+ key: TabKey;
+ href: string;
+ text: React.ReactNode;
+ hidden?: boolean;
+}
+
+type TabKey =
+ | 'errors'
+ | 'metrics'
+ | 'nodes'
+ | 'overview'
+ | 'service-map'
+ | 'profiling'
+ | 'transactions';
+
+export function ApmServiceTemplate({
+ children,
+ serviceName,
+ selectedTab,
+ searchBarOptions,
+}: {
+ children: React.ReactNode;
+ serviceName: string;
+ selectedTab: TabKey;
+ searchBarOptions?: {
+ hidden?: boolean;
+ showTransactionTypeSelector?: boolean;
+ showTimeComparison?: boolean;
+ };
+}) {
+ return (
+
+
+
+
+ {serviceName}
+
+
+
+
+
+
+ >
+ }
+ >
+
+
+
+
+
+
+
+
+
+
+
+
+ {children}
+
+
+ );
+}
+
+function TabNavigation({
+ serviceName,
+ selectedTab,
+}: {
+ serviceName: string;
+ selectedTab: TabKey;
+}) {
+ const { agentName, transactionType } = useApmServiceContext();
+ const { core, config } = useApmPluginContext();
+ const { urlParams } = useUrlParams();
+
+ const tabs: Tab[] = [
+ {
+ key: 'overview',
+ href: useServiceOverviewHref({ serviceName, transactionType }),
+ text: i18n.translate('xpack.apm.serviceDetails.overviewTabLabel', {
+ defaultMessage: 'Overview',
+ }),
+ hidden: !core.uiSettings.get(enableServiceOverview),
+ },
+ {
+ key: 'transactions',
+ href: useTransactionsOverviewHref({
+ serviceName,
+ latencyAggregationType: urlParams.latencyAggregationType,
+ transactionType,
+ }),
+ text: i18n.translate('xpack.apm.serviceDetails.transactionsTabLabel', {
+ defaultMessage: 'Transactions',
+ }),
+ },
+ {
+ key: 'errors',
+ href: useErrorOverviewHref(serviceName),
+ text: i18n.translate('xpack.apm.serviceDetails.errorsTabLabel', {
+ defaultMessage: 'Errors',
+ }),
+ },
+ {
+ key: 'nodes',
+ href: useServiceNodeOverviewHref(serviceName),
+ text: i18n.translate('xpack.apm.serviceDetails.nodesTabLabel', {
+ defaultMessage: 'JVMs',
+ }),
+ hidden: !isJavaAgentName(agentName),
+ },
+ {
+ key: 'metrics',
+ href: useMetricOverviewHref(serviceName),
+ text: i18n.translate('xpack.apm.serviceDetails.metricsTabLabel', {
+ defaultMessage: 'Metrics',
+ }),
+ hidden:
+ !agentName || isRumAgentName(agentName) || isJavaAgentName(agentName),
+ },
+ {
+ key: 'service-map',
+ href: useServiceMapHref(serviceName),
+ text: i18n.translate('xpack.apm.home.serviceMapTabLabel', {
+ defaultMessage: 'Service Map',
+ }),
+ },
+ {
+ key: 'profiling',
+ href: useServiceProfilingHref({ serviceName }),
+ hidden: !config.profilingEnabled,
+ text: (
+
+
+ {i18n.translate('xpack.apm.serviceDetails.profilingTabLabel', {
+ defaultMessage: 'Profiling',
+ })}
+
+
+
+
+
+ ),
+ },
+ ];
+
+ return (
+
+ {tabs
+ .filter((t) => !t.hidden)
+ .map(({ href, key, text }) => (
+
+ {text}
+
+ ))}
+
+ );
+}
diff --git a/x-pack/plugins/apm/public/components/routing/views/service_inventory.tsx b/x-pack/plugins/apm/public/components/routing/views/service_inventory.tsx
index da147ced12291ae..7027f655acf72cb 100644
--- a/x-pack/plugins/apm/public/components/routing/views/service_inventory.tsx
+++ b/x-pack/plugins/apm/public/components/routing/views/service_inventory.tsx
@@ -8,7 +8,7 @@
import { i18n } from '@kbn/i18n';
import { RouteComponentProps } from 'react-router-dom';
import React from 'react';
-import { renderAsRedirectTo } from '../../routing/render_as_redirect';
+import { redirectTo } from '../../routing/render_as_redirect';
import { ApmMainTemplate } from '../../routing/templates/apm_main_template';
import { ServiceInventory } from '../../app/service_inventory';
@@ -20,7 +20,7 @@ export const serviceInventoryRoutes = [
{
exact: true,
path: '/',
- render: renderAsRedirectTo('/services'),
+ render: redirectTo('/services'),
breadcrumb: 'APM',
},
diff --git a/x-pack/plugins/apm/public/components/shared/search_bar.tsx b/x-pack/plugins/apm/public/components/shared/search_bar.tsx
index e5aba0e76e6b39b..17497e1fb4b30a8 100644
--- a/x-pack/plugins/apm/public/components/shared/search_bar.tsx
+++ b/x-pack/plugins/apm/public/components/shared/search_bar.tsx
@@ -15,7 +15,6 @@ import {
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
import React from 'react';
-import { euiStyled } from '../../../../../../src/plugins/kibana_react/common';
import { enableInspectEsQueries } from '../../../../observability/public';
import { useApmPluginContext } from '../../context/apm_plugin/use_apm_plugin_context';
import { useKibanaUrl } from '../../hooks/useKibanaUrl';
@@ -27,6 +26,8 @@ import { TimeComparison } from './time_comparison';
import { TransactionTypeSelect } from './transaction_type_select';
interface Props {
+ hidden?: boolean;
+ showKueryBar?: boolean;
showTimeComparison?: boolean;
showTransactionTypeSelector?: boolean;
}
@@ -78,10 +79,17 @@ function DebugQueryCallout() {
}
export function SearchBar({
+ hidden = false,
+ showKueryBar = true,
showTimeComparison = false,
showTransactionTypeSelector = false,
}: Props) {
const { isSmall, isMedium, isLarge, isXl, isXXL } = useBreakPoints();
+
+ if (hidden) {
+ return null;
+ }
+
return (
<>
@@ -101,9 +109,12 @@ export function SearchBar({
)}
-
-
-
+
+ {showKueryBar && (
+
+
+
+ )}
diff --git a/x-pack/plugins/apm/public/components/app/service_details/service_icons/alert_details.tsx b/x-pack/plugins/apm/public/components/shared/service_icons/alert_details.tsx
similarity index 84%
rename from x-pack/plugins/apm/public/components/app/service_details/service_icons/alert_details.tsx
rename to x-pack/plugins/apm/public/components/shared/service_icons/alert_details.tsx
index 0066480230c6bff..9f6378ccb449713 100644
--- a/x-pack/plugins/apm/public/components/app/service_details/service_icons/alert_details.tsx
+++ b/x-pack/plugins/apm/public/components/shared/service_icons/alert_details.tsx
@@ -14,12 +14,12 @@ import {
RULE_ID,
RULE_NAME,
} from '@kbn/rule-data-utils/target/technical_field_names';
-import { parseTechnicalFields } from '../../../../../../rule_registry/common';
-import { useUrlParams } from '../../../../context/url_params_context/use_url_params';
-import { useApmPluginContext } from '../../../../context/apm_plugin/use_apm_plugin_context';
-import { APIReturnType } from '../../../../services/rest/createCallApmApi';
-import { asPercent, asDuration } from '../../../../../common/utils/formatters';
-import { TimestampTooltip } from '../../../shared/TimestampTooltip';
+import { parseTechnicalFields } from '../../../../../rule_registry/common';
+import { useUrlParams } from '../../../context/url_params_context/use_url_params';
+import { useApmPluginContext } from '../../../context/apm_plugin/use_apm_plugin_context';
+import { APIReturnType } from '../../../services/rest/createCallApmApi';
+import { asPercent, asDuration } from '../../../../common/utils/formatters';
+import { TimestampTooltip } from '../TimestampTooltip';
interface AlertDetailProps {
alerts: APIReturnType<'GET /api/apm/services/{serviceName}/alerts'>['alerts'];
diff --git a/x-pack/plugins/apm/public/components/app/service_details/service_icons/cloud_details.tsx b/x-pack/plugins/apm/public/components/shared/service_icons/cloud_details.tsx
similarity index 97%
rename from x-pack/plugins/apm/public/components/app/service_details/service_icons/cloud_details.tsx
rename to x-pack/plugins/apm/public/components/shared/service_icons/cloud_details.tsx
index 2e19bc684d68152..2e8fcfa1df67252 100644
--- a/x-pack/plugins/apm/public/components/app/service_details/service_icons/cloud_details.tsx
+++ b/x-pack/plugins/apm/public/components/shared/service_icons/cloud_details.tsx
@@ -9,7 +9,7 @@ import { EuiBadge, EuiDescriptionList } from '@elastic/eui';
import { EuiDescriptionListProps } from '@elastic/eui/src/components/description_list/description_list';
import { i18n } from '@kbn/i18n';
import React from 'react';
-import { APIReturnType } from '../../../../services/rest/createCallApmApi';
+import { APIReturnType } from '../../../services/rest/createCallApmApi';
type ServiceDetailsReturnType = APIReturnType<'GET /api/apm/services/{serviceName}/metadata/details'>;
diff --git a/x-pack/plugins/apm/public/components/app/service_details/service_icons/container_details.tsx b/x-pack/plugins/apm/public/components/shared/service_icons/container_details.tsx
similarity index 94%
rename from x-pack/plugins/apm/public/components/app/service_details/service_icons/container_details.tsx
rename to x-pack/plugins/apm/public/components/shared/service_icons/container_details.tsx
index efc9a46526cf876..b590a67409d9ee6 100644
--- a/x-pack/plugins/apm/public/components/app/service_details/service_icons/container_details.tsx
+++ b/x-pack/plugins/apm/public/components/shared/service_icons/container_details.tsx
@@ -9,8 +9,8 @@ import { EuiDescriptionList } from '@elastic/eui';
import { EuiDescriptionListProps } from '@elastic/eui/src/components/description_list/description_list';
import { i18n } from '@kbn/i18n';
import React from 'react';
-import { asInteger } from '../../../../../common/utils/formatters';
-import { APIReturnType } from '../../../../services/rest/createCallApmApi';
+import { asInteger } from '../../../../common/utils/formatters';
+import { APIReturnType } from '../../../services/rest/createCallApmApi';
type ServiceDetailsReturnType = APIReturnType<'GET /api/apm/services/{serviceName}/metadata/details'>;
diff --git a/x-pack/plugins/apm/public/components/app/service_details/service_icons/icon_popover.tsx b/x-pack/plugins/apm/public/components/shared/service_icons/icon_popover.tsx
similarity index 93%
rename from x-pack/plugins/apm/public/components/app/service_details/service_icons/icon_popover.tsx
rename to x-pack/plugins/apm/public/components/shared/service_icons/icon_popover.tsx
index 79f93ea76ee51f8..05305558564f137 100644
--- a/x-pack/plugins/apm/public/components/app/service_details/service_icons/icon_popover.tsx
+++ b/x-pack/plugins/apm/public/components/shared/service_icons/icon_popover.tsx
@@ -13,8 +13,8 @@ import {
EuiPopoverTitle,
} from '@elastic/eui';
import React from 'react';
-import { FETCH_STATUS } from '../../../../hooks/use_fetcher';
-import { px } from '../../../../style/variables';
+import { FETCH_STATUS } from '../../../hooks/use_fetcher';
+import { px } from '../../../style/variables';
interface IconPopoverProps {
title: string;
diff --git a/x-pack/plugins/apm/public/components/app/service_details/service_icons/index.test.tsx b/x-pack/plugins/apm/public/components/shared/service_icons/index.test.tsx
similarity index 95%
rename from x-pack/plugins/apm/public/components/app/service_details/service_icons/index.test.tsx
rename to x-pack/plugins/apm/public/components/shared/service_icons/index.test.tsx
index 6027e8b1d07c59c..d66625f613cdcc2 100644
--- a/x-pack/plugins/apm/public/components/app/service_details/service_icons/index.test.tsx
+++ b/x-pack/plugins/apm/public/components/shared/service_icons/index.test.tsx
@@ -11,14 +11,14 @@ import { merge } from 'lodash';
// import { renderWithTheme } from '../../../../utils/testHelpers';
import React, { ReactNode } from 'react';
import { createKibanaReactContext } from 'src/plugins/kibana_react/public';
-import { MockUrlParamsContextProvider } from '../../../../context/url_params_context/mock_url_params_context_provider';
-import { ApmPluginContextValue } from '../../../../context/apm_plugin/apm_plugin_context';
+import { MockUrlParamsContextProvider } from '../../../context/url_params_context/mock_url_params_context_provider';
+import { ApmPluginContextValue } from '../../../context/apm_plugin/apm_plugin_context';
import {
mockApmPluginContextValue,
MockApmPluginContextWrapper,
-} from '../../../../context/apm_plugin/mock_apm_plugin_context';
-import * as fetcherHook from '../../../../hooks/use_fetcher';
-import { ServiceIcons } from './';
+} from '../../../context/apm_plugin/mock_apm_plugin_context';
+import * as fetcherHook from '../../../hooks/use_fetcher';
+import { ServiceIcons } from '.';
import { EuiThemeProvider } from 'src/plugins/kibana_react/common';
const KibanaReactContext = createKibanaReactContext({
diff --git a/x-pack/plugins/apm/public/components/app/service_details/service_icons/index.tsx b/x-pack/plugins/apm/public/components/shared/service_icons/index.tsx
similarity index 91%
rename from x-pack/plugins/apm/public/components/app/service_details/service_icons/index.tsx
rename to x-pack/plugins/apm/public/components/shared/service_icons/index.tsx
index f7bed4e09a696da..d64605da2bc3f9b 100644
--- a/x-pack/plugins/apm/public/components/app/service_details/service_icons/index.tsx
+++ b/x-pack/plugins/apm/public/components/shared/service_icons/index.tsx
@@ -8,12 +8,12 @@
import { EuiFlexGroup, EuiFlexItem, EuiLoadingSpinner } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import React, { ReactChild, useState } from 'react';
-import { useApmServiceContext } from '../../../../context/apm_service/use_apm_service_context';
-import { useTheme } from '../../../../hooks/use_theme';
-import { ContainerType } from '../../../../../common/service_metadata';
-import { useUrlParams } from '../../../../context/url_params_context/use_url_params';
-import { FETCH_STATUS, useFetcher } from '../../../../hooks/use_fetcher';
-import { getAgentIcon } from '../../../shared/AgentIcon/get_agent_icon';
+import { useApmServiceContext } from '../../../context/apm_service/use_apm_service_context';
+import { useTheme } from '../../../hooks/use_theme';
+import { ContainerType } from '../../../../common/service_metadata';
+import { useUrlParams } from '../../../context/url_params_context/use_url_params';
+import { FETCH_STATUS, useFetcher } from '../../../hooks/use_fetcher';
+import { getAgentIcon } from '../AgentIcon/get_agent_icon';
import { CloudDetails } from './cloud_details';
import { ContainerDetails } from './container_details';
import { IconPopover } from './icon_popover';
diff --git a/x-pack/plugins/apm/public/components/app/service_details/service_icons/service_details.tsx b/x-pack/plugins/apm/public/components/shared/service_icons/service_details.tsx
similarity index 96%
rename from x-pack/plugins/apm/public/components/app/service_details/service_icons/service_details.tsx
rename to x-pack/plugins/apm/public/components/shared/service_icons/service_details.tsx
index ed503a5cb34a033..1828465fff450ae 100644
--- a/x-pack/plugins/apm/public/components/app/service_details/service_icons/service_details.tsx
+++ b/x-pack/plugins/apm/public/components/shared/service_icons/service_details.tsx
@@ -9,7 +9,7 @@ import { EuiDescriptionList } from '@elastic/eui';
import { EuiDescriptionListProps } from '@elastic/eui/src/components/description_list/description_list';
import { i18n } from '@kbn/i18n';
import React from 'react';
-import { APIReturnType } from '../../../../services/rest/createCallApmApi';
+import { APIReturnType } from '../../../services/rest/createCallApmApi';
type ServiceDetailsReturnType = APIReturnType<'GET /api/apm/services/{serviceName}/metadata/details'>;