1#![doc = include_str!("../README.md")]
16
17mod event;
19
20#[expect(
22 dead_code,
23 reason = "consumed by the pipeline (`Telemetry`, `Exporter`), not in place yet"
24)]
25mod store;
26
27#[expect(
29 dead_code,
30 reason = "consumed by the pipeline (`Telemetry`, `Exporter`), not in place yet"
31)]
32mod stats;
33
34#[cfg_attr(
36 not(test),
37 expect(
38 dead_code,
39 reason = "consumed by the pipeline (`Telemetry`, `Exporter`), not in place yet"
40 )
41)]
42mod device;
43
44#[cfg_attr(
46 not(test),
47 expect(
48 dead_code,
49 reason = "consumed by the pipeline (`Telemetry`, `Exporter`), not in place yet"
50 )
51)]
52mod rtc;
53
54#[expect(
56 dead_code,
57 reason = "consumed by the pipeline (`Telemetry`, `Exporter`), not in place yet"
58)]
59mod scope;
60#[expect(
62 dead_code,
63 reason = "consumed by the pipeline (`Telemetry`, `Exporter`), not in place yet"
64)]
65mod span;
66
67#[expect(
69 dead_code,
70 reason = "consumed by the pipeline (`Telemetry`, `Exporter`), not in place yet"
71)]
72mod otlp;
73
74mod cache;
76
77mod proto;
79
80#[cfg_attr(
82 not(test),
83 expect(
84 dead_code,
85 reason = "consumed by the pipeline (`Telemetry`, `Exporter`), not in place yet"
86 )
87)]
88mod transport;
89
90#[expect(
92 dead_code,
93 reason = "consumed by the pipeline (`Telemetry`, `Exporter`), not in place yet"
94)]
95mod destination;
96
97pub use cache::{BatchCache, FileCache, MemoryCache};
98pub use destination::ENDPOINT_OVERRIDE_ENV;
99pub use device::*;
100pub use event::*;
101pub use rtc::{RtcStat, RtcStatsSample, StreamDirection, TrackKind};
102pub use span::SpanOutcome;
103pub use stats::{TelemetryStats, TelemetryStatus};
104#[cfg(feature = "net")]
105pub use transport::NetTransport;
106pub use transport::{ExportError, ExportRequest, ExportResponse, TelemetryTransport};
107
108#[cfg(feature = "uniffi")]
109uniffi::setup_scaffolding!();
110
111#[cfg(test)]
113pub(crate) mod test_log {
114 use std::cell::RefCell;
115 use std::sync::{Mutex, Once};
116 use std::thread::{self, ThreadId};
117
118 static LINES: Mutex<Vec<(ThreadId, String)>> = Mutex::new(Vec::new());
119
120 thread_local! {
121 static HELD: RefCell<Option<Box<dyn Fn() -> bool>>> = const { RefCell::new(None) };
123 }
124
125 struct Capture;
126
127 impl log::Log for Capture {
128 fn enabled(&self, metadata: &log::Metadata) -> bool {
129 metadata.level() <= log::Level::Warn
130 }
131
132 fn log(&self, record: &log::Record) {
133 if self.enabled(record.metadata()) {
134 let held = HELD.with(|held| held.borrow().as_ref().is_some_and(|held| held()));
135 let line = format!("{}{}", if held { "held: " } else { "" }, record.args());
136 let line = (thread::current().id(), line);
137 LINES.lock().unwrap_or_else(|e| e.into_inner()).push(line);
138 }
139 }
140
141 fn flush(&self) {}
142 }
143
144 pub fn capture() {
146 static INSTALL: Once = Once::new();
147 INSTALL.call_once(|| {
148 log::set_logger(&Capture).expect("the only logger in tests");
149 log::set_max_level(log::LevelFilter::Warn);
150 });
151 }
152
153 pub fn mark_while(held: impl Fn() -> bool + 'static) {
156 HELD.with(|slot| *slot.borrow_mut() = Some(Box::new(held)));
157 }
158
159 pub fn take() -> Vec<String> {
162 let me = thread::current().id();
163 let mut lines = LINES.lock().unwrap_or_else(|e| e.into_inner());
164 let (mine, others): (Vec<_>, Vec<_>) =
165 std::mem::take(&mut *lines).into_iter().partition(|(id, _)| *id == me);
166 *lines = others;
167 mine.into_iter().map(|(_, line)| line).collect()
168 }
169}