I have created an Open Telemetry instrument extension (following this) to trace all method call to any interfaces in a package. However the interface method is not traced by OTEL.
This is the InstrumentationModule class:
@AutoService(InstrumentationModule.class)
public class JMoquiInterfacesInstrumentationModule extends InstrumentationModule {
protected final static Logger logger = LoggerFactory.getLogger(JMoquiInterfacesInstrumentationModule.class);
public JMoquiInterfacesInstrumentationModule() {
super("jmoqui-demo", "jmoqui-99");
logger.info("JMoquiInterfacesInstrumentationModule instantiated");
}
/*
We want this instrumentation to be applied after the standard servlet instrumentation.
The latter creates a server span around http request.
This instrumentation needs access to that server span.
*/
@Override
public int order() {
return 1;
}
@Override
public ElementMatcher.Junction<ClassLoader> classLoaderMatcher() {
return AgentElementMatchers.hasClassesNamed("org.moqui.Moqui");
}
@Override
public List<TypeInstrumentation> typeInstrumentations() {
return singletonList(new JMoquiInterfacesInstrumentation());
}
}
And this is the custom TypeInstrumentation class:
public class JMoquiInterfacesInstrumentation implements TypeInstrumentation {
protected final static Logger logger = LoggerFactory.getLogger(JMoquiInterfacesInstrumentation.class);
@Override
public ElementMatcher<TypeDescription> typeMatcher() {
logger.info("typeMatcher");
return AgentElementMatchers.implementsInterface(
new NameMatcher<>(new StringMatcher("org.moqui", StringMatcher.Mode.STARTS_WITH) {
@Override
protected boolean doMatch(String target) {
boolean match = super.doMatch(target);
if (match) logger.info("doMatch, match: {}", target);
return match;
}
})
);
}
@Override
public void transform(TypeTransformer typeTransformer) {
logger.info("transform");
typeTransformer.applyAdviceToMethod(
any(),
this.getClass().getName() + "$JMoquiItfAdvice");
}
@SuppressWarnings("unused")
public static class JMoquiItfAdvice {
protected final static Logger logger = LoggerFactory.getLogger(JMoquiItfAdvice.class);
private static final Tracer tracer = GlobalOpenTelemetry.getTracer("method-call-tracer");
@Advice.OnMethodEnter
public static void onEnter(@Advice.Origin String method) {
logger.info("onEnter: {}", method);
Span span = tracer.spanBuilder(method).startSpan();
span.makeCurrent();
}
@Advice.OnMethodExit(onThrowable = Throwable.class)
public static void onExit(@Advice.Thrown Throwable throwable) {
Span span = Span.current();
if (throwable != null) {
span.recordException(throwable);
}
logger.info("onExit");
span.end();
}
}
}
However the onEnter
and onExit
never printed. After activating otel debug, this WARN showed:
00:35:03.651 [main] INFO com.example.javaagent.instrumentation.JMoquiInterfacesInstrumentation -- doMatch, match: org.moqui.context.L10nFacade
00:35:03.651 [main] INFO com.example.javaagent.instrumentation.JMoquiInterfacesInstrumentation -- doMatch, match: org.moqui.context.LogEventSubscriber
[otel.javaagent 2024-07-15 00:35:03:636 +0800] [main] WARN io.opentelemetry.javaagent.tooling.instrumentation.MuzzleMatcher - Instrumentation skipped, mismatched references were found: jmoqui-demo [class com.example.javaagent.instrumentation.JMoquiInterfacesInstrumentationModule] on jdk.internal.loader.ClassLoaders$AppClassLoader@76ed5528
[otel.javaagent 2024-07-15 00:35:03:636 +0800] [main] WARN io.opentelemetry.javaagent.tooling.instrumentation.MuzzleMatcher - -- com.example.javaagent.instrumentation.JMoquiInterfacesInstrumentation$JMoquiItfAdvice:0 Missing class com.example.javaagent.instrumentation.JMoquiInterfacesInstrumentation$JMoquiItfAdvice
00:35:03.667 [main] INFO com.example.javaagent.instrumentation.JMoquiInterfacesInstrumentation -- doMatch, match: org.moqui.context.LoggerFacade
00:35:03.667 [main] INFO com.example.javaagent.instrumentation.JMoquiInterfacesInstrumentation -- doMatch, match: org.moqui.context.MessageFacade
The logs from JMoquiInterfacesInstrumentation
are correctly shown, however JMoquiInterfacesInstrumentation.JMoquiItfAdvice class is reported missing.
The questions are:
- How to fix the missing class?
- The “method-call-tracer” on JMoquiItfAdvice is copied over from the example. How does “method-call-tracer” suddenly exists, what does it signifies?
private static final Tracer tracer = GlobalOpenTelemetry.getTracer("method-call-tracer");