Releases: voip-rs/freeswitch-log-parser
Release list
v0.17.1
New features:
- LogEntry::is_destroy() tells whether an entry records a channel's teardown: the Close Channel line, whatever state it shows, or a state change into CS_DESTROY. It reads the classification only, never raw text, and one channel can match on more than one entry.
- fslog: --help prints the same short help as -h on every subcommand. The full per-option text is under fslog help .
Bug fixes:
- "destroy/unlink session from object" is logged when a Lua, Python or Java script releases its session object, usually while the call is still up. It is now classified as LifecycleEvent::Other instead of Destroy. fslog monitor no longer ends a call's row when a script finishes on it.
v0.17.0
New features:
- A session now carries the caller stated by the dialplan's Processing line, as initial_caller_number and initial_caller_name. Both are set once, from the first such line seen, so a transfer cannot restate the caller as the transfer target's. Only a caller side that brackets its number fills them.
- SessionState::caller_number() and SessionState::callee_number() resolve the caller and the dialed number across every source a session has: the CHANNEL_DATA field, then sip_from_user or sip_to_user, then the dialplan. A leg whose box never dumped its channel now reports a caller instead of nothing.
v0.16.0
Breaking changes:
LogLeveland its parse error are re-exports offreeswitch-typesrather than local types. Severity followsswitch_log_level_tnumbering, so the less severe level compares greater and alevel >= minfilter has to becomelevel <= min. The variant isErrorrather thanErr, aDisablevariant exists that is not a severity,FromStris case sensitive, and the freelevel_from_bracketedreplacesLogLevel::from_bracketed.- A channel variable's name is a
VarName: onMessageKind::Variable, on a CHANNEL_DATA block's variable keys, and on the warnings that name a cut variable. It holds the bare name,Displayrenders thevariable_spelling the log uses, and it implements no comparison againststr, so a consumer comparing with a prefixed literal fails to compile instead of silently matching nothing. MessageKind::ChannelLifecyclecarries a typedLifecycleEventbeside its raw detail.- An originate success line classifies as
MessageKind::OriginateSuccess, carrying the channel name and a validated peer UUID, where it previously arrived as a channel lifecycle message.fslog --categoryselects it asoriginate-success. MessageKind::Execute's depth isOption<u32>: a missing or unreadable[depth=N]no longer reads as zero.ParseStats::unaccounted_linesreturns a signed difference, so an over-count is visible instead of clamped to zero.- Removed:
FieldKind::SipUri,UnclassifiedReason::UnknownMessageFormat,UnclassifiedReason::TruncatedField, and theis_peer_uuid_varexport.
New features:
stamp_lower_boundandstamp_upper_boundpad a partial date into the rotation stamp form, which every consumer windowing a log had been re-deriving.- The
fixturesandcorpuscargo features gate the production-log tests. Without a corpus they compile to nothing rather than skipping silently, and the whole-corpus sweep runs before a release rather than on every commit.
Bug fixes:
- A peer's back-link survives another leg relinking through the same key, and removing a session no longer leaves a reverse pointer that a later channel could follow into a resurrected empty session.
- A conference move that keeps its instance re-seats on the new name instead of leaving the registry keyed on the old one.
- One validator now reads the log header grammar, and a record starts only where the level field closes, so a write cut inside that field no longer opens an entry.
- An originate peer UUID the write buffer cut is reported as unreadable instead of being indistinguishable from a build that omits it.
- fslog: a log file it cannot open fails the search instead of reporting no matches and exiting zero; a mid-file read error ends the command and names the file; errors print their whole source chain; a corrupt timestamp no longer panics the printer; invalid UTF-8 is counted once per file instead of warned per line;
monitor --dumpreads the configuration the TUI reads; one rule resolves a FILE argument for read, tail and monitor;--levelsays which way it was wrong and rejectsdisable.
Build:
- Requires
freeswitch-types1.5. - The release image is built on bookworm, raising the binary's glibc floor to 2.34. A Debian 11 target can no longer install the package.
Refactoring:
- The parser's internals were split and deduplicated throughout, including the collision detector and the stream's own iterator, with parser output verified byte-identical against the fixture corpus.
v0.15.0
New features:
- read_log_lines_capped reads with a caller-set byte bound, so one absurdly long physical line — a collided write or a long verbatim record — no longer sets a reader's peak memory. Every line past the bound is reported with its full length, so nothing is dropped silently. read_log_line_capped exposes the same primitive to a reader owning its loop, such as a tail follower.
- LogStream::max_attached_bytes bounds the continuation lines one entry may hold. A line past the budget is reported as ParseWarning::AttachedOverflow and counted in ParseStats::lines_dropped, the path an unaddressable line already took.
- AttachedLines::byte_len reports what an entry's attached lines occupy.
- fslog reads with a 1 MiB line cap by default, overridable with --max-line-bytes. Over-cap lines are warned once as they happen, then summarized per file with a count and the largest length seen.
Build:
- The uncapped and capped readers share one read loop and reuse a single byte buffer across lines, instead of allocating one per line.
v0.14.3
Build:
- Release assets are now PGP-signed. The release workflow leaves the GitHub release as a draft, sign-release.sh detach-signs every asset — the .deb packages, the bare binaries, the source tarball and SHA256SUMS — verifies each signature, uploads the .asc files and only then publishes. Signing has to happen before publication because a published release's assets are immutable and can no longer be replaced.
v0.14.2
Bug fixes:
- A channel variable whose value the log buffer cut mid-write no longer ends
there. Reassembly runs past the cut and stops at the next variable or field
name, so the rest of a multi-line value — an SDP part inside sip_multipart,
a long SIP header — is recovered instead of being reported line by line as
unreadable. The value is still flagged as cut, since its middle is lost.
v0.14.1
Bug fixes:
- A line split by write contention is no longer reported as truncated: only a
split at the exact write-budget boundary marks text as cut, so a consumer
filtering incomplete text stops dropping whole records - UnparseableChannelData now reads as an incomplete-line fragment rather than a
parser failure, which is what a name cut mid-token actually is
v0.14.0
The buffer cut is now found at an exact offset instead of guessed from a
line's length. A mod_logfile write is at most 2047 bytes and an intact one
never reaches that, so the cut has one possible position, and the parser
tracks how much of the budget the write in progress has spent to name it.
Because a write spans a UUID-prefixed line and the bare lines under it, the
cut usually lands on a short line that no length test would examine. Those
were being absorbed into the value of whichever channel variable was open —
84903 of them across the fixture corpus, 27% of every cut, including values
of variable_call_uuid and variable_sip_multipart. Records that vanished into
a variable's value now surface as their own entries.
Breaking changes:
ParseWarning::OversizeLine { bytes }is nowParseWarning::CutLine,
fieldless. It reports that a record was cut rather than that a line was
long, and the byte count it carried described the physical line rather
than the record.decode_log_lineandread_log_lineskeep a CR before the newline;
LogStreamtrims it after counting the write's bytes. A byte dropped
before the count is one the boundary drifts by, and SDP inside channel
variables makes CRLF 14-19% of production lines. Consumers feeding
LogStreamare unaffected; one using the decoded text directly now sees
the CR.
Also:
- A physical line holding several cut records reports each of them, rather
than only the first. - Splits gained across 766 fixture files: 84903. Splits lost: none.
v0.13.1
Bug fixes:
- A record is reported as cut only where mod_logfile's write buffer could have
cut it. That buffer applies only when mod_logfile prepends a session UUID;
records written without one go out verbatim and are intact at any length, so
they are no longer reported as truncated. Production logs carry verbatim
lines past 11 KB that every prior version flagged. - The reported byte count is now the physical line length. It previously added
the 37-byte UUID prefix to a line that already carried it. - A prefixed line is reported as cut at the length where the trailing newline
no longer fits, rather than against a payload budget 37 bytes below it, so
intact lines just over that budget are no longer flagged. - The warning text now states the cut rather than hedging that data "may be"
truncated.
v0.13.0
New features:
- LogEntry::is_truncated(&Field) answers whether the logger's write buffer cut
short the text a field span covers, so a consumer rewriting spans can withhold
a partial value instead of scrubbing it blind. LogEntry::cut_texts names the
entry's texts that ended at a cut. - Every slot of a CHANNEL_DATA dump now carries a span for its value. A name
outside the identity vocabulary spans as FieldKind::VariableValue, so an
identity-carrying slot the mapping does not name no longer reaches a consumer
unlocated; the consumer decides sensitivity from the name. - The value a dialplan Regex condition tested is spanned, and RegexCondition
with the slicer that cuts it is public API. - Three core narrations that never classified as a channel variable now do:
EXPORTING, "setting variable", and set()'s PUSH/UNSHIFT verbs.
Bug fixes:
- An SDP body whose marker sits on a continuation line becomes a Block::Sdp
rather than untyped text — the shape sofia logs for outbound invites, and the
majority of Local SDP occurrences in production logs. A body carrying no
marker opens on its version line. - A CHANNEL_DATA value the logger cut no longer swallows the variable that
follows it on the collided line; the value closes at the cut with a
TruncatedVariable warning. - A bracketed value ends at its matching bracket rather than the first one, so a
value containing brackets is no longer cut short. SET GLOBAL no longer yields
a channel span.
Breaking:
- LogEntry gained the cut_texts field, so literal construction needs updating.
LogEntry::synthetic plus struct-update syntax keeps compiling.