I'm using the Elastic APM Agent as a Java Agent to monitor usages of various methods in my spring boot microservice. This all works fine and we're able to graph various metrics in Kibana. Unfortunately what it doesn't do is consistently attach the same labels to all spans within a transaction e.g. details of the user who made the original request.
To work around this I thought I could use ByteBuddy (which I've never used before) to wrap any usages of the APM Span class and attach that information (as it's readily available from ThreadLocal) to each instance. I am however having issues accessing the Span class as it's in the APM Java Agent and with the following code I get the following logs where it appears that it's not able to find the Span class...
Instrumentation instrumentation = ByteBuddyAgent.install();
new AgentBuilder.Default()
.with(debuggingListener)
.ignore(ElementMatchers.nameStartsWith("net.bytebuddy."))
.type(ElementMatchers.named("co.elastic.apm.agent.impl.transaction.Span"), ElementMatchers.isBootstrapClassLoader())
.transform((builder, type, classLoader, module) -> builder.visit(Advice.to(SpanAdvice.class).on(ElementMatchers.hasMethodName("start"))))
.installOn(instrumentation);
[Byte Buddy] DISCOVERY co.elastic.apm.agent.impl.transaction.Transaction [null, unnamed module @758a34ce, loaded=false]
[Byte Buddy] IGNORE co.elastic.apm.agent.impl.transaction.Transaction [null, unnamed module @758a34ce, loaded=false]
[Byte Buddy] COMPLETE co.elastic.apm.agent.impl.transaction.Transaction [null, unnamed module @758a34ce, loaded=false]
[Byte Buddy] DISCOVERY co.elastic.apm.agent.impl.transaction.Transaction$1 [null, unnamed module @758a34ce, loaded=false]
[Byte Buddy] IGNORE co.elastic.apm.agent.impl.transaction.Transaction$1 [null, unnamed module @758a34ce, loaded=false]
[Byte Buddy] COMPLETE co.elastic.apm.agent.impl.transaction.Transaction$1 [null, unnamed module @758a34ce, loaded=false]
[Byte Buddy] DISCOVERY co.elastic.apm.agent.impl.transaction.AbstractSpan$ChildDurationTimer [null, unnamed module @758a34ce, loaded=false]
[Byte Buddy] IGNORE co.elastic.apm.agent.impl.transaction.AbstractSpan$ChildDurationTimer [null, unnamed module @758a34ce, loaded=false]
[Byte Buddy] COMPLETE co.elastic.apm.agent.impl.transaction.AbstractSpan$ChildDurationTimer [null, unnamed module @758a34ce, loaded=false]
[Byte Buddy] DISCOVERY co.elastic.apm.agent.impl.transaction.SpanCount [null, unnamed module @758a34ce, loaded=false]
[Byte Buddy] IGNORE co.elastic.apm.agent.impl.transaction.SpanCount [null, unnamed module @758a34ce, loaded=false]
[Byte Buddy] COMPLETE co.elastic.apm.agent.impl.transaction.SpanCount [null, unnamed module @758a34ce, loaded=false]
[Byte Buddy] DISCOVERY co.elastic.apm.agent.impl.transaction.TraceState$TextTracestateAppender [null, unnamed module @758a34ce, loaded=false]
[Byte Buddy] IGNORE co.elastic.apm.agent.impl.transaction.TraceState$TextTracestateAppender [null, unnamed module @758a34ce, loaded=false]
[Byte Buddy] COMPLETE co.elastic.apm.agent.impl.transaction.TraceState$TextTracestateAppender [null, unnamed module @758a34ce, loaded=false]
I've tried using ByteBuddy for my own classes and it all works without issue, but I'm getting very confused around which classloader has loaded what and how to point ByteBuddy at them.