[Actionable Observability] Remove alerts, rules and cases experimental feature flags (#134157)

* remove rules feature flag

* remove alertingExperience feature flag

* remove cases feature flag

* remove experimental badge from alerts page, alerts flyout, rules page, rule details page, overview page

* rempve disclaimer files

* fix tests

* [CI] Auto-commit changed files from 'node scripts/precommit_hook.js --ref HEAD~1..HEAD --fix'

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
mgiota 2022-06-15 16:54:41 +02:00 committed by GitHub
parent b32052e66a
commit 165a604e1a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
35 changed files with 70 additions and 435 deletions

View file

@ -292,8 +292,6 @@ kibana_vars=(
xpack.ingestManager.fleet.tlsCheckDisabled
xpack.ingestManager.registryUrl
xpack.observability.annotations.index
xpack.observability.unsafe.alertingExperience.enabled
xpack.observability.unsafe.cases.enabled
xpack.reporting.capture.browser.autoDownload
xpack.reporting.capture.browser.chromium.disableSandbox
xpack.reporting.capture.browser.chromium.inspect

View file

@ -184,9 +184,6 @@ export default function ({ getService }: PluginFunctionalProviderContext) {
'xpack.license_management.ui.enabled (boolean)',
'xpack.maps.preserveDrawingBuffer (boolean)',
'xpack.maps.showMapsInspectorAdapter (boolean)',
'xpack.observability.unsafe.alertingExperience.enabled (boolean)',
'xpack.observability.unsafe.cases.enabled (boolean)',
'xpack.observability.unsafe.rules.enabled (boolean)',
'xpack.osquery.actionEnabled (boolean)',
'xpack.osquery.packs (boolean)',
'xpack.osquery.savedQueries (boolean)',

View file

@ -58,7 +58,7 @@ const stories: Meta<Args> = {
},
uiSettings: { get: () => '' },
},
plugins: { observability: { isAlertingExperienceEnabled: () => true } },
plugins: {},
observabilityRuleTypeRegistry: { getFormatter: () => undefined },
} as unknown as ApmPluginContextValue;

View file

@ -86,9 +86,6 @@ const mockPlugin = {
timefilter: { timefilter: { setTime: () => {}, getTime: () => ({}) } },
},
},
observability: {
isAlertingExperienceEnabled: () => false,
},
};
const mockCorePlugins = {

View file

@ -4,33 +4,14 @@ This plugin provides shared components and services for use across observability
## Rules, Alerts, and Cases
The Observability plugin contains experimental support for improved alerting and
case management.
If you have:
```yaml
xpack.observability.unsafe.cases.enabled: true
```
In your Kibana configuration, the Cases page will be available.
If you have:
```yaml
xpack.observability.unsafe.alertingExperience.enabled: true
```
In your Kibana configuration, the Alerts page will be available.
This will only enable the UI for this page when. In order to have alert data indexed
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.write.enabled: true
```
When both of the these are set to `true`, your alerts should show on the alerts page.
When this is set to `true`, your alerts should show on the alerts page.
## Shared navigation

View file

@ -59,14 +59,6 @@ describe('renderApp', () => {
theme: themeServiceMock.createStartContract(),
} as unknown as CoreStart;
const config = {
unsafe: {
alertingExperience: { enabled: true },
cases: { enabled: true },
rules: { enabled: true },
},
};
const params = {
element: window.document.createElement('div'),
history: createMemoryHistory(),
@ -76,7 +68,6 @@ describe('renderApp', () => {
expect(() => {
const unmount = renderApp({
config,
core,
plugins,
appMountParameters: params,

View file

@ -19,7 +19,6 @@ import {
} from '@kbn/kibana-react-plugin/public';
import { Storage } from '@kbn/kibana-utils-plugin/public';
import { UsageCollectionSetup } from '@kbn/usage-collection-plugin/public';
import { ConfigSchema } from '..';
import type { LazyObservabilityPageTemplateProps } from '../components/shared/page_template/lazy_page_template';
import { DatePickerContextProvider } from '../context/date_picker_context';
import { HasDataContextProvider } from '../context/has_data_context';
@ -48,7 +47,6 @@ function App() {
}
export const renderApp = ({
config,
core,
plugins,
appMountParameters,
@ -57,7 +55,6 @@ export const renderApp = ({
kibanaFeatures,
usageCollection,
}: {
config: ConfigSchema;
core: CoreStart;
plugins: ObservabilityPublicPluginsStart;
observabilityRuleTypeRegistry: ObservabilityRuleTypeRegistry;
@ -91,7 +88,6 @@ export const renderApp = ({
<PluginContext.Provider
value={{
appMountParameters,
config,
observabilityRuleTypeRegistry,
ObservabilityPageTemplate,
kibanaFeatures,

View file

@ -46,13 +46,6 @@ describe('APMSection', () => {
jest.spyOn(pluginContext, 'usePluginContext').mockImplementation(() => ({
appMountParameters: {} as AppMountParameters,
config: {
unsafe: {
alertingExperience: { enabled: true },
cases: { enabled: true },
rules: { enabled: true },
},
},
core: {} as CoreStart,
plugins: {} as ObservabilityPublicPluginsStart,
observabilityRuleTypeRegistry: createObservabilityRuleTypeRegistryMock(),

View file

@ -8,13 +8,11 @@
import { AppMountParameters } from '@kbn/core/public';
import { createContext } from 'react';
import { KibanaFeature } from '@kbn/features-plugin/common';
import { ConfigSchema } from '..';
import { ObservabilityRuleTypeRegistry } from '../rules/create_observability_rule_type_registry';
import type { LazyObservabilityPageTemplateProps } from '../components/shared/page_template/lazy_page_template';
export interface PluginContextValue {
appMountParameters: AppMountParameters;
config: ConfigSchema;
observabilityRuleTypeRegistry: ObservabilityRuleTypeRegistry;
ObservabilityPageTemplate: React.ComponentType<LazyObservabilityPageTemplateProps>;
kibanaFeatures: KibanaFeature[];

View file

@ -6,17 +6,13 @@
*/
import { Options, useLinkProps } from './use_link_props';
export function createUseRulesLink(isNewRuleManagementEnabled = false) {
return function (options: Options = {}) {
const linkProps = isNewRuleManagementEnabled
? {
app: 'observability',
pathname: '/alerts/rules',
}
: {
app: 'management',
pathname: '/insightsAndAlerting/triggersActions/rules',
};
export const createUseRulesLink =
() =>
(options: Options = {}) => {
const linkProps = {
app: 'observability',
pathname: '/alerts/rules',
};
return useLinkProps(linkProps, options);
};
}

View file

@ -8,7 +8,7 @@
// TODO: https://github.com/elastic/kibana/issues/110905
/* eslint-disable @kbn/eslint/no_export_all */
import { PluginInitializerContext, PluginInitializer } from '@kbn/core/public';
import { PluginInitializer } from '@kbn/core/public';
import { lazy } from 'react';
import {
Plugin,
@ -33,21 +33,13 @@ export {
} from '../common/ui_settings_keys';
export { uptimeOverviewLocatorID } from '../common';
export interface ConfigSchema {
unsafe: {
alertingExperience: { enabled: boolean };
rules: { enabled: boolean };
cases: { enabled: boolean };
};
}
export const plugin: PluginInitializer<
ObservabilityPublicSetup,
ObservabilityPublicStart,
ObservabilityPublicPluginsSetup,
ObservabilityPublicPluginsStart
> = (context: PluginInitializerContext<ConfigSchema>) => {
return new Plugin(context);
> = () => {
return new Plugin();
};
export * from './components/shared/action_menu';

View file

@ -1,71 +0,0 @@
/*
* 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 React, { useState } from 'react';
import { EuiLink, EuiCallOut, EuiButton, EuiSpacer } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n-react';
const LOCAL_STORAGE_KEY_MSG_ACK = 'xpack.observability.alert.ack.experimental.message';
export function AlertsDisclaimer() {
const getCurrentExperimentalMsgAckState = () => {
try {
const isExperimentalMsgAck = localStorage.getItem(LOCAL_STORAGE_KEY_MSG_ACK);
return isExperimentalMsgAck && JSON.parse(isExperimentalMsgAck) === true;
} catch {
return false;
}
};
const [experimentalMsgAck, setExperimentalMsgAck] = useState(getCurrentExperimentalMsgAckState);
const dismissMessage = () => {
setExperimentalMsgAck(true);
localStorage.setItem(LOCAL_STORAGE_KEY_MSG_ACK, 'true');
};
return (
<>
{!experimentalMsgAck && (
<EuiCallOut
data-test-subj="o11yExperimentalDisclaimer"
title={i18n.translate('xpack.observability.alertsDisclaimerTitle', {
defaultMessage: 'Technical preview',
})}
color="warning"
>
<FormattedMessage
id="xpack.observability.alertsDisclaimerText"
defaultMessage="This functionality is in technical preview and may be changed or removed completely in a future release. Elastic will take a best effort approach to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. Provide {feedback}."
values={{
feedback: (
<EuiLink href="https://discuss.elastic.co/c/observability/82" target="_blank">
{i18n.translate('xpack.observability.alertsDisclaimerLinkText', {
defaultMessage: 'feedback',
})}
</EuiLink>
),
}}
/>
<EuiSpacer size="l" />
<EuiButton
data-test-subj="o11yExperimentalDisclaimerDismissBtn"
color="warning"
onClick={dismissMessage}
tabIndex={0}
>
{i18n.translate('xpack.observability.alertsDisclaimerDismissMessage', {
defaultMessage: 'Dismiss message',
})}
</EuiButton>
</EuiCallOut>
)}
</>
);
}

View file

@ -39,7 +39,6 @@ import { asDuration } from '../../../../../common/utils/formatters';
import type { ObservabilityRuleTypeRegistry } from '../../../../rules/create_observability_rule_type_registry';
import { parseAlert } from '../parse_alert';
import { AlertStatusIndicator } from '../../../../components/shared/alert_status_indicator';
import { ExperimentalBadge } from '../../../../components/shared/experimental_badge';
import { translations, paths } from '../../../../config';
type AlertsFlyoutProps = {
@ -122,7 +121,6 @@ export function AlertsFlyout({
return (
<EuiFlyout onClose={onClose} size="s" data-test-subj="alertsFlyout">
<EuiFlyoutHeader hasBorder>
<ExperimentalBadge />
<EuiSpacer size="s" />
<EuiTitle size="m" data-test-subj="alertsFlyoutTitle">
<h2>{alertData.fields[ALERT_RULE_NAME]}</h2>

View file

@ -8,14 +8,12 @@ import React from 'react';
import { ALERT_RULE_NAME } from '@kbn/rule-data-utils';
import { get } from 'lodash';
import { EuiSpacer, EuiTitle } from '@elastic/eui';
import { ExperimentalBadge } from '../../../../components/shared/experimental_badge';
import { FlyoutProps } from './types';
// eslint-disable-next-line import/no-default-export
export default function AlertsFlyoutHeader({ alert }: FlyoutProps) {
return (
<>
<ExperimentalBadge />
<EuiSpacer size="s" />
<EuiTitle size="m" data-test-subj="alertsFlyoutTitle">
<h2>{get(alert, ALERT_RULE_NAME)}</h2>

View file

@ -10,7 +10,6 @@ export * from './render_cell_value';
export * from './severity_badge';
export * from './workflow_status_filter';
export * from './alerts_search_bar';
export * from './alerts_disclaimer';
export * from './default_cell_actions';
export * from './filter_for_value';
export * from './parse_alert';

View file

@ -20,7 +20,6 @@ import { Storage } from '@kbn/kibana-utils-plugin/public';
import { AlertStatusFilterButton } from '../../../../../common/typings';
import { useGetUserCasesPermissions } from '../../../../hooks/use_get_user_cases_permissions';
import { observabilityFeatureId } from '../../../../../common';
import { ExperimentalBadge } from '../../../../components/shared/experimental_badge';
import { useBreadcrumbs } from '../../../../hooks/use_breadcrumbs';
import { useAlertIndexNames } from '../../../../hooks/use_alert_index_names';
import { useHasData } from '../../../../hooks/use_has_data';
@ -35,7 +34,7 @@ import {
useAlertsPageStateContainer,
} from '../state_container';
import './styles.scss';
import { AlertsStatusFilter, AlertsDisclaimer, AlertsSearchBar } from '../../components';
import { AlertsStatusFilter, AlertsSearchBar } from '../../components';
import { renderRuleStats } from '../../components/rule_stats';
import { ObservabilityAppServices } from '../../../../application/types';
@ -69,7 +68,7 @@ const ALERT_STATUS_REGEX = new RegExp(
const ALERT_TABLE_STATE_STORAGE_KEY = 'xpack.observability.alert.tableState';
function AlertsPage() {
const { ObservabilityPageTemplate, config, observabilityRuleTypeRegistry } = usePluginContext();
const { ObservabilityPageTemplate, observabilityRuleTypeRegistry } = usePluginContext();
const [alertFilterStatus, setAlertFilterStatus] = useState('' as AlertStatusFilterButton);
const refetch = useRef<() => void>();
const timefilterService = useTimefilterService();
@ -145,9 +144,7 @@ function AlertsPage() {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
const manageRulesHref = config.unsafe.rules.enabled
? http.basePath.prepend('/app/observability/alerts/rules')
: http.basePath.prepend('/app/management/insightsAndAlerting/triggersActions/rules');
const manageRulesHref = http.basePath.prepend('/app/observability/alerts/rules');
const dynamicIndexPatternsAsyncState = useAsync(async (): Promise<DataViewBase[]> => {
if (indexNames.length === 0) {
@ -240,18 +237,12 @@ function AlertsPage() {
data-test-subj={noDataConfig ? 'noDataPage' : undefined}
pageHeader={{
pageTitle: (
<>
{i18n.translate('xpack.observability.alertsTitle', { defaultMessage: 'Alerts' })}{' '}
<ExperimentalBadge />
</>
<>{i18n.translate('xpack.observability.alertsTitle', { defaultMessage: 'Alerts' })} </>
),
rightSideItems: renderRuleStats(ruleStats, manageRulesHref, ruleStatsLoading),
}}
>
<EuiFlexGroup direction="column" gutterSize="s">
<EuiFlexItem>
<AlertsDisclaimer />
</EuiFlexItem>
<EuiFlexItem>
<AlertsSearchBar
dynamicIndexPatterns={dynamicIndexPatternsAsyncState.value ?? NO_INDEX_PATTERNS}

View file

@ -89,7 +89,7 @@ export function OverviewPage({ routeParams }: Props) {
application: { capabilities },
} = useKibana<ObservabilityAppServices>().services;
const { ObservabilityPageTemplate, config } = usePluginContext();
const { ObservabilityPageTemplate } = usePluginContext();
const { relativeStart, relativeEnd, absoluteStart, absoluteEnd } = useDatePickerContext();
const { data: newsFeed } = useFetcher(() => getNewsFeed({ http }), [http]);
@ -155,9 +155,7 @@ export function OverviewPage({ routeParams }: Props) {
docsLink: docLinks.links.observability.guide,
});
const alertsLink = config.unsafe.alertingExperience.enabled
? paths.observability.alerts
: paths.management.rules;
const alertsLink = paths.observability.alerts;
return (
<ObservabilityPageTemplate
@ -197,7 +195,6 @@ export function OverviewPage({ routeParams }: Props) {
defaultMessage: 'Show alerts',
}),
}}
showExperimentalBadge={true}
>
<CasesContext
owner={[observabilityFeatureId]}

View file

@ -82,13 +82,6 @@ const withCore = makeDecorator({
appMountParameters: {
setHeaderActionMenu: () => {},
} as unknown as AppMountParameters,
config: {
unsafe: {
alertingExperience: { enabled: true },
cases: { enabled: true },
rules: { enabled: true },
},
},
observabilityRuleTypeRegistry: createObservabilityRuleTypeRegistryMock(),
ObservabilityPageTemplate: KibanaPageTemplate,
kibanaFeatures: [],

View file

@ -7,7 +7,6 @@
import React, { useState } from 'react';
import moment from 'moment';
import { EuiText, EuiFlexGroup, EuiFlexItem, EuiBadge, EuiSpacer } from '@elastic/eui';
import { ExperimentalBadge } from '../../../components/shared/experimental_badge';
import { PageHeaderProps } from '../types';
import { useKibana } from '../../../utils/kibana_react';
import { LAST_UPDATED_MESSAGE, CREATED_WORD, BY_WORD, ON_WORD } from '../translations';
@ -27,7 +26,6 @@ export function PageTitle({ rule }: PageHeaderProps) {
<EuiFlexItem grow={false} data-test-subj="ruleName">
{rule.name}
</EuiFlexItem>
<ExperimentalBadge />
</EuiFlexGroup>
<EuiFlexItem grow={false}>
<EuiSpacer size="xs" />

View file

@ -43,14 +43,6 @@ jest.mock('@kbn/triggers-actions-ui-plugin/public', () => ({
jest.spyOn(pluginContext, 'usePluginContext').mockImplementation(() => ({
appMountParameters: {} as AppMountParameters,
config: {
unsafe: {
alertingExperience: { enabled: true },
cases: { enabled: true },
overviewNext: { enabled: false },
rules: { enabled: true },
},
},
observabilityRuleTypeRegistry: createObservabilityRuleTypeRegistryMock(),
ObservabilityPageTemplate: KibanaPageTemplate,
kibanaFeatures: [],

View file

@ -71,7 +71,6 @@ import {
RULES_PLURAL_TITLE,
SEARCH_PLACEHOLDER,
} from './translations';
import { ExperimentalBadge } from '../../components/shared/experimental_badge';
const ENTER_KEY = 13;
function RulesPage() {
@ -441,11 +440,7 @@ function RulesPage() {
return (
<ObservabilityPageTemplate
pageHeader={{
pageTitle: (
<>
{RULES_PAGE_TITLE} <ExperimentalBadge />
</>
),
pageTitle: <>{RULES_PAGE_TITLE}</>,
rightSideItems: [
authorizedToCreateAnyRules && (
<EuiButton

View file

@ -17,7 +17,6 @@ import {
CoreStart,
DEFAULT_APP_CATEGORIES,
Plugin as PluginClass,
PluginInitializerContext,
} from '@kbn/core/public';
import type { DataPublicPluginSetup, DataPublicPluginStart } from '@kbn/data-plugin/public';
import type { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public';
@ -35,7 +34,6 @@ import {
import { KibanaFeature } from '@kbn/features-plugin/common';
import { UsageCollectionSetup } from '@kbn/usage-collection-plugin/public';
import { ConfigSchema } from '.';
import { observabilityAppId, observabilityFeatureId, casesPath } from '../common';
import { createLazyObservabilityPageTemplate } from './components/shared';
import { registerDataHandler } from './data_handler';
@ -127,17 +125,12 @@ export class Plugin
}),
];
constructor(private readonly initializerContext: PluginInitializerContext<ConfigSchema>) {
this.initializerContext = initializerContext;
}
public setup(
coreSetup: CoreSetup<ObservabilityPublicPluginsStart, ObservabilityPublicStart>,
pluginsSetup: ObservabilityPublicPluginsSetup
) {
const category = DEFAULT_APP_CATEGORIES.observability;
const euiIconType = 'logoObservability';
const config = this.initializerContext.config.get();
createCallObservabilityApi(coreSetup.http);
@ -168,7 +161,6 @@ export class Plugin
}
return renderApp({
config,
core: coreStart,
plugins: pluginsStart,
appMountParameters: params,
@ -272,21 +264,18 @@ export class Plugin
return {
dashboard: { register: registerDataHandler },
observabilityRuleTypeRegistry,
isAlertingExperienceEnabled: () => config.unsafe.alertingExperience.enabled,
navigation: {
registerSections: this.navigationRegistry.registerSections,
},
useRulesLink: createUseRulesLink(config.unsafe.rules.enabled),
useRulesLink: createUseRulesLink(),
};
}
public start(coreStart: CoreStart, pluginsStart: ObservabilityPublicPluginsStart) {
const { application } = coreStart;
const config = this.initializerContext.config.get();
updateGlobalNavigation({
capabilities: application.capabilities,
config,
deepLinks: this.deepLinks,
updater$: this.appUpdater$,
});
@ -310,7 +299,7 @@ export class Plugin
pluginsStart.dataViews,
pluginsStart.lens
),
useRulesLink: createUseRulesLink(config.unsafe.rules.enabled),
useRulesLink: createUseRulesLink(),
};
}
}

View file

@ -6,7 +6,6 @@
*/
import { Subject } from 'rxjs';
import { ConfigSchema } from '.';
import { App, AppDeepLink, ApplicationStart, AppNavLinkStatus, AppUpdater } from '@kbn/core/public';
import { casesFeatureId } from '../common';
import { updateGlobalNavigation } from './update_global_navigation';
@ -20,16 +19,13 @@ describe('updateGlobalNavigation', () => {
const capabilities = {
navLinks: { apm: false, logs: false, metrics: false, uptime: false },
} as unknown as ApplicationStart['capabilities'];
const config = {
unsafe: { alertingExperience: { enabled: true }, cases: { enabled: true } },
} as ConfigSchema;
const deepLinks: AppDeepLink[] = [];
const callback = jest.fn();
const updater$ = {
next: (cb: AppUpdater) => callback(cb(app)),
} as unknown as Subject<AppUpdater>;
updateGlobalNavigation({ capabilities, config, deepLinks, updater$ });
updateGlobalNavigation({ capabilities, deepLinks, updater$ });
expect(callback).toHaveBeenCalledWith({
deepLinks,
@ -43,16 +39,13 @@ describe('updateGlobalNavigation', () => {
const capabilities = {
navLinks: { apm: true, logs: false, metrics: false, uptime: false },
} as unknown as ApplicationStart['capabilities'];
const config = {
unsafe: { alertingExperience: { enabled: true }, cases: { enabled: true } },
} as ConfigSchema;
const deepLinks: AppDeepLink[] = [];
const callback = jest.fn();
const updater$ = {
next: (cb: AppUpdater) => callback(cb(app)),
} as unknown as Subject<AppUpdater>;
updateGlobalNavigation({ capabilities, config, deepLinks, updater$ });
updateGlobalNavigation({ capabilities, deepLinks, updater$ });
expect(callback).toHaveBeenCalledWith({
deepLinks,
@ -66,9 +59,6 @@ describe('updateGlobalNavigation', () => {
[casesFeatureId]: { read_cases: true },
navLinks: { apm: true, logs: false, metrics: false, uptime: false },
} as unknown as ApplicationStart['capabilities'];
const config = {
unsafe: { alertingExperience: { enabled: true }, cases: { enabled: true } },
} as ConfigSchema;
const deepLinks = [
{
id: 'cases',
@ -83,7 +73,7 @@ describe('updateGlobalNavigation', () => {
next: (cb: AppUpdater) => callback(cb(app)),
} as unknown as Subject<AppUpdater>;
updateGlobalNavigation({ capabilities, config, deepLinks, updater$ });
updateGlobalNavigation({ capabilities, deepLinks, updater$ });
expect(callback).toHaveBeenCalledWith({
deepLinks: [
@ -100,55 +90,12 @@ describe('updateGlobalNavigation', () => {
});
});
describe('when cases are disabled', () => {
it('hides the cases deep link', () => {
const capabilities = {
[casesFeatureId]: { read_cases: true },
navLinks: { apm: true, logs: false, metrics: false, uptime: false },
} as unknown as ApplicationStart['capabilities'];
const config = {
unsafe: { alertingExperience: { enabled: true }, cases: { enabled: false } },
} as ConfigSchema;
const deepLinks = [
{
id: 'cases',
title: 'Cases',
order: 8002,
path: '/cases',
navLinkStatus: AppNavLinkStatus.hidden,
},
];
const callback = jest.fn();
const updater$ = {
next: (cb: AppUpdater) => callback(cb(app)),
} as unknown as Subject<AppUpdater>;
updateGlobalNavigation({ capabilities, config, deepLinks, updater$ });
expect(callback).toHaveBeenCalledWith({
deepLinks: [
{
id: 'cases',
title: 'Cases',
order: 8002,
path: '/cases',
navLinkStatus: AppNavLinkStatus.hidden,
},
],
navLinkStatus: AppNavLinkStatus.visible,
});
});
});
describe('with no case read capabilities', () => {
it('hides the cases deep link', () => {
const capabilities = {
[casesFeatureId]: { read_cases: false },
navLinks: { apm: true, logs: false, metrics: false, uptime: false },
} as unknown as ApplicationStart['capabilities'];
const config = {
unsafe: { alertingExperience: { enabled: true }, cases: { enabled: true } },
} as ConfigSchema;
const deepLinks = [
{
id: 'cases',
@ -163,7 +110,7 @@ describe('updateGlobalNavigation', () => {
next: (cb: AppUpdater) => callback(cb(app)),
} as unknown as Subject<AppUpdater>;
updateGlobalNavigation({ capabilities, config, deepLinks, updater$ });
updateGlobalNavigation({ capabilities, deepLinks, updater$ });
expect(callback).toHaveBeenCalledWith({
deepLinks: [
@ -186,9 +133,7 @@ describe('updateGlobalNavigation', () => {
[casesFeatureId]: { read_cases: true },
navLinks: { apm: true, logs: false, metrics: false, uptime: false },
} as unknown as ApplicationStart['capabilities'];
const config = {
unsafe: { alertingExperience: { enabled: true }, cases: { enabled: true } },
} as ConfigSchema;
const deepLinks = [
{
id: 'alerts',
@ -203,7 +148,7 @@ describe('updateGlobalNavigation', () => {
next: (cb: AppUpdater) => callback(cb(app)),
} as unknown as Subject<AppUpdater>;
updateGlobalNavigation({ capabilities, config, deepLinks, updater$ });
updateGlobalNavigation({ capabilities, deepLinks, updater$ });
expect(callback).toHaveBeenCalledWith({
deepLinks: [
@ -219,45 +164,5 @@ describe('updateGlobalNavigation', () => {
});
});
});
describe('when alerts are disabled', () => {
it('hides the alerts deep link', () => {
const capabilities = {
[casesFeatureId]: { read_cases: true },
navLinks: { apm: true, logs: false, metrics: false, uptime: false },
} as unknown as ApplicationStart['capabilities'];
const config = {
unsafe: { alertingExperience: { enabled: false }, cases: { enabled: false } },
} as ConfigSchema;
const deepLinks = [
{
id: 'alerts',
title: 'Alerts',
order: 8001,
path: '/alerts',
navLinkStatus: AppNavLinkStatus.hidden,
},
];
const callback = jest.fn();
const updater$ = {
next: (cb: AppUpdater) => callback(cb(app)),
} as unknown as Subject<AppUpdater>;
updateGlobalNavigation({ capabilities, config, deepLinks, updater$ });
expect(callback).toHaveBeenCalledWith({
deepLinks: [
{
id: 'alerts',
title: 'Alerts',
order: 8001,
path: '/alerts',
navLinkStatus: AppNavLinkStatus.hidden,
},
],
navLinkStatus: AppNavLinkStatus.visible,
});
});
});
});
});

View file

@ -8,17 +8,14 @@
import { Subject } from 'rxjs';
import { AppNavLinkStatus, AppUpdater, ApplicationStart, AppDeepLink } from '@kbn/core/public';
import { CasesDeepLinkId } from '@kbn/cases-plugin/public';
import { ConfigSchema } from '.';
import { casesFeatureId } from '../common';
export function updateGlobalNavigation({
capabilities,
config,
deepLinks,
updater$,
}: {
capabilities: ApplicationStart['capabilities'];
config: ConfigSchema;
deepLinks: AppDeepLink[];
updater$: Subject<AppUpdater>;
}) {
@ -31,25 +28,19 @@ export function updateGlobalNavigation({
return {
...link,
navLinkStatus:
config.unsafe.cases.enabled && capabilities[casesFeatureId].read_cases && someVisible
capabilities[casesFeatureId].read_cases && someVisible
? AppNavLinkStatus.visible
: AppNavLinkStatus.hidden,
};
case 'alerts':
return {
...link,
navLinkStatus:
config.unsafe.alertingExperience.enabled && someVisible
? AppNavLinkStatus.visible
: AppNavLinkStatus.hidden,
navLinkStatus: someVisible ? AppNavLinkStatus.visible : AppNavLinkStatus.hidden,
};
case 'rules':
return {
...link,
navLinkStatus:
config.unsafe.rules.enabled && someVisible
? AppNavLinkStatus.visible
: AppNavLinkStatus.hidden,
navLinkStatus: someVisible ? AppNavLinkStatus.visible : AppNavLinkStatus.hidden,
};
default:
return link;

View file

@ -24,14 +24,6 @@ const appMountParameters = { setHeaderActionMenu: () => {} } as unknown as AppMo
export const core = coreMock.createStart();
export const data = dataPluginMock.createStartContract();
const config = {
unsafe: {
alertingExperience: { enabled: true },
cases: { enabled: true },
rules: { enabled: true },
},
};
const observabilityRuleTypeRegistry = createObservabilityRuleTypeRegistryMock();
export const render = (component: React.ReactNode) => {
@ -41,7 +33,6 @@ export const render = (component: React.ReactNode) => {
<PluginContext.Provider
value={{
appMountParameters,
config,
observabilityRuleTypeRegistry,
ObservabilityPageTemplate: KibanaPageTemplate,
kibanaFeatures: [],

View file

@ -31,11 +31,6 @@ export const config: PluginConfigDescriptor = {
enabled: schema.boolean({ defaultValue: true }),
index: schema.string({ defaultValue: 'observability-annotations' }),
}),
unsafe: schema.object({
alertingExperience: schema.object({ enabled: schema.boolean({ defaultValue: true }) }),
rules: schema.object({ enabled: schema.boolean({ defaultValue: true }) }),
cases: schema.object({ enabled: schema.boolean({ defaultValue: true }) }),
}),
}),
};

View file

@ -40,47 +40,45 @@ export class ObservabilityPlugin implements Plugin<ObservabilityPluginSetup> {
public setup(core: CoreSetup, plugins: PluginSetup) {
const config = this.initContext.config.get<ObservabilityConfig>();
if (config.unsafe.cases.enabled) {
plugins.features.registerKibanaFeature({
id: casesFeatureId,
name: i18n.translate('xpack.observability.featureRegistry.linkObservabilityTitle', {
defaultMessage: 'Cases',
}),
order: 1100,
category: DEFAULT_APP_CATEGORIES.observability,
app: [casesFeatureId, 'kibana'],
catalogue: [observabilityFeatureId],
cases: [observabilityFeatureId],
privileges: {
all: {
app: [casesFeatureId, 'kibana'],
catalogue: [observabilityFeatureId],
cases: {
all: [observabilityFeatureId],
},
api: [],
savedObject: {
all: [],
read: [],
},
ui: ['crud_cases', 'read_cases'], // uiCapabilities[casesFeatureId].crud_cases or read_cases
plugins.features.registerKibanaFeature({
id: casesFeatureId,
name: i18n.translate('xpack.observability.featureRegistry.linkObservabilityTitle', {
defaultMessage: 'Cases',
}),
order: 1100,
category: DEFAULT_APP_CATEGORIES.observability,
app: [casesFeatureId, 'kibana'],
catalogue: [observabilityFeatureId],
cases: [observabilityFeatureId],
privileges: {
all: {
app: [casesFeatureId, 'kibana'],
catalogue: [observabilityFeatureId],
cases: {
all: [observabilityFeatureId],
},
read: {
app: [casesFeatureId, 'kibana'],
catalogue: [observabilityFeatureId],
cases: {
read: [observabilityFeatureId],
},
api: [],
savedObject: {
all: [],
read: [],
},
ui: ['read_cases'], // uiCapabilities[uiCapabilities[casesFeatureId]].read_cases
api: [],
savedObject: {
all: [],
read: [],
},
ui: ['crud_cases', 'read_cases'], // uiCapabilities[casesFeatureId].crud_cases or read_cases
},
});
}
read: {
app: [casesFeatureId, 'kibana'],
catalogue: [observabilityFeatureId],
cases: {
read: [observabilityFeatureId],
},
api: [],
savedObject: {
all: [],
read: [],
},
ui: ['read_cases'], // uiCapabilities[uiCapabilities[casesFeatureId]].read_cases
},
},
});
let annotationsApiPromise: Promise<AnnotationsAPI> | undefined;

View file

@ -21372,10 +21372,6 @@
"xpack.observability.alerts.workflowStatusFilter.acknowledgedButtonLabel": "Reconnue(s)",
"xpack.observability.alerts.workflowStatusFilter.closedButtonLabel": "Fermé",
"xpack.observability.alerts.workflowStatusFilter.openButtonLabel": "Ouvrir",
"xpack.observability.alertsDisclaimerDismissMessage": "Ignorer le message",
"xpack.observability.alertsDisclaimerLinkText": "commentaires",
"xpack.observability.alertsDisclaimerText": "Cette fonctionnalité est en version dévaluation technique et peut être modifiée ou retirée complètement dans une future version. Elastic s'efforcera au maximum de corriger tout problème, mais les fonctionnalités en version d'évaluation technique ne sont pas soumises aux accords de niveau de service d'assistance des fonctionnalités officielles en disponibilité générale. Veuillez laisser des {feedback}.",
"xpack.observability.alertsDisclaimerTitle": "Version dévaluation technique",
"xpack.observability.alertsFlyout.actualValueLabel": "Valeur réelle",
"xpack.observability.alertsFlyout.documentSummaryTitle": "Résumé du document",
"xpack.observability.alertsFlyout.durationLabel": "Durée",

View file

@ -21509,10 +21509,6 @@
"xpack.observability.alerts.workflowStatusFilter.acknowledgedButtonLabel": "認識",
"xpack.observability.alerts.workflowStatusFilter.closedButtonLabel": "終了",
"xpack.observability.alerts.workflowStatusFilter.openButtonLabel": "開く",
"xpack.observability.alertsDisclaimerDismissMessage": "メッセージを消去",
"xpack.observability.alertsDisclaimerLinkText": "フィードバック",
"xpack.observability.alertsDisclaimerText": "この機能はテクニカルプレビュー中であり、将来のリリースでは変更されたり完全に削除されたりする場合があります。Elasticは最善の努力を講じてすべての問題の修正に努めますが、テクニカルプレビュー中の機能には正式なGA機能のサポートSLAが適用されません。{feedback}を提出します。",
"xpack.observability.alertsDisclaimerTitle": "テクニカルプレビュー",
"xpack.observability.alertsFlyout.actualValueLabel": "実際の値",
"xpack.observability.alertsFlyout.documentSummaryTitle": "ドキュメント概要",
"xpack.observability.alertsFlyout.durationLabel": "期間",

View file

@ -21541,10 +21541,6 @@
"xpack.observability.alerts.workflowStatusFilter.acknowledgedButtonLabel": "已确认",
"xpack.observability.alerts.workflowStatusFilter.closedButtonLabel": "已关闭",
"xpack.observability.alerts.workflowStatusFilter.openButtonLabel": "打开",
"xpack.observability.alertsDisclaimerDismissMessage": "关闭消息",
"xpack.observability.alertsDisclaimerLinkText": "反馈",
"xpack.observability.alertsDisclaimerText": "此功能处于技术预览状态在未来版本中可能会更改或完全移除。Elastic 将尽最大努力来修复任何问题,但处于技术预览状态的功能不受正式 GA 功能支持 SLA 的约束。提供{feedback}。",
"xpack.observability.alertsDisclaimerTitle": "技术预览",
"xpack.observability.alertsFlyout.actualValueLabel": "实际值",
"xpack.observability.alertsFlyout.documentSummaryTitle": "文档摘要",
"xpack.observability.alertsFlyout.durationLabel": "持续时间",

View file

@ -31,9 +31,7 @@ const mockPlugin = {
timefilter: { timefilter: { setTime: () => {}, getTime: () => ({}) } },
},
},
observability: {
isAlertingExperienceEnabled: () => false,
},
observability: {},
};
const mockEmbeddable = embeddablePluginMock.createStartContract();

View file

@ -101,10 +101,6 @@ export function ObservabilityAlertsCommonProvider({
return await find.allByCssSelector('.euiDataGridRowCell input[type="checkbox"]:enabled');
};
const getExperimentalDisclaimer = async () => {
return testSubjects.existOrFail('o11yExperimentalDisclaimer');
};
const getTableCellsInRows = async () => {
const columnHeaders = await getTableColumnHeaders();
if (columnHeaders.length <= 0) {
@ -338,7 +334,6 @@ export function ObservabilityAlertsCommonProvider({
openActionsMenuForRow,
getTimeRange,
navigateWithoutFilter,
getExperimentalDisclaimer,
getActionsButtonByIndex,
viewRuleDetailsButtonClick,
viewRuleDetailsLinkClick,

View file

@ -11,7 +11,6 @@ export default function ({ loadTestFile }: FtrProviderContext) {
describe('ObservabilityApp', function () {
loadTestFile(require.resolve('./pages/alerts'));
loadTestFile(require.resolve('./pages/alerts/add_to_case'));
loadTestFile(require.resolve('./pages/alerts/alert_disclaimer'));
loadTestFile(require.resolve('./pages/alerts/alert_status'));
loadTestFile(require.resolve('./pages/alerts/pagination'));
loadTestFile(require.resolve('./pages/alerts/rule_stats'));

View file

@ -1,42 +0,0 @@
/*
* 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 expect from '@kbn/expect';
import { FtrProviderContext } from '../../../../ftr_provider_context';
export default ({ getService, getPageObject }: FtrProviderContext) => {
describe('Observability alert experimental disclaimer', function () {
this.tags('includeFirefox');
const observability = getService('observability');
const esArchiver = getService('esArchiver');
const testSubjects = getService('testSubjects');
before(async () => {
await esArchiver.load('x-pack/test/functional/es_archives/observability/alerts');
await esArchiver.load('x-pack/test/functional/es_archives/infra/metrics_and_logs');
await observability.alerts.common.navigateWithoutFilter();
});
after(async () => {
await esArchiver.unload('x-pack/test/functional/es_archives/infra/metrics_and_logs');
await esArchiver.unload('x-pack/test/functional/es_archives/observability/alerts');
});
it('Shows experimental disclaimer', async () => {
await observability.alerts.common.getExperimentalDisclaimer();
});
it('Dismiss experimental disclaimer', async () => {
await testSubjects.click('o11yExperimentalDisclaimerDismissBtn');
const o11yExperimentalDisclaimer = await testSubjects.exists('o11yExperimentalDisclaimer');
expect(o11yExperimentalDisclaimer).not.to.be(null);
});
});
};

View file

@ -58,8 +58,7 @@ export default ({ getService }: FtrProviderContext) => {
});
describe('Feature flag', () => {
// Related to the config inside x-pack/test/observability_functional/with_rac_write.config.ts
it('Link point to O11y Rules pages by default or when "xpack.observability.unsafe.rules.enabled: true"', async () => {
it('Link point to O11y Rules pages by default', async () => {
const manageRulesPageHref = await observability.alerts.rulesPage.getManageRulesPageHref();
expect(new URL(manageRulesPageHref).pathname).equal('/app/observability/alerts/rules');
});