Skip to content

Commit

Permalink
Update Metric-Etw exporter to use 0.27 of api and sdk (#128)
Browse files Browse the repository at this point in the history
  • Loading branch information
cijothomas authored Nov 15, 2024
1 parent b46dd69 commit d407cbf
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 62 deletions.
5 changes: 5 additions & 0 deletions opentelemetry-etw-metrics/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

## vNext

- Bump opentelemetry and opentelemetry_sdk versions to 0.27
- Bump opentelemetry-proto version to 0.27
- Uses internal logging from `opentelemetry` crate, which routes internal logs
via `tracing`.

## v0.5.0

### Changed
Expand Down
6 changes: 3 additions & 3 deletions opentelemetry-etw-metrics/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ license = "Apache-2.0"
rust-version = "1.71.1"

[dependencies]
opentelemetry = { workspace = true, features = ["metrics"] }
opentelemetry_sdk = { workspace = true, features = ["metrics", "rt-tokio"] }
opentelemetry-proto = { workspace = true, features = ["gen-tonic", "metrics"] }
opentelemetry = { version = "0.27", features = ["metrics"] }
opentelemetry_sdk = { version = "0.27", features = ["metrics", "rt-tokio"] }
opentelemetry-proto = { version = "0.27", features = ["gen-tonic", "metrics"] }
async-trait = "0.1"
prost = "0.13"
tracelogging = "1.2.1"
Expand Down
2 changes: 1 addition & 1 deletion opentelemetry-etw-metrics/examples/basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
.f64_counter("MyFruitCounter")
.with_description("test_description")
.with_unit("test_unit")
.init();
.build();

c.add(
1.0,
Expand Down
12 changes: 3 additions & 9 deletions opentelemetry-etw-metrics/src/etw/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use opentelemetry::{global, metrics::MetricsError};
use opentelemetry::otel_warn;

use tracelogging as tlg;

Expand Down Expand Up @@ -27,10 +27,7 @@ pub fn register() {
ETW_PROVIDER_REGISTRANT.call_once(|| {
let result = unsafe { PROVIDER.register() };
if result != 0 {
global::handle_error(MetricsError::Other(format!(
"Failed to register ETW provider with error code: {}",
result
)));
otel_warn!(name: "MetricExporter.EtwRegisterFailed", error_code = result);
}
});
}
Expand All @@ -51,10 +48,7 @@ pub fn unregister() {
if ETW_PROVIDER_REGISTRANT.is_completed() {
let result = PROVIDER.unregister();
if result != 0 {
global::handle_error(MetricsError::Other(format!(
"Failed to unregister ETW provider with error code: {}",
result
)));
otel_warn!(name: "MetricExporter.EtwUnRegisterFailed", error_code = result);
}
}
}
Expand Down
74 changes: 25 additions & 49 deletions opentelemetry-etw-metrics/src/exporter/mod.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
use opentelemetry::{
global,
metrics::{MetricsError, Result},
};
use opentelemetry::otel_warn;

use opentelemetry_proto::tonic::collector::metrics::v1::ExportMetricsServiceRequest;
use opentelemetry_sdk::metrics::{
data::{
self, ExponentialBucket, ExponentialHistogramDataPoint, Metric, ResourceMetrics,
ScopeMetrics, Temporality,
ScopeMetrics,
},
exporter::PushMetricsExporter,
reader::TemporalitySelector,
InstrumentKind,
exporter::PushMetricExporter,
MetricError, MetricResult, Temporality,
};
use prost::Message;

Expand All @@ -36,30 +33,15 @@ impl Default for MetricsExporter {
}
}

impl TemporalitySelector for MetricsExporter {
fn temporality(&self, kind: InstrumentKind) -> Temporality {
match kind {
InstrumentKind::Counter
| InstrumentKind::ObservableCounter
| InstrumentKind::ObservableGauge
| InstrumentKind::Histogram
| InstrumentKind::Gauge => Temporality::Delta,
InstrumentKind::UpDownCounter | InstrumentKind::ObservableUpDownCounter => {
Temporality::Cumulative
}
}
}
}

impl Debug for MetricsExporter {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.write_str("ETW metrics exporter")
}
}

#[async_trait]
impl PushMetricsExporter for MetricsExporter {
async fn export(&self, metrics: &mut ResourceMetrics) -> Result<()> {
impl PushMetricExporter for MetricsExporter {
async fn export(&self, metrics: &mut ResourceMetrics) -> MetricResult<()> {
for scope_metric in &metrics.scope_metrics {
for metric in &scope_metric.metrics {
let mut resource_metrics = Vec::new();
Expand Down Expand Up @@ -296,36 +278,26 @@ impl PushMetricsExporter for MetricsExporter {
resource_metrics.push(resource_metric);
}
} else {
global::handle_error(MetricsError::Other(format!(
"Unsupported aggregation type: {:?}",
data
)));
otel_warn!(name: "MetricExportFailedDueToUnsupportedMetricType", metric_type = format!("{:?}", data));
}

for resource_metric in resource_metrics {
let mut byte_array = Vec::new();
let proto_message: ExportMetricsServiceRequest = (&resource_metric).into();
proto_message
.encode(&mut byte_array)
.map_err(|err| MetricsError::Other(err.to_string()))?;
.map_err(|err| MetricError::Other(err.to_string()))?;

if (byte_array.len()) > etw::MAX_EVENT_SIZE {
global::handle_error(MetricsError::Other(format!(
"Exporting failed due to event size {} exceeding the maximum size of {} bytes",
byte_array.len(),
etw::MAX_EVENT_SIZE
)));
otel_warn!(name: "MetricExportFailedDueToMaxSizeLimit", size = byte_array.len(), max_size = etw::MAX_EVENT_SIZE);
} else {
let result = etw::write(&byte_array);
// TODO: Better logging/internal metrics needed here for non-failure
// case Uncomment the line below to see the exported bytes until a
// better logging solution is implemented
// println!("Exported {} bytes to ETW", byte_array.len());
if result != 0 {
global::handle_error(MetricsError::Other(format!(
"Failed to write ETW event with error code: {}",
result
)));
otel_warn!(name: "MetricExportFailed", error_code = result);
}
}
}
Expand All @@ -335,15 +307,19 @@ impl PushMetricsExporter for MetricsExporter {
Ok(())
}

async fn force_flush(&self) -> Result<()> {
async fn force_flush(&self) -> MetricResult<()> {
Ok(())
}

fn shutdown(&self) -> Result<()> {
fn shutdown(&self) -> MetricResult<()> {
etw::unregister();

Ok(())
}

fn temporality(&self) -> Temporality {
Temporality::Delta
}
}

#[cfg(test)]
Expand Down Expand Up @@ -374,49 +350,49 @@ mod tests {
.u64_histogram("Testu64Histogram")
.with_description("u64_histogram_test_description")
.with_unit("u64_histogram_test_unit")
.init();
.build();

let f64_histogram = meter
.f64_histogram("TestHistogram")
.with_description("f64_histogram_test_description")
.with_unit("f64_histogram_test_unit")
.init();
.build();

let u64_counter = meter
.u64_counter("Testu64Counter")
.with_description("u64_counter_test_description")
.with_unit("u64_counter_test_units")
.init();
.build();

let f64_counter = meter
.f64_counter("Testf64Counter")
.with_description("f64_counter_test_description")
.with_unit("f64_counter_test_units")
.init();
.build();

let i64_counter = meter
.i64_up_down_counter("Testi64Counter")
.with_description("i64_counter_test_description")
.with_unit("i64_counter_test_units")
.init();
.build();

let u64_gauge = meter
.u64_gauge("Testu64Gauge")
.with_description("u64_gauge_test_description")
.with_unit("u64_gauge_test_unit")
.init();
.build();

let i64_gauge = meter
.i64_gauge("Testi64Gauge")
.with_description("i64_gauge_test_description")
.with_unit("i64_gauge_test_unit")
.init();
.build();

let f64_gauge = meter
.f64_gauge("Testf64Gauge")
.with_description("f64_gauge_test_description")
.with_unit("f64_gauge_test_unit")
.init();
.build();

// Create a key that is 1/10th the size of the MAX_EVENT_SIZE
let key_size = etw::MAX_EVENT_SIZE / 10;
Expand Down

0 comments on commit d407cbf

Please sign in to comment.