15
15
#include " opentelemetry/sdk/common/attribute_utils.h"
16
16
#include " opentelemetry/sdk/common/attributemap_hash.h"
17
17
#include " opentelemetry/sdk/metrics/aggregation/aggregation.h"
18
+ #include " opentelemetry/sdk/metrics/state/filtered_ordered_attribute_map.h"
18
19
#include " opentelemetry/sdk/metrics/view/attributes_processor.h"
19
20
#include " opentelemetry/version.h"
20
21
@@ -29,9 +30,9 @@ using opentelemetry::sdk::common::OrderedAttributeMap;
29
30
constexpr size_t kAggregationCardinalityLimit = 2000 ;
30
31
const std::string kAttributesLimitOverflowKey = " otel.metrics.overflow" ;
31
32
const 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
35
36
36
37
class AttributeHashGenerator
37
38
{
@@ -42,18 +43,19 @@ class AttributeHashGenerator
42
43
}
43
44
};
44
45
45
- class AttributesHashMap
46
+ template <typename CustomHash = MetricAttributesHash>
47
+ class AttributesHashMapWithCustomHash
46
48
{
47
49
public:
48
- AttributesHashMap (size_t attributes_limit = kAggregationCardinalityLimit )
50
+ AttributesHashMapWithCustomHash (size_t attributes_limit = kAggregationCardinalityLimit )
49
51
: attributes_limit_(attributes_limit)
50
52
{}
51
- Aggregation *Get (size_t hash ) const
53
+ Aggregation *Get (const MetricAttributes &attributes ) const
52
54
{
53
- auto it = hash_map_.find (hash );
55
+ auto it = hash_map_.find (attributes );
54
56
if (it != hash_map_.end ())
55
57
{
56
- return it->second .second . get ();
58
+ return it->second .get ();
57
59
}
58
60
return nullptr ;
59
61
}
@@ -62,7 +64,10 @@ class AttributesHashMap
62
64
* @return check if key is present in hash
63
65
*
64
66
*/
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
+ }
66
71
67
72
/* *
68
73
* @return the pointer to value for given key if present.
@@ -71,108 +76,103 @@ class AttributesHashMap
71
76
*/
72
77
Aggregation *GetOrSetDefault (const opentelemetry::common::KeyValueIterable &attributes,
73
78
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)
76
80
{
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);
78
86
if (it != hash_map_.end ())
79
87
{
80
- return it->second .second . get ();
88
+ return it->second .get ();
81
89
}
82
90
83
91
if (IsOverflowAttributes ())
84
92
{
85
93
return GetOrSetOveflowAttributes (aggregation_callback);
86
94
}
87
95
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 ();
92
98
}
93
99
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 )
96
102
{
97
- auto it = hash_map_.find (hash );
103
+ auto it = hash_map_.find (attributes );
98
104
if (it != hash_map_.end ())
99
105
{
100
- return it->second .second . get ();
106
+ return it->second .get ();
101
107
}
102
108
103
109
if (IsOverflowAttributes ())
104
110
{
105
111
return GetOrSetOveflowAttributes (aggregation_callback);
106
112
}
107
113
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 ();
111
116
}
112
117
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)
116
120
{
117
- auto it = hash_map_.find (hash );
121
+ auto it = hash_map_.find (attributes );
118
122
if (it != hash_map_.end ())
119
123
{
120
- return it->second .second . get ();
124
+ return it->second .get ();
121
125
}
122
126
123
127
if (IsOverflowAttributes ())
124
128
{
125
129
return GetOrSetOveflowAttributes (aggregation_callback);
126
130
}
127
131
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 ();
132
134
}
133
-
134
135
/* *
135
136
* Set the value for given key, overwriting the value if already present
136
137
*/
137
138
void Set (const opentelemetry::common::KeyValueIterable &attributes,
138
139
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)
141
146
{
142
- auto it = hash_map_.find (hash );
147
+ auto it = hash_map_.find (attributes );
143
148
if (it != hash_map_.end ())
144
149
{
145
- it->second . second = std::move (aggr);
150
+ it->second = std::move (aggr);
146
151
}
147
152
else if (IsOverflowAttributes ())
148
153
{
149
- hash_map_[kOverflowAttributesHash ] = {
150
- MetricAttributes{{kAttributesLimitOverflowKey , kAttributesLimitOverflowValue }},
151
- std::move (aggr)};
154
+ hash_map_[kOverflowAttributes ] = std::move (aggr);
152
155
}
153
156
else
154
157
{
155
- MetricAttributes attr{attributes, attributes_processor};
156
- hash_map_[hash] = {attr, std::move (aggr)};
158
+ hash_map_[attributes] = std::move (aggr);
157
159
}
158
160
}
159
161
160
- void Set (const MetricAttributes &attributes, std::unique_ptr<Aggregation> aggr, size_t hash )
162
+ void Set (MetricAttributes && attributes, std::unique_ptr<Aggregation> aggr)
161
163
{
162
- auto it = hash_map_.find (hash );
164
+ auto it = hash_map_.find (attributes );
163
165
if (it != hash_map_.end ())
164
166
{
165
- it->second . second = std::move (aggr);
167
+ it->second = std::move (aggr);
166
168
}
167
169
else if (IsOverflowAttributes ())
168
170
{
169
- hash_map_[kOverflowAttributesHash ] = {
170
- MetricAttributes{{kAttributesLimitOverflowKey , kAttributesLimitOverflowValue }},
171
- std::move (aggr)};
171
+ hash_map_[kOverflowAttributes ] = std::move (aggr);
172
172
}
173
173
else
174
174
{
175
- hash_map_[hash ] = {attributes, std::move (aggr)} ;
175
+ hash_map_[std::move (attributes) ] = std::move (aggr);
176
176
}
177
177
}
178
178
@@ -184,7 +184,7 @@ class AttributesHashMap
184
184
{
185
185
for (auto &kv : hash_map_)
186
186
{
187
- if (!callback (kv.second . first , *(kv. second .second .get ())))
187
+ if (!callback (kv.first , *(kv.second .get ())))
188
188
{
189
189
return false ; // callback is not prepared to consume data
190
190
}
@@ -197,8 +197,13 @@ class AttributesHashMap
197
197
*/
198
198
size_t Size () { return hash_map_.size (); }
199
199
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
+
200
205
private:
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_;
202
207
size_t attributes_limit_;
203
208
204
209
Aggregation *GetOrSetOveflowAttributes (
@@ -210,19 +215,21 @@ class AttributesHashMap
210
215
211
216
Aggregation *GetOrSetOveflowAttributes (std::unique_ptr<Aggregation> agg)
212
217
{
213
- auto it = hash_map_.find (kOverflowAttributesHash );
218
+ auto it = hash_map_.find (kOverflowAttributes );
214
219
if (it != hash_map_.end ())
215
220
{
216
- return it->second .second . get ();
221
+ return it->second .get ();
217
222
}
218
223
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 ();
222
226
}
223
227
224
228
bool IsOverflowAttributes () const { return (hash_map_.size () + 1 >= attributes_limit_); }
225
229
};
230
+
231
+ using AttributesHashMap = AttributesHashMapWithCustomHash<>;
232
+
226
233
} // namespace metrics
227
234
228
235
} // namespace sdk
0 commit comments