xmtp_common/event_logging/
utils.rs1use std::sync::atomic::{AtomicU8, Ordering};
2
3use crate::Event;
4
5#[derive(Debug, Clone, Copy)]
8pub struct EventMetadata {
9 pub name: &'static str,
11 pub event: Event,
12 pub doc: &'static str,
14 pub context_fields: &'static [&'static str],
16}
17
18impl EventMetadata {
19 pub const fn validate_fields(&self, provided: &[&str]) {
22 let mut i = 0;
23 while i < self.context_fields.len() {
24 let required = self.context_fields[i];
25 if !str_contains(provided, required) {
26 const_panic::concat_panic!(
27 "log_event! missing required context field: `",
28 required,
29 "`"
30 );
31 }
32 i += 1;
33 }
34 }
35}
36
37const fn str_contains(haystack: &[&str], needle: &str) -> bool {
38 let mut i = 0;
39 while i < haystack.len() {
40 if str_eq(haystack[i], needle) {
41 return true;
42 }
43 i += 1;
44 }
45 false
46}
47
48const fn str_eq(a: &str, b: &str) -> bool {
49 let a = a.as_bytes();
50 let b = b.as_bytes();
51 if a.len() != b.len() {
52 return false;
53 }
54 let mut i = 0;
55 while i < a.len() {
56 if a[i] != b[i] {
57 return false;
58 }
59 i += 1;
60 }
61 true
62}
63
64const UNINITIALIZED: u8 = 0;
65const STRUCTURED: u8 = 1;
66const NOT_STRUCTURED: u8 = 2;
67
68static STRUCTURED_LOGGING: AtomicU8 = AtomicU8::new(UNINITIALIZED);
69
70#[inline]
74pub fn is_structured_logging() -> bool {
75 match STRUCTURED_LOGGING.load(Ordering::Relaxed) {
76 STRUCTURED => true,
77 NOT_STRUCTURED => false,
78 _ => is_structured_logging_init(),
79 }
80}
81
82#[cold]
83fn is_structured_logging_init() -> bool {
84 let is_structured = std::env::var("STRUCTURED").is_ok_and(|s| s == "true" || s == "1");
85 STRUCTURED_LOGGING.store(
86 if is_structured {
87 STRUCTURED
88 } else {
89 NOT_STRUCTURED
90 },
91 Ordering::Relaxed,
92 );
93 is_structured
94}