mirror of
https://github.com/XRPLF/rippled.git
synced 2026-07-28 17:40:25 +00:00
fix(telemetry): address review findings and PR #6437 comments
Critical fixes: - Restore accidentally removed mallocTrim call and MallocTrim.h include - Add missing shouldTraceLedger() to interface and all implementations - Derive networkId/networkType from config_->NETWORK_ID (0=mainnet, 1=testnet, 2=devnet) instead of leaving defaults unpopulated - Clamp sampling_ratio to [0.0, 1.0] in config parser PR comment fixes: - Rename rippled -> xrpld in service name defaults, getTracer() calls, Docker network, comments, and docs/build/telemetry.md - Remove exporter config option (only otlp_http supported) - Add trace_ledger and service_name to example config - Clarify head-based sampling semantics in config comments - Add filter descriptions for span intrinsic filters in Grafana datasource - Add inline comments to Docker Compose services Docker/config improvements: - Remove deprecated version: "3.8" from docker-compose.yml - Pin images: collector 0.121.0, grafana 11.5.2 - Add health_check extension to otel-collector-config.yaml - Comment out Tempo metrics_generator remote_write (no Prometheus service) - Add Prometheus datasource caveat in Grafana datasource config Other: - Revert unrelated formatting changes in ServiceRegistry.h - Change Conan telemetry default to False (matches CMake OFF) - Add CLAUDE.md-required docs (ASCII diagrams, usage examples, @note thread-safety) to Telemetry.h and SpanGuard.h Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -25,17 +25,18 @@ class Telemetry;
|
||||
// This is temporary until we migrate all code to use ServiceRegistry.
|
||||
class Application;
|
||||
|
||||
template <class Key,
|
||||
class T,
|
||||
bool IsKeyCache,
|
||||
class SharedWeakUnionPointer,
|
||||
class SharedPointerType,
|
||||
class Hash,
|
||||
class KeyEqual,
|
||||
class Mutex>
|
||||
template <
|
||||
class Key,
|
||||
class T,
|
||||
bool IsKeyCache,
|
||||
class SharedWeakUnionPointer,
|
||||
class SharedPointerType,
|
||||
class Hash,
|
||||
class KeyEqual,
|
||||
class Mutex>
|
||||
class TaggedCache;
|
||||
class STLedgerEntry;
|
||||
using SLE = STLedgerEntry;
|
||||
using SLE = STLedgerEntry;
|
||||
using CachedSLEs = TaggedCache<uint256, SLE const>;
|
||||
|
||||
// Forward declarations
|
||||
@@ -93,7 +94,7 @@ using NodeCache = TaggedCache<SHAMapHash, Blob>;
|
||||
class ServiceRegistry
|
||||
{
|
||||
public:
|
||||
ServiceRegistry() = default;
|
||||
ServiceRegistry() = default;
|
||||
virtual ~ServiceRegistry() = default;
|
||||
|
||||
// Core infrastructure services
|
||||
|
||||
@@ -6,10 +6,65 @@
|
||||
activated on the current thread's context (via Scope). On destruction,
|
||||
the span is ended and the previous context is restored.
|
||||
|
||||
Dependency diagram:
|
||||
|
||||
+------------------------------------+
|
||||
| SpanGuard |
|
||||
+------------------------------------+
|
||||
| - span_ : shared_ptr<Span> |
|
||||
| - scope_ : Scope |
|
||||
+------------------------------------+
|
||||
| uses
|
||||
+-------+-------+
|
||||
| |
|
||||
+--------+ +-------------+
|
||||
| Span | | Scope |
|
||||
| (OTel) | | (OTel, non- |
|
||||
| | | movable) |
|
||||
+--------+ +-------------+
|
||||
|
||||
Used by the XRPL_TRACE_* macros in TracingInstrumentation.h. Can also
|
||||
be stored in std::optional for conditional tracing (move-constructible).
|
||||
|
||||
Only compiled when XRPL_ENABLE_TELEMETRY is defined.
|
||||
|
||||
Usage examples:
|
||||
|
||||
1. Basic RAII tracing:
|
||||
@code
|
||||
{
|
||||
SpanGuard guard(telemetry.startSpan("rpc.command.submit"));
|
||||
guard.setAttribute("xrpl.rpc.command", "submit");
|
||||
// ... span is active on this thread's context
|
||||
} // span ended, previous context restored
|
||||
@endcode
|
||||
|
||||
2. Conditional tracing with std::optional:
|
||||
@code
|
||||
std::optional<SpanGuard> guard;
|
||||
if (telemetry.isEnabled() && telemetry.shouldTraceRpc())
|
||||
guard.emplace(telemetry.startSpan("rpc.request"));
|
||||
// ... guard may or may not hold a span
|
||||
@endcode
|
||||
|
||||
3. Error recording:
|
||||
@code
|
||||
SpanGuard guard(telemetry.startSpan("rpc.command.submit"));
|
||||
try {
|
||||
// ... do work
|
||||
guard.setOk();
|
||||
} catch (std::exception const& e) {
|
||||
guard.recordException(e); // sets status to error
|
||||
}
|
||||
@endcode
|
||||
|
||||
@note Thread safety: A SpanGuard must only be used on the thread where
|
||||
it was constructed (the Scope binds to the thread-local context stack).
|
||||
Use context() to propagate the trace to other threads.
|
||||
|
||||
@note Limitation: Move assignment is deleted because re-scoping a span
|
||||
mid-flight would corrupt the context stack. Only move construction is
|
||||
supported (for std::optional emplacement).
|
||||
*/
|
||||
|
||||
#ifdef XRPL_ENABLE_TELEMETRY
|
||||
|
||||
@@ -3,19 +3,70 @@
|
||||
/** Abstract interface for OpenTelemetry distributed tracing.
|
||||
|
||||
Provides the Telemetry base class that all components use to create trace
|
||||
spans. Two implementations exist:
|
||||
spans. Two concrete implementations exist, selected at construction time
|
||||
by make_Telemetry():
|
||||
|
||||
- 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.
|
||||
|
||||
Inheritance / dependency diagram:
|
||||
|
||||
+--------------------+
|
||||
| Telemetry | (abstract, this file)
|
||||
| <<interface>> |
|
||||
+---------+----------+
|
||||
|
|
||||
+---------+-----------+-------------------+
|
||||
| | |
|
||||
+---+------------+ +-----+---------+ +------+----------+
|
||||
| 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. Check before tracing (typical guard pattern):
|
||||
@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
|
||||
}
|
||||
@endcode
|
||||
|
||||
2. RAII tracing with SpanGuard (preferred):
|
||||
@code
|
||||
if (telemetry.isEnabled() && telemetry.shouldTraceRpc())
|
||||
{
|
||||
SpanGuard guard(telemetry.startSpan("rpc.command.submit"));
|
||||
guard.setAttribute("xrpl.rpc.command", "submit");
|
||||
// ... guard ends span automatically on scope exit
|
||||
}
|
||||
@endcode
|
||||
|
||||
3. Cross-thread context propagation:
|
||||
@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);
|
||||
@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 <xrpl/basics/BasicConfig.h>
|
||||
@@ -50,7 +101,7 @@ public:
|
||||
bool enabled = false;
|
||||
|
||||
/** OTel resource attribute `service.name`. */
|
||||
std::string serviceName = "rippled";
|
||||
std::string serviceName = "xrpld";
|
||||
|
||||
/** OTel resource attribute `service.version` (set from BuildInfo). */
|
||||
std::string serviceVersion;
|
||||
@@ -59,9 +110,6 @@ public:
|
||||
public key). */
|
||||
std::string serviceInstanceId;
|
||||
|
||||
/** Exporter type: currently only "otlp_http" is supported. */
|
||||
std::string exporterType = "otlp_http";
|
||||
|
||||
/** OTLP/HTTP endpoint URL where spans are sent. */
|
||||
std::string exporterEndpoint = "http://localhost:4318/v1/traces";
|
||||
|
||||
@@ -157,6 +205,10 @@ public:
|
||||
virtual bool
|
||||
shouldTracePeer() const = 0;
|
||||
|
||||
/** @return true if ledger close/accept should be traced. */
|
||||
virtual bool
|
||||
shouldTraceLedger() const = 0;
|
||||
|
||||
#ifdef XRPL_ENABLE_TELEMETRY
|
||||
/** Get or create a named tracer instance.
|
||||
|
||||
@@ -164,7 +216,7 @@ public:
|
||||
@return A shared pointer to the Tracer.
|
||||
*/
|
||||
virtual opentelemetry::nostd::shared_ptr<opentelemetry::trace::Tracer>
|
||||
getTracer(std::string_view name = "rippled") = 0;
|
||||
getTracer(std::string_view name = "xrpld") = 0;
|
||||
|
||||
/** Start a new span on the current thread's context.
|
||||
|
||||
@@ -214,13 +266,16 @@ make_Telemetry(Telemetry::Setup const& setup, beast::Journal journal);
|
||||
@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
|
||||
setup_Telemetry(
|
||||
Section const& section,
|
||||
std::string const& nodePublicKey,
|
||||
std::string const& version);
|
||||
std::string const& version,
|
||||
std::uint32_t networkId);
|
||||
|
||||
} // namespace telemetry
|
||||
} // namespace xrpl
|
||||
|
||||
Reference in New Issue
Block a user