Skip to content

Commit 606a3cd

Browse files
authored
Update Histogram Builder (#2130)
1 parent 26b3320 commit 606a3cd

File tree

5 files changed

+159
-83
lines changed

5 files changed

+159
-83
lines changed

opentelemetry-sdk/src/metrics/meter.rs

Lines changed: 45 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ use std::{borrow::Cow, sync::Arc};
44
use opentelemetry::{
55
global,
66
metrics::{
7-
noop::NoopAsyncInstrument, Callback, Counter, Gauge, Histogram, InstrumentProvider,
8-
MetricsError, ObservableCounter, ObservableGauge, ObservableUpDownCounter, Result,
9-
UpDownCounter,
7+
noop::NoopAsyncInstrument, Callback, Counter, Gauge, Histogram, HistogramBuilder,
8+
InstrumentProvider, MetricsError, ObservableCounter, ObservableGauge,
9+
ObservableUpDownCounter, Result, UpDownCounter,
1010
},
1111
};
1212

@@ -373,28 +373,28 @@ impl InstrumentProvider for SdkMeter {
373373
Ok(ObservableGauge::new(observable))
374374
}
375375

376-
fn f64_histogram(
377-
&self,
378-
name: Cow<'static, str>,
379-
description: Option<Cow<'static, str>>,
380-
unit: Option<Cow<'static, str>>,
381-
) -> Result<Histogram<f64>> {
382-
validate_instrument_config(name.as_ref(), &unit, self.validation_policy)?;
376+
fn f64_histogram(&self, builder: HistogramBuilder<'_, f64>) -> Result<Histogram<f64>> {
377+
validate_instrument_config(builder.name.as_ref(), &builder.unit, self.validation_policy)?;
383378
let p = InstrumentResolver::new(self, &self.f64_resolver);
384-
p.lookup(InstrumentKind::Histogram, name, description, unit)
385-
.map(|i| Histogram::new(Arc::new(i)))
379+
p.lookup(
380+
InstrumentKind::Histogram,
381+
builder.name,
382+
builder.description,
383+
builder.unit,
384+
)
385+
.map(|i| Histogram::new(Arc::new(i)))
386386
}
387387

388-
fn u64_histogram(
389-
&self,
390-
name: Cow<'static, str>,
391-
description: Option<Cow<'static, str>>,
392-
unit: Option<Cow<'static, str>>,
393-
) -> Result<Histogram<u64>> {
394-
validate_instrument_config(name.as_ref(), &unit, self.validation_policy)?;
388+
fn u64_histogram(&self, builder: HistogramBuilder<'_, u64>) -> Result<Histogram<u64>> {
389+
validate_instrument_config(builder.name.as_ref(), &builder.unit, self.validation_policy)?;
395390
let p = InstrumentResolver::new(self, &self.u64_resolver);
396-
p.lookup(InstrumentKind::Histogram, name, description, unit)
397-
.map(|i| Histogram::new(Arc::new(i)))
391+
p.lookup(
392+
InstrumentKind::Histogram,
393+
builder.name,
394+
builder.description,
395+
builder.unit,
396+
)
397+
.map(|i| Histogram::new(Arc::new(i)))
398398
}
399399
}
400400

@@ -524,7 +524,10 @@ where
524524
mod tests {
525525
use std::sync::Arc;
526526

527-
use opentelemetry::metrics::{InstrumentProvider, MeterProvider, MetricsError};
527+
use opentelemetry::{
528+
global,
529+
metrics::{InstrumentProvider, MeterProvider, MetricsError},
530+
};
528531

529532
use super::{
530533
InstrumentValidationPolicy, SdkMeter, INSTRUMENT_NAME_FIRST_ALPHABETIC,
@@ -629,8 +632,14 @@ mod tests {
629632
.f64_observable_gauge(name.into(), None, None, Vec::new())
630633
.map(|_| ()),
631634
);
632-
assert(meter.f64_histogram(name.into(), None, None).map(|_| ()));
633-
assert(meter.u64_histogram(name.into(), None, None).map(|_| ()));
635+
636+
// Get handle to HistogramBuilder for testing
637+
let global_meter = global::meter("test");
638+
let histogram_builder_f64 = global_meter.f64_histogram(name);
639+
let histogram_builder_u64 = global_meter.u64_histogram(name);
640+
641+
assert(meter.f64_histogram(histogram_builder_f64).map(|_| ()));
642+
assert(meter.u64_histogram(histogram_builder_u64).map(|_| ()));
634643
}
635644

636645
// (unit, expected error)
@@ -713,16 +722,18 @@ mod tests {
713722
.f64_observable_gauge("test".into(), None, unit.clone(), Vec::new())
714723
.map(|_| ()),
715724
);
716-
assert(
717-
meter
718-
.f64_histogram("test".into(), None, unit.clone())
719-
.map(|_| ()),
720-
);
721-
assert(
722-
meter
723-
.u64_histogram("test".into(), None, unit.clone())
724-
.map(|_| ()),
725-
);
725+
726+
// Get handle to HistogramBuilder for testing
727+
let global_meter = global::meter("test");
728+
let histogram_builder_f64 = global_meter
729+
.f64_histogram("test")
730+
.with_unit(unit.clone().unwrap());
731+
let histogram_builder_u64 = global_meter
732+
.u64_histogram("test")
733+
.with_unit(unit.clone().unwrap());
734+
735+
assert(meter.f64_histogram(histogram_builder_f64).map(|_| ()));
736+
assert(meter.u64_histogram(histogram_builder_u64).map(|_| ()));
726737
}
727738
}
728739
}

opentelemetry/src/metrics/instruments/histogram.rs

Lines changed: 1 addition & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
1-
use crate::{
2-
metrics::{InstrumentBuilder, MetricsError},
3-
KeyValue,
4-
};
1+
use crate::KeyValue;
52
use core::fmt;
63
use std::sync::Arc;
74

@@ -35,23 +32,3 @@ impl<T> Histogram<T> {
3532
self.0.record(value, attributes)
3633
}
3734
}
38-
39-
impl TryFrom<InstrumentBuilder<'_, Histogram<f64>>> for Histogram<f64> {
40-
type Error = MetricsError;
41-
42-
fn try_from(builder: InstrumentBuilder<'_, Histogram<f64>>) -> Result<Self, Self::Error> {
43-
builder
44-
.instrument_provider
45-
.f64_histogram(builder.name, builder.description, builder.unit)
46-
}
47-
}
48-
49-
impl TryFrom<InstrumentBuilder<'_, Histogram<u64>>> for Histogram<u64> {
50-
type Error = MetricsError;
51-
52-
fn try_from(builder: InstrumentBuilder<'_, Histogram<u64>>) -> Result<Self, Self::Error> {
53-
builder
54-
.instrument_provider
55-
.u64_histogram(builder.name, builder.description, builder.unit)
56-
}
57-
}

opentelemetry/src/metrics/instruments/mod.rs

Lines changed: 103 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::borrow::Cow;
66
use std::marker;
77
use std::sync::Arc;
88

9-
use super::InstrumentProvider;
9+
use super::{Histogram, InstrumentProvider};
1010

1111
pub(super) mod counter;
1212
pub(super) mod gauge;
@@ -24,6 +24,94 @@ pub trait AsyncInstrument<T>: Send + Sync {
2424
fn as_any(&self) -> Arc<dyn Any>;
2525
}
2626

27+
/// Configuration for building a Histogram.
28+
#[non_exhaustive]
29+
pub struct HistogramBuilder<'a, T> {
30+
/// Instrument provider is used to create the instrument.
31+
pub instrument_provider: &'a dyn InstrumentProvider,
32+
33+
/// Name of the Histogram.
34+
pub name: Cow<'static, str>,
35+
36+
/// Description of the Histogram.
37+
pub description: Option<Cow<'static, str>>,
38+
39+
/// Unit of the Histogram.
40+
pub unit: Option<Cow<'static, str>>,
41+
42+
// boundaries: Vec<T>,
43+
_marker: marker::PhantomData<T>,
44+
}
45+
46+
impl<'a, T> HistogramBuilder<'a, T> {
47+
/// Create a new instrument builder
48+
pub(crate) fn new(meter: &'a Meter, name: Cow<'static, str>) -> Self {
49+
HistogramBuilder {
50+
instrument_provider: meter.instrument_provider.as_ref(),
51+
name,
52+
description: None,
53+
unit: None,
54+
_marker: marker::PhantomData,
55+
}
56+
}
57+
58+
/// Set the description for this instrument
59+
pub fn with_description<S: Into<Cow<'static, str>>>(mut self, description: S) -> Self {
60+
self.description = Some(description.into());
61+
self
62+
}
63+
64+
/// Set the unit for this instrument.
65+
///
66+
/// Unit is case sensitive(`kb` is not the same as `kB`).
67+
///
68+
/// Unit must be:
69+
/// - ASCII string
70+
/// - No longer than 63 characters
71+
pub fn with_unit<S: Into<Cow<'static, str>>>(mut self, unit: S) -> Self {
72+
self.unit = Some(unit.into());
73+
self
74+
}
75+
}
76+
77+
impl<'a> HistogramBuilder<'a, f64> {
78+
/// Validate the instrument configuration and creates a new instrument.
79+
pub fn try_init(self) -> Result<Histogram<f64>> {
80+
self.instrument_provider.f64_histogram(self)
81+
}
82+
83+
/// Creates a new instrument.
84+
///
85+
/// Validate the instrument configuration and crates a new instrument.
86+
///
87+
/// # Panics
88+
///
89+
/// Panics if the instrument cannot be created. Use
90+
/// [`try_init`](InstrumentBuilder::try_init) if you want to handle errors.
91+
pub fn init(self) -> Histogram<f64> {
92+
self.try_init().unwrap()
93+
}
94+
}
95+
96+
impl<'a> HistogramBuilder<'a, u64> {
97+
/// Validate the instrument configuration and creates a new instrument.
98+
pub fn try_init(self) -> Result<Histogram<u64>> {
99+
self.instrument_provider.u64_histogram(self)
100+
}
101+
102+
/// Creates a new instrument.
103+
///
104+
/// Validate the instrument configuration and crates a new instrument.
105+
///
106+
/// # Panics
107+
///
108+
/// Panics if the instrument cannot be created. Use
109+
/// [`try_init`](InstrumentBuilder::try_init) if you want to handle errors.
110+
pub fn init(self) -> Histogram<u64> {
111+
self.try_init().unwrap()
112+
}
113+
}
114+
27115
/// Configuration for building a sync instrument.
28116
pub struct InstrumentBuilder<'a, T> {
29117
instrument_provider: &'a dyn InstrumentProvider,
@@ -95,6 +183,20 @@ impl<T> fmt::Debug for InstrumentBuilder<'_, T> {
95183
}
96184
}
97185

186+
impl<T> fmt::Debug for HistogramBuilder<'_, T> {
187+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
188+
f.debug_struct("HistogramBuilder")
189+
.field("name", &self.name)
190+
.field("description", &self.description)
191+
.field("unit", &self.unit)
192+
.field(
193+
"kind",
194+
&format!("Histogram<{}>", &std::any::type_name::<T>()),
195+
)
196+
.finish()
197+
}
198+
}
199+
98200
/// A function registered with a [Meter] that makes observations for the
99201
/// instruments it is registered with.
100202
///

opentelemetry/src/metrics/meter.rs

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@ use std::borrow::Cow;
33
use std::sync::Arc;
44

55
use crate::metrics::{
6-
AsyncInstrumentBuilder, Counter, Gauge, Histogram, InstrumentBuilder, InstrumentProvider,
6+
AsyncInstrumentBuilder, Counter, Gauge, InstrumentBuilder, InstrumentProvider,
77
ObservableCounter, ObservableGauge, ObservableUpDownCounter, UpDownCounter,
88
};
99
use crate::KeyValue;
1010

11+
use super::HistogramBuilder;
12+
1113
/// Provides access to named [Meter] instances, for instrumenting an application
1214
/// or crate.
1315
pub trait MeterProvider {
@@ -385,19 +387,13 @@ impl Meter {
385387
}
386388

387389
/// creates an instrument builder for recording a distribution of values.
388-
pub fn f64_histogram(
389-
&self,
390-
name: impl Into<Cow<'static, str>>,
391-
) -> InstrumentBuilder<'_, Histogram<f64>> {
392-
InstrumentBuilder::new(self, name.into())
390+
pub fn f64_histogram(&self, name: impl Into<Cow<'static, str>>) -> HistogramBuilder<'_, f64> {
391+
HistogramBuilder::new(self, name.into())
393392
}
394393

395394
/// creates an instrument builder for recording a distribution of values.
396-
pub fn u64_histogram(
397-
&self,
398-
name: impl Into<Cow<'static, str>>,
399-
) -> InstrumentBuilder<'_, Histogram<u64>> {
400-
InstrumentBuilder::new(self, name.into())
395+
pub fn u64_histogram(&self, name: impl Into<Cow<'static, str>>) -> HistogramBuilder<'_, u64> {
396+
HistogramBuilder::new(self, name.into())
401397
}
402398
}
403399

opentelemetry/src/metrics/mod.rs

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ pub use instruments::{
1717
gauge::{Gauge, ObservableGauge, SyncGauge},
1818
histogram::{Histogram, SyncHistogram},
1919
up_down_counter::{ObservableUpDownCounter, SyncUpDownCounter, UpDownCounter},
20-
AsyncInstrument, AsyncInstrumentBuilder, Callback, InstrumentBuilder,
20+
AsyncInstrument, AsyncInstrumentBuilder, Callback, HistogramBuilder, InstrumentBuilder,
2121
};
2222
pub use meter::{Meter, MeterProvider};
2323

@@ -273,22 +273,12 @@ pub trait InstrumentProvider {
273273
}
274274

275275
/// creates an instrument for recording a distribution of values.
276-
fn f64_histogram(
277-
&self,
278-
_name: Cow<'static, str>,
279-
_description: Option<Cow<'static, str>>,
280-
_unit: Option<Cow<'static, str>>,
281-
) -> Result<Histogram<f64>> {
276+
fn f64_histogram(&self, _builder: HistogramBuilder<'_, f64>) -> Result<Histogram<f64>> {
282277
Ok(Histogram::new(Arc::new(noop::NoopSyncInstrument::new())))
283278
}
284279

285280
/// creates an instrument for recording a distribution of values.
286-
fn u64_histogram(
287-
&self,
288-
_name: Cow<'static, str>,
289-
_description: Option<Cow<'static, str>>,
290-
_unit: Option<Cow<'static, str>>,
291-
) -> Result<Histogram<u64>> {
281+
fn u64_histogram(&self, _builder: HistogramBuilder<'_, u64>) -> Result<Histogram<u64>> {
292282
Ok(Histogram::new(Arc::new(noop::NoopSyncInstrument::new())))
293283
}
294284
}

0 commit comments

Comments
 (0)