Skip to content

Commit ea77ad7

Browse files
committed
Service naming: split by jee deployment
1 parent 32c64c4 commit ea77ad7

File tree

26 files changed

+413
-44
lines changed

26 files changed

+413
-44
lines changed

dd-java-agent/instrumentation/jboss-modules/src/main/java/datadog/trace/instrumentation/jbossmodules/ModuleInstrumentation.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
package datadog.trace.instrumentation.jbossmodules;
22

33
import static datadog.trace.agent.tooling.bytebuddy.matcher.NameMatchers.named;
4+
import static datadog.trace.instrumentation.jbossmodules.ModuleNameHelper.STRIPPER;
5+
import static net.bytebuddy.matcher.ElementMatchers.isConstructor;
46
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
57
import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
68
import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
79

810
import com.google.auto.service.AutoService;
911
import datadog.trace.agent.tooling.Instrumenter;
1012
import datadog.trace.agent.tooling.InstrumenterModule;
13+
import datadog.trace.api.naming.ClassloaderServiceNames;
1114
import datadog.trace.bootstrap.AgentClassLoading;
1215
import java.io.IOException;
1316
import java.io.InputStream;
@@ -33,7 +36,8 @@ public String[] helperClassNames() {
3336
return new String[] {
3437
"org.jboss.modules.ModuleLinkageHelper",
3538
"org.jboss.modules.ModuleLinkageHelper$1",
36-
"org.jboss.modules.ModuleLinkageHelper$2"
39+
"org.jboss.modules.ModuleLinkageHelper$2",
40+
packageName + ".ModuleNameHelper",
3741
};
3842
}
3943

@@ -60,6 +64,7 @@ public void methodAdvice(MethodTransformer transformer) {
6064
.and(takesArgument(0, String.class))
6165
.and(takesArgument(1, boolean.class)))),
6266
ModuleInstrumentation.class.getName() + "$WidenLoadClassAdvice");
67+
transformer.applyAdvice(isConstructor(), getClass().getName() + "$CaptureModuleNameAdvice");
6368
}
6469

6570
/**
@@ -154,4 +159,11 @@ public static void onExit(
154159
}
155160
}
156161
}
162+
163+
public static class CaptureModuleNameAdvice {
164+
@Advice.OnMethodExit(suppress = Throwable.class)
165+
public static void afterConstruct(@Advice.This final Module module) {
166+
ClassloaderServiceNames.addIfMissing(module.getClassLoader(), STRIPPER);
167+
}
168+
}
157169
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package datadog.trace.instrumentation.jbossmodules;
2+
3+
import java.util.function.Function;
4+
import java.util.function.Supplier;
5+
import java.util.regex.Matcher;
6+
import java.util.regex.Pattern;
7+
import org.jboss.modules.ModuleClassLoader;
8+
9+
public class ModuleNameHelper {
10+
private ModuleNameHelper() {}
11+
12+
private static final Pattern SUBDEPLOYMENT_MATCH =
13+
Pattern.compile("deployment(?>.+\\.ear)?\\.(.+)\\.[j|w]ar");
14+
public static final Function<ClassLoader, Supplier<String>> STRIPPER =
15+
classLoader -> {
16+
final Matcher matcher =
17+
SUBDEPLOYMENT_MATCH.matcher(
18+
((ModuleClassLoader) classLoader).getModule().getIdentifier().getName());
19+
if (matcher.matches()) {
20+
final String result = matcher.group(1);
21+
return () -> result;
22+
}
23+
return () -> null;
24+
};
25+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package datadog.trace.instrumentation.liberty20;
2+
3+
import com.ibm.ws.classloading.internal.ThreadContextClassLoader;
4+
import java.util.function.Function;
5+
import java.util.function.Supplier;
6+
7+
public class BundleNameHelper {
8+
private BundleNameHelper() {}
9+
10+
public static final Function<ClassLoader, Supplier<String>> EXTRACTOR =
11+
classLoader -> {
12+
final String id = ((ThreadContextClassLoader) classLoader).getKey();
13+
// id is something like <type>:name#somethingelse
14+
final int head = id.indexOf(':');
15+
if (head < 0) {
16+
return () -> null;
17+
}
18+
final int tail = id.lastIndexOf('#');
19+
if (tail < 0) {
20+
return () -> null;
21+
}
22+
final String name = id.substring(head + 1, tail);
23+
return () -> name;
24+
};
25+
}

dd-java-agent/instrumentation/liberty-20/src/main/java/datadog/trace/instrumentation/liberty20/LibertyServerInstrumentation.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,14 @@
1212
import com.google.auto.service.AutoService;
1313
import com.ibm.ws.webcontainer.srt.SRTServletRequest;
1414
import com.ibm.ws.webcontainer.srt.SRTServletResponse;
15+
import com.ibm.ws.webcontainer.webapp.WebApp;
16+
import com.ibm.wsspi.webcontainer.webapp.IWebAppDispatcherContext;
1517
import datadog.trace.agent.tooling.Instrumenter;
1618
import datadog.trace.agent.tooling.InstrumenterModule;
1719
import datadog.trace.api.CorrelationIdentifier;
1820
import datadog.trace.api.GlobalTracer;
1921
import datadog.trace.api.gateway.Flow;
22+
import datadog.trace.api.naming.ClassloaderServiceNames;
2023
import datadog.trace.bootstrap.ActiveSubsystems;
2124
import datadog.trace.bootstrap.ContextStore;
2225
import datadog.trace.bootstrap.InstrumentationContext;
@@ -104,7 +107,16 @@ public static class HandleRequestAdvice {
104107
request.setAttribute(DD_EXTRACTED_CONTEXT_ATTRIBUTE, extractedContext);
105108
final AgentSpan span = DECORATE.startSpan(request, extractedContext);
106109
scope = activateSpan(span, true);
107-
110+
final IWebAppDispatcherContext dispatcherContext = request.getWebAppDispatcherContext();
111+
if (dispatcherContext != null) {
112+
final WebApp webapp = dispatcherContext.getWebApp();
113+
if (webapp != null) {
114+
final ClassLoader cl = webapp.getClassLoader();
115+
if (cl != null) {
116+
ClassloaderServiceNames.maybeSetToSpan(span::setServiceName, span::getServiceName, cl);
117+
}
118+
}
119+
}
108120
DECORATE.afterStart(span);
109121
DECORATE.onRequest(span, request, request, extractedContext);
110122
request.setAttribute(DD_SPAN_ATTRIBUTE, span);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package datadog.trace.instrumentation.liberty20;
2+
3+
import static net.bytebuddy.matcher.ElementMatchers.isConstructor;
4+
5+
import com.google.auto.service.AutoService;
6+
import com.ibm.ws.classloading.internal.ThreadContextClassLoader;
7+
import datadog.trace.agent.tooling.Instrumenter;
8+
import datadog.trace.agent.tooling.InstrumenterModule;
9+
import datadog.trace.api.naming.ClassloaderServiceNames;
10+
import net.bytebuddy.asm.Advice;
11+
12+
@AutoService(InstrumenterModule.class)
13+
public class ThreadContextClassloaderInstrumentation extends InstrumenterModule.Tracing
14+
implements Instrumenter.ForSingleType {
15+
16+
public ThreadContextClassloaderInstrumentation() {
17+
super("liberty", "liberty-classloading");
18+
}
19+
20+
@Override
21+
public String instrumentedType() {
22+
return "com.ibm.ws.classloading.internal.ThreadContextClassLoader";
23+
}
24+
25+
@Override
26+
public String[] helperClassNames() {
27+
return new String[] {
28+
packageName + ".BundleNameHelper",
29+
};
30+
}
31+
32+
@Override
33+
public void methodAdvice(MethodTransformer transformer) {
34+
transformer.applyAdvice(
35+
isConstructor(), getClass().getName() + "$ThreadContextClassloaderAdvice");
36+
}
37+
38+
public static class ThreadContextClassloaderAdvice {
39+
@Advice.OnMethodExit(suppress = Throwable.class)
40+
public static void afterConstruct(@Advice.This ThreadContextClassLoader self) {
41+
ClassloaderServiceNames.addIfMissing(self, BundleNameHelper.EXTRACTOR);
42+
}
43+
}
44+
}

dd-java-agent/instrumentation/liberty-20/src/test/groovy/datadog/trace/instrumentation/liberty20/Liberty20Test.groovy

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,20 @@ class Liberty20AsyncForkedTest extends Liberty20Test implements TestingGenericHt
213213
}
214214
}
215215

216+
@IgnoreIf({
217+
// failing because org.apache.xalan.transformer.TransformerImpl is
218+
// instrumented while on the the global ignores list
219+
System.getProperty('java.vm.name') == 'IBM J9 VM' &&
220+
System.getProperty('java.specification.version') == '1.8' })
221+
class LibertyServletClassloaderNamingForkedTest extends Liberty20V0ForkedTest {
222+
@Override
223+
protected void configurePreAgent() {
224+
super.configurePreAgent()
225+
// will not set the service name according to the servlet context value
226+
injectSysConfig("trace.experimental.jee.split-by-deployment", "true")
227+
}
228+
}
229+
216230
@IgnoreIf({
217231
// failing because org.apache.xalan.transformer.TransformerImpl is
218232
// instrumented while on the the global ignores list

dd-java-agent/instrumentation/liberty-23/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ dependencies {
3434
testImplementation testFixtures(project(':dd-java-agent:appsec'))
3535
testRuntimeOnly project(':dd-java-agent:instrumentation:osgi-4.3')
3636
testRuntimeOnly files({ tasks.filterLogbackClassic.filteredLogbackDir })
37+
testRuntimeOnly project(':dd-java-agent:instrumentation:liberty-20')
3738
testRuntimeOnly project(':dd-java-agent:instrumentation:servlet:request-5')
3839
testRuntimeOnly files({ tasks.shadowJar.archiveFile })
3940

dd-java-agent/instrumentation/liberty-23/src/main/java/datadog/trace/instrumentation/liberty23/LibertyServerInstrumentation.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,14 @@
1212
import com.google.auto.service.AutoService;
1313
import com.ibm.ws.webcontainer.srt.SRTServletRequest;
1414
import com.ibm.ws.webcontainer.srt.SRTServletResponse;
15+
import com.ibm.ws.webcontainer.webapp.WebApp;
16+
import com.ibm.wsspi.webcontainer.webapp.IWebAppDispatcherContext;
1517
import datadog.trace.agent.tooling.Instrumenter;
1618
import datadog.trace.agent.tooling.InstrumenterModule;
1719
import datadog.trace.api.CorrelationIdentifier;
1820
import datadog.trace.api.GlobalTracer;
1921
import datadog.trace.api.gateway.Flow;
22+
import datadog.trace.api.naming.ClassloaderServiceNames;
2023
import datadog.trace.bootstrap.ActiveSubsystems;
2124
import datadog.trace.bootstrap.ContextStore;
2225
import datadog.trace.bootstrap.InstrumentationContext;
@@ -106,7 +109,16 @@ public static class HandleRequestAdvice {
106109
request.setAttribute(DD_EXTRACTED_CONTEXT_ATTRIBUTE, extractedContext);
107110
final AgentSpan span = DECORATE.startSpan(request, extractedContext);
108111
scope = activateSpan(span, true);
109-
112+
final IWebAppDispatcherContext dispatcherContext = request.getWebAppDispatcherContext();
113+
if (dispatcherContext != null) {
114+
final WebApp webapp = dispatcherContext.getWebApp();
115+
if (webapp != null) {
116+
final ClassLoader cl = webapp.getClassLoader();
117+
if (cl != null) {
118+
ClassloaderServiceNames.maybeSetToSpan(span::setServiceName, span::getServiceName, cl);
119+
}
120+
}
121+
}
110122
DECORATE.afterStart(span);
111123
DECORATE.onRequest(span, request, request, extractedContext);
112124
request.setAttribute(DD_SPAN_ATTRIBUTE, span);

dd-java-agent/instrumentation/liberty-23/src/test/groovy/datadog/trace/instrumentation/liberty23/Liberty23Test.groovy

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,3 +170,17 @@ class Liberty23V0ForkedTest extends Liberty23Test implements TestingGenericHttpN
170170
System.getProperty('java.specification.version') == '1.8' })
171171
class Liberty23V1ForkedTest extends Liberty23Test implements TestingGenericHttpNamingConventions.ServerV1 {
172172
}
173+
174+
@IgnoreIf({
175+
// failing because org.apache.xalan.transformer.TransformerImpl is
176+
// instrumented while on the the global ignores list
177+
System.getProperty('java.vm.name') == 'IBM J9 VM' &&
178+
System.getProperty('java.specification.version') == '1.8' })
179+
class LibertyServletClassloaderNamingForkedTest extends Liberty23V0ForkedTest {
180+
@Override
181+
protected void configurePreAgent() {
182+
super.configurePreAgent()
183+
// will not set the service name according to the servlet context value
184+
injectSysConfig("trace.experimental.jee.split-by-deployment", "true")
185+
}
186+
}

dd-java-agent/instrumentation/servlet/request-2/src/main/java/datadog/trace/instrumentation/servlet2/Servlet2Advice.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import datadog.trace.api.DDTags;
1010
import datadog.trace.api.GlobalTracer;
1111
import datadog.trace.api.gateway.Flow;
12+
import datadog.trace.api.naming.ClassloaderServiceNames;
1213
import datadog.trace.bootstrap.InstrumentationContext;
1314
import datadog.trace.bootstrap.instrumentation.api.AgentScope;
1415
import datadog.trace.bootstrap.instrumentation.api.AgentSpan;
@@ -39,6 +40,9 @@ public static boolean onEnter(
3940
Object spanAttr = request.getAttribute(DD_SPAN_ATTRIBUTE);
4041
final boolean hasServletTrace = spanAttr instanceof AgentSpan;
4142
if (hasServletTrace) {
43+
final AgentSpan span = (AgentSpan) spanAttr;
44+
ClassloaderServiceNames.maybeSetToSpan(
45+
span::setServiceName, span::getServiceName, Thread.currentThread());
4246
// Tracing might already be applied by the FilterChain or a parent request (forward/include).
4347
return false;
4448
}

0 commit comments

Comments
 (0)