freeswitch-log-parser 0.17.1

Parser for FreeSWITCH log files — handles compressed .xz files, multi-line dumps, truncated buffers, and stateful UUID/timestamp tracking
Documentation
//! Parser for FreeSWITCH log files.
//!
//! Handles the full complexity of `mod_logfile` output: the six [`LineKind`]
//! shapes, multi-line CHANNEL_DATA and SDP dumps, truncated buffer collisions,
//! and per-session state tracking — no regex, a single dependency
//! (`freeswitch-types`).
//!
//! # Architecture
//!
//! The parser is organized in three composable layers, each wrapping the previous:
//!
//! - **Layer 1** ([`parse_line`]) — stateless, zero-allocation single-line classifier
//! - **Layer 2** ([`LogStream`]) — structural state machine that groups continuations,
//!   classifies messages, and detects multi-line blocks
//! - **Layer 3** ([`SessionTracker`]) — per-UUID state machine that propagates
//!   dialplan context, channel state, and variables across entries; extensible
//!   via [`SessionTracker::with_pre_hook`] and [`SessionTracker::with_post_hook`]
//!   for custom leg detection
//!
//! See `docs/design-rationale.md` in the repository for the parsing strategy
//! and why each layer exists; the line-format anatomy lives in the repository's
//! CLAUDE.md.
//!
//! # Examples
//!
//! Read lines from stdin, process through all three layers, and print enriched entries:
//!
//! ```no_run
//! use std::io;
//! use freeswitch_log_parser::{read_log_lines, LogStream, SessionTracker};
//!
//! // read_log_lines tolerates mod_logfile's truncated codepoints; the strict
//! // BufRead::lines() reader would panic on them.
//! let lines = read_log_lines(io::stdin().lock()).map(|d| d.expect("read error").text);
//! let stream = LogStream::new(lines);
//! let mut tracker = SessionTracker::new(stream);
//!
//! for enriched in tracker.by_ref() {
//!     let e = &enriched.entry;
//!     println!("{} [{}] {}", e.timestamp, e.message_kind, e.message);
//! }
//!
//! let stats = tracker.stats();
//! eprintln!("{} lines, {} unclassified",
//!     stats.lines_processed, stats.lines_unclassified);
//! ```
//!
//! # Feature flags
//!
//! All off by default; docs.rs builds with all of them on.
//!
//! - **`sdp`** — `Block::sdp_codecs`, which parses an SDP body through `freeswitch-types`
//! - **`cli`** — the `fslog` binary: clap, xz decompression, regex filtering. Enables `sdp`
//! - **`tui`** — `fslog monitor`, the live call table. Enables `cli`
//! - **`fixtures`** — the production-log test suite, which requires a corpus in
//!   `tests/fixtures/` and fails rather than skips without one. Affects tests only

mod attached;
mod chain;
mod codec;
mod decode;
mod fields;
mod line;
mod mask;
mod message;
mod peer;
mod session;
mod stamp;
mod stream;
#[cfg(test)]
mod testdata;
mod uuid;

pub use attached::{AttachedLines, AttachedLinesIter, AttachedOverflow};
pub use chain::{SegmentTracker, TrackedChain};
pub use codec::{CodecMedia, CodecOffer, CodecParseError};
pub use decode::{
    classify_utf8, decode_log_line, read_log_line_capped, read_log_lines, read_log_lines_capped,
    trim_capped_tail, truncate_at_char_boundary, CappedLine, DecodedLine, LineRead, OverCap,
    Utf8Decode,
};
pub use fields::{
    apply_fields, message_fields, Field, FieldKind, FieldLocation, RenderError, RenderedEntry,
};
pub use freeswitch_types::{
    variables::{ConferenceVariable, SofiaVariable, VariableName},
    CallDirection, CallState, ChannelState, ChannelVariable, HangupCause, LogLevel,
    ParseLogLevelError,
};
pub use line::{level_from_bracketed, parse_line, LineKind, RawLine};
pub use message::{
    classify_message, regex_condition_parts, DtmfSource, LifecycleEvent, MessageKind,
    RegexCondition, SdpDirection, SipInviteDirection, VarName,
};
pub use peer::{
    for_each_peer_uuid, for_each_peer_uuid_with, LOOPBACK_PEER_UUID_VARS, PEER_UUID_VARS,
};
pub use session::{
    conference::ConferenceMembership,
    media::{CodecImpl, MediaCodecs, SessionMedia},
    parse_bridge_args, BridgeInfo, EnrichedEntry, SessionSnapshot, SessionState, SessionTracker,
};
pub use stamp::{
    log_rotation_stamp, normalize_entry_timestamp, stamp_lower_bound, stamp_upper_bound,
};
pub use stream::{
    Block, LogEntry, LogStream, ParseStats, ParseWarning, SessionReading, UnclassifiedLine,
    UnclassifiedReason, UnclassifiedTracking,
};
pub use uuid::{find_uuids, is_uuid, FindUuids};