Skip to content

java jni invoke tracing #7116

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
fidoooooowang opened this issue Feb 14, 2025 · 5 comments
Open

java jni invoke tracing #7116

fidoooooowang opened this issue Feb 14, 2025 · 5 comments

Comments

@fidoooooowang
Copy link

What are you trying to achieve?

I have a doubt now. Suppose I use jni in a Java program to call a c++ sdk written by myself. At the same time, the relevant opentelemetry SDK is connected to the Java application and C++ SDK to report trace data. How can I combine the span generated in the Java program with the span generated in the C++ program? I don't really want to use the method of passing parameters to transparently pass the traceId and spanId generated in the Java program to the c++ sdk. Is there any other way?

Additional context.

Add any other context about the problem here. If you followed an existing documentation, please share the link to it.

@svrnm svrnm transferred this issue from open-telemetry/opentelemetry-specification Feb 17, 2025
@svrnm
Copy link
Member

svrnm commented Feb 17, 2025

Hey @open-telemetry/java-maintainers, can you take a look here please? Is this something that the Java implementation of OpenTelemetry is already addressing and you can provide @fidoooooowang with some guidance around it? Or is this something you think is more generic (if we swap out Java + C++ here for any other language), and it needs to be treated at the spec level?

@trask
Copy link
Member

trask commented Feb 18, 2025

hi @fidoooooowang! you might find https://www.elastic.co/observability-labs/blog/continuous-profiling-distributed-tracing-correlation interesting, particularly this part:

The OTel Java agent itself keeps track of the active span by storing a stack of spans in the OpenTelemetryContext, which itself is stored in a ThreadLocal variable. We originally considered reading these Java structures directly from BPF, but we eventually decided against that approach. There is no documented specification on how ThreadLocals are implemented, and reliably reading and following the JVM's internal data-structures would incur a high maintenance burden. Any minor update to the JVM could change details of the structure layouts. To add to this, we would also have to reverse engineer how each JVM version lays out Java class fields in memory, as well as how all the high-level Java types used in the context objects are actually implemented under the hood. This approach further wouldn't generalize to any non-JVM language and needs to be repeated for any language that we wish to support.

After we had convinced ourselves that reading Java ThreadLocal directly is not the answer, we decided to look for more portable alternatives instead. The option that we ultimately settled with is to load and call into a C++ library that is responsible for making the required information available via a known and defined interface whenever the span changes.

(cc @JonasKunz)

@JonasKunz
Copy link
Contributor

JonasKunz commented Feb 18, 2025

You can find the relevant code for the blogpsot linked by @trask here and here.

However, if you control the JNI layer or have access to a JNIEnv from you cpp code I'd recommend to do the following:

  • Pass in the current java Otel-context as additional parameter to your JNI calls and translate it to an otel-cpp context there
  • Because you said you don't like the above method, Id' use JNIEnv to call java Context.current() when needed and translate it to a cpp otel context

I think those approaches are much simpler, but weren't applicable in our eBPF-usecase.

@fidoooooowang
Copy link
Author

fidoooooowang commented Feb 20, 2025

I'm not familiar with c++ and it's my first time trying to use jni. After briefly reading the solution provided above, can I understand, assuming that my Java service call calls c++ sdk through jni, if the Java service uses elastic-otel-java's javaagnet. The c++ sdk uses opentelemetry-sdk. I can set some variables through the JvmtiAccess class in the Java service. Can I access these data in the c++ sdk and then use it to create a trace event? Is there any relevant c++ demo? Is my understanding correct? @JonasKunz

@JonasKunz
Copy link
Contributor

No, I don't think you should be using the elastic Otel distro just because of you C++ use-case. I was just pointing to the code for you to get some inspiration on how to solve your problem.

I think the best thing for you to do would be too lookup how to invoke Java from JNI (via JNIEnv). Then play around and try to invoke the Opentelemetry java Context.current() method to get the current trace-ID from C++.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants