Skip to content

Commit 6418b31

Browse files
authored
W3C Final implementation (#785)
* W3C : Tracecontext classes (#775) * W3C Tracecontext * adding comments * addressing PR comments * Implement W3C tracestate * address review feedbacks * address review comments * W3C Integration (#782) * Initial integration of W3C protocol for incoming request * refactoring header name * updating the verbosity level when correlation fails * Fix bugs in correlation found via tests, implement more unit tests and address partial PR comments * improve createOutboundTracestate() * create tracestate when header not available * fix test * enable outbout w3c * Refactering code to use Helper methods with TraceContext classes * fix tracestate integration, fix outbound tracestate injection, fix tests, propogate traceflags * add property to turn on W3C in springboot starter, remove debug logs * adopt internal storage of id's to legacy AI format for backport, update tests * address PR comments * Fix an incorrect assert * refactor resolveCorrelation() method to be more readable and debuggable * rename method names, create outbound traceparent for http if there is no incoming request too * fixing a bug in w3c config for agent * fix the dependency type name, fix target to be host+port | target * update changelog and readme * Minor changes, add log trace to check W3C enabled on agent * adding support for backport with AI-Legacy-Correlation-Headers * adding tests for backward compatibility * address PR comments * add few tests, comments * add backport switch turn off test * reset after tests, to fix the build * adding tracing to understand when W3C is turned on for debugging * fix format string * fix a bug in creating correct target for dependencies
1 parent cd5ccbc commit 6418b31

File tree

23 files changed

+2152
-73
lines changed

23 files changed

+2152
-73
lines changed

Diff for: CHANGELOG.md

+3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# CHANGELOG
22

3+
# Version 2.3.0
4+
- [#716](https://github.com/Microsoft/ApplicationInsights-Java/issues/716) Introduced W3C Distributed tracing protocol.
5+
36
# Version 2.2.1
47
- Fixed [#767](https://github.com/Microsoft/ApplicationInsights-Java/issues/767). Updated gRPC dependencies which inlcudes latest netty version.
58
- Fixed [#751](https://github.com/Microsoft/ApplicationInsights-Java/issues/751). Added support for absolute paths for log file output.

Diff for: agent/src/main/java/com/microsoft/applicationinsights/agent/internal/agent/DefaultClassDataProvider.java

+4-1
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,10 @@ public void setConfiguration(AgentConfiguration agentConfiguration) {
8888

8989
if (agentConfiguration.getBuiltInConfiguration().isHttpEnabled()) {
9090
InternalLogger.INSTANCE.trace("Adding built-in HTTP instrumentation");
91-
new HttpClassDataProvider(classesToInstrument).add();
91+
HttpClassDataProvider httpClassDataProvider= new HttpClassDataProvider(classesToInstrument);
92+
httpClassDataProvider.setIsW3CEnabled(agentConfiguration.getBuiltInConfiguration().isW3cEnabled());
93+
httpClassDataProvider.setIsW3CBackportEnabled(agentConfiguration.getBuiltInConfiguration().isW3CBackportEnabled());
94+
httpClassDataProvider.add();
9295
}
9396

9497
if (agentConfiguration.getBuiltInConfiguration().isRedisEnabled()) {

Diff for: agent/src/main/java/com/microsoft/applicationinsights/agent/internal/agent/HttpClientMethodVisitor.java

+109-34
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,20 @@ public final class HttpClientMethodVisitor extends AbstractHttpMethodVisitor {
3434

3535
private final static String FINISH_DETECT_METHOD_NAME = "httpMethodFinished";
3636
private final static String FINISH_METHOD_RETURN_SIGNATURE = "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IJ)V";
37+
private final boolean isW3CEnabled;
38+
private final boolean isW3CBackportEnabled;
3739

3840
public HttpClientMethodVisitor(int access,
3941
String desc,
4042
String owner,
4143
String methodName,
4244
MethodVisitor methodVisitor,
43-
ClassToMethodTransformationData additionalData) {
45+
ClassToMethodTransformationData additionalData,
46+
boolean isW3CEnabled,
47+
boolean isW3CBackportEnabled) {
4448
super(access, desc, owner, methodName, methodVisitor, additionalData);
49+
this.isW3CEnabled = isW3CEnabled;
50+
this.isW3CBackportEnabled = isW3CBackportEnabled;
4551
}
4652

4753
private int deltaInNS;
@@ -50,43 +56,103 @@ public HttpClientMethodVisitor(int access,
5056
private int childIdLocal;
5157
private int correlationContextLocal;
5258
private int appCorrelationId;
59+
private int tracestate;
60+
private int traceparent;
5361

5462
@Override
5563
public void onMethodEnter() {
5664
mv.visitMethodInsn(INVOKESTATIC, "java/lang/System", "nanoTime", "()J", false);
5765
deltaInNS = this.newLocal(Type.LONG_TYPE);
5866
mv.visitVarInsn(LSTORE, deltaInNS);
5967

60-
// generate child ID
61-
mv.visitMethodInsn(INVOKESTATIC, "com/microsoft/applicationinsights/web/internal/correlation/TelemetryCorrelationUtils", "generateChildDependencyId", "()Ljava/lang/String;", false);
62-
childIdLocal = this.newLocal(Type.getType(Object.class));
63-
mv.visitVarInsn(ASTORE, childIdLocal);
64-
65-
// retrieve correlation context
66-
mv.visitMethodInsn(INVOKESTATIC, "com/microsoft/applicationinsights/web/internal/correlation/TelemetryCorrelationUtils", "retrieveCorrelationContext", "()Ljava/lang/String;", false);
67-
correlationContextLocal = this.newLocal(Type.getType(Object.class));
68-
mv.visitVarInsn(ASTORE, correlationContextLocal);
69-
70-
// retrieve request context
71-
mv.visitMethodInsn(INVOKESTATIC, "com/microsoft/applicationinsights/web/internal/correlation/TelemetryCorrelationUtils", "retrieveApplicationCorrelationId", "()Ljava/lang/String;", false);
72-
appCorrelationId = this.newLocal(Type.getType(Object.class));
73-
mv.visitVarInsn(ASTORE, appCorrelationId);
74-
75-
// inject headers
76-
mv.visitVarInsn(ALOAD, 2);
77-
mv.visitLdcInsn("Request-Id");
78-
mv.visitVarInsn(ALOAD, childIdLocal);
79-
mv.visitMethodInsn(INVOKEINTERFACE, "org/apache/http/HttpRequest", "addHeader", "(Ljava/lang/String;Ljava/lang/String;)V", true);
68+
// This byte code instrumentation is responsible for injecting legacy AI correlation headers which include
69+
// Request-Id and Request-Context and Correlation-Context. By default this headers are propagated if W3C
70+
// is turned off. Please refer to generateChildDependencyId(), retrieveCorrelationContext(),
71+
// retrieveApplicationCorrelationId() from TelemetryCorrelationUtils class for details on how these headers
72+
// are created.
73+
if (!isW3CEnabled) {
74+
// generate child ID
75+
mv.visitMethodInsn(INVOKESTATIC, "com/microsoft/applicationinsights/web/internal/correlation/TelemetryCorrelationUtils", "generateChildDependencyId", "()Ljava/lang/String;", false);
76+
childIdLocal = this.newLocal(Type.getType(Object.class));
77+
mv.visitVarInsn(ASTORE, childIdLocal);
78+
79+
// retrieve correlation context
80+
mv.visitMethodInsn(INVOKESTATIC, "com/microsoft/applicationinsights/web/internal/correlation/TelemetryCorrelationUtils", "retrieveCorrelationContext", "()Ljava/lang/String;", false);
81+
correlationContextLocal = this.newLocal(Type.getType(Object.class));
82+
mv.visitVarInsn(ASTORE, correlationContextLocal);
83+
84+
// retrieve request context
85+
mv.visitMethodInsn(INVOKESTATIC, "com/microsoft/applicationinsights/web/internal/correlation/TelemetryCorrelationUtils", "retrieveApplicationCorrelationId", "()Ljava/lang/String;", false);
86+
appCorrelationId = this.newLocal(Type.getType(Object.class));
87+
mv.visitVarInsn(ASTORE, appCorrelationId);
88+
89+
// inject headers
90+
// 2 because the 1 is the method being instrumented
91+
mv.visitVarInsn(ALOAD, 2);
92+
mv.visitLdcInsn("Request-Id");
93+
mv.visitVarInsn(ALOAD, childIdLocal);
94+
mv.visitMethodInsn(INVOKEINTERFACE, "org/apache/http/HttpRequest", "addHeader", "(Ljava/lang/String;Ljava/lang/String;)V", true);
95+
96+
mv.visitVarInsn(ALOAD, 2);
97+
mv.visitLdcInsn("Correlation-Context");
98+
mv.visitVarInsn(ALOAD, correlationContextLocal);
99+
mv.visitMethodInsn(INVOKEINTERFACE, "org/apache/http/HttpRequest", "addHeader", "(Ljava/lang/String;Ljava/lang/String;)V", true);
100+
101+
mv.visitVarInsn(ALOAD, 2);
102+
mv.visitLdcInsn("Request-Context");
103+
mv.visitVarInsn(ALOAD, appCorrelationId);
104+
mv.visitMethodInsn(INVOKEINTERFACE, "org/apache/http/HttpRequest", "addHeader", "(Ljava/lang/String;Ljava/lang/String;)V", true);
105+
} else {
106+
// If W3C is enabled, we propagate Traceparent, Tracecontext headers
107+
// to enable correlation. Please refer to generateChildDependencyTraceparent(), generateChildDependencyTraceparent()
108+
// from TraceContextCorrelation class on how to generate this headers.
109+
110+
// generate child Traceparent
111+
mv.visitMethodInsn(INVOKESTATIC, "com/microsoft/applicationinsights/web/internal/correlation/TraceContextCorrelation",
112+
"generateChildDependencyTraceparent", "()Ljava/lang/String;", false);
113+
traceparent = this.newLocal(Type.getType(Object.class));
114+
mv.visitVarInsn(ASTORE, traceparent);
115+
116+
mv.visitVarInsn(ALOAD, traceparent);
117+
mv.visitMethodInsn(INVOKESTATIC, "com/microsoft/applicationinsights/web/internal/correlation/TraceContextCorrelation",
118+
"createChildIdFromTraceparentString", "(Ljava/lang/String;)Ljava/lang/String;", false);
119+
childIdLocal = this.newLocal(Type.getType(Object.class));
120+
mv.visitVarInsn(ASTORE, childIdLocal);
121+
122+
// retrieve tracestate
123+
mv.visitMethodInsn(INVOKESTATIC, "com/microsoft/applicationinsights/web/internal/correlation/TraceContextCorrelation",
124+
"retriveTracestate", "()Ljava/lang/String;", false);
125+
tracestate = this.newLocal(Type.getType(Object.class));
126+
mv.visitVarInsn(ASTORE, tracestate);
127+
128+
// inject headers
129+
// load 2nd variable because the 1st is the method being instrumented
130+
mv.visitVarInsn(ALOAD, 2);
131+
mv.visitLdcInsn("traceparent");
132+
mv.visitVarInsn(ALOAD, traceparent);
133+
mv.visitMethodInsn(INVOKEINTERFACE, "org/apache/http/HttpRequest", "addHeader", "(Ljava/lang/String;Ljava/lang/String;)V", true);
134+
135+
if (isW3CBackportEnabled) {
136+
mv.visitVarInsn(ALOAD, 2);
137+
mv.visitLdcInsn("Request-Id");
138+
mv.visitVarInsn(ALOAD, childIdLocal);
139+
mv.visitMethodInsn(INVOKEINTERFACE, "org/apache/http/HttpRequest", "addHeader", "(Ljava/lang/String;Ljava/lang/String;)V", true);
140+
}
141+
142+
mv.visitVarInsn(ALOAD, tracestate);
143+
Label nullLabel = new Label();
144+
mv.visitJumpInsn(IFNULL, nullLabel);
145+
146+
mv.visitVarInsn(ALOAD, 2);
147+
mv.visitLdcInsn("tracestate");
148+
mv.visitVarInsn(ALOAD, tracestate);
149+
150+
mv.visitMethodInsn(INVOKEINTERFACE, "org/apache/http/HttpRequest", "addHeader", "(Ljava/lang/String;Ljava/lang/String;)V", true);
151+
152+
// skip adding tracestate
153+
mv.visitLabel(nullLabel);
154+
}
80155

81-
mv.visitVarInsn(ALOAD, 2);
82-
mv.visitLdcInsn("Correlation-Context");
83-
mv.visitVarInsn(ALOAD, correlationContextLocal);
84-
mv.visitMethodInsn(INVOKEINTERFACE, "org/apache/http/HttpRequest", "addHeader", "(Ljava/lang/String;Ljava/lang/String;)V", true);
85-
86-
mv.visitVarInsn(ALOAD, 2);
87-
mv.visitLdcInsn("Request-Context");
88-
mv.visitVarInsn(ALOAD, appCorrelationId);
89-
mv.visitMethodInsn(INVOKEINTERFACE, "org/apache/http/HttpRequest", "addHeader", "(Ljava/lang/String;Ljava/lang/String;)V", true);
90156

91157
mv.visitVarInsn(ALOAD, 2);
92158
mv.visitMethodInsn(INVOKEINTERFACE, "org/apache/http/HttpRequest", "getRequestLine", "()Lorg/apache/http/RequestLine;", true);
@@ -153,11 +219,20 @@ protected void byteCodeForMethodExit(int opcode) {
153219
int headerValueLocal = this.newLocal(Type.getType(Object.class));
154220
mv.visitVarInsn(ASTORE, headerValueLocal);
155221

156-
//generate target
157-
mv.visitVarInsn(ALOAD, headerValueLocal);
158-
mv.visitMethodInsn(INVOKESTATIC, "com/microsoft/applicationinsights/web/internal/correlation/TelemetryCorrelationUtils", "generateChildDependencyTarget", "(Ljava/lang/String;)Ljava/lang/String;", false);
159222
int targetLocal = this.newLocal(Type.getType(Object.class));
160-
mv.visitVarInsn(ASTORE, targetLocal);
223+
if (!isW3CEnabled) {
224+
//generate target
225+
mv.visitVarInsn(ALOAD, headerValueLocal);
226+
mv.visitMethodInsn(INVOKESTATIC, "com/microsoft/applicationinsights/web/internal/correlation/TelemetryCorrelationUtils", "generateChildDependencyTarget", "(Ljava/lang/String;)Ljava/lang/String;", false);
227+
mv.visitVarInsn(ASTORE, targetLocal);
228+
} else {
229+
//generate target
230+
mv.visitVarInsn(ALOAD, headerValueLocal);
231+
mv.visitMethodInsn(INVOKESTATIC, "com/microsoft/applicationinsights/web/internal/correlation/TraceContextCorrelation",
232+
"generateChildDependencyTarget", "(Ljava/lang/String;)Ljava/lang/String;", false);
233+
mv.visitVarInsn(ASTORE, targetLocal);
234+
}
235+
161236

162237
mv.visitFieldInsn(Opcodes.GETSTATIC, internalName, "INSTANCE", "L" + internalName + ";");
163238

Diff for: agent/src/main/java/com/microsoft/applicationinsights/agent/internal/agent/http/HttpClassDataProvider.java

+13-1
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,18 @@ public final class HttpClassDataProvider {
6363

6464
private final static String REST_TEMPLATE_METTHOD = "doExecute";
6565

66+
public static void setIsW3CEnabled(boolean isW3CEnabled) {
67+
HttpClassDataProvider.isW3CEnabled = isW3CEnabled;
68+
}
69+
70+
private static boolean isW3CEnabled;
71+
72+
private static boolean isW3CBackportEnabled;
73+
74+
public static void setIsW3CBackportEnabled(boolean isW3CBackportEnabled) {
75+
HttpClassDataProvider.isW3CBackportEnabled = isW3CBackportEnabled;
76+
}
77+
6678
private final Map<String, ClassInstrumentationData> classesToInstrument;
6779

6880
public HttpClassDataProvider(Map<String, ClassInstrumentationData> classesToInstrument) {
@@ -80,7 +92,7 @@ public MethodVisitor create(MethodInstrumentationDecision decision,
8092
String methodName,
8193
MethodVisitor methodVisitor,
8294
ClassToMethodTransformationData additionalData) {
83-
return new HttpClientMethodVisitor(access, desc, className, methodName, methodVisitor, additionalData);
95+
return new HttpClientMethodVisitor(access, desc, className, methodName, methodVisitor, additionalData, isW3CEnabled, isW3CBackportEnabled);
8496
}
8597
};
8698

Diff for: agent/src/main/java/com/microsoft/applicationinsights/agent/internal/config/AgentBuiltInConfiguration.java

+14
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
public class AgentBuiltInConfiguration {
3232
private final boolean enabled;
3333
private final boolean httpEnabled;
34+
private final boolean w3cEnabled;
35+
private final boolean isW3CBackportEnabled;
3436
private final boolean jdbcEnabled;
3537
private final boolean hibernateEnabled;
3638
private final boolean jedisEnabled;
@@ -43,6 +45,8 @@ public class AgentBuiltInConfiguration {
4345
public AgentBuiltInConfiguration(boolean enabled,
4446
List<ClassInstrumentationData> simpleBuiltInClasses,
4547
boolean httpEnabled,
48+
boolean w3cEnabled,
49+
boolean isW3CBackportEnabled,
4650
boolean jdbcEnabled,
4751
boolean hibernateEnabled,
4852
boolean jedisEnabled,
@@ -53,6 +57,8 @@ public AgentBuiltInConfiguration(boolean enabled,
5357
this.simpleBuiltInClasses = simpleBuiltInClasses;
5458
this.enabled = enabled;
5559
this.httpEnabled = httpEnabled;
60+
this.w3cEnabled = w3cEnabled;
61+
this.isW3CBackportEnabled = isW3CBackportEnabled;
5662
this.jdbcEnabled = jdbcEnabled;
5763
this.hibernateEnabled = hibernateEnabled;
5864
this.jmxEnabled = jmxEnabled;
@@ -97,6 +103,14 @@ public boolean isJmxEnabled() {
97103
return jmxEnabled;
98104
}
99105

106+
public boolean isW3cEnabled() {
107+
return w3cEnabled;
108+
}
109+
110+
public boolean isW3CBackportEnabled() {
111+
return isW3CBackportEnabled;
112+
}
113+
100114
public DataOfConfigurationForException getDataOfConfigurationForException() {
101115
return dataOfConfigurationForException;
102116
}

Diff for: agent/src/main/java/com/microsoft/applicationinsights/agent/internal/config/AgentBuiltInConfigurationBuilder.java

+12-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
import com.microsoft.applicationinsights.agent.internal.agent.ClassInstrumentationData;
2525

26+
import com.microsoft.applicationinsights.internal.logger.InternalLogger;
2627
import java.util.List;
2728

2829
/**
@@ -35,6 +36,8 @@ public class AgentBuiltInConfigurationBuilder {
3536
private boolean hibernateEnabled = false;
3637
private boolean jedisEnabled = false;
3738
private boolean jmxEnabled = false;
39+
private boolean w3cEnabled = false;
40+
private boolean isW3CBackportEnabled = true;
3841
private long jedisThresholdInMS = 10000L;
3942
private Long maxSqlQueryLimitInMS = 10000L;
4043
private DataOfConfigurationForException dataOfConfigurationForException = new DataOfConfigurationForException();
@@ -45,9 +48,14 @@ public AgentBuiltInConfiguration create() {
4548
this.dataOfConfigurationForException.setEnabled(false);
4649
}
4750

51+
InternalLogger.INSTANCE.trace(String.format("Outbound W3C tracing is enabled : %s", w3cEnabled));
52+
InternalLogger.INSTANCE.trace(String.format("Outbound W3C backport mode is enabled : %s", isW3CBackportEnabled));
53+
4854
return new AgentBuiltInConfiguration(enabled,
4955
simpleBuiltInClasses,
5056
httpEnabled && enabled,
57+
w3cEnabled && enabled,
58+
isW3CBackportEnabled && enabled,
5159
jdbcEnabled && enabled,
5260
hibernateEnabled && enabled,
5361
jedisEnabled && enabled,
@@ -62,8 +70,11 @@ public AgentBuiltInConfigurationBuilder setEnabled(boolean enabled) {
6270
return this;
6371
}
6472

65-
public AgentBuiltInConfigurationBuilder setHttpEnabled(boolean httpEnabled) {
73+
public AgentBuiltInConfigurationBuilder setHttpEnabled(boolean httpEnabled, boolean w3cEnabled,
74+
boolean isW3CBackportEnabled) {
6675
this.httpEnabled = httpEnabled;
76+
this.w3cEnabled = w3cEnabled;
77+
this.isW3CBackportEnabled = isW3CBackportEnabled;
6778
return this;
6879
}
6980

Diff for: agent/src/main/java/com/microsoft/applicationinsights/agent/internal/config/XmlAgentConfigurationBuilder.java

+6-1
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ final class XmlAgentConfigurationBuilder implements AgentConfigurationBuilder {
6969
@VisibleForTesting final static String SDK_LOGGER_NUMBER_OF_TOTAL_SIZE_IN_MB = "NumberOfTotalSizeInMB";
7070

7171
private final static long JEDIS_ARGS_THRESHOLD_IN_MS = 10000L;
72+
private final static String W3C_ENABLED = "W3C";
73+
private final static String W3C_BACKCOMPAT_PARAMETER = "enableW3CBackCompat";
7274

7375
private final static String EXCLUDED_PREFIXES_TAG = "ExcludedPrefixes";
7476
private final static String FORBIDDEN_PREFIX_TAG = "Prefix";
@@ -223,7 +225,10 @@ private void setBuiltInInstrumentation(AgentConfigurationDefaultImpl agentConfig
223225
new ConfigRuntimeExceptionDataBuilder().setRuntimeExceptionData(builtInElement, builtInConfigurationBuilder);
224226

225227
nodes = builtInElement.getElementsByTagName(HTTP_TAG);
226-
builtInConfigurationBuilder.setHttpEnabled(XmlParserUtils.getEnabled(XmlParserUtils.getFirst(nodes), HTTP_TAG));
228+
Element httpElement = XmlParserUtils.getFirst(nodes);
229+
boolean isW3CEnabled = XmlParserUtils.w3cEnabled(httpElement, W3C_ENABLED, false);
230+
boolean isW3CBackportEnabled =XmlParserUtils.w3cEnabled(httpElement, W3C_BACKCOMPAT_PARAMETER, true);
231+
builtInConfigurationBuilder.setHttpEnabled(XmlParserUtils.getEnabled(element, HTTP_TAG),isW3CEnabled, isW3CBackportEnabled);
227232

228233
nodes = builtInElement.getElementsByTagName(JDBC_TAG);
229234
builtInConfigurationBuilder.setJdbcEnabled(XmlParserUtils.getEnabled(XmlParserUtils.getFirst(nodes), JDBC_TAG));

Diff for: agent/src/main/java/com/microsoft/applicationinsights/agent/internal/config/XmlParserUtils.java

+23
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
import com.microsoft.applicationinsights.agent.internal.common.StringUtils;
2525
import com.microsoft.applicationinsights.internal.logger.InternalLogger;
26+
import org.apache.commons.lang3.exception.ExceptionUtils;
2627
import org.w3c.dom.Element;
2728
import org.w3c.dom.Node;
2829
import org.w3c.dom.NodeList;
@@ -59,6 +60,28 @@ public static boolean getEnabled(Element element, String attributeName) {
5960
return getEnabled(element, attributeName, true);
6061
}
6162

63+
/**
64+
* Method to get the attribute value for W3C
65+
* @param element
66+
* @param attributeName
67+
* @return boolean
68+
*/
69+
static boolean w3cEnabled(Element element, String attributeName, boolean defaultValue) {
70+
try {
71+
String strValue = element.getAttribute(attributeName);
72+
if (!StringUtils.isNullOrEmpty(strValue)) {
73+
boolean value = Boolean.valueOf(strValue);
74+
return value;
75+
}
76+
return defaultValue;
77+
78+
} catch (Exception e) {
79+
InternalLogger.INSTANCE.error("cannot parse the correlation format, will default"
80+
+ "to AI proprietory correlation", ExceptionUtils.getStackTrace(e));
81+
}
82+
return defaultValue;
83+
}
84+
6285
public static boolean getEnabled(Element element, String elementName, boolean defaultValue) {
6386
if (element == null) {
6487
return true;

0 commit comments

Comments
 (0)