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

Signed-off-by: Pratik Mankawde <3397372+pratikmankawde@users.noreply.github.com>
This commit is contained in:
Pratik Mankawde
2026-05-29 14:51:12 +01:00
10 changed files with 68 additions and 74 deletions

View File

@@ -1,25 +1,23 @@
/** No-op implementation of the Telemetry interface.
Always compiled (regardless of XRPL_ENABLE_TELEMETRY). Provides the
make_Telemetry() factory when telemetry is compiled out (#ifndef), which
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 make_Telemetry()
(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 <xrpl/beast/utility/Journal.h>
#include <xrpl/telemetry/Telemetry.h>
#include <string_view>
#ifdef XRPL_ENABLE_TELEMETRY
#include <opentelemetry/trace/noop.h>
#endif
#include <memory>
#include <utility>
namespace xrpl::telemetry {
namespace {
@@ -122,7 +120,7 @@ public:
*/
#ifndef XRPL_ENABLE_TELEMETRY
std::unique_ptr<Telemetry>
make_Telemetry(Telemetry::Setup const& setup, beast::Journal)
makeTelemetry(Telemetry::Setup const& setup, beast::Journal)
{
return std::make_unique<NullTelemetry>(setup);
}

View File

@@ -35,12 +35,15 @@
#include <opentelemetry/trace/span_startoptions.h>
#include <opentelemetry/trace/tracer.h>
#include <cstdint>
#include <exception>
#include <memory>
#include <string>
#include <string_view>
#include <typeinfo>
#include <utility>
namespace xrpl {
namespace telemetry {
namespace xrpl::telemetry {
namespace otel_trace = opentelemetry::trace;
@@ -164,7 +167,7 @@ SpanGuard
SpanGuard::span(TraceCategory cat, std::string_view prefix, std::string_view name)
{
auto* tel = Telemetry::getInstance();
if (!tel || !tel->isEnabled() || !isCategoryEnabled(*tel, cat))
if ((tel == nullptr) || !tel->isEnabled() || !isCategoryEnabled(*tel, cat))
return {};
auto fullName = std::string(prefix) + "." + std::string(name);
return SpanGuard(std::make_unique<Impl>(tel->startSpan(fullName, categoryToSpanKind(cat))));
@@ -178,7 +181,7 @@ SpanGuard::childSpan(std::string_view name) const
if (!impl_)
return {};
auto* tel = Telemetry::getInstance();
if (!tel || !tel->isEnabled())
if ((tel == nullptr) || !tel->isEnabled())
return {};
auto ctx = opentelemetry::context::RuntimeContext::GetCurrent();
return SpanGuard(std::make_unique<Impl>(tel->startSpan(name, ctx)));
@@ -190,7 +193,7 @@ SpanGuard::childSpan(std::string_view name, SpanContext const& parentCtx)
if (!parentCtx.isValid())
return {};
auto* tel = Telemetry::getInstance();
if (!tel || !tel->isEnabled())
if ((tel == nullptr) || !tel->isEnabled())
return {};
return SpanGuard(std::make_unique<Impl>(tel->startSpan(name, parentCtx.impl_->ctx)));
}
@@ -201,7 +204,7 @@ SpanGuard::linkedSpan(std::string_view name) const
if (!impl_)
return {};
auto* tel = Telemetry::getInstance();
if (!tel || !tel->isEnabled())
if ((tel == nullptr) || !tel->isEnabled())
return {};
auto tracer = tel->getTracer("xrpld");
@@ -228,7 +231,7 @@ SpanGuard::linkedSpan(std::string_view name, SpanContext const& linkCtx)
if (!linkCtx.isValid())
return {};
auto* tel = Telemetry::getInstance();
if (!tel || !tel->isEnabled())
if ((tel == nullptr) || !tel->isEnabled())
return {};
auto tracer = tel->getTracer("xrpld");
@@ -271,9 +274,11 @@ void
SpanGuard::setAttribute(std::string_view key, std::string_view value)
{
if (impl_)
{
impl_->span->SetAttribute(
opentelemetry::nostd::string_view(key.data(), key.size()),
opentelemetry::nostd::string_view(value.data(), value.size()));
}
}
void
@@ -342,14 +347,13 @@ SpanGuard::discard()
{
if (impl_)
{
tl_discardCurrentSpan = true;
gTlDiscardCurrentSpan = true;
impl_->span->End();
impl_->span = nullptr; // prevent ~Impl from calling End() again
impl_.reset();
}
}
} // namespace telemetry
} // namespace xrpl
} // namespace xrpl::telemetry
#endif // XRPL_ENABLE_TELEMETRY

View File

@@ -10,7 +10,7 @@
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).
- make_Telemetry(): factory that selects the appropriate implementation.
- makeTelemetry(): factory that selects the appropriate implementation.
*/
#ifdef XRPL_ENABLE_TELEMETRY
@@ -34,8 +34,12 @@
#include <opentelemetry/trace/noop.h>
#include <opentelemetry/trace/provider.h>
namespace xrpl {
namespace telemetry {
#include <chrono>
#include <string>
#include <string_view>
#include <utility>
namespace xrpl::telemetry {
namespace {
@@ -47,7 +51,7 @@ namespace resource = opentelemetry::sdk::resource;
/** SpanProcessor decorator that drops discarded spans.
Wraps a delegate processor (typically BatchSpanProcessor). In OnEnd(),
checks the tl_discardCurrentSpan thread-local flag. If set (by
checks the gTlDiscardCurrentSpan thread-local flag. If set (by
SpanGuard::discard()), the span is silently dropped — never entering
the batch queue, never sent over the network, never stored.
@@ -73,12 +77,12 @@ namespace resource = opentelemetry::sdk::resource;
+---------------------+
@note Thread safety: OnEnd() may be called concurrently from multiple
threads. The tl_discardCurrentSpan flag is thread-local, so each
threads. The gTlDiscardCurrentSpan flag is thread-local, so each
thread's discard state is independent — no synchronization needed.
*/
class FilteringSpanProcessor : public trace_sdk::SpanProcessor
{
std::unique_ptr<trace_sdk::SpanProcessor> delegate_;
std::unique_ptr<trace_sdk::SpanProcessor> delegate_{};
public:
explicit FilteringSpanProcessor(std::unique_ptr<trace_sdk::SpanProcessor> delegate)
@@ -103,12 +107,12 @@ public:
void
OnEnd(std::unique_ptr<trace_sdk::Recordable>&& span) noexcept override
{
if (tl_discardCurrentSpan)
if (gTlDiscardCurrentSpan)
{
// SpanGuard::discard() set the flag on this thread just before
// calling Span::End(), which invokes OnEnd() synchronously.
// Clear the flag and drop the span.
tl_discardCurrentSpan = false;
gTlDiscardCurrentSpan = false;
return;
}
delegate_->OnEnd(std::move(span));
@@ -141,7 +145,7 @@ class NullTelemetryOtel : public Telemetry
Setup const setup_;
public:
explicit NullTelemetryOtel(Setup const& setup) : setup_(setup)
explicit NullTelemetryOtel(Setup setup) : setup_(std::move(setup))
{
}
@@ -157,37 +161,37 @@ public:
Telemetry::setInstance(nullptr);
}
bool
[[nodiscard]] bool
isEnabled() const override
{
return false;
}
bool
[[nodiscard]] bool
shouldTraceTransactions() const override
{
return false;
}
bool
[[nodiscard]] bool
shouldTraceConsensus() const override
{
return false;
}
bool
[[nodiscard]] bool
shouldTraceRpc() const override
{
return false;
}
bool
[[nodiscard]] bool
shouldTracePeer() const override
{
return false;
}
bool
[[nodiscard]] bool
shouldTraceLedger() const override
{
return false;
@@ -236,10 +240,10 @@ class TelemetryImpl : public Telemetry
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<trace_sdk::TracerProvider> sdkProvider_;
std::shared_ptr<trace_sdk::TracerProvider> sdkProvider_{};
public:
TelemetryImpl(Setup const& setup, beast::Journal journal) : setup_(setup), journal_(journal)
TelemetryImpl(Setup setup, beast::Journal journal) : setup_(std::move(setup)), journal_(journal)
{
}
@@ -331,37 +335,37 @@ public:
JLOG(journal_.info()) << "Telemetry stopped";
}
bool
[[nodiscard]] bool
isEnabled() const override
{
return true;
}
bool
[[nodiscard]] bool
shouldTraceTransactions() const override
{
return setup_.traceTransactions;
}
bool
[[nodiscard]] bool
shouldTraceConsensus() const override
{
return setup_.traceConsensus;
}
bool
[[nodiscard]] bool
shouldTraceRpc() const override
{
return setup_.traceRpc;
}
bool
[[nodiscard]] bool
shouldTracePeer() const override
{
return setup_.tracePeer;
}
bool
[[nodiscard]] bool
shouldTraceLedger() const override
{
return setup_.traceLedger;
@@ -401,14 +405,13 @@ public:
} // namespace
std::unique_ptr<Telemetry>
make_Telemetry(Telemetry::Setup const& setup, beast::Journal journal)
makeTelemetry(Telemetry::Setup const& setup, beast::Journal journal)
{
if (setup.enabled)
return std::make_unique<TelemetryImpl>(setup, journal);
return std::make_unique<NullTelemetryOtel>(setup);
}
} // namespace telemetry
} // namespace xrpl
} // namespace xrpl::telemetry
#endif // XRPL_ENABLE_TELEMETRY

View File

@@ -41,7 +41,7 @@ networkTypeFromId(std::uint32_t networkId)
} // namespace
Telemetry::Setup
setup_Telemetry(
setupTelemetry(
Section const& section,
std::string const& nodePublicKey,
std::string const& version,

View File

@@ -324,8 +324,8 @@ public:
[this] { signalStop("PerfLog"); }))
, telemetry_(
telemetry::make_Telemetry(
telemetry::setup_Telemetry(
telemetry::makeTelemetry(
telemetry::setupTelemetry(
config_->section("telemetry"),
"", // Updated later via setServiceInstanceId()
BuildInfo::getVersionString(),