mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[APM] getInjectedVars shim (#51635)
* [APM] getInjectedVars shim Set up the APM public NP plugin to expose the config variables on its context, and replace use of getInjectedVars with that. Since we're not yet running as an NP plugin, we don't get passed a `pluginInitializerContext`, so we use a shim in the plugin setup that gets the config values from injected vars for the time being. Also: * Move toggle app link in nav shim to plugin setup * Replace the routes exported from Main/route_config with a function that takes a configuration object
This commit is contained in:
parent
a46833ec98
commit
0ba5c1e4d2
13 changed files with 350 additions and 251 deletions
|
@ -43,7 +43,6 @@ export const apm: LegacyPluginInitializer = kibana => {
|
|||
apmServiceMapEnabled: config.get('xpack.apm.serviceMapEnabled')
|
||||
};
|
||||
},
|
||||
hacks: ['plugins/apm/hacks/toggle_app_link_in_nav'],
|
||||
savedObjectSchemas: {
|
||||
'apm-services-telemetry': {
|
||||
isNamespaceAgnostic: true
|
||||
|
|
|
@ -7,8 +7,13 @@
|
|||
import { shallow } from 'enzyme';
|
||||
import React from 'react';
|
||||
import { Home } from '../Home';
|
||||
import * as plugin from '../../../new-platform/plugin';
|
||||
|
||||
jest.mock('ui/new_platform');
|
||||
jest.spyOn(plugin, 'usePlugins').mockReturnValue(({
|
||||
apm: { config: {} as plugin.ConfigSchema }
|
||||
} as unknown) as plugin.ApmPluginStartDeps & {
|
||||
apm: { config: plugin.ConfigSchema };
|
||||
});
|
||||
|
||||
describe('Home component', () => {
|
||||
it('should render services', () => {
|
||||
|
|
|
@ -13,7 +13,6 @@ import {
|
|||
EuiSpacer
|
||||
} from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { npStart } from 'ui/new_platform';
|
||||
import React from 'react';
|
||||
import { $ElementType } from 'utility-types';
|
||||
import { ApmHeader } from '../../shared/ApmHeader';
|
||||
|
@ -26,46 +25,54 @@ import { EuiTabLink } from '../../shared/EuiTabLink';
|
|||
import { SettingsLink } from '../../shared/Links/apm/SettingsLink';
|
||||
import { ServiceMapLink } from '../../shared/Links/apm/ServiceMapLink';
|
||||
import { ServiceMap } from '../ServiceMap';
|
||||
import { usePlugins } from '../../../new-platform/plugin';
|
||||
|
||||
const homeTabs = [
|
||||
{
|
||||
link: (
|
||||
<ServiceOverviewLink>
|
||||
{i18n.translate('xpack.apm.home.servicesTabLabel', {
|
||||
defaultMessage: 'Services'
|
||||
})}
|
||||
</ServiceOverviewLink>
|
||||
),
|
||||
render: () => <ServiceOverview />,
|
||||
name: 'services'
|
||||
},
|
||||
{
|
||||
link: (
|
||||
<TraceOverviewLink>
|
||||
{i18n.translate('xpack.apm.home.tracesTabLabel', {
|
||||
defaultMessage: 'Traces'
|
||||
})}
|
||||
</TraceOverviewLink>
|
||||
),
|
||||
render: () => <TraceOverview />,
|
||||
name: 'traces'
|
||||
function getHomeTabs({
|
||||
apmServiceMapEnabled = false
|
||||
}: {
|
||||
apmServiceMapEnabled: boolean;
|
||||
}) {
|
||||
const homeTabs = [
|
||||
{
|
||||
link: (
|
||||
<ServiceOverviewLink>
|
||||
{i18n.translate('xpack.apm.home.servicesTabLabel', {
|
||||
defaultMessage: 'Services'
|
||||
})}
|
||||
</ServiceOverviewLink>
|
||||
),
|
||||
render: () => <ServiceOverview />,
|
||||
name: 'services'
|
||||
},
|
||||
{
|
||||
link: (
|
||||
<TraceOverviewLink>
|
||||
{i18n.translate('xpack.apm.home.tracesTabLabel', {
|
||||
defaultMessage: 'Traces'
|
||||
})}
|
||||
</TraceOverviewLink>
|
||||
),
|
||||
render: () => <TraceOverview />,
|
||||
name: 'traces'
|
||||
}
|
||||
];
|
||||
|
||||
if (apmServiceMapEnabled) {
|
||||
homeTabs.push({
|
||||
link: (
|
||||
<ServiceMapLink>
|
||||
{i18n.translate('xpack.apm.home.serviceMapTabLabel', {
|
||||
defaultMessage: 'Service Map'
|
||||
})}
|
||||
</ServiceMapLink>
|
||||
),
|
||||
render: () => <ServiceMap />,
|
||||
name: 'service-map'
|
||||
});
|
||||
}
|
||||
];
|
||||
|
||||
if (npStart.core.injectedMetadata.getInjectedVar('apmServiceMapEnabled')) {
|
||||
homeTabs.push({
|
||||
link: (
|
||||
<ServiceMapLink>
|
||||
{i18n.translate('xpack.apm.home.serviceMapTabLabel', {
|
||||
defaultMessage: 'Service Map'
|
||||
})}
|
||||
</ServiceMapLink>
|
||||
),
|
||||
render: () => <ServiceMap />,
|
||||
name: 'service-map'
|
||||
});
|
||||
return homeTabs;
|
||||
}
|
||||
|
||||
const SETTINGS_LINK_LABEL = i18n.translate('xpack.apm.settingsLinkLabel', {
|
||||
defaultMessage: 'Settings'
|
||||
});
|
||||
|
@ -75,6 +82,9 @@ interface Props {
|
|||
}
|
||||
|
||||
export function Home({ tab }: Props) {
|
||||
const { apm } = usePlugins();
|
||||
const { apmServiceMapEnabled } = apm.config;
|
||||
const homeTabs = getHomeTabs({ apmServiceMapEnabled });
|
||||
const selectedTab = homeTabs.find(
|
||||
homeTab => homeTab.name === tab
|
||||
) as $ElementType<typeof homeTabs, number>;
|
||||
|
|
|
@ -9,8 +9,11 @@ import React from 'react';
|
|||
import { LegacyCoreStart } from 'src/core/public';
|
||||
import { useKibanaCore } from '../../../../../observability/public';
|
||||
import { getAPMHref } from '../../shared/Links/apm/APMLink';
|
||||
import { Breadcrumb, ProvideBreadcrumbs } from './ProvideBreadcrumbs';
|
||||
import { routes } from './route_config';
|
||||
import {
|
||||
Breadcrumb,
|
||||
ProvideBreadcrumbs,
|
||||
BreadcrumbRoute
|
||||
} from './ProvideBreadcrumbs';
|
||||
|
||||
interface Props {
|
||||
location: Location;
|
||||
|
@ -49,7 +52,11 @@ class UpdateBreadcrumbsComponent extends React.Component<Props> {
|
|||
}
|
||||
}
|
||||
|
||||
export function UpdateBreadcrumbs() {
|
||||
interface UpdateBreadcrumbsProps {
|
||||
routes: BreadcrumbRoute[];
|
||||
}
|
||||
|
||||
export function UpdateBreadcrumbs({ routes }: UpdateBreadcrumbsProps) {
|
||||
const core = useKibanaCore();
|
||||
return (
|
||||
<ProvideBreadcrumbs
|
||||
|
|
|
@ -9,8 +9,9 @@ import React from 'react';
|
|||
import { MemoryRouter } from 'react-router-dom';
|
||||
import { UpdateBreadcrumbs } from '../UpdateBreadcrumbs';
|
||||
import * as kibanaCore from '../../../../../../observability/public/context/kibana_core';
|
||||
import { getRoutes } from '../route_config';
|
||||
|
||||
jest.mock('ui/new_platform');
|
||||
jest.mock('ui/index_patterns');
|
||||
|
||||
const coreMock = {
|
||||
chrome: {
|
||||
|
@ -20,10 +21,12 @@ const coreMock = {
|
|||
|
||||
jest.spyOn(kibanaCore, 'useKibanaCore').mockReturnValue(coreMock);
|
||||
|
||||
const routes = getRoutes({ apmServiceMapEnabled: true });
|
||||
|
||||
function expectBreadcrumbToMatchSnapshot(route, params = '') {
|
||||
mount(
|
||||
<MemoryRouter initialEntries={[`${route}?kuery=myKuery&${params}`]}>
|
||||
<UpdateBreadcrumbs />
|
||||
<UpdateBreadcrumbs routes={routes} />
|
||||
</MemoryRouter>
|
||||
);
|
||||
expect(coreMock.chrome.setBreadcrumbs).toHaveBeenCalledTimes(1);
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
import { i18n } from '@kbn/i18n';
|
||||
import React from 'react';
|
||||
import { Redirect, RouteComponentProps } from 'react-router-dom';
|
||||
import { npStart } from 'ui/new_platform';
|
||||
import { SERVICE_NODE_NAME_MISSING } from '../../../../../common/service_nodes';
|
||||
import { ErrorGroupDetails } from '../../ErrorGroupDetails';
|
||||
import { ServiceDetails } from '../../ServiceDetails';
|
||||
|
@ -42,172 +41,180 @@ const renderAsRedirectTo = (to: string) => {
|
|||
);
|
||||
};
|
||||
|
||||
export const routes: BreadcrumbRoute[] = [
|
||||
{
|
||||
exact: true,
|
||||
path: '/',
|
||||
render: renderAsRedirectTo('/services'),
|
||||
breadcrumb: 'APM',
|
||||
name: RouteName.HOME
|
||||
},
|
||||
{
|
||||
exact: true,
|
||||
path: '/services',
|
||||
component: () => <Home tab="services" />,
|
||||
breadcrumb: i18n.translate('xpack.apm.breadcrumb.servicesTitle', {
|
||||
defaultMessage: 'Services'
|
||||
}),
|
||||
name: RouteName.SERVICES
|
||||
},
|
||||
{
|
||||
exact: true,
|
||||
path: '/traces',
|
||||
component: () => <Home tab="traces" />,
|
||||
breadcrumb: i18n.translate('xpack.apm.breadcrumb.tracesTitle', {
|
||||
defaultMessage: 'Traces'
|
||||
}),
|
||||
name: RouteName.TRACES
|
||||
},
|
||||
{
|
||||
exact: true,
|
||||
path: '/settings',
|
||||
render: renderAsRedirectTo('/settings/agent-configuration'),
|
||||
breadcrumb: i18n.translate('xpack.apm.breadcrumb.listSettingsTitle', {
|
||||
defaultMessage: 'Settings'
|
||||
}),
|
||||
name: RouteName.SETTINGS
|
||||
},
|
||||
{
|
||||
exact: true,
|
||||
path: '/settings/apm-indices',
|
||||
component: () => (
|
||||
<Settings>
|
||||
<ApmIndices />
|
||||
</Settings>
|
||||
),
|
||||
breadcrumb: i18n.translate('xpack.apm.breadcrumb.settings.indicesTitle', {
|
||||
defaultMessage: 'Indices'
|
||||
}),
|
||||
name: RouteName.INDICES
|
||||
},
|
||||
{
|
||||
exact: true,
|
||||
path: '/settings/agent-configuration',
|
||||
component: () => (
|
||||
<Settings>
|
||||
<AgentConfigurations />
|
||||
</Settings>
|
||||
),
|
||||
breadcrumb: i18n.translate(
|
||||
'xpack.apm.breadcrumb.settings.agentConfigurationTitle',
|
||||
{
|
||||
defaultMessage: 'Agent Configuration'
|
||||
}
|
||||
),
|
||||
name: RouteName.AGENT_CONFIGURATION
|
||||
},
|
||||
{
|
||||
exact: true,
|
||||
path: '/services/:serviceName',
|
||||
breadcrumb: ({ match }) => match.params.serviceName,
|
||||
render: (props: RouteComponentProps<RouteParams>) =>
|
||||
renderAsRedirectTo(
|
||||
`/services/${props.match.params.serviceName}/transactions`
|
||||
)(props),
|
||||
name: RouteName.SERVICE
|
||||
},
|
||||
// errors
|
||||
{
|
||||
exact: true,
|
||||
path: '/services/:serviceName/errors/:groupId',
|
||||
component: ErrorGroupDetails,
|
||||
breadcrumb: ({ match }) => match.params.groupId,
|
||||
name: RouteName.ERROR
|
||||
},
|
||||
{
|
||||
exact: true,
|
||||
path: '/services/:serviceName/errors',
|
||||
component: () => <ServiceDetails tab="errors" />,
|
||||
breadcrumb: i18n.translate('xpack.apm.breadcrumb.errorsTitle', {
|
||||
defaultMessage: 'Errors'
|
||||
}),
|
||||
name: RouteName.ERRORS
|
||||
},
|
||||
// transactions
|
||||
{
|
||||
exact: true,
|
||||
path: '/services/:serviceName/transactions',
|
||||
component: () => <ServiceDetails tab="transactions" />,
|
||||
breadcrumb: i18n.translate('xpack.apm.breadcrumb.transactionsTitle', {
|
||||
defaultMessage: 'Transactions'
|
||||
}),
|
||||
name: RouteName.TRANSACTIONS
|
||||
},
|
||||
// metrics
|
||||
{
|
||||
exact: true,
|
||||
path: '/services/:serviceName/metrics',
|
||||
component: () => <ServiceDetails tab="metrics" />,
|
||||
breadcrumb: metricsBreadcrumb,
|
||||
name: RouteName.METRICS
|
||||
},
|
||||
// service nodes, only enabled for java agents for now
|
||||
{
|
||||
exact: true,
|
||||
path: '/services/:serviceName/nodes',
|
||||
component: () => <ServiceDetails tab="nodes" />,
|
||||
breadcrumb: i18n.translate('xpack.apm.breadcrumb.nodesTitle', {
|
||||
defaultMessage: 'JVMs'
|
||||
}),
|
||||
name: RouteName.SERVICE_NODES
|
||||
},
|
||||
// node metrics
|
||||
{
|
||||
exact: true,
|
||||
path: '/services/:serviceName/nodes/:serviceNodeName/metrics',
|
||||
component: () => <ServiceNodeMetrics />,
|
||||
breadcrumb: ({ location }) => {
|
||||
const { serviceNodeName } = resolveUrlParams(location, {});
|
||||
|
||||
if (serviceNodeName === SERVICE_NODE_NAME_MISSING) {
|
||||
return UNIDENTIFIED_SERVICE_NODES_LABEL;
|
||||
}
|
||||
|
||||
return serviceNodeName || '';
|
||||
},
|
||||
name: RouteName.SERVICE_NODE_METRICS
|
||||
},
|
||||
{
|
||||
exact: true,
|
||||
path: '/services/:serviceName/transactions/view',
|
||||
component: TransactionDetails,
|
||||
breadcrumb: ({ location }) => {
|
||||
const query = toQuery(location.search);
|
||||
return query.transactionName as string;
|
||||
},
|
||||
name: RouteName.TRANSACTION_NAME
|
||||
}
|
||||
];
|
||||
|
||||
if (npStart.core.injectedMetadata.getInjectedVar('apmServiceMapEnabled')) {
|
||||
routes.push(
|
||||
export function getRoutes({
|
||||
apmServiceMapEnabled
|
||||
}: {
|
||||
apmServiceMapEnabled: boolean;
|
||||
}): BreadcrumbRoute[] {
|
||||
const routes: BreadcrumbRoute[] = [
|
||||
{
|
||||
exact: true,
|
||||
path: '/service-map',
|
||||
component: () => <Home tab="service-map" />,
|
||||
breadcrumb: i18n.translate('xpack.apm.breadcrumb.serviceMapTitle', {
|
||||
defaultMessage: 'Service Map'
|
||||
}),
|
||||
name: RouteName.SERVICE_MAP
|
||||
path: '/',
|
||||
render: renderAsRedirectTo('/services'),
|
||||
breadcrumb: 'APM',
|
||||
name: RouteName.HOME
|
||||
},
|
||||
{
|
||||
exact: true,
|
||||
path: '/services/:serviceName/service-map',
|
||||
component: () => <ServiceDetails tab="service-map" />,
|
||||
breadcrumb: i18n.translate('xpack.apm.breadcrumb.serviceMapTitle', {
|
||||
defaultMessage: 'Service Map'
|
||||
path: '/services',
|
||||
component: () => <Home tab="services" />,
|
||||
breadcrumb: i18n.translate('xpack.apm.breadcrumb.servicesTitle', {
|
||||
defaultMessage: 'Services'
|
||||
}),
|
||||
name: RouteName.SINGLE_SERVICE_MAP
|
||||
name: RouteName.SERVICES
|
||||
},
|
||||
{
|
||||
exact: true,
|
||||
path: '/traces',
|
||||
component: () => <Home tab="traces" />,
|
||||
breadcrumb: i18n.translate('xpack.apm.breadcrumb.tracesTitle', {
|
||||
defaultMessage: 'Traces'
|
||||
}),
|
||||
name: RouteName.TRACES
|
||||
},
|
||||
{
|
||||
exact: true,
|
||||
path: '/settings',
|
||||
render: renderAsRedirectTo('/settings/agent-configuration'),
|
||||
breadcrumb: i18n.translate('xpack.apm.breadcrumb.listSettingsTitle', {
|
||||
defaultMessage: 'Settings'
|
||||
}),
|
||||
name: RouteName.SETTINGS
|
||||
},
|
||||
{
|
||||
exact: true,
|
||||
path: '/settings/apm-indices',
|
||||
component: () => (
|
||||
<Settings>
|
||||
<ApmIndices />
|
||||
</Settings>
|
||||
),
|
||||
breadcrumb: i18n.translate('xpack.apm.breadcrumb.settings.indicesTitle', {
|
||||
defaultMessage: 'Indices'
|
||||
}),
|
||||
name: RouteName.INDICES
|
||||
},
|
||||
{
|
||||
exact: true,
|
||||
path: '/settings/agent-configuration',
|
||||
component: () => (
|
||||
<Settings>
|
||||
<AgentConfigurations />
|
||||
</Settings>
|
||||
),
|
||||
breadcrumb: i18n.translate(
|
||||
'xpack.apm.breadcrumb.settings.agentConfigurationTitle',
|
||||
{
|
||||
defaultMessage: 'Agent Configuration'
|
||||
}
|
||||
),
|
||||
name: RouteName.AGENT_CONFIGURATION
|
||||
},
|
||||
{
|
||||
exact: true,
|
||||
path: '/services/:serviceName',
|
||||
breadcrumb: ({ match }) => match.params.serviceName,
|
||||
render: (props: RouteComponentProps<RouteParams>) =>
|
||||
renderAsRedirectTo(
|
||||
`/services/${props.match.params.serviceName}/transactions`
|
||||
)(props),
|
||||
name: RouteName.SERVICE
|
||||
},
|
||||
// errors
|
||||
{
|
||||
exact: true,
|
||||
path: '/services/:serviceName/errors/:groupId',
|
||||
component: ErrorGroupDetails,
|
||||
breadcrumb: ({ match }) => match.params.groupId,
|
||||
name: RouteName.ERROR
|
||||
},
|
||||
{
|
||||
exact: true,
|
||||
path: '/services/:serviceName/errors',
|
||||
component: () => <ServiceDetails tab="errors" />,
|
||||
breadcrumb: i18n.translate('xpack.apm.breadcrumb.errorsTitle', {
|
||||
defaultMessage: 'Errors'
|
||||
}),
|
||||
name: RouteName.ERRORS
|
||||
},
|
||||
// transactions
|
||||
{
|
||||
exact: true,
|
||||
path: '/services/:serviceName/transactions',
|
||||
component: () => <ServiceDetails tab="transactions" />,
|
||||
breadcrumb: i18n.translate('xpack.apm.breadcrumb.transactionsTitle', {
|
||||
defaultMessage: 'Transactions'
|
||||
}),
|
||||
name: RouteName.TRANSACTIONS
|
||||
},
|
||||
// metrics
|
||||
{
|
||||
exact: true,
|
||||
path: '/services/:serviceName/metrics',
|
||||
component: () => <ServiceDetails tab="metrics" />,
|
||||
breadcrumb: metricsBreadcrumb,
|
||||
name: RouteName.METRICS
|
||||
},
|
||||
// service nodes, only enabled for java agents for now
|
||||
{
|
||||
exact: true,
|
||||
path: '/services/:serviceName/nodes',
|
||||
component: () => <ServiceDetails tab="nodes" />,
|
||||
breadcrumb: i18n.translate('xpack.apm.breadcrumb.nodesTitle', {
|
||||
defaultMessage: 'JVMs'
|
||||
}),
|
||||
name: RouteName.SERVICE_NODES
|
||||
},
|
||||
// node metrics
|
||||
{
|
||||
exact: true,
|
||||
path: '/services/:serviceName/nodes/:serviceNodeName/metrics',
|
||||
component: () => <ServiceNodeMetrics />,
|
||||
breadcrumb: ({ location }) => {
|
||||
const { serviceNodeName } = resolveUrlParams(location, {});
|
||||
|
||||
if (serviceNodeName === SERVICE_NODE_NAME_MISSING) {
|
||||
return UNIDENTIFIED_SERVICE_NODES_LABEL;
|
||||
}
|
||||
|
||||
return serviceNodeName || '';
|
||||
},
|
||||
name: RouteName.SERVICE_NODE_METRICS
|
||||
},
|
||||
{
|
||||
exact: true,
|
||||
path: '/services/:serviceName/transactions/view',
|
||||
component: TransactionDetails,
|
||||
breadcrumb: ({ location }) => {
|
||||
const query = toQuery(location.search);
|
||||
return query.transactionName as string;
|
||||
},
|
||||
name: RouteName.TRANSACTION_NAME
|
||||
}
|
||||
);
|
||||
];
|
||||
|
||||
if (apmServiceMapEnabled) {
|
||||
routes.push(
|
||||
{
|
||||
exact: true,
|
||||
path: '/service-map',
|
||||
component: () => <Home tab="service-map" />,
|
||||
breadcrumb: i18n.translate('xpack.apm.breadcrumb.serviceMapTitle', {
|
||||
defaultMessage: 'Service Map'
|
||||
}),
|
||||
name: RouteName.SERVICE_MAP
|
||||
},
|
||||
{
|
||||
exact: true,
|
||||
path: '/services/:serviceName/service-map',
|
||||
component: () => <ServiceDetails tab="service-map" />,
|
||||
breadcrumb: i18n.translate('xpack.apm.breadcrumb.serviceMapTitle', {
|
||||
defaultMessage: 'Service Map'
|
||||
}),
|
||||
name: RouteName.SINGLE_SERVICE_MAP
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
return routes;
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
import { i18n } from '@kbn/i18n';
|
||||
import React from 'react';
|
||||
import { EuiTabs, EuiSpacer } from '@elastic/eui';
|
||||
import { npStart } from 'ui/new_platform';
|
||||
import { ErrorGroupOverview } from '../ErrorGroupOverview';
|
||||
import { TransactionOverview } from '../TransactionOverview';
|
||||
import { ServiceMetrics } from '../ServiceMetrics';
|
||||
|
@ -22,6 +21,7 @@ import { ServiceNodeOverview } from '../ServiceNodeOverview';
|
|||
import { useAgentName } from '../../../hooks/useAgentName';
|
||||
import { ServiceMap } from '../ServiceMap';
|
||||
import { ServiceMapLink } from '../../shared/Links/apm/ServiceMapLink';
|
||||
import { usePlugins } from '../../../new-platform/plugin';
|
||||
|
||||
interface Props {
|
||||
tab: 'transactions' | 'errors' | 'metrics' | 'nodes' | 'service-map';
|
||||
|
@ -31,6 +31,8 @@ export function ServiceDetailTabs({ tab }: Props) {
|
|||
const { urlParams } = useUrlParams();
|
||||
const { serviceName } = urlParams;
|
||||
const { agentName } = useAgentName();
|
||||
const { apm } = usePlugins();
|
||||
const { apmServiceMapEnabled } = apm.config;
|
||||
|
||||
if (!serviceName) {
|
||||
// this never happens, urlParams type is not accurate enough
|
||||
|
@ -105,7 +107,7 @@ export function ServiceDetailTabs({ tab }: Props) {
|
|||
name: 'service-map'
|
||||
};
|
||||
|
||||
if (npStart.core.injectedMetadata.getInjectedVar('apmServiceMapEnabled')) {
|
||||
if (apmServiceMapEnabled) {
|
||||
tabs.push(serviceMapTab);
|
||||
}
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ import { IUrlParams } from '../../../../context/UrlParamsContext/types';
|
|||
import { KibanaLink } from '../../../shared/Links/KibanaLink';
|
||||
import { createErrorGroupWatch, Schedule } from './createErrorGroupWatch';
|
||||
import { ElasticDocsLink } from '../../../shared/Links/ElasticDocsLink';
|
||||
import { PluginsContext } from '../../../../new-platform/plugin';
|
||||
|
||||
type ScheduleKey = keyof Schedule;
|
||||
|
||||
|
@ -149,9 +150,13 @@ export class WatcherFlyout extends Component<
|
|||
this.setState({ slackUrl: event.target.value });
|
||||
};
|
||||
|
||||
public createWatch = () => {
|
||||
const core = this.context;
|
||||
public createWatch = ({
|
||||
apmIndexPatternTitle
|
||||
}: {
|
||||
apmIndexPatternTitle: string;
|
||||
}) => () => {
|
||||
const { serviceName } = this.props.urlParams;
|
||||
const core = this.context;
|
||||
|
||||
if (!serviceName) {
|
||||
return;
|
||||
|
@ -186,10 +191,6 @@ export class WatcherFlyout extends Component<
|
|||
unit: 'h'
|
||||
};
|
||||
|
||||
const apmIndexPatternTitle = core.injectedMetadata.getInjectedVar(
|
||||
'apmIndexPatternTitle'
|
||||
) as string;
|
||||
|
||||
return createErrorGroupWatch({
|
||||
http: core.http,
|
||||
emails,
|
||||
|
@ -613,20 +614,26 @@ export class WatcherFlyout extends Component<
|
|||
<EuiFlyoutFooter>
|
||||
<EuiFlexGroup justifyContent="flexEnd">
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiButton
|
||||
onClick={this.createWatch}
|
||||
fill
|
||||
disabled={
|
||||
!this.state.actions.email && !this.state.actions.slack
|
||||
}
|
||||
>
|
||||
{i18n.translate(
|
||||
'xpack.apm.serviceDetails.enableErrorReportsPanel.createWatchButtonLabel',
|
||||
{
|
||||
defaultMessage: 'Create watch'
|
||||
}
|
||||
)}
|
||||
</EuiButton>
|
||||
<PluginsContext.Consumer>
|
||||
{({ apm }) => {
|
||||
return (
|
||||
<EuiButton
|
||||
onClick={this.createWatch(apm.config)}
|
||||
fill
|
||||
disabled={
|
||||
!this.state.actions.email && !this.state.actions.slack
|
||||
}
|
||||
>
|
||||
{i18n.translate(
|
||||
'xpack.apm.serviceDetails.enableErrorReportsPanel.createWatchButtonLabel',
|
||||
{
|
||||
defaultMessage: 'Create watch'
|
||||
}
|
||||
)}
|
||||
</EuiButton>
|
||||
);
|
||||
}}
|
||||
</PluginsContext.Consumer>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</EuiFlyoutFooter>
|
||||
|
|
|
@ -3,16 +3,21 @@
|
|||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
import React, { useMemo } from 'react';
|
||||
import React, { useMemo, ReactChild } from 'react';
|
||||
import { matchPath } from 'react-router-dom';
|
||||
import { routes } from '../components/app/Main/route_config';
|
||||
import { useLocation } from '../hooks/useLocation';
|
||||
import { BreadcrumbRoute } from '../components/app/Main/ProvideBreadcrumbs';
|
||||
|
||||
export const MatchedRouteContext = React.createContext<Array<typeof routes[0]>>(
|
||||
[]
|
||||
);
|
||||
export const MatchedRouteContext = React.createContext<BreadcrumbRoute[]>([]);
|
||||
|
||||
export const MatchedRouteProvider: React.FC = ({ children }) => {
|
||||
interface MatchedRouteProviderProps {
|
||||
children: ReactChild;
|
||||
routes: BreadcrumbRoute[];
|
||||
}
|
||||
export function MatchedRouteProvider({
|
||||
children,
|
||||
routes
|
||||
}: MatchedRouteProviderProps) {
|
||||
const { pathname } = useLocation();
|
||||
|
||||
const contextValue = useMemo(() => {
|
||||
|
@ -21,9 +26,9 @@ export const MatchedRouteProvider: React.FC = ({ children }) => {
|
|||
path: route.path
|
||||
});
|
||||
});
|
||||
}, [pathname]);
|
||||
}, [pathname, routes]);
|
||||
|
||||
return (
|
||||
<MatchedRouteContext.Provider value={contextValue} children={children} />
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { npStart } from 'ui/new_platform';
|
||||
import { ConfigSchema } from './plugin';
|
||||
|
||||
const { core } = npStart;
|
||||
|
||||
export function getConfigFromInjectedMetadata(): ConfigSchema {
|
||||
const {
|
||||
apmIndexPatternTitle,
|
||||
apmServiceMapEnabled,
|
||||
apmUiEnabled
|
||||
} = core.injectedMetadata.getInjectedVars();
|
||||
|
||||
return {
|
||||
apmIndexPatternTitle,
|
||||
apmServiceMapEnabled,
|
||||
apmUiEnabled
|
||||
} as ConfigSchema;
|
||||
}
|
|
@ -10,4 +10,4 @@ import { ApmPlugin, ApmPluginSetup, ApmPluginStart } from './plugin';
|
|||
export const plugin: PluginInitializer<
|
||||
ApmPluginSetup,
|
||||
ApmPluginStart
|
||||
> = _core => new ApmPlugin();
|
||||
> = pluginInitializerContext => new ApmPlugin(pluginInitializerContext);
|
||||
|
|
|
@ -13,7 +13,8 @@ import {
|
|||
CoreStart,
|
||||
LegacyCoreStart,
|
||||
Plugin,
|
||||
CoreSetup
|
||||
CoreSetup,
|
||||
PluginInitializerContext
|
||||
} from '../../../../../../src/core/public';
|
||||
import { DataPublicPluginStart } from '../../../../../../src/plugins/data/public';
|
||||
import { KibanaCoreContextProvider } from '../../../observability/public';
|
||||
|
@ -24,13 +25,16 @@ import { px, unit, units } from '../style/variables';
|
|||
import { LoadingIndicatorProvider } from '../context/LoadingIndicatorContext';
|
||||
import { LicenseProvider } from '../context/LicenseContext';
|
||||
import { UpdateBreadcrumbs } from '../components/app/Main/UpdateBreadcrumbs';
|
||||
import { routes } from '../components/app/Main/route_config';
|
||||
import { getRoutes } from '../components/app/Main/route_config';
|
||||
import { ScrollToTopOnPathChange } from '../components/app/Main/ScrollToTopOnPathChange';
|
||||
import { MatchedRouteProvider } from '../context/MatchedRouteContext';
|
||||
import { createStaticIndexPattern } from '../services/rest/index_pattern';
|
||||
import { setHelpExtension } from './setHelpExtension';
|
||||
import { setReadonlyBadge } from './updateBadge';
|
||||
import { featureCatalogueEntry } from './featureCatalogueEntry';
|
||||
import { getConfigFromInjectedMetadata } from './getConfigFromInjectedMetadata';
|
||||
import { toggleAppLinkInNav } from './toggleAppLinkInNav';
|
||||
import { BreadcrumbRoute } from '../components/app/Main/ProvideBreadcrumbs';
|
||||
|
||||
export const REACT_APP_ROOT_ID = 'react-apm-root';
|
||||
|
||||
|
@ -39,10 +43,10 @@ const MainContainer = styled.main`
|
|||
padding: ${px(units.plus)};
|
||||
`;
|
||||
|
||||
const App = () => {
|
||||
const App = ({ routes }: { routes: BreadcrumbRoute[] }) => {
|
||||
return (
|
||||
<MainContainer data-test-subj="apmMainContainer">
|
||||
<UpdateBreadcrumbs />
|
||||
<UpdateBreadcrumbs routes={routes} />
|
||||
<Route component={ScrollToTopOnPathChange} />
|
||||
<Switch>
|
||||
{routes.map((route, i) => (
|
||||
|
@ -64,8 +68,17 @@ export interface ApmPluginStartDeps {
|
|||
data: DataPublicPluginStart;
|
||||
}
|
||||
|
||||
const PluginsContext = createContext({} as ApmPluginStartDeps);
|
||||
export interface ConfigSchema {
|
||||
apmIndexPatternTitle: string;
|
||||
apmServiceMapEnabled: boolean;
|
||||
apmUiEnabled: boolean;
|
||||
}
|
||||
|
||||
// These are to be used until we switch over all our context handling to
|
||||
// kibana_react
|
||||
export const PluginsContext = createContext<
|
||||
ApmPluginStartDeps & { apm: { config: ConfigSchema } }
|
||||
>({} as ApmPluginStartDeps & { apm: { config: ConfigSchema } });
|
||||
export function usePlugins() {
|
||||
return useContext(PluginsContext);
|
||||
}
|
||||
|
@ -78,6 +91,12 @@ export class ApmPlugin
|
|||
ApmPluginSetupDeps,
|
||||
ApmPluginStartDeps
|
||||
> {
|
||||
constructor(
|
||||
// @ts-ignore Not using initializerContext now, but will be once NP
|
||||
// migration is complete.
|
||||
private readonly initializerContext: PluginInitializerContext<ConfigSchema>
|
||||
) {}
|
||||
|
||||
// Take the DOM element as the constructor, so we can mount the app.
|
||||
public setup(_core: CoreSetup, plugins: ApmPluginSetupDeps) {
|
||||
plugins.home.featureCatalogue.register(featureCatalogueEntry);
|
||||
|
@ -85,21 +104,33 @@ export class ApmPlugin
|
|||
|
||||
public start(core: CoreStart, plugins: ApmPluginStartDeps) {
|
||||
const i18nCore = core.i18n;
|
||||
|
||||
// Once we're actually an NP plugin we'll get the config from the
|
||||
// initializerContext like:
|
||||
//
|
||||
// const config = this.initializerContext.config.get<ConfigSchema>();
|
||||
//
|
||||
// Until then we use a shim to get it from legacy injectedMetadata:
|
||||
const config = getConfigFromInjectedMetadata();
|
||||
const pluginsForContext = { ...plugins, apm: { config } };
|
||||
const routes = getRoutes(config);
|
||||
|
||||
// render APM feedback link in global help menu
|
||||
setHelpExtension(core);
|
||||
setReadonlyBadge(core);
|
||||
toggleAppLinkInNav(core, config);
|
||||
|
||||
ReactDOM.render(
|
||||
<KibanaCoreContextProvider core={core as LegacyCoreStart}>
|
||||
<PluginsContext.Provider value={plugins}>
|
||||
<PluginsContext.Provider value={pluginsForContext}>
|
||||
<i18nCore.Context>
|
||||
<Router history={history}>
|
||||
<LocationProvider>
|
||||
<MatchedRouteProvider>
|
||||
<MatchedRouteProvider routes={routes}>
|
||||
<UrlParamsProvider>
|
||||
<LoadingIndicatorProvider>
|
||||
<LicenseProvider>
|
||||
<App />
|
||||
<App routes={routes} />
|
||||
</LicenseProvider>
|
||||
</LoadingIndicatorProvider>
|
||||
</UrlParamsProvider>
|
||||
|
|
|
@ -4,11 +4,10 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { npStart } from 'ui/new_platform';
|
||||
import { CoreStart } from 'kibana/public';
|
||||
|
||||
const { core } = npStart;
|
||||
const apmUiEnabled = core.injectedMetadata.getInjectedVar('apmUiEnabled');
|
||||
|
||||
if (apmUiEnabled === false) {
|
||||
core.chrome.navLinks.update('apm', { hidden: true });
|
||||
export function toggleAppLinkInNav(core: CoreStart, { apmUiEnabled = false }) {
|
||||
if (apmUiEnabled === false) {
|
||||
core.chrome.navLinks.update('apm', { hidden: true });
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue