Skip to content

Commit 434cc86

Browse files
mattboddlalitb
andauthored
Improve efficiency of ETW metrics exporter (#134)
Co-authored-by: Lalit Kumar Bhasin <[email protected]>
1 parent 8ecb2b2 commit 434cc86

File tree

4 files changed

+264
-268
lines changed

4 files changed

+264
-268
lines changed

Cargo.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,7 @@ opentelemetry-http = "0.27"
1919
opentelemetry-proto = { version = "0.27", default-features = false }
2020
opentelemetry_sdk = { version = "0.27", default-features = false }
2121
opentelemetry-stdout = "0.27"
22-
opentelemetry-semantic-conventions = { version = "0.27", features = ["semconv_experimental"] }
22+
opentelemetry-semantic-conventions = { version = "0.27", features = [
23+
"semconv_experimental",
24+
] }
25+
criterion = "0.5"

opentelemetry-etw-metrics/Cargo.toml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,18 @@ opentelemetry-proto = { workspace = true, features = ["gen-tonic", "metrics"] }
1717
async-trait = "0.1"
1818
prost = "0.13"
1919
tracelogging = "1.2.1"
20-
tracing = {version = "0.1", optional = true}
21-
20+
tracing = { version = "0.1", optional = true }
2221
[dev-dependencies]
2322
tokio = { version = "1.0", features = ["full"] }
23+
criterion = { workspace = true, features = ["html_reports"] }
2424

2525
[features]
2626
internal-logs = ["tracing"]
2727
default = ["internal-logs"]
2828

2929
[package.metadata.cargo-machete]
3030
ignored = ["tracing"]
31+
32+
[[bench]]
33+
name = "exporter"
34+
harness = false
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
//! run with `$ cargo bench --bench exporter -- --exact <test_name>` to run specific test for logs
2+
//! So to run test named "fibonacci" you would run `$ cargo bench --bench exporter -- --exact fibonacci`
3+
//! To run all tests for logs you would run `$ cargo bench --bench exporter`
4+
//!
5+
/*
6+
The benchmark results:
7+
criterion = "0.5.1"
8+
OS: Windows 11 Enterprise N, 23H2, Build 22631.4460
9+
Hardware: Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz 2.79 GHz, 16vCPUs
10+
RAM: 64.0 GB
11+
| Test | Average time|
12+
|--------------------------------|-------------|
13+
| exporter | 22.203 ms |
14+
*/
15+
16+
use opentelemetry::{InstrumentationScope, KeyValue};
17+
use opentelemetry_etw_metrics::MetricsExporter;
18+
19+
use opentelemetry_sdk::{
20+
metrics::{
21+
data::{DataPoint, Metric, ResourceMetrics, ScopeMetrics, Sum},
22+
exporter::PushMetricExporter,
23+
Temporality,
24+
},
25+
Resource,
26+
};
27+
28+
use criterion::{criterion_group, criterion_main, Criterion};
29+
30+
async fn export(exporter: &MetricsExporter, resource_metrics: &mut ResourceMetrics) {
31+
exporter.export(resource_metrics).await.unwrap();
32+
}
33+
34+
fn create_resource_metrics() -> ResourceMetrics {
35+
// Metric does not implement clone so this helper function is used to create a metric
36+
fn create_metric() -> Metric {
37+
let data_point = DataPoint {
38+
attributes: vec![KeyValue::new("datapoint key", "datapoint value")],
39+
start_time: Some(std::time::SystemTime::now()),
40+
time: Some(std::time::SystemTime::now()),
41+
value: 1.0_f64,
42+
exemplars: vec![],
43+
};
44+
45+
let sum: Sum<f64> = Sum {
46+
data_points: vec![data_point.clone(); 2_000],
47+
temporality: Temporality::Delta,
48+
is_monotonic: true,
49+
};
50+
51+
Metric {
52+
name: "metric_name".into(),
53+
description: "metric description".into(),
54+
unit: "metric unit".into(),
55+
data: Box::new(sum),
56+
}
57+
}
58+
59+
ResourceMetrics {
60+
resource: Resource::new(vec![KeyValue::new("service.name", "my-service")]),
61+
scope_metrics: vec![ScopeMetrics {
62+
scope: InstrumentationScope::default(),
63+
metrics: vec![
64+
create_metric(),
65+
create_metric(),
66+
create_metric(),
67+
create_metric(),
68+
create_metric(),
69+
create_metric(),
70+
create_metric(),
71+
create_metric(),
72+
create_metric(),
73+
create_metric(),
74+
],
75+
}],
76+
}
77+
}
78+
79+
fn criterion_benchmark(c: &mut Criterion) {
80+
let runtime = tokio::runtime::Builder::new_multi_thread()
81+
.worker_threads(1)
82+
.enable_all()
83+
.build()
84+
.unwrap();
85+
86+
c.bench_function("export", move |b| {
87+
b.iter_custom(|iters| {
88+
let exporter = MetricsExporter::new();
89+
90+
let mut resource_metrics = create_resource_metrics();
91+
92+
let start = std::time::Instant::now();
93+
94+
for _i in 0..iters {
95+
runtime.block_on(async {
96+
export(&exporter, &mut resource_metrics).await;
97+
});
98+
}
99+
start.elapsed()
100+
})
101+
});
102+
}
103+
104+
criterion_group!(benches, criterion_benchmark);
105+
criterion_main!(benches);

0 commit comments

Comments
 (0)