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()
{
lmpx.com only provides a reader for public news (NNTP) servers. It is not
affiliated with the servers or forums shown here and is not responsible for
the content of articles, which is written by their respective authors.