From 64719c72286330d587733bc736f87060535a778a Mon Sep 17 00:00:00 2001 From: Douglas Barker Date: Tue, 17 Dec 2024 22:45:44 +0000 Subject: [PATCH 1/9] fix: return distinct loggers, meters, and tracers when instrumentation scope attributes differ --- .../sdk/common/attribute_utils.h | 76 ++++++++++++++ .../instrumentation_scope.h | 20 +++- sdk/src/logs/logger_provider.cc | 2 +- sdk/src/metrics/meter_provider.cc | 2 +- sdk/src/trace/tracer_provider.cc | 2 +- sdk/test/common/attribute_utils_test.cc | 99 +++++++++++++++++++ .../instrumentationscope_test.cc | 36 +++++++ sdk/test/logs/logger_provider_sdk_test.cc | 40 +++++++- sdk/test/metrics/meter_provider_sdk_test.cc | 73 ++++++++++++++ sdk/test/trace/tracer_provider_test.cc | 71 +++++++++++++ 10 files changed, 415 insertions(+), 6 deletions(-) diff --git a/sdk/include/opentelemetry/sdk/common/attribute_utils.h b/sdk/include/opentelemetry/sdk/common/attribute_utils.h index 86b507a66b..e6bdfec259 100644 --- a/sdk/include/opentelemetry/sdk/common/attribute_utils.h +++ b/sdk/include/opentelemetry/sdk/common/attribute_utils.h @@ -105,6 +105,54 @@ struct AttributeConverter } }; +/** + * Evaluates if an owned value (from an OwnedAttributeValue) is equal to another value (from a non-owning AttributeValue). + * This only supports the checking equality with nostd::visit(AttributeEqualToVisitor, OwnedAttributeValue, AttributeValue). + */ +struct AttributeEqualToVisitor +{ + // Different types are not equal including containers of different element types + template + bool operator()(const T &, const U &) const noexcept + { + return false; + } + + // Compare the same arithmatic types + template + bool operator()(const T &owned_value, const T &value) const noexcept + { + return owned_value == value; + } + + // Compare std::string and const char* + bool operator()(const std::string &owned_value, const char* value) const noexcept + { + return owned_value == value; + } + + // Compare std::string and nostd::string_view + bool operator()(const std::string &owned_value, nostd::string_view value) const noexcept + { + return owned_value == value; + } + + // Compare std::vector and nostd::span + bool operator()(const std::vector &owned_value, const nostd::span &value) const noexcept + { + return owned_value.size() == value.size() && std::equal(owned_value.begin(), owned_value.end(), value.begin(), + [](const std::string &owned_element, nostd::string_view element) { return owned_element == element; }); + } + + // Compare nostd::span and std::vector for arithmatic types + template + bool operator()(const std::vector &owned_value, const nostd::span &value) const noexcept + { + return owned_value.size() == value.size() && std::equal(owned_value.begin(), owned_value.end(), value.begin()); + } +}; + + /** * Class for storing attributes. */ @@ -162,8 +210,36 @@ class AttributeMap : public std::unordered_map (*this)[std::string(key)] = nostd::visit(converter_, value); } + bool EqualTo(const opentelemetry::common::KeyValueIterable& attributes) const noexcept + { + if(attributes.size() != this->size()) + { + return false; + } + + const bool is_equal = attributes.ForEachKeyValue( + [this](nostd::string_view key, const opentelemetry::common::AttributeValue& value) noexcept + { + // Perform a linear search to find the key assuming the map is small + // This avoids temporary string creation from this->find(std::string(key)) + for (const auto &kv : *this) + { + if (kv.first == key) + { + // Order of arguments is important here. OwnedAttributeValue is first then AttributeValue + // AttributeEqualToVisitor does not support the reverse order + return nostd::visit(equal_to_visitor_, kv.second, value); + } + } + return false; + }); + + return is_equal; + } + private: AttributeConverter converter_; + AttributeEqualToVisitor equal_to_visitor_; }; /** diff --git a/sdk/include/opentelemetry/sdk/instrumentationscope/instrumentation_scope.h b/sdk/include/opentelemetry/sdk/instrumentationscope/instrumentation_scope.h index 1bf0facaa6..40d0043cf5 100644 --- a/sdk/include/opentelemetry/sdk/instrumentationscope/instrumentation_scope.h +++ b/sdk/include/opentelemetry/sdk/instrumentationscope/instrumentation_scope.h @@ -117,9 +117,25 @@ class InstrumentationScope */ bool equal(const nostd::string_view name, const nostd::string_view version, - const nostd::string_view schema_url = "") const noexcept + const nostd::string_view schema_url = "", + const opentelemetry::common::KeyValueIterable *attributes = nullptr) const noexcept { - return this->name_ == name && this->version_ == version && this->schema_url_ == schema_url; + + if (this->name_ != name || this->version_ != version || this->schema_url_ != schema_url) + { + return false; + } + + if (attributes == nullptr) + { + if (attributes_.empty()) + { + return true; + } + return false; + } + + return attributes_.EqualTo(*attributes); } const std::string &GetName() const noexcept { return name_; } diff --git a/sdk/src/logs/logger_provider.cc b/sdk/src/logs/logger_provider.cc index 14febdf721..da282ab655 100644 --- a/sdk/src/logs/logger_provider.cc +++ b/sdk/src/logs/logger_provider.cc @@ -80,7 +80,7 @@ opentelemetry::nostd::shared_ptr LoggerProvider::Ge { auto &logger_lib = logger->GetInstrumentationScope(); if (logger->GetName() == logger_name && - logger_lib.equal(library_name, library_version, schema_url)) + logger_lib.equal(library_name, library_version, schema_url, &attributes)) { return opentelemetry::nostd::shared_ptr{logger}; } diff --git a/sdk/src/metrics/meter_provider.cc b/sdk/src/metrics/meter_provider.cc index 1c70fc2ed3..6856dac3a1 100644 --- a/sdk/src/metrics/meter_provider.cc +++ b/sdk/src/metrics/meter_provider.cc @@ -71,7 +71,7 @@ nostd::shared_ptr MeterProvider::GetMeter( for (auto &meter : context_->GetMeters()) { auto meter_lib = meter->GetInstrumentationScope(); - if (meter_lib->equal(name, version, schema_url)) + if (meter_lib->equal(name, version, schema_url, attributes)) { return nostd::shared_ptr{meter}; } diff --git a/sdk/src/trace/tracer_provider.cc b/sdk/src/trace/tracer_provider.cc index 6a26e13914..81bd7e6f11 100644 --- a/sdk/src/trace/tracer_provider.cc +++ b/sdk/src/trace/tracer_provider.cc @@ -101,7 +101,7 @@ nostd::shared_ptr TracerProvider::GetTracer( for (auto &tracer : tracers_) { auto &tracer_scope = tracer->GetInstrumentationScope(); - if (tracer_scope.equal(name, version, schema_url)) + if (tracer_scope.equal(name, version, schema_url, attributes)) { return nostd::shared_ptr{tracer}; } diff --git a/sdk/test/common/attribute_utils_test.cc b/sdk/test/common/attribute_utils_test.cc index 9b1f6bd56e..93476f3613 100644 --- a/sdk/test/common/attribute_utils_test.cc +++ b/sdk/test/common/attribute_utils_test.cc @@ -2,12 +2,15 @@ // SPDX-License-Identifier: Apache-2.0 #include +#include #include #include #include #include "opentelemetry/common/key_value_iterable_view.h" #include "opentelemetry/nostd/variant.h" +#include "opentelemetry/nostd/span.h" +#include "opentelemetry/nostd/string_view.h" #include "opentelemetry/sdk/common/attribute_utils.h" TEST(AttributeMapTest, DefaultConstruction) @@ -55,3 +58,99 @@ TEST(OrderedAttributeMapTest, AttributesConstruction) EXPECT_EQ(opentelemetry::nostd::get(attribute_map.GetAttributes().at(keys[i])), values[i]); } } + +TEST(AttributeEqualToVisitorTest, AttributeValueEqualTo) +{ + namespace sdk = opentelemetry::sdk::common; + namespace api = opentelemetry::common; + namespace nostd = opentelemetry::nostd; + + using AV = api::AttributeValue; + using OV = sdk::OwnedAttributeValue; + + sdk::AttributeEqualToVisitor equal_to_visitor; + + // arithmetic types + EXPECT_TRUE(opentelemetry::nostd::visit(equal_to_visitor, OV{bool(true)}, AV{bool(true)})); + EXPECT_TRUE(opentelemetry::nostd::visit(equal_to_visitor, OV{int32_t(22)}, AV{int32_t(22)})); + EXPECT_TRUE(opentelemetry::nostd::visit(equal_to_visitor, OV{int64_t(22)}, AV{int64_t(22)})); + EXPECT_TRUE(opentelemetry::nostd::visit(equal_to_visitor, OV{uint32_t(22)}, AV{uint32_t(22)})); + EXPECT_TRUE(opentelemetry::nostd::visit(equal_to_visitor, OV{uint64_t(22)}, AV{uint64_t(22)})); + EXPECT_TRUE(opentelemetry::nostd::visit(equal_to_visitor, OV{double(22.0)}, AV{double(22.0)})); + + // string types + EXPECT_TRUE(opentelemetry::nostd::visit(equal_to_visitor, OV{std::string("string to const char*")}, AV{"string to const char*"})); + EXPECT_TRUE(opentelemetry::nostd::visit(equal_to_visitor, OV{std::string("string to string_view")}, AV{nostd::string_view("string to string_view")})); + + //container types + EXPECT_TRUE(opentelemetry::nostd::visit(equal_to_visitor, OV{std::vector{true, false}}, AV{std::array{true, false}})); + EXPECT_TRUE(opentelemetry::nostd::visit(equal_to_visitor, OV{std::vector{33, 44}}, AV{std::array{33, 44}})); + EXPECT_TRUE(opentelemetry::nostd::visit(equal_to_visitor, OV{std::vector{33, 44}}, AV{std::array{33, 44}})); + EXPECT_TRUE(opentelemetry::nostd::visit(equal_to_visitor, OV{std::vector{33, 44}}, AV{std::array{33, 44}})); + EXPECT_TRUE(opentelemetry::nostd::visit(equal_to_visitor, OV{std::vector{33, 44}}, AV{std::array{33, 44}})); + EXPECT_TRUE(opentelemetry::nostd::visit(equal_to_visitor, OV{std::vector{33, 44}}, AV{std::array{33, 44}})); + EXPECT_TRUE(opentelemetry::nostd::visit(equal_to_visitor, OV{std::vector{33.0, 44.0}}, AV{std::array{33.0, 44.0}})); + EXPECT_TRUE(opentelemetry::nostd::visit(equal_to_visitor, OV{std::vector{"a string", "another string"}}, AV{std::array{"a string", "another string"}})); +} + +TEST(AttributeEqualToVisitorTest, AttributeValueNotEqualTo) +{ + namespace sdk = opentelemetry::sdk::common; + namespace api = opentelemetry::common; + namespace nostd = opentelemetry::nostd; + + using AV = api::AttributeValue; + using OV = sdk::OwnedAttributeValue; + + sdk::AttributeEqualToVisitor equal_to_visitor; + + // check different values of the same type + EXPECT_FALSE(opentelemetry::nostd::visit(equal_to_visitor, OV{bool(true)}, AV{bool(false)})); + EXPECT_FALSE(opentelemetry::nostd::visit(equal_to_visitor, OV{int32_t(22)}, AV{int32_t(33)})); + EXPECT_FALSE(opentelemetry::nostd::visit(equal_to_visitor, OV{int64_t(22)}, AV{int64_t(33)})); + EXPECT_FALSE(opentelemetry::nostd::visit(equal_to_visitor, OV{uint32_t(22)}, AV{uint32_t(33)})); + EXPECT_FALSE(opentelemetry::nostd::visit(equal_to_visitor, OV{double(22.2)}, AV{double(33.3)})); + EXPECT_FALSE(opentelemetry::nostd::visit(equal_to_visitor, OV{std::string("string one")}, AV{"another string"})); + EXPECT_FALSE(opentelemetry::nostd::visit(equal_to_visitor, OV{std::string("string one")}, AV{nostd::string_view("another string")})); + + // check different value types + EXPECT_FALSE(opentelemetry::nostd::visit(equal_to_visitor, OV{bool(true)}, AV{uint32_t(0)})); + EXPECT_FALSE(opentelemetry::nostd::visit(equal_to_visitor, OV{int32_t(22)}, AV{uint32_t(22)})); + + // check containers of different element values + EXPECT_FALSE(opentelemetry::nostd::visit(equal_to_visitor, OV{std::vector{true, false}}, AV{std::array{false, true}})); + EXPECT_FALSE(opentelemetry::nostd::visit(equal_to_visitor, OV{std::vector{22, 33}}, AV{std::array{33, 44}})); + EXPECT_FALSE(opentelemetry::nostd::visit(equal_to_visitor, OV{std::vector{"a string", "another string"}}, AV{std::array{"a string", "a really different string"}})); + + // check containers of different element types + EXPECT_FALSE(opentelemetry::nostd::visit(equal_to_visitor, OV{std::vector{22, 33}}, AV{std::array{22, 33}})); +} + +TEST(AttributeMapTest, EqualTo) +{ + using Attributes = std::initializer_list>; + + // check for case where both are empty + Attributes attributes_empty = {}; + auto kv_iterable_empty = opentelemetry::common::MakeKeyValueIterableView(attributes_empty); + opentelemetry::sdk::common::AttributeMap attribute_map_empty(kv_iterable_empty); + EXPECT_TRUE(attribute_map_empty.EqualTo(kv_iterable_empty)); + + // check for equality with a range of attributes and types + Attributes attributes = {{"key0", "some value"}, {"key1", 1}, {"key2", 2.0}, {"key3", true}}; + auto kv_iterable_match = opentelemetry::common::MakeKeyValueIterableView(attributes); + opentelemetry::sdk::common::AttributeMap attribute_map(attributes); + EXPECT_TRUE(attribute_map.EqualTo(kv_iterable_match)); + + // check for several cases where the attributes are different + Attributes attributes_different_value = {{"key0", "some value"}, {"key1", 1}, {"key2", 2.0}, {"key3", false}}; + Attributes attributes_different_type = {{"key0", "some value"}, {"key1", 1.0} ,{"key2", 2.0}, {"key3", true}}; + Attributes attributes_different_size = {{"key0", "some value"}}; + auto kv_iterable_different_value = opentelemetry::common::MakeKeyValueIterableView(attributes_different_value); + auto kv_iterable_different_type = opentelemetry::common::MakeKeyValueIterableView(attributes_different_type); + auto kv_iterable_different_size = opentelemetry::common::MakeKeyValueIterableView(attributes_different_size); + + EXPECT_FALSE(attribute_map.EqualTo(kv_iterable_different_value)); + EXPECT_FALSE(attribute_map.EqualTo(kv_iterable_different_type)); + EXPECT_FALSE(attribute_map.EqualTo(kv_iterable_different_size)); +} \ No newline at end of file diff --git a/sdk/test/instrumentationscope/instrumentationscope_test.cc b/sdk/test/instrumentationscope/instrumentationscope_test.cc index da00ec8e93..442e9ea005 100644 --- a/sdk/test/instrumentationscope/instrumentationscope_test.cc +++ b/sdk/test/instrumentationscope/instrumentationscope_test.cc @@ -208,3 +208,39 @@ TEST(InstrumentationScope, LegacyInstrumentationLibrary) EXPECT_EQ(instrumentation_library->GetVersion(), library_version); EXPECT_EQ(instrumentation_library->GetSchemaURL(), schema_url); } + +TEST(InstrumentationScope, Equal) +{ + using Attributes = std::initializer_list>; + Attributes attributes_empty = {}; + Attributes attributes_match = {{"key0", "some value"}, {"key1", 1}, {"key2", 2.0}, {"key3", true}}; + Attributes attributes_different = {{"key42", "some other"}}; + + auto kv_iterable_empty = opentelemetry::common::MakeKeyValueIterableView(attributes_empty); + auto kv_iterable_match = opentelemetry::common::MakeKeyValueIterableView(attributes_match); + auto kv_iterable_different = opentelemetry::common::MakeKeyValueIterableView(attributes_different); + + // try with no attributes added to the instrumentation scope + auto instrumentation_scope = + opentelemetry::sdk::instrumentationscope::InstrumentationScope::Create("library_name", "library_version", "schema_url"); + + // the instrumentation scope is equal if all parameters are equal (must handle nullptr attributes or empty attributes) + EXPECT_TRUE(instrumentation_scope->equal("library_name", "library_version", "schema_url")); + EXPECT_TRUE(instrumentation_scope->equal("library_name", "library_version", "schema_url", nullptr)); + EXPECT_TRUE(instrumentation_scope->equal("library_name", "library_version", "schema_url", &kv_iterable_empty)); + + // the instrumentation scope is not equal if any parameter is different + EXPECT_FALSE(instrumentation_scope->equal("library_name", "")); + EXPECT_FALSE(instrumentation_scope->equal("library_name", "library_version", "")); + EXPECT_FALSE(instrumentation_scope->equal("library_name", "library_version", "schema_url", &kv_iterable_different)); + + // try with attributes added to the instrumentation scope + auto instrumentation_scope_w_attributes = + opentelemetry::sdk::instrumentationscope::InstrumentationScope::Create("library_name", "library_version", "schema_url", attributes_match); + + // the instrumentation scope is equal if all parameters including all attribute keys, types, and values are equal + EXPECT_TRUE(instrumentation_scope_w_attributes->equal("library_name", "library_version", "schema_url", &kv_iterable_match)); + EXPECT_FALSE(instrumentation_scope_w_attributes->equal("library_name", "library_version", "schema_url", nullptr)); + EXPECT_FALSE(instrumentation_scope_w_attributes->equal("library_name", "library_version", "schema_url", &kv_iterable_empty)); + EXPECT_FALSE(instrumentation_scope_w_attributes->equal("library_name", "library_version", "schema_url", &kv_iterable_different)); +} diff --git a/sdk/test/logs/logger_provider_sdk_test.cc b/sdk/test/logs/logger_provider_sdk_test.cc index a5a3d3a68a..1a8ad4d28c 100644 --- a/sdk/test/logs/logger_provider_sdk_test.cc +++ b/sdk/test/logs/logger_provider_sdk_test.cc @@ -129,7 +129,7 @@ TEST(LoggerProviderSDK, EventLoggerProviderFactory) auto event_logger = elp->CreateEventLogger(logger1, "otel-cpp.test"); } -TEST(LoggerPviderSDK, LoggerEquityCheck) +TEST(LoggerProviderSDK, LoggerEqualityCheck) { auto lp = std::shared_ptr(new LoggerProvider()); nostd::string_view schema_url{"https://opentelemetry.io/schemas/1.11.0"}; @@ -141,6 +141,44 @@ TEST(LoggerPviderSDK, LoggerEquityCheck) auto logger3 = lp->GetLogger("logger3"); auto another_logger3 = lp->GetLogger("logger3"); EXPECT_EQ(logger3, another_logger3); + + auto logger4 = lp->GetLogger("logger4", "opentelelemtry_library", "1.0.0", schema_url); + auto another_logger4 = lp->GetLogger("logger4", "opentelelemtry_library", "1.0.0", schema_url); + EXPECT_EQ(logger4, another_logger4); + + auto logger5 = lp->GetLogger("logger5", "opentelelemtry_library", "1.0.0", schema_url, {{"key", "value"}}); + auto another_logger5 = lp->GetLogger("logger5", "opentelelemtry_library", "1.0.0", schema_url, {{"key", "value"}}); + EXPECT_EQ(logger5, another_logger5); +} + +TEST(LoggerProviderSDK, GetLoggerInequalityCheck) +{ + auto lp = std::shared_ptr(new LoggerProvider()); + auto logger_library_1 = lp->GetLogger("logger1", "library_1"); + auto logger_library_2 = lp->GetLogger("logger1", "library_2"); + auto logger_version_1 = lp->GetLogger("logger1", "library_1", "1.0.0"); + auto logger_version_2 = lp->GetLogger("logger1", "library_1", "2.0.0"); + auto logger_url_1 = lp->GetLogger("logger1", "library_1", "1.0.0", "url_1"); + auto logger_url_2 = lp->GetLogger("logger1", "library_1", "1.0.0", "url_2"); + auto logger_attribute_1 = lp->GetLogger("logger1", "library_1", "1.0.0", "url_1", {{"key", "one"}}); + auto logger_attribute_2 = lp->GetLogger("logger1", "library_1", "1.0.0", "url_1", {{"key", "two"}}); + + // different scope names should return distinct loggers + EXPECT_NE(logger_library_1, logger_library_2); + + // different scope versions should return distinct loggers + EXPECT_NE(logger_version_1, logger_library_1); + EXPECT_NE(logger_version_1, logger_version_2); + + // different scope schema urls should return distinct loggers + EXPECT_NE(logger_url_1, logger_library_1); + EXPECT_NE(logger_url_1, logger_version_1); + EXPECT_NE(logger_url_1, logger_url_2); + + // different scope attributes should return distinct loggers + EXPECT_NE(logger_attribute_1, logger_library_1); + EXPECT_NE(logger_attribute_1, logger_url_1); + EXPECT_NE(logger_attribute_1, logger_attribute_2); } class DummyLogRecordable final : public opentelemetry::sdk::logs::Recordable diff --git a/sdk/test/metrics/meter_provider_sdk_test.cc b/sdk/test/metrics/meter_provider_sdk_test.cc index 36cb28c228..feee60e30e 100644 --- a/sdk/test/metrics/meter_provider_sdk_test.cc +++ b/sdk/test/metrics/meter_provider_sdk_test.cc @@ -12,6 +12,7 @@ #include "opentelemetry/sdk/metrics/instruments.h" #include "opentelemetry/sdk/metrics/meter.h" #include "opentelemetry/sdk/metrics/meter_provider.h" +#include "opentelemetry/sdk/metrics/meter_provider_factory.h" #include "opentelemetry/sdk/metrics/metric_reader.h" #include "opentelemetry/sdk/metrics/push_metric_exporter.h" #include "opentelemetry/sdk/metrics/view/instrument_selector.h" @@ -239,3 +240,75 @@ TEST(MeterProvider, RemoveMeter) mp.Shutdown(); } #endif /* OPENTELEMETRY_ABI_VERSION_NO >= 2 */ + +TEST(MeterProvider, GetMeterEqualityCheck) +{ + auto provider = MeterProviderFactory::Create(); + + // providing the same scope names should return the same Meter + auto meter_library_1a = provider->GetMeter("library_name"); + auto meter_library_1b = provider->GetMeter("library_name"); + EXPECT_EQ(meter_library_1a, meter_library_1b); + + // providing the same scope name and version should return the same meter + auto meter_version_1a = provider->GetMeter("library_name", "v1.0"); + auto meter_version_1b = provider->GetMeter("library_name", "v1.0"); + EXPECT_EQ(meter_version_1a, meter_version_1b); + + // providing the same name, version, and schema urls should return the same meter + auto meter_urla = provider->GetMeter("library_name", "v1.0", "url"); + auto meter_urlb = provider->GetMeter("library_name", "v1.0", "url"); + EXPECT_EQ(meter_urla, meter_urlb); +} + +TEST(MeterProvider, GetMeterInequalityCheck) +{ + auto provider = MeterProviderFactory::Create(); + + auto meter_library_1 = provider->GetMeter("library_1"); + auto meter_library_2 = provider->GetMeter("library_2"); + auto meter_version_1 = provider->GetMeter("library_1", "v1.0"); + auto meter_version_2 = provider->GetMeter("library_1", "v2.0"); + auto meter_url_1 = provider->GetMeter("library_1", "v1.0", "url_1"); + auto meter_url_2 = provider->GetMeter("library_1", "v1.0", "url_2"); + + // different scope names should return distinct meters + EXPECT_NE(meter_library_1, meter_library_2); + + // different scope versions should return distinct meters + EXPECT_NE(meter_version_1, meter_library_1); + EXPECT_NE(meter_version_1, meter_version_2); + + // different scope schema urls should return distinct meters + EXPECT_NE(meter_url_1, meter_library_1); + EXPECT_NE(meter_url_1, meter_version_1); + EXPECT_NE(meter_url_1, meter_url_2); +} + + +#if OPENTELEMETRY_ABI_VERSION_NO >= 2 + +TEST(MeterProvider, GetMeterEqualityCheckAbiv2) +{ + auto provider = MeterProviderFactory::Create(); + + // providing the same name, version, schema url and attributes should return the same meter + auto meter_attribute1a = provider->GetMeter("library_name", "v1.0", "url", {{"key", "one"}}); + auto meter_attribute1b = provider->GetMeter("library_name", "v1.0", "url", {{"key", "one"}}); + EXPECT_EQ(meter_attribute1a, meter_attribute1b); +} + +TEST(MeterProvider, GetMeterInequalityCheckAbiv2) +{ + auto provider = MeterProviderFactory::Create(); + + auto meter_1 = provider->GetMeter("library_name", "v1.0", "url"); + auto meter_attribute_1 = provider->GetMeter("library_name", "v1.0", "url", {{"key", "one"}}); + auto meter_attribute_2 = provider->GetMeter("library_name", "v1.0", "url", {{"key", "two"}}); + + // different scope attributes should return distinct meters + EXPECT_NE(meter_attribute_1, meter_1); + EXPECT_NE(meter_attribute_1, meter_attribute_2); +} + +#endif /* OPENTELEMETRY_ABI_VERSION_NO >= 2 */ diff --git a/sdk/test/trace/tracer_provider_test.cc b/sdk/test/trace/tracer_provider_test.cc index fa3afa2690..a76ef8885f 100644 --- a/sdk/test/trace/tracer_provider_test.cc +++ b/sdk/test/trace/tracer_provider_test.cc @@ -19,9 +19,11 @@ #include "opentelemetry/sdk/trace/sampler.h" #include "opentelemetry/sdk/trace/samplers/always_off.h" #include "opentelemetry/sdk/trace/simple_processor.h" +#include "opentelemetry/sdk/trace/simple_processor_factory.h" #include "opentelemetry/sdk/trace/tracer.h" #include "opentelemetry/sdk/trace/tracer_context.h" #include "opentelemetry/sdk/trace/tracer_provider.h" +#include "opentelemetry/sdk/trace/tracer_provider_factory.h" using namespace opentelemetry::sdk::trace; using namespace opentelemetry::sdk::resource; @@ -89,7 +91,76 @@ TEST(TracerProvider, GetTracer) ASSERT_EQ(instrumentation_scope3.GetVersion(), "1.0.0"); } +TEST(TracerProvider, GetTracerEqualityCheck) +{ + auto provider = TracerProviderFactory::Create(std::move(SimpleSpanProcessorFactory::Create(nullptr))); + + // providing the same scope names should return the same tracer + auto tracer_1a = provider->GetTracer("library_name"); + auto tracer_1b = provider->GetTracer("library_name"); + EXPECT_EQ(tracer_1a, tracer_1b); + + // providing the same scope name and version should return the same tracer + auto tracer_version1a = provider->GetTracer("library_name", "v1.0"); + auto tracer_version1b = provider->GetTracer("library_name", "v1.0"); + EXPECT_EQ(tracer_version1a, tracer_version1b); + + // providing the same name, version, and schema urls should return the same tracer + auto tracer_urla = provider->GetTracer("library_name", "v1.0", "url"); + auto tracer_urlb = provider->GetTracer("library_name", "v1.0", "url"); + EXPECT_EQ(tracer_urla, tracer_urlb); + +} + +TEST(TracerProvider, GetTracerInequalityCheck) +{ + auto provider = TracerProviderFactory::Create(std::move(SimpleSpanProcessorFactory::Create(nullptr))); + auto tracer_library_1 = provider->GetTracer("library_1"); + auto tracer_library_2 = provider->GetTracer("library_2"); + auto tracer_version_1 = provider->GetTracer("library_1", "v1.0"); + auto tracer_version_2 = provider->GetTracer("library_1", "v2.0"); + auto tracer_url_1 = provider->GetTracer("library_1", "v1.0", "url_1"); + auto tracer_url_2 = provider->GetTracer("library_1", "v1.0", "url_2"); + + // different scope names should return distinct tracers + EXPECT_NE(tracer_library_1, tracer_library_2); + + // different scope versions should return distinct tracers + EXPECT_NE(tracer_version_1, tracer_library_1); + EXPECT_NE(tracer_version_1, tracer_version_2); + + // different scope schema urls should return distinct tracers + EXPECT_NE(tracer_url_1, tracer_library_1); + EXPECT_NE(tracer_url_1, tracer_version_1); + EXPECT_NE(tracer_url_1, tracer_url_2); +} + + #if OPENTELEMETRY_ABI_VERSION_NO >= 2 + +TEST(TracerProvider, GetTracerEqualityCheckAbiv2) +{ + auto provider = TracerProviderFactory::Create(std::move(SimpleSpanProcessorFactory::Create(nullptr))); + + auto tracer_attribute1a = provider->GetTracer("library_name", "v1.0", "url", {{"key", "one"}}); + auto tracer_attribute1b = provider->GetTracer("library_name", "v1.0", "url", {{"key", "one"}}); + + // providing the same name, version, schema url and attributes should return the same tracer + EXPECT_EQ(tracer_attribute1a, tracer_attribute1b); +} + +TEST(TracerProvider, GetTracerInequalityCheckAbiv2) +{ + auto provider = TracerProviderFactory::Create(std::move(SimpleSpanProcessorFactory::Create(nullptr))); + auto tracer_1 = provider->GetTracer("library_name", "v1.0", "url"); + auto tracer_attribute1 = provider->GetTracer("library_name", "v1.0", "url", {{"key", "one"}}); + auto tracer_attribute2 = provider->GetTracer("library_name", "v1.0", "url", {{"key", "two"}}); + + // different scope attributes should return distinct tracers + EXPECT_NE(tracer_attribute1, tracer_1); + EXPECT_NE(tracer_attribute1, tracer_attribute2); +} + TEST(TracerProvider, GetTracerAbiv2) { std::unique_ptr processor(new SimpleSpanProcessor(nullptr)); From 0f5a72022c715fffc2b727c39c9d2f8759d7e6f9 Mon Sep 17 00:00:00 2001 From: Douglas Barker Date: Tue, 17 Dec 2024 15:58:41 -0700 Subject: [PATCH 2/9] apply formatting --- .../sdk/common/attribute_utils.h | 102 +++++++------- .../instrumentation_scope.h | 8 +- sdk/test/common/attribute_utils_test.cc | 128 +++++++++++------- .../instrumentationscope_test.cc | 62 +++++---- sdk/test/logs/logger_provider_sdk_test.cc | 34 +++-- sdk/test/metrics/meter_provider_sdk_test.cc | 15 +- sdk/test/trace/tracer_provider_test.cc | 22 +-- 7 files changed, 212 insertions(+), 159 deletions(-) diff --git a/sdk/include/opentelemetry/sdk/common/attribute_utils.h b/sdk/include/opentelemetry/sdk/common/attribute_utils.h index e6bdfec259..a1da839421 100644 --- a/sdk/include/opentelemetry/sdk/common/attribute_utils.h +++ b/sdk/include/opentelemetry/sdk/common/attribute_utils.h @@ -106,52 +106,58 @@ struct AttributeConverter }; /** - * Evaluates if an owned value (from an OwnedAttributeValue) is equal to another value (from a non-owning AttributeValue). - * This only supports the checking equality with nostd::visit(AttributeEqualToVisitor, OwnedAttributeValue, AttributeValue). + * Evaluates if an owned value (from an OwnedAttributeValue) is equal to another value (from a + * non-owning AttributeValue). This only supports the checking equality with + * nostd::visit(AttributeEqualToVisitor, OwnedAttributeValue, AttributeValue). */ struct AttributeEqualToVisitor { - // Different types are not equal including containers of different element types - template - bool operator()(const T &, const U &) const noexcept - { - return false; - } + // Different types are not equal including containers of different element types + template + bool operator()(const T &, const U &) const noexcept + { + return false; + } - // Compare the same arithmatic types - template - bool operator()(const T &owned_value, const T &value) const noexcept - { - return owned_value == value; - } - - // Compare std::string and const char* - bool operator()(const std::string &owned_value, const char* value) const noexcept - { - return owned_value == value; - } + // Compare the same arithmatic types + template + bool operator()(const T &owned_value, const T &value) const noexcept + { + return owned_value == value; + } - // Compare std::string and nostd::string_view - bool operator()(const std::string &owned_value, nostd::string_view value) const noexcept - { - return owned_value == value; - } + // Compare std::string and const char* + bool operator()(const std::string &owned_value, const char *value) const noexcept + { + return owned_value == value; + } - // Compare std::vector and nostd::span - bool operator()(const std::vector &owned_value, const nostd::span &value) const noexcept - { - return owned_value.size() == value.size() && std::equal(owned_value.begin(), owned_value.end(), value.begin(), - [](const std::string &owned_element, nostd::string_view element) { return owned_element == element; }); - } + // Compare std::string and nostd::string_view + bool operator()(const std::string &owned_value, nostd::string_view value) const noexcept + { + return owned_value == value; + } - // Compare nostd::span and std::vector for arithmatic types - template - bool operator()(const std::vector &owned_value, const nostd::span &value) const noexcept - { - return owned_value.size() == value.size() && std::equal(owned_value.begin(), owned_value.end(), value.begin()); - } -}; + // Compare std::vector and nostd::span + bool operator()(const std::vector &owned_value, + const nostd::span &value) const noexcept + { + return owned_value.size() == value.size() && + std::equal(owned_value.begin(), owned_value.end(), value.begin(), + [](const std::string &owned_element, nostd::string_view element) { + return owned_element == element; + }); + } + // Compare nostd::span and std::vector for arithmatic types + template + bool operator()(const std::vector &owned_value, + const nostd::span &value) const noexcept + { + return owned_value.size() == value.size() && + std::equal(owned_value.begin(), owned_value.end(), value.begin()); + } +}; /** * Class for storing attributes. @@ -210,30 +216,30 @@ class AttributeMap : public std::unordered_map (*this)[std::string(key)] = nostd::visit(converter_, value); } - bool EqualTo(const opentelemetry::common::KeyValueIterable& attributes) const noexcept + bool EqualTo(const opentelemetry::common::KeyValueIterable &attributes) const noexcept { - if(attributes.size() != this->size()) + if (attributes.size() != this->size()) { return false; } const bool is_equal = attributes.ForEachKeyValue( - [this](nostd::string_view key, const opentelemetry::common::AttributeValue& value) noexcept - { - // Perform a linear search to find the key assuming the map is small + [this](nostd::string_view key, + const opentelemetry::common::AttributeValue &value) noexcept { + // Perform a linear search to find the key assuming the map is small // This avoids temporary string creation from this->find(std::string(key)) for (const auto &kv : *this) { - if (kv.first == key) + if (kv.first == key) { - // Order of arguments is important here. OwnedAttributeValue is first then AttributeValue - // AttributeEqualToVisitor does not support the reverse order + // Order of arguments is important here. OwnedAttributeValue is first then + // AttributeValue AttributeEqualToVisitor does not support the reverse order return nostd::visit(equal_to_visitor_, kv.second, value); } } - return false; + return false; }); - + return is_equal; } diff --git a/sdk/include/opentelemetry/sdk/instrumentationscope/instrumentation_scope.h b/sdk/include/opentelemetry/sdk/instrumentationscope/instrumentation_scope.h index 40d0043cf5..b69948b4bf 100644 --- a/sdk/include/opentelemetry/sdk/instrumentationscope/instrumentation_scope.h +++ b/sdk/include/opentelemetry/sdk/instrumentationscope/instrumentation_scope.h @@ -117,16 +117,16 @@ class InstrumentationScope */ bool equal(const nostd::string_view name, const nostd::string_view version, - const nostd::string_view schema_url = "", + const nostd::string_view schema_url = "", const opentelemetry::common::KeyValueIterable *attributes = nullptr) const noexcept { - + if (this->name_ != name || this->version_ != version || this->schema_url_ != schema_url) { - return false; + return false; } - if (attributes == nullptr) + if (attributes == nullptr) { if (attributes_.empty()) { diff --git a/sdk/test/common/attribute_utils_test.cc b/sdk/test/common/attribute_utils_test.cc index 93476f3613..4028098d56 100644 --- a/sdk/test/common/attribute_utils_test.cc +++ b/sdk/test/common/attribute_utils_test.cc @@ -2,15 +2,15 @@ // SPDX-License-Identifier: Apache-2.0 #include -#include +#include #include #include #include #include "opentelemetry/common/key_value_iterable_view.h" -#include "opentelemetry/nostd/variant.h" #include "opentelemetry/nostd/span.h" #include "opentelemetry/nostd/string_view.h" +#include "opentelemetry/nostd/variant.h" #include "opentelemetry/sdk/common/attribute_utils.h" TEST(AttributeMapTest, DefaultConstruction) @@ -61,96 +61,122 @@ TEST(OrderedAttributeMapTest, AttributesConstruction) TEST(AttributeEqualToVisitorTest, AttributeValueEqualTo) { - namespace sdk = opentelemetry::sdk::common; - namespace api = opentelemetry::common; + namespace sdk = opentelemetry::sdk::common; + namespace api = opentelemetry::common; namespace nostd = opentelemetry::nostd; - + using AV = api::AttributeValue; - using OV = sdk::OwnedAttributeValue; + using OV = sdk::OwnedAttributeValue; sdk::AttributeEqualToVisitor equal_to_visitor; - + // arithmetic types EXPECT_TRUE(opentelemetry::nostd::visit(equal_to_visitor, OV{bool(true)}, AV{bool(true)})); EXPECT_TRUE(opentelemetry::nostd::visit(equal_to_visitor, OV{int32_t(22)}, AV{int32_t(22)})); EXPECT_TRUE(opentelemetry::nostd::visit(equal_to_visitor, OV{int64_t(22)}, AV{int64_t(22)})); EXPECT_TRUE(opentelemetry::nostd::visit(equal_to_visitor, OV{uint32_t(22)}, AV{uint32_t(22)})); EXPECT_TRUE(opentelemetry::nostd::visit(equal_to_visitor, OV{uint64_t(22)}, AV{uint64_t(22)})); - EXPECT_TRUE(opentelemetry::nostd::visit(equal_to_visitor, OV{double(22.0)}, AV{double(22.0)})); - - // string types - EXPECT_TRUE(opentelemetry::nostd::visit(equal_to_visitor, OV{std::string("string to const char*")}, AV{"string to const char*"})); - EXPECT_TRUE(opentelemetry::nostd::visit(equal_to_visitor, OV{std::string("string to string_view")}, AV{nostd::string_view("string to string_view")})); - - //container types - EXPECT_TRUE(opentelemetry::nostd::visit(equal_to_visitor, OV{std::vector{true, false}}, AV{std::array{true, false}})); - EXPECT_TRUE(opentelemetry::nostd::visit(equal_to_visitor, OV{std::vector{33, 44}}, AV{std::array{33, 44}})); - EXPECT_TRUE(opentelemetry::nostd::visit(equal_to_visitor, OV{std::vector{33, 44}}, AV{std::array{33, 44}})); - EXPECT_TRUE(opentelemetry::nostd::visit(equal_to_visitor, OV{std::vector{33, 44}}, AV{std::array{33, 44}})); - EXPECT_TRUE(opentelemetry::nostd::visit(equal_to_visitor, OV{std::vector{33, 44}}, AV{std::array{33, 44}})); - EXPECT_TRUE(opentelemetry::nostd::visit(equal_to_visitor, OV{std::vector{33, 44}}, AV{std::array{33, 44}})); - EXPECT_TRUE(opentelemetry::nostd::visit(equal_to_visitor, OV{std::vector{33.0, 44.0}}, AV{std::array{33.0, 44.0}})); - EXPECT_TRUE(opentelemetry::nostd::visit(equal_to_visitor, OV{std::vector{"a string", "another string"}}, AV{std::array{"a string", "another string"}})); + EXPECT_TRUE(opentelemetry::nostd::visit(equal_to_visitor, OV{double(22.0)}, AV{double(22.0)})); + + // string types + EXPECT_TRUE(opentelemetry::nostd::visit( + equal_to_visitor, OV{std::string("string to const char*")}, AV{"string to const char*"})); + EXPECT_TRUE(opentelemetry::nostd::visit(equal_to_visitor, + OV{std::string("string to string_view")}, + AV{nostd::string_view("string to string_view")})); + + // container types + EXPECT_TRUE(opentelemetry::nostd::visit(equal_to_visitor, OV{std::vector{true, false}}, + AV{std::array{true, false}})); + EXPECT_TRUE(opentelemetry::nostd::visit(equal_to_visitor, OV{std::vector{33, 44}}, + AV{std::array{33, 44}})); + EXPECT_TRUE(opentelemetry::nostd::visit(equal_to_visitor, OV{std::vector{33, 44}}, + AV{std::array{33, 44}})); + EXPECT_TRUE(opentelemetry::nostd::visit(equal_to_visitor, OV{std::vector{33, 44}}, + AV{std::array{33, 44}})); + EXPECT_TRUE(opentelemetry::nostd::visit(equal_to_visitor, OV{std::vector{33, 44}}, + AV{std::array{33, 44}})); + EXPECT_TRUE(opentelemetry::nostd::visit(equal_to_visitor, OV{std::vector{33, 44}}, + AV{std::array{33, 44}})); + EXPECT_TRUE(opentelemetry::nostd::visit(equal_to_visitor, OV{std::vector{33.0, 44.0}}, + AV{std::array{33.0, 44.0}})); + EXPECT_TRUE(opentelemetry::nostd::visit( + equal_to_visitor, OV{std::vector{"a string", "another string"}}, + AV{std::array{"a string", "another string"}})); } TEST(AttributeEqualToVisitorTest, AttributeValueNotEqualTo) { - namespace sdk = opentelemetry::sdk::common; - namespace api = opentelemetry::common; + namespace sdk = opentelemetry::sdk::common; + namespace api = opentelemetry::common; namespace nostd = opentelemetry::nostd; - + using AV = api::AttributeValue; - using OV = sdk::OwnedAttributeValue; + using OV = sdk::OwnedAttributeValue; sdk::AttributeEqualToVisitor equal_to_visitor; - - // check different values of the same type + + // check different values of the same type EXPECT_FALSE(opentelemetry::nostd::visit(equal_to_visitor, OV{bool(true)}, AV{bool(false)})); EXPECT_FALSE(opentelemetry::nostd::visit(equal_to_visitor, OV{int32_t(22)}, AV{int32_t(33)})); EXPECT_FALSE(opentelemetry::nostd::visit(equal_to_visitor, OV{int64_t(22)}, AV{int64_t(33)})); EXPECT_FALSE(opentelemetry::nostd::visit(equal_to_visitor, OV{uint32_t(22)}, AV{uint32_t(33)})); EXPECT_FALSE(opentelemetry::nostd::visit(equal_to_visitor, OV{double(22.2)}, AV{double(33.3)})); - EXPECT_FALSE(opentelemetry::nostd::visit(equal_to_visitor, OV{std::string("string one")}, AV{"another string"})); - EXPECT_FALSE(opentelemetry::nostd::visit(equal_to_visitor, OV{std::string("string one")}, AV{nostd::string_view("another string")})); + EXPECT_FALSE(opentelemetry::nostd::visit(equal_to_visitor, OV{std::string("string one")}, + AV{"another string"})); + EXPECT_FALSE(opentelemetry::nostd::visit(equal_to_visitor, OV{std::string("string one")}, + AV{nostd::string_view("another string")})); - // check different value types + // check different value types EXPECT_FALSE(opentelemetry::nostd::visit(equal_to_visitor, OV{bool(true)}, AV{uint32_t(0)})); EXPECT_FALSE(opentelemetry::nostd::visit(equal_to_visitor, OV{int32_t(22)}, AV{uint32_t(22)})); // check containers of different element values - EXPECT_FALSE(opentelemetry::nostd::visit(equal_to_visitor, OV{std::vector{true, false}}, AV{std::array{false, true}})); - EXPECT_FALSE(opentelemetry::nostd::visit(equal_to_visitor, OV{std::vector{22, 33}}, AV{std::array{33, 44}})); - EXPECT_FALSE(opentelemetry::nostd::visit(equal_to_visitor, OV{std::vector{"a string", "another string"}}, AV{std::array{"a string", "a really different string"}})); + EXPECT_FALSE(opentelemetry::nostd::visit(equal_to_visitor, OV{std::vector{true, false}}, + AV{std::array{false, true}})); + EXPECT_FALSE(opentelemetry::nostd::visit(equal_to_visitor, OV{std::vector{22, 33}}, + AV{std::array{33, 44}})); + EXPECT_FALSE(opentelemetry::nostd::visit( + equal_to_visitor, OV{std::vector{"a string", "another string"}}, + AV{std::array{"a string", "a really different string"}})); // check containers of different element types - EXPECT_FALSE(opentelemetry::nostd::visit(equal_to_visitor, OV{std::vector{22, 33}}, AV{std::array{22, 33}})); + EXPECT_FALSE(opentelemetry::nostd::visit(equal_to_visitor, OV{std::vector{22, 33}}, + AV{std::array{22, 33}})); } TEST(AttributeMapTest, EqualTo) { - using Attributes = std::initializer_list>; - + using Attributes = std::initializer_list< + std::pair>; + // check for case where both are empty - Attributes attributes_empty = {}; - auto kv_iterable_empty = opentelemetry::common::MakeKeyValueIterableView(attributes_empty); + Attributes attributes_empty = {}; + auto kv_iterable_empty = + opentelemetry::common::MakeKeyValueIterableView(attributes_empty); opentelemetry::sdk::common::AttributeMap attribute_map_empty(kv_iterable_empty); EXPECT_TRUE(attribute_map_empty.EqualTo(kv_iterable_empty)); - // check for equality with a range of attributes and types - Attributes attributes = {{"key0", "some value"}, {"key1", 1}, {"key2", 2.0}, {"key3", true}}; + // check for equality with a range of attributes and types + Attributes attributes = {{"key0", "some value"}, {"key1", 1}, {"key2", 2.0}, {"key3", true}}; auto kv_iterable_match = opentelemetry::common::MakeKeyValueIterableView(attributes); opentelemetry::sdk::common::AttributeMap attribute_map(attributes); EXPECT_TRUE(attribute_map.EqualTo(kv_iterable_match)); - // check for several cases where the attributes are different - Attributes attributes_different_value = {{"key0", "some value"}, {"key1", 1}, {"key2", 2.0}, {"key3", false}}; - Attributes attributes_different_type = {{"key0", "some value"}, {"key1", 1.0} ,{"key2", 2.0}, {"key3", true}}; - Attributes attributes_different_size = {{"key0", "some value"}}; - auto kv_iterable_different_value = opentelemetry::common::MakeKeyValueIterableView(attributes_different_value); - auto kv_iterable_different_type = opentelemetry::common::MakeKeyValueIterableView(attributes_different_type); - auto kv_iterable_different_size = opentelemetry::common::MakeKeyValueIterableView(attributes_different_size); - + // check for several cases where the attributes are different + Attributes attributes_different_value = { + {"key0", "some value"}, {"key1", 1}, {"key2", 2.0}, {"key3", false}}; + Attributes attributes_different_type = { + {"key0", "some value"}, {"key1", 1.0}, {"key2", 2.0}, {"key3", true}}; + Attributes attributes_different_size = {{"key0", "some value"}}; + auto kv_iterable_different_value = + opentelemetry::common::MakeKeyValueIterableView(attributes_different_value); + auto kv_iterable_different_type = + opentelemetry::common::MakeKeyValueIterableView(attributes_different_type); + auto kv_iterable_different_size = + opentelemetry::common::MakeKeyValueIterableView(attributes_different_size); + EXPECT_FALSE(attribute_map.EqualTo(kv_iterable_different_value)); - EXPECT_FALSE(attribute_map.EqualTo(kv_iterable_different_type)); - EXPECT_FALSE(attribute_map.EqualTo(kv_iterable_different_size)); + EXPECT_FALSE(attribute_map.EqualTo(kv_iterable_different_type)); + EXPECT_FALSE(attribute_map.EqualTo(kv_iterable_different_size)); } \ No newline at end of file diff --git a/sdk/test/instrumentationscope/instrumentationscope_test.cc b/sdk/test/instrumentationscope/instrumentationscope_test.cc index 442e9ea005..aa579c7328 100644 --- a/sdk/test/instrumentationscope/instrumentationscope_test.cc +++ b/sdk/test/instrumentationscope/instrumentationscope_test.cc @@ -211,36 +211,52 @@ TEST(InstrumentationScope, LegacyInstrumentationLibrary) TEST(InstrumentationScope, Equal) { - using Attributes = std::initializer_list>; - Attributes attributes_empty = {}; - Attributes attributes_match = {{"key0", "some value"}, {"key1", 1}, {"key2", 2.0}, {"key3", true}}; - Attributes attributes_different = {{"key42", "some other"}}; - - auto kv_iterable_empty = opentelemetry::common::MakeKeyValueIterableView(attributes_empty); - auto kv_iterable_match = opentelemetry::common::MakeKeyValueIterableView(attributes_match); - auto kv_iterable_different = opentelemetry::common::MakeKeyValueIterableView(attributes_different); - + using Attributes = std::initializer_list< + std::pair>; + Attributes attributes_empty = {}; + Attributes attributes_match = { + {"key0", "some value"}, {"key1", 1}, {"key2", 2.0}, {"key3", true}}; + Attributes attributes_different = {{"key42", "some other"}}; + + auto kv_iterable_empty = + opentelemetry::common::MakeKeyValueIterableView(attributes_empty); + auto kv_iterable_match = + opentelemetry::common::MakeKeyValueIterableView(attributes_match); + auto kv_iterable_different = + opentelemetry::common::MakeKeyValueIterableView(attributes_different); + // try with no attributes added to the instrumentation scope auto instrumentation_scope = - opentelemetry::sdk::instrumentationscope::InstrumentationScope::Create("library_name", "library_version", "schema_url"); + opentelemetry::sdk::instrumentationscope::InstrumentationScope::Create( + "library_name", "library_version", "schema_url"); - // the instrumentation scope is equal if all parameters are equal (must handle nullptr attributes or empty attributes) + // the instrumentation scope is equal if all parameters are equal (must handle nullptr attributes + // or empty attributes) EXPECT_TRUE(instrumentation_scope->equal("library_name", "library_version", "schema_url")); - EXPECT_TRUE(instrumentation_scope->equal("library_name", "library_version", "schema_url", nullptr)); - EXPECT_TRUE(instrumentation_scope->equal("library_name", "library_version", "schema_url", &kv_iterable_empty)); - + EXPECT_TRUE( + instrumentation_scope->equal("library_name", "library_version", "schema_url", nullptr)); + EXPECT_TRUE(instrumentation_scope->equal("library_name", "library_version", "schema_url", + &kv_iterable_empty)); + // the instrumentation scope is not equal if any parameter is different EXPECT_FALSE(instrumentation_scope->equal("library_name", "")); EXPECT_FALSE(instrumentation_scope->equal("library_name", "library_version", "")); - EXPECT_FALSE(instrumentation_scope->equal("library_name", "library_version", "schema_url", &kv_iterable_different)); - + EXPECT_FALSE(instrumentation_scope->equal("library_name", "library_version", "schema_url", + &kv_iterable_different)); + // try with attributes added to the instrumentation scope auto instrumentation_scope_w_attributes = - opentelemetry::sdk::instrumentationscope::InstrumentationScope::Create("library_name", "library_version", "schema_url", attributes_match); - - // the instrumentation scope is equal if all parameters including all attribute keys, types, and values are equal - EXPECT_TRUE(instrumentation_scope_w_attributes->equal("library_name", "library_version", "schema_url", &kv_iterable_match)); - EXPECT_FALSE(instrumentation_scope_w_attributes->equal("library_name", "library_version", "schema_url", nullptr)); - EXPECT_FALSE(instrumentation_scope_w_attributes->equal("library_name", "library_version", "schema_url", &kv_iterable_empty)); - EXPECT_FALSE(instrumentation_scope_w_attributes->equal("library_name", "library_version", "schema_url", &kv_iterable_different)); + opentelemetry::sdk::instrumentationscope::InstrumentationScope::Create( + "library_name", "library_version", "schema_url", attributes_match); + + // the instrumentation scope is equal if all parameters including all attribute keys, types, and + // values are equal + EXPECT_TRUE(instrumentation_scope_w_attributes->equal("library_name", "library_version", + "schema_url", &kv_iterable_match)); + EXPECT_FALSE(instrumentation_scope_w_attributes->equal("library_name", "library_version", + "schema_url", nullptr)); + EXPECT_FALSE(instrumentation_scope_w_attributes->equal("library_name", "library_version", + "schema_url", &kv_iterable_empty)); + EXPECT_FALSE(instrumentation_scope_w_attributes->equal("library_name", "library_version", + "schema_url", &kv_iterable_different)); } diff --git a/sdk/test/logs/logger_provider_sdk_test.cc b/sdk/test/logs/logger_provider_sdk_test.cc index 1a8ad4d28c..edddf2ef96 100644 --- a/sdk/test/logs/logger_provider_sdk_test.cc +++ b/sdk/test/logs/logger_provider_sdk_test.cc @@ -142,39 +142,43 @@ TEST(LoggerProviderSDK, LoggerEqualityCheck) auto another_logger3 = lp->GetLogger("logger3"); EXPECT_EQ(logger3, another_logger3); - auto logger4 = lp->GetLogger("logger4", "opentelelemtry_library", "1.0.0", schema_url); + auto logger4 = lp->GetLogger("logger4", "opentelelemtry_library", "1.0.0", schema_url); auto another_logger4 = lp->GetLogger("logger4", "opentelelemtry_library", "1.0.0", schema_url); EXPECT_EQ(logger4, another_logger4); - auto logger5 = lp->GetLogger("logger5", "opentelelemtry_library", "1.0.0", schema_url, {{"key", "value"}}); - auto another_logger5 = lp->GetLogger("logger5", "opentelelemtry_library", "1.0.0", schema_url, {{"key", "value"}}); + auto logger5 = + lp->GetLogger("logger5", "opentelelemtry_library", "1.0.0", schema_url, {{"key", "value"}}); + auto another_logger5 = + lp->GetLogger("logger5", "opentelelemtry_library", "1.0.0", schema_url, {{"key", "value"}}); EXPECT_EQ(logger5, another_logger5); } TEST(LoggerProviderSDK, GetLoggerInequalityCheck) { - auto lp = std::shared_ptr(new LoggerProvider()); - auto logger_library_1 = lp->GetLogger("logger1", "library_1"); - auto logger_library_2 = lp->GetLogger("logger1", "library_2"); - auto logger_version_1 = lp->GetLogger("logger1", "library_1", "1.0.0"); - auto logger_version_2 = lp->GetLogger("logger1", "library_1", "2.0.0"); - auto logger_url_1 = lp->GetLogger("logger1", "library_1", "1.0.0", "url_1"); - auto logger_url_2 = lp->GetLogger("logger1", "library_1", "1.0.0", "url_2"); - auto logger_attribute_1 = lp->GetLogger("logger1", "library_1", "1.0.0", "url_1", {{"key", "one"}}); - auto logger_attribute_2 = lp->GetLogger("logger1", "library_1", "1.0.0", "url_1", {{"key", "two"}}); + auto lp = std::shared_ptr(new LoggerProvider()); + auto logger_library_1 = lp->GetLogger("logger1", "library_1"); + auto logger_library_2 = lp->GetLogger("logger1", "library_2"); + auto logger_version_1 = lp->GetLogger("logger1", "library_1", "1.0.0"); + auto logger_version_2 = lp->GetLogger("logger1", "library_1", "2.0.0"); + auto logger_url_1 = lp->GetLogger("logger1", "library_1", "1.0.0", "url_1"); + auto logger_url_2 = lp->GetLogger("logger1", "library_1", "1.0.0", "url_2"); + auto logger_attribute_1 = + lp->GetLogger("logger1", "library_1", "1.0.0", "url_1", {{"key", "one"}}); + auto logger_attribute_2 = + lp->GetLogger("logger1", "library_1", "1.0.0", "url_1", {{"key", "two"}}); // different scope names should return distinct loggers EXPECT_NE(logger_library_1, logger_library_2); - + // different scope versions should return distinct loggers EXPECT_NE(logger_version_1, logger_library_1); EXPECT_NE(logger_version_1, logger_version_2); - + // different scope schema urls should return distinct loggers EXPECT_NE(logger_url_1, logger_library_1); EXPECT_NE(logger_url_1, logger_version_1); EXPECT_NE(logger_url_1, logger_url_2); - + // different scope attributes should return distinct loggers EXPECT_NE(logger_attribute_1, logger_library_1); EXPECT_NE(logger_attribute_1, logger_url_1); diff --git a/sdk/test/metrics/meter_provider_sdk_test.cc b/sdk/test/metrics/meter_provider_sdk_test.cc index feee60e30e..ee8a8a88c6 100644 --- a/sdk/test/metrics/meter_provider_sdk_test.cc +++ b/sdk/test/metrics/meter_provider_sdk_test.cc @@ -249,7 +249,7 @@ TEST(MeterProvider, GetMeterEqualityCheck) auto meter_library_1a = provider->GetMeter("library_name"); auto meter_library_1b = provider->GetMeter("library_name"); EXPECT_EQ(meter_library_1a, meter_library_1b); - + // providing the same scope name and version should return the same meter auto meter_version_1a = provider->GetMeter("library_name", "v1.0"); auto meter_version_1b = provider->GetMeter("library_name", "v1.0"); @@ -264,28 +264,27 @@ TEST(MeterProvider, GetMeterEqualityCheck) TEST(MeterProvider, GetMeterInequalityCheck) { auto provider = MeterProviderFactory::Create(); - + auto meter_library_1 = provider->GetMeter("library_1"); auto meter_library_2 = provider->GetMeter("library_2"); auto meter_version_1 = provider->GetMeter("library_1", "v1.0"); - auto meter_version_2 = provider->GetMeter("library_1", "v2.0"); + auto meter_version_2 = provider->GetMeter("library_1", "v2.0"); auto meter_url_1 = provider->GetMeter("library_1", "v1.0", "url_1"); auto meter_url_2 = provider->GetMeter("library_1", "v1.0", "url_2"); - + // different scope names should return distinct meters EXPECT_NE(meter_library_1, meter_library_2); - + // different scope versions should return distinct meters EXPECT_NE(meter_version_1, meter_library_1); EXPECT_NE(meter_version_1, meter_version_2); - + // different scope schema urls should return distinct meters EXPECT_NE(meter_url_1, meter_library_1); EXPECT_NE(meter_url_1, meter_version_1); EXPECT_NE(meter_url_1, meter_url_2); } - #if OPENTELEMETRY_ABI_VERSION_NO >= 2 TEST(MeterProvider, GetMeterEqualityCheckAbiv2) @@ -305,7 +304,7 @@ TEST(MeterProvider, GetMeterInequalityCheckAbiv2) auto meter_1 = provider->GetMeter("library_name", "v1.0", "url"); auto meter_attribute_1 = provider->GetMeter("library_name", "v1.0", "url", {{"key", "one"}}); auto meter_attribute_2 = provider->GetMeter("library_name", "v1.0", "url", {{"key", "two"}}); - + // different scope attributes should return distinct meters EXPECT_NE(meter_attribute_1, meter_1); EXPECT_NE(meter_attribute_1, meter_attribute_2); diff --git a/sdk/test/trace/tracer_provider_test.cc b/sdk/test/trace/tracer_provider_test.cc index a76ef8885f..8424283fcb 100644 --- a/sdk/test/trace/tracer_provider_test.cc +++ b/sdk/test/trace/tracer_provider_test.cc @@ -93,32 +93,33 @@ TEST(TracerProvider, GetTracer) TEST(TracerProvider, GetTracerEqualityCheck) { - auto provider = TracerProviderFactory::Create(std::move(SimpleSpanProcessorFactory::Create(nullptr))); + auto provider = + TracerProviderFactory::Create(std::move(SimpleSpanProcessorFactory::Create(nullptr))); // providing the same scope names should return the same tracer auto tracer_1a = provider->GetTracer("library_name"); auto tracer_1b = provider->GetTracer("library_name"); EXPECT_EQ(tracer_1a, tracer_1b); - + // providing the same scope name and version should return the same tracer auto tracer_version1a = provider->GetTracer("library_name", "v1.0"); auto tracer_version1b = provider->GetTracer("library_name", "v1.0"); EXPECT_EQ(tracer_version1a, tracer_version1b); - + // providing the same name, version, and schema urls should return the same tracer auto tracer_urla = provider->GetTracer("library_name", "v1.0", "url"); auto tracer_urlb = provider->GetTracer("library_name", "v1.0", "url"); EXPECT_EQ(tracer_urla, tracer_urlb); - } TEST(TracerProvider, GetTracerInequalityCheck) { - auto provider = TracerProviderFactory::Create(std::move(SimpleSpanProcessorFactory::Create(nullptr))); + auto provider = + TracerProviderFactory::Create(std::move(SimpleSpanProcessorFactory::Create(nullptr))); auto tracer_library_1 = provider->GetTracer("library_1"); auto tracer_library_2 = provider->GetTracer("library_2"); auto tracer_version_1 = provider->GetTracer("library_1", "v1.0"); - auto tracer_version_2 = provider->GetTracer("library_1", "v2.0"); + auto tracer_version_2 = provider->GetTracer("library_1", "v2.0"); auto tracer_url_1 = provider->GetTracer("library_1", "v1.0", "url_1"); auto tracer_url_2 = provider->GetTracer("library_1", "v1.0", "url_2"); @@ -128,19 +129,19 @@ TEST(TracerProvider, GetTracerInequalityCheck) // different scope versions should return distinct tracers EXPECT_NE(tracer_version_1, tracer_library_1); EXPECT_NE(tracer_version_1, tracer_version_2); - + // different scope schema urls should return distinct tracers EXPECT_NE(tracer_url_1, tracer_library_1); EXPECT_NE(tracer_url_1, tracer_version_1); EXPECT_NE(tracer_url_1, tracer_url_2); } - #if OPENTELEMETRY_ABI_VERSION_NO >= 2 TEST(TracerProvider, GetTracerEqualityCheckAbiv2) { - auto provider = TracerProviderFactory::Create(std::move(SimpleSpanProcessorFactory::Create(nullptr))); + auto provider = + TracerProviderFactory::Create(std::move(SimpleSpanProcessorFactory::Create(nullptr))); auto tracer_attribute1a = provider->GetTracer("library_name", "v1.0", "url", {{"key", "one"}}); auto tracer_attribute1b = provider->GetTracer("library_name", "v1.0", "url", {{"key", "one"}}); @@ -151,7 +152,8 @@ TEST(TracerProvider, GetTracerEqualityCheckAbiv2) TEST(TracerProvider, GetTracerInequalityCheckAbiv2) { - auto provider = TracerProviderFactory::Create(std::move(SimpleSpanProcessorFactory::Create(nullptr))); + auto provider = + TracerProviderFactory::Create(std::move(SimpleSpanProcessorFactory::Create(nullptr))); auto tracer_1 = provider->GetTracer("library_name", "v1.0", "url"); auto tracer_attribute1 = provider->GetTracer("library_name", "v1.0", "url", {{"key", "one"}}); auto tracer_attribute2 = provider->GetTracer("library_name", "v1.0", "url", {{"key", "two"}}); From 53ec99cabdea6b9cbd2ab5ae53783299d329d9ef Mon Sep 17 00:00:00 2001 From: Douglas Barker Date: Tue, 17 Dec 2024 16:13:02 -0700 Subject: [PATCH 3/9] fix issue found with maintainer test --- sdk/test/trace/tracer_provider_test.cc | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/sdk/test/trace/tracer_provider_test.cc b/sdk/test/trace/tracer_provider_test.cc index 8424283fcb..8bdad908ad 100644 --- a/sdk/test/trace/tracer_provider_test.cc +++ b/sdk/test/trace/tracer_provider_test.cc @@ -93,8 +93,8 @@ TEST(TracerProvider, GetTracer) TEST(TracerProvider, GetTracerEqualityCheck) { - auto provider = - TracerProviderFactory::Create(std::move(SimpleSpanProcessorFactory::Create(nullptr))); + auto processor = SimpleSpanProcessorFactory::Create(nullptr); + auto provider = TracerProviderFactory::Create(std::move(processor)); // providing the same scope names should return the same tracer auto tracer_1a = provider->GetTracer("library_name"); @@ -114,8 +114,9 @@ TEST(TracerProvider, GetTracerEqualityCheck) TEST(TracerProvider, GetTracerInequalityCheck) { - auto provider = - TracerProviderFactory::Create(std::move(SimpleSpanProcessorFactory::Create(nullptr))); + auto processor = SimpleSpanProcessorFactory::Create(nullptr); + auto provider = TracerProviderFactory::Create(std::move(processor)); + auto tracer_library_1 = provider->GetTracer("library_1"); auto tracer_library_2 = provider->GetTracer("library_2"); auto tracer_version_1 = provider->GetTracer("library_1", "v1.0"); @@ -140,8 +141,8 @@ TEST(TracerProvider, GetTracerInequalityCheck) TEST(TracerProvider, GetTracerEqualityCheckAbiv2) { - auto provider = - TracerProviderFactory::Create(std::move(SimpleSpanProcessorFactory::Create(nullptr))); + auto processor = SimpleSpanProcessorFactory::Create(nullptr); + auto provider = TracerProviderFactory::Create(std::move(processor)); auto tracer_attribute1a = provider->GetTracer("library_name", "v1.0", "url", {{"key", "one"}}); auto tracer_attribute1b = provider->GetTracer("library_name", "v1.0", "url", {{"key", "one"}}); @@ -152,8 +153,9 @@ TEST(TracerProvider, GetTracerEqualityCheckAbiv2) TEST(TracerProvider, GetTracerInequalityCheckAbiv2) { - auto provider = - TracerProviderFactory::Create(std::move(SimpleSpanProcessorFactory::Create(nullptr))); + auto processor = SimpleSpanProcessorFactory::Create(nullptr); + auto provider = TracerProviderFactory::Create(std::move(processor)); + auto tracer_1 = provider->GetTracer("library_name", "v1.0", "url"); auto tracer_attribute1 = provider->GetTracer("library_name", "v1.0", "url", {{"key", "one"}}); auto tracer_attribute2 = provider->GetTracer("library_name", "v1.0", "url", {{"key", "two"}}); From 0379249de28e8b7ab6d2a5c3480260b95422f38a Mon Sep 17 00:00:00 2001 From: Douglas Barker Date: Tue, 17 Dec 2024 16:48:02 -0700 Subject: [PATCH 4/9] add missing newline at end of file --- sdk/test/common/attribute_utils_test.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/test/common/attribute_utils_test.cc b/sdk/test/common/attribute_utils_test.cc index 4028098d56..14f00affae 100644 --- a/sdk/test/common/attribute_utils_test.cc +++ b/sdk/test/common/attribute_utils_test.cc @@ -179,4 +179,4 @@ TEST(AttributeMapTest, EqualTo) EXPECT_FALSE(attribute_map.EqualTo(kv_iterable_different_value)); EXPECT_FALSE(attribute_map.EqualTo(kv_iterable_different_type)); EXPECT_FALSE(attribute_map.EqualTo(kv_iterable_different_size)); -} \ No newline at end of file +} From d0d6bba8a1cd13dadbb4ae725d2231f0f88dd5cf Mon Sep 17 00:00:00 2001 From: Douglas Barker Date: Tue, 17 Dec 2024 16:53:03 -0700 Subject: [PATCH 5/9] update changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 22176df917..71d8f19743 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,9 @@ Increment the: ## [Unreleased] +* [SDK] Fix instrumentation scope attributes evaluated in equal method + [#3214](https://github.com/open-telemetry/opentelemetry-cpp/pull/3214) + ## [1.18 2024-11-25] * [EXPORTER] Fix crash in ElasticsearchLogRecordExporter From 69f4355aa5bd61fa0a4eb5d7d512882fbc0326a8 Mon Sep 17 00:00:00 2001 From: Douglas Barker Date: Tue, 17 Dec 2024 17:13:42 -0700 Subject: [PATCH 6/9] add missing test check --- sdk/test/common/attribute_utils_test.cc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sdk/test/common/attribute_utils_test.cc b/sdk/test/common/attribute_utils_test.cc index 14f00affae..98fdb682e9 100644 --- a/sdk/test/common/attribute_utils_test.cc +++ b/sdk/test/common/attribute_utils_test.cc @@ -169,14 +169,20 @@ TEST(AttributeMapTest, EqualTo) Attributes attributes_different_type = { {"key0", "some value"}, {"key1", 1.0}, {"key2", 2.0}, {"key3", true}}; Attributes attributes_different_size = {{"key0", "some value"}}; + + Attributes attributes_different_all = {{"a", "b"}, {"c", "d"}, {"f", uint8_t(5)}}; + auto kv_iterable_different_value = opentelemetry::common::MakeKeyValueIterableView(attributes_different_value); auto kv_iterable_different_type = opentelemetry::common::MakeKeyValueIterableView(attributes_different_type); auto kv_iterable_different_size = opentelemetry::common::MakeKeyValueIterableView(attributes_different_size); + auto kv_iterable_different_all = + opentelemetry::common::MakeKeyValueIterableView(attributes_different_all); EXPECT_FALSE(attribute_map.EqualTo(kv_iterable_different_value)); EXPECT_FALSE(attribute_map.EqualTo(kv_iterable_different_type)); EXPECT_FALSE(attribute_map.EqualTo(kv_iterable_different_size)); + EXPECT_FALSE(attribute_map.EqualTo(kv_iterable_different_all)); } From ae3339363abd994d78157765d1197ab07bd51bc5 Mon Sep 17 00:00:00 2001 From: Doug Barker Date: Tue, 17 Dec 2024 17:16:35 -0700 Subject: [PATCH 7/9] Fix spelling Co-authored-by: Marc Alff --- sdk/include/opentelemetry/sdk/common/attribute_utils.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/include/opentelemetry/sdk/common/attribute_utils.h b/sdk/include/opentelemetry/sdk/common/attribute_utils.h index a1da839421..e3bd17c78e 100644 --- a/sdk/include/opentelemetry/sdk/common/attribute_utils.h +++ b/sdk/include/opentelemetry/sdk/common/attribute_utils.h @@ -119,7 +119,7 @@ struct AttributeEqualToVisitor return false; } - // Compare the same arithmatic types + // Compare the same arithmetic types template bool operator()(const T &owned_value, const T &value) const noexcept { From ac5c33fc70a0944dfe2c4659bb24ba65380a3c20 Mon Sep 17 00:00:00 2001 From: Doug Barker Date: Tue, 17 Dec 2024 17:17:08 -0700 Subject: [PATCH 8/9] Fix spelling Co-authored-by: Marc Alff --- sdk/include/opentelemetry/sdk/common/attribute_utils.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/include/opentelemetry/sdk/common/attribute_utils.h b/sdk/include/opentelemetry/sdk/common/attribute_utils.h index e3bd17c78e..734868700f 100644 --- a/sdk/include/opentelemetry/sdk/common/attribute_utils.h +++ b/sdk/include/opentelemetry/sdk/common/attribute_utils.h @@ -149,7 +149,7 @@ struct AttributeEqualToVisitor }); } - // Compare nostd::span and std::vector for arithmatic types + // Compare nostd::span and std::vector for arithmetic types template bool operator()(const std::vector &owned_value, const nostd::span &value) const noexcept From 6a786796d8ab7975b9defa34fe87c0ec89600a38 Mon Sep 17 00:00:00 2001 From: Douglas Barker Date: Wed, 18 Dec 2024 10:36:38 -0700 Subject: [PATCH 9/9] add missing comments and update the instrumentation scope equality operator to check attributes. add a test and minor fixes/comments to the tests --- .../sdk/common/attribute_utils.h | 1 + .../instrumentation_scope.h | 4 +- sdk/test/common/attribute_utils_test.cc | 5 ++- .../instrumentationscope_test.cc | 44 +++++++++++++++++++ 4 files changed, 51 insertions(+), 3 deletions(-) diff --git a/sdk/include/opentelemetry/sdk/common/attribute_utils.h b/sdk/include/opentelemetry/sdk/common/attribute_utils.h index 734868700f..c2d0209a7d 100644 --- a/sdk/include/opentelemetry/sdk/common/attribute_utils.h +++ b/sdk/include/opentelemetry/sdk/common/attribute_utils.h @@ -216,6 +216,7 @@ class AttributeMap : public std::unordered_map (*this)[std::string(key)] = nostd::visit(converter_, value); } + // Compare the attributes of this map with another KeyValueIterable bool EqualTo(const opentelemetry::common::KeyValueIterable &attributes) const noexcept { if (attributes.size() != this->size()) diff --git a/sdk/include/opentelemetry/sdk/instrumentationscope/instrumentation_scope.h b/sdk/include/opentelemetry/sdk/instrumentationscope/instrumentation_scope.h index b69948b4bf..68e9d10d40 100644 --- a/sdk/include/opentelemetry/sdk/instrumentationscope/instrumentation_scope.h +++ b/sdk/include/opentelemetry/sdk/instrumentationscope/instrumentation_scope.h @@ -103,7 +103,8 @@ class InstrumentationScope */ bool operator==(const InstrumentationScope &other) const noexcept { - return equal(other.name_, other.version_, other.schema_url_); + return this->name_ == other.name_ && this->version_ == other.version_ && + this->schema_url_ == other.schema_url_ && this->attributes_ == other.attributes_; } /** @@ -112,6 +113,7 @@ class InstrumentationScope * @param name name of the instrumentation scope to compare. * @param version version of the instrumentation scope to compare. * @param schema_url schema url of the telemetry emitted by the scope. + * @param attributes attributes of the instrumentation scope to compare. * @returns true if name and version in this instrumentation scope are equal with the given name * and version. */ diff --git a/sdk/test/common/attribute_utils_test.cc b/sdk/test/common/attribute_utils_test.cc index 98fdb682e9..da303643d0 100644 --- a/sdk/test/common/attribute_utils_test.cc +++ b/sdk/test/common/attribute_utils_test.cc @@ -128,7 +128,7 @@ TEST(AttributeEqualToVisitorTest, AttributeValueNotEqualTo) AV{nostd::string_view("another string")})); // check different value types - EXPECT_FALSE(opentelemetry::nostd::visit(equal_to_visitor, OV{bool(true)}, AV{uint32_t(0)})); + EXPECT_FALSE(opentelemetry::nostd::visit(equal_to_visitor, OV{bool(true)}, AV{uint32_t(1)})); EXPECT_FALSE(opentelemetry::nostd::visit(equal_to_visitor, OV{int32_t(22)}, AV{uint32_t(22)})); // check containers of different element values @@ -170,7 +170,8 @@ TEST(AttributeMapTest, EqualTo) {"key0", "some value"}, {"key1", 1.0}, {"key2", 2.0}, {"key3", true}}; Attributes attributes_different_size = {{"key0", "some value"}}; - Attributes attributes_different_all = {{"a", "b"}, {"c", "d"}, {"f", uint8_t(5)}}; + // check for the case where the number of attributes is the same but all keys are different + Attributes attributes_different_all = {{"a", "b"}, {"c", "d"}, {"e", 4.0}, {"f", uint8_t(5)}}; auto kv_iterable_different_value = opentelemetry::common::MakeKeyValueIterableView(attributes_different_value); diff --git a/sdk/test/instrumentationscope/instrumentationscope_test.cc b/sdk/test/instrumentationscope/instrumentationscope_test.cc index aa579c7328..347e107aca 100644 --- a/sdk/test/instrumentationscope/instrumentationscope_test.cc +++ b/sdk/test/instrumentationscope/instrumentationscope_test.cc @@ -260,3 +260,47 @@ TEST(InstrumentationScope, Equal) EXPECT_FALSE(instrumentation_scope_w_attributes->equal("library_name", "library_version", "schema_url", &kv_iterable_different)); } + +TEST(InstrumentationScope, OperatorEqual) +{ + using Attributes = std::initializer_list< + std::pair>; + Attributes attributes_empty = {}; + Attributes attributes_match = { + {"key0", "some value"}, {"key1", 1}, {"key2", 2.0}, {"key3", true}}; + Attributes attributes_different = {{"key42", "some other"}}; + + auto instrumentation_scope_1a = + opentelemetry::sdk::instrumentationscope::InstrumentationScope::Create( + "library_name", "library_version", "schema_url"); + + auto instrumentation_scope_1b = + opentelemetry::sdk::instrumentationscope::InstrumentationScope::Create( + "library_name", "library_version", "schema_url"); + + auto instrumentation_scope_2a = + opentelemetry::sdk::instrumentationscope::InstrumentationScope::Create( + "library_name_2", "library_version", "schema_url"); + + auto instrumentation_scope_2b = + opentelemetry::sdk::instrumentationscope::InstrumentationScope::Create( + "library_name_2", "library_version", "schema_url", attributes_empty); + + auto instrumentation_scope_3a = + opentelemetry::sdk::instrumentationscope::InstrumentationScope::Create( + "library_name_2", "library_version", "schema_url", attributes_match); + + auto instrumentation_scope_3b = + opentelemetry::sdk::instrumentationscope::InstrumentationScope::Create( + "library_name_2", "library_version", "schema_url", attributes_match); + + auto instrumentation_scope_4 = + opentelemetry::sdk::instrumentationscope::InstrumentationScope::Create( + "library_name_2", "library_version", "schema_url", attributes_different); + + EXPECT_EQ(*instrumentation_scope_1a, *instrumentation_scope_1b); + EXPECT_FALSE(*instrumentation_scope_1a == *instrumentation_scope_2a); + EXPECT_EQ(*instrumentation_scope_2a, *instrumentation_scope_2b); + EXPECT_EQ(*instrumentation_scope_3a, *instrumentation_scope_3b); + EXPECT_FALSE(*instrumentation_scope_3a == *instrumentation_scope_4); +}