use crate::{
global,
metrics::{sdk_api, MetricsError, Number},
KeyValue,
};
use std::fmt;
use std::marker;
use std::sync::Arc;
#[derive(Debug)]
pub struct Observation {
number: Number,
instrument: Arc<dyn sdk_api::AsyncInstrumentCore>,
}
impl Observation {
pub(crate) fn new(number: Number, instrument: Arc<dyn sdk_api::AsyncInstrumentCore>) -> Self {
Observation { number, instrument }
}
pub fn number(&self) -> &Number {
&self.number
}
pub fn instrument(&self) -> &Arc<dyn sdk_api::AsyncInstrumentCore> {
&self.instrument
}
}
type F64ObserverCallback = Box<dyn Fn(ObserverResult<f64>) + Send + Sync>;
type U64ObserverCallback = Box<dyn Fn(ObserverResult<u64>) + Send + Sync>;
type I64ObserverCallback = Box<dyn Fn(ObserverResult<i64>) + Send + Sync>;
type BatchObserverCallback = Box<dyn Fn(BatchObserverResult) + Send + Sync>;
pub struct ObserverResult<T> {
instrument: Arc<dyn sdk_api::AsyncInstrumentCore>,
f: fn(&[KeyValue], &[Observation]),
_marker: marker::PhantomData<T>,
}
impl<T> ObserverResult<T>
where
T: Into<Number>,
{
fn new(
instrument: Arc<dyn sdk_api::AsyncInstrumentCore>,
f: fn(&[KeyValue], &[Observation]),
) -> Self {
ObserverResult {
instrument,
f,
_marker: marker::PhantomData,
}
}
pub fn observe(&self, value: T, attributes: &[KeyValue]) {
(self.f)(
attributes,
&[Observation {
number: value.into(),
instrument: self.instrument.clone(),
}],
)
}
}
impl<T> fmt::Debug for ObserverResult<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ObserverResult")
.field("instrument", &self.instrument)
.field("f", &"fn(&[KeyValue], &[Observation])")
.finish()
}
}
pub struct BatchObserverResult {
f: fn(&[KeyValue], &[Observation]),
}
impl fmt::Debug for BatchObserverResult {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("BatchObserverResult")
.field("f", &"fn(&[KeyValue], &[Observation])")
.finish()
}
}
impl BatchObserverResult {
fn new(f: fn(&[KeyValue], &[Observation])) -> Self {
BatchObserverResult { f }
}
pub fn observe(&self, attributes: &[KeyValue], observations: &[Observation]) {
(self.f)(attributes, observations)
}
}
pub enum AsyncRunner {
F64(F64ObserverCallback),
I64(I64ObserverCallback),
U64(U64ObserverCallback),
Batch(BatchObserverCallback),
}
impl AsyncRunner {
pub fn run(
&self,
instrument: &Option<Arc<dyn sdk_api::AsyncInstrumentCore>>,
f: fn(&[KeyValue], &[Observation]),
) {
match (instrument, self) {
(Some(i), AsyncRunner::F64(run)) => run(ObserverResult::new(i.clone(), f)),
(Some(i), AsyncRunner::I64(run)) => run(ObserverResult::new(i.clone(), f)),
(Some(i), AsyncRunner::U64(run)) => run(ObserverResult::new(i.clone(), f)),
(None, AsyncRunner::Batch(run)) => run(BatchObserverResult::new(f)),
_ => global::handle_error(MetricsError::Other(
"Invalid async runner / instrument pair".into(),
)),
}
}
}
impl fmt::Debug for AsyncRunner {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
AsyncRunner::F64(_) => f
.debug_struct("AsyncRunner::F64")
.field("closure", &"Fn(ObserverResult)")
.finish(),
AsyncRunner::I64(_) => f
.debug_struct("AsyncRunner::I64")
.field("closure", &"Fn(ObserverResult)")
.finish(),
AsyncRunner::U64(_) => f
.debug_struct("AsyncRunner::U64")
.field("closure", &"Fn(ObserverResult)")
.finish(),
AsyncRunner::Batch(_) => f
.debug_struct("AsyncRunner::Batch")
.field("closure", &"Fn(BatchObserverResult)")
.finish(),
}
}
}