chronograph/
schema.rs

1//! Serialization and deserialization of chronograph data, utilizing rkyv for fast serialization and deserialization.
2
3use std::{hash::Hasher, time::SystemTime};
4
5use rkyv::util::AlignedVec;
6use zwohash::ZwoHasher;
7
8#[derive(Debug, Clone, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
9pub struct SpanBatch {
10    pub spans: Vec<SpanData>,
11}
12
13#[derive(Debug, Clone, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
14pub struct SpanData {
15    pub span_id: u64,
16    pub start_unix_time: i64,
17    pub start_instant: u64,
18    pub end_instant: u64,
19    pub records: Vec<RecordData>,
20}
21
22#[derive(Debug, Clone, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
23pub struct RecordData {
24    pub datapoint_id: DatapointId,
25    pub value: RecordValue,
26}
27
28#[derive(
29    Debug, Clone, Copy, PartialEq, Eq, Hash, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize,
30)]
31pub struct DatapointId {
32    pub value: u64,
33}
34
35#[derive(Debug, Clone, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
36pub enum RecordValue {
37    /// Monotonic instant (accurate nanosecond timer elapsed from when the Cronograph was started)
38    Instant(u64),
39    /// Unix timestamp (as nanoseconds since epoch)
40    UnixTime(i64),
41    /// An arbitrary string value formatted as UTF-8
42    Utf8String(String),
43    /// An arbitrary i32 value
44    I32(i32),
45    /// An arbitrary i64 value
46    I64(i64),
47    /// An arbitrary i128 value
48    I128(i128),
49    /// An arbitrary u32 value
50    U32(u32),
51    /// An arbitrary u64 value
52    U64(u64),
53    /// An arbitrary u128 value
54    U128(u128),
55    /// An arbitrary f64 value
56    F32(f32),
57    /// An arbitrary f64 value
58    F64(f64),
59}
60
61impl From<&SpanBatch> for AlignedVec {
62    fn from(value: &SpanBatch) -> Self {
63        rkyv::to_bytes::<rkyv::rancor::Error>(value).unwrap_or_default()
64    }
65}
66
67impl From<SpanBatch> for AlignedVec {
68    fn from(value: SpanBatch) -> Self {
69        rkyv::to_bytes::<rkyv::rancor::Error>(&value).unwrap_or_default()
70    }
71}
72
73impl From<&SpanBatch> for Vec<u8> {
74    fn from(value: &SpanBatch) -> Self {
75        rkyv::to_bytes::<rkyv::rancor::Error>(value)
76            .unwrap_or_default()
77            .into_vec()
78    }
79}
80
81impl From<SpanBatch> for Vec<u8> {
82    fn from(value: SpanBatch) -> Self {
83        rkyv::to_bytes::<rkyv::rancor::Error>(&value)
84            .unwrap_or_default()
85            .into_vec()
86    }
87}
88
89impl TryFrom<&[u8]> for SpanBatch {
90    type Error = rkyv::rancor::Error;
91    fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
92        rkyv::from_bytes::<Self, rkyv::rancor::Error>(value)
93    }
94}
95
96impl From<&SpanData> for AlignedVec {
97    fn from(value: &SpanData) -> Self {
98        rkyv::to_bytes::<rkyv::rancor::Error>(value).unwrap_or_default()
99    }
100}
101
102impl From<SpanData> for AlignedVec {
103    fn from(value: SpanData) -> Self {
104        rkyv::to_bytes::<rkyv::rancor::Error>(&value).unwrap_or_default()
105    }
106}
107
108impl From<&SpanData> for Vec<u8> {
109    fn from(value: &SpanData) -> Self {
110        rkyv::to_bytes::<rkyv::rancor::Error>(value)
111            .unwrap_or_default()
112            .into_vec()
113    }
114}
115
116impl From<SpanData> for Vec<u8> {
117    fn from(value: SpanData) -> Self {
118        rkyv::to_bytes::<rkyv::rancor::Error>(&value)
119            .unwrap_or_default()
120            .into_vec()
121    }
122}
123
124impl TryFrom<&[u8]> for SpanData {
125    type Error = rkyv::rancor::Error;
126    fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
127        rkyv::from_bytes::<Self, rkyv::rancor::Error>(value)
128    }
129}
130
131impl From<u64> for DatapointId {
132    fn from(value: u64) -> Self {
133        Self { value }
134    }
135}
136
137impl From<&str> for DatapointId {
138    fn from(value: &str) -> Self {
139        let mut hasher = ZwoHasher::default();
140        hasher.write(value.as_bytes());
141        Self {
142            value: hasher.finish(),
143        }
144    }
145}
146
147impl From<SystemTime> for RecordValue {
148    fn from(value: SystemTime) -> Self {
149        Self::UnixTime(
150            value
151                .duration_since(SystemTime::UNIX_EPOCH)
152                .unwrap_or_default()
153                .as_nanos() as i64,
154        )
155    }
156}
157
158impl From<usize> for RecordValue {
159    fn from(value: usize) -> Self {
160        Self::U64(value as u64)
161    }
162}
163
164impl From<String> for RecordValue {
165    fn from(value: String) -> Self {
166        Self::Utf8String(value)
167    }
168}
169
170impl From<i32> for RecordValue {
171    fn from(value: i32) -> Self {
172        Self::I32(value)
173    }
174}
175
176impl From<i64> for RecordValue {
177    fn from(value: i64) -> Self {
178        Self::I64(value)
179    }
180}
181
182impl From<i128> for RecordValue {
183    fn from(value: i128) -> Self {
184        Self::I128(value)
185    }
186}
187
188impl From<u32> for RecordValue {
189    fn from(value: u32) -> Self {
190        Self::U32(value)
191    }
192}
193
194impl From<u64> for RecordValue {
195    fn from(value: u64) -> Self {
196        Self::U64(value)
197    }
198}
199
200impl From<u128> for RecordValue {
201    fn from(value: u128) -> Self {
202        Self::U128(value)
203    }
204}
205
206impl From<f32> for RecordValue {
207    fn from(value: f32) -> Self {
208        Self::F32(value)
209    }
210}
211
212impl From<f64> for RecordValue {
213    fn from(value: f64) -> Self {
214        Self::F64(value)
215    }
216}