Skip to content

Commit 7bb3e56

Browse files
authored
feat: produce measurement with attributes (#43)
## Motivation Support #32 This change will allow user to associate Attributes with metrics from tracing. ## Solution 1. MetricsLayer is only interested in events that contain fields with metrics prefixes such as `counter`, so I have utilized the [tracing_subscriber Filter trait](https://docs.rs/tracing-subscriber/latest/tracing_subscriber/layer/#per-layer-filtering). 2. Since it's necessary to pass Attributes when outputting Measurements, it's required to complete the visit for all fields first before invoking the Metrics API(`Counter:add()`). `SmallVec` is used to hold Attribute KeyValues, Metrics names, and Instruments for invocation, aiming to avoid allocations in typical use cases.
1 parent 6bc7dce commit 7bb3e56

File tree

4 files changed

+661
-79
lines changed

4 files changed

+661
-79
lines changed

Cargo.toml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ rust-version = "1.60.0"
2222
[features]
2323
default = ["tracing-log", "metrics"]
2424
# Enables support for exporting OpenTelemetry metrics
25-
metrics = ["opentelemetry/metrics"]
25+
metrics = ["opentelemetry/metrics", "smallvec"]
2626

2727
[dependencies]
2828
opentelemetry = { version = "0.20.0", default-features = false, features = ["trace"] }
@@ -35,6 +35,7 @@ once_cell = "1.13.0"
3535
# Fix minimal-versions
3636
async-trait = { version = "0.1.56", optional = true }
3737
thiserror = { version = "1.0.31", optional = true }
38+
smallvec = { version = "1.0", optional = true }
3839

3940
[dev-dependencies]
4041
async-trait = "0.1.56"
@@ -56,6 +57,10 @@ bench = false
5657
name = "trace"
5758
harness = false
5859

60+
[[bench]]
61+
name = "metrics"
62+
harness = false
63+
5964
[package.metadata.docs.rs]
6065
all-features = true
6166
rustdoc-args = ["--cfg", "docsrs"]

benches/metrics.rs

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
use criterion::{criterion_group, criterion_main, Criterion};
2+
use opentelemetry::metrics::noop::NoopMeterProvider;
3+
use tracing_opentelemetry::MetricsLayer;
4+
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
5+
6+
fn metrics_events(c: &mut Criterion) {
7+
let mut group = c.benchmark_group("otel_metrics_events");
8+
{
9+
let _subscriber = tracing_subscriber::registry().set_default();
10+
group.bench_function("no_metrics_layer", |b| {
11+
b.iter(|| {
12+
tracing::info!(key_1 = "va", "msg");
13+
})
14+
});
15+
}
16+
17+
{
18+
let _subscriber = tracing_subscriber::registry()
19+
.with(MetricsLayer::new(NoopMeterProvider::new()))
20+
.set_default();
21+
group.bench_function("metrics_events_0_attr_0", |b| {
22+
b.iter(|| {
23+
tracing::info!(key_1 = "va", "msg");
24+
})
25+
});
26+
}
27+
28+
{
29+
let _subscriber = tracing_subscriber::registry()
30+
.with(MetricsLayer::new(NoopMeterProvider::new()))
31+
.set_default();
32+
group.bench_function("metrics_events_1_attr_0", |b| {
33+
b.iter(|| {
34+
tracing::info!(monotonic_counter.c1 = 1, "msg");
35+
})
36+
});
37+
}
38+
39+
{
40+
let _subscriber = tracing_subscriber::registry()
41+
.with(MetricsLayer::new(NoopMeterProvider::new()))
42+
.set_default();
43+
group.bench_function("metrics_events_2_attr_0", |b| {
44+
b.iter(|| {
45+
tracing::info!(monotonic_counter.c1 = 1, monotonic_counter.c2 = 1, "msg");
46+
})
47+
});
48+
}
49+
50+
{
51+
let _subscriber = tracing_subscriber::registry()
52+
.with(MetricsLayer::new(NoopMeterProvider::new()))
53+
.set_default();
54+
group.bench_function("metrics_events_4_attr_0", |b| {
55+
b.iter(|| {
56+
tracing::info!(
57+
monotonic_counter.c1 = 1,
58+
monotonic_counter.c2 = 1,
59+
monotonic_counter.c3 = 1,
60+
monotonic_counter.c4 = 1,
61+
"msg"
62+
);
63+
})
64+
});
65+
}
66+
67+
{
68+
let _subscriber = tracing_subscriber::registry()
69+
.with(MetricsLayer::new(NoopMeterProvider::new()))
70+
.set_default();
71+
group.bench_function("metrics_events_8_attr_0", |b| {
72+
b.iter(|| {
73+
tracing::info!(
74+
monotonic_counter.c1 = 1,
75+
monotonic_counter.c2 = 1,
76+
monotonic_counter.c3 = 1,
77+
monotonic_counter.c4 = 1,
78+
monotonic_counter.c5 = 1,
79+
monotonic_counter.c6 = 1,
80+
monotonic_counter.c7 = 1,
81+
monotonic_counter.c8 = 1,
82+
"msg"
83+
);
84+
})
85+
});
86+
}
87+
88+
{
89+
let _subscriber = tracing_subscriber::registry()
90+
.with(MetricsLayer::new(NoopMeterProvider::new()))
91+
.set_default();
92+
group.bench_function("metrics_events_1_attr_1", |b| {
93+
b.iter(|| {
94+
tracing::info!(monotonic_counter.c1 = 1, key_1 = 1_i64, "msg");
95+
})
96+
});
97+
}
98+
99+
{
100+
let _subscriber = tracing_subscriber::registry()
101+
.with(MetricsLayer::new(NoopMeterProvider::new()))
102+
.set_default();
103+
group.bench_function("metrics_events_1_attr_2", |b| {
104+
b.iter(|| {
105+
tracing::info!(
106+
monotonic_counter.c1 = 1,
107+
key_1 = 1_i64,
108+
key_2 = 1_i64,
109+
"msg"
110+
);
111+
})
112+
});
113+
}
114+
115+
{
116+
let _subscriber = tracing_subscriber::registry()
117+
.with(MetricsLayer::new(NoopMeterProvider::new()))
118+
.set_default();
119+
group.bench_function("metrics_events_1_attr_4", |b| {
120+
b.iter(|| {
121+
tracing::info!(
122+
monotonic_counter.c1 = 1,
123+
key_1 = 1_i64,
124+
key_2 = 1_i64,
125+
key_3 = 1_i64,
126+
key_4 = 1_i64,
127+
"msg"
128+
);
129+
})
130+
});
131+
}
132+
133+
{
134+
let _subscriber = tracing_subscriber::registry()
135+
.with(MetricsLayer::new(NoopMeterProvider::new()))
136+
.set_default();
137+
group.bench_function("metrics_events_1_attr_8", |b| {
138+
b.iter(|| {
139+
tracing::info!(
140+
monotonic_counter.c1 = 1,
141+
key_1 = 1_i64,
142+
key_2 = 1_i64,
143+
key_3 = 1_i64,
144+
key_4 = 1_i64,
145+
key_5 = 1_i64,
146+
key_6 = 1_i64,
147+
key_7 = 1_i64,
148+
key_8 = 1_i64,
149+
"msg"
150+
);
151+
})
152+
});
153+
}
154+
group.finish();
155+
}
156+
157+
criterion_group! {
158+
name = benches;
159+
config = Criterion::default();
160+
targets = metrics_events
161+
}
162+
criterion_main!(benches);

0 commit comments

Comments
 (0)