Skip to main content

dial9_trace_format/
lib.rs

1//! # dial9-trace-format
2//!
3//! A compact binary trace format for recording timestamped events with
4//! schema-driven encoding. Events are described by schemas (registered at
5//! write time) and encoded with delta-compressed timestamps, LEB128 varints,
6//! and an interned string pool.
7//!
8//! ## Crate layout
9//!
10//! - [`encoder`] — high-level [`Encoder`](encoder::Encoder) for writing traces
11//! - [`decoder`] — streaming [`Decoder`](decoder::Decoder) for reading traces
12//! - [`codec`]   — wire-format types ([`WireTypeId`](codec::WireTypeId),
13//!   [`PoolEntry`](codec::PoolEntry)) that appear in decoded frames
14//! - [`schema`]  — [`SchemaEntry`] and
15//!   [`FieldDef`] describing event layouts
16//! - [`types`]   — field value types, the [`TraceField`]
17//!   trait, and the [`EventEncoder`] used by derived code
18
19pub mod codec;
20#[cfg(feature = "serde-deserialize")]
21pub mod de;
22pub mod decoder;
23pub mod encoder;
24pub(crate) mod leb128;
25pub mod schema;
26pub mod types;
27
28#[cfg(feature = "serde-deserialize")]
29pub use de::DeserError;
30pub use dial9_trace_format_derive::TraceEvent;
31pub use types::DynamicListRef;
32pub use types::DynamicMapRef;
33pub use types::EventEncoder;
34pub use types::FieldValue;
35pub use types::InternedStackFrames;
36pub use types::InternedString;
37pub use types::StackFrames;
38pub use types::TraceField;
39
40use schema::{FieldDef, SchemaEntry};
41
42/// Slots `1..STATIC_WIRE_ID_LIMIT` double as wire IDs and take the inline fast
43/// path in the encoder. Only `#[traceevent(wire_slot)]` types claim a slot, so
44/// this bounds how many event types share the fast range, dynamic registration
45/// starts here.
46pub const STATIC_WIRE_ID_LIMIT: u16 = 256;
47
48/// Global counter for assigning dense type slots to opted-in `TraceEvent`
49/// impls. Slot 0 is reserved as "unset".
50#[doc(hidden)]
51pub static __NEXT_TYPE_SLOT: std::sync::atomic::AtomicU16 = std::sync::atomic::AtomicU16::new(1);
52
53/// Trait implemented by `#[derive(TraceEvent)]` for compile-time event types.
54pub trait TraceEvent {
55    /// Per-type wire-ID slot. Default 0 means no slot (dynamic path);
56    /// `#[traceevent(wire_slot)]` overrides it to claim a fast-path slot.
57    fn type_slot() -> u16 {
58        0
59    }
60
61    /// The event type name (used in schema registration).
62    fn event_name() -> &'static str;
63    /// Field definitions for schema registration.
64    /// When `has_timestamp()` is true, the timestamp is NOT included here —
65    /// it is encoded in the event frame header.
66    fn field_defs() -> Vec<FieldDef>;
67    /// Whether this event type carries a packed timestamp in the event header.
68    fn has_timestamp() -> bool {
69        true
70    }
71    /// Return the event's timestamp in nanoseconds.
72    fn timestamp(&self) -> u64;
73    /// Encode this event's non-timestamp fields into the encoder.
74    fn encode_fields<W: std::io::Write>(
75        &self,
76        enc: &mut types::EventEncoder<'_, W>,
77    ) -> std::io::Result<()>;
78
79    /// Build a SchemaEntry for this event type.
80    fn schema_entry() -> SchemaEntry {
81        SchemaEntry {
82            name: Self::event_name().to_string(),
83            has_timestamp: Self::has_timestamp(),
84            fields: Self::field_defs(),
85            annotations: Vec::new(),
86        }
87    }
88}