All Products
Search
Document Center

Application Real-Time Monitoring Service:Use the OpenTelemetry SDK for Java to pass the cross-process context

Last Updated:Jan 06, 2025

After you integrate the Application Monitoring sub-service of Application Real-Time Monitoring Service (ARMS) to monitor applications that use common Java frameworks, the ARMS agent automatically instruments the frameworks. This way, traces are collected without the need to modify your code. However, if you want to pass the cross-process context, you can install the OpenTelemetry SDK for Java.

For information about the components and frameworks supported by the ARMS agent, see Java components and frameworks supported by ARMS.

Scenarios

When a proprietary protocol is used for cross-process communication, the client and server may not be connected in the trace. In such a case, you must manually retrieve the trace context on the client side, including the trace ID, span ID, sample flag, and baggage, then pass the context to the server side.

Prerequisites

Add dependencies

Add the following Maven dependencies to introduce OpenTelemetry SDK for Java. For more information, see Instrumentation.

<dependencies>
    <dependency>
    <groupId>io.opentelemetry</groupId>
    <artifactId>opentelemetry-api</artifactId>
    </dependency>
    <dependency>
    <groupId>io.opentelemetry</groupId>
    <artifactId>opentelemetry-sdk-trace</artifactId>
    </dependency>
    <dependency>
    <groupId>io.opentelemetry</groupId>
    <artifactId>opentelemetry-sdk</artifactId>
    </dependency>
</dependencies>

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>io.opentelemetry</groupId>
      <artifactId>opentelemetry-bom</artifactId>
      <version>1.23.0</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

Pass the cross-process context

In the following code, CustomRpcCallMessage indicates the entity used for cross-process communication in a proprietary protocol, and uses headerMap to pass the context. If headerMap is missing, manually modify the code to add the headerMap field.

class CustomRpcCallMessage {

    private Map<String, String> headerMap;
    //Omit other fields.

    public String getHeader(String key) {
        return headerMap.get(key);
    }

    public void setHeader(String key, String value) {
        this.headerMap.put(key, value);
    }

    public Map<String, String> getHeaderMap() {
        return headerMap;
    }
}

public class CrossProcessPropagateDemo {
    public static void clientSide(String[] args) {
        CustomRpcCallMessage rpcCall = new CustomRpcCallMessage();
        TextMapSetter<CustomRpcCallMessage> setter = new TextMapSetter<CustomRpcCallMessage>() {
            @Override
            public void set(CustomRpcCallMessage carrier, String key, String value) {
                carrier.setHeader(key, value);
            }
        };
        W3CTraceContextPropagator.getInstance().inject(Context.current(), rpcCall, setter);
        W3CBaggagePropagator.getInstance().inject(Context.current(), rpcCall, setter);
    }

    private static void serverSide() {
        //Receive requests from the server.
        CustomRpcCallMessage rpcCall ;
        TextMapGetter<CustomRpcCallMessage> getter = new TextMapGetter<CustomRpcCallMessage>() {
            @Override
            public Iterable<String> keys(CustomRpcCallMessage carrier) {
                return carrier.getHeaderMap().keySet();
            }

            @Override
            public String get(CustomRpcCallMessage carrier, String key) {
                return carrier.getHeader(key);
            }
        };
        Context context = W3CTraceContextPropagator.getInstance().extract(Context.current(), rpcCall, getter);
        context = W3CBaggagePropagator.getInstance().extract(context, rpcCall, getter);
        try (Scope scope = context.makeCurrent()) {
            //Omit the server processing logic. 
        }
    }
}

In real business scenarios, you need to modify only the implementation classes of the setter and getter variables in the preceding code snippet. This ensures that the set and get methods convey the intended meaning.

Related step

You can associate trace IDs with application logs to promptly locate, analyze, and resolve errors. For more information, see Associate trace IDs with logs for a Java application.