From 2209343c4f4625f2c41ec9c87a529e83e7802f09 Mon Sep 17 00:00:00 2001 From: Tom Tan Date: Fri, 9 Jul 2021 01:24:21 -0700 Subject: [PATCH] Populate resource attributes into process tags in Jaeger (#897) --- .../exporters/jaeger/recordable.h | 6 +++ exporters/jaeger/src/recordable.cc | 39 ++++++++++++++++--- exporters/jaeger/src/thrift_sender.cc | 1 + .../jaeger/test/jaeger_recordable_test.cc | 35 +++++++++++++++++ 4 files changed, 76 insertions(+), 5 deletions(-) diff --git a/exporters/jaeger/include/opentelemetry/exporters/jaeger/recordable.h b/exporters/jaeger/include/opentelemetry/exporters/jaeger/recordable.h index bd827f7669..7829eef011 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 ResourceTags() noexcept { return std::move(resource_tags_); } std::vector Logs() noexcept { return std::move(logs_); } const std::string &ServiceName() const noexcept { return service_name_; } @@ -99,9 +100,14 @@ class Recordable final : public sdk::trace::Recordable const opentelemetry::common::AttributeValue &value, std::vector &tags); + void PopulateAttribute(nostd::string_view key, + const sdk::common::OwnedAttributeValue &value, + std::vector &tags); + private: std::unique_ptr span_; std::vector tags_; + std::vector resource_tags_; std::vector logs_; std::string service_name_; }; diff --git a/exporters/jaeger/src/recordable.cc b/exporters/jaeger/src/recordable.cc index 38370ba8a2..b932140897 100644 --- a/exporters/jaeger/src/recordable.cc +++ b/exporters/jaeger/src/recordable.cc @@ -41,6 +41,29 @@ void Recordable::PopulateAttribute(nostd::string_view key, // TODO: extend other AttributeType to the types supported by Jaeger. } +void Recordable::PopulateAttribute(nostd::string_view key, + const sdk::common::OwnedAttributeValue &value, + std::vector &tags) +{ + if (nostd::holds_alternative(value)) + { + AddTag(std::string{key}, nostd::get(value), tags); + } + else if (nostd::holds_alternative(value)) + { + AddTag(std::string{key}, nostd::get(value), tags); + } + else if (nostd::holds_alternative(value)) + { + AddTag(std::string{key}, nostd::get(value), tags); + } + else if (nostd::holds_alternative(value)) + { + AddTag(std::string{key}, std::string{nostd::get(value)}, tags); + } + // TODO: extend other OwnedAttributeType to the types supported by Jaeger. +} + void Recordable::SetIdentity(const trace::SpanContext &span_context, trace::SpanId parent_span_id) noexcept { @@ -77,7 +100,7 @@ void Recordable::AddEvent(nostd::string_view name, const common::KeyValueIterable &attributes) noexcept { std::vector tags; - PopulateAttribute("event", name.data(), tags); + PopulateAttribute("event", static_cast(name.data()), tags); attributes.ForEachKeyValue([&](nostd::string_view key, common::AttributeValue value) noexcept { PopulateAttribute(key, value, tags); @@ -131,11 +154,17 @@ void Recordable::SetName(nostd::string_view name) noexcept void Recordable::SetResource(const opentelemetry::sdk::resource::Resource &resource) noexcept { - // only service.name attribute is supported by specs as of now. - auto attributes = resource.GetAttributes(); - if (attributes.find(OTEL_CPP_GET_ATTR(AttrServiceName)) != attributes.end()) + for (const auto &attribute_iter : resource.GetAttributes()) { - service_name_ = nostd::get(attributes[OTEL_CPP_GET_ATTR(AttrServiceName)]); + if (attribute_iter.first != "service.name") + { + PopulateAttribute(nostd::string_view{attribute_iter.first}, attribute_iter.second, + resource_tags_); + } + else + { + service_name_ = nostd::get(attribute_iter.second); + } } } diff --git a/exporters/jaeger/src/thrift_sender.cc b/exporters/jaeger/src/thrift_sender.cc index 9a0b5fae6d..488f4fc8c1 100644 --- a/exporters/jaeger/src/thrift_sender.cc +++ b/exporters/jaeger/src/thrift_sender.cc @@ -29,6 +29,7 @@ int ThriftSender::Append(std::unique_ptr &&span) noexcept if (process_.serviceName.empty()) { process_.serviceName = span->ServiceName(); + process_.__set_tags(span->ResourceTags()); process_bytes_size_ = CalcSizeOfSerializedThrift(process_); max_span_bytes -= process_bytes_size_; diff --git a/exporters/jaeger/test/jaeger_recordable_test.cc b/exporters/jaeger/test/jaeger_recordable_test.cc index e3ef6b07bf..693e630fe3 100644 --- a/exporters/jaeger/test/jaeger_recordable_test.cc +++ b/exporters/jaeger/test/jaeger_recordable_test.cc @@ -178,3 +178,38 @@ TEST(JaegerSpanRecordable, SetInstrumentationLibrary) EXPECT_EQ(tags[1].vType, thrift::TagType::STRING); EXPECT_EQ(tags[1].vStr, library_version); } + +TEST(JaegerSpanRecordable, SetResource) +{ + opentelemetry::exporter::jaeger::Recordable rec; + + const std::string service_name_key = "service.name"; + std::string service_name_value = "test-jaeger-service-name"; + auto resource = opentelemetry::sdk::resource::Resource::Create( + {{service_name_key, service_name_value}, {"key1", "value1"}, {"key2", "value2"}}); + rec.SetResource(resource); + + auto service_name = rec.ServiceName(); + auto resource_tags = rec.ResourceTags(); + + EXPECT_GE(resource_tags.size(), 2); + EXPECT_EQ(service_name, service_name_value); + + bool found_key1 = false; + bool found_key2 = false; + for (const auto &tag : resource_tags) + { + if (tag.key == "key1") + { + found_key1 = true; + EXPECT_EQ(tag.vType, thrift::TagType::STRING); + EXPECT_EQ(tag.vStr, "value1"); + } + else if (tag.key == "key2") + { + found_key2 = true; + EXPECT_EQ(tag.vType, thrift::TagType::STRING); + EXPECT_EQ(tag.vStr, "value2"); + } + } +}