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] [Alerting] "Group by" functionality #68250

Merged
merged 35 commits into from
Jun 30, 2020
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
a02b17d
Server side (executor) support for group by
Kerry350 Jun 2, 2020
dd92f5f
Add UI functionality
Kerry350 Jun 4, 2020
2f9f6cd
Ensure array entries
Kerry350 Jun 4, 2020
4246222
Merge remote-tracking branch 'upstream/master' into 67465-logs-alert-…
Kerry350 Jun 4, 2020
7563fac
Merge remote-tracking branch 'upstream/master' into 67465-logs-alert-…
Kerry350 Jun 5, 2020
9be25e6
Merge remote-tracking branch 'upstream/master' into 67465-logs-alert-…
Kerry350 Jun 5, 2020
b773abe
Amend current executor tests
Kerry350 Jun 5, 2020
8726524
Merge branch 'master' into 67465-logs-alert-group-by
elasticmachine Jun 8, 2020
7461571
Merge remote-tracking branch 'upstream/master' into 67465-logs-alert-…
Kerry350 Jun 10, 2020
54d0144
Merge remote-tracking branch 'upstream/master' into 67465-logs-alert-…
Kerry350 Jun 11, 2020
c9ef022
Server side amendments
Kerry350 Jun 12, 2020
27296a9
Client side changes
Kerry350 Jun 12, 2020
b29ee1a
Merge remote-tracking branch 'upstream/master' into 67465-logs-alert-…
Kerry350 Jun 12, 2020
3901a07
Ensure "more than" is handled and ensure correct component is exporte…
Kerry350 Jun 12, 2020
0ceb3fe
Remove hit total capping due to document count total dependency
Kerry350 Jun 12, 2020
f0e11f6
Spread aggs properly
Kerry350 Jun 12, 2020
7806cf3
Alter handling of composite aggs
Kerry350 Jun 12, 2020
971e4bd
Merge remote-tracking branch 'upstream/master' into 67465-logs-alert-…
Kerry350 Jun 12, 2020
c9e56a2
Add response runtime type check
Kerry350 Jun 12, 2020
16608ee
Fix type to account for undefined group_key
Kerry350 Jun 12, 2020
b4bcde8
Merge remote-tracking branch 'upstream/master' into 67465-logs-alert-…
Kerry350 Jun 15, 2020
8bc54ff
Use separate functions for grouped and ungrouped ES queries
Kerry350 Jun 15, 2020
8093dca
Cast a wider net for group results and add "must" filters to a sub ag…
Kerry350 Jun 15, 2020
0ae6fe3
Merge remote-tracking branch 'upstream/master' into 67465-logs-alert-…
Kerry350 Jun 15, 2020
c40d459
Merge remote-tracking branch 'upstream/master' into 67465-logs-alert-…
Kerry350 Jun 15, 2020
aed4063
Merge remote-tracking branch 'upstream/master' into 67465-logs-alert-…
Kerry350 Jun 16, 2020
902bd37
Amend executor tests
Kerry350 Jun 16, 2020
8cae6b6
Ensure inner filtering scopes back to unpadded range
Kerry350 Jun 16, 2020
b67ad73
Merge remote-tracking branch 'upstream/master' into 67465-logs-alert-…
Kerry350 Jun 29, 2020
b50de34
Update x-pack/plugins/infra/server/lib/alerting/log_threshold/log_thr…
Kerry350 Jun 29, 2020
34bbece
Update x-pack/plugins/infra/server/lib/alerting/log_threshold/log_thr…
Kerry350 Jun 29, 2020
827071d
Review changes
Kerry350 Jun 29, 2020
1b4b99f
Merge branch '67465-logs-alert-group-by' of github.com:Kerry350/kiban…
Kerry350 Jun 29, 2020
a6dfeb6
Tweak filtering of fields (remove searchable requirement)
Kerry350 Jun 29, 2020
17b49f8
Update x-pack/plugins/infra/public/components/alerting/logs/expressio…
Kerry350 Jun 29, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions x-pack/plugins/infra/common/alerting/logs/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,17 @@ export interface LogDocumentCountAlertParams {
criteria: Criterion[];
timeUnit: 's' | 'm' | 'h' | 'd';
timeSize: number;
groupBy?: string[];
Kerry350 marked this conversation as resolved.
Show resolved Hide resolved
}

export type TimeUnit = 's' | 'm' | 'h' | 'd';

export interface Aggregations {
Kerry350 marked this conversation as resolved.
Show resolved Hide resolved
[key: string]: Record<string, object[]>;
interval_buckets: {
buckets: Array<{
key: Record<string, string>;
doc_count: number;
}>;
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { DocumentCount } from './document_count';
import { Criteria } from './criteria';
import { useSourceId } from '../../../../containers/source_id';
import { LogSourceProvider, useLogSourceContext } from '../../../../containers/logs/log_source';
import { GroupByExpression } from '../../shared/group_by_expression/group_by_expression';

export interface ExpressionCriteria {
field?: string;
Expand Down Expand Up @@ -172,6 +173,13 @@ export const Editor: React.FC<Props> = (props) => {
[setAlertParams]
);

const updateGroupBy = useCallback(
(groups: string[]) => {
setAlertParams('groupBy', groups);
},
[setAlertParams]
);

const addCriterion = useCallback(() => {
const nextCriteria = alertParams?.criteria
? [...alertParams.criteria, DEFAULT_CRITERIA]
Expand Down Expand Up @@ -219,6 +227,12 @@ export const Editor: React.FC<Props> = (props) => {
errors={errors as { [key: string]: string[] }}
/>

<GroupByExpression
selectedGroups={alertParams.groupBy}
onChange={updateGroupBy}
fields={supportedFields}
/>

<div>
<EuiButtonEmpty
color={'primary'}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export function getAlertType(): AlertTypeModel {
defaultActionMessage: i18n.translate(
'xpack.infra.logs.alerting.threshold.defaultActionMessage',
{
defaultMessage: `\\{\\{context.matchingDocuments\\}\\} log entries have matched the following conditions: \\{\\{context.conditions\\}\\}`,
defaultMessage: `\\{\\{context.group\\}\\} - \\{\\{context.matchingDocuments\\}\\} log entries have matched the following conditions: \\{\\{context.conditions\\}\\}`,
Kerry350 marked this conversation as resolved.
Show resolved Hide resolved
}
),
requiresAppContext: false,
Expand Down
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;
* you may not use this file except in compliance with the Elastic License.
*/

import React, { useState, useMemo } from 'react';
import { IFieldType } from 'src/plugins/data/public';
import { i18n } from '@kbn/i18n';
import {
EuiPopoverTitle,
EuiFlexItem,
EuiFlexGroup,
EuiPopover,
EuiExpression,
} from '@elastic/eui';
import { GroupBySelector } from './selector';

interface Props {
selectedGroups?: string[];
fields: IFieldType[];
onChange: (groupBy: string[]) => void;
label?: string;
}

const DEFAULT_GROUP_BY_LABEL = i18n.translate('xpack.infra.alerting.alertFlyout.groupByLabel', {
defaultMessage: 'Group By',
});

const EVERYTHING_PLACEHOLDER = i18n.translate(
'xpack.infra.alerting.alertFlyout.groupBy.placeholder',
{
defaultMessage: 'Everything (ungrouped)',
Kerry350 marked this conversation as resolved.
Show resolved Hide resolved
}
);

export const GroupByExpression: React.FC<Props> = ({
selectedGroups = [],
fields,
label,
onChange,
}) => {
const [isPopoverOpen, setIsPopoverOpen] = useState(false);

const expressionValue = useMemo(() => {
return selectedGroups.length > 0 ? selectedGroups.join(', ') : EVERYTHING_PLACEHOLDER;
}, [selectedGroups]);

const labelProp = useMemo(() => {
Kerry350 marked this conversation as resolved.
Show resolved Hide resolved
return label || DEFAULT_GROUP_BY_LABEL;
Kerry350 marked this conversation as resolved.
Show resolved Hide resolved
}, [label]);

return (
<EuiFlexGroup gutterSize="s">
<EuiFlexItem grow={false}>
<EuiPopover
id="groupByExpression"
button={
<EuiExpression
description={labelProp}
uppercase={true}
value={expressionValue}
isActive={isPopoverOpen}
onClick={() => setIsPopoverOpen(true)}
/>
}
isOpen={isPopoverOpen}
closePopover={() => setIsPopoverOpen(false)}
ownFocus
panelPaddingSize="s"
anchorPosition="downLeft"
>
<div style={{ zIndex: 11000 }}>
<EuiPopoverTitle>{labelProp}</EuiPopoverTitle>
<GroupBySelector
selectedGroups={selectedGroups}
onChange={onChange}
fields={fields}
label={labelProp}
placeholder={EVERYTHING_PLACEHOLDER}
/>
</div>
</EuiPopover>
</EuiFlexItem>
</EuiFlexGroup>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { EuiComboBox } from '@elastic/eui';
import React, { useCallback, useMemo } from 'react';
import { IFieldType } from 'src/plugins/data/public';

interface Props {
selectedGroups?: string[];
onChange: (groupBy: string[]) => void;
fields: IFieldType[];
label: string;
placeholder: string;
}

export const GroupBySelector = ({
onChange,
fields,
selectedGroups = [],
label,
placeholder,
}: Props) => {
const handleChange = useCallback(
(selectedOptions: Array<{ label: string }>) => {
const groupBy = selectedOptions.map((option) => option.label);
onChange(groupBy);
},
[onChange]
);

const formattedSelectedGroups = useMemo(() => {
return selectedGroups.map((group) => ({ label: group }));
}, [selectedGroups]);

const options = useMemo(() => {
return fields
Kerry350 marked this conversation as resolved.
Show resolved Hide resolved
.filter((field) => field.aggregatable && field.type === 'string')
Kerry350 marked this conversation as resolved.
Show resolved Hide resolved
.map((field) => ({ label: field.name }));
}, [fields]);

return (
<div style={{ minWidth: '300px' }}>
<EuiComboBox
placeholder={placeholder}
aria-label={label}
fullWidth
singleSelection={false}
selectedOptions={formattedSelectedGroups}
options={options}
onChange={handleChange}
isClearable={true}
/>
</div>
);
};
Loading