Skip to content

Commit 3f4e9f4

Browse files
[Security Solution] [Detections] Log message enhancements (#78429)
* adds missing buildRuleMessage to debug logs to display rule id, name, etc. in logs * add buildRuleMessage fn to params Co-authored-by: Elastic Machine <[email protected]>
1 parent 25682bf commit 3f4e9f4

File tree

9 files changed

+62
-11
lines changed

9 files changed

+62
-11
lines changed

x-pack/plugins/security_solution/server/lib/detection_engine/signals/bulk_create_ml_signals.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { RuleAlertAction } from '../../../../common/detection_engine/types';
1414
import { RuleTypeParams, RefreshTypes } from '../types';
1515
import { singleBulkCreate, SingleBulkCreateResponse } from './single_bulk_create';
1616
import { AnomalyResults, Anomaly } from '../../machine_learning';
17+
import { BuildRuleMessage } from './rule_messages';
1718

1819
interface BulkCreateMlSignalsParams {
1920
actions: RuleAlertAction[];
@@ -33,6 +34,7 @@ interface BulkCreateMlSignalsParams {
3334
refresh: RefreshTypes;
3435
tags: string[];
3536
throttle: string;
37+
buildRuleMessage: BuildRuleMessage;
3638
}
3739

3840
interface EcsAnomaly extends Anomaly {
@@ -85,6 +87,6 @@ export const bulkCreateMlSignals = async (
8587
): Promise<SingleBulkCreateResponse> => {
8688
const anomalyResults = params.someResult;
8789
const ecsResults = transformAnomalyResultsToEcs(anomalyResults);
88-
89-
return singleBulkCreate({ ...params, filteredEvents: ecsResults });
90+
const buildRuleMessage = params.buildRuleMessage;
91+
return singleBulkCreate({ ...params, filteredEvents: ecsResults, buildRuleMessage });
9092
};

x-pack/plugins/security_solution/server/lib/detection_engine/signals/bulk_create_threshold_signals.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { RuleAlertAction } from '../../../../common/detection_engine/types';
1515
import { RuleTypeParams, RefreshTypes } from '../types';
1616
import { singleBulkCreate, SingleBulkCreateResponse } from './single_bulk_create';
1717
import { SignalSearchResponse } from './types';
18+
import { BuildRuleMessage } from './rule_messages';
1819

1920
// used to generate constant Threshold Signals ID when run with the same params
2021
const NAMESPACE_ID = '0684ec03-7201-4ee0-8ee0-3a3f6b2479b2';
@@ -40,6 +41,7 @@ interface BulkCreateThresholdSignalsParams {
4041
tags: string[];
4142
throttle: string;
4243
startedAt: Date;
44+
buildRuleMessage: BuildRuleMessage;
4345
}
4446

4547
interface FilterObject {
@@ -195,6 +197,7 @@ export const bulkCreateThresholdSignals = async (
195197
params.ruleParams.threshold!,
196198
params.ruleParams.ruleId
197199
);
200+
const buildRuleMessage = params.buildRuleMessage;
198201

199-
return singleBulkCreate({ ...params, filteredEvents: ecsResults });
202+
return singleBulkCreate({ ...params, filteredEvents: ecsResults, buildRuleMessage });
200203
};

x-pack/plugins/security_solution/server/lib/detection_engine/signals/find_threshold_signals.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { singleSearchAfter } from './single_search_after';
1212
import { AlertServices } from '../../../../../alerts/server';
1313
import { Logger } from '../../../../../../../src/core/server';
1414
import { SignalSearchResponse } from './types';
15+
import { BuildRuleMessage } from './rule_messages';
1516

1617
interface FindThresholdSignalsParams {
1718
from: string;
@@ -21,6 +22,7 @@ interface FindThresholdSignalsParams {
2122
logger: Logger;
2223
filter: unknown;
2324
threshold: Threshold;
25+
buildRuleMessage: BuildRuleMessage;
2426
}
2527

2628
export const findThresholdSignals = async ({
@@ -31,6 +33,7 @@ export const findThresholdSignals = async ({
3133
logger,
3234
filter,
3335
threshold,
36+
buildRuleMessage,
3437
}: FindThresholdSignalsParams): Promise<{
3538
searchResult: SignalSearchResponse;
3639
searchDuration: string;
@@ -59,5 +62,6 @@ export const findThresholdSignals = async ({
5962
logger,
6063
filter,
6164
pageSize: 0,
65+
buildRuleMessage,
6266
});
6367
};

x-pack/plugins/security_solution/server/lib/detection_engine/signals/search_after_bulk_create.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ export const searchAfterAndBulkCreate = async ({
8080

8181
// perform search_after with optionally undefined sortId
8282
const { searchResult, searchDuration, searchErrors } = await singleSearchAfter({
83+
buildRuleMessage,
8384
searchAfterSortId: sortId,
8485
index: inputIndexPattern,
8586
from: tuple.from.toISOString(),
@@ -153,6 +154,7 @@ export const searchAfterAndBulkCreate = async ({
153154
success: bulkSuccess,
154155
errors: bulkErrors,
155156
} = await singleBulkCreate({
157+
buildRuleMessage,
156158
filteredEvents,
157159
ruleParams,
158160
services,

x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,7 @@ export const signalRulesAlertType = ({
257257
enabled,
258258
refresh,
259259
tags,
260+
buildRuleMessage,
260261
});
261262
// The legacy ES client does not define failures when it can be present on the structure, hence why I have the & { failures: [] }
262263
const shardFailures =
@@ -295,6 +296,7 @@ export const signalRulesAlertType = ({
295296
logger,
296297
filter: esFilter,
297298
threshold,
299+
buildRuleMessage,
298300
});
299301

300302
const {
@@ -323,6 +325,7 @@ export const signalRulesAlertType = ({
323325
enabled,
324326
refresh,
325327
tags,
328+
buildRuleMessage,
326329
});
327330
result = mergeReturns([
328331
result,

x-pack/plugins/security_solution/server/lib/detection_engine/signals/single_bulk_create.test.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,14 @@ import {
1919
import { DEFAULT_SIGNALS_INDEX } from '../../../../common/constants';
2020
import { singleBulkCreate, filterDuplicateRules } from './single_bulk_create';
2121
import { alertsMock, AlertServicesMock } from '../../../../../alerts/server/mocks';
22+
import { buildRuleMessageFactory } from './rule_messages';
2223

24+
const buildRuleMessage = buildRuleMessageFactory({
25+
id: 'fake id',
26+
ruleId: 'fake rule id',
27+
index: 'fakeindex',
28+
name: 'fake name',
29+
});
2330
describe('singleBulkCreate', () => {
2431
const mockService: AlertServicesMock = alertsMock.createAlertServices();
2532

@@ -158,6 +165,7 @@ describe('singleBulkCreate', () => {
158165
refresh: false,
159166
tags: ['some fake tag 1', 'some fake tag 2'],
160167
throttle: 'no_actions',
168+
buildRuleMessage,
161169
});
162170
expect(success).toEqual(true);
163171
expect(createdItemsCount).toEqual(0);
@@ -192,6 +200,7 @@ describe('singleBulkCreate', () => {
192200
refresh: false,
193201
tags: ['some fake tag 1', 'some fake tag 2'],
194202
throttle: 'no_actions',
203+
buildRuleMessage,
195204
});
196205
expect(success).toEqual(true);
197206
expect(createdItemsCount).toEqual(0);
@@ -218,6 +227,7 @@ describe('singleBulkCreate', () => {
218227
refresh: false,
219228
tags: ['some fake tag 1', 'some fake tag 2'],
220229
throttle: 'no_actions',
230+
buildRuleMessage,
221231
});
222232
expect(success).toEqual(true);
223233
expect(createdItemsCount).toEqual(0);
@@ -245,6 +255,7 @@ describe('singleBulkCreate', () => {
245255
refresh: false,
246256
tags: ['some fake tag 1', 'some fake tag 2'],
247257
throttle: 'no_actions',
258+
buildRuleMessage,
248259
});
249260

250261
expect(mockLogger.error).not.toHaveBeenCalled();
@@ -274,6 +285,7 @@ describe('singleBulkCreate', () => {
274285
refresh: false,
275286
tags: ['some fake tag 1', 'some fake tag 2'],
276287
throttle: 'no_actions',
288+
buildRuleMessage,
277289
});
278290
expect(mockLogger.error).toHaveBeenCalled();
279291
expect(errors).toEqual(['[4]: internal server error']);
@@ -339,6 +351,7 @@ describe('singleBulkCreate', () => {
339351
refresh: false,
340352
tags: ['some fake tag 1', 'some fake tag 2'],
341353
throttle: 'no_actions',
354+
buildRuleMessage,
342355
});
343356
expect(success).toEqual(true);
344357
expect(createdItemsCount).toEqual(1);

x-pack/plugins/security_solution/server/lib/detection_engine/signals/single_bulk_create.ts

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { RuleAlertAction } from '../../../../common/detection_engine/types';
1212
import { RuleTypeParams, RefreshTypes } from '../types';
1313
import { generateId, makeFloatString, errorAggregator } from './utils';
1414
import { buildBulkBody } from './build_bulk_body';
15+
import { BuildRuleMessage } from './rule_messages';
1516
import { Logger } from '../../../../../../../src/core/server';
1617

1718
interface SingleBulkCreateParams {
@@ -32,6 +33,7 @@ interface SingleBulkCreateParams {
3233
tags: string[];
3334
throttle: string;
3435
refresh: RefreshTypes;
36+
buildRuleMessage: BuildRuleMessage;
3537
}
3638

3739
/**
@@ -85,6 +87,7 @@ export interface BulkInsertSignalsResponse {
8587

8688
// Bulk Index documents.
8789
export const singleBulkCreate = async ({
90+
buildRuleMessage,
8891
filteredEvents,
8992
ruleParams,
9093
services,
@@ -104,9 +107,9 @@ export const singleBulkCreate = async ({
104107
throttle,
105108
}: SingleBulkCreateParams): Promise<SingleBulkCreateResponse> => {
106109
filteredEvents.hits.hits = filterDuplicateRules(id, filteredEvents);
107-
logger.debug(`about to bulk create ${filteredEvents.hits.hits.length} events`);
110+
logger.debug(buildRuleMessage(`about to bulk create ${filteredEvents.hits.hits.length} events`));
108111
if (filteredEvents.hits.hits.length === 0) {
109-
logger.debug(`all events were duplicates`);
112+
logger.debug(buildRuleMessage(`all events were duplicates`));
110113
return { success: true, createdItemsCount: 0, errors: [] };
111114
}
112115
// index documents after creating an ID based on the
@@ -153,21 +156,27 @@ export const singleBulkCreate = async ({
153156
body: bulkBody,
154157
});
155158
const end = performance.now();
156-
logger.debug(`individual bulk process time took: ${makeFloatString(end - start)} milliseconds`);
157-
logger.debug(`took property says bulk took: ${response.took} milliseconds`);
159+
logger.debug(
160+
buildRuleMessage(
161+
`individual bulk process time took: ${makeFloatString(end - start)} milliseconds`
162+
)
163+
);
164+
logger.debug(buildRuleMessage(`took property says bulk took: ${response.took} milliseconds`));
158165

159166
const createdItemsCount = countBy(response.items, 'create.status')['201'] ?? 0;
160167
const duplicateSignalsCount = countBy(response.items, 'create.status')['409'];
161168
const errorCountByMessage = errorAggregator(response, [409]);
162169

163-
logger.debug(`bulk created ${createdItemsCount} signals`);
170+
logger.debug(buildRuleMessage(`bulk created ${createdItemsCount} signals`));
164171
if (duplicateSignalsCount > 0) {
165-
logger.debug(`ignored ${duplicateSignalsCount} duplicate signals`);
172+
logger.debug(buildRuleMessage(`ignored ${duplicateSignalsCount} duplicate signals`));
166173
}
167174

168175
if (!isEmpty(errorCountByMessage)) {
169176
logger.error(
170-
`[-] bulkResponse had errors with responses of: ${JSON.stringify(errorCountByMessage)}`
177+
buildRuleMessage(
178+
`[-] bulkResponse had errors with responses of: ${JSON.stringify(errorCountByMessage)}`
179+
)
171180
);
172181
return {
173182
errors: Object.keys(errorCountByMessage),

x-pack/plugins/security_solution/server/lib/detection_engine/signals/single_search_after.test.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,14 @@ import {
1212
import { singleSearchAfter } from './single_search_after';
1313
import { alertsMock, AlertServicesMock } from '../../../../../alerts/server/mocks';
1414
import { ShardError } from '../../types';
15+
import { buildRuleMessageFactory } from './rule_messages';
1516

17+
const buildRuleMessage = buildRuleMessageFactory({
18+
id: 'fake id',
19+
ruleId: 'fake rule id',
20+
index: 'fakeindex',
21+
name: 'fake name',
22+
});
1623
describe('singleSearchAfter', () => {
1724
const mockService: AlertServicesMock = alertsMock.createAlertServices();
1825

@@ -32,6 +39,7 @@ describe('singleSearchAfter', () => {
3239
pageSize: 1,
3340
filter: undefined,
3441
timestampOverride: undefined,
42+
buildRuleMessage,
3543
});
3644
expect(searchResult).toEqual(sampleDocSearchResultsNoSortId());
3745
});
@@ -47,6 +55,7 @@ describe('singleSearchAfter', () => {
4755
pageSize: 1,
4856
filter: undefined,
4957
timestampOverride: undefined,
58+
buildRuleMessage,
5059
});
5160
expect(searchErrors).toEqual([]);
5261
});
@@ -94,6 +103,7 @@ describe('singleSearchAfter', () => {
94103
pageSize: 1,
95104
filter: undefined,
96105
timestampOverride: undefined,
106+
buildRuleMessage,
97107
});
98108
expect(searchErrors).toEqual(['reason: some reason, type: some type, caused by: some reason']);
99109
});
@@ -110,6 +120,7 @@ describe('singleSearchAfter', () => {
110120
pageSize: 1,
111121
filter: undefined,
112122
timestampOverride: undefined,
123+
buildRuleMessage,
113124
});
114125
expect(searchResult).toEqual(sampleDocSearchResultsWithSortId());
115126
});
@@ -129,6 +140,7 @@ describe('singleSearchAfter', () => {
129140
pageSize: 1,
130141
filter: undefined,
131142
timestampOverride: undefined,
143+
buildRuleMessage,
132144
})
133145
).rejects.toThrow('Fake Error');
134146
});

x-pack/plugins/security_solution/server/lib/detection_engine/signals/single_search_after.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { performance } from 'perf_hooks';
88
import { AlertServices } from '../../../../../alerts/server';
99
import { Logger } from '../../../../../../../src/core/server';
1010
import { SignalSearchResponse } from './types';
11+
import { BuildRuleMessage } from './rule_messages';
1112
import { buildEventsSearchQuery } from './build_events_query';
1213
import { createErrorsFromShard, makeFloatString } from './utils';
1314
import { TimestampOverrideOrUndefined } from '../../../../common/detection_engine/schemas/common/schemas';
@@ -23,6 +24,7 @@ interface SingleSearchAfterParams {
2324
pageSize: number;
2425
filter: unknown;
2526
timestampOverride: TimestampOverrideOrUndefined;
27+
buildRuleMessage: BuildRuleMessage;
2628
}
2729

2830
// utilize search_after for paging results into bulk.
@@ -37,6 +39,7 @@ export const singleSearchAfter = async ({
3739
logger,
3840
pageSize,
3941
timestampOverride,
42+
buildRuleMessage,
4043
}: SingleSearchAfterParams): Promise<{
4144
searchResult: SignalSearchResponse;
4245
searchDuration: string;
@@ -69,7 +72,7 @@ export const singleSearchAfter = async ({
6972
searchErrors,
7073
};
7174
} catch (exc) {
72-
logger.error(`[-] nextSearchAfter threw an error ${exc}`);
75+
logger.error(buildRuleMessage(`[-] nextSearchAfter threw an error ${exc}`));
7376
throw exc;
7477
}
7578
};

0 commit comments

Comments
 (0)