Remove alerting feature flag from advanced settings (#97265)

* Remove alerting feature flag from advanced settings

Make it so the alerting UI in Observability can only be turned on and off in kibana.yml with `xpack.observability.enableAlertingExperience`.

We no longer:

* Allow turning this on and off for the current space in the advanced settings in Kibana
* Allow turning this on on cloud
* Send telemetry on whether or not the flag is enabled

Add some docs in READMEs as well.
This commit is contained in:
Nathan L Smith 2021-04-19 22:09:51 -05:00 committed by GitHub
parent 1fc1bcdb08
commit 042fa1a2ce
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 84 additions and 46 deletions

View file

@ -229,6 +229,7 @@ kibana_vars=(
xpack.maps.enabled xpack.maps.enabled
xpack.maps.showMapVisualizationTypes xpack.maps.showMapVisualizationTypes
xpack.ml.enabled xpack.ml.enabled
xpack.observability.unsafe.alertingExperience.enabled
xpack.reporting.capture.browser.autoDownload xpack.reporting.capture.browser.autoDownload
xpack.reporting.capture.browser.chromium.disableSandbox xpack.reporting.capture.browser.chromium.disableSandbox
xpack.reporting.capture.browser.chromium.inspect xpack.reporting.capture.browser.chromium.inspect
@ -273,6 +274,7 @@ kibana_vars=(
xpack.reporting.queue.timeout xpack.reporting.queue.timeout
xpack.reporting.roles.allow xpack.reporting.roles.allow
xpack.rollup.enabled xpack.rollup.enabled
xpack.ruleRegistry.unsafe.write.enabled
xpack.searchprofiler.enabled xpack.searchprofiler.enabled
xpack.security.audit.enabled xpack.security.audit.enabled
xpack.security.audit.appender.type xpack.security.audit.appender.type

View file

@ -432,10 +432,6 @@ export const stackManagementSchema: MakeSchemaFrom<UsageStats> = {
type: 'text', type: 'text',
_meta: { description: 'Non-default value of setting.' }, _meta: { description: 'Non-default value of setting.' },
}, },
'observability:enableAlertingExperience': {
type: 'boolean',
_meta: { description: 'Non-default value of setting.' },
},
'labs:presentation:unifiedToolbar': { 'labs:presentation:unifiedToolbar': {
type: 'boolean', type: 'boolean',
_meta: { description: 'Non-default value of setting.' }, _meta: { description: 'Non-default value of setting.' },

View file

@ -32,7 +32,6 @@ export interface UsageStats {
'securitySolution:rulesTableRefresh': string; 'securitySolution:rulesTableRefresh': string;
'apm:enableSignificantTerms': boolean; 'apm:enableSignificantTerms': boolean;
'apm:enableServiceOverview': boolean; 'apm:enableServiceOverview': boolean;
'observability:enableAlertingExperience': boolean;
'observability:enableInspectEsQueries': boolean; 'observability:enableInspectEsQueries': boolean;
'visualize:enableLabs': boolean; 'visualize:enableLabs': boolean;
'visualization:heatmap:maxBuckets': number; 'visualization:heatmap:maxBuckets': number;

View file

@ -8200,12 +8200,6 @@
"description": "Non-default value of setting." "description": "Non-default value of setting."
} }
}, },
"observability:enableAlertingExperience": {
"type": "boolean",
"_meta": {
"description": "Non-default value of setting."
}
},
"labs:presentation:unifiedToolbar": { "labs:presentation:unifiedToolbar": {
"type": "boolean", "type": "boolean",
"_meta": { "_meta": {

View file

@ -2,6 +2,28 @@
This plugin provides shared components and services for use across observability solutions, as well as the observability landing page UI. This plugin provides shared components and services for use across observability solutions, as well as the observability landing page UI.
## Rules, Alerts, and Cases
The Observability plugin contains experimental support for improved alerting and
case management.
If you have:
```yaml
xpack.observability.unsafe.alertingExperience.enabled: true
```
In your Kibana configuration, the Alerts and Cases pages will be available.
This will only enable the UI for these pages. In order to have alert data indexed
you'll need to enable writing in the [Rule Registry plugin](../rule_registry/README.md):
```yaml
xpack.ruleRegistry.unsafe.write.enabled: true
```
When both of the these are set to `true`, your alerts should show on the alerts page.
## Unit testing ## Unit testing
Note: Run the following commands from `kibana/x-pack/plugins/observability`. Note: Run the following commands from `kibana/x-pack/plugins/observability`.

View file

@ -5,5 +5,4 @@
* 2.0. * 2.0.
*/ */
export const enableAlertingExperience = 'observability:enableAlertingExperience';
export const enableInspectEsQueries = 'observability:enableInspectEsQueries'; export const enableInspectEsQueries = 'observability:enableInspectEsQueries';

View file

@ -45,6 +45,7 @@ describe('renderApp', () => {
uiSettings: { get: () => false }, uiSettings: { get: () => false },
http: { basePath: { prepend: (path: string) => path } }, http: { basePath: { prepend: (path: string) => path } },
} as unknown) as CoreStart; } as unknown) as CoreStart;
const config = { unsafe: { alertingExperience: { enabled: true } } };
const params = ({ const params = ({
element: window.document.createElement('div'), element: window.document.createElement('div'),
history: createMemoryHistory(), history: createMemoryHistory(),
@ -53,6 +54,7 @@ describe('renderApp', () => {
expect(() => { expect(() => {
const unmount = renderApp({ const unmount = renderApp({
config,
core, core,
plugins, plugins,
appMountParameters: params, appMountParameters: params,

View file

@ -22,6 +22,7 @@ import { ObservabilityPublicPluginsStart, ObservabilityRuleRegistry } from '../p
import { HasDataContextProvider } from '../context/has_data_context'; import { HasDataContextProvider } from '../context/has_data_context';
import { Breadcrumbs, routes } from '../routes'; import { Breadcrumbs, routes } from '../routes';
import { Storage } from '../../../../../src/plugins/kibana_utils/public'; import { Storage } from '../../../../../src/plugins/kibana_utils/public';
import { ConfigSchema } from '..';
function getTitleFromBreadCrumbs(breadcrumbs: Breadcrumbs) { function getTitleFromBreadCrumbs(breadcrumbs: Breadcrumbs) {
return breadcrumbs.map(({ text }) => text).reverse(); return breadcrumbs.map(({ text }) => text).reverse();
@ -67,11 +68,13 @@ function App() {
} }
export const renderApp = ({ export const renderApp = ({
config,
core, core,
plugins, plugins,
appMountParameters, appMountParameters,
observabilityRuleRegistry, observabilityRuleRegistry,
}: { }: {
config: ConfigSchema;
core: CoreStart; core: CoreStart;
plugins: ObservabilityPublicPluginsStart; plugins: ObservabilityPublicPluginsStart;
observabilityRuleRegistry: ObservabilityRuleRegistry; observabilityRuleRegistry: ObservabilityRuleRegistry;
@ -91,7 +94,7 @@ export const renderApp = ({
ReactDOM.render( ReactDOM.render(
<KibanaContextProvider services={{ ...core, ...plugins, storage: new Storage(localStorage) }}> <KibanaContextProvider services={{ ...core, ...plugins, storage: new Storage(localStorage) }}>
<PluginContext.Provider <PluginContext.Provider
value={{ appMountParameters, core, plugins, observabilityRuleRegistry }} value={{ appMountParameters, config, core, plugins, observabilityRuleRegistry }}
> >
<Router history={history}> <Router history={history}>
<EuiThemeProvider darkMode={isDarkMode}> <EuiThemeProvider darkMode={isDarkMode}>

View file

@ -21,7 +21,6 @@ import React, { useState } from 'react';
import { EuiSelect } from '@elastic/eui'; import { EuiSelect } from '@elastic/eui';
import { uniqBy } from 'lodash'; import { uniqBy } from 'lodash';
import { Alert } from '../../../../../../alerting/common'; import { Alert } from '../../../../../../alerting/common';
import { enableAlertingExperience } from '../../../../../common/ui_settings_keys';
import { usePluginContext } from '../../../../hooks/use_plugin_context'; import { usePluginContext } from '../../../../hooks/use_plugin_context';
import { SectionContainer } from '..'; import { SectionContainer } from '..';
@ -38,10 +37,9 @@ interface Props {
} }
export function AlertsSection({ alerts }: Props) { export function AlertsSection({ alerts }: Props) {
const { core } = usePluginContext(); const { config, core } = usePluginContext();
const [filter, setFilter] = useState(ALL_TYPES); const [filter, setFilter] = useState(ALL_TYPES);
const href = config.unsafe.alertingExperience.enabled
const href = core.uiSettings.get(enableAlertingExperience)
? '/app/observability/alerts' ? '/app/observability/alerts'
: '/app/management/insightsAndAlerting/triggersActions/alerts'; : '/app/management/insightsAndAlerting/triggersActions/alerts';

View file

@ -40,6 +40,7 @@ describe('APMSection', () => {
http: { basePath: { prepend: jest.fn() } }, http: { basePath: { prepend: jest.fn() } },
} as unknown) as CoreStart, } as unknown) as CoreStart,
appMountParameters: {} as AppMountParameters, appMountParameters: {} as AppMountParameters,
config: { unsafe: { alertingExperience: { enabled: true } } },
observabilityRuleRegistry: ({ observabilityRuleRegistry: ({
registerType: jest.fn(), registerType: jest.fn(),
getTypeByRuleId: jest.fn(), getTypeByRuleId: jest.fn(),

View file

@ -40,6 +40,7 @@ describe('UXSection', () => {
http: { basePath: { prepend: jest.fn() } }, http: { basePath: { prepend: jest.fn() } },
} as unknown) as CoreStart, } as unknown) as CoreStart,
appMountParameters: {} as AppMountParameters, appMountParameters: {} as AppMountParameters,
config: { unsafe: { alertingExperience: { enabled: true } } },
plugins: ({ plugins: ({
data: { data: {
query: { query: {

View file

@ -8,9 +8,11 @@
import { createContext } from 'react'; import { createContext } from 'react';
import { AppMountParameters, CoreStart } from 'kibana/public'; import { AppMountParameters, CoreStart } from 'kibana/public';
import { ObservabilityPublicPluginsStart, ObservabilityRuleRegistry } from '../plugin'; import { ObservabilityPublicPluginsStart, ObservabilityRuleRegistry } from '../plugin';
import { ConfigSchema } from '..';
export interface PluginContextValue { export interface PluginContextValue {
appMountParameters: AppMountParameters; appMountParameters: AppMountParameters;
config: ConfigSchema;
core: CoreStart; core: CoreStart;
plugins: ObservabilityPublicPluginsStart; plugins: ObservabilityPublicPluginsStart;
observabilityRuleRegistry: ObservabilityRuleRegistry; observabilityRuleRegistry: ObservabilityRuleRegistry;

View file

@ -24,6 +24,7 @@ describe('useTimeRange', () => {
jest.spyOn(pluginContext, 'usePluginContext').mockImplementation(() => ({ jest.spyOn(pluginContext, 'usePluginContext').mockImplementation(() => ({
core: {} as CoreStart, core: {} as CoreStart,
appMountParameters: {} as AppMountParameters, appMountParameters: {} as AppMountParameters,
config: { unsafe: { alertingExperience: { enabled: true } } },
plugins: ({ plugins: ({
data: { data: {
query: { query: {
@ -65,6 +66,7 @@ describe('useTimeRange', () => {
jest.spyOn(pluginContext, 'usePluginContext').mockImplementation(() => ({ jest.spyOn(pluginContext, 'usePluginContext').mockImplementation(() => ({
core: {} as CoreStart, core: {} as CoreStart,
appMountParameters: {} as AppMountParameters, appMountParameters: {} as AppMountParameters,
config: { unsafe: { alertingExperience: { enabled: true } } },
plugins: ({ plugins: ({
data: { data: {
query: { query: {

View file

@ -21,12 +21,16 @@ export type {
}; };
export { enableInspectEsQueries } from '../common/ui_settings_keys'; export { enableInspectEsQueries } from '../common/ui_settings_keys';
export interface ConfigSchema {
unsafe: { alertingExperience: { enabled: boolean } };
}
export const plugin: PluginInitializer< export const plugin: PluginInitializer<
ObservabilityPublicSetup, ObservabilityPublicSetup,
ObservabilityPublicStart, ObservabilityPublicStart,
ObservabilityPublicPluginsSetup, ObservabilityPublicPluginsSetup,
ObservabilityPublicPluginsStart ObservabilityPublicPluginsStart
> = (context: PluginInitializerContext) => { > = (context: PluginInitializerContext<ConfigSchema>) => {
return new Plugin(context); return new Plugin(context);
}; };

View file

@ -45,6 +45,7 @@ const withCore = makeDecorator({
appMountParameters: ({ appMountParameters: ({
setHeaderActionMenu: () => {}, setHeaderActionMenu: () => {},
} as unknown) as AppMountParameters, } as unknown) as AppMountParameters,
config: { unsafe: { alertingExperience: { enabled: true } } },
core: options as CoreStart, core: options as CoreStart,
plugins: ({ plugins: ({
data: { data: {

View file

@ -32,6 +32,7 @@ import { registerDataHandler } from './data_handler';
import { FormatterRuleRegistry } from './rules/formatter_rule_registry'; import { FormatterRuleRegistry } from './rules/formatter_rule_registry';
import { createCallObservabilityApi } from './services/call_observability_api'; import { createCallObservabilityApi } from './services/call_observability_api';
import { toggleOverviewLinkInNav } from './toggle_overview_link_in_nav'; import { toggleOverviewLinkInNav } from './toggle_overview_link_in_nav';
import { ConfigSchema } from '.';
export type ObservabilityPublicSetup = ReturnType<Plugin['setup']>; export type ObservabilityPublicSetup = ReturnType<Plugin['setup']>;
export type ObservabilityRuleRegistry = ObservabilityPublicSetup['ruleRegistry']; export type ObservabilityRuleRegistry = ObservabilityPublicSetup['ruleRegistry'];
@ -60,7 +61,9 @@ export class Plugin
> { > {
private readonly appUpdater$ = new BehaviorSubject<AppUpdater>(() => ({})); private readonly appUpdater$ = new BehaviorSubject<AppUpdater>(() => ({}));
constructor(context: PluginInitializerContext) {} constructor(private readonly initializerContext: PluginInitializerContext<ConfigSchema>) {
this.initializerContext = initializerContext;
}
public setup( public setup(
coreSetup: CoreSetup<ObservabilityPublicPluginsStart>, coreSetup: CoreSetup<ObservabilityPublicPluginsStart>,
@ -68,6 +71,7 @@ export class Plugin
) { ) {
const category = DEFAULT_APP_CATEGORIES.observability; const category = DEFAULT_APP_CATEGORIES.observability;
const euiIconType = 'logoObservability'; const euiIconType = 'logoObservability';
const config = this.initializerContext.config.get();
createCallObservabilityApi(coreSetup.http); createCallObservabilityApi(coreSetup.http);
@ -84,6 +88,7 @@ export class Plugin
const [coreStart, pluginsStart] = await coreSetup.getStartServices(); const [coreStart, pluginsStart] = await coreSetup.getStartServices();
return renderApp({ return renderApp({
config,
core: coreStart, core: coreStart,
plugins: pluginsStart, plugins: pluginsStart,
appMountParameters: params, appMountParameters: params,
@ -104,7 +109,7 @@ export class Plugin
updater$, updater$,
}); });
if (coreSetup.uiSettings.get('observability:enableAlertingExperience')) { if (config.unsafe.alertingExperience.enabled) {
coreSetup.application.register({ coreSetup.application.register({
id: 'observability-alerts', id: 'observability-alerts',
title: 'Alerts', title: 'Alerts',

View file

@ -31,6 +31,8 @@ export const core = ({
}, },
} as unknown) as CoreStart; } as unknown) as CoreStart;
const config = { unsafe: { alertingExperience: { enabled: true } } };
const plugins = ({ const plugins = ({
data: { query: { timefilter: { timefilter: { setTime: jest.fn() } } } }, data: { query: { timefilter: { timefilter: { setTime: jest.fn() } } } },
} as unknown) as ObservabilityPublicPluginsStart; } as unknown) as ObservabilityPublicPluginsStart;
@ -42,7 +44,7 @@ export const render = (component: React.ReactNode) => {
<IntlProvider locale="en-US" messages={translations.messages}> <IntlProvider locale="en-US" messages={translations.messages}>
<KibanaContextProvider services={{ ...core }}> <KibanaContextProvider services={{ ...core }}>
<PluginContext.Provider <PluginContext.Provider
value={{ appMountParameters, core, plugins, observabilityRuleRegistry }} value={{ appMountParameters, config, core, plugins, observabilityRuleRegistry }}
> >
<EuiThemeProvider>{component}</EuiThemeProvider> <EuiThemeProvider>{component}</EuiThemeProvider>
</PluginContext.Provider> </PluginContext.Provider>

View file

@ -16,12 +16,18 @@ export { rangeQuery, kqlQuery } from './utils/queries';
export * from './types'; export * from './types';
export const config = { export const config = {
exposeToBrowser: {
unsafe: { alertingExperience: { enabled: true } },
},
schema: schema.object({ schema: schema.object({
enabled: schema.boolean({ defaultValue: true }), enabled: schema.boolean({ defaultValue: true }),
annotations: schema.object({ annotations: schema.object({
enabled: schema.boolean({ defaultValue: true }), enabled: schema.boolean({ defaultValue: true }),
index: schema.string({ defaultValue: 'observability-annotations' }), index: schema.string({ defaultValue: 'observability-annotations' }),
}), }),
unsafe: schema.object({
alertingExperience: schema.object({ enabled: schema.boolean({ defaultValue: false }) }),
}),
}), }),
}; };

View file

@ -8,27 +8,12 @@
import { schema } from '@kbn/config-schema'; import { schema } from '@kbn/config-schema';
import { i18n } from '@kbn/i18n'; import { i18n } from '@kbn/i18n';
import { UiSettingsParams } from '../../../../src/core/types'; import { UiSettingsParams } from '../../../../src/core/types';
import { enableAlertingExperience, enableInspectEsQueries } from '../common/ui_settings_keys'; import { enableInspectEsQueries } from '../common/ui_settings_keys';
/** /**
* uiSettings definitions for Observability. * uiSettings definitions for Observability.
*/ */
export const uiSettings: Record<string, UiSettingsParams<boolean>> = { export const uiSettings: Record<string, UiSettingsParams<boolean>> = {
[enableAlertingExperience]: {
category: ['observability'],
name: i18n.translate('xpack.observability.enableAlertingExperienceExperimentName', {
defaultMessage: 'Observability alerting experience',
}),
value: false,
description: i18n.translate(
'xpack.observability.enableAlertingExperienceExperimentDescription',
{
defaultMessage:
'Enable the experimental alerting experience for Observability. Adds the Alerts and Cases pages.',
}
),
schema: schema.boolean(),
},
[enableInspectEsQueries]: { [enableInspectEsQueries]: {
category: ['observability'], category: ['observability'],
name: i18n.translate('xpack.observability.enableInspectEsQueriesExperimentName', { name: i18n.translate('xpack.observability.enableInspectEsQueriesExperimentName', {

View file

@ -1,3 +1,5 @@
# Rule Registry
The rule registry plugin aims to make it easy for rule type producers to have their rules produce the data that they need to build rich experiences on top of a unified experience, without the risk of mapping conflicts. The rule registry plugin aims to make it easy for rule type producers to have their rules produce the data that they need to build rich experiences on top of a unified experience, without the risk of mapping conflicts.
A rule registry creates a template, an ILM policy, and an alias. The template mappings can be configured. It also injects a client scoped to these indices. A rule registry creates a template, an ILM policy, and an alias. The template mappings can be configured. It also injects a client scoped to these indices.
@ -6,7 +8,17 @@ It also supports inheritance, which means that producers can create a registry s
The rule registry plugin creates a root rule registry, with the mappings defined needed to create a unified experience. Rule type producers can use the plugin to access the root rule registry, and create their own registry that branches off of the root rule registry. The rule registry client sees data from its own registry, and all registries that branches off of it. It does not see data from its parents. The rule registry plugin creates a root rule registry, with the mappings defined needed to create a unified experience. Rule type producers can use the plugin to access the root rule registry, and create their own registry that branches off of the root rule registry. The rule registry client sees data from its own registry, and all registries that branches off of it. It does not see data from its parents.
Creating a rule registry ## Enabling writing
Set
```yaml
xpack.ruleRegistry.unsafe.write.enabled: true
```
in your Kibana configuration to allow the Rule Registry to write events to the alert indices.
## Creating a rule registry
To create a rule registry, producers should add the `ruleRegistry` plugin to their dependencies. They can then use the `ruleRegistry.create` method to create a child registry, with the additional mappings that should be used by specifying `fieldMap`: To create a rule registry, producers should add the `ruleRegistry` plugin to their dependencies. They can then use the `ruleRegistry.create` method to create a child registry, with the additional mappings that should be used by specifying `fieldMap`:
@ -16,7 +28,7 @@ const observabilityRegistry = plugins.ruleRegistry.create({
fieldMap: { fieldMap: {
...pickWithPatterns(ecsFieldMap, 'host.name', 'service.name'), ...pickWithPatterns(ecsFieldMap, 'host.name', 'service.name'),
}, },
}) });
``` ```
`fieldMap` is a key-value map of field names and mapping options: `fieldMap` is a key-value map of field names and mapping options:
@ -37,13 +49,13 @@ To pick many fields, you can use `pickWithPatterns`, which supports wildcards wi
If a registry is created, it will initialise as soon as the core services needed become available. It will create a (versioned) template, alias, and ILM policy, but only if these do not exist yet. If a registry is created, it will initialise as soon as the core services needed become available. It will create a (versioned) template, alias, and ILM policy, but only if these do not exist yet.
### Rule registry client ## Rule registry client
The rule registry client can either be injected in the executor, or created in the scope of a request. It exposes a `search` method and a `bulkIndex` method. When `search` is called, it first gets all the rules the current user has access to, and adds these ids to the search request that it executes. This means that the user can only see data from rules they have access to. The rule registry client can either be injected in the executor, or created in the scope of a request. It exposes a `search` method and a `bulkIndex` method. When `search` is called, it first gets all the rules the current user has access to, and adds these ids to the search request that it executes. This means that the user can only see data from rules they have access to.
Both `search` and `bulkIndex` are fully typed, in the sense that they reflect the mappings defined for the registry. Both `search` and `bulkIndex` are fully typed, in the sense that they reflect the mappings defined for the registry.
### Schema ## Schema
The following fields are available in the root rule registry: The following fields are available in the root rule registry:
@ -60,8 +72,8 @@ The following fields are available in the root rule registry:
- `kibana.rac.alert.uuid`: the unique identifier for the alert during its lifespan. If an alert recovers (or closes), this identifier is re-generated when it is opened again. - `kibana.rac.alert.uuid`: the unique identifier for the alert during its lifespan. If an alert recovers (or closes), this identifier is re-generated when it is opened again.
- `kibana.rac.alert.status`: the status of the alert. Can be `open` or `closed`. - `kibana.rac.alert.status`: the status of the alert. Can be `open` or `closed`.
- `kibana.rac.alert.start`: the ISO timestamp of the time at which the alert started. - `kibana.rac.alert.start`: the ISO timestamp of the time at which the alert started.
- `kibana.rac.alert.end`: the ISO timestamp of the time at which the alert recovered. - `kibana.rac.alert.end`: the ISO timestamp of the time at which the alert recovered.
- `kibana.rac.alert.duration.us`: the duration of the alert, in microseconds. This is always the difference between either the current time, or the time when the alert recovered. - `kibana.rac.alert.duration.us`: the duration of the alert, in microseconds. This is always the difference between either the current time, or the time when the alert recovered.
- `kibana.rac.alert.severity.level`: the severity of the alert, as a keyword (e.g. critical). - `kibana.rac.alert.severity.level`: the severity of the alert, as a keyword (e.g. critical).
- `kibana.rac.alert.severity.value`: the severity of the alert, as a numerical value, which allows sorting. - `kibana.rac.alert.severity.value`: the severity of the alert, as a numerical value, which allows sorting.

View file

@ -17,7 +17,9 @@ export { ScopedRuleRegistryClient } from './rule_registry/create_scoped_rule_reg
export const config = { export const config = {
schema: schema.object({ schema: schema.object({
enabled: schema.boolean({ defaultValue: true }), enabled: schema.boolean({ defaultValue: true }),
writeEnabled: schema.boolean({ defaultValue: false }), unsafe: schema.object({
write: schema.object({ enabled: schema.boolean({ defaultValue: false }) }),
}),
}), }),
}; };

View file

@ -37,7 +37,7 @@ export class RuleRegistryPlugin implements Plugin<RuleRegistryPluginSetupContrac
kibanaVersion: this.initContext.env.packageInfo.version, kibanaVersion: this.initContext.env.packageInfo.version,
logger: logger.get('root'), logger: logger.get('root'),
alertingPluginSetupContract: plugins.alerting, alertingPluginSetupContract: plugins.alerting,
writeEnabled: config.writeEnabled, writeEnabled: config.unsafe.write.enabled,
}); });
return rootRegistry; return rootRegistry;

View file

@ -18,7 +18,7 @@ const apmFtrConfigs = {
rules: { rules: {
license: 'trial' as const, license: 'trial' as const,
kibanaConfig: { kibanaConfig: {
'xpack.ruleRegistry.writeEnabled': 'true', 'xpack.ruleRegistry.unsafe.write.enabled': 'true',
}, },
}, },
}; };