Merge branch 'pratik/otel-phase1b-telemetry-infra' into pratik/otel-phase1c-rpc-integration

Brings coroutine-aware OTel context storage forward: CoroAwareContextStorage,
its install in Telemetry, ScopedSpanGuard same-store assertion, and the
non-owning ScopedActivation helper.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Pratik Mankawde
2026-07-22 19:49:26 +01:00
6 changed files with 471 additions and 53 deletions

View File

@@ -20,11 +20,13 @@
#include <xrpl/basics/Log.h>
#include <xrpl/beast/utility/Journal.h>
#include <xrpl/telemetry/CoroAwareContextStorage.h>
#include <xrpl/telemetry/DeterministicIdGenerator.h>
#include <xrpl/telemetry/DiscardFlag.h>
#include <xrpl/telemetry/SpanNames.h>
#include <opentelemetry/context/context.h>
#include <opentelemetry/context/runtime_context.h>
#include <opentelemetry/exporters/otlp/otlp_http_exporter_factory.h>
#include <opentelemetry/exporters/otlp/otlp_http_exporter_options.h>
#include <opentelemetry/nostd/shared_ptr.h>
@@ -264,6 +266,13 @@ class TelemetryImpl : public Telemetry
*/
std::shared_ptr<trace_sdk::TracerProvider> sdkProvider_;
/**
* Coroutine-aware runtime-context storage, installed globally so the OTel
* ambient context follows JobQueue coroutines. Held for the process
* lifetime because it must outlive every span (SDK requirement).
*/
opentelemetry::nostd::shared_ptr<opentelemetry::context::RuntimeContextStorage> contextStorage_;
public:
TelemetryImpl(Setup setup, beast::Journal journal) : setup_(std::move(setup)), journal_(journal)
{
@@ -334,6 +343,18 @@ public:
std::move(sampler),
std::make_unique<DeterministicIdGenerator>());
// Install coroutine-aware context storage BEFORE any span is created
// so the OTel ambient context follows JobQueue coroutines across
// yield/resume (fixes wrong-thread scope pop; keeps log-trace
// correlation). Must precede SetTracerProvider and the first span.
// Not reset in stop(): resetting the storage while spans may still
// exist is undefined behaviour (SDK), and by stop() all spans are
// gone, so the storage is simply left installed for process lifetime.
contextStorage_ =
opentelemetry::nostd::shared_ptr<opentelemetry::context::RuntimeContextStorage>(
new CoroAwareContextStorage());
opentelemetry::context::RuntimeContext::SetRuntimeContextStorage(contextStorage_);
// Set as global provider
trace_api::Provider::SetTracerProvider(
opentelemetry::nostd::shared_ptr<trace_api::TracerProvider>(sdkProvider_));