Expand description
An OpenTracing implementation for rust.
This crate provides a generic Tracer interface following the OpenTracing specification that allows users (libraries, framework, applications) to implement distributed tracing across ecosystems and without committing to a specific distributed tracer.
This means that:
- Frameworks don’t have to impose a tracer on applications.
- Libraries can integrate their user’s traces.
- Applications lock end-users into a distributed tracer.
§Official API heads up
An Opentracing official API is in the works: https://github.com/opentracing/opentracing-rust
Once the official API crate and utility crate are finished I hope to deprecate this crate in favour of the official crates.
For that reason, development of this crate will be limited while I dedicate my time to help with the development of the offical opentracing-api crate.
Lessons learend while developing this crate will be valuable knowledge for opentracing-api. If you find any issue and or usability limit, please let me know!
§Architecture
At the core of this library are three types:
Tracer
: an interface to create and serialiseSpan
s.Span
: each instance represents an operation and its metadata.SpanContext
: a tracer-specific identifier of aSpan
.
§Configuraing a Tracer
Application developers MUST read this, library and framework
developers SHOULD still read it for completeness.
Every application and all the libraries and frameworks it uses
share a single Tracer
instance, unique to the entire process.
The instance should be passed around using a dependency injection
technique, of which there are many.
This crate provides a GlobalTracer
utility singleton for cases
where dependency injections are not usable.
Configuration of the Tracer
instance used across the process is the
responsibility of the application and should be performed as soon as
possible in the initialisation phase.
Tracers are implemented in separate crates and each tracers can be implemented as desired but there are two requirements of concrete tracers:
- Initialisation returns instance of
Tracer
. - A
crossbeam_channel::unbounded
is used by the tracer to sendFinishedSpan
s to a reporting thread.
The reporting thread is responsible for pushing the spans to the distributed tracer of choice.
In code:
extern crate opentracingrust;
use std::time::Duration;
use opentracingrust::tracers::NoopTracer;
use opentracingrust::utils::GlobalTracer;
use opentracingrust::utils::ReporterThread;
fn main() {
let (tracer, receiver) = NoopTracer::new();
let reporter = ReporterThread::new_with_duration(
receiver, Duration::from_millis(50), NoopTracer::report
);
GlobalTracer::init(tracer);
// ... snip ...
}
§Tracing an operation
Now that a Tracer
is configured and we are sending FinishedSpan
s to a
distributed tracing software, it is possible to trace operations.
Tracing operations is done by:
- Creating a named
Span
that represents the operation. - Attaching causality information with
SpanContext
s. - Adding any needed metadata.
- Finishing the span once the operation is done.
extern crate opentracingrust;
use std::time::Duration;
use opentracingrust::SpanContext;
use opentracingrust::StartOptions;
use opentracingrust::tracers::NoopTracer;
use opentracingrust::utils::GlobalTracer;
use opentracingrust::utils::ReporterThread;
fn main() {
let (tracer, receiver) = NoopTracer::new();
let reporter = ReporterThread::new_with_duration(
receiver, Duration::from_millis(50), NoopTracer::report
);
GlobalTracer::init(tracer);
// Once the tracer is configured we can start working.
start_working();
}
fn start_working() {
let mut root_span = GlobalTracer::get().span("start_working");
// The actual work is done in a sub-operation.
do_work(root_span.context().clone());
root_span.finish();
}
fn do_work(context: SpanContext) {
let mut span = GlobalTracer::get().span_with_options(
"do_work", StartOptions::default().child_of(context)
);
// ... do work ...
span.finish();
}
The examples/
directoy includes many more working
end-to-end examples of different use cases.
§The NoopTracer
As mentioned above, the crate does not provide concrete Tracer
s
but rather a standard interface for projects to bind against.
The NoopTracer
is the perfect tool to write tests with and a good default
for examples and projects that do not yet implement full tracing support.
Modules§
Structs§
- Auto
Finishing Span - A
Span
wrapper that finishes a span when dropped. - Finished
Span - A
Span
that represents a finished operation. - Impl
Context Box - Utility structure to create
ImplContext
s. - Log
- Structured logging information to attach to spans.
- Span
- Model of an in progress operation.
- Span
Context Trecer
-specific span and trace identifier and metadata.- Start
Options - Additional options that are passed to
Tracer::span
. - Tracer
- The library users interface to tracing.
Enums§
- Error
- Enumeration of all errors returned by OpenTracingRust.
- Extract
Format SpanContext
extraction format and source.- Inject
Format SpanContext
injection format and destination.- LogValue
- Enumeration of valid types for log values.
- Span
Reference - Enumerates all known relationships among
SpanContext
s. - TagValue
- Enumeration of valid types for tag values.
Traits§
- Impl
Context - Tracer implementation’s context details.
- MapCarrier
- Interface for HTTP header and text map carriers.
- Span
Reference Aware - Trait for structures that want to be wrapped in
ImplContextBox
s. - Tracer
Interface - Smallest set of operations that a concrete tracer must implement.
Type Aliases§
- Result
- Type alias for
Result
s that can fail with an OpenTracingRustError
. - Span
Receiver - Type alias for an
crossbeam_channel::Receiver
ofFinishedSpan
s. - Span
Sender - Type alias for an
crossbeam_channel::Sender
ofFinishedSpan
s.