diff --git a/x-pack/plugins/apm/common/environment_filter_values.ts b/x-pack/plugins/apm/common/environment_filter_values.ts
index c80541ee1ba6b..e4f0b40607679 100644
--- a/x-pack/plugins/apm/common/environment_filter_values.ts
+++ b/x-pack/plugins/apm/common/environment_filter_values.ts
@@ -37,6 +37,18 @@ export function getEnvironmentLabel(environment: string) {
return environmentLabels[environment] || environment;
}
+export function omitEsFieldValue({
+ esFieldValue,
+ value,
+ text,
+}: {
+ esFieldValue?: string;
+ value: string;
+ text: string;
+}) {
+ return { value, text };
+}
+
export function parseEnvironmentUrlParam(environment: string) {
if (environment === ENVIRONMENT_ALL_VALUE) {
return ENVIRONMENT_ALL;
diff --git a/x-pack/plugins/apm/e2e/cypress/support/step_definitions/csm/csm_dashboard.ts b/x-pack/plugins/apm/e2e/cypress/support/step_definitions/csm/csm_dashboard.ts
index 47154ee214dc4..cbcb48796a6d4 100644
--- a/x-pack/plugins/apm/e2e/cypress/support/step_definitions/csm/csm_dashboard.ts
+++ b/x-pack/plugins/apm/e2e/cypress/support/step_definitions/csm/csm_dashboard.ts
@@ -51,16 +51,16 @@ Then(`should display percentile for page load chart`, () => {
cy.get(pMarkers).eq(3).should('have.text', '95th');
});
-Then(`should display chart legend`, () => {
- const chartLegend = 'button.echLegendItem__label';
+// Then(`should display chart legend`, () => {
+// const chartLegend = 'button.echLegendItem__label';
- waitForLoadingToFinish();
- cy.get('.euiLoadingChart').should('not.exist');
+// waitForLoadingToFinish();
+// cy.get('.euiLoadingChart').should('not.exist');
- cy.get('[data-cy=pageLoadDist]').within(() => {
- cy.get(chartLegend, DEFAULT_TIMEOUT).eq(0).should('have.text', 'Overall');
- });
-});
+// cy.get('[data-cy=pageLoadDist]').within(() => {
+// cy.get(chartLegend, DEFAULT_TIMEOUT).eq(0).should('have.text', 'Overall');
+// });
+// });
Then(`should display tooltip on hover`, () => {
cy.get('.euiLoadingChart').should('not.exist');
diff --git a/x-pack/plugins/apm/public/application/application.test.tsx b/x-pack/plugins/apm/public/application/application.test.tsx
index 4ec654a6c0bfd..57285649677dc 100644
--- a/x-pack/plugins/apm/public/application/application.test.tsx
+++ b/x-pack/plugins/apm/public/application/application.test.tsx
@@ -5,6 +5,7 @@
* 2.0.
*/
+import React from 'react';
import { act } from '@testing-library/react';
import { createMemoryHistory } from 'history';
import { Observable } from 'rxjs';
@@ -15,6 +16,7 @@ import { renderApp } from './';
import { disableConsoleWarning } from '../utils/testHelpers';
import { dataPluginMock } from 'src/plugins/data/public/mocks';
import { embeddablePluginMock } from 'src/plugins/embeddable/public/mocks';
+import { ApmPluginStartDeps } from '../plugin';
jest.mock('../services/rest/index_pattern', () => ({
createStaticIndexPattern: () => Promise.resolve(undefined),
@@ -44,6 +46,7 @@ describe('renderApp', () => {
config,
observabilityRuleTypeRegistry,
} = mockApmPluginContextValue;
+
const plugins = {
licensing: { license$: new Observable() },
triggersActionsUi: { actionTypeRegistry: {}, alertTypeRegistry: {} },
@@ -56,7 +59,7 @@ describe('renderApp', () => {
},
},
};
- const params = {
+ const appMountParameters = {
element: document.createElement('div'),
history: createMemoryHistory(),
setHeaderActionMenu: () => {},
@@ -64,7 +67,16 @@ describe('renderApp', () => {
const data = dataPluginMock.createStartContract();
const embeddable = embeddablePluginMock.createStartContract();
- const startDeps = {
+
+ const pluginsStart = ({
+ observability: {
+ navigation: {
+ registerSections: () => jest.fn(),
+ PageTemplate: ({ children }: { children: React.ReactNode }) => (
+
hello worlds {children}
+ ),
+ },
+ },
triggersActionsUi: {
actionTypeRegistry: {},
alertTypeRegistry: {},
@@ -73,7 +85,8 @@ describe('renderApp', () => {
},
data,
embeddable,
- };
+ } as unknown) as ApmPluginStartDeps;
+
jest.spyOn(window, 'scrollTo').mockReturnValueOnce(undefined);
createCallApmApi((core as unknown) as CoreStart);
@@ -93,8 +106,8 @@ describe('renderApp', () => {
unmount = renderApp({
coreStart: core as any,
pluginsSetup: plugins as any,
- appMountParameters: params as any,
- pluginsStart: startDeps as any,
+ appMountParameters: appMountParameters as any,
+ pluginsStart,
config,
observabilityRuleTypeRegistry,
});
diff --git a/x-pack/plugins/apm/public/application/csmApp.tsx b/x-pack/plugins/apm/public/application/csmApp.tsx
index 11a2777f47f6a..ca4f4856894f9 100644
--- a/x-pack/plugins/apm/public/application/csmApp.tsx
+++ b/x-pack/plugins/apm/public/application/csmApp.tsx
@@ -20,7 +20,6 @@ import {
useUiSetting$,
} from '../../../../../src/plugins/kibana_react/public';
import { APMRouteDefinition } from '../application/routes';
-import { renderAsRedirectTo } from '../components/app/Main/route_config';
import { ScrollToTopOnPathChange } from '../components/app/Main/ScrollToTopOnPathChange';
import { RumHome, UX_LABEL } from '../components/app/RumDashboard/RumHome';
import { ApmPluginContext } from '../context/apm_plugin/apm_plugin_context';
@@ -32,6 +31,7 @@ import { createCallApmApi } from '../services/rest/createCallApmApi';
import { px, units } from '../style/variables';
import { createStaticIndexPattern } from '../services/rest/index_pattern';
import { UXActionMenu } from '../components/app/RumDashboard/ActionMenu';
+import { redirectTo } from '../components/routing/redirect_to';
const CsmMainContainer = euiStyled.div`
padding: ${px(units.plus)};
@@ -42,7 +42,7 @@ export const rumRoutes: APMRouteDefinition[] = [
{
exact: true,
path: '/',
- render: renderAsRedirectTo('/ux'),
+ render: redirectTo('/ux'),
breadcrumb: UX_LABEL,
},
];
diff --git a/x-pack/plugins/apm/public/application/index.tsx b/x-pack/plugins/apm/public/application/index.tsx
index e2a0bdb6b48b1..9b8d3c7822d3d 100644
--- a/x-pack/plugins/apm/public/application/index.tsx
+++ b/x-pack/plugins/apm/public/application/index.tsx
@@ -5,99 +5,18 @@
* 2.0.
*/
-import { ApmRoute } from '@elastic/apm-rum-react';
-import euiDarkVars from '@elastic/eui/dist/eui_theme_dark.json';
-import euiLightVars from '@elastic/eui/dist/eui_theme_light.json';
import React from 'react';
import ReactDOM from 'react-dom';
-import { Route, Router, Switch } from 'react-router-dom';
import 'react-vis/dist/style.css';
-import { DefaultTheme, ThemeProvider } from 'styled-components';
import type { ObservabilityRuleTypeRegistry } from '../../../observability/public';
-import { euiStyled } from '../../../../../src/plugins/kibana_react/common';
import { ConfigSchema } from '../';
import { AppMountParameters, CoreStart } from '../../../../../src/core/public';
-import {
- KibanaContextProvider,
- RedirectAppLinks,
- useUiSetting$,
-} from '../../../../../src/plugins/kibana_react/public';
-import { routes } from '../components/app/Main/route_config';
-import { ScrollToTopOnPathChange } from '../components/app/Main/ScrollToTopOnPathChange';
-import {
- ApmPluginContext,
- ApmPluginContextValue,
-} from '../context/apm_plugin/apm_plugin_context';
-import { LicenseProvider } from '../context/license/license_context';
-import { UrlParamsProvider } from '../context/url_params_context/url_params_context';
-import { useBreadcrumbs } from '../hooks/use_breadcrumbs';
import { ApmPluginSetupDeps, ApmPluginStartDeps } from '../plugin';
import { createCallApmApi } from '../services/rest/createCallApmApi';
import { createStaticIndexPattern } from '../services/rest/index_pattern';
import { setHelpExtension } from '../setHelpExtension';
import { setReadonlyBadge } from '../updateBadge';
-import { AnomalyDetectionJobsContextProvider } from '../context/anomaly_detection_jobs/anomaly_detection_jobs_context';
-
-const MainContainer = euiStyled.div`
- height: 100%;
-`;
-
-function App() {
- const [darkMode] = useUiSetting$('theme:darkMode');
-
- useBreadcrumbs(routes);
-
- return (
- ({
- ...outerTheme,
- eui: darkMode ? euiDarkVars : euiLightVars,
- darkMode,
- })}
- >
-
-
-
- {routes.map((route, i) => (
-
- ))}
-
-
-
- );
-}
-
-export function ApmAppRoot({
- apmPluginContextValue,
- startDeps,
-}: {
- apmPluginContextValue: ApmPluginContextValue;
- startDeps: ApmPluginStartDeps;
-}) {
- const { appMountParameters, core } = apmPluginContextValue;
- const { history } = appMountParameters;
- const i18nCore = core.i18n;
-
- return (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- );
-}
+import { ApmAppRoot } from '../components/routing/app_root';
/**
* This module is rendered asynchronously in the Kibana platform.
@@ -141,7 +60,7 @@ export const renderApp = ({
ReactDOM.render(
,
element
);
diff --git a/x-pack/plugins/apm/public/components/alerting/alerting_flyout/index.tsx b/x-pack/plugins/apm/public/components/alerting/alerting_flyout/index.tsx
index 50788c28999b5..35863d8099394 100644
--- a/x-pack/plugins/apm/public/components/alerting/alerting_flyout/index.tsx
+++ b/x-pack/plugins/apm/public/components/alerting/alerting_flyout/index.tsx
@@ -10,24 +10,17 @@ import { useParams } from 'react-router-dom';
import { useKibana } from '../../../../../../../src/plugins/kibana_react/public';
import { AlertType } from '../../../../common/alert_types';
import { getInitialAlertValues } from '../get_initial_alert_values';
-import { TriggersAndActionsUIPublicPluginStart } from '../../../../../triggers_actions_ui/public';
+import { ApmPluginStartDeps } from '../../../plugin';
interface Props {
addFlyoutVisible: boolean;
setAddFlyoutVisibility: React.Dispatch>;
alertType: AlertType | null;
}
-interface KibanaDeps {
- triggersActionsUi: TriggersAndActionsUIPublicPluginStart;
-}
-
export function AlertingFlyout(props: Props) {
const { addFlyoutVisible, setAddFlyoutVisibility, alertType } = props;
const { serviceName } = useParams<{ serviceName?: string }>();
- const {
- services: { triggersActionsUi },
- } = useKibana();
-
+ const { services } = useKibana();
const initialValues = getInitialAlertValues(alertType, serviceName);
const onCloseAddFlyout = useCallback(() => setAddFlyoutVisibility(false), [
@@ -37,7 +30,7 @@ export function AlertingFlyout(props: Props) {
const addAlertFlyout = useMemo(
() =>
alertType &&
- triggersActionsUi.getAddAlertFlyout({
+ services.triggersActionsUi.getAddAlertFlyout({
consumer: 'apm',
onClose: onCloseAddFlyout,
alertTypeId: alertType,
@@ -45,7 +38,7 @@ export function AlertingFlyout(props: Props) {
initialValues,
}),
/* eslint-disable-next-line react-hooks/exhaustive-deps */
- [alertType, onCloseAddFlyout, triggersActionsUi]
+ [alertType, onCloseAddFlyout, services.triggersActionsUi]
);
return <>{addFlyoutVisible && addAlertFlyout}>;
}
diff --git a/x-pack/plugins/apm/public/components/app/ErrorGroupDetails/DetailView/index.test.tsx b/x-pack/plugins/apm/public/components/app/ErrorGroupDetails/DetailView/index.test.tsx
index 5671f0bfcf085..9cb5a57b090f3 100644
--- a/x-pack/plugins/apm/public/components/app/ErrorGroupDetails/DetailView/index.test.tsx
+++ b/x-pack/plugins/apm/public/components/app/ErrorGroupDetails/DetailView/index.test.tsx
@@ -6,7 +6,6 @@
*/
import { shallow } from 'enzyme';
-import { Location } from 'history';
import React from 'react';
import { mockMoment } from '../../../../utils/testHelpers';
import { DetailView } from './index';
@@ -19,11 +18,7 @@ describe('DetailView', () => {
it('should render empty state', () => {
const wrapper = shallow(
-
+
);
expect(wrapper.isEmptyRender()).toBe(true);
});
@@ -46,11 +41,7 @@ describe('DetailView', () => {
};
const wrapper = shallow(
-
+
).find('DiscoverErrorLink');
expect(wrapper.exists()).toBe(true);
@@ -69,11 +60,7 @@ describe('DetailView', () => {
transaction: undefined,
};
const wrapper = shallow(
-
+
).find('Summary');
expect(wrapper.exists()).toBe(true);
@@ -93,11 +80,7 @@ describe('DetailView', () => {
} as any,
};
const wrapper = shallow(
-
+
).find('EuiTabs');
expect(wrapper.exists()).toBe(true);
@@ -117,11 +100,7 @@ describe('DetailView', () => {
} as any,
};
const wrapper = shallow(
-
+
).find('TabContent');
expect(wrapper.exists()).toBe(true);
@@ -145,13 +124,7 @@ describe('DetailView', () => {
} as any,
};
expect(() =>
- shallow(
-
- )
+ shallow()
).not.toThrowError();
});
});
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 cd893c1736988..da55f274bd77c 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 5fcd2914f2225..0f2180721afe3 100644
--- a/x-pack/plugins/apm/public/components/app/ErrorGroupDetails/index.tsx
+++ b/x-pack/plugins/apm/public/components/app/ErrorGroupDetails/index.tsx
@@ -9,24 +9,19 @@ import {
EuiBadge,
EuiFlexGroup,
EuiFlexItem,
- EuiPage,
- EuiPageBody,
EuiPanel,
EuiSpacer,
EuiText,
EuiTitle,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
-import React, { Fragment } from 'react';
-import { RouteComponentProps } from 'react-router-dom';
+import React from 'react';
import { euiStyled } from '../../../../../../../src/plugins/kibana_react/common';
import { useTrackPageview } from '../../../../../observability/public';
import { NOT_AVAILABLE_LABEL } from '../../../../common/i18n';
import { useFetcher } from '../../../hooks/use_fetcher';
import { useUrlParams } from '../../../context/url_params_context/use_url_params';
import { fontFamilyCode, fontSizes, px, units } from '../../../style/variables';
-import { ApmHeader } from '../../shared/ApmHeader';
-import { SearchBar } from '../../shared/search_bar';
import { DetailView } from './DetailView';
import { ErrorDistribution } from './Distribution';
import { useErrorGroupDistributionFetcher } from '../../../hooks/use_error_group_distribution_fetcher';
@@ -68,44 +63,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.unhandledLabel', {
- defaultMessage: 'Unhandled',
- })}
-
-
- )}
-
-
-
- >
+
+
+
+
+ {i18n.translate('xpack.apm.errorGroupDetails.errorGroupTitle', {
+ defaultMessage: 'Error group {errorGroupId}',
+ values: {
+ errorGroupId: getShortGroupId(groupId),
+ },
+ })}
+
+
+
+
+ {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(
@@ -154,66 +147,56 @@ export function ErrorGroupDetails({ location, match }: ErrorGroupDetailsProps) {
return (
<>
-
-
-
- {showDetails && (
-
-
- {logMessage && (
-
-
- {logMessage}
-
- )}
-
- {excMessage || NOT_AVAILABLE_LABEL}
+
+
+ {showDetails && (
+
+
+ {logMessage && (
+ <>
- {culprit || NOT_AVAILABLE_LABEL}
-
-
- )}
- {logMessage}
+ >
)}
- />
-
-
- {showDetails && (
-
+
+ {excMessage || NOT_AVAILABLE_LABEL}
+
+ {culprit || NOT_AVAILABLE_LABEL}
+
+
+ )}
+
-
+ />
+
+
+ {showDetails && (
+
+ )}
>
);
}
diff --git a/x-pack/plugins/apm/public/components/app/Home/Home.test.tsx b/x-pack/plugins/apm/public/components/app/Home/Home.test.tsx
deleted file mode 100644
index ab3b76848c248..0000000000000
--- a/x-pack/plugins/apm/public/components/app/Home/Home.test.tsx
+++ /dev/null
@@ -1,33 +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 { shallow } from 'enzyme';
-import React from 'react';
-import { Home } from '../Home';
-import { MockApmPluginContextWrapper } from '../../../context/apm_plugin/mock_apm_plugin_context';
-
-describe('Home component', () => {
- it('should render services', () => {
- expect(
- shallow(
-
-
-
- )
- ).toMatchSnapshot();
- });
-
- it('should render traces', () => {
- expect(
- shallow(
-
-
-
- )
- ).toMatchSnapshot();
- });
-});
diff --git a/x-pack/plugins/apm/public/components/app/Home/__snapshots__/Home.test.tsx.snap b/x-pack/plugins/apm/public/components/app/Home/__snapshots__/Home.test.tsx.snap
deleted file mode 100644
index f13cce3fd9b40..0000000000000
--- a/x-pack/plugins/apm/public/components/app/Home/__snapshots__/Home.test.tsx.snap
+++ /dev/null
@@ -1,189 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`Home component should render services 1`] = `
-
-
-
-`;
-
-exports[`Home component should render traces 1`] = `
-
-
-
-`;
diff --git a/x-pack/plugins/apm/public/components/app/Home/index.tsx b/x-pack/plugins/apm/public/components/app/Home/index.tsx
deleted file mode 100644
index 834c2d5c40bce..0000000000000
--- a/x-pack/plugins/apm/public/components/app/Home/index.tsx
+++ /dev/null
@@ -1,80 +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, EuiTitle } from '@elastic/eui';
-import { i18n } from '@kbn/i18n';
-import React, { ComponentType } from 'react';
-import { $ElementType } from 'utility-types';
-import { ApmHeader } from '../../shared/ApmHeader';
-import { useServiceMapHref } from '../../shared/Links/apm/ServiceMapLink';
-import { useServiceInventoryHref } from '../../shared/Links/apm/service_inventory_link';
-import { useTraceOverviewHref } from '../../shared/Links/apm/TraceOverviewLink';
-import { MainTabs } from '../../shared/main_tabs';
-import { ServiceMap } from '../ServiceMap';
-import { ServiceInventory } from '../service_inventory';
-import { TraceOverview } from '../trace_overview';
-
-interface Tab {
- key: string;
- href: string;
- text: string;
- Component: ComponentType;
-}
-
-interface Props {
- tab: 'traces' | 'services' | 'service-map';
-}
-
-export function Home({ tab }: Props) {
- const homeTabs: Tab[] = [
- {
- key: 'services',
- href: useServiceInventoryHref(),
- text: i18n.translate('xpack.apm.home.servicesTabLabel', {
- defaultMessage: 'Services',
- }),
- Component: ServiceInventory,
- },
- {
- key: 'traces',
- href: useTraceOverviewHref(),
- text: i18n.translate('xpack.apm.home.tracesTabLabel', {
- defaultMessage: 'Traces',
- }),
- Component: TraceOverview,
- },
- {
- key: 'service-map',
- href: useServiceMapHref(),
- text: i18n.translate('xpack.apm.home.serviceMapTabLabel', {
- defaultMessage: 'Service Map',
- }),
- Component: ServiceMap,
- },
- ];
- const selectedTab = homeTabs.find(
- (homeTab) => homeTab.key === tab
- ) as $ElementType;
-
- return (
- <>
-
-
- APM
-
-
-
- {homeTabs.map(({ href, key, text }) => (
-
- {text}
-
- ))}
-
-
- >
- );
-}
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
deleted file mode 100644
index 89b8db5f386dc..0000000000000
--- a/x-pack/plugins/apm/public/components/app/Main/route_config/index.tsx
+++ /dev/null
@@ -1,369 +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 { i18n } from '@kbn/i18n';
-import React from 'react';
-import { Redirect, 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 { Home } from '../../Home';
-import { ServiceDetails } from '../../service_details';
-import { ServiceNodeMetrics } from '../../service_node_metrics';
-import { Settings } from '../../Settings';
-import { AgentConfigurations } from '../../Settings/AgentConfigurations';
-import { AnomalyDetection } from '../../Settings/anomaly_detection';
-import { ApmIndices } from '../../Settings/ApmIndices';
-import { CustomizeUI } from '../../Settings/CustomizeUI';
-import { TraceLink } from '../../TraceLink';
-import { TransactionDetails } from '../../transaction_details';
-import {
- CreateAgentConfigurationRouteHandler,
- EditAgentConfigurationRouteHandler,
-} from './route_handlers/agent_configuration';
-import { enableServiceOverview } from '../../../../../common/ui_settings_keys';
-import { useApmPluginContext } from '../../../../context/apm_plugin/use_apm_plugin_context';
-
-/**
- * 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) {
- return ({ location }: RouteComponentProps<{}>) => {
- let resolvedUrl: URL | undefined;
-
- // Redirect root URLs with a hash to support backward compatibility with URLs
- // from before we switched to the non-hash platform history.
- if (location.pathname === '' && location.hash.length > 0) {
- // We just want the search and pathname so the host doesn't matter
- resolvedUrl = new URL(location.hash.slice(1), 'http://localhost');
- to = resolvedUrl.pathname;
- }
-
- return (
-
- );
- };
-}
-
-// These component function definitions are used below with the `component`
-// property of the route definitions.
-//
-// If you provide an inline function to the component prop, you would create a
-// new component every render. This results in the existing component unmounting
-// and the new component mounting instead of just updating the existing component.
-function HomeServices() {
- return ;
-}
-
-function HomeServiceMap() {
- return ;
-}
-
-function HomeTraces() {
- return ;
-}
-
-function ServiceDetailsErrors(
- props: RouteComponentProps<{ serviceName: string }>
-) {
- return ;
-}
-
-function ServiceDetailsMetrics(
- props: RouteComponentProps<{ serviceName: string }>
-) {
- return ;
-}
-
-function ServiceDetailsNodes(
- props: RouteComponentProps<{ serviceName: string }>
-) {
- return ;
-}
-
-function ServiceDetailsOverview(
- props: RouteComponentProps<{ serviceName: string }>
-) {
- return ;
-}
-
-function ServiceDetailsServiceMap(
- props: RouteComponentProps<{ serviceName: string }>
-) {
- return ;
-}
-
-function ServiceDetailsTransactions(
- props: RouteComponentProps<{ serviceName: string }>
-) {
- return ;
-}
-
-function ServiceDetailsProfiling(
- props: RouteComponentProps<{ serviceName: string }>
-) {
- return ;
-}
-
-function SettingsAgentConfiguration(props: RouteComponentProps<{}>) {
- return (
-
-
-
- );
-}
-
-function SettingsAnomalyDetection(props: RouteComponentProps<{}>) {
- return (
-
-
-
- );
-}
-
-function SettingsApmIndices(props: RouteComponentProps<{}>) {
- return (
-
-
-
- );
-}
-
-function SettingsCustomizeUI(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);
-}
-
-/**
- * The array of route definitions to be used when the application
- * creates the routes.
- */
-export const routes: APMRouteDefinition[] = [
- {
- exact: true,
- path: '/',
- render: renderAsRedirectTo('/services'),
- breadcrumb: 'APM',
- },
- // !! Need to be kept in sync with the deepLinks in x-pack/plugins/apm/public/plugin.ts
- {
- exact: true,
- path: '/services',
- component: HomeServices,
- breadcrumb: i18n.translate('xpack.apm.breadcrumb.servicesTitle', {
- defaultMessage: 'Services',
- }),
- },
- // !! Need to be kept in sync with the deepLinks in x-pack/plugins/apm/public/plugin.ts
- {
- exact: true,
- path: '/traces',
- component: HomeTraces,
- breadcrumb: i18n.translate('xpack.apm.breadcrumb.tracesTitle', {
- defaultMessage: 'Traces',
- }),
- },
- {
- exact: true,
- path: '/settings',
- render: renderAsRedirectTo('/settings/agent-configuration'),
- breadcrumb: i18n.translate('xpack.apm.breadcrumb.listSettingsTitle', {
- defaultMessage: 'Settings',
- }),
- },
- {
- exact: true,
- path: '/settings/apm-indices',
- component: SettingsApmIndices,
- breadcrumb: i18n.translate('xpack.apm.breadcrumb.settings.indicesTitle', {
- defaultMessage: 'Indices',
- }),
- },
- {
- exact: true,
- path: '/settings/agent-configuration',
- component: SettingsAgentConfiguration,
- breadcrumb: i18n.translate(
- 'xpack.apm.breadcrumb.settings.agentConfigurationTitle',
- { defaultMessage: 'Agent Configuration' }
- ),
- },
- {
- exact: true,
- path: '/settings/agent-configuration/create',
- breadcrumb: i18n.translate(
- 'xpack.apm.breadcrumb.settings.createAgentConfigurationTitle',
- { defaultMessage: 'Create Agent Configuration' }
- ),
- component: CreateAgentConfigurationRouteHandler,
- },
- {
- exact: true,
- path: '/settings/agent-configuration/edit',
- breadcrumb: i18n.translate(
- 'xpack.apm.breadcrumb.settings.editAgentConfigurationTitle',
- { defaultMessage: 'Edit Agent Configuration' }
- ),
- component: EditAgentConfigurationRouteHandler,
- },
- {
- exact: true,
- path: '/services/:serviceName',
- breadcrumb: ({ match }) => match.params.serviceName,
- component: DefaultServicePageRouteHandler,
- } as APMRouteDefinition<{ serviceName: string }>,
- {
- exact: true,
- path: '/services/:serviceName/overview',
- breadcrumb: i18n.translate('xpack.apm.breadcrumb.overviewTitle', {
- defaultMessage: 'Overview',
- }),
- component: withApmServiceContext(ServiceDetailsOverview),
- } as APMRouteDefinition<{ serviceName: string }>,
- // errors
- {
- exact: true,
- path: '/services/:serviceName/errors/:groupId',
- component: withApmServiceContext(ErrorGroupDetails),
- breadcrumb: ({ match }) => match.params.groupId,
- } as APMRouteDefinition<{ groupId: string; serviceName: string }>,
- {
- exact: true,
- path: '/services/:serviceName/errors',
- component: withApmServiceContext(ServiceDetailsErrors),
- breadcrumb: i18n.translate('xpack.apm.breadcrumb.errorsTitle', {
- defaultMessage: 'Errors',
- }),
- },
- // transactions
- {
- exact: true,
- path: '/services/:serviceName/transactions',
- component: withApmServiceContext(ServiceDetailsTransactions),
- breadcrumb: i18n.translate('xpack.apm.breadcrumb.transactionsTitle', {
- defaultMessage: 'Transactions',
- }),
- },
- // metrics
- {
- exact: true,
- path: '/services/:serviceName/metrics',
- component: withApmServiceContext(ServiceDetailsMetrics),
- breadcrumb: i18n.translate('xpack.apm.breadcrumb.metricsTitle', {
- defaultMessage: 'Metrics',
- }),
- },
- // service nodes, only enabled for java agents for now
- {
- exact: true,
- path: '/services/:serviceName/nodes',
- component: withApmServiceContext(ServiceDetailsNodes),
- breadcrumb: i18n.translate('xpack.apm.breadcrumb.nodesTitle', {
- defaultMessage: 'JVMs',
- }),
- },
- // node metrics
- {
- exact: true,
- path: '/services/:serviceName/nodes/:serviceNodeName/metrics',
- component: withApmServiceContext(ServiceNodeMetrics),
- breadcrumb: ({ match }) => getServiceNodeName(match.params.serviceNodeName),
- },
- {
- exact: true,
- path: '/services/:serviceName/transactions/view',
- component: withApmServiceContext(TransactionDetails),
- breadcrumb: ({ location }) => {
- const query = toQuery(location.search);
- return query.transactionName as string;
- },
- },
- {
- exact: true,
- path: '/services/:serviceName/profiling',
- component: withApmServiceContext(ServiceDetailsProfiling),
- breadcrumb: i18n.translate('xpack.apm.breadcrumb.serviceProfilingTitle', {
- defaultMessage: 'Profiling',
- }),
- },
- {
- exact: true,
- path: '/services/:serviceName/service-map',
- component: withApmServiceContext(ServiceDetailsServiceMap),
- breadcrumb: i18n.translate('xpack.apm.breadcrumb.serviceMapTitle', {
- defaultMessage: 'Service Map',
- }),
- },
- {
- exact: true,
- path: '/link-to/trace/:traceId',
- component: TraceLink,
- breadcrumb: null,
- },
- // !! Need to be kept in sync with the deepLinks in x-pack/plugins/apm/public/plugin.ts
- {
- exact: true,
- path: '/service-map',
- component: HomeServiceMap,
- breadcrumb: i18n.translate('xpack.apm.breadcrumb.serviceMapTitle', {
- defaultMessage: 'Service Map',
- }),
- },
- {
- exact: true,
- path: '/settings/customize-ui',
- component: SettingsCustomizeUI,
- breadcrumb: i18n.translate('xpack.apm.breadcrumb.settings.customizeUI', {
- defaultMessage: 'Customize UI',
- }),
- },
- {
- exact: true,
- path: '/settings/anomaly-detection',
- component: SettingsAnomalyDetection,
- breadcrumb: i18n.translate(
- 'xpack.apm.breadcrumb.settings.anomalyDetection',
- {
- defaultMessage: 'Anomaly detection',
- }
- ),
- },
-];
-
-function withApmServiceContext(WrappedComponent: React.ComponentType) {
- return (props: any) => {
- return (
-
-
-
- );
- };
-}
diff --git a/x-pack/plugins/apm/public/components/app/Settings/AgentConfigurations/index.tsx b/x-pack/plugins/apm/public/components/app/Settings/AgentConfigurations/index.tsx
index 3225951fd6c70..b781a6569cc35 100644
--- a/x-pack/plugins/apm/public/components/app/Settings/AgentConfigurations/index.tsx
+++ b/x-pack/plugins/apm/public/components/app/Settings/AgentConfigurations/index.tsx
@@ -42,12 +42,12 @@ export function AgentConfigurations() {
return (
<>
-
-
+
+
{i18n.translate('xpack.apm.agentConfig.titleText', {
defaultMessage: 'Agent central configuration',
})}
-
+
diff --git a/x-pack/plugins/apm/public/components/app/Settings/ApmIndices/index.test.tsx b/x-pack/plugins/apm/public/components/app/Settings/ApmIndices/index.test.tsx
index 70672df85b649..28cb4ebd51cdd 100644
--- a/x-pack/plugins/apm/public/components/app/Settings/ApmIndices/index.test.tsx
+++ b/x-pack/plugins/apm/public/components/app/Settings/ApmIndices/index.test.tsx
@@ -25,11 +25,11 @@ describe('ApmIndices', () => {
);
expect(getByText('Indices')).toMatchInlineSnapshot(`
-
Indices
-
+
`);
expect(spy).toHaveBeenCalledTimes(2);
diff --git a/x-pack/plugins/apm/public/components/app/Settings/ApmIndices/index.tsx b/x-pack/plugins/apm/public/components/app/Settings/ApmIndices/index.tsx
index 9d2b4bba22afb..44a3c4655417c 100644
--- a/x-pack/plugins/apm/public/components/app/Settings/ApmIndices/index.tsx
+++ b/x-pack/plugins/apm/public/components/app/Settings/ApmIndices/index.tsx
@@ -176,12 +176,12 @@ export function ApmIndices() {
return (
<>
-
-
+
+
{i18n.translate('xpack.apm.settings.apmIndices.title', {
defaultMessage: 'Indices',
})}
-
+
diff --git a/x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/index.tsx b/x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/index.tsx
index fabd70cec6647..c4b3c39248ffb 100644
--- a/x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/index.tsx
+++ b/x-pack/plugins/apm/public/components/app/Settings/CustomizeUI/index.tsx
@@ -13,12 +13,12 @@ import { CustomLinkOverview } from './CustomLink';
export function CustomizeUI() {
return (
<>
-
-
+
+
{i18n.translate('xpack.apm.settings.customizeApp.title', {
defaultMessage: 'Customize app',
})}
-
+
diff --git a/x-pack/plugins/apm/public/components/app/Settings/anomaly_detection/index.tsx b/x-pack/plugins/apm/public/components/app/Settings/anomaly_detection/index.tsx
index 62b39664cf63d..38b9970f64d32 100644
--- a/x-pack/plugins/apm/public/components/app/Settings/anomaly_detection/index.tsx
+++ b/x-pack/plugins/apm/public/components/app/Settings/anomaly_detection/index.tsx
@@ -66,12 +66,12 @@ export function AnomalyDetection() {
return (
<>
-
-
+
+
{i18n.translate('xpack.apm.settings.anomalyDetection.titleText', {
defaultMessage: 'Anomaly detection',
})}
-
+
diff --git a/x-pack/plugins/apm/public/components/app/Settings/index.tsx b/x-pack/plugins/apm/public/components/app/Settings/index.tsx
index 36c36e3957e96..b4cba2afc2550 100644
--- a/x-pack/plugins/apm/public/components/app/Settings/index.tsx
+++ b/x-pack/plugins/apm/public/components/app/Settings/index.tsx
@@ -5,32 +5,19 @@
* 2.0.
*/
-import {
- EuiButtonEmpty,
- EuiPage,
- EuiPageBody,
- EuiPageSideBar,
- EuiSideNav,
- EuiSpacer,
-} from '@elastic/eui';
+import { EuiPage, EuiPageBody, EuiPageSideBar, EuiSideNav } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import React, { ReactNode, useState } from 'react';
-import { RouteComponentProps } from 'react-router-dom';
-import { HeaderMenuPortal } from '../../../../../observability/public';
-import { ActionMenu } from '../../../application/action_menu';
+import { useHistory } from 'react-router-dom';
import { useApmPluginContext } from '../../../context/apm_plugin/use_apm_plugin_context';
import { getAPMHref } from '../../shared/Links/apm/APMLink';
-import { HomeLink } from '../../shared/Links/apm/HomeLink';
-interface SettingsProps extends RouteComponentProps<{}> {
- children: ReactNode;
-}
-
-export function Settings({ children, location }: SettingsProps) {
- const { appMountParameters, core } = useApmPluginContext();
+export function Settings({ children }: { children: ReactNode }) {
+ const { core } = useApmPluginContext();
+ const history = useHistory();
const { basePath } = core.http;
const canAccessML = !!core.application.capabilities.ml?.canAccessML;
- const { search, pathname } = location;
+ const { search, pathname } = history.location;
const [isSideNavOpenOnMobile, setisSideNavOpenOnMobile] = useState(false);
@@ -43,86 +30,65 @@ export function Settings({ children, location }: SettingsProps) {
}
return (
- <>
-
-
-
-
-
-
-
- {i18n.translate('xpack.apm.settings.returnLinkLabel', {
- defaultMessage: 'Return to inventory',
- })}
-
-
-
- toggleOpenOnMobile()}
- isOpenOnMobile={isSideNavOpenOnMobile}
- items={[
- {
- name: i18n.translate('xpack.apm.settings.pageTitle', {
- defaultMessage: 'Settings',
- }),
- id: 0,
- items: [
- {
- name: i18n.translate('xpack.apm.settings.agentConfig', {
- defaultMessage: 'Agent Configuration',
- }),
- id: '1',
- href: getSettingsHref('/agent-configuration'),
- isSelected: pathname.startsWith(
- '/settings/agent-configuration'
- ),
- },
- ...(canAccessML
- ? [
- {
- name: i18n.translate(
- 'xpack.apm.settings.anomalyDetection',
- {
- defaultMessage: 'Anomaly detection',
- }
- ),
- id: '4',
- href: getSettingsHref('/anomaly-detection'),
- isSelected:
- pathname === '/settings/anomaly-detection',
- },
- ]
- : []),
- {
- name: i18n.translate('xpack.apm.settings.customizeApp', {
- defaultMessage: 'Customize app',
- }),
- id: '3',
- href: getSettingsHref('/customize-ui'),
- isSelected: pathname === '/settings/customize-ui',
- },
- {
- name: i18n.translate('xpack.apm.settings.indices', {
- defaultMessage: 'Indices',
- }),
- id: '2',
- href: getSettingsHref('/apm-indices'),
- isSelected: pathname === '/settings/apm-indices',
- },
- ],
- },
- ]}
- />
-
- {children}
-
- >
+
+
+ toggleOpenOnMobile()}
+ isOpenOnMobile={isSideNavOpenOnMobile}
+ items={[
+ {
+ name: i18n.translate('xpack.apm.settings.pageTitle', {
+ defaultMessage: 'Settings',
+ }),
+ id: 0,
+ items: [
+ {
+ name: i18n.translate('xpack.apm.settings.agentConfig', {
+ defaultMessage: 'Agent Configuration',
+ }),
+ id: '1',
+ href: getSettingsHref('/agent-configuration'),
+ isSelected: pathname.startsWith(
+ '/settings/agent-configuration'
+ ),
+ },
+ ...(canAccessML
+ ? [
+ {
+ name: i18n.translate(
+ 'xpack.apm.settings.anomalyDetection',
+ {
+ defaultMessage: 'Anomaly detection',
+ }
+ ),
+ id: '4',
+ href: getSettingsHref('/anomaly-detection'),
+ isSelected: pathname === '/settings/anomaly-detection',
+ },
+ ]
+ : []),
+ {
+ name: i18n.translate('xpack.apm.settings.customizeApp', {
+ defaultMessage: 'Customize app',
+ }),
+ id: '3',
+ href: getSettingsHref('/customize-ui'),
+ isSelected: pathname === '/settings/customize-ui',
+ },
+ {
+ name: i18n.translate('xpack.apm.settings.indices', {
+ defaultMessage: 'Indices',
+ }),
+ id: '2',
+ href: getSettingsHref('/apm-indices'),
+ isSelected: pathname === '/settings/apm-indices',
+ },
+ ],
+ },
+ ]}
+ />
+
+ {children}
+
);
}
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 6f7a8228db298..95ec80b1a51bc 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
@@ -7,7 +7,7 @@
import {
EuiFlexGroup,
- EuiPage,
+ EuiFlexItem,
EuiPanel,
EuiSpacer,
EuiTitle,
@@ -18,7 +18,6 @@ import { useTrackPageview } from '../../../../../observability/public';
import { useUrlParams } from '../../../context/url_params_context/use_url_params';
import { useErrorGroupDistributionFetcher } from '../../../hooks/use_error_group_distribution_fetcher';
import { useFetcher } from '../../../hooks/use_fetcher';
-import { SearchBar } from '../../shared/search_bar';
import { ErrorDistribution } from '../ErrorGroupDetails/Distribution';
import { ErrorGroupList } from './List';
@@ -68,41 +67,41 @@ export function ErrorGroupOverview({ serviceName }: ErrorGroupOverviewProps) {
useTrackPageview({ app: 'apm', path: 'error_group_overview', delay: 15000 });
if (!errorDistributionData || !errorGroupListData) {
- return ;
+ return null;
}
return (
- <>
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+ {i18n.translate(
+ 'xpack.apm.serviceDetails.metrics.errorsList.title',
+ { defaultMessage: '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 29bb1c04ab945..0000000000000
--- a/x-pack/plugins/apm/public/components/app/service_details/index.tsx
+++ /dev/null
@@ -1,39 +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 { EuiFlexGroup, EuiFlexItem, EuiTitle } from '@elastic/eui';
-import React from 'react';
-import { RouteComponentProps } from 'react-router-dom';
-import { ApmHeader } from '../../shared/ApmHeader';
-import { ServiceIcons } from './service_icons';
-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 (
-
-
-
-
-
- {serviceName}
-
-
-
-
-
-
-
-
-
- );
-}
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 d360b186aba16..0000000000000
--- a/x-pack/plugins/apm/public/components/app/service_details/service_detail_tabs.tsx
+++ /dev/null
@@ -1,202 +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 { 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 { MainTabs } from '../../shared/main_tabs';
-import { ErrorGroupOverview } from '../error_group_overview';
-import { ServiceMap } from '../ServiceMap';
-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';
-
-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}
- >
- );
-}
diff --git a/x-pack/plugins/apm/public/components/app/service_inventory/index.tsx b/x-pack/plugins/apm/public/components/app/service_inventory/index.tsx
index 9c4728488d96a..78f02c5a66701 100644
--- a/x-pack/plugins/apm/public/components/app/service_inventory/index.tsx
+++ b/x-pack/plugins/apm/public/components/app/service_inventory/index.tsx
@@ -5,13 +5,7 @@
* 2.0.
*/
-import {
- EuiFlexGroup,
- EuiFlexItem,
- EuiLink,
- EuiPage,
- EuiPanel,
-} from '@elastic/eui';
+import { EuiFlexGroup, EuiFlexItem, EuiLink, EuiPanel } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import React, { useEffect } from 'react';
import { toMountPoint } from '../../../../../../../src/plugins/kibana_react/public';
@@ -126,28 +120,26 @@ export function ServiceInventory() {
return (
<>
-
-
- {displayMlCallout ? (
-
- setUserHasDismissedCallout(true)} />
-
- ) : null}
+
+ {displayMlCallout && (
-
-
- }
- />
-
+ setUserHasDismissedCallout(true)} />
-
-
+ )}
+
+
+
+ }
+ />
+
+
+
>
);
}
diff --git a/x-pack/plugins/apm/public/components/app/ServiceMap/Controls.test.tsx b/x-pack/plugins/apm/public/components/app/service_map/Controls.test.tsx
similarity index 100%
rename from x-pack/plugins/apm/public/components/app/ServiceMap/Controls.test.tsx
rename to x-pack/plugins/apm/public/components/app/service_map/Controls.test.tsx
diff --git a/x-pack/plugins/apm/public/components/app/ServiceMap/Controls.tsx b/x-pack/plugins/apm/public/components/app/service_map/Controls.tsx
similarity index 100%
rename from x-pack/plugins/apm/public/components/app/ServiceMap/Controls.tsx
rename to x-pack/plugins/apm/public/components/app/service_map/Controls.tsx
diff --git a/x-pack/plugins/apm/public/components/app/ServiceMap/Cytoscape.tsx b/x-pack/plugins/apm/public/components/app/service_map/Cytoscape.tsx
similarity index 100%
rename from x-pack/plugins/apm/public/components/app/ServiceMap/Cytoscape.tsx
rename to x-pack/plugins/apm/public/components/app/service_map/Cytoscape.tsx
diff --git a/x-pack/plugins/apm/public/components/app/ServiceMap/EmptyBanner.tsx b/x-pack/plugins/apm/public/components/app/service_map/EmptyBanner.tsx
similarity index 100%
rename from x-pack/plugins/apm/public/components/app/ServiceMap/EmptyBanner.tsx
rename to x-pack/plugins/apm/public/components/app/service_map/EmptyBanner.tsx
diff --git a/x-pack/plugins/apm/public/components/app/ServiceMap/Popover/AnomalyDetection.tsx b/x-pack/plugins/apm/public/components/app/service_map/Popover/AnomalyDetection.tsx
similarity index 100%
rename from x-pack/plugins/apm/public/components/app/ServiceMap/Popover/AnomalyDetection.tsx
rename to x-pack/plugins/apm/public/components/app/service_map/Popover/AnomalyDetection.tsx
diff --git a/x-pack/plugins/apm/public/components/app/ServiceMap/Popover/Buttons.test.tsx b/x-pack/plugins/apm/public/components/app/service_map/Popover/Buttons.test.tsx
similarity index 100%
rename from x-pack/plugins/apm/public/components/app/ServiceMap/Popover/Buttons.test.tsx
rename to x-pack/plugins/apm/public/components/app/service_map/Popover/Buttons.test.tsx
diff --git a/x-pack/plugins/apm/public/components/app/ServiceMap/Popover/Buttons.tsx b/x-pack/plugins/apm/public/components/app/service_map/Popover/Buttons.tsx
similarity index 100%
rename from x-pack/plugins/apm/public/components/app/ServiceMap/Popover/Buttons.tsx
rename to x-pack/plugins/apm/public/components/app/service_map/Popover/Buttons.tsx
diff --git a/x-pack/plugins/apm/public/components/app/ServiceMap/Popover/Contents.tsx b/x-pack/plugins/apm/public/components/app/service_map/Popover/Contents.tsx
similarity index 100%
rename from x-pack/plugins/apm/public/components/app/ServiceMap/Popover/Contents.tsx
rename to x-pack/plugins/apm/public/components/app/service_map/Popover/Contents.tsx
diff --git a/x-pack/plugins/apm/public/components/app/ServiceMap/Popover/Info.tsx b/x-pack/plugins/apm/public/components/app/service_map/Popover/Info.tsx
similarity index 100%
rename from x-pack/plugins/apm/public/components/app/ServiceMap/Popover/Info.tsx
rename to x-pack/plugins/apm/public/components/app/service_map/Popover/Info.tsx
diff --git a/x-pack/plugins/apm/public/components/app/ServiceMap/Popover/Popover.stories.tsx b/x-pack/plugins/apm/public/components/app/service_map/Popover/Popover.stories.tsx
similarity index 97%
rename from x-pack/plugins/apm/public/components/app/ServiceMap/Popover/Popover.stories.tsx
rename to x-pack/plugins/apm/public/components/app/service_map/Popover/Popover.stories.tsx
index ac1846155569a..fe3922060533a 100644
--- a/x-pack/plugins/apm/public/components/app/ServiceMap/Popover/Popover.stories.tsx
+++ b/x-pack/plugins/apm/public/components/app/service_map/Popover/Popover.stories.tsx
@@ -13,11 +13,11 @@ import { MockApmPluginContextWrapper } from '../../../../context/apm_plugin/mock
import { MockUrlParamsContextProvider } from '../../../../context/url_params_context/mock_url_params_context_provider';
import { createCallApmApi } from '../../../../services/rest/createCallApmApi';
import { CytoscapeContext } from '../Cytoscape';
-import { Popover } from './';
+import { Popover } from '.';
import exampleGroupedConnectionsData from '../__stories__/example_grouped_connections.json';
export default {
- title: 'app/ServiceMap/Popover',
+ title: 'app/service_map/Popover',
component: Popover,
decorators: [
(Story: ComponentType) => {
diff --git a/x-pack/plugins/apm/public/components/app/ServiceMap/Popover/ServiceStatsFetcher.tsx b/x-pack/plugins/apm/public/components/app/service_map/Popover/ServiceStatsFetcher.tsx
similarity index 100%
rename from x-pack/plugins/apm/public/components/app/ServiceMap/Popover/ServiceStatsFetcher.tsx
rename to x-pack/plugins/apm/public/components/app/service_map/Popover/ServiceStatsFetcher.tsx
diff --git a/x-pack/plugins/apm/public/components/app/ServiceMap/Popover/ServiceStatsList.tsx b/x-pack/plugins/apm/public/components/app/service_map/Popover/ServiceStatsList.tsx
similarity index 100%
rename from x-pack/plugins/apm/public/components/app/ServiceMap/Popover/ServiceStatsList.tsx
rename to x-pack/plugins/apm/public/components/app/service_map/Popover/ServiceStatsList.tsx
diff --git a/x-pack/plugins/apm/public/components/app/ServiceMap/Popover/index.tsx b/x-pack/plugins/apm/public/components/app/service_map/Popover/index.tsx
similarity index 100%
rename from x-pack/plugins/apm/public/components/app/ServiceMap/Popover/index.tsx
rename to x-pack/plugins/apm/public/components/app/service_map/Popover/index.tsx
diff --git a/x-pack/plugins/apm/public/components/app/ServiceMap/Popover/service_stats_list.stories.tsx b/x-pack/plugins/apm/public/components/app/service_map/Popover/service_stats_list.stories.tsx
similarity index 96%
rename from x-pack/plugins/apm/public/components/app/ServiceMap/Popover/service_stats_list.stories.tsx
rename to x-pack/plugins/apm/public/components/app/service_map/Popover/service_stats_list.stories.tsx
index a8f004a7295d9..83f0a3ea7e4b9 100644
--- a/x-pack/plugins/apm/public/components/app/ServiceMap/Popover/service_stats_list.stories.tsx
+++ b/x-pack/plugins/apm/public/components/app/service_map/Popover/service_stats_list.stories.tsx
@@ -10,7 +10,7 @@ import { EuiThemeProvider } from '../../../../../../../../src/plugins/kibana_rea
import { ServiceStatsList } from './ServiceStatsList';
export default {
- title: 'app/ServiceMap/Popover/ServiceStatsList',
+ title: 'app/service_map/Popover/ServiceStatsList',
component: ServiceStatsList,
decorators: [
(Story: ComponentType) => (
diff --git a/x-pack/plugins/apm/public/components/app/ServiceMap/__stories__/Cytoscape.stories.tsx b/x-pack/plugins/apm/public/components/app/service_map/__stories__/Cytoscape.stories.tsx
similarity index 99%
rename from x-pack/plugins/apm/public/components/app/ServiceMap/__stories__/Cytoscape.stories.tsx
rename to x-pack/plugins/apm/public/components/app/service_map/__stories__/Cytoscape.stories.tsx
index 37644c084815e..c3f3c09e10e4f 100644
--- a/x-pack/plugins/apm/public/components/app/ServiceMap/__stories__/Cytoscape.stories.tsx
+++ b/x-pack/plugins/apm/public/components/app/service_map/__stories__/Cytoscape.stories.tsx
@@ -14,7 +14,7 @@ import { iconForNode } from '../icons';
import { Centerer } from './centerer';
export default {
- title: 'app/ServiceMap/Cytoscape',
+ title: 'app/service_map/Cytoscape',
component: Cytoscape,
decorators: [
(Story: ComponentType) => (
diff --git a/x-pack/plugins/apm/public/components/app/ServiceMap/__stories__/centerer.tsx b/x-pack/plugins/apm/public/components/app/service_map/__stories__/centerer.tsx
similarity index 100%
rename from x-pack/plugins/apm/public/components/app/ServiceMap/__stories__/centerer.tsx
rename to x-pack/plugins/apm/public/components/app/service_map/__stories__/centerer.tsx
diff --git a/x-pack/plugins/apm/public/components/app/ServiceMap/__stories__/cytoscape_example_data.stories.tsx b/x-pack/plugins/apm/public/components/app/service_map/__stories__/cytoscape_example_data.stories.tsx
similarity index 98%
rename from x-pack/plugins/apm/public/components/app/ServiceMap/__stories__/cytoscape_example_data.stories.tsx
rename to x-pack/plugins/apm/public/components/app/service_map/__stories__/cytoscape_example_data.stories.tsx
index 41eecb9181a2c..84351d5716edb 100644
--- a/x-pack/plugins/apm/public/components/app/ServiceMap/__stories__/cytoscape_example_data.stories.tsx
+++ b/x-pack/plugins/apm/public/components/app/service_map/__stories__/cytoscape_example_data.stories.tsx
@@ -25,7 +25,7 @@ import exampleResponseOpbeansBeats from './example_response_opbeans_beats.json';
import exampleResponseTodo from './example_response_todo.json';
import { generateServiceMapElements } from './generate_service_map_elements';
-const STORYBOOK_PATH = 'app/ServiceMap/Cytoscape/Example data';
+const STORYBOOK_PATH = 'app/service_map/Cytoscape/Example data';
const SESSION_STORAGE_KEY = `${STORYBOOK_PATH}/pre-loaded map`;
function getSessionJson() {
@@ -40,7 +40,7 @@ function getHeight() {
}
export default {
- title: 'app/ServiceMap/Cytoscape/Example data',
+ title: 'app/service_map/Cytoscape/Example data',
component: Cytoscape,
decorators: [
(Story: ComponentType) => (
diff --git a/x-pack/plugins/apm/public/components/app/ServiceMap/__stories__/example_grouped_connections.json b/x-pack/plugins/apm/public/components/app/service_map/__stories__/example_grouped_connections.json
similarity index 100%
rename from x-pack/plugins/apm/public/components/app/ServiceMap/__stories__/example_grouped_connections.json
rename to x-pack/plugins/apm/public/components/app/service_map/__stories__/example_grouped_connections.json
diff --git a/x-pack/plugins/apm/public/components/app/ServiceMap/__stories__/example_response_hipster_store.json b/x-pack/plugins/apm/public/components/app/service_map/__stories__/example_response_hipster_store.json
similarity index 100%
rename from x-pack/plugins/apm/public/components/app/ServiceMap/__stories__/example_response_hipster_store.json
rename to x-pack/plugins/apm/public/components/app/service_map/__stories__/example_response_hipster_store.json
diff --git a/x-pack/plugins/apm/public/components/app/ServiceMap/__stories__/example_response_opbeans_beats.json b/x-pack/plugins/apm/public/components/app/service_map/__stories__/example_response_opbeans_beats.json
similarity index 100%
rename from x-pack/plugins/apm/public/components/app/ServiceMap/__stories__/example_response_opbeans_beats.json
rename to x-pack/plugins/apm/public/components/app/service_map/__stories__/example_response_opbeans_beats.json
diff --git a/x-pack/plugins/apm/public/components/app/ServiceMap/__stories__/example_response_todo.json b/x-pack/plugins/apm/public/components/app/service_map/__stories__/example_response_todo.json
similarity index 100%
rename from x-pack/plugins/apm/public/components/app/ServiceMap/__stories__/example_response_todo.json
rename to x-pack/plugins/apm/public/components/app/service_map/__stories__/example_response_todo.json
diff --git a/x-pack/plugins/apm/public/components/app/ServiceMap/__stories__/generate_service_map_elements.ts b/x-pack/plugins/apm/public/components/app/service_map/__stories__/generate_service_map_elements.ts
similarity index 100%
rename from x-pack/plugins/apm/public/components/app/ServiceMap/__stories__/generate_service_map_elements.ts
rename to x-pack/plugins/apm/public/components/app/service_map/__stories__/generate_service_map_elements.ts
diff --git a/x-pack/plugins/apm/public/components/app/ServiceMap/cytoscape_options.ts b/x-pack/plugins/apm/public/components/app/service_map/cytoscape_options.ts
similarity index 100%
rename from x-pack/plugins/apm/public/components/app/ServiceMap/cytoscape_options.ts
rename to x-pack/plugins/apm/public/components/app/service_map/cytoscape_options.ts
diff --git a/x-pack/plugins/apm/public/components/app/ServiceMap/empty_banner.test.tsx b/x-pack/plugins/apm/public/components/app/service_map/empty_banner.test.tsx
similarity index 100%
rename from x-pack/plugins/apm/public/components/app/ServiceMap/empty_banner.test.tsx
rename to x-pack/plugins/apm/public/components/app/service_map/empty_banner.test.tsx
diff --git a/x-pack/plugins/apm/public/components/app/ServiceMap/empty_prompt.tsx b/x-pack/plugins/apm/public/components/app/service_map/empty_prompt.tsx
similarity index 100%
rename from x-pack/plugins/apm/public/components/app/ServiceMap/empty_prompt.tsx
rename to x-pack/plugins/apm/public/components/app/service_map/empty_prompt.tsx
diff --git a/x-pack/plugins/apm/public/components/app/ServiceMap/icons.ts b/x-pack/plugins/apm/public/components/app/service_map/icons.ts
similarity index 100%
rename from x-pack/plugins/apm/public/components/app/ServiceMap/icons.ts
rename to x-pack/plugins/apm/public/components/app/service_map/icons.ts
diff --git a/x-pack/plugins/apm/public/components/app/ServiceMap/index.test.tsx b/x-pack/plugins/apm/public/components/app/service_map/index.test.tsx
similarity index 99%
rename from x-pack/plugins/apm/public/components/app/ServiceMap/index.test.tsx
rename to x-pack/plugins/apm/public/components/app/service_map/index.test.tsx
index e8384de1d15ba..f68d8e46f66e3 100644
--- a/x-pack/plugins/apm/public/components/app/ServiceMap/index.test.tsx
+++ b/x-pack/plugins/apm/public/components/app/service_map/index.test.tsx
@@ -15,7 +15,7 @@ import { EuiThemeProvider } from '../../../../../../../src/plugins/kibana_react/
import { MockApmPluginContextWrapper } from '../../../context/apm_plugin/mock_apm_plugin_context';
import { LicenseContext } from '../../../context/license/license_context';
import * as useFetcherModule from '../../../hooks/use_fetcher';
-import { ServiceMap } from './';
+import { ServiceMap } from '.';
import { UrlParamsProvider } from '../../../context/url_params_context/url_params_context';
import { Router } from 'react-router-dom';
diff --git a/x-pack/plugins/apm/public/components/app/ServiceMap/index.tsx b/x-pack/plugins/apm/public/components/app/service_map/index.tsx
similarity index 87%
rename from x-pack/plugins/apm/public/components/app/ServiceMap/index.tsx
rename to x-pack/plugins/apm/public/components/app/service_map/index.tsx
index b338d1e4ab03d..714228d58f962 100644
--- a/x-pack/plugins/apm/public/components/app/ServiceMap/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.test.tsx b/x-pack/plugins/apm/public/components/app/service_node_metrics/index.test.tsx
index d9cd003042a45..8711366fdd185 100644
--- a/x-pack/plugins/apm/public/components/app/service_node_metrics/index.test.tsx
+++ b/x-pack/plugins/apm/public/components/app/service_node_metrics/index.test.tsx
@@ -9,20 +9,17 @@ import React from 'react';
import { shallow } from 'enzyme';
import { ServiceNodeMetrics } from '.';
import { MockApmPluginContextWrapper } from '../../../context/apm_plugin/mock_apm_plugin_context';
-import { RouteComponentProps } from 'react-router-dom';
describe('ServiceNodeMetrics', () => {
describe('render', () => {
it('renders', () => {
- const props = ({} as unknown) as RouteComponentProps<{
- serviceName: string;
- serviceNodeName: string;
- }>;
-
expect(() =>
shallow(
-
+
)
).not.toThrowError();
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 186c148fa6918..20b78b90e0378 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
@@ -10,17 +10,14 @@ import {
EuiFlexGrid,
EuiFlexGroup,
EuiFlexItem,
- EuiPage,
EuiPanel,
EuiSpacer,
EuiStat,
- EuiTitle,
EuiToolTip,
} from '@elastic/eui';
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';
@@ -29,10 +26,8 @@ import { useServiceMetricChartsFetcher } from '../../../hooks/use_service_metric
import { useUrlParams } from '../../../context/url_params_context/use_url_params';
import { useApmServiceContext } from '../../../context/apm_service/use_apm_service_context';
import { px, truncate, unit } from '../../../style/variables';
-import { ApmHeader } from '../../shared/ApmHeader';
import { MetricsChart } from '../../shared/charts/metrics_chart';
import { ElasticDocsLink } from '../../shared/Links/ElasticDocsLink';
-import { SearchBar } from '../../shared/search_bar';
const INITIAL_DATA = {
host: '',
@@ -51,16 +46,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 });
@@ -89,15 +86,6 @@ export function ServiceNodeMetrics({ match }: ServiceNodeMetricsProps) {
return (
<>
-
-
-
-
- {serviceName}
-
-
-
-
{isAggregatedData ? (
)}
-
-
- {agentName && (
-
-
- {data.charts.map((chart) => (
-
-
-
-
-
- ))}
-
-
-
- )}
-
+
+ {agentName && (
+
+
+ {data.charts.map((chart) => (
+
+
+
+
+
+ ))}
+
+
+
+ )}
>
);
}
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 3d284de621ea3..69e5ea5a78ea1 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
@@ -4,7 +4,7 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
-import { EuiFlexGroup, EuiPage, EuiPanel, EuiToolTip } from '@elastic/eui';
+import { EuiPanel, EuiToolTip } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import React from 'react';
import { euiStyled } from '../../../../../../../src/plugins/kibana_react/common';
@@ -22,7 +22,6 @@ import { useFetcher } from '../../../hooks/use_fetcher';
import { px, truncate, unit } from '../../../style/variables';
import { ServiceNodeMetricOverviewLink } from '../../shared/Links/apm/ServiceNodeMetricOverviewLink';
import { ITableColumn, ManagedTable } from '../../shared/ManagedTable';
-import { SearchBar } from '../../shared/search_bar';
const INITIAL_PAGE_SIZE = 25;
const INITIAL_SORT_FIELD = 'cpu';
@@ -143,28 +142,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 cd1ced1830123..f7046d9e40138 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
@@ -5,17 +5,17 @@
* 2.0.
*/
-import { EuiFlexGroup, EuiFlexItem, EuiPage, EuiPanel } from '@elastic/eui';
+import { EuiFlexGroup, EuiFlexItem, EuiPanel } from '@elastic/eui';
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';
import { TransactionBreakdownChart } from '../../shared/charts/transaction_breakdown_chart';
import { TransactionErrorRateChart } from '../../shared/charts/transaction_error_rate_chart';
-import { SearchBar } from '../../shared/search_bar';
import { ServiceOverviewDependenciesTable } from './service_overview_dependencies_table';
import { ServiceOverviewErrorsTable } from './service_overview_errors_table';
import { ServiceOverviewInstancesChartAndTable } from './service_overview_instances_chart_and_table';
@@ -29,14 +29,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,89 +47,84 @@ export function ServiceOverview({
return (
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {!isRumAgent && (
-
+
+ )}
+
+
+
+
+
+
+
+
+
+
+
+
+ {!isRumAgent && (
-
-
-
+ )}
+
+
+ {!isRumAgent && (
- {!isRumAgent && (
-
-
-
- )}
-
-
-
-
-
+
-
-
-
-
-
- {!isRumAgent && (
-
-
-
-
-
- )}
-
-
- {!isRumAgent && (
-
-
-
-
-
- )}
-
-
+ )}
+
);
diff --git a/x-pack/plugins/apm/public/components/app/service_overview/service_overview_instances_table/get_columns.tsx b/x-pack/plugins/apm/public/components/app/service_overview/service_overview_instances_table/get_columns.tsx
index 46747e18c44af..a92efff103910 100644
--- a/x-pack/plugins/apm/public/components/app/service_overview/service_overview_instances_table/get_columns.tsx
+++ b/x-pack/plugins/apm/public/components/app/service_overview/service_overview_instances_table/get_columns.tsx
@@ -234,6 +234,7 @@ export function getColumns({
anchorPosition="leftCenter"
button={
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 ba1da7e6dd6eb..5c2bbd9e20c59 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 94391b5b2fb06..c6e1f575298c6 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
@@ -4,14 +4,7 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
-import {
- EuiFlexGroup,
- EuiFlexItem,
- EuiPage,
- EuiPanel,
- EuiTitle,
-} from '@elastic/eui';
-import { i18n } from '@kbn/i18n';
+import { EuiFlexGroup, EuiFlexItem, EuiPanel, EuiTitle } from '@elastic/eui';
import React, { useEffect, useState } from 'react';
import {
getValueTypeConfig,
@@ -20,7 +13,6 @@ import {
import { useUrlParams } from '../../../context/url_params_context/use_url_params';
import { useFetcher } from '../../../hooks/use_fetcher';
import { APIReturnType } from '../../../services/rest/createCallApmApi';
-import { SearchBar } from '../../shared/search_bar';
import { ServiceProfilingFlamegraph } from './service_profiling_flamegraph';
import { ServiceProfilingTimeline } from './service_profiling_timeline';
@@ -90,54 +82,38 @@ export function ServiceProfiling({
return (
<>
-
-
-
-
-
-
- {i18n.translate('xpack.apm.profilingOverviewTitle', {
- defaultMessage: 'Profiling',
- })}
-
-
+
+
+
+ {
+ setValueType(type);
+ }}
+ selectedValueType={valueType}
+ />
+ {valueType ? (
+
+
+ {getValueTypeConfig(valueType).label}
+
+
+ ) : null}
-
-
-
- {
- setValueType(type);
- }}
- selectedValueType={valueType}
- />
-
- {valueType ? (
-
-
- {getValueTypeConfig(valueType).label}
-
-
- ) : null}
-
-
-
-
-
+
-
+
>
);
}
diff --git a/x-pack/plugins/apm/public/components/app/trace_overview/index.tsx b/x-pack/plugins/apm/public/components/app/trace_overview/index.tsx
index 364266d277482..0938456193dc0 100644
--- a/x-pack/plugins/apm/public/components/app/trace_overview/index.tsx
+++ b/x-pack/plugins/apm/public/components/app/trace_overview/index.tsx
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { EuiFlexGroup, EuiPage, EuiPanel } from '@elastic/eui';
+import { EuiPanel } from '@elastic/eui';
import React from 'react';
import { useTrackPageview } from '../../../../../observability/public';
import { useUrlParams } from '../../../context/url_params_context/use_url_params';
@@ -50,16 +50,13 @@ export function TraceOverview() {
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 7f8ffb62d9e72..ae58e6f60cf09 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 baced34ad3e56..b0721791081fa 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 4be595ac16c6c..d7613699221b4 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/WaterfallContainer.stories.tsx b/x-pack/plugins/apm/public/components/app/transaction_details/WaterfallWithSummmary/WaterfallContainer/WaterfallContainer.stories.tsx
index 57743590ea566..5ea2fca2dfa32 100644
--- a/x-pack/plugins/apm/public/components/app/transaction_details/WaterfallWithSummmary/WaterfallContainer/WaterfallContainer.stories.tsx
+++ b/x-pack/plugins/apm/public/components/app/transaction_details/WaterfallWithSummmary/WaterfallContainer/WaterfallContainer.stories.tsx
@@ -15,7 +15,6 @@ import { WaterfallContainer } from './index';
import { getWaterfall } from './Waterfall/waterfall_helpers/waterfall_helpers';
import {
inferredSpans,
- location,
simpleTrace,
traceChildStartBeforeParent,
traceWithErrors,
@@ -45,7 +44,6 @@ export function Example() {
);
return (
;
-
-export function TransactionDetails({
- location,
- match,
-}: TransactionDetailsProps) {
+export function TransactionDetails() {
const { urlParams } = useUrlParams();
const history = useHistory();
const {
@@ -90,48 +76,43 @@ export function TransactionDetails({
return (
<>
-
-
- {transactionName}
-
-
-
-
-
-
-
-
-
-
-
-
- {
- if (!isEmpty(bucket.samples)) {
- selectSampleFromBucketClick(bucket.samples[0]);
- }
- }}
- />
-
-
-
-
-
-
-
-
-
+
+ {transactionName}
+
+
+
+
+
+
+
+
+
+
+
+ {
+ if (!isEmpty(bucket.samples)) {
+ selectSampleFromBucketClick(bucket.samples[0]);
+ }
+ }}
+ />
+
+
+
+
+
+
+
>
);
}
diff --git a/x-pack/plugins/apm/public/components/app/transaction_overview/index.tsx b/x-pack/plugins/apm/public/components/app/transaction_overview/index.tsx
index 9e2743d7b5986..38066b4ecd3f7 100644
--- a/x-pack/plugins/apm/public/components/app/transaction_overview/index.tsx
+++ b/x-pack/plugins/apm/public/components/app/transaction_overview/index.tsx
@@ -8,8 +8,6 @@
import {
EuiCallOut,
EuiCode,
- EuiFlexGroup,
- EuiPage,
EuiPanel,
EuiSpacer,
EuiTitle,
@@ -26,7 +24,6 @@ import { useUrlParams } from '../../../context/url_params_context/use_url_params
import { TransactionCharts } from '../../shared/charts/transaction_charts';
import { ElasticDocsLink } from '../../shared/Links/ElasticDocsLink';
import { fromQuery, toQuery } from '../../shared/Links/url_helpers';
-import { SearchBar } from '../../shared/search_bar';
import { TransactionList } from './TransactionList';
import { useRedirect } from './useRedirect';
import { useTransactionListFetcher } from './use_transaction_list';
@@ -80,62 +77,55 @@ export function TransactionOverview({ serviceName }: TransactionOverviewProps) {
return (
<>
-
-
-
-
-
-
-
- Transactions
-
-
- {!transactionListData.isAggregationAccurate && (
-
-
-
- xpack.apm.ui.transactionGroupBucketSize
-
- ),
- }}
- />
-
-
- {i18n.translate(
- 'xpack.apm.transactionCardinalityWarning.docsLink',
- { defaultMessage: 'Learn more in the docs' }
- )}
-
-
-
+
+
+
+
+ Transactions
+
+
+ {!transactionListData.isAggregationAccurate && (
+
-
-
-
-
+ color="danger"
+ iconType="alert"
+ >
+
+ xpack.apm.ui.transactionGroupBucketSize
+ ),
+ }}
+ />
+
+
+ {i18n.translate(
+ 'xpack.apm.transactionCardinalityWarning.docsLink',
+ { defaultMessage: 'Learn more in the docs' }
+ )}
+
+
+
+ )}
+
+
+
>
);
}
diff --git a/x-pack/plugins/apm/public/components/app/transaction_overview/transaction_overview.test.tsx b/x-pack/plugins/apm/public/components/app/transaction_overview/transaction_overview.test.tsx
index e4fbd07566060..9c4c2aa11a858 100644
--- a/x-pack/plugins/apm/public/components/app/transaction_overview/transaction_overview.test.tsx
+++ b/x-pack/plugins/apm/public/components/app/transaction_overview/transaction_overview.test.tsx
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { fireEvent, getByText, queryByLabelText } from '@testing-library/react';
+import { queryByLabelText } from '@testing-library/react';
import { createMemoryHistory } from 'history';
import { CoreStart } from 'kibana/public';
import React from 'react';
@@ -107,46 +107,6 @@ describe('TransactionOverview', () => {
const FILTER_BY_TYPE_LABEL = 'Transaction type';
- describe('when transactionType is selected and multiple transaction types are given', () => {
- it('renders a radio group with transaction types', () => {
- const { container } = setup({
- serviceTransactionTypes: ['firstType', 'secondType'],
- urlParams: {
- transactionType: 'secondType',
- },
- });
-
- expect(getByText(container, 'firstType')).toBeInTheDocument();
- expect(getByText(container, 'secondType')).toBeInTheDocument();
-
- expect(getByText(container, 'firstType')).not.toBeNull();
- });
-
- it('should update the URL when a transaction type is selected', () => {
- const { container } = setup({
- serviceTransactionTypes: ['firstType', 'secondType'],
- urlParams: {
- transactionType: 'secondType',
- },
- });
-
- expect(history.location.search).toEqual(
- '?transactionType=secondType&rangeFrom=now-15m&rangeTo=now'
- );
- expect(getByText(container, 'firstType')).toBeInTheDocument();
- expect(getByText(container, 'secondType')).toBeInTheDocument();
-
- fireEvent.change(getByText(container, 'firstType').parentElement!, {
- target: { value: 'firstType' },
- });
-
- expect(history.push).toHaveBeenCalled();
- expect(history.location.search).toEqual(
- '?transactionType=firstType&rangeFrom=now-15m&rangeTo=now'
- );
- });
- });
-
describe('when a transaction type is selected, and there are no other transaction types', () => {
it('does not render a radio group with transaction types', () => {
const { container } = setup({
diff --git a/x-pack/plugins/apm/public/components/routing/apm_route_config.tsx b/x-pack/plugins/apm/public/components/routing/apm_route_config.tsx
new file mode 100644
index 0000000000000..af62f4f235af7
--- /dev/null
+++ b/x-pack/plugins/apm/public/components/routing/apm_route_config.tsx
@@ -0,0 +1,478 @@
+/*
+ * 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 { i18n } from '@kbn/i18n';
+import React from 'react';
+import { RouteComponentProps } from 'react-router-dom';
+import { getServiceNodeName } from '../../../common/service_nodes';
+import { APMRouteDefinition } from '../../application/routes';
+import { toQuery } from '../shared/Links/url_helpers';
+import { ErrorGroupDetails } from '../app/ErrorGroupDetails';
+import { useApmPluginContext } from '../../context/apm_plugin/use_apm_plugin_context';
+import { ServiceNodeMetrics } from '../app/service_node_metrics';
+import { Settings } from '../app/Settings';
+import { AgentConfigurations } from '../app/Settings/AgentConfigurations';
+import { AnomalyDetection } from '../app/Settings/anomaly_detection';
+import { ApmIndices } from '../app/Settings/ApmIndices';
+import { CustomizeUI } from '../app/Settings/CustomizeUI';
+import { TraceLink } from '../app/TraceLink';
+import { TransactionDetails } from '../app/transaction_details';
+import {
+ CreateAgentConfigurationRouteHandler,
+ EditAgentConfigurationRouteHandler,
+} from './route_handlers/agent_configuration';
+import { enableServiceOverview } from '../../../common/ui_settings_keys';
+import { redirectTo } from './redirect_to';
+import { ApmMainTemplate } from './templates/apm_main_template';
+import { ApmServiceTemplate } from './templates/apm_service_template';
+import { ServiceProfiling } from '../app/service_profiling';
+import { ErrorGroupOverview } from '../app/error_group_overview';
+import { ServiceMap } from '../app/service_map';
+import { ServiceNodeOverview } from '../app/service_node_overview';
+import { ServiceMetrics } from '../app/service_metrics';
+import { ServiceOverview } from '../app/service_overview';
+import { TransactionOverview } from '../app/transaction_overview';
+import { ServiceInventory } from '../app/service_inventory';
+import { TraceOverview } from '../app/trace_overview';
+
+// These component function definitions are used below with the `component`
+// property of the route definitions.
+//
+// If you provide an inline function to the component prop, you would create a
+// new component every render. This results in the existing component unmounting
+// and the new component mounting instead of just updating the existing component.
+
+const ServiceInventoryTitle = i18n.translate(
+ 'xpack.apm.views.serviceInventory.title',
+ { defaultMessage: 'Services' }
+);
+
+function ServiceInventoryView() {
+ return (
+
+
+
+ );
+}
+
+const TraceOverviewTitle = i18n.translate(
+ 'xpack.apm.views.traceOverview.title',
+ {
+ defaultMessage: 'Traces',
+ }
+);
+
+function TraceOverviewView() {
+ return (
+
+
+
+ );
+}
+
+const ServiceMapTitle = i18n.translate('xpack.apm.views.serviceMap.title', {
+ defaultMessage: 'Service Map',
+});
+
+function ServiceMapView() {
+ return (
+
+
+
+ );
+}
+
+function ServiceDetailsErrorsRouteView(
+ props: RouteComponentProps<{ serviceName: string }>
+) {
+ const { serviceName } = props.match.params;
+ return (
+
+
+
+ );
+}
+
+function ErrorGroupDetailsRouteView(
+ props: RouteComponentProps<{ serviceName: string; groupId: string }>
+) {
+ const { serviceName, groupId } = props.match.params;
+ return (
+
+
+
+ );
+}
+
+function ServiceDetailsMetricsRouteView(
+ props: RouteComponentProps<{ serviceName: string }>
+) {
+ const { serviceName } = props.match.params;
+ return (
+
+
+
+ );
+}
+
+function ServiceDetailsNodesRouteView(
+ props: RouteComponentProps<{ serviceName: string }>
+) {
+ const { serviceName } = props.match.params;
+ return (
+
+
+
+ );
+}
+
+function ServiceDetailsOverviewRouteView(
+ props: RouteComponentProps<{ serviceName: string }>
+) {
+ const { serviceName } = props.match.params;
+ return (
+
+
+
+ );
+}
+
+function ServiceDetailsServiceMapRouteView(
+ props: RouteComponentProps<{ serviceName: string }>
+) {
+ const { serviceName } = props.match.params;
+ return (
+
+
+
+ );
+}
+
+function ServiceDetailsTransactionsRouteView(
+ props: RouteComponentProps<{ serviceName: string }>
+) {
+ const { serviceName } = props.match.params;
+ return (
+
+
+
+ );
+}
+
+function ServiceDetailsProfilingRouteView(
+ props: RouteComponentProps<{ serviceName: string }>
+) {
+ const { serviceName } = props.match.params;
+ return (
+
+
+
+ );
+}
+
+function ServiceNodeMetricsRouteView(
+ props: RouteComponentProps<{
+ serviceName: string;
+ serviceNodeName: string;
+ }>
+) {
+ const { serviceName, serviceNodeName } = props.match.params;
+ return (
+
+
+
+ );
+}
+
+function TransactionDetailsRouteView(
+ props: RouteComponentProps<{ serviceName: string }>
+) {
+ const { serviceName } = props.match.params;
+ return (
+
+
+
+ );
+}
+
+function SettingsAgentConfigurationRouteView() {
+ return (
+
+
+
+
+
+ );
+}
+
+function SettingsAnomalyDetectionRouteView() {
+ return (
+
+
+
+
+
+ );
+}
+
+function SettingsApmIndicesRouteView() {
+ return (
+
+
+
+
+
+ );
+}
+
+function SettingsCustomizeUI() {
+ return (
+
+
+
+
+
+ );
+}
+
+const SettingsApmIndicesTitle = i18n.translate(
+ 'xpack.apm.views.settings.indices.title',
+ { defaultMessage: 'Indices' }
+);
+
+const SettingsAgentConfigurationTitle = i18n.translate(
+ 'xpack.apm.views.settings.agentConfiguration.title',
+ { defaultMessage: 'Agent Configuration' }
+);
+const CreateAgentConfigurationTitle = i18n.translate(
+ 'xpack.apm.views.settings.createAgentConfiguration.title',
+ { defaultMessage: 'Create Agent Configuration' }
+);
+const EditAgentConfigurationTitle = i18n.translate(
+ 'xpack.apm.views.settings.editAgentConfiguration.title',
+ { defaultMessage: 'Edit Agent Configuration' }
+);
+const SettingsCustomizeUITitle = i18n.translate(
+ 'xpack.apm.views.settings.customizeUI.title',
+ { defaultMessage: 'Customize app' }
+);
+const SettingsAnomalyDetectionTitle = i18n.translate(
+ '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.
+ */
+export const apmRouteConfig: APMRouteDefinition[] = [
+ /*
+ * Home routes
+ */
+ {
+ exact: true,
+ path: '/',
+ render: redirectTo('/services'),
+ breadcrumb: 'APM',
+ },
+ {
+ exact: true,
+ path: '/services', // !! Need to be kept in sync with the deepLinks in x-pack/plugins/apm/public/plugin.ts
+ component: ServiceInventoryView,
+ breadcrumb: ServiceInventoryTitle,
+ },
+ {
+ exact: true,
+ path: '/traces', // !! Need to be kept in sync with the deepLinks in x-pack/plugins/apm/public/plugin.ts
+ component: TraceOverviewView,
+ breadcrumb: TraceOverviewTitle,
+ },
+ {
+ exact: true,
+ path: '/service-map', // !! Need to be kept in sync with the deepLinks in x-pack/plugins/apm/public/plugin.ts
+ component: ServiceMapView,
+ breadcrumb: ServiceMapTitle,
+ },
+
+ /*
+ * Settings routes
+ */
+ {
+ exact: true,
+ path: '/settings',
+ render: redirectTo('/settings/agent-configuration'),
+ breadcrumb: SettingsTitle,
+ },
+ {
+ exact: true,
+ path: '/settings/agent-configuration',
+ component: SettingsAgentConfigurationRouteView,
+ breadcrumb: SettingsAgentConfigurationTitle,
+ },
+ {
+ exact: true,
+ path: '/settings/agent-configuration/create',
+ component: CreateAgentConfigurationRouteHandler,
+ breadcrumb: CreateAgentConfigurationTitle,
+ },
+ {
+ exact: true,
+ path: '/settings/agent-configuration/edit',
+ breadcrumb: EditAgentConfigurationTitle,
+ component: EditAgentConfigurationRouteHandler,
+ },
+ {
+ exact: true,
+ path: '/settings/apm-indices',
+ component: SettingsApmIndicesRouteView,
+ breadcrumb: SettingsApmIndicesTitle,
+ },
+ {
+ exact: true,
+ path: '/settings/customize-ui',
+ component: SettingsCustomizeUI,
+ breadcrumb: SettingsCustomizeUITitle,
+ },
+ {
+ exact: true,
+ path: '/settings/anomaly-detection',
+ component: SettingsAnomalyDetectionRouteView,
+ breadcrumb: SettingsAnomalyDetectionTitle,
+ },
+
+ /*
+ * Services routes (with APM Service context)
+ */
+ {
+ exact: true,
+ path: '/services/:serviceName',
+ breadcrumb: ({ match }) => match.params.serviceName,
+ component: RedirectToDefaultServiceRouteView,
+ },
+ {
+ exact: true,
+ path: '/services/:serviceName/overview',
+ breadcrumb: i18n.translate('xpack.apm.views.overview.title', {
+ defaultMessage: 'Overview',
+ }),
+ component: ServiceDetailsOverviewRouteView,
+ },
+ {
+ exact: true,
+ path: '/services/:serviceName/transactions',
+ component: ServiceDetailsTransactionsRouteView,
+ breadcrumb: i18n.translate('xpack.apm.views.transactions.title', {
+ defaultMessage: 'Transactions',
+ }),
+ },
+ {
+ exact: true,
+ path: '/services/:serviceName/errors/:groupId',
+ component: ErrorGroupDetailsRouteView,
+ breadcrumb: ({ match }) => match.params.groupId,
+ },
+ {
+ exact: true,
+ path: '/services/:serviceName/errors',
+ component: ServiceDetailsErrorsRouteView,
+ breadcrumb: i18n.translate('xpack.apm.views.errors.title', {
+ defaultMessage: 'Errors',
+ }),
+ },
+ {
+ exact: true,
+ path: '/services/:serviceName/metrics',
+ component: ServiceDetailsMetricsRouteView,
+ breadcrumb: i18n.translate('xpack.apm.views.metrics.title', {
+ defaultMessage: 'Metrics',
+ }),
+ },
+ // service nodes, only enabled for java agents for now
+ {
+ exact: true,
+ path: '/services/:serviceName/nodes',
+ component: ServiceDetailsNodesRouteView,
+ breadcrumb: i18n.translate('xpack.apm.views.nodes.title', {
+ defaultMessage: 'JVMs',
+ }),
+ },
+ // node metrics
+ {
+ exact: true,
+ path: '/services/:serviceName/nodes/:serviceNodeName/metrics',
+ component: ServiceNodeMetricsRouteView,
+ breadcrumb: ({ match }) => getServiceNodeName(match.params.serviceNodeName),
+ },
+ {
+ exact: true,
+ path: '/services/:serviceName/transactions/view',
+ component: TransactionDetailsRouteView,
+ breadcrumb: ({ location }) => {
+ const query = toQuery(location.search);
+ return query.transactionName as string;
+ },
+ },
+ {
+ exact: true,
+ path: '/services/:serviceName/profiling',
+ component: ServiceDetailsProfilingRouteView,
+ breadcrumb: i18n.translate('xpack.apm.views.serviceProfiling.title', {
+ defaultMessage: 'Profiling',
+ }),
+ },
+ {
+ exact: true,
+ path: '/services/:serviceName/service-map',
+ component: ServiceDetailsServiceMapRouteView,
+ breadcrumb: i18n.translate('xpack.apm.views.serviceMap.title', {
+ defaultMessage: 'Service Map',
+ }),
+ },
+ /*
+ * Utilility routes
+ */
+ {
+ exact: true,
+ path: '/link-to/trace/:traceId',
+ component: TraceLink,
+ breadcrumb: null,
+ },
+];
+
+function RedirectToDefaultServiceRouteView(
+ props: RouteComponentProps<{ serviceName: string }>
+) {
+ 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/routing/app_root.tsx b/x-pack/plugins/apm/public/components/routing/app_root.tsx
new file mode 100644
index 0000000000000..9529a67210748
--- /dev/null
+++ b/x-pack/plugins/apm/public/components/routing/app_root.tsx
@@ -0,0 +1,110 @@
+/*
+ * 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 { ApmRoute } from '@elastic/apm-rum-react';
+import euiDarkVars from '@elastic/eui/dist/eui_theme_dark.json';
+import euiLightVars from '@elastic/eui/dist/eui_theme_light.json';
+import React from 'react';
+import { Route, Router, Switch } from 'react-router-dom';
+import { DefaultTheme, ThemeProvider } from 'styled-components';
+import { euiStyled } from '../../../../../../src/plugins/kibana_react/common';
+import {
+ KibanaContextProvider,
+ RedirectAppLinks,
+ useUiSetting$,
+} from '../../../../../../src/plugins/kibana_react/public';
+import { ScrollToTopOnPathChange } from '../../components/app/Main/ScrollToTopOnPathChange';
+import {
+ ApmPluginContext,
+ ApmPluginContextValue,
+} from '../../context/apm_plugin/apm_plugin_context';
+import { LicenseProvider } from '../../context/license/license_context';
+import { UrlParamsProvider } from '../../context/url_params_context/url_params_context';
+import { useBreadcrumbs } from '../../hooks/use_breadcrumbs';
+import { ApmPluginStartDeps } from '../../plugin';
+import { HeaderMenuPortal } from '../../../../observability/public';
+import { ApmHeaderActionMenu } from '../shared/apm_header_action_menu';
+import { useApmPluginContext } from '../../context/apm_plugin/use_apm_plugin_context';
+import { AnomalyDetectionJobsContextProvider } from '../../context/anomaly_detection_jobs/anomaly_detection_jobs_context';
+import { apmRouteConfig } from './apm_route_config';
+
+const MainContainer = euiStyled.div`
+ height: 100%;
+`;
+
+export function ApmAppRoot({
+ apmPluginContextValue,
+ pluginsStart,
+}: {
+ apmPluginContextValue: ApmPluginContextValue;
+ pluginsStart: ApmPluginStartDeps;
+}) {
+ const { appMountParameters, core } = apmPluginContextValue;
+ const { history } = appMountParameters;
+ const i18nCore = core.i18n;
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {apmRouteConfig.map((route, i) => (
+
+ ))}
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
+
+function MountApmHeaderActionMenu() {
+ useBreadcrumbs(apmRouteConfig);
+ 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/redirect_to.tsx b/x-pack/plugins/apm/public/components/routing/redirect_to.tsx
new file mode 100644
index 0000000000000..68ff2fce77f13
--- /dev/null
+++ b/x-pack/plugins/apm/public/components/routing/redirect_to.tsx
@@ -0,0 +1,38 @@
+/*
+ * 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 { 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 redirectTo(to: string) {
+ return ({ location }: RouteComponentProps<{}>) => {
+ let resolvedUrl: URL | undefined;
+
+ // Redirect root URLs with a hash to support backward compatibility with URLs
+ // from before we switched to the non-hash platform history.
+ if (location.pathname === '' && location.hash.length > 0) {
+ // We just want the search and pathname so the host doesn't matter
+ resolvedUrl = new URL(location.hash.slice(1), 'http://localhost');
+ to = resolvedUrl.pathname;
+ }
+
+ return (
+
+ );
+ };
+}
diff --git a/x-pack/plugins/apm/public/components/app/Main/route_config/route_config.test.tsx b/x-pack/plugins/apm/public/components/routing/route_config.test.tsx
similarity index 93%
rename from x-pack/plugins/apm/public/components/app/Main/route_config/route_config.test.tsx
rename to x-pack/plugins/apm/public/components/routing/route_config.test.tsx
index 62202d9489d51..b1d5c1a83b43b 100644
--- a/x-pack/plugins/apm/public/components/app/Main/route_config/route_config.test.tsx
+++ b/x-pack/plugins/apm/public/components/routing/route_config.test.tsx
@@ -5,11 +5,11 @@
* 2.0.
*/
-import { routes } from './';
+import { apmRouteConfig } from './apm_route_config';
describe('routes', () => {
describe('/', () => {
- const route = routes.find((r) => r.path === '/');
+ const route = apmRouteConfig.find((r) => r.path === '/');
describe('with no hash path', () => {
it('redirects to /services', () => {
diff --git a/x-pack/plugins/apm/public/components/app/Main/route_config/route_handlers/agent_configuration.tsx b/x-pack/plugins/apm/public/components/routing/route_handlers/agent_configuration.tsx
similarity index 86%
rename from x-pack/plugins/apm/public/components/app/Main/route_config/route_handlers/agent_configuration.tsx
rename to x-pack/plugins/apm/public/components/routing/route_handlers/agent_configuration.tsx
index e5d238e6aa89c..8e0a08603bc76 100644
--- a/x-pack/plugins/apm/public/components/app/Main/route_config/route_handlers/agent_configuration.tsx
+++ b/x-pack/plugins/apm/public/components/routing/route_handlers/agent_configuration.tsx
@@ -7,10 +7,10 @@
import React from 'react';
import { RouteComponentProps } from 'react-router-dom';
-import { useFetcher } from '../../../../../hooks/use_fetcher';
-import { toQuery } from '../../../../shared/Links/url_helpers';
-import { Settings } from '../../../Settings';
-import { AgentConfigurationCreateEdit } from '../../../Settings/AgentConfigurations/AgentConfigurationCreateEdit';
+import { useFetcher } from '../../../hooks/use_fetcher';
+import { toQuery } from '../../shared/Links/url_helpers';
+import { Settings } from '../../app/Settings';
+import { AgentConfigurationCreateEdit } from '../../app/Settings/AgentConfigurations/AgentConfigurationCreateEdit';
type EditAgentConfigurationRouteHandler = RouteComponentProps<{}>;
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
new file mode 100644
index 0000000000000..0473e88c23d12
--- /dev/null
+++ b/x-pack/plugins/apm/public/components/routing/templates/apm_main_template.tsx
@@ -0,0 +1,43 @@
+/*
+ * 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 { useKibana } from '../../../../../../../src/plugins/kibana_react/public';
+import { ApmPluginStartDeps } from '../../../plugin';
+import { EnvironmentFilter } from '../../shared/EnvironmentFilter';
+
+/*
+ * This template contains:
+ * - The Shared Observability Nav (https://github.com/elastic/kibana/blob/f7698bd8aa8787d683c728300ba4ca52b202369c/x-pack/plugins/observability/public/components/shared/page_template/README.md)
+ * - The APM Header Action Menu
+ * - Page title
+ *
+ * Optionally:
+ * - EnvironmentFilter
+ */
+export function ApmMainTemplate({
+ pageTitle,
+ children,
+}: {
+ pageTitle: React.ReactNode;
+ children: React.ReactNode;
+}) {
+ const { services } = useKibana();
+ const ObservabilityPageTemplate =
+ services.observability.navigation.PageTemplate;
+
+ return (
+ ],
+ }}
+ >
+ {children}
+
+ );
+}
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 0000000000000..526d9eb3551d0
--- /dev/null
+++ b/x-pack/plugins/apm/public/components/routing/templates/apm_service_template.tsx
@@ -0,0 +1,216 @@
+/*
+ * 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/shared/ApmHeader/apm_header.stories.tsx b/x-pack/plugins/apm/public/components/shared/ApmHeader/apm_header.stories.tsx
deleted file mode 100644
index 4bc9764b704b0..0000000000000
--- a/x-pack/plugins/apm/public/components/shared/ApmHeader/apm_header.stories.tsx
+++ /dev/null
@@ -1,53 +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 { EuiTitle } from '@elastic/eui';
-import React, { ComponentType } from 'react';
-import { MemoryRouter } from 'react-router-dom';
-import { CoreStart } from '../../../../../../../src/core/public';
-import { EuiThemeProvider } from '../../../../../../../src/plugins/kibana_react/common';
-import { MockApmPluginContextWrapper } from '../../../context/apm_plugin/mock_apm_plugin_context';
-import { MockUrlParamsContextProvider } from '../../../context/url_params_context/mock_url_params_context_provider';
-import { createCallApmApi } from '../../../services/rest/createCallApmApi';
-import { ApmHeader } from './';
-
-export default {
- title: 'shared/ApmHeader',
- component: ApmHeader,
- decorators: [
- (Story: ComponentType) => {
- createCallApmApi(({} as unknown) as CoreStart);
-
- return (
-
-
-
-
-
-
-
-
-
- );
- },
- ],
-};
-
-export function Example() {
- return (
-
-
-
- GET
- /api/v1/regions/azure-eastus2/clusters/elasticsearch/xc18de071deb4262be54baebf5f6a1ce/proxy/_snapshot/found-snapshots/_all
-
-
-
- );
-}
diff --git a/x-pack/plugins/apm/public/components/shared/ApmHeader/index.tsx b/x-pack/plugins/apm/public/components/shared/ApmHeader/index.tsx
deleted file mode 100644
index f94bba84526a7..0000000000000
--- a/x-pack/plugins/apm/public/components/shared/ApmHeader/index.tsx
+++ /dev/null
@@ -1,36 +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 { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
-import React, { ReactNode } from 'react';
-import { euiStyled } from '../../../../../../../src/plugins/kibana_react/common';
-import { HeaderMenuPortal } from '../../../../../observability/public';
-import { ActionMenu } from '../../../application/action_menu';
-import { useApmPluginContext } from '../../../context/apm_plugin/use_apm_plugin_context';
-import { EnvironmentFilter } from '../EnvironmentFilter';
-
-const HeaderFlexGroup = euiStyled(EuiFlexGroup)`
- padding: ${({ theme }) => theme.eui.gutterTypes.gutterMedium};
- background: ${({ theme }) => theme.eui.euiColorEmptyShade};
- border-bottom: ${({ theme }) => theme.eui.euiBorderThin};
-`;
-
-export function ApmHeader({ children }: { children: ReactNode }) {
- const { setHeaderActionMenu } = useApmPluginContext().appMountParameters;
-
- return (
-
-
-
-
- {children}
-
-
-
-
- );
-}
diff --git a/x-pack/plugins/apm/public/components/shared/EnvironmentFilter/index.tsx b/x-pack/plugins/apm/public/components/shared/EnvironmentFilter/index.tsx
index 59c99463144cb..c1bef7ac407ff 100644
--- a/x-pack/plugins/apm/public/components/shared/EnvironmentFilter/index.tsx
+++ b/x-pack/plugins/apm/public/components/shared/EnvironmentFilter/index.tsx
@@ -13,6 +13,7 @@ import { useHistory, useLocation, useParams } from 'react-router-dom';
import {
ENVIRONMENT_ALL,
ENVIRONMENT_NOT_DEFINED,
+ omitEsFieldValue,
} from '../../../../common/environment_filter_values';
import { useEnvironmentsFetcher } from '../../../hooks/use_environments_fetcher';
import { useUrlParams } from '../../../context/url_params_context/use_url_params';
@@ -51,9 +52,9 @@ function getOptions(environments: string[]) {
}));
return [
- ENVIRONMENT_ALL,
+ omitEsFieldValue(ENVIRONMENT_ALL),
...(environments.includes(ENVIRONMENT_NOT_DEFINED.value)
- ? [ENVIRONMENT_NOT_DEFINED]
+ ? [omitEsFieldValue(ENVIRONMENT_NOT_DEFINED)]
: []),
...(environmentOptions.length > 0 ? [SEPARATOR_OPTION] : []),
...environmentOptions,
@@ -78,12 +79,14 @@ export function EnvironmentFilter() {
// the contents.
const minWidth = 200;
+ const options = getOptions(environments);
+
return (
{
updateEnvironmentUrl(history, location, event.target.value);
diff --git a/x-pack/plugins/apm/public/application/action_menu/alerting_popover_flyout.tsx b/x-pack/plugins/apm/public/components/shared/apm_header_action_menu/alerting_popover_flyout.tsx
similarity index 96%
rename from x-pack/plugins/apm/public/application/action_menu/alerting_popover_flyout.tsx
rename to x-pack/plugins/apm/public/components/shared/apm_header_action_menu/alerting_popover_flyout.tsx
index 2ff3756855d14..95acc55196c54 100644
--- a/x-pack/plugins/apm/public/application/action_menu/alerting_popover_flyout.tsx
+++ b/x-pack/plugins/apm/public/components/shared/apm_header_action_menu/alerting_popover_flyout.tsx
@@ -13,9 +13,9 @@ import {
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import React, { useState } from 'react';
-import { IBasePath } from '../../../../../../src/core/public';
-import { AlertType } from '../../../common/alert_types';
-import { AlertingFlyout } from '../../components/alerting/alerting_flyout';
+import { IBasePath } from '../../../../../../../src/core/public';
+import { AlertType } from '../../../../common/alert_types';
+import { AlertingFlyout } from '../../alerting/alerting_flyout';
const alertLabel = i18n.translate('xpack.apm.home.alertsMenu.alerts', {
defaultMessage: 'Alerts',
diff --git a/x-pack/plugins/apm/public/application/action_menu/anomaly_detection_setup_link.test.tsx b/x-pack/plugins/apm/public/components/shared/apm_header_action_menu/anomaly_detection_setup_link.test.tsx
similarity index 95%
rename from x-pack/plugins/apm/public/application/action_menu/anomaly_detection_setup_link.test.tsx
rename to x-pack/plugins/apm/public/components/shared/apm_header_action_menu/anomaly_detection_setup_link.test.tsx
index 044abbb2ec792..6a6ba3f9529ff 100644
--- a/x-pack/plugins/apm/public/application/action_menu/anomaly_detection_setup_link.test.tsx
+++ b/x-pack/plugins/apm/public/components/shared/apm_header_action_menu/anomaly_detection_setup_link.test.tsx
@@ -8,8 +8,8 @@
import React from 'react';
import { render, fireEvent, waitFor } from '@testing-library/react';
import { MissingJobsAlert } from './anomaly_detection_setup_link';
-import * as hooks from '../../context/anomaly_detection_jobs/use_anomaly_detection_jobs_context';
-import { FETCH_STATUS } from '../../hooks/use_fetcher';
+import * as hooks from '../../../context/anomaly_detection_jobs/use_anomaly_detection_jobs_context';
+import { FETCH_STATUS } from '../../../hooks/use_fetcher';
async function renderTooltipAnchor({
jobs,
diff --git a/x-pack/plugins/apm/public/application/action_menu/anomaly_detection_setup_link.tsx b/x-pack/plugins/apm/public/components/shared/apm_header_action_menu/anomaly_detection_setup_link.tsx
similarity index 83%
rename from x-pack/plugins/apm/public/application/action_menu/anomaly_detection_setup_link.tsx
rename to x-pack/plugins/apm/public/components/shared/apm_header_action_menu/anomaly_detection_setup_link.tsx
index 296e55fdff82b..ade49bc7e3aa4 100644
--- a/x-pack/plugins/apm/public/application/action_menu/anomaly_detection_setup_link.tsx
+++ b/x-pack/plugins/apm/public/components/shared/apm_header_action_menu/anomaly_detection_setup_link.tsx
@@ -16,15 +16,15 @@ import React from 'react';
import {
ENVIRONMENT_ALL,
getEnvironmentLabel,
-} from '../../../common/environment_filter_values';
-import { getAPMHref } from '../../components/shared/Links/apm/APMLink';
-import { useAnomalyDetectionJobsContext } from '../../context/anomaly_detection_jobs/use_anomaly_detection_jobs_context';
-import { useApmPluginContext } from '../../context/apm_plugin/use_apm_plugin_context';
-import { useLicenseContext } from '../../context/license/use_license_context';
-import { useUrlParams } from '../../context/url_params_context/use_url_params';
-import { FETCH_STATUS } from '../../hooks/use_fetcher';
-import { APIReturnType } from '../../services/rest/createCallApmApi';
-import { units } from '../../style/variables';
+} from '../../../../common/environment_filter_values';
+import { getAPMHref } from '../Links/apm/APMLink';
+import { useAnomalyDetectionJobsContext } from '../../../context/anomaly_detection_jobs/use_anomaly_detection_jobs_context';
+import { useApmPluginContext } from '../../../context/apm_plugin/use_apm_plugin_context';
+import { useLicenseContext } from '../../../context/license/use_license_context';
+import { useUrlParams } from '../../../context/url_params_context/use_url_params';
+import { FETCH_STATUS } from '../../../hooks/use_fetcher';
+import { APIReturnType } from '../../../services/rest/createCallApmApi';
+import { units } from '../../../style/variables';
export type AnomalyDetectionApiResponse = APIReturnType<'GET /api/apm/settings/anomaly-detection/jobs'>;
diff --git a/x-pack/plugins/apm/public/application/action_menu/index.tsx b/x-pack/plugins/apm/public/components/shared/apm_header_action_menu/index.tsx
similarity index 88%
rename from x-pack/plugins/apm/public/application/action_menu/index.tsx
rename to x-pack/plugins/apm/public/components/shared/apm_header_action_menu/index.tsx
index 2d9b619a3176d..134941990a0f4 100644
--- a/x-pack/plugins/apm/public/application/action_menu/index.tsx
+++ b/x-pack/plugins/apm/public/components/shared/apm_header_action_menu/index.tsx
@@ -9,13 +9,13 @@ import { EuiHeaderLink, EuiHeaderLinks } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import React from 'react';
import { useParams } from 'react-router-dom';
-import { getAlertingCapabilities } from '../../components/alerting/get_alerting_capabilities';
-import { getAPMHref } from '../../components/shared/Links/apm/APMLink';
-import { useApmPluginContext } from '../../context/apm_plugin/use_apm_plugin_context';
+import { getAlertingCapabilities } from '../../alerting/get_alerting_capabilities';
+import { getAPMHref } from '../Links/apm/APMLink';
+import { useApmPluginContext } from '../../../context/apm_plugin/use_apm_plugin_context';
import { AlertingPopoverAndFlyout } from './alerting_popover_flyout';
import { AnomalyDetectionSetupLink } from './anomaly_detection_setup_link';
-export function ActionMenu() {
+export function ApmHeaderActionMenu() {
const { core, plugins } = useApmPluginContext();
const { serviceName } = useParams<{ serviceName?: string }>();
const { search } = window.location;
diff --git a/x-pack/plugins/apm/public/components/shared/main_tabs.tsx b/x-pack/plugins/apm/public/components/shared/main_tabs.tsx
deleted file mode 100644
index f60da7c308711..0000000000000
--- a/x-pack/plugins/apm/public/components/shared/main_tabs.tsx
+++ /dev/null
@@ -1,24 +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 { EuiTabs } from '@elastic/eui';
-import React, { ReactNode } from 'react';
-import { euiStyled } from '../../../../../../src/plugins/kibana_react/common';
-
-// 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: ${({ theme }) => `${theme.eui.gutterTypes.gutterMedium}`};
- border-bottom: ${({ theme }) => theme.eui.euiBorderThin};
- border-top: ${({ theme }) => theme.eui.euiBorderThin};
- background: ${({ theme }) => theme.eui.euiColorEmptyShade};
-`;
-
-export function MainTabs({ children }: { children: ReactNode }) {
- return {children};
-}
diff --git a/x-pack/plugins/apm/public/components/shared/search_bar.test.tsx b/x-pack/plugins/apm/public/components/shared/search_bar.test.tsx
new file mode 100644
index 0000000000000..105bdb008042e
--- /dev/null
+++ b/x-pack/plugins/apm/public/components/shared/search_bar.test.tsx
@@ -0,0 +1,120 @@
+/*
+ * 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 { getByTestId, fireEvent, getByText } from '@testing-library/react';
+import { createMemoryHistory, MemoryHistory } from 'history';
+import React from 'react';
+import { Router } from 'react-router-dom';
+import { createKibanaReactContext } from 'src/plugins/kibana_react/public';
+import { MockApmPluginContextWrapper } from '../../context/apm_plugin/mock_apm_plugin_context';
+import { ApmServiceContextProvider } from '../../context/apm_service/apm_service_context';
+import { UrlParamsProvider } from '../../context/url_params_context/url_params_context';
+import { IUrlParams } from '../../context/url_params_context/types';
+import * as useFetcherHook from '../../hooks/use_fetcher';
+import * as useServiceTransactionTypesHook from '../../context/apm_service/use_service_transaction_types_fetcher';
+import { renderWithTheme } from '../../utils/testHelpers';
+import { fromQuery } from './Links/url_helpers';
+import { CoreStart } from 'kibana/public';
+import { SearchBar } from './search_bar';
+
+function setup({
+ urlParams,
+ serviceTransactionTypes,
+ history,
+}: {
+ urlParams: IUrlParams;
+ serviceTransactionTypes: string[];
+ history: MemoryHistory;
+}) {
+ history.replace({
+ pathname: '/services/foo/transactions',
+ search: fromQuery(urlParams),
+ });
+
+ const KibanaReactContext = createKibanaReactContext({
+ usageCollection: { reportUiCounter: () => {} },
+ } as Partial);
+
+ // mock transaction types
+ jest
+ .spyOn(useServiceTransactionTypesHook, 'useServiceTransactionTypesFetcher')
+ .mockReturnValue(serviceTransactionTypes);
+
+ jest.spyOn(useFetcherHook, 'useFetcher').mockReturnValue({} as any);
+
+ return renderWithTheme(
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
+
+describe('when transactionType is selected and multiple transaction types are given', () => {
+ let history: MemoryHistory;
+ beforeEach(() => {
+ history = createMemoryHistory();
+ jest.spyOn(history, 'push');
+ jest.spyOn(history, 'replace');
+ });
+
+ it('renders a radio group with transaction types', () => {
+ const { container } = setup({
+ history,
+ serviceTransactionTypes: ['firstType', 'secondType'],
+ urlParams: {
+ transactionType: 'secondType',
+ },
+ });
+
+ // transaction type selector
+ const dropdown = getByTestId(container, 'headerFilterTransactionType');
+
+ // both options should be listed
+ expect(getByText(dropdown, 'firstType')).toBeInTheDocument();
+ expect(getByText(dropdown, 'secondType')).toBeInTheDocument();
+
+ // second option should be selected
+ expect(dropdown).toHaveValue('secondType');
+ });
+
+ it('should update the URL when a transaction type is selected', () => {
+ const { container } = setup({
+ history,
+ serviceTransactionTypes: ['firstType', 'secondType'],
+ urlParams: {
+ transactionType: 'secondType',
+ },
+ });
+
+ expect(history.location.search).toEqual(
+ '?transactionType=secondType&rangeFrom=now-15m&rangeTo=now'
+ );
+
+ // transaction type selector
+ const dropdown = getByTestId(container, 'headerFilterTransactionType');
+ expect(getByText(dropdown, 'firstType')).toBeInTheDocument();
+ expect(getByText(dropdown, 'secondType')).toBeInTheDocument();
+
+ // change dropdown value
+ fireEvent.change(dropdown, { target: { value: 'firstType' } });
+
+ // assert that value was changed
+ expect(dropdown).toHaveValue('firstType');
+ expect(history.push).toHaveBeenCalled();
+ expect(history.location.search).toEqual(
+ '?transactionType=firstType&rangeFrom=now-15m&rangeTo=now'
+ );
+ });
+});
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 f0fc18cf266b9..17497e1fb4b30 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';
@@ -26,12 +25,9 @@ import { KueryBar } from './KueryBar';
import { TimeComparison } from './time_comparison';
import { TransactionTypeSelect } from './transaction_type_select';
-const EuiFlexGroupSpaced = euiStyled(EuiFlexGroup)`
- margin: ${({ theme }) =>
- `${theme.eui.euiSizeS} ${theme.eui.euiSizeS} -${theme.eui.gutterTypes.gutterMedium} ${theme.eui.euiSizeS}`};
-`;
-
interface Props {
+ hidden?: boolean;
+ showKueryBar?: boolean;
showTimeComparison?: boolean;
showTransactionTypeSelector?: boolean;
}
@@ -49,7 +45,7 @@ function DebugQueryCallout() {
}
return (
-
+
-
+
);
}
export function SearchBar({
+ hidden = false,
+ showKueryBar = true,
showTimeComparison = false,
showTransactionTypeSelector = false,
}: Props) {
const { isSmall, isMedium, isLarge, isXl, isXXL } = useBreakPoints();
+
+ if (hidden) {
+ return null;
+ }
+
return (
<>
-
)}
-
-
-
+
+ {showKueryBar && (
+
+
+
+ )}
@@ -128,7 +134,7 @@ export function SearchBar({
-
+
>
);
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 0066480230c6b..9f6378ccb4497 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 2e19bc684d681..2e8fcfa1df672 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 efc9a46526cf8..b590a67409d9e 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 79f93ea76ee51..05305558564f1 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 6027e8b1d07c5..d66625f613cdc 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 f7bed4e09a696..d64605da2bc3f 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 ed503a5cb34a0..1828465fff450 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'>;
diff --git a/x-pack/plugins/apm/public/hooks/use_breadcrumbs.test.tsx b/x-pack/plugins/apm/public/hooks/use_breadcrumbs.test.tsx
index 13a2fa3b227da..64990651b52bb 100644
--- a/x-pack/plugins/apm/public/hooks/use_breadcrumbs.test.tsx
+++ b/x-pack/plugins/apm/public/hooks/use_breadcrumbs.test.tsx
@@ -9,7 +9,7 @@ import { renderHook } from '@testing-library/react-hooks';
import produce from 'immer';
import React, { ReactNode } from 'react';
import { MemoryRouter } from 'react-router-dom';
-import { routes } from '../components/app/Main/route_config';
+import { apmRouteConfig } from '../components/routing/apm_route_config';
import { ApmPluginContextValue } from '../context/apm_plugin/apm_plugin_context';
import {
mockApmPluginContextValue,
@@ -36,7 +36,9 @@ function createWrapper(path: string) {
}
function mountBreadcrumb(path: string) {
- renderHook(() => useBreadcrumbs(routes), { wrapper: createWrapper(path) });
+ renderHook(() => useBreadcrumbs(apmRouteConfig), {
+ wrapper: createWrapper(path),
+ });
}
const changeTitle = jest.fn();
diff --git a/x-pack/plugins/apm/public/plugin.ts b/x-pack/plugins/apm/public/plugin.ts
index 10af1837dab42..845b18b707f93 100644
--- a/x-pack/plugins/apm/public/plugin.ts
+++ b/x-pack/plugins/apm/public/plugin.ts
@@ -6,6 +6,7 @@
*/
import { i18n } from '@kbn/i18n';
+import { of } from 'rxjs';
import type { ConfigSchema } from '.';
import {
AppMountParameters,
@@ -34,6 +35,7 @@ import type {
FetchDataParams,
HasDataParams,
ObservabilityPublicSetup,
+ ObservabilityPublicStart,
} from '../../observability/public';
import type {
TriggersAndActionsUIPublicPluginSetup,
@@ -48,24 +50,25 @@ export type ApmPluginStart = void;
export interface ApmPluginSetupDeps {
alerting?: AlertingPluginPublicSetup;
- ml?: MlPluginSetup;
data: DataPublicPluginSetup;
features: FeaturesPluginSetup;
home?: HomePublicPluginSetup;
licensing: LicensingPluginSetup;
- triggersActionsUi: TriggersAndActionsUIPublicPluginSetup;
+ ml?: MlPluginSetup;
observability: ObservabilityPublicSetup;
+ triggersActionsUi: TriggersAndActionsUIPublicPluginSetup;
}
export interface ApmPluginStartDeps {
alerting?: AlertingPluginPublicStart;
- ml?: MlPluginStart;
data: DataPublicPluginStart;
+ embeddable: EmbeddableStart;
home: void;
licensing: void;
- triggersActionsUi: TriggersAndActionsUIPublicPluginStart;
- embeddable: EmbeddableStart;
maps?: MapsStartApi;
+ ml?: MlPluginStart;
+ observability: ObservabilityPublicStart;
+ triggersActionsUi: TriggersAndActionsUIPublicPluginStart;
}
export class ApmPlugin implements Plugin {
@@ -83,6 +86,21 @@ export class ApmPlugin implements Plugin {
pluginSetupDeps.home.featureCatalogue.register(featureCatalogueEntry);
}
+ // register observability nav
+ plugins.observability.navigation.registerSections(
+ of([
+ {
+ label: 'APM',
+ sortKey: 200,
+ entries: [
+ { label: 'Services', app: 'apm', path: '/services' },
+ { label: 'Traces', app: 'apm', path: '/traces' },
+ { label: 'Service Map', app: 'apm', path: '/service-map' },
+ ],
+ },
+ ])
+ );
+
const getApmDataHelper = async () => {
const {
fetchObservabilityOverviewPageData,
diff --git a/x-pack/plugins/apm/public/utils/getRangeFromTimeSeries.ts b/x-pack/plugins/apm/public/utils/getRangeFromTimeSeries.ts
deleted file mode 100644
index 7b4a07dc7bbc5..0000000000000
--- a/x-pack/plugins/apm/public/utils/getRangeFromTimeSeries.ts
+++ /dev/null
@@ -1,22 +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 { flatten } from 'lodash';
-import { TimeSeries } from '../../typings/timeseries';
-
-export function getRangeFromTimeSeries(timeseries: TimeSeries[]) {
- const dataPoints = flatten(timeseries.map((series) => series.data));
-
- if (dataPoints.length) {
- return {
- start: dataPoints[0].x,
- end: dataPoints[dataPoints.length - 1].x,
- };
- }
-
- return null;
-}
diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json
index a637080a44820..8b47938896c24 100644
--- a/x-pack/plugins/translations/translations/ja-JP.json
+++ b/x-pack/plugins/translations/translations/ja-JP.json
@@ -5400,22 +5400,9 @@
"xpack.apm.apply.label": "適用",
"xpack.apm.applyFilter": "{title} フィルターを適用",
"xpack.apm.applyOptions": "オプションを適用",
- "xpack.apm.breadcrumb.errorsTitle": "エラー",
- "xpack.apm.breadcrumb.listSettingsTitle": "設定",
- "xpack.apm.breadcrumb.metricsTitle": "メトリック",
- "xpack.apm.breadcrumb.nodesTitle": "JVM",
- "xpack.apm.breadcrumb.overviewTitle": "概要",
"xpack.apm.breadcrumb.serviceMapTitle": "サービスマップ",
- "xpack.apm.breadcrumb.serviceProfilingTitle": "プロファイリング",
"xpack.apm.breadcrumb.servicesTitle": "サービス",
- "xpack.apm.breadcrumb.settings.agentConfigurationTitle": "エージェントの編集",
- "xpack.apm.breadcrumb.settings.anomalyDetection": "異常検知",
- "xpack.apm.breadcrumb.settings.createAgentConfigurationTitle": "エージェント構成の作成",
- "xpack.apm.breadcrumb.settings.customizeUI": "UI をカスタマイズ",
- "xpack.apm.breadcrumb.settings.editAgentConfigurationTitle": "エージェント構成の編集",
- "xpack.apm.breadcrumb.settings.indicesTitle": "インデックス",
"xpack.apm.breadcrumb.tracesTitle": "トレース",
- "xpack.apm.breadcrumb.transactionsTitle": "トランザクション",
"xpack.apm.chart.annotation.version": "バージョン",
"xpack.apm.chart.cpuSeries.processAverageLabel": "プロセス平均",
"xpack.apm.chart.cpuSeries.processMaxLabel": "プロセス最大",
@@ -5524,8 +5511,6 @@
"xpack.apm.home.alertsMenu.transactionErrorRate": "トランザクションエラー率",
"xpack.apm.home.alertsMenu.viewActiveAlerts": "アクティブアラートを表示",
"xpack.apm.home.serviceMapTabLabel": "サービスマップ",
- "xpack.apm.home.servicesTabLabel": "サービス",
- "xpack.apm.home.tracesTabLabel": "トレース",
"xpack.apm.instancesLatencyDistributionChartLegend": "インスタンス",
"xpack.apm.instancesLatencyDistributionChartLegend.previousPeriod": "前の期間",
"xpack.apm.instancesLatencyDistributionChartTitle": "インスタンスのレイテンシ分布",
@@ -5589,7 +5574,6 @@
"xpack.apm.profiling.highlightFrames": "検索",
"xpack.apm.profiling.table.name": "名前",
"xpack.apm.profiling.table.value": "自己",
- "xpack.apm.profilingOverviewTitle": "プロファイリング",
"xpack.apm.propertiesTable.agentFeature.noDataAvailableLabel": "利用可能なデータがありません",
"xpack.apm.propertiesTable.agentFeature.noResultFound": "\"{value}\"に対する結果が見つかりませんでした。",
"xpack.apm.propertiesTable.tabs.exceptionStacktraceLabel": "例外のスタックトレース",
@@ -5654,7 +5638,6 @@
"xpack.apm.selectPlaceholder": "オプションを選択:",
"xpack.apm.serviceDetails.errorsTabLabel": "エラー",
"xpack.apm.serviceDetails.metrics.cpuUsageChartTitle": "CPU 使用状況",
- "xpack.apm.serviceDetails.metrics.errorOccurrencesChartTitle": "エラーのオカレンス",
"xpack.apm.serviceDetails.metrics.memoryUsageChartTitle": "システムメモリー使用状況",
"xpack.apm.serviceDetails.metricsTabLabel": "メトリック",
"xpack.apm.serviceDetails.nodesTabLabel": "JVM",
@@ -5891,7 +5874,6 @@
"xpack.apm.settings.customizeUI.customLink.table.url": "URL",
"xpack.apm.settings.indices": "インデックス",
"xpack.apm.settings.pageTitle": "設定",
- "xpack.apm.settings.returnLinkLabel": "インベントリに戻る",
"xpack.apm.settingsLinkLabel": "設定",
"xpack.apm.setupInstructionsButtonLabel": "セットアップの手順",
"xpack.apm.significanTerms.license.text": "相関関係APIを使用するには、Elastic Platinumライセンスのサブスクリプションが必要です。",
diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json
index 9882c15445263..34cfed2130adc 100644
--- a/x-pack/plugins/translations/translations/zh-CN.json
+++ b/x-pack/plugins/translations/translations/zh-CN.json
@@ -5429,22 +5429,9 @@
"xpack.apm.apply.label": "应用",
"xpack.apm.applyFilter": "应用 {title} 筛选",
"xpack.apm.applyOptions": "应用选项",
- "xpack.apm.breadcrumb.errorsTitle": "错误",
- "xpack.apm.breadcrumb.listSettingsTitle": "设置",
- "xpack.apm.breadcrumb.metricsTitle": "指标",
- "xpack.apm.breadcrumb.nodesTitle": "JVM",
- "xpack.apm.breadcrumb.overviewTitle": "概览",
"xpack.apm.breadcrumb.serviceMapTitle": "服务地图",
- "xpack.apm.breadcrumb.serviceProfilingTitle": "分析",
"xpack.apm.breadcrumb.servicesTitle": "服务",
- "xpack.apm.breadcrumb.settings.agentConfigurationTitle": "代理配置",
- "xpack.apm.breadcrumb.settings.anomalyDetection": "异常检测",
- "xpack.apm.breadcrumb.settings.createAgentConfigurationTitle": "创建代理配置",
- "xpack.apm.breadcrumb.settings.customizeUI": "定制 UI",
- "xpack.apm.breadcrumb.settings.editAgentConfigurationTitle": "编辑代理配置",
- "xpack.apm.breadcrumb.settings.indicesTitle": "索引",
"xpack.apm.breadcrumb.tracesTitle": "追溯",
- "xpack.apm.breadcrumb.transactionsTitle": "事务",
"xpack.apm.chart.annotation.version": "版本",
"xpack.apm.chart.cpuSeries.processAverageLabel": "进程平均值",
"xpack.apm.chart.cpuSeries.processMaxLabel": "进程最大值",
@@ -5554,8 +5541,6 @@
"xpack.apm.home.alertsMenu.transactionErrorRate": "事务错误率",
"xpack.apm.home.alertsMenu.viewActiveAlerts": "查看活动告警",
"xpack.apm.home.serviceMapTabLabel": "服务地图",
- "xpack.apm.home.servicesTabLabel": "服务",
- "xpack.apm.home.tracesTabLabel": "追溯",
"xpack.apm.instancesLatencyDistributionChartLegend": "实例",
"xpack.apm.instancesLatencyDistributionChartLegend.previousPeriod": "上一时段",
"xpack.apm.instancesLatencyDistributionChartTitle": "实例延迟分布",
@@ -5622,7 +5607,6 @@
"xpack.apm.profiling.highlightFrames": "搜索",
"xpack.apm.profiling.table.name": "名称",
"xpack.apm.profiling.table.value": "自我",
- "xpack.apm.profilingOverviewTitle": "分析",
"xpack.apm.propertiesTable.agentFeature.noDataAvailableLabel": "没有可用数据",
"xpack.apm.propertiesTable.agentFeature.noResultFound": "没有“{value}”的结果。",
"xpack.apm.propertiesTable.tabs.exceptionStacktraceLabel": "异常堆栈跟踪",
@@ -5687,7 +5671,6 @@
"xpack.apm.selectPlaceholder": "选择选项:",
"xpack.apm.serviceDetails.errorsTabLabel": "错误",
"xpack.apm.serviceDetails.metrics.cpuUsageChartTitle": "CPU 使用",
- "xpack.apm.serviceDetails.metrics.errorOccurrencesChartTitle": "错误发生次数",
"xpack.apm.serviceDetails.metrics.memoryUsageChartTitle": "系统内存使用",
"xpack.apm.serviceDetails.metricsTabLabel": "指标",
"xpack.apm.serviceDetails.nodesTabLabel": "JVM",
@@ -5925,7 +5908,6 @@
"xpack.apm.settings.customizeUI.customLink.table.url": "URL",
"xpack.apm.settings.indices": "索引",
"xpack.apm.settings.pageTitle": "设置",
- "xpack.apm.settings.returnLinkLabel": "返回库存",
"xpack.apm.settingsLinkLabel": "设置",
"xpack.apm.setupInstructionsButtonLabel": "设置说明",
"xpack.apm.significanTerms.license.text": "要使用相关性 API,必须订阅 Elastic 白金级许可证。",