Application Techniques



Customizing the Logging Class

How to use the Server Administration API to create a custom class to log server activity.

About this technique

Details

Category

Administration Techniques

Description

You'll learn about:

Related reading

See the chapter on using the Server Administration API in the Administrator's Guide

You can have the server log HTTP requests, errors, and trace information (see the section on server logging in the Administrator's Guide).

By default, SilverStream uses its own internal class to do the logging. If you want to customize the log output--for example, to specify an extended log file format--you can write your own class, then specify it to SilverStream.

Creating a custom logging class   Top of page

To enable customized logging, SilverStream provides the com.sssw.srv.api.AgiLogger interface. The Server calls methods in AgiLogger to initialize the logger class; log HTTP requests, errors, and trace events; and shut the logger down.

Your customized logging class must implement the AgiLogger interface.

    For more information about the interface and its methods, see AgiLogger in the SilverStream API documentation.

To customize logging:

  1. Write your custom logging class that implements AgiLogger. The class must:

  2. Make sure the .class file is on the AGCLASSPATH.

  3. Tell SilverStream to use the custom logging class by doing one of the following:

  4. Set the types of logging you want in the SMC (HTTP, Error, and/or Trace).

  5. Specify the names of the files to log the output to.

  6. Restart the server.

    SilverStream uses your custom class to log the information.

Writing the custom class

The logging class you write is a class that lives outside of the SilverStream Server but uses SilverStream classes. Here are two ways you might write such a class:

An example   Top of page

Here is a custom logging class that logs information in the W3C compound log file format (like the W3C common log file format, except that it also logs the Referer and User-Agent headers from each HTTP request):

  //   Copyright (c) 1999, SilverStream Software, Inc. 
  //   All Rights Reserved 
  // 
   
  // This is a simple example extended logging class that implements 
  // the com.sssw.srv.api.AgiLogger interface.  It logs to files in 
  // the file system in the W3C "Compound Log File Format", creating 
  // a new log file each time. 
   
  package myLogger; 
   
  import java.util.*; 
  import java.io.*; 
   
  import com.sssw.shr.http.*; 
  import com.sssw.rt.util.AgoApplicationException; 
  import com.sssw.srv.api.*; 
   
  public class SimpleLogger implements AgiLogger 
  { 
     private AgiServer m_server = null; 
     private boolean m_logging = false; 
     private String m_logName = null; 
     private PrintWriter m_logWriter = null; 
     private boolean m_errlogging = false; 
     private String m_errlogName = null; 
     private PrintWriter m_errlogWriter = null; 
     private boolean m_tracelogging = false; 
     private String m_tracelogName = null; 
     private PrintWriter m_tracelogWriter = null; 
   
     /* Empty constructor */ 
     public SimpleLogger() 
     { 
     } 
   
     private static final String months[] = 
     { 
        "Jan", "Feb", "Mar", "Apr", "May", "Jun", 
        "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" 
     }; 
   
     /** 
      * Log normally a full handled request.  The request and reply 
      * are in the standard HttpServletRequest and HttpServletReply  
      * format.  The logger must not modify the request or reply. 
      */ 
     public void log(AgiHttpServletRequest request, AgiHttpServletResponse reply, 
                 int nbytes, long duration) 
     { 
        if (!m_logging) 
           return; 
   
        StringBuffer entry  = new StringBuffer(120); 
        Date now = null; 
        try { 
           now = new Date(reply.getDateHeader("Date")); 
        } catch (Exception ex) { 
           now = new Date(); 
        } 
        String user   = request.getRemoteUser(); 
   
        int d = now.getDate(); 
        int h = now.getHours(); 
        int m = now.getMinutes(); 
        int s = now.getSeconds(); 
        int z = now.getTimezoneOffset() / 60;// assume whole hour tz 
   
        entry.append(request.getRemoteAddr()); 
        entry.append(" - ");                     // user name 
        entry.append((user==null) ? "-" : user); // auth user name 
        entry.append((d<10) ? " [0" : " [");     // date 
        entry.append(d); 
        entry.append("/"); 
        entry.append(months[now.getMonth()]);    // month 
        entry.append("/"); 
        entry.append((now.getYear() + 1900));    // year 
        entry.append((h<10) ? ":0" : ":");       // hour 
        entry.append(h); 
        entry.append((m<10) ? ":0" : ":");       // minute 
        entry.append(m); 
        entry.append((s<10) ? ":0" : ":");       // second 
        entry.append(s); 
        entry.append((z<0) ? " " : " +");        // timezone 
        entry.append(z); 
        entry.append("]"); 
        entry.append(" \"");                     // request line 
        entry.append(request.getMethod()); 
        entry.append(" "); 
        entry.append(request.getRequestURI()); 
        entry.append(" "); 
        entry.append(request.getProtocol()); 
        entry.append("\" "); 
        entry.append(reply.getStatus());       // reply status 
        entry.append(" "); 
        entry.append(nbytes);                  // # of emitted bytes 
        entry.append(" \""); 
        entry.append(request.getHeader("Referer")); // Referer 
        entry.append("\" \""); 
        entry.append(request.getHeader("User-Agent")); // User Agent 
        entry.append("\""); 
   
        log(entry.toString()); 
     } 
   
     /** 
      * Log a message not associated with any particular session or 
      * request to the error log. 
      */ 
     public void log(String msg) 
     { 
        errlog(msg); 
     } 
   
     /** 
      * Log an error message on behalf of the specified session  
      * to an error log. 
      */ 
     public void errlog(AgiSession session, String msg) 
     { 
        errlog("Error on session " + session.getId() + ": " + msg); 
     } 
   
     /** 
      * Log an error message not associated with any  
      * particular session to the error log. 
      */ 
     public void errlog(String msg) 
     { 
        if (m_errlogging) 
           m_errlogWriter.println(msg); 
     } 
   
     /** 
      * Log a tracing message to the trace log. 
      */ 
     public void trace(AgiSession session, String msg) 
     { 
        trace("Trace from session " + session.getId() + ": " + msg); 
     } 
   
     /** 
      * Log a tracing message not associated with a particular 
      * session to the trace log 
      */ 
     public void trace(String msg) 
     { 
        if (m_tracelogging) 
           m_tracelogWriter.println(msg); 
     } 
   
     /** 
      * Initialize this logger for the specified server. 
      */ 
     public void initialize(AgiServer server) 
     { 
        m_server = server; 
     } 
   
     /** 
      * Shut down the logger, closing any resources it may hold. 
      */ 
     public void shutdown() 
     { 
        if (m_logWriter != null) { 
           m_logWriter.close(); 
           m_logWriter = null; 
           m_logging = false; 
        } 
        if (m_errlogWriter != null) { 
           m_errlogWriter.close(); 
           m_errlogWriter = null; 
           m_errlogging = false; 
        } 
        if (m_tracelogWriter != null) { 
           m_tracelogWriter.close(); 
           m_tracelogWriter = null; 
           m_tracelogging = false; 
        } 
     } 
   
     /** 
      * Enable or disable standard HTTP-level logging.  If disabled, 
      * the log() methods should not write anything to the log. 
      * The logFileName is a parameter passed to the logger (null 
      * if disabled). 
      */ 
     public void enableLogging(boolean doEnable, String logFileName) 
     { 
        try { 
           if (m_logWriter != null) { 
              m_logWriter.close(); 
              m_logWriter = null; 
           } 
           m_logging = doEnable; 
           m_logName = logFileName; 
           if (m_logging) { 
              m_logWriter = new PrintWriter(new FileWriter(m_logName), true); 
           } 
        } catch (IOException ex) { 
           m_logging = false; 
           throw new AgoApplicationException(ex, "Error opening " + logFileName); 
        } 
     } 
   
     /** 
      * Enable or disable error logging.  If disabled, 
      * the errlog() methods should not write anything to the log. 
      * The logFileName is a parameter passed to the logger (null 
      * if disabled). 
      */ 
     public void enableErrorLogging(boolean doEnable, String errorLogFileName) 
     { 
        try { 
           if (m_errlogWriter != null) { 
              m_errlogWriter.close(); 
              m_errlogWriter = null; 
           } 
           m_errlogging = doEnable; 
           m_errlogName = errorLogFileName; 
           if (m_errlogging) { 
              m_errlogWriter = new PrintWriter(new FileWriter(m_errlogName), true); 
           } 
        } catch (IOException ex) { 
           m_errlogging = false; 
           throw new AgoApplicationException(ex, "Error opening " + errorLogFileName); 
        } 
     } 
   
   
     /** 
      * Enable or disable trace logging.  If disabled, 
      * the trace() methods should not write anything to the log. 
      * The logFileName is a parameter passed to the logger (null 
      * if disabled). 
      */ 
     public void enableTraceLogging(boolean doEnable, String traceLogFileName) 
     { 
        try { 
           if (m_tracelogWriter != null) { 
              m_tracelogWriter.close(); 
              m_tracelogWriter = null; 
           } 
           m_tracelogging = doEnable; 
           m_tracelogName = traceLogFileName; 
           if (m_tracelogging) { 
              m_tracelogWriter = new PrintWriter(new FileWriter(m_tracelogName), true); 
           } 
        } catch (IOException ex) { 
           m_tracelogging = false; 
           throw new AgoApplicationException(ex, "Error opening " + traceLogFileName); 
        } 
     } 
   
  } 

Using the example   Top of page

To use the previous example, we:

  1. Compiled it and placed it in c:\myclasses\myLogger\SimpleLogger.class.

  2. Defined AGCLASSPATH as follows:

      set AGCLASSPATH=c:\myclasses 
    
  3. In the SMC General panel, selected User Defined under Server logging and specified the following class:

      myLogger.SimpleLogger 
    
  4. Specified the kinds of logging we wanted and what files to log the output to.

  5. Restarted the server.






Copyright © 2000, SilverStream Software, Inc. All rights reserved.