Author: leif
Date: Fri Jul 30 00:46:30 2004
New Revision: 30969

Modified:
   avalon/trunk/runtime/index.xml
   
avalon/trunk/runtime/logkit/src/java/org/apache/log/output/net/SMTPOutputLogTarget.java
Log:
Modify the SMTPOutputLogTarget so it is not possible to have it send batched groups of 
log events in a single message.  This was possible before, but the message would never 
be sent until a predetermined number of messages had arrived.  These changes make it 
possible to set a timeout where the message will be sent if no more log events are 
received within a specified time period.
In other words, it is great at keeping groups of messages together while at the same 
time making sure they are delivered in a timely fashion.

Modified: avalon/trunk/runtime/index.xml
==============================================================================
--- avalon/trunk/runtime/index.xml      (original)
+++ avalon/trunk/runtime/index.xml      Fri Jul 30 00:46:30 2004
@@ -63,7 +63,7 @@
     <info>
       <group>avalon/logkit</group>
       <name>avalon-logkit</name>
-      <version>2.0.0</version>
+      <version>2.0.1</version>
     </info>
     <dependencies>
       <include key="mailapi" runtime="false"/>

Modified: 
avalon/trunk/runtime/logkit/src/java/org/apache/log/output/net/SMTPOutputLogTarget.java
==============================================================================
--- 
avalon/trunk/runtime/logkit/src/java/org/apache/log/output/net/SMTPOutputLogTarget.java
     (original)
+++ 
avalon/trunk/runtime/logkit/src/java/org/apache/log/output/net/SMTPOutputLogTarget.java
     Fri Jul 30 00:46:30 2004
@@ -35,29 +35,43 @@
  */
 public class SMTPOutputLogTarget extends AbstractOutputTarget
 {
-    // Mail session
+    /** Mail session. */
     private final Session m_session;
 
-    // Message to be sent
+    /** Message to be sent. */
     private Message m_message;
 
-    // Address to sent mail to
+    /** Address to sent mail to. */
     private final Address[] m_toAddresses;
 
-    // Address to mail is to be listed as sent from
+    /** Address to mail is to be listed as sent from. */
     private final Address m_fromAddress;
 
-    // Mail subject
+    /** Mail subject. */
     private final String m_subject;
 
-    // Current size of mail, in units of log events
+    /** Current size of mail, in units of log events. */
     private int m_msgSize;
 
-    // Maximum size of mail, in units of log events
+    /** Maximum size of mail, in units of log events. */
     private final int m_maxMsgSize;
 
-    // Buffer containing current mail
+    /** Buffer containing current mail. */
     private StringBuffer m_buffer;
+    
+    /** The time that the first log entry in the current buffer arrived. */
+    private long m_bufferTime;
+    
+    /** The maximun delay that a message will be allowed to wait in the queue
+     *   before being sent. */
+    private long m_maxDelayTime;
+    
+    /** Runner thread which is responsible for sending batched log entries in
+     * the background. */
+    private Thread m_runner;
+    
+    /** Flag which will be set in the close method when it is time to shutdown. */
+    private boolean m_shutdown;
 
     /** SMTPOutputLogTarget constructor.
      *
@@ -68,7 +82,17 @@
      * @param toAddresses addresses logs should be sent to
      * @param fromAddress address logs say they come from
      * @param subject subject line logs should use
-     * @param maxMsgSize maximum size of any log mail, in units of log events
+     * @param maxMsgSize maximum size of any log mail, in units of log events.
+     *                   If this is greater than one but maxDelayTime is 0 then
+     *                   log events may stay queued for a long period of time
+     *                   if less than the specified number of messages are
+     *                   logged.  Any unset messages will be sent when the
+     *                   target is closed.
+     * @param maxDelayTime specifies the longest delay in seconds that a log
+     *                     entry will be queued before being sent.  Setting
+     *                     this to a value larger than 0 will cause a
+     *                     background thread to be used to queue up and send
+     *                     messages.  Ignored if maxMsgSize is 1 or less.
      * @param formatter log formatter to use
      */
     public SMTPOutputLogTarget(
@@ -77,6 +101,7 @@
         final Address fromAddress,
         final String subject,
         final int maxMsgSize,
+        final int maxDelayTime,
         final Formatter formatter )
     {
         super( formatter );
@@ -87,11 +112,103 @@
         m_fromAddress = fromAddress;
         m_subject = subject;
         m_session = session;
+        m_maxDelayTime = maxDelayTime * 1000;
+        
+        if ( ( m_maxDelayTime > 0 ) && ( m_maxMsgSize > 1 ) ) 
+        {
+            // Create a runner thread which will
+            m_runner = new Thread( "SMTPOutputLogTarget_Queue_Daemon" )
+            {
+                public void run()
+                {
+                    try
+                    {
+                        //System.out.println( "SMTPOutputLogTarget runner Started." );
+                        synchronized( SMTPOutputLogTarget.this )
+                        {
+                            try
+                            {
+                                do
+                                {
+                                    // Wait up to a second for notification that a 
message is
+                                    //  available.
+                                    try
+                                    {
+                                        SMTPOutputLogTarget.this.wait( 1000 );
+                                    }
+                                    catch ( InterruptedException e )
+                                    {
+                                        // Ignore.
+                                    }
+                                    
+                                    // Is a message waiting?
+                                    if ( m_message != null )
+                                    {
+                                        // Is the message big enough to send or been
+                                        //  waiting long enough?
+                                        long now = System.currentTimeMillis();
+                                        if ( m_shutdown || ( m_msgSize >= 
m_maxMsgSize ) ||
+                                            ( now - m_bufferTime >= m_maxDelayTime ) )
+                                        {
+                                            // Time to send the message.
+                                            send();
+                                        }
+                                    }
+                                }
+                                while ( !m_shutdown );
+                            }
+                            finally
+                            {
+                                //System.out.println( "SMTPOutputLogTarget runner 
Completed." );
+                                m_runner = null;
+                                
+                                // The close method waits for this to complete.
+                                SMTPOutputLogTarget.this.notifyAll();
+                            }
+                        }
+                    }
+                    catch ( Throwable t )
+                    {
+                        getErrorHandler().error(
+                            "Unexpected error in the SMTPOutputLogTarget queue 
daemon", t, null );
+                    }
+                }
+            };
+            m_runner.setDaemon( true );
+            m_runner.start();
+        }
 
         // ready for business
         open();
     }
 
+    /** SMTPOutputLogTarget constructor.
+     *
+     * It creates a logkit output target capable of logging to SMTP 
+     * (ie. email, email gateway) targets.
+     *
+     * @param session mail session to be used
+     * @param toAddresses addresses logs should be sent to
+     * @param fromAddress address logs say they come from
+     * @param subject subject line logs should use
+     * @param maxMsgSize maximum size of any log mail, in units of log events.
+     *                   Log events may stay queued for a long period of time
+     *                   if less than the specified number of messages are
+     *                   logged.  Any unset messages will be sent when the
+     *                   target is closed.
+     * @param formatter log formatter to use
+     */
+    public SMTPOutputLogTarget(
+        final Session session,
+        final Address[] toAddresses,
+        final Address fromAddress,
+        final String subject,
+        final int maxMsgSize,
+        final Formatter formatter )
+    {
+        this( session, toAddresses, fromAddress, subject, maxMsgSize, 0, formatter );
+    }
+
     /** Method to write data to the log target. 
      * 
      * Logging data is stored in
@@ -101,36 +218,52 @@
      *
      * @param data logging data to be written to target
      */
-    protected void write( final String data )
+    protected synchronized void write( final String data )
     {
-        try
+        // If this is the first log entry then start a new Message.
+        if ( m_message == null )
         {
-            // ensure we have a message object available
-            if( m_message == null )
+            try
             {
                 m_message = new MimeMessage( m_session );
                 m_message.setFrom( m_fromAddress );
                 m_message.setRecipients( Message.RecipientType.TO, m_toAddresses );
                 m_message.setSubject( m_subject );
                 m_message.setSentDate( new Date() );
-                m_msgSize = 0;
-                m_buffer = new StringBuffer();
             }
+            catch( MessagingException e )
+            {
+                getErrorHandler().error( "Error creating message", e, null );
+            }
+            
+            m_buffer = new StringBuffer();
+            m_bufferTime = System.currentTimeMillis();
+            m_msgSize = 0;
+        }
+        
+        // Add the new log entry to the buffer.
+        m_buffer.append( data );
+        if ( !data.endsWith( "\n" ) )
+        {
+            m_buffer.append( "\n" );
+        }
+        m_msgSize++;
+        
+        // Decide what to do with the message.
+        if ( m_runner == null )
+        {
+            // Messages are sent in line.
 
-            // add the data to the buffer, separated by a newline
-            m_buffer.append( data );
-            m_buffer.append( '\n' );
-            ++m_msgSize;
-
-            // send mail if message size has reached it's size limit
-            if( m_msgSize >= m_maxMsgSize )
+            // Send mail if message size has reached it's size limit
+            if ( m_msgSize >= m_maxMsgSize )
             {
                 send();
             }
         }
-        catch( MessagingException e )
+        else
         {
-            getErrorHandler().error( "Error creating message", e, null );
+            // Messages are sent by the runner thread.
+            notifyAll();
         }
     }
 
@@ -140,8 +273,36 @@
      */
     public synchronized void close()
     {
+        //System.out.println( "SMTPOutputLogTarget close Started." );
+        
         super.close();
-        send();
+        
+        if ( m_runner == null )
+        {
+            // Log Events are being handled in line.
+            send();
+        }
+        else
+        {
+            // Log Events are being handled by a background thread.  Signal it
+            //  and then wait for it to complete.
+            m_shutdown = true;
+            notifyAll();
+            
+            while ( m_runner != null )
+            {
+                try
+                {
+                    wait();
+                }
+                catch ( InterruptedException e )
+                {
+                    // Ignore.
+                }
+            }
+        }
+        
+        //System.out.println( "SMTPOutputLogTarget close Completed." );
     }
 
     /**
@@ -157,6 +318,8 @@
     /**
      * Helper method to send the currently buffered message,
      * if existing.
+     * <p>
+     * Only called when synchronized.
      */
     private void send()
     {

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to