#![warn(missing_docs)]
#![allow(clippy::new_ret_no_self)]
#[macro_use]
extern crate trackable;
pub use crate::error::{Error, ErrorKind};
pub use crate::tracer::Tracer;
pub mod carrier;
pub mod convert;
pub mod log;
pub mod sampler;
pub mod span;
pub mod tag;
mod error;
mod tracer;
pub type Result<T> = std::result::Result<T, Error>;
#[cfg(test)]
mod tests {
use super::*;
use crate::sampler::AllSampler;
use crate::span::{FinishedSpan, RoutingMetadata, Span};
use crate::tag::{StdTag, Tag, TagValue};
use std::sync::atomic::{AtomicI64, Ordering};
use std::sync::Arc;
use std::thread;
use std::time::Duration;
#[derive(Debug)]
struct TestRouting {
zone_id: u64,
account_id: u64,
}
impl RoutingMetadata for TestRouting {
fn group_key(&self) -> String {
format!("{}|{}", self.zone_id, self.account_id)
}
fn encode(&self) -> String {
format!("zone={};account={}", self.zone_id, self.account_id)
}
}
#[tokio::test]
async fn it_works() {
let (tracer, mut span_rx) = Tracer::new(AllSampler);
{
let span = tracer.span("it_works").start_with_state(());
let mut child = span.child("child", |options| options.start_with_state(()));
child.set_tags(|| StdTag::peer_addr("127.0.0.1:80".parse().unwrap()));
}
let span = span_rx.recv().await.unwrap();
assert_eq!(span.operation_name(), "child");
let span = span_rx.recv().await.unwrap();
assert_eq!(span.operation_name(), "it_works");
}
#[tokio::test]
async fn example_code_works() {
let (tracer, mut span_rx) = Tracer::new(AllSampler);
{
let parent_span = tracer.span("parent").start_with_state(());
thread::sleep(Duration::from_millis(10));
{
let mut child_span = tracer
.span("child_span")
.child_of(&parent_span)
.tag(Tag::new("key", "value"))
.start_with_state(());
child_span.log(|log| {
log.error().message("a log message");
});
} }
let span = span_rx.recv().await.unwrap();
assert_eq!(span.operation_name(), "child_span");
let span = span_rx.recv().await.unwrap();
assert_eq!(span.operation_name(), "parent");
}
#[test]
fn finish_callback() {
let span_counter = AtomicI64::new(1);
let finish_cb = move |span: &mut Span<()>| {
let call_num = span_counter.fetch_add(1, Ordering::Relaxed);
span.set_tag(|| Tag::new("callback-call", call_num));
};
let (tracer, mut span_rx) = Tracer::new(AllSampler);
{
let parent_span = tracer
.span("parent")
.finish_callback(finish_cb)
.start_with_state(());
let child_with_cb = parent_span.child("child_with_cb", |s| s.start_with_state(()));
let mut child_no_cb = parent_span.child("child_no_cb", |s| s.start_with_state(()));
child_no_cb.take_finish_callback();
drop(child_with_cb);
drop(child_no_cb);
drop(parent_span);
}
let find_span_counter = |s: &FinishedSpan<()>| match s
.tags()
.iter()
.find(|t| t.name() == "callback-call")?
.value()
{
TagValue::Integer(v) => Some(*v),
v => panic!("invalid `callback-call` tag value: {v:?}"),
};
let child_with_cb = span_rx.try_recv().unwrap();
assert_eq!(child_with_cb.operation_name(), "child_with_cb");
assert_eq!(find_span_counter(&child_with_cb), Some(1));
let child_no_cb = span_rx.try_recv().unwrap();
assert_eq!(child_no_cb.operation_name(), "child_no_cb");
assert_eq!(find_span_counter(&child_no_cb), None);
let parent_span = span_rx.try_recv().unwrap();
assert_eq!(parent_span.operation_name(), "parent");
assert_eq!(find_span_counter(&parent_span), Some(2));
}
#[allow(dead_code)]
fn span_can_be_shared() {
fn trait_check<T: Send + Sync>() {}
trait_check::<Span<()>>();
}
#[test]
fn routing_inherited_by_children() {
let routing = Arc::new(TestRouting {
zone_id: 7,
account_id: 99,
});
let expected_group_key = routing.group_key();
let expected_encoded = routing.encode();
let (tracer, mut span_rx) = Tracer::new(AllSampler);
{
let parent = tracer
.span("parent")
.routing(routing.clone())
.start_with_state(());
let child = parent.child("child", |s| s.start_with_state(()));
let grandchild = child.child("grandchild", |s| s.start_with_state(()));
drop(grandchild);
drop(child);
drop(parent);
}
for expected in ["grandchild", "child", "parent"] {
let span = span_rx.try_recv().unwrap();
assert_eq!(span.operation_name(), expected);
let r = span
.routing()
.unwrap_or_else(|| panic!("{expected} should inherit routing"));
assert_eq!(r.group_key(), expected_group_key);
assert_eq!(r.encode(), expected_encoded);
}
}
#[test]
fn routing_last_set_wins() {
let second = Arc::new(TestRouting {
zone_id: 2,
account_id: 2,
});
let expected_group_key = second.group_key();
let expected_encoded = second.encode();
let (tracer, mut span_rx) = Tracer::new(AllSampler);
{
let span = tracer
.span("span")
.routing(Arc::new(TestRouting {
zone_id: 1,
account_id: 1,
}))
.routing(second.clone())
.start_with_state(());
drop(span);
}
let span = span_rx.try_recv().unwrap();
let r = span.routing().expect("routing should be set");
assert_eq!(r.group_key(), expected_group_key);
assert_eq!(r.encode(), expected_encoded);
}
}