rustracing/lib.rs
1//! [OpenTracing][opentracing] API for Rust
2//!
3//! # Examples
4//!
5//! ```
6//! use rustracing::sampler::AllSampler;
7//! use rustracing::tag::Tag;
8//! use rustracing::Tracer;
9//! use std::thread;
10//! use std::time::Duration;
11//!
12//! // Creates a tracer
13//! let (span_tx, span_rx) = crossbeam_channel::bounded(10);
14//! let tracer = Tracer::with_sender(AllSampler, span_tx);
15//! {
16//! // Starts "parent" span
17//! let parent_span = tracer.span("parent").start_with_state(());
18//! thread::sleep(Duration::from_millis(10));
19//! {
20//! // Starts "child" span
21//! let mut child_span = tracer
22//! .span("child_span")
23//! .child_of(&parent_span)
24//! .tag(Tag::new("key", "value"))
25//! .start_with_state(());
26//!
27//! child_span.log(|log| {
28//! log.error().message("a log message");
29//! });
30//! } // The "child" span dropped and will be sent to `span_rx`
31//! } // The "parent" span dropped and will be sent to `span_rx`
32//!
33//! // Outputs finished spans to the standard output
34//! while let Ok(span) = span_rx.try_recv() {
35//! println!("# SPAN: {:?}", span);
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::tag::{StdTag, Tag};
75 use std::thread;
76 use std::time::Duration;
77
78 #[test]
79 fn it_works() {
80 let (span_tx, span_rx) = crossbeam_channel::bounded(10);
81 let tracer = Tracer::with_sender(AllSampler, span_tx);
82 {
83 let span = tracer.span("it_works").start_with_state(());
84 let mut child = span.child("child", |options| options.start_with_state(()));
85 child.set_tags(|| StdTag::peer_addr("127.0.0.1:80".parse().unwrap()));
86 }
87
88 let span = span_rx.try_recv().unwrap();
89 assert_eq!(span.operation_name(), "child");
90
91 let span = span_rx.try_recv().unwrap();
92 assert_eq!(span.operation_name(), "it_works");
93 }
94
95 #[test]
96 fn example_code_works() {
97 // Creates a tracer
98 let (span_tx, span_rx) = crossbeam_channel::bounded(10);
99 let tracer = Tracer::with_sender(AllSampler, span_tx);
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 // Outputs finished spans to the standard output
119 let mut count = 0;
120 while let Ok(span) = span_rx.try_recv() {
121 println!("# SPAN: {:?}", span);
122 count += 1;
123 }
124 assert_eq!(count, 2);
125 }
126
127 #[test]
128 fn nonblocking_on_full_queue() {
129 let (span_tx, span_rx) = crossbeam_channel::bounded(2);
130 let tracer = Tracer::with_sender(AllSampler, span_tx);
131 {
132 let span = tracer.span("first").start_with_state(());
133 let mut child = span.child("second", |options| options.start_with_state(()));
134 child.set_tags(|| StdTag::peer_addr("127.0.0.1:80".parse().unwrap()));
135 let _ = tracer.span("third").start_with_state(());
136 } // All spans dropped but only two ones will be sent to `span_rx` due to capacity limit, others are lost
137
138 // If the code continues, there was no blocking operation while sending span to the channel
139 assert!(span_rx.is_full());
140 assert_eq!(span_rx.len(), 2);
141
142 let span = span_rx.try_recv().unwrap();
143 assert_eq!(span.operation_name(), "third");
144
145 let span = span_rx.try_recv().unwrap();
146 assert_eq!(span.operation_name(), "second");
147
148 assert!(span_rx.is_empty());
149 }
150}