Skip to content

Commit 8c4d65e

Browse files
kryalamatrask
andauthored
add logprocessor to agent (#1713)
* add logprocessor to agent * comments addressed, added smoketest for log processor, fixed bug in telemetryprocessorOpenTelemetryConfigurer * StringBuffer -> StringBuilder * addressing comments * removed lognames, fixed smoke test * replace name with body in log processor, address comments Co-authored-by: Trask Stalnaker <[email protected]>
1 parent 76e97c8 commit 8c4d65e

File tree

27 files changed

+1275
-212
lines changed

27 files changed

+1275
-212
lines changed

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

Lines changed: 46 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,40 @@
1+
/*
2+
* ApplicationInsights-Java
3+
* Copyright (c) Microsoft Corporation
4+
* All rights reserved.
5+
*
6+
* MIT License
7+
* Permission is hereby granted, free of charge, to any person obtaining a copy of this
8+
* software and associated documentation files (the ""Software""), to deal in the Software
9+
* without restriction, including without limitation the rights to use, copy, modify, merge,
10+
* publish, distribute, sublicense, and/or sell copies of the Software, and to permit
11+
* persons to whom the Software is furnished to do so, subject to the following conditions:
12+
* The above copyright notice and this permission notice shall be included in all copies or
13+
* substantial portions of the Software.
14+
* THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
15+
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
16+
* PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
17+
* FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
18+
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
19+
* DEALINGS IN THE SOFTWARE.
20+
*/
21+
122
package com.microsoft.applicationinsights.agent.internal.processors;
223

24+
import com.microsoft.applicationinsights.agent.internal.wasbootstrap.configuration.Configuration.MatchType;
25+
import com.microsoft.applicationinsights.agent.internal.wasbootstrap.configuration.Configuration.ProcessorAttribute;
26+
import com.microsoft.applicationinsights.agent.internal.wasbootstrap.configuration.Configuration.ProcessorIncludeExclude;
27+
import io.opentelemetry.api.common.AttributeKey;
28+
import io.opentelemetry.sdk.trace.data.SpanData;
29+
import org.checkerframework.checker.nullness.qual.Nullable;
30+
331
import java.util.ArrayList;
432
import java.util.HashMap;
533
import java.util.List;
634
import java.util.Map;
735
import java.util.Map.Entry;
836
import java.util.regex.Pattern;
937

10-
import com.microsoft.applicationinsights.agent.internal.wasbootstrap.configuration.Configuration.ProcessorAttribute;
11-
import com.microsoft.applicationinsights.agent.internal.wasbootstrap.configuration.Configuration.ProcessorIncludeExclude;
12-
import com.microsoft.applicationinsights.agent.internal.wasbootstrap.configuration.Configuration.MatchType;
13-
import io.opentelemetry.api.common.AttributeKey;
14-
import io.opentelemetry.sdk.trace.data.SpanData;
15-
import org.checkerframework.checker.nullness.qual.Nullable;
16-
1738
public abstract class AgentProcessor {
1839
private final @Nullable IncludeExclude include;
1940
private final @Nullable IncludeExclude exclude;
@@ -36,13 +57,12 @@ protected static AttributeProcessor.IncludeExclude getNormalizedIncludeExclude(P
3657
return exclude;
3758
}
3859

60+
3961
public static abstract class IncludeExclude {
4062
// Function to compare span with user provided span names or span patterns
41-
public abstract boolean isMatch(SpanData span);
42-
63+
public abstract boolean isMatch(SpanData span, boolean isLog);
4364
}
4465

45-
// ok to have this class cover both spanNames and logNames
4666
public static class StrictIncludeExclude extends IncludeExclude {
4767
private final List<ProcessorAttribute> attributes;
4868
private final List<String> spanNames;
@@ -65,10 +85,12 @@ public static StrictIncludeExclude create(ProcessorIncludeExclude includeExclude
6585
}
6686

6787
// Function to compare span with user provided span names
68-
public boolean isMatch(SpanData span) {
69-
if (!spanNames.isEmpty() && !spanNames.contains(span.getName())) {
70-
// span name doesn't match
71-
return false;
88+
public boolean isMatch(SpanData span, boolean isLog) {
89+
if (isLog) {
90+
// If user provided spanNames , then donot include log in the include/exclude criteria
91+
if(!spanNames.isEmpty()) return false;
92+
} else {
93+
if (!spanNames.isEmpty() && !spanNames.contains(span.getName())) return false;
7294
}
7395
return this.checkAttributes(span);
7496
}
@@ -115,13 +137,13 @@ public static RegexpIncludeExclude create(ProcessorIncludeExclude includeExclude
115137
}
116138
}
117139
}
140+
118141
List<Pattern> spanPatterns = new ArrayList<>();
119142
if (includeExclude.spanNames != null) {
120143
for (String regex : includeExclude.spanNames) {
121144
spanPatterns.add(Pattern.compile(regex));
122145
}
123146
}
124-
125147
return new RegexpIncludeExclude(spanPatterns, attributeKeyValuePatterns);
126148
}
127149

@@ -130,8 +152,8 @@ private static boolean isAttributeValueMatch(String attributeValue, Pattern valu
130152
return valuePattern.matcher(attributeValue).find();
131153
}
132154

133-
private boolean isPatternFound(SpanData span) {
134-
for (Pattern pattern : spanPatterns) {
155+
private static boolean isPatternFound(SpanData span, List<Pattern> patterns) {
156+
for (Pattern pattern : patterns) {
135157
if (pattern.matcher(span.getName()).find()) {
136158
// pattern matches the span!!!
137159
return true;
@@ -141,10 +163,13 @@ private boolean isPatternFound(SpanData span) {
141163
return false;
142164
}
143165

144-
// Function to compare span with user provided span patterns
145-
public boolean isMatch(SpanData span) {
146-
if (!spanPatterns.isEmpty() && !isPatternFound(span)) {
147-
return false;
166+
// Function to compare span/log with user provided span patterns/log patterns
167+
public boolean isMatch(SpanData span, boolean isLog) {
168+
if (isLog) {
169+
// If user provided spanNames, then do not include log in the include/exclude criteria
170+
if (!spanPatterns.isEmpty()) return false;
171+
} else {
172+
if (!spanPatterns.isEmpty() && !isPatternFound(span, spanPatterns)) return false;
148173
}
149174
return checkAttributes(span);
150175
}

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

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,25 @@
1-
package com.microsoft.applicationinsights.agent.internal.processors;
1+
/*
2+
* ApplicationInsights-Java
3+
* Copyright (c) Microsoft Corporation
4+
* All rights reserved.
5+
*
6+
* MIT License
7+
* Permission is hereby granted, free of charge, to any person obtaining a copy of this
8+
* software and associated documentation files (the ""Software""), to deal in the Software
9+
* without restriction, including without limitation the rights to use, copy, modify, merge,
10+
* publish, distribute, sublicense, and/or sell copies of the Software, and to permit
11+
* persons to whom the Software is furnished to do so, subject to the following conditions:
12+
* The above copyright notice and this permission notice shall be included in all copies or
13+
* substantial portions of the Software.
14+
* THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
15+
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
16+
* PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
17+
* FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
18+
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
19+
* DEALINGS IN THE SOFTWARE.
20+
*/
221

3-
import java.util.List;
4-
import java.util.regex.Matcher;
22+
package com.microsoft.applicationinsights.agent.internal.processors;
523

624
import com.microsoft.applicationinsights.agent.internal.wasbootstrap.configuration.Configuration.ProcessorAction;
725
import com.microsoft.applicationinsights.agent.internal.wasbootstrap.configuration.Configuration.ProcessorConfig;
@@ -12,6 +30,9 @@
1230
import org.apache.commons.codec.digest.DigestUtils;
1331
import org.checkerframework.checker.nullness.qual.Nullable;
1432

33+
import java.util.List;
34+
import java.util.regex.Matcher;
35+
1536
// structure which only allows valid data
1637
// normalization has to occur before construction
1738
public class AttributeProcessor extends AgentProcessor {
@@ -33,6 +54,18 @@ public static AttributeProcessor create(ProcessorConfig config) {
3354
return new AttributeProcessor(config.actions, normalizedInclude, normalizedExclude);
3455
}
3556

57+
// this won't be needed once we update to 0.13.0
58+
// see https://github.com/open-telemetry/opentelemetry-java/pull/2284
59+
public static String getAttribute(Attributes attributes, AttributeKey<String> key) {
60+
Object existingValueObj = attributes.get(key);
61+
// checking the return type won't be needed once we update to 0.13.0
62+
// see https://github.com/open-telemetry/opentelemetry-java/pull/2284
63+
if (existingValueObj instanceof String) {
64+
return (String) existingValueObj;
65+
}
66+
return null;
67+
}
68+
3669
// Function to process actions
3770
public SpanData processActions(SpanData span) {
3871
SpanData updatedSpan = span;
@@ -149,19 +182,6 @@ private SpanData processExtractAction(SpanData span, ProcessorAction actionObj)
149182
return new MySpanData(span, builder.build());
150183
}
151184

152-
// this won't be needed once we update to 0.13.0
153-
// see https://github.com/open-telemetry/opentelemetry-java/pull/2284
154-
public static String getAttribute(Attributes attributes, AttributeKey<String> key) {
155-
Object existingValueObj = attributes.get(key);
156-
// checking the return type won't be needed once we update to 0.13.0
157-
// see https://github.com/open-telemetry/opentelemetry-java/pull/2284
158-
if (existingValueObj instanceof String) {
159-
return (String) existingValueObj;
160-
} else {
161-
return null;
162-
}
163-
}
164-
165185
@SuppressWarnings("unchecked")
166186
private void putIntoBuilder(AttributesBuilder builder, AttributeKey<?> key, Object value) {
167187
switch (key.getType()) {

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

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,37 @@
1-
package com.microsoft.applicationinsights.agent.internal.processors;
2-
3-
import java.util.ArrayList;
4-
import java.util.Collection;
5-
import java.util.List;
1+
/*
2+
* ApplicationInsights-Java
3+
* Copyright (c) Microsoft Corporation
4+
* All rights reserved.
5+
*
6+
* MIT License
7+
* Permission is hereby granted, free of charge, to any person obtaining a copy of this
8+
* software and associated documentation files (the ""Software""), to deal in the Software
9+
* without restriction, including without limitation the rights to use, copy, modify, merge,
10+
* publish, distribute, sublicense, and/or sell copies of the Software, and to permit
11+
* persons to whom the Software is furnished to do so, subject to the following conditions:
12+
* The above copyright notice and this permission notice shall be included in all copies or
13+
* substantial portions of the Software.
14+
* THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
15+
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
16+
* PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
17+
* FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
18+
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
19+
* DEALINGS IN THE SOFTWARE.
20+
*/
621

22+
package com.microsoft.applicationinsights.agent.internal.processors;
723

8-
import com.microsoft.applicationinsights.agent.internal.wasbootstrap.configuration.Configuration.ProcessorConfig;
924
import com.microsoft.applicationinsights.agent.internal.processors.AgentProcessor.IncludeExclude;
25+
import com.microsoft.applicationinsights.agent.internal.wasbootstrap.configuration.Configuration.ProcessorConfig;
1026
import com.microsoft.applicationinsights.customExceptions.FriendlyException;
1127
import io.opentelemetry.sdk.common.CompletableResultCode;
1228
import io.opentelemetry.sdk.trace.data.SpanData;
1329
import io.opentelemetry.sdk.trace.export.SpanExporter;
1430

31+
import java.util.ArrayList;
32+
import java.util.Collection;
33+
import java.util.List;
34+
1535
public class ExporterWithAttributeProcessor implements SpanExporter {
1636

1737
private final SpanExporter delegate;
@@ -27,21 +47,23 @@ public ExporterWithAttributeProcessor(ProcessorConfig config, SpanExporter deleg
2747
@Override
2848
public CompletableResultCode export(Collection<SpanData> spans) {
2949
// we need to filter attributes before passing on to delegate
30-
List<SpanData> copy = new ArrayList<>();
31-
for (SpanData span : spans) {
32-
copy.add(process(span));
33-
}
34-
return delegate.export(copy);
50+
List<SpanData> copy = new ArrayList<>();
51+
for (SpanData span : spans) {
52+
copy.add(process(span));
53+
}
54+
return delegate.export(copy);
3555
}
3656

3757
private SpanData process(SpanData span) {
3858
IncludeExclude include = attributeProcessor.getInclude();
39-
if (include != null && !include.isMatch(span)) {
40-
//If Not included we can skip further processing
59+
boolean isLog = ProcessorUtil.isSpanOfTypeLog(span);
60+
if (include != null && !include.isMatch(span, isLog)) {
61+
//If not included we can skip further processing
4162
return span;
4263
}
4364
IncludeExclude exclude = attributeProcessor.getExclude();
44-
if (exclude != null && exclude.isMatch(span)) {
65+
if (exclude != null && exclude.isMatch(span, isLog)) {
66+
//If excluded we can skip further processing
4567
return span;
4668
}
4769
return attributeProcessor.processActions(span);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/*
2+
* ApplicationInsights-Java
3+
* Copyright (c) Microsoft Corporation
4+
* All rights reserved.
5+
*
6+
* MIT License
7+
* Permission is hereby granted, free of charge, to any person obtaining a copy of this
8+
* software and associated documentation files (the ""Software""), to deal in the Software
9+
* without restriction, including without limitation the rights to use, copy, modify, merge,
10+
* publish, distribute, sublicense, and/or sell copies of the Software, and to permit
11+
* persons to whom the Software is furnished to do so, subject to the following conditions:
12+
* The above copyright notice and this permission notice shall be included in all copies or
13+
* substantial portions of the Software.
14+
* THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
15+
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
16+
* PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
17+
* FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
18+
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
19+
* DEALINGS IN THE SOFTWARE.
20+
*/
21+
22+
package com.microsoft.applicationinsights.agent.internal.processors;
23+
24+
import com.microsoft.applicationinsights.agent.internal.processors.AgentProcessor.IncludeExclude;
25+
import com.microsoft.applicationinsights.agent.internal.wasbootstrap.configuration.Configuration.ProcessorConfig;
26+
import com.microsoft.applicationinsights.customExceptions.FriendlyException;
27+
import io.opentelemetry.sdk.common.CompletableResultCode;
28+
import io.opentelemetry.sdk.trace.data.SpanData;
29+
import io.opentelemetry.sdk.trace.export.SpanExporter;
30+
31+
import java.util.ArrayList;
32+
import java.util.Collection;
33+
import java.util.List;
34+
35+
public class ExporterWithLogProcessor implements SpanExporter {
36+
37+
private final SpanExporter delegate;
38+
private final LogProcessor logProcessor;
39+
40+
// caller should check config.isValid before creating
41+
public ExporterWithLogProcessor(ProcessorConfig config, SpanExporter delegate) throws FriendlyException {
42+
config.validate();
43+
logProcessor = LogProcessor.create(config);
44+
this.delegate = delegate;
45+
}
46+
47+
@Override
48+
public CompletableResultCode export(Collection<SpanData> spans) {
49+
// we need to filter attributes before passing on to delegate
50+
List<SpanData> copy = new ArrayList<>();
51+
for (SpanData span : spans) {
52+
copy.add(process(span));
53+
}
54+
return delegate.export(copy);
55+
}
56+
57+
private SpanData process(SpanData span) {
58+
if (!ProcessorUtil.isSpanOfTypeLog(span)) {
59+
return span;
60+
}
61+
IncludeExclude include = logProcessor.getInclude();
62+
if (include != null && !include.isMatch(span, true)) {
63+
//If Not included we can skip further processing
64+
return span;
65+
}
66+
IncludeExclude exclude = logProcessor.getExclude();
67+
if (exclude != null && exclude.isMatch(span, true)) {
68+
return span;
69+
}
70+
71+
SpanData updatedSpan = logProcessor.processFromAttributes(span);
72+
return logProcessor.processToAttributes(updatedSpan);
73+
}
74+
75+
@Override
76+
public CompletableResultCode flush() {
77+
return delegate.flush();
78+
}
79+
80+
@Override
81+
public CompletableResultCode shutdown() {
82+
return delegate.shutdown();
83+
}
84+
}

0 commit comments

Comments
 (0)