| Crates.io | chronograph |
| lib.rs | chronograph |
| version | 0.1.2 |
| created_at | 2025-06-13 02:16:29.690734+00 |
| updated_at | 2025-07-09 14:25:30.118476+00 |
| description | Timestamp Tracers |
| homepage | |
| repository | https://github.com/thill/chronograph |
| max_upload_size | |
| id | 1710967 |
| size | 45,512 |
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.
All spans contain a unique monotonically increasing ID, a start unix time, a start instant, an end instant, and user datapoints.
User datapoints are recorded as a set of key-value pairs.
The DatapointId key is serialized as a u64 value.
impl Into<DatapointId> can be used as a datapoint.u64 will be used as-is.&str will be converted to a u64 using zwohash to derive a one-way, consistent u64 value.The RecordValue can be one of the following types:
Spans can elect to be sampled. It is most efficient to use a sampling rate that is a power of two.
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.
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 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
use std::time::Duration;
use std::thread::sleep;
use chronograph::macros::*;
use chronograph::recorder::batch::*;
use chronograph::schema::*;
use chronograph::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 = BatchingSpanRecorder::start(
Box::new(|batch: SpanBatch| {
let serialized: Vec<u8> = batch.into();
let deserialized = SpanBatch::try_from(serialized.as_slice()).unwrap();
println!("collected {:?}", deserialized);
println!("serialized to {} bytes", serialized.len());
}),
BatchCollectionOptions::default().with_batch_size_threshold(4),
);
// Initialize the global chronograph and record some random spans.
chronograph::init(
Chronograph::builder()
.with_recorder(recorder)
.with_sample_rate(16) // it's most efficient to sample at a power of two
.build(),
);
// Record some random data
for _ in 0..1000 {
start_span!();
record_instant!("my_op_start");
record_value!("count", 42);
record_instant!("mt_op_end");
end_span!();
sleep(Duration::from_millis(1));
}
// Give the collector thread a chance to wakeup and batch spans.
sleep(Duration::from_millis(100));
Example without macros or global instances.
use chronograph::recorder::batch::*;
use chronograph::schema::*;
use chronograph::Chronograph;
use std::thread::sleep;
use std::time::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 = BatchingSpanRecorder::start(
Box::new(|batch: SpanBatch| {
let serialized: Vec<u8> = batch.into();
let deserialized = SpanBatch::try_from(serialized.as_slice()).unwrap();
println!("collected {:?}", deserialized);
println!("serialized to {} bytes", serialized.len());
}),
BatchCollectionOptions::default().with_batch_size_threshold(4),
);
// Create a chronograph and record some random spans.
let chronograph = Chronograph::builder()
.with_recorder(recorder)
.with_sample_rate(16) // it's most efficient to sample at a power of two
.build();
// Record some random data
for _ in 0..1000 {
let mut span = chronograph.start_span();
span.record_instant("my_op_start");
span.record_value("count", 42);
span.record_instant("my_op_end");
sleep(Duration::from_millis(1));
}
// Give the collector thread a chance to wakeup and batch spans.
sleep(Duration::from_millis(100));