Download presentation
Presentation is loading. Please wait.
Published byRussell Atkins Modified over 9 years ago
1
Stop Being A Caveman! use Log::Log4perl; by Eric Andreychek eric@openthought.net
2
A long time ago... in a galaxy far, far away people debugged Perl code using print and warn statements some of these Perl coders even used the legendary and infamous Perl debugger these hard working Perl coders were known as... Cavemen
3
Put These To Rest Log4perl can help us make ideas like print, warn, and the Perl debugger artifacts of history
4
Lets get this part out of the way... ● Log4perl lets you log stuff ● In Perl ● And it's really cool
5
All You Need... ● Define a logging level ● Define where and what to log ● Use the (so-simple-it's-silly) interface
6
Log Levels fatal error warn info debug Highest Lowest
7
Logger Objects ● Logger objects ($logger) do the work – Retrieved using Log4perl's get_logger() method ● Logging may occur in any sub in your program – No need to pass $logger to each sub ● Messy and Annoying ● Log4perl stores the logger object internally – A call to get_logger() returns that stored object ● Called a singleton
8
Logging Example $logger = get_logger(); # Logs when warn, info, or debug $logger->warn(“Help me Obi-Wan, you're my only hope”); # Remains dormant when error or fatal!
9
Initializing Log4perl # To set up logging, you could use the following: use Log::Log4perl qw( :easy ); Log::Log4perl->easy_init( $ERROR );
10
Not! We don't need no steenking “easy” # To set up logging, you could use the following: use Log::Log4perl qw( :easy ); Log::Log4perl->easy_init( $ERROR );
11
Initializing Log4perl: / The Real (:?wo)?man's Way/ # Darth.pl use Darth(); use Log::Log4perl(); $config = get_my_config(); Log::Log4perl::init( $config );
12
Using Log4perl package Darth; use Log::Log4perl qw( get_logger ); sub new { my ( $class, $name ) = @_; my $logger = get_logger(); $logger->debug(“Creating Darth $name”); return bless( { darth => $name }, $class ); }
13
Using Log4perl sub get_lightsaber { my $self = shift; my $logger = get_logger(); $logger->debug(“Fetching lightsaber from the armory”); my $saber = $self->_saber_type || “Red Single-Sided Saber”; $logger->warn(“Giving Darth his light saber: $saber”); return $saber; }
14
Log4perl Return Values ● Logging functions return the number of places they were logged – If message logged: return true – If no message logged: return undef – $total = $logger->warn( $message ); ● Being at the WARN level doesn't necessarily mean $logger->warn($message) will be logged – Log4perl could suppress the message – A suppressed message would return undef
15
Using Log4perl: Errors # Later on in darth.pl my $saber = $darth->get_lightsaber; unless ( $saber ) { my $error = “Nothing to defend against the good guys with, ”. “not even an electronic sausage!” # This will often work, but tends to be a really bad idea $logger->fatal( $error ) && die( $error ) # This utility method doesn't depend on the return value of # $logger->fatal, it will always die $logger->logdie( $error ) }
16
Future of Internet Keyboards
17
Configuring The Beast ● Configuring Log4perl: TMTOWTDI – Perl – Config files – Both
18
Config Files (my favorite) use Log::Log4perl qw( get_logger ); Log::Log4perl::init( “log4perl.conf” ); my $logger = get_logger();
19
Config File Example Contents of log4perl.conf log4perl.logger = INFO, Screen log4perl.appender.Screen = Log::Dispatch::Screen log4perl.appender.Screen.layout = SimpleLayout
20
Config File: Category This config applies to my what? log4perl.logger = INFO, Screen log4perl.appender.Screen = Log::Dispatch::Screen log4perl.appender.Screen.layout = SimpleLayout
21
Config File: Appender You want me to log where? log4perl.logger = INFO, Screen log4perl.appender.Screen = Log::Dispatch::Screen log4perl.appender.Screen.layout = SimpleLayout
22
Config File: Message Layout You want me to log how? log4perl.logger = INFO, Screen log4perl.appender.Screen = Log::Dispatch::Screen log4perl.appender.Screen.layout = SimpleLayout
23
Appender (log) Methods ● Log4perl uses Log::Dispatch to perform logging – Log::Dispatch supports a number of locations ● ApacheLog ● DBI ● Email ● Files ● STDOUT / STDERR (Screen) ● Syslog ● Jabber ● Anything else you write
24
Appender Location: Log to File Change From Screen to File log4perl.logger = INFO, Screen log4perl.appender.Screen = Log::Dispatch:: File log4perl.appender.Screen. Filename = myfile.log log4perl.appender.Screen.layout = SimpleLayout
25
Appender Name Should Make Sense! log4perl.logger = INFO, FileLog log4perl.appender. FileLog = Log::Dispatch::File log4perl.appender.FileLog.Filename = myfile.log log4perl.appender. FileLog.layout = SimpleLayout
26
Logging To Multiple Locations Change to File and Screen with Two Appenders log4perl.logger = INFO, Screen, FileLog log4perl.appender.Screen = Log::Dispatch::Screen log4perl.appender.Screen.layout = SimpleLayout log4perl.appender.FileLog = Log::Dispatch::File log4perl.appender.FileLog.filename = myfile.log log4perl.appender.FileLog.layout = SimpleLayout
27
Changing The Log Format log4perl.logger = INFO, Screen log4perl.appender.Screen = Log::Dispatch::Screen log4perl.appender.Screen.layout = PatternLayout log4perl.appender.Screen.layout.ConversionPattern=%F %L: %m%n
28
Available Placeholders (16 total) %c Category of the logging event. %C Fully qualified package (or class) name of the caller %d Current date in yyyy/MM/dd hh:mm:ss format %F File where the logging event occurred %H Hostname %l Fully qualified name of the calling method followed by the callers source the file name and line number between parentheses. %L Line number within the file where the log statement was issued %m The message to be logged %M Method or function where the logging request was issued %n Newline (OS-independent) %p Priority of the logging event %P pid of the current process %r Number of milliseconds elapsed from program start to logging event %x The topmost NDC (see below) %X{key} The entry 'key' of the MDC (see below) % A literal percent (%) sign
29
Custom Placeholders # Define a conversion specifier (cspec) in the config file: log4perl.logger = INFO, Screen log4perl.appender.Screen = Log::Dispatch::Screen log4perl.appender.Screen.layout = PatternLayout log4perl.appender.Screen.layout.ConversionPattern= %O: %F %L %m%n log4perl.PatternLayout.cspec.O = sub { return "OS $^O" }
30
Perl Code In Config File # Programmatically get the filename and layout log4perl.logger = INFO, FileLog log4perl.appender.FileLog = Log::Dispatch::File log4perl.appender.FileLog.Filename = \ sub { getFileName(); } log4perl.appender.FileLog.layout = \ sub { getLayout(); }
31
Code in the Config File: Notes ● We can put any code into the config file ● This code is run within the main namespace ● Some might consider this a security risk – This feature can be disabled with: $Log::Log4perl::ALLOW_CODE_IN_CONFIG_FILE = 0;
32
Take a Break Everyone take a break, and allow Patrick a few moments to catch up
33
Putting Categories to Use Going Beyond the System Defined Root Logger ● One of Log4perl's key features is categories – Enable extra logging for just one portion of your application – Remainder of application produces typical output ● Category name: often the name of the current package / class ● You've seen the default, root category – To use your own, pass a parameter into get_logger() $logger = get_logger( $category_name );
34
Using Categories: Config File # This is the root category / logger log4perl.logger = WARN, Screen # Create a new category like so: log4perl.logger. CategoryName = DEBUG, Screen
35
Using Categories: Class Example Skywalker Class Hierarchy
36
Log Using Multiple Categories ● Leia knows what she wants ● Vader is set in his ways ● We can put these two at a normal log level of “warn” ● Luke has issues ● He should be put at a log level of “debug”
37
Multiple Categories Example Two categories: Log Skywalkers to Screen log4perl.logger. Skywalker = WARN, Screen log4perl.logger.Skywalker.Luke = DEBUG, Screen log4perl.appender.Screen = Log::Dispatch::Screen log4perl.appender.Screen.layout = SimpleLayout
38
Multiple Categories Example Log base class to File, sub class to Screen and File log4perl.logger.Skywalker = WARN, FileLog log4perl.logger.Skywalker.Luke = DEBUG, Screen log4perl.appender.FileLog = Log::Dispatch::File log4perl.appender.FileLog.layout = SimpleLayout log4perl.appender.FileLog.Filename = myfile.log log4perl.appender.Screen = Log::Dispatch::Screen log4perl.appender.Screen.layout = SimpleLayout
39
Tell Log4perl Your Category Pass in Your Class Name ● In package Skywalker: my $logger = get_logger( 'Skywalker' ); ● In package Skywalker::Leia: my $logger = get_logger( 'Skywalker::Leia' ); ● In package Skywalker::Luke: my $logger = get_logger( 'Skywalker::Luke' ); ● Or just... my $logger = get_logger( __PACKAGE__ );
40
Now, Pay Attention!
41
Important Logging Behavior ● Once a logger decides to log a message, it does a few things ● The message is first logged using each appender attached to that logger ● Then, the message is unconditionally logged using every appender attached to the logger's parents
42
Important Logging Behavior Example Config File log4perl.logger = ERROR, Syslog log4perl.logger.Skywalker.Luke = DEBUG, Screen log4perl.appender.Syslog = Log::Dispatch::Syslog log4perl.appender.Syslog.layout = SimpleLayout log4perl.appender.Screen = Log::Dispatch::Screen log4perl.appender.Screen.layout = SimpleLayout
43
Important Logging Behavior ERROR (inherited) Log::Dispatch::S yslog Skywalker Skywalker::LukeSkywalker::Leia ERROR (inherited) DEBUG Log::Dispatch::S creen root logger ERROR
44
What This Means Lets take a look at how logging will work throughout the hierarchy
45
Logging Behavior: root logger Category root logger (when no category is defined) Properties Defines level: ERROR, location: Syslog Code $logger->error( $light_saber ); Result Logs $light_saber to a syslog
46
Logging Behavior: Skywalker, Skywalker::Leia Category Skywalker and Skywalker::Leia Properties Inherits ERROR and Syslog from root logger Code $logger->error( $light_saber ); Result Logs $light_saber to syslog
47
Logging Behavior: Skywalker::Luke Category Skywalker::Luke Properties Defines level: DEBUG, location: Screen Code $logger->error( $light_saber ); Result Logs $light_saber to the screen Logs $light_saber to syslog
48
Logging Behavior: Skywalker::Luke Category Skywalker::Luke Properties Defines level: DEBUG, location: Screen Code $logger-> debug ( $light_saber ); Result (even though parents are at ERROR) Logs $light_saber to the screen Logs $light_saber to syslog
49
Logging Behavior ● Might be unnecessarily duplicating the logs – Luke's debug messages all going to syslog ● Take advantage of Log4perl! – Continue to log all debugging messages to the screen – Be more picky about what gets logged to syslog ● Should all of Skywalker::Luke's debugging messages be in our system logs? – Remember, Luke has a lot of issues
50
Preventing Duplicate Logs ● If this behavior isn't what you want, change it: – Set the additivity of a category to zero ● Prevents messages from bubbling up ● Do this to the Skywalker::Luke category – Set the threshold of an appender to some log level ● Defines a minimum log level for oncoming messages ● Do this to the root or parent category ● Can also set a system-wide default threshold
51
Setting Additivity Prevent The Message From Bubbling Up log4perl.logger = ERROR, Syslog log4perl.logger.Skywalker.Luke = ERROR, Screen log4perl.additivity.Skywalker.Luke = 0 log4perl.appender.Syslog = Log::Dispatch::Syslog log4perl.appender.Syslog.layout = SimpleLayout log4perl.appender.Screen = Log::Dispatch::Screen log4perl.appender.Screen.layout = SimpleLayout
52
Setting a Threshold Define minimum log level of ERROR log4perl.logger = ERROR, Syslog log4perl.logger.Skywalker.Luke = DEBUG, Screen log4perl.appender.Syslog = Log::Dispatch::Syslog log4perl.appender.Syslog.layout = SimpleLayout log4perl.appender.Syslog.Threshold = ERROR log4perl.appender.Screen = Log::Dispatch::Screen log4perl.appender.Screen.layout = SimpleLayout
53
One Last Look ● If a logger decides to fire, it sends the message to all of it's appenders ● The logger then has the message bubble up the hierarchy to hit all the other appenders on the way up
54
Important Logging Behavior This behavior effects our earlier examples!
55
Preventing Duplicate Logs Two categories: Log Skywalkers to Screen # Does this previous example do what you think? log4perl.logger.Skywalker = WARN, Screen log4perl.logger.Skywalker.Luke = DEBUG, Screen log4perl.appender.Screen = Log::Dispatch::Screen log4perl.appender.Screen.layout = SimpleLayout
56
Preventing Duplicate Logs Use Additivity To Your Advantage log4perl.logger.Skywalker = WARN, Screen log4perl.logger.Skywalker.Luke = DEBUG, Screen log4perl.additivity.Skywalker.Luke = 0 log4perl.appender.Screen = Log::Dispatch::Screen log4perl.appender.Screen.layout = SimpleLayout
57
Preventing Duplicate Logs: Filters Yoda Filter: Do or do not, there is no “try” log4perl.logger.Skywalker.Luke = DEBUG, Screen log4perl.appender.Screen = Log::Dispatch::Screen log4perl.appender.Screen.layout = SimpleLayout log4perl.appender.Screen.filter = MyFilter log4perl.filter.MyFilter = sub { /try/i } log4perl.filter.MyFilter.AcceptOnMatch = false
58
this door 0wnz j00
59
Performance Penalties ● Logging has a (small) price tag – Decision to log is made at runtime ● Calls are optimized to run as fast as possible ● There are still things you can do to help
60
Bad Performance Example # Current Log Level: WARN # (doesn't actually log) use Data::Dumper; $logger->debug( “Contents: ”, Dumper( %config ));
61
Optimizing Performance: Example 1 # Pass in a subroutine reference $logger->debug( “Contents: ”, sub { use Data::Dumper; Dumper( %config ) } );
62
Optimizing Performance: Example 2 # Is it necessary to pass any parameters at all? if ( $logger->is_debug ) { $logger->debug( “Array Contents: ”, @big_array ); }
63
Log4perl ● Log4perl has a boatload of features – Different log levels – Multiple logging destinations – Multiple categories ● There's more!
64
Resources ● Log4perl Homepage http://log4perl.sourceforge.net ● Log4perl Documentation http://log4perl.sourceforge.net/releases/LogLog4perl/docs/html/Log/Log4p erl.htm ● Perl.com Article: Retire Your Debugger http://www.perl.com/pub/a/2002/09/11/log4perl.html ● Most Recent Version of this Presentation http://openthought.org
65
Thank You
66
More Cool Stuff (You've reached the bonus slides!)
67
Automatically Rotate Logs # Rotate logs daily, keep no more than 5 files log4perl.logger = WARN, Logfile log4perl.appender.Logfile = Log::Dispatch::FileRotate log4perl.appender.Logfile.filename = /var/log/log4perl.log log4perl.appender.Logfile.max = 5 log4perl.appender.Logfile.DatePattern = yyyy-MM-dd log4perl.appender.Logfile.TZ = EST log4perl.appender.Logfile.layout = SimpleLayout
68
Reloading The Config # To load the config, we originally wrote: Log::Log4perl::init( “config.conf” ); # We can also check the config at regular intervals: Log::Log4perl::init_and_watch( “config.conf”, 60 );
69
Remote Config # We can also use: my $config = “http://openthought.org/config.pl”; Log::Log4perl::init( $config ); # (this doesn't work with init_and_watch... yet)
70
Decisions Based on Log Level Application Which Sends Email my $email_address; if ( $logger->is_debug ) { $email_address = “test_account”; } else { $email_address = “real_account”; } send_email( $email_address );
71
More Decisions Based On Log Level Database Application if ( $logger->is_debug ) { $logger->debug( dumper(%data) ); return; # Don't even touch the database } elsif ( $logger->is_info ) { $database = “Test”; } else { $database = “Production” } $self->insert_into_database( %data );
Similar presentations
© 2024 SlidePlayer.com Inc.
All rights reserved.