freeswitch_log_parser/lib.rs
1//! Parser for FreeSWITCH log files.
2//!
3//! Handles the full complexity of `mod_logfile` output: five distinct line
4//! formats, multi-line CHANNEL_DATA and SDP dumps, truncated buffer collisions,
5//! and per-session state tracking — all with zero dependencies and no regex.
6//!
7//! # Architecture
8//!
9//! The parser is organized in three composable layers, each wrapping the previous:
10//!
11//! - **Layer 1** ([`parse_line`]) — stateless, zero-allocation single-line classifier
12//! - **Layer 2** ([`LogStream`]) — structural state machine that groups continuations,
13//! classifies messages, and detects multi-line blocks
14//! - **Layer 3** ([`SessionTracker`]) — per-UUID state machine that propagates
15//! dialplan context, channel state, and variables across entries
16//!
17//! See `docs/design-rationale.md` in the repository for the full story on format
18//! discovery, parsing strategy, and why each layer exists.
19//!
20//! # Examples
21//!
22//! Read lines from stdin, process through all three layers, and print enriched entries:
23//!
24//! ```no_run
25//! use std::io::{self, BufRead};
26//! use freeswitch_log_parser::{LogStream, SessionTracker};
27//!
28//! let lines = io::stdin().lock().lines().map(|l| l.expect("read error"));
29//! let stream = LogStream::new(lines);
30//! let mut tracker = SessionTracker::new(stream);
31//!
32//! for enriched in tracker.by_ref() {
33//! let e = &enriched.entry;
34//! println!("{} [{}] {}", e.timestamp, e.message_kind, e.message);
35//! }
36//!
37//! let stats = tracker.stats();
38//! eprintln!("{} lines, {} unclassified",
39//! stats.lines_processed, stats.lines_unclassified);
40//! ```
41//!
42//! # Feature flags
43//!
44//! - **`cli`** — enables the `fslog` binary with clap, xz decompression, and regex filtering
45
46mod attached;
47mod chain;
48mod level;
49mod line;
50mod message;
51mod session;
52mod stream;
53
54pub use attached::{AttachedLines, AttachedLinesIter};
55pub use chain::{SegmentTracker, TrackedChain};
56pub use freeswitch_types::{
57 variables::SofiaVariable, CallDirection, CallState, ChannelState, ChannelVariable,
58};
59pub use level::{LogLevel, ParseLevelError};
60pub use line::{parse_line, LineKind, RawLine};
61pub use message::{classify_message, MessageKind, SdpDirection, SipInviteDirection};
62pub use session::{EnrichedEntry, SessionSnapshot, SessionState, SessionTracker};
63pub use stream::{
64 Block, LogEntry, LogStream, ParseStats, UnclassifiedLine, UnclassifiedReason,
65 UnclassifiedTracking,
66};