Skip to content

Commit ca9d3ba

Browse files
committed
Refactor get/set_telemetry_provider functions to return Result
1 parent d8b519d commit ca9d3ba

File tree

2 files changed

+46
-21
lines changed

2 files changed

+46
-21
lines changed

rust-runtime/aws-smithy-observability/src/error.rs

+19-2
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,10 @@ pub struct ObservabilityError {
2121
#[non_exhaustive]
2222
#[derive(Debug)]
2323
pub enum ErrorKind {
24-
/// An error setting the `GlobalTelemetryProvider``
24+
/// An error setting the global [crate::TelemetryProvider]
2525
SettingGlobalProvider,
26+
/// An error getting the global [crate::TelemetryProvider]
27+
GettingGlobalProvider,
2628
/// Error flushing metrics pipeline
2729
MetricsFlush,
2830
/// Error gracefully shutting down Metrics Provider
@@ -54,7 +56,10 @@ impl fmt::Display for ObservabilityError {
5456
match &self.kind {
5557
ErrorKind::Other => write!(f, "unclassified error"),
5658
ErrorKind::SettingGlobalProvider => {
57-
write!(f, "failed to set global telemetry provider")
59+
write!(f, "failed to set global TelemetryProvider")
60+
}
61+
ErrorKind::GettingGlobalProvider => {
62+
write!(f, "failed to get global TelemetryProvider")
5863
}
5964
ErrorKind::MetricsFlush => write!(f, "failed to flush metrics pipeline"),
6065
ErrorKind::MetricsShutdown => write!(f, "failed to shutdown metrics provider"),
@@ -67,3 +72,15 @@ impl std::error::Error for ObservabilityError {
6772
Some(self.source.as_ref())
6873
}
6974
}
75+
76+
/// An simple error to represent issues with the global [crate::TelemetryProvider].
77+
#[derive(Debug)]
78+
pub struct GlobalTelemetryProviderError;
79+
80+
impl std::error::Error for GlobalTelemetryProviderError {}
81+
82+
impl fmt::Display for GlobalTelemetryProviderError {
83+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
84+
write!(f, "GlobalTelemetryProviderError")
85+
}
86+
}

rust-runtime/aws-smithy-observability/src/global.rs

+27-19
Original file line numberDiff line numberDiff line change
@@ -11,37 +11,45 @@ use std::{
1111
sync::{Arc, RwLock},
1212
};
1313

14-
use crate::provider::{GlobalTelemetryProvider, TelemetryProvider};
14+
use crate::{
15+
error::{ErrorKind, GlobalTelemetryProviderError},
16+
provider::{GlobalTelemetryProvider, TelemetryProvider},
17+
ObservabilityError,
18+
};
1519

1620
// Statically store the global provider
1721
static GLOBAL_TELEMETRY_PROVIDER: Lazy<RwLock<GlobalTelemetryProvider>> =
1822
Lazy::new(|| RwLock::new(GlobalTelemetryProvider::new(TelemetryProvider::default())));
1923

2024
/// Set the current global [TelemetryProvider].
2125
///
22-
/// This is meant to be run once at the beginning of an application. It will panic if two threads
23-
/// attempt to call it at the same time.
24-
pub fn set_telemetry_provider(new_provider: TelemetryProvider) {
25-
// TODO(smithyObservability): would probably be nicer to return a Result here, but the Guard held by the error from
26-
// .try_write is not Send so I struggled to build an ObservabilityError from it
27-
let mut old_provider = GLOBAL_TELEMETRY_PROVIDER
28-
.try_write()
29-
.expect("GLOBAL_TELEMETRY_PROVIDER RwLock Poisoned");
26+
/// This is meant to be run once at the beginning of an application. Will return an [Err] if the
27+
/// [RwLock] holding the global [TelemetryProvider] is locked or poisoned.
28+
pub fn set_telemetry_provider(new_provider: TelemetryProvider) -> Result<(), ObservabilityError> {
29+
if let Ok(mut old_provider) = GLOBAL_TELEMETRY_PROVIDER.try_write() {
30+
let new_global_provider = GlobalTelemetryProvider::new(new_provider);
3031

31-
let new_global_provider = GlobalTelemetryProvider::new(new_provider);
32+
let _ = mem::replace(&mut *old_provider, new_global_provider);
3233

33-
let _ = mem::replace(&mut *old_provider, new_global_provider);
34+
Ok(())
35+
} else {
36+
Err(ObservabilityError::new(
37+
ErrorKind::GettingGlobalProvider,
38+
GlobalTelemetryProviderError,
39+
))
40+
}
3441
}
3542

36-
/// Get an [Arc] reference to the current global [TelemetryProvider]. [None] is returned if the [RwLock] containing
37-
/// the global [TelemetryProvider] is poisoned or is currently locked by a writer.
38-
pub fn get_telemetry_provider() -> Option<Arc<TelemetryProvider>> {
39-
// TODO(smithyObservability): would probably make more sense to return a Result rather than an Option here, but the Guard held by the error from
40-
// .try_read is not Send so I struggled to build an ObservabilityError from it
43+
/// Get an [Arc] reference to the current global [TelemetryProvider]. Will return an [Err] if the
44+
/// [RwLock] holding the global [TelemetryProvider] is locked or poisoned.
45+
pub fn get_telemetry_provider() -> Result<Arc<TelemetryProvider>, ObservabilityError> {
4146
if let Ok(tp) = GLOBAL_TELEMETRY_PROVIDER.try_read() {
42-
Some(tp.telemetry_provider().clone())
47+
Ok(tp.telemetry_provider().clone())
4348
} else {
44-
None
49+
Err(ObservabilityError::new(
50+
ErrorKind::GettingGlobalProvider,
51+
GlobalTelemetryProviderError,
52+
))
4553
}
4654
}
4755

@@ -59,7 +67,7 @@ mod tests {
5967
let my_provider = TelemetryProvider::default();
6068

6169
// Set the new counter and get a reference to the old one
62-
set_telemetry_provider(my_provider);
70+
set_telemetry_provider(my_provider).unwrap();
6371
}
6472

6573
#[test]

0 commit comments

Comments
 (0)