Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

creating Opentelemetry Context using trace-id and span-id of remote parent

I have micro service which support open tracing and that injecting trace-id and span-id in to header. Other micro service support open telemetry. how can I create parent span using trace-id and span-id in second micro service?

Thanks,

like image 354
techzone4all Avatar asked Sep 07 '25 23:09

techzone4all


1 Answers

You can use W3C Trace Context specifications to achieve this. We need to send traceparent(Ex: 00-8652a752089f33e2659dff28d683a18f-7359b90f4355cfd9-01) from producer via HTTP headres ( or you can create it using the trace-id and span-id in the consumer). Then we can extract the remote context and create the span with traceparent.

This is the consumer controller. TextMapGetter used to map that traceparent data to the Context. ExtractModel is just a custom class.

  @GetMapping(value = "/second")
  public String sencondTest(@RequestHeader(value = "traceparent") String traceparent){
    try {
      Tracer tracer = openTelemetry.getTracer("cloud.events.second");

      TextMapGetter<ExtractModel> getter = new TextMapGetter<>() {
        @Override
        public String get(ExtractModel carrier, String key) {
          if (carrier.getHeaders().containsKey(key)) {
            return carrier.getHeaders().get(key);
          }
          return null;
        }

        @Override
        public Iterable<String> keys(ExtractModel carrier) {
          return carrier.getHeaders().keySet();
        }
      };

      ExtractModel model = new ExtractModel();
      model.addHeader("traceparent", traceparent);
      Context extractedContext = openTelemetry.getPropagators().getTextMapPropagator()
              .extract(Context.current(), model, getter);

      try (Scope scope = extractedContext.makeCurrent()) {
        // Automatically use the extracted SpanContext as parent.
        Span serverSpan = tracer.spanBuilder("CloudEvents Server")
                .setSpanKind(SpanKind.SERVER)
                .startSpan();
        try {

          Thread.sleep(150);
        } finally {
          serverSpan.end();
        }
      }

    } catch (InterruptedException e) {
      throw new RuntimeException(e);
    }

    return "Server Received!";
  }

Then when we configuring the OpenTelemetrySdk need to set W3CTraceContextPropagator in Context Propagators.

// Use W3C Propagator(to extract span from HTTP headers) since we use the W3C specifications
TextMapPropagator textMapPropagator = W3CTraceContextPropagator.getInstance();

OpenTelemetrySdk openTelemetrySdk = OpenTelemetrySdk.builder()
        .setTracerProvider(tracerProvider)
        .setPropagators(ContextPropagators.create(textMapPropagator))
        .buildAndRegisterGlobal();

Here is my customer ExtractModel class

public class ExtractModel {

  private Map<String, String> headers;

  public void addHeader(String key, String value) {
    if (this.headers == null){
      headers = new HashMap<>();
    }
    headers.put(key, value);
  }

  public Map<String, String> getHeaders() {
    return headers;
  }

  public void setHeaders(Map<String, String> headers) {
    this.headers = headers;
  }
}

You can find more details in the official documentation for manual instrumentation.

like image 180
Prabhash Karunathilaka Avatar answered Sep 11 '25 02:09

Prabhash Karunathilaka