open-telemetry / open-telemetry/opentelemetry-cpp

Issue: ETW Exporter Tracer Uses a Single Trace ID for All Spans

Open
#3,846 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug do-not-stale triage/accepted
Dominant language
C++
Stars
1.4k
Forks
632
Avg merge
1d 13h
Merged PRs (30d)
75

Description

The ETW Exporter provides its own tracer implementation, which inherits from the OpenTelemetry Tracer interface. The relevant code is here:
https://github.com/open-telemetry/opentelemetry-cpp/blob/main/exporters/etw/include/opentelemetry/exporters/etw/etw_tracer.h#L162C28-L163

Expected Behavior (OpenTelemetry C++ SDK)

Using the standard OpenTelemetry SDK, two spans created with the default tracer correctly receive different Trace IDs. Here is the example code used to verify this behavior:

  void TestOTelTracer()
  {
    auto ostream_exporter = opentelemetry::exporter::trace::OStreamSpanExporterFactory::Create();
    auto ostream_processor = opentelemetry::sdk::trace::SimpleSpanProcessorFactory::Create(std::move(ostream_exporter));

    std::vector<std::unique_ptr<opentelemetry::sdk::trace::SpanProcessor>> processors;
    processors.push_back(std::move(ostream_processor));

    auto resource_attributes = opentelemetry::sdk::resource::ResourceAttributes{ {"service.name", "Test OTel"} };
    auto resource_ptr = opentelemetry::sdk::resource::Resource::Create(resource_attributes);

    std::unique_ptr<opentelemetry::sdk::trace::TracerContext> context =
      opentelemetry::sdk::trace::TracerContextFactory::Create(std::move(processors), resource_ptr);

    auto traceProvider = opentelemetry::sdk::trace::TracerProviderFactory::Create(std::move(context));
    auto tracer = traceProvider->GetTracer("OTel-Tracer-Foo");

    {
      auto spanFoo = tracer->StartSpan("Span-Foo");
    }

    {
      auto spanBar = tracer->StartSpan("Span-Bar");
    }
  }

As shown in the screenshot, spans Foo and Bar have distinct Trace IDs, which is the correct behavior.

Image
Actual Behavior (ETW Exporter Tracer)

Using the ETW Exporter Tracer, based on the sample provided here:
https://github.com/open-telemetry/opentelemetry-cpp-contrib/blob/main/exporters/geneva-trace/example/main.cc
Both spans Foo and Bar end up with identical Trace IDs, which is incorrect.

  void TestEtwTracer()
  {
    auto traceProvider = std::make_unique<opentelemetry::exporter::etw::TracerProvider>();
    auto tracer = traceProvider->GetTracer("Geneva-Tracer-Foo");

    {
      auto spanFoo = tracer->StartSpan("Span-Foo");
    }

    {
      auto spanBar = tracer->StartSpan("Span-Bar");
    }
  }
Image
00000012	Geneva-Tracer-Foo	44052	44428	4	0	02\05\2026-13:25:30:652	{"duration":69100,"env_dt_spanId":"8c8974003664fa4e","env_dt_traceId":"8507dcdc651af34fb8f21152a98e2977","env_name":"Span","env_time":"2026-02-05T21:25:30.652491600Z","kind":1,"name":"Span-Foo","startTime":"2026-02-05T21:25:30.652422500Z","statusCode":0,"statusMessage":"","success":"True","meta":{"provider":"Geneva-Tracer-Foo","event":"Span","time":"2026-02-05T13:25:30.652","cpu":4,"pid":44052,"tid":44428,"channel":11,"tags":"0x1000000"}}
00000013	Geneva-Tracer-Foo	44052	44428	4	0	02\05\2026-13:25:30:652	{"duration":18800,"env_dt_spanId":"b87630b5986e364f","env_dt_traceId":"8507dcdc651af34fb8f21152a98e2977","env_name":"Span","env_time":"2026-02-05T21:25:30.652654800Z","kind":1,"name":"Span-Bar","startTime":"2026-02-05T21:25:30.652636000Z","statusCode":0,"statusMessage":"","success":"True","meta":{"provider":"Geneva-Tracer-Foo","event":"Span","time":"2026-02-05T13:25:30.652","cpu":4,"pid":44052,"tid":44428,"channel":11,"tags":"0x1000000"}}

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with exporters/etw/include/opentelemetry/exporters/etw/etw_tracer.h at the referenced lines, then compare the ETW tracer used by exporters/geneva-trace/example/main.cc with the standard tracer example in the issue. Reproduce the two-span case and verify that Span-Foo and Span-Bar receive distinct Trace IDs while their span data still exports correctly.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
observability-sre
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
54/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.