[ Team LiB ] Previous Section Next Section

Gathering Information with Logging APIs

In the previous section, we discussed the importance of unit testing in application development. Although building and maintain a good suite of unit tests is important for regression testing and quality assurance purposes, a successful run of the test suite cannot possibly be considered a proof that the full system will run flawlessly when deployed to its production environment and opened to its user community. Bugs and unexpected behaviors will always reveal themselves as unanticipated and untested input sequences begin to hit the system. So, when a user reports a bug in the system, what recourse does a programmer have to track down and fix that bug? It is often very helpful to "instrument" server-side code with the help of a logging API, which allows the system to print messages regarding the current state of the system to a log file, a database, or some other destination.

Programmers very often place System.out.println() statements within their code as they're developing it so that they can watch the system execute by simply looking at the standard out. Even though this practice is certainly helpful, it's also severely lacking in some of the more useful features that a logging API can provide. For example, when an application is deployed on a cluster of WebLogic servers, it's helpful to aggregate the logs from all the running servers into one place. It's also useful to assign a priority level to the messages to distinguish severe error messages from more routine informational status messages. WebLogic provides its own logging API, which is built on top of the standard java.util.logging package that is included with J2SE v1.4. The documentation for this package can be found at http://java.sun.com/j2se/1.4.2/docs/api.

WebLogic Logging Services

WebLogic has quite substantial logging capability. It has the capability to log messages on a per-server basis, as well as across an entire domain, which may encompass several physical machines. In addition, the Administration Console provides the capability to manage the log files by specifying maximum file sizes, file rotation schemes, and message filters. These logging mechanisms are used by WebLogic internally to report various system events, but can also be used by application developers through the WebLogic Logging Services. More information about WebLogic Logging Services is available at http://e-docs.bea.com/wls/docs81/logging/index.html.

The most straightforward way to use the WebLogic Logging Services within an application is through the weblogic.logging.NonCatalogLogger class. The class has a constructor that takes a String argument, which is the name that shows up in the log file to identify the particular logger. It also defines the following methods:

  • emergency(String msg)

  • emergency(String msg, Throwable t)

  • alert(String msg)

  • alert(String msg, Throwable t)

  • critical(String msg)

  • critical(String msg, Throwable t)

  • error(String msg)

  • error(String msg, Throwable t)

  • warning(String msg)

  • warning(String msg, Throwable t)

  • info(String msg)

  • info(String msg, Throwable t)

  • debug(String msg)

  • debug(String msg, Throwable t)

Each of these methods writes the given message to the log file and marks it with the priority given by the method name. Emergency messages are more severe than alerts, and so on. For the methods that take an additional Throwable argument, the stack trace of the Throwable is sent to the log file as well.

Listing 24.5 shows a simple servlet class that illustrates the use of the NonCatalogLogger.

Listing 24.5 Servlet with Logging (LogServlet.java)
package wls8unleashed.testing;
import weblogic.logging.NonCatalogLogger;
import java.io.PrintWriter;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class LogServlet extends HttpServlet {
  public void service(HttpServletRequest request,
            HttpServletResponse response)
      throws ServletException, IOException {
    NonCatalogLogger log = new NonCatalogLogger("Logging Demo Servlet");
    log.info("In service() method");
    try {
      PrintWriter out = response.getWriter();
      out.println("This is the Logging Demo Servlet");
    }
    catch (Exception e) {
      log.error("An exception occurred in service()", e);
    }
  }
}

In this example, the NonCatalogLogger is created with the name Logging Demo Servlet. It sends a message of priority info to the log file. If an exception is caught, the servlet sends a message, along with the stack track, as an error. After running this servlet, the log file looks like this:



###<Jul 21, 2003 11:44:21 AM EDT> <Info> <Logging Demo Servlet> <localhost> <testServer>
graphics/ccc.gif <ExecuteThread: '10' for queue: 'default'> <WLS Kernel> <> <000000> <In service() method>

CAUTION

Be extra certain that logging messages themselves do not cause any errors. All too often, mistakes are made like the following:


log.info("Person's name is " + person.getName());

If the system is designed in such a way that the person object could possibly be null, a NullPointerException can be thrown trying to log the message. In general, log messages should have the minimal possible effect on the system.


    [ Team LiB ] Previous Section Next Section