mirror of
https://github.com/elastic/kibana.git
synced 2025-06-27 10:40:07 -04:00
Closes #163282 ## Summary This PR: * Adds a `featureFlags.metricsExplorerEnabled` property to the Infra plugin config to enable and disable Metrics Explorer depending on the offering type * Prevents `MetricsExplorerViewsService` initialization for serveless based on the feature flag * Prevents creating Metrics Explorer frontend routes when in serverless * Prevents registration of the MetricsExplorerViews saved object when in serverless * Prevents initialization of the `metrics_explorer_views` API routes when in serverless **Trying to access Metrics Explorer in serverless** <img width="1829" alt="CleanShot 2023-09-22 at 12 59 35@2x" src="2b039925
-0f0b-4c07-be29-bbe910de7a34"> **Trying to access views API** <img width="1829" alt="CleanShot 2023-09-22 at 13 00 00@2x" src="15269ec2
-becd-4ee3-9b5e-d916df28a7b8"> **`infra/metrics_explorer` API still works as per ticket requirements** <img width="1829" alt="CleanShot 2023-09-22 at 13 00 06@2x" src="fb23f912
-c6fd-46c8-9084-c17c51e5b064"> ## How to test * Checkout locally * Enable Infra in `serverless.oblt.yml`: `xpack.infra.enabled: true` * Run Kibana in serverless mode * Try accessing `/app/metrics/explorer` route and make sure it's not available * Make sure other Infra routes (`/app/metrics/inventory` and `/app/metrics/hosts`) still load as expected * In Kibana dev console make sure you get 404 for `GET kbn:/api/infra/metrics_explorer_views` * Also check that you don't see `metrics-explorer-view` saved object in the response for `GET kbn:/api/kibana/management/saved_objects/_allowed_types` * Run Kibana in non-serverless mode and make sure Metrics Explorer is accessible and works as usual --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
345 lines
12 KiB
TypeScript
345 lines
12 KiB
TypeScript
/*
|
|
* 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 {
|
|
AppMountParameters,
|
|
AppUpdater,
|
|
CoreStart,
|
|
DEFAULT_APP_CATEGORIES,
|
|
PluginInitializerContext,
|
|
} from '@kbn/core/public';
|
|
import { i18n } from '@kbn/i18n';
|
|
import { enableInfrastructureHostsView } from '@kbn/observability-plugin/public';
|
|
import { ObservabilityTriggerId } from '@kbn/observability-shared-plugin/common';
|
|
import { BehaviorSubject, combineLatest, from } from 'rxjs';
|
|
import { map } from 'rxjs/operators';
|
|
import { InfraPublicConfig } from '../common/plugin_config_types';
|
|
import { createInventoryMetricRuleType } from './alerting/inventory';
|
|
import { createLogThresholdRuleType } from './alerting/log_threshold';
|
|
import { createMetricThresholdRuleType } from './alerting/metric_threshold';
|
|
import { createLazyContainerMetricsTable } from './components/infrastructure_node_metrics_tables/container/create_lazy_container_metrics_table';
|
|
import { createLazyHostMetricsTable } from './components/infrastructure_node_metrics_tables/host/create_lazy_host_metrics_table';
|
|
import { createLazyPodMetricsTable } from './components/infrastructure_node_metrics_tables/pod/create_lazy_pod_metrics_table';
|
|
import { LOG_STREAM_EMBEDDABLE } from './components/log_stream/log_stream_embeddable';
|
|
import { LogStreamEmbeddableFactoryDefinition } from './components/log_stream/log_stream_embeddable_factory';
|
|
import {
|
|
InfraLocators,
|
|
LogsLocatorDefinition,
|
|
NodeLogsLocatorDefinition,
|
|
} from '../common/locators';
|
|
import { createMetricsFetchData, createMetricsHasData } from './metrics_overview_fetchers';
|
|
import { registerFeatures } from './register_feature';
|
|
import { InventoryViewsService } from './services/inventory_views';
|
|
import { MetricsExplorerViewsService } from './services/metrics_explorer_views';
|
|
import { TelemetryService } from './services/telemetry';
|
|
import {
|
|
InfraClientCoreSetup,
|
|
InfraClientCoreStart,
|
|
InfraClientPluginClass,
|
|
InfraClientSetupDeps,
|
|
InfraClientStartDeps,
|
|
InfraClientStartExports,
|
|
InfraClientStartServices,
|
|
} from './types';
|
|
import { getLogsHasDataFetcher, getLogsOverviewDataFetcher } from './utils/logs_overview_fetchers';
|
|
|
|
export class Plugin implements InfraClientPluginClass {
|
|
public config: InfraPublicConfig;
|
|
private inventoryViews: InventoryViewsService;
|
|
private metricsExplorerViews?: MetricsExplorerViewsService;
|
|
private telemetry: TelemetryService;
|
|
private locators?: InfraLocators;
|
|
private kibanaVersion: string;
|
|
private readonly appUpdater$ = new BehaviorSubject<AppUpdater>(() => ({}));
|
|
|
|
constructor(context: PluginInitializerContext<InfraPublicConfig>) {
|
|
this.config = context.config.get();
|
|
|
|
this.inventoryViews = new InventoryViewsService();
|
|
this.metricsExplorerViews = this.config.featureFlags.metricsExplorerEnabled
|
|
? new MetricsExplorerViewsService()
|
|
: undefined;
|
|
this.telemetry = new TelemetryService();
|
|
this.kibanaVersion = context.env.packageInfo.version;
|
|
}
|
|
|
|
setup(core: InfraClientCoreSetup, pluginsSetup: InfraClientSetupDeps) {
|
|
if (pluginsSetup.home) {
|
|
registerFeatures(pluginsSetup.home);
|
|
}
|
|
|
|
pluginsSetup.uiActions.registerTrigger({
|
|
id: ObservabilityTriggerId.LogEntryContextMenu,
|
|
});
|
|
|
|
pluginsSetup.observability.observabilityRuleTypeRegistry.register(
|
|
createInventoryMetricRuleType()
|
|
);
|
|
|
|
pluginsSetup.observability.observabilityRuleTypeRegistry.register(
|
|
createMetricThresholdRuleType()
|
|
);
|
|
pluginsSetup.observability.dashboard.register({
|
|
appName: 'infra_logs',
|
|
hasData: getLogsHasDataFetcher(core.getStartServices),
|
|
fetchData: getLogsOverviewDataFetcher(core.getStartServices),
|
|
});
|
|
|
|
pluginsSetup.observability.dashboard.register({
|
|
appName: 'infra_metrics',
|
|
hasData: createMetricsHasData(core.getStartServices),
|
|
fetchData: createMetricsFetchData(core.getStartServices),
|
|
});
|
|
|
|
pluginsSetup.logsShared.logViews.setLogViewsStaticConfig({
|
|
messageFields: this.config.sources?.default?.fields?.message,
|
|
});
|
|
|
|
const startDep$AndHostViewFlag$ = combineLatest([
|
|
from(core.getStartServices()),
|
|
core.uiSettings.get$<boolean>(enableInfrastructureHostsView),
|
|
]);
|
|
|
|
/** !! Need to be kept in sync with the deepLinks in x-pack/plugins/infra/public/plugin.ts */
|
|
const infraEntries = [
|
|
{ label: 'Inventory', app: 'metrics', path: '/inventory' },
|
|
...(this.config.featureFlags.metricsExplorerEnabled
|
|
? [{ label: 'Metrics Explorer', app: 'metrics', path: '/explorer' }]
|
|
: []),
|
|
{ label: 'Hosts', isBetaFeature: true, app: 'metrics', path: '/hosts' },
|
|
];
|
|
pluginsSetup.observabilityShared.navigation.registerSections(
|
|
startDep$AndHostViewFlag$.pipe(
|
|
map(
|
|
([
|
|
[
|
|
{
|
|
application: { capabilities },
|
|
},
|
|
],
|
|
]) => [
|
|
...(capabilities.logs.show
|
|
? [
|
|
{
|
|
label: 'Logs',
|
|
sortKey: 200,
|
|
entries: [
|
|
{
|
|
label: 'Explorer',
|
|
app: 'observability-log-explorer',
|
|
path: '/',
|
|
isBetaFeature: true,
|
|
},
|
|
{ label: 'Stream', app: 'logs', path: '/stream' },
|
|
{ label: 'Anomalies', app: 'logs', path: '/anomalies' },
|
|
{ label: 'Categories', app: 'logs', path: '/log-categories' },
|
|
],
|
|
},
|
|
]
|
|
: []),
|
|
...(capabilities.infrastructure.show
|
|
? [
|
|
{
|
|
label: 'Infrastructure',
|
|
sortKey: 300,
|
|
entries: infraEntries,
|
|
},
|
|
]
|
|
: []),
|
|
]
|
|
)
|
|
)
|
|
);
|
|
|
|
pluginsSetup.embeddable.registerEmbeddableFactory(
|
|
LOG_STREAM_EMBEDDABLE,
|
|
new LogStreamEmbeddableFactoryDefinition(core.getStartServices)
|
|
);
|
|
|
|
// Register Locators
|
|
const logsLocator = pluginsSetup.share.url.locators.create(new LogsLocatorDefinition({ core }));
|
|
const nodeLogsLocator = pluginsSetup.share.url.locators.create(
|
|
new NodeLogsLocatorDefinition({ core })
|
|
);
|
|
|
|
pluginsSetup.observability.observabilityRuleTypeRegistry.register(
|
|
createLogThresholdRuleType(core, logsLocator)
|
|
);
|
|
|
|
core.application.register({
|
|
id: 'logs',
|
|
title: i18n.translate('xpack.infra.logs.pluginTitle', {
|
|
defaultMessage: 'Logs',
|
|
}),
|
|
euiIconType: 'logoObservability',
|
|
order: 8100,
|
|
appRoute: '/app/logs',
|
|
// !! Need to be kept in sync with the routes in x-pack/plugins/infra/public/pages/logs/page_content.tsx
|
|
deepLinks: [
|
|
{
|
|
id: 'stream',
|
|
title: i18n.translate('xpack.infra.logs.index.streamTabTitle', {
|
|
defaultMessage: 'Stream',
|
|
}),
|
|
path: '/stream',
|
|
},
|
|
{
|
|
id: 'anomalies',
|
|
title: i18n.translate('xpack.infra.logs.index.anomaliesTabTitle', {
|
|
defaultMessage: 'Anomalies',
|
|
}),
|
|
path: '/anomalies',
|
|
},
|
|
{
|
|
id: 'log-categories',
|
|
title: i18n.translate('xpack.infra.logs.index.logCategoriesBetaBadgeTitle', {
|
|
defaultMessage: 'Categories',
|
|
}),
|
|
path: '/log-categories',
|
|
},
|
|
{
|
|
id: 'settings',
|
|
title: i18n.translate('xpack.infra.logs.index.settingsTabTitle', {
|
|
defaultMessage: 'Settings',
|
|
}),
|
|
path: '/settings',
|
|
},
|
|
],
|
|
category: DEFAULT_APP_CATEGORIES.observability,
|
|
mount: async (params: AppMountParameters) => {
|
|
// mount callback should not use setup dependencies, get start dependencies instead
|
|
const [coreStart, plugins, pluginStart] = await core.getStartServices();
|
|
|
|
const { renderApp } = await import('./apps/logs_app');
|
|
return renderApp(coreStart, plugins, pluginStart, params);
|
|
},
|
|
});
|
|
|
|
// !! Need to be kept in sync with the routes in x-pack/plugins/infra/public/pages/metrics/index.tsx
|
|
const infraDeepLinks = [
|
|
{
|
|
id: 'inventory',
|
|
title: i18n.translate('xpack.infra.homePage.inventoryTabTitle', {
|
|
defaultMessage: 'Inventory',
|
|
}),
|
|
path: '/inventory',
|
|
},
|
|
{
|
|
id: 'metrics-hosts',
|
|
title: i18n.translate('xpack.infra.homePage.metricsHostsTabTitle', {
|
|
defaultMessage: 'Hosts',
|
|
}),
|
|
path: '/hosts',
|
|
},
|
|
...(this.config.featureFlags.metricsExplorerEnabled
|
|
? [
|
|
{
|
|
id: 'metrics-explorer',
|
|
title: i18n.translate('xpack.infra.homePage.metricsExplorerTabTitle', {
|
|
defaultMessage: 'Metrics Explorer',
|
|
}),
|
|
path: '/explorer',
|
|
},
|
|
]
|
|
: []),
|
|
{
|
|
id: 'settings',
|
|
title: i18n.translate('xpack.infra.homePage.settingsTabTitle', {
|
|
defaultMessage: 'Settings',
|
|
}),
|
|
path: '/settings',
|
|
},
|
|
];
|
|
core.application.register({
|
|
id: 'metrics',
|
|
title: i18n.translate('xpack.infra.metrics.pluginTitle', {
|
|
defaultMessage: 'Infrastructure',
|
|
}),
|
|
euiIconType: 'logoObservability',
|
|
order: 8200,
|
|
appRoute: '/app/metrics',
|
|
category: DEFAULT_APP_CATEGORIES.observability,
|
|
updater$: this.appUpdater$,
|
|
deepLinks: infraDeepLinks,
|
|
mount: async (params: AppMountParameters) => {
|
|
// mount callback should not use setup dependencies, get start dependencies instead
|
|
const [coreStart, plugins, pluginStart] = await core.getStartServices();
|
|
const { renderApp } = await import('./apps/metrics_app');
|
|
|
|
return renderApp(
|
|
coreStart,
|
|
{ ...plugins, kibanaVersion: this.kibanaVersion },
|
|
pluginStart,
|
|
this.config,
|
|
params
|
|
);
|
|
},
|
|
});
|
|
|
|
startDep$AndHostViewFlag$.subscribe(
|
|
([_startServices]: [[CoreStart, InfraClientStartDeps, InfraClientStartExports], boolean]) => {
|
|
this.appUpdater$.next(() => ({
|
|
deepLinks: infraDeepLinks,
|
|
}));
|
|
}
|
|
);
|
|
|
|
/* This exists purely to facilitate URL redirects from the old App ID ("infra"),
|
|
to our new App IDs ("metrics" and "logs"). With version 8.0.0 we can remove this. */
|
|
core.application.register({
|
|
id: 'infra',
|
|
appRoute: '/app/infra',
|
|
title: 'infra',
|
|
navLinkStatus: 3,
|
|
mount: async (params: AppMountParameters) => {
|
|
const { renderApp } = await import('./apps/legacy_app');
|
|
|
|
return renderApp(params);
|
|
},
|
|
});
|
|
|
|
// Setup telemetry events
|
|
this.telemetry.setup({ analytics: core.analytics });
|
|
|
|
this.locators = {
|
|
logsLocator,
|
|
nodeLogsLocator,
|
|
};
|
|
|
|
return {
|
|
locators: this.locators,
|
|
};
|
|
}
|
|
|
|
start(core: InfraClientCoreStart, plugins: InfraClientStartDeps) {
|
|
const getStartServices = (): InfraClientStartServices => [core, plugins, startContract];
|
|
|
|
const inventoryViews = this.inventoryViews.start({
|
|
http: core.http,
|
|
});
|
|
|
|
const metricsExplorerViews = this.metricsExplorerViews?.start({
|
|
http: core.http,
|
|
});
|
|
|
|
const telemetry = this.telemetry.start();
|
|
|
|
const startContract: InfraClientStartExports = {
|
|
inventoryViews,
|
|
metricsExplorerViews,
|
|
telemetry,
|
|
locators: this.locators!,
|
|
ContainerMetricsTable: createLazyContainerMetricsTable(getStartServices),
|
|
HostMetricsTable: createLazyHostMetricsTable(getStartServices),
|
|
PodMetricsTable: createLazyPodMetricsTable(getStartServices),
|
|
};
|
|
|
|
return startContract;
|
|
}
|
|
|
|
stop() {}
|
|
}
|