Skip to content

Commit 5dd63de

Browse files
authored
Service naming: split by jee deployment (#8064)
* Service naming: split by jee deployment * Do not use invokedynamic * fix tests * collapse enter and local * Adjust service name for non legacy tracing * Add wildfly ejb test * limit max java verson to 11 for wildfly 15 * renaming * refactor according to the review * remove helper * avoid casting * review
1 parent 9918d21 commit 5dd63de

File tree

35 files changed

+529
-73
lines changed

35 files changed

+529
-73
lines changed

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

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

33
import static datadog.trace.agent.tooling.bytebuddy.matcher.NameMatchers.named;
4+
import static net.bytebuddy.matcher.ElementMatchers.isConstructor;
45
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
56
import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
67
import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
78

89
import com.google.auto.service.AutoService;
910
import datadog.trace.agent.tooling.Instrumenter;
1011
import datadog.trace.agent.tooling.InstrumenterModule;
12+
import datadog.trace.api.naming.ClassloaderServiceNames;
1113
import datadog.trace.bootstrap.AgentClassLoading;
1214
import java.io.IOException;
1315
import java.io.InputStream;
@@ -33,7 +35,8 @@ public String[] helperClassNames() {
3335
return new String[] {
3436
"org.jboss.modules.ModuleLinkageHelper",
3537
"org.jboss.modules.ModuleLinkageHelper$1",
36-
"org.jboss.modules.ModuleLinkageHelper$2"
38+
"org.jboss.modules.ModuleLinkageHelper$2",
39+
packageName + ".ModuleNameHelper",
3740
};
3841
}
3942

@@ -60,6 +63,7 @@ public void methodAdvice(MethodTransformer transformer) {
6063
.and(takesArgument(0, String.class))
6164
.and(takesArgument(1, boolean.class)))),
6265
ModuleInstrumentation.class.getName() + "$WidenLoadClassAdvice");
66+
transformer.applyAdvice(isConstructor(), getClass().getName() + "$CaptureModuleNameAdvice");
6367
}
6468

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

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

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,15 @@
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;
19+
import datadog.trace.api.Config;
1720
import datadog.trace.api.CorrelationIdentifier;
1821
import datadog.trace.api.GlobalTracer;
1922
import datadog.trace.api.gateway.Flow;
23+
import datadog.trace.api.naming.ClassloaderServiceNames;
2024
import datadog.trace.bootstrap.ActiveSubsystems;
2125
import datadog.trace.bootstrap.ContextStore;
2226
import datadog.trace.bootstrap.InstrumentationContext;
@@ -104,7 +108,18 @@ public static class HandleRequestAdvice {
104108
request.setAttribute(DD_EXTRACTED_CONTEXT_ATTRIBUTE, extractedContext);
105109
final AgentSpan span = DECORATE.startSpan(request, extractedContext);
106110
scope = activateSpan(span, true);
107-
111+
if (Config.get().isJeeSplitByDeployment()) {
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, cl);
119+
}
120+
}
121+
}
122+
}
108123
DECORATE.afterStart(span);
109124
DECORATE.onRequest(span, request, request, extractedContext);
110125
request.setAttribute(DD_SPAN_ATTRIBUTE, span);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
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+
final String name = BundleNameHelper.extractDeploymentName(self);
42+
if (name != null && !name.isEmpty()) {
43+
ClassloaderServiceNames.addServiceName(self, name);
44+
}
45+
}
46+
}
47+
}

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: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,15 @@
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;
19+
import datadog.trace.api.Config;
1720
import datadog.trace.api.CorrelationIdentifier;
1821
import datadog.trace.api.GlobalTracer;
1922
import datadog.trace.api.gateway.Flow;
23+
import datadog.trace.api.naming.ClassloaderServiceNames;
2024
import datadog.trace.bootstrap.ActiveSubsystems;
2125
import datadog.trace.bootstrap.ContextStore;
2226
import datadog.trace.bootstrap.InstrumentationContext;
@@ -106,7 +110,18 @@ public static class HandleRequestAdvice {
106110
request.setAttribute(DD_EXTRACTED_CONTEXT_ATTRIBUTE, extractedContext);
107111
final AgentSpan span = DECORATE.startSpan(request, extractedContext);
108112
scope = activateSpan(span, true);
109-
113+
if (Config.get().isJeeSplitByDeployment()) {
114+
final IWebAppDispatcherContext dispatcherContext = request.getWebAppDispatcherContext();
115+
if (dispatcherContext != null) {
116+
final WebApp webapp = dispatcherContext.getWebApp();
117+
if (webapp != null) {
118+
final ClassLoader cl = webapp.getClassLoader();
119+
if (cl != null) {
120+
ClassloaderServiceNames.maybeSetToSpan(span, cl);
121+
}
122+
}
123+
}
124+
}
110125
DECORATE.afterStart(span);
111126
DECORATE.onRequest(span, request, request, extractedContext);
112127
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: 3 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,8 @@ 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(span);
4245
// Tracing might already be applied by the FilterChain or a parent request (forward/include).
4346
return false;
4447
}

0 commit comments

Comments
 (0)