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