1#![forbid(unsafe_code)]
2#![warn(rust_2024_compatibility, missing_docs, missing_debug_implementations)]
3#![cfg_attr(
5 test,
6 allow(
7 clippy::unwrap_used,
8 clippy::expect_used,
9 clippy::panic,
10 clippy::indexing_slicing
11 )
12)]
13
14pub mod audit_spool;
34pub mod callsite;
39pub mod codegen_helpers;
40pub mod config;
41pub mod config_watcher;
42pub mod emit;
43pub mod envelope;
44pub mod filter;
45pub mod forensic;
46pub mod instrumented;
47pub mod metric;
48pub mod observer;
49pub mod panic_hook;
50pub mod propagator;
51pub mod registry;
52pub mod resource;
53pub mod sampling;
54pub mod scope;
55mod self_event;
56pub(crate) mod self_events;
57pub use self_event::{now_ns, self_event};
58pub mod self_events_public {
62 pub use crate::self_events::{
63 emit_callsite_hash_collision_pub as emit_callsite_hash_collision,
64 emit_label_cardinality_high_pub as emit_label_cardinality_high,
65 emit_oversized_label_dropped_pub as emit_label_oversized,
66 emit_span_pair_orphaned_pub as emit_span_pair_orphaned,
67 };
68}
69pub mod sink;
70pub mod span_trace;
71#[cfg(feature = "test")]
72pub mod test;
73pub mod wire;
74
75#[doc(hidden)]
76#[cfg(feature = "test")]
77pub mod __macro_deps {
78 pub use serde_json;
79}
80
81#[must_use]
90pub fn cap_external_string(field: &'static str, raw: String, max_bytes: u16) -> String {
91 let max = max_bytes as usize;
92 if raw.len() <= max {
93 return raw;
94 }
95 let original_size = raw.len() as u64;
96 let mut end = max;
98 while end > 0 && !raw.is_char_boundary(end) {
99 end -= 1;
100 }
101 let mut out = String::with_capacity(end + 24);
102 out.push_str(&raw[..end]);
103 out.push_str(&format!("…<truncated:{}>", original_size));
104 self_events::emit_oversized_label_dropped_pub(field, original_size, out.len() as u64);
105 out
106}
107
108pub use callsite::ObsCallsite;
109#[doc(hidden)]
112pub use codegen_helpers as aux;
113pub use codegen_helpers::{BuildableTo, EnumCount, FieldCapture, SpanCtx, SpanFrame};
114pub use config::{EventsConfig, SamplingConfig};
115pub use config_watcher::{ConfigWatcher, DEFAULT_DEBOUNCE};
116pub use emit::Emit;
117pub use envelope::{Envelope, EventSchema, FieldMeta, FieldRole};
118pub use filter::Filter;
119pub use instrumented::{Instrument, Instrumented, WithObserver};
120pub use metric::{MetricEmitter, NoopMetricEmitter};
121pub use obs_proto::{
122 ENVELOPE_FORMAT_VER,
123 obs::v1::{
124 Cardinality, Classification, FieldKind, MetricKind, ObsBatch, ObsEnvelope, SamplingReason,
125 Severity, Tier,
126 },
127};
128pub use observer::{
129 BuildError, InMemoryHandle, InMemoryObserver, NoopObserver, Observer, StandardObserver,
130 StandardObserverBuilder, ThreadObserverGuard, WeakObserver, WorkerCounters, install_observer,
131 install_observer_arc, observer, observer_weak, with_observer_task, with_observer_task_sync,
132 with_observer_thread_local, with_test_observer,
133};
134pub use panic_hook::install_panic_hook;
135pub use propagator::{
136 ObsTraceCtx, W3cPropagator, extract_w3c, fresh_span_id, fresh_trace_id, inject_w3c,
137 status_class,
138};
139pub use registry::{
140 ArrowEventSchema, ArrowField, ArrowLeafType, ArrowSchemaModel, ArrowStructBuilder,
141 CallsiteRecord, CallsiteSource, DecodeError, ENVELOPE_COLUMNS, EVENT_SCHEMAS,
142 EventSchemaErased, ObsCallsiteRegistry, OtelAttributeView, OtlpValue, SchemaRegistry,
143 ScrubError, ScrubbedEnvelope, callsite_id, render_payload_json, scrub_payload,
144};
145pub use resource::ResourceAttrs;
146pub use sampling::{SamplingDecision, decide as sample_decide};
147pub use scope::{ScopeField, ScopeFrame, ScopeFrameBuilder, ScopeGuard, ScopeKind};
148pub use sink::{
149 FanOutSink, FormatterStyle, InMemorySink, LevelSplitWriter, MakeWriter, NdjsonFileSink,
150 NonBlockingWriter, NoopSink, RollingFileWriter, RollingFileWriterBuilder, RollingPolicy, Sink,
151 StderrWriter, StdoutSink, StdoutWriter, TeeWriter, WorkerGuard,
152};
153pub use span_trace::SpanTrace;
154
155#[doc(hidden)]
158pub mod __private {
159 pub use std::sync::OnceLock;
160
161 pub use buffa;
162 pub use bytes::BytesMut;
163 pub use linkme;
164 pub use obs_proto::obs::v1::{
170 Cardinality, Classification, FieldKind, MetricKind, SamplingReason,
171 SamplingReason as ProtoSamplingReason, Severity, Severity as ProtoSeverity, Tier,
172 Tier as ProtoTier,
173 };
174 pub use obs_proto::{__private::*, UnknownVariant};
175 pub use secrecy;
176 pub use serde_json;
177
178 pub use crate::{
179 callsite::ObsCallsite,
180 codegen_helpers::{BuildableTo, EnumCount, FieldCapture, SpanCtx, SpanFrame},
181 forensic::{ForensicLimiter, ensure_limiter, try_acquire_forensic},
182 registry::{EVENT_SCHEMAS, EventSchemaErased, Sealed},
183 scope::{ScopeField, ScopeGuard, ScopeKind},
184 wire::BuffaEncodeField,
185 };
186
187 #[must_use]
190 #[allow(clippy::indexing_slicing)]
191 pub const fn starts_with_obs(name: &str, prefix: &str) -> bool {
192 let n = name.as_bytes();
193 let p = prefix.as_bytes();
194 if n.len() < p.len() {
195 return false;
196 }
197 let mut i = 0;
198 while i < p.len() {
199 if n[i] != p[i] {
200 return false;
201 }
202 i += 1;
203 }
204 true
205 }
206}