Skip to content

Commit d98fa32

Browse files
authored
Merge pull request prometheus#5 from mxinden/protobuf-support-associated-type
src/encoding/proto: Refactor EncodeLabel and EncodeMetric
2 parents da84323 + 87f0e21 commit d98fa32

1 file changed

Lines changed: 79 additions & 75 deletions

File tree

src/encoding/proto.rs

Lines changed: 79 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,10 @@ pub trait EncodeMetric {
8787
fn metric_type(&self) -> MetricType;
8888
}
8989

90-
impl EncodeMetric for Box<dyn EncodeMetric<Iterator = IntoIter<openmetrics_data_model::Metric>>> {
91-
type Iterator = IntoIter<openmetrics_data_model::Metric>;
90+
impl EncodeMetric
91+
for Box<dyn EncodeMetric<Iterator = Box<dyn Iterator<Item = openmetrics_data_model::Metric>>>>
92+
{
93+
type Iterator = Box<dyn Iterator<Item = openmetrics_data_model::Metric>>;
9294

9395
fn encode(&self, labels: Vec<openmetrics_data_model::Label>) -> Self::Iterator {
9496
self.deref().encode(labels)
@@ -104,9 +106,11 @@ pub trait SendEncodeMetric: EncodeMetric + Send {}
104106
impl<T: EncodeMetric + Send> SendEncodeMetric for T {}
105107

106108
impl EncodeMetric
107-
for Box<dyn SendEncodeMetric<Iterator = IntoIter<openmetrics_data_model::Metric>>>
109+
for Box<
110+
dyn SendEncodeMetric<Iterator = Box<dyn Iterator<Item = openmetrics_data_model::Metric>>>,
111+
>
108112
{
109-
type Iterator = IntoIter<openmetrics_data_model::Metric>;
113+
type Iterator = Box<dyn Iterator<Item = openmetrics_data_model::Metric>>;
110114

111115
fn encode(&self, labels: Vec<openmetrics_data_model::Label>) -> Self::Iterator {
112116
self.deref().encode(labels)
@@ -117,59 +121,49 @@ impl EncodeMetric
117121
}
118122
}
119123

124+
// TODO: Rename to EncodeLabels?
120125
pub trait EncodeLabel {
121126
type Iterator: Iterator<Item = openmetrics_data_model::Label>;
122127

123-
fn encode(&self) -> Self::Iterator;
128+
fn encode(self) -> Self::Iterator;
124129
}
125130

126-
impl<K: ToString, V: ToString> EncodeLabel for (K, V) {
127-
type Iterator = IntoIter<openmetrics_data_model::Label>;
128-
129-
fn encode(&self) -> Self::Iterator {
131+
impl<K: ToString, V: ToString> Into<openmetrics_data_model::Label> for &(K, V) {
132+
fn into(self) -> openmetrics_data_model::Label {
130133
let mut label = openmetrics_data_model::Label::default();
131134
label.name = self.0.to_string();
132135
label.value = self.1.to_string();
133-
vec![label].into_iter()
134-
}
135-
}
136-
137-
impl<T: EncodeLabel> EncodeLabel for Vec<T> {
138-
type Iterator = IntoIter<openmetrics_data_model::Label>;
139-
140-
fn encode(&self) -> Self::Iterator {
141-
self.iter()
142-
.map(|t| t.encode())
143-
.flatten()
144-
.collect::<Vec<_>>()
145-
.into_iter()
136+
label
146137
}
147138
}
148139

149-
impl<T: EncodeLabel> EncodeLabel for &[T] {
150-
type Iterator = IntoIter<openmetrics_data_model::Label>;
140+
// TODO: Is this needed? We already have `&'a [T]` below.
141+
impl<'a, T> EncodeLabel for &'a Vec<T>
142+
where
143+
for<'b> &'b T: Into<openmetrics_data_model::Label>,
144+
{
145+
type Iterator = Box<dyn Iterator<Item = openmetrics_data_model::Label> + 'a>;
151146

152-
fn encode(&self) -> Self::Iterator {
153-
self.iter()
154-
.map(|t| t.encode())
155-
.flatten()
156-
.collect::<Vec<_>>()
157-
.into_iter()
147+
fn encode(self) -> Self::Iterator {
148+
Box::new(self.iter().map(|t| t.into()))
158149
}
159150
}
160151

161-
impl EncodeLabel for () {
162-
type Iterator = IntoIter<openmetrics_data_model::Label>;
152+
impl<'a, T> EncodeLabel for &'a [T]
153+
where
154+
for<'b> &'b T: Into<openmetrics_data_model::Label>,
155+
{
156+
type Iterator = Box<dyn Iterator<Item = openmetrics_data_model::Label> + 'a>;
163157

164-
fn encode(&self) -> Self::Iterator {
165-
vec![].into_iter()
158+
fn encode(self) -> Self::Iterator {
159+
Box::new(self.iter().map(|t| t.into()))
166160
}
167161
}
168162

169163
fn encode_exemplar<S, N>(exemplar: &Exemplar<S, N>) -> openmetrics_data_model::Exemplar
170164
where
171165
N: Clone,
172-
S: EncodeLabel,
166+
for<'a> &'a S: EncodeLabel,
173167
f64: From<N>, // required because Exemplar.value is defined as `double` in protobuf
174168
{
175169
let mut exemplar_proto = openmetrics_data_model::Exemplar::default();
@@ -203,28 +197,28 @@ where
203197
N: EncodeCounterValue,
204198
A: counter::Atomic<N>,
205199
{
206-
type Iterator = IntoIter<openmetrics_data_model::Metric>;
200+
type Iterator = std::iter::Once<openmetrics_data_model::Metric>;
207201

208202
fn encode(&self, labels: Vec<openmetrics_data_model::Label>) -> Self::Iterator {
209203
let mut metric = encode_counter_with_maybe_exemplar(self.get(), None);
210204
metric.labels = labels;
211205

212-
vec![metric].into_iter()
206+
std::iter::once(metric)
213207
}
214208

215209
fn metric_type(&self) -> MetricType {
216210
Self::TYPE
217211
}
218212
}
219213

220-
impl<S, N, A> EncodeMetric for CounterWithExemplar<S, N, A>
214+
impl<'a, S, N, A> EncodeMetric for CounterWithExemplar<S, N, A>
221215
where
222-
S: EncodeLabel,
216+
for<'b> &'b S: EncodeLabel,
223217
N: Clone + EncodeCounterValue,
224218
A: counter::Atomic<N>,
225219
f64: From<N>,
226220
{
227-
type Iterator = IntoIter<openmetrics_data_model::Metric>;
221+
type Iterator = std::iter::Once<openmetrics_data_model::Metric>;
228222

229223
fn encode(&self, labels: Vec<openmetrics_data_model::Label>) -> Self::Iterator {
230224
let (value, exemplar) = self.get();
@@ -238,7 +232,7 @@ where
238232
let mut metric = encode_counter_with_maybe_exemplar(value.clone(), exemplar_proto);
239233
metric.labels = labels;
240234

241-
vec![metric].into_iter()
235+
std::iter::once(metric)
242236
}
243237

244238
fn metric_type(&self) -> MetricType {
@@ -293,12 +287,12 @@ impl EncodeGaugeValue for f64 {
293287
}
294288
}
295289

296-
impl<N, A> EncodeMetric for Gauge<N, A>
290+
impl<'a, N, A> EncodeMetric for Gauge<N, A>
297291
where
298292
N: EncodeGaugeValue,
299293
A: gauge::Atomic<N>,
300294
{
301-
type Iterator = IntoIter<openmetrics_data_model::Metric>;
295+
type Iterator = std::iter::Once<openmetrics_data_model::Metric>;
302296

303297
fn encode(&self, labels: Vec<openmetrics_data_model::Label>) -> Self::Iterator {
304298
let mut metric = openmetrics_data_model::Metric::default();
@@ -318,7 +312,7 @@ where
318312
};
319313

320314
metric.labels = labels;
321-
vec![metric].into_iter()
315+
std::iter::once(metric)
322316
}
323317

324318
fn metric_type(&self) -> MetricType {
@@ -329,25 +323,30 @@ where
329323
/////////////////////////////////////////////////////////////////////////////////
330324
// Family
331325

332-
impl<S, M, C> EncodeMetric for Family<S, M, C>
326+
impl<'c, S, M, C> EncodeMetric for Family<S, M, C>
333327
where
334-
S: Clone + std::hash::Hash + Eq + EncodeLabel,
328+
S: Clone + std::hash::Hash + Eq,
329+
for<'b> &'b S: EncodeLabel,
335330
M: EncodeMetric + TypedMetric,
336331
C: MetricConstructor<M>,
337332
{
338333
type Iterator = IntoIter<openmetrics_data_model::Metric>;
339334

340335
fn encode(&self, labels: Vec<openmetrics_data_model::Label>) -> Self::Iterator {
341-
let mut metrics = vec![];
342-
343-
let guard = self.read();
344-
for (label_set, metric) in guard.iter() {
345-
let mut label = label_set.encode().collect::<Vec<_>>();
346-
label.append(&mut labels.clone());
347-
metrics.extend(metric.encode(label));
348-
}
349-
350-
metrics.into_iter()
336+
self.read()
337+
.iter()
338+
.map(|(label_set, metric)| {
339+
let mut labels = labels.clone();
340+
labels.extend(label_set.encode());
341+
metric.encode(labels)
342+
})
343+
.flatten()
344+
// TODO: Ideally we would not have to collect into a vector here,
345+
// though we have to as we borrow from the `MutexGuard`. Once
346+
// https://github.com/prometheus/client_rust/pull/78/ merged, we
347+
// might be able to leverage `MutexGuard::map`.
348+
.collect::<Vec<_>>()
349+
.into_iter()
351350
}
352351

353352
fn metric_type(&self) -> MetricType {
@@ -359,14 +358,17 @@ where
359358
// Histogram
360359

361360
impl EncodeMetric for Histogram {
362-
type Iterator = IntoIter<openmetrics_data_model::Metric>;
361+
type Iterator = std::iter::Once<openmetrics_data_model::Metric>;
363362

364363
fn encode(&self, labels: Vec<openmetrics_data_model::Label>) -> Self::Iterator {
365364
let (sum, count, buckets) = self.get();
366365
// TODO: Would be better to use never type instead of `()`.
367-
let mut metric = encode_histogram_with_maybe_exemplars::<()>(sum, count, &buckets, None);
366+
// TODO: Revert (String, String)?
367+
let mut metric = encode_histogram_with_maybe_exemplars::<Vec<(String, String)>>(
368+
sum, count, &buckets, None,
369+
);
368370
metric.labels = labels;
369-
vec![metric].into_iter()
371+
std::iter::once(metric)
370372
}
371373

372374
fn metric_type(&self) -> MetricType {
@@ -376,30 +378,33 @@ impl EncodeMetric for Histogram {
376378

377379
impl<S> EncodeMetric for HistogramWithExemplars<S>
378380
where
379-
S: EncodeLabel,
381+
for<'b> &'b S: EncodeLabel,
380382
{
381-
type Iterator = IntoIter<openmetrics_data_model::Metric>;
383+
type Iterator = std::iter::Once<openmetrics_data_model::Metric>;
382384

383385
fn encode(&self, labels: Vec<openmetrics_data_model::Label>) -> Self::Iterator {
384386
let inner = self.inner();
385387
let (sum, count, buckets) = inner.histogram.get();
386388
let mut metric =
387389
encode_histogram_with_maybe_exemplars(sum, count, &buckets, Some(&inner.exemplars));
388390
metric.labels = labels;
389-
vec![metric].into_iter()
391+
std::iter::once(metric)
390392
}
391393

392394
fn metric_type(&self) -> MetricType {
393395
Histogram::TYPE
394396
}
395397
}
396398

397-
fn encode_histogram_with_maybe_exemplars<S: EncodeLabel>(
399+
fn encode_histogram_with_maybe_exemplars<'a, S>(
398400
sum: f64,
399401
count: u64,
400402
buckets: &[(f64, u64)],
401-
exemplars: Option<&HashMap<usize, Exemplar<S, f64>>>,
402-
) -> openmetrics_data_model::Metric {
403+
exemplars: Option<&'a HashMap<usize, Exemplar<S, f64>>>,
404+
) -> openmetrics_data_model::Metric
405+
where
406+
for<'b> &'b S: EncodeLabel,
407+
{
403408
let mut metric = openmetrics_data_model::Metric::default();
404409

405410
metric.metric_points = {
@@ -439,21 +444,20 @@ fn encode_histogram_with_maybe_exemplars<S: EncodeLabel>(
439444

440445
impl<S> EncodeMetric for Info<S>
441446
where
442-
S: EncodeLabel,
447+
for<'b> &'b S: EncodeLabel,
443448
{
444-
type Iterator = IntoIter<openmetrics_data_model::Metric>;
449+
type Iterator = std::iter::Once<openmetrics_data_model::Metric>;
445450

446-
fn encode(&self, labels: Vec<openmetrics_data_model::Label>) -> Self::Iterator {
451+
fn encode(&self, mut labels: Vec<openmetrics_data_model::Label>) -> Self::Iterator {
447452
let mut metric = openmetrics_data_model::Metric::default();
448453

449454
metric.metric_points = {
450455
let mut metric_point = openmetrics_data_model::MetricPoint::default();
451456
metric_point.value = {
452-
let mut label = self.0.encode().collect::<Vec<_>>();
453-
label.append(&mut labels.clone());
457+
labels.extend(self.0.encode());
454458

455459
let mut info_value = openmetrics_data_model::InfoValue::default();
456-
info_value.info = label;
460+
info_value.info = labels;
457461

458462
Some(openmetrics_data_model::metric_point::Value::InfoValue(
459463
info_value,
@@ -463,7 +467,7 @@ where
463467
vec![metric_point]
464468
};
465469

466-
vec![metric].into_iter()
470+
std::iter::once(metric)
467471
}
468472

469473
fn metric_type(&self) -> MetricType {
@@ -562,15 +566,15 @@ mod tests {
562566
fn encode_counter_with_exemplar() {
563567
let mut registry = Registry::default();
564568

565-
let counter_with_exemplar: CounterWithExemplar<(String, f64), f64> =
569+
let counter_with_exemplar: CounterWithExemplar<Vec<(String, f64)>, f64> =
566570
CounterWithExemplar::default();
567571
registry.register(
568572
"my_counter_with_exemplar",
569573
"My counter with exemplar",
570574
counter_with_exemplar.clone(),
571575
);
572576

573-
counter_with_exemplar.inc_by(1.0, Some(("user_id".to_string(), 42.0)));
577+
counter_with_exemplar.inc_by(1.0, Some(vec![("user_id".to_string(), 42.0)]));
574578

575579
let metric_set = encode(&registry);
576580

@@ -757,7 +761,7 @@ mod tests {
757761
let mut registry = Registry::default();
758762
let histogram = HistogramWithExemplars::new(exponential_buckets(1.0, 2.0, 10));
759763
registry.register("my_histogram", "My histogram", histogram.clone());
760-
histogram.observe(1.0, Some(("user_id".to_string(), 42u64)));
764+
histogram.observe(1.0, Some(vec![("user_id".to_string(), 42u64)]));
761765

762766
let metric_set = encode(&registry);
763767

0 commit comments

Comments
 (0)