open-telemetry / open-telemetry/opentelemetry-cpp
Issue: ETW Exporter Tracer Uses a Single Trace ID for All Spans
Nobody has claimed this yet.
- 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.
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");
}
}
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
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- 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