3

I need a logging module with a simple interface, for logging messages from multiple processes to a common local log file.

Since some of these processes may be running simultaneously, the logging module must manage conflicting write requests from these process.

I know about Log::Log4perl, but every time I try to use it I end up with an inordinately complex logging interface. I'm looking for an alternative. Any suggestions?


I looked into Log::Message, which is AFAICT the only logging module included among Perl's core modules (sadly enough, IMO). I found no indication that it handles concurrency at all.

I also tried searching CPAN for an alternative, but just searching for 'Log::' under Modules produced over 3000 hits, in no particular order. Even scanning this list is impractical, let alone reading the documentation for the possible candidates, and trying out those that seem promising. (I wonder if the very difficulty of finding a reasonable logging module in CPAN is what gets people to roll their own, which they submit later to CPAN, thus adding one more item to the already unsurmountable mountain of logging modules. IOW, we may have a case of runaway growth here.)


I'm looking for a simple interface. Ideally, all the setup (e.g. the path to the log file, log level, etc.) would be done via a globally-shared ~/.*rc-type config file and/or environment variables.

Here's an example of what I mean by "a simple interface" (though, of course, I don't expect that I'll find a module out there that offers this exact interface; and, of course also, EasyLog is a made-up name; if a module by that name already exists, it is a coincidence):

#!/usr/bin/env perl

# some/script.pl

use strict;
use EasyLog ':all';

...

DEBUG "cwd: " + Cwd::cwd();

...

WARN "skipping empty line $.";

...

FATAL "timeout";  # maybe calls exit ?

Then, in some file $ENV{ EASYLOG_PATH }, I'd see lines like

30031   1430599390  /path/to/some/script.pl 2   INFO    Starting script.pl on Sat May  2 16:43:10 2015
30031   1430599429  /path/to/some/script.pl 19  WARN    skipping empty line 898
30036   1430599542  /path/to/some/script.pl 2   INFO    Starting script.pl on Sat May  2 16:45:42 2015
30031   1430599583  /path/to/some/script.pl 94  INFO    script.pl terminated normally on Sat May  2 16:46:23 2015
30036   1430599583  /path/to/some/script.pl 32  FATAL   timeout
kjo
  • 33,683
  • 52
  • 148
  • 265
  • 1
    Log::Log4perl's [easy mode](https://www.securecoding.cert.org/confluence/plugins/servlet/mobile#content/view/76775519) is pretty simple: `use Log::Log4perl qw(:easy); Log::Log4perl->easy_init($DEBUG); DEBUG('Debug this!'); ERROR('Error this!');` – ThisSuitIsBlackNot May 03 '15 at 00:24
  • "logging messages from multiple processes to a common local log file" if each process simply appends to the log file then you're likely to get a corrupted logfile (intermixed writes) if the writes are larger than a certain size ([PIPE_BUF, typically 4096 bytes](http://stackoverflow.com/questions/1154446/is-file-append-atomic-in-unix)). To workaround that you'd need to use locking or send the logs to a separate process such as rsyslogd to offload and serialize the writes. – Tim Bunce May 10 '15 at 12:57

1 Answers1

3

Log::Any with Log::Any::Adapter::File should do the trick.

use Log::Any::Adapter (
    File => $ENV{ EASYLOG_PATH }
    log_level => 'warn',
);

Set this in the your application. Any modules used by your application,

use Log::Any qw( $log );

Later on, if you want to switch to Log4perl, you only need to change the use Log::Any::Adapter statement.

Sinan Ünür
  • 116,958
  • 15
  • 196
  • 339