Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ describe('ESQL query utils', () => {
buckets: [
{
doc_count: 1,
key: '1.8.0',
key: ['1.8.0'],
topHitsAgg: {
hits: {
hits: [
Expand All @@ -135,7 +135,7 @@ describe('ESQL query utils', () => {
},
{
doc_count: 1,
key: '1.2.0',
key: ['1.2.0'],
topHitsAgg: {
hits: {
hits: [
Expand All @@ -161,6 +161,7 @@ describe('ESQL query utils', () => {
},
isCountAgg: false,
isGroupAgg: true,
termField: ['ecs.version'],
});
expect(rows).toEqual([
{
Expand Down Expand Up @@ -200,7 +201,7 @@ describe('ESQL query utils', () => {
buckets: [
{
doc_count: 1,
key: '1.8.0',
key: ['1.8.0'],
topHitsAgg: {
hits: {
hits: [
Expand All @@ -219,7 +220,7 @@ describe('ESQL query utils', () => {
},
{
doc_count: 2,
key: '1.2.0',
key: ['1.2.0'],
topHitsAgg: {
hits: {
hits: [
Expand Down Expand Up @@ -254,6 +255,7 @@ describe('ESQL query utils', () => {
},
isCountAgg: false,
isGroupAgg: true,
termField: ['ecs.version'],
});
expect(duplicateAlertIds?.size).toBe(1);
});
Expand Down Expand Up @@ -323,7 +325,17 @@ describe('ESQL query utils', () => {
buckets: [
{
doc_count: 1,
key: '2023-07-12T13:32:04.174Z,1.8.0,www.elastic.co,test,US,Mozilla/5.0 (X11; Linux x86_64; rv:6.0a1) Gecko/20110421 Firefox/6.0a1,info,test message,/app-search',
key: [
'2023-07-12T13:32:04.174Z',
'1.8.0',
'www.elastic.co',
'test',
'US',
'Mozilla/5.0 (X11; Linux x86_64; rv:6.0a1) Gecko/20110421 Firefox/6.0a1',
'info',
'test message',
'/app-search',
],
topHitsAgg: {
hits: {
hits: [
Expand All @@ -350,7 +362,18 @@ describe('ESQL query utils', () => {
},
{
doc_count: 1,
key: '2025-07-12T13:32:04.174Z,1.2.0,400,artifacts.elastic.co,test,US,Mozilla/5.0 (X11; Linux x86_64; rv:6.0a1) Gecko/20110421 Firefox/6.0a1,info,test message,/app-search',
key: [
'2025-07-12T13:32:04.174Z',
'1.2.0',
'400',
'artifacts.elastic.co',
'test',
'US',
'Mozilla/5.0 (X11; Linux x86_64; rv:6.0a1) Gecko/20110421 Firefox/6.0a1',
'info',
'test message',
'/app-search',
],
topHitsAgg: {
hits: {
hits: [
Expand Down Expand Up @@ -387,6 +410,18 @@ describe('ESQL query utils', () => {
},
isCountAgg: false,
isGroupAgg: true,
termField: [
'@timestamp',
'ecs.version',
'error.code',
'host',
'name',
'geo.dest',
'agent',
'tags',
'message',
'request',
],
});
expect(longAlertIds?.size).toBe(1);
});
Expand All @@ -406,7 +441,7 @@ describe('ESQL query utils', () => {
buckets: [
{
doc_count: 1,
key: '400',
key: ['400'],
topHitsAgg: {
hits: {
hits: [
Expand All @@ -432,6 +467,7 @@ describe('ESQL query utils', () => {
},
isCountAgg: false,
isGroupAgg: true,
termField: ['error.code'],
});
expect(rows).toEqual([
{
Expand Down Expand Up @@ -466,7 +502,7 @@ describe('ESQL query utils', () => {
buckets: [
{
doc_count: 1,
key: '1.8.0',
key: ['1.8.0'],
topHitsAgg: {
hits: {
hits: [
Expand All @@ -485,7 +521,7 @@ describe('ESQL query utils', () => {
},
{
doc_count: 1,
key: '400,1.2.0',
key: ['400', '1.2.0'],
topHitsAgg: {
hits: {
hits: [
Expand All @@ -504,7 +540,7 @@ describe('ESQL query utils', () => {
},
{
doc_count: 1,
key: '1.2.0',
key: ['1.2.0'],
topHitsAgg: {
hits: {
hits: [
Expand All @@ -530,6 +566,7 @@ describe('ESQL query utils', () => {
},
isCountAgg: false,
isGroupAgg: true,
termField: ['error.code', 'ecs.version'],
});
expect(rows).toEqual([
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ export const toGroupedEsqlQueryHits = (
const duplicateAlertIds: Set<string> = new Set<string>();
const longAlertIds: Set<string> = new Set<string>();
const rows: EsqlDocument[] = [];
const mappedAlertIds: Record<string, Array<string | null>> = {};
const groupedHits = table.values.reduce<Record<string, EsqlHit[]>>((acc, row) => {
const document = rowToDocument(table.columns, row);
const mappedAlertId = alertIdFields.filter((a) => !isNil(document[a])).map((a) => document[a]);
Expand All @@ -121,6 +122,7 @@ export const toGroupedEsqlQueryHits = (
acc[alertId].push(hit);
} else {
acc[alertId] = [hit];
mappedAlertIds[alertId] = mappedAlertId;
}
rows.push({ [ALERT_ID_COLUMN]: alertId, ...document });

Expand All @@ -135,7 +137,7 @@ export const toGroupedEsqlQueryHits = (
groupAgg: {
buckets: entries(groupedHits).map(([key, value]) => {
return {
key,
key: mappedAlertIds[key],
doc_count: value.length,
topHitsAgg: {
hits: {
Expand All @@ -158,6 +160,7 @@ export const toGroupedEsqlQueryHits = (
hits: { hits: [] },
aggregations,
},
termField: alertIdFields,
},
duplicateAlertIds,
longAlertIds,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,15 +126,17 @@ export default function ruleTests({ getService }: FtrProviderContext) {
const messagePattern =
/Document count is 1 in the last 30s for group-\d. Alert when greater than 0./;
const conditionPattern = /Query matched documents for group "group-\d"/;
const groupPattern = /{"group":"group-\d"}/;

for (let i = 0; i < docs.length; i++) {
const doc = docs[i];
const { hits } = doc._source;
const { hits, grouping } = doc._source;
const { name, title, message } = doc._source.params;
expect(name).to.be('always fire');
expect(title).to.match(titlePattern);
expect(message).to.match(messagePattern);
expect(hits).not.to.be.empty();
expect(grouping).to.match(groupPattern);
}

const aadDocs = await getAllAADDocs(3, ALERT_INSTANCE_ID);
Expand Down Expand Up @@ -174,15 +176,18 @@ export default function ruleTests({ getService }: FtrProviderContext) {
/Query matched documents for group "[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}"/;
const idPattern =
/[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}/;
const groupPattern =
/{"_id":"[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}"}/;

for (let i = 0; i < docs.length; i++) {
const doc = docs[i];
const { hits } = doc._source;
const { hits, grouping } = doc._source;
const { name, title, message } = doc._source.params;
expect(name).to.be('always fire');
expect(title).to.match(titlePattern);
expect(message).to.match(messagePattern);
expect(hits).not.to.be.empty();
expect(grouping).to.match(groupPattern);
}

const aadDocs = await getAllAADDocs(2);
Expand Down Expand Up @@ -222,11 +227,23 @@ export default function ruleTests({ getService }: FtrProviderContext) {
for (let i = 0; i < docs.length; i++) {
const doc = docs[i];
const { hits } = doc._source;
const grouping = JSON.parse(doc._source.grouping);
const { name, title, message } = doc._source.params;
expect(name).to.be('always fire');
expect(title).to.match(titlePattern);
expect(message).to.match(messagePattern);
expect(hits).not.to.be.empty();
expect(grouping['@timestamp']).to.be.ok();
expect(grouping.date).to.be.ok();
expect(grouping.date_epoch_millis).to.be.ok();
expect(grouping.group).to.be.ok();
expect(grouping.host.hostname).to.be.ok();
expect(grouping.host.id).to.be.ok();
expect(grouping.host.name).to.be.ok();
expect(grouping.reference).to.be.ok();
expect(grouping.source).to.be.ok();
expect(grouping.testedValue).to.be.ok();
expect(grouping.testedValueFloat).to.be.ok();
}

const aadDocs = await getAllAADDocs(3);
Expand Down Expand Up @@ -576,6 +593,7 @@ export default function ruleTests({ getService }: FtrProviderContext) {
hits: '{{context.hits}}',
date: '{{{context.date}}}',
previousTimestamp: '{{{state.latestTimestamp}}}',
grouping: '{{context.grouping}}',
},
],
},
Expand All @@ -597,6 +615,7 @@ export default function ruleTests({ getService }: FtrProviderContext) {
},
hits: '{{context.hits}}',
date: '{{{context.date}}}',
grouping: '{{context.grouping}}',
},
],
},
Expand Down