diff --git a/src/Umbraco.Core/Logging/AppDomainTokenFormatter.cs b/src/Umbraco.Core/Logging/AppDomainTokenConverter.cs
similarity index 100%
rename from src/Umbraco.Core/Logging/AppDomainTokenFormatter.cs
rename to src/Umbraco.Core/Logging/AppDomainTokenConverter.cs
diff --git a/src/Umbraco.Core/Logging/AsyncForwardingAppenderBase.cs b/src/Umbraco.Core/Logging/AsyncForwardingAppenderBase.cs
new file mode 100644
index 0000000000..74a1de81f4
--- /dev/null
+++ b/src/Umbraco.Core/Logging/AsyncForwardingAppenderBase.cs
@@ -0,0 +1,105 @@
+using System;
+using log4net.Appender;
+using log4net.Core;
+using log4net.Util;
+
+namespace Umbraco.Core.Logging
+{
+ ///
+ /// Based on https://github.com/cjbhaines/Log4Net.Async
+ ///
+ public abstract class AsyncForwardingAppenderBase : ForwardingAppender
+ {
+ #region Private Members
+
+ private const FixFlags DefaultFixFlags = FixFlags.Partial;
+ private FixFlags _fixFlags = DefaultFixFlags;
+ private LoggingEventHelper _loggingEventHelper;
+
+ #endregion Private Members
+
+ #region Properties
+
+ public FixFlags Fix
+ {
+ get { return _fixFlags; }
+ set { SetFixFlags(value); }
+ }
+
+ ///
+ /// The logger name that will be used for logging internal errors.
+ ///
+ protected abstract string InternalLoggerName { get; }
+
+ public abstract int? BufferSize { get; set; }
+
+ #endregion Properties
+
+ public override void ActivateOptions()
+ {
+ base.ActivateOptions();
+ _loggingEventHelper = new LoggingEventHelper(InternalLoggerName, DefaultFixFlags);
+ InitializeAppenders();
+ }
+
+ #region Appender Management
+
+ public override void AddAppender(IAppender newAppender)
+ {
+ base.AddAppender(newAppender);
+ SetAppenderFixFlags(newAppender);
+ }
+
+ private void SetFixFlags(FixFlags newFixFlags)
+ {
+ if (newFixFlags != _fixFlags)
+ {
+ _loggingEventHelper.Fix = newFixFlags;
+ _fixFlags = newFixFlags;
+ InitializeAppenders();
+ }
+ }
+
+ private void InitializeAppenders()
+ {
+ foreach (var appender in Appenders)
+ {
+ SetAppenderFixFlags(appender);
+ }
+ }
+
+ private void SetAppenderFixFlags(IAppender appender)
+ {
+ var bufferingAppender = appender as BufferingAppenderSkeleton;
+ if (bufferingAppender != null)
+ {
+ bufferingAppender.Fix = Fix;
+ }
+ }
+
+ #endregion Appender Management
+
+ #region Forwarding
+
+ protected void ForwardInternalError(string message, Exception exception, Type thisType)
+ {
+ LogLog.Error(thisType, message, exception);
+ var loggingEvent = _loggingEventHelper.CreateLoggingEvent(Level.Error, message, exception);
+ ForwardLoggingEvent(loggingEvent, thisType);
+ }
+
+ protected void ForwardLoggingEvent(LoggingEvent loggingEvent, Type thisType)
+ {
+ try
+ {
+ base.Append(loggingEvent);
+ }
+ catch (Exception exception)
+ {
+ LogLog.Error(thisType, "Unable to forward logging event", exception);
+ }
+ }
+
+ #endregion Forwarding
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Logging/AsynchronousRollingFileAppender.cs b/src/Umbraco.Core/Logging/AsynchronousRollingFileAppender.cs
index 56d04c8426..cb58ebbfaa 100644
--- a/src/Umbraco.Core/Logging/AsynchronousRollingFileAppender.cs
+++ b/src/Umbraco.Core/Logging/AsynchronousRollingFileAppender.cs
@@ -1,276 +1,276 @@
+using log4net.Core;
+using log4net.Util;
using System;
+using System.Runtime.Remoting.Messaging;
using System.Security.Principal;
using System.Threading;
using System.Threading.Tasks;
using log4net.Appender;
-using log4net.Core;
-using log4net.Util;
namespace Umbraco.Core.Logging
{
- ///
- /// Based on code by Chris Haines http://cjbhaines.wordpress.com/2012/02/13/asynchronous-log4net-appenders/
+ ///
+ /// Based on https://github.com/cjbhaines/Log4Net.Async
+ /// which is based on code by Chris Haines http://cjbhaines.wordpress.com/2012/02/13/asynchronous-log4net-appenders/
///
public class AsynchronousRollingFileAppender : RollingFileAppender
{
- private readonly ManualResetEvent _manualResetEvent;
- private int _bufferOverflowCounter;
- private bool _forceStop;
- private bool _hasFinished;
- private DateTime _lastLoggedBufferOverflow;
- private bool _logBufferOverflow;
- private RingBuffer _pendingAppends;
- private int _queueSizeLimit = 1000;
- private bool _shuttingDown;
+ private RingBuffer pendingAppends;
+ private readonly ManualResetEvent manualResetEvent;
+ private bool shuttingDown;
+ private bool hasFinished;
+ private bool forceStop;
+ private bool logBufferOverflow;
+ private int bufferOverflowCounter;
+ private DateTime lastLoggedBufferOverflow;
+ private int queueSizeLimit = 1000;
+ public int QueueSizeLimit
+ {
+ get
+ {
+ return queueSizeLimit;
+ }
+ set
+ {
+ queueSizeLimit = value;
+ }
+ }
- public AsynchronousRollingFileAppender()
- {
- _manualResetEvent = new ManualResetEvent(false);
- }
+ public AsynchronousRollingFileAppender()
+ {
+ manualResetEvent = new ManualResetEvent(false);
+ }
- public int QueueSizeLimit
- {
- get { return _queueSizeLimit; }
- set { _queueSizeLimit = value; }
- }
+ public override void ActivateOptions()
+ {
+ base.ActivateOptions();
+ pendingAppends = new RingBuffer(QueueSizeLimit);
+ pendingAppends.BufferOverflow += OnBufferOverflow;
+ StartAppendTask();
+ }
- public override void ActivateOptions()
- {
- base.ActivateOptions();
- _pendingAppends = new RingBuffer(QueueSizeLimit);
- _pendingAppends.BufferOverflow += OnBufferOverflow;
- StartAppendTask();
- }
+ protected override void Append(LoggingEvent[] loggingEvents)
+ {
+ Array.ForEach(loggingEvents, Append);
+ }
- protected override void Append(LoggingEvent[] loggingEvents)
- {
- Array.ForEach(loggingEvents, Append);
- }
+ protected override void Append(LoggingEvent loggingEvent)
+ {
+ if (FilterEvent(loggingEvent))
+ {
+ pendingAppends.Enqueue(loggingEvent);
+ }
+ }
- protected override void Append(LoggingEvent loggingEvent)
- {
- if (FilterEvent(loggingEvent))
- {
- _pendingAppends.Enqueue(loggingEvent);
- }
- }
+ protected override void OnClose()
+ {
+ shuttingDown = true;
+ manualResetEvent.WaitOne(TimeSpan.FromSeconds(5));
- protected override void OnClose()
- {
- _shuttingDown = true;
- _manualResetEvent.WaitOne(TimeSpan.FromSeconds(5));
+ if (!hasFinished)
+ {
+ forceStop = true;
+ base.Append(new LoggingEvent(new LoggingEventData
+ {
+ Level = Level.Error,
+ Message = "Unable to clear out the AsyncRollingFileAppender buffer in the allotted time, forcing a shutdown",
+ TimeStamp = DateTime.UtcNow,
+ Identity = "",
+ ExceptionString = "",
+ UserName = WindowsIdentity.GetCurrent() != null ? WindowsIdentity.GetCurrent().Name : "",
+ Domain = AppDomain.CurrentDomain.FriendlyName,
+ ThreadName = Thread.CurrentThread.ManagedThreadId.ToString(),
+ LocationInfo = new LocationInfo(this.GetType().Name, "OnClose", "AsyncRollingFileAppender.cs", "75"),
+ LoggerName = this.GetType().FullName,
+ Properties = new PropertiesDictionary(),
+ })
+ );
+ }
- if (!_hasFinished)
- {
- _forceStop = true;
- var windowsIdentity = WindowsIdentity.GetCurrent();
+ base.OnClose();
+ }
- var logEvent = new LoggingEvent(new LoggingEventData
- {
- Level = global::log4net.Core.Level.Error,
- Message =
- "Unable to clear out the AsynchronousRollingFileAppender buffer in the allotted time, forcing a shutdown",
- TimeStamp = DateTime.UtcNow,
- Identity = "",
- ExceptionString = "",
- UserName = windowsIdentity != null ? windowsIdentity.Name : "",
- Domain = AppDomain.CurrentDomain.FriendlyName,
- ThreadName = Thread.CurrentThread.ManagedThreadId.ToString(),
- LocationInfo =
- new LocationInfo(this.GetType().Name, "OnClose", "AsynchronousRollingFileAppender.cs", "59"),
- LoggerName = this.GetType().FullName,
- Properties = new PropertiesDictionary(),
- });
+ private void StartAppendTask()
+ {
+ if (!shuttingDown)
+ {
+ Task appendTask = new Task(AppendLoggingEvents, TaskCreationOptions.LongRunning);
+ appendTask.LogErrors(LogAppenderError).ContinueWith(x => StartAppendTask()).LogErrors(LogAppenderError);
+ appendTask.Start();
+ }
+ }
- if (this.DateTimeStrategy != null)
- {
- base.Append(logEvent);
- }
- }
+ private void LogAppenderError(string logMessage, Exception exception)
+ {
+ base.Append(new LoggingEvent(new LoggingEventData
+ {
+ Level = Level.Error,
+ Message = "Appender exception: " + logMessage,
+ TimeStamp = DateTime.UtcNow,
+ Identity = "",
+ ExceptionString = exception.ToString(),
+ UserName = WindowsIdentity.GetCurrent() != null ? WindowsIdentity.GetCurrent().Name : "",
+ Domain = AppDomain.CurrentDomain.FriendlyName,
+ ThreadName = Thread.CurrentThread.ManagedThreadId.ToString(),
+ LocationInfo = new LocationInfo(this.GetType().Name, "LogAppenderError", "AsyncRollingFileAppender.cs", "152"),
+ LoggerName = this.GetType().FullName,
+ Properties = new PropertiesDictionary(),
+ }));
+ }
- base.OnClose();
- }
+ private void AppendLoggingEvents()
+ {
+ LoggingEvent loggingEventToAppend;
+ while (!shuttingDown)
+ {
+ if (logBufferOverflow)
+ {
+ LogBufferOverflowError();
+ logBufferOverflow = false;
+ bufferOverflowCounter = 0;
+ lastLoggedBufferOverflow = DateTime.UtcNow;
+ }
- private void StartAppendTask()
- {
- if (!_shuttingDown)
- {
- Task appendTask = new Task(AppendLoggingEvents, TaskCreationOptions.LongRunning);
- appendTask.LogErrors(LogAppenderError).ContinueWith(x => StartAppendTask()).LogErrors(LogAppenderError);
- appendTask.Start();
- }
- }
+ while (!pendingAppends.TryDequeue(out loggingEventToAppend))
+ {
+ Thread.Sleep(10);
+ if (shuttingDown)
+ {
+ break;
+ }
+ }
+ if (loggingEventToAppend == null)
+ {
+ continue;
+ }
- private void LogAppenderError(string logMessage, Exception exception)
- {
- var windowsIdentity = WindowsIdentity.GetCurrent();
- base.Append(new LoggingEvent(new LoggingEventData
- {
- Level = Level.Error,
- Message = "Appender exception: " + logMessage,
- TimeStamp = DateTime.UtcNow,
- Identity = "",
- ExceptionString = exception.ToString(),
- UserName = windowsIdentity != null ? windowsIdentity.Name : "",
- Domain = AppDomain.CurrentDomain.FriendlyName,
- ThreadName = Thread.CurrentThread.ManagedThreadId.ToString(),
- LocationInfo =
- new LocationInfo(this.GetType().Name,
- "LogAppenderError",
- "AsynchronousRollingFileAppender.cs",
- "100"),
- LoggerName = this.GetType().FullName,
- Properties = new PropertiesDictionary(),
- }));
- }
+ try
+ {
+ base.Append(loggingEventToAppend);
+ }
+ catch
+ {
+ }
+ }
- private void AppendLoggingEvents()
- {
- LoggingEvent loggingEventToAppend;
- while (!_shuttingDown)
- {
- if (_logBufferOverflow)
- {
- LogBufferOverflowError();
- _logBufferOverflow = false;
- _bufferOverflowCounter = 0;
- _lastLoggedBufferOverflow = DateTime.UtcNow;
- }
+ while (pendingAppends.TryDequeue(out loggingEventToAppend) && !forceStop)
+ {
+ try
+ {
+ base.Append(loggingEventToAppend);
+ }
+ catch
+ {
+ }
+ }
+ hasFinished = true;
+ manualResetEvent.Set();
+ }
- while (!_pendingAppends.TryDequeue(out loggingEventToAppend))
- {
- Thread.Sleep(10);
- if (_shuttingDown)
- {
- break;
- }
- }
- if (loggingEventToAppend == null)
- {
- continue;
- }
+ private void LogBufferOverflowError()
+ {
+ base.Append(new LoggingEvent(new LoggingEventData
+ {
+ Level = Level.Error,
+ Message = string.Format("Buffer overflow. {0} logging events have been lost in the last 30 seconds. [QueueSizeLimit: {1}]", bufferOverflowCounter, QueueSizeLimit),
+ TimeStamp = DateTime.UtcNow,
+ Identity = "",
+ ExceptionString = "",
+ UserName = WindowsIdentity.GetCurrent() != null ? WindowsIdentity.GetCurrent().Name : "",
+ Domain = AppDomain.CurrentDomain.FriendlyName,
+ ThreadName = Thread.CurrentThread.ManagedThreadId.ToString(),
+ LocationInfo = new LocationInfo(this.GetType().Name, "LogBufferOverflowError", "AsyncRollingFileAppender.cs", "152"),
+ LoggerName = this.GetType().FullName,
+ Properties = new PropertiesDictionary(),
+ }));
+ }
- try
- {
- base.Append(loggingEventToAppend);
- }
- catch
- {
- }
- }
+ private void OnBufferOverflow(object sender, EventArgs eventArgs)
+ {
+ bufferOverflowCounter++;
+ if (logBufferOverflow == false)
+ {
+ if (lastLoggedBufferOverflow < DateTime.UtcNow.AddSeconds(-30))
+ {
+ logBufferOverflow = true;
+ }
+ }
+ }
+ }
- while (_pendingAppends.TryDequeue(out loggingEventToAppend) && !_forceStop)
- {
- try
- {
- base.Append(loggingEventToAppend);
- }
- catch
- {
- }
- }
- _hasFinished = true;
- _manualResetEvent.Set();
- }
+ internal interface IQueue
+ {
+ void Enqueue(T item);
+ bool TryDequeue(out T ret);
+ }
- private void LogBufferOverflowError()
- {
- var windowsIdentity = WindowsIdentity.GetCurrent();
- base.Append(new LoggingEvent(new LoggingEventData
- {
- Level = Level.Error,
- Message =
- string.Format(
- "Buffer overflow. {0} logging events have been lost in the last 30 seconds. [QueueSizeLimit: {1}]",
- _bufferOverflowCounter,
- QueueSizeLimit),
- TimeStamp = DateTime.UtcNow,
- Identity = "",
- ExceptionString = "",
- UserName = windowsIdentity != null ? windowsIdentity.Name : "",
- Domain = AppDomain.CurrentDomain.FriendlyName,
- ThreadName = Thread.CurrentThread.ManagedThreadId.ToString(),
- LocationInfo =
- new LocationInfo(this.GetType().Name,
- "LogBufferOverflowError",
- "AsynchronousRollingFileAppender.cs",
- "172"),
- LoggerName = this.GetType().FullName,
- Properties = new PropertiesDictionary(),
- }));
- }
+ internal class RingBuffer : IQueue
+ {
+ private readonly object lockObject = new object();
+ private readonly T[] buffer;
+ private readonly int size;
+ private int readIndex = 0;
+ private int writeIndex = 0;
+ private bool bufferFull = false;
- private void OnBufferOverflow(object sender, EventArgs eventArgs)
- {
- _bufferOverflowCounter++;
- if (_logBufferOverflow == false)
- {
- if (_lastLoggedBufferOverflow < DateTime.UtcNow.AddSeconds(-30))
- {
- _logBufferOverflow = true;
- }
- }
- }
+ public int Size { get { return size; } }
- private class RingBuffer
- {
- private readonly object _lockObject = new object();
- private readonly T[] _buffer;
- private readonly int _size;
- private int _readIndex = 0;
- private int _writeIndex = 0;
- private bool _bufferFull = false;
+ public event Action