logging

Logging is the cutting, skidding, on-site processing, and loading of trees or logs onto trucks or skeleton cars. read more at WikiPedia

  • Log4J: A logging framework for J2EE

    Log4j homepage: http://jakarta.apache.org/log4j/

    Reference book on log4j:

    The Complete Log4j Manual

    by Ceki Gulcu
    Edition: Paperback

    Introduction
    Log4j is an open source tool (OSS) developed for inserting logs statements into your application and was developed by people at Apache fundation. It's speed and flexibility allows log statements to remain in shipped code while giving the user the ability to enable logging at runtime without modifying any of the application binary. All of this while not incurring a high performance cost/loss.

    Requirements

    • Log4j need at least a compatible JDK 1.1.x to run.
    • The DOMConfigurator is based on the DOM Level 1 API. The DOMConfigurator.configure(Element) method will work with any XML parser that will pass it a DOM tree. The DOMConfigurator.configure(String filename) method and its variants require a JAXP compatible XML parser, for example Xerces or Sun's parser. Compiling the DOMConfigurator requires the presence of a JAXP parser in the classpath.
    • The org.apache.log4j.net.SMTPAppender relies on the JavaMail API. It has been tested with JavaMail API version 1.2. The JavaMail API requires the JavaBeans Activation Framework package.
    • The org.apache.log4j.net.JMSAppender requires the presence of the JMS API as well as JNDI.
    • Log4j test code relies on the JUnit testing framework in order to maintain quality of release.

    Why inserting log statement or rely on this (old) technology?

    Advantages Drawbacks
    It offers several advantages. It provides precise context about a run of the application.
    Once inserted into the code:
    • It Help developer to develop and correct bugs,
    • Generation of logging output requires no human intervention,
    • Log output can be saved in persistent medium to be studied at a later time,
    • Rich logging package can also be viewed as an auditing tool, for example to determine performance...
    • Debugging statements stay with the program (for years) while debugging sessions are always transient (lifetime of bug resolution).
    • Log can make the glue between developer within a development environment and specialist within a production environment. The know how or description in log statements can help the production specialist to undestand how your application work.
    But
    • It can/May slow down an application.
    • If the program verbosity is high, it can pollute reader's mind, or lead to misanalyse of a problems.
      For example:
      - saying something false in a log statement can have tremendous effects...
      - Writing too much info (irrelevent), can hide some major error.

    Why choosing Log4J? (Fromapache.org)

    • log4j is optimized for speed. The system write has been rewrite for efficiency and is now asynchrone (compare to System.err)
    • log4j is based on a named logger hierarchy. (category)
    • log4j is fail-stop but not reliable.
    • log4j is thread-safe. No interblocking thread, or memory leaks.
    • log4j is not restricted to a predefined set of facilities.
    • Logging behavior can be set at runtime using a configuration file. Configuration files can be property files or in XML format.
    • log4j is designed to handle Java Exceptions from the start.
    • log4j can direct its output to a file, the console, an java.io.OutputStream, java.io.Writer, a remote server using TCP, a remote Unix Syslog daemon, to a remote listener using JMS, to the NT EventLog or even send e-mail. (Appenders)
    • log4j uses 5 levels, namely DEBUG, INFO, WARN, ERROR and FATAL.
    • The format of the log output can be easily changed by extending the Layout class.
    • The target of the log output as well as the writing strategy can be altered by implementations of the Appender interface.
    • log4j supports multiple output appenders per logger
    • log4j supports internationalization.
    • It is used extensively by thousands of Java developers. If a flaw is discovered it gets fixed in the next release.
    • The log4j code is likely to be better than code you'd write yourself and is l ikely to improve over time.
    • Ports to other languages are: C++, Eifel, Perl, .NET, Python, Ruby…more than 57 languages are supported

    Log4j concepts

    Logger Logger are responsible for handling the majority of log operations. The logger is the core component of the logging process.
    Levels Log4j by default can log messages with five priority levels (not including custom Levels). More can be defined by subclassing, but it is not recommended.

    debug to write debugging messages which should not be printed when the application is in production.
    log.debug("Starting init of RequestController");

    info for messages similar to the "verbose" mode of many applications.
    log.info("Analyser init successfull");

    warn for warning messages which are logged to some log but the application is able to carry on without a problem.
    log.warn("Inconsistent value in conf for key 'debug', line 123 assuming default value true");

    error for application error messages which are also logged to some log but, still, the application can hobble along. Such as when some administrator-supplied configuration parameter is incorrect and you fall back to using some hard-coded default value. You must use this level in all catch clause, if you can not resolve the exception!
    log.error("The object Account is null");

    fatal for critical messages, after logging of which the application quits abnormally
    log.fatal("Can not get any new connection from database");

    Notes:

    A logger will only output messages that are of a level greater than or equal to it. If the level of a logger is not set it will inherit the level of the closest ancestor. So if a logger is created in the package com.waltercedric.account and no level is set for it, it will inherit the level of the logger created in com.waltercedric. If no logger was created in com.waltercedric., the logger created in com.waltercedric.balance will inherit the level of the root logger, the root logger is always instantiated and available.

    Appender Appender
    1. Are responsible for controlling the output of log operations.
    2. Controls where and how logging result is store.

    The Appenders available are (from the log4j API)

    • ConsoleAppender: appends log events to System.out or System.err using a layout specified by the user. The default target is System.out
    • DailyRollingFileAppender extends FileAppender so that the underlying file is rolled over at a user chosen frequency.
    • FileAppender appends log events to a file.
    • RollingFileAppender extends FileAppender to backup the log files when they reach a certain size.
    • WriterAppender appends log events to a Writer or an OutputStream depending on the user's choice.
    • SMTPAppender sends an e-mail when a specific logging event occurs, typically on errors or fatal errors.
    • SocketAppender sends LoggingEvent objects to a remote a log server, usually a SocketNode.
    • SocketHubAppender sends LoggingEvent objects to a set of remote log servers, usually a SocketNodes
    • SyslogAppender sends messages to a remote syslog daemon.
    • TelnetAppender is a log4j appender that specializes in writing to a read-only socket.

    One may also implement the Appender interface to create ones own ways of outputting log statements.

    Layout Layout:
    1. Are responsible for formatting the output for Appender.
    2. Are always used by Appender
    3. Knows how to format the output.

    There are three types of Layout available:

    • HTMLLayout formats the output as a HTML table.
    • PatternLayout formats the output based on a conversion pattern specified, or if none is specified, the default conversion pattern.
    • SimpleLayout formats the output in a very simple manner, it prints the Level, then a dash '-' and then the log message.

    Using Log4j in your code

    It is not recommended to use log4j api directly, since who knows if a better logging framework won't do better in the future or if log4j won't modify its api's. The main idea is that when you aquire a 3rd party component, is to build a wrapper around it. It is even better if the wrapper contains an abstract factory: maybe in some case you wil have to use different class of logging (because of performance, licence...)

    A simple log4j wrapper
    Import com.waltercedric.LogWrapper;

    public LogWrapper {

    ...
    }

    Using your newly created wrapper
    Import com.waltercedric.LogWrapper;

    public void init() throws com.waltercedric.applicationException {

    LogWrapper logger = new LogWrapper(Account.class);
    logger.info("Starting init");

    logger.debug("create an Account");
    up = new Account(new NullObject());
    }

    Log4j Guidelines
    The FAQ of log4J is a must to read, here are the most important points:

    1. Respect Levels!
      Respect levels and categorize the logs according to severity and messages size. Please define a special logger (restricted to a package) that can be switch off and that do not write to much statement in log output.
    2. Meaningful statements
      Create code with System.err.println or System.out.println If you are doing some internal reviews of your code, please try to write some meaningful information in logs. Avoid log of type: "I am here", "here 1", "here 2" and so on..
    3. Classwide static logger
      It is recommended to provide a class wide logger access point, if you need to do a lot of output in a class or hierarchy. Define a protected Logger in the parent hierarchie
      public class Mamals {
      protected static LoggerWrapper logger = LogFactory.getLog(Mamals.class);
      ...
      }
      and use it in all children
      public class Human extends Mamals {

      public Human() {
      super();
      logger.debug("init");
      }

      }

    4. Increase speed
      Log4J is not slow, it is even faster than System.out or System.err (System.err or System.out are synchronous while NOT with log4j, the cost in times comes more from costs during formating messages!
      If you know that you must heavily formatted the output message, do not use the following:
      l.debug("Cash balance is " + cashvalue);
      use instead
      if(myLogger.isDebugEnabled()) {
      myLogger.debug("Cash balance is " + cashBalance.toXML());
      }
    5. How to name Loggers?
      You can name loggers by locality. It turns out that instantiating a logger in each class, with the logger name equal to the fully-qualified name of the class, is a useful and straightforward approach of defining loggers. This approach has many benefits:
    • It is very simple to implement.
    • It is very simple to explain to new developers.
    • It automatically mirrors your application's own modular design.
    • It can be further refined at will.
    • Printing the logger automatically gives information on the locality of the log statement.

    However, this is not the only way for naming loggers. A common alternative is to name loggers by functional areas. For example, the "database" logger, "RMI" logger, "security" logger, or the "XML" logger. You are totally free in choosing the names of your loggers. The log4j package merely allows you to manage your names in a hierarchy. However, it is your responsibility to define this hierarchy. Note by naming loggers by locality one tends to name things by functionality, since in most cases the locality relates closely to functionality.

    Remote logging over TCP
    Read carefully: http://jakarta.apache.org/log4j/docs/api/org/apache/log4j/net/SocketAppender.html and
    http://jakarta.apache.org/log4j/docs/api/org/apache/log4j/net/SocketHubAppender.html

    Starting the server.Chainsaw
    Chainsaw is a graphical logging client, where you can see, sort and filter logs data.
    Documentation can be read here: http://jakarta.apache.org/log4j/docs/api/org/apache/log4j/chainsaw/package-summary.html and it is a part of log4j.jar

    Starting chainsaw
    c:jdk1.4.2binjava org.apache.log4j.chainsaw.Main "chainsaw.port", "5000"
    1. Log4 gives you the ability to send messages to a remote location over a socket for logging purposes. The org.apache.log4j.net.SocketAppender and org.apache.log4j.net.SocketServer classes are the key classes used in remote logging.
    2. Modify all logger in your log4j.xml to use a SocketApender as appender, Once you have loaded this configuration, all messages will be written to the machine and port that you specify.
    3. Start the client application (Chainsaw), this program will receive logs and show them in a swing GUI
    Example of TCP appender in log4j.xml
    log4j.appender.remote =org.apache.log4j.net.SocketAppender
    log4j.appender. remote.RemoteHost=localhost
    log4j.appender. remote.Port=5000
    log4j.appender. remote.LocationInfo=true

    On the server side (where your application create logs), you will need to run log4j's SocketServer class. You can create a configuration file with configuration information similar to the following: The whole applcation is in DEBUG mode

    Example of socketserver.properties
    log4j.rootCategory=DEBUG,log1

    ############################
    # log1 is set to be a file

    log4j.appender.log1=org.apache.log4j.RollingFileAppender
    log4j.appender.log1.MaxFileSize=100KB
    log4j.appender.log1.MaxBackupIndex=1
    log4j.appender.log1.File=c://logs.log
    log4j.appender.log1.append = true
    log4j.appender.log1.layout=org.apache.log4j.PatternLayout
    log4j.appender.log1.layout.ConversionPattern=%p %t %c - %m%n
    1. Set up your CLASSPATH on both the client and server to contain log4j.jar
    2. Run the SocketServer at the command line. The command line syntax for the SocketServer is as follows:
      java org.apache.log4j.net.SocketServer portNumber configurationFile configurationDirectory
      start the server:
    Start the server
    java org.apache.log4j.net.SocketServer 5000 C:socketserver.properties C:temp
    org.apache.log4j.net.SocketServer "5000", "C:socketserver.properties", "C:temp"

    Start your application, without doing any change in your code or recompiling it, you can now log data remotely!

    Configuring log4j

    Location of configuration file
    The configuration files of log4j must be in classpath, if more than one are in classpath, the first found will be used. Log4j require to have a compatible parser in classpath in order to read the configuration file. As default, Logj use Crimson.jar

    Location of DTD
    The DTD is needed in order to initialize log4j, 2 solutions are available:

    Public DTD, the file must be on internet or on network System path, but with a fix path (URI)

    "http://www.waltercedric.com/log4j.dtd">

    Extending log4j

    Defining your application specific loggers, appenders and layouts
    You can look at the Log4j API to see how to implement a logger, appender and layout.

    Conclusions

    One of the strength of log4j is that is do not require to recompile the java code to binary classes to change considerably the ouput amount in logs. You can add logging statements in your code, and without changing the code shipped, change at runtime the amount of log output. Thus the major behaviour logging strategies are done in this file (it can be a properties file or a XML file). You should store this file in the classpath of your application.

    Annexes

    Example of configuration files:

    Example of log4j.xml













































































    Example of log4j.properties
    ###########################################################################
    #
    # log4Java properties
    #
    # Documentation can be found at
    http://jakarta.apache.org/log4j/docs/api/index.html
    # There is no other documentation except forum, a commercial book is due (oreilly)
    #
    # To permit reloading during runtime, the LogDecorator will test each 60s if the file has changed
    # and update configuration of log4j if needed
    #
    # Ascending prioriy INFO < WARNING < DEBUG < ERROR < FATAL
    # log visible only if current log level >= defined level
    #
    # current layout can be: DateLayout, HTMLLayout, PatternLayout, SimpleLayout, XMLLayout
    #
    ###########################################################################

    # Set root logger level to [FATAL|ERROR|WARN|INFO|DEBUG], and provide default appender

    log4j.rootLogger=DEBUG, stdout

    ############################
    # define category (and their level [INHERITED|FATAL|ERROR|WARN|INFO|DEBUG] and appender)
    # category should be fully qualified class name or incomplete package name
    # Note that you inherit from the root logger otherwise specified (set addtivity flag)
    #
    # additivity= true (default) all request will also be forwarded to the hierarchy
    # -> log twice if the same appender is already in the hierarchy
    # additivity= false do not forward to ancestor appenders
    #
    # INHERITED can be optionally specified which means that named category should inherit
    # its priority from the category hierarchy. If you add the flag additivity to false,
    # you do not inherit of appender
    ##

    log4j.category.com.waltercedric.account=INHERIT, log1
    log4j.additivity.com.waltercedric.account=false

    log4j.category.com.waltercedric=DEBUG, log1

    ########################################################
    # You Can defined as many appender as you want
    ########################################################

    ############################
    # stdout is set to be a ConsoleAppender.
    ##

    log4j.appender.stdout=org.apache.log4j.ConsoleAppender
    log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
    see http://jakarta.apache.org/log4j/docs/api/org/apache/log4j/PatternLayout.html
    log4j.appender.stdout.layout.ConversionPattern=%d %r [%t] %-5p %c - %m%n

    ##################################
    # log1 is set to be a file by date

    log4j.appender.log1=org.apache.log4j.DailyRollingFileAppender
    rollover each day at midnight, see DailyRollingFileAppender object
    log4j.appender.log1.DatePattern='.'yyyy-MM- dd
    by size
    #log4j.appender.log1=org.apache.log4j.RollingFileAppender
    #log4j.appender.log1.MaxFileSize=100KB
    #log4j.appender.log1.MaxBackupIndex=1


    #/WEB-INF/conf/Log4j.properties
    log4j.appender.log1.File=c://VirtualTransport.log
    log4j.appender.log1.append = true
    log4j.appender.log1.layout=org.apache.log4j.PatternLayout
    see http://jakarta.apache.org/log4j/docs/api/org/apache/log4j/PatternLayout.html
    #-4r [%t] %-5p %c %x - %m%n lead to 331 [main] ERROR com.waltercedric.account - classCastexception-->

    log4j.appender.log1.layout.ConversionPattern=%p %t %c - %m%n

    ############################
    # eMail logging
    #
    # SMTPAppender will store all the logging events on an
    # internal cache and it will send all the messages when
    # the TriggeringEventEvaluator you set with the
    # setEvaluatorMethod or the constructor parameter return true.
    # By default the evaluator is set with an instance of
    # DefaultEvaluator wich is a package-private class
    # defined in the same compilation unit of SMTPAppender.
    # This evaluator will return true only when the logging
    # event has a priority greater or equal than ERROR.
    ##

    log4j.appender.email=org.apache.log4j.net.SMTPAppender
    log4j.appender.email.Threshold=FATAL
    log4j.appender.email.SMTPHost=XXX.XXX.XXX.XXX
    log4j.appender.email.To=This email address is being protected from spambots. You need JavaScript enabled to view it.
    log4j.appender.email.From=This email address is being protected from spambots. You need JavaScript enabled to view it.
    log4j.appender.email.Subject=A Fatal error has occured in your application
    log4j.appender.email.BufferSize=1
    log4j.appender.email.layout=org.apache.log4j.PatternLayout
    see http://jakarta.apache.org/log4j/docs/api/org/apache/log4j/PatternLayout.html
    log4j.appender.email.ConversionPattern=%d{ABSOLUTE} (%F:%L) - %m%n

    ############################
    # remote socket server logging
    #
    # The SocketAppender has the following properties:
    # please read: http://jakarta.apache.org/log4j/docs/api/org/apache/log4j/net/SocketAppender.html
    #
    # If you want to have a server that listen, you can start the following utilities Chainsaw
    # (swing gui) read how at http://jakarta.apache.org/log4j/docs/api/org/apache/log4j/chainsaw/package-summary.html
    # Chainsaw is a particular server!
    ##

    log4j.appender.CHAINSAW_CLIENT=org.apache.log4j.net.SocketAppender
    log4j.appender.CHAINSAW_CLIENT.RemoteHost=localhost
    log4j.appender.CHAINSAW_CLIENT.Port=5000
    log4j.appender.CHAINSAW_CLIENT.LocationInfo=true

    Resources

  • Introduction

    I am presenting here some tips which may help You to correct bugs in programs or applications faster, If you have comments or want to submit new ideas, feel free to do it here
    Being good in the process of solving bugs is more or less a habit:

    • You must discover the right informations (most if the time coming from logs file),
    • Know a little bit the system and how components are interacting each other (software architecture),
    • Use some rules and decide what to do (actions).

    This document is all about theses points...and is targeted for java web applications.

    Process

    1. Discovering a bug. Depending on the type of person who report bugs: You, end users, a pool of professional tester, your developer collegues. You will have a different amount of informations and instructions to reproduce it. For a user, assertions like: "The system is not working, the system is slow" is common but it does not contains any real informations, except the fact that something is not working. Most of the time, a persons is responsibble to collect all user&39;s complains, be careful since this person may filter the only useful informations as well. In this phase, you need to collect as many informations as possible.
    2. Use a bug tracking tool, to keep a track of the bug, to have the name of persons and a description how to reproduce it (a web frontend tool like Mantis or Bugzilla is a good start). As a rule: Explain a bug, is the first step for avoiding it! Be descriptive when you assign a ticket in a tracking tool. If you still think You do not need such a tool, the quality of your application, cost controlling and distribution of tasks among developers before shipment will be disastrous,.
    3. Define priorities based on bug severity and assign to a developer (I will suppose it&39;s You :-)). All bug tracking let You define your own subset of priorities.
    4. Define Categories: is it a graphical user interface (GUI), backend, input control problem? All bug tracking let You define your own subset of categories.

      Example of Error Severity Definitions
      taken from Mantis

      Severity
      level

      Definition

      Description

      Consequences

      1Critical
      Error
      Productive operation is not possible.


      Example:
      - Crash,

      The system cannot be launched.
      1Functional ErrorPrevents the usage of the system

      .
      Examples:
      - A needed function is interrupted,
      - Loss of data, corruption of data
      - Usage of the system is hampered in a way that wrong results are created for critical data.
      - Performance or acceptance.o users

      The system cannot be launched.
      2Median ErrorThe productive usage of the system is possible with some interference (a "workaround" can be established)

      Example:
      - Deactivate some functions which are not working properly
      - A Hack in done in code which prevent the bug.
      A "workaround" will be implemented for a short time until the problem is properly fixed.
      3Minor ErrorT he system can be used and errors are imperceptible.
      The bug has to be enter in the bug tracking tool.Priority has to be assigned
      4Change RequestNice to have, improvments

      Example:
      - GUI is not perfect, colors has to be changed, font size, layout
      - Error in Titles, subtitles and blocs of text

      The bug has to be enter in the bug tracking tool.Priority has to be assigned. Usually these bugs are solved if the efforts is small or if developer has some spare time.
    5. Try to reproduce this bug in your development environment, whih is in best case not so much different from production environment. Of course You do not have the same processor or memory or disk but the same software components (database, jvm, classpath, structure of data))
    6. Correct the bug by changing code/avoiding exception case, rewriting algorithm, changing architecture, finding a workaround (hack), adapt functionnalities if it is possible.
    7. In an ideal world:
      1. Write JUNIT testcase(s) to avoid further existence of the same issue. This will greatly improve quality of code!
      2. Document the bugs, correction, and in worst case: a workaround in a central place: a FAQ (Frequently Asked Questions) for developer

    Bug life cycle

    from Mantis

     

     

    Loging, logs files

    • Logs file are the oldest way to degug or monitor an application and it&39;s probably the slowest way to debug or locate bugs. Most of the time, you need to reproduce the error in the system, and that can take a lot of time especially if the application has a very complicated workflow. A workflow: dialog and navigation through the application, ex: select a customer, view all account, do a transfer between 2 account This can be the execution of a use-case or a chain of use-cases.
    • It is a common Fact: Without informations, nobody can debug a process and this even with a lot of chance.
    • Worst case: developper use System.err and System.out for everything, they write "bullshit" in log output ("This is value of i= 2"). Developer do not use the same convention: "Exception : oups" or "@EXCEPTION: ioexception". You must force them to use a logging framework and teach them what to write and level of severity.
    • Best case: Your applications is already using a logging framework like Log4j.
      Log4j let You reduce the amount of logs to a special part of your application or keep track of unusual case in a elegant mannner.
      • The amount of logs (Level),
      • The location (file or TCP server, mail or...),
      • The domains in the system (packages, or components, or arbitrary part),
      • The layout is standard because the developer can not influence the apparence, you can add relevant information like thread name, time, date

      All these things can be changed without restarting your application and are controlled by a configuration file (.xml or .properties)!

    • Why logs are sometimes better? because during debugging You may change variables values in realtime to let the bug happen. This is why debugging session are called transient: the know how You bring during these sessions (where you set breakpoints, the iterations You do in code, how you manipulate variables/instances on the fly) is simply lost or not share with your collegue. In this case logging output is better because it may stay even after correcting the bug. This can be useful to avoid further existence of the same bug.
    • Some mistakes:
      • Do not log too much mainly because of performance issues or try to use a preprocessor which remove logging statements before deploying to production...
      • Do not write stupid data during logging, e.g. "this is the value of i" or "iteration i", in this case use the debuger. for the same reasons avoid writing a 100Kb XML, it is useless, write the XML in a file...
      • Do not rely on logging to rescue You from bad code: instead of losing correcting a bad code, why not try refactor it!
    • Log amount can be enormous, especially when you track a bug at the same time with 4000 users working in production on many server (webserver, application server, servlet runner, database cluster).... this is why You "must":
      • Use Unix or install cygwin (if your running under windows) only for having some command like grep, sed, tail, awk, ssh
      • Learn regular expression, to filter the logs file with command like grep, sed, awk
      • Watch logs files in realtime (when users or you are testing your application). Prefer the unix tail command because it is very efficient. You can even combine the tail with a grep command to filter logs output.tail -f Tomcat.out | grep &39;error&39;
      • If You really can not work with a command line, use Jedit which also support regular expression and will probaly have a tail pulgin.

    Silent exceptions

    The worst case in production is what I call "silent exception", these affects some users but not all. They are silent because the users can still use the application but can have some really bad effects afterwards. Example: During a save, your program encounter a problem, but do not rollback the transaction (due to a bad design or implementation) and save an imcomplete state on disk or in the database. In fact, You must really not let them occur, do something before users even remark the problem (It took always 2-3 days before a pool of end-users got crazy about a problem in general, this time is comming from communication channel).

    How to avoid silent exceptions:

    • Define job (can be unix crontab) that parse log files daily or weekly with regular expression, and send a report. With log4j you can for example decide to send an email if a certain error level is thrown (level FATAL fro example)
    • Explain to developer (with a training) differences between logging level, what is fatal, error, warning, what meaningful info they must add in their logging statements. Review their code by checking usage of logging levels, or reading logs when Your application is in DEBUG mode.
    • If you need more error level (better granularity, most of the times it is not a good idea), You may want to define your own level. (and that&39;s easy with log4j)

    Debugger and remote debugging

    The Java Virtual Machine has an interface which allow to remotely debug an application

    Running your application remotely

    The code is running in the developer environment but not in production...one more time there is a difference somewhere, finding it may not be easy...

    • If you are running your application on remote server, are You sure that you deploy the latest code version? this is very easy to test:
      • You can for example run a Unix scripts which compare class CRC or
      • Use beyond compare, a graphical tools to compare directories and contents even through FTP.
      • If You know the class name and package where the exception occurred (look at the stacktrace in log files), use a decompiler like JAD to verify if the latest code is there (follow the rule 1 : "never trust anyone" even You sometimes ;-) )
    • Suspect the classloader:
      • You may have different version of the same class in the classpath = bad deployment
      • The classloader do not respect the servlet guidelines (the servlet runner Resin has some problems for example)
      • Order of jar in classpath, You can have dfferent parser version in different jar files for example.
        In all cases above try:
        • to start the JVM in verbose mode, to see which classes is load a which moment.
        • Use the utility JWhich, inform You where the class was loaded (jar or directory)

    Process throw an Exception of Type X

    • If the process throw an exception and You know the exceptions class created. Use your IDE! all of them have the ability to trigger a breakpoint on that type. The debugger will then stop where the exception is thrown.

    Mistakes

    • Do not made a runtime patch (= identifying condition of exception and testing it through IF statements to avoid it), but instead try to find the real reason (design, init phase...) and operate before it occurs, maybe you will need to change your algorithm.
    • Do not correct bug or listen to people which assign too many critical errors, if You can proove that it only affect 0.1% of users in production. Definition of bugs priority is essential as ressources are always limited.

    Automate gathering of informations

    If the system crash, or run in troubles, try to create a journal written on the disk, it can contains

    Example of journal
    - Date: 13.02.2004
    - Application name:
    - Cause: application.io.database.CanNotOpenDB
    - Stacktrace:

    - memory state
    - user name to contact, useful in order to reproduce the bug
    - Meaningful state of the application like
    * http user session
    * main data structure: previous action done,

    Advantages:

    • You can look periodically to see if some error appear often enough to be corrected
    • You have some information on the state of the application, if youre design is good enough You can even imagine using/loading this state to put the application in the same status.

    Hotline or developer asking for support

    Capitalize problems and resolutions in a central place!

    • Use FAQ (Frequently Asked Questions) Maybe the error has been already described and a solution found. You may create a lot of FAQs, for developer, manager, hotline. You can not save informations in 1 FAQs for all audience as you may need to adapt responses to the audience.
    • Use the Bugs Tracking tool and search if this bug has exist in the past.
      Example: A new bug has been discover, search in the database, if it has already exist, (bug status closed) then it has to be reopened otherwise you can create a new one.
    • Do not listen to a developer on telephone when He ask for support, or need help and never trust totally what he says (depend on the person of course)! Always ask for the logs files, because most of the time, they tell the truth and based on my experience, nobody really read them!

    No code is perfect, accept it

    • Code is living! and like any living creature it is evolving (both in the good and bad way) Development time will or may improve some parts,
    • Never trust a process ! Before judging that is your process who made the fault, please verify the previous process. (It let you think that you are one of the best programmer 3 minutes more ;-) Sometimes it can be a consecutive error, so only look at the first exception on top of the list.
    • Bug in Apache frameworks or open source projects, of course their code is perfectible, people from Apache try to deliver highly reusable code, but they can not guaranty you that in some particular case it will always work. Remember that some database, OS are existing since 20 years and are constantly improved. So if you find a bug and find an elegant way to handle it, you can send them the corrected code with a short explanation. Do not forget that they do not have your particular application environment, and that they may need to reproduce all conditions before providing a correction to the community (and that&39;s very time consuming).

    Links, references

    Log4j

    Junit
    "Developers write code. Unfortunately, developers also write defects, most of which are injected during the initial coding phase. The cheapest place to fix these defects is, likewise, during the initial phases of development. If you wait until function or system testing to catch and fix defects, your software development costs will be much higher. In this article , authors Scott Will, Ted Rivera, and Adam Tate discuss some basic "defensive" coding and unit testing practices to make it easier for developers to find defects -- and, more importantly, help to prevent them in the first place."
    http://www-106.ibm.com/developerworks/java/library/j-arrive/?ca=dgr-jw17j-arrive

    Cygwin