Skip to content

Commit c2ad81d

Browse files
Add TraceContextPropagator gtest + fix OTel API compat in header
Add 6 gtest cases for protobuf trace context round-trip, edge cases (empty proto, wrong sizes, invalid span), and flags preservation. Fix TraceContextPropagator.h to use nostd::span for TraceId/SpanId constructors (required by opentelemetry-cpp 1.18.0). Minor clang-format adjustments to existing Phase 2 test files. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 1f96b5d commit c2ad81d

File tree

4 files changed

+163
-9
lines changed

4 files changed

+163
-9
lines changed

include/xrpl/telemetry/TraceContextPropagator.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <xrpl/proto/xrpl.pb.h>
1515

1616
#include <opentelemetry/context/context.h>
17+
#include <opentelemetry/trace/context.h>
1718
#include <opentelemetry/trace/default_span.h>
1819
#include <opentelemetry/trace/span_context.h>
1920
#include <opentelemetry/trace/trace_flags.h>
@@ -41,8 +42,10 @@ extractFromProtobuf(protocol::TraceContext const& proto)
4142
return opentelemetry::context::Context{};
4243
}
4344

44-
trace::TraceId traceId(reinterpret_cast<std::uint8_t const*>(proto.trace_id().data()));
45-
trace::SpanId spanId(reinterpret_cast<std::uint8_t const*>(proto.span_id().data()));
45+
auto const* rawTraceId = reinterpret_cast<std::uint8_t const*>(proto.trace_id().data());
46+
auto const* rawSpanId = reinterpret_cast<std::uint8_t const*>(proto.span_id().data());
47+
trace::TraceId traceId(opentelemetry::nostd::span<std::uint8_t const, 16>(rawTraceId, 16));
48+
trace::SpanId spanId(opentelemetry::nostd::span<std::uint8_t const, 8>(rawSpanId, 8));
4649
trace::TraceFlags flags(
4750
proto.has_trace_flags() ? static_cast<std::uint8_t>(proto.trace_flags())
4851
: trace::TraceFlags::kIsSampled);

src/tests/libxrpl/telemetry/TelemetryConfig.cpp

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,7 @@ TEST(TelemetryConfig, setup_defaults)
3434
TEST(TelemetryConfig, parse_empty_section)
3535
{
3636
Section section;
37-
auto setup =
38-
telemetry::setup_Telemetry(section, "nHUtest123", "2.0.0");
37+
auto setup = telemetry::setup_Telemetry(section, "nHUtest123", "2.0.0");
3938

4039
EXPECT_FALSE(setup.enabled);
4140
EXPECT_EQ(setup.serviceName, "rippled");
@@ -70,15 +69,13 @@ TEST(TelemetryConfig, parse_full_section)
7069
section.set("trace_peer", "1");
7170
section.set("trace_ledger", "0");
7271

73-
auto setup =
74-
telemetry::setup_Telemetry(section, "nHUtest123", "2.0.0");
72+
auto setup = telemetry::setup_Telemetry(section, "nHUtest123", "2.0.0");
7573

7674
EXPECT_TRUE(setup.enabled);
7775
EXPECT_EQ(setup.serviceName, "my-rippled");
7876
EXPECT_EQ(setup.serviceInstanceId, "custom-id");
7977
EXPECT_EQ(setup.exporterType, "otlp_http");
80-
EXPECT_EQ(
81-
setup.exporterEndpoint, "http://collector:4318/v1/traces");
78+
EXPECT_EQ(setup.exporterEndpoint, "http://collector:4318/v1/traces");
8279
EXPECT_TRUE(setup.useTls);
8380
EXPECT_EQ(setup.tlsCertPath, "/etc/ssl/ca.pem");
8481
EXPECT_DOUBLE_EQ(setup.samplingRatio, 0.5);
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
#include <gtest/gtest.h>
2+
3+
#ifdef XRPL_ENABLE_TELEMETRY
4+
5+
#include <xrpl/telemetry/TraceContextPropagator.h>
6+
7+
#include <opentelemetry/context/context.h>
8+
#include <opentelemetry/trace/default_span.h>
9+
#include <opentelemetry/trace/span_context.h>
10+
#include <opentelemetry/trace/trace_flags.h>
11+
#include <opentelemetry/nostd/span.h>
12+
#include <opentelemetry/trace/context.h>
13+
#include <opentelemetry/trace/trace_id.h>
14+
15+
#include <cstring>
16+
17+
namespace trace = opentelemetry::trace;
18+
19+
TEST(TraceContextPropagator, round_trip)
20+
{
21+
std::uint8_t traceIdBuf[16] = {
22+
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
23+
0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10};
24+
std::uint8_t spanIdBuf[8] = {
25+
0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x11, 0x22};
26+
27+
trace::TraceId traceId(
28+
opentelemetry::nostd::span<const uint8_t, 16>(traceIdBuf, 16));
29+
trace::SpanId spanId(
30+
opentelemetry::nostd::span<const uint8_t, 8>(spanIdBuf, 8));
31+
trace::TraceFlags flags(trace::TraceFlags::kIsSampled);
32+
trace::SpanContext spanCtx(traceId, spanId, flags, true);
33+
34+
auto ctx = opentelemetry::context::Context{}.SetValue(
35+
trace::kSpanKey,
36+
opentelemetry::nostd::shared_ptr<trace::Span>(
37+
new trace::DefaultSpan(spanCtx)));
38+
39+
protocol::TraceContext proto;
40+
xrpl::telemetry::injectToProtobuf(ctx, proto);
41+
42+
EXPECT_TRUE(proto.has_trace_id());
43+
EXPECT_EQ(proto.trace_id().size(), 16u);
44+
EXPECT_TRUE(proto.has_span_id());
45+
EXPECT_EQ(proto.span_id().size(), 8u);
46+
EXPECT_EQ(
47+
proto.trace_flags(),
48+
static_cast<uint32_t>(trace::TraceFlags::kIsSampled));
49+
EXPECT_EQ(std::memcmp(proto.trace_id().data(), traceIdBuf, 16), 0);
50+
EXPECT_EQ(std::memcmp(proto.span_id().data(), spanIdBuf, 8), 0);
51+
52+
auto extractedCtx =
53+
xrpl::telemetry::extractFromProtobuf(proto);
54+
auto extractedSpan = trace::GetSpan(extractedCtx);
55+
ASSERT_NE(extractedSpan, nullptr);
56+
57+
auto const& extracted = extractedSpan->GetContext();
58+
EXPECT_TRUE(extracted.IsValid());
59+
EXPECT_TRUE(extracted.IsRemote());
60+
EXPECT_EQ(extracted.trace_id(), traceId);
61+
EXPECT_EQ(extracted.span_id(), spanId);
62+
EXPECT_TRUE(
63+
extracted.trace_flags().IsSampled());
64+
}
65+
66+
TEST(TraceContextPropagator, extract_empty_protobuf)
67+
{
68+
protocol::TraceContext proto;
69+
auto ctx = xrpl::telemetry::extractFromProtobuf(proto);
70+
auto span = trace::GetSpan(ctx);
71+
if (span)
72+
{
73+
EXPECT_FALSE(span->GetContext().IsValid());
74+
}
75+
}
76+
77+
TEST(TraceContextPropagator, extract_wrong_size_trace_id)
78+
{
79+
protocol::TraceContext proto;
80+
proto.set_trace_id(std::string(8, '\x01'));
81+
proto.set_span_id(std::string(8, '\xaa'));
82+
83+
auto ctx = xrpl::telemetry::extractFromProtobuf(proto);
84+
auto span = trace::GetSpan(ctx);
85+
if (span)
86+
{
87+
EXPECT_FALSE(span->GetContext().IsValid());
88+
}
89+
}
90+
91+
TEST(TraceContextPropagator, extract_wrong_size_span_id)
92+
{
93+
protocol::TraceContext proto;
94+
proto.set_trace_id(std::string(16, '\x01'));
95+
proto.set_span_id(std::string(4, '\xaa'));
96+
97+
auto ctx = xrpl::telemetry::extractFromProtobuf(proto);
98+
auto span = trace::GetSpan(ctx);
99+
if (span)
100+
{
101+
EXPECT_FALSE(span->GetContext().IsValid());
102+
}
103+
}
104+
105+
TEST(TraceContextPropagator, inject_invalid_span)
106+
{
107+
auto ctx = opentelemetry::context::Context{};
108+
protocol::TraceContext proto;
109+
xrpl::telemetry::injectToProtobuf(ctx, proto);
110+
111+
EXPECT_FALSE(proto.has_trace_id());
112+
EXPECT_FALSE(proto.has_span_id());
113+
}
114+
115+
TEST(TraceContextPropagator, flags_preservation)
116+
{
117+
std::uint8_t traceIdBuf[16] = {
118+
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
119+
std::uint8_t spanIdBuf[8] = {1, 2, 3, 4, 5, 6, 7, 8};
120+
121+
// Test with flags NOT sampled (flags = 0)
122+
trace::TraceFlags flags(0);
123+
trace::SpanContext spanCtx(
124+
trace::TraceId(
125+
opentelemetry::nostd::span<const uint8_t, 16>(traceIdBuf, 16)),
126+
trace::SpanId(
127+
opentelemetry::nostd::span<const uint8_t, 8>(spanIdBuf, 8)),
128+
flags,
129+
true);
130+
131+
auto ctx = opentelemetry::context::Context{}.SetValue(
132+
trace::kSpanKey,
133+
opentelemetry::nostd::shared_ptr<trace::Span>(
134+
new trace::DefaultSpan(spanCtx)));
135+
136+
protocol::TraceContext proto;
137+
xrpl::telemetry::injectToProtobuf(ctx, proto);
138+
EXPECT_EQ(proto.trace_flags(), 0u);
139+
140+
auto extracted = xrpl::telemetry::extractFromProtobuf(proto);
141+
auto span = trace::GetSpan(extracted);
142+
ASSERT_NE(span, nullptr);
143+
EXPECT_FALSE(span->GetContext().trace_flags().IsSampled());
144+
}
145+
146+
#else // XRPL_ENABLE_TELEMETRY not defined
147+
148+
TEST(TraceContextPropagator, compiles_without_telemetry)
149+
{
150+
SUCCEED();
151+
}
152+
153+
#endif // XRPL_ENABLE_TELEMETRY

src/tests/libxrpl/telemetry/TracingMacros.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
#include <xrpl/telemetry/Telemetry.h>
21
#include <xrpld/telemetry/TracingInstrumentation.h>
32

3+
#include <xrpl/telemetry/Telemetry.h>
4+
45
#include <gtest/gtest.h>
56

67
using namespace xrpl;

0 commit comments

Comments
 (0)