mirror of
https://github.com/elastic/kibana.git
synced 2025-06-28 03:01:21 -04:00
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:
parent
1fc1bcdb08
commit
042fa1a2ce
23 changed files with 84 additions and 46 deletions
|
@ -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
|
||||||
|
|
|
@ -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.' },
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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": {
|
||||||
|
|
|
@ -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`.
|
||||||
|
|
|
@ -5,5 +5,4 @@
|
||||||
* 2.0.
|
* 2.0.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export const enableAlertingExperience = 'observability:enableAlertingExperience';
|
|
||||||
export const enableInspectEsQueries = 'observability:enableInspectEsQueries';
|
export const enableInspectEsQueries = 'observability:enableInspectEsQueries';
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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}>
|
||||||
|
|
|
@ -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';
|
||||||
|
|
||||||
|
|
|
@ -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(),
|
||||||
|
|
|
@ -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: {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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: {
|
||||||
|
|
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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: {
|
||||||
|
|
|
@ -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',
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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 }) }),
|
||||||
|
}),
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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', {
|
||||||
|
|
|
@ -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.
|
||||||
|
|
||||||
|
|
|
@ -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 }) }),
|
||||||
|
}),
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue