diff --git a/exporters/jaeger/include/opentelemetry/exporters/jaeger/recordable.h b/exporters/jaeger/include/opentelemetry/exporters/jaeger/recordable.h index 01a4bb0d79b..bd827f7669b 100644 --- a/exporters/jaeger/include/opentelemetry/exporters/jaeger/recordable.h +++ b/exporters/jaeger/include/opentelemetry/exporters/jaeger/recordable.h @@ -56,6 +56,7 @@ class Recordable final : public sdk::trace::Recordable thrift::Span *Span() noexcept { return span_.release(); } std::vector Tags() noexcept { return std::move(tags_); } + std::vector Logs() noexcept { return std::move(logs_); } const std::string &ServiceName() const noexcept { return service_name_; } void SetIdentity(const opentelemetry::trace::SpanContext &span_context, @@ -88,18 +89,20 @@ class Recordable final : public sdk::trace::Recordable &instrumentation_library) noexcept override; private: - void AddTag(const std::string &key, const std::string &value); - void AddTag(const std::string &key, const char *value); - void AddTag(const std::string &key, bool value); - void AddTag(const std::string &key, int64_t value); - void AddTag(const std::string &key, double value); + void AddTag(const std::string &key, const std::string &value, std::vector &tags); + void AddTag(const std::string &key, const char *value, std::vector &tags); + void AddTag(const std::string &key, bool value, std::vector &tags); + void AddTag(const std::string &key, int64_t value, std::vector &tags); + void AddTag(const std::string &key, double value, std::vector &tags); void PopulateAttribute(nostd::string_view key, - const opentelemetry::common::AttributeValue &value); + const opentelemetry::common::AttributeValue &value, + std::vector &tags); private: std::unique_ptr span_; std::vector tags_; + std::vector logs_; std::string service_name_; }; diff --git a/exporters/jaeger/src/recordable.cc b/exporters/jaeger/src/recordable.cc index c9425b963bc..38370ba8a2b 100644 --- a/exporters/jaeger/src/recordable.cc +++ b/exporters/jaeger/src/recordable.cc @@ -14,27 +14,29 @@ using namespace opentelemetry::sdk::resource; Recordable::Recordable() : span_{new thrift::Span} {} -void Recordable::PopulateAttribute(nostd::string_view key, const common::AttributeValue &value) +void Recordable::PopulateAttribute(nostd::string_view key, + const common::AttributeValue &value, + std::vector &tags) { if (nostd::holds_alternative(value)) { - AddTag(std::string{key}, nostd::get(value)); + AddTag(std::string{key}, nostd::get(value), tags); } else if (nostd::holds_alternative(value)) { - AddTag(std::string{key}, nostd::get(value)); + AddTag(std::string{key}, nostd::get(value), tags); } else if (nostd::holds_alternative(value)) { - AddTag(std::string{key}, nostd::get(value)); + AddTag(std::string{key}, nostd::get(value), tags); } else if (nostd::holds_alternative(value)) { - AddTag(std::string{key}, std::string{nostd::get(value)}); + AddTag(std::string{key}, std::string{nostd::get(value)}, tags); } else if (nostd::holds_alternative(value)) { - AddTag(std::string{key}, std::string{nostd::get(value)}); + AddTag(std::string{key}, std::string{nostd::get(value)}, tags); } // TODO: extend other AttributeType to the types supported by Jaeger. } @@ -67,22 +69,33 @@ void Recordable::SetIdentity(const trace::SpanContext &span_context, void Recordable::SetAttribute(nostd::string_view key, const common::AttributeValue &value) noexcept { - PopulateAttribute(key, value); + PopulateAttribute(key, value, tags_); } void Recordable::AddEvent(nostd::string_view name, common::SystemTimestamp timestamp, const common::KeyValueIterable &attributes) noexcept { - // TODO: convert event to Jaeger Log + std::vector tags; + PopulateAttribute("event", name.data(), tags); + + attributes.ForEachKeyValue([&](nostd::string_view key, common::AttributeValue value) noexcept { + PopulateAttribute(key, value, tags); + return true; + }); + thrift::Log log; + log.__set_fields(tags); + log.__set_timestamp( + std::chrono::duration_cast(timestamp.time_since_epoch()).count()); + logs_.push_back(log); } void Recordable::SetInstrumentationLibrary( const opentelemetry::sdk::instrumentationlibrary::InstrumentationLibrary &instrumentation_library) noexcept { - AddTag("otel.library.name", instrumentation_library.GetName()); - AddTag("otel.library.version", instrumentation_library.GetVersion()); + AddTag("otel.library.name", instrumentation_library.GetName(), tags_); + AddTag("otel.library.version", instrumentation_library.GetVersion(), tags_); } void Recordable::AddLink(const trace::SpanContext &span_context, @@ -100,15 +113,15 @@ void Recordable::SetStatus(trace::StatusCode code, nostd::string_view descriptio if (code == trace::StatusCode::kOk) { - AddTag("otel.status_code", "OK"); + AddTag("otel.status_code", "OK", tags_); } else if (code == trace::StatusCode::kError) { - AddTag("otel.status_code", "ERROR"); - AddTag("error", true); + AddTag("otel.status_code", "ERROR", tags_); + AddTag("error", true, tags_); } - AddTag("otel.status_description", std::string{description}); + AddTag("otel.status_description", std::string{description}, tags_); } void Recordable::SetName(nostd::string_view name) noexcept @@ -166,11 +179,13 @@ void Recordable::SetSpanKind(trace::SpanKind span_kind) noexcept if (span_kind_str != nullptr) { - AddTag("span.kind", span_kind_str); + AddTag("span.kind", span_kind_str, tags_); } } -void Recordable::AddTag(const std::string &key, const std::string &value) +void Recordable::AddTag(const std::string &key, + const std::string &value, + std::vector &tags) { thrift::Tag tag; @@ -178,15 +193,15 @@ void Recordable::AddTag(const std::string &key, const std::string &value) tag.__set_vType(thrift::TagType::STRING); tag.__set_vStr(value); - tags_.push_back(tag); + tags.push_back(tag); } -void Recordable::AddTag(const std::string &key, const char *value) +void Recordable::AddTag(const std::string &key, const char *value, std::vector &tags) { - AddTag(key, std::string{value}); + AddTag(key, std::string{value}, tags); } -void Recordable::AddTag(const std::string &key, bool value) +void Recordable::AddTag(const std::string &key, bool value, std::vector &tags) { thrift::Tag tag; @@ -194,10 +209,10 @@ void Recordable::AddTag(const std::string &key, bool value) tag.__set_vType(thrift::TagType::BOOL); tag.__set_vBool(value); - tags_.push_back(tag); + tags.push_back(tag); } -void Recordable::AddTag(const std::string &key, int64_t value) +void Recordable::AddTag(const std::string &key, int64_t value, std::vector &tags) { thrift::Tag tag; @@ -205,10 +220,10 @@ void Recordable::AddTag(const std::string &key, int64_t value) tag.__set_vType(thrift::TagType::LONG); tag.__set_vLong(value); - tags_.push_back(tag); + tags.push_back(tag); } -void Recordable::AddTag(const std::string &key, double value) +void Recordable::AddTag(const std::string &key, double value, std::vector &tags) { thrift::Tag tag; @@ -216,7 +231,7 @@ void Recordable::AddTag(const std::string &key, double value) tag.__set_vType(thrift::TagType::DOUBLE); tag.__set_vDouble(value); - tags_.push_back(tag); + tags.push_back(tag); } } // namespace jaeger diff --git a/exporters/jaeger/src/thrift_sender.cc b/exporters/jaeger/src/thrift_sender.cc index 8cca1806095..9a0b5fae6d5 100644 --- a/exporters/jaeger/src/thrift_sender.cc +++ b/exporters/jaeger/src/thrift_sender.cc @@ -36,6 +36,7 @@ int ThriftSender::Append(std::unique_ptr &&span) noexcept thrift::Span &jaeger_span = *span->Span(); jaeger_span.__set_tags(span->Tags()); + jaeger_span.__set_logs(span->Logs()); const uint32_t span_size = CalcSizeOfSerializedThrift(jaeger_span); if (span_size > max_span_bytes) diff --git a/exporters/jaeger/test/jaeger_recordable_test.cc b/exporters/jaeger/test/jaeger_recordable_test.cc index 73a089556e2..e3ef6b07bfc 100644 --- a/exporters/jaeger/test/jaeger_recordable_test.cc +++ b/exporters/jaeger/test/jaeger_recordable_test.cc @@ -123,6 +123,40 @@ TEST(JaegerSpanRecordable, SetStatus) EXPECT_EQ(tags[2].vStr, error_description); } +TEST(JaegerSpanRecordable, AddEvent) +{ + opentelemetry::exporter::jaeger::Recordable rec; + + nostd::string_view name = "Test Event"; + + std::chrono::system_clock::time_point event_time = std::chrono::system_clock::now(); + opentelemetry::common::SystemTimestamp event_timestamp(event_time); + uint64_t epoch_us = + std::chrono::duration_cast(event_time.time_since_epoch()).count(); + + const int kNumAttributes = 3; + std::string keys[kNumAttributes] = {"attr1", "attr2", "attr3"}; + int64_t values[kNumAttributes] = {4, 7, 23}; + std::map attributes = { + {keys[0], values[0]}, {keys[1], values[1]}, {keys[2], values[2]}}; + + rec.AddEvent( + "Test Event", event_timestamp, + opentelemetry::common::KeyValueIterableView>(attributes)); + thrift::Log log = rec.Logs().at(0); + EXPECT_EQ(log.timestamp, epoch_us); + auto tags = log.fields; + size_t index = 0; + EXPECT_EQ(tags[index].key, "event"); + EXPECT_EQ(tags[index++].vStr, "Test Event"); + while (index <= kNumAttributes) + { + EXPECT_EQ(tags[index].key, keys[index - 1]); + EXPECT_EQ(tags[index].vLong, values[index - 1]); + index++; + } +} + TEST(JaegerSpanRecordable, SetInstrumentationLibrary) { opentelemetry::exporter::jaeger::Recordable rec;