Skip to content

Commit 10faa9a

Browse files
authored
Merge pull request #113 from DataDog/tyler/jetty
Add version checking via class/method for jetty
2 parents 59d1be4 + 9a9da92 commit 10faa9a

File tree

7 files changed

+103
-56
lines changed

7 files changed

+103
-56
lines changed

buildSrc/src/main/groovy/VersionScanPlugin.groovy

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,12 @@ class VersionScanPlugin implements Plugin<Project> {
139139

140140
def errors = []
141141
for (String className : verifyPresent.keySet()) {
142+
if (project.versionScan.scanMethods && verifyPresent.get(className) == null) {
143+
throw new AssertionError("When 'scanMethods' is enabled, a method must be configured for '$className'")
144+
} else if (!project.versionScan.scanMethods && verifyPresent.get(className) != null) {
145+
throw new AssertionError("When 'scanMethods' is not enabled, configured method must be null for '$className'")
146+
}
147+
142148
String identifier = project.versionScan.scanMethods ? "$className|${verifyPresent.get(className)}" : className
143149
if (!keyPresent.get().contains(identifier)) {
144150
errors << "not a 'keyPresent' identifier: $identifier"
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
apply plugin: 'version-scan'
2+
3+
versionScan {
4+
group = "org.eclipse.jetty"
5+
module = "jetty-server"
6+
versions = "[8.0,)"
7+
legacyGroup = "org.mortbay.jetty"
8+
legacyModule = "jetty"
9+
scanMethods = true
10+
verifyPresent = [
11+
"org.eclipse.jetty.server.ServletRequestHttpWrapper": "getPart",
12+
]
13+
}

dd-java-agent/src/main/java/com/datadoghq/trace/agent/InstrumentationChecker.java

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import com.fasterxml.jackson.annotation.JsonProperty;
55
import com.fasterxml.jackson.core.type.TypeReference;
66
import java.io.File;
7+
import java.lang.reflect.Method;
78
import java.util.ArrayList;
89
import java.util.Collections;
910
import java.util.HashMap;
@@ -131,11 +132,33 @@ private List<String> doGetUnsupportedRules() {
131132
log.debug("Checking rule {}", check);
132133

133134
boolean matched = true;
134-
for (final String identifyingClass : check.identifyingPresentClasses) {
135-
final boolean classPresent = isClassPresent(identifyingClass);
135+
for (final Map.Entry<String, String> identifier :
136+
check.identifyingPresentClasses.entrySet()) {
137+
final boolean classPresent = isClassPresent(identifier.getKey());
136138
if (!classPresent) {
137-
log.debug(
138-
"Instrumentation {} not applied due to missing class {}.", rule, identifyingClass);
139+
log.debug("Instrumentation {} not applied due to missing class {}.", rule, identifier);
140+
} else {
141+
String identifyingMethod = identifier.getValue();
142+
if (identifyingMethod != null && !identifyingMethod.isEmpty()) {
143+
Class clazz = getClassIfPresent(identifier.getKey(), classLoader);
144+
// already confirmed above the class is there.
145+
Method[] declaredMethods = clazz.getDeclaredMethods();
146+
boolean methodFound = false;
147+
for (Method m : declaredMethods) {
148+
if (m.getName().equals(identifyingMethod)) {
149+
methodFound = true;
150+
break;
151+
}
152+
}
153+
if (!methodFound) {
154+
log.debug(
155+
"Instrumentation {} not applied due to missing method {}.{}",
156+
rule,
157+
identifier.getKey(),
158+
identifyingMethod);
159+
matched = false;
160+
}
161+
}
139162
}
140163
matched &= classPresent;
141164
}
@@ -183,11 +206,14 @@ private boolean isClassPresent(final String identifyingPresentClass) {
183206
}
184207

185208
static boolean isClassPresent(final String identifyingPresentClass, ClassLoader classLoader) {
209+
return getClassIfPresent(identifyingPresentClass, classLoader) != null;
210+
}
211+
212+
static Class getClassIfPresent(final String identifyingPresentClass, ClassLoader classLoader) {
186213
try {
187-
return identifyingPresentClass != null
188-
&& Class.forName(identifyingPresentClass, false, classLoader) != null;
189-
} catch (final ClassNotFoundException e) {
190-
return false;
214+
return Class.forName(identifyingPresentClass, false, classLoader);
215+
} catch (final Exception e) {
216+
return null;
191217
}
192218
}
193219

@@ -199,7 +225,7 @@ static class ArtifactSupport {
199225
private String supportedVersion;
200226

201227
@JsonProperty("identifying_present_classes")
202-
private List<String> identifyingPresentClasses = Collections.emptyList();
228+
private Map<String, String> identifyingPresentClasses = Collections.emptyMap();
203229

204230
@JsonProperty("identifying_missing_classes")
205231
private List<String> identifyingMissingClasses = Collections.emptyList();
Lines changed: 36 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
### This file define all supported libraries
22
### Syntax:
3-
### <rulename>: # the rule name defined in the otarules.btm
4-
### - artifact: <artifactId> # the artifact name to be tested
5-
### supported_version: # a regex expression to express the version required by the rule
6-
### identifying_present_classes: # a list of classes that distinctly identify the range of supported libraries
7-
### - some.key.FrameworkClass # only if missing, supported_version regex is used.
3+
### <rulename>: # the rule name defined in the otarules.btm
4+
### - artifact: <artifactId> # the artifact name to be tested
5+
### supported_version: # a regex expression to express the version required by the rule
6+
### identifying_present_classes: # a list of classes that distinctly identify the range of supported libraries
7+
### some.key.FrameworkClass: orMethod # only if missing, supported_version regex is used.
88
### - ...
99

1010
opentracing-apache-httpclient:
1111
- artifact: httpclient
1212
supported_version: 4\.[3|4|5]\..*
1313
identifying_present_classes:
14-
- org.apache.http.conn.SchemePortResolver
15-
- org.apache.http.conn.ssl.SSLContexts
14+
org.apache.http.conn.SchemePortResolver:
15+
org.apache.http.conn.ssl.SSLContexts:
1616

1717
- artifact: commons-httpclient
1818
supported_version: none
@@ -21,82 +21,83 @@ opentracing-aws-sdk:
2121
- artifact: aws-java-sdk
2222
supported_version: 1\.11\..*
2323
identifying_present_classes:
24-
- com.amazonaws.http.client.HttpClientFactory
25-
- com.amazonaws.http.apache.utils.ApacheUtils
26-
- com.amazonaws.http.request.HttpRequestFactory
24+
com.amazonaws.http.client.HttpClientFactory:
25+
com.amazonaws.http.apache.utils.ApacheUtils:
26+
com.amazonaws.http.request.HttpRequestFactory:
2727

2828
opentracing-cassandra-driver:
2929
- artifact: cassandra-driver-core
3030
supported_version: 3\.2.*
3131
identifying_present_classes:
32-
- com.datastax.driver.core.utils.MoreObjects
33-
- com.datastax.driver.core.RemoteEndpointAwareNettySSLOptions
34-
- com.datastax.driver.core.GuavaCompatibility
32+
com.datastax.driver.core.utils.MoreObjects:
33+
com.datastax.driver.core.RemoteEndpointAwareNettySSLOptions:
34+
com.datastax.driver.core.GuavaCompatibility:
3535

3636
opentracing-jms-2_producer:
3737
- artifact: javax.jms-api
3838
supported_version: 2\..*
3939
identifying_present_classes:
40-
- javax.jms.JMSContext
41-
- javax.jms.CompletionListener
40+
javax.jms.JMSContext:
41+
javax.jms.CompletionListener:
4242

4343
opentracing-jms-2_consumer:
4444
- artifact: javax.jms-api
4545
supported_version: 2\..*
4646
identifying_present_classes:
47-
- javax.jms.JMSContext
48-
- javax.jms.CompletionListener
47+
javax.jms.JMSContext:
48+
javax.jms.CompletionListener:
4949

5050
opentracing-mongo-driver:
5151
- artifact: mongo-java-driver
5252
supported_version: 3\..*
5353
identifying_present_classes:
54-
- com.mongodb.operation.AsyncReadOperation
55-
- com.mongodb.client.model.MapReduceAction
54+
com.mongodb.operation.AsyncReadOperation:
55+
com.mongodb.client.model.MapReduceAction:
5656

5757
- artifact: mongodb-driver-async
5858
supported_version: 3\..*
5959
identifying_present_classes:
60-
- com.mongodb.operation.AsyncReadOperation
61-
- com.mongodb.client.model.MapReduceAction
60+
com.mongodb.operation.AsyncReadOperation:
61+
com.mongodb.client.model.MapReduceAction:
6262

6363
opentracing-mongo-driver-helper:
6464
- artifact: mongo-java-driver
6565
supported_version: 3\..*
6666
identifying_present_classes:
67-
- com.mongodb.operation.AsyncReadOperation
68-
- com.mongodb.client.model.MapReduceAction
67+
com.mongodb.operation.AsyncReadOperation:
68+
com.mongodb.client.model.MapReduceAction:
6969

7070
- artifact: mongodb-driver-async
7171
supported_version: 3\..*
7272
identifying_present_classes:
73-
- com.mongodb.operation.AsyncReadOperation
74-
- com.mongodb.client.model.MapReduceAction
73+
com.mongodb.operation.AsyncReadOperation:
74+
com.mongodb.client.model.MapReduceAction:
7575

7676
opentracing-okhttp3:
7777
- artifact: okhttp
7878
supported_version: 3\..*
7979
identifying_present_classes:
80-
- okhttp3.Cookie
81-
- okhttp3.ConnectionPool
82-
- okhttp3.Headers
80+
okhttp3.Cookie:
81+
okhttp3.ConnectionPool:
82+
okhttp3.Headers:
8383

8484
opentracing-web-servlet-filter_jetty:
8585
- artifact: jetty-server
8686
supported_version: (8\.|9\.).*
87-
# identifying_present_classes:
87+
identifying_present_classes:
88+
org.eclipse.jetty.server.ServletRequestHttpWrapper: getPart
8889

8990
opentracing-web-servlet-filter_tomcat:
9091
- artifact: opentracing-web-servlet-filter_tomcat
9192
supported_version: (8\.|9\.).*
9293
identifying_present_classes:
93-
- org.apache.catalina.WebResource
94-
- org.apache.catalina.webresources.TrackedInputStream
95-
- org.apache.catalina.webresources.AbstractArchiveResource
94+
org.apache.catalina.WebResource:
95+
org.apache.catalina.webresources.TrackedInputStream:
96+
org.apache.catalina.webresources.AbstractArchiveResource:
9697

9798
- artifact: opentracing-web-servlet-filter_tomcat
9899
supported_version: (8\.|9\.).*
99100
identifying_present_classes:
100-
- org.apache.catalina.WebResource
101-
- org.apache.catalina.webresources.TrackedInputStream
102-
- org.apache.catalina.webresources.AbstractArchiveResource
101+
org.apache.catalina.WebResource:
102+
org.apache.catalina.webresources.TrackedInputStream:
103+
org.apache.catalina.webresources.AbstractArchiveResource:

dd-java-agent/src/test/groovy/com/datadoghq/trace/agent/InstrumentationCheckerTest.groovy

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ class InstrumentationCheckerTest extends Specification {
2424
rules.sort() == ["unsupportedRuleOne", "unsupportedRuleThree", "unsupportedRuleTwo"]
2525
}
2626

27-
static class DemoClass1 {}
27+
static class DemoClass1 {
28+
void testMethod(String arg) {}
29+
}
2830

2931
static class DemoClass2 {}
3032

dd-java-agent/src/test/resources/supported-version-test.yaml

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,38 +4,36 @@ unsupportedRuleOne:
44

55
- artifact: artifact-2
66
supported_version: none
7-
identifying_present_classes:
8-
-
97

108
unsupportedRuleTwo:
119
- artifact: artifact-1
1210
supported_version: 2\.3\.
1311
identifying_present_classes:
14-
- com.datadoghq.trace.agent.InstrumentationCheckerTest$MissingClass
12+
com.datadoghq.trace.agent.InstrumentationCheckerTest$DemoClass1: missingMethod
1513

1614
supportedRuleOne:
1715
- artifact: artifact-3
1816
supported_version: 5\..*
1917
identifying_present_classes:
20-
- com.datadoghq.trace.agent.InstrumentationCheckerTest$DemoClass1
21-
- com.datadoghq.trace.agent.InstrumentationCheckerTest$DemoClass2
22-
- com.datadoghq.trace.agent.InstrumentationCheckerTest$DemoClass3
18+
com.datadoghq.trace.agent.InstrumentationCheckerTest$DemoClass1:
19+
com.datadoghq.trace.agent.InstrumentationCheckerTest$DemoClass2:
20+
com.datadoghq.trace.agent.InstrumentationCheckerTest$DemoClass3:
2321

2422
supportedRuleTwo:
2523
- artifact: artifact-1
2624
supported_version: 1\.2\.3\..*
2725
identifying_present_classes:
28-
- com.datadoghq.trace.agent.InstrumentationCheckerTest$DemoClass1
29-
- com.datadoghq.trace.agent.InstrumentationCheckerTest$DemoClass2
26+
com.datadoghq.trace.agent.InstrumentationCheckerTest$DemoClass1: testMethod
27+
com.datadoghq.trace.agent.InstrumentationCheckerTest$DemoClass2:
3028

3129
- artifact: artifact-2
3230
supported_version: 4\..*
3331
identifying_present_classes:
34-
- com.datadoghq.trace.agent.InstrumentationCheckerTest$DemoClass3
32+
com.datadoghq.trace.agent.InstrumentationCheckerTest$DemoClass3: missingMethod
3533

3634
unsupportedRuleThree:
3735
- artifact: foo
3836
supported_version: 1
3937
identifying_present_classes:
40-
- com.datadoghq.trace.agent.InstrumentationCheckerTest$DemoClass1
41-
- com.datadoghq.trace.agent.InstrumentationCheckerTest$MissingClass
38+
com.datadoghq.trace.agent.InstrumentationCheckerTest$DemoClass1:
39+
com.datadoghq.trace.agent.InstrumentationCheckerTest$MissingClass:

settings.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ include ':dd-trace-annotations'
1414
include ':dd-java-agent:integrations:apache-httpclient'
1515
include ':dd-java-agent:integrations:aws-sdk'
1616
include ':dd-java-agent:integrations:cassandra'
17+
include ':dd-java-agent:integrations:jetty'
1718
include ':dd-java-agent:integrations:jms'
1819
include ':dd-java-agent:integrations:mongo'
1920
include ':dd-java-agent:integrations:mongo-async'

0 commit comments

Comments
 (0)