diff --git a/sdk/include/opentelemetry/sdk/metrics/view/attributes_processor.h b/sdk/include/opentelemetry/sdk/metrics/view/attributes_processor.h index 7ab8cafb13..7b320d8d6a 100644 --- a/sdk/include/opentelemetry/sdk/metrics/view/attributes_processor.h +++ b/sdk/include/opentelemetry/sdk/metrics/view/attributes_processor.h @@ -80,7 +80,7 @@ class FilteringAttributesProcessor : public AttributesProcessor MetricAttributes result; attributes.ForEachKeyValue( [&](nostd::string_view key, opentelemetry::common::AttributeValue value) noexcept { - if (allowed_attribute_keys_.find(key.data()) != allowed_attribute_keys_.end()) + if (allowed_attribute_keys_.find(std::string(key)) != allowed_attribute_keys_.end()) { result.SetAttribute(key, value); return true; @@ -94,13 +94,57 @@ class FilteringAttributesProcessor : public AttributesProcessor bool isPresent(nostd::string_view key) const noexcept override { - return (allowed_attribute_keys_.find(key.data()) != allowed_attribute_keys_.end()); + return (allowed_attribute_keys_.find(std::string(key)) != allowed_attribute_keys_.end()); } private: std::unordered_map allowed_attribute_keys_; }; +/** + * FilteringExcludeAttributeProcessor filters by exclude attribute list and drops names if they are + * present in the exclude list + */ + +class FilteringExcludeAttributesProcessor : public AttributesProcessor +{ +public: + FilteringExcludeAttributesProcessor(std::unordered_map &&exclude_list = {}) + : exclude_list_(std::move(exclude_list)) + {} + + FilteringExcludeAttributesProcessor( + const std::unordered_map &exclude_list = {}) + : exclude_list_(exclude_list) + {} + + MetricAttributes process( + const opentelemetry::common::KeyValueIterable &attributes) const noexcept override + { + MetricAttributes result; + attributes.ForEachKeyValue( + [&](nostd::string_view key, opentelemetry::common::AttributeValue value) noexcept { + if (exclude_list_.find(std::string(key)) == exclude_list_.end()) + { + result.SetAttribute(key, value); + return true; + } + return true; + }); + + result.UpdateHash(); + return result; + } + + bool isPresent(nostd::string_view key) const noexcept override + { + return (exclude_list_.find(std::string(key)) == exclude_list_.end()); + } + +private: + std::unordered_map exclude_list_; +}; + } // namespace metrics } // namespace sdk OPENTELEMETRY_END_NAMESPACE diff --git a/sdk/test/metrics/attributes_processor_test.cc b/sdk/test/metrics/attributes_processor_test.cc index 25652ed3e1..8de97cc6df 100644 --- a/sdk/test/metrics/attributes_processor_test.cc +++ b/sdk/test/metrics/attributes_processor_test.cc @@ -51,3 +51,40 @@ TEST(AttributesProcessor, FilteringAllAttributesProcessor) auto filtered_attributes = attributes_processor.process(iterable); EXPECT_EQ(filter.size(), kNumFilterAttributes); } + +TEST(AttributesProcessor, FilteringExcludeAttributesProcessor) +{ + std::unordered_map filter = { + {"attr2", true}, {"attr4", true}, {"attr6", true}}; + const int kNumAttributes = 7; + std::string keys[kNumAttributes] = {"attr1", "attr2", "attr3", "attr4", + "attr5", "attr6", "attr7"}; + int values[kNumAttributes] = {10, 20, 30, 40, 50, 60, 70}; + std::map attributes = { + {keys[0], values[0]}, {keys[1], values[1]}, {keys[2], values[2]}, {keys[3], values[3]}, + {keys[4], values[4]}, {keys[5], values[5]}, {keys[6], values[6]}}; + FilteringExcludeAttributesProcessor attributes_processor(filter); + opentelemetry::common::KeyValueIterableView> iterable(attributes); + auto filtered_attributes = attributes_processor.process(iterable); + for (auto &e : filtered_attributes) + { + EXPECT_TRUE(filter.find(e.first) == filter.end()); + } + int expected_filtered_attributes_size = 4; + EXPECT_EQ(filtered_attributes.size(), expected_filtered_attributes_size); +} + +TEST(AttributesProcessor, FilteringExcludeAllAttributesProcessor) +{ + std::unordered_map filter = {}; + const int kNumAttributes = 6; + std::string keys[kNumAttributes] = {"attr1", "attr2", "attr3", "attr4", "attr5", "attr6"}; + int values[kNumAttributes] = {10, 20, 30, 40, 50, 60}; + std::map attributes = {{keys[0], values[0]}, {keys[1], values[1]}, + {keys[2], values[2]}, {keys[3], values[3]}, + {keys[4], values[4]}, {keys[5], values[5]}}; + FilteringExcludeAttributesProcessor attributes_processor(filter); + opentelemetry::common::KeyValueIterableView> iterable(attributes); + auto filtered_attributes = attributes_processor.process(iterable); + EXPECT_EQ(filtered_attributes.size(), kNumAttributes); +}