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

Signed-off-by: Pratik Mankawde <3397372+pratikmankawde@users.noreply.github.com>
This commit is contained in:
Pratik Mankawde
2026-05-27 16:57:08 +01:00
4 changed files with 29 additions and 17 deletions

View File

@@ -36,7 +36,8 @@ such as Grafana Tempo.
Telemetry is **off by default** at both compile time and runtime:
- **Compile time**: The Conan option `telemetry` and CMake option `telemetry` must be set to `True`/`ON`.
When disabled, all tracing macros compile to `((void)0)` with zero overhead.
When disabled, all `SpanGuard` calls compile to inline no-ops (defined in `SpanGuard.h`)
with zero overhead — no OTel SDK dependency required.
- **Runtime**: The `[telemetry]` config section must set `enabled=1`.
When disabled at runtime, a no-op implementation is used.

View File

@@ -15,7 +15,6 @@
// Add new amendments to the top of this list.
// Keep it sorted in reverse chronological order.
XRPL_FIX (Cleanup3_2_0, Supported::no, VoteBehavior::DefaultNo)
XRPL_FEATURE(MPTokensV2, Supported::no, VoteBehavior::DefaultNo)
XRPL_FIX (Security3_1_3, Supported::no, VoteBehavior::DefaultNo)
XRPL_FIX (PermissionedDomainInvariant, Supported::yes, VoteBehavior::DefaultNo)

View File

@@ -35,19 +35,18 @@
Usage examples:
1. Check before tracing (typical guard pattern):
1. Root span at a subsystem entry point (typical usage):
@code
auto& telemetry = registry.getTelemetry();
if (telemetry.isEnabled() && telemetry.shouldTraceRpc())
{
auto span = telemetry.startSpan("rpc.command.server_info");
// ... do work, span ends when shared_ptr refcount drops to 0
}
// In an RPC handler dispatch:
auto guard = SpanGuard::span(TraceCategory::Rpc, "rpc", commandName);
guard.setAttribute("xrpl.rpc.command", commandName);
// ... process request
// guard destructor automatically ends the span on scope exit
@endcode
2. RAII tracing with SpanGuard (preferred):
2. Child span for a sub-operation (cross-scope):
@code
if (telemetry.isEnabled() && telemetry.shouldTraceRpc())
auto parent = SpanGuard::span(TraceCategory::Transactions, "tx", "process");
{
SpanGuard guard(telemetry.startSpan("rpc.command.submit"));
guard.setAttribute("command", "submit");
@@ -55,12 +54,24 @@
}
@endcode
3. Cross-thread context propagation:
3. Child span for a sub-operation (cross-scope):
@code
// On thread A: capture context
auto ctx = guard.context();
// On thread B: create child span with explicit parent
auto child = telemetry.startSpan("async.work", ctx);
auto parent = SpanGuard::span(TraceCategory::Transactions, "tx", "process");
{
auto child = parent.childSpan("tx.apply");
child.setAttribute("xrpl.tx.type", txType);
// child ends here
}
// parent continues, then ends here
@endcode
4. Cross-thread context propagation:
@code
// Thread A: capture the active context while span is in scope
auto ctx = parentGuard.captureContext();
// Thread B: create child span with explicit parent
auto child = SpanGuard::childSpan("async.work", ctx);
@endcode
@note Thread safety: The Telemetry interface is safe for concurrent reads

View File

@@ -36,6 +36,7 @@
#include <opentelemetry/trace/tracer.h>
#include <string>
#include <typeinfo>
#include <utility>
namespace xrpl {
@@ -332,7 +333,7 @@ SpanGuard::recordException(std::exception const& e)
return;
impl_->span->AddEvent(
"exception",
{{"exception.type", "std::exception"}, {"exception.message", std::string(e.what())}});
{{"exception.type", typeid(e).name()}, {"exception.message", std::string(e.what())}});
impl_->span->SetStatus(otel_trace::StatusCode::kError, e.what());
}