diff --git a/.github/scripts/levelization/results/loops.txt b/.github/scripts/levelization/results/loops.txt index a1b2bcd92e..cf70468e32 100644 --- a/.github/scripts/levelization/results/loops.txt +++ b/.github/scripts/levelization/results/loops.txt @@ -1,6 +1,3 @@ -Loop: xrpl.telemetry xrpld.rpc - xrpld.rpc > xrpl.telemetry - Loop: xrpld.app xrpld.overlay xrpld.app > xrpld.overlay diff --git a/.github/scripts/levelization/results/ordering.txt b/.github/scripts/levelization/results/ordering.txt index adc3de10e4..8c68bf4287 100644 --- a/.github/scripts/levelization/results/ordering.txt +++ b/.github/scripts/levelization/results/ordering.txt @@ -112,6 +112,7 @@ test.csf > xrpl.basics test.csf > xrpld.consensus test.csf > xrpl.json test.csf > xrpl.ledger +test.csf > xrpl.telemetry test.json > test.jtx test.json > xrpl.json test.jtx > test.unit_test @@ -321,6 +322,7 @@ xrpld.rpc > xrpl.rdb xrpld.rpc > xrpl.resource xrpld.rpc > xrpl.server xrpld.rpc > xrpl.shamap +xrpld.rpc > xrpl.telemetry xrpld.rpc > xrpl.tx xrpld.shamap > xrpl.basics xrpld.shamap > xrpld.core diff --git a/include/xrpl/telemetry/DiscardFlag.h b/include/xrpl/telemetry/DiscardFlag.h index b8e7bc4ea7..1bd1f668bb 100644 --- a/include/xrpl/telemetry/DiscardFlag.h +++ b/include/xrpl/telemetry/DiscardFlag.h @@ -1,56 +1,58 @@ #pragma once -/** Thread-local discard signaling between SpanGuard and the span processor. - - SpanGuard::discard() wants to drop a span without sending it to the - exporter. The OTel SDK calls SpanProcessor::OnEnd() synchronously on the - same thread that calls Span::End(), so a thread-local flag set just before - End() and read inside OnEnd() lets FilteringSpanProcessor drop the span - before it enters the batch export queue. - - This side-channel avoids inspecting the Recordable's internals (which vary - by exporter type — SpanData vs OtlpRecordable). - - The flag is a *private* thread-local member of DiscardScope, mutated only by - its constructor and destructor. This gives real access control rather than a - naming convention: no code that includes this header can flip the flag - directly — it can only enter a DiscardScope (which sets and clears the flag - over its own lifetime) and observe the state via DiscardScope::isActive(). - Binding set/clear to a scope also means the flag cannot leak onto the next - span even if End() were to throw. - - Kept in a separate header to avoid transitive include bloat: SpanGuard.h - only needs this signaling, not the full Telemetry.h with BasicConfig/Journal. - - Usage: - @code - // In SpanGuard::discard(): - { - DiscardScope discardScope; // flag set for this scope only - span->End(); // OnEnd() runs synchronously, sees flag - } // flag cleared here, unconditionally - - // In FilteringSpanProcessor::OnEnd(): - if (DiscardScope::isActive()) - return; // drop the span - @endcode - - @note Thread safety: the flag is thread-local, so each thread observes only - its own discard signal — no synchronization is required. - - @see SpanGuard::discard(), FilteringSpanProcessor (Telemetry.cpp) -*/ +/** + * Thread-local discard signaling between SpanGuard and the span processor. + * + * SpanGuard::discard() wants to drop a span without sending it to the + * exporter. The OTel SDK calls SpanProcessor::OnEnd() synchronously on the + * same thread that calls Span::End(), so a thread-local flag set just before + * End() and read inside OnEnd() lets FilteringSpanProcessor drop the span + * before it enters the batch export queue. + * + * This side-channel avoids inspecting the Recordable's internals (which vary + * by exporter type — SpanData vs OtlpRecordable). + * + * The flag is a *private* thread-local member of DiscardScope, mutated only by + * its constructor and destructor. This gives real access control rather than a + * naming convention: no code that includes this header can flip the flag + * directly — it can only enter a DiscardScope (which sets and clears the flag + * over its own lifetime) and observe the state via DiscardScope::isActive(). + * Binding set/clear to a scope also means the flag cannot leak onto the next + * span even if End() were to throw. + * + * Kept in a separate header to avoid transitive include bloat: SpanGuard.h + * only needs this signaling, not the full Telemetry.h with BasicConfig/Journal. + * + * Usage: + * @code + * // In SpanGuard::discard(): + * { + * DiscardScope discardScope; // flag set for this scope only + * span->End(); // OnEnd() runs synchronously, sees flag + * } // flag cleared here, unconditionally + * + * // In FilteringSpanProcessor::OnEnd(): + * if (DiscardScope::isActive()) + * return; // drop the span + * @endcode + * + * @note Thread safety: the flag is thread-local, so each thread observes only + * its own discard signal — no synchronization is required. + * + * @see SpanGuard::discard(), FilteringSpanProcessor (Telemetry.cpp) + */ namespace xrpl::telemetry { -/** RAII guard that marks the current thread's span for discard. - - Sets the thread-local discard flag on construction and clears it on - destruction, so a span ended within the guard's scope is dropped by - FilteringSpanProcessor::OnEnd() while the flag stays confined to that scope. - The flag is private and mutated only here, so no other code can set it. - Non-copyable and non-movable — its sole purpose is the scoped flag lifetime. -*/ +/** + * RAII guard that marks the current thread's span for discard. + * + * Sets the thread-local discard flag on construction and clears it on + * destruction, so a span ended within the guard's scope is dropped by + * FilteringSpanProcessor::OnEnd() while the flag stays confined to that scope. + * The flag is private and mutated only here, so no other code can set it. + * Non-copyable and non-movable — its sole purpose is the scoped flag lifetime. + */ class DiscardScope { public: @@ -71,9 +73,11 @@ public: DiscardScope& operator=(DiscardScope&&) = delete; - /** @return true if the current thread is inside a DiscardScope, i.e. the - span ending now should be dropped rather than exported. Read by - FilteringSpanProcessor::OnEnd(). */ + /** + * @return true if the current thread is inside a DiscardScope, i.e. the + * span ending now should be dropped rather than exported. Read by + * FilteringSpanProcessor::OnEnd(). + */ [[nodiscard]] static bool isActive() noexcept { @@ -81,8 +85,10 @@ public: } private: - /** Thread-local discard flag. Private, so only this class's ctor/dtor can - mutate it; observers use isActive(). One instance per thread. */ + /** + * Thread-local discard flag. Private, so only this class's ctor/dtor can + * mutate it; observers use isActive(). One instance per thread. + */ inline static thread_local bool discarding = false; }; diff --git a/include/xrpl/telemetry/Redaction.h b/include/xrpl/telemetry/Redaction.h index ed84ae2964..3b1e8f67ef 100644 --- a/include/xrpl/telemetry/Redaction.h +++ b/include/xrpl/telemetry/Redaction.h @@ -1,63 +1,65 @@ #pragma once -/** Account-address redaction for telemetry span attributes. - - Path-finding RPC handlers would otherwise emit the caller's raw - account addresses as span attributes. To keep plaintext addresses out - of the telemetry backend, they are hashed at the point of emission. - This header exposes a single pure helper that turns an address into a - short, stable, obfuscated token. - - Data flow: - - handler -> redactAccount(addr) -> span attribute -> OTLP export - - The returned token is the first 16 hex characters (lowercase) of the - SHA-512Half digest of the address. It is deterministic (same address - always maps to the same token) so operators can still correlate spans - for a given account across nodes and restarts. - - The hash is unsalted, so it is obfuscation, not a secrecy guarantee: - XRP account addresses are a public, enumerable set, so a determined - observer with the telemetry stream could rebuild the address->token - mapping. The goal here is to keep plaintext addresses out of traces - and dashboards, not to defend against a precomputation attack. A salt - is intentionally omitted because it would break cross-node/restart - correlation, which is the reason for hashing rather than dropping. - - A second, independent hashing layer runs in the OpenTelemetry - Collector (an `attributes/hash` processor) as defense-in-depth for - any node that emits a raw value. - - @note This function is pure and reentrant: it holds no global state, - performs no I/O, and is safe to call concurrently from any thread. - - Usage example: - @code - #include - using namespace xrpl::telemetry; - - span.setAttribute( - pathfind_span::attr::sourceAccount, redactAccount(src.asString())); - @endcode - - Edge case (empty input yields empty output): - @code - assert(redactAccount("") == ""); - @endcode -*/ +/** + * Account-address redaction for telemetry span attributes. + * + * Path-finding RPC handlers would otherwise emit the caller's raw + * account addresses as span attributes. To keep plaintext addresses out + * of the telemetry backend, they are hashed at the point of emission. + * This header exposes a single pure helper that turns an address into a + * short, stable, obfuscated token. + * + * Data flow: + * + * handler -> redactAccount(addr) -> span attribute -> OTLP export + * + * The returned token is the first 16 hex characters (lowercase) of the + * SHA-512Half digest of the address. It is deterministic (same address + * always maps to the same token) so operators can still correlate spans + * for a given account across nodes and restarts. + * + * The hash is unsalted, so it is obfuscation, not a secrecy guarantee: + * XRP account addresses are a public, enumerable set, so a determined + * observer with the telemetry stream could rebuild the address->token + * mapping. The goal here is to keep plaintext addresses out of traces + * and dashboards, not to defend against a precomputation attack. A salt + * is intentionally omitted because it would break cross-node/restart + * correlation, which is the reason for hashing rather than dropping. + * + * A second, independent hashing layer runs in the OpenTelemetry + * Collector (an `attributes/hash` processor) as defense-in-depth for + * any node that emits a raw value. + * + * @note This function is pure and reentrant: it holds no global state, + * performs no I/O, and is safe to call concurrently from any thread. + * + * Usage example: + * @code + * #include + * using namespace xrpl::telemetry; + * + * span.setAttribute( + * pathfind_span::attr::sourceAccount, redactAccount(src.asString())); + * @endcode + * + * Edge case (empty input yields empty output): + * @code + * assert(redactAccount("") == ""); + * @endcode + */ #include #include namespace xrpl::telemetry { -/** Hash an account address into a short, stable, obfuscated token. - - @param addr The account address to redact (e.g. an r-address). - @return The first 16 lowercase hex characters of sha512Half(addr), - or an empty string when @p addr is empty. -*/ +/** + * Hash an account address into a short, stable, obfuscated token. + * + * @param addr The account address to redact (e.g. an r-address). + * @return The first 16 lowercase hex characters of sha512Half(addr), + * or an empty string when @p addr is empty. + */ [[nodiscard]] std::string redactAccount(std::string_view addr); diff --git a/include/xrpl/telemetry/SpanNames.h b/include/xrpl/telemetry/SpanNames.h index c81d77d692..9bc70a99b1 100644 --- a/include/xrpl/telemetry/SpanNames.h +++ b/include/xrpl/telemetry/SpanNames.h @@ -1,18 +1,19 @@ #pragma once -/** Compile-time string concatenation utility and shared telemetry constants. +/** + * Compile-time string concatenation utility and shared telemetry constants. * * Provides StaticStr — a compile-time string buffer that implicitly * converts to std::string_view — and join() for dot-separated concatenation. * Module-specific span names (e.g. RPC, consensus) live in their respective * modules and build upon these shared primitives. * - * @note These constants are NOT guarded by XRPL_ENABLE_TELEMETRY because + * @note These constants are NOT guarded by XRPL_ENABLE_TELEMETRY because * call sites reference them even when SpanGuard methods are no-ops * (the no-op stubs still accept string_view parameters). The compiler * elides all inline constexpr values whose only uses are in dead code. * - * @note Json::StaticString (jss.h) is a pointer wrapper without + * @note Json::StaticString (jss.h) is a pointer wrapper without * concatenation support. boost::static_string is not constexpr. * StaticStr exists specifically for compile-time dot-join composition. * @@ -37,8 +38,10 @@ namespace xrpl::telemetry { // ===== Compile-time string utility ========================================= -/// Fixed-size character buffer for compile-time string operations. -/// Implicitly converts to std::string_view at zero cost. +/** + * Fixed-size character buffer for compile-time string operations. + * Implicitly converts to std::string_view at zero cost. + */ template struct StaticStr { @@ -60,11 +63,15 @@ struct StaticStr } }; -/// Deduction guide: StaticStr from string literal. +/** + * Deduction guide: StaticStr from string literal. + */ template StaticStr(char const (&)[N]) -> StaticStr; -/// Create a StaticStr from a string literal. +/** + * Create a StaticStr from a string literal. + */ template constexpr auto makeStr(char const (&str)[N]) @@ -72,7 +79,9 @@ makeStr(char const (&str)[N]) return StaticStr(str); } -/// Concatenate two StaticStr values with a dot separator. +/** + * Concatenate two StaticStr values with a dot separator. + */ template constexpr auto join(StaticStr const& lhs, StaticStr const& rhs) @@ -108,27 +117,33 @@ namespace attr { inline constexpr auto networkId = join(join(seg::xrpl, seg::network), makeStr("id")); inline constexpr auto networkType = join(join(seg::xrpl, seg::network), makeStr("type")); -/// Canonical shared attrs (rule 5 — _ underscore form). -/// -/// Per the naming convention header note: shared cross-span attribute -/// keys use the underscore form, reserving the dotted xrpl.. -/// form for resource attributes set on the OTel resource at startup. -/// Defined once here, aliased by domain-specific headers. These are -/// literal underscore-joined names, not dot-joined via `join()`, since -/// `join()` always inserts `.` between its arguments. +/** + * Canonical shared attrs (rule 5 — _ underscore form). + * + * Per the naming convention header note: shared cross-span attribute + * keys use the underscore form, reserving the dotted xrpl.. + * form for resource attributes set on the OTel resource at startup. + * Defined once here, aliased by domain-specific headers. These are + * literal underscore-joined names, not dot-joined via `join()`, since + * `join()` always inserts `.` between its arguments. + */ inline constexpr auto txHash = makeStr("tx_hash"); inline constexpr auto peerId = makeStr("peer_id"); inline constexpr auto ledgerSeq = makeStr("ledger_seq"); -/// Shared close-time attrs — bare names, reused by consensus and ledger. +/** + * Shared close-time attrs — bare names, reused by consensus and ledger. + */ inline constexpr auto closeTime = makeStr("close_time"); inline constexpr auto closeTimeCorrect = makeStr("close_time_correct"); inline constexpr auto closeResolutionMs = makeStr("close_resolution_ms"); -/// Shared validation attrs — reused by the consensus and peer validation -/// spans. Same concept, same key on every span; the span name tells them -/// apart, so neither is emitter-prefixed. `ledgerHash` is a ledger-object -/// property (bare, like ledgerSeq); `fullValidation` is the is-full-validation -/// flag. Never the dotted xrpl. form (reserved for resource attrs). +/** + * Shared validation attrs — reused by the consensus and peer validation + * spans. Same concept, same key on every span; the span name tells them + * apart, so neither is emitter-prefixed. `ledgerHash` is a ledger-object + * property (bare, like ledgerSeq); `fullValidation` is the is-full-validation + * flag. Never the dotted xrpl. form (reserved for resource attrs). + */ inline constexpr auto ledgerHash = makeStr("ledger_hash"); inline constexpr auto fullValidation = makeStr("full_validation"); } // namespace attr diff --git a/include/xrpl/telemetry/Telemetry.h b/include/xrpl/telemetry/Telemetry.h index 8e4b23eb9c..0697e7f39d 100644 --- a/include/xrpl/telemetry/Telemetry.h +++ b/include/xrpl/telemetry/Telemetry.h @@ -1,90 +1,91 @@ #pragma once -/** Abstract interface for OpenTelemetry distributed tracing. - - Provides the Telemetry base class that all components use to create trace - spans. Three concrete implementations exist, selected at construction time - by makeTelemetry(): - - - TelemetryImpl (Telemetry.cpp): real OTel SDK integration, compiled - only when XRPL_ENABLE_TELEMETRY is defined and enabled at runtime. - - NullTelemetry (NullTelemetry.cpp): no-op stub used when telemetry is - disabled at compile time or runtime. - - NullTelemetryOtel (Telemetry.cpp): no-op stub that still depends on - the OTel API (used during transition or for testing). - - Inheritance / dependency diagram: - - +--------------------+ - | Telemetry | (abstract, this file) - | <> | - +---------+----------+ - | - +---------+-----------+-------------------+ - | | | - +---+------------+ +-----+---------+ +------+----------+ - | TelemetryImpl | | NullTelemetry | | NullTelemetryOtel| - | (Telemetry.cpp)| |(NullTelemetry | | (Telemetry.cpp) | - | OTel SDK | | .cpp) | | noop w/ OTel API | - +----------------+ +---------------+ +------------------+ - - The Setup struct holds all configuration parsed from the [telemetry] - section of xrpld.cfg. See TelemetryConfig.cpp for the parser and - cfg/xrpld-example.cfg for the available options. - - OTel SDK headers are conditionally included behind XRPL_ENABLE_TELEMETRY - so that builds without telemetry have zero dependency on opentelemetry-cpp. - - Usage examples: - - 1. Root span at a subsystem entry point (typical usage): - @code - #include - using namespace xrpl::telemetry; - - // In an RPC handler dispatch: - auto guard = SpanGuard::span( - TraceCategory::Rpc, rpc_span::prefix::command, commandName); - guard.setAttribute(rpc_span::attr::command, commandName); - // ... process request - // guard destructor automatically ends the span on scope exit - @endcode - - 2. Child span for a sub-operation (scoped child): - @code - auto parent = SpanGuard::span( - TraceCategory::Rpc, rpc_span::prefix::rpc, rpc_span::op::process); - { - auto child = parent.childSpan(rpc_span::op::process); - child.setAttribute(rpc_span::attr::version, apiVersion); - // child ends here - } - @endcode - - 3. Unrelated span (cross-scope, same thread): - @code - // gRPC and RPC handlers can be active simultaneously - auto grpcSpan = SpanGuard::span( - TraceCategory::Rpc, grpc_span::prefix::grpc, grpc_span::attr::method); - auto rpcSpan = SpanGuard::span( - TraceCategory::Rpc, rpc_span::prefix::command, commandName); - // both spans end on scope exit - @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(rpc_span::op::process, ctx); - @endcode - - @note Thread safety: The Telemetry interface is safe for concurrent reads - (isEnabled, shouldTrace*, getTracer, startSpan) after start() completes. - setServiceInstanceId() must be called before start() and is not thread-safe. - The OTel SDK's TracerProvider and Tracer are internally thread-safe. -*/ +/** + * Abstract interface for OpenTelemetry distributed tracing. + * + * Provides the Telemetry base class that all components use to create trace + * spans. Three concrete implementations exist, selected at construction time + * by makeTelemetry(): + * + * - TelemetryImpl (Telemetry.cpp): real OTel SDK integration, compiled + * only when XRPL_ENABLE_TELEMETRY is defined and enabled at runtime. + * - NullTelemetry (NullTelemetry.cpp): no-op stub used when telemetry is + * disabled at compile time or runtime. + * - NullTelemetryOtel (Telemetry.cpp): no-op stub that still depends on + * the OTel API (used during transition or for testing). + * + * Inheritance / dependency diagram: + * + * +--------------------+ + * | Telemetry | (abstract, this file) + * | <> | + * +---------+----------+ + * | + * +---------+-----------+-------------------+ + * | | | + * +---+------------+ +-----+---------+ +------+----------+ + * | TelemetryImpl | | NullTelemetry | | NullTelemetryOtel| + * | (Telemetry.cpp)| |(NullTelemetry | | (Telemetry.cpp) | + * | OTel SDK | | .cpp) | | noop w/ OTel API | + * +----------------+ +---------------+ +------------------+ + * + * The Setup struct holds all configuration parsed from the [telemetry] + * section of xrpld.cfg. See TelemetryConfig.cpp for the parser and + * cfg/xrpld-example.cfg for the available options. + * + * OTel SDK headers are conditionally included behind XRPL_ENABLE_TELEMETRY + * so that builds without telemetry have zero dependency on opentelemetry-cpp. + * + * Usage examples: + * + * 1. Root span at a subsystem entry point (typical usage): + * @code + * #include + * using namespace xrpl::telemetry; + * + * // In an RPC handler dispatch: + * auto guard = SpanGuard::span( + * TraceCategory::Rpc, rpc_span::prefix::command, commandName); + * guard.setAttribute(rpc_span::attr::command, commandName); + * // ... process request + * // guard destructor automatically ends the span on scope exit + * @endcode + * + * 2. Child span for a sub-operation (scoped child): + * @code + * auto parent = SpanGuard::span( + * TraceCategory::Rpc, rpc_span::prefix::rpc, rpc_span::op::process); + * { + * auto child = parent.childSpan(rpc_span::op::process); + * child.setAttribute(rpc_span::attr::version, apiVersion); + * // child ends here + * } + * @endcode + * + * 3. Unrelated span (cross-scope, same thread): + * @code + * // gRPC and RPC handlers can be active simultaneously + * auto grpcSpan = SpanGuard::span( + * TraceCategory::Rpc, grpc_span::prefix::grpc, grpc_span::attr::method); + * auto rpcSpan = SpanGuard::span( + * TraceCategory::Rpc, rpc_span::prefix::command, commandName); + * // both spans end on scope exit + * @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(rpc_span::op::process, ctx); + * @endcode + * + * @note Thread safety: The Telemetry interface is safe for concurrent reads + * (isEnabled, shouldTrace*, getTracer, startSpan) after start() completes. + * setServiceInstanceId() must be called before start() and is not thread-safe. + * The OTel SDK's TracerProvider and Tracer are internally thread-safe. + */ #include #include @@ -107,145 +108,192 @@ namespace xrpl::telemetry { #ifdef XRPL_ENABLE_TELEMETRY -/** OTel instrumentation scope (tracer) name. Identifies this library as the - source of spans; distinct from the `service.name` resource attribute - (Setup::serviceName), which is config-overridable. */ +/** + * OTel instrumentation scope (tracer) name. Identifies this library as the + * source of spans; distinct from the `service.name` resource attribute + * (Setup::serviceName), which is config-overridable. + */ inline constexpr std::string_view kTracerName{"xrpld"}; #endif class Telemetry { - /** Global singleton pointer, set by start()/stop() in the active - implementation. Allows SpanGuard factory methods to access the - Telemetry instance without callers passing it explicitly. - - Atomic with acquire/release ordering: start()/stop() store on - the initialization thread, factory methods load on worker threads. - @see setInstance(), getInstance() - */ + /** + * Global singleton pointer, set by start()/stop() in the active + * implementation. Allows SpanGuard factory methods to access the + * Telemetry instance without callers passing it explicitly. + * + * Atomic with acquire/release ordering: start()/stop() store on + * the initialization thread, factory methods load on worker threads. + * @see setInstance(), getInstance() + */ inline static std::atomic instance{nullptr}; public: - /** Get the global Telemetry instance. - @return Pointer to the active instance, or nullptr if not started. - */ + /** + * Get the global Telemetry instance. + * @return Pointer to the active instance, or nullptr if not started. + */ static Telemetry* getInstance() { return instance.load(std::memory_order_acquire); } - /** Set the global Telemetry instance. - Called by start()/stop() in concrete implementations. - Tests can call this with a mock to override the global instance. - @param t Pointer to the Telemetry instance, or nullptr to clear. - */ + /** + * Set the global Telemetry instance. + * Called by start()/stop() in concrete implementations. + * Tests can call this with a mock to override the global instance. + * @param t Pointer to the Telemetry instance, or nullptr to clear. + */ static void setInstance(Telemetry* t) { instance.store(t, std::memory_order_release); } - /** Configuration parsed from the [telemetry] section of xrpld.cfg. - - All fields have sensible defaults so the section can be minimal - or omitted entirely. See TelemetryConfig.cpp for the parser. - */ + /** + * Configuration parsed from the [telemetry] section of xrpld.cfg. + * + * All fields have sensible defaults so the section can be minimal + * or omitted entirely. See TelemetryConfig.cpp for the parser. + */ struct Setup { - /** Master switch: true to enable tracing at runtime. */ + /** + * Master switch: true to enable tracing at runtime. + */ bool enabled = false; - /** OTel resource attribute `service.name`. */ + /** + * OTel resource attribute `service.name`. + */ std::string serviceName = "xrpld"; - /** OTel resource attribute `service.version` (set from BuildInfo). */ + /** + * OTel resource attribute `service.version` (set from BuildInfo). + */ std::string serviceVersion; - /** OTel resource attribute `service.instance.id` (defaults to node - public key). */ + /** + * OTel resource attribute `service.instance.id` (defaults to node + * public key). + */ std::string serviceInstanceId; - /** OTLP/HTTP endpoint URL where spans are sent. */ + /** + * OTLP/HTTP endpoint URL where spans are sent. + */ std::string exporterEndpoint = "http://localhost:4318/v1/traces"; - /** Whether to use TLS for the exporter connection. */ + /** + * Whether to use TLS for the exporter connection. + */ bool useTls = false; - /** Path to a CA certificate bundle for TLS verification. */ + /** + * Path to a CA certificate bundle for TLS verification. + */ std::string tlsCertPath; - /** Path to this node's client certificate (PEM), presented to the - collector for mutual TLS. Empty disables client-side auth, in - which case only server (one-way) TLS is used. */ + /** + * Path to this node's client certificate (PEM), presented to the + * collector for mutual TLS. Empty disables client-side auth, in + * which case only server (one-way) TLS is used. + */ std::string tlsClientCertPath; - /** Path to the private key (PEM) for tlsClientCertPath. Required - whenever tlsClientCertPath is set. */ + /** + * Path to the private key (PEM) for tlsClientCertPath. Required + * whenever tlsClientCertPath is set. + */ std::string tlsClientKeyPath; - /** Head-based sampling ratio. Intentionally fixed at 1.0 (sample - everything) and NOT read from config. A per-node ratio would let - nodes make divergent keep/drop decisions for the same distributed - trace, producing broken/partial traces. The ratio sampler is wrapped - in a ParentBasedSampler (see Telemetry.cpp) so spans inheriting a - remote parent honor the upstream sampled flag. Volume reduction is - delegated to the collector's tail sampling; for node-local post-hoc - dropping see SpanGuard::discard(). - */ + /** + * Head-based sampling ratio. Intentionally fixed at 1.0 (sample + * everything) and NOT read from config. A per-node ratio would let + * nodes make divergent keep/drop decisions for the same distributed + * trace, producing broken/partial traces. The ratio sampler is wrapped + * in a ParentBasedSampler (see Telemetry.cpp) so spans inheriting a + * remote parent honor the upstream sampled flag. Volume reduction is + * delegated to the collector's tail sampling; for node-local post-hoc + * dropping see SpanGuard::discard(). + */ static constexpr double samplingRatio = 1.0; - /** Maximum number of spans per batch export. */ + /** + * Maximum number of spans per batch export. + */ std::uint32_t batchSize = 512; - /** Delay between batch exports. */ + /** + * Delay between batch exports. + */ std::chrono::milliseconds batchDelay = std::chrono::milliseconds{5000}; - /** Maximum number of spans queued before dropping. */ + /** + * Maximum number of spans queued before dropping. + */ std::uint32_t maxQueueSize = 2048; - /** Network identifier, added as an OTel resource attribute. */ + /** + * Network identifier, added as an OTel resource attribute. + */ std::uint32_t networkId = 0; - /** Network type label (e.g. "mainnet", "testnet", "devnet"). */ + /** + * Network type label (e.g. "mainnet", "testnet", "devnet"). + */ std::string networkType = "mainnet"; - /** Enable tracing for transaction processing. */ + /** + * Enable tracing for transaction processing. + */ bool traceTransactions = true; - /** Enable tracing for consensus rounds. */ + /** + * Enable tracing for consensus rounds. + */ bool traceConsensus = true; - /** Enable tracing for RPC request handling. */ + /** + * Enable tracing for RPC request handling. + */ bool traceRpc = true; - /** Enable tracing for peer-to-peer messages (enabled by default; - high volume). */ + /** + * Enable tracing for peer-to-peer messages (enabled by default; + * high volume). + */ bool tracePeer = true; - /** Enable tracing for ledger close/accept. */ + /** + * Enable tracing for ledger close/accept. + */ bool traceLedger = true; - /** Strategy for cross-node consensus trace correlation. - "deterministic" — derive trace_id from ledger hash so all - validators in the same round share the same trace_id. - "attribute" — random trace_id, correlate via ledger_id attribute. - */ + /** + * Strategy for cross-node consensus trace correlation. + * "deterministic" — derive trace_id from ledger hash so all + * validators in the same round share the same trace_id. + * "attribute" — random trace_id, correlate via ledger_id attribute. + */ std::string consensusTraceStrategy = "deterministic"; }; virtual ~Telemetry() = default; - /** Update the service instance ID (OTel resource attribute - `service.instance.id`). - - Must be called before start(). The node public key is not available - when Telemetry is constructed (during the ApplicationImp member - initializer list), so this setter allows Application::setup() to - inject the identity once nodeIdentity_ is known. - - @param id The node's base58-encoded public key or custom identifier. - */ + /** + * Update the service instance ID (OTel resource attribute + * `service.instance.id`). + * + * Must be called before start(). The node public key is not available + * when Telemetry is constructed (during the ApplicationImp member + * initializer list), so this setter allows Application::setup() to + * inject the identity once nodeIdentity_ is known. + * + * @param id The node's base58-encoded public key or custom identifier. + */ virtual void setServiceInstanceId(std::string const& id) { @@ -253,84 +301,103 @@ public: (void)id; } - /** Initialize the tracing pipeline (exporter, processor, provider). - Call after construction. - */ + /** + * Initialize the tracing pipeline (exporter, processor, provider). + * Call after construction. + */ virtual void start() = 0; - /** Flush pending spans and shut down the tracing pipeline. - Call before destruction. - */ + /** + * Flush pending spans and shut down the tracing pipeline. + * Call before destruction. + */ virtual void stop() = 0; - /** @return true if this instance is actively exporting spans. */ + /** + * @return true if this instance is actively exporting spans. + */ [[nodiscard]] virtual bool isEnabled() const = 0; - /** @return true if transaction processing should be traced. */ + /** + * @return true if transaction processing should be traced. + */ [[nodiscard]] virtual bool shouldTraceTransactions() const = 0; - /** @return true if consensus rounds should be traced. */ + /** + * @return true if consensus rounds should be traced. + */ [[nodiscard]] virtual bool shouldTraceConsensus() const = 0; - /** @return true if RPC request handling should be traced. */ + /** + * @return true if RPC request handling should be traced. + */ [[nodiscard]] virtual bool shouldTraceRpc() const = 0; - /** @return true if peer-to-peer messages should be traced. */ + /** + * @return true if peer-to-peer messages should be traced. + */ [[nodiscard]] virtual bool shouldTracePeer() const = 0; - /** @return true if ledger close/accept should be traced. */ + /** + * @return true if ledger close/accept should be traced. + */ [[nodiscard]] virtual bool shouldTraceLedger() const = 0; - /** @return The configured consensus trace correlation strategy. */ + /** + * @return The configured consensus trace correlation strategy. + */ [[nodiscard]] virtual std::string const& getConsensusTraceStrategy() const = 0; #ifdef XRPL_ENABLE_TELEMETRY - /** Get or create a named tracer instance. - - @param name Tracer name used to identify the instrumentation library. - @return A shared pointer to the Tracer. - */ + /** + * Get or create a named tracer instance. + * + * @param name Tracer name used to identify the instrumentation library. + * @return A shared pointer to the Tracer. + */ virtual opentelemetry::nostd::shared_ptr getTracer(std::string_view name = kTracerName) = 0; - /** Start a new span on the current thread's context. - - The span becomes a child of the current active span (if any) via - OpenTelemetry's context propagation. - - @param name Span name (typically "rpc.command."). - @param kind The span kind (defaults to kInternal). Possible values: - - kInternal: default, in-process operation - - kServer: incoming synchronous request (e.g. RPC) - - kClient: outgoing synchronous request - - kProducer: async message send (e.g. peer broadcast) - - kConsumer: async message receive - @return A shared pointer to the new Span. - */ + /** + * Start a new span on the current thread's context. + * + * The span becomes a child of the current active span (if any) via + * OpenTelemetry's context propagation. + * + * @param name Span name (typically "rpc.command."). + * @param kind The span kind (defaults to kInternal). Possible values: + * - kInternal: default, in-process operation + * - kServer: incoming synchronous request (e.g. RPC) + * - kClient: outgoing synchronous request + * - kProducer: async message send (e.g. peer broadcast) + * - kConsumer: async message receive + * @return A shared pointer to the new Span. + */ virtual opentelemetry::nostd::shared_ptr startSpan( std::string_view name, opentelemetry::trace::SpanKind kind = opentelemetry::trace::SpanKind::kInternal) = 0; - /** Start a new span with an explicit parent context. - - Use this overload when the parent span is not on the current - thread's context stack (e.g. cross-thread trace propagation). - - @param name Span name. - @param parentContext The parent span's context. - @param kind The span kind (defaults to kInternal). - @return A shared pointer to the new Span. - */ + /** + * Start a new span with an explicit parent context. + * + * Use this overload when the parent span is not on the current + * thread's context stack (e.g. cross-thread trace propagation). + * + * @param name Span name. + * @param parentContext The parent span's context. + * @param kind The span kind (defaults to kInternal). + * @return A shared pointer to the new Span. + */ virtual opentelemetry::nostd::shared_ptr startSpan( std::string_view name, @@ -339,26 +406,28 @@ public: #endif }; -/** Create a Telemetry instance. - - Returns a TelemetryImpl when setup.enabled is true, or a - NullTelemetry no-op stub otherwise. - - @param setup Configuration from the [telemetry] config section. - @param journal Journal for log output during initialization. -*/ +/** + * Create a Telemetry instance. + * + * Returns a TelemetryImpl when setup.enabled is true, or a + * NullTelemetry no-op stub otherwise. + * + * @param setup Configuration from the [telemetry] config section. + * @param journal Journal for log output during initialization. + */ std::unique_ptr makeTelemetry(Telemetry::Setup const& setup, beast::Journal journal); -/** Parse the [telemetry] config section into a Setup struct. - - @param section The [telemetry] config section. - @param nodePublicKey Node public key, used as default instance ID. - @param version Build version string. - @param networkId Network identifier from [network_id] config - (0 = mainnet, 1 = testnet, 2 = devnet). - @return A populated Setup struct with defaults for missing values. -*/ +/** + * Parse the [telemetry] config section into a Setup struct. + * + * @param section The [telemetry] config section. + * @param nodePublicKey Node public key, used as default instance ID. + * @param version Build version string. + * @param networkId Network identifier from [network_id] config + * (0 = mainnet, 1 = testnet, 2 = devnet). + * @return A populated Setup struct with defaults for missing values. + */ Telemetry::Setup makeTelemetrySetup( Section const& section, diff --git a/include/xrpl/telemetry/TraceContextPropagator.h b/include/xrpl/telemetry/TraceContextPropagator.h index 8a33687613..e8d851e53e 100644 --- a/include/xrpl/telemetry/TraceContextPropagator.h +++ b/include/xrpl/telemetry/TraceContextPropagator.h @@ -1,18 +1,19 @@ #pragma once -/** Utilities for trace context propagation across nodes. - - Provides serialization/deserialization of OTel trace context to/from - Protocol Buffer TraceContext messages (P2P cross-node propagation). - Wired into the P2P message flow via PropagationHelpers.h for - TMTransaction, TMProposeSet, and TMValidation messages. - - Only compiled when XRPL_ENABLE_TELEMETRY is defined. - - @see PropagationHelpers.h (high-level inject helpers), - TxTracing.h (transaction receive-side extraction), - ConsensusReceiveTracing.h (proposal/validation receive-side). -*/ +/** + * Utilities for trace context propagation across nodes. + * + * Provides serialization/deserialization of OTel trace context to/from + * Protocol Buffer TraceContext messages (P2P cross-node propagation). + * Wired into the P2P message flow via PropagationHelpers.h for + * TMTransaction, TMProposeSet, and TMValidation messages. + * + * Only compiled when XRPL_ENABLE_TELEMETRY is defined. + * + * @see PropagationHelpers.h (high-level inject helpers), + * TxTracing.h (transaction receive-side extraction), + * ConsensusReceiveTracing.h (proposal/validation receive-side). + */ #ifdef XRPL_ENABLE_TELEMETRY @@ -35,12 +36,13 @@ namespace xrpl::telemetry { -/** Extract OTel context from a protobuf TraceContext message. - - @param proto The protobuf TraceContext received from a peer. - @return An OTel Context with the extracted parent span, or an empty - context if the protobuf fields are missing or invalid. -*/ +/** + * Extract OTel context from a protobuf TraceContext message. + * + * @param proto The protobuf TraceContext received from a peer. + * @return An OTel Context with the extracted parent span, or an empty + * context if the protobuf fields are missing or invalid. + */ inline opentelemetry::context::Context extractFromProtobuf(protocol::TraceContext const& proto) { @@ -69,11 +71,12 @@ extractFromProtobuf(protocol::TraceContext const& proto) opentelemetry::nostd::shared_ptr(new trace::DefaultSpan(spanCtx))); } -/** Inject the current span's trace context into a protobuf TraceContext. - - @param ctx The OTel context containing the span to propagate. - @param proto The protobuf TraceContext to populate. -*/ +/** + * Inject the current span's trace context into a protobuf TraceContext. + * + * @param ctx The OTel context containing the span to propagate. + * @param proto The protobuf TraceContext to populate. + */ inline void injectToProtobuf(opentelemetry::context::Context const& ctx, protocol::TraceContext& proto) { diff --git a/include/xrpl/telemetry/TraceContextValidation.h b/include/xrpl/telemetry/TraceContextValidation.h index 1c1554acf0..e69b2d17ca 100644 --- a/include/xrpl/telemetry/TraceContextValidation.h +++ b/include/xrpl/telemetry/TraceContextValidation.h @@ -1,6 +1,7 @@ #pragma once -/** Validation predicates for peer-supplied trace context. +/** + * Validation predicates for peer-supplied trace context. * * A protobuf TraceContext arrives inside untrusted peer messages * (TMTransaction, TMProposeSet, TMValidation). Before a receiving node @@ -28,7 +29,7 @@ * no OpenTelemetry headers, so receive sites that use SpanGuard keep * SpanGuard's encapsulation of OTel types. * - * @note Thread-safe: all functions are pure and operate only on their + * @note Thread-safe: all functions are pure and operate only on their * arguments. No shared state. * * Usage: @@ -50,10 +51,11 @@ namespace xrpl::telemetry { -/** True if the bytes are a valid OTel trace_id: 16 bytes, not all-zero. +/** + * True if the bytes are a valid OTel trace_id: 16 bytes, not all-zero. * - * @param traceId The raw trace_id bytes from a protobuf TraceContext. - * @return true if usable as a trace identifier, false otherwise. + * @param traceId The raw trace_id bytes from a protobuf TraceContext. + * @return true if usable as a trace identifier, false otherwise. */ inline bool isValidTraceId(std::string const& traceId) @@ -61,10 +63,11 @@ isValidTraceId(std::string const& traceId) return traceId.size() == 16 && std::ranges::any_of(traceId, [](char c) { return c != 0; }); } -/** True if the bytes are a valid OTel span_id: 8 bytes, not all-zero. +/** + * True if the bytes are a valid OTel span_id: 8 bytes, not all-zero. * - * @param spanId The raw span_id bytes from a protobuf TraceContext. - * @return true if usable as a span identifier, false otherwise. + * @param spanId The raw span_id bytes from a protobuf TraceContext. + * @return true if usable as a span identifier, false otherwise. */ inline bool isValidSpanId(std::string const& spanId) @@ -72,15 +75,16 @@ isValidSpanId(std::string const& spanId) return spanId.size() == 8 && std::ranges::any_of(spanId, [](char c) { return c != 0; }); } -/** True if the context carries a usable parent: a valid trace_id and a +/** + * True if the context carries a usable parent: a valid trace_id and a * valid span_id together. * * Use this where both ids are taken from the peer (consensus receive, * generic extraction). The transaction path derives its trace_id * locally from the txID, so it checks isValidSpanId() alone instead. * - * @param tc The protobuf TraceContext received from a peer. - * @return true if both ids are present and valid, false otherwise. + * @param tc The protobuf TraceContext received from a peer. + * @return true if both ids are present and valid, false otherwise. */ inline bool isValidTraceContext(protocol::TraceContext const& tc) diff --git a/include/xrpl/tx/detail/TxApplySpanNames.h b/include/xrpl/tx/detail/TxApplySpanNames.h index 2084458cf5..1228bd57ef 100644 --- a/include/xrpl/tx/detail/TxApplySpanNames.h +++ b/include/xrpl/tx/detail/TxApplySpanNames.h @@ -1,6 +1,7 @@ #pragma once -/** Compile-time span name constants for the transaction apply pipeline. +/** + * Compile-time span name constants for the transaction apply pipeline. * * Defines the span names and attribute keys used by the three apply-pipeline * stages — preflight, preclaim, and transactor (apply) — that run inside the @@ -67,47 +68,73 @@ namespace xrpl::telemetry::tx_apply_span { // ===== Span operation suffixes ============================================= namespace op { -/// "preflight" — stateless transaction checks (suffix form). +/** + * "preflight" — stateless transaction checks (suffix form). + */ inline constexpr auto preflight = makeStr("preflight"); -/// "preclaim" — ledger-aware checks before fee claim (suffix form). +/** + * "preclaim" — ledger-aware checks before fee claim (suffix form). + */ inline constexpr auto preclaim = makeStr("preclaim"); -/// "transactor" — the apply stage (suffix form, used with span()). +/** + * "transactor" — the apply stage (suffix form, used with span()). + */ inline constexpr auto transactor = makeStr("transactor"); } // namespace op // ===== Full span names (tx.) =========================================== -/// "tx.preflight" — full name for hashSpan() at the preflight stage. +/** + * "tx.preflight" — full name for hashSpan() at the preflight stage. + */ inline constexpr auto preflight = join(seg::tx, op::preflight); -/// "tx.preclaim" — full name for hashSpan() at the preclaim stage. +/** + * "tx.preclaim" — full name for hashSpan() at the preclaim stage. + */ inline constexpr auto preclaim = join(seg::tx, op::preclaim); -/// "tx.transactor" — full name for hashSpan() at the apply stage. Shares the -/// txID-derived trace_id so it co-traces with tx.preflight and tx.preclaim. +/** + * "tx.transactor" — full name for hashSpan() at the apply stage. Shares the + * txID-derived trace_id so it co-traces with tx.preflight and tx.preclaim. + */ inline constexpr auto transactor = join(seg::tx, op::transactor); // ===== Attribute keys ====================================================== namespace attr { -/// "stage" — which apply-pipeline stage this span represents. Drives the -/// collector spanmetrics `stage` dimension for per-stage RED metrics. +/** + * "stage" — which apply-pipeline stage this span represents. Drives the + * collector spanmetrics `stage` dimension for per-stage RED metrics. + */ inline constexpr auto stage = makeStr("stage"); -/// "tx_type" — transaction type name (e.g., "Payment", "OfferCreate"). -/// Matches tx_span::attr::txType so both share the spanmetrics dimension. +/** + * "tx_type" — transaction type name (e.g., "Payment", "OfferCreate"). + * Matches tx_span::attr::txType so both share the spanmetrics dimension. + */ inline constexpr auto txType = makeStr("tx_type"); -/// "ter_result" — engine result code after the stage (e.g., "tesSUCCESS"). +/** + * "ter_result" — engine result code after the stage (e.g., "tesSUCCESS"). + */ inline constexpr auto terResult = makeStr("ter_result"); -/// "applied" — whether the transaction was applied to the ledger (apply only). +/** + * "applied" — whether the transaction was applied to the ledger (apply only). + */ inline constexpr auto applied = makeStr("applied"); } // namespace attr // ===== Attribute values (stage names) ====================================== namespace val { -/// "preflight" — value of the stage attribute on tx.preflight. +/** + * "preflight" — value of the stage attribute on tx.preflight. + */ inline constexpr auto preflight = makeStr("preflight"); -/// "preclaim" — value of the stage attribute on tx.preclaim. +/** + * "preclaim" — value of the stage attribute on tx.preclaim. + */ inline constexpr auto preclaim = makeStr("preclaim"); -/// "apply" — value of the stage attribute on tx.transactor. +/** + * "apply" — value of the stage attribute on tx.transactor. + */ inline constexpr auto apply = makeStr("apply"); } // namespace val diff --git a/src/libxrpl/telemetry/NullTelemetry.cpp b/src/libxrpl/telemetry/NullTelemetry.cpp index e986cba8d6..92cc7303ef 100644 --- a/src/libxrpl/telemetry/NullTelemetry.cpp +++ b/src/libxrpl/telemetry/NullTelemetry.cpp @@ -1,14 +1,15 @@ -/** No-op implementation of the Telemetry interface. - - Always compiled (regardless of XRPL_ENABLE_TELEMETRY). Provides the - makeTelemetry() factory when telemetry is compiled out (#ifndef), which - unconditionally returns a NullTelemetry that does nothing. - - When XRPL_ENABLE_TELEMETRY IS defined, the OTel virtual methods - (getTracer, startSpan) return noop tracers/spans. The makeTelemetry() - factory in this file is not used in that case -- Telemetry.cpp provides - its own factory that can return the real TelemetryImpl. -*/ +/** + * No-op implementation of the Telemetry interface. + * + * Always compiled (regardless of XRPL_ENABLE_TELEMETRY). Provides the + * makeTelemetry() factory when telemetry is compiled out (#ifndef), which + * unconditionally returns a NullTelemetry that does nothing. + * + * When XRPL_ENABLE_TELEMETRY IS defined, the OTel virtual methods + * (getTracer, startSpan) return noop tracers/spans. The makeTelemetry() + * factory in this file is not used in that case -- Telemetry.cpp provides + * its own factory that can return the real TelemetryImpl. + */ #include @@ -31,14 +32,17 @@ namespace xrpl::telemetry { namespace { -/** No-op Telemetry that returns immediately from every method. - - Used as the sole implementation when XRPL_ENABLE_TELEMETRY is not - defined, or as a fallback when it is defined but enabled=0. -*/ +/** + * No-op Telemetry that returns immediately from every method. + * + * Used as the sole implementation when XRPL_ENABLE_TELEMETRY is not + * defined, or as a fallback when it is defined but enabled=0. + */ class NullTelemetry : public Telemetry { - /** Retained configuration (unused, kept for diagnostic access). */ + /** + * Retained configuration (unused, kept for diagnostic access). + */ Setup const setup_; public: @@ -130,9 +134,10 @@ public: } // namespace -/** Factory used when XRPL_ENABLE_TELEMETRY is not defined. - Unconditionally returns a NullTelemetry instance. -*/ +/** + * Factory used when XRPL_ENABLE_TELEMETRY is not defined. + * Unconditionally returns a NullTelemetry instance. + */ #ifndef XRPL_ENABLE_TELEMETRY std::unique_ptr makeTelemetry(Telemetry::Setup const& setup, beast::Journal) diff --git a/src/libxrpl/telemetry/Telemetry.cpp b/src/libxrpl/telemetry/Telemetry.cpp index 0dfa95e63d..963d0a71ef 100644 --- a/src/libxrpl/telemetry/Telemetry.cpp +++ b/src/libxrpl/telemetry/Telemetry.cpp @@ -1,17 +1,18 @@ -/** OpenTelemetry SDK implementation of the Telemetry interface. - - Compiled only when XRPL_ENABLE_TELEMETRY is defined (via CMake - telemetry=ON). Contains: - - - FilteringSpanProcessor: decorator that drops spans marked with - kDiscardedAttr before they enter the batch export queue. - - TelemetryImpl: configures the OTel SDK with an OTLP/HTTP exporter, - FilteringSpanProcessor wrapping a batch span processor, - trace-ID-ratio sampler, and resource attributes. - - NullTelemetryOtel: no-op fallback used when telemetry is compiled in - but disabled at runtime (enabled=0 in config). - - makeTelemetry(): factory that selects the appropriate implementation. -*/ +/** + * OpenTelemetry SDK implementation of the Telemetry interface. + * + * Compiled only when XRPL_ENABLE_TELEMETRY is defined (via CMake + * telemetry=ON). Contains: + * + * - FilteringSpanProcessor: decorator that drops spans marked with + * kDiscardedAttr before they enter the batch export queue. + * - TelemetryImpl: configures the OTel SDK with an OTLP/HTTP exporter, + * FilteringSpanProcessor wrapping a batch span processor, + * trace-ID-ratio sampler, and resource attributes. + * - NullTelemetryOtel: no-op fallback used when telemetry is compiled in + * but disabled at runtime (enabled=0 in config). + * - makeTelemetry(): factory that selects the appropriate implementation. + */ #ifdef XRPL_ENABLE_TELEMETRY @@ -60,39 +61,40 @@ namespace trace_sdk = opentelemetry::sdk::trace; namespace otlp_http = opentelemetry::exporter::otlp; namespace resource = opentelemetry::sdk::resource; -/** SpanProcessor decorator that drops discarded spans. - - Wraps a delegate processor (typically BatchSpanProcessor). In OnEnd(), - calls DiscardScope::isActive(). If the calling thread is inside a - DiscardScope (entered by SpanGuard::discard()), the span is silently - dropped — never entering the batch queue, never sent over the network, - never stored. - - Uses a thread-local flag rather than inspecting Recordable attributes - because the Recordable type varies by exporter (SpanData for simple - exporters, OtlpRecordable for OTLP) and none expose a uniform getter. - The flag is safe because Span::End() calls OnEnd() synchronously on - the same thread. - - All other methods delegate directly to the wrapped processor. - - Dependency diagram: - - +---------------------------+ - | FilteringSpanProcessor | - +---------------------------+ - | - delegate_ : unique_ptr | - | | - +---------------------------+ - | wraps - +---------+-----------+ - | BatchSpanProcessor | - +---------------------+ - - @note Thread safety: OnEnd() may be called concurrently from multiple - threads. The discard flag behind DiscardScope is thread-local, so each - thread's discard state is independent — no synchronization needed. -*/ +/** + * SpanProcessor decorator that drops discarded spans. + * + * Wraps a delegate processor (typically BatchSpanProcessor). In OnEnd(), + * calls DiscardScope::isActive(). If the calling thread is inside a + * DiscardScope (entered by SpanGuard::discard()), the span is silently + * dropped — never entering the batch queue, never sent over the network, + * never stored. + * + * Uses a thread-local flag rather than inspecting Recordable attributes + * because the Recordable type varies by exporter (SpanData for simple + * exporters, OtlpRecordable for OTLP) and none expose a uniform getter. + * The flag is safe because Span::End() calls OnEnd() synchronously on + * the same thread. + * + * All other methods delegate directly to the wrapped processor. + * + * Dependency diagram: + * + * +---------------------------+ + * | FilteringSpanProcessor | + * +---------------------------+ + * | - delegate_ : unique_ptr | + * | | + * +---------------------------+ + * | wraps + * +---------+-----------+ + * | BatchSpanProcessor | + * +---------------------+ + * + * @note Thread safety: OnEnd() may be called concurrently from multiple + * threads. The discard flag behind DiscardScope is thread-local, so each + * thread's discard state is independent — no synchronization needed. + */ class FilteringSpanProcessor : public trace_sdk::SpanProcessor { std::unique_ptr delegate_; @@ -144,15 +146,18 @@ public: } }; -/** No-op implementation used when XRPL_ENABLE_TELEMETRY is defined but - setup.enabled is false at runtime. - - Lives in the anonymous namespace so there is no ODR conflict with the - NullTelemetry in NullTelemetry.cpp. -*/ +/** + * No-op implementation used when XRPL_ENABLE_TELEMETRY is defined but + * setup.enabled is false at runtime. + * + * Lives in the anonymous namespace so there is no ODR conflict with the + * NullTelemetry in NullTelemetry.cpp. + */ class NullTelemetryOtel : public Telemetry { - /** Retained configuration (unused, kept for diagnostic access). */ + /** + * Retained configuration (unused, kept for diagnostic access). + */ Setup const setup_; public: @@ -236,27 +241,32 @@ public: } }; -/** Full OTel SDK implementation that exports trace spans via OTLP/HTTP. - - Configures an OTLP/HTTP exporter, batch span processor, - TraceIdRatioBasedSampler, and resource attributes on start(). -*/ +/** + * Full OTel SDK implementation that exports trace spans via OTLP/HTTP. + * + * Configures an OTLP/HTTP exporter, batch span processor, + * TraceIdRatioBasedSampler, and resource attributes on start(). + */ class TelemetryImpl : public Telemetry { - /** Configuration from the [telemetry] config section. - Non-const so setServiceInstanceId() can update the instance ID - before start() creates the OTel resource. - */ + /** + * Configuration from the [telemetry] config section. + * Non-const so setServiceInstanceId() can update the instance ID + * before start() creates the OTel resource. + */ Setup setup_; - /** Journal used for log output during start/stop. */ + /** + * Journal used for log output during start/stop. + */ beast::Journal const journal_; - /** The SDK TracerProvider that owns the export pipeline. - - Held as std::shared_ptr so we can call ForceFlush() on shutdown. - Wrapped in a nostd::shared_ptr when registered as the global provider. - */ + /** + * The SDK TracerProvider that owns the export pipeline. + * + * Held as std::shared_ptr so we can call ForceFlush() on shutdown. + * Wrapped in a nostd::shared_ptr when registered as the global provider. + */ std::shared_ptr sdkProvider_; public: diff --git a/src/libxrpl/telemetry/TelemetryConfig.cpp b/src/libxrpl/telemetry/TelemetryConfig.cpp index 102ae3291c..9544c71345 100644 --- a/src/libxrpl/telemetry/TelemetryConfig.cpp +++ b/src/libxrpl/telemetry/TelemetryConfig.cpp @@ -1,11 +1,12 @@ -/** Parser for the [telemetry] section of xrpld.cfg. - - Reads configuration values from the config file and populates a - Telemetry::Setup struct. All options have sensible defaults so the - section can be minimal or omitted entirely. - - See cfg/xrpld-example.cfg for the full list of available options. -*/ +/** + * Parser for the [telemetry] section of xrpld.cfg. + * + * Reads configuration values from the config file and populates a + * Telemetry::Setup struct. All options have sensible defaults so the + * section can be minimal or omitted entirely. + * + * See cfg/xrpld-example.cfg for the full list of available options. + */ #include #include @@ -20,13 +21,14 @@ namespace xrpl::telemetry { namespace { -/** Config key names for the [telemetry] section. - - Each must match the corresponding option documented in - cfg/xrpld-example.cfg verbatim. Defined as `char const*` so they - pass to Section::valueOr() (which takes `std::string const&`) - without an explicit conversion, exactly as a literal would. -*/ +/** + * Config key names for the [telemetry] section. + * + * Each must match the corresponding option documented in + * cfg/xrpld-example.cfg verbatim. Defined as `char const*` so they + * pass to Section::valueOr() (which takes `std::string const&`) + * without an explicit conversion, exactly as a literal would. + */ namespace key { constexpr char const* enabled = "enabled"; constexpr char const* serviceName = "service_name"; @@ -46,13 +48,14 @@ constexpr char const* tracePeer = "trace_peer"; constexpr char const* traceLedger = "trace_ledger"; } // namespace key -/** Default values applied when a key is absent from the config. - - @note serviceName mirrors SystemParameters' systemName() ("xrpld") but - is duplicated here as a literal: the telemetry module deliberately does - not link xrpl.libxrpl.protocol, so including SystemParameters.h would - introduce an undeclared cross-module dependency. -*/ +/** + * Default values applied when a key is absent from the config. + * + * @note serviceName mirrors SystemParameters' systemName() ("xrpld") but + * is duplicated here as a literal: the telemetry module deliberately does + * not link xrpl.libxrpl.protocol, so including SystemParameters.h would + * introduce an undeclared cross-module dependency. + */ namespace dflt { constexpr char const* serviceName = "xrpld"; constexpr char const* endpoint = "http://localhost:4318/v1/traces"; @@ -61,10 +64,11 @@ constexpr std::uint32_t batchDelayMs = 5000u; constexpr std::uint32_t maxQueueSize = 2048u; } // namespace dflt -/** Derive a human-readable network type label from the numeric network ID. - @param networkId The network identifier from [network_id] config. - @return "mainnet", "testnet", "devnet", or "unknown" for other values. -*/ +/** + * Derive a human-readable network type label from the numeric network ID. + * @param networkId The network identifier from [network_id] config. + * @return "mainnet", "testnet", "devnet", or "unknown" for other values. + */ std::string networkTypeFromId(std::uint32_t networkId) { diff --git a/src/tests/libxrpl/telemetry/TxApplySpanNames.cpp b/src/tests/libxrpl/telemetry/TxApplySpanNames.cpp index 170fef3ae4..52c4bdab0e 100644 --- a/src/tests/libxrpl/telemetry/TxApplySpanNames.cpp +++ b/src/tests/libxrpl/telemetry/TxApplySpanNames.cpp @@ -4,7 +4,8 @@ #include -/** Contract tests for the transaction apply-pipeline span constants. +/** + * Contract tests for the transaction apply-pipeline span constants. * * The span names and attribute keys in TxApplySpanNames.h are a cross-component * contract: the collector spanmetrics connector aggregates on these exact diff --git a/src/xrpld/app/main/GRPCServer.h b/src/xrpld/app/main/GRPCServer.h index 2e00fe9b54..d8b19234e9 100644 --- a/src/xrpld/app/main/GRPCServer.h +++ b/src/xrpld/app/main/GRPCServer.h @@ -197,7 +197,9 @@ private: std::vector const& secureGatewayIPs_; - /// Human-readable name for telemetry spans (e.g. "GetLedger"). + /** + * Human-readable name for telemetry spans (e.g. "GetLedger"). + */ std::string_view name_; public: diff --git a/src/xrpld/app/main/GrpcSpanNames.h b/src/xrpld/app/main/GrpcSpanNames.h index 83f4f11f57..2eb2f44ca2 100644 --- a/src/xrpld/app/main/GrpcSpanNames.h +++ b/src/xrpld/app/main/GrpcSpanNames.h @@ -1,6 +1,7 @@ #pragma once -/** Compile-time span name constants for the gRPC subsystem. +/** + * Compile-time span name constants for the gRPC subsystem. * * All span prefixes, operation names, and attribute keys used by gRPC * tracing call sites are defined here. Built on the StaticStr/join() @@ -28,19 +29,27 @@ namespace xrpl::telemetry::grpc_span { // ===== Span prefixes ======================================================= namespace prefix { -/// "grpc" — root prefix for gRPC transport spans. The full span name is -/// formed at the call site as `grpc.` (see GRPCServer.cpp). +/** + * "grpc" — root prefix for gRPC transport spans. The full span name is + * formed at the call site as `grpc.` (see GRPCServer.cpp). + */ inline constexpr auto grpc = makeStr("grpc"); } // namespace prefix // ===== Attribute keys ====================================================== namespace attr { -/// "method" — gRPC method name (e.g. GetLedger). +/** + * "method" — gRPC method name (e.g. GetLedger). + */ inline constexpr auto method = makeStr("method"); -/// "grpc_role" — Domain-qualified: collides with rpc_role. +/** + * "grpc_role" — Domain-qualified: collides with rpc_role. + */ inline constexpr auto grpcRole = makeStr("grpc_role"); -/// "grpc_status" — Domain-qualified: avoids OTel reserved span status. +/** + * "grpc_status" — Domain-qualified: avoids OTel reserved span status. + */ inline constexpr auto grpcStatus = makeStr("grpc_status"); } // namespace attr diff --git a/src/xrpld/app/misc/detail/TxQSpanNames.h b/src/xrpld/app/misc/detail/TxQSpanNames.h index 24c2cfa458..e062e361d1 100644 --- a/src/xrpld/app/misc/detail/TxQSpanNames.h +++ b/src/xrpld/app/misc/detail/TxQSpanNames.h @@ -1,6 +1,7 @@ #pragma once -/** Compile-time span name constants for Transaction Queue tracing. +/** + * Compile-time span name constants for Transaction Queue tracing. * * Covers the TxQ lifecycle: enqueue decisions, direct apply, batch * clear, ledger-close accept loop, per-tx apply, and cleanup. @@ -55,7 +56,9 @@ namespace xrpl::telemetry::txq_span { // ===== Span prefixes ======================================================= namespace prefix { -/// "txq" — root prefix for transaction queue spans. +/** + * "txq" — root prefix for transaction queue spans. + */ inline constexpr auto txq = makeStr("txq"); } // namespace prefix @@ -73,29 +76,51 @@ inline constexpr auto cleanup = makeStr("cleanup"); // ===== Attribute keys ====================================================== namespace attr { -/// Canonical shared constants (defined in SpanNames.h). +/** + * Canonical shared constants (defined in SpanNames.h). + */ using ::xrpl::telemetry::attr::ledgerSeq; using ::xrpl::telemetry::attr::txHash; -/// "txq_status" — domain-qualified (collides with tx_status, rpc_status). +/** + * "txq_status" — domain-qualified (collides with tx_status, rpc_status). + */ inline constexpr auto txqStatus = makeStr("txq_status"); -/// "fee_level_paid" — fee level paid by queued tx. +/** + * "fee_level_paid" — fee level paid by queued tx. + */ inline constexpr auto feeLevelPaid = makeStr("fee_level_paid"); -/// "required_fee_level" — minimum fee level for inclusion. +/** + * "required_fee_level" — minimum fee level for inclusion. + */ inline constexpr auto requiredFeeLevel = makeStr("required_fee_level"); -/// "queue_size" — current TxQ depth. +/** + * "queue_size" — current TxQ depth. + */ inline constexpr auto queueSize = makeStr("queue_size"); -/// "ledger_changed" — whether ledger changed since last attempt. +/** + * "ledger_changed" — whether ledger changed since last attempt. + */ inline constexpr auto ledgerChanged = makeStr("ledger_changed"); -/// "expired_count" — number of expired entries cleared. +/** + * "expired_count" — number of expired entries cleared. + */ inline constexpr auto expiredCount = makeStr("expired_count"); -/// "ter_code" — transaction engine result code. +/** + * "ter_code" — transaction engine result code. + */ inline constexpr auto terCode = makeStr("ter_code"); -/// "retries_remaining" — retries left before discard. +/** + * "retries_remaining" — retries left before discard. + */ inline constexpr auto retriesRemaining = makeStr("retries_remaining"); -/// "num_cleared" — entries cleared in batch. +/** + * "num_cleared" — entries cleared in batch. + */ inline constexpr auto numCleared = makeStr("num_cleared"); -/// "tx_type" — transaction type name (e.g., "Payment", "OfferCreate"). +/** + * "tx_type" — transaction type name (e.g., "Payment", "OfferCreate"). + */ inline constexpr auto txType = makeStr("tx_type"); } // namespace attr diff --git a/src/xrpld/consensus/ConsensusSpanNames.h b/src/xrpld/consensus/ConsensusSpanNames.h index c516807af5..6c79cd3132 100644 --- a/src/xrpld/consensus/ConsensusSpanNames.h +++ b/src/xrpld/consensus/ConsensusSpanNames.h @@ -1,6 +1,7 @@ #pragma once -/** Compile-time span name constants for consensus tracing. +/** + * Compile-time span name constants for consensus tracing. * * Used by RCLConsensus (app), Consensus.h (template), and PeerImp * (overlay) for consensus lifecycle spans. @@ -125,9 +126,11 @@ inline constexpr auto phaseOpen = join(seg::consensus, op::phaseOpen); // ===== Attribute keys ======================================================== namespace attr { -/// Canonical shared constants (defined in SpanNames.h). `ledgerHash` and -/// `fullValidation` are shared with the peer.validation.receive span — same -/// concept, same key, distinguished by span name (not an emitter prefix). +/** + * Canonical shared constants (defined in SpanNames.h). `ledgerHash` and + * `fullValidation` are shared with the peer.validation.receive span — same + * concept, same key, distinguished by span name (not an emitter prefix). + */ using ::xrpl::telemetry::attr::closeResolutionMs; using ::xrpl::telemetry::attr::closeTime; using ::xrpl::telemetry::attr::closeTimeCorrect; @@ -135,43 +138,67 @@ using ::xrpl::telemetry::attr::fullValidation; using ::xrpl::telemetry::attr::ledgerHash; using ::xrpl::telemetry::attr::ledgerSeq; -/// Domain-qualified attrs (rule 5 — bare name ambiguous across domains). -/// Use `_` underscore form for TraceQL ergonomics. +/** + * Domain-qualified attrs (rule 5 — bare name ambiguous across domains). + * Use `_` underscore form for TraceQL ergonomics. + */ inline constexpr auto ledgerId = makeStr("consensus_ledger_id"); inline constexpr auto mode = makeStr("consensus_mode"); inline constexpr auto round = makeStr("consensus_round"); inline constexpr auto roundId = makeStr("consensus_round_id"); -/// Current phase name attached to consensus.round; updated on each -/// phase transition event (open/establish/accepted). +/** + * Current phase name attached to consensus.round; updated on each + * phase transition event (open/establish/accepted). + */ inline constexpr auto consensusPhase = makeStr("consensus_phase"); -/// Boolean flag set on consensus.check when checkConsensus reports stalled. +/** + * Boolean flag set on consensus.check when checkConsensus reports stalled. + */ inline constexpr auto consensusStalled = makeStr("consensus_stalled"); -/// Domain-owned bare attrs. +/** + * Domain-owned bare attrs. + */ inline constexpr auto proposers = makeStr("proposers"); inline constexpr auto roundTimeMs = makeStr("round_time_ms"); inline constexpr auto proposing = makeStr("proposing"); -/// Round continuity / context attrs (set on consensus.round at round start). +/** + * Round continuity / context attrs (set on consensus.round at round start). + */ inline constexpr auto previousProposers = makeStr("previous_proposers"); inline constexpr auto previousRoundTimeMs = makeStr("previous_round_time_ms"); inline constexpr auto previousLedgerSeq = makeStr("previous_ledger_seq"); inline constexpr auto closeTimeResolutionMs = makeStr("close_time_resolution_ms"); -/// Open-phase end metadata (set on consensus.phase.open before reset). +/** + * Open-phase end metadata (set on consensus.phase.open before reset). + */ inline constexpr auto openDurationMs = makeStr("open_duration_ms"); inline constexpr auto peerPositionsAtClose = makeStr("peer_positions_at_close"); -/// Ledger-close inputs. +/** + * Ledger-close inputs. + */ inline constexpr auto txCountOpen = makeStr("tx_count_open"); -/// Establish/check additional state. +/** + * Establish/check additional state. + */ inline constexpr auto proposersFinished = makeStr("proposers_finished"); -/// Accept/apply enrichment. +/** + * Accept/apply enrichment. + */ inline constexpr auto disputesResolvedCount = makeStr("disputes_resolved_count"); -/// Validation send/receive enrichment. (`full_validation` is shared — see the -/// `using` re-export above.) +/** + * Validation send/receive enrichment. (`full_validation` is shared — see the + * `using` re-export above.) + */ inline constexpr auto validationSignTime = makeStr("validation_sign_time"); -/// Receive-side hash prefixes for cross-peer correlation. +/** + * Receive-side hash prefixes for cross-peer correlation. + */ inline constexpr auto prevLedgerPrefix = makeStr("prev_ledger_prefix"); inline constexpr auto positionHashPrefix = makeStr("position_hash_prefix"); -/// "consensus_state" — domain-qualified (collides with other domains' state). +/** + * "consensus_state" — domain-qualified (collides with other domains' state). + */ inline constexpr auto consensusState = makeStr("consensus_state"); inline constexpr auto parentCloseTime = makeStr("parent_close_time"); inline constexpr auto closeTimeSelf = makeStr("close_time_self"); @@ -185,27 +212,35 @@ inline constexpr auto haveCloseTimeConsensus = makeStr("have_close_time_consensu inline constexpr auto agreeCount = makeStr("agree_count"); inline constexpr auto disagreeCount = makeStr("disagree_count"); inline constexpr auto thresholdPercent = makeStr("threshold_percent"); -/// "consensus_result" — domain-qualified (collides with generic result). +/** + * "consensus_result" — domain-qualified (collides with generic result). + */ inline constexpr auto consensusResult = makeStr("consensus_result"); inline constexpr auto quorum = makeStr("quorum"); inline constexpr auto traceStrategy = makeStr("trace_strategy"); inline constexpr auto modeOld = makeStr("mode_old"); inline constexpr auto modeNew = makeStr("mode_new"); -/// "is_bow_out" — whether this proposal is a bow-out (resigning from round). +/** + * "is_bow_out" — whether this proposal is a bow-out (resigning from round). + */ inline constexpr auto isBowOut = makeStr("is_bow_out"); -/// Transaction/dispute attrs used in consensus accept spans. +/** + * Transaction/dispute attrs used in consensus accept spans. + */ inline constexpr auto txId = makeStr("tx_id"); inline constexpr auto disputeOurVote = makeStr("dispute_our_vote"); inline constexpr auto disputeYays = makeStr("dispute_yays"); inline constexpr auto disputeNays = makeStr("dispute_nays"); inline constexpr auto txCount = makeStr("tx_count"); inline constexpr auto disputesCount = makeStr("disputes_count"); -/// Trust flag (is the message origin a trusted UNL validator). Qualified by -/// message type, shared with the peer.{proposal,validation}.receive spans: -/// consensus.proposal.receive uses `proposal_trusted`, consensus.validation. -/// receive uses `validation_trusted`. Same concept on both emitters → same key. +/** + * Trust flag (is the message origin a trusted UNL validator). Qualified by + * message type, shared with the peer.{proposal,validation}.receive spans: + * consensus.proposal.receive uses `proposal_trusted`, consensus.validation. + * receive uses `validation_trusted`. Same concept on both emitters → same key. + */ inline constexpr auto proposalTrusted = makeStr("proposal_trusted"); inline constexpr auto validationTrusted = makeStr("validation_trusted"); } // namespace attr @@ -213,21 +248,29 @@ inline constexpr auto validationTrusted = makeStr("validation_trusted"); // ===== Event names =========================================================== namespace event { -/// "dispute.resolve" +/** + * "dispute.resolve" + */ inline constexpr auto disputeResolve = join(makeStr("dispute"), makeStr("resolve")); -/// "tx.included" +/** + * "tx.included" + */ inline constexpr auto txIncluded = join(makeStr("tx"), makeStr("included")); -/// Phase transition events — fired on consensus.round at each transition -/// so the round-level span carries a complete timeline of phase changes, -/// including the handleWrongLedger recovery edge that re-enters Open. +/** + * Phase transition events — fired on consensus.round at each transition + * so the round-level span carries a complete timeline of phase changes, + * including the handleWrongLedger recovery edge that re-enters Open. + */ inline constexpr auto phaseOpen = join(makeStr("phase"), makeStr("open")); inline constexpr auto phaseEstablish = join(makeStr("phase"), makeStr("establish")); inline constexpr auto phaseAccepted = join(makeStr("phase"), makeStr("accepted")); inline constexpr auto phaseRecovery = join(makeStr("phase"), makeStr("recovery")); -/// Outcome events — fired on consensus.round at the establish→accepted -/// transition so the path that drove acceptance is queryable. +/** + * Outcome events — fired on consensus.round at the establish→accepted + * transition so the path that drove acceptance is queryable. + */ inline constexpr auto outcomeYes = join(makeStr("outcome"), makeStr("yes")); inline constexpr auto outcomeMovedOn = join(makeStr("outcome"), makeStr("moved_on")); inline constexpr auto outcomeExpired = join(makeStr("outcome"), makeStr("expired")); diff --git a/src/xrpld/rpc/ServerHandler.h b/src/xrpld/rpc/ServerHandler.h index 2b9701a6b4..fbe487654e 100644 --- a/src/xrpld/rpc/ServerHandler.h +++ b/src/xrpld/rpc/ServerHandler.h @@ -192,10 +192,11 @@ private: void processSession(std::shared_ptr const&, std::shared_ptr coro); - /** Process an RPC request and write the reply to `output`. - @return false if the request resulted in an error response, true - otherwise. Lets the caller's enclosing span reflect the outcome. - */ + /** + * Process an RPC request and write the reply to `output`. + * @return false if the request resulted in an error response, true + * otherwise. Lets the caller's enclosing span reflect the outcome. + */ bool processRequest( Port const& port, diff --git a/src/xrpld/rpc/detail/PathFindSpanNames.h b/src/xrpld/rpc/detail/PathFindSpanNames.h index 71eb805ea3..65ce81bb96 100644 --- a/src/xrpld/rpc/detail/PathFindSpanNames.h +++ b/src/xrpld/rpc/detail/PathFindSpanNames.h @@ -1,6 +1,7 @@ #pragma once -/** Compile-time span name constants for PathFind tracing. +/** + * Compile-time span name constants for PathFind tracing. * * Covers the path_find and ripple_path_find RPC handlers, the * PathRequest computation engine, and the Pathfinder graph exploration. @@ -48,7 +49,9 @@ namespace xrpl::telemetry::pathfind_span { // ===== Span prefixes ======================================================= namespace prefix { -/// "pathfind" — root prefix for path finding spans. +/** + * "pathfind" — root prefix for path finding spans. + */ inline constexpr auto pathfind = makeStr("pathfind"); } // namespace prefix @@ -68,25 +71,43 @@ inline constexpr auto discover = makeStr("discover"); // `fast` or `num_paths` that other subsystems may introduce. namespace attr { -/// "pathfind_source_account" — originating account for path search. +/** + * "pathfind_source_account" — originating account for path search. + */ inline constexpr auto sourceAccount = makeStr("pathfind_source_account"); -/// "pathfind_dest_account" — destination account. +/** + * "pathfind_dest_account" — destination account. + */ inline constexpr auto destAccount = makeStr("pathfind_dest_account"); -/// "pathfind_fast" — whether fast pathfinding mode enabled. +/** + * "pathfind_fast" — whether fast pathfinding mode enabled. + */ inline constexpr auto fast = makeStr("pathfind_fast"); -/// "pathfind_search_level" — depth of graph exploration. +/** + * "pathfind_search_level" — depth of graph exploration. + */ inline constexpr auto searchLevel = makeStr("pathfind_search_level"); -/// "pathfind_num_paths" — total paths produced across the per-source-asset -/// loop in PathRequest::findPaths (sum of getBestPaths().size() per asset). +/** + * "pathfind_num_paths" — total paths produced across the per-source-asset + * loop in PathRequest::findPaths (sum of getBestPaths().size() per asset). + */ inline constexpr auto numPaths = makeStr("pathfind_num_paths"); -/// "pathfind_num_requests" — snapshot size of requests_ at update_all start -/// (may include weak_ptrs that subsequently expire during processing). +/** + * "pathfind_num_requests" — snapshot size of requests_ at update_all start + * (may include weak_ptrs that subsequently expire during processing). + */ inline constexpr auto numRequests = makeStr("pathfind_num_requests"); -/// "pathfind_ledger_index" — pathfind target ledger index. +/** + * "pathfind_ledger_index" — pathfind target ledger index. + */ inline constexpr auto ledgerIndex = makeStr("pathfind_ledger_index"); -/// "pathfind_dest_currency" — destination currency code. +/** + * "pathfind_dest_currency" — destination currency code. + */ inline constexpr auto destCurrency = makeStr("pathfind_dest_currency"); -/// "pathfind_num_source_assets" — candidate source assets count. +/** + * "pathfind_num_source_assets" — candidate source assets count. + */ inline constexpr auto numSourceAssets = makeStr("pathfind_num_source_assets"); } // namespace attr diff --git a/src/xrpld/rpc/detail/RpcSpanNames.h b/src/xrpld/rpc/detail/RpcSpanNames.h index 88fd299f29..07202a7592 100644 --- a/src/xrpld/rpc/detail/RpcSpanNames.h +++ b/src/xrpld/rpc/detail/RpcSpanNames.h @@ -1,6 +1,7 @@ #pragma once -/** Compile-time span name constants for the RPC subsystem. +/** + * Compile-time span name constants for the RPC subsystem. * * All span prefixes, operation names, and attribute keys used by RPC * tracing call sites are defined here. Built on the StaticStr/join() @@ -116,9 +117,13 @@ namespace xrpl::telemetry::rpc_span { // ===== Span prefixes ======================================================= namespace prefix { -/// "rpc" — root prefix for transport-level spans. +/** + * "rpc" — root prefix for transport-level spans. + */ inline constexpr auto rpc = seg::rpc; -/// "rpc.command" — prefix for individual RPC command spans. +/** + * "rpc.command" — prefix for individual RPC command spans. + */ inline constexpr auto command = join(seg::rpc, makeStr("command")); } // namespace prefix @@ -134,21 +139,37 @@ inline constexpr auto process = makeStr("process"); // ===== Attribute keys ====================================================== namespace attr { -/// "command" — RPC method name. +/** + * "command" — RPC method name. + */ inline constexpr auto command = makeStr("command"); -/// "version" — api_version per request. +/** + * "version" — api_version per request. + */ inline constexpr auto version = makeStr("version"); -/// "rpc_role" — admin|user. Domain-qualified: collides with grpc_role. +/** + * "rpc_role" — admin|user. Domain-qualified: collides with grpc_role. + */ inline constexpr auto rpcRole = makeStr("rpc_role"); -/// "rpc_status" — success|error. Domain-qualified: avoids OTel reserved span status. +/** + * "rpc_status" — success|error. Domain-qualified: avoids OTel reserved span status. + */ inline constexpr auto rpcStatus = makeStr("rpc_status"); -/// "request_payload_size" — bytes of inbound request payload. +/** + * "request_payload_size" — bytes of inbound request payload. + */ inline constexpr auto requestPayloadSize = makeStr("request_payload_size"); -/// "is_batch" — whether request is a JSON-RPC batch. +/** + * "is_batch" — whether request is a JSON-RPC batch. + */ inline constexpr auto isBatch = makeStr("is_batch"); -/// "batch_size" — number of sub-requests in a batch. +/** + * "batch_size" — number of sub-requests in a batch. + */ inline constexpr auto batchSize = makeStr("batch_size"); -/// "load_type" — resource cost category after execution. +/** + * "load_type" — resource cost category after execution. + */ inline constexpr auto loadType = makeStr("load_type"); } // namespace attr @@ -160,7 +181,9 @@ using telemetry::attr_val::success; inline constexpr auto admin = makeStr("admin"); inline constexpr auto user = makeStr("user"); inline constexpr auto unknownCommand = makeStr("unknown"); -/// "invalid_json" — WS message parse failure or oversize. +/** + * "invalid_json" — WS message parse failure or oversize. + */ inline constexpr auto invalidJson = makeStr("invalid_json"); } // namespace val diff --git a/src/xrpld/telemetry/PropagationHelpers.h b/src/xrpld/telemetry/PropagationHelpers.h index 44959ae039..ff6f8e71fe 100644 --- a/src/xrpld/telemetry/PropagationHelpers.h +++ b/src/xrpld/telemetry/PropagationHelpers.h @@ -1,6 +1,7 @@ #pragma once -/** Helpers for injecting trace context into protobuf messages. +/** + * Helpers for injecting trace context into protobuf messages. * * Bridges the gap between SpanGuard (which hides OTel types) and the * protobuf TraceContext message used for cross-node propagation. @@ -13,7 +14,7 @@ * | | * injectSpanContext(span, proto) * - * @note When XRPL_ENABLE_TELEMETRY is disabled, getTraceBytes() returns + * @note When XRPL_ENABLE_TELEMETRY is disabled, getTraceBytes() returns * {.valid=false}, so injectSpanContext becomes a no-op with zero overhead. * * Usage: @@ -25,8 +26,8 @@ * overlay.relay(txID, tx, toSkip); * @endcode * - * @see ConsensusReceiveTracing.h for receive-side extraction helpers. - * @see TraceContextPropagator.h for low-level OTel context serialization. + * @see ConsensusReceiveTracing.h for receive-side extraction helpers. + * @see TraceContextPropagator.h for low-level OTel context serialization. */ #include @@ -34,7 +35,8 @@ namespace xrpl::telemetry { -/** Inject trace context from an active SpanGuard into a protobuf +/** + * Inject trace context from an active SpanGuard into a protobuf * TraceContext message for cross-node propagation. * * Reads the span's trace_id, span_id, and trace_flags via @@ -42,8 +44,8 @@ namespace xrpl::telemetry { * Safe to call from any thread that holds a reference to the span. * No-op if the span is null or inactive. * - * @param span The active SpanGuard whose context to propagate. - * @param proto The protobuf TraceContext to populate. + * @param span The active SpanGuard whose context to propagate. + * @param proto The protobuf TraceContext to populate. */ inline void injectSpanContext(SpanGuard const& span, protocol::TraceContext& proto) diff --git a/src/xrpld/telemetry/TxSpanNames.h b/src/xrpld/telemetry/TxSpanNames.h index 443171c5c9..e8d75f17af 100644 --- a/src/xrpld/telemetry/TxSpanNames.h +++ b/src/xrpld/telemetry/TxSpanNames.h @@ -1,6 +1,7 @@ #pragma once -/** Compile-time span name constants for transaction tracing. +/** + * Compile-time span name constants for transaction tracing. * * Used by PeerImp (overlay) and NetworkOPs (app) for transaction * lifecycle spans. Built on StaticStr/join() from SpanNames.h. @@ -22,7 +23,9 @@ namespace xrpl::telemetry::tx_span { // ===== Span prefixes ======================================================= namespace prefix { -/// "tx" — root prefix for transaction lifecycle spans. +/** + * "tx" — root prefix for transaction lifecycle spans. + */ inline constexpr auto tx = seg::tx; } // namespace prefix @@ -41,29 +44,51 @@ inline constexpr auto process = join(prefix::tx, op::process); // ===== Attribute keys ====================================================== namespace attr { -/// Canonical shared constants (defined in SpanNames.h). +/** + * Canonical shared constants (defined in SpanNames.h). + */ using ::xrpl::telemetry::attr::peerId; using ::xrpl::telemetry::attr::txHash; -/// "local" — whether tx originated locally. +/** + * "local" — whether tx originated locally. + */ inline constexpr auto local = makeStr("local"); -/// "path" — sync or async processing path. +/** + * "path" — sync or async processing path. + */ inline constexpr auto path = makeStr("path"); -/// "suppressed" — whether tx was suppressed as duplicate. +/** + * "suppressed" — whether tx was suppressed as duplicate. + */ inline constexpr auto suppressed = makeStr("suppressed"); -/// "tx_status" — domain-qualified (collides with rpc_status, txq_status). +/** + * "tx_status" — domain-qualified (collides with rpc_status, txq_status). + */ inline constexpr auto txStatus = makeStr("tx_status"); -/// "peer_version" — version of peer that sent the tx. +/** + * "peer_version" — version of peer that sent the tx. + */ inline constexpr auto peerVersion = makeStr("peer_version"); -/// "tx_type" — transaction type name (e.g., "Payment", "OfferCreate"). +/** + * "tx_type" — transaction type name (e.g., "Payment", "OfferCreate"). + */ inline constexpr auto txType = makeStr("tx_type"); -/// "fee" — transaction fee in drops. +/** + * "fee" — transaction fee in drops. + */ inline constexpr auto fee = makeStr("fee"); -/// "sequence" — transaction sequence number. +/** + * "sequence" — transaction sequence number. + */ inline constexpr auto sequence = makeStr("sequence"); -/// "ter_result" — engine result code after application. +/** + * "ter_result" — engine result code after application. + */ inline constexpr auto terResult = makeStr("ter_result"); -/// "applied" — whether the transaction was applied to the ledger. +/** + * "applied" — whether the transaction was applied to the ledger. + */ inline constexpr auto applied = makeStr("applied"); } // namespace attr @@ -73,16 +98,24 @@ namespace val { inline constexpr auto sync = makeStr("sync"); inline constexpr auto async = makeStr("async"); inline constexpr auto knownBad = makeStr("known_bad"); -/// Transaction was suppressed via HashRouter (duplicate, not flagged bad). +/** + * Transaction was suppressed via HashRouter (duplicate, not flagged bad). + */ inline constexpr auto suppressed = makeStr("suppressed"); -/// Transaction was rejected because it carried tfInnerBatchTxn, which -/// must never appear in network-relayed traffic. +/** + * Transaction was rejected because it carried tfInnerBatchTxn, which + * must never appear in network-relayed traffic. + */ inline constexpr auto rejectedInnerBatch = makeStr("rejected_inner_batch"); -/// Transaction was dropped because the validated ledger is too old to -/// confidently apply new transactions (server is out of sync). +/** + * Transaction was dropped because the validated ledger is too old to + * confidently apply new transactions (server is out of sync). + */ inline constexpr auto droppedNoSync = makeStr("dropped_no_sync"); -/// Transaction was dropped because the local job queue for jtTRANSACTION -/// is at MAX_TRANSACTIONS — backpressure on the receive side. +/** + * Transaction was dropped because the local job queue for jtTRANSACTION + * is at MAX_TRANSACTIONS — backpressure on the receive side. + */ inline constexpr auto droppedQueueFull = makeStr("dropped_queue_full"); } // namespace val diff --git a/src/xrpld/telemetry/TxTracing.h b/src/xrpld/telemetry/TxTracing.h index a6633034d3..02900fa9b4 100644 --- a/src/xrpld/telemetry/TxTracing.h +++ b/src/xrpld/telemetry/TxTracing.h @@ -1,6 +1,7 @@ #pragma once -/** Helper functions for creating transaction trace spans. +/** + * Helper functions for creating transaction trace spans. * * Encapsulates the logic for creating SpanGuard instances with * hash-derived trace IDs and optional protobuf parent extraction. @@ -21,7 +22,8 @@ namespace xrpl::telemetry { -/** Create a "tx.receive" span for a transaction received from a peer. +/** + * Create a "tx.receive" span for a transaction received from a peer. * trace_id is derived from txID[0:16]. If the incoming message carries * a protobuf TraceContext with a valid span_id, it is used as the * parent to preserve relay ordering. @@ -53,7 +55,8 @@ txReceiveSpan(uint256 const& txID, [[maybe_unused]] protocol::TMTransaction cons TraceCategory::Transactions, tx_span::receive, txID.data(), txID.kBytes); } -/** Create a "tx.process" span for transaction processing in NetworkOPs. +/** + * Create a "tx.process" span for transaction processing in NetworkOPs. * trace_id is derived from txID[0:16]. */ inline SpanGuard