Skip to content

Commit bdb777b

Browse files
authored
Add basic example showing how to use various metric instruments (#1062)
1 parent db2c6de commit bdb777b

File tree

5 files changed

+176
-1
lines changed

5 files changed

+176
-1
lines changed

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ members = [
3131
"examples/grpc",
3232
"examples/http",
3333
"examples/hyper-prometheus",
34+
"examples/metrics-basic",
3435
"examples/traceresponse",
3536
"examples/tracing-grpc",
3637
"examples/jaeger-remote-sampler",

examples/metrics-basic/Cargo.toml

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
[package]
2+
name = "metrics-basic"
3+
version = "0.1.0"
4+
edition = "2021"
5+
publish = false
6+
7+
[dependencies]
8+
futures-util = { version = "0.3", default-features = false, features = ["std"] }
9+
once_cell = "1.17"
10+
opentelemetry_api = { path = "../../opentelemetry-api", features = ["metrics"] }
11+
opentelemetry_sdk = { path = "../../opentelemetry-sdk", features = ["metrics", "rt-tokio"] }
12+
opentelemetry-stdout = { path = "../../opentelemetry-stdout", features = ["metrics"]}
13+
serde_json = "1.0"
14+
tokio = { version = "1.0", features = ["full"] }

examples/metrics-basic/README.md

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Metric Instrument Usage Example
2+
3+
This example shows how to use the various metric instruments to report metrics. The
4+
example setups a MeterProvider with stdout exporter, so metrics can be seen on
5+
the stdout.
6+
7+
## Usage
8+
9+
Run the following, and the Metrics will be written out to stdout.
10+
11+
```shell
12+
$ cargo run
13+
```
14+
15+
16+

examples/metrics-basic/src/main.rs

+139
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
use opentelemetry_api::metrics::Unit;
2+
use opentelemetry_api::{metrics::MeterProvider as _, Context, KeyValue};
3+
use opentelemetry_sdk::metrics::{MeterProvider, PeriodicReader};
4+
use opentelemetry_sdk::{runtime, Resource};
5+
use std::error::Error;
6+
7+
fn init_meter_provider() -> MeterProvider {
8+
let exporter = opentelemetry_stdout::MetricsExporter::default();
9+
let reader = PeriodicReader::builder(exporter, runtime::Tokio).build();
10+
MeterProvider::builder()
11+
.with_reader(reader)
12+
.with_resource(Resource::new(vec![KeyValue::new(
13+
"service.name",
14+
"metrics-basic-example",
15+
)]))
16+
.build()
17+
}
18+
19+
#[tokio::main]
20+
async fn main() -> Result<(), Box<dyn Error + Send + Sync + 'static>> {
21+
// Initialize the MeterProvider with the stdout Exporter.
22+
let meter_provider = init_meter_provider();
23+
24+
// Create a meter from the above MeterProvider.
25+
let meter = meter_provider.meter("mylibraryname");
26+
27+
// Create a Counter Instrument.
28+
let counter = meter.u64_counter("my_counter").init();
29+
30+
// Record measurements using the Counter instrument.
31+
counter.add(
32+
&Context::current(),
33+
10,
34+
[
35+
KeyValue::new("mykey1", "myvalue1"),
36+
KeyValue::new("mykey2", "myvalue2"),
37+
]
38+
.as_ref(),
39+
);
40+
41+
// Create a ObservableCounter instrument and register a callback that reports the measurement.
42+
let observable_counter = meter
43+
.u64_observable_counter("my_observable_counter")
44+
.with_description("My observable counter example description")
45+
.with_unit(Unit::new("myunit"))
46+
.init();
47+
48+
meter.register_callback(&[observable_counter.as_any()], move |observer| {
49+
observer.observe_u64(
50+
&observable_counter,
51+
100,
52+
[
53+
KeyValue::new("mykey1", "myvalue1"),
54+
KeyValue::new("mykey2", "myvalue2"),
55+
]
56+
.as_ref(),
57+
)
58+
})?;
59+
60+
// Create a UpCounter Instrument.
61+
let updown_counter = meter.i64_up_down_counter("my_updown_counter").init();
62+
63+
// Record measurements using the UpCounter instrument.
64+
updown_counter.add(
65+
&Context::current(),
66+
-10,
67+
[
68+
KeyValue::new("mykey1", "myvalue1"),
69+
KeyValue::new("mykey2", "myvalue2"),
70+
]
71+
.as_ref(),
72+
);
73+
74+
// Create a Observable UpDownCounter instrument and register a callback that reports the measurement.
75+
let observable_up_down_counter = meter
76+
.i64_observable_up_down_counter("my_observable_updown_counter")
77+
.with_description("My observable updown counter example description")
78+
.with_unit(Unit::new("myunit"))
79+
.init();
80+
81+
meter.register_callback(&[observable_up_down_counter.as_any()], move |observer| {
82+
observer.observe_i64(
83+
&observable_up_down_counter,
84+
100,
85+
[
86+
KeyValue::new("mykey1", "myvalue1"),
87+
KeyValue::new("mykey2", "myvalue2"),
88+
]
89+
.as_ref(),
90+
)
91+
})?;
92+
93+
// Create a Histogram Instrument.
94+
let histogram = meter
95+
.f64_histogram("my_histogram")
96+
.with_description("My histogram example description")
97+
.init();
98+
99+
// Record measurements using the histogram instrument.
100+
histogram.record(
101+
&Context::current(),
102+
10.5,
103+
[
104+
KeyValue::new("mykey1", "myvalue1"),
105+
KeyValue::new("mykey2", "myvalue2"),
106+
]
107+
.as_ref(),
108+
);
109+
110+
// Note that there is no ObservableHistogram instruments.
111+
112+
// Create a ObservableGauge instrument and register a callback that reports the measurement.
113+
let gauge = meter
114+
.f64_observable_gauge("my_gauge")
115+
.with_description("A gauge set to 1.0")
116+
.with_unit(Unit::new("myunit"))
117+
.init();
118+
119+
// Register a callback that reports the measurement.
120+
meter.register_callback(&[gauge.as_any()], move |observer| {
121+
observer.observe_f64(
122+
&gauge,
123+
1.0,
124+
[
125+
KeyValue::new("mykey1", "myvalue1"),
126+
KeyValue::new("mykey2", "myvalue2"),
127+
]
128+
.as_ref(),
129+
)
130+
})?;
131+
132+
// Note that Gauge only has a Observable version.
133+
134+
// Metrics are exported by default every 30 seconds,
135+
// however shutting down the MeterProvider here instantly flushes
136+
// the metrics, instead of waiting for the 30 sec interval.
137+
meter_provider.shutdown()?;
138+
Ok(())
139+
}

opentelemetry-api/src/metrics/instruments/up_down_counter.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ use crate::{
33
Context, KeyValue,
44
};
55
use core::fmt;
6-
use std::convert::TryFrom;
76
use std::sync::Arc;
7+
use std::{any::Any, convert::TryFrom};
88

99
use super::{AsyncInstrument, AsyncInstrumentBuilder};
1010

@@ -96,6 +96,11 @@ impl<T> ObservableUpDownCounter<T> {
9696
pub fn observe(&self, value: T, attributes: &[KeyValue]) {
9797
self.0.observe(value, attributes)
9898
}
99+
100+
/// Used for SDKs to downcast instruments in callbacks.
101+
pub fn as_any(&self) -> Arc<dyn Any> {
102+
self.0.as_any()
103+
}
99104
}
100105

101106
impl<T> AsyncInstrument<T> for ObservableUpDownCounter<T> {

0 commit comments

Comments
 (0)