Skip to content

Commit

Permalink
[RAM] add observability feature for server less (elastic#168636)
Browse files Browse the repository at this point in the history
## Summary

FIX => elastic#168034


### Checklist

- [ ] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios

---------

Co-authored-by: mgiota <[email protected]>
Co-authored-by: kibanamachine <[email protected]>
  • Loading branch information
3 people authored and delanni committed Nov 6, 2023
1 parent 9cecf10 commit 02e744f
Show file tree
Hide file tree
Showing 64 changed files with 787 additions and 85 deletions.
5 changes: 5 additions & 0 deletions config/serverless.oblt.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ xpack.serverless.plugin.developer.projectSwitcher.currentType: 'observability'
## Disable adding the component template `.fleet_agent_id_verification-1` to every index template for each datastream for each integration
xpack.fleet.agentIdVerificationEnabled: false

## Enable the capability for the observability feature ID in the serverless environment to take ownership of the rules.
## The value need to be a featureId observability Or stackAlerts Or siem
xpack.alerting.rules.overwriteProducer: 'observability'
xpack.observability.createO11yGenericFeatureId: true

## APM Serverless Onboarding flow
xpack.apm.serverlessOnboarding: true

Expand Down
7 changes: 7 additions & 0 deletions packages/kbn-rule-data-utils/src/rule_types/o11y_rules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,10 @@
*/

export const OBSERVABILITY_THRESHOLD_RULE_TYPE_ID = 'observability.rules.custom_threshold';

export enum ApmRuleType {
ErrorCount = 'apm.error_rate', // ErrorRate was renamed to ErrorCount but the key is kept as `error_rate` for backwards-compat.
TransactionErrorRate = 'apm.transaction_error_rate',
TransactionDuration = 'apm.transaction_duration',
Anomaly = 'apm.anomaly',
}
7 changes: 7 additions & 0 deletions x-pack/plugins/alerting/server/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,13 @@ const rulesSchema = schema.object({
enforce: schema.boolean({ defaultValue: false }), // if enforce is false, only warnings will be shown
}),
maxScheduledPerMinute: schema.number({ defaultValue: 10000, max: 10000, min: 0 }),
overwriteProducer: schema.maybe(
schema.oneOf([
schema.literal('observability'),
schema.literal('siem'),
schema.literal('stackAlerts'),
])
),
run: schema.object({
timeout: schema.maybe(schema.string({ validate: validateDurationSchema })),
actions: schema.object({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { ILicenseState } from './license_state';
import { licenseStateMock } from './license_state.mock';
import { schema } from '@kbn/config-schema';
import { createGetAlertIndicesAliasFn } from './create_get_alert_indices_alias';
import { AlertingConfig } from '../config';

describe('createGetAlertIndicesAliasFn', () => {
const logger = loggingSystemMock.create().get();
Expand All @@ -23,6 +24,7 @@ describe('createGetAlertIndicesAliasFn', () => {
const inMemoryMetrics = inMemoryMetricsMock.create();

const ruleTypeRegistryParams: ConstructorOptions = {
config: {} as AlertingConfig,
logger,
taskManager,
taskRunnerFactory: new TaskRunnerFactory(),
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/alerting/server/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,7 @@ export class AlertingPlugin {
}

const ruleTypeRegistry = new RuleTypeRegistry({
config: this.config,
logger: this.logger,
taskManager: plugins.taskManager,
taskRunnerFactory: this.taskRunnerFactory,
Expand Down
59 changes: 59 additions & 0 deletions x-pack/plugins/alerting/server/rule_type_registry.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { inMemoryMetricsMock } from './monitoring/in_memory_metrics.mock';
import { alertsServiceMock } from './alerts_service/alerts_service.mock';
import { schema } from '@kbn/config-schema';
import { RecoveredActionGroupId } from '../common';
import { AlertingConfig } from './config';

const logger = loggingSystemMock.create().get();
let mockedLicenseState: jest.Mocked<ILicenseState>;
Expand All @@ -30,6 +31,7 @@ beforeEach(() => {
jest.clearAllMocks();
mockedLicenseState = licenseStateMock.create();
ruleTypeRegistryParams = {
config: {} as AlertingConfig,
logger,
taskManager,
taskRunnerFactory: new TaskRunnerFactory(),
Expand Down Expand Up @@ -582,6 +584,63 @@ describe('Create Lifecycle', () => {

expect(alertsService.register).not.toHaveBeenCalled();
});

test('registers rule with no overwrite on producer', () => {
const ruleType: RuleType<never, never, never, never, never, 'default', 'recovered', {}> = {
id: 'test',
name: 'Test',
actionGroups: [
{
id: 'default',
name: 'Default',
},
],
defaultActionGroupId: 'default',
minimumLicenseRequired: 'basic',
isExportable: true,
executor: jest.fn(),
category: 'test',
producer: 'alerts',
ruleTaskTimeout: '20m',
validate: {
params: { validate: (params) => params },
},
};
const registry = new RuleTypeRegistry(ruleTypeRegistryParams);
registry.register(ruleType);
expect(registry.get('test').producer).toEqual('alerts');
});
});

describe('register() with overwriteProducer', () => {
test('registers rule and overwrite producer', () => {
const ruleType: RuleType<never, never, never, never, never, 'default', 'recovered', {}> = {
id: 'test',
name: 'Test',
actionGroups: [
{
id: 'default',
name: 'Default',
},
],
defaultActionGroupId: 'default',
minimumLicenseRequired: 'basic',
isExportable: true,
executor: jest.fn(),
category: 'test',
producer: 'alerts',
ruleTaskTimeout: '20m',
validate: {
params: { validate: (params) => params },
},
};
const registry = new RuleTypeRegistry({
...ruleTypeRegistryParams,
config: { rules: { overwriteProducer: 'observability' } } as unknown as AlertingConfig,
});
registry.register(ruleType);
expect(registry.get('test').producer).toEqual('observability');
});
});

describe('get()', () => {
Expand Down
11 changes: 9 additions & 2 deletions x-pack/plugins/alerting/server/rule_type_registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,10 @@ import { InMemoryMetrics } from './monitoring';
import { AlertingRulesConfig } from '.';
import { AlertsService } from './alerts_service/alerts_service';
import { getRuleTypeIdValidLegacyConsumers } from './rule_type_registry_deprecated_consumers';
import { AlertingConfig } from './config';

export interface ConstructorOptions {
config: AlertingConfig;
logger: Logger;
taskManager: TaskManagerSetupContract;
taskRunnerFactory: TaskRunnerFactory;
Expand Down Expand Up @@ -148,6 +150,7 @@ export type UntypedNormalizedRuleType = NormalizedRuleType<
>;

export class RuleTypeRegistry {
private readonly config: AlertingConfig;
private readonly logger: Logger;
private readonly taskManager: TaskManagerSetupContract;
private readonly ruleTypes: Map<string, UntypedNormalizedRuleType> = new Map();
Expand All @@ -159,6 +162,7 @@ export class RuleTypeRegistry {
private readonly alertsService: AlertsService | null;

constructor({
config,
logger,
taskManager,
taskRunnerFactory,
Expand All @@ -168,6 +172,7 @@ export class RuleTypeRegistry {
inMemoryMetrics,
alertsService,
}: ConstructorOptions) {
this.config = config;
this.logger = logger;
this.taskManager = taskManager;
this.taskRunnerFactory = taskRunnerFactory;
Expand Down Expand Up @@ -277,7 +282,7 @@ export class RuleTypeRegistry {
ActionGroupIds,
RecoveryActionGroupId,
AlertData
>(ruleType);
>(ruleType, this.config);

this.ruleTypes.set(
ruleTypeIdSchema.validate(ruleType.id),
Expand Down Expand Up @@ -457,7 +462,8 @@ function augmentActionGroupsWithReserved<
ActionGroupIds,
RecoveryActionGroupId,
AlertData
>
>,
config: AlertingConfig
): NormalizedRuleType<
Params,
ExtractedParams,
Expand Down Expand Up @@ -505,6 +511,7 @@ function augmentActionGroupsWithReserved<

return {
...ruleType,
...(config?.rules?.overwriteProducer ? { producer: config.rules.overwriteProducer } : {}),
actionGroups: [...actionGroups, ...reservedActionGroups],
recoveryActionGroup: recoveryActionGroup ?? RecoveredActionGroup,
validLegacyConsumers: getRuleTypeIdValidLegacyConsumers(id),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { licensingMock } from '@kbn/licensing-plugin/server/mocks';
import { isRuleExportable } from './is_rule_exportable';
import { inMemoryMetricsMock } from '../monitoring/in_memory_metrics.mock';
import { loggingSystemMock } from '@kbn/core/server/mocks';
import { AlertingConfig } from '../config';

let ruleTypeRegistryParams: ConstructorOptions;
let logger: MockedLogger;
Expand All @@ -27,6 +28,7 @@ beforeEach(() => {
mockedLicenseState = licenseStateMock.create();
logger = loggerMock.create();
ruleTypeRegistryParams = {
config: {} as AlertingConfig,
logger: loggingSystemMock.create().get(),
taskManager,
alertsService: null,
Expand Down
8 changes: 1 addition & 7 deletions x-pack/plugins/apm/common/rules/apm_rule_types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import type { ActionGroup } from '@kbn/alerting-plugin/common';
import { formatDurationFromTimeUnitChar } from '@kbn/observability-plugin/common';
import { ML_ANOMALY_SEVERITY } from '@kbn/ml-anomaly-utils/anomaly_severity';
import { ML_ANOMALY_THRESHOLD } from '@kbn/ml-anomaly-utils/anomaly_threshold';
import { ApmRuleType } from '@kbn/rule-data-utils';
import {
ERROR_GROUP_ID,
ERROR_GROUP_NAME,
Expand All @@ -28,13 +29,6 @@ import { getEnvironmentLabel } from '../environment_filter_values';

export const APM_SERVER_FEATURE_ID = 'apm';

export enum ApmRuleType {
ErrorCount = 'apm.error_rate', // ErrorRate was renamed to ErrorCount but the key is kept as `error_rate` for backwards-compat.
TransactionErrorRate = 'apm.transaction_error_rate',
TransactionDuration = 'apm.transaction_duration',
Anomaly = 'apm.anomaly',
}

export enum AggregationType {
Avg = 'avg',
P95 = '95th',
Expand Down
2 changes: 1 addition & 1 deletion x-pack/plugins/apm/common/rules/get_all_groupby_fields.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*/

import { union } from 'lodash';
import { ApmRuleType } from './apm_rule_types';
import { ApmRuleType } from '@kbn/rule-data-utils';
import {
SERVICE_ENVIRONMENT,
SERVICE_NAME,
Expand Down
3 changes: 2 additions & 1 deletion x-pack/plugins/apm/common/rules/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@

import { schema, TypeOf } from '@kbn/config-schema';
import { ML_ANOMALY_SEVERITY } from '@kbn/ml-anomaly-utils/anomaly_severity';
import { AggregationType, ApmRuleType } from './apm_rule_types';
import { ApmRuleType } from '@kbn/rule-data-utils';
import { AggregationType } from './apm_rule_types';

export const searchConfigurationSchema = schema.object({
query: schema.object({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,12 @@

import { i18n } from '@kbn/i18n';
import { lazy } from 'react';
import { ALERT_REASON } from '@kbn/rule-data-utils';
import { ALERT_REASON, ApmRuleType } from '@kbn/rule-data-utils';
import type { ObservabilityRuleTypeRegistry } from '@kbn/observability-plugin/public';
import {
getAlertUrlErrorCount,
getAlertUrlTransaction,
} from '../../../../common/utils/formatters';
import { ApmRuleType } from '../../../../common/rules/apm_rule_types';
import {
anomalyMessage,
errorCountMessage,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,8 @@

import React, { useCallback, useMemo } from 'react';
import { useKibana } from '@kbn/kibana-react-plugin/public';
import {
ApmRuleType,
APM_SERVER_FEATURE_ID,
} from '../../../../../common/rules/apm_rule_types';
import { ApmRuleType } from '@kbn/rule-data-utils';
import { APM_SERVER_FEATURE_ID } from '../../../../../common/rules/apm_rule_types';
import { getInitialAlertValues } from '../../utils/get_initial_alert_values';
import { ApmPluginStartDeps } from '../../../../plugin';
import { useServiceName } from '../../../../hooks/use_service_name';
Expand Down Expand Up @@ -70,6 +68,7 @@ export function AlertingFlyout(props: Props) {
start,
end,
} as AlertMetadata,
useRuleProducer: true,
}),
/* eslint-disable-next-line react-hooks/exhaustive-deps */
[
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,8 @@
*/

import { getInitialAlertValues } from './get_initial_alert_values';
import {
ApmRuleType,
RULE_TYPES_CONFIG,
} from '../../../../common/rules/apm_rule_types';
import { RULE_TYPES_CONFIG } from '../../../../common/rules/apm_rule_types';
import { ApmRuleType } from '@kbn/rule-data-utils';

test('handles null rule type and undefined service name', () => {
expect(getInitialAlertValues(null, undefined)).toEqual({ tags: ['apm'] });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,8 @@
* 2.0.
*/

import {
ApmRuleType,
RULE_TYPES_CONFIG,
} from '../../../../common/rules/apm_rule_types';
import { ApmRuleType } from '@kbn/rule-data-utils';
import { RULE_TYPES_CONFIG } from '../../../../common/rules/apm_rule_types';

export function getInitialAlertValues(
ruleType: ApmRuleType | null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ export function AlertsOverview() {
}
id={'service-overview-alerts'}
configurationId={AlertConsumers.OBSERVABILITY}
featureIds={[AlertConsumers.APM]}
featureIds={[AlertConsumers.APM, AlertConsumers.OBSERVABILITY]}
query={esQuery}
showAlertStatusWithFlapping
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import React, { useState } from 'react';
import { ApmRuleType } from '../../../../../common/rules/apm_rule_types';
import { ApmRuleType } from '@kbn/rule-data-utils';
import { AlertingFlyout } from '../../../alerting/ui_components/alerting_flyout';
import { useApmPluginContext } from '../../../../context/apm_plugin/use_apm_plugin_context';

Expand Down
6 changes: 2 additions & 4 deletions x-pack/plugins/apm/server/feature.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,8 @@ import {
} from '@kbn/licensing-plugin/server';

import { APM_INDEX_SETTINGS_SAVED_OBJECT_TYPE } from '@kbn/apm-data-access-plugin/server/saved_objects/apm_indices';
import {
ApmRuleType,
APM_SERVER_FEATURE_ID,
} from '../common/rules/apm_rule_types';
import { ApmRuleType } from '@kbn/rule-data-utils';
import { APM_SERVER_FEATURE_ID } from '../common/rules/apm_rule_types';

const ruleTypes = Object.values(ApmRuleType);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
ALERT_EVALUATION_VALUE,
ALERT_REASON,
ALERT_SEVERITY,
ApmRuleType,
} from '@kbn/rule-data-utils';
import { createLifecycleRuleTypeFactory } from '@kbn/rule-registry-plugin/server';
import { addSpaceIdToPath } from '@kbn/spaces-plugin/common';
Expand All @@ -43,7 +44,7 @@ import {
} from '../../../../../common/environment_filter_values';
import {
ANOMALY_ALERT_SEVERITY_TYPES,
ApmRuleType,
APM_SERVER_FEATURE_ID,
formatAnomalyReason,
RULE_TYPES_CONFIG,
} from '../../../../../common/rules/apm_rule_types';
Expand Down Expand Up @@ -94,7 +95,7 @@ export function registerAnomalyRuleType({
],
},
category: DEFAULT_APP_CATEGORIES.observability.id,
producer: 'apm',
producer: APM_SERVER_FEATURE_ID,
minimumLicenseRequired: 'basic',
isExportable: true,
executor: async ({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
termQuery,
} from '@kbn/observability-plugin/server';
import { ProcessorEvent } from '@kbn/observability-plugin/common';
import { ApmRuleType } from '@kbn/rule-data-utils';
import {
ERROR_GROUP_ID,
PROCESSOR_EVENT,
Expand All @@ -21,7 +22,6 @@ import { environmentQuery } from '../../../../../common/utils/environment_query'
import { APMEventClient } from '../../../../lib/helpers/create_es_client/create_apm_event_client';
import { getGroupByTerms } from '../utils/get_groupby_terms';
import { getAllGroupByFields } from '../../../../../common/rules/get_all_groupby_fields';
import { ApmRuleType } from '../../../../../common/rules/apm_rule_types';
import {
BarSeriesDataMap,
getFilteredBarSeries,
Expand Down
Loading

0 comments on commit 02e744f

Please sign in to comment.