How to use the Server Administration API to create a custom class to log server activity.
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.
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.
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:
javac -classpath d:\silverstream\lib\SilverServerAll.zip; d:\silverstream\lib\servlet.jar SimpleLogger.java
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); } } }
To use the previous example, we:
set AGCLASSPATH=c:\myclasses
myLogger.SimpleLogger