[logback-dev] [GIT] Logback: the generic, reliable, fast and flexible logging framework. branch, master, updated. v_0.9.25-53-g668e446

added by portage for gitosis-gentoo git-noreply at pixie.qos.ch
Wed Dec 22 22:53:04 CET 2010


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Logback: the generic, reliable, fast and flexible logging framework.".

The branch, master has been updated
       via  668e4464586c07ebe59c578406c3e7799508d46f (commit)
      from  8f3f52105b1f95909cb48be721fe3046473b2a4b (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
http://git.qos.ch/gitweb/?p=logback.git;a=commit;h=668e4464586c07ebe59c578406c3e7799508d46f
http://github.com/ceki/logback/commit/668e4464586c07ebe59c578406c3e7799508d46f

commit 668e4464586c07ebe59c578406c3e7799508d46f
Author: Ceki Gulcu <ceki at qos.ch>
Date:   Wed Dec 22 22:50:31 2010 +0100

    - doc improvements
    - minor indentation changes

diff --git a/logback-core/src/main/java/ch/qos/logback/core/net/SMTPAppenderBase.java b/logback-core/src/main/java/ch/qos/logback/core/net/SMTPAppenderBase.java
index a835638..f3bb08c 100644
--- a/logback-core/src/main/java/ch/qos/logback/core/net/SMTPAppenderBase.java
+++ b/logback-core/src/main/java/ch/qos/logback/core/net/SMTPAppenderBase.java
@@ -59,18 +59,14 @@ import ch.qos.logback.core.util.OptionHelper;
  */
 public abstract class SMTPAppenderBase<E> extends AppenderBase<E> {
 
-    static InternetAddress[] EMPTY_IA_ARRAY = new InternetAddress[0];
+  static InternetAddress[] EMPTY_IA_ARRAY = new InternetAddress[0];
   // ~ 14 days
   static final int MAX_DELAY_BETWEEN_STATUS_MESSAGES = 1228800 * CoreConstants.MILLIS_IN_ONE_SECOND;
 
   long lastTrackerStatusPrint = 0;
   int delayBetweenStatusMessages = 300 * CoreConstants.MILLIS_IN_ONE_SECOND;
 
-
-
-
   protected Layout<E> subjectLayout;
-
   protected Layout<E> layout;
 
   private List<PatternLayoutBase<E>> toPatternLayoutList = new ArrayList<PatternLayoutBase<E>>();
@@ -110,7 +106,7 @@ public abstract class SMTPAppenderBase<E> extends AppenderBase<E> {
    */
   public void start() {
 
-    if(cbTracker == null) {
+    if (cbTracker == null) {
       cbTracker = new CyclicBufferTrackerImpl<E>();
     }
 
@@ -189,15 +185,13 @@ public abstract class SMTPAppenderBase<E> extends AppenderBase<E> {
       }
     }
 
-
-    if(isEventMarkedForBufferRemoval(eventObject)) {
+    // immediately remove the buffer if asked by the user
+    if (isEventMarkedForBufferRemoval(eventObject)) {
       cbTracker.removeBuffer(key);
     }
 
     cbTracker.clearStaleBuffers(now);
 
-
-
     if (lastTrackerStatusPrint + delayBetweenStatusMessages < now) {
       addInfo("SMTPAppender [" + name + "] is tracking [" + cbTracker.size() + "] buffers");
       lastTrackerStatusPrint = now;
@@ -268,14 +262,14 @@ public abstract class SMTPAppenderBase<E> extends AppenderBase<E> {
       try {
         PatternLayoutBase<E> emailPL = toPatternLayoutList.get(i);
         String email = emailPL.doLayout(event);
-        if(email == null || email.length() == 0) {
+        if (email == null || email.length() == 0) {
           continue;
         }
         InternetAddress[] tmp = InternetAddress.parse(email, true);
         // one <To> element should contain one email address
         iaList.add(tmp[0]);
       } catch (AddressException e) {
-        addError("Could not parse email address for [" + toPatternLayoutList.get(i) + "] for event ["+event+"]", e);
+        addError("Could not parse email address for [" + toPatternLayoutList.get(i) + "] for event [" + event + "]", e);
         return iaList;
       }
     }
@@ -325,12 +319,12 @@ public abstract class SMTPAppenderBase<E> extends AppenderBase<E> {
                 charsetEncoding);
       }
 
-     List<InternetAddress> destinationAddresses  =  parseAddress(lastEventObject);
-     if(destinationAddresses.isEmpty()) {
-       addInfo("Empty destination address. Aborting email transmission");
-       return;
-     }
-     mimeMsg.setRecipients(Message.RecipientType.TO, destinationAddresses.toArray(EMPTY_IA_ARRAY));
+      List<InternetAddress> destinationAddresses = parseAddress(lastEventObject);
+      if (destinationAddresses.isEmpty()) {
+        addInfo("Empty destination address. Aborting email transmission");
+        return;
+      }
+      mimeMsg.setRecipients(Message.RecipientType.TO, destinationAddresses.toArray(EMPTY_IA_ARRAY));
 
       String contentType = layout.getContentType();
 
@@ -352,8 +346,6 @@ public abstract class SMTPAppenderBase<E> extends AppenderBase<E> {
     }
   }
 
-
-
   abstract protected void fillBuffer(CyclicBuffer<E> cb, StringBuffer sbuf);
 
   /**
@@ -388,6 +380,7 @@ public abstract class SMTPAppenderBase<E> extends AppenderBase<E> {
 
   /**
    * Alias for smtpHost
+   *
    * @param smtpHost
    */
   public void setSMTPHost(String smtpHost) {
@@ -422,7 +415,7 @@ public abstract class SMTPAppenderBase<E> extends AppenderBase<E> {
    * @param port
    */
   public void setSMTPPort(int port) {
-   setSmtpPort(port);
+    setSmtpPort(port);
   }
 
   /**
@@ -436,13 +429,16 @@ public abstract class SMTPAppenderBase<E> extends AppenderBase<E> {
 
   /**
    * Alias for {@link #getSmtpPort}
+   *
    * @return
-  */
+   */
   public int getSMTPPort() {
     return getSmtpPort();
   }
+
   /**
    * See {@link #setSmtpPort}
+   *
    * @return
    */
   public int getSmtpPort() {
@@ -466,27 +462,27 @@ public abstract class SMTPAppenderBase<E> extends AppenderBase<E> {
   }
 
   public void addTo(String to) {
-     if(to == null || to.length() == 0) {
-       throw new IllegalArgumentException("Null or empty <to> property");
-     }
-     PatternLayoutBase plb = makeNewToPatternLayout(to.trim());
-     plb.setContext(context);
-     plb.start();
-     this.toPatternLayoutList.add(plb);
+    if (to == null || to.length() == 0) {
+      throw new IllegalArgumentException("Null or empty <to> property");
+    }
+    PatternLayoutBase plb = makeNewToPatternLayout(to.trim());
+    plb.setContext(context);
+    plb.start();
+    this.toPatternLayoutList.add(plb);
   }
 
   abstract protected PatternLayoutBase<E> makeNewToPatternLayout(String toPattern);
 
- public List<String> getToAsListOfString() {
-   List<String> toList = new ArrayList<String>();
-   for(PatternLayoutBase plb: toPatternLayoutList) {
-       toList.add(plb.getPattern());
-   }
-   return toList;
- }
+  public List<String> getToAsListOfString() {
+    List<String> toList = new ArrayList<String>();
+    for (PatternLayoutBase plb : toPatternLayoutList) {
+      toList.add(plb.getPattern());
+    }
+    return toList;
+  }
 
   // for testing purpose only
- public Message getMessage() {
+  public Message getMessage() {
     return mimeMsg;
   }
 
diff --git a/logback-core/src/main/java/ch/qos/logback/core/pattern/ReplacingCompositeConverter.java b/logback-core/src/main/java/ch/qos/logback/core/pattern/ReplacingCompositeConverter.java
index 6542a44..40d1eae 100644
--- a/logback-core/src/main/java/ch/qos/logback/core/pattern/ReplacingCompositeConverter.java
+++ b/logback-core/src/main/java/ch/qos/logback/core/pattern/ReplacingCompositeConverter.java
@@ -40,9 +40,6 @@ public class ReplacingCompositeConverter<E> extends CompositeConverter<E> {
     }
     regex = optionList.get(0);
     pattern = Pattern.compile(regex);
-
-    //.matcher(this).replaceAll(replacement);
-
     replacement = optionList.get(1);
     super.start();
   }
diff --git a/logback-core/src/main/java/ch/qos/logback/core/spi/CyclicBufferTracker.java b/logback-core/src/main/java/ch/qos/logback/core/spi/CyclicBufferTracker.java
index 0c9fe80..83cc39f 100644
--- a/logback-core/src/main/java/ch/qos/logback/core/spi/CyclicBufferTracker.java
+++ b/logback-core/src/main/java/ch/qos/logback/core/spi/CyclicBufferTracker.java
@@ -31,8 +31,6 @@ public interface CyclicBufferTracker<E> {
   public int getBufferSize();
 
   public void setBufferSize(int size);
-
-
   public int getMaxNumberOfBuffers();
 
   /**
diff --git a/logback-site/src/site/pages/manual/appenders.html b/logback-site/src/site/pages/manual/appenders.html
index c527c4f..a37f67c 100644
--- a/logback-site/src/site/pages/manual/appenders.html
+++ b/logback-site/src/site/pages/manual/appenders.html
@@ -1695,10 +1695,11 @@ public interface TriggeringPolicy&lt;E&gt; extends LifeCycle {
       <tr>
         <td><a name="smtpTo" href="#smtpTo"><b><span class="option">to</span></b></a></td>
         <td><code>String</code></td>
-        <td>The email address of the recipient as a pattern. The
-        pattern is evaluated anew with the triggering event as input
-        for each outgoing email. Multiple recipients can be specified
-        by using several <code>&lt;to></code> elements.</td>
+        <td>The email address of the recipient as a
+        <em>pattern</em>. The pattern is evaluated anew with the
+        triggering event as input for each outgoing email. Multiple
+        recipients can be specified by using several
+        <code>&lt;to></code> elements.</td>
       </tr>
       <tr class="alt">
         <td><b><span class="option">from</span></b></td>
@@ -1818,8 +1819,8 @@ public interface TriggeringPolicy&lt;E&gt; extends LifeCycle {
           href="../xref/ch/qos/logback/core/spi/CyclicBufferTrackerImpl.html">CyclicBufferTrackerImpl</a>
           will be automatically created. By default, this instance
           will keep events in a cyclic buffer of size 256. You may
-          change the size with the help of the <code>BufferSize</code>
-          option.</p>
+          change the size with the help of the <span
+          class="option">bufferSize</span> option (see below).</p>
         </td>
         
       </tr>
@@ -2369,6 +2370,45 @@ logger.error(<b>notifyAdmin</b>,
     host, greatly facilitating problem diagnosis.
     </p>
     
+    <h4><a name= "bufferManagement" href="#bufferManagement">On buffer
+    management in very busy systems</a></h4>
+
+    <p>Internally, each distinct value returned by the disciminator
+    will cause the creation of a new cyclic buffer. However, at most
+    <span class="option">maxNumberOfBuffers</span> (by default 64)
+    will be maintained.  Whenever the number of buffers rises above
+    <span class="option">maxNumberOfBuffers</span>, the least recently
+    updated buffer is automatically discarded. As a second safety
+    measure, any buffer which has not been updated in the last 30
+    minutes will be automatically discarded as well.</p>
+
+    <p>On systems serving a large number of transactions per minute,
+    allowing only a small number for <span
+    class="option">maxNumberOfBuffers</span> (by default 64) will
+    often cause the number of events in the outgoing email to be
+    unnecessarily small. Indeed, in the presence of a large number of
+    transactions, there will be more than one buffer associated with
+    the same transaction as buffers will be killed and re-born in
+    succession for the same discriminator value (or transaction). Note
+    that in even such very busy systems, the maximum number of cyclic
+    buffers is capped by <span
+    class="option">maxNumberOfBuffers</span>.
+    </p>
+
+    <p>To avoid such yo-yo effects, <code>SMTPAppender</code> will
+    release the buffer associated with a given discriminator key as
+    soon as it sees an event marked as "FINALIZE_SESSION". This will
+    cause the appropriate buffer to be discarded at the end of each
+    transaction. You can then safely increase the value of <span
+    class="option">maxNumberOfBuffers</span> to a larger value such as
+    512 or 1024 without risking running out of memory.
+    </p>
+
+    <p>Thuse reare three distinct but complementary mechanisms working
+    together to manage cyclic buffers. They ensure that only relevant
+    buffers are kept alive at any given moment, even in very busy
+    systems.</p>
+
     <!-- =========================================================== -->
     <!-- =========================================================== -->
 
diff --git a/logback-site/src/site/pages/news.html b/logback-site/src/site/pages/news.html
index 55138ef..99f8e53 100644
--- a/logback-site/src/site/pages/news.html
+++ b/logback-site/src/site/pages/news.html
@@ -28,10 +28,14 @@
 
     <hr width="80%" align="center" />
 
-    <h3>xxx, 2010 - Release of version 0.9.27</h3>
+    <h3>December 22nd, 2010 - Release of version 0.9.27</h3>
 
-    <p><code>PatternLayout</code> now supports compound conversion
-    words of which <a href="manual/layouts.html#replace">"%replace"</a> is one example.
+    <p>Added a new section in the documentation about <a
+    href="recipes/index.html">real-world inspired recipes</a>.</p>
+
+    <p><code>PatternLayout</code> now supports
+    compound conversion words of which <a
+    href="manual/layouts.html#replace">"%replace"</a> is one example.
     </p>
 
     <p>The <a href="manual/appenders.html#smtpTo"><span
diff --git a/logback-site/src/site/pages/recipes/emailPerTransaction.html b/logback-site/src/site/pages/recipes/emailPerTransaction.html
index 5eb054b..a7ca756 100644
--- a/logback-site/src/site/pages/recipes/emailPerTransaction.html
+++ b/logback-site/src/site/pages/recipes/emailPerTransaction.html
@@ -21,7 +21,7 @@
     </div>
     <div id="content">
       
-      <h2>Triggering an email containing the isoloated logs of selected
+      <h2>Triggering an email containing the isolated logs of selected
       transactions</h2>
       
       <p>Let Dave and Carol be software QA engineers working at a
@@ -86,7 +86,7 @@ import javax.servlet.http.HttpServletResponse;
 public class PrimeAction extends Action {
 
   Logger logger = LoggerFactory.getLogger(PrimeAction.class);
-  Marker SMTP_TRIGGER = MarkerFactory.getMarker("SMTP_TRIGGER");
+  static Marker SMTP_TRIGGER = MarkerFactory.getMarker("SMTP_TRIGGER");
 
   public ActionForward execute(ActionMapping actionMapping,
                                ActionForm actionForm, HttpServletRequest request,
@@ -302,7 +302,7 @@ MDC.put("txId", transactionId); </pre>
     &lt;/layout>
 
     &lt;discriminator class="ch.qos.logback.classic.sift.MDCBasedDiscriminator">
-      &lt;key>uuid&lt;/key>
+      &lt;key>txId&lt;/key>
       &lt;defaultValue>default&lt;/defaultValue>
     &lt;/discriminator>
 
@@ -314,18 +314,131 @@ MDC.put("txId", transactionId); </pre>
         (marker != null  &amp;&amp; marker.contains("SMTP_TRIGGER") )
       &lt;/expression>
     &lt;/evaluator>
+  &lt;/appender>
+
+  &lt;root level="DEBUG">
+    &lt;appender-ref ref="SMTP" /> 
+  &lt;/root>
+&lt;/configuration>  </pre>
+
+     <p>If your particular SMTP server does not handle address tags,
+     you can still use them within the evaluator but remove them in
+     the recipient address with the help of the <a
+     href="../manual/layouts.html#replace">%replace</a> conversion
+     word. Here is the relevant configuraton snippet:</p>
+
+     <pre class="prettyprint source">&lt;appender name="SMTP" class="ch.qos.logback.classic.net.SMTPAppender">
+  &lt;to>%replace(%mdc{txEmail}){'\+log', ''}&lt;/to>
+  ...
+&lt;/appender></pre>
+
+     <p>This replaces any occurrence of the string "+log" within the
+     string returned by %mdc{txEmail} with the empty string,
+     effectively erasing +log from the recipient address.</p>
+
+     <h3>Buffer management in very busy systems</h3>
+
+     <p>The solution described so far provides an amazingly flexible
+     solution to the initial problem. Indeed, any QA-engineer at
+     Fooware.com, say Carol, can have the logs generated by requests
+     she makes to Buscrit sent to her automatically by email. All she
+     has to do is to suffix the user part in her email address with
+     "+log" when she registers with Buscrit.
+     </p>
+
+     <p>By default <code>SMTPAppender</code> will cap the number of
+     buffers it maintains to the value of the <span
+     class="option">maxNumberOfBuffers</span> option (64 by default)
+     and automatically discards buffers untouched for at least 30
+     minutes. While this approach will work nicely in a test
+     environment with few transactions, in a very busy production
+     system, these buffer management mechanims will cause Carol to
+     receive <a
+     href="../manual/appenders.html#bufferManagement">truncated log
+     buffers</a>.  </p>
+
+     <p>To deal with this problem, we instruct SMTPAppender to discard
+     apprioate buffer at the end of each transaction. This is done by
+     logging an event marked as "FINALIZE_SESSION". Here is a modified
+     version of <code>PrimeAction</code> which marks the end of a
+     transaction with "FINALIZE_SESSION".
+     </p>
+
+     <pre class="prettyprint source">package ch.qos.logback.demo.prime;
+
+<b>import static ch.qos.logback.classic.ClassicConstants.FINALIZE_SESSION_MARKER;</b>
+
+public class PrimeAction extends Action {
+
+  Logger logger = LoggerFactory.getLogger(PrimeAction.class);
+  static Marker SMTP_TRIGGER = MarkerFactory.getMarker("SMTP_TRIGGER");
+  static {
+     // markers can hold references to other markers
+     <b>SMTP_TRIGGER.add(FINALIZE_SESSION_MARKER);</b>
+  }
+
+  public ActionForward execute(ActionMapping actionMapping, ... ) throws Exception {
+
+    Long number = form.getNumber();
+    try {
+      ...
+    } finally {
+      <b>logger.info(SMTP_TRIGGER, "Prime computation ended");</b>
+      MDC.put("txId", null); // clear txId asap to avoid accidental rebirth
+    }
+  }
+} </pre>
+
+
+   <p>Not that at the end of each transaction the appropriate buffer
+   is discarded, we can incrase the value of <span
+   class="option">maxNumberOfBuffers</span> as shown in the next
+   configuration file..
+   </p>
+
+   <pre class="prettyprint   source">&lt;configuration scan="true" scanPeriod="3 seconds">
+
+  &lt;statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" /&gt;
+
+  &lt;appender name="SMTP" class="ch.qos.logback.classic.net.SMTPAppender">
+    &lt;SMTPHost>NAME_OF_SMTP_HOST&lt;/SMTPHost>
+    &lt;to>%mdc{txEmail}&lt;/to>
+    &lt;from>&lt;/from>
+    &lt;subject>Prime - %mdc{number}&lt;/subject>
+
+    &lt;layout class="ch.qos.logback.classic.html.HTMLLayout">
+       &lt;pattern>%date%level%logger{24}%msg&lt;/pattern>
+    &lt;/layout>
 
     &lt;discriminator class="ch.qos.logback.classic.sift.MDCBasedDiscriminator">
-      &lt;key>uuid&lt;/key>
+      &lt;key>txId&lt;/key>
       &lt;defaultValue>default&lt;/defaultValue>
     &lt;/discriminator>
-  &lt;/appender>
+
+    <b>&lt;cyclicBufferTracker class="ch.qos.logback.core.spi.CyclicBufferTrackerImpl"></b>
+      <b>&lt;maxNumberOfBuffers>512&lt;/maxNumberOfBuffers></b>
+    <b>&lt;/cyclicBufferTracker></b>
+
+    &lt;evaluator class="ch.qos.logback.classic.boolex.JaninoEventEvaluator">
+      &lt;expression>
+        (mdc != null &amp;amp;&amp;amp; mdc.get("txEmail") != null &amp;amp;&amp;amp;
+            ((String) mdc.get("txEmail")).contains("+log") )
+        &amp;amp;&amp;amp;
+        (marker != null  &amp;&amp; marker.contains("SMTP_TRIGGER") )
+      &lt;/expression>
+    &lt;/evaluator>
 
   &lt;root level="DEBUG">
     &lt;appender-ref ref="SMTP" /> 
   &lt;/root>
 &lt;/configuration>  </pre>
-      <script src="../templates/footer.js" type="text/javascript"></script>	
+
+    <p>With these latest changes, we can selectively send isolated
+    logs for selected transactions to the concerned recipient, even in
+    very busy production systems without excessive memory consumption.
+    </p>
+
+     <script src="../templates/footer.js" type="text/javascript"></script>	
     </div>
   </body>
 </html>

-----------------------------------------------------------------------

Summary of changes:
 .../ch/qos/logback/core/net/SMTPAppenderBase.java  |   70 +++++------
 .../core/pattern/ReplacingCompositeConverter.java  |    3 -
 .../qos/logback/core/spi/CyclicBufferTracker.java  |    2 -
 logback-site/src/site/pages/manual/appenders.html  |   52 +++++++-
 logback-site/src/site/pages/news.html              |   10 +-
 .../site/pages/recipes/emailPerTransaction.html    |  125 +++++++++++++++++++-
 6 files changed, 205 insertions(+), 57 deletions(-)


hooks/post-receive
-- 
Logback: the generic, reliable, fast and flexible logging framework.


More information about the logback-dev mailing list