[slf4j-dev] svn commit: r1283 - in slf4j/trunk: slf4j-ext/src/main/java/org/slf4j/ext slf4j-site/src/site/pages

rgoers at slf4j.org rgoers at slf4j.org
Fri Feb 27 00:18:59 CET 2009


Author: rgoers
Date: Fri Feb 27 00:18:58 2009
New Revision: 1283

Modified:
   slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/ext/EventData.java
   slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/ext/EventException.java
   slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/ext/EventLogger.java
   slf4j/trunk/slf4j-site/src/site/pages/extensions.html

Log:
Fix style and add documentation

Modified: slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/ext/EventData.java
==============================================================================
--- slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/ext/EventData.java	(original)
+++ slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/ext/EventData.java	Fri Feb 27 00:18:58 2009
@@ -18,176 +18,229 @@
  *
  * @author Ralph Goers
  */
-public class EventData implements Serializable
-{
-    private Map<String, Object> eventData = new HashMap<String,Object>();
-    public static final String EVENT_MESSAGE = "EventMessage";
-    public static final String EVENT_TYPE = "EventType";
-    public static final String EVENT_DATETIME = "EventDateTime";
-    public static final String EVENT_ID = "EventId";
-
-    /**
-     * Default Constructor
-     */
-    public EventData()
-    {
-    }
-
-    /**
-     * Constructor to create event data from a Map.
-     * @param map The event data.
-     */
-    public EventData(Map<String, Object> map)
-    {
-        eventData.putAll(map);
-    }
-
-    /**
-     * Construct from a serialized form of the Map containing the RequestInfo elements
-     * @param xml The serialized form of the RequestInfo Map.
-     */
-    public EventData(String xml)
-    {
-        ByteArrayInputStream bais = new ByteArrayInputStream(xml.getBytes());
-        try
-        {
-            XMLDecoder decoder = new XMLDecoder(bais);
-            this.eventData = (Map<String, Object>)decoder.readObject();
+public class EventData implements Serializable {
+  private Map<String, Object> eventData = new HashMap<String, Object>();
+  public static final String EVENT_MESSAGE = "EventMessage";
+  public static final String EVENT_TYPE = "EventType";
+  public static final String EVENT_DATETIME = "EventDateTime";
+  public static final String EVENT_ID = "EventId";
+
+  /**
+   * Default Constructor
+   */
+  public EventData() {
+  }
+
+  /**
+   * Constructor to create event data from a Map.
+   *
+   * @param map The event data.
+   */
+  public EventData(Map<String, Object> map) {
+    eventData.putAll(map);
+  }
+
+  /**
+   * Construct from a serialized form of the Map containing the RequestInfo elements
+   *
+   * @param xml The serialized form of the RequestInfo Map.
+   */
+  public EventData(String xml) {
+    ByteArrayInputStream bais = new ByteArrayInputStream(xml.getBytes());
+    try {
+      XMLDecoder decoder = new XMLDecoder(bais);
+      this.eventData = (Map<String, Object>) decoder.readObject();
+    }
+    catch (Exception e) {
+      throw new EventException("Error decoding " + xml, e);
+    }
+  }
+
+  /**
+   * Serialize all the EventData items into an XML representation.
+   *
+   * @return an XML String containing all the EventDAta items.
+   */
+  public String toXML() {
+    return toXML(eventData);
+  }
+
+  /**
+   * Serialize all the EventData items into an XML representation.
+   *
+   * @return an XML String containing all the EventDAta items.
+   */
+  public static String toXML(Map<String, Object> map) {
+    ByteArrayOutputStream baos = new ByteArrayOutputStream();
+    try {
+      XMLEncoder encoder = new XMLEncoder(baos);
+      encoder.setExceptionListener(new ExceptionListener() {
+        public void exceptionThrown(Exception exception) {
+          exception.printStackTrace();
         }
-        catch (Exception e)
-        {
-            throw new EventException("Error decoding " + xml, e);
-        }
-    }
-    
-    /**
-     * Serialize all the EventData items into an XML representation.
-     * @return an XML String containing all the EventDAta items.
-     */
-    public String toXML()
-    {
-        return toXML(eventData);
-    }
-
-    /**
-     * Serialize all the EventData items into an XML representation.
-     * @return an XML String containing all the EventDAta items.
-     */
-    public static String toXML(Map<String, Object>map)
-    {
-        ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        try
-        {
-            XMLEncoder encoder = new XMLEncoder(baos);
-            encoder.setExceptionListener(new ExceptionListener()
-            {
-                public void exceptionThrown(Exception exception)
-                {
-                    exception.printStackTrace();
-                }
-            });
-            encoder.writeObject(map);
-            encoder.close();
-            return baos.toString();
-        }
-        catch (Exception e)
-        {
-            e.printStackTrace();
-            return null;
-        }
-    }
-
-    public String getEventId()
-    {
-        return (String)this.eventData.get(EVENT_ID);
-    }
-
-    public void setEventId(String eventId)
-    {
-        if (eventId == null)
-        {
-            throw new IllegalArgumentException("eventId cannot be null");
-        }
-        this.eventData.put(EVENT_ID, eventId);
-    }
-
-    public String getMessage()
-    {
-        return (String)this.eventData.get(EVENT_MESSAGE);
-    }
-
-    public void setMessage(String message)
-    {
-        this.eventData.put(EVENT_MESSAGE, message);
-    }
-
-    public Date getEventDateTime()
-    {
-        return (Date)this.eventData.get(EVENT_DATETIME);
-    }
-
-    public void setEventDateTime(Date eventDateTime)
-    {
-        this.eventData.put(EVENT_DATETIME, eventDateTime);
-    }
-
-    public void setEventType(String eventType)
-    {
-        this.eventData.put(EVENT_TYPE, eventType);
-    }
-
-    public String getEventType()
-    {
-        return (String)this.eventData.get(EVENT_TYPE);
-    }
-
-
-    public void put(String name, Serializable obj)
-    {
-        this.eventData.put(name, obj);
-    }
-
-    public Serializable get(String name)
-    {
-        return (Serializable) this.eventData.get(name);
-    }
-
-    public void putAll(Map data)
-    {
-        this.eventData.putAll(data);
-    }
-
-    public int getSize()
-    {
-        return this.eventData.size();
-    }
-
-    public Iterator getEntrySetIterator()
-    {
-        return this.eventData.entrySet().iterator();
-    }
-
-    public Map getEventMap()
-    {
-        return this.eventData;
-    }
-
-    public String toString()
-    {
-        return toXML();
-    }
-
-    public boolean equals(Object o)
-    {
-        if (this == o) return true;
-        if (!(o instanceof EventData || o instanceof Map)) return false;
-        Map<String, Object>map = (o instanceof EventData) ? ((EventData)o).getEventMap() : (Map<String, Object>)o;
-
-        return this.eventData.equals(map);
-    }
-
-    public int hashCode()
-    {
-        return this.eventData.hashCode();
-    }
+      });
+      encoder.writeObject(map);
+      encoder.close();
+      return baos.toString();
+    }
+    catch (Exception e) {
+      e.printStackTrace();
+      return null;
+    }
+  }
+
+  /**
+   * Retrieve the event identifier.
+   * @return The event identifier
+   */
+  public String getEventId() {
+    return (String) this.eventData.get(EVENT_ID);
+  }
+
+  /**
+   * Set the event identifier.
+   * @param eventId The event identifier.
+   */
+  public void setEventId(String eventId) {
+    if (eventId == null) {
+      throw new IllegalArgumentException("eventId cannot be null");
+    }
+    this.eventData.put(EVENT_ID, eventId);
+  }
+
+  /**
+   * Retrieve the message text associated with this event, if any.
+   * @return The message text associated with this event or null if there is none.
+   */
+  public String getMessage() {
+    return (String) this.eventData.get(EVENT_MESSAGE);
+  }
+
+  /**
+   * Set the message text associated with this event.
+   * @param message The message text.
+   */
+  public void setMessage(String message) {
+    this.eventData.put(EVENT_MESSAGE, message);
+  }
+
+  /**
+   * Retrieve the date and time the event occurred.
+   * @return The Date associated with the event.
+   */
+  public Date getEventDateTime() {
+    return (Date) this.eventData.get(EVENT_DATETIME);
+  }
+
+  /**
+   * Set the date and time the event occurred in case it is not the same as when
+   * the event was logged.
+   * @param eventDateTime The event Date.
+   */
+  public void setEventDateTime(Date eventDateTime) {
+    this.eventData.put(EVENT_DATETIME, eventDateTime);
+  }
+
+  /**
+   * Set the type of event that occurred.
+   * @param eventType The type of the event.
+   */
+  public void setEventType(String eventType) {
+    this.eventData.put(EVENT_TYPE, eventType);
+  }
+
+  /**
+   * Retrieve the type of the event.
+   * @return The event type.
+   */
+  public String getEventType() {
+    return (String) this.eventData.get(EVENT_TYPE);
+  }
+
+  /**
+   * Add arbitrary attributes about the event.
+   * @param name The attribute's key.
+   * @param obj The data associated with the key.
+   */
+  public void put(String name, Serializable obj) {
+    this.eventData.put(name, obj);
+  }
+
+  /**
+   * Retrieve an event attribute.
+   * @param name The attribute's key.
+   * @return The value associated with the key or null if the key is not present.
+   */
+  public Serializable get(String name) {
+    return (Serializable) this.eventData.get(name);
+  }
+
+  /**
+   * Populate the event data from a Map.
+   * @param data The Map to copy.
+   */
+  public void putAll(Map data) {
+    this.eventData.putAll(data);
+  }
+
+  /**
+   * Returns the number of attributes in the EventData.
+   * @return the number of attributes in the EventData.
+   */
+  public int getSize() {
+    return this.eventData.size();
+  }
+
+  /**
+   * Returns an Iterator over all the entries in the EventDAta.
+   * @return an Iterator that can be used to access all the event attributes.
+   */
+  public Iterator getEntrySetIterator() {
+    return this.eventData.entrySet().iterator();
+  }
+
+  /**
+   * Retrieve all the attributes in the EventData as a Map. Changes to this map will be
+   * reflected in the EventData.
+   * @return The Map of attributes in this EventData instance.
+   */
+  public Map getEventMap() {
+    return this.eventData;
+  }
+
+  /**
+   * Convert the EventData to a String.
+   * @return The EventData as a String.
+   */
+  @Override
+  public String toString() {
+    return toXML();
+  }
+
+  /**
+   * Compare two EventData objects for equality.
+   * @param o The Object to compare.
+   * @return true if the objects are the same instance or contain all the same keys and their values.
+   */
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (!(o instanceof EventData || o instanceof Map)) {
+      return false;
+    }
+    Map<String, Object> map = (o instanceof EventData) ? ((EventData) o).getEventMap() : (Map<String, Object>) o;
+
+    return this.eventData.equals(map);
+  }
+
+  /**
+   * Compute the hashCode for this EventData instance.
+   * @return The hashcode for this EventData instance.
+   */
+  @Override
+  public int hashCode() {
+    return this.eventData.hashCode();
+  }
 }
\ No newline at end of file

Modified: slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/ext/EventException.java
==============================================================================
--- slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/ext/EventException.java	(original)
+++ slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/ext/EventException.java	Fri Feb 27 00:18:58 2009
@@ -1,27 +1,39 @@
 package org.slf4j.ext;
 
 /**
- * 
+ * Exception used to identify issues related to an event that is being logged.
  */
-public class EventException extends RuntimeException
-{
-    public EventException()
-    {
-        super();
-    }
+public class EventException extends RuntimeException {
+  /**
+   * Default constructor.
+   */
+  public EventException() {
+    super();
+  }
 
-    public EventException(String exceptionMessage)
-    {
-        super(exceptionMessage);
-    }
+  /**
+   * Constructor that allows an exception message.
+   * @param exceptionMessage The exception message.
+   */
+  public EventException(String exceptionMessage) {
+    super(exceptionMessage);
+  }
 
-    public EventException(Throwable originalException)
-    {
-        super(originalException);
-    }
+  /**
+   * Constructor that chains another Exception or Error.
+   * @param originalException The original exception.
+   */
+  public EventException(Throwable originalException) {
+    super(originalException);
+  }
 
-    public EventException(String exceptionMessage, Throwable originalException)
-    {
-        super(exceptionMessage, originalException);
-    }
+  /**
+   * Constructor that chains another Exception or Error and also allows a message
+   * to be specified.
+   * @param exceptionMessage The exception message.
+   * @param originalException The original excepton.
+   */
+  public EventException(String exceptionMessage, Throwable originalException) {
+    super(exceptionMessage, originalException);
+  }
 }

Modified: slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/ext/EventLogger.java
==============================================================================
--- slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/ext/EventLogger.java	(original)
+++ slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/ext/EventLogger.java	Fri Feb 27 00:18:58 2009
@@ -5,6 +5,8 @@
 import org.slf4j.MarkerFactory;
 import org.slf4j.spi.LocationAwareLogger;
 
+import java.util.Map;
+
 /**
  * Simple Logger used to log events. All events are directed to a logger named "EventLogger"
  * with a level of ERROR (the closest to "always" that SLF4J gets) and with an Event marker.
@@ -13,32 +15,30 @@
  */
 public class EventLogger {
 
-    private static final String FQCN = EventLogger.class.getName();
-
-    static Marker EVENT_MARKER = MarkerFactory.getMarker("EVENT");
-
-    private static LoggerWrapper eventLogger =
-      eventLogger = new LoggerWrapper(LoggerFactory.getLogger("EventLogger"), FQCN);
+  private static final String FQCN = EventLogger.class.getName();
 
+  static Marker EVENT_MARKER = MarkerFactory.getMarker("EVENT");
 
+  private static LoggerWrapper eventLogger =
+      new LoggerWrapper(LoggerFactory.getLogger("EventLogger"), FQCN);
 
-    /**
-     * There can only be a single EventLogger.
-     */
-    private EventLogger() {
-    }
-
-    /**
-     * Logs the event.
-     * @param data The EventData.
-     */
-    public static void logEvent(EventData data)
-    {
-      if (eventLogger.instanceofLAL) {
-        ((LocationAwareLogger) eventLogger.logger).log(EVENT_MARKER, FQCN,
+  /**
+   * There can only be a single EventLogger.
+   */
+  private EventLogger() {
+  }
+
+  /**
+   * Logs the event.
+   *
+   * @param data The EventData.
+   */
+  public static void logEvent(EventData data) {
+    if (eventLogger.instanceofLAL) {
+      ((LocationAwareLogger) eventLogger.logger).log(EVENT_MARKER, FQCN,
           LocationAwareLogger.ERROR_INT, data.toXML(), null);
-      } else {
-        eventLogger.logger.error(EVENT_MARKER, data.toXML(), data);
-      }
+    } else {
+      eventLogger.logger.error(EVENT_MARKER, data.toXML(), data);
     }
+  }
 }

Modified: slf4j/trunk/slf4j-site/src/site/pages/extensions.html
==============================================================================
--- slf4j/trunk/slf4j-site/src/site/pages/extensions.html	(original)
+++ slf4j/trunk/slf4j-site/src/site/pages/extensions.html	Fri Feb 27 00:18:58 2009
@@ -26,6 +26,7 @@
     <ul>
       <li><a href="#profiler">Profiler</a></li>
       <li><a href="#extended_logger">Extended logger</a></li>
+      <li><a href="#event_logger">Event Logging</a></li>
       <li><a href="#javaagent">Logging added with Java agent (requires Java 5)</a></li>
     </ul>
 
@@ -579,6 +580,149 @@
   at org.apache.maven.surefire.booter.SurefireBooter.runSuitesInProcess(SurefireBooter.java:338)
   at org.apache.maven.surefire.booter.SurefireBooter.main(SurefireBooter.java:997)    </p>
 
+  <!-- .............................................................. -->
+
+  <h2><a name="event_logger"></a>Event Logging</h2>
+
+  <p>The EventLogger class provides a simple mechansim for logging events that occur in an application.
+  While the EventLogger is useful as a way of initiating events that should be processed by an audit
+  Logging system, it does not implement any of the features an audit logging system would require
+  such as guaranteed delivery.</p>
+
+  <p>The recommended way of using the EventLogger in a typcial web application is to populate
+  the SLF4J MDC with data that is related to the entire lifespan of the request such as the user's id,
+  the user's ip address, the product name, etc. This can easily be done in a servlet fileter where
+  the MDC can also be cleared at the end of the request. When an event that needs to be recorded
+  occurs an EventData object should be created and populated. Then call EventLogger.logEvent(data)
+  where data is a reference to the EventData object.</p>
+
+  <p class="source">import org.slf4j.MDC;
+import org.apache.commons.lang.time.DateUtils;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.FilterChain;
+import javax.servlet.http.HttpSession;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.TimeZone;
+
+public class RequestFilter implements Filter
+{
+  private FilterConfig filterConfig;
+  private static String TZ_NAME = "timezoneOffset";
+
+  public void init(FilterConfig filterConfig) throws ServletException {
+    this.filterConfig = filterConfig;
+  }
+
+  /**
+   * Sample filter that populates the MDC on every request.
+   */
+  public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
+                       FilterChain filterChain) throws IOException, ServletException {
+    HttpServletRequest request = (HttpServletRequest)servletRequest;
+    HttpServletResponse response = (HttpServletResponse)servletResponse;
+    MDC.put("ipAddress", request.getRemoteAddr());
+    HttpSession session = request.getSession(false);
+    TimeZone timeZone = null;
+    if (session != null) {
+      // Something should set this after authentication completes
+      String loginId = (String)session.getAttribute("LoginId");
+      if (loginId != null) {
+        MDC.put("loginId", loginId);
+      }
+      // This assumes there is some javascript on the user's page to create the cookie.
+      if (session.getAttribute(TZ_NAME) == null) {
+        if (request.getCookies() != null) {
+          for (Cookie cookie : request.getCookies()) {
+            if (TZ_NAME.equals(cookie.getName())) {
+              int tzOffsetMinutes = Integer.parseInt(cookie.getValue());
+              timeZone = TimeZone.getTimeZone("GMT");
+              timeZone.setRawOffset((int)(tzOffsetMinutes * DateUtils.MILLIS_PER_MINUTE));
+              request.getSession().setAttribute(TZ_NAME, tzOffsetMinutes);
+              cookie.setMaxAge(0);
+              response.addCookie(cookie);
+            }
+          }
+        }
+      }
+    }
+    MDC.put("hostname", servletRequest.getServerName());
+    MDC.put("productName", filterConfig.getInitParameter("ProductName"));
+    MDC.put("locale", servletRequest.getLocale().getDisplayName());
+    if (timeZone == null) {
+      timeZone = TimeZone.getDefault();
+    }
+    MDC.put("timezone", timeZone.getDisplayName());
+    filterChain.doFilter(servletRequest, servletResponse);
+    MDC.clear();
+  }
+
+  public void destroy() {
+  }
+}
+  </p>
+  <p>Sample class that uses EventLogger.</p>
+  <p class="source">import org.slf4j.ext.EventData;
+import org.slf4j.ext.EventLogger;
+
+import java.util.Date;
+import java.util.UUID;
+
+public class MyApp {
+
+  public String doFundsTransfer(Account toAccount, Account fromAccount, long amount) {
+    toAccount.deposit(amount);
+    fromAccount.withdraw(amount);
+    EventData data = new EventData();
+    data.setEventDateTime(new Date());
+    data.setEventType("transfer");
+    String confirm = UUID.randomUUID().toString();
+    data.setEventId(confirm);
+    data.put("toAccount", toAccount);
+    data.put("fromAccount", fromAccount);
+    data.put("amount", amount);
+    EventLogger.logEvent(data);
+    return confirm;
+  }
+}
+  </p>
+  <p>The EventLogger class uses a Logger named "EventLogger". EventLogger uses a logging level
+  of ERROR since SLF4J has no level that represents "always on". The following shows a
+  configuraton using Logback.</p>
+  <p class="source">&lt;configuration&gt;
+  &lt;appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"&gt;
+    &lt;layout class="ch.qos.logback.classic.PatternLayout"&gt;
+      &lt;Pattern&gt;%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n&lt;/Pattern&gt;
+    &lt;/layout&gt;
+  &lt;/appender&gt;
+
+  &lt;appender name="events" class="ch.qos.logback.core.ConsoleAppender"&gt;
+    &lt;layout class="ch.qos.logback.classic.PatternLayout"&gt;
+      &lt;Pattern&gt;%d{HH:mm:ss.SSS} %X - %msg%n&lt;/Pattern&gt;
+    &lt;/layout&gt;
+  &lt;/appender&gt;
+
+  &lt;logger name="EventLogger" additivity="false"&gt;
+    &lt;level value="INFO"/&gt;
+    &lt;appender appender-ref="events"/&gt;
+  &lt;/logger&gt;
+
+  &lt;root level="DEBUG"&gt;
+    &lt;appender-ref ref="STDOUT" /&gt;
+  &lt;/root&gt;
+
+&lt;/configuration&gt;
+  </p>
+
+  <!-- .............................................................. -->
+
   <h2><a name="javaagent"></a>Adding logging with Java agent</h2>
 
   <p><b>NOTE:  BETA RELEASE, NOT PRODUCTION QUALITY</b>  </p>



More information about the slf4j-dev mailing list