@@ -23,44 +23,65 @@ using MetricAttributes = opentelemetry::sdk::metrics::FilteredOrderedAttributeMa
2323
2424/* *
2525 * Hash and equality for nostd::string_view, enabling safe use in unordered_map
26- * without requiring null termination. Supports heterogeneous lookup with
27- * std::string and std::string_view as well.
26+ * without requiring null termination.
2827 */
2928struct StringViewHash
3029{
3130 using is_transparent = void ;
31+
32+ std::size_t operator ()(const std::string &s) const noexcept
33+ {
34+ return std::hash<std::string>{}(s);
35+ }
36+ std::size_t operator ()(std::string_view sv) const noexcept
37+ {
38+ return std::hash<std::string_view>{}(sv);
39+ }
3240 std::size_t operator ()(opentelemetry::nostd::string_view sv) const noexcept
3341 {
34- return std::hash<std::string_view>{}(
35- std::string_view{sv.data (), sv.size ()});
42+ return std::hash<std::string_view>{}(std::string_view{sv.data (), sv.size ()});
3643 }
3744};
3845
3946struct StringViewEqual
4047{
4148 using is_transparent = void ;
42- bool operator ()(opentelemetry::nostd::string_view lhs,
43- opentelemetry::nostd::string_view rhs) const noexcept
49+
50+ bool operator ()( const std::string &lhs, const std::string & rhs) const noexcept
4451 {
45- return lhs.size () == rhs.size () &&
46- std::memcmp (lhs.data (), rhs.data (), lhs.size ()) == 0 ;
52+ return lhs == rhs;
4753 }
48-
49- bool operator ()(const std::string &lhs,
50- opentelemetry::nostd::string_view rhs) const noexcept
54+ bool operator ()(const std::string &lhs, std::string_view rhs) const noexcept
5155 {
52- return lhs.size () == rhs.size () &&
53- std::memcmp (lhs.data (), rhs.data (), lhs.size ()) == 0 ;
56+ return lhs.size () == rhs.size () && std::memcmp (lhs.data (), rhs.data (), lhs.size ()) == 0 ;
5457 }
55-
56- bool operator ()(opentelemetry::nostd::string_view lhs,
57- const std::string &rhs) const noexcept
58+ bool operator ()(std::string_view lhs, const std::string &rhs) const noexcept
5859 {
59- return rhs.size () == lhs.size () &&
60- std::memcmp (lhs.data (), rhs.data (), rhs.size ()) == 0 ;
60+ return lhs.size () == rhs.size () && std::memcmp (lhs.data (), rhs.data (), lhs.size ()) == 0 ;
61+ }
62+ bool operator ()(opentelemetry::nostd::string_view lhs, const std::string &rhs) const noexcept
63+ {
64+ return lhs.size () == rhs.size () && std::memcmp (lhs.data (), rhs.data (), lhs.size ()) == 0 ;
6165 }
6266};
6367
68+ /* *
69+ * Cross-platform heterogeneous lookup wrapper.
70+ * Falls back to std::string construction on libc++ (macOS),
71+ * but uses direct lookup on libstdc++ (Linux).
72+ */
73+ template <typename Map, typename Key>
74+ auto find_hetero (Map &map, Key &&key)
75+ {
76+ #if defined(_LIBCPP_VERSION) && !defined(_LIBCPP_HAS_UNORDERED_MAP_TRANSPARENT_LOOKUP)
77+ // libc++ (macOS) does not yet support heterogeneous lookup in unordered_map
78+ return map.find (std::string (key));
79+ #else
80+ // libstdc++ (Linux, GCC/Clang) supports it
81+ return map.find (std::forward<Key>(key));
82+ #endif
83+ }
84+
6485/* *
6586 * The AttributesProcessor is responsible for customizing which
6687 * attribute(s) are to be reported as metrics dimension(s).
@@ -106,12 +127,15 @@ class DefaultAttributesProcessor : public AttributesProcessor
106127class FilteringAttributesProcessor : public AttributesProcessor
107128{
108129public:
109- FilteringAttributesProcessor (std::unordered_map<std::string, bool , StringViewHash, StringViewEqual> &&allowed_attribute_keys = {})
130+ FilteringAttributesProcessor (
131+ std::unordered_map<std::string, bool , StringViewHash, StringViewEqual>
132+ &&allowed_attribute_keys = {})
110133 : allowed_attribute_keys_(std::move(allowed_attribute_keys))
111134 {}
112135
113136 FilteringAttributesProcessor (
114- const std::unordered_map<std::string, bool , StringViewHash, StringViewEqual> &allowed_attribute_keys = {})
137+ const std::unordered_map<std::string, bool , StringViewHash, StringViewEqual>
138+ &allowed_attribute_keys = {})
115139 : allowed_attribute_keys_(allowed_attribute_keys)
116140 {}
117141
@@ -121,7 +145,7 @@ class FilteringAttributesProcessor : public AttributesProcessor
121145 MetricAttributes result;
122146 attributes.ForEachKeyValue (
123147 [&](nostd::string_view key, opentelemetry::common::AttributeValue value) noexcept {
124- if (allowed_attribute_keys_. find ( key) != allowed_attribute_keys_.end ())
148+ if (find_hetero (allowed_attribute_keys_, key) != allowed_attribute_keys_.end ())
125149 {
126150 result.SetAttribute (key, value);
127151 return true ;
@@ -135,7 +159,7 @@ class FilteringAttributesProcessor : public AttributesProcessor
135159
136160 bool isPresent (nostd::string_view key) const noexcept override
137161 {
138- return (allowed_attribute_keys_. find ( key) != allowed_attribute_keys_.end ());
162+ return (find_hetero (allowed_attribute_keys_, key) != allowed_attribute_keys_.end ());
139163 }
140164
141165private:
@@ -150,12 +174,14 @@ class FilteringAttributesProcessor : public AttributesProcessor
150174class FilteringExcludeAttributesProcessor : public AttributesProcessor
151175{
152176public:
153- FilteringExcludeAttributesProcessor (std::unordered_map<std::string, bool , StringViewHash, StringViewEqual> &&exclude_list = {})
177+ FilteringExcludeAttributesProcessor (
178+ std::unordered_map<std::string, bool , StringViewHash, StringViewEqual> &&exclude_list = {})
154179 : exclude_list_(std::move(exclude_list))
155180 {}
156181
157182 FilteringExcludeAttributesProcessor (
158- const std::unordered_map<std::string, bool , StringViewHash, StringViewEqual> &exclude_list = {})
183+ const std::unordered_map<std::string, bool , StringViewHash, StringViewEqual> &exclude_list =
184+ {})
159185 : exclude_list_(exclude_list)
160186 {}
161187
@@ -165,7 +191,7 @@ class FilteringExcludeAttributesProcessor : public AttributesProcessor
165191 MetricAttributes result;
166192 attributes.ForEachKeyValue (
167193 [&](nostd::string_view key, opentelemetry::common::AttributeValue value) noexcept {
168- if (exclude_list_. find ( key) == exclude_list_.end ())
194+ if (find_hetero (exclude_list_, key) == exclude_list_.end ())
169195 {
170196 result.SetAttribute (key, value);
171197 return true ;
@@ -179,7 +205,7 @@ class FilteringExcludeAttributesProcessor : public AttributesProcessor
179205
180206 bool isPresent (nostd::string_view key) const noexcept override
181207 {
182- return (exclude_list_. find ( key) == exclude_list_.end ());
208+ return (find_hetero (exclude_list_, key) == exclude_list_.end ());
183209 }
184210
185211private:
0 commit comments