mirror of
https://github.com/XRPLF/rippled.git
synced 2026-07-24 15:40:26 +00:00
Give developers direct access to the full OpenTelemetry metrics API, symmetric with getTracer(), so all seven OTel instrument types (including UpDownCounter, sync Gauge, and the observable variants) are reachable — not just the four beast::insight models. - Telemetry: build and own the metrics pipeline (OTLP HTTP metric exporter + PeriodicExportingMetricReader + SpanMetrics histogram view) alongside the tracer, sharing the same resource attributes and TLS config. Register it globally via metrics::Provider::SetMeterProvider and expose Telemetry::getMeter(). Metrics enable with [telemetry]; the metrics endpoint is derived from the trace endpoint. - beast OTelCollector: no longer owns a pipeline. It fetches the global Meter, becoming a thin shim over the shared provider (legacy path during beast deprecation). This also resolves the review note that the metric exporter ignored [telemetry] use_tls — TLS now comes from the shared telemetry pipeline. - Add a libxrpl unit test covering getMeter() on the enabled (global provider) and disabled (noop) paths, exercising an UpDownCounter. Design: docs/superpowers/specs/2026-07-07-direct-otel-metrics-api-design.md Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
577 lines
21 KiB
C++
577 lines
21 KiB
C++
/** 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
|
|
|
|
#include <xrpl/telemetry/Telemetry.h>
|
|
|
|
#include <xrpl/basics/Log.h>
|
|
#include <xrpl/beast/utility/Journal.h>
|
|
#include <xrpl/telemetry/DiscardFlag.h>
|
|
#include <xrpl/telemetry/SpanNames.h>
|
|
|
|
#include <opentelemetry/context/context.h>
|
|
#include <opentelemetry/exporters/otlp/otlp_http_exporter_factory.h>
|
|
#include <opentelemetry/exporters/otlp/otlp_http_exporter_options.h>
|
|
#include <opentelemetry/exporters/otlp/otlp_http_metric_exporter_factory.h>
|
|
#include <opentelemetry/exporters/otlp/otlp_http_metric_exporter_options.h>
|
|
#include <opentelemetry/metrics/meter.h>
|
|
#include <opentelemetry/metrics/meter_provider.h>
|
|
#include <opentelemetry/metrics/noop.h>
|
|
#include <opentelemetry/metrics/provider.h>
|
|
#include <opentelemetry/nostd/shared_ptr.h>
|
|
#include <opentelemetry/sdk/metrics/aggregation/aggregation_config.h>
|
|
#include <opentelemetry/sdk/metrics/export/periodic_exporting_metric_reader_factory.h>
|
|
#include <opentelemetry/sdk/metrics/export/periodic_exporting_metric_reader_options.h>
|
|
#include <opentelemetry/sdk/metrics/instruments.h>
|
|
#include <opentelemetry/sdk/metrics/meter_provider.h>
|
|
#include <opentelemetry/sdk/metrics/meter_provider_factory.h>
|
|
#include <opentelemetry/sdk/metrics/view/instrument_selector_factory.h>
|
|
#include <opentelemetry/sdk/metrics/view/meter_selector_factory.h>
|
|
#include <opentelemetry/sdk/metrics/view/view_factory.h>
|
|
#include <opentelemetry/sdk/metrics/view/view_registry.h>
|
|
#include <opentelemetry/sdk/resource/resource.h>
|
|
#include <opentelemetry/sdk/trace/batch_span_processor_factory.h>
|
|
#include <opentelemetry/sdk/trace/batch_span_processor_options.h>
|
|
#include <opentelemetry/sdk/trace/processor.h>
|
|
#include <opentelemetry/sdk/trace/sampler.h>
|
|
#include <opentelemetry/sdk/trace/samplers/parent_factory.h>
|
|
#include <opentelemetry/sdk/trace/samplers/trace_id_ratio.h>
|
|
#include <opentelemetry/sdk/trace/tracer_provider.h>
|
|
#include <opentelemetry/sdk/trace/tracer_provider_factory.h>
|
|
#include <opentelemetry/semconv/incubating/service_attributes.h>
|
|
#include <opentelemetry/trace/noop.h>
|
|
#include <opentelemetry/trace/provider.h>
|
|
#include <opentelemetry/trace/span.h>
|
|
#include <opentelemetry/trace/span_metadata.h>
|
|
#include <opentelemetry/trace/span_startoptions.h>
|
|
#include <opentelemetry/trace/tracer.h>
|
|
#include <opentelemetry/trace/tracer_provider.h>
|
|
|
|
#include <chrono>
|
|
#include <cstdint>
|
|
#include <memory>
|
|
#include <string>
|
|
#include <string_view>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
namespace xrpl::telemetry {
|
|
|
|
namespace {
|
|
|
|
namespace trace_api = opentelemetry::trace;
|
|
namespace trace_sdk = opentelemetry::sdk::trace;
|
|
namespace metrics_api = opentelemetry::metrics;
|
|
namespace metrics_sdk = opentelemetry::sdk::metrics;
|
|
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 |
|
|
| <SpanProcessor> |
|
|
+---------------------------+
|
|
| 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<trace_sdk::SpanProcessor> delegate_;
|
|
|
|
public:
|
|
explicit FilteringSpanProcessor(std::unique_ptr<trace_sdk::SpanProcessor> delegate)
|
|
: delegate_(std::move(delegate))
|
|
{
|
|
}
|
|
|
|
std::unique_ptr<trace_sdk::Recordable>
|
|
MakeRecordable() noexcept override
|
|
{
|
|
return delegate_->MakeRecordable();
|
|
}
|
|
|
|
void
|
|
OnStart(
|
|
trace_sdk::Recordable& span,
|
|
opentelemetry::trace::SpanContext const& parentContext) noexcept override
|
|
{
|
|
delegate_->OnStart(span, parentContext);
|
|
}
|
|
|
|
void
|
|
OnEnd(std::unique_ptr<trace_sdk::Recordable>&& span) noexcept override
|
|
{
|
|
if (DiscardScope::isActive())
|
|
{
|
|
// SpanGuard::discard() is inside a DiscardScope on this thread,
|
|
// which it entered just before calling Span::End() — and End()
|
|
// invokes OnEnd() synchronously. Drop the span.
|
|
return;
|
|
}
|
|
delegate_->OnEnd(std::move(span));
|
|
}
|
|
|
|
bool
|
|
ForceFlush(
|
|
std::chrono::microseconds timeout = std::chrono::microseconds::max()) noexcept override
|
|
{
|
|
return delegate_->ForceFlush(timeout);
|
|
}
|
|
|
|
bool
|
|
Shutdown(std::chrono::microseconds timeout = std::chrono::microseconds::max()) noexcept override
|
|
{
|
|
return delegate_->Shutdown(timeout);
|
|
}
|
|
};
|
|
|
|
/** 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). */
|
|
Setup const setup_;
|
|
|
|
public:
|
|
explicit NullTelemetryOtel(Setup setup) : setup_(std::move(setup))
|
|
{
|
|
}
|
|
|
|
void
|
|
start() override
|
|
{
|
|
Telemetry::setInstance(this);
|
|
}
|
|
|
|
void
|
|
stop() override
|
|
{
|
|
Telemetry::setInstance(nullptr);
|
|
}
|
|
|
|
[[nodiscard]] bool
|
|
isEnabled() const override
|
|
{
|
|
return false;
|
|
}
|
|
|
|
[[nodiscard]] bool
|
|
shouldTraceTransactions() const override
|
|
{
|
|
return false;
|
|
}
|
|
|
|
[[nodiscard]] bool
|
|
shouldTraceConsensus() const override
|
|
{
|
|
return false;
|
|
}
|
|
|
|
[[nodiscard]] bool
|
|
shouldTraceRpc() const override
|
|
{
|
|
return false;
|
|
}
|
|
|
|
[[nodiscard]] bool
|
|
shouldTracePeer() const override
|
|
{
|
|
return false;
|
|
}
|
|
|
|
[[nodiscard]] bool
|
|
shouldTraceLedger() const override
|
|
{
|
|
return false;
|
|
}
|
|
|
|
[[nodiscard]] std::string const&
|
|
getConsensusTraceStrategy() const override
|
|
{
|
|
return setup_.consensusTraceStrategy;
|
|
}
|
|
|
|
opentelemetry::nostd::shared_ptr<trace_api::Tracer>
|
|
getTracer(std::string_view) override
|
|
{
|
|
static auto noopTracer =
|
|
opentelemetry::nostd::shared_ptr<trace_api::Tracer>(new trace_api::NoopTracer());
|
|
return noopTracer;
|
|
}
|
|
|
|
opentelemetry::nostd::shared_ptr<metrics_api::Meter>
|
|
getMeter(std::string_view name) override
|
|
{
|
|
// Serve a meter from a process-wide noop provider, mirroring the
|
|
// noop tracer above. Instruments created from it are inert.
|
|
static auto noopProvider = opentelemetry::nostd::shared_ptr<metrics_api::MeterProvider>(
|
|
new metrics_api::NoopMeterProvider());
|
|
return noopProvider->GetMeter(std::string(name), std::string(kMeterVersion));
|
|
}
|
|
|
|
opentelemetry::nostd::shared_ptr<trace_api::Span>
|
|
startSpan(std::string_view, trace_api::SpanKind) override
|
|
{
|
|
return opentelemetry::nostd::shared_ptr<trace_api::Span>(new trace_api::NoopSpan(nullptr));
|
|
}
|
|
|
|
opentelemetry::nostd::shared_ptr<trace_api::Span>
|
|
startSpan(std::string_view, opentelemetry::context::Context const&, trace_api::SpanKind)
|
|
override
|
|
{
|
|
return opentelemetry::nostd::shared_ptr<trace_api::Span>(new trace_api::NoopSpan(nullptr));
|
|
}
|
|
};
|
|
|
|
/** 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.
|
|
*/
|
|
Setup setup_;
|
|
|
|
/** 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.
|
|
*/
|
|
std::shared_ptr<trace_sdk::TracerProvider> sdkProvider_;
|
|
|
|
/** The SDK MeterProvider that owns the metric export pipeline.
|
|
|
|
Symmetric with sdkProvider_ on the tracing side. Held as
|
|
std::shared_ptr so we can ForceFlush() on shutdown; wrapped in a
|
|
nostd::shared_ptr when registered as the global meter provider.
|
|
*/
|
|
std::shared_ptr<metrics_sdk::MeterProvider> meterProvider_;
|
|
|
|
public:
|
|
TelemetryImpl(Setup setup, beast::Journal journal) : setup_(std::move(setup)), journal_(journal)
|
|
{
|
|
}
|
|
|
|
void
|
|
setServiceInstanceId(std::string const& id) override
|
|
{
|
|
setup_.serviceInstanceId = id;
|
|
}
|
|
|
|
void
|
|
start() override
|
|
{
|
|
JLOG(journal_.info()) << "Telemetry starting: endpoint=" << setup_.exporterEndpoint
|
|
<< " sampling=" << setup_.samplingRatio;
|
|
|
|
// Configure OTLP HTTP exporter
|
|
otlp_http::OtlpHttpExporterOptions exporterOpts;
|
|
exporterOpts.url = setup_.exporterEndpoint;
|
|
if (setup_.useTls)
|
|
{
|
|
exporterOpts.ssl_ca_cert_path = setup_.tlsCertPath;
|
|
// Present a client cert for mutual TLS. When both paths are
|
|
// empty the connection falls back to one-way (server) TLS.
|
|
exporterOpts.ssl_client_cert_path = setup_.tlsClientCertPath;
|
|
exporterOpts.ssl_client_key_path = setup_.tlsClientKeyPath;
|
|
}
|
|
|
|
auto exporter = otlp_http::OtlpHttpExporterFactory::Create(exporterOpts);
|
|
|
|
// Configure batch processor
|
|
trace_sdk::BatchSpanProcessorOptions processorOpts;
|
|
processorOpts.max_queue_size = setup_.maxQueueSize;
|
|
processorOpts.schedule_delay_millis = std::chrono::milliseconds(setup_.batchDelay);
|
|
processorOpts.max_export_batch_size = setup_.batchSize;
|
|
|
|
auto batchProcessor =
|
|
trace_sdk::BatchSpanProcessorFactory::Create(std::move(exporter), processorOpts);
|
|
|
|
// Wrap batch processor with filtering processor that drops spans
|
|
// marked with kDiscardedAttr (via SpanGuard::discard()).
|
|
auto processor = std::make_unique<FilteringSpanProcessor>(std::move(batchProcessor));
|
|
|
|
// Configure resource attributes
|
|
auto resourceAttrs = resource::Resource::Create({
|
|
{opentelemetry::semconv::service::kServiceName, setup_.serviceName},
|
|
{opentelemetry::semconv::service::kServiceVersion, setup_.serviceVersion},
|
|
{opentelemetry::semconv::service::kServiceInstanceId, setup_.serviceInstanceId},
|
|
{std::string(attr::networkId),
|
|
static_cast<int64_t>(setup_.networkId)}, // LCOV_EXCL_LINE
|
|
{std::string(attr::networkType), setup_.networkType}, // LCOV_EXCL_LINE
|
|
});
|
|
|
|
// Configure sampler. Head sampling is fixed at 1.0 (sample everything);
|
|
// setup_.samplingRatio is not config-driven. Wrap the ratio sampler in a
|
|
// ParentBasedSampler so spans with a remote parent honor the upstream
|
|
// sampled flag — this keeps keep/drop decisions coherent for a single
|
|
// distributed trace spanning multiple nodes. Volume reduction is left to
|
|
// the collector's tail sampling.
|
|
auto rootSampler =
|
|
std::make_shared<trace_sdk::TraceIdRatioBasedSampler>(setup_.samplingRatio);
|
|
auto sampler = trace_sdk::ParentBasedSamplerFactory::Create(std::move(rootSampler));
|
|
|
|
// Create TracerProvider
|
|
sdkProvider_ = trace_sdk::TracerProviderFactory::Create(
|
|
std::move(processor), resourceAttrs, std::move(sampler));
|
|
|
|
// Set as global provider
|
|
trace_api::Provider::SetTracerProvider(
|
|
opentelemetry::nostd::shared_ptr<trace_api::TracerProvider>(sdkProvider_));
|
|
|
|
// Build the metrics pipeline, parallel to the tracer above and
|
|
// reusing the same resourceAttrs so metrics and traces share one
|
|
// resource identity.
|
|
|
|
// Derive the metrics endpoint from the trace endpoint by swapping
|
|
// the trailing "/v1/traces" path for "/v1/metrics". Any other URL
|
|
// shape is used as-is.
|
|
std::string metricsEndpoint = setup_.exporterEndpoint;
|
|
constexpr std::string_view tracesPath{"/v1/traces"};
|
|
if (metricsEndpoint.ends_with(tracesPath))
|
|
{
|
|
metricsEndpoint.replace(
|
|
metricsEndpoint.size() - tracesPath.size(), tracesPath.size(), "/v1/metrics");
|
|
}
|
|
|
|
// Configure OTLP HTTP metric exporter, honoring the same TLS
|
|
// options as the trace exporter.
|
|
otlp_http::OtlpHttpMetricExporterOptions metricExporterOpts;
|
|
metricExporterOpts.url = metricsEndpoint;
|
|
if (setup_.useTls)
|
|
{
|
|
metricExporterOpts.ssl_ca_cert_path = setup_.tlsCertPath;
|
|
metricExporterOpts.ssl_client_cert_path = setup_.tlsClientCertPath;
|
|
metricExporterOpts.ssl_client_key_path = setup_.tlsClientKeyPath;
|
|
}
|
|
|
|
auto metricExporter = otlp_http::OtlpHttpMetricExporterFactory::Create(metricExporterOpts);
|
|
|
|
// Configure periodic metric reader (1-second export interval,
|
|
// matching the beast OTelCollector path).
|
|
metrics_sdk::PeriodicExportingMetricReaderOptions readerOpts;
|
|
readerOpts.export_interval_millis = std::chrono::milliseconds(1000);
|
|
readerOpts.export_timeout_millis = std::chrono::milliseconds(500);
|
|
|
|
auto reader = metrics_sdk::PeriodicExportingMetricReaderFactory::Create(
|
|
std::move(metricExporter), readerOpts);
|
|
|
|
// Create MeterProvider with the shared resource, then attach reader.
|
|
meterProvider_ = metrics_sdk::MeterProviderFactory::Create(
|
|
std::make_unique<metrics_sdk::ViewRegistry>(), resourceAttrs);
|
|
meterProvider_->AddMetricReader(std::move(reader));
|
|
|
|
// Histogram view: SpanMetrics-compatible bucket boundaries (ms) so
|
|
// histogram instruments align with the collector's SpanMetrics.
|
|
auto histogramSelector = metrics_sdk::InstrumentSelectorFactory::Create(
|
|
metrics_sdk::InstrumentType::kHistogram, "*", "ms");
|
|
auto meterSelector = metrics_sdk::MeterSelectorFactory::Create("xrpld_metrics", "", "");
|
|
auto histogramConfig = std::make_shared<metrics_sdk::HistogramAggregationConfig>();
|
|
histogramConfig->boundaries_ =
|
|
std::vector<double>{1.0, 5.0, 10.0, 25.0, 50.0, 100.0, 250.0, 500.0, 1000.0, 5000.0};
|
|
auto histogramView = metrics_sdk::ViewFactory::Create(
|
|
"default_histogram",
|
|
"Default histogram view with SpanMetrics-compatible buckets",
|
|
metrics_sdk::AggregationType::kHistogram,
|
|
std::move(histogramConfig));
|
|
|
|
meterProvider_->AddView(
|
|
std::move(histogramSelector), std::move(meterSelector), std::move(histogramView));
|
|
|
|
// Publish as the global meter provider so developers (and the beast
|
|
// OTelCollector shim) reach the same pipeline.
|
|
metrics_api::Provider::SetMeterProvider(
|
|
opentelemetry::nostd::shared_ptr<metrics_api::MeterProvider>(meterProvider_));
|
|
|
|
// Register as the global Telemetry instance so SpanGuard factory
|
|
// methods can access it without callers passing a reference.
|
|
Telemetry::setInstance(this);
|
|
|
|
JLOG(journal_.info()) << "Telemetry started successfully";
|
|
}
|
|
|
|
void
|
|
stop() override
|
|
{
|
|
JLOG(journal_.info()) << "Telemetry stopping";
|
|
|
|
// Unregister global instance before tearing down the pipeline.
|
|
Telemetry::setInstance(nullptr);
|
|
|
|
if (sdkProvider_)
|
|
{
|
|
// Force flush with timeout to avoid blocking indefinitely
|
|
// when the OTLP endpoint is unreachable.
|
|
sdkProvider_->ForceFlush(std::chrono::milliseconds(5000));
|
|
// TODO: sdkProvider_ is not thread-safe. This reset() races with
|
|
// getTracer() if any thread is still calling startSpan().
|
|
// Currently safe because Application::stop() shuts down
|
|
// serverHandler_, overlay_, and jobQueue_ before calling
|
|
// telemetry_->stop() — so no callers should remain. If the
|
|
// shutdown order ever changes, add an std::atomic<bool> stopped_
|
|
// flag checked in getTracer() to make this robust.
|
|
sdkProvider_.reset();
|
|
trace_api::Provider::SetTracerProvider(
|
|
opentelemetry::nostd::shared_ptr<trace_api::TracerProvider>(
|
|
new trace_api::NoopTracerProvider()));
|
|
}
|
|
|
|
if (meterProvider_)
|
|
{
|
|
// Mirror the tracer teardown: bounded flush, drop our provider,
|
|
// then restore a noop global provider. Same shutdown-order
|
|
// caveat as sdkProvider_ above applies to getMeter() callers.
|
|
meterProvider_->ForceFlush(std::chrono::milliseconds(5000));
|
|
meterProvider_.reset();
|
|
metrics_api::Provider::SetMeterProvider(
|
|
opentelemetry::nostd::shared_ptr<metrics_api::MeterProvider>(
|
|
new metrics_api::NoopMeterProvider()));
|
|
}
|
|
JLOG(journal_.info()) << "Telemetry stopped";
|
|
}
|
|
|
|
[[nodiscard]] bool
|
|
isEnabled() const override
|
|
{
|
|
return true;
|
|
}
|
|
|
|
[[nodiscard]] bool
|
|
shouldTraceTransactions() const override
|
|
{
|
|
return setup_.traceTransactions;
|
|
}
|
|
|
|
[[nodiscard]] bool
|
|
shouldTraceConsensus() const override
|
|
{
|
|
return setup_.traceConsensus;
|
|
}
|
|
|
|
[[nodiscard]] bool
|
|
shouldTraceRpc() const override
|
|
{
|
|
return setup_.traceRpc;
|
|
}
|
|
|
|
[[nodiscard]] bool
|
|
shouldTracePeer() const override
|
|
{
|
|
return setup_.tracePeer;
|
|
}
|
|
|
|
[[nodiscard]] bool
|
|
shouldTraceLedger() const override
|
|
{
|
|
return setup_.traceLedger;
|
|
}
|
|
|
|
[[nodiscard]] std::string const&
|
|
getConsensusTraceStrategy() const override
|
|
{
|
|
return setup_.consensusTraceStrategy;
|
|
}
|
|
|
|
opentelemetry::nostd::shared_ptr<trace_api::Tracer>
|
|
getTracer(std::string_view name = kTracerName) override
|
|
{
|
|
if (!sdkProvider_)
|
|
return trace_api::Provider::GetTracerProvider()->GetTracer(std::string(name));
|
|
return sdkProvider_->GetTracer(std::string(name));
|
|
}
|
|
|
|
opentelemetry::nostd::shared_ptr<metrics_api::Meter>
|
|
getMeter(std::string_view name = kMeterName) override
|
|
{
|
|
if (!meterProvider_)
|
|
return metrics_api::Provider::GetMeterProvider()->GetMeter(
|
|
std::string(name), std::string(kMeterVersion));
|
|
return meterProvider_->GetMeter(std::string(name), std::string(kMeterVersion));
|
|
}
|
|
|
|
opentelemetry::nostd::shared_ptr<trace_api::Span>
|
|
startSpan(std::string_view name, trace_api::SpanKind kind) override
|
|
{
|
|
auto tracer = getTracer();
|
|
trace_api::StartSpanOptions opts;
|
|
opts.kind = kind;
|
|
return tracer->StartSpan(std::string(name), opts);
|
|
}
|
|
|
|
opentelemetry::nostd::shared_ptr<trace_api::Span>
|
|
startSpan(
|
|
std::string_view name,
|
|
opentelemetry::context::Context const& parentContext,
|
|
trace_api::SpanKind kind) override
|
|
{
|
|
auto tracer = getTracer();
|
|
trace_api::StartSpanOptions opts;
|
|
opts.kind = kind;
|
|
opts.parent = parentContext;
|
|
return tracer->StartSpan(std::string(name), opts);
|
|
}
|
|
};
|
|
|
|
} // namespace
|
|
|
|
std::unique_ptr<Telemetry>
|
|
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 xrpl::telemetry
|
|
|
|
#endif // XRPL_ENABLE_TELEMETRY
|