diff --git a/exporters/etw/include/opentelemetry/exporters/etw/etw_data.h b/exporters/etw/include/opentelemetry/exporters/etw/etw_data.h index a60c2517af..5da8057deb 100644 --- a/exporters/etw/include/opentelemetry/exporters/etw/etw_data.h +++ b/exporters/etw/include/opentelemetry/exporters/etw/etw_data.h @@ -17,6 +17,7 @@ #include "opentelemetry/trace/trace_id.h" #include "opentelemetry/trace/tracer_provider.h" +#include "opentelemetry/sdk/resource/resource.h" #include "opentelemetry/sdk/trace/exporter.h" #include "opentelemetry/sdk/trace/recordable.h" #include "opentelemetry/sdk/trace/span_data.h" @@ -498,6 +499,14 @@ class ETWSpanData final : public sdk::trace::Recordable span_kind_ = span_kind; } + void SetResourceAttribute( + std::string key, + const opentelemetry::sdk::common::OwnedAttributeValue &value) noexcept override + { + UNREFERENCED_PARAMETER(key); + UNREFERENCED_PARAMETER(value); + } + void SetStartTime(opentelemetry::core::SystemTimestamp start_time) noexcept override { start_time_ = start_time; diff --git a/exporters/otlp/include/opentelemetry/exporters/otlp/recordable.h b/exporters/otlp/include/opentelemetry/exporters/otlp/recordable.h index c37a68aba5..717d6471b2 100644 --- a/exporters/otlp/include/opentelemetry/exporters/otlp/recordable.h +++ b/exporters/otlp/include/opentelemetry/exporters/otlp/recordable.h @@ -1,6 +1,8 @@ #pragma once +#include "opentelemetry/proto/resource/v1/resource.pb.h" #include "opentelemetry/proto/trace/v1/trace.pb.h" +#include "opentelemetry/sdk/resource/resource.h" #include "opentelemetry/sdk/trace/recordable.h" #include "opentelemetry/version.h" @@ -34,12 +36,19 @@ class Recordable final : public sdk::trace::Recordable void SetSpanKind(opentelemetry::trace::SpanKind span_kind) noexcept override; + void SetResourceAttribute( + std::string key, + const opentelemetry::sdk::common::OwnedAttributeValue &value) noexcept override; + void SetStartTime(opentelemetry::core::SystemTimestamp start_time) noexcept override; void SetDuration(std::chrono::nanoseconds duration) noexcept override; + proto::resource::v1::Resource &GetResources() noexcept; + private: proto::trace::v1::Span span_; + proto::resource::v1::Resource resource_; }; } // namespace otlp } // namespace exporter diff --git a/exporters/otlp/src/otlp_exporter.cc b/exporters/otlp/src/otlp_exporter.cc index 63db30436c..671d319b68 100644 --- a/exporters/otlp/src/otlp_exporter.cc +++ b/exporters/otlp/src/otlp_exporter.cc @@ -23,10 +23,23 @@ void PopulateRequest(const nostd::span> auto resource_span = request->add_resource_spans(); auto instrumentation_lib = resource_span->add_instrumentation_library_spans(); + // TBD -> Group using Resources and Instrumentation Lib ( version and name) + bool resource_added = false; for (auto &recordable : spans) { auto rec = std::unique_ptr(static_cast(recordable.release())); *instrumentation_lib->add_spans() = std::move(rec->span()); + + if (!resource_added) + { + auto resource = rec->GetResources(); + if (resource.attributes_size()) + { + // TODO + // resource_span->set_allocated_resource(&resource); + resource_added = true; + } + } } } diff --git a/exporters/otlp/src/recordable.cc b/exporters/otlp/src/recordable.cc index ebc9c3047b..85fd7b7021 100644 --- a/exporters/otlp/src/recordable.cc +++ b/exporters/otlp/src/recordable.cc @@ -117,6 +117,101 @@ void PopulateAttribute(opentelemetry::proto::common::v1::KeyValue *attribute, } } +void PopulateResourceAttribute(opentelemetry::proto::common::v1::KeyValue *attribute, + const std::string &key, + const opentelemetry::sdk::common::OwnedAttributeValue &value) +{ + + attribute->set_key(key.data(), key.size()); + + if (nostd::holds_alternative(value)) + { + attribute->mutable_value()->set_bool_value(nostd::get(value)); + } + + else if (nostd::holds_alternative(value)) + { + attribute->mutable_value()->set_int_value(nostd::get(value)); + } + else if (nostd::holds_alternative(value)) + { + attribute->mutable_value()->set_int_value(nostd::get(value)); + } + else if (nostd::holds_alternative(value)) + { + attribute->mutable_value()->set_int_value(nostd::get(value)); + } + else if (nostd::holds_alternative(value)) + { + attribute->mutable_value()->set_int_value(nostd::get(value)); + } + else if (nostd::holds_alternative(value)) + { + attribute->mutable_value()->set_double_value(nostd::get(value)); + } + else if (nostd::holds_alternative(value)) + { + attribute->mutable_value()->set_string_value(nostd::get(value).data(), + nostd::get(value).size()); + } +#ifdef HAVE_SPAN_BYTE + else if (nostd::holds_alternative(value)) + { + attribute->mutable_value()->set_string_value(nostd::get(value)); + } +#endif + else if (nostd::holds_alternative>(value)) + { + for (const auto &val : nostd::get>(value)) + { + attribute->mutable_value()->mutable_array_value()->add_values()->set_bool_value(val); + } + } + else if (nostd::holds_alternative>(value)) + { + for (const auto &val : nostd::get>(value)) + { + attribute->mutable_value()->mutable_array_value()->add_values()->set_int_value(val); + } + } + else if (nostd::holds_alternative>(value)) + { + for (const auto &val : nostd::get>(value)) + { + attribute->mutable_value()->mutable_array_value()->add_values()->set_int_value(val); + } + } + else if (nostd::holds_alternative>(value)) + { + for (const auto &val : nostd::get>(value)) + { + attribute->mutable_value()->mutable_array_value()->add_values()->set_int_value(val); + } + } + else if (nostd::holds_alternative>(value)) + { + for (const auto &val : nostd::get>(value)) + { + attribute->mutable_value()->mutable_array_value()->add_values()->set_int_value(val); + } + } + else if (nostd::holds_alternative>(value)) + { + for (const auto &val : nostd::get>(value)) + { + attribute->mutable_value()->mutable_array_value()->add_values()->set_double_value(val); + } + } + else if (nostd::holds_alternative>(value)) + { + for (const auto &val : nostd::get>(value)) + { + attribute->mutable_value()->mutable_array_value()->add_values()->set_string_value(val.data(), + val.size()); + } + } +} + void Recordable::SetAttribute(nostd::string_view key, const opentelemetry::common::AttributeValue &value) noexcept { @@ -207,6 +302,14 @@ void Recordable::SetSpanKind(opentelemetry::trace::SpanKind span_kind) noexcept span_.set_kind(proto_span_kind); } +void Recordable::SetResourceAttribute( + std::string key, + const opentelemetry::sdk::common::OwnedAttributeValue &value) noexcept +{ + auto attribute = resource_.add_attributes(); + PopulateResourceAttribute(attribute, key, value); +} + void Recordable::SetStartTime(opentelemetry::core::SystemTimestamp start_time) noexcept { span_.set_start_time_unix_nano(start_time.time_since_epoch().count()); @@ -217,6 +320,11 @@ void Recordable::SetDuration(std::chrono::nanoseconds duration) noexcept const uint64_t unix_end_time = span_.start_time_unix_nano() + duration.count(); span_.set_end_time_unix_nano(unix_end_time); } + +proto::resource::v1::Resource &Recordable::GetResources() noexcept +{ + return resource_; +} } // namespace otlp } // namespace exporter OPENTELEMETRY_END_NAMESPACE diff --git a/exporters/otlp/test/otlp_exporter_test.cc b/exporters/otlp/test/otlp_exporter_test.cc index a221365179..57522e48ee 100644 --- a/exporters/otlp/test/otlp_exporter_test.cc +++ b/exporters/otlp/test/otlp_exporter_test.cc @@ -69,8 +69,9 @@ TEST_F(OtlpExporterTestPeer, ExportIntegrationTest) auto processor = std::shared_ptr( new sdk::trace::SimpleSpanProcessor(std::move(exporter))); - auto provider = - nostd::shared_ptr(new sdk::trace::TracerProvider(processor)); + auto resource = opentelemetry::sdk::resource::Resource::Create({}); + auto provider = nostd::shared_ptr( + new sdk::trace::TracerProvider(processor, std::move(resource))); auto tracer = provider->GetTracer("test"); EXPECT_CALL(*mock_stub, Export(_, _, _)) diff --git a/ext/include/opentelemetry/ext/zpages/threadsafe_span_data.h b/ext/include/opentelemetry/ext/zpages/threadsafe_span_data.h index 3bb0326130..b3013bd2bc 100644 --- a/ext/include/opentelemetry/ext/zpages/threadsafe_span_data.h +++ b/ext/include/opentelemetry/ext/zpages/threadsafe_span_data.h @@ -46,6 +46,17 @@ class ThreadsafeSpanData final : public opentelemetry::sdk::trace::Recordable return span_id_; } + /** + * Get the resources for this span + * @return the resources for this span + */ + const std::unordered_map + GetResources() + { + std::lock_guard lock(mutex_); + return resources_; + } + /** * Get the parent span id for this span * @return the span id for this span's parent @@ -152,6 +163,15 @@ class ThreadsafeSpanData final : public opentelemetry::sdk::trace::Recordable span_kind_ = span_kind; } + void SetResourceAttribute( + std::string key, + const opentelemetry::sdk::common::OwnedAttributeValue &value) noexcept override + { + std::lock_guard lock(mutex_); + attributes_.insert( + std::pair(key, value)); + } + void SetStartTime(opentelemetry::core::SystemTimestamp start_time) noexcept override { std::lock_guard lock(mutex_); @@ -221,6 +241,7 @@ class ThreadsafeSpanData final : public opentelemetry::sdk::trace::Recordable std::unordered_map attributes_; std::vector events_; opentelemetry::sdk::common::AttributeConverter converter_; + std::unordered_map resources_; }; } // namespace zpages } // namespace ext diff --git a/ext/test/zpages/tracez_data_aggregator_test.cc b/ext/test/zpages/tracez_data_aggregator_test.cc index eb077d636a..f370fbfab4 100644 --- a/ext/test/zpages/tracez_data_aggregator_test.cc +++ b/ext/test/zpages/tracez_data_aggregator_test.cc @@ -35,12 +35,13 @@ class TracezDataAggregatorTest : public ::testing::Test void SetUp() override { std::shared_ptr processor(new TracezSpanProcessor()); - auto resource = opentelemetry::sdk::resource::Resource::Create({}); - tracer = std::shared_ptr(new Tracer(processor, resource)); + tracer = std::shared_ptr(new Tracer(processor, resource)); tracez_data_aggregator = std::unique_ptr( new TracezDataAggregator(processor, milliseconds(10))); } + opentelemetry::sdk::resource::Resource resource = + opentelemetry::sdk::resource::Resource::Create({}); std::unique_ptr tracez_data_aggregator; std::shared_ptr tracer; }; diff --git a/ext/test/zpages/tracez_processor_test.cc b/ext/test/zpages/tracez_processor_test.cc index 2d9246495a..f7a32a5cb2 100644 --- a/ext/test/zpages/tracez_processor_test.cc +++ b/ext/test/zpages/tracez_processor_test.cc @@ -175,9 +175,7 @@ class TracezProcessor : public ::testing::Test protected: void SetUp() override { - processor = std::shared_ptr(new TracezSpanProcessor()); - auto resource = opentelemetry::sdk::resource::Resource::Create({}); - + processor = std::shared_ptr(new TracezSpanProcessor()); tracer = std::shared_ptr(new Tracer(processor, resource)); auto spans = processor->GetSpanSnapshot(); running = spans.running; @@ -187,6 +185,9 @@ class TracezProcessor : public ::testing::Test } std::shared_ptr processor; + opentelemetry::sdk::resource::Resource resource = + opentelemetry::sdk::resource::Resource::Create({}); + std::shared_ptr tracer; std::vector span_names; diff --git a/sdk/include/opentelemetry/sdk/trace/recordable.h b/sdk/include/opentelemetry/sdk/trace/recordable.h index e179f440bb..feec738f77 100644 --- a/sdk/include/opentelemetry/sdk/trace/recordable.h +++ b/sdk/include/opentelemetry/sdk/trace/recordable.h @@ -4,6 +4,7 @@ #include "opentelemetry/common/key_value_iterable.h" #include "opentelemetry/core/timestamp.h" #include "opentelemetry/nostd/string_view.h" +#include "opentelemetry/sdk/common/attribute_utils.h" #include "opentelemetry/sdk/common/empty_attributes.h" #include "opentelemetry/trace/canonical_code.h" #include "opentelemetry/trace/span.h" @@ -13,6 +14,7 @@ #include "opentelemetry/version.h" #include +#include // TODO: Create generic short pattern for opentelemetry::common and opentelemetry::trace @@ -115,6 +117,16 @@ class Recordable * @param span_kind the spankind to set */ virtual void SetSpanKind(opentelemetry::trace::SpanKind span_kind) noexcept = 0; + + /** + * Set Resource attribute of the span. + * @param key attribute key + * @param value attribute value + */ + virtual void SetResourceAttribute( + std::string key, + const opentelemetry::sdk::common::OwnedAttributeValue &value) noexcept = 0; + /** * Set the start time of the span. * @param start_time the start time to set diff --git a/sdk/include/opentelemetry/sdk/trace/span_data.h b/sdk/include/opentelemetry/sdk/trace/span_data.h index 629d68d7f0..3e80a86410 100644 --- a/sdk/include/opentelemetry/sdk/trace/span_data.h +++ b/sdk/include/opentelemetry/sdk/trace/span_data.h @@ -121,6 +121,16 @@ class SpanData final : public Recordable */ opentelemetry::trace::SpanKind GetSpanKind() const noexcept { return span_kind_; } + /** + * Get Resources. + * @return the resource of this span + */ + const std::unordered_map + &GetResources() const noexcept + { + return resources_; + } + /** * Get the status for this span * @return the status for this span @@ -213,6 +223,14 @@ class SpanData final : public Recordable span_kind_ = span_kind; } + void SetResourceAttribute( + std::string key, + const opentelemetry::sdk::common::OwnedAttributeValue &value) noexcept override + { + resources_.insert(std::pair( + std::string(key.data()), value)); + } + void SetStartTime(opentelemetry::core::SystemTimestamp start_time) noexcept override { start_time_ = start_time; @@ -233,6 +251,7 @@ class SpanData final : public Recordable std::vector events_; std::vector links_; opentelemetry::trace::SpanKind span_kind_{opentelemetry::trace::SpanKind::kInternal}; + std::unordered_map resources_; }; } // namespace trace } // namespace sdk diff --git a/sdk/src/trace/span.cc b/sdk/src/trace/span.cc index bcadef775d..9da37b83d6 100644 --- a/sdk/src/trace/span.cc +++ b/sdk/src/trace/span.cc @@ -76,7 +76,6 @@ Span::Span(std::shared_ptr &&tracer, return; } recordable_->SetName(name); - trace_api::TraceId trace_id; trace_api::SpanId span_id = GenerateRandomSpanId(); @@ -109,7 +108,10 @@ Span::Span(std::shared_ptr &&tracer, recordable_->SetSpanKind(options.kind); recordable_->SetStartTime(NowOr(options.start_system_time)); start_steady_time = NowOr(options.start_steady_time); - // recordable_->SetResource(resource_); TODO + for (auto attribute : resource.GetAttributes()) + { + recordable_->SetResourceAttribute(attribute.first, attribute.second); + } processor_->OnStart(*recordable_, parent_span_context); } diff --git a/sdk/src/trace/tracer.cc b/sdk/src/trace/tracer.cc index 27e3aad58c..2fef0ec10a 100644 --- a/sdk/src/trace/tracer.cc +++ b/sdk/src/trace/tracer.cc @@ -13,7 +13,7 @@ namespace trace Tracer::Tracer(std::shared_ptr processor, const opentelemetry::sdk::resource::Resource &resource, std::shared_ptr sampler) noexcept - : processor_{processor}, sampler_{sampler}, resource_{resource} + : processor_{processor}, sampler_{sampler}, resource_(resource) {} void Tracer::SetProcessor(std::shared_ptr processor) noexcept diff --git a/sdk/test/trace/tracer_test.cc b/sdk/test/trace/tracer_test.cc index d244ef2528..dfb6df3cdc 100644 --- a/sdk/test/trace/tracer_test.cc +++ b/sdk/test/trace/tracer_test.cc @@ -18,6 +18,7 @@ namespace common = opentelemetry::common; using opentelemetry::common::KeyValueIterableView; using opentelemetry::exporter::memory::InMemorySpanData; using opentelemetry::exporter::memory::InMemorySpanExporter; +using opentelemetry::sdk::resource::Resource; using opentelemetry::trace::SpanContext; /** @@ -48,20 +49,19 @@ class MockSampler final : public Sampler namespace { std::shared_ptr initTracer( - std::unique_ptr &&exporter) + std::unique_ptr &&exporter, + Resource &resource) { auto processor = std::make_shared(std::move(exporter)); - auto resource = Resource::Create({}); return std::shared_ptr(new Tracer(processor, resource)); } std::shared_ptr initTracer( std::unique_ptr &&exporter, + Resource &resource, std::shared_ptr sampler) { auto processor = std::make_shared(std::move(exporter)); - auto resource = Resource::Create({}); - return std::shared_ptr(new Tracer(processor, resource, sampler)); } } // namespace @@ -70,7 +70,8 @@ TEST(Tracer, ToInMemorySpanExporter) { std::unique_ptr exporter(new InMemorySpanExporter()); std::shared_ptr span_data = exporter->GetData(); - auto tracer = initTracer(std::move(exporter)); + auto resource = Resource::Create({}); + auto tracer = initTracer(std::move(exporter), resource); auto span_first = tracer->StartSpan("span 1"); auto scope_first = tracer->WithActiveSpan(span_first); @@ -105,7 +106,8 @@ TEST(Tracer, StartSpanSampleOn) { std::unique_ptr exporter(new InMemorySpanExporter()); std::shared_ptr span_data = exporter->GetData(); - auto tracer_on = initTracer(std::move(exporter)); + auto resource = Resource::Create({}); + auto tracer_on = initTracer(std::move(exporter), resource); tracer_on->StartSpan("span 1")->End(); @@ -121,7 +123,8 @@ TEST(Tracer, StartSpanSampleOff) { std::unique_ptr exporter(new InMemorySpanExporter()); std::shared_ptr span_data = exporter->GetData(); - auto tracer_off = initTracer(std::move(exporter), std::make_shared()); + auto resource = Resource::Create({}); + auto tracer_off = initTracer(std::move(exporter), resource, std::make_shared()); // This span will not be recorded. tracer_off->StartSpan("span 2")->End(); @@ -135,7 +138,8 @@ TEST(Tracer, StartSpanWithOptionsTime) { std::unique_ptr exporter(new InMemorySpanExporter()); std::shared_ptr span_data = exporter->GetData(); - auto tracer = initTracer(std::move(exporter)); + auto resource = Resource::Create({}); + auto tracer = initTracer(std::move(exporter), resource); opentelemetry::trace::StartSpanOptions start; start.start_system_time = SystemTimestamp(std::chrono::nanoseconds(300)); @@ -158,7 +162,8 @@ TEST(Tracer, StartSpanWithAttributes) { std::unique_ptr exporter(new InMemorySpanExporter()); std::shared_ptr span_data = exporter->GetData(); - auto tracer = initTracer(std::move(exporter)); + auto resource = Resource::Create({}); + auto tracer = initTracer(std::move(exporter), resource); // Start a span with all supported scalar attribute types. tracer @@ -238,7 +243,9 @@ TEST(Tracer, StartSpanWithAttributesCopy) { std::unique_ptr exporter(new InMemorySpanExporter()); std::shared_ptr span_data = exporter->GetData(); - auto tracer = initTracer(std::move(exporter)); + auto resource = Resource::Create({}); + + auto tracer = initTracer(std::move(exporter), resource); { std::unique_ptr> numbers(new std::vector); @@ -301,7 +308,8 @@ TEST(Tracer, SpanSetAttribute) { std::unique_ptr exporter(new InMemorySpanExporter()); std::shared_ptr span_data = exporter->GetData(); - auto tracer = initTracer(std::move(exporter)); + auto resource = Resource::Create({}); + auto tracer = initTracer(std::move(exporter), resource); auto span = tracer->StartSpan("span 1"); @@ -319,7 +327,8 @@ TEST(Tracer, SpanSetEvents) { std::unique_ptr exporter(new InMemorySpanExporter()); std::shared_ptr span_data = exporter->GetData(); - auto tracer = initTracer(std::move(exporter)); + auto resource = Resource::Create({}); + auto tracer = initTracer(std::move(exporter), resource); auto span = tracer->StartSpan("span 1"); span->AddEvent("event 1"); @@ -344,7 +353,8 @@ TEST(Tracer, SpanSetLinks) { std::unique_ptr exporter(new InMemorySpanExporter()); std::shared_ptr span_data = exporter->GetData(); - auto tracer = initTracer(std::move(exporter)); + auto resource = Resource::Create({}); + auto tracer = initTracer(std::move(exporter), resource); { @@ -421,7 +431,8 @@ TEST(Tracer, TestAlwaysOnSampler) { std::unique_ptr exporter(new InMemorySpanExporter()); std::shared_ptr span_data = exporter->GetData(); - auto tracer_on = initTracer(std::move(exporter)); + auto resource = Resource::Create({}); + auto tracer_on = initTracer(std::move(exporter), resource); // Testing AlwaysOn sampler. // Create two spans for each tracer. Check the exported result. @@ -440,7 +451,8 @@ TEST(Tracer, TestAlwaysOffSampler) { std::unique_ptr exporter(new InMemorySpanExporter()); std::shared_ptr span_data = exporter->GetData(); - auto tracer_off = initTracer(std::move(exporter), std::make_shared()); + auto resource = Resource::Create({}); + auto tracer_off = initTracer(std::move(exporter), resource, std::make_shared()); auto span_off_1 = tracer_off->StartSpan("span 1"); auto span_off_2 = tracer_off->StartSpan("span 2"); @@ -459,8 +471,9 @@ TEST(Tracer, TestParentBasedSampler) // so this sampler will work as an AlwaysOnSampler. std::unique_ptr exporter(new InMemorySpanExporter()); std::shared_ptr span_data_parent_on = exporter->GetData(); + auto resource = Resource::Create({}); auto tracer_parent_on = - initTracer(std::move(exporter), + initTracer(std::move(exporter), resource, std::make_shared(std::make_shared())); auto span_parent_on_1 = tracer_parent_on->StartSpan("span 1"); @@ -481,7 +494,7 @@ TEST(Tracer, TestParentBasedSampler) std::unique_ptr exporter2(new InMemorySpanExporter()); std::shared_ptr span_data_parent_off = exporter2->GetData(); auto tracer_parent_off = - initTracer(std::move(exporter2), + initTracer(std::move(exporter2), resource, std::make_shared(std::make_shared())); auto span_parent_off_1 = tracer_parent_off->StartSpan("span 1"); @@ -498,7 +511,8 @@ TEST(Tracer, WithActiveSpan) { std::unique_ptr exporter(new InMemorySpanExporter()); std::shared_ptr span_data = exporter->GetData(); - auto tracer = initTracer(std::move(exporter)); + auto resource = Resource::Create({}); + auto tracer = initTracer(std::move(exporter), resource); auto spans = span_data.get()->GetSpans(); ASSERT_EQ(0, spans.size()); @@ -533,7 +547,8 @@ TEST(Tracer, ExpectParent) { std::unique_ptr exporter(new InMemorySpanExporter()); std::shared_ptr span_data = exporter->GetData(); - auto tracer = initTracer(std::move(exporter)); + auto resource = Resource::Create({}); + auto tracer = initTracer(std::move(exporter), resource); auto spans = span_data.get()->GetSpans(); ASSERT_EQ(0, spans.size());