use crate::{
reporter::{CollectItem, DynReport, Report},
trace::trace_context::TracingContext,
};
use std::sync::{Arc, Weak};
use tokio::sync::OnceCell;
static GLOBAL_TRACER: OnceCell<Tracer> = OnceCell::const_new();
pub fn set_global_tracer(tracer: Tracer) {
if GLOBAL_TRACER.set(tracer).is_err() {
panic!("global tracer has set")
}
}
pub fn global_tracer() -> &'static Tracer {
GLOBAL_TRACER.get().expect("global tracer haven't set")
}
pub fn create_trace_context() -> TracingContext {
global_tracer().create_trace_context()
}
struct Inner {
service_name: String,
instance_name: String,
reporter: Box<DynReport>,
}
#[derive(Clone)]
pub struct Tracer {
inner: Arc<Inner>,
}
impl Tracer {
pub fn new(
service_name: impl Into<String>,
instance_name: impl Into<String>,
reporter: impl Report + Send + Sync + 'static,
) -> Self {
Self {
inner: Arc::new(Inner {
service_name: service_name.into(),
instance_name: instance_name.into(),
reporter: Box::new(reporter),
}),
}
}
pub fn service_name(&self) -> &str {
&self.inner.service_name
}
pub fn instance_name(&self) -> &str {
&self.inner.instance_name
}
pub fn create_trace_context(&self) -> TracingContext {
TracingContext::new(
&self.inner.service_name,
&self.inner.instance_name,
self.downgrade(),
)
}
pub(crate) fn finalize_context(&self, context: &mut TracingContext) {
let segment_object = context.convert_to_segment_object();
self.inner
.reporter
.report(CollectItem::Trace(Box::new(segment_object)));
}
fn downgrade(&self) -> WeakTracer {
WeakTracer {
inner: Arc::downgrade(&self.inner),
}
}
}
#[derive(Clone)]
pub(crate) struct WeakTracer {
inner: Weak<Inner>,
}
impl WeakTracer {
pub(crate) fn upgrade(&self) -> Option<Tracer> {
Weak::upgrade(&self.inner).map(|inner| Tracer { inner })
}
}
#[cfg(test)]
mod tests {
use super::*;
#[allow(dead_code)]
trait AssertSend: Send {}
impl AssertSend for Tracer {}
}