Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for span links to Jaeger export. #1251

Merged
merged 1 commit into from
Mar 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ Increment the:

## [Unreleased]

* [EXPORTER] Jaeger Exporter - Populate Span Links ([#1251](https://github.com/open-telemetry/opentelemetry-cpp/pull/1251))

## [1.2.0] 2022-01-31

* [CI] Continuous benchmark tests as part of the CI ([#1174](https://github.com/open-telemetry/opentelemetry-cpp/pull/1174))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ class JaegerRecordable final : public sdk::trace::Recordable
std::vector<thrift::Tag> Tags() noexcept { return std::move(tags_); }
std::vector<thrift::Tag> ResourceTags() noexcept { return std::move(resource_tags_); }
std::vector<thrift::Log> Logs() noexcept { return std::move(logs_); }
std::vector<thrift::SpanRef> References() noexcept { return std::move(references_); }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems SpanRefs are not attached to jaeger_span?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const std::string &ServiceName() const noexcept { return service_name_; }

void SetIdentity(const opentelemetry::trace::SpanContext &span_context,
Expand Down Expand Up @@ -109,6 +110,7 @@ class JaegerRecordable final : public sdk::trace::Recordable
std::vector<thrift::Tag> tags_;
std::vector<thrift::Tag> resource_tags_;
std::vector<thrift::Log> logs_;
std::vector<thrift::SpanRef> references_;
std::string service_name_;
};

Expand Down
28 changes: 27 additions & 1 deletion exporters/jaeger/src/recordable.cc
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,33 @@ void JaegerRecordable::SetInstrumentationLibrary(
void JaegerRecordable::AddLink(const trace::SpanContext &span_context,
const common::KeyValueIterable &attributes) noexcept
{
// TODO: convert link to SpanRefernece
// Note: "The Link’s attributes cannot be represented in Jaeger explicitly."
// -- https://opentelemetry.io/docs/reference/specification/trace/sdk_exporters/jaeger/#links
//
// This implementation does not (currently) implement the optional conversion to span logs.

thrift::SpanRef reference;

reference.__set_refType(thrift::SpanRefType::FOLLOWS_FROM);

// IDs should be converted to big endian before transmission.
// https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/sdk_exporters/jaeger.md#ids
#if JAEGER_IS_LITTLE_ENDIAN == 1
reference.__set_traceIdHigh(
otel_bswap_64(*(reinterpret_cast<const int64_t *>(span_context.trace_id().Id().data()))));
reference.__set_traceIdLow(
otel_bswap_64(*(reinterpret_cast<const int64_t *>(span_context.trace_id().Id().data()) + 1)));
reference.__set_spanId(
otel_bswap_64(*(reinterpret_cast<const int64_t *>(span_context.span_id().Id().data()))));
#else
reference.__set_traceIdLow(
*(reinterpret_cast<const int64_t *>(span_context.trace_id().Id().data())));
reference.__set_traceIdHigh(
*(reinterpret_cast<const int64_t *>(span_context.trace_id().Id().data()) + 1));
reference.__set_spanId(*(reinterpret_cast<const int64_t *>(span_context.span_id().Id().data())));
#endif
lalitb marked this conversation as resolved.
Show resolved Hide resolved

references_.push_back(reference);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how will this list of links get exported to the backend? Does some code need to be added in ThriftSender::Append() to do that?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

}

void JaegerRecordable::SetStatus(trace::StatusCode code, nostd::string_view description) noexcept
Expand Down
1 change: 1 addition & 0 deletions exporters/jaeger/src/thrift_sender.cc
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ int ThriftSender::Append(std::unique_ptr<JaegerRecordable> &&span) noexcept
auto jaeger_span = std::unique_ptr<thrift::Span>(span->Span());
jaeger_span->__set_tags(span->Tags());
jaeger_span->__set_logs(span->Logs());
jaeger_span->__set_references(span->References());

const uint32_t span_size = CalcSizeOfSerializedThrift(*jaeger_span);
if (span_size > max_span_bytes)
Expand Down
35 changes: 35 additions & 0 deletions exporters/jaeger/test/jaeger_recordable_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ using namespace opentelemetry::exporter::jaeger;
using namespace opentelemetry::sdk::instrumentationlibrary;
using std::vector;

using Attributes = std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>>;

TEST(JaegerSpanRecordable, SetIdentity)
{
JaegerRecordable rec;
Expand Down Expand Up @@ -297,3 +299,36 @@ TEST(JaegerSpanRecordable, SetResource)
}
}
}

TEST(JaegerSpanRecordable, AddLink)
{
JaegerRecordable rec;

int64_t trace_id_val[2] = {0x0000000000000000, 0x1000000000000000};
int64_t span_id_val = 0x2000000000000000;

const trace::TraceId trace_id{
nostd::span<uint8_t, 16>(reinterpret_cast<uint8_t *>(trace_id_val), 16)};

const trace::SpanId span_id(
nostd::span<uint8_t, 8>(reinterpret_cast<uint8_t *>(&span_id_val), 8));

const trace::SpanContext span_context{trace_id, span_id,
trace::TraceFlags{trace::TraceFlags::kIsSampled}, true};
rec.AddLink(span_context, common::KeyValueIterableView<Attributes>({{"attr1", "string"}}));

auto references = rec.References();
EXPECT_EQ(references.size(), 1);

auto reference = references.front();

#if JAEGER_IS_LITTLE_ENDIAN == 1
EXPECT_EQ(reference.traceIdLow, otel_bswap_64(trace_id_val[1]));
EXPECT_EQ(reference.traceIdHigh, otel_bswap_64(trace_id_val[0]));
EXPECT_EQ(reference.spanId, otel_bswap_64(span_id_val));
#else
EXPECT_EQ(reference.traceIdLow, trace_id_val[0]);
EXPECT_EQ(reference.traceIdHigh, trace_id_val[1]);
EXPECT_EQ(reference.spanId, span_id_val);
#endif
}