1515#include " opentelemetry/sdk/common/attribute_utils.h"
1616#include " opentelemetry/sdk/common/attributemap_hash.h"
1717#include " opentelemetry/sdk/metrics/aggregation/aggregation.h"
18+ #include " opentelemetry/sdk/metrics/state/filtered_ordered_attribute_map.h"
1819#include " opentelemetry/sdk/metrics/view/attributes_processor.h"
1920#include " opentelemetry/version.h"
2021
@@ -29,9 +30,9 @@ using opentelemetry::sdk::common::OrderedAttributeMap;
2930constexpr size_t kAggregationCardinalityLimit = 2000 ;
3031const std::string kAttributesLimitOverflowKey = " otel.metrics.overflow" ;
3132const bool kAttributesLimitOverflowValue = true ;
32- const size_t kOverflowAttributesHash = opentelemetry::sdk::common::GetHashForAttributeMap(
33- {{ kAttributesLimitOverflowKey ,
34- kAttributesLimitOverflowValue }}) ; // precalculated for optimization
33+ const MetricAttributes kOverflowAttributes = {
34+ {kAttributesLimitOverflowKey ,
35+ kAttributesLimitOverflowValue }}; // precalculated for optimization
3536
3637class AttributeHashGenerator
3738{
@@ -42,18 +43,19 @@ class AttributeHashGenerator
4243 }
4344};
4445
45- class AttributesHashMap
46+ template <typename CustomHash = MetricAttributesHash>
47+ class AttributesHashMapWithCustomHash
4648{
4749public:
48- AttributesHashMap (size_t attributes_limit = kAggregationCardinalityLimit )
50+ AttributesHashMapWithCustomHash (size_t attributes_limit = kAggregationCardinalityLimit )
4951 : attributes_limit_(attributes_limit)
5052 {}
51- Aggregation *Get (size_t hash ) const
53+ Aggregation *Get (const MetricAttributes &attributes ) const
5254 {
53- auto it = hash_map_.find (hash );
55+ auto it = hash_map_.find (attributes );
5456 if (it != hash_map_.end ())
5557 {
56- return it->second .second . get ();
58+ return it->second .get ();
5759 }
5860 return nullptr ;
5961 }
@@ -62,7 +64,10 @@ class AttributesHashMap
6264 * @return check if key is present in hash
6365 *
6466 */
65- bool Has (size_t hash) const { return hash_map_.find (hash) != hash_map_.end (); }
67+ bool Has (const MetricAttributes &attributes) const
68+ {
69+ return hash_map_.find (attributes) != hash_map_.end ();
70+ }
6671
6772 /* *
6873 * @return the pointer to value for given key if present.
@@ -71,108 +76,103 @@ class AttributesHashMap
7176 */
7277 Aggregation *GetOrSetDefault (const opentelemetry::common::KeyValueIterable &attributes,
7378 const AttributesProcessor *attributes_processor,
74- std::function<std::unique_ptr<Aggregation>()> aggregation_callback,
75- size_t hash)
79+ std::function<std::unique_ptr<Aggregation>()> aggregation_callback)
7680 {
77- auto it = hash_map_.find (hash);
81+ // TODO: avoid constructing MetricAttributes from KeyValueIterable for
82+ // hash_map_.find which is a heavy operation
83+ MetricAttributes attr{attributes, attributes_processor};
84+
85+ auto it = hash_map_.find (attr);
7886 if (it != hash_map_.end ())
7987 {
80- return it->second .second . get ();
88+ return it->second .get ();
8189 }
8290
8391 if (IsOverflowAttributes ())
8492 {
8593 return GetOrSetOveflowAttributes (aggregation_callback);
8694 }
8795
88- MetricAttributes attr{attributes, attributes_processor};
89-
90- hash_map_[hash] = {attr, aggregation_callback ()};
91- return hash_map_[hash].second .get ();
96+ auto result = hash_map_.emplace (std::move (attr), aggregation_callback ());
97+ return result.first ->second .get ();
9298 }
9399
94- Aggregation *GetOrSetDefault (std::function<std::unique_ptr<Aggregation>()> aggregation_callback ,
95- size_t hash )
100+ Aggregation *GetOrSetDefault (const MetricAttributes &attributes ,
101+ std::function<std::unique_ptr<Aggregation>()> aggregation_callback )
96102 {
97- auto it = hash_map_.find (hash );
103+ auto it = hash_map_.find (attributes );
98104 if (it != hash_map_.end ())
99105 {
100- return it->second .second . get ();
106+ return it->second .get ();
101107 }
102108
103109 if (IsOverflowAttributes ())
104110 {
105111 return GetOrSetOveflowAttributes (aggregation_callback);
106112 }
107113
108- MetricAttributes attr{};
109- hash_map_[hash] = {attr, aggregation_callback ()};
110- return hash_map_[hash].second .get ();
114+ hash_map_[attributes] = aggregation_callback ();
115+ return hash_map_[attributes].get ();
111116 }
112117
113- Aggregation *GetOrSetDefault (const MetricAttributes &attributes,
114- std::function<std::unique_ptr<Aggregation>()> aggregation_callback,
115- size_t hash)
118+ Aggregation *GetOrSetDefault (MetricAttributes &&attributes,
119+ std::function<std::unique_ptr<Aggregation>()> aggregation_callback)
116120 {
117- auto it = hash_map_.find (hash );
121+ auto it = hash_map_.find (attributes );
118122 if (it != hash_map_.end ())
119123 {
120- return it->second .second . get ();
124+ return it->second .get ();
121125 }
122126
123127 if (IsOverflowAttributes ())
124128 {
125129 return GetOrSetOveflowAttributes (aggregation_callback);
126130 }
127131
128- MetricAttributes attr{attributes};
129-
130- hash_map_[hash] = {attr, aggregation_callback ()};
131- return hash_map_[hash].second .get ();
132+ auto result = hash_map_.emplace (std::move (attributes), aggregation_callback ());
133+ return result.first ->second .get ();
132134 }
133-
134135 /* *
135136 * Set the value for given key, overwriting the value if already present
136137 */
137138 void Set (const opentelemetry::common::KeyValueIterable &attributes,
138139 const AttributesProcessor *attributes_processor,
139- std::unique_ptr<Aggregation> aggr,
140- size_t hash)
140+ std::unique_ptr<Aggregation> aggr)
141+ {
142+ Set (MetricAttributes{attributes, attributes_processor}, std::move (aggr));
143+ }
144+
145+ void Set (const MetricAttributes &attributes, std::unique_ptr<Aggregation> aggr)
141146 {
142- auto it = hash_map_.find (hash );
147+ auto it = hash_map_.find (attributes );
143148 if (it != hash_map_.end ())
144149 {
145- it->second . second = std::move (aggr);
150+ it->second = std::move (aggr);
146151 }
147152 else if (IsOverflowAttributes ())
148153 {
149- hash_map_[kOverflowAttributesHash ] = {
150- MetricAttributes{{kAttributesLimitOverflowKey , kAttributesLimitOverflowValue }},
151- std::move (aggr)};
154+ hash_map_[kOverflowAttributes ] = std::move (aggr);
152155 }
153156 else
154157 {
155- MetricAttributes attr{attributes, attributes_processor};
156- hash_map_[hash] = {attr, std::move (aggr)};
158+ hash_map_[attributes] = std::move (aggr);
157159 }
158160 }
159161
160- void Set (const MetricAttributes &attributes, std::unique_ptr<Aggregation> aggr, size_t hash )
162+ void Set (MetricAttributes && attributes, std::unique_ptr<Aggregation> aggr)
161163 {
162- auto it = hash_map_.find (hash );
164+ auto it = hash_map_.find (attributes );
163165 if (it != hash_map_.end ())
164166 {
165- it->second . second = std::move (aggr);
167+ it->second = std::move (aggr);
166168 }
167169 else if (IsOverflowAttributes ())
168170 {
169- hash_map_[kOverflowAttributesHash ] = {
170- MetricAttributes{{kAttributesLimitOverflowKey , kAttributesLimitOverflowValue }},
171- std::move (aggr)};
171+ hash_map_[kOverflowAttributes ] = std::move (aggr);
172172 }
173173 else
174174 {
175- hash_map_[hash ] = {attributes, std::move (aggr)} ;
175+ hash_map_[std::move (attributes) ] = std::move (aggr);
176176 }
177177 }
178178
@@ -184,7 +184,7 @@ class AttributesHashMap
184184 {
185185 for (auto &kv : hash_map_)
186186 {
187- if (!callback (kv.second . first , *(kv. second .second .get ())))
187+ if (!callback (kv.first , *(kv.second .get ())))
188188 {
189189 return false ; // callback is not prepared to consume data
190190 }
@@ -197,8 +197,13 @@ class AttributesHashMap
197197 */
198198 size_t Size () { return hash_map_.size (); }
199199
200+ #ifdef UNIT_TESTING
201+ size_t BucketCount () { return hash_map_.bucket_count (); }
202+ size_t BucketSize (size_t n) { return hash_map_.bucket_size (n); }
203+ #endif
204+
200205private:
201- std::unordered_map<size_t , std::pair< MetricAttributes, std::unique_ptr<Aggregation>> > hash_map_;
206+ std::unordered_map<MetricAttributes, std::unique_ptr<Aggregation>, CustomHash > hash_map_;
202207 size_t attributes_limit_;
203208
204209 Aggregation *GetOrSetOveflowAttributes (
@@ -210,19 +215,21 @@ class AttributesHashMap
210215
211216 Aggregation *GetOrSetOveflowAttributes (std::unique_ptr<Aggregation> agg)
212217 {
213- auto it = hash_map_.find (kOverflowAttributesHash );
218+ auto it = hash_map_.find (kOverflowAttributes );
214219 if (it != hash_map_.end ())
215220 {
216- return it->second .second . get ();
221+ return it->second .get ();
217222 }
218223
219- MetricAttributes attr{{kAttributesLimitOverflowKey , kAttributesLimitOverflowValue }};
220- hash_map_[kOverflowAttributesHash ] = {attr, std::move (agg)};
221- return hash_map_[kOverflowAttributesHash ].second .get ();
224+ auto result = hash_map_.emplace (kOverflowAttributes , std::move (agg));
225+ return result.first ->second .get ();
222226 }
223227
224228 bool IsOverflowAttributes () const { return (hash_map_.size () + 1 >= attributes_limit_); }
225229};
230+
231+ using AttributesHashMap = AttributesHashMapWithCustomHash<>;
232+
226233} // namespace metrics
227234
228235} // namespace sdk
0 commit comments