Top Banner
1 | Page Instant Messenger logging: Instant Messenger logging: Instant Messenger logging: Instant Messenger logging: Rein Rein Rein Rein-in the ab in the ab in the ab in the ability lity lity lity of log4j with of log4j with of log4j with of log4j with Gtalk Gtalk Gtalk Gtalk (PNotifyAppender NotifyAppender NotifyAppender NotifyAppender) BY BY BY BY SAURAV PAUL SAURAV PAUL SAURAV PAUL SAURAV PAUL
13

Rein_in_the_ability_of_log4j

Nov 10, 2014

Download

Technology

It describes how to build Instant Messenger logger using log4j with GTalk
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Rein_in_the_ability_of_log4j

1 | P a g e

Instant Messenger loggingInstant Messenger loggingInstant Messenger loggingInstant Messenger logging

ReinReinReinRein----in the abin the abin the abin the abiiiilitylitylitylity of log4j with of log4j with of log4j with of log4j with GtalkGtalkGtalkGtalk

((((PPPPNotifyAppenderNotifyAppenderNotifyAppenderNotifyAppender))))

BYBYBYBY SAURAV PAULSAURAV PAULSAURAV PAULSAURAV PAUL

2 | P a g e

TABLE OF CONTENTSTABLE OF CONTENTSTABLE OF CONTENTSTABLE OF CONTENTS

SL NO TOPICS PAGE NO 1 Introduction 3 2 Revisit-log4j framework in brief 3-7 3 Case study real-world example appender 7-8 4 Overview of PNotifyAppender 9-11 5 Putting it all together 11-13 6 Conclusion 13 7 Resources 13

Note 1 For Technical details ndash refer page no 3-11 2 Guide to quick start ndash refer page no 11-13

3 | P a g e

1 1 1 1 IntroductionIntroductionIntroductionIntroduction No matter how many well-designed test cases you write even the smallest application will hide one or more bugs once itrsquos deployed in the production environment While test-driven development and QA practices improve code quality and provide confidence in the application when a system fails dev elopers and system administrators need contextual information about its execution With the appropriate information they can identify the nature of the problem and fix it quickly saving time and money Logging application events is a central part of many applications Most of our applications do some sort of logging using a variety of mechanisms When things go wrong the first course of action is usually to get hold of the application log file and go through its contents Someone supporting live deployed applications would probably appreciate the importance of getting notified of application errors as early as possible It is much better to be proactive dealing with errors rather than waiting to hear from the customer that something seems to have gone wrong So how about getting notified immediately by utilizing an instant messenger client like Gtalk Messenger

2 Revis2 Revis2 Revis2 Revisitititit----llllog4jog4jog4jog4j fffframework in brieframework in brieframework in brieframework in brief The log4j framework is the de facto logging framework written in the Java language As part of the Jakarta project it is distributed under the Apache Software License a popular open source license certified by the Open Source Initiative (OSI) The log4j environment is fully configurable programmatically or through configuration files either in properties or XML format In addition it allows dev elopers to filter out logging requests selectively without modifying the source code The log4j environment has three main components Loggers Control which logging statements are enabled or disabled Loggers may be assigned the levels ALL DEBUG INFO WARN ERROR FATAL or OFF To make a logging request you invoke one of the printing methods of Logger instance Layout Format the logging request according to the users wishes Appenders Send formatted output to its destinations

21 Under the hood All appenders must extend the orgapachelog4jAppenderSkeleton class an abstract class that implements the orgapachelog4jAppender and orgapachelog4jspiOptionHandler interfaces The UML class diagram of the AppenderSkeleton

4 | P a g e

Lets examine the methods of the Appender interface implemented by the AppenderSkeleton class As Listing above indicates nearly all methods in the Appender interface are setter and getter methods Appender Interface package orgapachelog4j public interface Appender void addFilter (Filter newFilter) public Filter getFilter () public void close () public void clearFilters () public void close () public String getName () public void setErrorHandler (ErrorHandler errorHandler) public ErrorHandler setErrorHandler () public void set Layout (Layout layout) public Layout getLayout () public void setName (String name) public boolean requiresLayout () These methods handle appender properties like the following Name Appenders are named entities so there is a settergetter for its name

5 | P a g e

Layout Appenders may have a Layout associated with them so there is another settergetter method for the lay out Note as said it may but not must The reason is that some appenders dont require a lay out Layout manages format output -- that is it returns a String representation of the LoggingEvent On the other hand JMSAppender sends the event serialized so youre not required to attach a layout with it If your custom appender doesnt require a layout the requiresLayout () method must return false to prevent log4j from complaining about missing layout information ErrorHandler Another settergetter method exists for ErrorHandler Appenders may delegate their error handling to an ErrorHandler object -- an interface in the orgapachelog4jspi package There are two implementing classes OnlyOnceErrorHandler and FallbackErrorHandler The OnlyOnceErrorHandler implements log4js default error handling policy which consists of emitting a message for the first error in an appender and ignoring all following errors The error message is printed on Systemerr FallbackErrorHandler implements the ErrorHandler interface such that a secondary appender may be specified This secondary appender takes over if the primary appender fails The error message is printed on Systemerr then logged in new secondary appender There are other methods to manage filters (such as the addFilter () clearFilters () and getFilter () methods) Even though log4j has several built-in ways to filter log requests (such as repository -wide level logger level and appender threshold) it is also very powerful in its approach to using custom filters An appender can contain multiple filters Custom filters must extend the orgapachelog4jspiFilter abstract class This abstract class requires filters to be organized in a linear chain The decide (LoggingEvent) method orgapachelog4jspiFilter an abstract Class of each filter is called sequentially in the order it was added to the chain Custom filters are based on ternary logic The decide () method must return one of the DENY NEUTRAL or ACCEPT integer constants Besides settergetter methods and the ones related with filters there are two other methods close () and doAppend () The close () method releases any resources allocated within the appender such as file handlers network connections and so on When coding your custom appender be sure you implement this method so that when your appender is closed its closed field is set to true The doAppend () method follows the Gang of Four (GOF) Template Method design pattern This method provides a skeleton of an algorithm deferring some steps to subclasses public synchronized void doAppend (LoggingEvent event) if (closed) s t e p 1 LogLogerror(Attempted to append to closed appender [ + name + ]) return if ( isAsSevereAsThreshold (eventlevel)) s t e p 2 return Filter f = thisheadFilter s t e p 3 FILTER_LOOP while (f = null) switch (f decide (event)) case Filter DENY return case FilterACCEPT break FILTER_LOOP case FilterNEUTRAL f = fnext

6 | P a g e

this append (e v e n t) s t e p 4 211 The algorithm 1 Checks whether the appender is closed 2 Checks whether the logging event is below the threshold of the appender 3 Checks whether filters attached to the appender if any deny the request 4 Invokes append () method of the appender This step is delegated to each subclass The methods and properties that AppenderSkeleton inherits from Appender Lets see why AppenderSkeleton implements the OptionHandler interface OptionHandler contains only one method activateOptions () This method is invoked by a configurator class after calling setter methods for properties Some properties depend on each other so they cannot be activated until all of them have been loaded such as in the activateOptions () method This method is a mechanism for developers to perform whatever tasks were necessary before the appender became activated and ready In addition to all the methods mentioned look again at Class diagram above Notice that AppenderSkeleton provides a new abstract method (append () method) and a new JavaBeans property (threshold) The threshold property is used to filter logging requests by the appender with only requests over the threshold handled We mentioned append () method before when we talked about the doAppend () method It is an abstract method that your custom appender must implement because the framework calls it within the doAppend () method The append () method is one of the hooks of the framework Now that wersquove seen all the methods available in the AppenderSkeleton class lets see whats happening behind the scenes Below figure illustrates the life cycle of an appender object inside log4j

7 | P a g e

212 Letrsquos take a look in brief what is going on above diagram The appender instance does not exist Perhaps the framework has not been yet configured The framework instantiates a new appender This happens when the configurator classes parse an appender declaration in configuration scripts The configurator classes call ClassnewInstance YourCustomAppenderclass) which is the dynamic equivalent of calling new YourCustomAppender () The framework does this so that the framework is not hard-coded to any specific appender name the framework is generic and works with any appender The framework determines whether the appender requires a layout If the appender does not require a lay out then configurators dont try to load lay out information from configuration scripts Log4j configurator calls setter methods The framework transparently handles appenders properties following JavaBeans naming conventions Configurator invokes the activateOptions () method After all the properties have been set the framework invokes this method Programmers can activate properties here that have to be activated at the same time Appender is ready At this point the framework can call append () method to handle a logging request This method is invoked by the AppenderSkeleton doAppend () method Finally the appender is closed When the framework is about to remove y our custom appender instance it calls y our appenders close () method close () is a cleanup method which means you need to free all the resources you have allocated It is a required method and it takes no parameters It must set the closed field to true alerting the framework when an attempt to use a closed appender occurs Weve reviewed the concepts related to building y our own appender 3 Case study r3 Case study r3 Case study r3 Case study realealealeal----world example appenderworld example appenderworld example appenderworld example appender 31 Writing an Instant Messenger -based appender The code presented in this document shows how you can extend the log4j framework to integrate IM features Its designed to enable a log4j-compliant application to log its output onto Instant Messenger like GTalk The PNotifyAppender actually works as a customized IM client However instead of Systemout files or TCP sockets it takes Instant Messenger as the underlying output device To provide IM support we dont need to reinvent the wheel when developing ad-hoc solutions Instead were going to leverage a tool here I considered the best of breed GTalk which internally uses XML based protocol for instant messaging and presence ie XMPP (Extensible Messaging and Presence Protocol) which is an open-standard communications protocol for message-oriented middleware based on XML the protocol originally named as Jabber We chose Jabber over other IM systems because it offers a wide variety of benefits including its 1 Open source 2 Simplicity 3 Interoperability with other IM systems 4 Resource awareness

8 | P a g e

32 Usage Scenario of PNotifyAppender Below diagram shows the PNotifyAppender usage scenario Any application configured to use PNotifyAppender logs its debugging data wrapped as GTalk IM message The instant message is routed over organization network to the system administrator Thus whenever system administrator needs to check on the application status they simply log into their Gmail account using Gtalk IM using his desktop or laptops at work or when he is away from his desk he may use Gtalk IM running on any handheld devices As Gtalk IM has the capability to notify us even when we are offline once we log in it will notify system administrator with the pending notifications or real time

But why do we need PNotifyAppender The answer is that sending messages to IM (Gtalk) allows us to monitor application behavior more easily with tools at our disposal PNotifyAppender offers several advantages 1 You get real-time notification about the exception occurred at server we can consider as ldquoImmediate Loggingrdquo 2 GTalk IM isnrsquot just for desktop computers It is also being developed for wireless devices such as PDArsquos and mobile phones 3 No setup overhead 4 PNotifyAppender notifies the real time exception immediately with the exception details automatically to the Instant Messenger like GTalk and has the ability to keep track of the exception history into the GMail account

9 | P a g e

4 Ov4 Ov4 Ov4 Overviewerviewerviewerview of of of of PNotifyAppenderPNotifyAppenderPNotifyAppenderPNotifyAppender PNotifyAppender is modeled based on SMTPAppender logging strategy PNotifyAppender stores logging events in an internal cyclic buffer and send them as an instant message only when the logging request received triggers a user-specified condition Optionally users may provide a triggering event evaluator class However by default delivery is triggered on events assigned the level ERROR or higher The number of logging events delivered in each message is limited by the buffer size The cyclic buffer holds only the last buffer size logging events overflowing when it becomes full and throwing away the older events To connect to a GTalk PNotifyAppender relies on Smack API Smack is an open source high-level library that handles the protocol details for communicating with GTalk servers As a result you dont need any special Jabber or XML expertise to understand the code The properties for PNotifyAppender are summarized in Table 1

Property Description Type Required

username Gmail Account username eg anthing123 If SSL is true then eg anything123gmailcom

String Yes

password Gmail Account password String Yes

toNotify Recipients address just as e-mail addresses do xxxxgmailcom

String Yes

SSL Used to secure connections boolean No defaults to false

buffersize The maximum number of logging events that can be kept in the cyclic buffer

int

defaults is 16

evaluatorClass

Takes as a value a string representing the fully qualified name of a class that implements the orgapachelog4jspi TriggeringEventEvaluator interface (in other words a class that contains a custom triggering logic that overrides the default one) If this option is not specified PNotifyAppender uses an instance of the DefaultEvaluator class which triggers a response to events assigned the level ERROR or higher

String

No defaults to DefaultEvaluator

proxy It is used to identify whether log4j application behind any proxy

boolean No Default is false

proxyHost If the proxy property is true proxyHost takes the proxy address Example 192168xxxx

String Yes if proxy sets to true else No

proxyPort Proxy Port eg 3245 String Yes if proxy sets to true else No

history This property is used if we want to log the exception history of the real time notification

boolean No Default is false

subject The subject option takes a string value which should be a the subject of the e-mail message

String Yes if history sets to true else No

cc Set the cc recipient addresses String No

bcc Set the bcc recipient addresses String No

SMTPHost The SMTPHost option takes a string value which should be a the host name of the SMTP server that will send the email message

String Yes if history sets to true else No

10 | P a g e

41 Letrsquos take a closer look at below code package compnotifyappender import orgapachelog4jAppenderSkeleton import orgapachelog4jLayout import orgapachelog4jhelpersCyclicBuffer import orgapachelog4jhelpersLogLog import orgapachelog4jhelpersOptionConverter import orgapachelog4jspiLoggingEvent import orgapachelog4jspiTriggeringEventEvaluator public class PNotifyAppender extends AppenderSkeleton protected CyclicBuffer cb private int buffersize private String username private String password private String toNotify private boolean SSL private String proxyHost private String proxyPort private boolean proxy protected boolean checkEntryConditions () public boolean verifyRosterEntryJabberClient (XMPPConnection connection) AppenderSkeleton callback method public void activateOptions () protected void sendBuffer () public synchronized void close () public boolean requiresLayout () return true protected void append (LoggingEvent event) Notice the following about the PNotifyAppender a) The PNotifyAppender class extends orgapachelog4jAppenderSkeleton which all custom appenders must do PNotifyAppender inherits common functionalities from AppenderSkeleton such as appender threshold and custom filtering b) The first part of our appender is straight-forward We have the appenders fields and setget methods f or each of them Properties and method signatures obey the JavaBeans naming convention Thus log4j can analyze the appender using ref lection transparently handling the appender configuration c) To complete our appender we must implement the callback methods that the log4j framework calls to manage our appender requiresLayout () activateOptions () append () and close ()The log4j framework calls the requiresLayout () method to know whether the custom appender requires a lay out Notice that some appenders use a built-in format or dont format the events at all so they dont require a Layout object The PNotifyAppender requires a lay out hence the method returns true

11 | P a g e

d) Notice that AppenderSkeleton implements the orgapachelog4jspiOptionHandler interface AppenderSkeleton implements the single method of this interface activateOptions () as an empty method PNotifyAppender needs this method because of the interdependence between its properties For example the connection with a GTalk Server depends on the Host Port username password and toNotify properties so PNotifyAppender cannot establish a connection until these five properties have been initialized The log4j framework calls the activateOptions () method to signal to the appenders that all the properties have been set e) Once the activateOptions () method returns the appender is ready to handle logging requests AppenderSkeletondoAppend () does most of the real appending work f) The checkEntryConditions () method checks whether there is a Chat object available to append the output and also whether there is a Layout object to format the incoming event object If these preconditions are not satisfied then append () outputs a warning message and returns without proceeding g) The sendBuffer () method sends the contents of the buffer as an IM message The method loops through the events kept in the buffer formatting each one by invoking the format () method of the layout object The string representation of the events is appended to a StringBuffer object Finally sendBuffer () calls the sendMessage () method of the chat object sending the message h) The AppenderSkeletondoAppend () method which invokes append () is synchronized so sendBuffer () already owns the monitor for the appender This frees us from needing to synchronize the CyclicBuffer Object cb i) The verifyRosterEntryJabber () method subscribes to the given email Id provided to toNotify property of the PNotifyAppender if it is not present into account

5 Putting5 Putting5 Putting5 Putting it all togetherit all togetherit all togetherit all together Well wrap up by showing you PNotifyAppender in action STEP 1STEP 1STEP 1STEP 1 Drop in the requisite Jars into application a) commons-logging-111jar b) log4j-1216jar c) mailjar d) smackjar (321) e) smackxjar (321) f) pnotifyappenderjar STEP STEP STEP STEP 2 2 2 2 Configuring log4jproperties log4jrootLogger=GTALK STEP 21STEP 21STEP 21STEP 21 Minimum configuration required if we want real time notification of the exception in GTalk log4jappenderGTALK=compnotifyappenderPNotifyAppender log4jappenderGTALKThreshold=ERROR log4jappenderGTALKusername=xxxxxxx or xxxxxgmailcom (if SSLhistory property is set to true) log4jappenderGTALKpassword=xxxxxxx log4jappenderGTALKtoNotify=xxxxgmailcom log4jappenderGTALKlayout=orgapachelog4jPatternLayout log4jappenderGTALKlayoutConversionPattern=dMM-ddHHmmss[-5p][CML]-(F) mn

12 | P a g e

log4jadditivityGTALK=false if behind a proxy log4jappenderGTALKproxy=true log4jappenderGTALKproxyHost=xxxxxxxxx log4jappenderGTALKproxyPort=xxxx STEP 2STEP 2STEP 2STEP 22222 If we want to keep the history of notified exception into the respective GMail account log4jappenderGTALK=compnotifyappenderPNotifyAppender log4jappenderGTALKThreshold=ERROR log4jappenderGTALKusername=xxxxxgmailcom log4jappenderGTALKpassword=xxxxxxx log4jappenderGTALKtoNotify=xxxxgmailcom log4jappenderGTALKlayout=orgapachelog4jPatternLayout log4jappenderGTALKlayoutConversionPattern=dMM-ddHHmmss[-5p][CML]-(F) mn log4jappenderGTALKhistory=true log4jappenderGTALKSMTPHost=smtpgmailcom log4jappenderGTALKsubject=Email Notification from Application log4jappenderGTALKcc=xxxxxxxxcom log4jappenderGTALKbcc=xxxxxxxxcom log4jadditivityGTALK=false The above configuration script adds PNotifyAppender to the root logger so each logging request received will be dispatched to our appender When we run our respective application An IM message then pops up on the recipients screen and the below screenshots shows the resulting message received by GTalk and GMail

13 | P a g e

Notice that the above figure depicts the real time notification about the exception occurred in the application at GTalk in the mail Id mentioned in toNotify property of PNotifyAppender

The above figure depicts the exception got recorded into the given GMail Account when history property in PNotifyAppender is set to true and setting the other dependent property As we can see in the both cases the exception information contained in the last Logging events has been correctly transmitted This example application simply showcases use of the PNotifyAppender so explore and have fun

6 Conclusion6 Conclusion6 Conclusion6 Conclusion The log4j network appenders SocketAppender JMSAppender and SMTPAppender already provide mechanisms to monitor Java-distributed applications However several factors make IM a suitable technology for remote logging in real-time In this article weve covered the basics of extending log4j with y our custom appenders and weve seen the implementation of a basic PNotifyAppender step by step Many developers and system administrators can benefit from their use

7 Resources7 Resources7 Resources7 Resources 1 httploggingapacheorglog4j12 2 httpwwwjavaworldcomjavaworldjw-10-1999jw-10-cooltoolshtml 3 Book Template Method - Design Patterns in Java by Steven John Metsker and William CWake 4 httpwwwigniterealtimeorgprojectssmack 5 Book Instant Messaging in Java the jabber Protocol by Ian Shigeoka 6 MagicwithMerling Exception and Logging httpwwwibmcomdeveloperworksjavalibraryj-mer1211indexhtml

Page 2: Rein_in_the_ability_of_log4j

2 | P a g e

TABLE OF CONTENTSTABLE OF CONTENTSTABLE OF CONTENTSTABLE OF CONTENTS

SL NO TOPICS PAGE NO 1 Introduction 3 2 Revisit-log4j framework in brief 3-7 3 Case study real-world example appender 7-8 4 Overview of PNotifyAppender 9-11 5 Putting it all together 11-13 6 Conclusion 13 7 Resources 13

Note 1 For Technical details ndash refer page no 3-11 2 Guide to quick start ndash refer page no 11-13

3 | P a g e

1 1 1 1 IntroductionIntroductionIntroductionIntroduction No matter how many well-designed test cases you write even the smallest application will hide one or more bugs once itrsquos deployed in the production environment While test-driven development and QA practices improve code quality and provide confidence in the application when a system fails dev elopers and system administrators need contextual information about its execution With the appropriate information they can identify the nature of the problem and fix it quickly saving time and money Logging application events is a central part of many applications Most of our applications do some sort of logging using a variety of mechanisms When things go wrong the first course of action is usually to get hold of the application log file and go through its contents Someone supporting live deployed applications would probably appreciate the importance of getting notified of application errors as early as possible It is much better to be proactive dealing with errors rather than waiting to hear from the customer that something seems to have gone wrong So how about getting notified immediately by utilizing an instant messenger client like Gtalk Messenger

2 Revis2 Revis2 Revis2 Revisitititit----llllog4jog4jog4jog4j fffframework in brieframework in brieframework in brieframework in brief The log4j framework is the de facto logging framework written in the Java language As part of the Jakarta project it is distributed under the Apache Software License a popular open source license certified by the Open Source Initiative (OSI) The log4j environment is fully configurable programmatically or through configuration files either in properties or XML format In addition it allows dev elopers to filter out logging requests selectively without modifying the source code The log4j environment has three main components Loggers Control which logging statements are enabled or disabled Loggers may be assigned the levels ALL DEBUG INFO WARN ERROR FATAL or OFF To make a logging request you invoke one of the printing methods of Logger instance Layout Format the logging request according to the users wishes Appenders Send formatted output to its destinations

21 Under the hood All appenders must extend the orgapachelog4jAppenderSkeleton class an abstract class that implements the orgapachelog4jAppender and orgapachelog4jspiOptionHandler interfaces The UML class diagram of the AppenderSkeleton

4 | P a g e

Lets examine the methods of the Appender interface implemented by the AppenderSkeleton class As Listing above indicates nearly all methods in the Appender interface are setter and getter methods Appender Interface package orgapachelog4j public interface Appender void addFilter (Filter newFilter) public Filter getFilter () public void close () public void clearFilters () public void close () public String getName () public void setErrorHandler (ErrorHandler errorHandler) public ErrorHandler setErrorHandler () public void set Layout (Layout layout) public Layout getLayout () public void setName (String name) public boolean requiresLayout () These methods handle appender properties like the following Name Appenders are named entities so there is a settergetter for its name

5 | P a g e

Layout Appenders may have a Layout associated with them so there is another settergetter method for the lay out Note as said it may but not must The reason is that some appenders dont require a lay out Layout manages format output -- that is it returns a String representation of the LoggingEvent On the other hand JMSAppender sends the event serialized so youre not required to attach a layout with it If your custom appender doesnt require a layout the requiresLayout () method must return false to prevent log4j from complaining about missing layout information ErrorHandler Another settergetter method exists for ErrorHandler Appenders may delegate their error handling to an ErrorHandler object -- an interface in the orgapachelog4jspi package There are two implementing classes OnlyOnceErrorHandler and FallbackErrorHandler The OnlyOnceErrorHandler implements log4js default error handling policy which consists of emitting a message for the first error in an appender and ignoring all following errors The error message is printed on Systemerr FallbackErrorHandler implements the ErrorHandler interface such that a secondary appender may be specified This secondary appender takes over if the primary appender fails The error message is printed on Systemerr then logged in new secondary appender There are other methods to manage filters (such as the addFilter () clearFilters () and getFilter () methods) Even though log4j has several built-in ways to filter log requests (such as repository -wide level logger level and appender threshold) it is also very powerful in its approach to using custom filters An appender can contain multiple filters Custom filters must extend the orgapachelog4jspiFilter abstract class This abstract class requires filters to be organized in a linear chain The decide (LoggingEvent) method orgapachelog4jspiFilter an abstract Class of each filter is called sequentially in the order it was added to the chain Custom filters are based on ternary logic The decide () method must return one of the DENY NEUTRAL or ACCEPT integer constants Besides settergetter methods and the ones related with filters there are two other methods close () and doAppend () The close () method releases any resources allocated within the appender such as file handlers network connections and so on When coding your custom appender be sure you implement this method so that when your appender is closed its closed field is set to true The doAppend () method follows the Gang of Four (GOF) Template Method design pattern This method provides a skeleton of an algorithm deferring some steps to subclasses public synchronized void doAppend (LoggingEvent event) if (closed) s t e p 1 LogLogerror(Attempted to append to closed appender [ + name + ]) return if ( isAsSevereAsThreshold (eventlevel)) s t e p 2 return Filter f = thisheadFilter s t e p 3 FILTER_LOOP while (f = null) switch (f decide (event)) case Filter DENY return case FilterACCEPT break FILTER_LOOP case FilterNEUTRAL f = fnext

6 | P a g e

this append (e v e n t) s t e p 4 211 The algorithm 1 Checks whether the appender is closed 2 Checks whether the logging event is below the threshold of the appender 3 Checks whether filters attached to the appender if any deny the request 4 Invokes append () method of the appender This step is delegated to each subclass The methods and properties that AppenderSkeleton inherits from Appender Lets see why AppenderSkeleton implements the OptionHandler interface OptionHandler contains only one method activateOptions () This method is invoked by a configurator class after calling setter methods for properties Some properties depend on each other so they cannot be activated until all of them have been loaded such as in the activateOptions () method This method is a mechanism for developers to perform whatever tasks were necessary before the appender became activated and ready In addition to all the methods mentioned look again at Class diagram above Notice that AppenderSkeleton provides a new abstract method (append () method) and a new JavaBeans property (threshold) The threshold property is used to filter logging requests by the appender with only requests over the threshold handled We mentioned append () method before when we talked about the doAppend () method It is an abstract method that your custom appender must implement because the framework calls it within the doAppend () method The append () method is one of the hooks of the framework Now that wersquove seen all the methods available in the AppenderSkeleton class lets see whats happening behind the scenes Below figure illustrates the life cycle of an appender object inside log4j

7 | P a g e

212 Letrsquos take a look in brief what is going on above diagram The appender instance does not exist Perhaps the framework has not been yet configured The framework instantiates a new appender This happens when the configurator classes parse an appender declaration in configuration scripts The configurator classes call ClassnewInstance YourCustomAppenderclass) which is the dynamic equivalent of calling new YourCustomAppender () The framework does this so that the framework is not hard-coded to any specific appender name the framework is generic and works with any appender The framework determines whether the appender requires a layout If the appender does not require a lay out then configurators dont try to load lay out information from configuration scripts Log4j configurator calls setter methods The framework transparently handles appenders properties following JavaBeans naming conventions Configurator invokes the activateOptions () method After all the properties have been set the framework invokes this method Programmers can activate properties here that have to be activated at the same time Appender is ready At this point the framework can call append () method to handle a logging request This method is invoked by the AppenderSkeleton doAppend () method Finally the appender is closed When the framework is about to remove y our custom appender instance it calls y our appenders close () method close () is a cleanup method which means you need to free all the resources you have allocated It is a required method and it takes no parameters It must set the closed field to true alerting the framework when an attempt to use a closed appender occurs Weve reviewed the concepts related to building y our own appender 3 Case study r3 Case study r3 Case study r3 Case study realealealeal----world example appenderworld example appenderworld example appenderworld example appender 31 Writing an Instant Messenger -based appender The code presented in this document shows how you can extend the log4j framework to integrate IM features Its designed to enable a log4j-compliant application to log its output onto Instant Messenger like GTalk The PNotifyAppender actually works as a customized IM client However instead of Systemout files or TCP sockets it takes Instant Messenger as the underlying output device To provide IM support we dont need to reinvent the wheel when developing ad-hoc solutions Instead were going to leverage a tool here I considered the best of breed GTalk which internally uses XML based protocol for instant messaging and presence ie XMPP (Extensible Messaging and Presence Protocol) which is an open-standard communications protocol for message-oriented middleware based on XML the protocol originally named as Jabber We chose Jabber over other IM systems because it offers a wide variety of benefits including its 1 Open source 2 Simplicity 3 Interoperability with other IM systems 4 Resource awareness

8 | P a g e

32 Usage Scenario of PNotifyAppender Below diagram shows the PNotifyAppender usage scenario Any application configured to use PNotifyAppender logs its debugging data wrapped as GTalk IM message The instant message is routed over organization network to the system administrator Thus whenever system administrator needs to check on the application status they simply log into their Gmail account using Gtalk IM using his desktop or laptops at work or when he is away from his desk he may use Gtalk IM running on any handheld devices As Gtalk IM has the capability to notify us even when we are offline once we log in it will notify system administrator with the pending notifications or real time

But why do we need PNotifyAppender The answer is that sending messages to IM (Gtalk) allows us to monitor application behavior more easily with tools at our disposal PNotifyAppender offers several advantages 1 You get real-time notification about the exception occurred at server we can consider as ldquoImmediate Loggingrdquo 2 GTalk IM isnrsquot just for desktop computers It is also being developed for wireless devices such as PDArsquos and mobile phones 3 No setup overhead 4 PNotifyAppender notifies the real time exception immediately with the exception details automatically to the Instant Messenger like GTalk and has the ability to keep track of the exception history into the GMail account

9 | P a g e

4 Ov4 Ov4 Ov4 Overviewerviewerviewerview of of of of PNotifyAppenderPNotifyAppenderPNotifyAppenderPNotifyAppender PNotifyAppender is modeled based on SMTPAppender logging strategy PNotifyAppender stores logging events in an internal cyclic buffer and send them as an instant message only when the logging request received triggers a user-specified condition Optionally users may provide a triggering event evaluator class However by default delivery is triggered on events assigned the level ERROR or higher The number of logging events delivered in each message is limited by the buffer size The cyclic buffer holds only the last buffer size logging events overflowing when it becomes full and throwing away the older events To connect to a GTalk PNotifyAppender relies on Smack API Smack is an open source high-level library that handles the protocol details for communicating with GTalk servers As a result you dont need any special Jabber or XML expertise to understand the code The properties for PNotifyAppender are summarized in Table 1

Property Description Type Required

username Gmail Account username eg anthing123 If SSL is true then eg anything123gmailcom

String Yes

password Gmail Account password String Yes

toNotify Recipients address just as e-mail addresses do xxxxgmailcom

String Yes

SSL Used to secure connections boolean No defaults to false

buffersize The maximum number of logging events that can be kept in the cyclic buffer

int

defaults is 16

evaluatorClass

Takes as a value a string representing the fully qualified name of a class that implements the orgapachelog4jspi TriggeringEventEvaluator interface (in other words a class that contains a custom triggering logic that overrides the default one) If this option is not specified PNotifyAppender uses an instance of the DefaultEvaluator class which triggers a response to events assigned the level ERROR or higher

String

No defaults to DefaultEvaluator

proxy It is used to identify whether log4j application behind any proxy

boolean No Default is false

proxyHost If the proxy property is true proxyHost takes the proxy address Example 192168xxxx

String Yes if proxy sets to true else No

proxyPort Proxy Port eg 3245 String Yes if proxy sets to true else No

history This property is used if we want to log the exception history of the real time notification

boolean No Default is false

subject The subject option takes a string value which should be a the subject of the e-mail message

String Yes if history sets to true else No

cc Set the cc recipient addresses String No

bcc Set the bcc recipient addresses String No

SMTPHost The SMTPHost option takes a string value which should be a the host name of the SMTP server that will send the email message

String Yes if history sets to true else No

10 | P a g e

41 Letrsquos take a closer look at below code package compnotifyappender import orgapachelog4jAppenderSkeleton import orgapachelog4jLayout import orgapachelog4jhelpersCyclicBuffer import orgapachelog4jhelpersLogLog import orgapachelog4jhelpersOptionConverter import orgapachelog4jspiLoggingEvent import orgapachelog4jspiTriggeringEventEvaluator public class PNotifyAppender extends AppenderSkeleton protected CyclicBuffer cb private int buffersize private String username private String password private String toNotify private boolean SSL private String proxyHost private String proxyPort private boolean proxy protected boolean checkEntryConditions () public boolean verifyRosterEntryJabberClient (XMPPConnection connection) AppenderSkeleton callback method public void activateOptions () protected void sendBuffer () public synchronized void close () public boolean requiresLayout () return true protected void append (LoggingEvent event) Notice the following about the PNotifyAppender a) The PNotifyAppender class extends orgapachelog4jAppenderSkeleton which all custom appenders must do PNotifyAppender inherits common functionalities from AppenderSkeleton such as appender threshold and custom filtering b) The first part of our appender is straight-forward We have the appenders fields and setget methods f or each of them Properties and method signatures obey the JavaBeans naming convention Thus log4j can analyze the appender using ref lection transparently handling the appender configuration c) To complete our appender we must implement the callback methods that the log4j framework calls to manage our appender requiresLayout () activateOptions () append () and close ()The log4j framework calls the requiresLayout () method to know whether the custom appender requires a lay out Notice that some appenders use a built-in format or dont format the events at all so they dont require a Layout object The PNotifyAppender requires a lay out hence the method returns true

11 | P a g e

d) Notice that AppenderSkeleton implements the orgapachelog4jspiOptionHandler interface AppenderSkeleton implements the single method of this interface activateOptions () as an empty method PNotifyAppender needs this method because of the interdependence between its properties For example the connection with a GTalk Server depends on the Host Port username password and toNotify properties so PNotifyAppender cannot establish a connection until these five properties have been initialized The log4j framework calls the activateOptions () method to signal to the appenders that all the properties have been set e) Once the activateOptions () method returns the appender is ready to handle logging requests AppenderSkeletondoAppend () does most of the real appending work f) The checkEntryConditions () method checks whether there is a Chat object available to append the output and also whether there is a Layout object to format the incoming event object If these preconditions are not satisfied then append () outputs a warning message and returns without proceeding g) The sendBuffer () method sends the contents of the buffer as an IM message The method loops through the events kept in the buffer formatting each one by invoking the format () method of the layout object The string representation of the events is appended to a StringBuffer object Finally sendBuffer () calls the sendMessage () method of the chat object sending the message h) The AppenderSkeletondoAppend () method which invokes append () is synchronized so sendBuffer () already owns the monitor for the appender This frees us from needing to synchronize the CyclicBuffer Object cb i) The verifyRosterEntryJabber () method subscribes to the given email Id provided to toNotify property of the PNotifyAppender if it is not present into account

5 Putting5 Putting5 Putting5 Putting it all togetherit all togetherit all togetherit all together Well wrap up by showing you PNotifyAppender in action STEP 1STEP 1STEP 1STEP 1 Drop in the requisite Jars into application a) commons-logging-111jar b) log4j-1216jar c) mailjar d) smackjar (321) e) smackxjar (321) f) pnotifyappenderjar STEP STEP STEP STEP 2 2 2 2 Configuring log4jproperties log4jrootLogger=GTALK STEP 21STEP 21STEP 21STEP 21 Minimum configuration required if we want real time notification of the exception in GTalk log4jappenderGTALK=compnotifyappenderPNotifyAppender log4jappenderGTALKThreshold=ERROR log4jappenderGTALKusername=xxxxxxx or xxxxxgmailcom (if SSLhistory property is set to true) log4jappenderGTALKpassword=xxxxxxx log4jappenderGTALKtoNotify=xxxxgmailcom log4jappenderGTALKlayout=orgapachelog4jPatternLayout log4jappenderGTALKlayoutConversionPattern=dMM-ddHHmmss[-5p][CML]-(F) mn

12 | P a g e

log4jadditivityGTALK=false if behind a proxy log4jappenderGTALKproxy=true log4jappenderGTALKproxyHost=xxxxxxxxx log4jappenderGTALKproxyPort=xxxx STEP 2STEP 2STEP 2STEP 22222 If we want to keep the history of notified exception into the respective GMail account log4jappenderGTALK=compnotifyappenderPNotifyAppender log4jappenderGTALKThreshold=ERROR log4jappenderGTALKusername=xxxxxgmailcom log4jappenderGTALKpassword=xxxxxxx log4jappenderGTALKtoNotify=xxxxgmailcom log4jappenderGTALKlayout=orgapachelog4jPatternLayout log4jappenderGTALKlayoutConversionPattern=dMM-ddHHmmss[-5p][CML]-(F) mn log4jappenderGTALKhistory=true log4jappenderGTALKSMTPHost=smtpgmailcom log4jappenderGTALKsubject=Email Notification from Application log4jappenderGTALKcc=xxxxxxxxcom log4jappenderGTALKbcc=xxxxxxxxcom log4jadditivityGTALK=false The above configuration script adds PNotifyAppender to the root logger so each logging request received will be dispatched to our appender When we run our respective application An IM message then pops up on the recipients screen and the below screenshots shows the resulting message received by GTalk and GMail

13 | P a g e

Notice that the above figure depicts the real time notification about the exception occurred in the application at GTalk in the mail Id mentioned in toNotify property of PNotifyAppender

The above figure depicts the exception got recorded into the given GMail Account when history property in PNotifyAppender is set to true and setting the other dependent property As we can see in the both cases the exception information contained in the last Logging events has been correctly transmitted This example application simply showcases use of the PNotifyAppender so explore and have fun

6 Conclusion6 Conclusion6 Conclusion6 Conclusion The log4j network appenders SocketAppender JMSAppender and SMTPAppender already provide mechanisms to monitor Java-distributed applications However several factors make IM a suitable technology for remote logging in real-time In this article weve covered the basics of extending log4j with y our custom appenders and weve seen the implementation of a basic PNotifyAppender step by step Many developers and system administrators can benefit from their use

7 Resources7 Resources7 Resources7 Resources 1 httploggingapacheorglog4j12 2 httpwwwjavaworldcomjavaworldjw-10-1999jw-10-cooltoolshtml 3 Book Template Method - Design Patterns in Java by Steven John Metsker and William CWake 4 httpwwwigniterealtimeorgprojectssmack 5 Book Instant Messaging in Java the jabber Protocol by Ian Shigeoka 6 MagicwithMerling Exception and Logging httpwwwibmcomdeveloperworksjavalibraryj-mer1211indexhtml

Page 3: Rein_in_the_ability_of_log4j

3 | P a g e

1 1 1 1 IntroductionIntroductionIntroductionIntroduction No matter how many well-designed test cases you write even the smallest application will hide one or more bugs once itrsquos deployed in the production environment While test-driven development and QA practices improve code quality and provide confidence in the application when a system fails dev elopers and system administrators need contextual information about its execution With the appropriate information they can identify the nature of the problem and fix it quickly saving time and money Logging application events is a central part of many applications Most of our applications do some sort of logging using a variety of mechanisms When things go wrong the first course of action is usually to get hold of the application log file and go through its contents Someone supporting live deployed applications would probably appreciate the importance of getting notified of application errors as early as possible It is much better to be proactive dealing with errors rather than waiting to hear from the customer that something seems to have gone wrong So how about getting notified immediately by utilizing an instant messenger client like Gtalk Messenger

2 Revis2 Revis2 Revis2 Revisitititit----llllog4jog4jog4jog4j fffframework in brieframework in brieframework in brieframework in brief The log4j framework is the de facto logging framework written in the Java language As part of the Jakarta project it is distributed under the Apache Software License a popular open source license certified by the Open Source Initiative (OSI) The log4j environment is fully configurable programmatically or through configuration files either in properties or XML format In addition it allows dev elopers to filter out logging requests selectively without modifying the source code The log4j environment has three main components Loggers Control which logging statements are enabled or disabled Loggers may be assigned the levels ALL DEBUG INFO WARN ERROR FATAL or OFF To make a logging request you invoke one of the printing methods of Logger instance Layout Format the logging request according to the users wishes Appenders Send formatted output to its destinations

21 Under the hood All appenders must extend the orgapachelog4jAppenderSkeleton class an abstract class that implements the orgapachelog4jAppender and orgapachelog4jspiOptionHandler interfaces The UML class diagram of the AppenderSkeleton

4 | P a g e

Lets examine the methods of the Appender interface implemented by the AppenderSkeleton class As Listing above indicates nearly all methods in the Appender interface are setter and getter methods Appender Interface package orgapachelog4j public interface Appender void addFilter (Filter newFilter) public Filter getFilter () public void close () public void clearFilters () public void close () public String getName () public void setErrorHandler (ErrorHandler errorHandler) public ErrorHandler setErrorHandler () public void set Layout (Layout layout) public Layout getLayout () public void setName (String name) public boolean requiresLayout () These methods handle appender properties like the following Name Appenders are named entities so there is a settergetter for its name

5 | P a g e

Layout Appenders may have a Layout associated with them so there is another settergetter method for the lay out Note as said it may but not must The reason is that some appenders dont require a lay out Layout manages format output -- that is it returns a String representation of the LoggingEvent On the other hand JMSAppender sends the event serialized so youre not required to attach a layout with it If your custom appender doesnt require a layout the requiresLayout () method must return false to prevent log4j from complaining about missing layout information ErrorHandler Another settergetter method exists for ErrorHandler Appenders may delegate their error handling to an ErrorHandler object -- an interface in the orgapachelog4jspi package There are two implementing classes OnlyOnceErrorHandler and FallbackErrorHandler The OnlyOnceErrorHandler implements log4js default error handling policy which consists of emitting a message for the first error in an appender and ignoring all following errors The error message is printed on Systemerr FallbackErrorHandler implements the ErrorHandler interface such that a secondary appender may be specified This secondary appender takes over if the primary appender fails The error message is printed on Systemerr then logged in new secondary appender There are other methods to manage filters (such as the addFilter () clearFilters () and getFilter () methods) Even though log4j has several built-in ways to filter log requests (such as repository -wide level logger level and appender threshold) it is also very powerful in its approach to using custom filters An appender can contain multiple filters Custom filters must extend the orgapachelog4jspiFilter abstract class This abstract class requires filters to be organized in a linear chain The decide (LoggingEvent) method orgapachelog4jspiFilter an abstract Class of each filter is called sequentially in the order it was added to the chain Custom filters are based on ternary logic The decide () method must return one of the DENY NEUTRAL or ACCEPT integer constants Besides settergetter methods and the ones related with filters there are two other methods close () and doAppend () The close () method releases any resources allocated within the appender such as file handlers network connections and so on When coding your custom appender be sure you implement this method so that when your appender is closed its closed field is set to true The doAppend () method follows the Gang of Four (GOF) Template Method design pattern This method provides a skeleton of an algorithm deferring some steps to subclasses public synchronized void doAppend (LoggingEvent event) if (closed) s t e p 1 LogLogerror(Attempted to append to closed appender [ + name + ]) return if ( isAsSevereAsThreshold (eventlevel)) s t e p 2 return Filter f = thisheadFilter s t e p 3 FILTER_LOOP while (f = null) switch (f decide (event)) case Filter DENY return case FilterACCEPT break FILTER_LOOP case FilterNEUTRAL f = fnext

6 | P a g e

this append (e v e n t) s t e p 4 211 The algorithm 1 Checks whether the appender is closed 2 Checks whether the logging event is below the threshold of the appender 3 Checks whether filters attached to the appender if any deny the request 4 Invokes append () method of the appender This step is delegated to each subclass The methods and properties that AppenderSkeleton inherits from Appender Lets see why AppenderSkeleton implements the OptionHandler interface OptionHandler contains only one method activateOptions () This method is invoked by a configurator class after calling setter methods for properties Some properties depend on each other so they cannot be activated until all of them have been loaded such as in the activateOptions () method This method is a mechanism for developers to perform whatever tasks were necessary before the appender became activated and ready In addition to all the methods mentioned look again at Class diagram above Notice that AppenderSkeleton provides a new abstract method (append () method) and a new JavaBeans property (threshold) The threshold property is used to filter logging requests by the appender with only requests over the threshold handled We mentioned append () method before when we talked about the doAppend () method It is an abstract method that your custom appender must implement because the framework calls it within the doAppend () method The append () method is one of the hooks of the framework Now that wersquove seen all the methods available in the AppenderSkeleton class lets see whats happening behind the scenes Below figure illustrates the life cycle of an appender object inside log4j

7 | P a g e

212 Letrsquos take a look in brief what is going on above diagram The appender instance does not exist Perhaps the framework has not been yet configured The framework instantiates a new appender This happens when the configurator classes parse an appender declaration in configuration scripts The configurator classes call ClassnewInstance YourCustomAppenderclass) which is the dynamic equivalent of calling new YourCustomAppender () The framework does this so that the framework is not hard-coded to any specific appender name the framework is generic and works with any appender The framework determines whether the appender requires a layout If the appender does not require a lay out then configurators dont try to load lay out information from configuration scripts Log4j configurator calls setter methods The framework transparently handles appenders properties following JavaBeans naming conventions Configurator invokes the activateOptions () method After all the properties have been set the framework invokes this method Programmers can activate properties here that have to be activated at the same time Appender is ready At this point the framework can call append () method to handle a logging request This method is invoked by the AppenderSkeleton doAppend () method Finally the appender is closed When the framework is about to remove y our custom appender instance it calls y our appenders close () method close () is a cleanup method which means you need to free all the resources you have allocated It is a required method and it takes no parameters It must set the closed field to true alerting the framework when an attempt to use a closed appender occurs Weve reviewed the concepts related to building y our own appender 3 Case study r3 Case study r3 Case study r3 Case study realealealeal----world example appenderworld example appenderworld example appenderworld example appender 31 Writing an Instant Messenger -based appender The code presented in this document shows how you can extend the log4j framework to integrate IM features Its designed to enable a log4j-compliant application to log its output onto Instant Messenger like GTalk The PNotifyAppender actually works as a customized IM client However instead of Systemout files or TCP sockets it takes Instant Messenger as the underlying output device To provide IM support we dont need to reinvent the wheel when developing ad-hoc solutions Instead were going to leverage a tool here I considered the best of breed GTalk which internally uses XML based protocol for instant messaging and presence ie XMPP (Extensible Messaging and Presence Protocol) which is an open-standard communications protocol for message-oriented middleware based on XML the protocol originally named as Jabber We chose Jabber over other IM systems because it offers a wide variety of benefits including its 1 Open source 2 Simplicity 3 Interoperability with other IM systems 4 Resource awareness

8 | P a g e

32 Usage Scenario of PNotifyAppender Below diagram shows the PNotifyAppender usage scenario Any application configured to use PNotifyAppender logs its debugging data wrapped as GTalk IM message The instant message is routed over organization network to the system administrator Thus whenever system administrator needs to check on the application status they simply log into their Gmail account using Gtalk IM using his desktop or laptops at work or when he is away from his desk he may use Gtalk IM running on any handheld devices As Gtalk IM has the capability to notify us even when we are offline once we log in it will notify system administrator with the pending notifications or real time

But why do we need PNotifyAppender The answer is that sending messages to IM (Gtalk) allows us to monitor application behavior more easily with tools at our disposal PNotifyAppender offers several advantages 1 You get real-time notification about the exception occurred at server we can consider as ldquoImmediate Loggingrdquo 2 GTalk IM isnrsquot just for desktop computers It is also being developed for wireless devices such as PDArsquos and mobile phones 3 No setup overhead 4 PNotifyAppender notifies the real time exception immediately with the exception details automatically to the Instant Messenger like GTalk and has the ability to keep track of the exception history into the GMail account

9 | P a g e

4 Ov4 Ov4 Ov4 Overviewerviewerviewerview of of of of PNotifyAppenderPNotifyAppenderPNotifyAppenderPNotifyAppender PNotifyAppender is modeled based on SMTPAppender logging strategy PNotifyAppender stores logging events in an internal cyclic buffer and send them as an instant message only when the logging request received triggers a user-specified condition Optionally users may provide a triggering event evaluator class However by default delivery is triggered on events assigned the level ERROR or higher The number of logging events delivered in each message is limited by the buffer size The cyclic buffer holds only the last buffer size logging events overflowing when it becomes full and throwing away the older events To connect to a GTalk PNotifyAppender relies on Smack API Smack is an open source high-level library that handles the protocol details for communicating with GTalk servers As a result you dont need any special Jabber or XML expertise to understand the code The properties for PNotifyAppender are summarized in Table 1

Property Description Type Required

username Gmail Account username eg anthing123 If SSL is true then eg anything123gmailcom

String Yes

password Gmail Account password String Yes

toNotify Recipients address just as e-mail addresses do xxxxgmailcom

String Yes

SSL Used to secure connections boolean No defaults to false

buffersize The maximum number of logging events that can be kept in the cyclic buffer

int

defaults is 16

evaluatorClass

Takes as a value a string representing the fully qualified name of a class that implements the orgapachelog4jspi TriggeringEventEvaluator interface (in other words a class that contains a custom triggering logic that overrides the default one) If this option is not specified PNotifyAppender uses an instance of the DefaultEvaluator class which triggers a response to events assigned the level ERROR or higher

String

No defaults to DefaultEvaluator

proxy It is used to identify whether log4j application behind any proxy

boolean No Default is false

proxyHost If the proxy property is true proxyHost takes the proxy address Example 192168xxxx

String Yes if proxy sets to true else No

proxyPort Proxy Port eg 3245 String Yes if proxy sets to true else No

history This property is used if we want to log the exception history of the real time notification

boolean No Default is false

subject The subject option takes a string value which should be a the subject of the e-mail message

String Yes if history sets to true else No

cc Set the cc recipient addresses String No

bcc Set the bcc recipient addresses String No

SMTPHost The SMTPHost option takes a string value which should be a the host name of the SMTP server that will send the email message

String Yes if history sets to true else No

10 | P a g e

41 Letrsquos take a closer look at below code package compnotifyappender import orgapachelog4jAppenderSkeleton import orgapachelog4jLayout import orgapachelog4jhelpersCyclicBuffer import orgapachelog4jhelpersLogLog import orgapachelog4jhelpersOptionConverter import orgapachelog4jspiLoggingEvent import orgapachelog4jspiTriggeringEventEvaluator public class PNotifyAppender extends AppenderSkeleton protected CyclicBuffer cb private int buffersize private String username private String password private String toNotify private boolean SSL private String proxyHost private String proxyPort private boolean proxy protected boolean checkEntryConditions () public boolean verifyRosterEntryJabberClient (XMPPConnection connection) AppenderSkeleton callback method public void activateOptions () protected void sendBuffer () public synchronized void close () public boolean requiresLayout () return true protected void append (LoggingEvent event) Notice the following about the PNotifyAppender a) The PNotifyAppender class extends orgapachelog4jAppenderSkeleton which all custom appenders must do PNotifyAppender inherits common functionalities from AppenderSkeleton such as appender threshold and custom filtering b) The first part of our appender is straight-forward We have the appenders fields and setget methods f or each of them Properties and method signatures obey the JavaBeans naming convention Thus log4j can analyze the appender using ref lection transparently handling the appender configuration c) To complete our appender we must implement the callback methods that the log4j framework calls to manage our appender requiresLayout () activateOptions () append () and close ()The log4j framework calls the requiresLayout () method to know whether the custom appender requires a lay out Notice that some appenders use a built-in format or dont format the events at all so they dont require a Layout object The PNotifyAppender requires a lay out hence the method returns true

11 | P a g e

d) Notice that AppenderSkeleton implements the orgapachelog4jspiOptionHandler interface AppenderSkeleton implements the single method of this interface activateOptions () as an empty method PNotifyAppender needs this method because of the interdependence between its properties For example the connection with a GTalk Server depends on the Host Port username password and toNotify properties so PNotifyAppender cannot establish a connection until these five properties have been initialized The log4j framework calls the activateOptions () method to signal to the appenders that all the properties have been set e) Once the activateOptions () method returns the appender is ready to handle logging requests AppenderSkeletondoAppend () does most of the real appending work f) The checkEntryConditions () method checks whether there is a Chat object available to append the output and also whether there is a Layout object to format the incoming event object If these preconditions are not satisfied then append () outputs a warning message and returns without proceeding g) The sendBuffer () method sends the contents of the buffer as an IM message The method loops through the events kept in the buffer formatting each one by invoking the format () method of the layout object The string representation of the events is appended to a StringBuffer object Finally sendBuffer () calls the sendMessage () method of the chat object sending the message h) The AppenderSkeletondoAppend () method which invokes append () is synchronized so sendBuffer () already owns the monitor for the appender This frees us from needing to synchronize the CyclicBuffer Object cb i) The verifyRosterEntryJabber () method subscribes to the given email Id provided to toNotify property of the PNotifyAppender if it is not present into account

5 Putting5 Putting5 Putting5 Putting it all togetherit all togetherit all togetherit all together Well wrap up by showing you PNotifyAppender in action STEP 1STEP 1STEP 1STEP 1 Drop in the requisite Jars into application a) commons-logging-111jar b) log4j-1216jar c) mailjar d) smackjar (321) e) smackxjar (321) f) pnotifyappenderjar STEP STEP STEP STEP 2 2 2 2 Configuring log4jproperties log4jrootLogger=GTALK STEP 21STEP 21STEP 21STEP 21 Minimum configuration required if we want real time notification of the exception in GTalk log4jappenderGTALK=compnotifyappenderPNotifyAppender log4jappenderGTALKThreshold=ERROR log4jappenderGTALKusername=xxxxxxx or xxxxxgmailcom (if SSLhistory property is set to true) log4jappenderGTALKpassword=xxxxxxx log4jappenderGTALKtoNotify=xxxxgmailcom log4jappenderGTALKlayout=orgapachelog4jPatternLayout log4jappenderGTALKlayoutConversionPattern=dMM-ddHHmmss[-5p][CML]-(F) mn

12 | P a g e

log4jadditivityGTALK=false if behind a proxy log4jappenderGTALKproxy=true log4jappenderGTALKproxyHost=xxxxxxxxx log4jappenderGTALKproxyPort=xxxx STEP 2STEP 2STEP 2STEP 22222 If we want to keep the history of notified exception into the respective GMail account log4jappenderGTALK=compnotifyappenderPNotifyAppender log4jappenderGTALKThreshold=ERROR log4jappenderGTALKusername=xxxxxgmailcom log4jappenderGTALKpassword=xxxxxxx log4jappenderGTALKtoNotify=xxxxgmailcom log4jappenderGTALKlayout=orgapachelog4jPatternLayout log4jappenderGTALKlayoutConversionPattern=dMM-ddHHmmss[-5p][CML]-(F) mn log4jappenderGTALKhistory=true log4jappenderGTALKSMTPHost=smtpgmailcom log4jappenderGTALKsubject=Email Notification from Application log4jappenderGTALKcc=xxxxxxxxcom log4jappenderGTALKbcc=xxxxxxxxcom log4jadditivityGTALK=false The above configuration script adds PNotifyAppender to the root logger so each logging request received will be dispatched to our appender When we run our respective application An IM message then pops up on the recipients screen and the below screenshots shows the resulting message received by GTalk and GMail

13 | P a g e

Notice that the above figure depicts the real time notification about the exception occurred in the application at GTalk in the mail Id mentioned in toNotify property of PNotifyAppender

The above figure depicts the exception got recorded into the given GMail Account when history property in PNotifyAppender is set to true and setting the other dependent property As we can see in the both cases the exception information contained in the last Logging events has been correctly transmitted This example application simply showcases use of the PNotifyAppender so explore and have fun

6 Conclusion6 Conclusion6 Conclusion6 Conclusion The log4j network appenders SocketAppender JMSAppender and SMTPAppender already provide mechanisms to monitor Java-distributed applications However several factors make IM a suitable technology for remote logging in real-time In this article weve covered the basics of extending log4j with y our custom appenders and weve seen the implementation of a basic PNotifyAppender step by step Many developers and system administrators can benefit from their use

7 Resources7 Resources7 Resources7 Resources 1 httploggingapacheorglog4j12 2 httpwwwjavaworldcomjavaworldjw-10-1999jw-10-cooltoolshtml 3 Book Template Method - Design Patterns in Java by Steven John Metsker and William CWake 4 httpwwwigniterealtimeorgprojectssmack 5 Book Instant Messaging in Java the jabber Protocol by Ian Shigeoka 6 MagicwithMerling Exception and Logging httpwwwibmcomdeveloperworksjavalibraryj-mer1211indexhtml

Page 4: Rein_in_the_ability_of_log4j

4 | P a g e

Lets examine the methods of the Appender interface implemented by the AppenderSkeleton class As Listing above indicates nearly all methods in the Appender interface are setter and getter methods Appender Interface package orgapachelog4j public interface Appender void addFilter (Filter newFilter) public Filter getFilter () public void close () public void clearFilters () public void close () public String getName () public void setErrorHandler (ErrorHandler errorHandler) public ErrorHandler setErrorHandler () public void set Layout (Layout layout) public Layout getLayout () public void setName (String name) public boolean requiresLayout () These methods handle appender properties like the following Name Appenders are named entities so there is a settergetter for its name

5 | P a g e

Layout Appenders may have a Layout associated with them so there is another settergetter method for the lay out Note as said it may but not must The reason is that some appenders dont require a lay out Layout manages format output -- that is it returns a String representation of the LoggingEvent On the other hand JMSAppender sends the event serialized so youre not required to attach a layout with it If your custom appender doesnt require a layout the requiresLayout () method must return false to prevent log4j from complaining about missing layout information ErrorHandler Another settergetter method exists for ErrorHandler Appenders may delegate their error handling to an ErrorHandler object -- an interface in the orgapachelog4jspi package There are two implementing classes OnlyOnceErrorHandler and FallbackErrorHandler The OnlyOnceErrorHandler implements log4js default error handling policy which consists of emitting a message for the first error in an appender and ignoring all following errors The error message is printed on Systemerr FallbackErrorHandler implements the ErrorHandler interface such that a secondary appender may be specified This secondary appender takes over if the primary appender fails The error message is printed on Systemerr then logged in new secondary appender There are other methods to manage filters (such as the addFilter () clearFilters () and getFilter () methods) Even though log4j has several built-in ways to filter log requests (such as repository -wide level logger level and appender threshold) it is also very powerful in its approach to using custom filters An appender can contain multiple filters Custom filters must extend the orgapachelog4jspiFilter abstract class This abstract class requires filters to be organized in a linear chain The decide (LoggingEvent) method orgapachelog4jspiFilter an abstract Class of each filter is called sequentially in the order it was added to the chain Custom filters are based on ternary logic The decide () method must return one of the DENY NEUTRAL or ACCEPT integer constants Besides settergetter methods and the ones related with filters there are two other methods close () and doAppend () The close () method releases any resources allocated within the appender such as file handlers network connections and so on When coding your custom appender be sure you implement this method so that when your appender is closed its closed field is set to true The doAppend () method follows the Gang of Four (GOF) Template Method design pattern This method provides a skeleton of an algorithm deferring some steps to subclasses public synchronized void doAppend (LoggingEvent event) if (closed) s t e p 1 LogLogerror(Attempted to append to closed appender [ + name + ]) return if ( isAsSevereAsThreshold (eventlevel)) s t e p 2 return Filter f = thisheadFilter s t e p 3 FILTER_LOOP while (f = null) switch (f decide (event)) case Filter DENY return case FilterACCEPT break FILTER_LOOP case FilterNEUTRAL f = fnext

6 | P a g e

this append (e v e n t) s t e p 4 211 The algorithm 1 Checks whether the appender is closed 2 Checks whether the logging event is below the threshold of the appender 3 Checks whether filters attached to the appender if any deny the request 4 Invokes append () method of the appender This step is delegated to each subclass The methods and properties that AppenderSkeleton inherits from Appender Lets see why AppenderSkeleton implements the OptionHandler interface OptionHandler contains only one method activateOptions () This method is invoked by a configurator class after calling setter methods for properties Some properties depend on each other so they cannot be activated until all of them have been loaded such as in the activateOptions () method This method is a mechanism for developers to perform whatever tasks were necessary before the appender became activated and ready In addition to all the methods mentioned look again at Class diagram above Notice that AppenderSkeleton provides a new abstract method (append () method) and a new JavaBeans property (threshold) The threshold property is used to filter logging requests by the appender with only requests over the threshold handled We mentioned append () method before when we talked about the doAppend () method It is an abstract method that your custom appender must implement because the framework calls it within the doAppend () method The append () method is one of the hooks of the framework Now that wersquove seen all the methods available in the AppenderSkeleton class lets see whats happening behind the scenes Below figure illustrates the life cycle of an appender object inside log4j

7 | P a g e

212 Letrsquos take a look in brief what is going on above diagram The appender instance does not exist Perhaps the framework has not been yet configured The framework instantiates a new appender This happens when the configurator classes parse an appender declaration in configuration scripts The configurator classes call ClassnewInstance YourCustomAppenderclass) which is the dynamic equivalent of calling new YourCustomAppender () The framework does this so that the framework is not hard-coded to any specific appender name the framework is generic and works with any appender The framework determines whether the appender requires a layout If the appender does not require a lay out then configurators dont try to load lay out information from configuration scripts Log4j configurator calls setter methods The framework transparently handles appenders properties following JavaBeans naming conventions Configurator invokes the activateOptions () method After all the properties have been set the framework invokes this method Programmers can activate properties here that have to be activated at the same time Appender is ready At this point the framework can call append () method to handle a logging request This method is invoked by the AppenderSkeleton doAppend () method Finally the appender is closed When the framework is about to remove y our custom appender instance it calls y our appenders close () method close () is a cleanup method which means you need to free all the resources you have allocated It is a required method and it takes no parameters It must set the closed field to true alerting the framework when an attempt to use a closed appender occurs Weve reviewed the concepts related to building y our own appender 3 Case study r3 Case study r3 Case study r3 Case study realealealeal----world example appenderworld example appenderworld example appenderworld example appender 31 Writing an Instant Messenger -based appender The code presented in this document shows how you can extend the log4j framework to integrate IM features Its designed to enable a log4j-compliant application to log its output onto Instant Messenger like GTalk The PNotifyAppender actually works as a customized IM client However instead of Systemout files or TCP sockets it takes Instant Messenger as the underlying output device To provide IM support we dont need to reinvent the wheel when developing ad-hoc solutions Instead were going to leverage a tool here I considered the best of breed GTalk which internally uses XML based protocol for instant messaging and presence ie XMPP (Extensible Messaging and Presence Protocol) which is an open-standard communications protocol for message-oriented middleware based on XML the protocol originally named as Jabber We chose Jabber over other IM systems because it offers a wide variety of benefits including its 1 Open source 2 Simplicity 3 Interoperability with other IM systems 4 Resource awareness

8 | P a g e

32 Usage Scenario of PNotifyAppender Below diagram shows the PNotifyAppender usage scenario Any application configured to use PNotifyAppender logs its debugging data wrapped as GTalk IM message The instant message is routed over organization network to the system administrator Thus whenever system administrator needs to check on the application status they simply log into their Gmail account using Gtalk IM using his desktop or laptops at work or when he is away from his desk he may use Gtalk IM running on any handheld devices As Gtalk IM has the capability to notify us even when we are offline once we log in it will notify system administrator with the pending notifications or real time

But why do we need PNotifyAppender The answer is that sending messages to IM (Gtalk) allows us to monitor application behavior more easily with tools at our disposal PNotifyAppender offers several advantages 1 You get real-time notification about the exception occurred at server we can consider as ldquoImmediate Loggingrdquo 2 GTalk IM isnrsquot just for desktop computers It is also being developed for wireless devices such as PDArsquos and mobile phones 3 No setup overhead 4 PNotifyAppender notifies the real time exception immediately with the exception details automatically to the Instant Messenger like GTalk and has the ability to keep track of the exception history into the GMail account

9 | P a g e

4 Ov4 Ov4 Ov4 Overviewerviewerviewerview of of of of PNotifyAppenderPNotifyAppenderPNotifyAppenderPNotifyAppender PNotifyAppender is modeled based on SMTPAppender logging strategy PNotifyAppender stores logging events in an internal cyclic buffer and send them as an instant message only when the logging request received triggers a user-specified condition Optionally users may provide a triggering event evaluator class However by default delivery is triggered on events assigned the level ERROR or higher The number of logging events delivered in each message is limited by the buffer size The cyclic buffer holds only the last buffer size logging events overflowing when it becomes full and throwing away the older events To connect to a GTalk PNotifyAppender relies on Smack API Smack is an open source high-level library that handles the protocol details for communicating with GTalk servers As a result you dont need any special Jabber or XML expertise to understand the code The properties for PNotifyAppender are summarized in Table 1

Property Description Type Required

username Gmail Account username eg anthing123 If SSL is true then eg anything123gmailcom

String Yes

password Gmail Account password String Yes

toNotify Recipients address just as e-mail addresses do xxxxgmailcom

String Yes

SSL Used to secure connections boolean No defaults to false

buffersize The maximum number of logging events that can be kept in the cyclic buffer

int

defaults is 16

evaluatorClass

Takes as a value a string representing the fully qualified name of a class that implements the orgapachelog4jspi TriggeringEventEvaluator interface (in other words a class that contains a custom triggering logic that overrides the default one) If this option is not specified PNotifyAppender uses an instance of the DefaultEvaluator class which triggers a response to events assigned the level ERROR or higher

String

No defaults to DefaultEvaluator

proxy It is used to identify whether log4j application behind any proxy

boolean No Default is false

proxyHost If the proxy property is true proxyHost takes the proxy address Example 192168xxxx

String Yes if proxy sets to true else No

proxyPort Proxy Port eg 3245 String Yes if proxy sets to true else No

history This property is used if we want to log the exception history of the real time notification

boolean No Default is false

subject The subject option takes a string value which should be a the subject of the e-mail message

String Yes if history sets to true else No

cc Set the cc recipient addresses String No

bcc Set the bcc recipient addresses String No

SMTPHost The SMTPHost option takes a string value which should be a the host name of the SMTP server that will send the email message

String Yes if history sets to true else No

10 | P a g e

41 Letrsquos take a closer look at below code package compnotifyappender import orgapachelog4jAppenderSkeleton import orgapachelog4jLayout import orgapachelog4jhelpersCyclicBuffer import orgapachelog4jhelpersLogLog import orgapachelog4jhelpersOptionConverter import orgapachelog4jspiLoggingEvent import orgapachelog4jspiTriggeringEventEvaluator public class PNotifyAppender extends AppenderSkeleton protected CyclicBuffer cb private int buffersize private String username private String password private String toNotify private boolean SSL private String proxyHost private String proxyPort private boolean proxy protected boolean checkEntryConditions () public boolean verifyRosterEntryJabberClient (XMPPConnection connection) AppenderSkeleton callback method public void activateOptions () protected void sendBuffer () public synchronized void close () public boolean requiresLayout () return true protected void append (LoggingEvent event) Notice the following about the PNotifyAppender a) The PNotifyAppender class extends orgapachelog4jAppenderSkeleton which all custom appenders must do PNotifyAppender inherits common functionalities from AppenderSkeleton such as appender threshold and custom filtering b) The first part of our appender is straight-forward We have the appenders fields and setget methods f or each of them Properties and method signatures obey the JavaBeans naming convention Thus log4j can analyze the appender using ref lection transparently handling the appender configuration c) To complete our appender we must implement the callback methods that the log4j framework calls to manage our appender requiresLayout () activateOptions () append () and close ()The log4j framework calls the requiresLayout () method to know whether the custom appender requires a lay out Notice that some appenders use a built-in format or dont format the events at all so they dont require a Layout object The PNotifyAppender requires a lay out hence the method returns true

11 | P a g e

d) Notice that AppenderSkeleton implements the orgapachelog4jspiOptionHandler interface AppenderSkeleton implements the single method of this interface activateOptions () as an empty method PNotifyAppender needs this method because of the interdependence between its properties For example the connection with a GTalk Server depends on the Host Port username password and toNotify properties so PNotifyAppender cannot establish a connection until these five properties have been initialized The log4j framework calls the activateOptions () method to signal to the appenders that all the properties have been set e) Once the activateOptions () method returns the appender is ready to handle logging requests AppenderSkeletondoAppend () does most of the real appending work f) The checkEntryConditions () method checks whether there is a Chat object available to append the output and also whether there is a Layout object to format the incoming event object If these preconditions are not satisfied then append () outputs a warning message and returns without proceeding g) The sendBuffer () method sends the contents of the buffer as an IM message The method loops through the events kept in the buffer formatting each one by invoking the format () method of the layout object The string representation of the events is appended to a StringBuffer object Finally sendBuffer () calls the sendMessage () method of the chat object sending the message h) The AppenderSkeletondoAppend () method which invokes append () is synchronized so sendBuffer () already owns the monitor for the appender This frees us from needing to synchronize the CyclicBuffer Object cb i) The verifyRosterEntryJabber () method subscribes to the given email Id provided to toNotify property of the PNotifyAppender if it is not present into account

5 Putting5 Putting5 Putting5 Putting it all togetherit all togetherit all togetherit all together Well wrap up by showing you PNotifyAppender in action STEP 1STEP 1STEP 1STEP 1 Drop in the requisite Jars into application a) commons-logging-111jar b) log4j-1216jar c) mailjar d) smackjar (321) e) smackxjar (321) f) pnotifyappenderjar STEP STEP STEP STEP 2 2 2 2 Configuring log4jproperties log4jrootLogger=GTALK STEP 21STEP 21STEP 21STEP 21 Minimum configuration required if we want real time notification of the exception in GTalk log4jappenderGTALK=compnotifyappenderPNotifyAppender log4jappenderGTALKThreshold=ERROR log4jappenderGTALKusername=xxxxxxx or xxxxxgmailcom (if SSLhistory property is set to true) log4jappenderGTALKpassword=xxxxxxx log4jappenderGTALKtoNotify=xxxxgmailcom log4jappenderGTALKlayout=orgapachelog4jPatternLayout log4jappenderGTALKlayoutConversionPattern=dMM-ddHHmmss[-5p][CML]-(F) mn

12 | P a g e

log4jadditivityGTALK=false if behind a proxy log4jappenderGTALKproxy=true log4jappenderGTALKproxyHost=xxxxxxxxx log4jappenderGTALKproxyPort=xxxx STEP 2STEP 2STEP 2STEP 22222 If we want to keep the history of notified exception into the respective GMail account log4jappenderGTALK=compnotifyappenderPNotifyAppender log4jappenderGTALKThreshold=ERROR log4jappenderGTALKusername=xxxxxgmailcom log4jappenderGTALKpassword=xxxxxxx log4jappenderGTALKtoNotify=xxxxgmailcom log4jappenderGTALKlayout=orgapachelog4jPatternLayout log4jappenderGTALKlayoutConversionPattern=dMM-ddHHmmss[-5p][CML]-(F) mn log4jappenderGTALKhistory=true log4jappenderGTALKSMTPHost=smtpgmailcom log4jappenderGTALKsubject=Email Notification from Application log4jappenderGTALKcc=xxxxxxxxcom log4jappenderGTALKbcc=xxxxxxxxcom log4jadditivityGTALK=false The above configuration script adds PNotifyAppender to the root logger so each logging request received will be dispatched to our appender When we run our respective application An IM message then pops up on the recipients screen and the below screenshots shows the resulting message received by GTalk and GMail

13 | P a g e

Notice that the above figure depicts the real time notification about the exception occurred in the application at GTalk in the mail Id mentioned in toNotify property of PNotifyAppender

The above figure depicts the exception got recorded into the given GMail Account when history property in PNotifyAppender is set to true and setting the other dependent property As we can see in the both cases the exception information contained in the last Logging events has been correctly transmitted This example application simply showcases use of the PNotifyAppender so explore and have fun

6 Conclusion6 Conclusion6 Conclusion6 Conclusion The log4j network appenders SocketAppender JMSAppender and SMTPAppender already provide mechanisms to monitor Java-distributed applications However several factors make IM a suitable technology for remote logging in real-time In this article weve covered the basics of extending log4j with y our custom appenders and weve seen the implementation of a basic PNotifyAppender step by step Many developers and system administrators can benefit from their use

7 Resources7 Resources7 Resources7 Resources 1 httploggingapacheorglog4j12 2 httpwwwjavaworldcomjavaworldjw-10-1999jw-10-cooltoolshtml 3 Book Template Method - Design Patterns in Java by Steven John Metsker and William CWake 4 httpwwwigniterealtimeorgprojectssmack 5 Book Instant Messaging in Java the jabber Protocol by Ian Shigeoka 6 MagicwithMerling Exception and Logging httpwwwibmcomdeveloperworksjavalibraryj-mer1211indexhtml

Page 5: Rein_in_the_ability_of_log4j

5 | P a g e

Layout Appenders may have a Layout associated with them so there is another settergetter method for the lay out Note as said it may but not must The reason is that some appenders dont require a lay out Layout manages format output -- that is it returns a String representation of the LoggingEvent On the other hand JMSAppender sends the event serialized so youre not required to attach a layout with it If your custom appender doesnt require a layout the requiresLayout () method must return false to prevent log4j from complaining about missing layout information ErrorHandler Another settergetter method exists for ErrorHandler Appenders may delegate their error handling to an ErrorHandler object -- an interface in the orgapachelog4jspi package There are two implementing classes OnlyOnceErrorHandler and FallbackErrorHandler The OnlyOnceErrorHandler implements log4js default error handling policy which consists of emitting a message for the first error in an appender and ignoring all following errors The error message is printed on Systemerr FallbackErrorHandler implements the ErrorHandler interface such that a secondary appender may be specified This secondary appender takes over if the primary appender fails The error message is printed on Systemerr then logged in new secondary appender There are other methods to manage filters (such as the addFilter () clearFilters () and getFilter () methods) Even though log4j has several built-in ways to filter log requests (such as repository -wide level logger level and appender threshold) it is also very powerful in its approach to using custom filters An appender can contain multiple filters Custom filters must extend the orgapachelog4jspiFilter abstract class This abstract class requires filters to be organized in a linear chain The decide (LoggingEvent) method orgapachelog4jspiFilter an abstract Class of each filter is called sequentially in the order it was added to the chain Custom filters are based on ternary logic The decide () method must return one of the DENY NEUTRAL or ACCEPT integer constants Besides settergetter methods and the ones related with filters there are two other methods close () and doAppend () The close () method releases any resources allocated within the appender such as file handlers network connections and so on When coding your custom appender be sure you implement this method so that when your appender is closed its closed field is set to true The doAppend () method follows the Gang of Four (GOF) Template Method design pattern This method provides a skeleton of an algorithm deferring some steps to subclasses public synchronized void doAppend (LoggingEvent event) if (closed) s t e p 1 LogLogerror(Attempted to append to closed appender [ + name + ]) return if ( isAsSevereAsThreshold (eventlevel)) s t e p 2 return Filter f = thisheadFilter s t e p 3 FILTER_LOOP while (f = null) switch (f decide (event)) case Filter DENY return case FilterACCEPT break FILTER_LOOP case FilterNEUTRAL f = fnext

6 | P a g e

this append (e v e n t) s t e p 4 211 The algorithm 1 Checks whether the appender is closed 2 Checks whether the logging event is below the threshold of the appender 3 Checks whether filters attached to the appender if any deny the request 4 Invokes append () method of the appender This step is delegated to each subclass The methods and properties that AppenderSkeleton inherits from Appender Lets see why AppenderSkeleton implements the OptionHandler interface OptionHandler contains only one method activateOptions () This method is invoked by a configurator class after calling setter methods for properties Some properties depend on each other so they cannot be activated until all of them have been loaded such as in the activateOptions () method This method is a mechanism for developers to perform whatever tasks were necessary before the appender became activated and ready In addition to all the methods mentioned look again at Class diagram above Notice that AppenderSkeleton provides a new abstract method (append () method) and a new JavaBeans property (threshold) The threshold property is used to filter logging requests by the appender with only requests over the threshold handled We mentioned append () method before when we talked about the doAppend () method It is an abstract method that your custom appender must implement because the framework calls it within the doAppend () method The append () method is one of the hooks of the framework Now that wersquove seen all the methods available in the AppenderSkeleton class lets see whats happening behind the scenes Below figure illustrates the life cycle of an appender object inside log4j

7 | P a g e

212 Letrsquos take a look in brief what is going on above diagram The appender instance does not exist Perhaps the framework has not been yet configured The framework instantiates a new appender This happens when the configurator classes parse an appender declaration in configuration scripts The configurator classes call ClassnewInstance YourCustomAppenderclass) which is the dynamic equivalent of calling new YourCustomAppender () The framework does this so that the framework is not hard-coded to any specific appender name the framework is generic and works with any appender The framework determines whether the appender requires a layout If the appender does not require a lay out then configurators dont try to load lay out information from configuration scripts Log4j configurator calls setter methods The framework transparently handles appenders properties following JavaBeans naming conventions Configurator invokes the activateOptions () method After all the properties have been set the framework invokes this method Programmers can activate properties here that have to be activated at the same time Appender is ready At this point the framework can call append () method to handle a logging request This method is invoked by the AppenderSkeleton doAppend () method Finally the appender is closed When the framework is about to remove y our custom appender instance it calls y our appenders close () method close () is a cleanup method which means you need to free all the resources you have allocated It is a required method and it takes no parameters It must set the closed field to true alerting the framework when an attempt to use a closed appender occurs Weve reviewed the concepts related to building y our own appender 3 Case study r3 Case study r3 Case study r3 Case study realealealeal----world example appenderworld example appenderworld example appenderworld example appender 31 Writing an Instant Messenger -based appender The code presented in this document shows how you can extend the log4j framework to integrate IM features Its designed to enable a log4j-compliant application to log its output onto Instant Messenger like GTalk The PNotifyAppender actually works as a customized IM client However instead of Systemout files or TCP sockets it takes Instant Messenger as the underlying output device To provide IM support we dont need to reinvent the wheel when developing ad-hoc solutions Instead were going to leverage a tool here I considered the best of breed GTalk which internally uses XML based protocol for instant messaging and presence ie XMPP (Extensible Messaging and Presence Protocol) which is an open-standard communications protocol for message-oriented middleware based on XML the protocol originally named as Jabber We chose Jabber over other IM systems because it offers a wide variety of benefits including its 1 Open source 2 Simplicity 3 Interoperability with other IM systems 4 Resource awareness

8 | P a g e

32 Usage Scenario of PNotifyAppender Below diagram shows the PNotifyAppender usage scenario Any application configured to use PNotifyAppender logs its debugging data wrapped as GTalk IM message The instant message is routed over organization network to the system administrator Thus whenever system administrator needs to check on the application status they simply log into their Gmail account using Gtalk IM using his desktop or laptops at work or when he is away from his desk he may use Gtalk IM running on any handheld devices As Gtalk IM has the capability to notify us even when we are offline once we log in it will notify system administrator with the pending notifications or real time

But why do we need PNotifyAppender The answer is that sending messages to IM (Gtalk) allows us to monitor application behavior more easily with tools at our disposal PNotifyAppender offers several advantages 1 You get real-time notification about the exception occurred at server we can consider as ldquoImmediate Loggingrdquo 2 GTalk IM isnrsquot just for desktop computers It is also being developed for wireless devices such as PDArsquos and mobile phones 3 No setup overhead 4 PNotifyAppender notifies the real time exception immediately with the exception details automatically to the Instant Messenger like GTalk and has the ability to keep track of the exception history into the GMail account

9 | P a g e

4 Ov4 Ov4 Ov4 Overviewerviewerviewerview of of of of PNotifyAppenderPNotifyAppenderPNotifyAppenderPNotifyAppender PNotifyAppender is modeled based on SMTPAppender logging strategy PNotifyAppender stores logging events in an internal cyclic buffer and send them as an instant message only when the logging request received triggers a user-specified condition Optionally users may provide a triggering event evaluator class However by default delivery is triggered on events assigned the level ERROR or higher The number of logging events delivered in each message is limited by the buffer size The cyclic buffer holds only the last buffer size logging events overflowing when it becomes full and throwing away the older events To connect to a GTalk PNotifyAppender relies on Smack API Smack is an open source high-level library that handles the protocol details for communicating with GTalk servers As a result you dont need any special Jabber or XML expertise to understand the code The properties for PNotifyAppender are summarized in Table 1

Property Description Type Required

username Gmail Account username eg anthing123 If SSL is true then eg anything123gmailcom

String Yes

password Gmail Account password String Yes

toNotify Recipients address just as e-mail addresses do xxxxgmailcom

String Yes

SSL Used to secure connections boolean No defaults to false

buffersize The maximum number of logging events that can be kept in the cyclic buffer

int

defaults is 16

evaluatorClass

Takes as a value a string representing the fully qualified name of a class that implements the orgapachelog4jspi TriggeringEventEvaluator interface (in other words a class that contains a custom triggering logic that overrides the default one) If this option is not specified PNotifyAppender uses an instance of the DefaultEvaluator class which triggers a response to events assigned the level ERROR or higher

String

No defaults to DefaultEvaluator

proxy It is used to identify whether log4j application behind any proxy

boolean No Default is false

proxyHost If the proxy property is true proxyHost takes the proxy address Example 192168xxxx

String Yes if proxy sets to true else No

proxyPort Proxy Port eg 3245 String Yes if proxy sets to true else No

history This property is used if we want to log the exception history of the real time notification

boolean No Default is false

subject The subject option takes a string value which should be a the subject of the e-mail message

String Yes if history sets to true else No

cc Set the cc recipient addresses String No

bcc Set the bcc recipient addresses String No

SMTPHost The SMTPHost option takes a string value which should be a the host name of the SMTP server that will send the email message

String Yes if history sets to true else No

10 | P a g e

41 Letrsquos take a closer look at below code package compnotifyappender import orgapachelog4jAppenderSkeleton import orgapachelog4jLayout import orgapachelog4jhelpersCyclicBuffer import orgapachelog4jhelpersLogLog import orgapachelog4jhelpersOptionConverter import orgapachelog4jspiLoggingEvent import orgapachelog4jspiTriggeringEventEvaluator public class PNotifyAppender extends AppenderSkeleton protected CyclicBuffer cb private int buffersize private String username private String password private String toNotify private boolean SSL private String proxyHost private String proxyPort private boolean proxy protected boolean checkEntryConditions () public boolean verifyRosterEntryJabberClient (XMPPConnection connection) AppenderSkeleton callback method public void activateOptions () protected void sendBuffer () public synchronized void close () public boolean requiresLayout () return true protected void append (LoggingEvent event) Notice the following about the PNotifyAppender a) The PNotifyAppender class extends orgapachelog4jAppenderSkeleton which all custom appenders must do PNotifyAppender inherits common functionalities from AppenderSkeleton such as appender threshold and custom filtering b) The first part of our appender is straight-forward We have the appenders fields and setget methods f or each of them Properties and method signatures obey the JavaBeans naming convention Thus log4j can analyze the appender using ref lection transparently handling the appender configuration c) To complete our appender we must implement the callback methods that the log4j framework calls to manage our appender requiresLayout () activateOptions () append () and close ()The log4j framework calls the requiresLayout () method to know whether the custom appender requires a lay out Notice that some appenders use a built-in format or dont format the events at all so they dont require a Layout object The PNotifyAppender requires a lay out hence the method returns true

11 | P a g e

d) Notice that AppenderSkeleton implements the orgapachelog4jspiOptionHandler interface AppenderSkeleton implements the single method of this interface activateOptions () as an empty method PNotifyAppender needs this method because of the interdependence between its properties For example the connection with a GTalk Server depends on the Host Port username password and toNotify properties so PNotifyAppender cannot establish a connection until these five properties have been initialized The log4j framework calls the activateOptions () method to signal to the appenders that all the properties have been set e) Once the activateOptions () method returns the appender is ready to handle logging requests AppenderSkeletondoAppend () does most of the real appending work f) The checkEntryConditions () method checks whether there is a Chat object available to append the output and also whether there is a Layout object to format the incoming event object If these preconditions are not satisfied then append () outputs a warning message and returns without proceeding g) The sendBuffer () method sends the contents of the buffer as an IM message The method loops through the events kept in the buffer formatting each one by invoking the format () method of the layout object The string representation of the events is appended to a StringBuffer object Finally sendBuffer () calls the sendMessage () method of the chat object sending the message h) The AppenderSkeletondoAppend () method which invokes append () is synchronized so sendBuffer () already owns the monitor for the appender This frees us from needing to synchronize the CyclicBuffer Object cb i) The verifyRosterEntryJabber () method subscribes to the given email Id provided to toNotify property of the PNotifyAppender if it is not present into account

5 Putting5 Putting5 Putting5 Putting it all togetherit all togetherit all togetherit all together Well wrap up by showing you PNotifyAppender in action STEP 1STEP 1STEP 1STEP 1 Drop in the requisite Jars into application a) commons-logging-111jar b) log4j-1216jar c) mailjar d) smackjar (321) e) smackxjar (321) f) pnotifyappenderjar STEP STEP STEP STEP 2 2 2 2 Configuring log4jproperties log4jrootLogger=GTALK STEP 21STEP 21STEP 21STEP 21 Minimum configuration required if we want real time notification of the exception in GTalk log4jappenderGTALK=compnotifyappenderPNotifyAppender log4jappenderGTALKThreshold=ERROR log4jappenderGTALKusername=xxxxxxx or xxxxxgmailcom (if SSLhistory property is set to true) log4jappenderGTALKpassword=xxxxxxx log4jappenderGTALKtoNotify=xxxxgmailcom log4jappenderGTALKlayout=orgapachelog4jPatternLayout log4jappenderGTALKlayoutConversionPattern=dMM-ddHHmmss[-5p][CML]-(F) mn

12 | P a g e

log4jadditivityGTALK=false if behind a proxy log4jappenderGTALKproxy=true log4jappenderGTALKproxyHost=xxxxxxxxx log4jappenderGTALKproxyPort=xxxx STEP 2STEP 2STEP 2STEP 22222 If we want to keep the history of notified exception into the respective GMail account log4jappenderGTALK=compnotifyappenderPNotifyAppender log4jappenderGTALKThreshold=ERROR log4jappenderGTALKusername=xxxxxgmailcom log4jappenderGTALKpassword=xxxxxxx log4jappenderGTALKtoNotify=xxxxgmailcom log4jappenderGTALKlayout=orgapachelog4jPatternLayout log4jappenderGTALKlayoutConversionPattern=dMM-ddHHmmss[-5p][CML]-(F) mn log4jappenderGTALKhistory=true log4jappenderGTALKSMTPHost=smtpgmailcom log4jappenderGTALKsubject=Email Notification from Application log4jappenderGTALKcc=xxxxxxxxcom log4jappenderGTALKbcc=xxxxxxxxcom log4jadditivityGTALK=false The above configuration script adds PNotifyAppender to the root logger so each logging request received will be dispatched to our appender When we run our respective application An IM message then pops up on the recipients screen and the below screenshots shows the resulting message received by GTalk and GMail

13 | P a g e

Notice that the above figure depicts the real time notification about the exception occurred in the application at GTalk in the mail Id mentioned in toNotify property of PNotifyAppender

The above figure depicts the exception got recorded into the given GMail Account when history property in PNotifyAppender is set to true and setting the other dependent property As we can see in the both cases the exception information contained in the last Logging events has been correctly transmitted This example application simply showcases use of the PNotifyAppender so explore and have fun

6 Conclusion6 Conclusion6 Conclusion6 Conclusion The log4j network appenders SocketAppender JMSAppender and SMTPAppender already provide mechanisms to monitor Java-distributed applications However several factors make IM a suitable technology for remote logging in real-time In this article weve covered the basics of extending log4j with y our custom appenders and weve seen the implementation of a basic PNotifyAppender step by step Many developers and system administrators can benefit from their use

7 Resources7 Resources7 Resources7 Resources 1 httploggingapacheorglog4j12 2 httpwwwjavaworldcomjavaworldjw-10-1999jw-10-cooltoolshtml 3 Book Template Method - Design Patterns in Java by Steven John Metsker and William CWake 4 httpwwwigniterealtimeorgprojectssmack 5 Book Instant Messaging in Java the jabber Protocol by Ian Shigeoka 6 MagicwithMerling Exception and Logging httpwwwibmcomdeveloperworksjavalibraryj-mer1211indexhtml

Page 6: Rein_in_the_ability_of_log4j

6 | P a g e

this append (e v e n t) s t e p 4 211 The algorithm 1 Checks whether the appender is closed 2 Checks whether the logging event is below the threshold of the appender 3 Checks whether filters attached to the appender if any deny the request 4 Invokes append () method of the appender This step is delegated to each subclass The methods and properties that AppenderSkeleton inherits from Appender Lets see why AppenderSkeleton implements the OptionHandler interface OptionHandler contains only one method activateOptions () This method is invoked by a configurator class after calling setter methods for properties Some properties depend on each other so they cannot be activated until all of them have been loaded such as in the activateOptions () method This method is a mechanism for developers to perform whatever tasks were necessary before the appender became activated and ready In addition to all the methods mentioned look again at Class diagram above Notice that AppenderSkeleton provides a new abstract method (append () method) and a new JavaBeans property (threshold) The threshold property is used to filter logging requests by the appender with only requests over the threshold handled We mentioned append () method before when we talked about the doAppend () method It is an abstract method that your custom appender must implement because the framework calls it within the doAppend () method The append () method is one of the hooks of the framework Now that wersquove seen all the methods available in the AppenderSkeleton class lets see whats happening behind the scenes Below figure illustrates the life cycle of an appender object inside log4j

7 | P a g e

212 Letrsquos take a look in brief what is going on above diagram The appender instance does not exist Perhaps the framework has not been yet configured The framework instantiates a new appender This happens when the configurator classes parse an appender declaration in configuration scripts The configurator classes call ClassnewInstance YourCustomAppenderclass) which is the dynamic equivalent of calling new YourCustomAppender () The framework does this so that the framework is not hard-coded to any specific appender name the framework is generic and works with any appender The framework determines whether the appender requires a layout If the appender does not require a lay out then configurators dont try to load lay out information from configuration scripts Log4j configurator calls setter methods The framework transparently handles appenders properties following JavaBeans naming conventions Configurator invokes the activateOptions () method After all the properties have been set the framework invokes this method Programmers can activate properties here that have to be activated at the same time Appender is ready At this point the framework can call append () method to handle a logging request This method is invoked by the AppenderSkeleton doAppend () method Finally the appender is closed When the framework is about to remove y our custom appender instance it calls y our appenders close () method close () is a cleanup method which means you need to free all the resources you have allocated It is a required method and it takes no parameters It must set the closed field to true alerting the framework when an attempt to use a closed appender occurs Weve reviewed the concepts related to building y our own appender 3 Case study r3 Case study r3 Case study r3 Case study realealealeal----world example appenderworld example appenderworld example appenderworld example appender 31 Writing an Instant Messenger -based appender The code presented in this document shows how you can extend the log4j framework to integrate IM features Its designed to enable a log4j-compliant application to log its output onto Instant Messenger like GTalk The PNotifyAppender actually works as a customized IM client However instead of Systemout files or TCP sockets it takes Instant Messenger as the underlying output device To provide IM support we dont need to reinvent the wheel when developing ad-hoc solutions Instead were going to leverage a tool here I considered the best of breed GTalk which internally uses XML based protocol for instant messaging and presence ie XMPP (Extensible Messaging and Presence Protocol) which is an open-standard communications protocol for message-oriented middleware based on XML the protocol originally named as Jabber We chose Jabber over other IM systems because it offers a wide variety of benefits including its 1 Open source 2 Simplicity 3 Interoperability with other IM systems 4 Resource awareness

8 | P a g e

32 Usage Scenario of PNotifyAppender Below diagram shows the PNotifyAppender usage scenario Any application configured to use PNotifyAppender logs its debugging data wrapped as GTalk IM message The instant message is routed over organization network to the system administrator Thus whenever system administrator needs to check on the application status they simply log into their Gmail account using Gtalk IM using his desktop or laptops at work or when he is away from his desk he may use Gtalk IM running on any handheld devices As Gtalk IM has the capability to notify us even when we are offline once we log in it will notify system administrator with the pending notifications or real time

But why do we need PNotifyAppender The answer is that sending messages to IM (Gtalk) allows us to monitor application behavior more easily with tools at our disposal PNotifyAppender offers several advantages 1 You get real-time notification about the exception occurred at server we can consider as ldquoImmediate Loggingrdquo 2 GTalk IM isnrsquot just for desktop computers It is also being developed for wireless devices such as PDArsquos and mobile phones 3 No setup overhead 4 PNotifyAppender notifies the real time exception immediately with the exception details automatically to the Instant Messenger like GTalk and has the ability to keep track of the exception history into the GMail account

9 | P a g e

4 Ov4 Ov4 Ov4 Overviewerviewerviewerview of of of of PNotifyAppenderPNotifyAppenderPNotifyAppenderPNotifyAppender PNotifyAppender is modeled based on SMTPAppender logging strategy PNotifyAppender stores logging events in an internal cyclic buffer and send them as an instant message only when the logging request received triggers a user-specified condition Optionally users may provide a triggering event evaluator class However by default delivery is triggered on events assigned the level ERROR or higher The number of logging events delivered in each message is limited by the buffer size The cyclic buffer holds only the last buffer size logging events overflowing when it becomes full and throwing away the older events To connect to a GTalk PNotifyAppender relies on Smack API Smack is an open source high-level library that handles the protocol details for communicating with GTalk servers As a result you dont need any special Jabber or XML expertise to understand the code The properties for PNotifyAppender are summarized in Table 1

Property Description Type Required

username Gmail Account username eg anthing123 If SSL is true then eg anything123gmailcom

String Yes

password Gmail Account password String Yes

toNotify Recipients address just as e-mail addresses do xxxxgmailcom

String Yes

SSL Used to secure connections boolean No defaults to false

buffersize The maximum number of logging events that can be kept in the cyclic buffer

int

defaults is 16

evaluatorClass

Takes as a value a string representing the fully qualified name of a class that implements the orgapachelog4jspi TriggeringEventEvaluator interface (in other words a class that contains a custom triggering logic that overrides the default one) If this option is not specified PNotifyAppender uses an instance of the DefaultEvaluator class which triggers a response to events assigned the level ERROR or higher

String

No defaults to DefaultEvaluator

proxy It is used to identify whether log4j application behind any proxy

boolean No Default is false

proxyHost If the proxy property is true proxyHost takes the proxy address Example 192168xxxx

String Yes if proxy sets to true else No

proxyPort Proxy Port eg 3245 String Yes if proxy sets to true else No

history This property is used if we want to log the exception history of the real time notification

boolean No Default is false

subject The subject option takes a string value which should be a the subject of the e-mail message

String Yes if history sets to true else No

cc Set the cc recipient addresses String No

bcc Set the bcc recipient addresses String No

SMTPHost The SMTPHost option takes a string value which should be a the host name of the SMTP server that will send the email message

String Yes if history sets to true else No

10 | P a g e

41 Letrsquos take a closer look at below code package compnotifyappender import orgapachelog4jAppenderSkeleton import orgapachelog4jLayout import orgapachelog4jhelpersCyclicBuffer import orgapachelog4jhelpersLogLog import orgapachelog4jhelpersOptionConverter import orgapachelog4jspiLoggingEvent import orgapachelog4jspiTriggeringEventEvaluator public class PNotifyAppender extends AppenderSkeleton protected CyclicBuffer cb private int buffersize private String username private String password private String toNotify private boolean SSL private String proxyHost private String proxyPort private boolean proxy protected boolean checkEntryConditions () public boolean verifyRosterEntryJabberClient (XMPPConnection connection) AppenderSkeleton callback method public void activateOptions () protected void sendBuffer () public synchronized void close () public boolean requiresLayout () return true protected void append (LoggingEvent event) Notice the following about the PNotifyAppender a) The PNotifyAppender class extends orgapachelog4jAppenderSkeleton which all custom appenders must do PNotifyAppender inherits common functionalities from AppenderSkeleton such as appender threshold and custom filtering b) The first part of our appender is straight-forward We have the appenders fields and setget methods f or each of them Properties and method signatures obey the JavaBeans naming convention Thus log4j can analyze the appender using ref lection transparently handling the appender configuration c) To complete our appender we must implement the callback methods that the log4j framework calls to manage our appender requiresLayout () activateOptions () append () and close ()The log4j framework calls the requiresLayout () method to know whether the custom appender requires a lay out Notice that some appenders use a built-in format or dont format the events at all so they dont require a Layout object The PNotifyAppender requires a lay out hence the method returns true

11 | P a g e

d) Notice that AppenderSkeleton implements the orgapachelog4jspiOptionHandler interface AppenderSkeleton implements the single method of this interface activateOptions () as an empty method PNotifyAppender needs this method because of the interdependence between its properties For example the connection with a GTalk Server depends on the Host Port username password and toNotify properties so PNotifyAppender cannot establish a connection until these five properties have been initialized The log4j framework calls the activateOptions () method to signal to the appenders that all the properties have been set e) Once the activateOptions () method returns the appender is ready to handle logging requests AppenderSkeletondoAppend () does most of the real appending work f) The checkEntryConditions () method checks whether there is a Chat object available to append the output and also whether there is a Layout object to format the incoming event object If these preconditions are not satisfied then append () outputs a warning message and returns without proceeding g) The sendBuffer () method sends the contents of the buffer as an IM message The method loops through the events kept in the buffer formatting each one by invoking the format () method of the layout object The string representation of the events is appended to a StringBuffer object Finally sendBuffer () calls the sendMessage () method of the chat object sending the message h) The AppenderSkeletondoAppend () method which invokes append () is synchronized so sendBuffer () already owns the monitor for the appender This frees us from needing to synchronize the CyclicBuffer Object cb i) The verifyRosterEntryJabber () method subscribes to the given email Id provided to toNotify property of the PNotifyAppender if it is not present into account

5 Putting5 Putting5 Putting5 Putting it all togetherit all togetherit all togetherit all together Well wrap up by showing you PNotifyAppender in action STEP 1STEP 1STEP 1STEP 1 Drop in the requisite Jars into application a) commons-logging-111jar b) log4j-1216jar c) mailjar d) smackjar (321) e) smackxjar (321) f) pnotifyappenderjar STEP STEP STEP STEP 2 2 2 2 Configuring log4jproperties log4jrootLogger=GTALK STEP 21STEP 21STEP 21STEP 21 Minimum configuration required if we want real time notification of the exception in GTalk log4jappenderGTALK=compnotifyappenderPNotifyAppender log4jappenderGTALKThreshold=ERROR log4jappenderGTALKusername=xxxxxxx or xxxxxgmailcom (if SSLhistory property is set to true) log4jappenderGTALKpassword=xxxxxxx log4jappenderGTALKtoNotify=xxxxgmailcom log4jappenderGTALKlayout=orgapachelog4jPatternLayout log4jappenderGTALKlayoutConversionPattern=dMM-ddHHmmss[-5p][CML]-(F) mn

12 | P a g e

log4jadditivityGTALK=false if behind a proxy log4jappenderGTALKproxy=true log4jappenderGTALKproxyHost=xxxxxxxxx log4jappenderGTALKproxyPort=xxxx STEP 2STEP 2STEP 2STEP 22222 If we want to keep the history of notified exception into the respective GMail account log4jappenderGTALK=compnotifyappenderPNotifyAppender log4jappenderGTALKThreshold=ERROR log4jappenderGTALKusername=xxxxxgmailcom log4jappenderGTALKpassword=xxxxxxx log4jappenderGTALKtoNotify=xxxxgmailcom log4jappenderGTALKlayout=orgapachelog4jPatternLayout log4jappenderGTALKlayoutConversionPattern=dMM-ddHHmmss[-5p][CML]-(F) mn log4jappenderGTALKhistory=true log4jappenderGTALKSMTPHost=smtpgmailcom log4jappenderGTALKsubject=Email Notification from Application log4jappenderGTALKcc=xxxxxxxxcom log4jappenderGTALKbcc=xxxxxxxxcom log4jadditivityGTALK=false The above configuration script adds PNotifyAppender to the root logger so each logging request received will be dispatched to our appender When we run our respective application An IM message then pops up on the recipients screen and the below screenshots shows the resulting message received by GTalk and GMail

13 | P a g e

Notice that the above figure depicts the real time notification about the exception occurred in the application at GTalk in the mail Id mentioned in toNotify property of PNotifyAppender

The above figure depicts the exception got recorded into the given GMail Account when history property in PNotifyAppender is set to true and setting the other dependent property As we can see in the both cases the exception information contained in the last Logging events has been correctly transmitted This example application simply showcases use of the PNotifyAppender so explore and have fun

6 Conclusion6 Conclusion6 Conclusion6 Conclusion The log4j network appenders SocketAppender JMSAppender and SMTPAppender already provide mechanisms to monitor Java-distributed applications However several factors make IM a suitable technology for remote logging in real-time In this article weve covered the basics of extending log4j with y our custom appenders and weve seen the implementation of a basic PNotifyAppender step by step Many developers and system administrators can benefit from their use

7 Resources7 Resources7 Resources7 Resources 1 httploggingapacheorglog4j12 2 httpwwwjavaworldcomjavaworldjw-10-1999jw-10-cooltoolshtml 3 Book Template Method - Design Patterns in Java by Steven John Metsker and William CWake 4 httpwwwigniterealtimeorgprojectssmack 5 Book Instant Messaging in Java the jabber Protocol by Ian Shigeoka 6 MagicwithMerling Exception and Logging httpwwwibmcomdeveloperworksjavalibraryj-mer1211indexhtml

Page 7: Rein_in_the_ability_of_log4j

7 | P a g e

212 Letrsquos take a look in brief what is going on above diagram The appender instance does not exist Perhaps the framework has not been yet configured The framework instantiates a new appender This happens when the configurator classes parse an appender declaration in configuration scripts The configurator classes call ClassnewInstance YourCustomAppenderclass) which is the dynamic equivalent of calling new YourCustomAppender () The framework does this so that the framework is not hard-coded to any specific appender name the framework is generic and works with any appender The framework determines whether the appender requires a layout If the appender does not require a lay out then configurators dont try to load lay out information from configuration scripts Log4j configurator calls setter methods The framework transparently handles appenders properties following JavaBeans naming conventions Configurator invokes the activateOptions () method After all the properties have been set the framework invokes this method Programmers can activate properties here that have to be activated at the same time Appender is ready At this point the framework can call append () method to handle a logging request This method is invoked by the AppenderSkeleton doAppend () method Finally the appender is closed When the framework is about to remove y our custom appender instance it calls y our appenders close () method close () is a cleanup method which means you need to free all the resources you have allocated It is a required method and it takes no parameters It must set the closed field to true alerting the framework when an attempt to use a closed appender occurs Weve reviewed the concepts related to building y our own appender 3 Case study r3 Case study r3 Case study r3 Case study realealealeal----world example appenderworld example appenderworld example appenderworld example appender 31 Writing an Instant Messenger -based appender The code presented in this document shows how you can extend the log4j framework to integrate IM features Its designed to enable a log4j-compliant application to log its output onto Instant Messenger like GTalk The PNotifyAppender actually works as a customized IM client However instead of Systemout files or TCP sockets it takes Instant Messenger as the underlying output device To provide IM support we dont need to reinvent the wheel when developing ad-hoc solutions Instead were going to leverage a tool here I considered the best of breed GTalk which internally uses XML based protocol for instant messaging and presence ie XMPP (Extensible Messaging and Presence Protocol) which is an open-standard communications protocol for message-oriented middleware based on XML the protocol originally named as Jabber We chose Jabber over other IM systems because it offers a wide variety of benefits including its 1 Open source 2 Simplicity 3 Interoperability with other IM systems 4 Resource awareness

8 | P a g e

32 Usage Scenario of PNotifyAppender Below diagram shows the PNotifyAppender usage scenario Any application configured to use PNotifyAppender logs its debugging data wrapped as GTalk IM message The instant message is routed over organization network to the system administrator Thus whenever system administrator needs to check on the application status they simply log into their Gmail account using Gtalk IM using his desktop or laptops at work or when he is away from his desk he may use Gtalk IM running on any handheld devices As Gtalk IM has the capability to notify us even when we are offline once we log in it will notify system administrator with the pending notifications or real time

But why do we need PNotifyAppender The answer is that sending messages to IM (Gtalk) allows us to monitor application behavior more easily with tools at our disposal PNotifyAppender offers several advantages 1 You get real-time notification about the exception occurred at server we can consider as ldquoImmediate Loggingrdquo 2 GTalk IM isnrsquot just for desktop computers It is also being developed for wireless devices such as PDArsquos and mobile phones 3 No setup overhead 4 PNotifyAppender notifies the real time exception immediately with the exception details automatically to the Instant Messenger like GTalk and has the ability to keep track of the exception history into the GMail account

9 | P a g e

4 Ov4 Ov4 Ov4 Overviewerviewerviewerview of of of of PNotifyAppenderPNotifyAppenderPNotifyAppenderPNotifyAppender PNotifyAppender is modeled based on SMTPAppender logging strategy PNotifyAppender stores logging events in an internal cyclic buffer and send them as an instant message only when the logging request received triggers a user-specified condition Optionally users may provide a triggering event evaluator class However by default delivery is triggered on events assigned the level ERROR or higher The number of logging events delivered in each message is limited by the buffer size The cyclic buffer holds only the last buffer size logging events overflowing when it becomes full and throwing away the older events To connect to a GTalk PNotifyAppender relies on Smack API Smack is an open source high-level library that handles the protocol details for communicating with GTalk servers As a result you dont need any special Jabber or XML expertise to understand the code The properties for PNotifyAppender are summarized in Table 1

Property Description Type Required

username Gmail Account username eg anthing123 If SSL is true then eg anything123gmailcom

String Yes

password Gmail Account password String Yes

toNotify Recipients address just as e-mail addresses do xxxxgmailcom

String Yes

SSL Used to secure connections boolean No defaults to false

buffersize The maximum number of logging events that can be kept in the cyclic buffer

int

defaults is 16

evaluatorClass

Takes as a value a string representing the fully qualified name of a class that implements the orgapachelog4jspi TriggeringEventEvaluator interface (in other words a class that contains a custom triggering logic that overrides the default one) If this option is not specified PNotifyAppender uses an instance of the DefaultEvaluator class which triggers a response to events assigned the level ERROR or higher

String

No defaults to DefaultEvaluator

proxy It is used to identify whether log4j application behind any proxy

boolean No Default is false

proxyHost If the proxy property is true proxyHost takes the proxy address Example 192168xxxx

String Yes if proxy sets to true else No

proxyPort Proxy Port eg 3245 String Yes if proxy sets to true else No

history This property is used if we want to log the exception history of the real time notification

boolean No Default is false

subject The subject option takes a string value which should be a the subject of the e-mail message

String Yes if history sets to true else No

cc Set the cc recipient addresses String No

bcc Set the bcc recipient addresses String No

SMTPHost The SMTPHost option takes a string value which should be a the host name of the SMTP server that will send the email message

String Yes if history sets to true else No

10 | P a g e

41 Letrsquos take a closer look at below code package compnotifyappender import orgapachelog4jAppenderSkeleton import orgapachelog4jLayout import orgapachelog4jhelpersCyclicBuffer import orgapachelog4jhelpersLogLog import orgapachelog4jhelpersOptionConverter import orgapachelog4jspiLoggingEvent import orgapachelog4jspiTriggeringEventEvaluator public class PNotifyAppender extends AppenderSkeleton protected CyclicBuffer cb private int buffersize private String username private String password private String toNotify private boolean SSL private String proxyHost private String proxyPort private boolean proxy protected boolean checkEntryConditions () public boolean verifyRosterEntryJabberClient (XMPPConnection connection) AppenderSkeleton callback method public void activateOptions () protected void sendBuffer () public synchronized void close () public boolean requiresLayout () return true protected void append (LoggingEvent event) Notice the following about the PNotifyAppender a) The PNotifyAppender class extends orgapachelog4jAppenderSkeleton which all custom appenders must do PNotifyAppender inherits common functionalities from AppenderSkeleton such as appender threshold and custom filtering b) The first part of our appender is straight-forward We have the appenders fields and setget methods f or each of them Properties and method signatures obey the JavaBeans naming convention Thus log4j can analyze the appender using ref lection transparently handling the appender configuration c) To complete our appender we must implement the callback methods that the log4j framework calls to manage our appender requiresLayout () activateOptions () append () and close ()The log4j framework calls the requiresLayout () method to know whether the custom appender requires a lay out Notice that some appenders use a built-in format or dont format the events at all so they dont require a Layout object The PNotifyAppender requires a lay out hence the method returns true

11 | P a g e

d) Notice that AppenderSkeleton implements the orgapachelog4jspiOptionHandler interface AppenderSkeleton implements the single method of this interface activateOptions () as an empty method PNotifyAppender needs this method because of the interdependence between its properties For example the connection with a GTalk Server depends on the Host Port username password and toNotify properties so PNotifyAppender cannot establish a connection until these five properties have been initialized The log4j framework calls the activateOptions () method to signal to the appenders that all the properties have been set e) Once the activateOptions () method returns the appender is ready to handle logging requests AppenderSkeletondoAppend () does most of the real appending work f) The checkEntryConditions () method checks whether there is a Chat object available to append the output and also whether there is a Layout object to format the incoming event object If these preconditions are not satisfied then append () outputs a warning message and returns without proceeding g) The sendBuffer () method sends the contents of the buffer as an IM message The method loops through the events kept in the buffer formatting each one by invoking the format () method of the layout object The string representation of the events is appended to a StringBuffer object Finally sendBuffer () calls the sendMessage () method of the chat object sending the message h) The AppenderSkeletondoAppend () method which invokes append () is synchronized so sendBuffer () already owns the monitor for the appender This frees us from needing to synchronize the CyclicBuffer Object cb i) The verifyRosterEntryJabber () method subscribes to the given email Id provided to toNotify property of the PNotifyAppender if it is not present into account

5 Putting5 Putting5 Putting5 Putting it all togetherit all togetherit all togetherit all together Well wrap up by showing you PNotifyAppender in action STEP 1STEP 1STEP 1STEP 1 Drop in the requisite Jars into application a) commons-logging-111jar b) log4j-1216jar c) mailjar d) smackjar (321) e) smackxjar (321) f) pnotifyappenderjar STEP STEP STEP STEP 2 2 2 2 Configuring log4jproperties log4jrootLogger=GTALK STEP 21STEP 21STEP 21STEP 21 Minimum configuration required if we want real time notification of the exception in GTalk log4jappenderGTALK=compnotifyappenderPNotifyAppender log4jappenderGTALKThreshold=ERROR log4jappenderGTALKusername=xxxxxxx or xxxxxgmailcom (if SSLhistory property is set to true) log4jappenderGTALKpassword=xxxxxxx log4jappenderGTALKtoNotify=xxxxgmailcom log4jappenderGTALKlayout=orgapachelog4jPatternLayout log4jappenderGTALKlayoutConversionPattern=dMM-ddHHmmss[-5p][CML]-(F) mn

12 | P a g e

log4jadditivityGTALK=false if behind a proxy log4jappenderGTALKproxy=true log4jappenderGTALKproxyHost=xxxxxxxxx log4jappenderGTALKproxyPort=xxxx STEP 2STEP 2STEP 2STEP 22222 If we want to keep the history of notified exception into the respective GMail account log4jappenderGTALK=compnotifyappenderPNotifyAppender log4jappenderGTALKThreshold=ERROR log4jappenderGTALKusername=xxxxxgmailcom log4jappenderGTALKpassword=xxxxxxx log4jappenderGTALKtoNotify=xxxxgmailcom log4jappenderGTALKlayout=orgapachelog4jPatternLayout log4jappenderGTALKlayoutConversionPattern=dMM-ddHHmmss[-5p][CML]-(F) mn log4jappenderGTALKhistory=true log4jappenderGTALKSMTPHost=smtpgmailcom log4jappenderGTALKsubject=Email Notification from Application log4jappenderGTALKcc=xxxxxxxxcom log4jappenderGTALKbcc=xxxxxxxxcom log4jadditivityGTALK=false The above configuration script adds PNotifyAppender to the root logger so each logging request received will be dispatched to our appender When we run our respective application An IM message then pops up on the recipients screen and the below screenshots shows the resulting message received by GTalk and GMail

13 | P a g e

Notice that the above figure depicts the real time notification about the exception occurred in the application at GTalk in the mail Id mentioned in toNotify property of PNotifyAppender

The above figure depicts the exception got recorded into the given GMail Account when history property in PNotifyAppender is set to true and setting the other dependent property As we can see in the both cases the exception information contained in the last Logging events has been correctly transmitted This example application simply showcases use of the PNotifyAppender so explore and have fun

6 Conclusion6 Conclusion6 Conclusion6 Conclusion The log4j network appenders SocketAppender JMSAppender and SMTPAppender already provide mechanisms to monitor Java-distributed applications However several factors make IM a suitable technology for remote logging in real-time In this article weve covered the basics of extending log4j with y our custom appenders and weve seen the implementation of a basic PNotifyAppender step by step Many developers and system administrators can benefit from their use

7 Resources7 Resources7 Resources7 Resources 1 httploggingapacheorglog4j12 2 httpwwwjavaworldcomjavaworldjw-10-1999jw-10-cooltoolshtml 3 Book Template Method - Design Patterns in Java by Steven John Metsker and William CWake 4 httpwwwigniterealtimeorgprojectssmack 5 Book Instant Messaging in Java the jabber Protocol by Ian Shigeoka 6 MagicwithMerling Exception and Logging httpwwwibmcomdeveloperworksjavalibraryj-mer1211indexhtml

Page 8: Rein_in_the_ability_of_log4j

8 | P a g e

32 Usage Scenario of PNotifyAppender Below diagram shows the PNotifyAppender usage scenario Any application configured to use PNotifyAppender logs its debugging data wrapped as GTalk IM message The instant message is routed over organization network to the system administrator Thus whenever system administrator needs to check on the application status they simply log into their Gmail account using Gtalk IM using his desktop or laptops at work or when he is away from his desk he may use Gtalk IM running on any handheld devices As Gtalk IM has the capability to notify us even when we are offline once we log in it will notify system administrator with the pending notifications or real time

But why do we need PNotifyAppender The answer is that sending messages to IM (Gtalk) allows us to monitor application behavior more easily with tools at our disposal PNotifyAppender offers several advantages 1 You get real-time notification about the exception occurred at server we can consider as ldquoImmediate Loggingrdquo 2 GTalk IM isnrsquot just for desktop computers It is also being developed for wireless devices such as PDArsquos and mobile phones 3 No setup overhead 4 PNotifyAppender notifies the real time exception immediately with the exception details automatically to the Instant Messenger like GTalk and has the ability to keep track of the exception history into the GMail account

9 | P a g e

4 Ov4 Ov4 Ov4 Overviewerviewerviewerview of of of of PNotifyAppenderPNotifyAppenderPNotifyAppenderPNotifyAppender PNotifyAppender is modeled based on SMTPAppender logging strategy PNotifyAppender stores logging events in an internal cyclic buffer and send them as an instant message only when the logging request received triggers a user-specified condition Optionally users may provide a triggering event evaluator class However by default delivery is triggered on events assigned the level ERROR or higher The number of logging events delivered in each message is limited by the buffer size The cyclic buffer holds only the last buffer size logging events overflowing when it becomes full and throwing away the older events To connect to a GTalk PNotifyAppender relies on Smack API Smack is an open source high-level library that handles the protocol details for communicating with GTalk servers As a result you dont need any special Jabber or XML expertise to understand the code The properties for PNotifyAppender are summarized in Table 1

Property Description Type Required

username Gmail Account username eg anthing123 If SSL is true then eg anything123gmailcom

String Yes

password Gmail Account password String Yes

toNotify Recipients address just as e-mail addresses do xxxxgmailcom

String Yes

SSL Used to secure connections boolean No defaults to false

buffersize The maximum number of logging events that can be kept in the cyclic buffer

int

defaults is 16

evaluatorClass

Takes as a value a string representing the fully qualified name of a class that implements the orgapachelog4jspi TriggeringEventEvaluator interface (in other words a class that contains a custom triggering logic that overrides the default one) If this option is not specified PNotifyAppender uses an instance of the DefaultEvaluator class which triggers a response to events assigned the level ERROR or higher

String

No defaults to DefaultEvaluator

proxy It is used to identify whether log4j application behind any proxy

boolean No Default is false

proxyHost If the proxy property is true proxyHost takes the proxy address Example 192168xxxx

String Yes if proxy sets to true else No

proxyPort Proxy Port eg 3245 String Yes if proxy sets to true else No

history This property is used if we want to log the exception history of the real time notification

boolean No Default is false

subject The subject option takes a string value which should be a the subject of the e-mail message

String Yes if history sets to true else No

cc Set the cc recipient addresses String No

bcc Set the bcc recipient addresses String No

SMTPHost The SMTPHost option takes a string value which should be a the host name of the SMTP server that will send the email message

String Yes if history sets to true else No

10 | P a g e

41 Letrsquos take a closer look at below code package compnotifyappender import orgapachelog4jAppenderSkeleton import orgapachelog4jLayout import orgapachelog4jhelpersCyclicBuffer import orgapachelog4jhelpersLogLog import orgapachelog4jhelpersOptionConverter import orgapachelog4jspiLoggingEvent import orgapachelog4jspiTriggeringEventEvaluator public class PNotifyAppender extends AppenderSkeleton protected CyclicBuffer cb private int buffersize private String username private String password private String toNotify private boolean SSL private String proxyHost private String proxyPort private boolean proxy protected boolean checkEntryConditions () public boolean verifyRosterEntryJabberClient (XMPPConnection connection) AppenderSkeleton callback method public void activateOptions () protected void sendBuffer () public synchronized void close () public boolean requiresLayout () return true protected void append (LoggingEvent event) Notice the following about the PNotifyAppender a) The PNotifyAppender class extends orgapachelog4jAppenderSkeleton which all custom appenders must do PNotifyAppender inherits common functionalities from AppenderSkeleton such as appender threshold and custom filtering b) The first part of our appender is straight-forward We have the appenders fields and setget methods f or each of them Properties and method signatures obey the JavaBeans naming convention Thus log4j can analyze the appender using ref lection transparently handling the appender configuration c) To complete our appender we must implement the callback methods that the log4j framework calls to manage our appender requiresLayout () activateOptions () append () and close ()The log4j framework calls the requiresLayout () method to know whether the custom appender requires a lay out Notice that some appenders use a built-in format or dont format the events at all so they dont require a Layout object The PNotifyAppender requires a lay out hence the method returns true

11 | P a g e

d) Notice that AppenderSkeleton implements the orgapachelog4jspiOptionHandler interface AppenderSkeleton implements the single method of this interface activateOptions () as an empty method PNotifyAppender needs this method because of the interdependence between its properties For example the connection with a GTalk Server depends on the Host Port username password and toNotify properties so PNotifyAppender cannot establish a connection until these five properties have been initialized The log4j framework calls the activateOptions () method to signal to the appenders that all the properties have been set e) Once the activateOptions () method returns the appender is ready to handle logging requests AppenderSkeletondoAppend () does most of the real appending work f) The checkEntryConditions () method checks whether there is a Chat object available to append the output and also whether there is a Layout object to format the incoming event object If these preconditions are not satisfied then append () outputs a warning message and returns without proceeding g) The sendBuffer () method sends the contents of the buffer as an IM message The method loops through the events kept in the buffer formatting each one by invoking the format () method of the layout object The string representation of the events is appended to a StringBuffer object Finally sendBuffer () calls the sendMessage () method of the chat object sending the message h) The AppenderSkeletondoAppend () method which invokes append () is synchronized so sendBuffer () already owns the monitor for the appender This frees us from needing to synchronize the CyclicBuffer Object cb i) The verifyRosterEntryJabber () method subscribes to the given email Id provided to toNotify property of the PNotifyAppender if it is not present into account

5 Putting5 Putting5 Putting5 Putting it all togetherit all togetherit all togetherit all together Well wrap up by showing you PNotifyAppender in action STEP 1STEP 1STEP 1STEP 1 Drop in the requisite Jars into application a) commons-logging-111jar b) log4j-1216jar c) mailjar d) smackjar (321) e) smackxjar (321) f) pnotifyappenderjar STEP STEP STEP STEP 2 2 2 2 Configuring log4jproperties log4jrootLogger=GTALK STEP 21STEP 21STEP 21STEP 21 Minimum configuration required if we want real time notification of the exception in GTalk log4jappenderGTALK=compnotifyappenderPNotifyAppender log4jappenderGTALKThreshold=ERROR log4jappenderGTALKusername=xxxxxxx or xxxxxgmailcom (if SSLhistory property is set to true) log4jappenderGTALKpassword=xxxxxxx log4jappenderGTALKtoNotify=xxxxgmailcom log4jappenderGTALKlayout=orgapachelog4jPatternLayout log4jappenderGTALKlayoutConversionPattern=dMM-ddHHmmss[-5p][CML]-(F) mn

12 | P a g e

log4jadditivityGTALK=false if behind a proxy log4jappenderGTALKproxy=true log4jappenderGTALKproxyHost=xxxxxxxxx log4jappenderGTALKproxyPort=xxxx STEP 2STEP 2STEP 2STEP 22222 If we want to keep the history of notified exception into the respective GMail account log4jappenderGTALK=compnotifyappenderPNotifyAppender log4jappenderGTALKThreshold=ERROR log4jappenderGTALKusername=xxxxxgmailcom log4jappenderGTALKpassword=xxxxxxx log4jappenderGTALKtoNotify=xxxxgmailcom log4jappenderGTALKlayout=orgapachelog4jPatternLayout log4jappenderGTALKlayoutConversionPattern=dMM-ddHHmmss[-5p][CML]-(F) mn log4jappenderGTALKhistory=true log4jappenderGTALKSMTPHost=smtpgmailcom log4jappenderGTALKsubject=Email Notification from Application log4jappenderGTALKcc=xxxxxxxxcom log4jappenderGTALKbcc=xxxxxxxxcom log4jadditivityGTALK=false The above configuration script adds PNotifyAppender to the root logger so each logging request received will be dispatched to our appender When we run our respective application An IM message then pops up on the recipients screen and the below screenshots shows the resulting message received by GTalk and GMail

13 | P a g e

Notice that the above figure depicts the real time notification about the exception occurred in the application at GTalk in the mail Id mentioned in toNotify property of PNotifyAppender

The above figure depicts the exception got recorded into the given GMail Account when history property in PNotifyAppender is set to true and setting the other dependent property As we can see in the both cases the exception information contained in the last Logging events has been correctly transmitted This example application simply showcases use of the PNotifyAppender so explore and have fun

6 Conclusion6 Conclusion6 Conclusion6 Conclusion The log4j network appenders SocketAppender JMSAppender and SMTPAppender already provide mechanisms to monitor Java-distributed applications However several factors make IM a suitable technology for remote logging in real-time In this article weve covered the basics of extending log4j with y our custom appenders and weve seen the implementation of a basic PNotifyAppender step by step Many developers and system administrators can benefit from their use

7 Resources7 Resources7 Resources7 Resources 1 httploggingapacheorglog4j12 2 httpwwwjavaworldcomjavaworldjw-10-1999jw-10-cooltoolshtml 3 Book Template Method - Design Patterns in Java by Steven John Metsker and William CWake 4 httpwwwigniterealtimeorgprojectssmack 5 Book Instant Messaging in Java the jabber Protocol by Ian Shigeoka 6 MagicwithMerling Exception and Logging httpwwwibmcomdeveloperworksjavalibraryj-mer1211indexhtml

Page 9: Rein_in_the_ability_of_log4j

9 | P a g e

4 Ov4 Ov4 Ov4 Overviewerviewerviewerview of of of of PNotifyAppenderPNotifyAppenderPNotifyAppenderPNotifyAppender PNotifyAppender is modeled based on SMTPAppender logging strategy PNotifyAppender stores logging events in an internal cyclic buffer and send them as an instant message only when the logging request received triggers a user-specified condition Optionally users may provide a triggering event evaluator class However by default delivery is triggered on events assigned the level ERROR or higher The number of logging events delivered in each message is limited by the buffer size The cyclic buffer holds only the last buffer size logging events overflowing when it becomes full and throwing away the older events To connect to a GTalk PNotifyAppender relies on Smack API Smack is an open source high-level library that handles the protocol details for communicating with GTalk servers As a result you dont need any special Jabber or XML expertise to understand the code The properties for PNotifyAppender are summarized in Table 1

Property Description Type Required

username Gmail Account username eg anthing123 If SSL is true then eg anything123gmailcom

String Yes

password Gmail Account password String Yes

toNotify Recipients address just as e-mail addresses do xxxxgmailcom

String Yes

SSL Used to secure connections boolean No defaults to false

buffersize The maximum number of logging events that can be kept in the cyclic buffer

int

defaults is 16

evaluatorClass

Takes as a value a string representing the fully qualified name of a class that implements the orgapachelog4jspi TriggeringEventEvaluator interface (in other words a class that contains a custom triggering logic that overrides the default one) If this option is not specified PNotifyAppender uses an instance of the DefaultEvaluator class which triggers a response to events assigned the level ERROR or higher

String

No defaults to DefaultEvaluator

proxy It is used to identify whether log4j application behind any proxy

boolean No Default is false

proxyHost If the proxy property is true proxyHost takes the proxy address Example 192168xxxx

String Yes if proxy sets to true else No

proxyPort Proxy Port eg 3245 String Yes if proxy sets to true else No

history This property is used if we want to log the exception history of the real time notification

boolean No Default is false

subject The subject option takes a string value which should be a the subject of the e-mail message

String Yes if history sets to true else No

cc Set the cc recipient addresses String No

bcc Set the bcc recipient addresses String No

SMTPHost The SMTPHost option takes a string value which should be a the host name of the SMTP server that will send the email message

String Yes if history sets to true else No

10 | P a g e

41 Letrsquos take a closer look at below code package compnotifyappender import orgapachelog4jAppenderSkeleton import orgapachelog4jLayout import orgapachelog4jhelpersCyclicBuffer import orgapachelog4jhelpersLogLog import orgapachelog4jhelpersOptionConverter import orgapachelog4jspiLoggingEvent import orgapachelog4jspiTriggeringEventEvaluator public class PNotifyAppender extends AppenderSkeleton protected CyclicBuffer cb private int buffersize private String username private String password private String toNotify private boolean SSL private String proxyHost private String proxyPort private boolean proxy protected boolean checkEntryConditions () public boolean verifyRosterEntryJabberClient (XMPPConnection connection) AppenderSkeleton callback method public void activateOptions () protected void sendBuffer () public synchronized void close () public boolean requiresLayout () return true protected void append (LoggingEvent event) Notice the following about the PNotifyAppender a) The PNotifyAppender class extends orgapachelog4jAppenderSkeleton which all custom appenders must do PNotifyAppender inherits common functionalities from AppenderSkeleton such as appender threshold and custom filtering b) The first part of our appender is straight-forward We have the appenders fields and setget methods f or each of them Properties and method signatures obey the JavaBeans naming convention Thus log4j can analyze the appender using ref lection transparently handling the appender configuration c) To complete our appender we must implement the callback methods that the log4j framework calls to manage our appender requiresLayout () activateOptions () append () and close ()The log4j framework calls the requiresLayout () method to know whether the custom appender requires a lay out Notice that some appenders use a built-in format or dont format the events at all so they dont require a Layout object The PNotifyAppender requires a lay out hence the method returns true

11 | P a g e

d) Notice that AppenderSkeleton implements the orgapachelog4jspiOptionHandler interface AppenderSkeleton implements the single method of this interface activateOptions () as an empty method PNotifyAppender needs this method because of the interdependence between its properties For example the connection with a GTalk Server depends on the Host Port username password and toNotify properties so PNotifyAppender cannot establish a connection until these five properties have been initialized The log4j framework calls the activateOptions () method to signal to the appenders that all the properties have been set e) Once the activateOptions () method returns the appender is ready to handle logging requests AppenderSkeletondoAppend () does most of the real appending work f) The checkEntryConditions () method checks whether there is a Chat object available to append the output and also whether there is a Layout object to format the incoming event object If these preconditions are not satisfied then append () outputs a warning message and returns without proceeding g) The sendBuffer () method sends the contents of the buffer as an IM message The method loops through the events kept in the buffer formatting each one by invoking the format () method of the layout object The string representation of the events is appended to a StringBuffer object Finally sendBuffer () calls the sendMessage () method of the chat object sending the message h) The AppenderSkeletondoAppend () method which invokes append () is synchronized so sendBuffer () already owns the monitor for the appender This frees us from needing to synchronize the CyclicBuffer Object cb i) The verifyRosterEntryJabber () method subscribes to the given email Id provided to toNotify property of the PNotifyAppender if it is not present into account

5 Putting5 Putting5 Putting5 Putting it all togetherit all togetherit all togetherit all together Well wrap up by showing you PNotifyAppender in action STEP 1STEP 1STEP 1STEP 1 Drop in the requisite Jars into application a) commons-logging-111jar b) log4j-1216jar c) mailjar d) smackjar (321) e) smackxjar (321) f) pnotifyappenderjar STEP STEP STEP STEP 2 2 2 2 Configuring log4jproperties log4jrootLogger=GTALK STEP 21STEP 21STEP 21STEP 21 Minimum configuration required if we want real time notification of the exception in GTalk log4jappenderGTALK=compnotifyappenderPNotifyAppender log4jappenderGTALKThreshold=ERROR log4jappenderGTALKusername=xxxxxxx or xxxxxgmailcom (if SSLhistory property is set to true) log4jappenderGTALKpassword=xxxxxxx log4jappenderGTALKtoNotify=xxxxgmailcom log4jappenderGTALKlayout=orgapachelog4jPatternLayout log4jappenderGTALKlayoutConversionPattern=dMM-ddHHmmss[-5p][CML]-(F) mn

12 | P a g e

log4jadditivityGTALK=false if behind a proxy log4jappenderGTALKproxy=true log4jappenderGTALKproxyHost=xxxxxxxxx log4jappenderGTALKproxyPort=xxxx STEP 2STEP 2STEP 2STEP 22222 If we want to keep the history of notified exception into the respective GMail account log4jappenderGTALK=compnotifyappenderPNotifyAppender log4jappenderGTALKThreshold=ERROR log4jappenderGTALKusername=xxxxxgmailcom log4jappenderGTALKpassword=xxxxxxx log4jappenderGTALKtoNotify=xxxxgmailcom log4jappenderGTALKlayout=orgapachelog4jPatternLayout log4jappenderGTALKlayoutConversionPattern=dMM-ddHHmmss[-5p][CML]-(F) mn log4jappenderGTALKhistory=true log4jappenderGTALKSMTPHost=smtpgmailcom log4jappenderGTALKsubject=Email Notification from Application log4jappenderGTALKcc=xxxxxxxxcom log4jappenderGTALKbcc=xxxxxxxxcom log4jadditivityGTALK=false The above configuration script adds PNotifyAppender to the root logger so each logging request received will be dispatched to our appender When we run our respective application An IM message then pops up on the recipients screen and the below screenshots shows the resulting message received by GTalk and GMail

13 | P a g e

Notice that the above figure depicts the real time notification about the exception occurred in the application at GTalk in the mail Id mentioned in toNotify property of PNotifyAppender

The above figure depicts the exception got recorded into the given GMail Account when history property in PNotifyAppender is set to true and setting the other dependent property As we can see in the both cases the exception information contained in the last Logging events has been correctly transmitted This example application simply showcases use of the PNotifyAppender so explore and have fun

6 Conclusion6 Conclusion6 Conclusion6 Conclusion The log4j network appenders SocketAppender JMSAppender and SMTPAppender already provide mechanisms to monitor Java-distributed applications However several factors make IM a suitable technology for remote logging in real-time In this article weve covered the basics of extending log4j with y our custom appenders and weve seen the implementation of a basic PNotifyAppender step by step Many developers and system administrators can benefit from their use

7 Resources7 Resources7 Resources7 Resources 1 httploggingapacheorglog4j12 2 httpwwwjavaworldcomjavaworldjw-10-1999jw-10-cooltoolshtml 3 Book Template Method - Design Patterns in Java by Steven John Metsker and William CWake 4 httpwwwigniterealtimeorgprojectssmack 5 Book Instant Messaging in Java the jabber Protocol by Ian Shigeoka 6 MagicwithMerling Exception and Logging httpwwwibmcomdeveloperworksjavalibraryj-mer1211indexhtml

Page 10: Rein_in_the_ability_of_log4j

10 | P a g e

41 Letrsquos take a closer look at below code package compnotifyappender import orgapachelog4jAppenderSkeleton import orgapachelog4jLayout import orgapachelog4jhelpersCyclicBuffer import orgapachelog4jhelpersLogLog import orgapachelog4jhelpersOptionConverter import orgapachelog4jspiLoggingEvent import orgapachelog4jspiTriggeringEventEvaluator public class PNotifyAppender extends AppenderSkeleton protected CyclicBuffer cb private int buffersize private String username private String password private String toNotify private boolean SSL private String proxyHost private String proxyPort private boolean proxy protected boolean checkEntryConditions () public boolean verifyRosterEntryJabberClient (XMPPConnection connection) AppenderSkeleton callback method public void activateOptions () protected void sendBuffer () public synchronized void close () public boolean requiresLayout () return true protected void append (LoggingEvent event) Notice the following about the PNotifyAppender a) The PNotifyAppender class extends orgapachelog4jAppenderSkeleton which all custom appenders must do PNotifyAppender inherits common functionalities from AppenderSkeleton such as appender threshold and custom filtering b) The first part of our appender is straight-forward We have the appenders fields and setget methods f or each of them Properties and method signatures obey the JavaBeans naming convention Thus log4j can analyze the appender using ref lection transparently handling the appender configuration c) To complete our appender we must implement the callback methods that the log4j framework calls to manage our appender requiresLayout () activateOptions () append () and close ()The log4j framework calls the requiresLayout () method to know whether the custom appender requires a lay out Notice that some appenders use a built-in format or dont format the events at all so they dont require a Layout object The PNotifyAppender requires a lay out hence the method returns true

11 | P a g e

d) Notice that AppenderSkeleton implements the orgapachelog4jspiOptionHandler interface AppenderSkeleton implements the single method of this interface activateOptions () as an empty method PNotifyAppender needs this method because of the interdependence between its properties For example the connection with a GTalk Server depends on the Host Port username password and toNotify properties so PNotifyAppender cannot establish a connection until these five properties have been initialized The log4j framework calls the activateOptions () method to signal to the appenders that all the properties have been set e) Once the activateOptions () method returns the appender is ready to handle logging requests AppenderSkeletondoAppend () does most of the real appending work f) The checkEntryConditions () method checks whether there is a Chat object available to append the output and also whether there is a Layout object to format the incoming event object If these preconditions are not satisfied then append () outputs a warning message and returns without proceeding g) The sendBuffer () method sends the contents of the buffer as an IM message The method loops through the events kept in the buffer formatting each one by invoking the format () method of the layout object The string representation of the events is appended to a StringBuffer object Finally sendBuffer () calls the sendMessage () method of the chat object sending the message h) The AppenderSkeletondoAppend () method which invokes append () is synchronized so sendBuffer () already owns the monitor for the appender This frees us from needing to synchronize the CyclicBuffer Object cb i) The verifyRosterEntryJabber () method subscribes to the given email Id provided to toNotify property of the PNotifyAppender if it is not present into account

5 Putting5 Putting5 Putting5 Putting it all togetherit all togetherit all togetherit all together Well wrap up by showing you PNotifyAppender in action STEP 1STEP 1STEP 1STEP 1 Drop in the requisite Jars into application a) commons-logging-111jar b) log4j-1216jar c) mailjar d) smackjar (321) e) smackxjar (321) f) pnotifyappenderjar STEP STEP STEP STEP 2 2 2 2 Configuring log4jproperties log4jrootLogger=GTALK STEP 21STEP 21STEP 21STEP 21 Minimum configuration required if we want real time notification of the exception in GTalk log4jappenderGTALK=compnotifyappenderPNotifyAppender log4jappenderGTALKThreshold=ERROR log4jappenderGTALKusername=xxxxxxx or xxxxxgmailcom (if SSLhistory property is set to true) log4jappenderGTALKpassword=xxxxxxx log4jappenderGTALKtoNotify=xxxxgmailcom log4jappenderGTALKlayout=orgapachelog4jPatternLayout log4jappenderGTALKlayoutConversionPattern=dMM-ddHHmmss[-5p][CML]-(F) mn

12 | P a g e

log4jadditivityGTALK=false if behind a proxy log4jappenderGTALKproxy=true log4jappenderGTALKproxyHost=xxxxxxxxx log4jappenderGTALKproxyPort=xxxx STEP 2STEP 2STEP 2STEP 22222 If we want to keep the history of notified exception into the respective GMail account log4jappenderGTALK=compnotifyappenderPNotifyAppender log4jappenderGTALKThreshold=ERROR log4jappenderGTALKusername=xxxxxgmailcom log4jappenderGTALKpassword=xxxxxxx log4jappenderGTALKtoNotify=xxxxgmailcom log4jappenderGTALKlayout=orgapachelog4jPatternLayout log4jappenderGTALKlayoutConversionPattern=dMM-ddHHmmss[-5p][CML]-(F) mn log4jappenderGTALKhistory=true log4jappenderGTALKSMTPHost=smtpgmailcom log4jappenderGTALKsubject=Email Notification from Application log4jappenderGTALKcc=xxxxxxxxcom log4jappenderGTALKbcc=xxxxxxxxcom log4jadditivityGTALK=false The above configuration script adds PNotifyAppender to the root logger so each logging request received will be dispatched to our appender When we run our respective application An IM message then pops up on the recipients screen and the below screenshots shows the resulting message received by GTalk and GMail

13 | P a g e

Notice that the above figure depicts the real time notification about the exception occurred in the application at GTalk in the mail Id mentioned in toNotify property of PNotifyAppender

The above figure depicts the exception got recorded into the given GMail Account when history property in PNotifyAppender is set to true and setting the other dependent property As we can see in the both cases the exception information contained in the last Logging events has been correctly transmitted This example application simply showcases use of the PNotifyAppender so explore and have fun

6 Conclusion6 Conclusion6 Conclusion6 Conclusion The log4j network appenders SocketAppender JMSAppender and SMTPAppender already provide mechanisms to monitor Java-distributed applications However several factors make IM a suitable technology for remote logging in real-time In this article weve covered the basics of extending log4j with y our custom appenders and weve seen the implementation of a basic PNotifyAppender step by step Many developers and system administrators can benefit from their use

7 Resources7 Resources7 Resources7 Resources 1 httploggingapacheorglog4j12 2 httpwwwjavaworldcomjavaworldjw-10-1999jw-10-cooltoolshtml 3 Book Template Method - Design Patterns in Java by Steven John Metsker and William CWake 4 httpwwwigniterealtimeorgprojectssmack 5 Book Instant Messaging in Java the jabber Protocol by Ian Shigeoka 6 MagicwithMerling Exception and Logging httpwwwibmcomdeveloperworksjavalibraryj-mer1211indexhtml

Page 11: Rein_in_the_ability_of_log4j

11 | P a g e

d) Notice that AppenderSkeleton implements the orgapachelog4jspiOptionHandler interface AppenderSkeleton implements the single method of this interface activateOptions () as an empty method PNotifyAppender needs this method because of the interdependence between its properties For example the connection with a GTalk Server depends on the Host Port username password and toNotify properties so PNotifyAppender cannot establish a connection until these five properties have been initialized The log4j framework calls the activateOptions () method to signal to the appenders that all the properties have been set e) Once the activateOptions () method returns the appender is ready to handle logging requests AppenderSkeletondoAppend () does most of the real appending work f) The checkEntryConditions () method checks whether there is a Chat object available to append the output and also whether there is a Layout object to format the incoming event object If these preconditions are not satisfied then append () outputs a warning message and returns without proceeding g) The sendBuffer () method sends the contents of the buffer as an IM message The method loops through the events kept in the buffer formatting each one by invoking the format () method of the layout object The string representation of the events is appended to a StringBuffer object Finally sendBuffer () calls the sendMessage () method of the chat object sending the message h) The AppenderSkeletondoAppend () method which invokes append () is synchronized so sendBuffer () already owns the monitor for the appender This frees us from needing to synchronize the CyclicBuffer Object cb i) The verifyRosterEntryJabber () method subscribes to the given email Id provided to toNotify property of the PNotifyAppender if it is not present into account

5 Putting5 Putting5 Putting5 Putting it all togetherit all togetherit all togetherit all together Well wrap up by showing you PNotifyAppender in action STEP 1STEP 1STEP 1STEP 1 Drop in the requisite Jars into application a) commons-logging-111jar b) log4j-1216jar c) mailjar d) smackjar (321) e) smackxjar (321) f) pnotifyappenderjar STEP STEP STEP STEP 2 2 2 2 Configuring log4jproperties log4jrootLogger=GTALK STEP 21STEP 21STEP 21STEP 21 Minimum configuration required if we want real time notification of the exception in GTalk log4jappenderGTALK=compnotifyappenderPNotifyAppender log4jappenderGTALKThreshold=ERROR log4jappenderGTALKusername=xxxxxxx or xxxxxgmailcom (if SSLhistory property is set to true) log4jappenderGTALKpassword=xxxxxxx log4jappenderGTALKtoNotify=xxxxgmailcom log4jappenderGTALKlayout=orgapachelog4jPatternLayout log4jappenderGTALKlayoutConversionPattern=dMM-ddHHmmss[-5p][CML]-(F) mn

12 | P a g e

log4jadditivityGTALK=false if behind a proxy log4jappenderGTALKproxy=true log4jappenderGTALKproxyHost=xxxxxxxxx log4jappenderGTALKproxyPort=xxxx STEP 2STEP 2STEP 2STEP 22222 If we want to keep the history of notified exception into the respective GMail account log4jappenderGTALK=compnotifyappenderPNotifyAppender log4jappenderGTALKThreshold=ERROR log4jappenderGTALKusername=xxxxxgmailcom log4jappenderGTALKpassword=xxxxxxx log4jappenderGTALKtoNotify=xxxxgmailcom log4jappenderGTALKlayout=orgapachelog4jPatternLayout log4jappenderGTALKlayoutConversionPattern=dMM-ddHHmmss[-5p][CML]-(F) mn log4jappenderGTALKhistory=true log4jappenderGTALKSMTPHost=smtpgmailcom log4jappenderGTALKsubject=Email Notification from Application log4jappenderGTALKcc=xxxxxxxxcom log4jappenderGTALKbcc=xxxxxxxxcom log4jadditivityGTALK=false The above configuration script adds PNotifyAppender to the root logger so each logging request received will be dispatched to our appender When we run our respective application An IM message then pops up on the recipients screen and the below screenshots shows the resulting message received by GTalk and GMail

13 | P a g e

Notice that the above figure depicts the real time notification about the exception occurred in the application at GTalk in the mail Id mentioned in toNotify property of PNotifyAppender

The above figure depicts the exception got recorded into the given GMail Account when history property in PNotifyAppender is set to true and setting the other dependent property As we can see in the both cases the exception information contained in the last Logging events has been correctly transmitted This example application simply showcases use of the PNotifyAppender so explore and have fun

6 Conclusion6 Conclusion6 Conclusion6 Conclusion The log4j network appenders SocketAppender JMSAppender and SMTPAppender already provide mechanisms to monitor Java-distributed applications However several factors make IM a suitable technology for remote logging in real-time In this article weve covered the basics of extending log4j with y our custom appenders and weve seen the implementation of a basic PNotifyAppender step by step Many developers and system administrators can benefit from their use

7 Resources7 Resources7 Resources7 Resources 1 httploggingapacheorglog4j12 2 httpwwwjavaworldcomjavaworldjw-10-1999jw-10-cooltoolshtml 3 Book Template Method - Design Patterns in Java by Steven John Metsker and William CWake 4 httpwwwigniterealtimeorgprojectssmack 5 Book Instant Messaging in Java the jabber Protocol by Ian Shigeoka 6 MagicwithMerling Exception and Logging httpwwwibmcomdeveloperworksjavalibraryj-mer1211indexhtml

Page 12: Rein_in_the_ability_of_log4j

12 | P a g e

log4jadditivityGTALK=false if behind a proxy log4jappenderGTALKproxy=true log4jappenderGTALKproxyHost=xxxxxxxxx log4jappenderGTALKproxyPort=xxxx STEP 2STEP 2STEP 2STEP 22222 If we want to keep the history of notified exception into the respective GMail account log4jappenderGTALK=compnotifyappenderPNotifyAppender log4jappenderGTALKThreshold=ERROR log4jappenderGTALKusername=xxxxxgmailcom log4jappenderGTALKpassword=xxxxxxx log4jappenderGTALKtoNotify=xxxxgmailcom log4jappenderGTALKlayout=orgapachelog4jPatternLayout log4jappenderGTALKlayoutConversionPattern=dMM-ddHHmmss[-5p][CML]-(F) mn log4jappenderGTALKhistory=true log4jappenderGTALKSMTPHost=smtpgmailcom log4jappenderGTALKsubject=Email Notification from Application log4jappenderGTALKcc=xxxxxxxxcom log4jappenderGTALKbcc=xxxxxxxxcom log4jadditivityGTALK=false The above configuration script adds PNotifyAppender to the root logger so each logging request received will be dispatched to our appender When we run our respective application An IM message then pops up on the recipients screen and the below screenshots shows the resulting message received by GTalk and GMail

13 | P a g e

Notice that the above figure depicts the real time notification about the exception occurred in the application at GTalk in the mail Id mentioned in toNotify property of PNotifyAppender

The above figure depicts the exception got recorded into the given GMail Account when history property in PNotifyAppender is set to true and setting the other dependent property As we can see in the both cases the exception information contained in the last Logging events has been correctly transmitted This example application simply showcases use of the PNotifyAppender so explore and have fun

6 Conclusion6 Conclusion6 Conclusion6 Conclusion The log4j network appenders SocketAppender JMSAppender and SMTPAppender already provide mechanisms to monitor Java-distributed applications However several factors make IM a suitable technology for remote logging in real-time In this article weve covered the basics of extending log4j with y our custom appenders and weve seen the implementation of a basic PNotifyAppender step by step Many developers and system administrators can benefit from their use

7 Resources7 Resources7 Resources7 Resources 1 httploggingapacheorglog4j12 2 httpwwwjavaworldcomjavaworldjw-10-1999jw-10-cooltoolshtml 3 Book Template Method - Design Patterns in Java by Steven John Metsker and William CWake 4 httpwwwigniterealtimeorgprojectssmack 5 Book Instant Messaging in Java the jabber Protocol by Ian Shigeoka 6 MagicwithMerling Exception and Logging httpwwwibmcomdeveloperworksjavalibraryj-mer1211indexhtml

Page 13: Rein_in_the_ability_of_log4j

13 | P a g e

Notice that the above figure depicts the real time notification about the exception occurred in the application at GTalk in the mail Id mentioned in toNotify property of PNotifyAppender

The above figure depicts the exception got recorded into the given GMail Account when history property in PNotifyAppender is set to true and setting the other dependent property As we can see in the both cases the exception information contained in the last Logging events has been correctly transmitted This example application simply showcases use of the PNotifyAppender so explore and have fun

6 Conclusion6 Conclusion6 Conclusion6 Conclusion The log4j network appenders SocketAppender JMSAppender and SMTPAppender already provide mechanisms to monitor Java-distributed applications However several factors make IM a suitable technology for remote logging in real-time In this article weve covered the basics of extending log4j with y our custom appenders and weve seen the implementation of a basic PNotifyAppender step by step Many developers and system administrators can benefit from their use

7 Resources7 Resources7 Resources7 Resources 1 httploggingapacheorglog4j12 2 httpwwwjavaworldcomjavaworldjw-10-1999jw-10-cooltoolshtml 3 Book Template Method - Design Patterns in Java by Steven John Metsker and William CWake 4 httpwwwigniterealtimeorgprojectssmack 5 Book Instant Messaging in Java the jabber Protocol by Ian Shigeoka 6 MagicwithMerling Exception and Logging httpwwwibmcomdeveloperworksjavalibraryj-mer1211indexhtml