Add global::meter_provider_shutdown (#1623)
Co-authored-by: Cijo Thomas <cithomas@microsoft.com> Co-authored-by: Zhongyang Wu <zhongyang.wu@outlook.com>
This commit is contained in:
parent
a4fae95bd6
commit
bae8fb3321
|
@ -1,3 +1,4 @@
|
||||||
|
use opentelemetry::global;
|
||||||
use opentelemetry::metrics::Unit;
|
use opentelemetry::metrics::Unit;
|
||||||
use opentelemetry::Key;
|
use opentelemetry::Key;
|
||||||
use opentelemetry::{metrics::MeterProvider as _, KeyValue};
|
use opentelemetry::{metrics::MeterProvider as _, KeyValue};
|
||||||
|
@ -7,7 +8,7 @@ use opentelemetry_sdk::metrics::{
|
||||||
use opentelemetry_sdk::{runtime, Resource};
|
use opentelemetry_sdk::{runtime, Resource};
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
|
||||||
fn init_meter_provider() -> SdkMeterProvider {
|
fn init_meter_provider() {
|
||||||
// for example 1
|
// for example 1
|
||||||
let my_view_rename_and_unit = |i: &Instrument| {
|
let my_view_rename_and_unit = |i: &Instrument| {
|
||||||
if i.name == "my_histogram" {
|
if i.name == "my_histogram" {
|
||||||
|
@ -50,7 +51,7 @@ fn init_meter_provider() -> SdkMeterProvider {
|
||||||
// Ok(serde_json::to_writer_pretty(writer, &data).unwrap()))
|
// Ok(serde_json::to_writer_pretty(writer, &data).unwrap()))
|
||||||
.build();
|
.build();
|
||||||
let reader = PeriodicReader::builder(exporter, runtime::Tokio).build();
|
let reader = PeriodicReader::builder(exporter, runtime::Tokio).build();
|
||||||
SdkMeterProvider::builder()
|
let provider = SdkMeterProvider::builder()
|
||||||
.with_reader(reader)
|
.with_reader(reader)
|
||||||
.with_resource(Resource::new(vec![KeyValue::new(
|
.with_resource(Resource::new(vec![KeyValue::new(
|
||||||
"service.name",
|
"service.name",
|
||||||
|
@ -59,13 +60,14 @@ fn init_meter_provider() -> SdkMeterProvider {
|
||||||
.with_view(my_view_rename_and_unit)
|
.with_view(my_view_rename_and_unit)
|
||||||
.with_view(my_view_drop_attributes)
|
.with_view(my_view_drop_attributes)
|
||||||
.with_view(my_view_change_aggregation)
|
.with_view(my_view_change_aggregation)
|
||||||
.build()
|
.build();
|
||||||
|
global::set_meter_provider(provider);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<(), Box<dyn Error + Send + Sync + 'static>> {
|
async fn main() -> Result<(), Box<dyn Error + Send + Sync + 'static>> {
|
||||||
let meter_provider = init_meter_provider();
|
init_meter_provider();
|
||||||
let meter = meter_provider.meter("mylibraryname");
|
let meter = global::meter("mylibraryname");
|
||||||
|
|
||||||
// Example 1 - Rename metric using View.
|
// Example 1 - Rename metric using View.
|
||||||
// This instrument will be renamed to "my_histogram_renamed",
|
// This instrument will be renamed to "my_histogram_renamed",
|
||||||
|
@ -151,6 +153,6 @@ async fn main() -> Result<(), Box<dyn Error + Send + Sync + 'static>> {
|
||||||
// Metrics are exported by default every 30 seconds when using stdout exporter,
|
// Metrics are exported by default every 30 seconds when using stdout exporter,
|
||||||
// however shutting down the MeterProvider here instantly flushes
|
// however shutting down the MeterProvider here instantly flushes
|
||||||
// the metrics, instead of waiting for the 30 sec interval.
|
// the metrics, instead of waiting for the 30 sec interval.
|
||||||
meter_provider.shutdown()?;
|
global::shutdown_meter_provider();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,32 +1,34 @@
|
||||||
|
use opentelemetry::global;
|
||||||
use opentelemetry::metrics::Unit;
|
use opentelemetry::metrics::Unit;
|
||||||
use opentelemetry::{metrics::MeterProvider as _, KeyValue};
|
use opentelemetry::{metrics::MeterProvider as _, KeyValue};
|
||||||
use opentelemetry_sdk::metrics::{PeriodicReader, SdkMeterProvider};
|
use opentelemetry_sdk::metrics::{PeriodicReader, SdkMeterProvider};
|
||||||
use opentelemetry_sdk::{runtime, Resource};
|
use opentelemetry_sdk::{runtime, Resource};
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
|
||||||
fn init_meter_provider() -> SdkMeterProvider {
|
fn init_meter_provider() {
|
||||||
let exporter = opentelemetry_stdout::MetricsExporterBuilder::default()
|
let exporter = opentelemetry_stdout::MetricsExporterBuilder::default()
|
||||||
// uncomment the below lines to pretty print output.
|
// uncomment the below lines to pretty print output.
|
||||||
// .with_encoder(|writer, data|
|
// .with_encoder(|writer, data|
|
||||||
// Ok(serde_json::to_writer_pretty(writer, &data).unwrap()))
|
// Ok(serde_json::to_writer_pretty(writer, &data).unwrap()))
|
||||||
.build();
|
.build();
|
||||||
let reader = PeriodicReader::builder(exporter, runtime::Tokio).build();
|
let reader = PeriodicReader::builder(exporter, runtime::Tokio).build();
|
||||||
SdkMeterProvider::builder()
|
let provider = SdkMeterProvider::builder()
|
||||||
.with_reader(reader)
|
.with_reader(reader)
|
||||||
.with_resource(Resource::new(vec![KeyValue::new(
|
.with_resource(Resource::new(vec![KeyValue::new(
|
||||||
"service.name",
|
"service.name",
|
||||||
"metrics-basic-example",
|
"metrics-basic-example",
|
||||||
)]))
|
)]))
|
||||||
.build()
|
.build();
|
||||||
|
global::set_meter_provider(provider);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<(), Box<dyn Error + Send + Sync + 'static>> {
|
async fn main() -> Result<(), Box<dyn Error + Send + Sync + 'static>> {
|
||||||
// Initialize the MeterProvider with the stdout Exporter.
|
// Initialize the MeterProvider with the stdout Exporter.
|
||||||
let meter_provider = init_meter_provider();
|
init_meter_provider();
|
||||||
|
|
||||||
// Create a meter from the above MeterProvider.
|
// Create a meter from the above MeterProvider.
|
||||||
let meter = meter_provider.meter("mylibraryname");
|
let meter = global::meter("mylibraryname");
|
||||||
|
|
||||||
// Create a Counter Instrument.
|
// Create a Counter Instrument.
|
||||||
let counter = meter.u64_counter("my_counter").init();
|
let counter = meter.u64_counter("my_counter").init();
|
||||||
|
@ -146,6 +148,6 @@ async fn main() -> Result<(), Box<dyn Error + Send + Sync + 'static>> {
|
||||||
// Metrics are exported by default every 30 seconds when using stdout exporter,
|
// Metrics are exported by default every 30 seconds when using stdout exporter,
|
||||||
// however shutting down the MeterProvider here instantly flushes
|
// however shutting down the MeterProvider here instantly flushes
|
||||||
// the metrics, instead of waiting for the 30 sec interval.
|
// the metrics, instead of waiting for the 30 sec interval.
|
||||||
meter_provider.shutdown()?;
|
global::shutdown_meter_provider();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use opentelemetry::{
|
use opentelemetry::{
|
||||||
global, metrics,
|
global,
|
||||||
|
metrics::MetricsError,
|
||||||
trace::{TraceContextExt, TraceError, Tracer},
|
trace::{TraceContextExt, TraceError, Tracer},
|
||||||
Key, KeyValue,
|
Key, KeyValue,
|
||||||
};
|
};
|
||||||
use opentelemetry_appender_tracing::layer::OpenTelemetryTracingBridge;
|
use opentelemetry_appender_tracing::layer::OpenTelemetryTracingBridge;
|
||||||
use opentelemetry_otlp::WithExportConfig;
|
use opentelemetry_otlp::WithExportConfig;
|
||||||
use opentelemetry_sdk::logs as sdklogs;
|
use opentelemetry_sdk::logs as sdklogs;
|
||||||
use opentelemetry_sdk::metrics as sdkmetrics;
|
|
||||||
use opentelemetry_sdk::resource;
|
use opentelemetry_sdk::resource;
|
||||||
use opentelemetry_sdk::trace as sdktrace;
|
use opentelemetry_sdk::trace as sdktrace;
|
||||||
|
|
||||||
|
@ -44,19 +44,20 @@ fn init_tracer() -> Result<sdktrace::Tracer, TraceError> {
|
||||||
.install_batch(opentelemetry_sdk::runtime::Tokio)
|
.install_batch(opentelemetry_sdk::runtime::Tokio)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init_metrics() -> metrics::Result<sdkmetrics::SdkMeterProvider> {
|
fn init_metrics() -> Result<(), MetricsError> {
|
||||||
let export_config = opentelemetry_otlp::ExportConfig {
|
let export_config = opentelemetry_otlp::ExportConfig {
|
||||||
endpoint: "http://localhost:4318/v1/metrics".to_string(),
|
endpoint: "http://localhost:4318/v1/metrics".to_string(),
|
||||||
..opentelemetry_otlp::ExportConfig::default()
|
..opentelemetry_otlp::ExportConfig::default()
|
||||||
};
|
};
|
||||||
opentelemetry_otlp::new_pipeline()
|
let provider = opentelemetry_otlp::new_pipeline()
|
||||||
.metrics(opentelemetry_sdk::runtime::Tokio)
|
.metrics(opentelemetry_sdk::runtime::Tokio)
|
||||||
.with_exporter(
|
.with_exporter(
|
||||||
opentelemetry_otlp::new_exporter()
|
opentelemetry_otlp::new_exporter()
|
||||||
.http()
|
.http()
|
||||||
.with_export_config(export_config),
|
.with_export_config(export_config),
|
||||||
)
|
)
|
||||||
.build()
|
.build();
|
||||||
|
provider.map(|_| ())
|
||||||
}
|
}
|
||||||
|
|
||||||
const LEMONS_KEY: Key = Key::from_static_str("ex.com/lemons");
|
const LEMONS_KEY: Key = Key::from_static_str("ex.com/lemons");
|
||||||
|
@ -74,7 +75,7 @@ static COMMON_ATTRIBUTES: Lazy<[KeyValue; 4]> = Lazy::new(|| {
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<(), Box<dyn Error + Send + Sync + 'static>> {
|
async fn main() -> Result<(), Box<dyn Error + Send + Sync + 'static>> {
|
||||||
let _ = init_tracer()?;
|
let _ = init_tracer()?;
|
||||||
let meter_provider = init_metrics()?;
|
let _ = init_metrics()?;
|
||||||
let _ = init_logs();
|
let _ = init_logs();
|
||||||
|
|
||||||
let tracer = global::tracer("ex.com/basic");
|
let tracer = global::tracer("ex.com/basic");
|
||||||
|
@ -108,7 +109,7 @@ async fn main() -> Result<(), Box<dyn Error + Send + Sync + 'static>> {
|
||||||
|
|
||||||
global::shutdown_tracer_provider();
|
global::shutdown_tracer_provider();
|
||||||
global::shutdown_logger_provider();
|
global::shutdown_logger_provider();
|
||||||
meter_provider.shutdown()?;
|
global::shutdown_meter_provider();
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +1,17 @@
|
||||||
use log::{info, Level};
|
use log::{info, Level};
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use opentelemetry::global;
|
use opentelemetry::global;
|
||||||
use opentelemetry::global::{logger_provider, shutdown_logger_provider, shutdown_tracer_provider};
|
|
||||||
use opentelemetry::logs::LogError;
|
use opentelemetry::logs::LogError;
|
||||||
|
use opentelemetry::metrics::MetricsError;
|
||||||
use opentelemetry::trace::TraceError;
|
use opentelemetry::trace::TraceError;
|
||||||
use opentelemetry::{
|
use opentelemetry::{
|
||||||
metrics,
|
|
||||||
trace::{TraceContextExt, Tracer},
|
trace::{TraceContextExt, Tracer},
|
||||||
Key, KeyValue,
|
Key, KeyValue,
|
||||||
};
|
};
|
||||||
use opentelemetry_appender_log::OpenTelemetryLogBridge;
|
use opentelemetry_appender_log::OpenTelemetryLogBridge;
|
||||||
use opentelemetry_otlp::{ExportConfig, WithExportConfig};
|
use opentelemetry_otlp::{ExportConfig, WithExportConfig};
|
||||||
use opentelemetry_sdk::logs::Config;
|
use opentelemetry_sdk::logs::Config;
|
||||||
use opentelemetry_sdk::{metrics::SdkMeterProvider, runtime, trace as sdktrace, Resource};
|
use opentelemetry_sdk::{runtime, trace as sdktrace, Resource};
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
|
||||||
fn init_tracer() -> Result<sdktrace::Tracer, TraceError> {
|
fn init_tracer() -> Result<sdktrace::Tracer, TraceError> {
|
||||||
|
@ -32,12 +31,12 @@ fn init_tracer() -> Result<sdktrace::Tracer, TraceError> {
|
||||||
.install_batch(runtime::Tokio)
|
.install_batch(runtime::Tokio)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init_metrics() -> metrics::Result<SdkMeterProvider> {
|
fn init_metrics() -> Result<(), MetricsError> {
|
||||||
let export_config = ExportConfig {
|
let export_config = ExportConfig {
|
||||||
endpoint: "http://localhost:4317".to_string(),
|
endpoint: "http://localhost:4317".to_string(),
|
||||||
..ExportConfig::default()
|
..ExportConfig::default()
|
||||||
};
|
};
|
||||||
opentelemetry_otlp::new_pipeline()
|
let provider = opentelemetry_otlp::new_pipeline()
|
||||||
.metrics(runtime::Tokio)
|
.metrics(runtime::Tokio)
|
||||||
.with_exporter(
|
.with_exporter(
|
||||||
opentelemetry_otlp::new_exporter()
|
opentelemetry_otlp::new_exporter()
|
||||||
|
@ -48,7 +47,11 @@ fn init_metrics() -> metrics::Result<SdkMeterProvider> {
|
||||||
opentelemetry_semantic_conventions::resource::SERVICE_NAME,
|
opentelemetry_semantic_conventions::resource::SERVICE_NAME,
|
||||||
"basic-otlp-metrics-example",
|
"basic-otlp-metrics-example",
|
||||||
)]))
|
)]))
|
||||||
.build()
|
.build();
|
||||||
|
match provider {
|
||||||
|
Ok(_provider) => Ok(()),
|
||||||
|
Err(err) => Err(err),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init_logs() -> Result<opentelemetry_sdk::logs::Logger, LogError> {
|
fn init_logs() -> Result<opentelemetry_sdk::logs::Logger, LogError> {
|
||||||
|
@ -87,13 +90,13 @@ async fn main() -> Result<(), Box<dyn Error + Send + Sync + 'static>> {
|
||||||
// matches the containing block, reporting traces and metrics during the whole
|
// matches the containing block, reporting traces and metrics during the whole
|
||||||
// execution.
|
// execution.
|
||||||
let _ = init_tracer()?;
|
let _ = init_tracer()?;
|
||||||
let meter_provider = init_metrics()?;
|
let _ = init_metrics()?;
|
||||||
|
|
||||||
// Initialize logs, which sets the global loggerprovider.
|
// Initialize logs, which sets the global loggerprovider.
|
||||||
let _ = init_logs();
|
let _ = init_logs();
|
||||||
|
|
||||||
// Retrieve the global LoggerProvider.
|
// Retrieve the global LoggerProvider.
|
||||||
let logger_provider = logger_provider();
|
let logger_provider = global::logger_provider();
|
||||||
|
|
||||||
// Create a new OpenTelemetryLogBridge using the above LoggerProvider.
|
// Create a new OpenTelemetryLogBridge using the above LoggerProvider.
|
||||||
let otel_log_appender = OpenTelemetryLogBridge::new(&logger_provider);
|
let otel_log_appender = OpenTelemetryLogBridge::new(&logger_provider);
|
||||||
|
@ -137,9 +140,9 @@ async fn main() -> Result<(), Box<dyn Error + Send + Sync + 'static>> {
|
||||||
|
|
||||||
info!(target: "my-target", "hello from {}. My price is {}", "apple", 1.99);
|
info!(target: "my-target", "hello from {}. My price is {}", "apple", 1.99);
|
||||||
|
|
||||||
shutdown_tracer_provider();
|
global::shutdown_tracer_provider();
|
||||||
shutdown_logger_provider();
|
global::shutdown_logger_provider();
|
||||||
meter_provider.shutdown()?;
|
global::shutdown_meter_provider();
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
[1612](https://github.com/open-telemetry/opentelemetry-rust/pull/1612/files)
|
[1612](https://github.com/open-telemetry/opentelemetry-rust/pull/1612/files)
|
||||||
- [#1422](https://github.com/open-telemetry/opentelemetry-rust/pull/1422)
|
- [#1422](https://github.com/open-telemetry/opentelemetry-rust/pull/1422)
|
||||||
Fix metrics aggregation bug when using Views to drop attributes.
|
Fix metrics aggregation bug when using Views to drop attributes.
|
||||||
|
- [#1623](https://github.com/open-telemetry/opentelemetry-rust/pull/1623) Add Drop implementation for SdkMeterProvider, which shuts down
|
||||||
|
metricreaders, thereby allowing metrics still in memory to be flushed out.
|
||||||
|
|
||||||
## v0.22.1
|
## v0.22.1
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ use std::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use opentelemetry::{
|
use opentelemetry::{
|
||||||
|
global,
|
||||||
metrics::{noop::NoopMeterCore, Meter, MeterProvider, MetricsError, Result},
|
metrics::{noop::NoopMeterCore, Meter, MeterProvider, MetricsError, Result},
|
||||||
KeyValue,
|
KeyValue,
|
||||||
};
|
};
|
||||||
|
@ -113,6 +114,13 @@ impl SdkMeterProvider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Drop for SdkMeterProvider {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
if let Err(err) = self.shutdown() {
|
||||||
|
global::handle_error(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
impl MeterProvider for SdkMeterProvider {
|
impl MeterProvider for SdkMeterProvider {
|
||||||
fn versioned_meter(
|
fn versioned_meter(
|
||||||
&self,
|
&self,
|
||||||
|
@ -211,6 +219,7 @@ impl fmt::Debug for MeterProviderBuilder {
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::testing::metrics::metric_reader::TestMetricReader;
|
use crate::testing::metrics::metric_reader::TestMetricReader;
|
||||||
use crate::Resource;
|
use crate::Resource;
|
||||||
|
use opentelemetry::global;
|
||||||
use opentelemetry::Key;
|
use opentelemetry::Key;
|
||||||
use opentelemetry::KeyValue;
|
use opentelemetry::KeyValue;
|
||||||
use std::env;
|
use std::env;
|
||||||
|
@ -228,14 +237,14 @@ mod tests {
|
||||||
expect.map(|s| s.to_string())
|
expect.map(|s| s.to_string())
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
let reader = TestMetricReader {};
|
let reader = TestMetricReader::new();
|
||||||
let default_meter_provider = super::SdkMeterProvider::builder()
|
let default_meter_provider = super::SdkMeterProvider::builder()
|
||||||
.with_reader(reader)
|
.with_reader(reader)
|
||||||
.build();
|
.build();
|
||||||
assert_service_name(default_meter_provider, Some("unknown_service"));
|
assert_service_name(default_meter_provider, Some("unknown_service"));
|
||||||
|
|
||||||
// If user provided a resource, use that.
|
// If user provided a resource, use that.
|
||||||
let reader2 = TestMetricReader {};
|
let reader2 = TestMetricReader::new();
|
||||||
let custom_meter_provider = super::SdkMeterProvider::builder()
|
let custom_meter_provider = super::SdkMeterProvider::builder()
|
||||||
.with_reader(reader2)
|
.with_reader(reader2)
|
||||||
.with_resource(Resource::new(vec![KeyValue::new(
|
.with_resource(Resource::new(vec![KeyValue::new(
|
||||||
|
@ -250,7 +259,7 @@ mod tests {
|
||||||
Some("key1=value1, k2, k3=value2"),
|
Some("key1=value1, k2, k3=value2"),
|
||||||
|| {
|
|| {
|
||||||
// If `OTEL_RESOURCE_ATTRIBUTES` is set, read them automatically
|
// If `OTEL_RESOURCE_ATTRIBUTES` is set, read them automatically
|
||||||
let reader3 = TestMetricReader {};
|
let reader3 = TestMetricReader::new();
|
||||||
let env_resource_provider = super::SdkMeterProvider::builder()
|
let env_resource_provider = super::SdkMeterProvider::builder()
|
||||||
.with_reader(reader3)
|
.with_reader(reader3)
|
||||||
.build();
|
.build();
|
||||||
|
@ -273,7 +282,7 @@ mod tests {
|
||||||
"OTEL_RESOURCE_ATTRIBUTES",
|
"OTEL_RESOURCE_ATTRIBUTES",
|
||||||
Some("my-custom-key=env-val,k2=value2"),
|
Some("my-custom-key=env-val,k2=value2"),
|
||||||
|| {
|
|| {
|
||||||
let reader4 = TestMetricReader {};
|
let reader4 = TestMetricReader::new();
|
||||||
let user_provided_resource_config_provider = super::SdkMeterProvider::builder()
|
let user_provided_resource_config_provider = super::SdkMeterProvider::builder()
|
||||||
.with_reader(reader4)
|
.with_reader(reader4)
|
||||||
.with_resource(Resource::default().merge(&mut Resource::new(vec![
|
.with_resource(Resource::default().merge(&mut Resource::new(vec![
|
||||||
|
@ -295,7 +304,7 @@ mod tests {
|
||||||
);
|
);
|
||||||
|
|
||||||
// If user provided a resource, it takes priority during collision.
|
// If user provided a resource, it takes priority during collision.
|
||||||
let reader5 = TestMetricReader {};
|
let reader5 = TestMetricReader::new();
|
||||||
let no_service_name = super::SdkMeterProvider::builder()
|
let no_service_name = super::SdkMeterProvider::builder()
|
||||||
.with_reader(reader5)
|
.with_reader(reader5)
|
||||||
.with_resource(Resource::empty())
|
.with_resource(Resource::empty())
|
||||||
|
@ -303,4 +312,29 @@ mod tests {
|
||||||
|
|
||||||
assert_service_name(no_service_name, None);
|
assert_service_name(no_service_name, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_meter_provider_shutdown() {
|
||||||
|
let reader = TestMetricReader::new();
|
||||||
|
let provider = super::SdkMeterProvider::builder()
|
||||||
|
.with_reader(reader.clone())
|
||||||
|
.build();
|
||||||
|
global::set_meter_provider(provider.clone());
|
||||||
|
assert!(!provider
|
||||||
|
.is_shutdown
|
||||||
|
.load(std::sync::atomic::Ordering::Relaxed));
|
||||||
|
assert!(!reader.is_shutdown());
|
||||||
|
// create a meter and an instrument
|
||||||
|
let meter = global::meter("test");
|
||||||
|
let counter = meter.u64_counter("test_counter").init();
|
||||||
|
// no need to drop a meter for meter_provider shutdown
|
||||||
|
global::shutdown_meter_provider();
|
||||||
|
assert!(provider
|
||||||
|
.is_shutdown
|
||||||
|
.load(std::sync::atomic::Ordering::Relaxed));
|
||||||
|
assert!(reader.is_shutdown());
|
||||||
|
// TODO Fix: the instrument is still available, and can be used.
|
||||||
|
// While the reader is shutdown, and no collect is happening
|
||||||
|
counter.add(1, &[]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use std::sync::Weak;
|
use std::sync::{Arc, Mutex, Weak};
|
||||||
|
|
||||||
use crate::metrics::{
|
use crate::metrics::{
|
||||||
aggregation::Aggregation,
|
aggregation::Aggregation,
|
||||||
|
@ -9,8 +9,30 @@ use crate::metrics::{
|
||||||
};
|
};
|
||||||
use opentelemetry::metrics::Result;
|
use opentelemetry::metrics::Result;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct TestMetricReader {}
|
pub struct TestMetricReader {
|
||||||
|
is_shutdown: Arc<Mutex<bool>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TestMetricReader {
|
||||||
|
// Constructor to initialize the TestMetricReader
|
||||||
|
pub fn new() -> Self {
|
||||||
|
TestMetricReader {
|
||||||
|
is_shutdown: Arc::new(Mutex::new(false)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method to check if the reader is shutdown
|
||||||
|
pub fn is_shutdown(&self) -> bool {
|
||||||
|
*self.is_shutdown.lock().unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for TestMetricReader {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl MetricReader for TestMetricReader {
|
impl MetricReader for TestMetricReader {
|
||||||
fn register_pipeline(&self, _pipeline: Weak<Pipeline>) {}
|
fn register_pipeline(&self, _pipeline: Weak<Pipeline>) {}
|
||||||
|
@ -24,7 +46,12 @@ impl MetricReader for TestMetricReader {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn shutdown(&self) -> Result<()> {
|
fn shutdown(&self) -> Result<()> {
|
||||||
self.force_flush()
|
let result = self.force_flush();
|
||||||
|
{
|
||||||
|
let mut is_shutdown = self.is_shutdown.lock().unwrap();
|
||||||
|
*is_shutdown = true;
|
||||||
|
}
|
||||||
|
result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
#[cfg(all(feature = "metrics", feature = "trace"))]
|
#[cfg(all(feature = "metrics", feature = "trace"))]
|
||||||
use opentelemetry::{
|
use opentelemetry::{
|
||||||
metrics::MeterProvider as _,
|
global,
|
||||||
trace::{Span, Tracer, TracerProvider as _},
|
trace::{Span, Tracer, TracerProvider as _},
|
||||||
KeyValue,
|
KeyValue,
|
||||||
};
|
};
|
||||||
|
@ -22,17 +22,18 @@ fn init_trace() -> TracerProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(feature = "metrics", feature = "trace"))]
|
#[cfg(all(feature = "metrics", feature = "trace"))]
|
||||||
fn init_metrics() -> SdkMeterProvider {
|
fn init_metrics() {
|
||||||
let exporter = opentelemetry_stdout::MetricsExporter::default();
|
let exporter = opentelemetry_stdout::MetricsExporter::default();
|
||||||
let reader = PeriodicReader::builder(exporter, runtime::Tokio).build();
|
let reader = PeriodicReader::builder(exporter, runtime::Tokio).build();
|
||||||
SdkMeterProvider::builder().with_reader(reader).build()
|
let provider = SdkMeterProvider::builder().with_reader(reader).build();
|
||||||
|
global::set_meter_provider(provider);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
#[cfg(all(feature = "metrics", feature = "trace"))]
|
#[cfg(all(feature = "metrics", feature = "trace"))]
|
||||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let tracer_provider = init_trace();
|
let tracer_provider = init_trace();
|
||||||
let meter_provider = init_metrics();
|
init_metrics();
|
||||||
|
|
||||||
let tracer = tracer_provider.tracer("stdout-test");
|
let tracer = tracer_provider.tracer("stdout-test");
|
||||||
let mut span = tracer.start("test_span");
|
let mut span = tracer.start("test_span");
|
||||||
|
@ -43,11 +44,11 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
);
|
);
|
||||||
span.end();
|
span.end();
|
||||||
|
|
||||||
let meter = meter_provider.meter("stdout-test");
|
let meter = global::meter("stdout-test");
|
||||||
let c = meter.u64_counter("test_events").init();
|
let c = meter.u64_counter("test_events").init();
|
||||||
c.add(1, &[KeyValue::new("test_key", "test_value")]);
|
c.add(1, &[KeyValue::new("test_key", "test_value")]);
|
||||||
|
|
||||||
meter_provider.shutdown()?;
|
global::shutdown_meter_provider();
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,12 @@
|
||||||
|
|
||||||
## vNext
|
## vNext
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- [#1623](https://github.com/open-telemetry/opentelemetry-rust/pull/1623) Add global::meter_provider_shutdown
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
|
||||||
- Remove `urlencoding` crate dependency. [#1613](https://github.com/open-telemetry/opentelemetry-rust/pull/1613)
|
- Remove `urlencoding` crate dependency. [#1613](https://github.com/open-telemetry/opentelemetry-rust/pull/1613)
|
||||||
|
|
||||||
## v0.22.0
|
## v0.22.0
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::metrics::{self, Meter, MeterProvider};
|
use crate::metrics::{self, noop::NoopMeterProvider, Meter, MeterProvider};
|
||||||
use crate::KeyValue;
|
use crate::KeyValue;
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
|
@ -116,6 +116,11 @@ pub fn meter(name: impl Into<Cow<'static, str>>) -> Meter {
|
||||||
meter_provider().meter(name.into())
|
meter_provider().meter(name.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Shut down the current global [`MeterProvider`].
|
||||||
|
pub fn shutdown_meter_provider() {
|
||||||
|
set_meter_provider(NoopMeterProvider::new());
|
||||||
|
}
|
||||||
|
|
||||||
/// Creates a [`Meter`] with the name, version and schema url.
|
/// Creates a [`Meter`] with the name, version and schema url.
|
||||||
///
|
///
|
||||||
/// - name SHOULD uniquely identify the instrumentation scope, such as the instrumentation library (e.g. io.opentelemetry.contrib.mongodb), package, module or class name.
|
/// - name SHOULD uniquely identify the instrumentation scope, such as the instrumentation library (e.g. io.opentelemetry.contrib.mongodb), package, module or class name.
|
||||||
|
|
Loading…
Reference in New Issue