Skip to content

Commit

Permalink
[Logs UI] Register log threshold rule as lifecycle rule (#104341)
Browse files Browse the repository at this point in the history
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
  • Loading branch information
weltenwort and kibanamachine committed Jul 13, 2021
1 parent 8c9de0b commit e9f42d2
Show file tree
Hide file tree
Showing 28 changed files with 844 additions and 342 deletions.
8 changes: 7 additions & 1 deletion x-pack/plugins/apm/server/lib/alerts/test_utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,14 @@ export const createRuleTypeMocks = () => {
executor: async ({ params }: { params: Record<string, any> }) => {
return alertExecutor({
services,
rule: { consumer: APM_SERVER_FEATURE_ID },
params,
rule: {
consumer: APM_SERVER_FEATURE_ID,
name: 'name',
producer: 'producer',
ruleTypeId: 'ruleTypeId',
ruleTypeName: 'ruleTypeName',
},
startedAt: new Date(),
});
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

export * from './rule_data';
export * from './types';
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { jsonRt } from '@kbn/io-ts-utils/target/json_rt';
import * as rt from 'io-ts';
import { alertParamsRT as logThresholdAlertParamsRT } from './types';

export const serializedParamsKey = 'serialized_params';

export const logThresholdRuleDataNamespace = 'log_threshold_rule';
export const logThresholdRuleDataSerializedParamsKey = `${logThresholdRuleDataNamespace}.${serializedParamsKey}` as const;

export const logThresholdRuleDataRT = rt.type({
[logThresholdRuleDataSerializedParamsKey]: rt.array(jsonRt.pipe(logThresholdAlertParamsRT)),
});
5 changes: 5 additions & 0 deletions x-pack/plugins/infra/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,8 @@ export const LOGS_INDEX_PATTERN = 'logs-*,filebeat-*,kibana_sample_data_logs*';
export const TIMESTAMP_FIELD = '@timestamp';
export const METRICS_APP = 'metrics';
export const LOGS_APP = 'logs';

export const METRICS_FEATURE_ID = 'infrastructure';
export const LOGS_FEATURE_ID = 'logs';

export type InfraFeatureId = typeof METRICS_FEATURE_ID | typeof LOGS_FEATURE_ID;
3 changes: 2 additions & 1 deletion x-pack/plugins/infra/kibana.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
"visTypeTimeseries",
"alerting",
"triggersActionsUi",
"observability"
"observability",
"ruleRegistry"
],
"optionalPlugins": ["ml", "home", "embeddable"],
"server": true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@
* 2.0.
*/

export { getAlertType } from './log_threshold_alert_type';
export * from './log_threshold_alert_type';
export { AlertDropdown } from './components/alert_dropdown';
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@

import { i18n } from '@kbn/i18n';
import React from 'react';
import { AlertTypeModel } from '../../../../triggers_actions_ui/public';
import { ObservabilityRuleTypeModel } from '../../../../observability/public';
import {
LOG_DOCUMENT_COUNT_ALERT_TYPE_ID,
PartialAlertParams,
} from '../../../common/alerting/logs/log_threshold/types';
import { formatReason } from './rule_data_formatters';
import { validateExpression } from './validation';

export function getAlertType(): AlertTypeModel<PartialAlertParams> {
export function createLogThresholdAlertType(): ObservabilityRuleTypeModel<PartialAlertParams> {
return {
id: LOG_DOCUMENT_COUNT_ALERT_TYPE_ID,
description: i18n.translate('xpack.infra.logs.alertFlyout.alertDescription', {
Expand All @@ -33,5 +34,6 @@ export function getAlertType(): AlertTypeModel<PartialAlertParams> {
}
),
requiresAppContext: false,
format: formatReason,
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { i18n } from '@kbn/i18n';
import {
ALERT_EVALUATION_THRESHOLD,
ALERT_EVALUATION_VALUE,
ALERT_ID,
ALERT_START,
} from '@kbn/rule-data-utils';
import { modifyUrl } from '@kbn/std';
import { fold } from 'fp-ts/lib/Either';
import { pipe } from 'fp-ts/lib/function';
import { ObservabilityRuleTypeFormatter } from '../../../../observability/public';
import {
ComparatorToi18nMap,
logThresholdRuleDataRT,
logThresholdRuleDataSerializedParamsKey,
ratioAlertParamsRT,
} from '../../../common/alerting/logs/log_threshold';

export const formatReason: ObservabilityRuleTypeFormatter = ({ fields }) => {
const reason = pipe(
logThresholdRuleDataRT.decode(fields),
fold(
() =>
i18n.translate('xpack.infra.logs.alerting.threshold.unknownReasonDescription', {
defaultMessage: 'unknown reason',
}),
(logThresholdRuleData) => {
const params = logThresholdRuleData[logThresholdRuleDataSerializedParamsKey][0];

const actualCount = fields[ALERT_EVALUATION_VALUE];
const groupName = fields[ALERT_ID];
const isGrouped = (params.groupBy?.length ?? 0) > 0;
const isRatio = ratioAlertParamsRT.is(params);
const thresholdCount = fields[ALERT_EVALUATION_THRESHOLD];
const translatedComparator = ComparatorToi18nMap[params.count.comparator];

if (isRatio) {
return i18n.translate('xpack.infra.logs.alerting.threshold.ratioAlertReasonDescription', {
defaultMessage:
'{isGrouped, select, true{{groupName}: } false{}}The log entries ratio is {actualCount} ({translatedComparator} {thresholdCount}).',
values: {
actualCount,
translatedComparator,
groupName,
isGrouped,
thresholdCount,
},
});
} else {
return i18n.translate('xpack.infra.logs.alerting.threshold.countAlertReasonDescription', {
defaultMessage:
'{isGrouped, select, true{{groupName}: } false{}}{actualCount, plural, one {{actualCount} log entry} other {{actualCount} log entries} } ({translatedComparator} {thresholdCount}) match the configured conditions.',
values: {
actualCount,
translatedComparator,
groupName,
isGrouped,
thresholdCount,
},
});
}
}
)
);

const alertStartDate = fields[ALERT_START];
const timestamp = alertStartDate != null ? new Date(alertStartDate).valueOf() : null;
const link = modifyUrl('/app/logs/link-to/default/logs', ({ query, ...otherUrlParts }) => ({
...otherUrlParts,
query: {
...query,
...(timestamp != null ? { time: `${timestamp}` } : {}),
},
}));

return {
reason,
link, // TODO: refactor to URL generators
};
};
18 changes: 10 additions & 8 deletions x-pack/plugins/infra/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,21 @@ import { AppMountParameters, PluginInitializerContext } from 'kibana/public';
import { from } from 'rxjs';
import { map } from 'rxjs/operators';
import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/public';
import { createMetricThresholdAlertType } from './alerting/metric_threshold';
import { createInventoryMetricAlertType } from './alerting/inventory';
import { getAlertType as getLogsAlertType } from './alerting/log_threshold';
import { createLogThresholdAlertType } from './alerting/log_threshold';
import { createMetricThresholdAlertType } from './alerting/metric_threshold';
import { LOG_STREAM_EMBEDDABLE } from './components/log_stream/log_stream_embeddable';
import { LogStreamEmbeddableFactoryDefinition } from './components/log_stream/log_stream_embeddable_factory';
import { createMetricsFetchData, createMetricsHasData } from './metrics_overview_fetchers';
import { registerFeatures } from './register_feature';
import {
InfraClientSetupDeps,
InfraClientStartDeps,
InfraClientCoreSetup,
InfraClientCoreStart,
InfraClientPluginClass,
InfraClientSetupDeps,
InfraClientStartDeps,
} from './types';
import { getLogsHasDataFetcher, getLogsOverviewDataFetcher } from './utils/logs_overview_fetchers';
import { createMetricsHasData, createMetricsFetchData } from './metrics_overview_fetchers';
import { LOG_STREAM_EMBEDDABLE } from './components/log_stream/log_stream_embeddable';
import { LogStreamEmbeddableFactoryDefinition } from './components/log_stream/log_stream_embeddable_factory';

export class Plugin implements InfraClientPluginClass {
constructor(_context: PluginInitializerContext) {}
Expand All @@ -35,7 +35,9 @@ export class Plugin implements InfraClientPluginClass {
}

pluginsSetup.triggersActionsUi.alertTypeRegistry.register(createInventoryMetricAlertType());
pluginsSetup.triggersActionsUi.alertTypeRegistry.register(getLogsAlertType());
pluginsSetup.observability.observabilityRuleTypeRegistry.register(
createLogThresholdAlertType()
);
pluginsSetup.triggersActionsUi.alertTypeRegistry.register(createMetricThresholdAlertType());

pluginsSetup.observability.dashboard.register({
Expand Down
5 changes: 3 additions & 2 deletions x-pack/plugins/infra/server/features.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ import { LOG_DOCUMENT_COUNT_ALERT_TYPE_ID } from '../common/alerting/logs/log_th
import { METRIC_INVENTORY_THRESHOLD_ALERT_TYPE_ID } from './lib/alerting/inventory_metric_threshold/types';
import { METRIC_THRESHOLD_ALERT_TYPE_ID } from './lib/alerting/metric_threshold/types';
import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/server';
import { LOGS_FEATURE_ID, METRICS_FEATURE_ID } from '../common/constants';

export const METRICS_FEATURE = {
id: 'infrastructure',
id: METRICS_FEATURE_ID,
name: i18n.translate('xpack.infra.featureRegistry.linkInfrastructureTitle', {
defaultMessage: 'Metrics',
}),
Expand Down Expand Up @@ -71,7 +72,7 @@ export const METRICS_FEATURE = {
};

export const LOGS_FEATURE = {
id: 'logs',
id: LOGS_FEATURE_ID,
name: i18n.translate('xpack.infra.featureRegistry.linkLogsTitle', {
defaultMessage: 'Logs',
}),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { PluginSetupContract as FeaturesPluginSetup } from '../../../../../../pl
import { SpacesPluginSetup } from '../../../../../../plugins/spaces/server';
import { PluginSetupContract as AlertingPluginContract } from '../../../../../alerting/server';
import { MlPluginSetup } from '../../../../../ml/server';
import { RuleRegistryPluginSetupContract } from '../../../../../rule_registry/server';

export interface InfraServerPluginSetupDeps {
data: DataPluginSetup;
Expand All @@ -29,6 +30,7 @@ export interface InfraServerPluginSetupDeps {
visTypeTimeseries: VisTypeTimeseriesSetup;
features: FeaturesPluginSetup;
alerting: AlertingPluginContract;
ruleRegistry: RuleRegistryPluginSetupContract;
ml?: MlPluginSetup;
}

Expand Down
Loading

0 comments on commit e9f42d2

Please sign in to comment.