You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by bo...@apache.org on 2016/10/16 10:32:50 UTC

svn commit: r1765136 - in /logging/log4net/trunk/src: ./ Appender/ Repository/

Author: bodewig
Date: Sun Oct 16 10:32:49 2016
New Revision: 1765136

URL: http://svn.apache.org/viewvc?rev=1765136&view=rev
Log:
LOG4NET-511 Implement flushing of appenders that buffer data

Patch by @JJoe2

closes #37

Added:
    logging/log4net/trunk/src/Appender/IFlushable.cs   (with props)
Modified:
    logging/log4net/trunk/src/Appender/BufferingAppenderSkeleton.cs
    logging/log4net/trunk/src/Appender/DebugAppender.cs
    logging/log4net/trunk/src/Appender/RemotingAppender.cs
    logging/log4net/trunk/src/Appender/TextWriterAppender.cs
    logging/log4net/trunk/src/Appender/TraceAppender.cs
    logging/log4net/trunk/src/LogManager.cs
    logging/log4net/trunk/src/Repository/LoggerRepositorySkeleton.cs
    logging/log4net/trunk/src/log4net.vs2008.csproj
    logging/log4net/trunk/src/log4net.vs2010.csproj
    logging/log4net/trunk/src/log4net.vs2012.csproj

Modified: logging/log4net/trunk/src/Appender/BufferingAppenderSkeleton.cs
URL: http://svn.apache.org/viewvc/logging/log4net/trunk/src/Appender/BufferingAppenderSkeleton.cs?rev=1765136&r1=1765135&r2=1765136&view=diff
==============================================================================
--- logging/log4net/trunk/src/Appender/BufferingAppenderSkeleton.cs (original)
+++ logging/log4net/trunk/src/Appender/BufferingAppenderSkeleton.cs Sun Oct 16 10:32:49 2016
@@ -68,7 +68,7 @@ namespace log4net.Appender
 	/// </remarks>
 	/// <author>Nicko Cadell</author>
 	/// <author>Gert Driesen</author>
-	public abstract class BufferingAppenderSkeleton : AppenderSkeleton
+    public abstract class BufferingAppenderSkeleton : AppenderSkeleton, IFlushable
 	{
 		#region Protected Instance Constructors
 
@@ -261,6 +261,17 @@ namespace log4net.Appender
 
 		#region Public Methods
 
+        /// <summary>
+        /// Flushes any buffered log data.
+        /// </summary>
+        /// <param name="millisecondsTimeout">The maximum time to wait for logging events to be flushed.</param>
+        /// <returns><c>True</c> if all logging events were flushed successfully, else <c>false</c>.</returns>
+        public virtual bool Flush(int millisecondsTimeout)
+        {
+            Flush();
+            return true;
+        }
+
 		/// <summary>
 		/// Flush the currently buffered events
 		/// </summary>

Modified: logging/log4net/trunk/src/Appender/DebugAppender.cs
URL: http://svn.apache.org/viewvc/logging/log4net/trunk/src/Appender/DebugAppender.cs?rev=1765136&r1=1765135&r2=1765136&view=diff
==============================================================================
--- logging/log4net/trunk/src/Appender/DebugAppender.cs (original)
+++ logging/log4net/trunk/src/Appender/DebugAppender.cs Sun Oct 16 10:32:49 2016
@@ -40,7 +40,7 @@ namespace log4net.Appender
 	/// </para>
 	/// </remarks>
 	/// <author>Nicko Cadell</author>
-	public class DebugAppender : AppenderSkeleton
+    public class DebugAppender : AppenderSkeleton, IFlushable
 	{
 		#region Public Instance Constructors
 
@@ -102,6 +102,23 @@ namespace log4net.Appender
 
 		#endregion Public Instance Properties
 
+
+            /// <summary>
+            /// Flushes any buffered log data.
+            /// </summary>
+            /// <param name="millisecondsTimeout">The maximum time to wait for logging events to be flushed.</param>
+            /// <returns><c>True</c> if all logging events were flushed successfully, else <c>false</c>.</returns>
+            public bool Flush(int millisecondsTimeout)
+            {
+                // Nothing to do if ImmediateFlush is true
+                if (m_immediateFlush) return true;
+
+                // System.Diagnostics.Debug is thread-safe, so no need for lock(this).
+                System.Diagnostics.Debug.Flush();
+
+                return true;
+            }
+
 		#region Override implementation of AppenderSkeleton
 
 		/// <summary>

Added: logging/log4net/trunk/src/Appender/IFlushable.cs
URL: http://svn.apache.org/viewvc/logging/log4net/trunk/src/Appender/IFlushable.cs?rev=1765136&view=auto
==============================================================================
--- logging/log4net/trunk/src/Appender/IFlushable.cs (added)
+++ logging/log4net/trunk/src/Appender/IFlushable.cs Sun Oct 16 10:32:49 2016
@@ -0,0 +1,44 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace log4net.Appender
+{
+    /// <summary>
+    /// Interface that can be implemented by Appenders that buffer logging data and expose a <see cref="Flush"/> method.
+    /// </summary>
+    public interface IFlushable
+    {
+        /// <summary>
+        /// Flushes any buffered log data.
+        /// </summary>
+        /// <remarks>
+        /// Appenders that implement the <see cref="Flush"/> method must do so in a thread-safe manner: it can be called concurrently with
+        /// the <see cref="log4net.Appender.IAppender.DoAppend"/> method.
+        /// <para>
+        /// Typically this is done by locking on the Appender instance, e.g.:
+        /// <code>
+        /// <![CDATA[
+        /// public bool Flush(int millisecondsTimeout)
+        /// {
+        ///     lock(this)
+        ///     {
+        ///         // Flush buffered logging data
+        ///         ...
+        ///     }
+        /// }
+        /// ]]>
+        /// </code>
+        /// </para>
+        /// <para>
+        /// The <paramref name="millisecondsTimeout"/> parameter is only relevant for appenders that process logging events asynchronously,
+        /// such as <see cref="RemotingAppender"/>.
+        /// </para>
+        /// </remarks>
+        /// <param name="millisecondsTimeout">The maximum time to wait for logging events to be flushed.</param>
+        /// <returns><c>True</c> if all logging events were flushed successfully, else <c>false</c>.</returns>
+        bool Flush(int millisecondsTimeout);
+    }
+}

Propchange: logging/log4net/trunk/src/Appender/IFlushable.cs
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: logging/log4net/trunk/src/Appender/RemotingAppender.cs
URL: http://svn.apache.org/viewvc/logging/log4net/trunk/src/Appender/RemotingAppender.cs?rev=1765136&r1=1765135&r2=1765136&view=diff
==============================================================================
--- logging/log4net/trunk/src/Appender/RemotingAppender.cs (original)
+++ logging/log4net/trunk/src/Appender/RemotingAppender.cs Sun Oct 16 10:32:49 2016
@@ -218,6 +218,17 @@ namespace log4net.Appender
 			}
 		}
 
+		/// <summary>
+		/// Flushes any buffered log data.
+		/// </summary>
+		/// <param name="millisecondsTimeout">The maximum time to wait for logging events to be flushed.</param>
+		/// <returns><c>True</c> if all logging events were flushed successfully, else <c>false</c>.</returns>
+		public override bool Flush(int millisecondsTimeout)
+		{
+			base.Flush();
+			return m_workQueueEmptyEvent.WaitOne(millisecondsTimeout, false);
+		}
+
 		#endregion
 
 		/// <summary>

Modified: logging/log4net/trunk/src/Appender/TextWriterAppender.cs
URL: http://svn.apache.org/viewvc/logging/log4net/trunk/src/Appender/TextWriterAppender.cs?rev=1765136&r1=1765135&r2=1765136&view=diff
==============================================================================
--- logging/log4net/trunk/src/Appender/TextWriterAppender.cs (original)
+++ logging/log4net/trunk/src/Appender/TextWriterAppender.cs Sun Oct 16 10:32:49 2016
@@ -42,7 +42,7 @@ namespace log4net.Appender
 	/// <author>Nicko Cadell</author>
 	/// <author>Gert Driesen</author>
 	/// <author>Douglas de la Torre</author>
-	public class TextWriterAppender : AppenderSkeleton
+    public class TextWriterAppender : AppenderSkeleton, IFlushable
 	{
 		#region Public Instance Constructors
 
@@ -481,5 +481,24 @@ namespace log4net.Appender
 	    private readonly static Type declaringType = typeof(TextWriterAppender);
 
 	    #endregion Private Static Fields
+
+            /// <summary>
+            /// Flushes any buffered log data.
+            /// </summary>
+            /// <param name="millisecondsTimeout">The maximum time to wait for logging events to be flushed.</param>
+            /// <returns><c>True</c> if all logging events were flushed successfully, else <c>false</c>.</returns>
+            public bool Flush(int millisecondsTimeout)
+            {
+                // Nothing to do if ImmediateFlush is true
+                if (m_immediateFlush) return true;
+
+                // lock(this) will block any Appends while the buffer is flushed.
+                lock (this)
+                {
+                    m_qtw.Flush();
+                }
+
+                return true;
+            }
 	}
 }

Modified: logging/log4net/trunk/src/Appender/TraceAppender.cs
URL: http://svn.apache.org/viewvc/logging/log4net/trunk/src/Appender/TraceAppender.cs?rev=1765136&r1=1765135&r2=1765136&view=diff
==============================================================================
--- logging/log4net/trunk/src/Appender/TraceAppender.cs (original)
+++ logging/log4net/trunk/src/Appender/TraceAppender.cs Sun Oct 16 10:32:49 2016
@@ -51,7 +51,7 @@ namespace log4net.Appender
 	/// <author>Nicko Cadell</author>
 	/// <author>Gert Driesen</author>
     /// <author>Ron Grabowski</author>
-	public class TraceAppender : AppenderSkeleton
+	public class TraceAppender : AppenderSkeleton, IFlushable
 	{
 		#region Public Instance Constructors
 
@@ -206,5 +206,24 @@ namespace log4net.Appender
         private PatternLayout m_category = new PatternLayout("%logger");
 
 		#endregion Private Instance Fields
-	}
+
+        /// <summary>
+        /// Flushes any buffered log data.
+        /// </summary>
+        /// <param name="millisecondsTimeout">The maximum time to wait for logging events to be flushed.</param>
+        /// <returns><c>True</c> if all logging events were flushed successfully, else <c>false</c>.</returns>
+        public bool Flush(int millisecondsTimeout)
+        {
+            // Nothing to do if ImmediateFlush is true
+            if (m_immediateFlush) return true;
+
+            // System.Diagnostics.Trace and System.Diagnostics.Debug are thread-safe, so no need for lock(this).
+#if NETCF
+			System.Diagnostics.Debug.Flush();
+#else
+            System.Diagnostics.Trace.Flush();
+#endif
+            return true;
+        }
+    }
 }

Modified: logging/log4net/trunk/src/LogManager.cs
URL: http://svn.apache.org/viewvc/logging/log4net/trunk/src/LogManager.cs?rev=1765136&r1=1765135&r2=1765136&view=diff
==============================================================================
--- logging/log4net/trunk/src/LogManager.cs (original)
+++ logging/log4net/trunk/src/LogManager.cs Sun Oct 16 10:32:49 2016
@@ -751,6 +751,25 @@ namespace log4net
 			return LoggerManager.GetAllRepositories();
 		}
 
+            /// <summary>
+            /// Flushes logging events buffered in all configured appenders in the default repository.
+            /// </summary>
+            /// <param name="millisecondsTimeout">The maximum time in milliseconds to wait for logging events from asycnhronous appenders to be flushed,
+            /// or <see cref="Timeout.Infinite"/> to wait indefinitely.</param>
+            /// <returns><c>True</c> if all logging events were flushed successfully, else <c>false</c>.</returns>
+            public static bool Flush(int millisecondsTimeout)
+            {
+                Appender.IFlushable flushableRepository = LoggerManager.GetRepository(Assembly.GetCallingAssembly()) as Appender.IFlushable;
+                if (flushableRepository == null)
+                {
+                    return false;
+                }
+                else
+                {
+                    return flushableRepository.Flush(millisecondsTimeout);
+                }
+            }
+
 		#endregion Domain & Repository Manager Methods
 
 		#region Extension Handlers

Modified: logging/log4net/trunk/src/Repository/LoggerRepositorySkeleton.cs
URL: http://svn.apache.org/viewvc/logging/log4net/trunk/src/Repository/LoggerRepositorySkeleton.cs?rev=1765136&r1=1765135&r2=1765136&view=diff
==============================================================================
--- logging/log4net/trunk/src/Repository/LoggerRepositorySkeleton.cs (original)
+++ logging/log4net/trunk/src/Repository/LoggerRepositorySkeleton.cs Sun Oct 16 10:32:49 2016
@@ -23,6 +23,7 @@ using log4net.ObjectRenderer;
 using log4net.Core;
 using log4net.Util;
 using log4net.Plugin;
+using System.Threading;
 
 namespace log4net.Repository
 {
@@ -40,7 +41,7 @@ namespace log4net.Repository
 	/// </remarks>
 	/// <author>Nicko Cadell</author>
 	/// <author>Gert Driesen</author>
-	public abstract class LoggerRepositorySkeleton : ILoggerRepository
+	public abstract class LoggerRepositorySkeleton : ILoggerRepository, Appender.IFlushable
 	{
 		#region Member Variables
 
@@ -573,5 +574,59 @@ namespace log4net.Repository
 		{
 			OnConfigurationChanged(e);
 		}
+
+        private static int GetWaitTime(DateTime startTimeUtc, int millisecondsTimeout)
+        {
+            if (millisecondsTimeout == Timeout.Infinite) return Timeout.Infinite;
+            if (millisecondsTimeout == 0) return 0;
+
+            int elapsedMilliseconds = (int)(DateTime.UtcNow - startTimeUtc).TotalMilliseconds;
+            int timeout = millisecondsTimeout - elapsedMilliseconds;
+            if (timeout < 0) timeout = 0;
+            return timeout;
+        }
+
+        /// <summary>
+        /// Flushes all configured Appenders that implement <see cref="log4net.Appender.IFlushable"/>.
+        /// </summary>
+        /// <param name="millisecondsTimeout">The maximum time in milliseconds to wait for logging events from asycnhronous appenders to be flushed,
+        /// or <see cref="Timeout.Infinite"/> to wait indefinitely.</param>
+        /// <returns><c>True</c> if all logging events were flushed successfully, else <c>false</c>.</returns>
+        public bool Flush(int millisecondsTimeout)
+        {
+            if (millisecondsTimeout < -1) throw new ArgumentOutOfRangeException("millisecondsTimeout", "Timeout must be -1 (Timeout.Infinite) or non-negative");
+
+            // Assume success until one of the appenders fails
+            bool result = true;
+
+            // Use DateTime.UtcNow rather than a System.Diagnostics.Stopwatch for compatibility with .NET 1.x
+            DateTime startTimeUtc = DateTime.UtcNow;
+
+            // Do buffering appenders first.  These may be forwarding to other appenders
+            foreach(var appender in GetAppenders())
+            {
+                log4net.Appender.IFlushable flushable = appender as log4net.Appender.IFlushable;
+                if (flushable == null) continue;
+                if (appender is Appender.BufferingAppenderSkeleton)
+                {
+                    int timeout = GetWaitTime(startTimeUtc, millisecondsTimeout);
+                    if (!flushable.Flush(timeout)) result = false;
+                }
+            }
+
+            // Do non-buffering appenders.
+            foreach (var appender in GetAppenders())
+            {
+                log4net.Appender.IFlushable flushable = appender as log4net.Appender.IFlushable;
+                if (flushable == null) continue;
+                if (!(appender is Appender.BufferingAppenderSkeleton))
+                {
+                    int timeout = GetWaitTime(startTimeUtc, millisecondsTimeout);
+                    if (!flushable.Flush(timeout)) result = false;
+                }
+            }
+
+            return result;
+        }
 	}
 }

Modified: logging/log4net/trunk/src/log4net.vs2008.csproj
URL: http://svn.apache.org/viewvc/logging/log4net/trunk/src/log4net.vs2008.csproj?rev=1765136&r1=1765135&r2=1765136&view=diff
==============================================================================
--- logging/log4net/trunk/src/log4net.vs2008.csproj (original)
+++ logging/log4net/trunk/src/log4net.vs2008.csproj Sun Oct 16 10:32:49 2016
@@ -148,6 +148,9 @@
     <Compile Include="Appender\IBulkAppender.cs">
       <SubType>Code</SubType>
     </Compile>
+    <Compile Include="Appender\IFlushable.cs">
+      <SubType>Code</SubType>
+    </Compile>
     <Compile Include="Appender\LocalSyslogAppender.cs">
       <SubType>Code</SubType>
     </Compile>

Modified: logging/log4net/trunk/src/log4net.vs2010.csproj
URL: http://svn.apache.org/viewvc/logging/log4net/trunk/src/log4net.vs2010.csproj?rev=1765136&r1=1765135&r2=1765136&view=diff
==============================================================================
--- logging/log4net/trunk/src/log4net.vs2010.csproj (original)
+++ logging/log4net/trunk/src/log4net.vs2010.csproj Sun Oct 16 10:32:49 2016
@@ -166,6 +166,9 @@
     <Compile Include="Appender\IBulkAppender.cs">
       <SubType>Code</SubType>
     </Compile>
+    <Compile Include="Appender\IFlushable.cs">
+      <SubType>Code</SubType>
+    </Compile>
     <Compile Include="Appender\LocalSyslogAppender.cs">
       <SubType>Code</SubType>
     </Compile>

Modified: logging/log4net/trunk/src/log4net.vs2012.csproj
URL: http://svn.apache.org/viewvc/logging/log4net/trunk/src/log4net.vs2012.csproj?rev=1765136&r1=1765135&r2=1765136&view=diff
==============================================================================
--- logging/log4net/trunk/src/log4net.vs2012.csproj (original)
+++ logging/log4net/trunk/src/log4net.vs2012.csproj Sun Oct 16 10:32:49 2016
@@ -166,6 +166,9 @@
     <Compile Include="Appender\IBulkAppender.cs">
       <SubType>Code</SubType>
     </Compile>
+    <Compile Include="Appender\IFlushable.cs">
+      <SubType>Code</SubType>
+    </Compile>
     <Compile Include="Appender\LocalSyslogAppender.cs">
       <SubType>Code</SubType>
     </Compile>