Skip to content

Commit 8f4fe23

Browse files
authored
fix: Avoid exposing HistogramBuckets and bounds (#2969)
1 parent fed6fee commit 8f4fe23

File tree

4 files changed

+39
-17
lines changed

4 files changed

+39
-17
lines changed

opentelemetry-proto/src/transform/metrics.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -215,8 +215,8 @@ pub mod tonic {
215215
time_unix_nano: to_nanos(hist.time),
216216
count: dp.count,
217217
sum: Some(dp.sum.into_f64()),
218-
bucket_counts: dp.bucket_counts.clone(),
219-
explicit_bounds: dp.bounds.clone(),
218+
bucket_counts: dp.bucket_counts().collect(),
219+
explicit_bounds: dp.bounds().collect(),
220220
exemplars: dp.exemplars().map(Into::into).collect(),
221221
flags: TonicDataPointFlags::default() as u32,
222222
min: dp.min.map(Numeric::into_f64),

opentelemetry-sdk/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ also modified to suppress telemetry before invoking exporters.
6161
- `Exemplar` no longer exposes `filtered_attributes` field, but instead
6262
offers `filtered_attributes()` method that returns an iterator over
6363
the same.
64+
- `HistogramDataPoint` no longer exposes `bounds` and `bucket_counts`, but
65+
instead offers `bounds()` and `bucket_counts()` methods that returns an
66+
iterator over the same.
6467

6568
## 0.29.0
6669

opentelemetry-sdk/src/metrics/data/mod.rs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ impl<T> GaugeDataPoint<T> {
148148
self.attributes.iter()
149149
}
150150

151-
/// Returns an iterator over the exemplars in [GaugeDataPoint].
151+
/// Returns an iterator over the [Exemplar]s in [GaugeDataPoint].
152152
pub fn exemplars(&self) -> impl Iterator<Item = &Exemplar<T>> {
153153
self.exemplars.iter()
154154
}
@@ -190,7 +190,7 @@ impl<T> SumDataPoint<T> {
190190
self.attributes.iter()
191191
}
192192

193-
/// Returns an iterator over the exemplars in [SumDataPoint].
193+
/// Returns an iterator over the [Exemplar]s in [SumDataPoint].
194194
pub fn exemplars(&self) -> impl Iterator<Item = &Exemplar<T>> {
195195
self.exemplars.iter()
196196
}
@@ -250,9 +250,9 @@ pub struct HistogramDataPoint<T> {
250250
/// The upper bounds of the buckets of the histogram.
251251
///
252252
/// Because the last boundary is +infinity this one is implied.
253-
pub bounds: Vec<f64>,
253+
pub(crate) bounds: Vec<f64>,
254254
/// The count of each of the buckets.
255-
pub bucket_counts: Vec<u64>,
255+
pub(crate) bucket_counts: Vec<u64>,
256256

257257
/// The minimum value recorded.
258258
pub min: Option<T>,
@@ -275,6 +275,16 @@ impl<T> HistogramDataPoint<T> {
275275
pub fn exemplars(&self) -> impl Iterator<Item = &Exemplar<T>> {
276276
self.exemplars.iter()
277277
}
278+
279+
/// Returns an iterator over the bucket boundaries in [HistogramDataPoint].
280+
pub fn bounds(&self) -> impl Iterator<Item = f64> + '_ {
281+
self.bounds.iter().copied()
282+
}
283+
284+
/// Returns an iterator over the bucket counts in [HistogramDataPoint].
285+
pub fn bucket_counts(&self) -> impl Iterator<Item = u64> + '_ {
286+
self.bucket_counts.iter().copied()
287+
}
278288
}
279289

280290
/// The histogram of all measurements of values from an instrument.

opentelemetry-stdout/src/metrics/exporter.rs

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -242,19 +242,28 @@ fn print_hist_data_points<'a, T: Debug + 'a>(
242242
println!("\t\t\t\t -> {}: {}", kv.key, kv.value.as_str());
243243
}
244244

245-
if !data_point.bucket_counts.is_empty() {
246-
println!("\t\t\tBuckets");
247-
let mut lower_bound = f64::NEG_INFINITY;
248-
for (i, &upper_bound) in data_point.bounds.iter().enumerate() {
249-
let count = data_point.bucket_counts.get(i).unwrap_or(&0);
250-
println!("\t\t\t\t {} to {} : {}", lower_bound, upper_bound, count);
251-
lower_bound = upper_bound;
245+
let mut lower_bound = f64::NEG_INFINITY;
246+
let bounds_iter = data_point.bounds();
247+
let mut bucket_counts_iter = data_point.bucket_counts();
248+
let mut header_printed = false;
249+
250+
// Process all the regular buckets
251+
for upper_bound in bounds_iter {
252+
// Print header only once before the first item
253+
if !header_printed {
254+
println!("\t\t\tBuckets");
255+
header_printed = true;
252256
}
253257

254-
let last_count = data_point
255-
.bucket_counts
256-
.get(data_point.bounds.len())
257-
.unwrap_or(&0);
258+
// Get the count for this bucket, or 0 if not available
259+
let count = bucket_counts_iter.next().unwrap_or(0);
260+
println!("\t\t\t\t {} to {} : {}", lower_bound, upper_bound, count);
261+
lower_bound = upper_bound;
262+
}
263+
264+
// Handle the final +Infinity bucket if we processed any buckets
265+
if header_printed {
266+
let last_count = bucket_counts_iter.next().unwrap_or(0);
258267
println!("\t\t\t\t{} to +Infinity : {}", lower_bound, last_count);
259268
}
260269
}

0 commit comments

Comments
 (0)