Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Logs UI] Log threshold ratio alerts #76867

Merged
merged 11 commits into from
Sep 29, 2020
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,18 @@
*/
import { i18n } from '@kbn/i18n';
import * as rt from 'io-ts';
import { commonSearchSuccessResponseFieldsRT } from '../../utils/elasticsearch_runtime_types';
import { commonSearchSuccessResponseFieldsRT } from '../../../utils/elasticsearch_runtime_types';

export const LOG_DOCUMENT_COUNT_ALERT_TYPE_ID = 'logs.alert.document.count';

const ThresholdTypeRT = rt.keyof({
count: null,
ratio: null,
});

export type ThresholdType = rt.TypeOf<typeof ThresholdTypeRT>;

// Comparators //
export enum Comparator {
GT = 'more than',
GT_OR_EQ = 'more than or equals',
Expand Down Expand Up @@ -82,19 +90,20 @@ export const ComparatorToi18nMap = {
),
};

// Alert parameters //
export enum AlertStates {
OK,
ALERT,
NO_DATA,
ERROR,
}

const DocumentCountRT = rt.type({
const ThresholdRT = rt.type({
comparator: ComparatorRT,
value: rt.number,
});

export type DocumentCount = rt.TypeOf<typeof DocumentCountRT>;
export type Threshold = rt.TypeOf<typeof ThresholdRT>;

export const CriterionRT = rt.type({
field: rt.string,
Expand All @@ -104,6 +113,13 @@ export const CriterionRT = rt.type({

export type Criterion = rt.TypeOf<typeof CriterionRT>;
export const criteriaRT = rt.array(CriterionRT);
export type Criteria = rt.TypeOf<typeof criteriaRT>;

export const countCriteriaRT = criteriaRT;
export type CountCriteria = rt.TypeOf<typeof countCriteriaRT>;

export const ratioCriteriaRT = rt.tuple([criteriaRT, criteriaRT]);
export type RatioCriteria = rt.TypeOf<typeof ratioCriteriaRT>;

export const TimeUnitRT = rt.union([
rt.literal('s'),
Expand All @@ -116,25 +132,69 @@ export type TimeUnit = rt.TypeOf<typeof TimeUnitRT>;
export const timeSizeRT = rt.number;
export const groupByRT = rt.array(rt.string);

export const LogDocumentCountAlertParamsRT = rt.intersection([
const RequiredAlertParamsRT = rt.type({
// NOTE: "count" would be better named as "threshold", but this would require a
// migration of encrypted saved objects, so we'll keep "count" until it's problematic.
count: ThresholdRT,
timeUnit: TimeUnitRT,
timeSize: timeSizeRT,
});

const OptionalAlertParamsRT = rt.partial({
groupBy: groupByRT,
});

export const alertParamsRT = rt.intersection([
rt.type({
count: DocumentCountRT,
criteria: criteriaRT,
timeUnit: TimeUnitRT,
timeSize: timeSizeRT,
criteria: countCriteriaRT,
...RequiredAlertParamsRT.props,
}),
rt.partial({
groupBy: groupByRT,
...OptionalAlertParamsRT.props,
}),
]);

export type LogDocumentCountAlertParams = rt.TypeOf<typeof LogDocumentCountAlertParamsRT>;
export type CountAlertParams = rt.TypeOf<typeof alertParamsRT>;

export const ratioAlertParamsRT = rt.intersection([
rt.type({
criteria: ratioCriteriaRT,
...RequiredAlertParamsRT.props,
}),
rt.partial({
...OptionalAlertParamsRT.props,
}),
]);

export type RatioAlertParams = rt.TypeOf<typeof ratioAlertParamsRT>;

export const AlertParamsRT = rt.union([alertParamsRT, ratioAlertParamsRT]);
export type AlertParams = rt.TypeOf<typeof AlertParamsRT>;

export const isRatioAlert = (criteria: AlertParams['criteria']) => {
return criteria.length > 0 && Array.isArray(criteria[0]) ? true : false;
};

export const getNumerator = (criteria: RatioCriteria): Criteria => {
return criteria[0];
};

export const getDenominator = (criteria: RatioCriteria): Criteria => {
return criteria[1];
};

export const hasGroupBy = (alertParams: AlertParams) => {
const { groupBy } = alertParams;
return groupBy && groupBy.length > 0 ? true : false;
};

// Chart previews //
const chartPreviewHistogramBucket = rt.type({
key: rt.number,
doc_count: rt.number,
});

// ES query responses //
export const UngroupedSearchQueryResponseRT = rt.intersection([
commonSearchSuccessResponseFieldsRT,
rt.intersection([
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@
*/

import * as rt from 'io-ts';
import { criteriaRT, TimeUnitRT, timeSizeRT, groupByRT } from '../../alerting/logs/types';
import {
criteriaRT,
TimeUnitRT,
timeSizeRT,
groupByRT,
} from '../../alerting/logs/log_threshold/types';

export const LOG_ALERTS_CHART_PREVIEW_DATA_PATH = '/api/infra/log_alerts/chart_preview_data';

Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import React, { useState, useCallback, useMemo } from 'react';
import { EuiPopover, EuiButtonEmpty, EuiContextMenuItem, EuiContextMenuPanel } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
import { AlertFlyout } from './alert_flyout';
import { useLinkProps } from '../../../hooks/use_link_props';
import { useLinkProps } from '../../../../hooks/use_link_props';

export const AlertDropdown = () => {
const [popoverOpen, setPopoverOpen] = useState(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,10 @@

import React, { useContext } from 'react';
import { ApplicationStart, DocLinksStart, HttpStart, NotificationsStart } from 'src/core/public';

import { AlertsContextProvider, AlertAdd } from '../../../../../triggers_actions_ui/public';
import { TriggerActionsContext } from '../../../utils/triggers_actions_context';
import { useKibana } from '../../../../../../../src/plugins/kibana_react/public';
import { LOG_DOCUMENT_COUNT_ALERT_TYPE_ID } from '../../../../common/alerting/logs/types';
import { AlertsContextProvider, AlertAdd } from '../../../../../../triggers_actions_ui/public';
import { TriggerActionsContext } from '../../../../utils/triggers_actions_context';
import { useKibana } from '../../../../../../../../src/plugins/kibana_react/public';
import { LOG_DOCUMENT_COUNT_ALERT_TYPE_ID } from '../../../../../common/alerting/logs/log_threshold/types';

interface Props {
visible?: boolean;
Expand Down
Loading