/** * Implementation of DeterministicIdGenerator and PendingTraceId. * * The pending trace_id lives in file-local thread_locals shared between the * generator and the RAII guard. GenerateTraceId() consumes the pending id on * the SDK's no-parent branch; PendingTraceId sets it and asserts consumption. * All OpenTelemetry SDK types stay confined to telemetry translation units. * * @see DeterministicIdGenerator, PendingTraceId (DeterministicIdGenerator.h) */ #ifdef XRPL_ENABLE_TELEMETRY #include #include #include #include #include #include #include #include #include #include namespace xrpl::telemetry { namespace { /** * Trace_id pinned by PendingTraceId, consumed by GenerateTraceId(). File-local * and thread-local, so it is set and read on the same thread with no locking. */ thread_local std::optional> gTlsPendingTraceId; /** * True once GenerateTraceId() has consumed the pending id. ~PendingTraceId * asserts on it to catch a forced-root span that never reached the SDK root * branch. */ thread_local bool gTlsPendingConsumed = false; } // namespace DeterministicIdGenerator::DeterministicIdGenerator() : opentelemetry::sdk::trace::IdGenerator(/*is_random=*/false) , random_(opentelemetry::sdk::trace::RandomIdGeneratorFactory::Create()) { } opentelemetry::trace::TraceId DeterministicIdGenerator::GenerateTraceId() noexcept { if (gTlsPendingTraceId) { auto const id = *gTlsPendingTraceId; gTlsPendingTraceId.reset(); gTlsPendingConsumed = true; return opentelemetry::trace::TraceId( opentelemetry::nostd::span(id.data(), 16)); } return random_->GenerateTraceId(); } opentelemetry::trace::SpanId DeterministicIdGenerator::GenerateSpanId() noexcept { return random_->GenerateSpanId(); // ALWAYS random — never uses the pending id } PendingTraceId::PendingTraceId(std::array const& id) noexcept { gTlsPendingTraceId = id; gTlsPendingConsumed = false; } PendingTraceId::~PendingTraceId() noexcept { // The forced no-parent (root) span-start MUST have consumed the pending id // via GenerateTraceId(). If not, the SDK took a different branch than the // caller forced — a bug — so fail loudly in debug/test builds. XRPL_ASSERT( gTlsPendingConsumed, "xrpl::telemetry::PendingTraceId : deterministic trace_id was not consumed"); gTlsPendingTraceId.reset(); // never leak, even in release gTlsPendingConsumed = false; } } // namespace xrpl::telemetry #endif // XRPL_ENABLE_TELEMETRY