mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[Alerting] revert the revert of Enforces typing of Alert's ActionGroups
(#87382)
The https://github.com/elastic/kibana/pull/86761 PR was reverted due to a small typing issue.
This PR reverts that revert and adds a commit to address the issue: 9e4ab2002c
.
This commit is contained in:
parent
8ead390813
commit
b99ca969e0
69 changed files with 1011 additions and 329 deletions
|
@ -10,15 +10,16 @@ export const ALERTING_EXAMPLE_APP_ID = 'AlertingExample';
|
|||
|
||||
// always firing
|
||||
export const DEFAULT_INSTANCES_TO_GENERATE = 5;
|
||||
export interface AlwaysFiringThresholds {
|
||||
small?: number;
|
||||
medium?: number;
|
||||
large?: number;
|
||||
}
|
||||
export interface AlwaysFiringParams extends AlertTypeParams {
|
||||
instances?: number;
|
||||
thresholds?: {
|
||||
small?: number;
|
||||
medium?: number;
|
||||
large?: number;
|
||||
};
|
||||
thresholds?: AlwaysFiringThresholds;
|
||||
}
|
||||
export type AlwaysFiringActionGroupIds = keyof AlwaysFiringParams['thresholds'];
|
||||
export type AlwaysFiringActionGroupIds = keyof AlwaysFiringThresholds;
|
||||
|
||||
// Astros
|
||||
export enum Craft {
|
||||
|
|
|
@ -133,8 +133,10 @@ export const AlwaysFiringExpression: React.FunctionComponent<
|
|||
};
|
||||
|
||||
interface TShirtSelectorProps {
|
||||
actionGroup?: ActionGroupWithCondition<number>;
|
||||
setTShirtThreshold: (actionGroup: ActionGroupWithCondition<number>) => void;
|
||||
actionGroup?: ActionGroupWithCondition<number, AlwaysFiringActionGroupIds>;
|
||||
setTShirtThreshold: (
|
||||
actionGroup: ActionGroupWithCondition<number, AlwaysFiringActionGroupIds>
|
||||
) => void;
|
||||
}
|
||||
const TShirtSelector = ({ actionGroup, setTShirtThreshold }: TShirtSelectorProps) => {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
|
|
|
@ -11,6 +11,7 @@ import {
|
|||
DEFAULT_INSTANCES_TO_GENERATE,
|
||||
ALERTING_EXAMPLE_APP_ID,
|
||||
AlwaysFiringParams,
|
||||
AlwaysFiringActionGroupIds,
|
||||
} from '../../common/constants';
|
||||
|
||||
type ActionGroups = 'small' | 'medium' | 'large';
|
||||
|
@ -39,7 +40,8 @@ export const alertType: AlertType<
|
|||
AlwaysFiringParams,
|
||||
{ count?: number },
|
||||
{ triggerdOnCycle: number },
|
||||
never
|
||||
never,
|
||||
AlwaysFiringActionGroupIds
|
||||
> = {
|
||||
id: 'example.always-firing',
|
||||
name: 'Always firing',
|
||||
|
|
|
@ -41,7 +41,10 @@ function getCraftFilter(craft: string) {
|
|||
export const alertType: AlertType<
|
||||
{ outerSpaceCapacity: number; craft: string; op: string },
|
||||
{ peopleInSpace: number },
|
||||
{ craft: string }
|
||||
{ craft: string },
|
||||
never,
|
||||
'default',
|
||||
'hasLandedBackOnEarth'
|
||||
> = {
|
||||
id: 'example.people-in-space',
|
||||
name: 'People In Space Right Now',
|
||||
|
|
|
@ -142,8 +142,41 @@ This example receives server and threshold as parameters. It will read the CPU u
|
|||
|
||||
```typescript
|
||||
import { schema } from '@kbn/config-schema';
|
||||
import {
|
||||
Alert,
|
||||
AlertTypeParams,
|
||||
AlertTypeState,
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext
|
||||
} from 'x-pack/plugins/alerts/common';
|
||||
...
|
||||
server.newPlatform.setup.plugins.alerts.registerType({
|
||||
interface MyAlertTypeParams extends AlertTypeParams {
|
||||
server: string;
|
||||
threshold: number;
|
||||
}
|
||||
|
||||
interface MyAlertTypeState extends AlertTypeState {
|
||||
lastChecked: number;
|
||||
}
|
||||
|
||||
interface MyAlertTypeInstanceState extends AlertInstanceState {
|
||||
cpuUsage: number;
|
||||
}
|
||||
|
||||
interface MyAlertTypeInstanceContext extends AlertInstanceContext {
|
||||
server: string;
|
||||
hasCpuUsageIncreased: boolean;
|
||||
}
|
||||
|
||||
type MyAlertTypeActionGroups = 'default' | 'warning';
|
||||
|
||||
const myAlertType: AlertType<
|
||||
MyAlertTypeParams,
|
||||
MyAlertTypeState,
|
||||
MyAlertTypeInstanceState,
|
||||
MyAlertTypeInstanceContext,
|
||||
MyAlertTypeActionGroups
|
||||
> = {
|
||||
id: 'my-alert-type',
|
||||
name: 'My alert type',
|
||||
validate: {
|
||||
|
@ -180,7 +213,7 @@ server.newPlatform.setup.plugins.alerts.registerType({
|
|||
services,
|
||||
params,
|
||||
state,
|
||||
}: AlertExecutorOptions) {
|
||||
}: AlertExecutorOptions<MyAlertTypeParams, MyAlertTypeState, MyAlertTypeInstanceState, MyAlertTypeInstanceContext, MyAlertTypeActionGroups>) {
|
||||
// Let's assume params is { server: 'server_1', threshold: 0.8 }
|
||||
const { server, threshold } = params;
|
||||
|
||||
|
@ -219,7 +252,9 @@ server.newPlatform.setup.plugins.alerts.registerType({
|
|||
};
|
||||
},
|
||||
producer: 'alerting',
|
||||
});
|
||||
};
|
||||
|
||||
server.newPlatform.setup.plugins.alerts.registerType(myAlertType);
|
||||
```
|
||||
|
||||
This example only receives threshold as a parameter. It will read the CPU usage of all the servers and schedule individual actions if the reading for a server is greater than the threshold. This is a better implementation than above as only one query is performed for all the servers instead of one query per server.
|
||||
|
|
|
@ -5,19 +5,29 @@
|
|||
*/
|
||||
|
||||
import { LicenseType } from '../../licensing/common/types';
|
||||
import { RecoveredActionGroupId, DefaultActionGroupId } from './builtin_action_groups';
|
||||
|
||||
export interface AlertType {
|
||||
export interface AlertType<
|
||||
ActionGroupIds extends Exclude<string, RecoveredActionGroupId> = DefaultActionGroupId,
|
||||
RecoveryActionGroupId extends string = RecoveredActionGroupId
|
||||
> {
|
||||
id: string;
|
||||
name: string;
|
||||
actionGroups: ActionGroup[];
|
||||
recoveryActionGroup: ActionGroup;
|
||||
actionGroups: Array<ActionGroup<ActionGroupIds>>;
|
||||
recoveryActionGroup: ActionGroup<RecoveryActionGroupId>;
|
||||
actionVariables: string[];
|
||||
defaultActionGroupId: ActionGroup['id'];
|
||||
defaultActionGroupId: ActionGroupIds;
|
||||
producer: string;
|
||||
minimumLicenseRequired: LicenseType;
|
||||
}
|
||||
|
||||
export interface ActionGroup {
|
||||
id: string;
|
||||
export interface ActionGroup<ActionGroupIds extends string> {
|
||||
id: ActionGroupIds;
|
||||
name: string;
|
||||
}
|
||||
|
||||
export type ActionGroupIdsOf<T> = T extends ActionGroup<infer groups>
|
||||
? groups
|
||||
: T extends Readonly<ActionGroup<infer groups>>
|
||||
? groups
|
||||
: never;
|
||||
|
|
|
@ -6,13 +6,27 @@
|
|||
import { i18n } from '@kbn/i18n';
|
||||
import { ActionGroup } from './alert_type';
|
||||
|
||||
export const RecoveredActionGroup: Readonly<ActionGroup> = {
|
||||
export type DefaultActionGroupId = 'default';
|
||||
|
||||
export type RecoveredActionGroupId = typeof RecoveredActionGroup['id'];
|
||||
export const RecoveredActionGroup: Readonly<ActionGroup<'recovered'>> = Object.freeze({
|
||||
id: 'recovered',
|
||||
name: i18n.translate('xpack.alerts.builtinActionGroups.recovered', {
|
||||
defaultMessage: 'Recovered',
|
||||
}),
|
||||
};
|
||||
});
|
||||
|
||||
export function getBuiltinActionGroups(customRecoveryGroup?: ActionGroup): ActionGroup[] {
|
||||
return [customRecoveryGroup ?? Object.freeze(RecoveredActionGroup)];
|
||||
export type ReservedActionGroups<RecoveryActionGroupId extends string> =
|
||||
| RecoveryActionGroupId
|
||||
| RecoveredActionGroupId;
|
||||
|
||||
export type WithoutReservedActionGroups<
|
||||
ActionGroupIds extends string,
|
||||
RecoveryActionGroupId extends string
|
||||
> = ActionGroupIds extends ReservedActionGroups<RecoveryActionGroupId> ? never : ActionGroupIds;
|
||||
|
||||
export function getBuiltinActionGroups<RecoveryActionGroupId extends string>(
|
||||
customRecoveryGroup?: ActionGroup<RecoveryActionGroupId>
|
||||
): [ActionGroup<ReservedActionGroups<RecoveryActionGroupId>>] {
|
||||
return [customRecoveryGroup ?? RecoveredActionGroup];
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
import sinon from 'sinon';
|
||||
import { AlertInstance } from './alert_instance';
|
||||
import { AlertInstanceState, AlertInstanceContext, DefaultActionGroupId } from '../../common';
|
||||
|
||||
let clock: sinon.SinonFakeTimers;
|
||||
|
||||
|
@ -17,12 +18,20 @@ afterAll(() => clock.restore());
|
|||
|
||||
describe('hasScheduledActions()', () => {
|
||||
test('defaults to false', () => {
|
||||
const alertInstance = new AlertInstance();
|
||||
const alertInstance = new AlertInstance<
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext,
|
||||
DefaultActionGroupId
|
||||
>();
|
||||
expect(alertInstance.hasScheduledActions()).toEqual(false);
|
||||
});
|
||||
|
||||
test('returns true when scheduleActions is called', () => {
|
||||
const alertInstance = new AlertInstance();
|
||||
const alertInstance = new AlertInstance<
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext,
|
||||
DefaultActionGroupId
|
||||
>();
|
||||
alertInstance.scheduleActions('default');
|
||||
expect(alertInstance.hasScheduledActions()).toEqual(true);
|
||||
});
|
||||
|
@ -30,7 +39,11 @@ describe('hasScheduledActions()', () => {
|
|||
|
||||
describe('isThrottled', () => {
|
||||
test(`should throttle when group didn't change and throttle period is still active`, () => {
|
||||
const alertInstance = new AlertInstance({
|
||||
const alertInstance = new AlertInstance<
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext,
|
||||
DefaultActionGroupId
|
||||
>({
|
||||
meta: {
|
||||
lastScheduledActions: {
|
||||
date: new Date(),
|
||||
|
@ -44,7 +57,11 @@ describe('isThrottled', () => {
|
|||
});
|
||||
|
||||
test(`shouldn't throttle when group didn't change and throttle period expired`, () => {
|
||||
const alertInstance = new AlertInstance({
|
||||
const alertInstance = new AlertInstance<
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext,
|
||||
DefaultActionGroupId
|
||||
>({
|
||||
meta: {
|
||||
lastScheduledActions: {
|
||||
date: new Date(),
|
||||
|
@ -58,7 +75,7 @@ describe('isThrottled', () => {
|
|||
});
|
||||
|
||||
test(`shouldn't throttle when group changes`, () => {
|
||||
const alertInstance = new AlertInstance({
|
||||
const alertInstance = new AlertInstance<never, never, 'default' | 'other-group'>({
|
||||
meta: {
|
||||
lastScheduledActions: {
|
||||
date: new Date(),
|
||||
|
@ -74,12 +91,20 @@ describe('isThrottled', () => {
|
|||
|
||||
describe('scheduledActionGroupOrSubgroupHasChanged()', () => {
|
||||
test('should be false if no last scheduled and nothing scheduled', () => {
|
||||
const alertInstance = new AlertInstance();
|
||||
const alertInstance = new AlertInstance<
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext,
|
||||
DefaultActionGroupId
|
||||
>();
|
||||
expect(alertInstance.scheduledActionGroupOrSubgroupHasChanged()).toEqual(false);
|
||||
});
|
||||
|
||||
test('should be false if group does not change', () => {
|
||||
const alertInstance = new AlertInstance({
|
||||
const alertInstance = new AlertInstance<
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext,
|
||||
DefaultActionGroupId
|
||||
>({
|
||||
meta: {
|
||||
lastScheduledActions: {
|
||||
date: new Date(),
|
||||
|
@ -92,7 +117,11 @@ describe('scheduledActionGroupOrSubgroupHasChanged()', () => {
|
|||
});
|
||||
|
||||
test('should be false if group and subgroup does not change', () => {
|
||||
const alertInstance = new AlertInstance({
|
||||
const alertInstance = new AlertInstance<
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext,
|
||||
DefaultActionGroupId
|
||||
>({
|
||||
meta: {
|
||||
lastScheduledActions: {
|
||||
date: new Date(),
|
||||
|
@ -106,7 +135,11 @@ describe('scheduledActionGroupOrSubgroupHasChanged()', () => {
|
|||
});
|
||||
|
||||
test('should be false if group does not change and subgroup goes from undefined to defined', () => {
|
||||
const alertInstance = new AlertInstance({
|
||||
const alertInstance = new AlertInstance<
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext,
|
||||
DefaultActionGroupId
|
||||
>({
|
||||
meta: {
|
||||
lastScheduledActions: {
|
||||
date: new Date(),
|
||||
|
@ -119,7 +152,11 @@ describe('scheduledActionGroupOrSubgroupHasChanged()', () => {
|
|||
});
|
||||
|
||||
test('should be false if group does not change and subgroup goes from defined to undefined', () => {
|
||||
const alertInstance = new AlertInstance({
|
||||
const alertInstance = new AlertInstance<
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext,
|
||||
DefaultActionGroupId
|
||||
>({
|
||||
meta: {
|
||||
lastScheduledActions: {
|
||||
date: new Date(),
|
||||
|
@ -133,13 +170,17 @@ describe('scheduledActionGroupOrSubgroupHasChanged()', () => {
|
|||
});
|
||||
|
||||
test('should be true if no last scheduled and has scheduled action', () => {
|
||||
const alertInstance = new AlertInstance();
|
||||
const alertInstance = new AlertInstance<
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext,
|
||||
DefaultActionGroupId
|
||||
>();
|
||||
alertInstance.scheduleActions('default');
|
||||
expect(alertInstance.scheduledActionGroupOrSubgroupHasChanged()).toEqual(true);
|
||||
});
|
||||
|
||||
test('should be true if group does change', () => {
|
||||
const alertInstance = new AlertInstance({
|
||||
const alertInstance = new AlertInstance<never, never, 'default' | 'penguin'>({
|
||||
meta: {
|
||||
lastScheduledActions: {
|
||||
date: new Date(),
|
||||
|
@ -152,7 +193,7 @@ describe('scheduledActionGroupOrSubgroupHasChanged()', () => {
|
|||
});
|
||||
|
||||
test('should be true if group does change and subgroup does change', () => {
|
||||
const alertInstance = new AlertInstance({
|
||||
const alertInstance = new AlertInstance<never, never, 'default' | 'penguin'>({
|
||||
meta: {
|
||||
lastScheduledActions: {
|
||||
date: new Date(),
|
||||
|
@ -166,7 +207,11 @@ describe('scheduledActionGroupOrSubgroupHasChanged()', () => {
|
|||
});
|
||||
|
||||
test('should be true if group does not change and subgroup does change', () => {
|
||||
const alertInstance = new AlertInstance({
|
||||
const alertInstance = new AlertInstance<
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext,
|
||||
DefaultActionGroupId
|
||||
>({
|
||||
meta: {
|
||||
lastScheduledActions: {
|
||||
date: new Date(),
|
||||
|
@ -182,14 +227,22 @@ describe('scheduledActionGroupOrSubgroupHasChanged()', () => {
|
|||
|
||||
describe('getScheduledActionOptions()', () => {
|
||||
test('defaults to undefined', () => {
|
||||
const alertInstance = new AlertInstance();
|
||||
const alertInstance = new AlertInstance<
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext,
|
||||
DefaultActionGroupId
|
||||
>();
|
||||
expect(alertInstance.getScheduledActionOptions()).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('unscheduleActions()', () => {
|
||||
test('makes hasScheduledActions() return false', () => {
|
||||
const alertInstance = new AlertInstance();
|
||||
const alertInstance = new AlertInstance<
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext,
|
||||
DefaultActionGroupId
|
||||
>();
|
||||
alertInstance.scheduleActions('default');
|
||||
expect(alertInstance.hasScheduledActions()).toEqual(true);
|
||||
alertInstance.unscheduleActions();
|
||||
|
@ -197,7 +250,11 @@ describe('unscheduleActions()', () => {
|
|||
});
|
||||
|
||||
test('makes getScheduledActionOptions() return undefined', () => {
|
||||
const alertInstance = new AlertInstance();
|
||||
const alertInstance = new AlertInstance<
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext,
|
||||
DefaultActionGroupId
|
||||
>();
|
||||
alertInstance.scheduleActions('default');
|
||||
expect(alertInstance.getScheduledActionOptions()).toEqual({
|
||||
actionGroup: 'default',
|
||||
|
@ -212,14 +269,22 @@ describe('unscheduleActions()', () => {
|
|||
describe('getState()', () => {
|
||||
test('returns state passed to constructor', () => {
|
||||
const state = { foo: true };
|
||||
const alertInstance = new AlertInstance({ state });
|
||||
const alertInstance = new AlertInstance<
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext,
|
||||
DefaultActionGroupId
|
||||
>({ state });
|
||||
expect(alertInstance.getState()).toEqual(state);
|
||||
});
|
||||
});
|
||||
|
||||
describe('scheduleActions()', () => {
|
||||
test('makes hasScheduledActions() return true', () => {
|
||||
const alertInstance = new AlertInstance({
|
||||
const alertInstance = new AlertInstance<
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext,
|
||||
DefaultActionGroupId
|
||||
>({
|
||||
state: { foo: true },
|
||||
meta: {
|
||||
lastScheduledActions: {
|
||||
|
@ -233,7 +298,11 @@ describe('scheduleActions()', () => {
|
|||
});
|
||||
|
||||
test('makes isThrottled() return true when throttled', () => {
|
||||
const alertInstance = new AlertInstance({
|
||||
const alertInstance = new AlertInstance<
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext,
|
||||
DefaultActionGroupId
|
||||
>({
|
||||
state: { foo: true },
|
||||
meta: {
|
||||
lastScheduledActions: {
|
||||
|
@ -247,7 +316,11 @@ describe('scheduleActions()', () => {
|
|||
});
|
||||
|
||||
test('make isThrottled() return false when throttled expired', () => {
|
||||
const alertInstance = new AlertInstance({
|
||||
const alertInstance = new AlertInstance<
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext,
|
||||
DefaultActionGroupId
|
||||
>({
|
||||
state: { foo: true },
|
||||
meta: {
|
||||
lastScheduledActions: {
|
||||
|
@ -262,7 +335,11 @@ describe('scheduleActions()', () => {
|
|||
});
|
||||
|
||||
test('makes getScheduledActionOptions() return given options', () => {
|
||||
const alertInstance = new AlertInstance({ state: { foo: true }, meta: {} });
|
||||
const alertInstance = new AlertInstance<
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext,
|
||||
DefaultActionGroupId
|
||||
>({ state: { foo: true }, meta: {} });
|
||||
alertInstance.replaceState({ otherField: true }).scheduleActions('default', { field: true });
|
||||
expect(alertInstance.getScheduledActionOptions()).toEqual({
|
||||
actionGroup: 'default',
|
||||
|
@ -272,7 +349,11 @@ describe('scheduleActions()', () => {
|
|||
});
|
||||
|
||||
test('cannot schdule for execution twice', () => {
|
||||
const alertInstance = new AlertInstance();
|
||||
const alertInstance = new AlertInstance<
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext,
|
||||
DefaultActionGroupId
|
||||
>();
|
||||
alertInstance.scheduleActions('default', { field: true });
|
||||
expect(() =>
|
||||
alertInstance.scheduleActions('default', { field: false })
|
||||
|
@ -284,7 +365,11 @@ describe('scheduleActions()', () => {
|
|||
|
||||
describe('scheduleActionsWithSubGroup()', () => {
|
||||
test('makes hasScheduledActions() return true', () => {
|
||||
const alertInstance = new AlertInstance({
|
||||
const alertInstance = new AlertInstance<
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext,
|
||||
DefaultActionGroupId
|
||||
>({
|
||||
state: { foo: true },
|
||||
meta: {
|
||||
lastScheduledActions: {
|
||||
|
@ -300,7 +385,11 @@ describe('scheduleActionsWithSubGroup()', () => {
|
|||
});
|
||||
|
||||
test('makes isThrottled() return true when throttled and subgroup is the same', () => {
|
||||
const alertInstance = new AlertInstance({
|
||||
const alertInstance = new AlertInstance<
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext,
|
||||
DefaultActionGroupId
|
||||
>({
|
||||
state: { foo: true },
|
||||
meta: {
|
||||
lastScheduledActions: {
|
||||
|
@ -317,7 +406,11 @@ describe('scheduleActionsWithSubGroup()', () => {
|
|||
});
|
||||
|
||||
test('makes isThrottled() return true when throttled and last schedule had no subgroup', () => {
|
||||
const alertInstance = new AlertInstance({
|
||||
const alertInstance = new AlertInstance<
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext,
|
||||
DefaultActionGroupId
|
||||
>({
|
||||
state: { foo: true },
|
||||
meta: {
|
||||
lastScheduledActions: {
|
||||
|
@ -333,7 +426,11 @@ describe('scheduleActionsWithSubGroup()', () => {
|
|||
});
|
||||
|
||||
test('makes isThrottled() return false when throttled and subgroup is the different', () => {
|
||||
const alertInstance = new AlertInstance({
|
||||
const alertInstance = new AlertInstance<
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext,
|
||||
DefaultActionGroupId
|
||||
>({
|
||||
state: { foo: true },
|
||||
meta: {
|
||||
lastScheduledActions: {
|
||||
|
@ -350,7 +447,11 @@ describe('scheduleActionsWithSubGroup()', () => {
|
|||
});
|
||||
|
||||
test('make isThrottled() return false when throttled expired', () => {
|
||||
const alertInstance = new AlertInstance({
|
||||
const alertInstance = new AlertInstance<
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext,
|
||||
DefaultActionGroupId
|
||||
>({
|
||||
state: { foo: true },
|
||||
meta: {
|
||||
lastScheduledActions: {
|
||||
|
@ -367,7 +468,11 @@ describe('scheduleActionsWithSubGroup()', () => {
|
|||
});
|
||||
|
||||
test('makes getScheduledActionOptions() return given options', () => {
|
||||
const alertInstance = new AlertInstance({ state: { foo: true }, meta: {} });
|
||||
const alertInstance = new AlertInstance<
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext,
|
||||
DefaultActionGroupId
|
||||
>({ state: { foo: true }, meta: {} });
|
||||
alertInstance
|
||||
.replaceState({ otherField: true })
|
||||
.scheduleActionsWithSubGroup('default', 'subgroup', { field: true });
|
||||
|
@ -380,7 +485,11 @@ describe('scheduleActionsWithSubGroup()', () => {
|
|||
});
|
||||
|
||||
test('cannot schdule for execution twice', () => {
|
||||
const alertInstance = new AlertInstance();
|
||||
const alertInstance = new AlertInstance<
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext,
|
||||
DefaultActionGroupId
|
||||
>();
|
||||
alertInstance.scheduleActionsWithSubGroup('default', 'subgroup', { field: true });
|
||||
expect(() =>
|
||||
alertInstance.scheduleActionsWithSubGroup('default', 'subgroup', { field: false })
|
||||
|
@ -390,7 +499,11 @@ describe('scheduleActionsWithSubGroup()', () => {
|
|||
});
|
||||
|
||||
test('cannot schdule for execution twice with different subgroups', () => {
|
||||
const alertInstance = new AlertInstance();
|
||||
const alertInstance = new AlertInstance<
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext,
|
||||
DefaultActionGroupId
|
||||
>();
|
||||
alertInstance.scheduleActionsWithSubGroup('default', 'subgroup', { field: true });
|
||||
expect(() =>
|
||||
alertInstance.scheduleActionsWithSubGroup('default', 'subgroup', { field: false })
|
||||
|
@ -400,7 +513,11 @@ describe('scheduleActionsWithSubGroup()', () => {
|
|||
});
|
||||
|
||||
test('cannot schdule for execution twice whether there are subgroups', () => {
|
||||
const alertInstance = new AlertInstance();
|
||||
const alertInstance = new AlertInstance<
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext,
|
||||
DefaultActionGroupId
|
||||
>();
|
||||
alertInstance.scheduleActions('default', { field: true });
|
||||
expect(() =>
|
||||
alertInstance.scheduleActionsWithSubGroup('default', 'subgroup', { field: false })
|
||||
|
@ -412,7 +529,11 @@ describe('scheduleActionsWithSubGroup()', () => {
|
|||
|
||||
describe('replaceState()', () => {
|
||||
test('replaces previous state', () => {
|
||||
const alertInstance = new AlertInstance({ state: { foo: true } });
|
||||
const alertInstance = new AlertInstance<
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext,
|
||||
DefaultActionGroupId
|
||||
>({ state: { foo: true } });
|
||||
alertInstance.replaceState({ bar: true });
|
||||
expect(alertInstance.getState()).toEqual({ bar: true });
|
||||
alertInstance.replaceState({ baz: true });
|
||||
|
@ -422,7 +543,11 @@ describe('replaceState()', () => {
|
|||
|
||||
describe('updateLastScheduledActions()', () => {
|
||||
test('replaces previous lastScheduledActions', () => {
|
||||
const alertInstance = new AlertInstance({ meta: {} });
|
||||
const alertInstance = new AlertInstance<
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext,
|
||||
DefaultActionGroupId
|
||||
>({ meta: {} });
|
||||
alertInstance.updateLastScheduledActions('default');
|
||||
expect(alertInstance.toJSON()).toEqual({
|
||||
state: {},
|
||||
|
@ -438,7 +563,11 @@ describe('updateLastScheduledActions()', () => {
|
|||
|
||||
describe('toJSON', () => {
|
||||
test('only serializes state and meta', () => {
|
||||
const alertInstance = new AlertInstance({
|
||||
const alertInstance = new AlertInstance<
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext,
|
||||
DefaultActionGroupId
|
||||
>({
|
||||
state: { foo: true },
|
||||
meta: {
|
||||
lastScheduledActions: {
|
||||
|
@ -464,7 +593,11 @@ describe('toRaw', () => {
|
|||
},
|
||||
},
|
||||
};
|
||||
const alertInstance = new AlertInstance(raw);
|
||||
const alertInstance = new AlertInstance<
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext,
|
||||
DefaultActionGroupId
|
||||
>(raw);
|
||||
expect(alertInstance.toRaw()).toEqual(raw);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -9,15 +9,17 @@ import {
|
|||
RawAlertInstance,
|
||||
rawAlertInstance,
|
||||
AlertInstanceContext,
|
||||
DefaultActionGroupId,
|
||||
} from '../../common';
|
||||
|
||||
import { parseDuration } from '../lib';
|
||||
|
||||
interface ScheduledExecutionOptions<
|
||||
State extends AlertInstanceState,
|
||||
Context extends AlertInstanceContext
|
||||
Context extends AlertInstanceContext,
|
||||
ActionGroupIds extends string = DefaultActionGroupId
|
||||
> {
|
||||
actionGroup: string;
|
||||
actionGroup: ActionGroupIds;
|
||||
subgroup?: string;
|
||||
context: Context;
|
||||
state: State;
|
||||
|
@ -25,17 +27,19 @@ interface ScheduledExecutionOptions<
|
|||
|
||||
export type PublicAlertInstance<
|
||||
State extends AlertInstanceState = AlertInstanceState,
|
||||
Context extends AlertInstanceContext = AlertInstanceContext
|
||||
Context extends AlertInstanceContext = AlertInstanceContext,
|
||||
ActionGroupIds extends string = DefaultActionGroupId
|
||||
> = Pick<
|
||||
AlertInstance<State, Context>,
|
||||
AlertInstance<State, Context, ActionGroupIds>,
|
||||
'getState' | 'replaceState' | 'scheduleActions' | 'scheduleActionsWithSubGroup'
|
||||
>;
|
||||
|
||||
export class AlertInstance<
|
||||
State extends AlertInstanceState = AlertInstanceState,
|
||||
Context extends AlertInstanceContext = AlertInstanceContext
|
||||
Context extends AlertInstanceContext = AlertInstanceContext,
|
||||
ActionGroupIds extends string = never
|
||||
> {
|
||||
private scheduledExecutionOptions?: ScheduledExecutionOptions<State, Context>;
|
||||
private scheduledExecutionOptions?: ScheduledExecutionOptions<State, Context, ActionGroupIds>;
|
||||
private meta: AlertInstanceMeta;
|
||||
private state: State;
|
||||
|
||||
|
@ -97,14 +101,14 @@ export class AlertInstance<
|
|||
|
||||
private scheduledActionGroupIsUnchanged(
|
||||
lastScheduledActions: NonNullable<AlertInstanceMeta['lastScheduledActions']>,
|
||||
scheduledExecutionOptions: ScheduledExecutionOptions<State, Context>
|
||||
scheduledExecutionOptions: ScheduledExecutionOptions<State, Context, ActionGroupIds>
|
||||
) {
|
||||
return lastScheduledActions.group === scheduledExecutionOptions.actionGroup;
|
||||
}
|
||||
|
||||
private scheduledActionSubgroupIsUnchanged(
|
||||
lastScheduledActions: NonNullable<AlertInstanceMeta['lastScheduledActions']>,
|
||||
scheduledExecutionOptions: ScheduledExecutionOptions<State, Context>
|
||||
scheduledExecutionOptions: ScheduledExecutionOptions<State, Context, ActionGroupIds>
|
||||
) {
|
||||
return lastScheduledActions.subgroup && scheduledExecutionOptions.subgroup
|
||||
? lastScheduledActions.subgroup === scheduledExecutionOptions.subgroup
|
||||
|
@ -128,7 +132,7 @@ export class AlertInstance<
|
|||
return this.state;
|
||||
}
|
||||
|
||||
scheduleActions(actionGroup: string, context: Context = {} as Context) {
|
||||
scheduleActions(actionGroup: ActionGroupIds, context: Context = {} as Context) {
|
||||
this.ensureHasNoScheduledActions();
|
||||
this.scheduledExecutionOptions = {
|
||||
actionGroup,
|
||||
|
@ -139,7 +143,7 @@ export class AlertInstance<
|
|||
}
|
||||
|
||||
scheduleActionsWithSubGroup(
|
||||
actionGroup: string,
|
||||
actionGroup: ActionGroupIds,
|
||||
subgroup: string,
|
||||
context: Context = {} as Context
|
||||
) {
|
||||
|
@ -164,7 +168,7 @@ export class AlertInstance<
|
|||
return this;
|
||||
}
|
||||
|
||||
updateLastScheduledActions(group: string, subgroup?: string) {
|
||||
updateLastScheduledActions(group: ActionGroupIds, subgroup?: string) {
|
||||
this.meta.lastScheduledActions = { group, subgroup, date: new Date() };
|
||||
}
|
||||
|
||||
|
|
|
@ -9,11 +9,12 @@ import { AlertInstance } from './alert_instance';
|
|||
|
||||
export function createAlertInstanceFactory<
|
||||
InstanceState extends AlertInstanceState,
|
||||
InstanceContext extends AlertInstanceContext
|
||||
>(alertInstances: Record<string, AlertInstance<InstanceState, InstanceContext>>) {
|
||||
return (id: string): AlertInstance<InstanceState, InstanceContext> => {
|
||||
InstanceContext extends AlertInstanceContext,
|
||||
ActionGroupIds extends string
|
||||
>(alertInstances: Record<string, AlertInstance<InstanceState, InstanceContext, ActionGroupIds>>) {
|
||||
return (id: string): AlertInstance<InstanceState, InstanceContext, ActionGroupIds> => {
|
||||
if (!alertInstances[id]) {
|
||||
alertInstances[id] = new AlertInstance<InstanceState, InstanceContext>();
|
||||
alertInstances[id] = new AlertInstance<InstanceState, InstanceContext, ActionGroupIds>();
|
||||
}
|
||||
|
||||
return alertInstances[id];
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
import { TaskRunnerFactory } from './task_runner';
|
||||
import { AlertTypeRegistry, ConstructorOptions } from './alert_type_registry';
|
||||
import { AlertType } from './types';
|
||||
import { ActionGroup, AlertType } from './types';
|
||||
import { taskManagerMock } from '../../task_manager/server/mocks';
|
||||
import { ILicenseState } from './lib/license_state';
|
||||
import { licenseStateMock } from './lib/license_state.mock';
|
||||
|
@ -55,7 +55,7 @@ describe('has()', () => {
|
|||
|
||||
describe('register()', () => {
|
||||
test('throws if AlertType Id contains invalid characters', () => {
|
||||
const alertType: AlertType = {
|
||||
const alertType: AlertType<never, never, never, never, 'default'> = {
|
||||
id: 'test',
|
||||
name: 'Test',
|
||||
actionGroups: [
|
||||
|
@ -87,7 +87,7 @@ describe('register()', () => {
|
|||
});
|
||||
|
||||
test('throws if AlertType Id isnt a string', () => {
|
||||
const alertType: AlertType = {
|
||||
const alertType: AlertType<never, never, never, never, 'default'> = {
|
||||
id: (123 as unknown) as string,
|
||||
name: 'Test',
|
||||
actionGroups: [
|
||||
|
@ -109,7 +109,7 @@ describe('register()', () => {
|
|||
});
|
||||
|
||||
test('throws if AlertType action groups contains reserved group id', () => {
|
||||
const alertType: AlertType = {
|
||||
const alertType: AlertType<never, never, never, never, 'default' | 'NotReserved'> = {
|
||||
id: 'test',
|
||||
name: 'Test',
|
||||
actionGroups: [
|
||||
|
@ -117,10 +117,14 @@ describe('register()', () => {
|
|||
id: 'default',
|
||||
name: 'Default',
|
||||
},
|
||||
{
|
||||
/**
|
||||
* The type system will ensure you can't use the `recovered` action group
|
||||
* but we also want to ensure this at runtime
|
||||
*/
|
||||
({
|
||||
id: 'recovered',
|
||||
name: 'Recovered',
|
||||
},
|
||||
} as unknown) as ActionGroup<'NotReserved'>,
|
||||
],
|
||||
defaultActionGroupId: 'default',
|
||||
minimumLicenseRequired: 'basic',
|
||||
|
@ -137,7 +141,7 @@ describe('register()', () => {
|
|||
});
|
||||
|
||||
test('allows an AlertType to specify a custom recovery group', () => {
|
||||
const alertType: AlertType = {
|
||||
const alertType: AlertType<never, never, never, never, 'default', 'backToAwesome'> = {
|
||||
id: 'test',
|
||||
name: 'Test',
|
||||
actionGroups: [
|
||||
|
@ -172,7 +176,14 @@ describe('register()', () => {
|
|||
});
|
||||
|
||||
test('throws if the custom recovery group is contained in the AlertType action groups', () => {
|
||||
const alertType: AlertType = {
|
||||
const alertType: AlertType<
|
||||
never,
|
||||
never,
|
||||
never,
|
||||
never,
|
||||
'default' | 'backToAwesome',
|
||||
'backToAwesome'
|
||||
> = {
|
||||
id: 'test',
|
||||
name: 'Test',
|
||||
actionGroups: [
|
||||
|
@ -204,7 +215,7 @@ describe('register()', () => {
|
|||
});
|
||||
|
||||
test('registers the executor with the task manager', () => {
|
||||
const alertType: AlertType = {
|
||||
const alertType: AlertType<never, never, never, never, 'default'> = {
|
||||
id: 'test',
|
||||
name: 'Test',
|
||||
actionGroups: [
|
||||
|
@ -234,7 +245,7 @@ describe('register()', () => {
|
|||
});
|
||||
|
||||
test('shallow clones the given alert type', () => {
|
||||
const alertType: AlertType = {
|
||||
const alertType: AlertType<never, never, never, never, 'default'> = {
|
||||
id: 'test',
|
||||
name: 'Test',
|
||||
actionGroups: [
|
||||
|
@ -475,8 +486,12 @@ describe('ensureAlertTypeEnabled', () => {
|
|||
});
|
||||
});
|
||||
|
||||
function alertTypeWithVariables(id: string, context: string, state: string): AlertType {
|
||||
const baseAlert: AlertType = {
|
||||
function alertTypeWithVariables<ActionGroupIds extends string>(
|
||||
id: ActionGroupIds,
|
||||
context: string,
|
||||
state: string
|
||||
): AlertType<never, never, never, never, ActionGroupIds> {
|
||||
const baseAlert: AlertType<never, never, never, never, ActionGroupIds> = {
|
||||
id,
|
||||
name: `${id}-name`,
|
||||
actionGroups: [],
|
||||
|
|
|
@ -19,7 +19,12 @@ import {
|
|||
AlertInstanceState,
|
||||
AlertInstanceContext,
|
||||
} from './types';
|
||||
import { RecoveredActionGroup, getBuiltinActionGroups } from '../common';
|
||||
import {
|
||||
RecoveredActionGroup,
|
||||
getBuiltinActionGroups,
|
||||
RecoveredActionGroupId,
|
||||
ActionGroup,
|
||||
} from '../common';
|
||||
import { ILicenseState } from './lib/license_state';
|
||||
import { getAlertTypeFeatureUsageName } from './lib/get_alert_type_feature_usage_name';
|
||||
|
||||
|
@ -69,15 +74,36 @@ export type NormalizedAlertType<
|
|||
Params extends AlertTypeParams,
|
||||
State extends AlertTypeState,
|
||||
InstanceState extends AlertInstanceState,
|
||||
InstanceContext extends AlertInstanceContext
|
||||
> = Omit<AlertType<Params, State, InstanceState, InstanceContext>, 'recoveryActionGroup'> &
|
||||
Pick<Required<AlertType<Params, State, InstanceState, InstanceContext>>, 'recoveryActionGroup'>;
|
||||
InstanceContext extends AlertInstanceContext,
|
||||
ActionGroupIds extends string,
|
||||
RecoveryActionGroupId extends string
|
||||
> = {
|
||||
actionGroups: Array<ActionGroup<ActionGroupIds | RecoveryActionGroupId>>;
|
||||
} & Omit<
|
||||
AlertType<Params, State, InstanceState, InstanceContext, ActionGroupIds, RecoveryActionGroupId>,
|
||||
'recoveryActionGroup' | 'actionGroups'
|
||||
> &
|
||||
Pick<
|
||||
Required<
|
||||
AlertType<
|
||||
Params,
|
||||
State,
|
||||
InstanceState,
|
||||
InstanceContext,
|
||||
ActionGroupIds,
|
||||
RecoveryActionGroupId
|
||||
>
|
||||
>,
|
||||
'recoveryActionGroup'
|
||||
>;
|
||||
|
||||
export type UntypedNormalizedAlertType = NormalizedAlertType<
|
||||
AlertTypeParams,
|
||||
AlertTypeState,
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext
|
||||
AlertInstanceContext,
|
||||
string,
|
||||
string
|
||||
>;
|
||||
|
||||
export class AlertTypeRegistry {
|
||||
|
@ -106,8 +132,19 @@ export class AlertTypeRegistry {
|
|||
Params extends AlertTypeParams,
|
||||
State extends AlertTypeState,
|
||||
InstanceState extends AlertInstanceState,
|
||||
InstanceContext extends AlertInstanceContext
|
||||
>(alertType: AlertType<Params, State, InstanceState, InstanceContext>) {
|
||||
InstanceContext extends AlertInstanceContext,
|
||||
ActionGroupIds extends string,
|
||||
RecoveryActionGroupId extends string
|
||||
>(
|
||||
alertType: AlertType<
|
||||
Params,
|
||||
State,
|
||||
InstanceState,
|
||||
InstanceContext,
|
||||
ActionGroupIds,
|
||||
RecoveryActionGroupId
|
||||
>
|
||||
) {
|
||||
if (this.has(alertType.id)) {
|
||||
throw new Error(
|
||||
i18n.translate('xpack.alerts.alertTypeRegistry.register.duplicateAlertTypeError', {
|
||||
|
@ -124,18 +161,28 @@ export class AlertTypeRegistry {
|
|||
Params,
|
||||
State,
|
||||
InstanceState,
|
||||
InstanceContext
|
||||
InstanceContext,
|
||||
ActionGroupIds,
|
||||
RecoveryActionGroupId
|
||||
>(alertType);
|
||||
|
||||
this.alertTypes.set(
|
||||
alertIdSchema.validate(alertType.id),
|
||||
normalizedAlertType as UntypedNormalizedAlertType
|
||||
/** stripping the typing is required in order to store the AlertTypes in a Map */
|
||||
(normalizedAlertType as unknown) as UntypedNormalizedAlertType
|
||||
);
|
||||
this.taskManager.registerTaskDefinitions({
|
||||
[`alerting:${alertType.id}`]: {
|
||||
title: alertType.name,
|
||||
createTaskRunner: (context: RunContext) =>
|
||||
this.taskRunnerFactory.create(normalizedAlertType as UntypedNormalizedAlertType, context),
|
||||
this.taskRunnerFactory.create<
|
||||
Params,
|
||||
State,
|
||||
InstanceState,
|
||||
InstanceContext,
|
||||
ActionGroupIds,
|
||||
RecoveryActionGroupId | RecoveredActionGroupId
|
||||
>(normalizedAlertType, context),
|
||||
},
|
||||
});
|
||||
// No need to notify usage on basic alert types
|
||||
|
@ -151,8 +198,19 @@ export class AlertTypeRegistry {
|
|||
Params extends AlertTypeParams = AlertTypeParams,
|
||||
State extends AlertTypeState = AlertTypeState,
|
||||
InstanceState extends AlertInstanceState = AlertInstanceState,
|
||||
InstanceContext extends AlertInstanceContext = AlertInstanceContext
|
||||
>(id: string): NormalizedAlertType<Params, State, InstanceState, InstanceContext> {
|
||||
InstanceContext extends AlertInstanceContext = AlertInstanceContext,
|
||||
ActionGroupIds extends string = string,
|
||||
RecoveryActionGroupId extends string = string
|
||||
>(
|
||||
id: string
|
||||
): NormalizedAlertType<
|
||||
Params,
|
||||
State,
|
||||
InstanceState,
|
||||
InstanceContext,
|
||||
ActionGroupIds,
|
||||
RecoveryActionGroupId
|
||||
> {
|
||||
if (!this.has(id)) {
|
||||
throw Boom.badRequest(
|
||||
i18n.translate('xpack.alerts.alertTypeRegistry.get.missingAlertTypeError', {
|
||||
|
@ -163,11 +221,18 @@ export class AlertTypeRegistry {
|
|||
})
|
||||
);
|
||||
}
|
||||
return this.alertTypes.get(id)! as NormalizedAlertType<
|
||||
/**
|
||||
* When we store the AlertTypes in the Map we strip the typing.
|
||||
* This means that returning a typed AlertType in `get` is an inherently
|
||||
* unsafe operation. Down casting to `unknown` is the only way to achieve this.
|
||||
*/
|
||||
return (this.alertTypes.get(id)! as unknown) as NormalizedAlertType<
|
||||
Params,
|
||||
State,
|
||||
InstanceState,
|
||||
InstanceContext
|
||||
InstanceContext,
|
||||
ActionGroupIds,
|
||||
RecoveryActionGroupId
|
||||
>;
|
||||
}
|
||||
|
||||
|
@ -217,15 +282,31 @@ function augmentActionGroupsWithReserved<
|
|||
Params extends AlertTypeParams,
|
||||
State extends AlertTypeState,
|
||||
InstanceState extends AlertInstanceState,
|
||||
InstanceContext extends AlertInstanceContext
|
||||
InstanceContext extends AlertInstanceContext,
|
||||
ActionGroupIds extends string,
|
||||
RecoveryActionGroupId extends string
|
||||
>(
|
||||
alertType: AlertType<Params, State, InstanceState, InstanceContext>
|
||||
): NormalizedAlertType<Params, State, InstanceState, InstanceContext> {
|
||||
alertType: AlertType<
|
||||
Params,
|
||||
State,
|
||||
InstanceState,
|
||||
InstanceContext,
|
||||
ActionGroupIds,
|
||||
RecoveryActionGroupId
|
||||
>
|
||||
): NormalizedAlertType<
|
||||
Params,
|
||||
State,
|
||||
InstanceState,
|
||||
InstanceContext,
|
||||
ActionGroupIds,
|
||||
RecoveredActionGroupId | RecoveryActionGroupId
|
||||
> {
|
||||
const reservedActionGroups = getBuiltinActionGroups(alertType.recoveryActionGroup);
|
||||
const { id, actionGroups, recoveryActionGroup } = alertType;
|
||||
|
||||
const activeActionGroups = new Set(actionGroups.map((item) => item.id));
|
||||
const intersectingReservedActionGroups = intersection(
|
||||
const activeActionGroups = new Set<string>(actionGroups.map((item) => item.id));
|
||||
const intersectingReservedActionGroups = intersection<string>(
|
||||
[...activeActionGroups.values()],
|
||||
reservedActionGroups.map((item) => item.id)
|
||||
);
|
||||
|
|
|
@ -16,6 +16,7 @@ export {
|
|||
ActionVariable,
|
||||
AlertType,
|
||||
ActionGroup,
|
||||
ActionGroupIdsOf,
|
||||
AlertingPlugin,
|
||||
AlertExecutorOptions,
|
||||
AlertActionParams,
|
||||
|
|
|
@ -56,7 +56,7 @@ describe('getLicenseCheckForAlertType', () => {
|
|||
let license: Subject<ILicense>;
|
||||
let licenseState: ILicenseState;
|
||||
const mockNotifyUsage = jest.fn();
|
||||
const alertType: AlertType = {
|
||||
const alertType: AlertType<never, never, never, never, 'default', 'recovered'> = {
|
||||
id: 'test',
|
||||
name: 'Test',
|
||||
actionGroups: [
|
||||
|
@ -190,7 +190,7 @@ describe('ensureLicenseForAlertType()', () => {
|
|||
let license: Subject<ILicense>;
|
||||
let licenseState: ILicenseState;
|
||||
const mockNotifyUsage = jest.fn();
|
||||
const alertType: AlertType = {
|
||||
const alertType: AlertType<never, never, never, never, string, string> = {
|
||||
id: 'test',
|
||||
name: 'Test',
|
||||
actionGroups: [
|
||||
|
|
|
@ -13,7 +13,13 @@ import { LicensingPluginStart } from '../../../licensing/server';
|
|||
import { ILicense, LicenseType } from '../../../licensing/common/types';
|
||||
import { PLUGIN } from '../constants/plugin';
|
||||
import { getAlertTypeFeatureUsageName } from './get_alert_type_feature_usage_name';
|
||||
import { AlertType } from '../types';
|
||||
import {
|
||||
AlertType,
|
||||
AlertTypeParams,
|
||||
AlertTypeState,
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext,
|
||||
} from '../types';
|
||||
import { AlertTypeDisabledError } from './errors/alert_type_disabled';
|
||||
|
||||
export type ILicenseState = PublicMethodsOf<LicenseState>;
|
||||
|
@ -130,7 +136,23 @@ export class LicenseState {
|
|||
}
|
||||
}
|
||||
|
||||
public ensureLicenseForAlertType(alertType: AlertType) {
|
||||
public ensureLicenseForAlertType<
|
||||
Params extends AlertTypeParams,
|
||||
State extends AlertTypeState,
|
||||
InstanceState extends AlertInstanceState,
|
||||
InstanceContext extends AlertInstanceContext,
|
||||
ActionGroupIds extends string,
|
||||
RecoveryActionGroupId extends string
|
||||
>(
|
||||
alertType: AlertType<
|
||||
Params,
|
||||
State,
|
||||
InstanceState,
|
||||
InstanceContext,
|
||||
ActionGroupIds,
|
||||
RecoveryActionGroupId
|
||||
>
|
||||
) {
|
||||
this.notifyUsage(alertType.name, alertType.minimumLicenseRequired);
|
||||
|
||||
const check = this.getLicenseCheckForAlertType(
|
||||
|
|
|
@ -58,7 +58,7 @@ describe('Alerting Plugin', () => {
|
|||
|
||||
describe('registerType()', () => {
|
||||
let setup: PluginSetupContract;
|
||||
const sampleAlertType: AlertType = {
|
||||
const sampleAlertType: AlertType<never, never, never, never, 'default'> = {
|
||||
id: 'test',
|
||||
name: 'test',
|
||||
minimumLicenseRequired: 'basic',
|
||||
|
|
|
@ -102,9 +102,18 @@ export interface PluginSetupContract {
|
|||
Params extends AlertTypeParams = AlertTypeParams,
|
||||
State extends AlertTypeState = AlertTypeState,
|
||||
InstanceState extends AlertInstanceState = AlertInstanceState,
|
||||
InstanceContext extends AlertInstanceContext = AlertInstanceContext
|
||||
InstanceContext extends AlertInstanceContext = AlertInstanceContext,
|
||||
ActionGroupIds extends string = never,
|
||||
RecoveryActionGroupId extends string = never
|
||||
>(
|
||||
alertType: AlertType<Params, State, InstanceState, InstanceContext>
|
||||
alertType: AlertType<
|
||||
Params,
|
||||
State,
|
||||
InstanceState,
|
||||
InstanceContext,
|
||||
ActionGroupIds,
|
||||
RecoveryActionGroupId
|
||||
>
|
||||
): void;
|
||||
}
|
||||
|
||||
|
@ -273,8 +282,19 @@ export class AlertingPlugin {
|
|||
Params extends AlertTypeParams = AlertTypeParams,
|
||||
State extends AlertTypeState = AlertTypeState,
|
||||
InstanceState extends AlertInstanceState = AlertInstanceState,
|
||||
InstanceContext extends AlertInstanceContext = AlertInstanceContext
|
||||
>(alertType: AlertType<Params, State, InstanceState, InstanceContext>) {
|
||||
InstanceContext extends AlertInstanceContext = AlertInstanceContext,
|
||||
ActionGroupIds extends string = never,
|
||||
RecoveryActionGroupId extends string = never
|
||||
>(
|
||||
alertType: AlertType<
|
||||
Params,
|
||||
State,
|
||||
InstanceState,
|
||||
InstanceContext,
|
||||
ActionGroupIds,
|
||||
RecoveryActionGroupId
|
||||
>
|
||||
) {
|
||||
if (!(alertType.minimumLicenseRequired in LICENSE_TYPE)) {
|
||||
throw new Error(`"${alertType.minimumLicenseRequired}" is not a valid license type`);
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ import { eventLoggerMock } from '../../../event_log/server/event_logger.mock';
|
|||
import { KibanaRequest } from 'kibana/server';
|
||||
import { asSavedObjectExecutionSource } from '../../../actions/server';
|
||||
import { InjectActionParamsOpts } from './inject_action_params';
|
||||
import { UntypedNormalizedAlertType } from '../alert_type_registry';
|
||||
import { NormalizedAlertType } from '../alert_type_registry';
|
||||
import {
|
||||
AlertTypeParams,
|
||||
AlertTypeState,
|
||||
|
@ -27,7 +27,14 @@ jest.mock('./inject_action_params', () => ({
|
|||
injectActionParams: jest.fn(),
|
||||
}));
|
||||
|
||||
const alertType: UntypedNormalizedAlertType = {
|
||||
const alertType: NormalizedAlertType<
|
||||
AlertTypeParams,
|
||||
AlertTypeState,
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext,
|
||||
'default' | 'other-group',
|
||||
'recovered'
|
||||
> = {
|
||||
id: 'test',
|
||||
name: 'Test',
|
||||
actionGroups: [
|
||||
|
@ -53,7 +60,9 @@ const createExecutionHandlerParams: jest.Mocked<
|
|||
AlertTypeParams,
|
||||
AlertTypeState,
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext
|
||||
AlertInstanceContext,
|
||||
'default' | 'other-group',
|
||||
'recovered'
|
||||
>
|
||||
> = {
|
||||
actionsPlugin: mockActionsPlugin,
|
||||
|
@ -348,7 +357,9 @@ test('state attribute gets parameterized', async () => {
|
|||
test(`logs an error when action group isn't part of actionGroups available for the alertType`, async () => {
|
||||
const executionHandler = createExecutionHandler(createExecutionHandlerParams);
|
||||
const result = await executionHandler({
|
||||
actionGroup: 'invalid-group',
|
||||
// we have to trick the compiler as this is an invalid type and this test checks whether we
|
||||
// enforce this at runtime as well as compile time
|
||||
actionGroup: 'invalid-group' as 'default' | 'other-group',
|
||||
context: {},
|
||||
state: {},
|
||||
alertInstanceId: '2',
|
||||
|
|
|
@ -27,7 +27,9 @@ export interface CreateExecutionHandlerOptions<
|
|||
Params extends AlertTypeParams,
|
||||
State extends AlertTypeState,
|
||||
InstanceState extends AlertInstanceState,
|
||||
InstanceContext extends AlertInstanceContext
|
||||
InstanceContext extends AlertInstanceContext,
|
||||
ActionGroupIds extends string,
|
||||
RecoveryActionGroupId extends string
|
||||
> {
|
||||
alertId: string;
|
||||
alertName: string;
|
||||
|
@ -36,26 +38,39 @@ export interface CreateExecutionHandlerOptions<
|
|||
actions: AlertAction[];
|
||||
spaceId: string;
|
||||
apiKey: RawAlert['apiKey'];
|
||||
alertType: NormalizedAlertType<Params, State, InstanceState, InstanceContext>;
|
||||
alertType: NormalizedAlertType<
|
||||
Params,
|
||||
State,
|
||||
InstanceState,
|
||||
InstanceContext,
|
||||
ActionGroupIds,
|
||||
RecoveryActionGroupId
|
||||
>;
|
||||
logger: Logger;
|
||||
eventLogger: IEventLogger;
|
||||
request: KibanaRequest;
|
||||
alertParams: AlertTypeParams;
|
||||
}
|
||||
|
||||
interface ExecutionHandlerOptions {
|
||||
actionGroup: string;
|
||||
interface ExecutionHandlerOptions<ActionGroupIds extends string> {
|
||||
actionGroup: ActionGroupIds;
|
||||
actionSubgroup?: string;
|
||||
alertInstanceId: string;
|
||||
context: AlertInstanceContext;
|
||||
state: AlertInstanceState;
|
||||
}
|
||||
|
||||
export type ExecutionHandler<ActionGroupIds extends string> = (
|
||||
options: ExecutionHandlerOptions<ActionGroupIds>
|
||||
) => Promise<void>;
|
||||
|
||||
export function createExecutionHandler<
|
||||
Params extends AlertTypeParams,
|
||||
State extends AlertTypeState,
|
||||
InstanceState extends AlertInstanceState,
|
||||
InstanceContext extends AlertInstanceContext
|
||||
InstanceContext extends AlertInstanceContext,
|
||||
ActionGroupIds extends string,
|
||||
RecoveryActionGroupId extends string
|
||||
>({
|
||||
logger,
|
||||
alertId,
|
||||
|
@ -69,7 +84,14 @@ export function createExecutionHandler<
|
|||
eventLogger,
|
||||
request,
|
||||
alertParams,
|
||||
}: CreateExecutionHandlerOptions<Params, State, InstanceState, InstanceContext>) {
|
||||
}: CreateExecutionHandlerOptions<
|
||||
Params,
|
||||
State,
|
||||
InstanceState,
|
||||
InstanceContext,
|
||||
ActionGroupIds,
|
||||
RecoveryActionGroupId
|
||||
>): ExecutionHandler<ActionGroupIds | RecoveryActionGroupId> {
|
||||
const alertTypeActionGroups = new Map(
|
||||
alertType.actionGroups.map((actionGroup) => [actionGroup.id, actionGroup.name])
|
||||
);
|
||||
|
@ -79,7 +101,7 @@ export function createExecutionHandler<
|
|||
context,
|
||||
state,
|
||||
alertInstanceId,
|
||||
}: ExecutionHandlerOptions) => {
|
||||
}: ExecutionHandlerOptions<ActionGroupIds | RecoveryActionGroupId>) => {
|
||||
if (!alertTypeActionGroups.has(actionGroup)) {
|
||||
logger.error(`Invalid action group "${actionGroup}" for alert "${alertType.id}".`);
|
||||
return;
|
||||
|
|
|
@ -266,7 +266,8 @@ describe('Task Runner', () => {
|
|||
AlertTypeParams,
|
||||
AlertTypeState,
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext
|
||||
AlertInstanceContext,
|
||||
string
|
||||
>) => {
|
||||
executorServices
|
||||
.alertInstanceFactory('1')
|
||||
|
@ -426,7 +427,8 @@ describe('Task Runner', () => {
|
|||
AlertTypeParams,
|
||||
AlertTypeState,
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext
|
||||
AlertInstanceContext,
|
||||
string
|
||||
>) => {
|
||||
executorServices.alertInstanceFactory('1').scheduleActions('default');
|
||||
}
|
||||
|
@ -542,7 +544,8 @@ describe('Task Runner', () => {
|
|||
AlertTypeParams,
|
||||
AlertTypeState,
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext
|
||||
AlertInstanceContext,
|
||||
string
|
||||
>) => {
|
||||
executorServices.alertInstanceFactory('1').scheduleActions('default');
|
||||
executorServices.alertInstanceFactory('2').scheduleActions('default');
|
||||
|
@ -595,7 +598,8 @@ describe('Task Runner', () => {
|
|||
AlertTypeParams,
|
||||
AlertTypeState,
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext
|
||||
AlertInstanceContext,
|
||||
string
|
||||
>) => {
|
||||
executorServices.alertInstanceFactory('1').scheduleActions('default');
|
||||
}
|
||||
|
@ -696,7 +700,8 @@ describe('Task Runner', () => {
|
|||
AlertTypeParams,
|
||||
AlertTypeState,
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext
|
||||
AlertInstanceContext,
|
||||
string
|
||||
>) => {
|
||||
executorServices.alertInstanceFactory('1').scheduleActions('default');
|
||||
}
|
||||
|
@ -743,7 +748,8 @@ describe('Task Runner', () => {
|
|||
AlertTypeParams,
|
||||
AlertTypeState,
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext
|
||||
AlertInstanceContext,
|
||||
string
|
||||
>) => {
|
||||
executorServices
|
||||
.alertInstanceFactory('1')
|
||||
|
@ -798,7 +804,8 @@ describe('Task Runner', () => {
|
|||
AlertTypeParams,
|
||||
AlertTypeState,
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext
|
||||
AlertInstanceContext,
|
||||
string
|
||||
>) => {
|
||||
executorServices.alertInstanceFactory('1').scheduleActions('default');
|
||||
}
|
||||
|
@ -973,7 +980,8 @@ describe('Task Runner', () => {
|
|||
AlertTypeParams,
|
||||
AlertTypeState,
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext
|
||||
AlertInstanceContext,
|
||||
string
|
||||
>) => {
|
||||
executorServices.alertInstanceFactory('1').scheduleActions('default');
|
||||
}
|
||||
|
@ -1080,7 +1088,8 @@ describe('Task Runner', () => {
|
|||
AlertTypeParams,
|
||||
AlertTypeState,
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext
|
||||
AlertInstanceContext,
|
||||
string
|
||||
>) => {
|
||||
executorServices.alertInstanceFactory('1').scheduleActions('default');
|
||||
}
|
||||
|
@ -1178,7 +1187,8 @@ describe('Task Runner', () => {
|
|||
AlertTypeParams,
|
||||
AlertTypeState,
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext
|
||||
AlertInstanceContext,
|
||||
string
|
||||
>) => {
|
||||
executorServices.alertInstanceFactory('1').scheduleActions('default');
|
||||
}
|
||||
|
@ -1447,7 +1457,8 @@ describe('Task Runner', () => {
|
|||
AlertTypeParams,
|
||||
AlertTypeState,
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext
|
||||
AlertInstanceContext,
|
||||
string
|
||||
>) => {
|
||||
throw new Error('OMG');
|
||||
}
|
||||
|
@ -1822,7 +1833,8 @@ describe('Task Runner', () => {
|
|||
AlertTypeParams,
|
||||
AlertTypeState,
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext
|
||||
AlertInstanceContext,
|
||||
string
|
||||
>) => {
|
||||
throw new Error('OMG');
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ import { addSpaceIdToPath } from '../../../spaces/server';
|
|||
import { Logger, KibanaRequest } from '../../../../../src/core/server';
|
||||
import { TaskRunnerContext } from './task_runner_factory';
|
||||
import { ConcreteTaskInstance, throwUnrecoverableError } from '../../../task_manager/server';
|
||||
import { createExecutionHandler } from './create_execution_handler';
|
||||
import { createExecutionHandler, ExecutionHandler } from './create_execution_handler';
|
||||
import { AlertInstance, createAlertInstanceFactory } from '../alert_instance';
|
||||
import {
|
||||
validateAlertTypeParams,
|
||||
|
@ -44,6 +44,7 @@ import {
|
|||
AlertTypeState,
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext,
|
||||
WithoutReservedActionGroups,
|
||||
} from '../../common';
|
||||
import { NormalizedAlertType } from '../alert_type_registry';
|
||||
|
||||
|
@ -64,16 +65,32 @@ export class TaskRunner<
|
|||
Params extends AlertTypeParams,
|
||||
State extends AlertTypeState,
|
||||
InstanceState extends AlertInstanceState,
|
||||
InstanceContext extends AlertInstanceContext
|
||||
InstanceContext extends AlertInstanceContext,
|
||||
ActionGroupIds extends string,
|
||||
RecoveryActionGroupId extends string
|
||||
> {
|
||||
private context: TaskRunnerContext;
|
||||
private logger: Logger;
|
||||
private taskInstance: AlertTaskInstance;
|
||||
private alertType: NormalizedAlertType<Params, State, InstanceState, InstanceContext>;
|
||||
private alertType: NormalizedAlertType<
|
||||
Params,
|
||||
State,
|
||||
InstanceState,
|
||||
InstanceContext,
|
||||
ActionGroupIds,
|
||||
RecoveryActionGroupId
|
||||
>;
|
||||
private readonly alertTypeRegistry: AlertTypeRegistry;
|
||||
|
||||
constructor(
|
||||
alertType: NormalizedAlertType<Params, State, InstanceState, InstanceContext>,
|
||||
alertType: NormalizedAlertType<
|
||||
Params,
|
||||
State,
|
||||
InstanceState,
|
||||
InstanceContext,
|
||||
ActionGroupIds,
|
||||
RecoveryActionGroupId
|
||||
>,
|
||||
taskInstance: ConcreteTaskInstance,
|
||||
context: TaskRunnerContext
|
||||
) {
|
||||
|
@ -144,7 +161,14 @@ export class TaskRunner<
|
|||
actions: Alert<Params>['actions'],
|
||||
alertParams: Params
|
||||
) {
|
||||
return createExecutionHandler({
|
||||
return createExecutionHandler<
|
||||
Params,
|
||||
State,
|
||||
InstanceState,
|
||||
InstanceContext,
|
||||
ActionGroupIds,
|
||||
RecoveryActionGroupId
|
||||
>({
|
||||
alertId,
|
||||
alertName,
|
||||
tags,
|
||||
|
@ -163,7 +187,7 @@ export class TaskRunner<
|
|||
async executeAlertInstance(
|
||||
alertInstanceId: string,
|
||||
alertInstance: AlertInstance<InstanceState, InstanceContext>,
|
||||
executionHandler: ReturnType<typeof createExecutionHandler>
|
||||
executionHandler: ExecutionHandler<ActionGroupIds | RecoveryActionGroupId>
|
||||
) {
|
||||
const {
|
||||
actionGroup,
|
||||
|
@ -180,7 +204,7 @@ export class TaskRunner<
|
|||
services: Services,
|
||||
alert: SanitizedAlert<Params>,
|
||||
params: Params,
|
||||
executionHandler: ReturnType<typeof createExecutionHandler>,
|
||||
executionHandler: ExecutionHandler<ActionGroupIds | RecoveryActionGroupId>,
|
||||
spaceId: string,
|
||||
event: Event
|
||||
): Promise<AlertTaskState> {
|
||||
|
@ -218,9 +242,11 @@ export class TaskRunner<
|
|||
alertId,
|
||||
services: {
|
||||
...services,
|
||||
alertInstanceFactory: createAlertInstanceFactory<InstanceState, InstanceContext>(
|
||||
alertInstances
|
||||
),
|
||||
alertInstanceFactory: createAlertInstanceFactory<
|
||||
InstanceState,
|
||||
InstanceContext,
|
||||
WithoutReservedActionGroups<ActionGroupIds, RecoveryActionGroupId>
|
||||
>(alertInstances),
|
||||
},
|
||||
params,
|
||||
state: alertTypeState as State,
|
||||
|
@ -278,7 +304,7 @@ export class TaskRunner<
|
|||
if (!muteAll) {
|
||||
const mutedInstanceIdsSet = new Set(mutedInstanceIds);
|
||||
|
||||
scheduleActionsForRecoveredInstances({
|
||||
scheduleActionsForRecoveredInstances<InstanceState, InstanceContext, RecoveryActionGroupId>({
|
||||
recoveryActionGroup: this.alertType.recoveryActionGroup,
|
||||
recoveredAlertInstances,
|
||||
executionHandler,
|
||||
|
@ -615,20 +641,30 @@ function generateNewAndRecoveredInstanceEvents<
|
|||
|
||||
interface ScheduleActionsForRecoveredInstancesParams<
|
||||
InstanceState extends AlertInstanceState,
|
||||
InstanceContext extends AlertInstanceContext
|
||||
InstanceContext extends AlertInstanceContext,
|
||||
RecoveryActionGroupId extends string
|
||||
> {
|
||||
logger: Logger;
|
||||
recoveryActionGroup: ActionGroup;
|
||||
recoveredAlertInstances: Dictionary<AlertInstance<InstanceState, InstanceContext>>;
|
||||
executionHandler: ReturnType<typeof createExecutionHandler>;
|
||||
recoveryActionGroup: ActionGroup<RecoveryActionGroupId>;
|
||||
recoveredAlertInstances: Dictionary<
|
||||
AlertInstance<InstanceState, InstanceContext, RecoveryActionGroupId>
|
||||
>;
|
||||
executionHandler: ExecutionHandler<RecoveryActionGroupId | RecoveryActionGroupId>;
|
||||
mutedInstanceIdsSet: Set<string>;
|
||||
alertLabel: string;
|
||||
}
|
||||
|
||||
function scheduleActionsForRecoveredInstances<
|
||||
InstanceState extends AlertInstanceState,
|
||||
InstanceContext extends AlertInstanceContext
|
||||
>(params: ScheduleActionsForRecoveredInstancesParams<InstanceState, InstanceContext>) {
|
||||
InstanceContext extends AlertInstanceContext,
|
||||
RecoveryActionGroupId extends string
|
||||
>(
|
||||
params: ScheduleActionsForRecoveredInstancesParams<
|
||||
InstanceState,
|
||||
InstanceContext,
|
||||
RecoveryActionGroupId
|
||||
>
|
||||
) {
|
||||
const {
|
||||
logger,
|
||||
recoveryActionGroup,
|
||||
|
@ -660,18 +696,31 @@ function scheduleActionsForRecoveredInstances<
|
|||
|
||||
interface LogActiveAndRecoveredInstancesParams<
|
||||
InstanceState extends AlertInstanceState,
|
||||
InstanceContext extends AlertInstanceContext
|
||||
InstanceContext extends AlertInstanceContext,
|
||||
ActionGroupIds extends string,
|
||||
RecoveryActionGroupId extends string
|
||||
> {
|
||||
logger: Logger;
|
||||
activeAlertInstances: Dictionary<AlertInstance<InstanceState, InstanceContext>>;
|
||||
recoveredAlertInstances: Dictionary<AlertInstance<InstanceState, InstanceContext>>;
|
||||
activeAlertInstances: Dictionary<AlertInstance<InstanceState, InstanceContext, ActionGroupIds>>;
|
||||
recoveredAlertInstances: Dictionary<
|
||||
AlertInstance<InstanceState, InstanceContext, RecoveryActionGroupId>
|
||||
>;
|
||||
alertLabel: string;
|
||||
}
|
||||
|
||||
function logActiveAndRecoveredInstances<
|
||||
InstanceState extends AlertInstanceState,
|
||||
InstanceContext extends AlertInstanceContext
|
||||
>(params: LogActiveAndRecoveredInstancesParams<InstanceState, InstanceContext>) {
|
||||
InstanceContext extends AlertInstanceContext,
|
||||
ActionGroupIds extends string,
|
||||
RecoveryActionGroupId extends string
|
||||
>(
|
||||
params: LogActiveAndRecoveredInstancesParams<
|
||||
InstanceState,
|
||||
InstanceContext,
|
||||
ActionGroupIds,
|
||||
RecoveryActionGroupId
|
||||
>
|
||||
) {
|
||||
const { logger, activeAlertInstances, recoveredAlertInstances, alertLabel } = params;
|
||||
const activeInstanceIds = Object.keys(activeAlertInstances);
|
||||
const recoveredInstanceIds = Object.keys(recoveredAlertInstances);
|
||||
|
|
|
@ -13,11 +13,19 @@ import {
|
|||
import { RunContext } from '../../../task_manager/server';
|
||||
import { EncryptedSavedObjectsClient } from '../../../encrypted_saved_objects/server';
|
||||
import { PluginStartContract as ActionsPluginStartContract } from '../../../actions/server';
|
||||
import { AlertTypeRegistry, GetServicesFunction, SpaceIdToNamespaceFunction } from '../types';
|
||||
import {
|
||||
AlertTypeParams,
|
||||
AlertTypeRegistry,
|
||||
GetServicesFunction,
|
||||
SpaceIdToNamespaceFunction,
|
||||
AlertTypeState,
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext,
|
||||
} from '../types';
|
||||
import { TaskRunner } from './task_runner';
|
||||
import { IEventLogger } from '../../../event_log/server';
|
||||
import { AlertsClient } from '../alerts_client';
|
||||
import { UntypedNormalizedAlertType } from '../alert_type_registry';
|
||||
import { NormalizedAlertType } from '../alert_type_registry';
|
||||
|
||||
export interface TaskRunnerContext {
|
||||
logger: Logger;
|
||||
|
@ -44,11 +52,35 @@ export class TaskRunnerFactory {
|
|||
this.taskRunnerContext = taskRunnerContext;
|
||||
}
|
||||
|
||||
public create(alertType: UntypedNormalizedAlertType, { taskInstance }: RunContext) {
|
||||
public create<
|
||||
Params extends AlertTypeParams,
|
||||
State extends AlertTypeState,
|
||||
InstanceState extends AlertInstanceState,
|
||||
InstanceContext extends AlertInstanceContext,
|
||||
ActionGroupIds extends string,
|
||||
RecoveryActionGroupId extends string
|
||||
>(
|
||||
alertType: NormalizedAlertType<
|
||||
Params,
|
||||
State,
|
||||
InstanceState,
|
||||
InstanceContext,
|
||||
ActionGroupIds,
|
||||
RecoveryActionGroupId
|
||||
>,
|
||||
{ taskInstance }: RunContext
|
||||
) {
|
||||
if (!this.isInitialized) {
|
||||
throw new Error('TaskRunnerFactory not initialized');
|
||||
}
|
||||
|
||||
return new TaskRunner(alertType, taskInstance, this.taskRunnerContext!);
|
||||
return new TaskRunner<
|
||||
Params,
|
||||
State,
|
||||
InstanceState,
|
||||
InstanceContext,
|
||||
ActionGroupIds,
|
||||
RecoveryActionGroupId
|
||||
>(alertType, taskInstance, this.taskRunnerContext!);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ import {
|
|||
AlertExecutionStatusErrorReasons,
|
||||
AlertsHealth,
|
||||
AlertNotifyWhenType,
|
||||
WithoutReservedActionGroups,
|
||||
} from '../common';
|
||||
import { LicenseType } from '../../licensing/server';
|
||||
|
||||
|
@ -58,21 +59,25 @@ export interface Services {
|
|||
|
||||
export interface AlertServices<
|
||||
InstanceState extends AlertInstanceState = AlertInstanceState,
|
||||
InstanceContext extends AlertInstanceContext = AlertInstanceContext
|
||||
InstanceContext extends AlertInstanceContext = AlertInstanceContext,
|
||||
ActionGroupIds extends string = never
|
||||
> extends Services {
|
||||
alertInstanceFactory: (id: string) => PublicAlertInstance<InstanceState, InstanceContext>;
|
||||
alertInstanceFactory: (
|
||||
id: string
|
||||
) => PublicAlertInstance<InstanceState, InstanceContext, ActionGroupIds>;
|
||||
}
|
||||
|
||||
export interface AlertExecutorOptions<
|
||||
Params extends AlertTypeParams = never,
|
||||
State extends AlertTypeState = never,
|
||||
InstanceState extends AlertInstanceState = never,
|
||||
InstanceContext extends AlertInstanceContext = never
|
||||
InstanceContext extends AlertInstanceContext = never,
|
||||
ActionGroupIds extends string = never
|
||||
> {
|
||||
alertId: string;
|
||||
startedAt: Date;
|
||||
previousStartedAt: Date | null;
|
||||
services: AlertServices<InstanceState, InstanceContext>;
|
||||
services: AlertServices<InstanceState, InstanceContext, ActionGroupIds>;
|
||||
params: Params;
|
||||
state: State;
|
||||
spaceId: string;
|
||||
|
@ -92,9 +97,10 @@ export type ExecutorType<
|
|||
Params extends AlertTypeParams = never,
|
||||
State extends AlertTypeState = never,
|
||||
InstanceState extends AlertInstanceState = never,
|
||||
InstanceContext extends AlertInstanceContext = never
|
||||
InstanceContext extends AlertInstanceContext = never,
|
||||
ActionGroupIds extends string = never
|
||||
> = (
|
||||
options: AlertExecutorOptions<Params, State, InstanceState, InstanceContext>
|
||||
options: AlertExecutorOptions<Params, State, InstanceState, InstanceContext, ActionGroupIds>
|
||||
) => Promise<State | void>;
|
||||
|
||||
export interface AlertTypeParamsValidator<Params extends AlertTypeParams> {
|
||||
|
@ -104,17 +110,29 @@ export interface AlertType<
|
|||
Params extends AlertTypeParams = never,
|
||||
State extends AlertTypeState = never,
|
||||
InstanceState extends AlertInstanceState = never,
|
||||
InstanceContext extends AlertInstanceContext = never
|
||||
InstanceContext extends AlertInstanceContext = never,
|
||||
ActionGroupIds extends string = never,
|
||||
RecoveryActionGroupId extends string = never
|
||||
> {
|
||||
id: string;
|
||||
name: string;
|
||||
validate?: {
|
||||
params?: AlertTypeParamsValidator<Params>;
|
||||
};
|
||||
actionGroups: ActionGroup[];
|
||||
defaultActionGroupId: ActionGroup['id'];
|
||||
recoveryActionGroup?: ActionGroup;
|
||||
executor: ExecutorType<Params, State, InstanceState, InstanceContext>;
|
||||
actionGroups: Array<ActionGroup<ActionGroupIds>>;
|
||||
defaultActionGroupId: ActionGroup<ActionGroupIds>['id'];
|
||||
recoveryActionGroup?: ActionGroup<RecoveryActionGroupId>;
|
||||
executor: ExecutorType<
|
||||
Params,
|
||||
State,
|
||||
InstanceState,
|
||||
InstanceContext,
|
||||
/**
|
||||
* Ensure that the reserved ActionGroups (such as `Recovered`) are not
|
||||
* available for scheduling in the Executor
|
||||
*/
|
||||
WithoutReservedActionGroups<ActionGroupIds, RecoveryActionGroupId>
|
||||
>;
|
||||
producer: string;
|
||||
actionVariables?: {
|
||||
context?: ActionVariable[];
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { ValuesType } from 'utility-types';
|
||||
import { ActionGroup } from '../../alerts/common';
|
||||
import { ANOMALY_SEVERITY, ANOMALY_THRESHOLD } from '../../ml/common';
|
||||
|
||||
export enum AlertType {
|
||||
|
@ -15,20 +16,31 @@ export enum AlertType {
|
|||
TransactionDurationAnomaly = 'apm.transaction_duration_anomaly',
|
||||
}
|
||||
|
||||
const THRESHOLD_MET_GROUP = {
|
||||
id: 'threshold_met',
|
||||
export const THRESHOLD_MET_GROUP_ID = 'threshold_met';
|
||||
export type ThresholdMetActionGroupId = typeof THRESHOLD_MET_GROUP_ID;
|
||||
const THRESHOLD_MET_GROUP: ActionGroup<ThresholdMetActionGroupId> = {
|
||||
id: THRESHOLD_MET_GROUP_ID,
|
||||
name: i18n.translate('xpack.apm.a.thresholdMet', {
|
||||
defaultMessage: 'Threshold met',
|
||||
}),
|
||||
};
|
||||
|
||||
export const ALERT_TYPES_CONFIG = {
|
||||
export const ALERT_TYPES_CONFIG: Record<
|
||||
AlertType,
|
||||
{
|
||||
name: string;
|
||||
actionGroups: Array<ActionGroup<ThresholdMetActionGroupId>>;
|
||||
defaultActionGroupId: ThresholdMetActionGroupId;
|
||||
minimumLicenseRequired: string;
|
||||
producer: string;
|
||||
}
|
||||
> = {
|
||||
[AlertType.ErrorCount]: {
|
||||
name: i18n.translate('xpack.apm.errorCountAlert.name', {
|
||||
defaultMessage: 'Error count threshold',
|
||||
}),
|
||||
actionGroups: [THRESHOLD_MET_GROUP],
|
||||
defaultActionGroupId: 'threshold_met',
|
||||
defaultActionGroupId: THRESHOLD_MET_GROUP_ID,
|
||||
minimumLicenseRequired: 'basic',
|
||||
producer: 'apm',
|
||||
},
|
||||
|
@ -37,7 +49,7 @@ export const ALERT_TYPES_CONFIG = {
|
|||
defaultMessage: 'Transaction duration threshold',
|
||||
}),
|
||||
actionGroups: [THRESHOLD_MET_GROUP],
|
||||
defaultActionGroupId: 'threshold_met',
|
||||
defaultActionGroupId: THRESHOLD_MET_GROUP_ID,
|
||||
minimumLicenseRequired: 'basic',
|
||||
producer: 'apm',
|
||||
},
|
||||
|
@ -46,7 +58,7 @@ export const ALERT_TYPES_CONFIG = {
|
|||
defaultMessage: 'Transaction duration anomaly',
|
||||
}),
|
||||
actionGroups: [THRESHOLD_MET_GROUP],
|
||||
defaultActionGroupId: 'threshold_met',
|
||||
defaultActionGroupId: THRESHOLD_MET_GROUP_ID,
|
||||
minimumLicenseRequired: 'basic',
|
||||
producer: 'apm',
|
||||
},
|
||||
|
@ -55,7 +67,7 @@ export const ALERT_TYPES_CONFIG = {
|
|||
defaultMessage: 'Transaction error rate threshold',
|
||||
}),
|
||||
actionGroups: [THRESHOLD_MET_GROUP],
|
||||
defaultActionGroupId: 'threshold_met',
|
||||
defaultActionGroupId: THRESHOLD_MET_GROUP_ID,
|
||||
minimumLicenseRequired: 'basic',
|
||||
producer: 'apm',
|
||||
},
|
||||
|
|
|
@ -4,14 +4,23 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { ThresholdMetActionGroupId } from '../../../common/alert_types';
|
||||
import {
|
||||
ESSearchRequest,
|
||||
ESSearchResponse,
|
||||
} from '../../../../../typings/elasticsearch';
|
||||
import { AlertServices } from '../../../../alerts/server';
|
||||
import {
|
||||
AlertInstanceContext,
|
||||
AlertInstanceState,
|
||||
AlertServices,
|
||||
} from '../../../../alerts/server';
|
||||
|
||||
export function alertingEsClient<TParams extends ESSearchRequest>(
|
||||
services: AlertServices,
|
||||
services: AlertServices<
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext,
|
||||
ThresholdMetActionGroupId
|
||||
>,
|
||||
params: TParams
|
||||
): Promise<ESSearchResponse<unknown, TParams>> {
|
||||
return services.callCluster('search', {
|
||||
|
|
|
@ -4,13 +4,22 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { schema } from '@kbn/config-schema';
|
||||
import { schema, TypeOf } from '@kbn/config-schema';
|
||||
import { isEmpty } from 'lodash';
|
||||
import { Observable } from 'rxjs';
|
||||
import { take } from 'rxjs/operators';
|
||||
import { APMConfig } from '../..';
|
||||
import { AlertingPlugin } from '../../../../alerts/server';
|
||||
import { AlertType, ALERT_TYPES_CONFIG } from '../../../common/alert_types';
|
||||
import {
|
||||
AlertingPlugin,
|
||||
AlertInstanceContext,
|
||||
AlertInstanceState,
|
||||
AlertTypeState,
|
||||
} from '../../../../alerts/server';
|
||||
import {
|
||||
AlertType,
|
||||
ALERT_TYPES_CONFIG,
|
||||
ThresholdMetActionGroupId,
|
||||
} from '../../../common/alert_types';
|
||||
import {
|
||||
PROCESSOR_EVENT,
|
||||
SERVICE_ENVIRONMENT,
|
||||
|
@ -41,7 +50,13 @@ export function registerErrorCountAlertType({
|
|||
alerts,
|
||||
config$,
|
||||
}: RegisterAlertParams) {
|
||||
alerts.registerType({
|
||||
alerts.registerType<
|
||||
TypeOf<typeof paramsSchema>,
|
||||
AlertTypeState,
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext,
|
||||
ThresholdMetActionGroupId
|
||||
>({
|
||||
id: AlertType.ErrorCount,
|
||||
name: alertTypeConfig.name,
|
||||
actionGroups: alertTypeConfig.actionGroups,
|
||||
|
|
|
@ -10,6 +10,7 @@ import { getCustomMetricLabel } from '../../../../common/formatters/get_custom_m
|
|||
import { toMetricOpt } from '../../../../common/snapshot_metric_i18n';
|
||||
import { AlertStates, InventoryMetricConditions } from './types';
|
||||
import {
|
||||
ActionGroup,
|
||||
AlertInstanceContext,
|
||||
AlertInstanceState,
|
||||
RecoveredActionGroup,
|
||||
|
@ -27,6 +28,7 @@ import {
|
|||
stateToAlertMessage,
|
||||
} from '../common/messages';
|
||||
import { evaluateCondition } from './evaluate_condition';
|
||||
import { InventoryMetricThresholdAllowedActionGroups } from './register_inventory_metric_threshold_alert_type';
|
||||
|
||||
interface InventoryMetricThresholdParams {
|
||||
criteria: InventoryMetricConditions[];
|
||||
|
@ -46,7 +48,8 @@ export const createInventoryMetricThresholdExecutor = (libs: InfraBackendLibs) =
|
|||
Record<string, any>,
|
||||
Record<string, any>,
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext
|
||||
AlertInstanceContext,
|
||||
InventoryMetricThresholdAllowedActionGroups
|
||||
>) => {
|
||||
const {
|
||||
criteria,
|
||||
|
@ -115,18 +118,25 @@ export const createInventoryMetricThresholdExecutor = (libs: InfraBackendLibs) =
|
|||
}
|
||||
if (reason) {
|
||||
const actionGroupId =
|
||||
nextState === AlertStates.OK ? RecoveredActionGroup.id : FIRED_ACTIONS.id;
|
||||
alertInstance.scheduleActions(actionGroupId, {
|
||||
group: item,
|
||||
alertState: stateToAlertMessage[nextState],
|
||||
reason,
|
||||
timestamp: moment().toISOString(),
|
||||
value: mapToConditionsLookup(results, (result) =>
|
||||
formatMetric(result[item].metric, result[item].currentValue)
|
||||
),
|
||||
threshold: mapToConditionsLookup(criteria, (c) => c.threshold),
|
||||
metric: mapToConditionsLookup(criteria, (c) => c.metric),
|
||||
});
|
||||
nextState === AlertStates.OK ? RecoveredActionGroup.id : FIRED_ACTIONS_ID;
|
||||
alertInstance.scheduleActions(
|
||||
/**
|
||||
* TODO: We're lying to the compiler here as explicitly calling `scheduleActions` on
|
||||
* the RecoveredActionGroup isn't allowed
|
||||
*/
|
||||
(actionGroupId as unknown) as InventoryMetricThresholdAllowedActionGroups,
|
||||
{
|
||||
group: item,
|
||||
alertState: stateToAlertMessage[nextState],
|
||||
reason,
|
||||
timestamp: moment().toISOString(),
|
||||
value: mapToConditionsLookup(results, (result) =>
|
||||
formatMetric(result[item].metric, result[item].currentValue)
|
||||
),
|
||||
threshold: mapToConditionsLookup(criteria, (c) => c.threshold),
|
||||
metric: mapToConditionsLookup(criteria, (c) => c.metric),
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
alertInstance.replaceState({
|
||||
|
@ -160,8 +170,9 @@ const mapToConditionsLookup = (
|
|||
{}
|
||||
);
|
||||
|
||||
export const FIRED_ACTIONS = {
|
||||
id: 'metrics.invenotry_threshold.fired',
|
||||
export const FIRED_ACTIONS_ID = 'metrics.invenotry_threshold.fired';
|
||||
export const FIRED_ACTIONS: ActionGroup<typeof FIRED_ACTIONS_ID> = {
|
||||
id: FIRED_ACTIONS_ID,
|
||||
name: i18n.translate('xpack.infra.metrics.alerting.inventory.threshold.fired', {
|
||||
defaultMessage: 'Fired',
|
||||
}),
|
||||
|
|
|
@ -9,6 +9,7 @@ import { AlertType, AlertInstanceState, AlertInstanceContext } from '../../../..
|
|||
import {
|
||||
createInventoryMetricThresholdExecutor,
|
||||
FIRED_ACTIONS,
|
||||
FIRED_ACTIONS_ID,
|
||||
} from './inventory_metric_threshold_executor';
|
||||
import { METRIC_INVENTORY_THRESHOLD_ALERT_TYPE_ID, Comparator } from './types';
|
||||
import { InfraBackendLibs } from '../../infra_types';
|
||||
|
@ -22,6 +23,7 @@ import {
|
|||
metricActionVariableDescription,
|
||||
thresholdActionVariableDescription,
|
||||
} from '../common/messages';
|
||||
import { RecoveredActionGroupId } from '../../../../../alerts/common';
|
||||
|
||||
const condition = schema.object({
|
||||
threshold: schema.arrayOf(schema.number()),
|
||||
|
@ -40,6 +42,8 @@ const condition = schema.object({
|
|||
),
|
||||
});
|
||||
|
||||
export type InventoryMetricThresholdAllowedActionGroups = typeof FIRED_ACTIONS_ID;
|
||||
|
||||
export const registerMetricInventoryThresholdAlertType = (
|
||||
libs: InfraBackendLibs
|
||||
): AlertType<
|
||||
|
@ -49,7 +53,9 @@ export const registerMetricInventoryThresholdAlertType = (
|
|||
Record<string, any>,
|
||||
Record<string, any>,
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext
|
||||
AlertInstanceContext,
|
||||
InventoryMetricThresholdAllowedActionGroups,
|
||||
RecoveredActionGroupId
|
||||
> => ({
|
||||
id: METRIC_INVENTORY_THRESHOLD_ALERT_TYPE_ID,
|
||||
name: i18n.translate('xpack.infra.metrics.inventory.alertName', {
|
||||
|
@ -69,7 +75,7 @@ export const registerMetricInventoryThresholdAlertType = (
|
|||
{ unknowns: 'allow' }
|
||||
),
|
||||
},
|
||||
defaultActionGroupId: FIRED_ACTIONS.id,
|
||||
defaultActionGroupId: FIRED_ACTIONS_ID,
|
||||
actionGroups: [FIRED_ACTIONS],
|
||||
producer: 'infrastructure',
|
||||
minimumLicenseRequired: 'basic',
|
||||
|
|
|
@ -13,6 +13,8 @@ import {
|
|||
AlertTypeState,
|
||||
AlertInstanceContext,
|
||||
AlertInstanceState,
|
||||
ActionGroup,
|
||||
ActionGroupIdsOf,
|
||||
} from '../../../../../alerts/server';
|
||||
import {
|
||||
AlertStates,
|
||||
|
@ -37,12 +39,18 @@ import { getIntervalInSeconds } from '../../../utils/get_interval_in_seconds';
|
|||
import { decodeOrThrow } from '../../../../common/runtime_types';
|
||||
import { UNGROUPED_FACTORY_KEY } from '../common/utils';
|
||||
|
||||
type LogThresholdAlertServices = AlertServices<AlertInstanceState, AlertInstanceContext>;
|
||||
type LogThresholdActionGroups = ActionGroupIdsOf<typeof FIRED_ACTIONS>;
|
||||
type LogThresholdAlertServices = AlertServices<
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext,
|
||||
LogThresholdActionGroups
|
||||
>;
|
||||
type LogThresholdAlertExecutorOptions = AlertExecutorOptions<
|
||||
AlertTypeParams,
|
||||
AlertTypeState,
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext
|
||||
AlertInstanceContext,
|
||||
LogThresholdActionGroups
|
||||
>;
|
||||
|
||||
const COMPOSITE_GROUP_SIZE = 40;
|
||||
|
@ -344,9 +352,9 @@ export const processGroupByRatioResults = (
|
|||
};
|
||||
|
||||
type AlertInstanceUpdater = (
|
||||
alertInstance: AlertInstance,
|
||||
alertInstance: AlertInstance<AlertInstanceState, AlertInstanceContext, LogThresholdActionGroups>,
|
||||
state: AlertStates,
|
||||
actions?: Array<{ actionGroup: string; context: AlertInstanceContext }>
|
||||
actions?: Array<{ actionGroup: LogThresholdActionGroups; context: AlertInstanceContext }>
|
||||
) => void;
|
||||
|
||||
export const updateAlertInstance: AlertInstanceUpdater = (alertInstance, state, actions) => {
|
||||
|
@ -653,8 +661,9 @@ const createConditionsMessageForCriteria = (criteria: CountCriteria) => {
|
|||
|
||||
// When the Alerting plugin implements support for multiple action groups, add additional
|
||||
// action groups here to send different messages, e.g. a recovery notification
|
||||
export const FIRED_ACTIONS = {
|
||||
id: 'logs.threshold.fired',
|
||||
export const LogsThresholdFiredActionGroupId = 'logs.threshold.fired';
|
||||
export const FIRED_ACTIONS: ActionGroup<'logs.threshold.fired'> = {
|
||||
id: LogsThresholdFiredActionGroupId,
|
||||
name: i18n.translate('xpack.infra.logs.alerting.threshold.fired', {
|
||||
defaultMessage: 'Fired',
|
||||
}),
|
||||
|
|
|
@ -4,7 +4,14 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { PluginSetupContract } from '../../../../../alerts/server';
|
||||
import {
|
||||
PluginSetupContract,
|
||||
AlertTypeParams,
|
||||
AlertTypeState,
|
||||
AlertInstanceContext,
|
||||
AlertInstanceState,
|
||||
ActionGroupIdsOf,
|
||||
} from '../../../../../alerts/server';
|
||||
import { createLogThresholdExecutor, FIRED_ACTIONS } from './log_threshold_executor';
|
||||
import {
|
||||
LOG_DOCUMENT_COUNT_ALERT_TYPE_ID,
|
||||
|
@ -79,7 +86,13 @@ export async function registerLogThresholdAlertType(
|
|||
);
|
||||
}
|
||||
|
||||
alertingPlugin.registerType({
|
||||
alertingPlugin.registerType<
|
||||
AlertTypeParams,
|
||||
AlertTypeState,
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext,
|
||||
ActionGroupIdsOf<typeof FIRED_ACTIONS>
|
||||
>({
|
||||
id: LOG_DOCUMENT_COUNT_ALERT_TYPE_ID,
|
||||
name: i18n.translate('xpack.infra.logs.alertName', {
|
||||
defaultMessage: 'Log threshold',
|
||||
|
|
|
@ -10,6 +10,7 @@ import {
|
|||
AlertInstanceState,
|
||||
AlertInstanceContext,
|
||||
AlertExecutorOptions,
|
||||
ActionGroupIdsOf,
|
||||
} from '../../../../../alerts/server';
|
||||
import { METRIC_EXPLORER_AGGREGATIONS } from '../../../../common/http_api/metrics_explorer';
|
||||
import { createMetricThresholdExecutor, FIRED_ACTIONS } from './metric_threshold_executor';
|
||||
|
@ -33,7 +34,8 @@ export type MetricThresholdAlertType = AlertType<
|
|||
Record<string, any>,
|
||||
Record<string, any>,
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext
|
||||
AlertInstanceContext,
|
||||
ActionGroupIdsOf<typeof FIRED_ACTIONS>
|
||||
>;
|
||||
export type MetricThresholdAlertExecutorOptions = AlertExecutorOptions<
|
||||
/**
|
||||
|
@ -42,7 +44,8 @@ export type MetricThresholdAlertExecutorOptions = AlertExecutorOptions<
|
|||
Record<string, any>,
|
||||
Record<string, any>,
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext
|
||||
AlertInstanceContext,
|
||||
ActionGroupIdsOf<typeof FIRED_ACTIONS>
|
||||
>;
|
||||
|
||||
export function registerMetricThresholdAlertType(libs: InfraBackendLibs): MetricThresholdAlertType {
|
||||
|
|
|
@ -93,7 +93,7 @@ export class BaseAlert {
|
|||
this.scopedLogger = Globals.app.getLogger(alertOptions.id!);
|
||||
}
|
||||
|
||||
public getAlertType(): AlertType {
|
||||
public getAlertType(): AlertType<never, never, never, never, 'default'> {
|
||||
const { id, name, actionVariables } = this.alertOptions;
|
||||
return {
|
||||
id,
|
||||
|
@ -108,8 +108,11 @@ export class BaseAlert {
|
|||
],
|
||||
defaultActionGroupId: 'default',
|
||||
minimumLicenseRequired: 'basic',
|
||||
executor: (options: AlertExecutorOptions & { state: ExecutedState }): Promise<any> =>
|
||||
this.execute(options),
|
||||
executor: (
|
||||
options: AlertExecutorOptions<never, never, AlertInstanceState, never, 'default'> & {
|
||||
state: ExecutedState;
|
||||
}
|
||||
): Promise<any> => this.execute(options),
|
||||
producer: 'monitoring',
|
||||
actionVariables: {
|
||||
context: actionVariables,
|
||||
|
@ -238,7 +241,9 @@ export class BaseAlert {
|
|||
services,
|
||||
params,
|
||||
state,
|
||||
}: AlertExecutorOptions & { state: ExecutedState }): Promise<any> {
|
||||
}: AlertExecutorOptions<never, never, AlertInstanceState, never, 'default'> & {
|
||||
state: ExecutedState;
|
||||
}): Promise<any> {
|
||||
this.scopedLogger.debug(
|
||||
`Executing alert with params: ${JSON.stringify(params)} and state: ${JSON.stringify(state)}`
|
||||
);
|
||||
|
@ -333,7 +338,7 @@ export class BaseAlert {
|
|||
protected async processData(
|
||||
data: AlertData[],
|
||||
clusters: AlertCluster[],
|
||||
services: AlertServices,
|
||||
services: AlertServices<AlertInstanceState, never, 'default'>,
|
||||
state: ExecutedState
|
||||
) {
|
||||
const currentUTC = +new Date();
|
||||
|
@ -387,7 +392,7 @@ export class BaseAlert {
|
|||
protected async processLegacyData(
|
||||
data: AlertData[],
|
||||
clusters: AlertCluster[],
|
||||
services: AlertServices,
|
||||
services: AlertServices<AlertInstanceState, never, 'default'>,
|
||||
state: ExecutedState
|
||||
) {
|
||||
const currentUTC = +new Date();
|
||||
|
|
|
@ -105,7 +105,7 @@ export const isNotificationAlertExecutor = (
|
|||
};
|
||||
|
||||
export type NotificationAlertTypeDefinition = Omit<
|
||||
AlertType<AlertTypeParams, AlertTypeState, AlertInstanceState, AlertInstanceContext>,
|
||||
AlertType<AlertTypeParams, AlertTypeState, AlertInstanceState, AlertInstanceContext, 'default'>,
|
||||
'executor'
|
||||
> & {
|
||||
executor: ({
|
||||
|
|
|
@ -8,7 +8,11 @@ import { flow, omit } from 'lodash/fp';
|
|||
import set from 'set-value';
|
||||
|
||||
import { Logger } from '../../../../../../../src/core/server';
|
||||
import { AlertServices } from '../../../../../alerts/server';
|
||||
import {
|
||||
AlertInstanceContext,
|
||||
AlertInstanceState,
|
||||
AlertServices,
|
||||
} from '../../../../../alerts/server';
|
||||
import { RuleAlertAction } from '../../../../common/detection_engine/types';
|
||||
import { RuleTypeParams, RefreshTypes } from '../types';
|
||||
import { singleBulkCreate, SingleBulkCreateResponse } from './single_bulk_create';
|
||||
|
@ -20,7 +24,7 @@ interface BulkCreateMlSignalsParams {
|
|||
actions: RuleAlertAction[];
|
||||
someResult: AnomalyResults;
|
||||
ruleParams: RuleTypeParams;
|
||||
services: AlertServices;
|
||||
services: AlertServices<AlertInstanceState, AlertInstanceContext, 'default'>;
|
||||
logger: Logger;
|
||||
id: string;
|
||||
signalsIndex: string;
|
||||
|
|
|
@ -12,7 +12,11 @@ import {
|
|||
TimestampOverrideOrUndefined,
|
||||
} from '../../../../common/detection_engine/schemas/common/schemas';
|
||||
import { Logger } from '../../../../../../../src/core/server';
|
||||
import { AlertServices } from '../../../../../alerts/server';
|
||||
import {
|
||||
AlertInstanceContext,
|
||||
AlertInstanceState,
|
||||
AlertServices,
|
||||
} from '../../../../../alerts/server';
|
||||
import { RuleAlertAction } from '../../../../common/detection_engine/types';
|
||||
import { RuleTypeParams, RefreshTypes } from '../types';
|
||||
import { singleBulkCreate, SingleBulkCreateResponse } from './single_bulk_create';
|
||||
|
@ -24,7 +28,7 @@ interface BulkCreateThresholdSignalsParams {
|
|||
actions: RuleAlertAction[];
|
||||
someResult: SignalSearchResponse;
|
||||
ruleParams: RuleTypeParams;
|
||||
services: AlertServices;
|
||||
services: AlertServices<AlertInstanceState, AlertInstanceContext, 'default'>;
|
||||
inputIndexPattern: string[];
|
||||
logger: Logger;
|
||||
id: string;
|
||||
|
|
|
@ -12,7 +12,11 @@ import {
|
|||
} from '../../../../common/detection_engine/schemas/common/schemas';
|
||||
import { singleSearchAfter } from './single_search_after';
|
||||
|
||||
import { AlertServices } from '../../../../../alerts/server';
|
||||
import {
|
||||
AlertInstanceContext,
|
||||
AlertInstanceState,
|
||||
AlertServices,
|
||||
} from '../../../../../alerts/server';
|
||||
import { Logger } from '../../../../../../../src/core/server';
|
||||
import { SignalSearchResponse } from './types';
|
||||
import { BuildRuleMessage } from './rule_messages';
|
||||
|
@ -21,7 +25,7 @@ interface FindThresholdSignalsParams {
|
|||
from: string;
|
||||
to: string;
|
||||
inputIndexPattern: string[];
|
||||
services: AlertServices;
|
||||
services: AlertServices<AlertInstanceState, AlertInstanceContext, 'default'>;
|
||||
logger: Logger;
|
||||
filter: unknown;
|
||||
threshold: Threshold;
|
||||
|
|
|
@ -15,7 +15,11 @@ import {
|
|||
Language,
|
||||
} from '../../../../common/detection_engine/schemas/common/schemas';
|
||||
import { ExceptionListItemSchema } from '../../../../../lists/common/schemas';
|
||||
import { AlertServices } from '../../../../../alerts/server';
|
||||
import {
|
||||
AlertInstanceContext,
|
||||
AlertInstanceState,
|
||||
AlertServices,
|
||||
} from '../../../../../alerts/server';
|
||||
import { PartialFilter } from '../types';
|
||||
import { BadRequestError } from '../errors/bad_request_error';
|
||||
import { QueryFilter } from './types';
|
||||
|
@ -26,7 +30,7 @@ interface GetFilterArgs {
|
|||
language: LanguageOrUndefined;
|
||||
query: QueryOrUndefined;
|
||||
savedId: SavedIdOrUndefined;
|
||||
services: AlertServices;
|
||||
services: AlertServices<AlertInstanceState, AlertInstanceContext, 'default'>;
|
||||
index: IndexOrUndefined;
|
||||
lists: ExceptionListItemSchema[];
|
||||
}
|
||||
|
|
|
@ -5,10 +5,14 @@
|
|||
*/
|
||||
|
||||
import { DEFAULT_INDEX_KEY, DEFAULT_INDEX_PATTERN } from '../../../../common/constants';
|
||||
import { AlertServices } from '../../../../../alerts/server';
|
||||
import {
|
||||
AlertInstanceContext,
|
||||
AlertInstanceState,
|
||||
AlertServices,
|
||||
} from '../../../../../alerts/server';
|
||||
|
||||
export const getInputIndex = async (
|
||||
services: AlertServices,
|
||||
services: AlertServices<AlertInstanceState, AlertInstanceContext, 'default'>,
|
||||
version: string,
|
||||
inputIndex: string[] | null | undefined
|
||||
): Promise<string[]> => {
|
||||
|
|
|
@ -5,8 +5,9 @@
|
|||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { ActionGroup } from '../../../../../alerts/common';
|
||||
|
||||
export const siemRuleActionGroups = [
|
||||
export const siemRuleActionGroups: Array<ActionGroup<'default'>> = [
|
||||
{
|
||||
id: 'default',
|
||||
name: i18n.translate(
|
||||
|
|
|
@ -6,7 +6,11 @@
|
|||
|
||||
import { countBy, isEmpty, get } from 'lodash';
|
||||
import { performance } from 'perf_hooks';
|
||||
import { AlertServices } from '../../../../../alerts/server';
|
||||
import {
|
||||
AlertInstanceContext,
|
||||
AlertInstanceState,
|
||||
AlertServices,
|
||||
} from '../../../../../alerts/server';
|
||||
import { SignalSearchResponse, BulkResponse, SignalHit, WrappedSignalHit } from './types';
|
||||
import { RuleAlertAction } from '../../../../common/detection_engine/types';
|
||||
import { RuleTypeParams, RefreshTypes } from '../types';
|
||||
|
@ -19,7 +23,7 @@ import { isEventTypeSignal } from './build_event_type_signal';
|
|||
interface SingleBulkCreateParams {
|
||||
filteredEvents: SignalSearchResponse;
|
||||
ruleParams: RuleTypeParams;
|
||||
services: AlertServices;
|
||||
services: AlertServices<AlertInstanceState, AlertInstanceContext, 'default'>;
|
||||
logger: Logger;
|
||||
id: string;
|
||||
signalsIndex: string;
|
||||
|
@ -222,7 +226,7 @@ export const singleBulkCreate = async ({
|
|||
export const bulkInsertSignals = async (
|
||||
signals: WrappedSignalHit[],
|
||||
logger: Logger,
|
||||
services: AlertServices,
|
||||
services: AlertServices<AlertInstanceState, AlertInstanceContext, 'default'>,
|
||||
refresh: RefreshTypes
|
||||
): Promise<BulkInsertSignalsResponse> => {
|
||||
// index documents after creating an ID based on the
|
||||
|
|
|
@ -5,7 +5,11 @@
|
|||
*/
|
||||
|
||||
import { performance } from 'perf_hooks';
|
||||
import { AlertServices } from '../../../../../alerts/server';
|
||||
import {
|
||||
AlertInstanceContext,
|
||||
AlertInstanceState,
|
||||
AlertServices,
|
||||
} from '../../../../../alerts/server';
|
||||
import { Logger } from '../../../../../../../src/core/server';
|
||||
import { SignalSearchResponse } from './types';
|
||||
import { BuildRuleMessage } from './rule_messages';
|
||||
|
@ -22,7 +26,7 @@ interface SingleSearchAfterParams {
|
|||
index: string[];
|
||||
from: string;
|
||||
to: string;
|
||||
services: AlertServices;
|
||||
services: AlertServices<AlertInstanceState, AlertInstanceContext, 'default'>;
|
||||
logger: Logger;
|
||||
pageSize: number;
|
||||
sortOrder?: SortOrderOrUndefined;
|
||||
|
|
|
@ -20,7 +20,11 @@ import {
|
|||
ItemsPerSearch,
|
||||
} from '../../../../../common/detection_engine/schemas/types/threat_mapping';
|
||||
import { PartialFilter, RuleTypeParams } from '../../types';
|
||||
import { AlertServices } from '../../../../../../alerts/server';
|
||||
import {
|
||||
AlertInstanceContext,
|
||||
AlertInstanceState,
|
||||
AlertServices,
|
||||
} from '../../../../../../alerts/server';
|
||||
import { ExceptionListItemSchema } from '../../../../../../lists/common/schemas';
|
||||
import { ILegacyScopedClusterClient, Logger } from '../../../../../../../../src/core/server';
|
||||
import { RuleAlertAction } from '../../../../../common/detection_engine/types';
|
||||
|
@ -38,7 +42,7 @@ export interface CreateThreatSignalsOptions {
|
|||
filters: PartialFilter[];
|
||||
language: LanguageOrUndefined;
|
||||
savedId: string | undefined;
|
||||
services: AlertServices;
|
||||
services: AlertServices<AlertInstanceState, AlertInstanceContext, 'default'>;
|
||||
exceptionItems: ExceptionListItemSchema[];
|
||||
gap: Duration | null;
|
||||
previousStartedAt: Date | null;
|
||||
|
@ -77,7 +81,7 @@ export interface CreateThreatSignalOptions {
|
|||
filters: PartialFilter[];
|
||||
language: LanguageOrUndefined;
|
||||
savedId: string | undefined;
|
||||
services: AlertServices;
|
||||
services: AlertServices<AlertInstanceState, AlertInstanceContext, 'default'>;
|
||||
exceptionItems: ExceptionListItemSchema[];
|
||||
gap: Duration | null;
|
||||
previousStartedAt: Date | null;
|
||||
|
|
|
@ -7,7 +7,11 @@
|
|||
import { TimestampOverrideOrUndefined } from '../../../../common/detection_engine/schemas/common/schemas';
|
||||
import { singleSearchAfter } from './single_search_after';
|
||||
|
||||
import { AlertServices } from '../../../../../alerts/server';
|
||||
import {
|
||||
AlertInstanceContext,
|
||||
AlertInstanceState,
|
||||
AlertServices,
|
||||
} from '../../../../../alerts/server';
|
||||
import { Logger } from '../../../../../../../src/core/server';
|
||||
import { SignalSearchResponse } from './types';
|
||||
import { BuildRuleMessage } from './rule_messages';
|
||||
|
@ -16,7 +20,7 @@ interface FindPreviousThresholdSignalsParams {
|
|||
from: string;
|
||||
to: string;
|
||||
indexPattern: string[];
|
||||
services: AlertServices;
|
||||
services: AlertServices<AlertInstanceState, AlertInstanceContext, 'default'>;
|
||||
logger: Logger;
|
||||
ruleId: string;
|
||||
bucketByField: string;
|
||||
|
|
|
@ -10,7 +10,11 @@ import { Filter } from 'src/plugins/data/common';
|
|||
import { ESFilter } from '../../../../../../typings/elasticsearch';
|
||||
|
||||
import { TimestampOverrideOrUndefined } from '../../../../common/detection_engine/schemas/common/schemas';
|
||||
import { AlertServices } from '../../../../../alerts/server';
|
||||
import {
|
||||
AlertInstanceContext,
|
||||
AlertInstanceState,
|
||||
AlertServices,
|
||||
} from '../../../../../alerts/server';
|
||||
import { Logger } from '../../../../../../../src/core/server';
|
||||
import { ThresholdQueryBucket } from './types';
|
||||
import { BuildRuleMessage } from './rule_messages';
|
||||
|
@ -20,7 +24,7 @@ interface GetThresholdBucketFiltersParams {
|
|||
from: string;
|
||||
to: string;
|
||||
indexPattern: string[];
|
||||
services: AlertServices;
|
||||
services: AlertServices<AlertInstanceState, AlertInstanceContext, 'default'>;
|
||||
logger: Logger;
|
||||
ruleId: string;
|
||||
bucketByField: string;
|
||||
|
|
|
@ -141,7 +141,13 @@ export type RuleExecutorOptions = AlertExecutorOptions<
|
|||
// since we are only increasing the strictness of params.
|
||||
export const isAlertExecutor = (
|
||||
obj: SignalRuleAlertTypeDefinition
|
||||
): obj is AlertType<RuleTypeParams, AlertTypeState, AlertInstanceState, AlertInstanceContext> => {
|
||||
): obj is AlertType<
|
||||
RuleTypeParams,
|
||||
AlertTypeState,
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext,
|
||||
'default'
|
||||
> => {
|
||||
return true;
|
||||
};
|
||||
|
||||
|
@ -149,7 +155,8 @@ export type SignalRuleAlertTypeDefinition = AlertType<
|
|||
RuleTypeParams,
|
||||
AlertTypeState,
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext
|
||||
AlertInstanceContext,
|
||||
'default'
|
||||
>;
|
||||
|
||||
export interface Ancestor {
|
||||
|
@ -224,7 +231,7 @@ export interface SearchAfterAndBulkCreateParams {
|
|||
gap: moment.Duration | null;
|
||||
previousStartedAt: Date | null | undefined;
|
||||
ruleParams: RuleTypeParams;
|
||||
services: AlertServices;
|
||||
services: AlertServices<AlertInstanceState, AlertInstanceContext, 'default'>;
|
||||
listClient: ListClient;
|
||||
exceptionsList: ExceptionListItemSchema[];
|
||||
logger: Logger;
|
||||
|
|
|
@ -10,7 +10,12 @@ import dateMath from '@elastic/datemath';
|
|||
|
||||
import { TimestampOverrideOrUndefined } from '../../../../common/detection_engine/schemas/common/schemas';
|
||||
import { Logger, SavedObjectsClientContract } from '../../../../../../../src/core/server';
|
||||
import { AlertServices, parseDuration } from '../../../../../alerts/server';
|
||||
import {
|
||||
AlertInstanceContext,
|
||||
AlertInstanceState,
|
||||
AlertServices,
|
||||
parseDuration,
|
||||
} from '../../../../../alerts/server';
|
||||
import { ExceptionListClient, ListClient, ListPluginSetup } from '../../../../../lists/server';
|
||||
import { ExceptionListItemSchema } from '../../../../../lists/common/schemas';
|
||||
import { ListArray } from '../../../../common/detection_engine/schemas/types/lists';
|
||||
|
@ -52,7 +57,10 @@ export const shorthandMap = {
|
|||
},
|
||||
};
|
||||
|
||||
export const checkPrivileges = async (services: AlertServices, indices: string[]) =>
|
||||
export const checkPrivileges = async (
|
||||
services: AlertServices<AlertInstanceState, AlertInstanceContext, 'default'>,
|
||||
indices: string[]
|
||||
) =>
|
||||
services.callCluster('transport.request', {
|
||||
path: '/_security/user/_has_privileges',
|
||||
method: 'POST',
|
||||
|
@ -154,7 +162,7 @@ export const getListsClient = ({
|
|||
lists: ListPluginSetup | undefined;
|
||||
spaceId: string;
|
||||
updatedByUser: string | null;
|
||||
services: AlertServices;
|
||||
services: AlertServices<AlertInstanceState, AlertInstanceContext, 'default'>;
|
||||
savedObjectClient: SavedObjectsClientContract;
|
||||
}): {
|
||||
listClient: ListClient;
|
||||
|
|
|
@ -20,6 +20,7 @@ import { Query } from '../../../../../../src/plugins/data/common/query';
|
|||
|
||||
export const GEO_CONTAINMENT_ID = '.geo-containment';
|
||||
export const ActionGroupId = 'Tracked entity contained';
|
||||
export const RecoveryActionGroupId = 'notGeoContained';
|
||||
|
||||
const actionVariableContextEntityIdLabel = i18n.translate(
|
||||
'xpack.stackAlerts.geoContainment.actionVariableContextEntityIdLabel',
|
||||
|
@ -141,7 +142,9 @@ export type GeoContainmentAlertType = AlertType<
|
|||
GeoContainmentParams,
|
||||
GeoContainmentState,
|
||||
GeoContainmentInstanceState,
|
||||
GeoContainmentInstanceContext
|
||||
GeoContainmentInstanceContext,
|
||||
typeof ActionGroupId,
|
||||
typeof RecoveryActionGroupId
|
||||
>;
|
||||
|
||||
export function getAlertType(logger: Logger): GeoContainmentAlertType {
|
||||
|
@ -161,7 +164,7 @@ export function getAlertType(logger: Logger): GeoContainmentAlertType {
|
|||
name: alertTypeName,
|
||||
actionGroups: [{ id: ActionGroupId, name: actionGroupName }],
|
||||
recoveryActionGroup: {
|
||||
id: 'notGeoContained',
|
||||
id: RecoveryActionGroupId,
|
||||
name: i18n.translate('xpack.stackAlerts.geoContainment.notGeoContained', {
|
||||
defaultMessage: 'No longer contained',
|
||||
}),
|
||||
|
|
|
@ -100,7 +100,8 @@ export function getActiveEntriesAndGenerateAlerts(
|
|||
currLocationMap: Map<string, LatestEntityLocation>,
|
||||
alertInstanceFactory: AlertServices<
|
||||
GeoContainmentInstanceState,
|
||||
GeoContainmentInstanceContext
|
||||
GeoContainmentInstanceContext,
|
||||
typeof ActionGroupId
|
||||
>['alertInstanceFactory'],
|
||||
shapesIdsNamesMap: Record<string, unknown>,
|
||||
currIntervalEndTime: Date
|
||||
|
|
|
@ -12,6 +12,8 @@ import {
|
|||
GeoContainmentInstanceState,
|
||||
GeoContainmentInstanceContext,
|
||||
getAlertType,
|
||||
ActionGroupId,
|
||||
RecoveryActionGroupId,
|
||||
} from './alert_type';
|
||||
|
||||
interface RegisterParams {
|
||||
|
@ -25,6 +27,8 @@ export function register(params: RegisterParams) {
|
|||
GeoContainmentParams,
|
||||
GeoContainmentState,
|
||||
GeoContainmentInstanceState,
|
||||
GeoContainmentInstanceContext
|
||||
GeoContainmentInstanceContext,
|
||||
typeof ActionGroupId,
|
||||
typeof RecoveryActionGroupId
|
||||
>(getAlertType(logger));
|
||||
}
|
||||
|
|
|
@ -209,7 +209,8 @@ export type GeoThresholdAlertType = AlertType<
|
|||
GeoThresholdParams,
|
||||
GeoThresholdState,
|
||||
GeoThresholdInstanceState,
|
||||
GeoThresholdInstanceContext
|
||||
GeoThresholdInstanceContext,
|
||||
typeof ActionGroupId
|
||||
>;
|
||||
export function getAlertType(logger: Logger): GeoThresholdAlertType {
|
||||
const alertTypeName = i18n.translate('xpack.stackAlerts.geoThreshold.alertTypeTitle', {
|
||||
|
|
|
@ -42,7 +42,7 @@ export const ComparatorFnNames = new Set(ComparatorFns.keys());
|
|||
export function getAlertType(
|
||||
logger: Logger,
|
||||
data: Promise<StackAlertsStartDeps['triggersActionsUi']['data']>
|
||||
): AlertType<Params, {}, {}, ActionContext> {
|
||||
): AlertType<Params, {}, {}, ActionContext, typeof ActionGroupId> {
|
||||
const alertTypeName = i18n.translate('xpack.stackAlerts.indexThreshold.alertTypeTitle', {
|
||||
defaultMessage: 'Index threshold',
|
||||
});
|
||||
|
@ -148,7 +148,9 @@ export function getAlertType(
|
|||
producer: STACK_ALERTS_FEATURE_ID,
|
||||
};
|
||||
|
||||
async function executor(options: AlertExecutorOptions<Params, {}, {}, ActionContext>) {
|
||||
async function executor(
|
||||
options: AlertExecutorOptions<Params, {}, {}, ActionContext, typeof ActionGroupId>
|
||||
) {
|
||||
const { alertId, name, services, params } = options;
|
||||
|
||||
const compareFn = ComparatorFns.get(params.thresholdComparator);
|
||||
|
|
|
@ -39,7 +39,7 @@ import { ActionGroup, AlertActionParam } from '../../../../../alerts/common';
|
|||
import { useKibana } from '../../../common/lib/kibana';
|
||||
import { DefaultActionParamsGetter } from '../../lib/get_defaults_for_action_params';
|
||||
|
||||
export interface ActionGroupWithMessageVariables extends ActionGroup {
|
||||
export interface ActionGroupWithMessageVariables extends ActionGroup<string> {
|
||||
omitOptionalMessageVariables?: boolean;
|
||||
defaultActionMessage?: string;
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import { Alert, ActionType, AlertTypeModel, AlertType } from '../../../../types'
|
|||
import { EuiTitle, EuiBadge, EuiFlexItem, EuiSwitch, EuiButtonEmpty, EuiText } from '@elastic/eui';
|
||||
import { ViewInApp } from './view_in_app';
|
||||
import {
|
||||
ActionGroup,
|
||||
AlertExecutionStatusErrorReasons,
|
||||
ALERTS_FEATURE_ID,
|
||||
} from '../../../../../../alerts/common';
|
||||
|
@ -47,7 +48,7 @@ const mockAlertApis = {
|
|||
const authorizedConsumers = {
|
||||
[ALERTS_FEATURE_ID]: { read: true, all: true },
|
||||
};
|
||||
const recoveryActionGroup = { id: 'recovered', name: 'Recovered' };
|
||||
const recoveryActionGroup: ActionGroup<'recovered'> = { id: 'recovered', name: 'Recovered' };
|
||||
|
||||
describe('alert_details', () => {
|
||||
// mock Api handlers
|
||||
|
|
|
@ -231,7 +231,7 @@ const INACTIVE_LABEL = i18n.translate(
|
|||
function getActionGroupName(alertType: AlertType, actionGroupId?: string): string | undefined {
|
||||
actionGroupId = actionGroupId || alertType.defaultActionGroupId;
|
||||
const actionGroup = alertType?.actionGroups?.find(
|
||||
(group: ActionGroup) => group.id === actionGroupId
|
||||
(group: ActionGroup<string>) => group.id === actionGroupId
|
||||
);
|
||||
return actionGroup?.name;
|
||||
}
|
||||
|
|
|
@ -61,7 +61,7 @@ describe('alert_conditions', () => {
|
|||
const ConditionForm = ({
|
||||
actionGroup,
|
||||
}: {
|
||||
actionGroup?: ActionGroupWithCondition<{ someProp: string }>;
|
||||
actionGroup?: ActionGroupWithCondition<{ someProp: string }, string>;
|
||||
}) => {
|
||||
return (
|
||||
<EuiDescriptionList>
|
||||
|
@ -113,7 +113,7 @@ describe('alert_conditions', () => {
|
|||
const ConditionForm = ({
|
||||
actionGroup,
|
||||
}: {
|
||||
actionGroup?: ActionGroupWithCondition<{ someProp: string }>;
|
||||
actionGroup?: ActionGroupWithCondition<{ someProp: string }, string>;
|
||||
}) => {
|
||||
return (
|
||||
<EuiDescriptionList>
|
||||
|
@ -165,7 +165,7 @@ describe('alert_conditions', () => {
|
|||
const ConditionForm = ({
|
||||
actionGroup,
|
||||
}: {
|
||||
actionGroup?: ActionGroupWithCondition<{ someProp: string }>;
|
||||
actionGroup?: ActionGroupWithCondition<{ someProp: string }, string>;
|
||||
}) => {
|
||||
return (
|
||||
<EuiDescriptionList>
|
||||
|
@ -218,8 +218,10 @@ describe('alert_conditions', () => {
|
|||
actionGroup,
|
||||
someCallbackProp,
|
||||
}: {
|
||||
actionGroup?: ActionGroupWithCondition<{ someProp: string }>;
|
||||
someCallbackProp: (actionGroup: ActionGroupWithCondition<{ someProp: string }>) => void;
|
||||
actionGroup?: ActionGroupWithCondition<{ someProp: string }, string>;
|
||||
someCallbackProp: (
|
||||
actionGroup: ActionGroupWithCondition<{ someProp: string }, string>
|
||||
) => void;
|
||||
}) => {
|
||||
if (!actionGroup) {
|
||||
return <div />;
|
||||
|
|
|
@ -11,7 +11,10 @@ import { ActionGroup, getBuiltinActionGroups } from '../../../../../alerts/commo
|
|||
|
||||
const BUILT_IN_ACTION_GROUPS: Set<string> = new Set(getBuiltinActionGroups().map(({ id }) => id));
|
||||
|
||||
export type ActionGroupWithCondition<T> = ActionGroup &
|
||||
export type ActionGroupWithCondition<
|
||||
T,
|
||||
ActionGroupIds extends string
|
||||
> = ActionGroup<ActionGroupIds> &
|
||||
(
|
||||
| // allow isRequired=false with or without conditions
|
||||
{
|
||||
|
@ -25,22 +28,26 @@ export type ActionGroupWithCondition<T> = ActionGroup &
|
|||
}
|
||||
);
|
||||
|
||||
export interface AlertConditionsProps<ConditionProps> {
|
||||
export interface AlertConditionsProps<ConditionProps, ActionGroupIds extends string> {
|
||||
headline?: string;
|
||||
actionGroups: Array<ActionGroupWithCondition<ConditionProps>>;
|
||||
onInitializeConditionsFor?: (actionGroup: ActionGroupWithCondition<ConditionProps>) => void;
|
||||
onResetConditionsFor?: (actionGroup: ActionGroupWithCondition<ConditionProps>) => void;
|
||||
actionGroups: Array<ActionGroupWithCondition<ConditionProps, ActionGroupIds>>;
|
||||
onInitializeConditionsFor?: (
|
||||
actionGroup: ActionGroupWithCondition<ConditionProps, ActionGroupIds>
|
||||
) => void;
|
||||
onResetConditionsFor?: (
|
||||
actionGroup: ActionGroupWithCondition<ConditionProps, ActionGroupIds>
|
||||
) => void;
|
||||
includeBuiltInActionGroups?: boolean;
|
||||
}
|
||||
|
||||
export const AlertConditions = <ConditionProps extends any>({
|
||||
export const AlertConditions = <ConditionProps extends any, ActionGroupIds extends string>({
|
||||
headline,
|
||||
actionGroups,
|
||||
onInitializeConditionsFor,
|
||||
onResetConditionsFor,
|
||||
includeBuiltInActionGroups = false,
|
||||
children,
|
||||
}: PropsWithChildren<AlertConditionsProps<ConditionProps>>) => {
|
||||
}: PropsWithChildren<AlertConditionsProps<ConditionProps, ActionGroupIds>>) => {
|
||||
const [withConditions, withoutConditions] = partition(
|
||||
includeBuiltInActionGroups
|
||||
? actionGroups
|
||||
|
|
|
@ -9,8 +9,8 @@ import { EuiFormRow, EuiButtonIcon, EuiTitle } from '@elastic/eui';
|
|||
import { AlertConditionsProps, ActionGroupWithCondition } from './alert_conditions';
|
||||
|
||||
export type AlertConditionsGroupProps<ConditionProps> = {
|
||||
actionGroup?: ActionGroupWithCondition<ConditionProps>;
|
||||
} & Pick<AlertConditionsProps<ConditionProps>, 'onResetConditionsFor'>;
|
||||
actionGroup?: ActionGroupWithCondition<ConditionProps, string>;
|
||||
} & Pick<AlertConditionsProps<ConditionProps, string>, 'onResetConditionsFor'>;
|
||||
|
||||
export const AlertConditionsGroup = <ConditionProps extends unknown>({
|
||||
actionGroup,
|
||||
|
|
|
@ -155,9 +155,11 @@ export const OPTIONAL_ACTION_VARIABLES = ['context'] as const;
|
|||
export type ActionVariables = AsActionVariables<typeof REQUIRED_ACTION_VARIABLES[number]> &
|
||||
Partial<AsActionVariables<typeof OPTIONAL_ACTION_VARIABLES[number]>>;
|
||||
|
||||
export interface AlertType
|
||||
extends Pick<
|
||||
CommonAlertType,
|
||||
export interface AlertType<
|
||||
ActionGroupIds extends string = string,
|
||||
RecoveryActionGroupId extends string = string
|
||||
> extends Pick<
|
||||
CommonAlertType<ActionGroupIds, RecoveryActionGroupId>,
|
||||
| 'id'
|
||||
| 'name'
|
||||
| 'actionGroups'
|
||||
|
@ -184,7 +186,8 @@ export interface AlertTableItem extends Alert {
|
|||
|
||||
export interface AlertTypeParamsExpressionProps<
|
||||
Params extends AlertTypeParams = AlertTypeParams,
|
||||
MetaData = Record<string, any>
|
||||
MetaData = Record<string, any>,
|
||||
ActionGroupIds extends string = string
|
||||
> {
|
||||
alertParams: Params;
|
||||
alertInterval: string;
|
||||
|
@ -196,7 +199,7 @@ export interface AlertTypeParamsExpressionProps<
|
|||
) => void;
|
||||
errors: IErrorObject;
|
||||
defaultActionGroupId: string;
|
||||
actionGroups: ActionGroup[];
|
||||
actionGroups: Array<ActionGroup<ActionGroupIds>>;
|
||||
metadata?: MetaData;
|
||||
charts: ChartsPluginSetup;
|
||||
data: DataPublicPluginStart;
|
||||
|
|
|
@ -4,14 +4,13 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
interface ActionGroupDefinition {
|
||||
id: string;
|
||||
name: string;
|
||||
}
|
||||
import { ActionGroup } from '../../../alerts/common';
|
||||
|
||||
type ActionGroupDefinitions = Record<string, ActionGroupDefinition>;
|
||||
|
||||
export const ACTION_GROUP_DEFINITIONS: ActionGroupDefinitions = {
|
||||
export const ACTION_GROUP_DEFINITIONS: {
|
||||
MONITOR_STATUS: ActionGroup<'xpack.uptime.alerts.actionGroups.monitorStatus'>;
|
||||
TLS: ActionGroup<'xpack.uptime.alerts.actionGroups.tls'>;
|
||||
DURATION_ANOMALY: ActionGroup<'xpack.uptime.alerts.actionGroups.durationAnomaly'>;
|
||||
} = {
|
||||
MONITOR_STATUS: {
|
||||
id: 'xpack.uptime.alerts.actionGroups.monitorStatus',
|
||||
name: 'Uptime Down Monitor',
|
||||
|
|
|
@ -874,7 +874,13 @@ describe('status check alert', () => {
|
|||
});
|
||||
|
||||
describe('alert factory', () => {
|
||||
let alert: AlertType<AlertTypeParams, AlertTypeState, AlertInstanceState, AlertInstanceContext>;
|
||||
let alert: AlertType<
|
||||
AlertTypeParams,
|
||||
AlertTypeState,
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext,
|
||||
'xpack.uptime.alerts.actionGroups.monitorStatus'
|
||||
>;
|
||||
|
||||
beforeEach(() => {
|
||||
const { server, libs, plugins } = bootstrapDependencies();
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
import { KibanaRequest, SavedObjectsClientContract } from 'kibana/server';
|
||||
import moment from 'moment';
|
||||
import { schema } from '@kbn/config-schema';
|
||||
import { ActionGroupIdsOf } from '../../../../alerts/common';
|
||||
import { updateState } from './common';
|
||||
import { ACTION_GROUP_DEFINITIONS } from '../../../common/constants/alerts';
|
||||
import { commonStateTranslations, durationAnomalyTranslations } from './translations';
|
||||
|
@ -20,6 +21,7 @@ import { getLatestMonitor } from '../requests/get_latest_monitor';
|
|||
import { uptimeAlertWrapper } from './uptime_alert_wrapper';
|
||||
|
||||
const { DURATION_ANOMALY } = ACTION_GROUP_DEFINITIONS;
|
||||
export type ActionGroupIds = ActionGroupIdsOf<typeof DURATION_ANOMALY>;
|
||||
|
||||
export const getAnomalySummary = (anomaly: AnomaliesTableRecord, monitorInfo: Ping) => {
|
||||
return {
|
||||
|
@ -61,8 +63,12 @@ const getAnomalies = async (
|
|||
);
|
||||
};
|
||||
|
||||
export const durationAnomalyAlertFactory: UptimeAlertTypeFactory = (_server, _libs, plugins) =>
|
||||
uptimeAlertWrapper({
|
||||
export const durationAnomalyAlertFactory: UptimeAlertTypeFactory<ActionGroupIds> = (
|
||||
_server,
|
||||
_libs,
|
||||
plugins
|
||||
) =>
|
||||
uptimeAlertWrapper<ActionGroupIds>({
|
||||
id: 'xpack.uptime.alerts.durationAnomaly',
|
||||
name: durationAnomalyTranslations.alertFactoryName,
|
||||
validate: {
|
||||
|
|
|
@ -5,12 +5,15 @@
|
|||
*/
|
||||
|
||||
import { UptimeAlertTypeFactory } from './types';
|
||||
import { statusCheckAlertFactory } from './status_check';
|
||||
import { tlsAlertFactory } from './tls';
|
||||
import { durationAnomalyAlertFactory } from './duration_anomaly';
|
||||
|
||||
export const uptimeAlertTypeFactories: UptimeAlertTypeFactory[] = [
|
||||
statusCheckAlertFactory,
|
||||
tlsAlertFactory,
|
||||
import { statusCheckAlertFactory, ActionGroupIds as statusCheckActionGroup } from './status_check';
|
||||
import { tlsAlertFactory, ActionGroupIds as tlsActionGroup } from './tls';
|
||||
import {
|
||||
durationAnomalyAlertFactory,
|
||||
];
|
||||
ActionGroupIds as durationAnomalyActionGroup,
|
||||
} from './duration_anomaly';
|
||||
|
||||
export const uptimeAlertTypeFactories: [
|
||||
UptimeAlertTypeFactory<statusCheckActionGroup>,
|
||||
UptimeAlertTypeFactory<tlsActionGroup>,
|
||||
UptimeAlertTypeFactory<durationAnomalyActionGroup>
|
||||
] = [statusCheckAlertFactory, tlsAlertFactory, durationAnomalyAlertFactory];
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
import { schema } from '@kbn/config-schema';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import Mustache from 'mustache';
|
||||
import { ActionGroupIdsOf } from '../../../../alerts/common';
|
||||
import { UptimeAlertTypeFactory } from './types';
|
||||
import { esKuery } from '../../../../../../src/plugins/data/server';
|
||||
import { JsonObject } from '../../../../../../src/plugins/kibana_utils/common';
|
||||
|
@ -28,6 +29,7 @@ import { getUptimeIndexPattern, IndexPatternTitleAndFields } from '../requests/g
|
|||
import { UMServerLibs, UptimeESClient } from '../lib';
|
||||
|
||||
const { MONITOR_STATUS } = ACTION_GROUP_DEFINITIONS;
|
||||
export type ActionGroupIds = ActionGroupIdsOf<typeof MONITOR_STATUS>;
|
||||
|
||||
const getMonIdByLoc = (monitorId: string, location: string) => {
|
||||
return monitorId + '-' + location;
|
||||
|
@ -178,8 +180,8 @@ const getInstanceId = (monitorInfo: Ping, monIdByLoc: string) => {
|
|||
return `${urlText}_${monIdByLoc}`;
|
||||
};
|
||||
|
||||
export const statusCheckAlertFactory: UptimeAlertTypeFactory = (_server, libs) =>
|
||||
uptimeAlertWrapper({
|
||||
export const statusCheckAlertFactory: UptimeAlertTypeFactory<ActionGroupIds> = (_server, libs) =>
|
||||
uptimeAlertWrapper<ActionGroupIds>({
|
||||
id: 'xpack.uptime.alerts.monitorStatus',
|
||||
name: i18n.translate('xpack.uptime.alerts.monitorStatus', {
|
||||
defaultMessage: 'Uptime monitor status',
|
||||
|
|
|
@ -14,8 +14,10 @@ import { Cert, CertResult } from '../../../common/runtime_types';
|
|||
import { commonStateTranslations, tlsTranslations } from './translations';
|
||||
import { DEFAULT_FROM, DEFAULT_TO } from '../../rest_api/certs/certs';
|
||||
import { uptimeAlertWrapper } from './uptime_alert_wrapper';
|
||||
import { ActionGroupIdsOf } from '../../../../alerts/common';
|
||||
|
||||
const { TLS } = ACTION_GROUP_DEFINITIONS;
|
||||
export type ActionGroupIds = ActionGroupIdsOf<typeof TLS>;
|
||||
|
||||
const DEFAULT_SIZE = 20;
|
||||
|
||||
|
@ -82,8 +84,8 @@ export const getCertSummary = (
|
|||
};
|
||||
};
|
||||
|
||||
export const tlsAlertFactory: UptimeAlertTypeFactory = (_server, libs) =>
|
||||
uptimeAlertWrapper({
|
||||
export const tlsAlertFactory: UptimeAlertTypeFactory<ActionGroupIds> = (_server, libs) =>
|
||||
uptimeAlertWrapper<ActionGroupIds>({
|
||||
id: 'xpack.uptime.alerts.tls',
|
||||
name: tlsTranslations.alertFactoryName,
|
||||
validate: {
|
||||
|
|
|
@ -10,7 +10,7 @@ import { AlertType, AlertInstanceState, AlertInstanceContext } from '../../../..
|
|||
|
||||
export type UptimeAlertTypeParam = Record<string, any>;
|
||||
export type UptimeAlertTypeState = Record<string, any>;
|
||||
export type UptimeAlertTypeFactory = (
|
||||
export type UptimeAlertTypeFactory<ActionGroupIds extends string> = (
|
||||
server: UptimeCoreSetup,
|
||||
libs: UMServerLibs,
|
||||
plugins: UptimeCorePlugins
|
||||
|
@ -18,5 +18,6 @@ export type UptimeAlertTypeFactory = (
|
|||
UptimeAlertTypeParam,
|
||||
UptimeAlertTypeState,
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext
|
||||
AlertInstanceContext,
|
||||
ActionGroupIds
|
||||
>;
|
||||
|
|
|
@ -15,8 +15,8 @@ import { DynamicSettings } from '../../../common/runtime_types';
|
|||
import { createUptimeESClient, UptimeESClient } from '../lib';
|
||||
import { UptimeAlertTypeFactory, UptimeAlertTypeParam, UptimeAlertTypeState } from './types';
|
||||
|
||||
export interface UptimeAlertType
|
||||
extends Omit<ReturnType<UptimeAlertTypeFactory>, 'executor' | 'producer'> {
|
||||
export interface UptimeAlertType<ActionGroupIds extends string>
|
||||
extends Omit<ReturnType<UptimeAlertTypeFactory<ActionGroupIds>>, 'executor' | 'producer'> {
|
||||
executor: ({
|
||||
options,
|
||||
uptimeEsClient,
|
||||
|
@ -26,7 +26,8 @@ export interface UptimeAlertType
|
|||
UptimeAlertTypeParam,
|
||||
UptimeAlertTypeState,
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext
|
||||
AlertInstanceContext,
|
||||
ActionGroupIds
|
||||
>;
|
||||
uptimeEsClient: UptimeESClient;
|
||||
dynamicSettings: DynamicSettings;
|
||||
|
@ -34,7 +35,9 @@ export interface UptimeAlertType
|
|||
}) => Promise<UptimeAlertTypeState | void>;
|
||||
}
|
||||
|
||||
export const uptimeAlertWrapper = (uptimeAlert: UptimeAlertType) => ({
|
||||
export const uptimeAlertWrapper = <ActionGroupIds extends string>(
|
||||
uptimeAlert: UptimeAlertType<ActionGroupIds>
|
||||
) => ({
|
||||
...uptimeAlert,
|
||||
producer: 'uptime',
|
||||
executor: async (
|
||||
|
@ -42,7 +45,8 @@ export const uptimeAlertWrapper = (uptimeAlert: UptimeAlertType) => ({
|
|||
UptimeAlertTypeParam,
|
||||
UptimeAlertTypeState,
|
||||
AlertInstanceState,
|
||||
AlertInstanceContext
|
||||
AlertInstanceContext,
|
||||
ActionGroupIds
|
||||
>
|
||||
) => {
|
||||
const {
|
||||
|
|
|
@ -61,7 +61,13 @@ function getAlwaysFiringAlertType() {
|
|||
interface InstanceContext extends AlertInstanceContext {
|
||||
instanceContextValue: boolean;
|
||||
}
|
||||
const result: AlertType<ParamsType & AlertTypeParams, State, InstanceState, InstanceContext> = {
|
||||
const result: AlertType<
|
||||
ParamsType & AlertTypeParams,
|
||||
State,
|
||||
InstanceState,
|
||||
InstanceContext,
|
||||
'default' | 'other'
|
||||
> = {
|
||||
id: 'test.always-firing',
|
||||
name: 'Test: Always Firing',
|
||||
actionGroups: [
|
||||
|
@ -149,7 +155,7 @@ function getCumulativeFiringAlertType() {
|
|||
interface InstanceState extends AlertInstanceState {
|
||||
instanceStateValue: boolean;
|
||||
}
|
||||
const result: AlertType<{}, State, InstanceState, {}> = {
|
||||
const result: AlertType<{}, State, InstanceState, {}, 'default' | 'other'> = {
|
||||
id: 'test.cumulative-firing',
|
||||
name: 'Test: Cumulative Firing',
|
||||
actionGroups: [
|
||||
|
@ -189,7 +195,7 @@ function getNeverFiringAlertType() {
|
|||
interface State extends AlertTypeState {
|
||||
globalStateValue: boolean;
|
||||
}
|
||||
const result: AlertType<ParamsType, State, {}, {}> = {
|
||||
const result: AlertType<ParamsType, State, {}, {}, 'default'> = {
|
||||
id: 'test.never-firing',
|
||||
name: 'Test: Never firing',
|
||||
actionGroups: [
|
||||
|
@ -229,7 +235,7 @@ function getFailingAlertType() {
|
|||
reference: schema.string(),
|
||||
});
|
||||
type ParamsType = TypeOf<typeof paramsSchema>;
|
||||
const result: AlertType<ParamsType, {}, {}, {}> = {
|
||||
const result: AlertType<ParamsType, {}, {}, {}, 'default'> = {
|
||||
id: 'test.failing',
|
||||
name: 'Test: Failing',
|
||||
validate: {
|
||||
|
@ -271,7 +277,7 @@ function getAuthorizationAlertType(core: CoreSetup<FixtureStartDeps>) {
|
|||
reference: schema.string(),
|
||||
});
|
||||
type ParamsType = TypeOf<typeof paramsSchema>;
|
||||
const result: AlertType<ParamsType, {}, {}, {}> = {
|
||||
const result: AlertType<ParamsType, {}, {}, {}, 'default'> = {
|
||||
id: 'test.authorization',
|
||||
name: 'Test: Authorization',
|
||||
actionGroups: [
|
||||
|
@ -358,7 +364,7 @@ function getValidationAlertType() {
|
|||
param1: schema.string(),
|
||||
});
|
||||
type ParamsType = TypeOf<typeof paramsSchema>;
|
||||
const result: AlertType<ParamsType, {}, {}, {}> = {
|
||||
const result: AlertType<ParamsType, {}, {}, {}, 'default'> = {
|
||||
id: 'test.validation',
|
||||
name: 'Test: Validation',
|
||||
actionGroups: [
|
||||
|
@ -390,7 +396,7 @@ function getPatternFiringAlertType() {
|
|||
interface State extends AlertTypeState {
|
||||
patternIndex?: number;
|
||||
}
|
||||
const result: AlertType<ParamsType, State, {}, {}> = {
|
||||
const result: AlertType<ParamsType, State, {}, {}, 'default'> = {
|
||||
id: 'test.patternFiring',
|
||||
name: 'Test: Firing on a Pattern',
|
||||
actionGroups: [{ id: 'default', name: 'Default' }],
|
||||
|
@ -454,7 +460,7 @@ export function defineAlertTypes(
|
|||
core: CoreSetup<FixtureStartDeps>,
|
||||
{ alerts }: Pick<FixtureSetupDeps, 'alerts'>
|
||||
) {
|
||||
const noopAlertType: AlertType = {
|
||||
const noopAlertType: AlertType<{}, {}, {}, {}, 'default'> = {
|
||||
id: 'test.noop',
|
||||
name: 'Test: Noop',
|
||||
actionGroups: [{ id: 'default', name: 'Default' }],
|
||||
|
@ -463,7 +469,7 @@ export function defineAlertTypes(
|
|||
minimumLicenseRequired: 'basic',
|
||||
async executor() {},
|
||||
};
|
||||
const goldNoopAlertType: AlertType = {
|
||||
const goldNoopAlertType: AlertType<{}, {}, {}, {}, 'default'> = {
|
||||
id: 'test.gold.noop',
|
||||
name: 'Test: Noop',
|
||||
actionGroups: [{ id: 'default', name: 'Default' }],
|
||||
|
@ -472,7 +478,7 @@ export function defineAlertTypes(
|
|||
minimumLicenseRequired: 'gold',
|
||||
async executor() {},
|
||||
};
|
||||
const onlyContextVariablesAlertType: AlertType = {
|
||||
const onlyContextVariablesAlertType: AlertType<{}, {}, {}, {}, 'default'> = {
|
||||
id: 'test.onlyContextVariables',
|
||||
name: 'Test: Only Context Variables',
|
||||
actionGroups: [{ id: 'default', name: 'Default' }],
|
||||
|
@ -484,7 +490,7 @@ export function defineAlertTypes(
|
|||
},
|
||||
async executor() {},
|
||||
};
|
||||
const onlyStateVariablesAlertType: AlertType = {
|
||||
const onlyStateVariablesAlertType: AlertType<{}, {}, {}, {}, 'default'> = {
|
||||
id: 'test.onlyStateVariables',
|
||||
name: 'Test: Only State Variables',
|
||||
actionGroups: [{ id: 'default', name: 'Default' }],
|
||||
|
@ -496,7 +502,7 @@ export function defineAlertTypes(
|
|||
minimumLicenseRequired: 'basic',
|
||||
async executor() {},
|
||||
};
|
||||
const throwAlertType: AlertType = {
|
||||
const throwAlertType: AlertType<{}, {}, {}, {}, 'default'> = {
|
||||
id: 'test.throw',
|
||||
name: 'Test: Throw',
|
||||
actionGroups: [
|
||||
|
@ -512,7 +518,7 @@ export function defineAlertTypes(
|
|||
throw new Error('this alert is intended to fail');
|
||||
},
|
||||
};
|
||||
const longRunningAlertType: AlertType = {
|
||||
const longRunningAlertType: AlertType<{}, {}, {}, {}, 'default'> = {
|
||||
id: 'test.longRunning',
|
||||
name: 'Test: Long Running',
|
||||
actionGroups: [
|
||||
|
|
|
@ -6,13 +6,13 @@
|
|||
|
||||
import { CoreSetup } from 'src/core/server';
|
||||
import { FixtureStartDeps, FixtureSetupDeps } from './plugin';
|
||||
import { AlertType, AlertExecutorOptions } from '../../../../../../../plugins/alerts/server';
|
||||
import { AlertType } from '../../../../../../../plugins/alerts/server';
|
||||
|
||||
export function defineAlertTypes(
|
||||
core: CoreSetup<FixtureStartDeps>,
|
||||
{ alerts }: Pick<FixtureSetupDeps, 'alerts'>
|
||||
) {
|
||||
const noopRestrictedAlertType: AlertType = {
|
||||
const noopRestrictedAlertType: AlertType<{}, {}, {}, {}, 'default', 'restrictedRecovered'> = {
|
||||
id: 'test.restricted-noop',
|
||||
name: 'Test: Restricted Noop',
|
||||
actionGroups: [{ id: 'default', name: 'Default' }],
|
||||
|
@ -20,16 +20,16 @@ export function defineAlertTypes(
|
|||
defaultActionGroupId: 'default',
|
||||
minimumLicenseRequired: 'basic',
|
||||
recoveryActionGroup: { id: 'restrictedRecovered', name: 'Restricted Recovery' },
|
||||
async executor({ services, params, state }: AlertExecutorOptions) {},
|
||||
async executor() {},
|
||||
};
|
||||
const noopUnrestrictedAlertType: AlertType = {
|
||||
const noopUnrestrictedAlertType: AlertType<{}, {}, {}, {}, 'default'> = {
|
||||
id: 'test.unrestricted-noop',
|
||||
name: 'Test: Unrestricted Noop',
|
||||
actionGroups: [{ id: 'default', name: 'Default' }],
|
||||
producer: 'alertsRestrictedFixture',
|
||||
defaultActionGroupId: 'default',
|
||||
minimumLicenseRequired: 'basic',
|
||||
async executor({ services, params, state }: AlertExecutorOptions) {},
|
||||
async executor() {},
|
||||
};
|
||||
alerts.registerType(noopRestrictedAlertType);
|
||||
alerts.registerType(noopUnrestrictedAlertType);
|
||||
|
|
|
@ -17,7 +17,7 @@ export interface AlertingExampleDeps {
|
|||
features: FeaturesPluginSetup;
|
||||
}
|
||||
|
||||
export const noopAlertType: AlertType = {
|
||||
export const noopAlertType: AlertType<{}, {}, {}, {}, 'default'> = {
|
||||
id: 'test.noop',
|
||||
name: 'Test: Noop',
|
||||
actionGroups: [{ id: 'default', name: 'Default' }],
|
||||
|
@ -33,7 +33,9 @@ export const alwaysFiringAlertType: AlertType<
|
|||
globalStateValue: boolean;
|
||||
groupInSeriesIndex: number;
|
||||
},
|
||||
{ instanceStateValue: boolean; globalStateValue: boolean; groupInSeriesIndex: number }
|
||||
{ instanceStateValue: boolean; globalStateValue: boolean; groupInSeriesIndex: number },
|
||||
never,
|
||||
'default' | 'other'
|
||||
> = {
|
||||
id: 'test.always-firing',
|
||||
name: 'Always Firing',
|
||||
|
@ -61,7 +63,7 @@ export const alwaysFiringAlertType: AlertType<
|
|||
},
|
||||
};
|
||||
|
||||
export const failingAlertType: AlertType = {
|
||||
export const failingAlertType: AlertType<never, never, never, never, 'default' | 'other'> = {
|
||||
id: 'test.failing',
|
||||
name: 'Test: Failing',
|
||||
actionGroups: [
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue