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 pub icon: &'static str,
18}
19
20impl EventMetadata {
21 pub const fn validate_fields(&self, provided: &[&str]) {
24 let mut i = 0;
25 while i < self.context_fields.len() {
26 let required = self.context_fields[i];
27 if !str_contains(provided, required) {
28 const_panic::concat_panic!(
29 "log_event! missing required context field: `",
30 required,
31 "`"
32 );
33 }
34 i += 1;
35 }
36 }
37}
38
39const fn str_contains(haystack: &[&str], needle: &str) -> bool {
40 let mut i = 0;
41 while i < haystack.len() {
42 if str_eq(haystack[i], needle) {
43 return true;
44 }
45 i += 1;
46 }
47 false
48}
49
50const fn str_eq(a: &str, b: &str) -> bool {
51 let a = a.as_bytes();
52 let b = b.as_bytes();
53 if a.len() != b.len() {
54 return false;
55 }
56 let mut i = 0;
57 while i < a.len() {
58 if a[i] != b[i] {
59 return false;
60 }
61 i += 1;
62 }
63 true
64}
65
66const UNINITIALIZED: u8 = 0;
67const STRUCTURED: u8 = 1;
68const NOT_STRUCTURED: u8 = 2;
69
70static STRUCTURED_LOGGING: AtomicU8 = AtomicU8::new(UNINITIALIZED);
71
72#[inline]
76pub fn is_structured_logging() -> bool {
77 match STRUCTURED_LOGGING.load(Ordering::Relaxed) {
78 STRUCTURED => true,
79 NOT_STRUCTURED => false,
80 _ => is_structured_logging_init(),
81 }
82}
83
84#[cold]
85fn is_structured_logging_init() -> bool {
86 let is_structured = std::env::var("STRUCTURED").is_ok_and(|s| s == "true" || s == "1");
87 STRUCTURED_LOGGING.store(
88 if is_structured {
89 STRUCTURED
90 } else {
91 NOT_STRUCTURED
92 },
93 Ordering::Relaxed,
94 );
95 is_structured
96}