mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[RUM Dashboard] Create new path for client side monitoring (#74740)
This commit is contained in:
parent
32bd45bfbb
commit
2c865f5649
11 changed files with 213 additions and 46 deletions
130
x-pack/plugins/apm/public/application/csmApp.tsx
Normal file
130
x-pack/plugins/apm/public/application/csmApp.tsx
Normal file
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { Route, Router } from 'react-router-dom';
|
||||
import styled, { ThemeProvider, DefaultTheme } from 'styled-components';
|
||||
import euiDarkVars from '@elastic/eui/dist/eui_theme_dark.json';
|
||||
import euiLightVars from '@elastic/eui/dist/eui_theme_light.json';
|
||||
import { CoreStart, AppMountParameters } from 'kibana/public';
|
||||
import { ApmPluginSetupDeps } from '../plugin';
|
||||
|
||||
import {
|
||||
KibanaContextProvider,
|
||||
useUiSetting$,
|
||||
} from '../../../../../src/plugins/kibana_react/public';
|
||||
import { px, units } from '../style/variables';
|
||||
import { UpdateBreadcrumbs } from '../components/app/Main/UpdateBreadcrumbs';
|
||||
import { ScrollToTopOnPathChange } from '../components/app/Main/ScrollToTopOnPathChange';
|
||||
import { history, resetHistory } from '../utils/history';
|
||||
import 'react-vis/dist/style.css';
|
||||
import { RumHome } from '../components/app/RumDashboard/RumHome';
|
||||
import { ConfigSchema } from '../index';
|
||||
import { BreadcrumbRoute } from '../components/app/Main/ProvideBreadcrumbs';
|
||||
import { RouteName } from '../components/app/Main/route_config/route_names';
|
||||
import { renderAsRedirectTo } from '../components/app/Main/route_config';
|
||||
import { ApmPluginContext } from '../context/ApmPluginContext';
|
||||
import { UrlParamsProvider } from '../context/UrlParamsContext';
|
||||
import { LoadingIndicatorProvider } from '../context/LoadingIndicatorContext';
|
||||
import { createCallApmApi } from '../services/rest/createCallApmApi';
|
||||
|
||||
const CsmMainContainer = styled.div`
|
||||
padding: ${px(units.plus)};
|
||||
height: 100%;
|
||||
`;
|
||||
|
||||
export const rumRoutes: BreadcrumbRoute[] = [
|
||||
{
|
||||
exact: true,
|
||||
path: '/',
|
||||
render: renderAsRedirectTo('/csm'),
|
||||
breadcrumb: 'Client Side Monitoring',
|
||||
name: RouteName.CSM,
|
||||
},
|
||||
];
|
||||
|
||||
function CsmApp() {
|
||||
const [darkMode] = useUiSetting$<boolean>('theme:darkMode');
|
||||
|
||||
return (
|
||||
<ThemeProvider
|
||||
theme={(outerTheme?: DefaultTheme) => ({
|
||||
...outerTheme,
|
||||
eui: darkMode ? euiDarkVars : euiLightVars,
|
||||
darkMode,
|
||||
})}
|
||||
>
|
||||
<CsmMainContainer data-test-subj="csmMainContainer" role="main">
|
||||
<UpdateBreadcrumbs routes={rumRoutes} />
|
||||
<Route component={ScrollToTopOnPathChange} />
|
||||
<RumHome />
|
||||
</CsmMainContainer>
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
|
||||
export function CsmAppRoot({
|
||||
core,
|
||||
deps,
|
||||
routerHistory,
|
||||
config,
|
||||
}: {
|
||||
core: CoreStart;
|
||||
deps: ApmPluginSetupDeps;
|
||||
routerHistory: typeof history;
|
||||
config: ConfigSchema;
|
||||
}) {
|
||||
const i18nCore = core.i18n;
|
||||
const plugins = deps;
|
||||
const apmPluginContextValue = {
|
||||
config,
|
||||
core,
|
||||
plugins,
|
||||
};
|
||||
return (
|
||||
<ApmPluginContext.Provider value={apmPluginContextValue}>
|
||||
<KibanaContextProvider services={{ ...core, ...plugins }}>
|
||||
<i18nCore.Context>
|
||||
<Router history={routerHistory}>
|
||||
<UrlParamsProvider>
|
||||
<LoadingIndicatorProvider>
|
||||
<CsmApp />
|
||||
</LoadingIndicatorProvider>
|
||||
</UrlParamsProvider>
|
||||
</Router>
|
||||
</i18nCore.Context>
|
||||
</KibanaContextProvider>
|
||||
</ApmPluginContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* This module is rendered asynchronously in the Kibana platform.
|
||||
*/
|
||||
|
||||
export const renderApp = (
|
||||
core: CoreStart,
|
||||
deps: ApmPluginSetupDeps,
|
||||
{ element }: AppMountParameters,
|
||||
config: ConfigSchema
|
||||
) => {
|
||||
createCallApmApi(core.http);
|
||||
|
||||
resetHistory();
|
||||
ReactDOM.render(
|
||||
<CsmAppRoot
|
||||
core={core}
|
||||
deps={deps}
|
||||
routerHistory={history}
|
||||
config={config}
|
||||
/>,
|
||||
element
|
||||
);
|
||||
return () => {
|
||||
ReactDOM.unmountComponentAtNode(element);
|
||||
};
|
||||
};
|
|
@ -20,6 +20,7 @@ import { LocationProvider } from '../context/LocationContext';
|
|||
import { MatchedRouteProvider } from '../context/MatchedRouteContext';
|
||||
import { UrlParamsProvider } from '../context/UrlParamsContext';
|
||||
import { AlertsContextProvider } from '../../../triggers_actions_ui/public';
|
||||
import { createStaticIndexPattern } from '../services/rest/index_pattern';
|
||||
import {
|
||||
KibanaContextProvider,
|
||||
useUiSetting$,
|
||||
|
@ -29,6 +30,9 @@ import { UpdateBreadcrumbs } from '../components/app/Main/UpdateBreadcrumbs';
|
|||
import { ScrollToTopOnPathChange } from '../components/app/Main/ScrollToTopOnPathChange';
|
||||
import { routes } from '../components/app/Main/route_config';
|
||||
import { history, resetHistory } from '../utils/history';
|
||||
import { setHelpExtension } from '../setHelpExtension';
|
||||
import { setReadonlyBadge } from '../updateBadge';
|
||||
import { createCallApmApi } from '../services/rest/createCallApmApi';
|
||||
import { ConfigSchema } from '..';
|
||||
import 'react-vis/dist/style.css';
|
||||
|
||||
|
@ -61,7 +65,7 @@ function App() {
|
|||
);
|
||||
}
|
||||
|
||||
function ApmAppRoot({
|
||||
export function ApmAppRoot({
|
||||
core,
|
||||
deps,
|
||||
routerHistory,
|
||||
|
@ -116,13 +120,27 @@ function ApmAppRoot({
|
|||
/**
|
||||
* This module is rendered asynchronously in the Kibana platform.
|
||||
*/
|
||||
|
||||
export const renderApp = (
|
||||
core: CoreStart,
|
||||
deps: ApmPluginSetupDeps,
|
||||
{ element }: AppMountParameters,
|
||||
config: ConfigSchema
|
||||
) => {
|
||||
// render APM feedback link in global help menu
|
||||
setHelpExtension(core);
|
||||
setReadonlyBadge(core);
|
||||
|
||||
createCallApmApi(core.http);
|
||||
|
||||
resetHistory();
|
||||
|
||||
// Automatically creates static index pattern and stores as saved object
|
||||
createStaticIndexPattern().catch((e) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Error creating static index pattern', e);
|
||||
});
|
||||
|
||||
ReactDOM.render(
|
||||
<ApmAppRoot
|
||||
core={core}
|
||||
|
|
|
@ -25,10 +25,9 @@ import { TraceLink } from '../../TraceLink';
|
|||
import { CustomizeUI } from '../../Settings/CustomizeUI';
|
||||
import { AnomalyDetection } from '../../Settings/anomaly_detection';
|
||||
import {
|
||||
EditAgentConfigurationRouteHandler,
|
||||
CreateAgentConfigurationRouteHandler,
|
||||
EditAgentConfigurationRouteHandler,
|
||||
} from './route_handlers/agent_configuration';
|
||||
import { RumHome } from '../../RumDashboard/RumHome';
|
||||
|
||||
const metricsBreadcrumb = i18n.translate('xpack.apm.breadcrumb.metricsTitle', {
|
||||
defaultMessage: 'Metrics',
|
||||
|
@ -38,7 +37,7 @@ interface RouteParams {
|
|||
serviceName: string;
|
||||
}
|
||||
|
||||
const renderAsRedirectTo = (to: string) => {
|
||||
export const renderAsRedirectTo = (to: string) => {
|
||||
return ({ location }: RouteComponentProps<RouteParams>) => (
|
||||
<Redirect
|
||||
to={{
|
||||
|
@ -252,15 +251,6 @@ export const routes: BreadcrumbRoute[] = [
|
|||
}),
|
||||
name: RouteName.CUSTOMIZE_UI,
|
||||
},
|
||||
{
|
||||
exact: true,
|
||||
path: '/rum-preview',
|
||||
component: () => <RumHome />,
|
||||
breadcrumb: i18n.translate('xpack.apm.home.rumOverview.title', {
|
||||
defaultMessage: 'Real User Monitoring',
|
||||
}),
|
||||
name: RouteName.RUM_OVERVIEW,
|
||||
},
|
||||
{
|
||||
exact: true,
|
||||
path: '/settings/anomaly-detection',
|
||||
|
|
|
@ -26,6 +26,6 @@ export enum RouteName {
|
|||
SERVICE_NODES = 'nodes',
|
||||
LINK_TO_TRACE = 'link_to_trace',
|
||||
CUSTOMIZE_UI = 'customize_ui',
|
||||
RUM_OVERVIEW = 'rum_overview',
|
||||
ANOMALY_DETECTION = 'anomaly_detection',
|
||||
CSM = 'csm',
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
import { EuiFlexGroup, EuiFlexItem, EuiTitle } from '@elastic/eui';
|
||||
import React from 'react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { RumOverview } from '../RumDashboard';
|
||||
import { RumHeader } from './RumHeader';
|
||||
|
||||
|
@ -16,7 +17,11 @@ export function RumHome() {
|
|||
<EuiFlexGroup alignItems="center">
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiTitle size="l">
|
||||
<h1>End User Experience</h1>
|
||||
<h1>
|
||||
{i18n.translate('xpack.apm.csm.title', {
|
||||
defaultMessage: 'Client Side Monitoring',
|
||||
})}
|
||||
</h1>
|
||||
</EuiTitle>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
|
|
|
@ -7,7 +7,10 @@
|
|||
import { i18n } from '@kbn/i18n';
|
||||
import { lazy } from 'react';
|
||||
import { ConfigSchema } from '.';
|
||||
import { ObservabilityPluginSetup } from '../../observability/public';
|
||||
import {
|
||||
FetchDataParams,
|
||||
ObservabilityPluginSetup,
|
||||
} from '../../observability/public';
|
||||
import {
|
||||
AppMountParameters,
|
||||
CoreSetup,
|
||||
|
@ -33,15 +36,7 @@ import {
|
|||
} from '../../triggers_actions_ui/public';
|
||||
import { AlertType } from '../common/alert_types';
|
||||
import { featureCatalogueEntry } from './featureCatalogueEntry';
|
||||
import { createCallApmApi } from './services/rest/createCallApmApi';
|
||||
import { setHelpExtension } from './setHelpExtension';
|
||||
import { toggleAppLinkInNav } from './toggleAppLinkInNav';
|
||||
import { setReadonlyBadge } from './updateBadge';
|
||||
import { createStaticIndexPattern } from './services/rest/index_pattern';
|
||||
import {
|
||||
fetchOverviewPageData,
|
||||
hasData,
|
||||
} from './services/rest/apm_overview_fetchers';
|
||||
|
||||
export type ApmPluginSetup = void;
|
||||
export type ApmPluginStart = void;
|
||||
|
@ -71,7 +66,6 @@ export class ApmPlugin implements Plugin<ApmPluginSetup, ApmPluginStart> {
|
|||
this.initializerContext = initializerContext;
|
||||
}
|
||||
public setup(core: CoreSetup, plugins: ApmPluginSetupDeps) {
|
||||
createCallApmApi(core.http);
|
||||
const config = this.initializerContext.config.get();
|
||||
const pluginSetupDeps = plugins;
|
||||
|
||||
|
@ -79,10 +73,27 @@ export class ApmPlugin implements Plugin<ApmPluginSetup, ApmPluginStart> {
|
|||
pluginSetupDeps.home.featureCatalogue.register(featureCatalogueEntry);
|
||||
|
||||
if (plugins.observability) {
|
||||
const getApmDataHelper = async () => {
|
||||
const {
|
||||
fetchOverviewPageData,
|
||||
hasData,
|
||||
createCallApmApi,
|
||||
} = await import('./services/rest/apm_overview_fetchers');
|
||||
// have to do this here as well in case app isn't mounted yet
|
||||
createCallApmApi(core.http);
|
||||
|
||||
return { fetchOverviewPageData, hasData };
|
||||
};
|
||||
plugins.observability.dashboard.register({
|
||||
appName: 'apm',
|
||||
fetchData: fetchOverviewPageData,
|
||||
hasData,
|
||||
hasData: async () => {
|
||||
const dataHelper = await getApmDataHelper();
|
||||
return await dataHelper.hasData();
|
||||
},
|
||||
fetchData: async (params: FetchDataParams) => {
|
||||
const dataHelper = await getApmDataHelper();
|
||||
return await dataHelper.fetchOverviewPageData(params);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -96,20 +107,28 @@ export class ApmPlugin implements Plugin<ApmPluginSetup, ApmPluginStart> {
|
|||
category: DEFAULT_APP_CATEGORIES.observability,
|
||||
|
||||
async mount(params: AppMountParameters<unknown>) {
|
||||
// Load application bundle
|
||||
const { renderApp } = await import('./application');
|
||||
// Get start services
|
||||
const [coreStart] = await core.getStartServices();
|
||||
// Load application bundle and Get start services
|
||||
const [{ renderApp }, [coreStart]] = await Promise.all([
|
||||
import('./application'),
|
||||
core.getStartServices(),
|
||||
]);
|
||||
|
||||
// render APM feedback link in global help menu
|
||||
setHelpExtension(coreStart);
|
||||
setReadonlyBadge(coreStart);
|
||||
return renderApp(coreStart, pluginSetupDeps, params, config);
|
||||
},
|
||||
});
|
||||
|
||||
// Automatically creates static index pattern and stores as saved object
|
||||
createStaticIndexPattern().catch((e) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Error creating static index pattern', e);
|
||||
});
|
||||
core.application.register({
|
||||
id: 'csm',
|
||||
title: 'Client Side Monitoring',
|
||||
order: 8500,
|
||||
category: DEFAULT_APP_CATEGORIES.observability,
|
||||
|
||||
async mount(params: AppMountParameters<unknown>) {
|
||||
// Load application bundle and Get start service
|
||||
const [{ renderApp }, [coreStart]] = await Promise.all([
|
||||
import('./application/csmApp'),
|
||||
core.getStartServices(),
|
||||
]);
|
||||
|
||||
return renderApp(coreStart, pluginSetupDeps, params, config);
|
||||
},
|
||||
|
|
|
@ -11,6 +11,8 @@ import {
|
|||
} from '../../../../observability/public';
|
||||
import { callApmApi } from './createCallApmApi';
|
||||
|
||||
export { createCallApmApi } from './createCallApmApi';
|
||||
|
||||
export const fetchOverviewPageData = async ({
|
||||
absoluteTime,
|
||||
relativeTime,
|
||||
|
|
|
@ -15,7 +15,7 @@ export const APM_FEATURE = {
|
|||
order: 900,
|
||||
icon: 'apmApp',
|
||||
navLinkId: 'apm',
|
||||
app: ['apm', 'kibana'],
|
||||
app: ['apm', 'csm', 'kibana'],
|
||||
catalogue: ['apm'],
|
||||
management: {
|
||||
insightsAndAlerting: ['triggersActions'],
|
||||
|
@ -24,7 +24,7 @@ export const APM_FEATURE = {
|
|||
// see x-pack/plugins/features/common/feature_kibana_privileges.ts
|
||||
privileges: {
|
||||
all: {
|
||||
app: ['apm', 'kibana'],
|
||||
app: ['apm', 'csm', 'kibana'],
|
||||
api: ['apm', 'apm_write'],
|
||||
catalogue: ['apm'],
|
||||
savedObject: {
|
||||
|
@ -40,7 +40,7 @@ export const APM_FEATURE = {
|
|||
ui: ['show', 'save', 'alerting:show', 'alerting:save'],
|
||||
},
|
||||
read: {
|
||||
app: ['apm', 'kibana'],
|
||||
app: ['apm', 'csm', 'kibana'],
|
||||
api: ['apm'],
|
||||
catalogue: ['apm'],
|
||||
savedObject: {
|
||||
|
|
|
@ -4833,7 +4833,6 @@
|
|||
"xpack.apm.header.badge.readOnly.tooltip": "を保存できませんでした",
|
||||
"xpack.apm.helpMenu.upgradeAssistantLink": "アップグレードアシスタント",
|
||||
"xpack.apm.histogram.plot.noDataLabel": "この時間範囲のデータがありません。",
|
||||
"xpack.apm.home.rumOverview.title": "リアルユーザー監視",
|
||||
"xpack.apm.home.serviceMapTabLabel": "サービスマップ",
|
||||
"xpack.apm.home.servicesTabLabel": "サービス",
|
||||
"xpack.apm.home.tracesTabLabel": "トレース",
|
||||
|
|
|
@ -4834,7 +4834,6 @@
|
|||
"xpack.apm.header.badge.readOnly.tooltip": "无法保存",
|
||||
"xpack.apm.helpMenu.upgradeAssistantLink": "升级助手",
|
||||
"xpack.apm.histogram.plot.noDataLabel": "此时间范围内没有数据。",
|
||||
"xpack.apm.home.rumOverview.title": "真实用户监测",
|
||||
"xpack.apm.home.serviceMapTabLabel": "服务地图",
|
||||
"xpack.apm.home.servicesTabLabel": "服务",
|
||||
"xpack.apm.home.tracesTabLabel": "追溯",
|
||||
|
|
|
@ -60,7 +60,12 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
|
|||
|
||||
it('shows apm navlink', async () => {
|
||||
const navLinks = await appsMenu.readLinks();
|
||||
expect(navLinks.map((link) => link.text)).to.eql(['Overview', 'APM', 'Stack Management']);
|
||||
expect(navLinks.map((link) => link.text)).to.eql([
|
||||
'Overview',
|
||||
'APM',
|
||||
'Client Side Monitoring',
|
||||
'Stack Management',
|
||||
]);
|
||||
});
|
||||
|
||||
it('can navigate to APM app', async () => {
|
||||
|
@ -109,7 +114,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
|
|||
|
||||
it('shows apm navlink', async () => {
|
||||
const navLinks = (await appsMenu.readLinks()).map((link) => link.text);
|
||||
expect(navLinks).to.eql(['Overview', 'APM', 'Stack Management']);
|
||||
expect(navLinks).to.eql(['Overview', 'APM', 'Client Side Monitoring', 'Stack Management']);
|
||||
});
|
||||
|
||||
it('can navigate to APM app', async () => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue