Skip to content

Commit 194be51

Browse files
authored
Optimise grok regex (#243096)
## Summary Optimise regex used to unwrap grok pattern definitions
1 parent 700ec7d commit 194be51

File tree

1 file changed

+25
-17
lines changed

1 file changed

+25
-17
lines changed

x-pack/platform/packages/shared/kbn-streamlang/types/utils/grok_pattern_definitions.ts

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -29,24 +29,32 @@ export function unwrapPatternDefinitions(
2929

3030
// Recursively inline a single pattern
3131
function unwrapPattern(pattern: string, seen: Set<string> = new Set()): string {
32-
// Match %{PATTERN_NAME} or %{PATTERN_NAME:field}
33-
return pattern.replace(/%{([A-Z0-9_]+)(:[^}]*)?}/g, (match, key, fieldName) => {
34-
if (pattern_definitions && pattern_definitions[key]) {
35-
if (seen.has(key)) {
36-
// Prevent infinite recursion on cyclic definitions
37-
return match;
38-
}
39-
seen.add(key);
40-
const inlined = unwrapPattern(pattern_definitions[key], seen);
41-
seen.delete(key);
42-
if (fieldName) {
43-
// Named capture group
44-
return `(?<${fieldName.substring(1)}>${inlined})`;
45-
}
46-
return `(${inlined})`;
32+
/**
33+
* Intentional optimization: previously a single regex /%{([A-Z0-9_]+)(:[^}]*)?}/g
34+
* with an optional capture group. We now perform two deterministic passes with two
35+
* separate regexes - one for patterns WITH a field name and one for patterns
36+
* WITHOUT - eliminating the optional branch.
37+
*/
38+
const WITHOUT_FIELD = /%{([A-Z0-9_]+)}/g; // %{PATTERN}
39+
const WITH_FIELD = /%{([A-Z0-9_]+):([^}]+)}/g; // %{PATTERN:field}
40+
41+
const expand = (match: string, key: string, fieldName?: string): string => {
42+
if (!pattern_definitions || !pattern_definitions[key]) {
43+
return match; // unknown definition - leave untouched
44+
}
45+
if (seen.has(key)) {
46+
return match; // cyclic reference safeguard
4747
}
48-
return match; // Leave as is if not in patternDefs
49-
});
48+
seen.add(key);
49+
const inlined = unwrapPattern(pattern_definitions[key], seen);
50+
seen.delete(key);
51+
if (fieldName) {
52+
return `(?<${fieldName}>${inlined})`;
53+
}
54+
return `(${inlined})`;
55+
};
56+
57+
return pattern.replace(WITHOUT_FIELD, expand).replace(WITH_FIELD, expand);
5058
}
5159

5260
return patterns.map((pattern) => unwrapPattern(pattern));

0 commit comments

Comments
 (0)