NAME

Log::Abstraction - Logging Abstraction Layer

VERSION

0.30

SYNOPSIS

use Log::Abstraction;

my $logger = Log::Abstraction->new(logger => 'logfile.log');

$logger->debug('This is a debug message');
$logger->info('This is an info message');
$logger->notice('This is a notice message');
$logger->trace('This is a trace message');
$logger->warn({ warning => 'This is a warning message' });

DESCRIPTION

The Log::Abstraction class provides a flexible logging layer on top of different types of loggers, including code references, arrays, file paths, and objects. It also supports logging to syslog if configured.

METHODS

new

my $logger = Log::Abstraction->new(%args);

Creates a new Log::Abstraction object.

The argument can be a hash, a reference to a hash or the logger value. The following arguments can be provided:

Clone existing objects with or without modifications:

my $clone = $logger->new();

_sanitize_email_header

my $clean_value = _sanitize_email_header($raw_value);

Internal routine to remove carriage return and line feed characters from an email header value to prevent header injection or formatting issues.

FORMAL SPECIFICATION

If the input is undefined (∅), the output is also undefined (∅).

If the input is defined, the result is a defined string with CR and LF characters removed.

[CHAR]

CR, LF : CHAR
CR == '\r'
LF == '\n'

STRING == seq CHAR

SanitizeEmailHeader
    raw?: STRING
    sanitized!: STRING
    -------------------------------------------------
    sanitized! = [ c : raw? | c ≠ CR ∧ c ≠ LF ]

level($self, $level)

Get/set the minimum level to log at. Returns the current level, as an integer.

is_debug

Are we at a debug level that will emit debug messages? For compatibility with Log::Any.

messages

Return all the messages emitted so far

debug

$logger->debug(@messages);

Logs a debug message.

info

$logger->info(@messages);

Logs an info message.

notice

$logger->notice(@messages);

Logs a notice message.

error

$logger->error(@messages);

Logs an error message. This method also supports logging to syslog if configured. If not logging mechanism is set, falls back to croak.

fatal

$logger->fatal(@messages);

Synonym of error.

trace

$logger->trace(@messages);

Logs a trace message.

warn

$logger->warn(@messages);
$logger->warn(\@messages);
$logger->warn(warning => \@messages);

Logs a warning message. This method also supports logging to syslog if configured. If not logging mechanism is set, falls back to Carp.

_high_priority

Helper to handle important messages.

EXAMPLES

CSV file logging for BI import

The code-reference backend gives you full control over the output format. The example below writes every message at trace level and above as a CSV row to a file, producing output that can be loaded directly into a spreadsheet or BI tool (Tableau, Power BI, Metabase, etc.).

Each row contains: timestamp, level, class, file, line, message.

use Log::Abstraction;

my $csv_file = 'app_events.csv';

# Write the header row once (skip if the file already exists and has data).
unless (-s $csv_file) {
    open my $fh, '>', $csv_file or die "Cannot open $csv_file: $!";
    print $fh qq{timestamp,level,class,file,line,message\n};
    close $fh;
}

# Helper: quote a single CSV field (escapes embedded double-quotes).
my $csv_field = sub {
    my $v = defined $_[0] ? $_[0] : '';
    $v =~ s/"/""/g;
    return qq{"$v"};
};

my $logger = Log::Abstraction->new(
    level  => 'trace',        # capture everything from trace upwards
    logger => sub {
        my $args = $_[0];

        my $timestamp = POSIX::strftime('%Y-%m-%dT%H:%M:%SZ', gmtime);
        my $message  = join(' ', @{ $args->{message} // [] });

        open my $fh, '>>', $csv_file or return;
        print $fh join(',',
            $csv_field->($timestamp),
            $csv_field->($args->{level}),
            $csv_field->($args->{class}),
            $csv_field->($args->{file}),
            $csv_field->($args->{line}),
            $csv_field->($message),
        ), "\n";
        close $fh;
    },
);

$logger->trace('application started');
$logger->info('user logged in', { user => 'alice' });
$logger->warn({ warning => 'disk usage above 80%' });

The resulting app_events.csv looks like:

timestamp,level,class,file,line,message
"2026-05-27T14:00:00Z","trace","main","app.pl","42","application started"
"2026-05-27T14:00:01Z","info","main","app.pl","43","user logged in"
"2026-05-27T14:00:02Z","warning","main","app.pl","44","disk usage above 80%"

For production use, consider replacing the manual $csv_field quoting with Text::CSV for correct handling of embedded newlines and other edge cases.

If you also want real-time alerting on critical events, combine the code-ref backend with the sendmail backend:

my $logger = Log::Abstraction->new(
    level  => 'trace',
    logger => {
        file    => $csv_file,   # use the file backend for simple append
        sendmail => {
            host         => 'smtp.example.com',
            to           => 'ops@example.com',
            from         => 'logger@example.com',
            subject      => 'Application alert',
            min_interval => 300,   # at most one alert email per 5 minutes
        },
    },
);

In this configuration every message at trace and above is appended to the file, while warn / error messages additionally trigger an email (throttled to one per five minutes).

AUTHOR

Nigel Horne njh@nigelhorne.com

SEE ALSO

SUPPORT

This module is provided as-is without any warranty.

Please report any bugs or feature requests to bug-log-abstraction at rt.cpan.org, or through the web interface at http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Log-Abstraction. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.

You can find documentation for this module with the perldoc command.

perldoc Log::Abstraction

You can also look for information at:

COPYRIGHT AND LICENSE

Copyright (C) 2025-2026 Nigel Horne

Usage is subject to the GPL2 licence terms. If you use it, please let me know.