use crate::span_context::HSpanContext;
use crate::span_wrap::SpanWrap;
use rustracing::sampler::*;
use rustracing::span::StartSpanOptions;
use rustracing_jaeger::Span as RjSpan;
use rustracing_jaeger::{span::SpanContextState, Tracer};
use std::borrow::Cow;
#[derive(Debug, Shrinkwrap)]
#[shrinkwrap(mutable)]
pub struct HSpan(pub RjSpan);
impl From<RjSpan> for HSpan {
fn from(span: RjSpan) -> HSpan {
HSpan(span)
}
}
impl HSpan {
pub fn event<S: Into<Cow<'static, str>>>(&mut self, msg: S) {
self.0.log(|l| {
l.std().event(msg);
})
}
pub fn error<S: Into<Cow<'static, str>>>(&mut self, kind: S, msg: S) {
self.0.log(|l| {
l.error().kind(kind).message(msg);
})
}
pub fn context(&self) -> Option<HSpanContext> {
self.0.context().map(|ctx| HSpanContext(ctx.to_owned()))
}
pub fn child_<'a, N: Into<Cow<'static, str>>, F>(&'a self, operation_name: N, f: F) -> RjSpan
where
F: FnOnce(StartSpanOptions<'_, AllSampler, SpanContextState>) -> RjSpan,
{
self.0.child(operation_name, f)
}
pub fn follower_<'a, N: Into<Cow<'static, str>>, F>(&'a self, operation_name: N, f: F) -> RjSpan
where
F: FnOnce(StartSpanOptions<'_, AllSampler, SpanContextState>) -> RjSpan,
{
self.0.follower(operation_name, f)
}
pub fn child<S: Into<Cow<'static, str>>>(&self, operation_name: S) -> Self {
self.0.child(operation_name, |o| o.start()).into()
}
pub fn follower<S: Into<Cow<'static, str>>>(&self, operation_name: S) -> Self {
self.0.follower(operation_name, |o| o.start()).into()
}
pub fn wrap<T>(self, data: T) -> SpanWrap<T> {
SpanWrap::new(data, self.0.context().cloned().map(HSpanContext))
}
pub fn noop() -> Self {
noop("no-op, intentionally disconnected RjSpan".into())
}
pub fn todo(reason: &'static str) -> Self {
noop(format!("TODO: {}", reason))
}
pub fn fixme() -> Self {
noop("not yet hooked up".into())
}
}
pub fn null_tracer() -> Tracer {
Tracer::new(NullSampler).0
}
fn noop(name: String) -> HSpan {
null_tracer().span(name).start().into()
}
pub fn test_span(name: &str) -> HSpan {
noop(name.into())
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{tracer_console, Tag};
#[test]
fn trace_test() {
let (tracer, mut reporter) = tracer_console::new_tracer_with_console_reporter();
{
let parent_span: HSpan = tracer.span("parent").start().into();
{
let mut child_span = parent_span.child("child_span");
child_span.set_tag(|| Tag::new("id", "A"));
child_span.event("a log message");
std::thread::sleep(std::time::Duration::from_millis(10));
let mut child_b_span = parent_span.child("child_b_span");
child_b_span.set_tag(|| Tag::new("id", "B"));
let mut _grand_child_span = child_span.child("grand_child_span");
let mut _follower_span = child_span.follower("child_follower_span");
} let parent_follower_span = parent_span.follower("parent_follower_span");
let _parent_follower_b_span = parent_span.follower("parent_follower_b_span");
let mut _parent_follower_follower_span =
parent_follower_span.follower("parent_follower_follower_span");
}
let count = reporter.drain();
assert_eq!(8, count);
reporter.print(false);
}
}