Skip to content

Commit fd5a621

Browse files
authored
Add support for span links to Jaeger export. (#1251)
1 parent c96a3e3 commit fd5a621

File tree

5 files changed

+67
-1
lines changed

5 files changed

+67
-1
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ Increment the:
1515

1616
## [Unreleased]
1717

18+
* [EXPORTER] Jaeger Exporter - Populate Span Links ([#1251](https://github.com/open-telemetry/opentelemetry-cpp/pull/1251))
19+
1820
## [1.2.0] 2022-01-31
1921

2022
* [CI] Continuous benchmark tests as part of the CI ([#1174](https://github.com/open-telemetry/opentelemetry-cpp/pull/1174))

exporters/jaeger/include/opentelemetry/exporters/jaeger/recordable.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ class JaegerRecordable final : public sdk::trace::Recordable
5858
std::vector<thrift::Tag> Tags() noexcept { return std::move(tags_); }
5959
std::vector<thrift::Tag> ResourceTags() noexcept { return std::move(resource_tags_); }
6060
std::vector<thrift::Log> Logs() noexcept { return std::move(logs_); }
61+
std::vector<thrift::SpanRef> References() noexcept { return std::move(references_); }
6162
const std::string &ServiceName() const noexcept { return service_name_; }
6263

6364
void SetIdentity(const opentelemetry::trace::SpanContext &span_context,
@@ -109,6 +110,7 @@ class JaegerRecordable final : public sdk::trace::Recordable
109110
std::vector<thrift::Tag> tags_;
110111
std::vector<thrift::Tag> resource_tags_;
111112
std::vector<thrift::Log> logs_;
113+
std::vector<thrift::SpanRef> references_;
112114
std::string service_name_;
113115
};
114116

exporters/jaeger/src/recordable.cc

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,33 @@ void JaegerRecordable::SetInstrumentationLibrary(
193193
void JaegerRecordable::AddLink(const trace::SpanContext &span_context,
194194
const common::KeyValueIterable &attributes) noexcept
195195
{
196-
// TODO: convert link to SpanRefernece
196+
// Note: "The Link’s attributes cannot be represented in Jaeger explicitly."
197+
// -- https://opentelemetry.io/docs/reference/specification/trace/sdk_exporters/jaeger/#links
198+
//
199+
// This implementation does not (currently) implement the optional conversion to span logs.
200+
201+
thrift::SpanRef reference;
202+
203+
reference.__set_refType(thrift::SpanRefType::FOLLOWS_FROM);
204+
205+
// IDs should be converted to big endian before transmission.
206+
// https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/sdk_exporters/jaeger.md#ids
207+
#if JAEGER_IS_LITTLE_ENDIAN == 1
208+
reference.__set_traceIdHigh(
209+
otel_bswap_64(*(reinterpret_cast<const int64_t *>(span_context.trace_id().Id().data()))));
210+
reference.__set_traceIdLow(
211+
otel_bswap_64(*(reinterpret_cast<const int64_t *>(span_context.trace_id().Id().data()) + 1)));
212+
reference.__set_spanId(
213+
otel_bswap_64(*(reinterpret_cast<const int64_t *>(span_context.span_id().Id().data()))));
214+
#else
215+
reference.__set_traceIdLow(
216+
*(reinterpret_cast<const int64_t *>(span_context.trace_id().Id().data())));
217+
reference.__set_traceIdHigh(
218+
*(reinterpret_cast<const int64_t *>(span_context.trace_id().Id().data()) + 1));
219+
reference.__set_spanId(*(reinterpret_cast<const int64_t *>(span_context.span_id().Id().data())));
220+
#endif
221+
222+
references_.push_back(reference);
197223
}
198224

199225
void JaegerRecordable::SetStatus(trace::StatusCode code, nostd::string_view description) noexcept

exporters/jaeger/src/thrift_sender.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ int ThriftSender::Append(std::unique_ptr<JaegerRecordable> &&span) noexcept
4040
auto jaeger_span = std::unique_ptr<thrift::Span>(span->Span());
4141
jaeger_span->__set_tags(span->Tags());
4242
jaeger_span->__set_logs(span->Logs());
43+
jaeger_span->__set_references(span->References());
4344

4445
const uint32_t span_size = CalcSizeOfSerializedThrift(*jaeger_span);
4546
if (span_size > max_span_bytes)

exporters/jaeger/test/jaeger_recordable_test.cc

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ using namespace opentelemetry::exporter::jaeger;
2121
using namespace opentelemetry::sdk::instrumentationlibrary;
2222
using std::vector;
2323

24+
using Attributes = std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>>;
25+
2426
TEST(JaegerSpanRecordable, SetIdentity)
2527
{
2628
JaegerRecordable rec;
@@ -297,3 +299,36 @@ TEST(JaegerSpanRecordable, SetResource)
297299
}
298300
}
299301
}
302+
303+
TEST(JaegerSpanRecordable, AddLink)
304+
{
305+
JaegerRecordable rec;
306+
307+
int64_t trace_id_val[2] = {0x0000000000000000, 0x1000000000000000};
308+
int64_t span_id_val = 0x2000000000000000;
309+
310+
const trace::TraceId trace_id{
311+
nostd::span<uint8_t, 16>(reinterpret_cast<uint8_t *>(trace_id_val), 16)};
312+
313+
const trace::SpanId span_id(
314+
nostd::span<uint8_t, 8>(reinterpret_cast<uint8_t *>(&span_id_val), 8));
315+
316+
const trace::SpanContext span_context{trace_id, span_id,
317+
trace::TraceFlags{trace::TraceFlags::kIsSampled}, true};
318+
rec.AddLink(span_context, common::KeyValueIterableView<Attributes>({{"attr1", "string"}}));
319+
320+
auto references = rec.References();
321+
EXPECT_EQ(references.size(), 1);
322+
323+
auto reference = references.front();
324+
325+
#if JAEGER_IS_LITTLE_ENDIAN == 1
326+
EXPECT_EQ(reference.traceIdLow, otel_bswap_64(trace_id_val[1]));
327+
EXPECT_EQ(reference.traceIdHigh, otel_bswap_64(trace_id_val[0]));
328+
EXPECT_EQ(reference.spanId, otel_bswap_64(span_id_val));
329+
#else
330+
EXPECT_EQ(reference.traceIdLow, trace_id_val[0]);
331+
EXPECT_EQ(reference.traceIdHigh, trace_id_val[1]);
332+
EXPECT_EQ(reference.spanId, span_id_val);
333+
#endif
334+
}

0 commit comments

Comments
 (0)