Skip to content

Commit 85325af

Browse files
Phase 1b: Telemetry core infrastructure
Add the OpenTelemetry telemetry library and supporting infrastructure: Build system: - Conan opentelemetry-cpp dependency with OTLP/gRPC exporter - CMake integration for xrpl_telemetry library target - Levelization ordering updates Core library (libxrpl): - Telemetry class: provider lifecycle, span creation, sampling config - SpanGuard: RAII span management with attribute/exception helpers - TelemetryConfig: parse [telemetry] config section - NullTelemetry: no-op implementation when telemetry is disabled Application integration: - Telemetry member in ApplicationImp with start/stop lifecycle - getTelemetry() interface on Application - ServiceRegistry telemetry accessor Docker observability stack: - OTel Collector, Jaeger, Grafana docker-compose setup - Collector config with OTLP gRPC receiver and Jaeger exporter Config and docs: - Example telemetry config section in xrpld-example.cfg - Build documentation for telemetry setup Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 8794ef9 commit 85325af

File tree

18 files changed

+1316
-4
lines changed

18 files changed

+1316
-4
lines changed

.github/scripts/levelization/results/ordering.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ libxrpl.server > xrpl.server
3232
libxrpl.shamap > xrpl.basics
3333
libxrpl.shamap > xrpl.protocol
3434
libxrpl.shamap > xrpl.shamap
35+
libxrpl.telemetry > xrpl.basics
36+
libxrpl.telemetry > xrpl.telemetry
3537
libxrpl.tx > xrpl.basics
3638
libxrpl.tx > xrpl.conditions
3739
libxrpl.tx > xrpl.core
@@ -206,6 +208,7 @@ xrpl.server > xrpl.shamap
206208
xrpl.shamap > xrpl.basics
207209
xrpl.shamap > xrpl.nodestore
208210
xrpl.shamap > xrpl.protocol
211+
xrpl.telemetry > xrpl.basics
209212
xrpl.tx > xrpl.basics
210213
xrpl.tx > xrpl.core
211214
xrpl.tx > xrpl.ledger
@@ -224,6 +227,7 @@ xrpld.app > xrpl.rdb
224227
xrpld.app > xrpl.resource
225228
xrpld.app > xrpl.server
226229
xrpld.app > xrpl.shamap
230+
xrpld.app > xrpl.telemetry
227231
xrpld.app > xrpl.tx
228232
xrpld.consensus > xrpl.basics
229233
xrpld.consensus > xrpl.json
@@ -255,6 +259,7 @@ xrpld.perflog > xrpl.json
255259
xrpld.rpc > xrpl.basics
256260
xrpld.rpc > xrpl.core
257261
xrpld.rpc > xrpld.core
262+
xrpld.rpc > xrpld.telemetry
258263
xrpld.rpc > xrpl.json
259264
xrpld.rpc > xrpl.ledger
260265
xrpld.rpc > xrpl.net
@@ -265,3 +270,4 @@ xrpld.rpc > xrpl.resource
265270
xrpld.rpc > xrpl.server
266271
xrpld.rpc > xrpl.tx
267272
xrpld.shamap > xrpl.shamap
273+
xrpld.telemetry > xrpl.telemetry

CMakeLists.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,18 @@ if (rocksdb)
126126
target_link_libraries(xrpl_libs INTERFACE RocksDB::rocksdb)
127127
endif ()
128128

129+
# OpenTelemetry distributed tracing (optional).
130+
# When ON, links against opentelemetry-cpp and defines XRPL_ENABLE_TELEMETRY
131+
# so that tracing macros in TracingInstrumentation.h are compiled in.
132+
# When OFF (default), all tracing code compiles to no-ops with zero overhead.
133+
# Enable via: conan install -o telemetry=True, or cmake -Dtelemetry=ON.
134+
option(telemetry "Enable OpenTelemetry tracing" OFF)
135+
if (telemetry)
136+
find_package(opentelemetry-cpp CONFIG REQUIRED)
137+
add_compile_definitions(XRPL_ENABLE_TELEMETRY)
138+
message(STATUS "OpenTelemetry tracing enabled")
139+
endif ()
140+
129141
# Work around changes to Conan recipe for now.
130142
if (TARGET nudb::core)
131143
set(nudb nudb::core)

cfg/xrpld-example.cfg

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1529,3 +1529,46 @@ validators.txt
15291529
# set to ssl_verify to 0.
15301530
[ssl_verify]
15311531
1
1532+
#-------------------------------------------------------------------------------
1533+
#
1534+
# 11. Telemetry (OpenTelemetry Tracing)
1535+
#
1536+
#-------------------------------------------------------------------------------
1537+
#
1538+
# Enables distributed tracing via OpenTelemetry. Requires building with
1539+
# -DXRPL_ENABLE_TELEMETRY=ON (telemetry Conan option).
1540+
#
1541+
# [telemetry]
1542+
#
1543+
# enabled=0
1544+
#
1545+
# Enable or disable telemetry at runtime. Default: 0 (disabled).
1546+
#
1547+
# endpoint=http://localhost:4318/v1/traces
1548+
#
1549+
# The OpenTelemetry Collector endpoint (OTLP/HTTP). Default: http://localhost:4318/v1/traces.
1550+
#
1551+
# exporter=otlp_http
1552+
#
1553+
# Exporter type: otlp_http. Default: otlp_http.
1554+
#
1555+
# sampling_ratio=1.0
1556+
#
1557+
# Fraction of traces to sample (0.0 to 1.0). Default: 1.0 (all traces).
1558+
#
1559+
# trace_rpc=1
1560+
#
1561+
# Enable RPC request tracing. Default: 1.
1562+
#
1563+
# trace_transactions=1
1564+
#
1565+
# Enable transaction lifecycle tracing. Default: 1.
1566+
#
1567+
# trace_consensus=1
1568+
#
1569+
# Enable consensus round tracing. Default: 1.
1570+
#
1571+
# trace_peer=0
1572+
#
1573+
# Enable peer message tracing (high volume). Default: 0.
1574+
#

cmake/XrplCore.cmake

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,17 @@ target_link_libraries(
119119
add_module(xrpl tx)
120120
target_link_libraries(xrpl.libxrpl.tx PUBLIC xrpl.libxrpl.ledger)
121121

122+
# Telemetry module — OpenTelemetry distributed tracing support.
123+
# Sources: include/xrpl/telemetry/ (headers), src/libxrpl/telemetry/ (impl).
124+
# When telemetry=ON, links the Conan-provided umbrella target
125+
# opentelemetry-cpp::opentelemetry-cpp (individual component targets like
126+
# ::api, ::sdk are not available in the Conan package).
127+
add_module(xrpl telemetry)
128+
target_link_libraries(xrpl.libxrpl.telemetry PUBLIC xrpl.libxrpl.basics xrpl.libxrpl.beast)
129+
if (telemetry)
130+
target_link_libraries(xrpl.libxrpl.telemetry PUBLIC opentelemetry-cpp::opentelemetry-cpp)
131+
endif ()
132+
122133
add_library(xrpl.libxrpl)
123134
set_target_properties(xrpl.libxrpl PROPERTIES OUTPUT_NAME xrpl)
124135

@@ -144,6 +155,7 @@ target_link_modules(
144155
resource
145156
server
146157
shamap
158+
telemetry
147159
tx)
148160

149161
# All headers in libxrpl are in modules.

cmake/XrplInstall.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ install(TARGETS common
3232
xrpl.libxrpl.resource
3333
xrpl.libxrpl.server
3434
xrpl.libxrpl.shamap
35+
xrpl.libxrpl.telemetry
3536
xrpl.libxrpl.tx
3637
antithesis-sdk-cpp
3738
EXPORT XrplExports

conan.lock

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,13 @@
1010
"rocksdb/10.5.1#4a197eca381a3e5ae8adf8cffa5aacd0%1765850186.86",
1111
"re2/20230301#ca3b241baec15bd31ea9187150e0b333%1765850148.103",
1212
"protobuf/6.32.1#f481fd276fc23a33b85a3ed1e898b693%1765850161.038",
13-
"openssl/3.5.5#05a4ac5b7323f7a329b2db1391d9941f%1769599205.414",
13+
"opentelemetry-cpp/1.18.0#efd9851e173f8a13b9c7d35232de8cf1%1750409186.472",
14+
"openssl/3.5.5#05a4ac5b7323f7a329b2db1391d9941f%1770229825.601",
1415
"nudb/2.0.9#0432758a24204da08fee953ec9ea03cb%1769436073.32",
16+
"nlohmann_json/3.11.3#45828be26eb619a2e04ca517bb7b828d%1701220705.259",
1517
"lz4/1.10.0#59fc63cac7f10fbe8e05c7e62c2f3504%1765850143.914",
1618
"libiconv/1.17#1e65319e945f2d31941a9d28cc13c058%1765842973.492",
19+
"libcurl/8.18.0#364bc3755cb9ef84ed9a7ae9c7efc1c1%1770984390.024",
1720
"libbacktrace/cci.20210118#a7691bfccd8caaf66309df196790a5a1%1765842973.03",
1821
"libarchive/3.8.1#ffee18995c706e02bf96e7a2f7042e0d%1765850144.736",
1922
"jemalloc/5.3.0#e951da9cf599e956cebc117880d2d9f8%1729241615.244",
@@ -30,9 +33,15 @@
3033
"zlib/1.3.1#b8bc2603263cf7eccbd6e17e66b0ed76%1765850150.075",
3134
"strawberryperl/5.32.1.1#707032463aa0620fa17ec0d887f5fe41%1765850165.196",
3235
"protobuf/6.32.1#f481fd276fc23a33b85a3ed1e898b693%1765850161.038",
36+
"pkgconf/2.5.1#93c2051284cba1279494a43a4fcfeae2%1757684701.089",
37+
"opentelemetry-proto/1.4.0#4096a3b05916675ef9628f3ffd571f51%1732731336.11",
38+
"ninja/1.13.2#c8c5dc2a52ed6e4e42a66d75b4717ceb%1764096931.974",
3339
"nasm/2.16.01#31e26f2ee3c4346ecd347911bd126904%1765850144.707",
3440
"msys2/cci.latest#eea83308ad7e9023f7318c60d5a9e6cb%1770199879.083",
41+
"meson/1.10.0#60786758ea978964c24525de19603cf4%1768294926.103",
3542
"m4/1.4.19#70dc8bbb33e981d119d2acc0175cf381%1763158052.846",
43+
"libtool/2.4.7#14e7739cc128bc1623d2ed318008e47e%1755679003.847",
44+
"gnu-config/cci.20210814#466e9d4d7779e1c142443f7ea44b4284%1762363589.329",
3645
"cmake/4.2.0#ae0a44f44a1ef9ab68fd4b3e9a1f8671%1765850153.937",
3746
"cmake/3.31.10#313d16a1aa16bbdb2ca0792467214b76%1765850153.479",
3847
"b2/5.3.3#107c15377719889654eb9a162a673975%1765850144.355",

conanfile.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ class Xrpl(ConanFile):
2222
"rocksdb": [True, False],
2323
"shared": [True, False],
2424
"static": [True, False],
25+
"telemetry": [True, False],
2526
"tests": [True, False],
2627
"unity": [True, False],
2728
"xrpld": [True, False],
@@ -54,6 +55,7 @@ class Xrpl(ConanFile):
5455
"rocksdb": True,
5556
"shared": False,
5657
"static": True,
58+
"telemetry": True,
5759
"tests": False,
5860
"unity": False,
5961
"xrpld": False,
@@ -140,6 +142,10 @@ def requirements(self):
140142
self.requires("jemalloc/5.3.0")
141143
if self.options.rocksdb:
142144
self.requires("rocksdb/10.5.1")
145+
# OpenTelemetry C++ SDK for distributed tracing (optional).
146+
# Provides OTLP/HTTP exporter, batch span processor, and trace API.
147+
if self.options.telemetry:
148+
self.requires("opentelemetry-cpp/1.18.0")
143149
self.requires("xxhash/0.8.3", **transitive_headers_opt)
144150

145151
exports_sources = (
@@ -168,6 +174,7 @@ def generate(self):
168174
tc.variables["rocksdb"] = self.options.rocksdb
169175
tc.variables["BUILD_SHARED_LIBS"] = self.options.shared
170176
tc.variables["static"] = self.options.static
177+
tc.variables["telemetry"] = self.options.telemetry
171178
tc.variables["unity"] = self.options.unity
172179
tc.variables["xrpld"] = self.options.xrpld
173180
tc.generate()
@@ -220,3 +227,5 @@ def package_info(self):
220227
]
221228
if self.options.rocksdb:
222229
libxrpl.requires.append("rocksdb::librocksdb")
230+
if self.options.telemetry:
231+
libxrpl.requires.append("opentelemetry-cpp::opentelemetry-cpp")
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# Docker Compose stack for rippled OpenTelemetry observability.
2+
#
3+
# Provides three services for local development:
4+
# - otel-collector: receives OTLP traces from rippled, batches and
5+
# forwards them to Jaeger. Listens on ports 4317 (gRPC) and 4318 (HTTP).
6+
# - jaeger: all-in-one tracing backend with UI on port 16686.
7+
# - grafana: dashboards on port 3000, pre-configured with Jaeger datasource.
8+
#
9+
# Usage:
10+
# docker compose -f docker/telemetry/docker-compose.yml up -d
11+
#
12+
# Configure rippled to export traces by adding to xrpld.cfg:
13+
# [telemetry]
14+
# enabled=1
15+
# endpoint=http://localhost:4318/v1/traces
16+
17+
version: "3.8"
18+
19+
services:
20+
otel-collector:
21+
image: otel/opentelemetry-collector-contrib:latest
22+
command: ["--config=/etc/otel-collector-config.yaml"]
23+
ports:
24+
- "4317:4317" # OTLP gRPC
25+
- "4318:4318" # OTLP HTTP
26+
- "13133:13133" # Health check
27+
volumes:
28+
- ./otel-collector-config.yaml:/etc/otel-collector-config.yaml:ro
29+
depends_on:
30+
- jaeger
31+
networks:
32+
- rippled-telemetry
33+
34+
jaeger:
35+
image: jaegertracing/all-in-one:latest
36+
environment:
37+
- COLLECTOR_OTLP_ENABLED=true
38+
ports:
39+
- "16686:16686" # Jaeger UI
40+
- "14250:14250" # gRPC
41+
networks:
42+
- rippled-telemetry
43+
44+
grafana:
45+
image: grafana/grafana:latest
46+
environment:
47+
- GF_AUTH_ANONYMOUS_ENABLED=true
48+
- GF_AUTH_ANONYMOUS_ORG_ROLE=Admin
49+
ports:
50+
- "3000:3000"
51+
volumes:
52+
- ./grafana/provisioning:/etc/grafana/provisioning:ro
53+
depends_on:
54+
- jaeger
55+
networks:
56+
- rippled-telemetry
57+
58+
networks:
59+
rippled-telemetry:
60+
driver: bridge
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Grafana datasource provisioning for the rippled telemetry stack.
2+
# Auto-configures Jaeger as a trace data source on Grafana startup.
3+
# Access Grafana at http://localhost:3000, then use Explore -> Jaeger
4+
# to browse rippled traces.
5+
6+
apiVersion: 1
7+
8+
datasources:
9+
- name: Jaeger
10+
type: jaeger
11+
access: proxy
12+
url: http://jaeger:16686
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# OpenTelemetry Collector configuration for rippled development.
2+
#
3+
# Pipeline: OTLP receiver -> batch processor -> debug exporter + Jaeger.
4+
# rippled sends traces via OTLP/HTTP to port 4318. The collector batches
5+
# them and forwards to Jaeger via OTLP/gRPC on the Docker network.
6+
7+
receivers:
8+
otlp:
9+
protocols:
10+
grpc:
11+
endpoint: 0.0.0.0:4317
12+
http:
13+
endpoint: 0.0.0.0:4318
14+
15+
processors:
16+
batch:
17+
timeout: 1s
18+
send_batch_size: 100
19+
20+
exporters:
21+
debug:
22+
verbosity: detailed
23+
otlp/jaeger:
24+
endpoint: jaeger:4317
25+
tls:
26+
insecure: true
27+
28+
service:
29+
pipelines:
30+
traces:
31+
receivers: [otlp]
32+
processors: [batch]
33+
exporters: [debug, otlp/jaeger]

0 commit comments

Comments
 (0)