1#![warn(missing_docs)]
50#![allow(clippy::new_ret_no_self)]
51#[macro_use]
52extern crate trackable;
53
54pub use crate::error::{Error, ErrorKind};
55pub use crate::tracer::Tracer;
56
57pub mod carrier;
58pub mod convert;
59pub mod log;
60pub mod sampler;
61pub mod span;
62pub mod tag;
63
64mod error;
65mod tracer;
66
67pub type Result<T> = std::result::Result<T, Error>;
69
70#[cfg(test)]
71mod tests {
72 use super::*;
73 use crate::sampler::AllSampler;
74 use crate::span::{FinishedSpan, Span};
75 use crate::tag::{StdTag, Tag, TagValue};
76 use std::sync::atomic::{AtomicI64, Ordering};
77 use std::thread;
78 use std::time::Duration;
79
80 #[tokio::test]
81 async fn it_works() {
82 let (tracer, mut span_rx) = Tracer::new(AllSampler);
83 {
84 let span = tracer.span("it_works").start_with_state(());
85 let mut child = span.child("child", |options| options.start_with_state(()));
86 child.set_tags(|| StdTag::peer_addr("127.0.0.1:80".parse().unwrap()));
87 }
88
89 let span = span_rx.recv().await.unwrap();
90 assert_eq!(span.operation_name(), "child");
91
92 let span = span_rx.recv().await.unwrap();
93 assert_eq!(span.operation_name(), "it_works");
94 }
95
96 #[tokio::test]
97 async fn example_code_works() {
98 let (tracer, mut span_rx) = Tracer::new(AllSampler);
100 {
101 let parent_span = tracer.span("parent").start_with_state(());
103 thread::sleep(Duration::from_millis(10));
104 {
105 let mut child_span = tracer
107 .span("child_span")
108 .child_of(&parent_span)
109 .tag(Tag::new("key", "value"))
110 .start_with_state(());
111
112 child_span.log(|log| {
113 log.error().message("a log message");
114 });
115 } } let span = span_rx.recv().await.unwrap();
119 assert_eq!(span.operation_name(), "child_span");
120
121 let span = span_rx.recv().await.unwrap();
122 assert_eq!(span.operation_name(), "parent");
123 }
124
125 #[test]
126 fn finish_callback() {
127 let span_counter = AtomicI64::new(1);
128 let finish_cb = move |span: &mut Span<()>| {
129 let call_num = span_counter.fetch_add(1, Ordering::Relaxed);
130 span.set_tag(|| Tag::new("callback-call", call_num));
131 };
132
133 let (tracer, mut span_rx) = Tracer::new(AllSampler);
134 {
135 let parent_span = tracer
136 .span("parent")
137 .finish_callback(finish_cb)
138 .start_with_state(());
139
140 let child_with_cb = parent_span.child("child_with_cb", |s| s.start_with_state(()));
141 let mut child_no_cb = parent_span.child("child_no_cb", |s| s.start_with_state(()));
142 child_no_cb.take_finish_callback();
143
144 drop(child_with_cb);
145 drop(child_no_cb);
146 drop(parent_span);
147 }
148
149 let find_span_counter = |s: &FinishedSpan<()>| match s
150 .tags()
151 .iter()
152 .find(|t| t.name() == "callback-call")?
153 .value()
154 {
155 TagValue::Integer(v) => Some(*v),
156 v => panic!("invalid `callback-call` tag value: {v:?}"),
157 };
158
159 let child_with_cb = span_rx.try_recv().unwrap();
160 assert_eq!(child_with_cb.operation_name(), "child_with_cb");
161 assert_eq!(find_span_counter(&child_with_cb), Some(1));
162
163 let child_no_cb = span_rx.try_recv().unwrap();
164 assert_eq!(child_no_cb.operation_name(), "child_no_cb");
165 assert_eq!(find_span_counter(&child_no_cb), None);
166
167 let parent_span = span_rx.try_recv().unwrap();
168 assert_eq!(parent_span.operation_name(), "parent");
169 assert_eq!(find_span_counter(&parent_span), Some(2));
170 }
171
172 #[allow(dead_code)]
173 fn span_can_be_shared() {
174 fn trait_check<T: Send + Sync>() {}
175 trait_check::<Span<()>>();
176 }
177}