NAME
Log::Munger - Extracts structured fields from log records using YAML rule files.
VERSION
Version 0.0.1
SYNOPSIS
use Log::Munger;
my $munger = Log::Munger->new( 'rules' => [ 'sshd', 'postfix' ] );
# a decoded record, such as what journald or syslog-ng JSON output gives you
my $fields = $munger->process_item(
'item' => {
'PROGRAM' => 'sshd',
'MESSAGE' => 'Failed password for root from 203.0.113.7 port 44444 ssh2',
}
);
# $fields = { ssh_method => 'password', ssh_user => 'root', ssh_src_ip => '203.0.113.7', ... }
# a bare string is matched as the MESSAGE field, so whole log lines work as-is
my $access = $munger->process_item( 'item' => $raw_apache_line );
Each rule file is a YAML document holding a library of named regexps and an ordered list of rules built from them. A record is walked against those rules in load order, and the first one whose gates pass and whose pattern matches returns its named captures. Captured fields can then be broken down further, looked up in a GeoIP database, and coerced to numbers.
This is the same idea as grok for Logstash, minus the Logstash. See Log::Munger::LogProcessor for the matching engine and the log_munger command for the CLI.
METHODS
new
Creates a new munger. Rule files may be supplied up front, added later via "load", or both.
Each name is resolved through Log::Munger::WhichRuleFile, so it may be a bare name such as sshd or a path. A rule file that fails to load or compile is fatal, which means a broken file is caught here rather than silently producing no matches later on.
my $munger = Log::Munger->new( 'rules' => [ 'base', 'postfix' ] );
my $munger = Log::Munger->new( 'rules' => ['postfix'], 'geoip' => '/path/to/GeoLite2-City.mmdb' );
- rules :: Rule files to load. The taken value is an array ref.
Default :: undef
- geoip :: Path to a MaxMind .mmdb database. When set, rules that flag
captured fields with a C<geoip:> list have those looked up, with the
result stored under C<< $result->{geoip}{$field} >>. Needs
L<IP::Geolocation::MMDB>, which is only loaded when this is used.
Default :: undef (geoip disabled)
load
Loads an additional rule file and rebuilds the processor. Rules from files loaded later are tried after rules from files loaded earlier, so load order is match priority.
Returns 1. Dies if the file cannot be found, loaded, or compiled.
- file :: The file to load. Required.
Default :: undef
$munger->load( 'file' => 'sshd' );
process_item
Runs a decoded log record through the loaded rules and returns the named captures of the first matching rule, or undef if nothing matched (or no rules have been loaded).
- item :: The decoded log record (a hash ref), or a bare string. A bare
string is treated as a raw log line and matched as the C<MESSAGE> field.
If given, C<item> takes precedence over the field args below.
Default :: undef
- message :: The raw log message, assembled into C<< { MESSAGE => ... } >>.
Default :: undef
- program :: Optional C<PROGRAM> field (the usual daemon-rule gate).
Default :: undef
- priority :: Optional C<PRIORITY> field.
Default :: undef
- facility :: Optional C<FACILITY> field.
Default :: undef
my $fields = $munger->process_item( 'item' => $json );
my $fields = $munger->process_item( 'item' => $raw_access_log_line );
# from a syslog reader that already has the fields split out (e.g. baphomet):
my $fields = $munger->process_item(
'message' => $message,
'program' => $program,
'priority' => $priority,
'facility' => $facility,
);
Returns a hash ref of the winning rule's named captures, or undef if nothing matched. Never dies: an exception during matching comes back as undef rather than taking down the stream. That bounds failures, not runtime -- a pattern prone to catastrophic backtracking can still burn CPU on a hostile line.
explain_item
Like "process_item", but reports which rule and pattern fired alongside the fields. Handy when a rule file is not matching what you expected it to. Takes the same args and never dies. See "explain_item" in Log::Munger::LogProcessor.
my $why = $munger->explain_item( 'item' => $json );
# { matched => 0 }
# { matched => 1, rule => 'sshd', pattern => 1, field => 'MESSAGE', fields => { ... } }
AUTHOR
Zane C. Bowers-Hadley, <vvelox at vvelox.net>
SEE ALSO
Log::Munger::LogProcessor - the matching engine.
Log::Munger::RulesTest - the test harness behind
log_munger test_all.Log::Munger::Degrok - converting existing grok patterns.
The
docs/directory in the distribution, which covers the rule file format, the primitive library, and writing your own rules.
BUGS
Report bugs and feature requests through GitHub at https://github.com/LilithSec/Log-Munger, or to bug-log-munger at rt.cpan.org.
SUPPORT
perldoc Log::Munger
You can also find this distribution at:
GitHub
MetaCPAN
RT, CPAN's request tracker
LICENSE AND COPYRIGHT
This software is Copyright (c) 2026 by Zane C. Bowers-Hadley.
This is free software, licensed under:
The GNU Lesser General Public License, Version 3, June 2007