Skip to content

Commit 7ec8339

Browse files
authored
Merge pull request #839 from DataDog/labbati/jdbc-error-glasshfish
Glassfish: prevent blacklisting of specific classes and dump stacktrace in debug mode if this happens
2 parents 0ea2d74 + eb032d1 commit 7ec8339

5 files changed

Lines changed: 130 additions & 0 deletions

File tree

dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/Utils.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,5 +84,17 @@ public static MethodDescription getMethodDefinition(
8484
return type.getDeclaredMethods().filter(named(methodName)).getOnly();
8585
}
8686

87+
/** @return The current stack trace with multiple entries on new lines. */
88+
public static String getStackTraceAsString() {
89+
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
90+
StringBuilder stringBuilder = new StringBuilder();
91+
String lineSeparator = System.getProperty("line.separator");
92+
for (StackTraceElement element : stackTrace) {
93+
stringBuilder.append(element.toString());
94+
stringBuilder.append(lineSeparator);
95+
}
96+
return stringBuilder.toString();
97+
}
98+
8799
private Utils() {}
88100
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package datadog.trace.agent.tooling
2+
3+
import spock.lang.Specification
4+
5+
6+
class UtilsTest extends Specification {
7+
8+
def "getStackTraceAsString() returns the stack trace as a single new line separated string"() {
9+
setup:
10+
def stackTrace = Utils.stackTraceAsString
11+
12+
expect:
13+
stackTrace.contains('datadog.trace.agent.tooling.Utils')
14+
stackTrace.contains(System.getProperty("line.separator"))
15+
}
16+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
apply from: "${rootDir}/gradle/java.gradle"
2+
apply plugin: 'idea'
3+
apply plugin: 'org.unbroken-dome.test-sets'
4+
5+
muzzle {
6+
pass {
7+
group = 'org.glassfish.main.extras'
8+
module = 'glassfish-embedded-all'
9+
versions = "[3.0,)"
10+
assertInverse = true
11+
}
12+
}
13+
14+
testSets {
15+
latestDepTest {
16+
dirName = 'test'
17+
}
18+
}
19+
20+
dependencies {
21+
22+
compile project(':dd-trace-ot')
23+
compile project(':dd-java-agent:agent-tooling')
24+
25+
compile deps.bytebuddy
26+
compile deps.opentracing
27+
compile deps.autoservice
28+
annotationProcessor deps.autoservice
29+
implementation deps.autoservice
30+
31+
testCompile project(':dd-java-agent:testing')
32+
testCompile group: 'org.glassfish.main.extras', name: 'glassfish-embedded-all', version: '4.1.2'
33+
34+
latestDepTestCompile sourceSets.test.output
35+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package datadog.trace.instrumentation.glassfish;
2+
3+
import static java.util.Collections.singletonMap;
4+
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
5+
import static net.bytebuddy.matcher.ElementMatchers.named;
6+
import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
7+
8+
import com.google.auto.service.AutoService;
9+
import datadog.trace.agent.tooling.Constants;
10+
import datadog.trace.agent.tooling.Instrumenter;
11+
import java.util.Map;
12+
import lombok.extern.slf4j.Slf4j;
13+
import net.bytebuddy.asm.Advice;
14+
import net.bytebuddy.description.method.MethodDescription;
15+
import net.bytebuddy.description.type.TypeDescription;
16+
import net.bytebuddy.matcher.ElementMatcher;
17+
import net.bytebuddy.matcher.ElementMatchers;
18+
19+
/**
20+
* This instrumenter prevents a mechanism from GlassFish classloader to produces a class not found
21+
* exception in our tracer. Link to the GH issue:
22+
* https://github.com/eclipse-ee4j/glassfish/issues/22566 If a class loading is attempted, as an
23+
* example, as a resource and is it not found, then it is blacklisted. Successive attempts to load a
24+
* class as a class (not a resource) will fail because the class is not even tried. We hook into the
25+
* blacklisting method to avoid specific namespaces to be blacklisted.
26+
*/
27+
@Slf4j
28+
@AutoService(Instrumenter.class)
29+
public final class GlassfishInstrumentation extends Instrumenter.Default {
30+
31+
public GlassfishInstrumentation() {
32+
super("glassfish");
33+
}
34+
35+
@Override
36+
public String[] helperClassNames() {
37+
return new String[] {Constants.class.getName()};
38+
}
39+
40+
@Override
41+
public ElementMatcher<? super TypeDescription> typeMatcher() {
42+
return ElementMatchers.named(
43+
"com.sun.enterprise.v3.server.APIClassLoaderServiceImpl$APIClassLoader");
44+
}
45+
46+
@Override
47+
public Map<? extends ElementMatcher<? super MethodDescription>, String> transformers() {
48+
return singletonMap(
49+
isMethod().and(named("addToBlackList")).and(takesArguments(1)),
50+
AvoidGlassFishBlacklistAdvice.class.getName());
51+
}
52+
53+
public static class AvoidGlassFishBlacklistAdvice {
54+
55+
@Advice.OnMethodEnter(suppress = Throwable.class)
56+
public static void preventBlacklistingOfTracerClasses(
57+
@Advice.Argument(value = 0, readOnly = false) String name) {
58+
for (String prefix : Constants.BOOTSTRAP_PACKAGE_PREFIXES) {
59+
if (name.startsWith(prefix)) {
60+
name = "__datadog_no_blacklist." + name;
61+
break;
62+
}
63+
}
64+
}
65+
}
66+
}

settings.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ include ':dd-java-agent:instrumentation:elasticsearch:transport-2'
4040
include ':dd-java-agent:instrumentation:elasticsearch:transport-5'
4141
include ':dd-java-agent:instrumentation:elasticsearch:transport-5.3'
4242
include ':dd-java-agent:instrumentation:elasticsearch:transport-6'
43+
include ':dd-java-agent:instrumentation:glassfish'
4344
include ':dd-java-agent:instrumentation:grpc-1.5'
4445
include ':dd-java-agent:instrumentation:hibernate'
4546
include ':dd-java-agent:instrumentation:hibernate:core-3.3'

0 commit comments

Comments
 (0)