obs_core/envelope/
builder.rs1use std::time::{SystemTime, UNIX_EPOCH};
4
5use bytes::BytesMut;
6use obs_proto::{
7 __private::Message,
8 obs::v1::{ObsEnvelope, SamplingReason, Severity},
9};
10
11use crate::{callsite::ObsCallsite, envelope::projection::EventSchema};
12
13thread_local! {
14 static EMIT_BUF: std::cell::RefCell<BytesMut> = std::cell::RefCell::new(BytesMut::with_capacity(4096));
17}
18
19#[derive(Debug, Clone, Default)]
24pub struct Envelope(pub ObsEnvelope);
25
26impl Envelope {
27 #[must_use]
29 pub fn inner(&self) -> &ObsEnvelope {
30 &self.0
31 }
32
33 pub fn inner_mut(&mut self) -> &mut ObsEnvelope {
35 &mut self.0
36 }
37
38 #[must_use]
40 pub fn into_inner(self) -> ObsEnvelope {
41 self.0
42 }
43}
44
45#[must_use]
52pub fn build_envelope<E: EventSchema>(callsite: &ObsCallsite, event: &E) -> ObsEnvelope {
53 build_envelope_at::<E>(callsite, event, E::DEFAULT_SEV)
54}
55
56#[must_use]
59pub fn build_envelope_at<E: EventSchema>(
60 callsite: &ObsCallsite,
61 event: &E,
62 sev: Severity,
63) -> ObsEnvelope {
64 let _ = callsite; let payload = EMIT_BUF.with(|cell| {
66 let mut buf = cell.borrow_mut();
67 buf.clear();
68 event.encode_payload(&mut buf);
69 buf.split().freeze().to_vec()
70 });
71
72 let ts_ns = SystemTime::now()
73 .duration_since(UNIX_EPOCH)
74 .map(|d| d.as_nanos() as u64)
75 .unwrap_or(0);
76
77 ObsEnvelope {
78 full_name: E::FULL_NAME.to_string(),
79 schema_hash: E::SCHEMA_HASH,
80 tier: ::buffa::EnumValue::Known(E::TIER),
81 sev: ::buffa::EnumValue::Known(sev),
82 ts_ns,
83 payload,
84 sampling_reason: ::buffa::EnumValue::Known(SamplingReason::HeadRate),
85 ..Default::default()
86 }
87}
88
89#[must_use]
92#[allow(dead_code)] pub fn encode_envelope(env: &ObsEnvelope) -> Vec<u8> {
94 let mut buf = Vec::with_capacity(env.encoded_len() as usize);
95 env.encode(&mut buf);
96 buf
97}