blob: 6c112d6a9ca0132df3d8ad81e3c069a45710bf4e [file] [log] [blame]
use crate::{Span, TracingSpan};
/// Context represents the context of a tracing process.
/// All new span belonging to this tracing context should be created through this context.
pub trait Context {
fn create_entry_span(&mut self, operation_name: String, parent: Option<&Box<dyn Span>>) -> Box<dyn Span>;
fn create_exit_span(&mut self, operation_name: String, parent: Option<&Box<dyn Span>>) -> Box<dyn Span>;
fn create_local_span(&mut self, operation_name: String, parent: Option<&Box<dyn Span>>) -> Box<dyn Span>;
fn finish_span(&mut self, span: Box<dyn Span>);
}
pub struct TracingContext {
/// Span id sequence. Indicate the number of created spans.
next_seq: i32,
finished_spans: Vec<Box<dyn Span>>,
}
impl TracingContext {
/// Create a new instance
pub fn new() -> Box<dyn Context> {
Box::new(TracingContext {
next_seq: -1,
finished_spans: Vec::new(),
})
}
/// Fetch the next id for new span
fn next_span_id(&mut self) -> i32 {
self.next_seq = self.next_seq + 1;
self.next_seq
}
}
/// Default implementation of Context
impl Context for TracingContext {
fn create_entry_span(&mut self, operation_name: String, parent: Option<&Box<dyn Span>>) -> Box<dyn Span> {
TracingSpan::new_entry_span(operation_name, self.next_span_id(), match parent {
None => { -1 }
Some(s) => { s.span_id() }
})
}
fn create_exit_span(&mut self, operation_name: String, parent: Option<&Box<dyn Span>>) -> Box<dyn Span> {
TracingSpan::new_exit_span(operation_name, self.next_span_id(), match parent {
None => { -1 }
Some(s) => { s.span_id() }
})
}
fn create_local_span(&mut self, operation_name: String, parent: Option<&Box<dyn Span>>) -> Box<dyn Span> {
TracingSpan::new_local_span(operation_name, self.next_span_id(), match parent {
None => { -1 }
Some(s) => { s.span_id() }
})
}
fn finish_span(&mut self, mut span: Box<dyn Span>) {
if !span.is_ended() {
span.end();
}
self.finished_spans.push(span);
}
}
#[cfg(test)]
mod context_tests {
use crate::TracingContext;
#[test]
fn test_context_stack() {
let mut context = TracingContext::new();
let span1 = context.create_entry_span(String::from("op1"), None);
{
assert_eq!(span1.span_id(), 0);
let span2 = context.create_entry_span(String::from("op2"), Some(&span1));
{
assert_eq!(span2.span_id(), 1);
let mut span3 = context.create_entry_span(String::from("op3"), Some(&span2));
assert_eq!(span3.span_id(), 2);
context.finish_span(span3);
}
context.finish_span(span2);
}
context.finish_span(span1);
}
}