nicko 2005/08/29 12:45:31
Modified: src/Appender AppenderSkeleton.cs
BufferingAppenderSkeleton.cs
BufferingForwardingAppender.cs FileAppender.cs
ForwardingAppender.cs RollingFileAppender.cs
TextWriterAppender.cs
examples/net/1.0/Appenders/SampleAppendersApp/cs/src/Appender
AsyncAppender.cs
src log4net.csproj
src/Util AppenderAttachedImpl.cs
Added: src/Appender IBulkAppender.cs
Log:
Fix for LOG4NET-46. Added IBulkAppender interface. Added implementation to
AppenderSkeleton and subclasses
Revision Changes Path
1.7 +182 -22 logging-log4net/src/Appender/AppenderSkeleton.cs
Index: AppenderSkeleton.cs
===================================================================
RCS file: /home/cvs/logging-log4net/src/Appender/AppenderSkeleton.cs,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- AppenderSkeleton.cs 14 Feb 2005 19:45:11 -0000 1.6
+++ AppenderSkeleton.cs 29 Aug 2005 19:45:30 -0000 1.7
@@ -18,6 +18,7 @@
using System;
using System.IO;
+using System.Collections;
using log4net.Filter;
using log4net.Util;
@@ -42,7 +43,7 @@
/// </remarks>
/// <author>Nicko Cadell</author>
/// <author>Gert Driesen</author>
- public abstract class AppenderSkeleton : IAppender, IOptionHandler
+ public abstract class AppenderSkeleton : IAppender, IBulkAppender,
IOptionHandler
{
#region Protected Instance Constructors
@@ -247,7 +248,7 @@
/// <summary>
/// Performs threshold checks and invokes filters before
/// delegating actual logging to the subclasses specific
- /// <see cref="AppenderSkeleton.Append"/> method.
+ /// <see cref="AppenderSkeleton.Append(LoggingEvent)"/> method.
/// </summary>
/// <param name="loggingEvent">The event to log.</param>
/// <remarks>
@@ -310,43 +311,120 @@
{
m_recursiveGuard = true;
- if
(!IsAsSevereAsThreshold(loggingEvent.Level))
+ if (FilterEvent(loggingEvent) &&
PreAppendCheck())
{
- return;
+ this.Append(loggingEvent);
}
+ }
+ catch(Exception ex)
+ {
+ ErrorHandler.Error("Failed in
DoAppend", ex);
+ }
+ catch
+ {
+ // Catch handler for non
System.Exception types
+ ErrorHandler.Error("Failed in DoAppend
(unknown exception)");
+ }
+ finally
+ {
+ m_recursiveGuard = false;
+ }
+ }
+ }
+
+ #endregion Implementation of IAppender
+
+ #region Implementation of IBulkAppender
+
+ /// <summary>
+ /// Performs threshold checks and invokes filters before
+ /// delegating actual logging to the subclasses specific
+ /// <see cref="AppenderSkeleton.Append(LoggingEvent[])"/>
method.
+ /// </summary>
+ /// <param name="loggingEvents">The array of events to
log.</param>
+ /// <remarks>
+ /// <para>
+ /// This method cannot be overridden by derived classes. A
+ /// derived class should override the <see cref="Append"/>
method
+ /// which is called by this method.
+ /// </para>
+ /// <para>
+ /// The implementation of this method is as follows:
+ /// </para>
+ /// <para>
+ /// <list type="bullet">
+ /// <item>
+ /// <description>
+ /// Checks that the severity of the
<paramref name="loggingEvent"/>
+ /// is greater than or equal to the <see
cref="Threshold"/> of this
+ /// appender.</description>
+ /// </item>
+ /// <item>
+ /// <description>
+ /// Checks that the <see cref="Filter"/>
chain accepts the
+ /// <paramref name="loggingEvent"/>.
+ /// </description>
+ /// </item>
+ /// <item>
+ /// <description>
+ /// Calls <see cref="PreAppendCheck()"/>
and checks that
+ /// it returns <c>true</c>.</description>
+ /// </item>
+ /// </list>
+ /// </para>
+ /// <para>
+ /// If all of the above steps succeed then the <paramref
name="loggingEvents"/>
+ /// will be passed to the <see cref="Append"/> method.
+ /// </para>
+ /// </remarks>
+ public void DoAppend(LoggingEvent[] loggingEvents)
+ {
+ // This lock is absolutely critical for correct
formatting
+ // of the message in a multi-threaded environment.
Without
+ // this, the message may be broken up into elements from
+ // multiple thread contexts (like get the wrong thread
ID).
- IFilter f = this.FilterHead;
+ lock(this)
+ {
+ if (m_closed)
+ {
+ ErrorHandler.Error("Attempted to append
to closed appender named ["+m_name+"].");
+ return;
+ }
- while(f != null)
+ // prevent re-entry
+ if (m_recursiveGuard)
+ {
+ return;
+ }
+
+ try
+ {
+ m_recursiveGuard = true;
+
+ ArrayList filteredEvents = new
ArrayList(loggingEvents.Length);
+
+ foreach(LoggingEvent loggingEvent in
loggingEvents)
{
- switch(f.Decide(loggingEvent))
+ if (FilterEvent(loggingEvent))
{
- case
FilterDecision.Deny:
- return;
// Return without appending
-
- case
FilterDecision.Accept:
- f = null;
// Break out of the loop
- break;
-
- case
FilterDecision.Neutral:
- f = f.Next;
// Move to next filter
- break;
+
filteredEvents.Add(loggingEvent);
}
}
- if (PreAppendCheck())
+ if (filteredEvents.Count > 0 &&
PreAppendCheck())
{
- this.Append(loggingEvent);
+
this.Append((LoggingEvent[])filteredEvents.ToArray(typeof(LoggingEvent)));
}
}
catch(Exception ex)
{
- ErrorHandler.Error("Failed in
DoAppend", ex);
+ ErrorHandler.Error("Failed in Bulk
DoAppend", ex);
}
catch
{
// Catch handler for non
System.Exception types
- ErrorHandler.Error("Failed in DoAppend
(unknown exception)");
+ ErrorHandler.Error("Failed in Bulk
DoAppend (unknown exception)");
}
finally
{
@@ -355,7 +433,67 @@
}
}
- #endregion Implementation of IAppender
+ #endregion Implementation of IBulkAppender
+
+ /// <summary>
+ /// Test if the logging event should we output by this appender
+ /// </summary>
+ /// <param name="loggingEvent">the event to test</param>
+ /// <returns><c>true</c> if the event should be output,
<c>false</c> if the event should be ignored</returns>
+ /// <remarks>
+ /// <para>
+ /// This method checks the logging event against the threshold
level set
+ /// on this appender and also against the filters specified on
this
+ /// appender.
+ /// </para>
+ /// <para>
+ /// The implementation of this method is as follows:
+ /// </para>
+ /// <para>
+ /// <list type="bullet">
+ /// <item>
+ /// <description>
+ /// Checks that the severity of the
<paramref name="loggingEvent"/>
+ /// is greater than or equal to the <see
cref="Threshold"/> of this
+ /// appender.</description>
+ /// </item>
+ /// <item>
+ /// <description>
+ /// Checks that the <see cref="Filter"/>
chain accepts the
+ /// <paramref name="loggingEvent"/>.
+ /// </description>
+ /// </item>
+ /// </list>
+ /// </para>
+ /// </remarks>
+ virtual protected bool FilterEvent(LoggingEvent loggingEvent)
+ {
+ if (!IsAsSevereAsThreshold(loggingEvent.Level))
+ {
+ return false;
+ }
+
+ IFilter f = this.FilterHead;
+
+ while(f != null)
+ {
+ switch(f.Decide(loggingEvent))
+ {
+ case FilterDecision.Deny:
+ return false; // Return
without appending
+
+ case FilterDecision.Accept:
+ f = null; //
Break out of the loop
+ break;
+
+ case FilterDecision.Neutral:
+ f = f.Next; // Move
to next filter
+ break;
+ }
+ }
+
+ return true;
+ }
#region Public Instance Methods
@@ -464,6 +602,28 @@
abstract protected void Append(LoggingEvent loggingEvent);
/// <summary>
+ /// Append a bulk array of logging events.
+ /// </summary>
+ /// <param name="loggingEvents">the array of logging
events</param>
+ /// <remarks>
+ /// <para>
+ /// This base class implementation calls the <see
cref="Append(LoggingEvent)"/>
+ /// method for each element in the bulk array.
+ /// </para>
+ /// <para>
+ /// A sub class that can better process a bulk array of events
should
+ /// override this method in addition to <see
cref="Append(LoggingEvent)"/>.
+ /// </para>
+ /// </remarks>
+ virtual protected void Append(LoggingEvent[] loggingEvents)
+ {
+ foreach(LoggingEvent loggingEvent in loggingEvents)
+ {
+ Append(loggingEvent);
+ }
+ }
+
+ /// <summary>
/// Called before <see cref="Append"/> as a precondition.
/// </summary>
/// <remarks>
1.11 +51 -21 logging-log4net/src/Appender/BufferingAppenderSkeleton.cs
Index: BufferingAppenderSkeleton.cs
===================================================================
RCS file:
/home/cvs/logging-log4net/src/Appender/BufferingAppenderSkeleton.cs,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- BufferingAppenderSkeleton.cs 8 Jun 2005 17:13:39 -0000 1.10
+++ BufferingAppenderSkeleton.cs 29 Aug 2005 19:45:30 -0000 1.11
@@ -17,6 +17,7 @@
#endregion
using System;
+using System.Collections;
using log4net.Util;
using log4net.Core;
@@ -286,7 +287,7 @@
// really be checking for.
if (m_cb != null && m_bufferSize > 1 &&
!m_lossy)
{
- SendBuffer(m_cb);
+ SendFromBuffer(null, m_cb);
}
}
}
@@ -355,18 +356,26 @@
{
if (m_lossyEvaluator != null)
{
- foreach(LoggingEvent
loggingEvent in m_cb.PopAll())
+ LoggingEvent[] bufferedEvents =
m_cb.PopAll();
+ ArrayList filteredEvents = new
ArrayList(bufferedEvents.Length);
+
+ foreach(LoggingEvent
loggingEvent in bufferedEvents)
{
if
(m_lossyEvaluator.IsTriggeringEvent(loggingEvent))
{
- SendBuffer(new
LoggingEvent[] { loggingEvent } );
+
filteredEvents.Add(loggingEvent);
}
}
+
+ if (filteredEvents.Count > 0)
+ {
+
SendBuffer((LoggingEvent[])filteredEvents.ToArray(typeof(LoggingEvent)));
+ }
}
}
else
{
- SendBuffer(m_cb);
+ SendFromBuffer(null, m_cb);
}
}
}
@@ -437,21 +446,26 @@
if (!m_lossy)
{
// Not lossy, must send all
events
- SendBuffer(new LoggingEvent[] {
discardedLoggingEvent } );
- SendBuffer(m_cb);
+
SendFromBuffer(discardedLoggingEvent, m_cb);
}
else
{
- // Check if the discarded event
should be logged
- if (m_lossyEvaluator != null &&
m_lossyEvaluator.IsTriggeringEvent(discardedLoggingEvent))
+ // Check if the discarded event
should not be logged
+ if (m_lossyEvaluator == null ||
!m_lossyEvaluator.IsTriggeringEvent(discardedLoggingEvent))
{
- SendBuffer(new
LoggingEvent[] { discardedLoggingEvent } );
+ // Clear the discarded
event as we should not forward it
+ discardedLoggingEvent =
null;
}
// Check if the event should
trigger the whole buffer to be sent
if (m_evaluator != null &&
m_evaluator.IsTriggeringEvent(loggingEvent))
{
- SendBuffer(m_cb);
+
SendFromBuffer(discardedLoggingEvent, m_cb);
+ }
+ else if (discardedLoggingEvent
!= null)
+ {
+ // Just send the
discarded event
+ SendBuffer(new
LoggingEvent[] { discardedLoggingEvent } );
}
}
}
@@ -462,7 +476,7 @@
// Check if the event should trigger
the whole buffer to be sent
if (m_evaluator != null &&
m_evaluator.IsTriggeringEvent(loggingEvent))
{
- SendBuffer(m_cb);
+ SendFromBuffer(null, m_cb);
}
}
}
@@ -475,29 +489,45 @@
/// <summary>
/// Sends the contents of the buffer.
/// </summary>
+ /// <param name="firstLoggingEvent">The first logging
event.</param>
/// <param name="buffer">The buffer containing the events that
need to be send.</param>
/// <remarks>
- /// The subclass must override either <see
cref="SendBuffer(CyclicBuffer)"/>
- /// or <see cref="SendBuffer(LoggingEvent[])"/>.
+ /// The subclass must override <see
cref="SendBuffer(LoggingEvent[])"/>.
/// </remarks>
- virtual protected void SendBuffer(CyclicBuffer buffer)
+ virtual protected void SendFromBuffer(LoggingEvent
firstLoggingEvent, CyclicBuffer buffer)
{
- SendBuffer(buffer.PopAll());
+ LoggingEvent[] bufferEvents = buffer.PopAll();
+
+ if (firstLoggingEvent == null)
+ {
+ SendBuffer(bufferEvents);
+ }
+ else if (bufferEvents.Length == 0)
+ {
+ SendBuffer(new LoggingEvent[] {
firstLoggingEvent } );
+ }
+ else
+ {
+ // Create new array with the firstLoggingEvent
at the head
+ LoggingEvent[] events = new
LoggingEvent[bufferEvents.Length + 1];
+ Array.Copy(bufferEvents, 0, events, 1,
bufferEvents.Length);
+ events[0] = firstLoggingEvent;
+
+ SendBuffer(events);
+ }
}
+ #endregion Protected Instance Methods
+
/// <summary>
/// Sends the events.
/// </summary>
/// <param name="events">The events that need to be
send.</param>
/// <remarks>
- /// The subclass must override either <see
cref="SendBuffer(CyclicBuffer)"/>
- /// or <see cref="SendBuffer(LoggingEvent[])"/>.
+ /// The subclass must override this method to process the
buffered events.
/// </remarks>
- virtual protected void SendBuffer(LoggingEvent[] events)
- {
- }
+ abstract protected void SendBuffer(LoggingEvent[] events);
- #endregion Protected Instance Methods
#region Private Static Fields
1.7 +1 -5
logging-log4net/src/Appender/BufferingForwardingAppender.cs
Index: BufferingForwardingAppender.cs
===================================================================
RCS file:
/home/cvs/logging-log4net/src/Appender/BufferingForwardingAppender.cs,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- BufferingForwardingAppender.cs 17 Jan 2005 20:18:41 -0000 1.6
+++ BufferingForwardingAppender.cs 29 Aug 2005 19:45:30 -0000 1.7
@@ -106,11 +106,7 @@
// Pass the logging event on to the attached appenders
if (m_appenderAttachedImpl != null)
{
- // Send each event one at a time
- foreach(LoggingEvent e in events)
- {
-
m_appenderAttachedImpl.AppendLoopOnAppenders(e);
- }
+
m_appenderAttachedImpl.AppendLoopOnAppenders(events);
}
}
1.20 +26 -0 logging-log4net/src/Appender/FileAppender.cs
Index: FileAppender.cs
===================================================================
RCS file: /home/cvs/logging-log4net/src/Appender/FileAppender.cs,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -r1.19 -r1.20
--- FileAppender.cs 21 Mar 2005 00:23:13 -0000 1.19
+++ FileAppender.cs 29 Aug 2005 19:45:30 -0000 1.20
@@ -839,6 +839,32 @@
}
/// <summary>
+ /// This method is called by the <see
cref="AppenderSkeleton.DoAppend"/>
+ /// method.
+ /// </summary>
+ /// <param name="loggingEvents">The array of events to
log.</param>
+ /// <remarks>
+ /// <para>
+ /// Acquires the output file locks once before writing all the
events to
+ /// the stream.
+ /// </para>
+ /// </remarks>
+ override protected void Append(LoggingEvent[] loggingEvents)
+ {
+ if (m_stream.AcquireLock())
+ {
+ try
+ {
+ base.Append(loggingEvents);
+ }
+ finally
+ {
+ m_stream.ReleaseLock();
+ }
+ }
+ }
+
+ /// <summary>
/// Writes a footer as produced by the embedded layout's <see
cref="ILayout.Footer"/> property.
/// </summary>
/// <remarks>
1.7 +19 -1 logging-log4net/src/Appender/ForwardingAppender.cs
Index: ForwardingAppender.cs
===================================================================
RCS file: /home/cvs/logging-log4net/src/Appender/ForwardingAppender.cs,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- ForwardingAppender.cs 17 Jan 2005 20:18:41 -0000 1.6
+++ ForwardingAppender.cs 29 Aug 2005 19:45:30 -0000 1.7
@@ -80,7 +80,7 @@
}
/// <summary>
- /// Append the logging event.
+ /// Forward the logging event to the attached appenders
/// </summary>
/// <param name="loggingEvent">The event to log.</param>
/// <remarks>
@@ -97,6 +97,24 @@
}
}
+ /// <summary>
+ /// Forward the logging events to the attached appenders
+ /// </summary>
+ /// <param name="loggingEvents">The array of events to
log.</param>
+ /// <remarks>
+ /// <para>
+ /// Delivers the logging events to all the attached appenders.
+ /// </para>
+ /// </remarks>
+ override protected void Append(LoggingEvent[] loggingEvents)
+ {
+ // Pass the logging event on the the attached appenders
+ if (m_appenderAttachedImpl != null)
+ {
+
m_appenderAttachedImpl.AppendLoopOnAppenders(loggingEvents);
+ }
+ }
+
#endregion Override implementation of AppenderSkeleton
#region Implementation of IAppenderAttachable
1.24 +35 -5 logging-log4net/src/Appender/RollingFileAppender.cs
Index: RollingFileAppender.cs
===================================================================
RCS file: /home/cvs/logging-log4net/src/Appender/RollingFileAppender.cs,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -r1.23 -r1.24
--- RollingFileAppender.cs 14 Aug 2005 21:41:19 -0000 1.23
+++ RollingFileAppender.cs 29 Aug 2005 19:45:30 -0000 1.24
@@ -473,13 +473,46 @@
/// <param name="loggingEvent">the event to write to
file.</param>
/// <remarks>
/// <para>
- /// Handles append time behavior for CompositeRollingAppender.
This checks
+ /// Handles append time behavior for RollingFileAppender. This
checks
/// if a roll over either by date (checked first) or time
(checked second)
/// is need and then appends to the file last.
/// </para>
/// </remarks>
override protected void Append(LoggingEvent loggingEvent)
{
+ AdjustFileBeforeAppend();
+ base.Append(loggingEvent);
+ }
+
+ /// <summary>
+ /// Write out an array of logging events.
+ /// </summary>
+ /// <param name="loggingEvents">the events to write to
file.</param>
+ /// <remarks>
+ /// <para>
+ /// Handles append time behavior for RollingFileAppender. This
checks
+ /// if a roll over either by date (checked first) or time
(checked second)
+ /// is need and then appends to the file last.
+ /// </para>
+ /// </remarks>
+ override protected void Append(LoggingEvent[] loggingEvents)
+ {
+ AdjustFileBeforeAppend();
+ base.Append(loggingEvents);
+ }
+
+ /// <summary>
+ /// Performs any required rolling before outputting the next
event
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// Handles append time behavior for RollingFileAppender. This
checks
+ /// if a roll over either by date (checked first) or time
(checked second)
+ /// is need and then appends to the file last.
+ /// </para>
+ /// </remarks>
+ virtual protected void AdjustFileBeforeAppend()
+ {
if (m_rollDate)
{
DateTime n = m_dateTime.Now;
@@ -499,11 +532,8 @@
RollOverSize();
}
}
-
- base.Append(loggingEvent);
}
-
-
+
/// <summary>
/// Creates and opens the file for logging. If <see
cref="StaticLogFileName"/>
/// is false then the fully qualified name is determined and
used.
1.8 +25 -1 logging-log4net/src/Appender/TextWriterAppender.cs
Index: TextWriterAppender.cs
===================================================================
RCS file: /home/cvs/logging-log4net/src/Appender/TextWriterAppender.cs,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- TextWriterAppender.cs 17 Jan 2005 20:18:42 -0000 1.7
+++ TextWriterAppender.cs 29 Aug 2005 19:45:30 -0000 1.8
@@ -223,7 +223,31 @@
{
m_qtw.Flush();
}
- }
+ }
+
+ /// <summary>
+ /// This method is called by the <see
cref="AppenderSkeleton.DoAppend"/>
+ /// method.
+ /// </summary>
+ /// <param name="loggingEvents">The array of events to
log.</param>
+ /// <remarks>
+ /// <para>
+ /// This method writes all the bulk logged events to the output
writer
+ /// before flushing the stream.
+ /// </para>
+ /// </remarks>
+ override protected void Append(LoggingEvent[] loggingEvents)
+ {
+ foreach(LoggingEvent loggingEvent in loggingEvents)
+ {
+ RenderLoggingEvent(m_qtw, loggingEvent);
+ }
+
+ if (m_immediateFlush)
+ {
+ m_qtw.Flush();
+ }
+ }
/// <summary>
/// Close this appender instance. The underlying stream or
writer is also closed.
1.1 logging-log4net/src/Appender/IBulkAppender.cs
Index: IBulkAppender.cs
===================================================================
#region Copyright & License
//
// Copyright 2001-2005 The Apache Software Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#endregion
using log4net.Core;
namespace log4net.Appender
{
/// <summary>
/// Interface for appenders that support bulk logging.
/// </summary>
/// <remarks>
/// <para>
/// This interface extends the <see cref="IAppender"/> interface to
/// support bulk logging of <see cref="LoggingEvent"/> objects.
Appenders
/// should only implement this interface if they can bulk log
efficiently.
/// </para>
/// </remarks>
/// <author>Nicko Cadell</author>
public interface IBulkAppender : IAppender
{
/// <summary>
/// Log the array of logging events in Appender specific way.
/// </summary>
/// <param name="loggingEvents">The events to log</param>
/// <remarks>
/// <para>
/// This method is called to log an array of events into this
appender.
/// </para>
/// </remarks>
void DoAppend(LoggingEvent[] loggingEvents);
}
}
1.3 +24 -5
logging-log4net/examples/net/1.0/Appenders/SampleAppendersApp/cs/src/Appender/AsyncAppender.cs
Index: AsyncAppender.cs
===================================================================
RCS file:
/home/cvs/logging-log4net/examples/net/1.0/Appenders/SampleAppendersApp/cs/src/Appender/AsyncAppender.cs,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- AsyncAppender.cs 15 Jun 2005 16:26:40 -0000 1.2
+++ AsyncAppender.cs 29 Aug 2005 19:45:31 -0000 1.3
@@ -33,7 +33,7 @@
/// This allows the calling thread to be released quickly, however it
does
/// not guarantee the ordering of events delivered to the attached
appenders.
/// </remarks>
- public sealed class AsyncAppender : IAppender, IOptionHandler,
IAppenderAttachable
+ public sealed class AsyncAppender : IAppender, IBulkAppender,
IOptionHandler, IAppenderAttachable
{
private string m_name;
@@ -71,13 +71,32 @@
System.Threading.ThreadPool.QueueUserWorkItem(new
WaitCallback(AsyncAppend), loggingEvent);
}
- private void AsyncAppend(object state)
+ public void DoAppend(LoggingEvent[] loggingEvents)
{
- LoggingEvent loggingEvent = state as LoggingEvent;
+ foreach(LoggingEvent loggingEvent in loggingEvents)
+ {
+ loggingEvent.Fix = m_fixFlags;
+ }
+ System.Threading.ThreadPool.QueueUserWorkItem(new
WaitCallback(AsyncAppend), loggingEvents);
+ }
- if (m_appenderAttachedImpl != null && loggingEvent !=
null)
+ private void AsyncAppend(object state)
+ {
+ if (m_appenderAttachedImpl != null)
{
-
m_appenderAttachedImpl.AppendLoopOnAppenders(loggingEvent);
+ LoggingEvent loggingEvent = state as
LoggingEvent;
+ if (loggingEvent != null)
+ {
+
m_appenderAttachedImpl.AppendLoopOnAppenders(loggingEvent);
+ }
+ else
+ {
+ LoggingEvent[] loggingEvents = state as
LoggingEvent[];
+ if (loggingEvents != null)
+ {
+
m_appenderAttachedImpl.AppendLoopOnAppenders(loggingEvents);
+ }
+ }
}
}
1.19 +5 -0 logging-log4net/src/log4net.csproj
Index: log4net.csproj
===================================================================
RCS file: /home/cvs/logging-log4net/src/log4net.csproj,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -r1.18 -r1.19
--- log4net.csproj 14 Feb 2005 03:24:36 -0000 1.18
+++ log4net.csproj 29 Aug 2005 19:45:31 -0000 1.19
@@ -193,6 +193,11 @@
BuildAction = "Compile"
/>
<File
+ RelPath = "Appender\IBulkAppender.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
RelPath = "Appender\LocalSyslogAppender.cs"
SubType = "Code"
BuildAction = "Compile"
1.7 +82 -0 logging-log4net/src/Util/AppenderAttachedImpl.cs
Index: AppenderAttachedImpl.cs
===================================================================
RCS file: /home/cvs/logging-log4net/src/Util/AppenderAttachedImpl.cs,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- AppenderAttachedImpl.cs 31 Jan 2005 22:56:49 -0000 1.6
+++ AppenderAttachedImpl.cs 29 Aug 2005 19:45:31 -0000 1.7
@@ -98,8 +98,90 @@
return m_appenderList.Count;
}
+ /// <summary>
+ /// Append on on all attached appenders.
+ /// </summary>
+ /// <param name="loggingEvents">The array of events being
logged.</param>
+ /// <returns>The number of appenders called.</returns>
+ /// <remarks>
+ /// <para>
+ /// Calls the <see cref="IAppender.DoAppend" /> method on all
+ /// attached appenders.
+ /// </para>
+ /// </remarks>
+ public int AppendLoopOnAppenders(LoggingEvent[] loggingEvents)
+ {
+ if (loggingEvents == null)
+ {
+ throw new
ArgumentNullException("loggingEvents");
+ }
+ if (loggingEvents.Length == 0)
+ {
+ throw new ArgumentException("loggingEvents
array must not be empty", "loggingEvents");
+ }
+ if (loggingEvents.Length == 1)
+ {
+ // Fall back to single event path
+ return AppendLoopOnAppenders(loggingEvents[0]);
+ }
+
+ // m_appenderList is null when empty
+ if (m_appenderList == null)
+ {
+ return 0;
+ }
+
+ if (m_appenderArray == null)
+ {
+ m_appenderArray = m_appenderList.ToArray();
+ }
+
+ foreach(IAppender appender in m_appenderArray)
+ {
+ try
+ {
+ CallAppend(appender, loggingEvents);
+ }
+ catch(Exception ex)
+ {
+ LogLog.Error("AppenderAttachedImpl:
Failed to append to appender [" + appender.Name + "]", ex);
+ }
+ }
+ return m_appenderList.Count;
+ }
+
#endregion Public Instance Methods
+ /// <summary>
+ /// Calls the DoAppende method on the <see cref="IAppender"/>
with
+ /// the <see cref="LoggingEvent"/> objects supplied.
+ /// </summary>
+ /// <param name="appender">The appender</param>
+ /// <param name="loggingEvents">The events</param>
+ /// <remarks>
+ /// <para>
+ /// If the <paramref name="appender" /> supports the <see
cref="IBulkAppender"/>
+ /// interface then the <paramref name="loggingEvents" /> will
be passed
+ /// through using that interface. Otherwise the <see
cref="LoggingEvent"/>
+ /// objects in the array will be passed one at a time.
+ /// </para>
+ /// </remarks>
+ private static void CallAppend(IAppender appender,
LoggingEvent[] loggingEvents)
+ {
+ IBulkAppender bulkAppender = appender as IBulkAppender;
+ if (bulkAppender != null)
+ {
+ bulkAppender.DoAppend(loggingEvents);
+ }
+ else
+ {
+ foreach(LoggingEvent loggingEvent in
loggingEvents)
+ {
+ appender.DoAppend(loggingEvent);
+ }
+ }
+ }
+
#region Implementation of IAppenderAttachable
/// <summary>