SlideShare una empresa de Scribd logo
1 de 38
Descargar para leer sin conexión
Getting Modern with
Logging via Log4perl
Dean Hamstead
Sydney PM
July 2015
dean@bytefoundry.com.au
Logging
Despite how much time we spend greping and
tailing logs (or both), logging is:
● Always overlooked
● Rarely done well
○ Inconsistent message formats (“started foo”, “foo
ended”)
○ Unhelpful messages (“Error 0x1234 occurred”)
○ Stacktraces???
○ Organic growth
● Reinvented over and over again
Why are we acting
against our own
self-interest?
Perl Logging 101.
● warn() and die(),
● collected via cron, apache etc.
● Similarly, print STDERR $foo
Better than nothing? Chaos in apache as
everything goes to the fallback error.log
Perl Logging 202.
● open(my $log,’>>’, ‘foo.log’)
● print $log “my message”
● $debug && print $log “debugging message”
For extra marks:
● sub log { print $log localtime, @_,”n” }
● log(“my message”)
● sub debug {} etc...
Perl Logging 203
● package MyApp::Log;
● use MyApp::Log qw/ log /;
● log(“my message”)
or
● $log = MyApp::Log->new();
● $log->message(“my message”)
(Then horrible stuff starts happening like
passing the $log object around)
Decisions, Decisions
Log::Log4perl
● Inspired by Log4j
● Modular
● Its own config file
● Optionally in-line
configured
● Available via CPAN
or your distro
packaging
Log::Dispatch
● It’s own design
● Module
● In-line configured
● Available via CPAN
or your distro
packaging
Also check out...
● Log::Any - which tries to let you not care as
much
● Log::Contextual
● Log::Agent - looks perfectly suitable too
● Sys::Syslog - it may be enough for you
● Apache2::Log - may also be just fine
Let’s just stick with Log4perl...
Installation
# The cpanm way
cpanm Log::Log4perl
# The Debian/Ubuntu/Mint way, where we say log and perl twice
# as a sort of incantation. Don’t say it in the mirror though.
apt-get install liblog-log4perl-perl
# The Fedora/RHEL/CentOS way
yum install ‘perl(Log::Log4perl)’
# The FreeBSD way
pkg install p5-log-log4perl
Basic Usage
use Log::Log4perl;
Log::Log4perl->init('my.log4perl.conf');
# defaults to pwd
$logger = Log::Log4perl->get_logger('My::Instance');
# Call the above over and over, you’ll always get the
# same object. i.e. it’s a Singleton
$logger->info('Foo');
$logger->fatal('Bar');
etc...
Basic Usage ++
Have Log4perl watch the config, reload and
reconfigure automagically on the fly:
Log::Log4perl->init_and_watch()
Or wait for HUP signal with:
Log::Log4perl->init_and_watch($conf_file, 'HUP');
Logging Levels
Lifted from Log::Log4perl pod:
There are six predefined log levels: FATAL, ERROR, WARN, INFO, DEBUG,
and TRACE (in descending priority). Your configured logging level has to at
least match (>=) the priority of the logging message.
If your configured logging level is WARN, then messages logged with info(),
debug(), and trace() will be suppressed. fatal(), error() and warn() will make
their way through, because their priority is higher or equal than the configured
setting.
Logging Levels (cont.)
The 6 basic logging levels have corresponding methods:
$logger->trace("..."); # Log a trace message
$logger->debug("..."); # Log a debug message
$logger->info("..."); # Log a info message
$logger->warn("..."); # Log a warn message
$logger->error("..."); # Log a error message
$logger->fatal("..."); # Log a fatal message
Logging Levels (cont.)
Because, why have just one way?
use Log::Log4perl::Level;
$logger->log($TRACE, "...");
$logger->log($DEBUG, "...");
$logger->log($INFO, "...");
$logger->log($WARN, "...");
$logger->log($ERROR, "...");
$logger->log($FATAL, "...");
This is actually useful for cleanly & concisely varying the log level based on
some logic appropriate to your program.
Austerity is a good thing!
This is expensive and useless if errors aren’t logged:
$logger->error("Erroneous array: @super_long_array");
So we can check before leaping into the cold murky waters:
if($logger->is_error()) {
$logger->error("Erroneous array: @super_long_array");
}
Here is the whole family:
$logger->is_trace() # True if trace messages would go through
$logger->is_debug() # True if debug messages would go through
$logger->is_info() # True if info messages would go through
$logger->is_warn() # True if warn messages would go through
$logger->is_error() # True if error messages would go through
$logger->is_fatal() # True if fatal messages would go through
This example lifted from Log::Log4perl pod
Not true in Log4perl!
Forget:
$logger->fatal($err) && die($err);
Use:
$logger->logdie($err);
Instead of:
warn($message);
$logger->warn($message);
Try:
$logger->logwarn($message);
Shortcuts!
Also you get for free:
● Log event time and date
● System hostname
● Pid of process
● Line number where called
● Package/Class caller
● Chomping, multi-line alignment
● OS-independant newline
● Milliseconds since program started
● Milliseconds since last log event
● Much much more!
Log4perl <3 Carp
Functions that, in addition to logging, also pass
the stringified message to their companions in
the Carp package:
$logger->logcarp(); # warn w/ 1-level stack trace
$logger->logcluck(); # warn w/ full stack trace
$logger->logcroak(); # die w/ 1-level stack trace
$logger->logconfess(); # die w/ full stack trace
Configuration: log4perl.conf
● By default, use a standalone config file
● Softens the observer problem
● Handy with config. management systems
and development. Install the file appropriate
to the environment
● Keep your own personal library of log4perl
configs. Copy them in place as needed.
A Bit of Theory
● As we have seen,
Log4perl provides
standard methods
● In the config file, select the minimum log
level then direct it to an Appender
● An Appender is basically an output
● An Appender can optionally apply a Filter
● Most Appenders allow you to specify a
layout for your log messages
Basic File Output
############################################################
# A simple root logger with a Log::Log4perl::Appender::File
# file appender in Perl.
############################################################
log4perl.rootLogger=DEBUG, LOGFILE
log4perl.appender.LOGFILE=Log::Log4perl::Appender::File
log4perl.appender.LOGFILE.filename=/var/log/myapp/myapp.log
log4perl.appender.LOGFILE.mode=append
log4perl.appender.LOGFILE.layout=PatternLayout
log4perl.appender.LOGFILE.layout.ConversionPattern=[%d] %F %L %c - %m%n
Basic Screen Output
############################################################
# A simple root logger with a Log::Log4perl::Appender::File
# file appender in Perl.
############################################################
log4perl.rootLogger=DEBUG, LOGFILE
log4perl.appender.LOGFILE=Log::Log4perl::Appender::Screen
log4perl.appender.LOGFILE.layout=PatternLayout
log4perl.appender.LOGFILE.layout.ConversionPattern=[%d] %F %L %c - %m%n
Other Appenders
● DBI - make your logs the DBA’s problem
● String - because perl
● RRDs - graphs impress management
● ScreenColoredLevels - like Screen but with colors
● Socket - why not?
3rd Party...
● SMTP - Why not flood your inbox?
● Gearman, RabbitMQ - flood your SOA
● Chunk::Store::S3 - because AWS solves everything
● ElasticSearch(::Bulk) - because no one ever got fired for
using ELK
● Journald - shove it into Lennart Poettering’s monster
When to log?
● Program starts, stops, awakens or sleeps
● Opening files, sockets etc.
● Before and after retrieving URL’s
● Done reading or calculating an important
value
● Before and after decisions
● When exceptions are caught
● Log more details when something bad
happens (insomuch as we can anticipate it)
My Rules of Thumb. Log when...
How much logging in Production?
What’s happening when no one’s watching...
Do not log when...
● You’re a discrete general purpose module
● Instead, “throw exceptions” (i.e. die() or carp()) and make the caller play
catch. Let them log if needed.
my $obj = Foo->new();
eval { $obj->action() };
if ($@) { # handle $@
● Or, return null and provide an error inspection method or variable
$obj->action() or die(‘Bad thing: ‘, $obj->errormsg);
$obj->action() or die(‘Bad thing: ‘, $Foo::errormsg);
● Keep it simple. Write shy modules and avoid side effects.
Using Log4perl in a larger program
● Frameworks tend to have it inbuilt or via
plugin: Catalyst, Net::Server for example.
Profit!
● Don’t pass the $logger object around,
remember that Log4perl is a Singleton!
Example 1
package MyApp::UtilityMethods;
use Log::Log4perl;
# Log::Log4perl::init() called in main::
my $log =
Log::Log4perl->get_logger(__PACKAGE__);
sub action {
$log->debug(q/Running Action/);
}
Example 2
package MyApp::Some::Base;
use Log::Log4perl; # Log::Log4perl::init() is called in main::
sub log { return $self->{_log} }
sub new {
my ( $p, @a ) = @_;
my $c = ref($p) || $p;
my $self = bless {}, $c;
$self->{_log} = Log::Log4perl->get_logger(ref $self);
$self->log->debug( q|I'm here| );
return $self
}
Example 2 (cont.)
package MyApp::Some::Thing;
use parent qw/ MyApp::Some::Base /;
sub action {
my $self = shift;
$self->log->debug(q| Running Action |);
}
Planning
● Have clear guidelines for severity levels
Planning (cont.)
● Let Log4perl take care of metadata line the
timestamp, hostname, pid, package name
etc.
$log->debug(‘Program: starting up at ’
. localtime()
$log->debug(‘starting up’);
Planning (cont.)
● Design consistent messages that are easily parsed
(regex match) and tokenized
$log->debug(q|starting up|);
$log->debug(q|got arguments: |.join(q|,|,@args));
$log->debug(q|shutting down|);
$log->debug(q|action: starting|);
$log->debug(q|action: init arguments: |.join(q|,|@args));
$log->debug(q|action: shutdown|);
You’ll be super grateful for this when you inevitably start
looking at ElasticSearch
Questions?
Thanks for listening

Más contenido relacionado

La actualidad más candente

Php(report)
Php(report)Php(report)
Php(report)
Yhannah
 
Php Operators N Controllers
Php Operators N ControllersPhp Operators N Controllers
Php Operators N Controllers
mussawir20
 
Php tutorial(w3schools)
Php tutorial(w3schools)Php tutorial(w3schools)
Php tutorial(w3schools)
Arjun Shanka
 
Design patterns revisited with PHP 5.3
Design patterns revisited with PHP 5.3Design patterns revisited with PHP 5.3
Design patterns revisited with PHP 5.3
Fabien Potencier
 

La actualidad más candente (20)

Introduction to PHP
Introduction to PHPIntroduction to PHP
Introduction to PHP
 
PHP
PHPPHP
PHP
 
Php Debugger
Php DebuggerPhp Debugger
Php Debugger
 
PyCon Korea 2019 REST API Document Generation
PyCon Korea 2019 REST API Document GenerationPyCon Korea 2019 REST API Document Generation
PyCon Korea 2019 REST API Document Generation
 
Php(report)
Php(report)Php(report)
Php(report)
 
Php Operators N Controllers
Php Operators N ControllersPhp Operators N Controllers
Php Operators N Controllers
 
Php tutorial
Php tutorialPhp tutorial
Php tutorial
 
Working Effectively With Legacy Code
Working Effectively With Legacy CodeWorking Effectively With Legacy Code
Working Effectively With Legacy Code
 
PHP 5.3
PHP 5.3PHP 5.3
PHP 5.3
 
Unit testing PHP apps with PHPUnit
Unit testing PHP apps with PHPUnitUnit testing PHP apps with PHPUnit
Unit testing PHP apps with PHPUnit
 
High Quality Symfony Bundles tutorial - Dutch PHP Conference 2014
High Quality Symfony Bundles tutorial - Dutch PHP Conference 2014High Quality Symfony Bundles tutorial - Dutch PHP Conference 2014
High Quality Symfony Bundles tutorial - Dutch PHP Conference 2014
 
TDD, BDD, RSpec
TDD, BDD, RSpecTDD, BDD, RSpec
TDD, BDD, RSpec
 
JavaScript - From Birth To Closure
JavaScript - From Birth To ClosureJavaScript - From Birth To Closure
JavaScript - From Birth To Closure
 
PHP - Introduction to PHP - Mazenet Solution
PHP - Introduction to PHP - Mazenet SolutionPHP - Introduction to PHP - Mazenet Solution
PHP - Introduction to PHP - Mazenet Solution
 
Web development
Web developmentWeb development
Web development
 
07 Introduction to PHP #burningkeyboards
07 Introduction to PHP #burningkeyboards07 Introduction to PHP #burningkeyboards
07 Introduction to PHP #burningkeyboards
 
Php tutorial(w3schools)
Php tutorial(w3schools)Php tutorial(w3schools)
Php tutorial(w3schools)
 
Living With Legacy Code
Living With Legacy CodeLiving With Legacy Code
Living With Legacy Code
 
Advanced PHPUnit Testing
Advanced PHPUnit TestingAdvanced PHPUnit Testing
Advanced PHPUnit Testing
 
Design patterns revisited with PHP 5.3
Design patterns revisited with PHP 5.3Design patterns revisited with PHP 5.3
Design patterns revisited with PHP 5.3
 

Similar a Getting modern with logging via log4perl

Troubleshooting Plone
Troubleshooting PloneTroubleshooting Plone
Troubleshooting Plone
Ricado Alves
 
Errors, Exceptions & Logging (PHPNW13 Uncon)
Errors, Exceptions & Logging (PHPNW13 Uncon)Errors, Exceptions & Logging (PHPNW13 Uncon)
Errors, Exceptions & Logging (PHPNW13 Uncon)
James Titcumb
 

Similar a Getting modern with logging via log4perl (20)

PHP - Introduction to PHP Error Handling
PHP -  Introduction to PHP Error HandlingPHP -  Introduction to PHP Error Handling
PHP - Introduction to PHP Error Handling
 
Low Latency Logging with RabbitMQ (PHP London - 4th Sep 2014)
Low Latency Logging with RabbitMQ (PHP London - 4th Sep 2014)Low Latency Logging with RabbitMQ (PHP London - 4th Sep 2014)
Low Latency Logging with RabbitMQ (PHP London - 4th Sep 2014)
 
Low Latency Logging with RabbitMQ (Brno PHP, CZ - 20th Sep 2014)
Low Latency Logging with RabbitMQ (Brno PHP, CZ - 20th Sep 2014)Low Latency Logging with RabbitMQ (Brno PHP, CZ - 20th Sep 2014)
Low Latency Logging with RabbitMQ (Brno PHP, CZ - 20th Sep 2014)
 
Application Logging in the 21st century - 2014.key
Application Logging in the 21st century - 2014.keyApplication Logging in the 21st century - 2014.key
Application Logging in the 21st century - 2014.key
 
PerlScripting
PerlScriptingPerlScripting
PerlScripting
 
Troubleshooting Plone
Troubleshooting PloneTroubleshooting Plone
Troubleshooting Plone
 
Logging
LoggingLogging
Logging
 
TYPO3 Extension development using new Extbase framework
TYPO3 Extension development using new Extbase frameworkTYPO3 Extension development using new Extbase framework
TYPO3 Extension development using new Extbase framework
 
Logging in Python for large applications
Logging in Python for large applicationsLogging in Python for large applications
Logging in Python for large applications
 
Errors, Exceptions & Logging (PHPNW13 Uncon)
Errors, Exceptions & Logging (PHPNW13 Uncon)Errors, Exceptions & Logging (PHPNW13 Uncon)
Errors, Exceptions & Logging (PHPNW13 Uncon)
 
Errors, Exceptions & Logging (PHP Hants Oct '13)
Errors, Exceptions & Logging (PHP Hants Oct '13)Errors, Exceptions & Logging (PHP Hants Oct '13)
Errors, Exceptions & Logging (PHP Hants Oct '13)
 
The Art Of Application Logging PHPNW12
The Art Of Application Logging PHPNW12The Art Of Application Logging PHPNW12
The Art Of Application Logging PHPNW12
 
Mojolicious
MojoliciousMojolicious
Mojolicious
 
Bioinformatica 27-10-2011-p4-files
Bioinformatica 27-10-2011-p4-filesBioinformatica 27-10-2011-p4-files
Bioinformatica 27-10-2011-p4-files
 
Bioinformatics p4-io v2013-wim_vancriekinge
Bioinformatics p4-io v2013-wim_vancriekingeBioinformatics p4-io v2013-wim_vancriekinge
Bioinformatics p4-io v2013-wim_vancriekinge
 
SPL, not a bridge too far
SPL, not a bridge too farSPL, not a bridge too far
SPL, not a bridge too far
 
Low latency Logging (BrightonPHP - 18th Nov 2013)
Low latency Logging (BrightonPHP - 18th Nov 2013)Low latency Logging (BrightonPHP - 18th Nov 2013)
Low latency Logging (BrightonPHP - 18th Nov 2013)
 
10 Catalyst Tips
10 Catalyst Tips10 Catalyst Tips
10 Catalyst Tips
 
Php logging
Php loggingPhp logging
Php logging
 
Master perl io_2011
Master perl io_2011Master perl io_2011
Master perl io_2011
 

Último

%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
masabamasaba
 
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
chiefasafspells
 
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
masabamasaba
 

Último (20)

WSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go PlatformlessWSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go Platformless
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
 
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
 
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
 
Microsoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdfMicrosoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdf
 
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
 
Architecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the pastArchitecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the past
 
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
 
What Goes Wrong with Language Definitions and How to Improve the Situation
What Goes Wrong with Language Definitions and How to Improve the SituationWhat Goes Wrong with Language Definitions and How to Improve the Situation
What Goes Wrong with Language Definitions and How to Improve the Situation
 
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
 
8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students
 
%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto
 
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation Template
 
%in Benoni+277-882-255-28 abortion pills for sale in Benoni
%in Benoni+277-882-255-28 abortion pills for sale in Benoni%in Benoni+277-882-255-28 abortion pills for sale in Benoni
%in Benoni+277-882-255-28 abortion pills for sale in Benoni
 
Announcing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK SoftwareAnnouncing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK Software
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learn
 
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
 

Getting modern with logging via log4perl

  • 1. Getting Modern with Logging via Log4perl Dean Hamstead Sydney PM July 2015 dean@bytefoundry.com.au
  • 2. Logging Despite how much time we spend greping and tailing logs (or both), logging is: ● Always overlooked ● Rarely done well ○ Inconsistent message formats (“started foo”, “foo ended”) ○ Unhelpful messages (“Error 0x1234 occurred”) ○ Stacktraces??? ○ Organic growth ● Reinvented over and over again
  • 3. Why are we acting against our own self-interest?
  • 4. Perl Logging 101. ● warn() and die(), ● collected via cron, apache etc. ● Similarly, print STDERR $foo Better than nothing? Chaos in apache as everything goes to the fallback error.log
  • 5. Perl Logging 202. ● open(my $log,’>>’, ‘foo.log’) ● print $log “my message” ● $debug && print $log “debugging message” For extra marks: ● sub log { print $log localtime, @_,”n” } ● log(“my message”) ● sub debug {} etc...
  • 6. Perl Logging 203 ● package MyApp::Log; ● use MyApp::Log qw/ log /; ● log(“my message”) or ● $log = MyApp::Log->new(); ● $log->message(“my message”) (Then horrible stuff starts happening like passing the $log object around)
  • 7.
  • 8. Decisions, Decisions Log::Log4perl ● Inspired by Log4j ● Modular ● Its own config file ● Optionally in-line configured ● Available via CPAN or your distro packaging Log::Dispatch ● It’s own design ● Module ● In-line configured ● Available via CPAN or your distro packaging
  • 9. Also check out... ● Log::Any - which tries to let you not care as much ● Log::Contextual ● Log::Agent - looks perfectly suitable too ● Sys::Syslog - it may be enough for you ● Apache2::Log - may also be just fine
  • 10. Let’s just stick with Log4perl...
  • 11. Installation # The cpanm way cpanm Log::Log4perl # The Debian/Ubuntu/Mint way, where we say log and perl twice # as a sort of incantation. Don’t say it in the mirror though. apt-get install liblog-log4perl-perl # The Fedora/RHEL/CentOS way yum install ‘perl(Log::Log4perl)’ # The FreeBSD way pkg install p5-log-log4perl
  • 12. Basic Usage use Log::Log4perl; Log::Log4perl->init('my.log4perl.conf'); # defaults to pwd $logger = Log::Log4perl->get_logger('My::Instance'); # Call the above over and over, you’ll always get the # same object. i.e. it’s a Singleton $logger->info('Foo'); $logger->fatal('Bar'); etc...
  • 13. Basic Usage ++ Have Log4perl watch the config, reload and reconfigure automagically on the fly: Log::Log4perl->init_and_watch() Or wait for HUP signal with: Log::Log4perl->init_and_watch($conf_file, 'HUP');
  • 14. Logging Levels Lifted from Log::Log4perl pod: There are six predefined log levels: FATAL, ERROR, WARN, INFO, DEBUG, and TRACE (in descending priority). Your configured logging level has to at least match (>=) the priority of the logging message. If your configured logging level is WARN, then messages logged with info(), debug(), and trace() will be suppressed. fatal(), error() and warn() will make their way through, because their priority is higher or equal than the configured setting.
  • 15. Logging Levels (cont.) The 6 basic logging levels have corresponding methods: $logger->trace("..."); # Log a trace message $logger->debug("..."); # Log a debug message $logger->info("..."); # Log a info message $logger->warn("..."); # Log a warn message $logger->error("..."); # Log a error message $logger->fatal("..."); # Log a fatal message
  • 16. Logging Levels (cont.) Because, why have just one way? use Log::Log4perl::Level; $logger->log($TRACE, "..."); $logger->log($DEBUG, "..."); $logger->log($INFO, "..."); $logger->log($WARN, "..."); $logger->log($ERROR, "..."); $logger->log($FATAL, "..."); This is actually useful for cleanly & concisely varying the log level based on some logic appropriate to your program.
  • 17. Austerity is a good thing! This is expensive and useless if errors aren’t logged: $logger->error("Erroneous array: @super_long_array"); So we can check before leaping into the cold murky waters: if($logger->is_error()) { $logger->error("Erroneous array: @super_long_array"); } Here is the whole family: $logger->is_trace() # True if trace messages would go through $logger->is_debug() # True if debug messages would go through $logger->is_info() # True if info messages would go through $logger->is_warn() # True if warn messages would go through $logger->is_error() # True if error messages would go through $logger->is_fatal() # True if fatal messages would go through This example lifted from Log::Log4perl pod
  • 18. Not true in Log4perl!
  • 19. Forget: $logger->fatal($err) && die($err); Use: $logger->logdie($err); Instead of: warn($message); $logger->warn($message); Try: $logger->logwarn($message); Shortcuts!
  • 20. Also you get for free: ● Log event time and date ● System hostname ● Pid of process ● Line number where called ● Package/Class caller ● Chomping, multi-line alignment ● OS-independant newline ● Milliseconds since program started ● Milliseconds since last log event ● Much much more!
  • 21. Log4perl <3 Carp Functions that, in addition to logging, also pass the stringified message to their companions in the Carp package: $logger->logcarp(); # warn w/ 1-level stack trace $logger->logcluck(); # warn w/ full stack trace $logger->logcroak(); # die w/ 1-level stack trace $logger->logconfess(); # die w/ full stack trace
  • 22. Configuration: log4perl.conf ● By default, use a standalone config file ● Softens the observer problem ● Handy with config. management systems and development. Install the file appropriate to the environment ● Keep your own personal library of log4perl configs. Copy them in place as needed.
  • 23. A Bit of Theory ● As we have seen, Log4perl provides standard methods ● In the config file, select the minimum log level then direct it to an Appender ● An Appender is basically an output ● An Appender can optionally apply a Filter ● Most Appenders allow you to specify a layout for your log messages
  • 24. Basic File Output ############################################################ # A simple root logger with a Log::Log4perl::Appender::File # file appender in Perl. ############################################################ log4perl.rootLogger=DEBUG, LOGFILE log4perl.appender.LOGFILE=Log::Log4perl::Appender::File log4perl.appender.LOGFILE.filename=/var/log/myapp/myapp.log log4perl.appender.LOGFILE.mode=append log4perl.appender.LOGFILE.layout=PatternLayout log4perl.appender.LOGFILE.layout.ConversionPattern=[%d] %F %L %c - %m%n
  • 25. Basic Screen Output ############################################################ # A simple root logger with a Log::Log4perl::Appender::File # file appender in Perl. ############################################################ log4perl.rootLogger=DEBUG, LOGFILE log4perl.appender.LOGFILE=Log::Log4perl::Appender::Screen log4perl.appender.LOGFILE.layout=PatternLayout log4perl.appender.LOGFILE.layout.ConversionPattern=[%d] %F %L %c - %m%n
  • 26. Other Appenders ● DBI - make your logs the DBA’s problem ● String - because perl ● RRDs - graphs impress management ● ScreenColoredLevels - like Screen but with colors ● Socket - why not? 3rd Party... ● SMTP - Why not flood your inbox? ● Gearman, RabbitMQ - flood your SOA ● Chunk::Store::S3 - because AWS solves everything ● ElasticSearch(::Bulk) - because no one ever got fired for using ELK ● Journald - shove it into Lennart Poettering’s monster
  • 28. ● Program starts, stops, awakens or sleeps ● Opening files, sockets etc. ● Before and after retrieving URL’s ● Done reading or calculating an important value ● Before and after decisions ● When exceptions are caught ● Log more details when something bad happens (insomuch as we can anticipate it) My Rules of Thumb. Log when...
  • 29. How much logging in Production? What’s happening when no one’s watching...
  • 30. Do not log when... ● You’re a discrete general purpose module ● Instead, “throw exceptions” (i.e. die() or carp()) and make the caller play catch. Let them log if needed. my $obj = Foo->new(); eval { $obj->action() }; if ($@) { # handle $@ ● Or, return null and provide an error inspection method or variable $obj->action() or die(‘Bad thing: ‘, $obj->errormsg); $obj->action() or die(‘Bad thing: ‘, $Foo::errormsg); ● Keep it simple. Write shy modules and avoid side effects.
  • 31. Using Log4perl in a larger program ● Frameworks tend to have it inbuilt or via plugin: Catalyst, Net::Server for example. Profit! ● Don’t pass the $logger object around, remember that Log4perl is a Singleton!
  • 32. Example 1 package MyApp::UtilityMethods; use Log::Log4perl; # Log::Log4perl::init() called in main:: my $log = Log::Log4perl->get_logger(__PACKAGE__); sub action { $log->debug(q/Running Action/); }
  • 33. Example 2 package MyApp::Some::Base; use Log::Log4perl; # Log::Log4perl::init() is called in main:: sub log { return $self->{_log} } sub new { my ( $p, @a ) = @_; my $c = ref($p) || $p; my $self = bless {}, $c; $self->{_log} = Log::Log4perl->get_logger(ref $self); $self->log->debug( q|I'm here| ); return $self }
  • 34. Example 2 (cont.) package MyApp::Some::Thing; use parent qw/ MyApp::Some::Base /; sub action { my $self = shift; $self->log->debug(q| Running Action |); }
  • 35. Planning ● Have clear guidelines for severity levels
  • 36. Planning (cont.) ● Let Log4perl take care of metadata line the timestamp, hostname, pid, package name etc. $log->debug(‘Program: starting up at ’ . localtime() $log->debug(‘starting up’);
  • 37. Planning (cont.) ● Design consistent messages that are easily parsed (regex match) and tokenized $log->debug(q|starting up|); $log->debug(q|got arguments: |.join(q|,|,@args)); $log->debug(q|shutting down|); $log->debug(q|action: starting|); $log->debug(q|action: init arguments: |.join(q|,|@args)); $log->debug(q|action: shutdown|); You’ll be super grateful for this when you inevitably start looking at ElasticSearch