Summary
The component mixes two fundamentally different kinds of code: patches that make upstream third-party libraries compile on Xtensa/ESP-IDF (workarounds), and purposeful ESP32 adaptations that are part of the integration's value (features). These should live in clearly labelled subtrees. The README should then list each workaround and each integration as a first-class item, alongside an explicit inventory of which upstream OTel C++ SDK features have been tested — each backed by a dedicated example.
Current structure
src/
esp_heap_align.cpp — operator new/delete aligned to alignof(max_align_t)
esp_posix_shims.c — nanosleep, pthread_atfork, sysconf, THREADPTR pre-init
esp_http_client_transport.cpp — esp_http_client-backed OTLP HTTP transport
esp_opentelemetry.cpp — user-facing setup facade
shims/
absl_encode_varint_bool_fix.h — EncodeVarint overload ambiguity fix (Xtensa GCC 13.2)
sys/mman.h — mmap/munmap backed by malloc (Abseil LowLevelAlloc)
time.h — tm_gmtoff macro for Abseil cctz
Everything is flattened together. A reader cannot tell at a glance which files exist because of upstream bugs / toolchain gaps, and which ones represent deliberate design choices that will still be relevant after the upstream is updated.
Proposed directory split
src/
workarounds/
heap_align.cpp — currently esp_heap_align.cpp
posix_shims.c — currently esp_posix_shims.c
absl_varint_bool.h — currently shims/absl_encode_varint_bool_fix.h
mman.h — currently shims/sys/mman.h
time_gmtoff.h — currently shims/time.h
integration/
esp_http_client_transport.cpp / .hpp
esp_opentelemetry.cpp
include/
esp_opentelemetry.hpp — unchanged public API
The workarounds/ subtree contains everything that exists purely to paper over an upstream deficiency. Each file should carry a one-line comment giving the upstream issue / GCC version / ESP-IDF version that necessitates it, making future removal straightforward.
The integration/ subtree contains code that is deliberately ESP32-specific and is part of the component's defined scope.
No public API changes; CMakeLists.txt and Kconfig are updated to reflect the new paths.
Documentation
The README should gain three explicit sections:
Workarounds
A table listing every workaround, the root cause it addresses, and the upstream component it targets. Example shape:
| File |
Root cause |
Upstream |
workarounds/heap_align.cpp |
ESP32-S3 heap_caps_aligned_alloc required for alignof(max_align_t)==8; plain malloc returns 4-byte-aligned blocks, corrupting protobuf's TaggedAllocationPolicyPtr |
protobuf, Abseil |
workarounds/posix_shims.c |
nanosleep missing from newlib; pthread_atfork missing (causes libnosys collision); sysconf(_SC_PAGESIZE) returns -1 (causes Abseil LowLevelAlloc overflow); THREADPTR uninitialised before FreeRTOS scheduler (crashes thread_local accesses during global constructors) |
Abseil, ESP-IDF newlib |
workarounds/absl_varint_bool.h |
int32_t is long not int on Xtensa; bool/int/pid_t do not match any EncodeVarint overload — ambiguous call on GCC 13.2 |
Abseil |
workarounds/mman.h |
sys/mman.h absent from newlib; Abseil LowLevelAlloc calls mmap to grow its arena |
Abseil |
workarounds/time_gmtoff.h |
struct tm in newlib lacks tm_gmtoff; Abseil cctz includes it unconditionally |
Abseil cctz |
ESP-specific integrations
A table of purposeful integrations:
| File |
What it provides |
integration/esp_http_client_transport.cpp |
HttpClientFactory backed by esp_http_client, replacing libcurl for the OTLP/HTTP exporter |
integration/esp_opentelemetry.cpp |
esp_opentelemetry_setup() / esp_opentelemetry_tracer() — ESP-friendly wiring of exporter, processor, resource, and W3C propagator via Kconfig |
Tested OTel C++ SDK features
An explicit list of which upstream SDK features have been validated on ESP32 hardware or QEMU, and which are untested / known not to work:
| Feature |
Status |
Example |
OStreamSpanExporter |
Tested (QEMU) |
examples/ostream/ |
SimpleSpanProcessor |
Tested (QEMU) |
examples/ostream/ |
BatchSpanProcessor |
Tested (hardware, ESP32-S3) |
examples/batch/ |
OtlpHttpExporter (JSON) |
Tested (hardware, ESP32-S3) |
examples/batch/ |
| W3C TraceContext propagation (inject) |
Tested (hardware) |
examples/propagation/ |
Span attributes (SetAttribute) |
Tested |
covered by existing examples |
Span events (AddEvent) |
Untested |
— |
OtlpHttpExporter (protobuf) |
Untested |
— |
| Metrics API |
Not integrated |
— |
| Logs API |
Not integrated |
— |
Per-feature examples
Currently examples/simple/ and examples/batch/ each demonstrate a combination of features rather than isolating one. The goal is one example per feature, named after what it demonstrates:
| Example |
Feature demonstrated |
Hardware needed |
examples/ostream/ |
OStreamSpanExporter + SimpleSpanProcessor; printout to serial |
None (QEMU) |
examples/batch/ |
BatchSpanProcessor + OtlpHttpExporter; Wi-Fi setup, PSRAM thread stack |
Wi-Fi |
examples/propagation/ |
W3C TraceContext inject/extract across an HTTP boundary |
Wi-Fi |
examples/ostream/ is a rename/copy of the current examples/simple/ with no code changes. The remaining examples follow the same pattern and need to be written.
Acceptance criteria
Summary
The component mixes two fundamentally different kinds of code: patches that make upstream third-party libraries compile on Xtensa/ESP-IDF (workarounds), and purposeful ESP32 adaptations that are part of the integration's value (features). These should live in clearly labelled subtrees. The README should then list each workaround and each integration as a first-class item, alongside an explicit inventory of which upstream OTel C++ SDK features have been tested — each backed by a dedicated example.
Current structure
Everything is flattened together. A reader cannot tell at a glance which files exist because of upstream bugs / toolchain gaps, and which ones represent deliberate design choices that will still be relevant after the upstream is updated.
Proposed directory split
The
workarounds/subtree contains everything that exists purely to paper over an upstream deficiency. Each file should carry a one-line comment giving the upstream issue / GCC version / ESP-IDF version that necessitates it, making future removal straightforward.The
integration/subtree contains code that is deliberately ESP32-specific and is part of the component's defined scope.No public API changes;
CMakeLists.txtand Kconfig are updated to reflect the new paths.Documentation
The README should gain three explicit sections:
Workarounds
A table listing every workaround, the root cause it addresses, and the upstream component it targets. Example shape:
workarounds/heap_align.cppheap_caps_aligned_allocrequired foralignof(max_align_t)==8; plainmallocreturns 4-byte-aligned blocks, corrupting protobuf'sTaggedAllocationPolicyPtrworkarounds/posix_shims.cnanosleepmissing from newlib;pthread_atforkmissing (causes libnosys collision);sysconf(_SC_PAGESIZE)returns -1 (causes AbseilLowLevelAllocoverflow); THREADPTR uninitialised before FreeRTOS scheduler (crashesthread_localaccesses during global constructors)workarounds/absl_varint_bool.hint32_tislongnotinton Xtensa;bool/int/pid_tdo not match anyEncodeVarintoverload — ambiguous call on GCC 13.2workarounds/mman.hsys/mman.habsent from newlib; AbseilLowLevelAlloccallsmmapto grow its arenaworkarounds/time_gmtoff.hstruct tmin newlib lackstm_gmtoff; Abseil cctz includes it unconditionallyESP-specific integrations
A table of purposeful integrations:
integration/esp_http_client_transport.cppHttpClientFactorybacked byesp_http_client, replacing libcurl for the OTLP/HTTP exporterintegration/esp_opentelemetry.cppesp_opentelemetry_setup()/esp_opentelemetry_tracer()— ESP-friendly wiring of exporter, processor, resource, and W3C propagator via KconfigTested OTel C++ SDK features
An explicit list of which upstream SDK features have been validated on ESP32 hardware or QEMU, and which are untested / known not to work:
OStreamSpanExporterexamples/ostream/SimpleSpanProcessorexamples/ostream/BatchSpanProcessorexamples/batch/OtlpHttpExporter(JSON)examples/batch/examples/propagation/SetAttribute)AddEvent)OtlpHttpExporter(protobuf)Per-feature examples
Currently
examples/simple/andexamples/batch/each demonstrate a combination of features rather than isolating one. The goal is one example per feature, named after what it demonstrates:examples/ostream/OStreamSpanExporter+SimpleSpanProcessor; printout to serialexamples/batch/BatchSpanProcessor+OtlpHttpExporter; Wi-Fi setup, PSRAM thread stackexamples/propagation/examples/ostream/is a rename/copy of the currentexamples/simple/with no code changes. The remaining examples follow the same pattern and need to be written.Acceptance criteria
src/is reorganised intoworkarounds/andintegration/subtrees; build and CI are unaffected.examples/.CMakeLists.txt,sdkconfig.defaults, and a short README explaining what to observe.