Structured JSON Logging with Log4perl

Posted by Markus Benning on December 28, 2014

With the help of the Log::Log4perl::Layout::JSON module Log4perl is able to output structured logs.

Example Log4perl Configuration with JSON output to syslog:

log4perl.rootLogger = DEBUG,SyslogJSON

# syslog/json logging
log4perl.appender.SyslogJSON = Log::Dispatch::Syslog
log4perl.appender.SyslogJSON.min_level = debug
log4perl.appender.SyslogJSON.ident = myapp
log4perl.appender.SyslogJSON.facility = daemon

log4perl.appender.SyslogJSON.layout = Log::Log4perl::Layout::JSON
log4perl.appender.SyslogJSON.layout.include_mdc = 1
log4perl.appender.SyslogJSON.layout.field.message = %m
log4perl.appender.SyslogJSON.layout.field.class = %C
log4perl.appender.SyslogJSON.layout.field.src_file = %F
log4perl.appender.SyslogJSON.layout.field.src_sub = %M{1}
log4perl.appender.SyslogJSON.layout.field.src_line = %L

Example Code:

use Log::Log4perl;

Log::Log4perl->init('log4perl.conf');
my $logger = Log::Log4perl::get_logger();
$logger->info('just for information');

Example Output:

{
  "src_line" : "784",
  "message" : "just for information",
  "src_sub" : "__ANON__",
  "src_file" : "/usr/share/perl5/Log/Log4perl/Logger.pm",
  "class" : "Log::Log4perl::Logger"
}

The Log4perl MDC feature could be used to attach additional information to all log events produced by your program. For a CGI script it may be usefull to attach the client ip or session information to log events.

Attach additional fields to the MDC:

use Log::Log4perl::MDC;

Log::Log4perl::MDC->put('remote_addr', $cgi->remote_addr);
Log::Log4perl::MDC->put('script_name', $cgi->script_name);
Log::Log4perl::MDC->put('query_string', $cgi->query_string);

MDC Example Output:

{
  "script_name" : "/cgi-bin/myapp.pl",
  "message" : "something is broken!",
  "src_line" : "784",
  "src_sub" : "__ANON__",
  "remote_addr" : "123.123.123.123",
  "query_string" : "bla=blub",
  "class" : "Log::Log4perl::Logger",
  "src_file" : "/usr/local/share/perl/5.20.1/Log/Log4perl/Logger.pm"
}