[logback-dev] svn commit: r625 - in logback/trunk: logback-access/src/main/java/ch/qos/logback/access/net logback-classic/src/main/java/ch/qos/logback/classic/helpers logback-classic/src/main/java/ch/qos/logback/classic/net logback-core/src/main/java/ch/qos/logback/core/helpers

noreply.seb at qos.ch noreply.seb at qos.ch
Thu Oct 5 10:44:41 CEST 2006


Author: seb
Date: Thu Oct  5 10:44:41 2006
New Revision: 625

Added:
   logback/trunk/logback-access/src/main/java/ch/qos/logback/access/net/
   logback/trunk/logback-access/src/main/java/ch/qos/logback/access/net/SMTPAppender.java
   logback/trunk/logback-core/src/main/java/ch/qos/logback/core/helpers/CyclicBuffer.java
Removed:
   logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/helpers/CyclicBuffer.java
Modified:
   logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/net/SMTPAppender.java

Log:
- added SMTPAppender for access module
- moved CyclicBuffer.java to the core module
- modified classic module's SMTPAppender accordingly

Added: logback/trunk/logback-access/src/main/java/ch/qos/logback/access/net/SMTPAppender.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-access/src/main/java/ch/qos/logback/access/net/SMTPAppender.java	Thu Oct  5 10:44:41 2006
@@ -0,0 +1,144 @@
+/**
+ * Logback: the reliable, generic, fast and flexible logging framework.
+ * 
+ * Copyright (C) 1999-2006, QOS.ch
+ * 
+ * This library is free software, you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation.
+ */
+
+package ch.qos.logback.access.net;
+
+import java.io.File;
+
+import ch.qos.logback.access.PatternLayout;
+import ch.qos.logback.core.helpers.CyclicBuffer;
+import ch.qos.logback.access.spi.AccessEvent;
+import ch.qos.logback.core.Layout;
+import ch.qos.logback.core.net.SMTPAppenderBase;
+import ch.qos.logback.core.rolling.TriggeringPolicy;
+
+/**
+ * Send an e-mail when a specific access event occurs, typically on errors or
+ * fatal errors.
+ * 
+ * <p>
+ * The number of access events delivered in this e-mail depend on the value of
+ * <b>BufferSize</b> option. The <code>SMTPAppender</code> keeps only the
+ * last <code>BufferSize</code> access events in its cyclic buffer. This
+ * keeps memory requirements at a reasonable level while still delivering useful
+ * application context.
+ * <p> 
+ * By default, the email is sent everything an event has a status code of 
+ * 500 (server error) or higher.
+ * <p>
+ * @author Ceki G&uuml;lc&uuml;
+ * @author S&eacute;bastien Pennec
+ * 
+ */
+public class SMTPAppender extends SMTPAppenderBase {
+
+  static final String DEFAULT_SUBJECT_PATTERN = "%m";
+  
+  private int bufferSize = 512;
+  protected CyclicBuffer cb = new CyclicBuffer(bufferSize);
+
+  /**
+   * The default constructor will instantiate the appender with a
+   * {@link TriggeringEventEvaluator} that will trigger on events with level
+   * ERROR or higher.
+   */
+  public SMTPAppender() {
+    this(new DefaultEvaluator());
+  }
+
+  /**
+   * Use <code>evaluator</code> passed as parameter as the {@link
+   * TriggeringEventEvaluator} for this SMTPAppender.
+   */
+  public SMTPAppender(TriggeringPolicy evaluator) {
+    this.evaluator = evaluator;
+  }
+
+  /**
+   * Perform SMTPAppender specific appending actions, mainly adding the event to
+   * a cyclic buffer.
+   */
+  protected void subAppend(Object eventObject) {
+    AccessEvent event = (AccessEvent) eventObject;
+
+    cb.add(event);
+    // addInfo("Added event to the cyclic buffer: " + event.getMessage());
+  }
+
+  @Override
+  protected void fillBuffer(StringBuffer sbuf) {
+    int len = cb.length();
+    for (int i = 0; i < len; i++) {
+      // sbuf.append(MimeUtility.encodeText(layout.format(cb.get())));
+      Object event = cb.get();
+      sbuf.append(layout.doLayout(event));
+    }
+  }
+
+  /**
+   * The <b>BufferSize</b> option takes a positive integer representing the
+   * maximum number of logging events to collect in a cyclic buffer. When the
+   * <code>BufferSize</code> is reached, oldest events are deleted as new
+   * events are added to the buffer. By default the size of the cyclic buffer is
+   * 512 events.
+   */
+  public void setBufferSize(int bufferSize) {
+    this.bufferSize = bufferSize;
+    cb.resize(bufferSize);
+  }
+
+  /**
+   * Returns value of the <b>BufferSize</b> option.
+   */
+  public int getBufferSize() {
+    return bufferSize;
+  }
+
+  @Override
+  protected Layout makeSubjectLayout(String subjectStr) {
+    if(subjectStr == null) {
+      subjectStr = DEFAULT_SUBJECT_PATTERN;
+    }
+    PatternLayout pl = new PatternLayout();
+    pl.setPattern(subjectStr);
+    pl.start();
+    return pl;
+  }
+}
+
+class DefaultEvaluator implements TriggeringPolicy {
+
+  private boolean started;
+
+  private static final Integer TRIGGERING_STATUS_CODE = 500;
+  /**
+   * Is this <code>event</code> the e-mail triggering event?
+   * 
+   * <p>
+   * This method returns <code>true</code>, if the event status code
+   * is 500 (server error) or higher. Otherwise it returns <code>false</code>.
+   */
+  public boolean isTriggeringEvent(File file, Object eventObject) {
+    AccessEvent event = (AccessEvent) eventObject;
+    return TRIGGERING_STATUS_CODE.compareTo(event.getStatusCode()) <= 0;
+  }
+
+  public boolean isStarted() {
+    return started == true;
+  }
+
+  public void start() {
+    started = true;
+  }
+
+  public void stop() {
+    started = false;
+  }
+}

Modified: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/net/SMTPAppender.java
==============================================================================
--- logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/net/SMTPAppender.java	(original)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/net/SMTPAppender.java	Thu Oct  5 10:44:41 2006
@@ -14,7 +14,7 @@
 
 import ch.qos.logback.classic.Level;
 import ch.qos.logback.classic.PatternLayout;
-import ch.qos.logback.classic.helpers.CyclicBuffer;
+import ch.qos.logback.core.helpers.CyclicBuffer;
 import ch.qos.logback.classic.spi.LoggingEvent;
 import ch.qos.logback.core.Layout;
 import ch.qos.logback.core.net.SMTPAppenderBase;

Added: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/helpers/CyclicBuffer.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/helpers/CyclicBuffer.java	Thu Oct  5 10:44:41 2006
@@ -0,0 +1,142 @@
+/**
+ * Logback: the reliable, generic, fast and flexible logging framework.
+ * 
+ * Copyright (C) 1999-2006, QOS.ch
+ * 
+ * This library is free software, you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation.
+ */
+
+package ch.qos.logback.core.helpers;
+
+
+/**
+ * 
+ * CyclicBuffer is used by other appenders to hold
+ * objects for immediate or differed display.
+ * <p>
+ * This buffer gives read access to any element in the buffer not just the first
+ * or last element.
+ * 
+ * @author Ceki G&uuml;lc&uuml;
+ */
+public class CyclicBuffer {
+
+  Object[] ea;
+  int first;
+  int last;
+  int numElems;
+  int maxSize;
+
+  /**
+   * Instantiate a new CyclicBuffer of at most <code>maxSize</code> events.
+   * 
+   * The <code>maxSize</code> argument must a positive integer.
+   * 
+   * @param maxSize
+   *          The maximum number of elements in the buffer.
+   */
+  public CyclicBuffer(int maxSize) throws IllegalArgumentException {
+    if (maxSize < 1) {
+      throw new IllegalArgumentException("The maxSize argument (" + maxSize
+          + ") is not a positive integer.");
+    }
+    this.maxSize = maxSize;
+    ea = new Object[maxSize];
+    first = 0;
+    last = 0;
+    numElems = 0;
+  }
+
+  /**
+   * Add an <code>event</code> as the last event in the buffer.
+   * 
+   */
+  public void add(Object event) {
+    ea[last] = event;
+    if (++last == maxSize)
+      last = 0;
+
+    if (numElems < maxSize)
+      numElems++;
+    else if (++first == maxSize)
+      first = 0;
+  }
+
+  /**
+   * Get the <i>i</i>th oldest event currently in the buffer. If <em>i</em>
+   * is outside the range 0 to the number of elements currently in the buffer,
+   * then <code>null</code> is returned.
+   */
+  public Object get(int i) {
+    if (i < 0 || i >= numElems)
+      return null;
+
+    return ea[(first + i) % maxSize];
+  }
+
+  public int getMaxSize() {
+    return maxSize;
+  }
+
+
+  /**
+   * Get the oldest (first) element in the buffer. The oldest element is removed
+   * from the buffer.
+   */
+  public Object get() {
+    Object r = null;
+    if (numElems > 0) {
+      numElems--;
+      r = ea[first];
+      ea[first] = null;
+      if (++first == maxSize)
+        first = 0;
+    }
+    return r;
+  }
+
+  /**
+   * Get the number of elements in the buffer. This number is guaranteed to be
+   * in the range 0 to <code>maxSize</code> (inclusive).
+   */
+  public int length() {
+    return numElems;
+  }
+
+  /**
+   * Resize the cyclic buffer to <code>newSize</code>.
+   * 
+   * @throws IllegalArgumentException
+   *           if <code>newSize</code> is negative.
+   */
+  public void resize(int newSize) {
+    if (newSize < 0) {
+      throw new IllegalArgumentException("Negative array size [" + newSize
+          + "] not allowed.");
+    }
+    if (newSize == numElems)
+      return; // nothing to do
+
+    Object[] temp = new Object[newSize];
+
+    int loopLen = newSize < numElems ? newSize : numElems;
+
+    for (int i = 0; i < loopLen; i++) {
+      temp[i] = ea[first];
+      ea[first] = null;
+      if (++first == numElems)
+        first = 0;
+    }
+    ea = temp;
+    first = 0;
+    numElems = loopLen;
+    maxSize = newSize;
+    if (loopLen == newSize) {
+      last = 0;
+    } else {
+      last = loopLen;
+    }
+  }
+}



More information about the logback-dev mailing list