Presentation is loading. Please wait.

Presentation is loading. Please wait.

Stop Being A Caveman! use Log::Log4perl; by Eric Andreychek

Similar presentations


Presentation on theme: "Stop Being A Caveman! use Log::Log4perl; by Eric Andreychek"— Presentation transcript:

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 );


Download ppt "Stop Being A Caveman! use Log::Log4perl; by Eric Andreychek"

Similar presentations


Ads by Google