cf_rustracing/
lib.rs

1//! [OpenTracing][opentracing] API for Rust
2//!
3//! # Examples
4//!
5//! ```
6//! use cf_rustracing::sampler::AllSampler;
7//! use cf_rustracing::tag::Tag;
8//! use cf_rustracing::Tracer;
9//! use std::thread;
10//! use std::time::Duration;
11//!
12//! # #[tokio::main]
13//! # async fn main() {
14//! // Creates a tracer
15//! let (tracer, mut span_rx) = Tracer::new(AllSampler);
16//! {
17//!     // Starts "parent" span
18//!     let parent_span = tracer.span("parent").start_with_state(());
19//!     thread::sleep(Duration::from_millis(10));
20//!     {
21//!         // Starts "child" span
22//!         let mut child_span = tracer
23//!             .span("child_span")
24//!             .child_of(&parent_span)
25//!             .tag(Tag::new("key", "value"))
26//!             .start_with_state(());
27//!
28//!         child_span.log(|log| {
29//!             log.error().message("a log message");
30//!         });
31//!     } // The "child" span dropped and will be sent to `span_rx`
32//! } // The "parent" span dropped and will be sent to `span_rx`
33//!
34//! println!("# SPAN: {:?}", span_rx.recv().await);
35//! println!("# SPAN: {:?}", span_rx.recv().await);
36//! # }
37//! ```
38//!
39//! As an actual usage example of the crate and an implmentation of the [OpenTracing] API,
40//! it may be helpful to looking at [rustracing_jaeger] crate.
41//!
42//! # References
43//!
44//! - [The OpenTracing Semantic Specification (v1.1)][specification]
45//!
46//! [opentracing]: http://opentracing.io/
47//! [specification]: https://github.com/opentracing/specification/blob/master/specification.md
48//! [rustracing_jaeger]: https://github.com/sile/rustracing_jaeger
49#![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
67/// This crate specific `Result` type.
68pub 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        // Creates a tracer
99        let (tracer, mut span_rx) = Tracer::new(AllSampler);
100        {
101            // Starts "parent" span
102            let parent_span = tracer.span("parent").start_with_state(());
103            thread::sleep(Duration::from_millis(10));
104            {
105                // Starts "child" span
106                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            } // The "child" span dropped and will be sent to `span_rx`
116        } // The "parent" span dropped and will be sent to `span_rx`
117
118        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}