[Infra UI] Disable infra logs UI in serverless (#168011)

closes https://github.com/elastic/kibana/issues/166977
## Summary

This PR creates a feature flag to disable logs UI features in
serverless.

_Serverless_

**Frontend routes**

<img width="1466" alt="image"
src="a856055b-f78b-4d47-b27e-678e19bdfae4">


`/logs/stream`
<img width="1714" alt="image"
src="83d50be2-ed3a-4441-b31c-1afe6f8fd0b9">

`/logs/log-categories`
<img width="1714" alt="image"
src="85cd369d-55b2-46a2-a61a-135c5f18e299">

`/logs/anomalies`
<img width="1714" alt="image"
src="d68e6f91-fe29-483f-931d-d05f4303effa">

**Server routes**

These will return 404

```
POST kbn://api/infra/log_analysis/results/log_entry_anomalies_datasets

POST kbn://api/infra/log_analysis/results/log_entry_anomalies

POST kbn://api/infra/log_analysis/results/log_entry_categories

POST kbn://api/infra/log_analysis/results/latest_log_entry_category_datasets_stats

POST kbn://api/infra/log_analysis/results/log_entry_category_datasets

POST kbn://api/infra/log_analysis/results/log_entry_category_examples

POST kbn://api/infra/log_analysis/results/log_entry_examples

POST kbn://api/infra/log_analysis/results/log_entry_datasets

POST kbn://api/infra/log_analysis/results/log_entry_rate_indices

POST kbn://api/infra/log_alerts/chart_preview_data                            
```


_Stateful_

<img width="1716" alt="image"
src="4406434f-78e4-437f-b3b5-1b03dc23f3c0">

**Server routes**

These will return 400 - currently there is no way to pass `version` via
dev tools

```
POST kbn://api/infra/log_analysis/results/log_entry_anomalies_datasets

POST kbn://api/infra/log_analysis/results/log_entry_anomalies

POST kbn://api/infra/log_analysis/results/log_entry_categories

POST kbn://api/infra/log_analysis/results/latest_log_entry_category_datasets_stats

POST kbn://api/infra/log_analysis/results/log_entry_category_datasets

POST kbn://api/infra/log_analysis/results/log_entry_category_examples

POST kbn://api/infra/log_analysis/results/log_entry_examples

POST kbn://api/infra/log_analysis/results/log_entry_datasets

POST kbn://api/infra/log_analysis/results/log_entry_rate_indices

POST kbn://api/infra/log_alerts/chart_preview_data                            
```

### How to test

### How to test

- Start a local es instance: `yarn es serverless --kill --clean
--license trial --ssl`
- Enable `infra` in the `serverless.oblt.dev.yml` file:
  - `xpack.infra.enabled: true`
- Start a local kibana instance: `yarn serverless-oblt --ssl` 
- Verify the items listed above both on serverless and stateful
This commit is contained in:
Carlos Crespo 2023-10-06 10:15:43 +02:00 committed by GitHub
parent 5d660f900f
commit 2f8ce938be
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 149 additions and 93 deletions

View file

@ -267,16 +267,21 @@ export default function ({ getService }: PluginFunctionalProviderContext) {
'xpack.index_management.enableLegacyTemplates (any)',
'xpack.index_management.enableIndexStats (any)',
'xpack.infra.sources.default.fields.message (array)',
/**
* xpack.infra.featureFlags.metricsExplorerEnabled is conditional based on traditional/serverless offering
* and will resolve to (boolean)
*/
'xpack.infra.featureFlags.metricsExplorerEnabled (any)',
/**
* xpack.infra.featureFlags.customThresholdAlertsEnabled is conditional based on traditional/serverless offering
* and will resolve to (boolean)
*/
'xpack.infra.featureFlags.customThresholdAlertsEnabled (any)',
/**
* xpack.infra.featureFlags.logsUIEnabled is conditional based on traditional/serverless offering
* and will resolve to (boolean)
*/
'xpack.infra.featureFlags.logsUIEnabled (any)',
/**
* xpack.infra.featureFlags.metricsExplorerEnabled is conditional based on traditional/serverless offering
* and will resolve to (boolean)
*/
'xpack.infra.featureFlags.metricsExplorerEnabled (any)',
/**
* xpack.infra.featureFlags.osqueryEnabled is conditional based on traditional/serverless offering
* and will resolve to (boolean)

View file

@ -26,8 +26,9 @@ export interface InfraConfig {
};
};
featureFlags: {
metricsExplorerEnabled: boolean;
customThresholdAlertsEnabled: boolean;
logsUIEnabled: boolean;
metricsExplorerEnabled: boolean;
osqueryEnabled: boolean;
};
}

View file

@ -20,9 +20,10 @@ describe('usePluginConfig()', () => {
it('returns the plugin config what was set through the provider', () => {
const config: Partial<InfraConfig> = {
featureFlags: {
customThresholdAlertsEnabled: true,
logsUIEnabled: false,
metricsExplorerEnabled: false,
osqueryEnabled: false,
customThresholdAlertsEnabled: true,
},
};
const { result } = renderHook(() => usePluginConfig(), {

View file

@ -85,18 +85,21 @@ export class Plugin implements InfraClientPluginClass {
pluginsSetup.observability.observabilityRuleTypeRegistry.register(
createMetricThresholdRuleType()
);
pluginsSetup.observability.dashboard.register({
appName: 'infra_logs',
hasData: getLogsHasDataFetcher(core.getStartServices),
fetchData: getLogsOverviewDataFetcher(core.getStartServices),
});
if (this.config.featureFlags.logsUIEnabled) {
// fetchData `appLink` redirects to logs/stream
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,
});
@ -107,13 +110,6 @@ export class Plugin implements InfraClientPluginClass {
]);
/** !! 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(
@ -136,9 +132,13 @@ export class Plugin implements InfraClientPluginClass {
path: '/',
isBetaFeature: true,
},
{ label: 'Stream', app: 'logs', path: '/stream' },
{ label: 'Anomalies', app: 'logs', path: '/anomalies' },
{ label: 'Categories', app: 'logs', path: '/log-categories' },
...(this.config.featureFlags.logsUIEnabled
? [
{ label: 'Stream', app: 'logs', path: '/stream' },
{ label: 'Anomalies', app: 'logs', path: '/anomalies' },
{ label: 'Categories', app: 'logs', path: '/log-categories' },
]
: []),
],
},
]
@ -148,7 +148,13 @@ export class Plugin implements InfraClientPluginClass {
{
label: 'Infrastructure',
sortKey: 300,
entries: infraEntries,
entries: [
{ 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' },
],
},
]
: []),
@ -172,54 +178,56 @@ export class Plugin implements InfraClientPluginClass {
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();
if (this.config.featureFlags.logsUIEnabled) {
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);
},
});
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: AppDeepLink[] = [
@ -285,14 +293,6 @@ export class Plugin implements InfraClientPluginClass {
},
});
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({
@ -307,6 +307,14 @@ export class Plugin implements InfraClientPluginClass {
},
});
startDep$AndHostViewFlag$.subscribe(
([_startServices]: [[CoreStart, InfraClientStartDeps, InfraClientStartExports], boolean]) => {
this.appUpdater$.next(() => ({
deepLinks: infraDeepLinks,
}));
}
);
// Setup telemetry events
this.telemetry.setup({ analytics: core.analytics });

View file

@ -1899,8 +1899,9 @@ const createMockStaticConfiguration = (sources: any): InfraConfig => ({
compositeSize: 2000,
},
featureFlags: {
metricsExplorerEnabled: true,
customThresholdAlertsEnabled: false,
logsUIEnabled: true,
metricsExplorerEnabled: true,
osqueryEnabled: true,
},
enabled: true,

View file

@ -126,8 +126,9 @@ const createMockStaticConfiguration = (sources: any): InfraConfig => ({
compositeSize: 2000,
},
featureFlags: {
metricsExplorerEnabled: true,
customThresholdAlertsEnabled: false,
logsUIEnabled: true,
metricsExplorerEnabled: true,
osqueryEnabled: true,
},
sources,

View file

@ -81,14 +81,18 @@ export const config: PluginConfigDescriptor<InfraConfig> = {
})
),
featureFlags: schema.object({
metricsExplorerEnabled: offeringBasedSchema({
traditional: schema.boolean({ defaultValue: true }),
serverless: schema.boolean({ defaultValue: false }),
}),
customThresholdAlertsEnabled: offeringBasedSchema({
traditional: schema.boolean({ defaultValue: false }),
serverless: schema.boolean({ defaultValue: true }),
}),
logsUIEnabled: offeringBasedSchema({
traditional: schema.boolean({ defaultValue: true }),
serverless: schema.boolean({ defaultValue: false }),
}),
metricsExplorerEnabled: offeringBasedSchema({
traditional: schema.boolean({ defaultValue: true }),
serverless: schema.boolean({ defaultValue: false }),
}),
osqueryEnabled: offeringBasedSchema({
traditional: schema.boolean({ defaultValue: true }),
serverless: schema.boolean({ defaultValue: false }),
@ -222,14 +226,16 @@ export class InfraServerPlugin
countLogs: () => UsageCollector.countLogs(),
});
plugins.home.sampleData.addAppLinksToSampleDataset('logs', [
{
sampleObject: null, // indicates that there is no sample object associated with this app link's path
getPath: () => `/app/logs`,
label: logsSampleDataLinkLabel,
icon: 'logsApp',
},
]);
if (this.config.featureFlags.logsUIEnabled) {
plugins.home.sampleData.addAppLinksToSampleDataset('logs', [
{
sampleObject: null, // indicates that there is no sample object associated with this app link's path
getPath: () => `/app/logs`,
label: logsSampleDataLinkLabel,
icon: 'logsApp',
},
]);
}
initInfraServer(this.libs);
registerRuleTypes(plugins.alerting, this.libs, plugins.ml);

View file

@ -16,6 +16,11 @@ export const initGetLogAlertsChartPreviewDataRoute = ({
framework,
getStartServices,
}: Pick<InfraBackendLibs, 'framework' | 'getStartServices'>) => {
// Replace with the corresponding logs alert rule feature flag
if (!framework.config.featureFlags.logsUIEnabled) {
return;
}
framework
.registerVersionedRoute({
access: 'internal',

View file

@ -16,6 +16,9 @@ import { getLogEntryAnomalies } from '../../../lib/log_analysis';
import { isMlPrivilegesError } from '../../../lib/log_analysis/errors';
export const initGetLogEntryAnomaliesRoute = ({ framework }: InfraBackendLibs) => {
if (!framework.config.featureFlags.logsUIEnabled) {
return;
}
framework
.registerVersionedRoute({
access: 'internal',

View file

@ -15,6 +15,9 @@ import { assertHasInfraMlPlugins } from '../../../utils/request_context';
import { isMlPrivilegesError } from '../../../lib/log_analysis/errors';
export const initGetLogEntryAnomaliesDatasetsRoute = ({ framework }: InfraBackendLibs) => {
if (!framework.config.featureFlags.logsUIEnabled) {
return;
}
framework
.registerVersionedRoute({
access: 'internal',

View file

@ -15,6 +15,9 @@ import { assertHasInfraMlPlugins } from '../../../utils/request_context';
import { isMlPrivilegesError } from '../../../lib/log_analysis/errors';
export const initGetLogEntryCategoriesRoute = ({ framework }: InfraBackendLibs) => {
if (!framework.config.featureFlags.logsUIEnabled) {
return;
}
framework
.registerVersionedRoute({
access: 'internal',

View file

@ -15,6 +15,9 @@ import { assertHasInfraMlPlugins } from '../../../utils/request_context';
import { isMlPrivilegesError } from '../../../lib/log_analysis/errors';
export const initGetLogEntryCategoryDatasetsRoute = ({ framework }: InfraBackendLibs) => {
if (!framework.config.featureFlags.logsUIEnabled) {
return;
}
framework
.registerVersionedRoute({
access: 'internal',

View file

@ -15,6 +15,9 @@ import { isMlPrivilegesError } from '../../../lib/log_analysis/errors';
import { assertHasInfraMlPlugins } from '../../../utils/request_context';
export const initGetLogEntryCategoryDatasetsStatsRoute = ({ framework }: InfraBackendLibs) => {
if (!framework.config.featureFlags.logsUIEnabled) {
return;
}
framework
.registerVersionedRoute({
access: 'internal',

View file

@ -18,6 +18,9 @@ export const initGetLogEntryCategoryExamplesRoute = ({
framework,
getStartServices,
}: Pick<InfraBackendLibs, 'framework' | 'getStartServices'>) => {
if (!framework.config.featureFlags.logsUIEnabled) {
return;
}
framework
.registerVersionedRoute({
access: 'internal',

View file

@ -18,6 +18,9 @@ export const initGetLogEntryExamplesRoute = ({
framework,
getStartServices,
}: Pick<InfraBackendLibs, 'framework' | 'getStartServices'>) => {
if (!framework.config.featureFlags.logsUIEnabled) {
return;
}
framework
.registerVersionedRoute({
access: 'internal',

View file

@ -17,6 +17,9 @@ export const initValidateLogAnalysisDatasetsRoute = ({
framework,
logEntries,
}: InfraBackendLibs) => {
if (!framework.config.featureFlags.logsUIEnabled) {
return;
}
framework
.registerVersionedRoute({
access: 'internal',

View file

@ -19,6 +19,10 @@ import { logAnalysisValidationV1 } from '../../../../common/http_api';
const escapeHatch = schema.object({}, { unknowns: 'allow' });
export const initValidateLogAnalysisIndicesRoute = ({ framework }: InfraBackendLibs) => {
if (!framework.config.featureFlags.logsUIEnabled) {
return;
}
framework
.registerVersionedRoute({
access: 'internal',