Skip to content

Commit 2d771fb

Browse files
jeanbisuttitrask
andauthored
Telemetry processor - Allow multimatch on log body and span name (#3229)
Co-authored-by: Trask Stalnaker <[email protected]>
1 parent d0c7730 commit 2d771fb

File tree

3 files changed

+75
-28
lines changed

3 files changed

+75
-28
lines changed

agent/agent-tooling/src/main/java/com/microsoft/applicationinsights/agent/internal/processors/ProcessorUtil.java

Lines changed: 40 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -15,33 +15,54 @@
1515

1616
public class ProcessorUtil {
1717

18+
// Rule applied on all matches for the returned string. The first match is taken to populate
19+
// extracted attributes.
1820
public static String applyRule(
19-
List<String> groupNamesList, Pattern pattern, String name, AttributesBuilder builder) {
21+
List<String> groupNamesList,
22+
Pattern pattern,
23+
String name,
24+
AttributesBuilder attributesBuilder) {
2025
if (groupNamesList.isEmpty()) {
2126
return name;
2227
}
2328
Matcher matcher = pattern.matcher(name);
24-
StringBuilder sb = new StringBuilder();
29+
StringBuilder output = new StringBuilder();
2530
int lastEnd = 0;
26-
// As of now we are considering only first match.
27-
if (matcher.find()) {
28-
sb.append(name, lastEnd, matcher.start());
29-
int innerLastEnd = matcher.start();
30-
for (int i = 1; i <= groupNamesList.size(); i++) {
31-
sb.append(name, innerLastEnd, matcher.start(i));
32-
sb.append("{");
33-
sb.append(groupNamesList.get(i - 1));
34-
// add attribute key=groupNames.get(i-1), value=matcher.group(i)
35-
builder.put(groupNamesList.get(i - 1), matcher.group(i));
36-
sb.append("}");
37-
innerLastEnd = matcher.end(i);
38-
}
39-
sb.append(name, innerLastEnd, matcher.end());
40-
lastEnd = matcher.end();
31+
boolean firstMatch = true;
32+
while (matcher.find()) {
33+
lastEnd =
34+
applyRule(groupNamesList, name, attributesBuilder, output, lastEnd, matcher, firstMatch);
35+
firstMatch = false;
4136
}
42-
sb.append(name, lastEnd, name.length());
37+
output.append(name, lastEnd, name.length());
38+
39+
return output.toString();
40+
}
4341

44-
return sb.toString();
42+
private static int applyRule(
43+
List<String> groupNamesList,
44+
String name,
45+
AttributesBuilder attributesBuilder,
46+
StringBuilder output,
47+
int lastEnd,
48+
Matcher matcher,
49+
boolean firstMatch) {
50+
output.append(name, lastEnd, matcher.start());
51+
int innerLastEnd = matcher.start();
52+
for (int i = 1; i <= groupNamesList.size(); i++) {
53+
output.append(name, innerLastEnd, matcher.start(i));
54+
output.append("{");
55+
output.append(groupNamesList.get(i - 1));
56+
// add attribute key=groupNames.get(i-1), value=matcher.group(i)
57+
if (firstMatch) {
58+
attributesBuilder.put(groupNamesList.get(i - 1), matcher.group(i));
59+
}
60+
output.append("}");
61+
innerLastEnd = matcher.end(i);
62+
}
63+
output.append(name, innerLastEnd, matcher.end());
64+
lastEnd = matcher.end();
65+
return lastEnd;
4566
}
4667

4768
public static List<List<String>> getGroupNamesList(List<String> toAttributeRules) {

agent/agent-tooling/src/test/java/com/microsoft/applicationinsights/agent/internal/processors/ExporterWithLogProcessorTest.java

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -227,9 +227,9 @@ void multiRuleToAttributesTest() {
227227
assertThat(
228228
Objects.requireNonNull(
229229
resultA.getAttributes().get(AttributeKey.stringKey("password2"))))
230-
.isEqualTo("555");
230+
.isEqualTo("555"); // The first match is taken to populate the attribute
231231
assertThat(resultA.getBody().asString())
232-
.isEqualTo("yyyPassword={password1} aba Pass={password2} xyx Pass=777 zzz");
232+
.isEqualTo("yyyPassword={password1} aba Pass={password2} xyx Pass={password2} zzz");
233233
assertThat(
234234
Objects.requireNonNull(
235235
resultB.getAttributes().get(AttributeKey.stringKey("password1"))))
@@ -241,6 +241,32 @@ void multiRuleToAttributesTest() {
241241
assertThat(resultB.getBody().asString()).isEqualTo("yyyPassword={password1} aba");
242242
}
243243

244+
@Test
245+
void multiMatch() {
246+
config.id = "MultiRuleToAttributes";
247+
config.body = new NameConfig();
248+
ToAttributeConfig toAttributeConfig = new ToAttributeConfig();
249+
toAttributeConfig.rules = new ArrayList<>();
250+
toAttributeConfig.rules.add("Password=(?<x>[^ ]+)");
251+
config.body.toAttributes = toAttributeConfig;
252+
LogRecordExporter logExporter = new ExporterWithLogProcessor(config, mockExporter);
253+
TestLogRecordData mockLogA =
254+
TestLogRecordData.builder()
255+
.setBody("yyyPassword=123 aba Password=555 xyx")
256+
.setAttributes(attributes)
257+
.build();
258+
259+
List<LogRecordData> logs = new ArrayList<>();
260+
logs.add(mockLogA);
261+
logExporter.export(logs);
262+
263+
// verify that resulting logs are filtered in the way we want
264+
List<LogRecordData> result = mockExporter.getLogs();
265+
LogRecordData resultA = result.get(0);
266+
267+
assertThat(resultA.getBody().asString()).isEqualTo("yyyPassword={x} aba Password={x} xyx");
268+
}
269+
244270
@Test
245271
void simpleRenameLogTestWithLogProcessor() {
246272
config.id = "SimpleRenameLog";

agent/agent-tooling/src/test/java/com/microsoft/applicationinsights/agent/internal/processors/ExporterWithSpanProcessorTest.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -355,9 +355,9 @@ void multiRuleToAttributesTest() {
355355
assertThat(
356356
Objects.requireNonNull(
357357
resultSpanA.getAttributes().get(AttributeKey.stringKey("password2"))))
358-
.isEqualTo("555");
358+
.isEqualTo("555"); // The first match is taken to populate the attribute
359359
assertThat(resultSpanA.getName())
360-
.isEqualTo("yyyPassword={password1} aba Pass={password2} xyx Pass=777 zzz");
360+
.isEqualTo("yyyPassword={password1} aba Pass={password2} xyx Pass={password2} zzz");
361361
assertThat(
362362
Objects.requireNonNull(
363363
resultSpanB.getAttributes().get(AttributeKey.stringKey("password1"))))
@@ -383,7 +383,7 @@ void extractAttributesWithIncludeExcludeTest() {
383383
config.exclude.matchType = MatchType.STRICT;
384384
config.exclude.spanNames = Arrays.asList("donot/change");
385385
config.name.toAttributes = new ToAttributeConfig();
386-
config.name.toAttributes.rules = Arrays.asList("(?<operationwebsite>.*?)$");
386+
config.name.toAttributes.rules = Arrays.asList("(?<operationwebsite>.*?)/.*$");
387387
SpanExporter exampleExporter = new ExporterWithSpanProcessor(config, mockSpanExporter);
388388

389389
Span spanA =
@@ -439,20 +439,20 @@ void extractAttributesWithIncludeExcludeTest() {
439439
SpanData resultSpanB = result.get(1);
440440
SpanData resultSpanC = result.get(2);
441441
SpanData resultSpanD = result.get(3);
442-
assertThat(resultSpanA.getName()).isEqualTo("{operationwebsite}");
442+
assertThat(resultSpanA.getName()).isEqualTo("{operationwebsite}/test");
443443
assertThat(resultSpanA.getAttributes().get(AttributeKey.stringKey("operationwebsite")))
444444
.isNotNull();
445445
assertThat(
446446
Objects.requireNonNull(
447447
resultSpanA.getAttributes().get(AttributeKey.stringKey("operationwebsite"))))
448-
.isEqualTo("svcA/test");
449-
assertThat(resultSpanB.getName()).isEqualTo("{operationwebsite}");
448+
.isEqualTo("svcA");
449+
assertThat(resultSpanB.getName()).isEqualTo("{operationwebsite}/test");
450450
assertThat(resultSpanB.getAttributes().get(AttributeKey.stringKey("operationwebsite")))
451451
.isNotNull();
452452
assertThat(
453453
Objects.requireNonNull(
454454
resultSpanB.getAttributes().get(AttributeKey.stringKey("operationwebsite"))))
455-
.isEqualTo("svcB/test");
455+
.isEqualTo("svcB");
456456
assertThat(resultSpanC.getName()).isEqualTo("svcC");
457457
assertThat(resultSpanD.getName()).isEqualTo("donot/change");
458458
}

0 commit comments

Comments
 (0)