use super::TracerSource;
use opentelemetry::{
trace::{SpanBuilder, TraceContextExt as _, Tracer as _},
Context, ContextGuard,
};
use std::{
fmt::{Debug, Formatter},
ops::{Deref, DerefMut},
};
pub fn new_span_if_parent_sampled(
builder_fn: impl FnOnce() -> SpanBuilder,
tracer: TracerSource<'_>,
) -> Option<Context> {
Context::map_current(|current| {
current.span().span_context().is_sampled().then(|| {
let builder = builder_fn();
let span = tracer.get().build_with_context(builder, current);
current.with_span(span)
})
})
}
pub fn new_span_if_recording(
builder_fn: impl FnOnce() -> SpanBuilder,
tracer: TracerSource<'_>,
) -> Option<Context> {
Context::map_current(|current| {
current.span().is_recording().then(|| {
let builder = builder_fn();
let span = tracer.get().build_with_context(builder, current);
current.with_span(span)
})
})
}
pub struct Contextualized<T>(T, Option<Context>);
impl<T> Contextualized<T> {
pub fn new(value: T, cx: Option<Context>) -> Self {
Self(value, cx)
}
pub fn pass_thru(value: T) -> Self {
Self::new(
value,
Context::map_current(|current| current.has_active_span().then(|| current.clone())),
)
}
pub fn into_inner(self) -> (T, Option<Context>) {
(self.0, self.1)
}
pub fn attach(self) -> (T, Option<ContextGuard>) {
(self.0, self.1.map(|cx| cx.attach()))
}
}
impl<T: Clone> Clone for Contextualized<T> {
fn clone(&self) -> Self {
Self(self.0.clone(), self.1.clone())
}
}
impl<T: Debug> Debug for Contextualized<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_tuple("Contextualized")
.field(&self.0)
.field(&self.1)
.finish()
}
}
impl<T> Deref for Contextualized<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T> DerefMut for Contextualized<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn cover_contextualized() {
let cx = Contextualized::new(17, None);
let (i, cx) = cx.into_inner();
assert_eq!(i, 17);
assert!(cx.is_none());
let cx = Contextualized::pass_thru(17);
let (i, _guard) = cx.attach();
assert_eq!(i, 17);
}
}