Skip to content

Commit 4d1a7c6

Browse files
examples/metrics-advanced: add example with exponential histogram
1 parent df412fe commit 4d1a7c6

File tree

2 files changed

+50
-2
lines changed

2 files changed

+50
-2
lines changed

examples/metrics-advanced/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,6 @@ bench = false
1414

1515
[dependencies]
1616
opentelemetry = { workspace = true, features = ["metrics"] }
17-
opentelemetry_sdk = { workspace = true }
17+
opentelemetry_sdk = { workspace = true, features = ["spec_unstable_metrics_views"] }
1818
opentelemetry-stdout = { workspace = true, features = ["metrics"] }
1919
tokio = { workspace = true, features = ["full"] }

examples/metrics-advanced/src/main.rs

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use opentelemetry::global;
22
use opentelemetry::KeyValue;
3-
use opentelemetry_sdk::metrics::{Instrument, SdkMeterProvider, Stream, Temporality};
3+
use opentelemetry_sdk::metrics::{Aggregation, Instrument, SdkMeterProvider, Stream, Temporality};
44
use opentelemetry_sdk::Resource;
55
use std::error::Error;
66

@@ -33,6 +33,36 @@ fn init_meter_provider() -> opentelemetry_sdk::metrics::SdkMeterProvider {
3333
}
3434
};
3535

36+
// for example 3
37+
// Unlike a regular OpenTelemetry histogram with fixed buckets, which can be
38+
// specified explicitly, an exponential histogram calculates bucket widths
39+
// automatically, growing them exponentially. The configuration is
40+
// controlled by two parameters: max_size defines the maximum number of
41+
// buckets, while max_scale adjusts the resolution, with higher values
42+
// providing greater precision.
43+
// If the minimum and maximum values are known in advance, a regular
44+
// histogram is often the better choice. However, if the range of values is
45+
// unpredictable e.g. may include extreme outliers, an exponential histogram
46+
// is more suitable. A example is measuring packet round-trip time in a
47+
// WLAN: while most packets return in milliseconds, some may occasionally
48+
// take hundreds of milliseconds or even seconds.
49+
// Details are in:
50+
// https://opentelemetry.io/docs/specs/otel/metrics/data-model/#exponentialhistogram
51+
let my_view_change_aggregation = |i: &Instrument| {
52+
if i.name() == "my_third_histogram" {
53+
Stream::builder()
54+
.with_aggregation(Aggregation::Base2ExponentialHistogram {
55+
max_size: 10,
56+
max_scale: 5,
57+
record_min_max: true,
58+
})
59+
.build()
60+
.ok()
61+
} else {
62+
None
63+
}
64+
};
65+
3666
// Build exporter using Delta Temporality.
3767
let exporter = opentelemetry_stdout::MetricExporterBuilder::default()
3868
.with_temporality(Temporality::Delta)
@@ -47,6 +77,7 @@ fn init_meter_provider() -> opentelemetry_sdk::metrics::SdkMeterProvider {
4777
.with_resource(resource)
4878
.with_view(my_view_rename_and_unit)
4979
.with_view(my_view_change_cardinality)
80+
.with_view(my_view_change_aggregation)
5081
.build();
5182
global::set_meter_provider(provider.clone());
5283
provider
@@ -112,6 +143,23 @@ async fn main() -> Result<(), Box<dyn Error + Send + Sync + 'static>> {
112143

113144
histogram2.record(1.8, &[KeyValue::new("mykey1", "v7")]);
114145

146+
// Example 3 - Use exponential histogram.
147+
let histogram3 = meter
148+
.f64_histogram("my_third_histogram")
149+
.with_description("My histogram example description")
150+
.build();
151+
histogram3.record(-1.3, &[KeyValue::new("mykey1", "myvalue1")]);
152+
histogram3.record(-5.5, &[KeyValue::new("mykey1", "myvalue1")]);
153+
// is intentionally at the boundary of bucket
154+
histogram3.record(-4.0, &[KeyValue::new("mykey1", "myvalue1")]);
155+
histogram3.record(7.5, &[KeyValue::new("mykey1", "myvalue1")]);
156+
// Internally the exponential histogram puts values either into a list of
157+
// negative buckets or a list of positive buckets. Based on the values which
158+
// are added the buckets are adjusted automatically. E.g. depending if the
159+
// next record is commented/uncommented, then exponential histogram will
160+
// have a different scale.
161+
histogram3.record(0.4, &[KeyValue::new("mykey1", "myvalue1")]);
162+
115163
// Metrics are exported by default every 60 seconds when using stdout exporter,
116164
// however shutting down the MeterProvider here instantly flushes
117165
// the metrics, instead of waiting for the 60 sec interval.

0 commit comments

Comments
 (0)