Overview
A tracing library that allows you to efficiently record timestamps and metadata as datapoints within a span.
The [Chronograph] is the main entry point for starting spans.
Spans are recorded when they are dropped from memory where an underlying [SpanRecorder] is responsible for recording a span's data.
Spans
All spans contain a unique monotonically increasing ID, a start unix time, a start instant, an end instant, and user datapoints.
- The start unix time is the unix time at the start of the span.
- The start instant is a monotonic instant, accurate nanosecond timer elapsed from when the Cronograph was started.
- The start instant can be used to calculate the duration of the span.
- The end instant is a monotonic instant, accurate nanosecond timer elapsed from when the Cronograph was started.
- User datapoints are typically recorded as "instant" time measurements, but they can also include metadata as simple types.
Datapoints
User datapoints are recorded as a set of key-value pairs.
The [DatapointId] key is serialized as a u64 value.
- Any
impl Into<DatapointId>can be used as a datapoint. - A
u64will be used as-is. - A
&strwill be converted to a u64 using [zwohash] to derive a one-way, consistent u64 value.
The [RecordValue] can be one of the following types:
- Instant: A monotonic instant, accurate nanosecond timer elapsed from when the Cronograph was started.
- UnixTime: A unix time, as nanoseconds since epoch.
- Utf8String: A string value formatted as UTF-8.
- I32: A 32-bit signed integer.
- I64: A 64-bit signed integer.
- I128: A 128-bit signed integer.
- U32: A 32-bit unsigned integer.
- U64: A 64-bit unsigned integer.
- U128: A 128-bit unsigned integer.
- F32: A 32-bit floating point number.
- F64: A 64-bit floating point number.
Sampling
Spans can elect to be sampled. It is most efficient to use a sampling rate that is a power of two.
Global Chronograph
The global chronograph is a singleton that can be used to record spans.
It is initialized by calling the [init] function, and can be accessed with the [global] function.
Macros
The [macros] module provides macros for recording datapoints.
- [macros::start_span] can be used to start a new thread-local span from the global chronograph.
- [macros::record_instant] can be used to record an instant datapoint to the current thread-local span.
- [macros::record_unix_time] can be used to record a unix time datapoint.
- [macros::record_value] can be used to record a value datapoint.
- [macros::end_span] can be used to end the current thread-local span.
- [macros::take_span] can be used to take the current thread-local span.
Thread-local Spans
Thread-local spans can be used to record spans without needing to keep a reference to the [Span]. These are the same thread-local spans used by the [macros] module.
A thread-local span can be started with the [global] chronograph by calling the [start_threadlocal_span] function. You may alternative set it to any arbitraty span using the [set_threadlocal_span] function.
The thread-local span can be accessed with the [get_threadlocal_span] function or with the included [macros].
[end_threadlocal_span] and [take_threadlocal_span] can be used to end/take the current thread-local span
Global Instance Example with Macros
use Duration;
use sleep;
use *;
use *;
use *;
use Chronograph;
// Create a batching span recorder that will print each batch.
// Your code should elect to store the results somewhere.
// The collect callback function is called from a dedicated collector thread.
let recorder = start;
// Initialize the global chronograph and record some random spans.
init;
// Record some random data
for _ in 0..1000
// Give the collector thread a chance to wakeup and batch spans.
sleep;
Zero-Magic Example
Example without macros or global instances.
use *;
use *;
use Chronograph;
use sleep;
use Duration;
// Create a batching span recorder that will print each batch.
// Your code should elect to store the results somewhere.
// The collect callback function is called from a dedicated collector thread.
let recorder = start;
// Create a chronograph and record some random spans.
let chronograph = builder
.with_recorder
.with_sample_rate // it's most efficient to sample at a power of two
.build;
// Record some random data
for _ in 0..1000
// Give the collector thread a chance to wakeup and batch spans.
sleep;