Added Log4Net and supporting classes from v5 in order to start integration of new diagnostic logging system.
This commit is contained in:
271
src/Umbraco.Core/Logging/AsynchronousRollingFileAppender.cs
Normal file
271
src/Umbraco.Core/Logging/AsynchronousRollingFileAppender.cs
Normal file
@@ -0,0 +1,271 @@
|
||||
using System;
|
||||
using System.Security.Principal;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using log4net.Appender;
|
||||
using log4net.Core;
|
||||
using log4net.Util;
|
||||
|
||||
namespace Umbraco.Core.Logging
|
||||
{
|
||||
/// <summary>
|
||||
/// Based on code by Chris Haines http://cjbhaines.wordpress.com/2012/02/13/asynchronous-log4net-appenders/
|
||||
/// </summary>
|
||||
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<LoggingEvent> _pendingAppends;
|
||||
private int _queueSizeLimit = 1000;
|
||||
private bool _shuttingDown;
|
||||
|
||||
public AsynchronousRollingFileAppender()
|
||||
{
|
||||
_manualResetEvent = new ManualResetEvent(false);
|
||||
}
|
||||
|
||||
public int QueueSizeLimit
|
||||
{
|
||||
get { return _queueSizeLimit; }
|
||||
set { _queueSizeLimit = value; }
|
||||
}
|
||||
|
||||
public override void ActivateOptions()
|
||||
{
|
||||
base.ActivateOptions();
|
||||
_pendingAppends = new RingBuffer<LoggingEvent>(QueueSizeLimit);
|
||||
_pendingAppends.BufferOverflow += OnBufferOverflow;
|
||||
StartAppendTask();
|
||||
}
|
||||
|
||||
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 OnClose()
|
||||
{
|
||||
_shuttingDown = true;
|
||||
_manualResetEvent.WaitOne(TimeSpan.FromSeconds(5));
|
||||
|
||||
if (!_hasFinished)
|
||||
{
|
||||
_forceStop = true;
|
||||
var windowsIdentity = WindowsIdentity.GetCurrent();
|
||||
base.Append(new LoggingEvent(new LoggingEventData
|
||||
{
|
||||
Level = 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(),
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
base.OnClose();
|
||||
}
|
||||
|
||||
private void StartAppendTask()
|
||||
{
|
||||
if (!_shuttingDown)
|
||||
{
|
||||
Task appendTask = new Task(AppendLoggingEvents, TaskCreationOptions.LongRunning);
|
||||
appendTask.LogErrors(LogAppenderError).ContinueWith(x => StartAppendTask()).LogErrors(LogAppenderError);
|
||||
appendTask.Start();
|
||||
}
|
||||
}
|
||||
|
||||
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(),
|
||||
}));
|
||||
}
|
||||
|
||||
private void AppendLoggingEvents()
|
||||
{
|
||||
LoggingEvent loggingEventToAppend;
|
||||
while (!_shuttingDown)
|
||||
{
|
||||
if (_logBufferOverflow)
|
||||
{
|
||||
LogBufferOverflowError();
|
||||
_logBufferOverflow = false;
|
||||
_bufferOverflowCounter = 0;
|
||||
_lastLoggedBufferOverflow = DateTime.UtcNow;
|
||||
}
|
||||
|
||||
while (!_pendingAppends.TryDequeue(out loggingEventToAppend))
|
||||
{
|
||||
Thread.Sleep(10);
|
||||
if (_shuttingDown)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (loggingEventToAppend == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
base.Append(loggingEventToAppend);
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
while (_pendingAppends.TryDequeue(out loggingEventToAppend) && !_forceStop)
|
||||
{
|
||||
try
|
||||
{
|
||||
base.Append(loggingEventToAppend);
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
_hasFinished = true;
|
||||
_manualResetEvent.Set();
|
||||
}
|
||||
|
||||
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(),
|
||||
}));
|
||||
}
|
||||
|
||||
private void OnBufferOverflow(object sender, EventArgs eventArgs)
|
||||
{
|
||||
_bufferOverflowCounter++;
|
||||
if (_logBufferOverflow == false)
|
||||
{
|
||||
if (_lastLoggedBufferOverflow < DateTime.UtcNow.AddSeconds(-30))
|
||||
{
|
||||
_logBufferOverflow = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class RingBuffer<T>
|
||||
{
|
||||
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<object, EventArgs> BufferOverflow;
|
||||
|
||||
public RingBuffer(int size)
|
||||
{
|
||||
this._size = size;
|
||||
_buffer = new T[size];
|
||||
}
|
||||
|
||||
public void Enqueue(T item)
|
||||
{
|
||||
lock (_lockObject)
|
||||
{
|
||||
_buffer[_writeIndex] = item;
|
||||
_writeIndex = (++_writeIndex) % _size;
|
||||
if (_bufferFull)
|
||||
{
|
||||
if (BufferOverflow != null)
|
||||
{
|
||||
BufferOverflow(this, EventArgs.Empty);
|
||||
}
|
||||
_readIndex = _writeIndex;
|
||||
}
|
||||
else if (_writeIndex == _readIndex)
|
||||
{
|
||||
_bufferFull = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool TryDequeue(out T ret)
|
||||
{
|
||||
if (_readIndex == _writeIndex && !_bufferFull)
|
||||
{
|
||||
ret = default(T);
|
||||
return false;
|
||||
}
|
||||
lock (_lockObject)
|
||||
{
|
||||
if (_readIndex == _writeIndex && !_bufferFull)
|
||||
{
|
||||
ret = default(T);
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = _buffer[_readIndex];
|
||||
_readIndex = (++_readIndex) % _size;
|
||||
_bufferFull = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,153 +1,156 @@
|
||||
//using System;
|
||||
//using System.Collections.Generic;
|
||||
//using System.Linq;
|
||||
//using System.Text;
|
||||
//using System.Threading;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using log4net;
|
||||
|
||||
//namespace Umbraco.Core.Logging
|
||||
//{
|
||||
// ///<summary>
|
||||
// /// Used for logging
|
||||
// ///</summary>
|
||||
// internal static class LogHelper
|
||||
// {
|
||||
// static LogHelper()
|
||||
// {
|
||||
// //var appSetting = ConfigurationManager.AppSettings["log4net-config-path"];
|
||||
// //if (appSetting != null && File.Exists(appSetting))
|
||||
// // XmlConfigurator.ConfigureAndWatch(new FileInfo(appSetting));
|
||||
// //else
|
||||
// //XmlConfigurator.Configure();
|
||||
// }
|
||||
namespace Umbraco.Core.Logging
|
||||
{
|
||||
///<summary>
|
||||
/// Used for logging
|
||||
///</summary>
|
||||
internal static class LogHelper
|
||||
{
|
||||
static LogHelper()
|
||||
{
|
||||
//var appSetting = ConfigurationManager.AppSettings["log4net-config-path"];
|
||||
//if (appSetting != null && File.Exists(appSetting))
|
||||
// XmlConfigurator.ConfigureAndWatch(new FileInfo(appSetting));
|
||||
//else
|
||||
//XmlConfigurator.Configure();
|
||||
}
|
||||
|
||||
// ///<summary>
|
||||
// /// Returns a logger for the type specified
|
||||
// ///</summary>
|
||||
// ///<typeparam name="T"></typeparam>
|
||||
// ///<returns></returns>
|
||||
// public static ILog LoggerFor<T>()
|
||||
// {
|
||||
// return LogManager.GetLogger(typeof(T));
|
||||
// }
|
||||
///<summary>
|
||||
/// Returns a logger for the type specified
|
||||
///</summary>
|
||||
///<typeparam name="T"></typeparam>
|
||||
///<returns></returns>
|
||||
public static ILog LoggerFor<T>()
|
||||
{
|
||||
return LogManager.GetLogger(typeof(T));
|
||||
}
|
||||
|
||||
// /// <summary>
|
||||
// /// Returns a logger for the object's type
|
||||
// /// </summary>
|
||||
// /// <param name="getTypeFromInstance"></param>
|
||||
// /// <returns></returns>
|
||||
// public static ILog LoggerFor(object getTypeFromInstance)
|
||||
// {
|
||||
// Mandate.ParameterNotNull(getTypeFromInstance, "getTypeFromInstance");
|
||||
// return LogManager.GetLogger(getTypeFromInstance.GetType());
|
||||
// }
|
||||
/// <summary>
|
||||
/// Returns a logger for the object's type
|
||||
/// </summary>
|
||||
/// <param name="getTypeFromInstance"></param>
|
||||
/// <returns></returns>
|
||||
public static ILog LoggerFor(object getTypeFromInstance)
|
||||
{
|
||||
if (getTypeFromInstance == null) throw new ArgumentNullException("getTypeFromInstance");
|
||||
|
||||
return LogManager.GetLogger(getTypeFromInstance.GetType());
|
||||
}
|
||||
|
||||
// /// <summary>
|
||||
// /// Adds an error log
|
||||
// /// </summary>
|
||||
// /// <typeparam name="T"></typeparam>
|
||||
// /// <param name="message"></param>
|
||||
// /// <param name="exception"></param>
|
||||
// public static void Error<T>(string message, Exception exception)
|
||||
// {
|
||||
// var logger = LoggerFor<T>();
|
||||
// if (logger != null)
|
||||
// logger.Error(PrefixThreadId(message), exception);
|
||||
// }
|
||||
/// <summary>
|
||||
/// Adds an error log
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="exception"></param>
|
||||
public static void Error<T>(string message, Exception exception)
|
||||
{
|
||||
var logger = LoggerFor<T>();
|
||||
if (logger != null)
|
||||
logger.Error(PrefixThreadId(message), exception);
|
||||
}
|
||||
|
||||
// /// <summary>
|
||||
// /// Traces a message, only generating the message if tracing is actually enabled. Use this method to avoid calling any long-running methods such as "ToDebugString" if logging is disabled.
|
||||
// /// </summary>
|
||||
// /// <typeparam name="T"></typeparam>
|
||||
// /// <param name="generateMessageFormat">The generate message format.</param>
|
||||
// /// <param name="formatItems">The format items.</param>
|
||||
// /// <remarks></remarks>
|
||||
// public static void TraceIfEnabled<T>(string generateMessageFormat, params Func<object>[] formatItems)
|
||||
// {
|
||||
// var logger = LoggerFor<T>();
|
||||
// if (logger == null || !logger.IsInfoEnabled) return;
|
||||
// var executedParams = formatItems.Select(x => x.Invoke()).ToArray();
|
||||
// logger.InfoFormat(PrefixThreadId(generateMessageFormat), executedParams);
|
||||
// }
|
||||
|
||||
|
||||
// /// <summary>
|
||||
// /// Useful if the logger itself is running on another thread
|
||||
// /// </summary>
|
||||
// /// <param name="generateMessageFormat"></param>
|
||||
// /// <returns></returns>
|
||||
// private static string PrefixThreadId(string generateMessageFormat)
|
||||
// {
|
||||
// return "[Thread " + Thread.CurrentThread.ManagedThreadId + "] " + generateMessageFormat;
|
||||
// }
|
||||
/// <summary>
|
||||
/// Useful if the logger itself is running on another thread
|
||||
/// </summary>
|
||||
/// <param name="generateMessageFormat"></param>
|
||||
/// <returns></returns>
|
||||
private static string PrefixThreadId(string generateMessageFormat)
|
||||
{
|
||||
return "[Thread " + Thread.CurrentThread.ManagedThreadId + "] " + generateMessageFormat;
|
||||
}
|
||||
|
||||
// /// <summary>
|
||||
// /// Traces a message, only generating the message if tracing is actually enabled. Use this method to avoid calling any long-running methods such as "ToDebugString" if logging is disabled.
|
||||
// /// </summary>
|
||||
// /// <typeparam name="T"></typeparam>
|
||||
// /// <param name="generateMessage">The delegate to generate a message.</param>
|
||||
// /// <remarks></remarks>
|
||||
// public static void TraceIfEnabled<T>(Func<string> generateMessage)
|
||||
// {
|
||||
// TraceIfEnabled(typeof(T), generateMessage);
|
||||
// }
|
||||
public static void Warn(Type callingType, string message)
|
||||
{
|
||||
var logger = LogManager.GetLogger(callingType);
|
||||
if (logger != null)
|
||||
logger.Warn(PrefixThreadId(message));
|
||||
}
|
||||
|
||||
// public static void TraceIfEnabled(Type callingType, Func<string> generateMessage)
|
||||
// {
|
||||
// var logger = LogManager.GetLogger(callingType);
|
||||
// if (logger == null || !logger.IsInfoEnabled) return;
|
||||
// logger.Info(PrefixThreadId(generateMessage.Invoke()));
|
||||
// }
|
||||
public static void Warn(Type callingType, string message, params object[] format)
|
||||
{
|
||||
var logger = LogManager.GetLogger(callingType);
|
||||
if (logger != null)
|
||||
logger.WarnFormat(PrefixThreadId(message), format);
|
||||
}
|
||||
|
||||
// public static void Warn(Type callingType, string message)
|
||||
// {
|
||||
// var logger = LogManager.GetLogger(callingType);
|
||||
// if (logger != null)
|
||||
// logger.Warn(PrefixThreadId(message));
|
||||
// }
|
||||
/// <summary>
|
||||
/// Adds a warn log
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="message"></param>
|
||||
public static void Warn<T>(string message)
|
||||
{
|
||||
var logger = LoggerFor<T>();
|
||||
if (logger != null)
|
||||
logger.Warn(PrefixThreadId(message));
|
||||
}
|
||||
|
||||
// public static void Warn(Type callingType, string message, params object[] format)
|
||||
// {
|
||||
// var logger = LogManager.GetLogger(callingType);
|
||||
// if (logger != null)
|
||||
// logger.WarnFormat(PrefixThreadId(message), format);
|
||||
// }
|
||||
/// <summary>
|
||||
/// Adds a warn log
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="format"></param>
|
||||
/// <param name="items"></param>
|
||||
public static void Warn<T>(string format, params object[] items)
|
||||
{
|
||||
var logger = LoggerFor<T>();
|
||||
if (logger != null)
|
||||
logger.WarnFormat(PrefixThreadId(format), items);
|
||||
}
|
||||
|
||||
// /// <summary>
|
||||
// /// Adds a warn log
|
||||
// /// </summary>
|
||||
// /// <typeparam name="T"></typeparam>
|
||||
// /// <param name="message"></param>
|
||||
// public static void Warn<T>(string message)
|
||||
// {
|
||||
// var logger = LoggerFor<T>();
|
||||
// if (logger != null)
|
||||
// logger.Warn(PrefixThreadId(message));
|
||||
// }
|
||||
/// <summary>
|
||||
/// Traces a message, only generating the message if tracing is actually enabled. Use this method to avoid calling any long-running methods such as "ToDebugString" if logging is disabled.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="generateMessage">The delegate to generate a message.</param>
|
||||
/// <remarks></remarks>
|
||||
public static void Info<T>(Func<string> generateMessage)
|
||||
{
|
||||
Info(typeof(T), generateMessage);
|
||||
}
|
||||
|
||||
// /// <summary>
|
||||
// /// Adds a warn log
|
||||
// /// </summary>
|
||||
// /// <typeparam name="T"></typeparam>
|
||||
// /// <param name="format"></param>
|
||||
// /// <param name="items"></param>
|
||||
// public static void Warn<T>(string format, params object[] items)
|
||||
// {
|
||||
// var logger = LoggerFor<T>();
|
||||
// if (logger != null)
|
||||
// logger.WarnFormat(PrefixThreadId(format), items);
|
||||
// }
|
||||
public static void Info(Type callingType, Func<string> generateMessage)
|
||||
{
|
||||
var logger = LogManager.GetLogger(callingType);
|
||||
if (logger == null || !logger.IsInfoEnabled) return;
|
||||
logger.Info(PrefixThreadId(generateMessage.Invoke()));
|
||||
}
|
||||
|
||||
// /// <summary>
|
||||
// /// Traces if tracing is enabled.
|
||||
// /// </summary>
|
||||
// /// <param name="type">The type for the logging namespace.</param>
|
||||
// /// <param name="generateMessageFormat">The message format.</param>
|
||||
// /// <param name="formatItems">The format items.</param>
|
||||
// public static void TraceIfEnabled(Type type, string generateMessageFormat, params Func<object>[] formatItems)
|
||||
// {
|
||||
// var logger = LogManager.GetLogger(type);
|
||||
// if (logger == null || !logger.IsInfoEnabled) return;
|
||||
// var executedParams = formatItems.Select(x => x.Invoke()).ToArray();
|
||||
// logger.InfoFormat(PrefixThreadId(generateMessageFormat), executedParams);
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
/// <summary>
|
||||
/// Traces if tracing is enabled.
|
||||
/// </summary>
|
||||
/// <param name="type">The type for the logging namespace.</param>
|
||||
/// <param name="generateMessageFormat">The message format.</param>
|
||||
/// <param name="formatItems">The format items.</param>
|
||||
public static void Info(Type type, string generateMessageFormat, params Func<object>[] formatItems)
|
||||
{
|
||||
var logger = LogManager.GetLogger(type);
|
||||
if (logger == null || !logger.IsInfoEnabled) return;
|
||||
var executedParams = formatItems.Select(x => x.Invoke()).ToArray();
|
||||
logger.InfoFormat(PrefixThreadId(generateMessageFormat), executedParams);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Traces a message, only generating the message if tracing is actually enabled. Use this method to avoid calling any long-running methods such as "ToDebugString" if logging is disabled.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="generateMessageFormat">The generate message format.</param>
|
||||
/// <param name="formatItems">The format items.</param>
|
||||
/// <remarks></remarks>
|
||||
public static void Info<T>(string generateMessageFormat, params Func<object>[] formatItems)
|
||||
{
|
||||
Info(typeof (T), generateMessageFormat, formatItems);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
44
src/Umbraco.Core/Logging/LoggingTaskExtension.cs
Normal file
44
src/Umbraco.Core/Logging/LoggingTaskExtension.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Umbraco.Core.Logging
|
||||
{
|
||||
internal static class LoggingTaskExtension
|
||||
{
|
||||
/// <summary>
|
||||
/// This task shouldn't be waited on (as it's not guaranteed to run), and you shouldn't wait on the parent task either (because it might throw an
|
||||
/// exception that doesn't get handled). If you want to be waiting on something, use LogErrorsWaitable instead.
|
||||
///
|
||||
/// None of these methods are suitable for tasks that return a value. If you're wanting a result, you should probably be handling
|
||||
/// errors yourself.
|
||||
/// </summary>
|
||||
public static Task LogErrors(this Task task, Action<string, Exception> logMethod)
|
||||
{
|
||||
return task.ContinueWith(t => LogErrorsInner(t, logMethod), TaskContinuationOptions.OnlyOnFaulted);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This task can be waited on (as it's guaranteed to run), and you should wait on this rather than the parent task. Because it's
|
||||
/// guaranteed to run, it may be slower than using LogErrors, and you should consider using that method if you don't want to wait.
|
||||
///
|
||||
/// None of these methods are suitable for tasks that return a value. If you're wanting a result, you should probably be handling
|
||||
/// errors yourself.
|
||||
/// </summary>
|
||||
public static Task LogErrorsWaitable(this Task task, Action<string, Exception> logMethod)
|
||||
{
|
||||
return task.ContinueWith(t => LogErrorsInner(t, logMethod));
|
||||
}
|
||||
|
||||
private static void LogErrorsInner(Task task, Action<string, Exception> logAction)
|
||||
{
|
||||
if (task.Exception != null)
|
||||
{
|
||||
logAction("Aggregate Exception with " + task.Exception.InnerExceptions.Count + " inner exceptions: ", task.Exception);
|
||||
foreach (var innerException in task.Exception.InnerExceptions)
|
||||
{
|
||||
logAction("Inner exception from aggregate exception: ", innerException);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -31,6 +31,9 @@
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="log4net">
|
||||
<HintPath>..\packages\log4net.2.0.0\lib\net40-full\log4net.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.configuration" />
|
||||
<Reference Include="System.Core" />
|
||||
@@ -54,6 +57,8 @@
|
||||
<Compile Include="IO\SystemDirectories.cs" />
|
||||
<Compile Include="IO\SystemFiles.cs" />
|
||||
<Compile Include="LambdaExpressionCacheKey.cs" />
|
||||
<Compile Include="Logging\AsynchronousRollingFileAppender.cs" />
|
||||
<Compile Include="Logging\LoggingTaskExtension.cs" />
|
||||
<Compile Include="Logging\LogHelper.cs" />
|
||||
<Compile Include="RazorDataTypeModelStaticMappingItem.cs" />
|
||||
<Compile Include="Resolving\ManyWeightedResolved.cs" />
|
||||
@@ -81,6 +86,9 @@
|
||||
<Compile Include="WriteLock.cs" />
|
||||
<Compile Include="XmlHelper.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
|
||||
4
src/Umbraco.Core/packages.config
Normal file
4
src/Umbraco.Core/packages.config
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="log4net" version="2.0.0" targetFramework="net40" />
|
||||
</packages>
|
||||
@@ -14,3 +14,5 @@ using System.Runtime.CompilerServices;
|
||||
//tg forcing .NET 2.0 security rules, since otherwise it wasn't possible to run in medium trust
|
||||
//(got an inheritance security rules violated by type error)
|
||||
[assembly: System.Security.SecurityRules(System.Security.SecurityRuleSet.Level1)]
|
||||
|
||||
[assembly: log4net.Config.XmlConfigurator(Watch = true)]
|
||||
@@ -113,6 +113,9 @@
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\lib\ICSharpCode.SharpZipLib.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="log4net">
|
||||
<HintPath>..\packages\log4net.2.0.0\lib\net40-full\log4net.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Lucene.Net, Version=2.9.4.1, Culture=neutral, PublicKeyToken=85089178b9ac3181, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\lib\Lucene.Net.dll</HintPath>
|
||||
@@ -264,6 +267,10 @@
|
||||
<None Include="config\ClientDependency.Release.config">
|
||||
<DependentUpon>ClientDependency.config</DependentUpon>
|
||||
</None>
|
||||
<Content Include="config\log4net.config" />
|
||||
<Content Include="config\log4net.Release.config">
|
||||
<DependentUpon>log4net.config</DependentUpon>
|
||||
</Content>
|
||||
<None Include="config\xsltExtensions.Release.config">
|
||||
<DependentUpon>xsltExtensions.config</DependentUpon>
|
||||
</None>
|
||||
@@ -307,6 +314,7 @@
|
||||
<None Include="config\Dashboard.Release.config">
|
||||
<DependentUpon>Dashboard.config</DependentUpon>
|
||||
</None>
|
||||
<Content Include="packages.config" />
|
||||
<None Include="umbraco\config\create\UI.Release.xml">
|
||||
<DependentUpon>UI.xml</DependentUpon>
|
||||
</None>
|
||||
|
||||
25
src/Umbraco.Web.UI/config/log4net.Release.config
Normal file
25
src/Umbraco.Web.UI/config/log4net.Release.config
Normal file
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0"?>
|
||||
<log4net>
|
||||
<root>
|
||||
<priority value="Info"/>
|
||||
<appender-ref ref="AsynchronousLog4NetAppender" />
|
||||
</root>
|
||||
|
||||
|
||||
<!--To Change the way logging works for certain namespaces, insert a new logger like: -->
|
||||
<!--
|
||||
<logger name="Umbraco.Core">
|
||||
<level value="WARN" />
|
||||
</logger>-->
|
||||
|
||||
<appender name="AsynchronousLog4NetAppender" type="Umbraco.Core.Logging.AsynchronousRollingFileAppender, Umbraco.Core">
|
||||
<file value="App_Data\Logs\UmbracoTraceLog.txt" />
|
||||
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
|
||||
<appendToFile value="true" />
|
||||
<rollingStyle value="Date" />
|
||||
<maximumFileSize value="5MB" />
|
||||
<layout type="log4net.Layout.PatternLayout">
|
||||
<conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
|
||||
</layout>
|
||||
</appender>
|
||||
</log4net>
|
||||
25
src/Umbraco.Web.UI/config/log4net.config
Normal file
25
src/Umbraco.Web.UI/config/log4net.config
Normal file
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0"?>
|
||||
<log4net>
|
||||
<root>
|
||||
<priority value="Info"/>
|
||||
<appender-ref ref="AsynchronousLog4NetAppender" />
|
||||
</root>
|
||||
|
||||
|
||||
<!--To Change the way logging works for certain namespaces, insert a new logger like: -->
|
||||
<!--
|
||||
<logger name="Umbraco.Core">
|
||||
<level value="WARN" />
|
||||
</logger>-->
|
||||
|
||||
<appender name="AsynchronousLog4NetAppender" type="Umbraco.Core.Logging.AsynchronousRollingFileAppender, Umbraco.Core">
|
||||
<file value="App_Data\Logs\UmbracoTraceLog.txt" />
|
||||
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
|
||||
<appendToFile value="true" />
|
||||
<rollingStyle value="Date" />
|
||||
<maximumFileSize value="5MB" />
|
||||
<layout type="log4net.Layout.PatternLayout">
|
||||
<conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
|
||||
</layout>
|
||||
</appender>
|
||||
</log4net>
|
||||
4
src/Umbraco.Web.UI/packages.config
Normal file
4
src/Umbraco.Web.UI/packages.config
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="log4net" version="2.0.0" targetFramework="net40" />
|
||||
</packages>
|
||||
@@ -57,6 +57,8 @@
|
||||
<add key="enableSimpleMembership" value="false"/>
|
||||
<add key="autoFormsAuthentication" value="false"/>
|
||||
<!-- End of added in Umbraco 4.6.2 -->
|
||||
|
||||
<add key="log4net.Config" value="config\log4net.config" />
|
||||
</appSettings>
|
||||
<system.net>
|
||||
<mailSettings>
|
||||
|
||||
BIN
src/packages/log4net.2.0.0/lib/net40-client/log4net.dll
vendored
Normal file
BIN
src/packages/log4net.2.0.0/lib/net40-client/log4net.dll
vendored
Normal file
Binary file not shown.
30000
src/packages/log4net.2.0.0/lib/net40-client/log4net.xml
vendored
Normal file
30000
src/packages/log4net.2.0.0/lib/net40-client/log4net.xml
vendored
Normal file
File diff suppressed because it is too large
Load Diff
BIN
src/packages/log4net.2.0.0/lib/net40-full/log4net.dll
vendored
Normal file
BIN
src/packages/log4net.2.0.0/lib/net40-full/log4net.dll
vendored
Normal file
Binary file not shown.
30205
src/packages/log4net.2.0.0/lib/net40-full/log4net.xml
vendored
Normal file
30205
src/packages/log4net.2.0.0/lib/net40-full/log4net.xml
vendored
Normal file
File diff suppressed because it is too large
Load Diff
BIN
src/packages/log4net.2.0.0/log4net.2.0.0.nupkg
vendored
Normal file
BIN
src/packages/log4net.2.0.0/log4net.2.0.0.nupkg
vendored
Normal file
Binary file not shown.
@@ -1,4 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<repositories>
|
||||
<repository path="..\Umbraco.Core\packages.config" />
|
||||
<repository path="..\Umbraco.Tests\packages.config" />
|
||||
<repository path="..\Umbraco.Web.UI\packages.config" />
|
||||
</repositories>
|
||||
Reference in New Issue
Block a user