diff --git a/src/ScriptCs.WebApi/App_Packages/LibLog.3.1/LibLog.cs b/src/ScriptCs.WebApi/App_Packages/LibLog.3.1/LibLog.cs
new file mode 100644
index 0000000..d153390
--- /dev/null
+++ b/src/ScriptCs.WebApi/App_Packages/LibLog.3.1/LibLog.cs
@@ -0,0 +1,1941 @@
+//===============================================================================
+// LibLog
+//
+// https://github.com/damianh/LibLog
+//===============================================================================
+// Copyright © 2011-2015 Damian Hickey. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+//===============================================================================
+
+// ReSharper disable PossibleNullReferenceException
+
+// Define LIBLOG_PORTABLE conditional compilation symbol for PCL compatibility
+
+#pragma warning disable 1591
+
+namespace ScriptCs.WebApi.Logging
+{
+ using System.Collections.Generic;
+ using ScriptCs.WebApi.Logging.LogProviders;
+ using System;
+ using System.Diagnostics;
+
+ ///
+ /// Simple interface that represent a logger.
+ ///
+ public interface ILog
+ {
+ ///
+ /// Log a message the specified log level.
+ ///
+ /// The log level.
+ /// The message function.
+ /// An optional exception.
+ /// Optional format parameters for the message generated by the messagefunc.
+ /// true if the message was logged. Otherwise false.
+ ///
+ /// Note to implementers: the message func should not be called if the loglevel is not enabled
+ /// so as not to incur performance penalties.
+ ///
+ /// To check IsEnabled call Log with only LogLevel and check the return value, no event will be written.
+ ///
+ bool Log(LogLevel logLevel, Func messageFunc, Exception exception = null, params object[] formatParameters );
+ }
+
+ ///
+ /// The log level.
+ ///
+ public enum LogLevel
+ {
+ Trace,
+ Debug,
+ Info,
+ Warn,
+ Error,
+ Fatal
+ }
+
+ public static class LogExtensions
+ {
+ public static bool IsDebugEnabled(this ILog logger)
+ {
+ GuardAgainstNullLogger(logger);
+ return logger.Log(LogLevel.Debug, null);
+ }
+
+ public static bool IsErrorEnabled(this ILog logger)
+ {
+ GuardAgainstNullLogger(logger);
+ return logger.Log(LogLevel.Error, null);
+ }
+
+ public static bool IsFatalEnabled(this ILog logger)
+ {
+ GuardAgainstNullLogger(logger);
+ return logger.Log(LogLevel.Fatal, null);
+ }
+
+ public static bool IsInfoEnabled(this ILog logger)
+ {
+ GuardAgainstNullLogger(logger);
+ return logger.Log(LogLevel.Info, null);
+ }
+
+ public static bool IsTraceEnabled(this ILog logger)
+ {
+ GuardAgainstNullLogger(logger);
+ return logger.Log(LogLevel.Trace, null);
+ }
+
+ public static bool IsWarnEnabled(this ILog logger)
+ {
+ GuardAgainstNullLogger(logger);
+ return logger.Log(LogLevel.Warn, null);
+ }
+
+ public static void Debug(this ILog logger, Func messageFunc)
+ {
+ GuardAgainstNullLogger(logger);
+ logger.Log(LogLevel.Debug, messageFunc);
+ }
+
+ public static void Debug(this ILog logger, string message)
+ {
+ if (logger.IsDebugEnabled())
+ {
+ logger.Log(LogLevel.Debug, message.AsFunc());
+ }
+ }
+
+ public static void DebugFormat(this ILog logger, string message, params object[] args)
+ {
+ if (logger.IsDebugEnabled())
+ {
+ logger.LogFormat(LogLevel.Debug, message, args);
+ }
+ }
+
+ public static void DebugException(this ILog logger, string message, Exception exception)
+ {
+ if (logger.IsDebugEnabled())
+ {
+ logger.Log(LogLevel.Debug, message.AsFunc(), exception);
+ }
+ }
+
+
+ public static void DebugException(this ILog logger, string message, Exception exception, params object[] formatParams)
+ {
+ if (logger.IsDebugEnabled())
+ {
+ logger.Log(LogLevel.Debug, message.AsFunc(), exception, formatParams);
+ }
+ }
+
+ public static void Error(this ILog logger, Func messageFunc)
+ {
+ logger.Log(LogLevel.Error, messageFunc);
+ }
+
+ public static void Error(this ILog logger, string message)
+ {
+ if (logger.IsErrorEnabled())
+ {
+ logger.Log(LogLevel.Error, message.AsFunc());
+ }
+ }
+
+ public static void ErrorFormat(this ILog logger, string message, params object[] args)
+ {
+ if (logger.IsErrorEnabled())
+ {
+ logger.LogFormat(LogLevel.Error, message, args);
+ }
+ }
+
+ public static void ErrorException(this ILog logger, string message, Exception exception, params object[] formatParams)
+ {
+ if (logger.IsErrorEnabled())
+ {
+ logger.Log(LogLevel.Error, message.AsFunc(), exception, formatParams);
+ }
+ }
+
+ public static void Fatal(this ILog logger, Func messageFunc)
+ {
+ logger.Log(LogLevel.Fatal, messageFunc);
+ }
+
+ public static void Fatal(this ILog logger, string message)
+ {
+ if (logger.IsFatalEnabled())
+ {
+ logger.Log(LogLevel.Fatal, message.AsFunc());
+ }
+ }
+
+ public static void FatalFormat(this ILog logger, string message, params object[] args)
+ {
+ if (logger.IsFatalEnabled())
+ {
+ logger.LogFormat(LogLevel.Fatal, message, args);
+ }
+ }
+
+ public static void FatalException(this ILog logger, string message, Exception exception, params object[] formatParams)
+ {
+ if (logger.IsFatalEnabled())
+ {
+ logger.Log(LogLevel.Fatal, message.AsFunc(), exception, formatParams);
+ }
+ }
+
+ public static void Info(this ILog logger, Func messageFunc)
+ {
+ GuardAgainstNullLogger(logger);
+ logger.Log(LogLevel.Info, messageFunc);
+ }
+
+ public static void Info(this ILog logger, string message)
+ {
+ if (logger.IsInfoEnabled())
+ {
+ logger.Log(LogLevel.Info, message.AsFunc());
+ }
+ }
+
+ public static void InfoFormat(this ILog logger, string message, params object[] args)
+ {
+ if (logger.IsInfoEnabled())
+ {
+ logger.LogFormat(LogLevel.Info, message, args);
+ }
+ }
+
+ public static void InfoException(this ILog logger, string message, Exception exception, params object[] formatParams)
+ {
+ if (logger.IsInfoEnabled())
+ {
+ logger.Log(LogLevel.Info, message.AsFunc(), exception, formatParams);
+ }
+ }
+
+ public static void Trace(this ILog logger, Func messageFunc)
+ {
+ GuardAgainstNullLogger(logger);
+ logger.Log(LogLevel.Trace, messageFunc);
+ }
+
+ public static void Trace(this ILog logger, string message)
+ {
+ if (logger.IsTraceEnabled())
+ {
+ logger.Log(LogLevel.Trace, message.AsFunc());
+ }
+ }
+
+ public static void TraceFormat(this ILog logger, string message, params object[] args)
+ {
+ if (logger.IsTraceEnabled())
+ {
+ logger.LogFormat(LogLevel.Trace, message, args);
+ }
+ }
+
+ public static void TraceException(this ILog logger, string message, Exception exception, params object[] formatParams)
+ {
+ if (logger.IsTraceEnabled())
+ {
+ logger.Log(LogLevel.Trace, message.AsFunc(), exception, formatParams);
+ }
+ }
+
+ public static void Warn(this ILog logger, Func messageFunc)
+ {
+ GuardAgainstNullLogger(logger);
+ logger.Log(LogLevel.Warn, messageFunc);
+ }
+
+ public static void Warn(this ILog logger, string message)
+ {
+ if (logger.IsWarnEnabled())
+ {
+ logger.Log(LogLevel.Warn, message.AsFunc());
+ }
+ }
+
+ public static void WarnFormat(this ILog logger, string message, params object[] args)
+ {
+ if (logger.IsWarnEnabled())
+ {
+ logger.LogFormat(LogLevel.Warn, message, args);
+ }
+ }
+
+ public static void WarnException(this ILog logger, string message, Exception exception, params object[] formatParams)
+ {
+ if (logger.IsWarnEnabled())
+ {
+ logger.Log(LogLevel.Warn, message.AsFunc(), exception, formatParams);
+ }
+ }
+
+ private static void GuardAgainstNullLogger(ILog logger)
+ {
+ if (logger == null)
+ {
+ throw new ArgumentNullException("logger");
+ }
+ }
+
+ private static void LogFormat(this ILog logger, LogLevel logLevel, string message, params object[] args)
+ {
+ logger.Log(logLevel, message.AsFunc(), null, args);
+ }
+
+ // Avoid the closure allocation, see https://gist.github.com/AArnott/d285feef75c18f6ecd2b
+ private static Func AsFunc(this T value) where T : class
+ {
+ return value.Return;
+ }
+
+ private static T Return(this T value)
+ {
+ return value;
+ }
+ }
+
+ ///
+ /// Represents a way to get a
+ ///
+ public interface ILogProvider
+ {
+ ///
+ /// Gets the specified named logger.
+ ///
+ /// Name of the logger.
+ /// The logger reference.
+ ILog GetLogger(string name);
+
+ ///
+ /// Opens a nested diagnostics context. Not supported in EntLib logging.
+ ///
+ /// The message to add to the diagnostics context.
+ /// A disposable that when disposed removes the message from the context.
+ IDisposable OpenNestedContext(string message);
+
+ ///
+ /// Opens a mapped diagnostics context. Not supported in EntLib logging.
+ ///
+ /// A key.
+ /// A value.
+ /// A disposable that when disposed removes the map from the context.
+ IDisposable OpenMappedContext(string key, string value);
+ }
+
+ ///
+ /// Provides a mechanism to create instances of objects.
+ ///
+ public static class LogProvider
+ {
+ private static ILogProvider _currentLogProvider;
+ private const string NullLogProvider = "Current Log Provider is not set. Call SetCurrentLogProvider " +
+ "with a non-null value first.";
+
+ ///
+ /// Gets a logger for the specified type.
+ ///
+ /// The type whose name will be used for the logger.
+ /// An instance of
+ public static ILog For()
+ {
+ return GetLogger(typeof(T));
+ }
+
+#if !LIBLOG_PORTABLE
+ ///
+ /// Gets a logger for the current class.
+ ///
+ /// An instance of
+ public static ILog GetCurrentClassLogger()
+ {
+ var stackFrame = new StackFrame(1, false);
+ return GetLogger(stackFrame.GetMethod().DeclaringType);
+ }
+#endif
+
+ ///
+ /// Gets a logger for the specified type.
+ ///
+ /// The type whose name will be used for the logger.
+ /// An instance of
+ public static ILog GetLogger(Type type)
+ {
+ return GetLogger(type.FullName);
+ }
+
+ ///
+ /// Gets a logger with the specified name.
+ ///
+ /// The name.
+ /// An instance of
+ public static ILog GetLogger(string name)
+ {
+ ILogProvider logProvider = _currentLogProvider ?? ResolveLogProvider();
+ return logProvider == null ? new NoOpLogger() : (ILog)new LoggerExecutionWrapper(logProvider.GetLogger(name));
+ }
+
+ ///
+ /// Sets the current log provider.
+ ///
+ /// The log provider.
+ public static void SetCurrentLogProvider(ILogProvider logProvider)
+ {
+ _currentLogProvider = logProvider;
+ }
+
+ public static IDisposable OpenNestedConext(string message)
+ {
+ if(_currentLogProvider == null)
+ {
+ throw new InvalidOperationException(NullLogProvider);
+ }
+ return _currentLogProvider.OpenNestedContext(message);
+ }
+
+ public static IDisposable OpenMappedContext(string key, string value)
+ {
+ if (_currentLogProvider == null)
+ {
+ throw new InvalidOperationException(NullLogProvider);
+ }
+ return _currentLogProvider.OpenMappedContext(key, value);
+ }
+
+ public delegate bool IsLoggerAvailable();
+
+ public delegate ILogProvider CreateLogProvider();
+
+ public static readonly List> LogProviderResolvers =
+ new List>
+ {
+ new Tuple(SerilogLogProvider.IsLoggerAvailable, () => new SerilogLogProvider()),
+ new Tuple(NLogLogProvider.IsLoggerAvailable, () => new NLogLogProvider()),
+ new Tuple(Log4NetLogProvider.IsLoggerAvailable, () => new Log4NetLogProvider()),
+ new Tuple(EntLibLogProvider.IsLoggerAvailable, () => new EntLibLogProvider()),
+ new Tuple(LoupeLogProvider.IsLoggerAvailable, () => new LoupeLogProvider()),
+ new Tuple(ColouredConsoleLogProvider.IsLoggerAvailable, () => new ColouredConsoleLogProvider()),
+ };
+
+ private static ILogProvider ResolveLogProvider()
+ {
+ try
+ {
+ foreach (var providerResolver in LogProviderResolvers)
+ {
+ if (providerResolver.Item1())
+ {
+ return providerResolver.Item2();
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+#if LIBLOG_PORTABLE
+ Debug.WriteLine(
+#else
+ Console.WriteLine(
+#endif
+ "Exception occured resolving a log provider. Logging for this assembly {0} is disabled. {1}",
+ typeof(LogProvider).GetAssemblyPortable().FullName,
+ ex);
+ }
+ return null;
+ }
+
+ internal class NoOpLogger : ILog
+ {
+ public bool Log(LogLevel logLevel, Func messageFunc, Exception exception, params object[] formatParameters)
+ {
+ return false;
+ }
+ }
+ }
+
+ internal class LoggerExecutionWrapper : ILog
+ {
+ private readonly ILog _logger;
+ internal const string FailedToGenerateLogMessage = "Failed to generate log message";
+
+ internal LoggerExecutionWrapper(ILog logger)
+ {
+ _logger = logger;
+ }
+
+ public ILog WrappedLogger
+ {
+ get { return _logger; }
+ }
+
+ public bool Log(LogLevel logLevel, Func messageFunc, Exception exception = null, params object[] formatParameters)
+ {
+ if (messageFunc == null)
+ {
+ return _logger.Log(logLevel, null);
+ }
+
+ Func wrappedMessageFunc = () =>
+ {
+ try
+ {
+ return messageFunc();
+ }
+ catch (Exception ex)
+ {
+ Log(LogLevel.Error, () => FailedToGenerateLogMessage, ex);
+ }
+ return null;
+ };
+ return _logger.Log(logLevel, wrappedMessageFunc, exception, formatParameters);
+ }
+ }
+}
+
+namespace ScriptCs.WebApi.Logging.LogProviders
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Globalization;
+ using System.Linq.Expressions;
+ using System.Reflection;
+ using System.Text;
+ using System.Text.RegularExpressions;
+
+ internal abstract class LogProviderBase : ILogProvider
+ {
+ protected delegate IDisposable OpenNdc(string message);
+ protected delegate IDisposable OpenMdc(string key, string value);
+
+ private readonly Lazy _lazyOpenNdcMethod;
+ private readonly Lazy _lazyOpenMdcMethod;
+ private static readonly IDisposable NoopDisposableInstance = new DisposableAction();
+
+ protected LogProviderBase()
+ {
+ _lazyOpenNdcMethod
+ = new Lazy(GetOpenNdcMethod);
+ _lazyOpenMdcMethod
+ = new Lazy(GetOpenMdcMethod);
+ }
+
+ public abstract ILog GetLogger(string name);
+
+ public IDisposable OpenNestedContext(string message)
+ {
+ return _lazyOpenNdcMethod.Value(message);
+ }
+
+ public IDisposable OpenMappedContext(string key, string value)
+ {
+ return _lazyOpenMdcMethod.Value(key, value);
+ }
+
+ protected virtual OpenNdc GetOpenNdcMethod()
+ {
+ return _ => NoopDisposableInstance;
+ }
+
+ protected virtual OpenMdc GetOpenMdcMethod()
+ {
+ return (_, __) => NoopDisposableInstance;
+ }
+ }
+
+ internal class NLogLogProvider : LogProviderBase
+ {
+ private readonly Func _getLoggerByNameDelegate;
+ private static bool _providerIsAvailableOverride = true;
+
+ public NLogLogProvider()
+ {
+ if (!IsLoggerAvailable())
+ {
+ throw new InvalidOperationException("NLog.LogManager not found");
+ }
+ _getLoggerByNameDelegate = GetGetLoggerMethodCall();
+ }
+
+ public static bool ProviderIsAvailableOverride
+ {
+ get { return _providerIsAvailableOverride; }
+ set { _providerIsAvailableOverride = value; }
+ }
+
+ public override ILog GetLogger(string name)
+ {
+ return new NLogLogger(_getLoggerByNameDelegate(name));
+ }
+
+ public static bool IsLoggerAvailable()
+ {
+ return ProviderIsAvailableOverride && GetLogManagerType() != null;
+ }
+
+ protected override OpenNdc GetOpenNdcMethod()
+ {
+ Type ndcContextType = Type.GetType("NLog.NestedDiagnosticsContext, NLog");
+ MethodInfo pushMethod = ndcContextType.GetMethodPortable("Push", new[] { typeof(string) });
+ ParameterExpression messageParam = Expression.Parameter(typeof(string), "message");
+ MethodCallExpression pushMethodCall = Expression.Call(null, pushMethod, messageParam);
+ return Expression.Lambda(pushMethodCall, messageParam).Compile();
+ }
+
+ protected override OpenMdc GetOpenMdcMethod()
+ {
+ Type mdcContextType = Type.GetType("NLog.MappedDiagnosticsContext, NLog");
+
+ MethodInfo setMethod = mdcContextType.GetMethodPortable("Set", new[] { typeof(string), typeof(string) });
+ MethodInfo removeMethod = mdcContextType.GetMethodPortable("Remove", new[] { typeof(string) });
+ ParameterExpression keyParam = Expression.Parameter(typeof(string), "key");
+ ParameterExpression valueParam = Expression.Parameter(typeof(string), "value");
+
+ MethodCallExpression setMethodCall = Expression.Call(null, setMethod, keyParam, valueParam);
+ MethodCallExpression removeMethodCall = Expression.Call(null, removeMethod, keyParam);
+
+ Action set = Expression
+ .Lambda>(setMethodCall, keyParam, valueParam)
+ .Compile();
+ Action remove = Expression
+ .Lambda>(removeMethodCall, keyParam)
+ .Compile();
+
+ return (key, value) =>
+ {
+ set(key, value);
+ return new DisposableAction(() => remove(key));
+ };
+ }
+
+ private static Type GetLogManagerType()
+ {
+ return Type.GetType("NLog.LogManager, NLog");
+ }
+
+ private static Func GetGetLoggerMethodCall()
+ {
+ Type logManagerType = GetLogManagerType();
+ MethodInfo method = logManagerType.GetMethodPortable("GetLogger", new[] { typeof(string) });
+ ParameterExpression nameParam = Expression.Parameter(typeof(string), "name");
+ MethodCallExpression methodCall = Expression.Call(null, method, nameParam);
+ return Expression.Lambda>(methodCall, nameParam).Compile();
+ }
+
+ public class NLogLogger : ILog
+ {
+ private readonly dynamic _logger;
+
+ internal NLogLogger(dynamic logger)
+ {
+ _logger = logger;
+ }
+
+ public bool Log(LogLevel logLevel, Func messageFunc, Exception exception, params object[] formatParameters)
+ {
+ if (messageFunc == null)
+ {
+ return IsLogLevelEnable(logLevel);
+ }
+ messageFunc = LogMessageFormatter.SimulateStructuredLogging(messageFunc, formatParameters);
+
+ if(exception != null)
+ {
+ return LogException(logLevel, messageFunc, exception);
+ }
+ switch (logLevel)
+ {
+ case LogLevel.Debug:
+ if (_logger.IsDebugEnabled)
+ {
+ _logger.Debug(messageFunc());
+ return true;
+ }
+ break;
+ case LogLevel.Info:
+ if (_logger.IsInfoEnabled)
+ {
+ _logger.Info(messageFunc());
+ return true;
+ }
+ break;
+ case LogLevel.Warn:
+ if (_logger.IsWarnEnabled)
+ {
+ _logger.Warn(messageFunc());
+ return true;
+ }
+ break;
+ case LogLevel.Error:
+ if (_logger.IsErrorEnabled)
+ {
+ _logger.Error(messageFunc());
+ return true;
+ }
+ break;
+ case LogLevel.Fatal:
+ if (_logger.IsFatalEnabled)
+ {
+ _logger.Fatal(messageFunc());
+ return true;
+ }
+ break;
+ default:
+ if (_logger.IsTraceEnabled)
+ {
+ _logger.Trace(messageFunc());
+ return true;
+ }
+ break;
+ }
+ return false;
+ }
+
+ private bool LogException(LogLevel logLevel, Func messageFunc, Exception exception)
+ {
+ switch (logLevel)
+ {
+ case LogLevel.Debug:
+ if (_logger.IsDebugEnabled)
+ {
+ _logger.DebugException(messageFunc(), exception);
+ return true;
+ }
+ break;
+ case LogLevel.Info:
+ if (_logger.IsInfoEnabled)
+ {
+ _logger.InfoException(messageFunc(), exception);
+ return true;
+ }
+ break;
+ case LogLevel.Warn:
+ if (_logger.IsWarnEnabled)
+ {
+ _logger.WarnException(messageFunc(), exception);
+ return true;
+ }
+ break;
+ case LogLevel.Error:
+ if (_logger.IsErrorEnabled)
+ {
+ _logger.ErrorException(messageFunc(), exception);
+ return true;
+ }
+ break;
+ case LogLevel.Fatal:
+ if (_logger.IsFatalEnabled)
+ {
+ _logger.FatalException(messageFunc(), exception);
+ return true;
+ }
+ break;
+ default:
+ if (_logger.IsTraceEnabled)
+ {
+ _logger.TraceException(messageFunc(), exception);
+ return true;
+ }
+ break;
+ }
+ return false;
+ }
+
+ private bool IsLogLevelEnable(LogLevel logLevel)
+ {
+ switch (logLevel)
+ {
+ case LogLevel.Debug:
+ return _logger.IsDebugEnabled;
+ case LogLevel.Info:
+ return _logger.IsInfoEnabled;
+ case LogLevel.Warn:
+ return _logger.IsWarnEnabled;
+ case LogLevel.Error:
+ return _logger.IsErrorEnabled;
+ case LogLevel.Fatal:
+ return _logger.IsFatalEnabled;
+ default:
+ return _logger.IsTraceEnabled;
+ }
+ }
+ }
+ }
+
+ internal class Log4NetLogProvider : LogProviderBase
+ {
+ private readonly Func _getLoggerByNameDelegate;
+ private static bool _providerIsAvailableOverride = true;
+
+ public Log4NetLogProvider()
+ {
+ if (!IsLoggerAvailable())
+ {
+ throw new InvalidOperationException("log4net.LogManager not found");
+ }
+ _getLoggerByNameDelegate = GetGetLoggerMethodCall();
+ }
+
+ public static bool ProviderIsAvailableOverride
+ {
+ get { return _providerIsAvailableOverride; }
+ set { _providerIsAvailableOverride = value; }
+ }
+
+ public override ILog GetLogger(string name)
+ {
+ return new Log4NetLogger(_getLoggerByNameDelegate(name));
+ }
+
+ internal static bool IsLoggerAvailable()
+ {
+ return ProviderIsAvailableOverride && GetLogManagerType() != null;
+ }
+
+ protected override OpenNdc GetOpenNdcMethod()
+ {
+ Type ndcContextType = Type.GetType("log4net.NDC, log4net");
+ MethodInfo pushMethod = ndcContextType.GetMethodPortable("Push", new[] { typeof(string) });
+ ParameterExpression messageParam = Expression.Parameter(typeof(string), "message");
+ MethodCallExpression pushMethodCall = Expression.Call(null, pushMethod, messageParam);
+ return Expression.Lambda(pushMethodCall, messageParam).Compile();
+ }
+
+ protected override OpenMdc GetOpenMdcMethod()
+ {
+ Type mdcContextType = Type.GetType("log4net.MDC, log4net");
+
+ MethodInfo setMethod = mdcContextType.GetMethodPortable("Set", new[] { typeof(string), typeof(string) });
+ MethodInfo removeMethod = mdcContextType.GetMethodPortable("Remove", new[] { typeof(string) });
+ ParameterExpression keyParam = Expression.Parameter(typeof(string), "key");
+ ParameterExpression valueParam = Expression.Parameter(typeof(string), "value");
+
+ MethodCallExpression setMethodCall = Expression.Call(null, setMethod, keyParam, valueParam);
+ MethodCallExpression removeMethodCall = Expression.Call(null, removeMethod, keyParam);
+
+ Action set = Expression
+ .Lambda>(setMethodCall, keyParam, valueParam)
+ .Compile();
+ Action remove = Expression
+ .Lambda>(removeMethodCall, keyParam)
+ .Compile();
+
+ return (key, value) =>
+ {
+ set(key, value);
+ return new DisposableAction(() => remove(key));
+ };
+ }
+
+ private static Type GetLogManagerType()
+ {
+ return Type.GetType("log4net.LogManager, log4net");
+ }
+
+ private static Func GetGetLoggerMethodCall()
+ {
+ Type logManagerType = GetLogManagerType();
+ MethodInfo method = logManagerType.GetMethodPortable("GetLogger", new[] { typeof(string) });
+ ParameterExpression nameParam = Expression.Parameter(typeof(string), "name");
+ MethodCallExpression methodCall = Expression.Call(null, method, nameParam);
+ return Expression.Lambda>(methodCall, nameParam).Compile();
+ }
+
+ public class Log4NetLogger : ILog
+ {
+ private readonly dynamic _logger;
+
+ internal Log4NetLogger(dynamic logger)
+ {
+ _logger = logger;
+ }
+
+ public bool Log(LogLevel logLevel, Func messageFunc, Exception exception, params object[] formatParameters)
+ {
+ if (messageFunc == null)
+ {
+ return IsLogLevelEnable(logLevel);
+ }
+
+ messageFunc = LogMessageFormatter.SimulateStructuredLogging(messageFunc, formatParameters);
+
+ if (exception != null)
+ {
+ return LogException(logLevel, messageFunc, exception);
+ }
+ switch (logLevel)
+ {
+ case LogLevel.Info:
+ if (_logger.IsInfoEnabled)
+ {
+ _logger.Info(messageFunc());
+ return true;
+ }
+ break;
+ case LogLevel.Warn:
+ if (_logger.IsWarnEnabled)
+ {
+ _logger.Warn(messageFunc());
+ return true;
+ }
+ break;
+ case LogLevel.Error:
+ if (_logger.IsErrorEnabled)
+ {
+ _logger.Error(messageFunc());
+ return true;
+ }
+ break;
+ case LogLevel.Fatal:
+ if (_logger.IsFatalEnabled)
+ {
+ _logger.Fatal(messageFunc());
+ return true;
+ }
+ break;
+ default:
+ if (_logger.IsDebugEnabled)
+ {
+ _logger.Debug(messageFunc()); // Log4Net doesn't have a 'Trace' level, so all Trace messages are written as 'Debug'
+ return true;
+ }
+ break;
+ }
+ return false;
+ }
+
+ private bool LogException(LogLevel logLevel, Func messageFunc, Exception exception)
+ {
+ switch (logLevel)
+ {
+ case LogLevel.Info:
+ if (_logger.IsDebugEnabled)
+ {
+ _logger.Info(messageFunc(), exception);
+ return true;
+ }
+ break;
+ case LogLevel.Warn:
+ if (_logger.IsWarnEnabled)
+ {
+ _logger.Warn(messageFunc(), exception);
+ return true;
+ }
+ break;
+ case LogLevel.Error:
+ if (_logger.IsErrorEnabled)
+ {
+ _logger.Error(messageFunc(), exception);
+ return true;
+ }
+ break;
+ case LogLevel.Fatal:
+ if (_logger.IsFatalEnabled)
+ {
+ _logger.Fatal(messageFunc(), exception);
+ return true;
+ }
+ break;
+ default:
+ if (_logger.IsDebugEnabled)
+ {
+ _logger.Debug(messageFunc(), exception);
+ return true;
+ }
+ break;
+ }
+ return false;
+ }
+
+ private bool IsLogLevelEnable(LogLevel logLevel)
+ {
+ switch (logLevel)
+ {
+ case LogLevel.Debug:
+ return _logger.IsDebugEnabled;
+ case LogLevel.Info:
+ return _logger.IsInfoEnabled;
+ case LogLevel.Warn:
+ return _logger.IsWarnEnabled;
+ case LogLevel.Error:
+ return _logger.IsErrorEnabled;
+ case LogLevel.Fatal:
+ return _logger.IsFatalEnabled;
+ default:
+ return _logger.IsDebugEnabled;
+ }
+ }
+ }
+ }
+
+ internal class EntLibLogProvider : LogProviderBase
+ {
+ private const string TypeTemplate = "Microsoft.Practices.EnterpriseLibrary.Logging.{0}, Microsoft.Practices.EnterpriseLibrary.Logging";
+ private static bool _providerIsAvailableOverride = true;
+ private static readonly Type LogEntryType;
+ private static readonly Type LoggerType;
+ private static readonly Type TraceEventTypeType;
+ private static readonly Action WriteLogEntry;
+ private static readonly Func ShouldLogEntry;
+
+ static EntLibLogProvider()
+ {
+ LogEntryType = Type.GetType(string.Format(TypeTemplate, "LogEntry"));
+ LoggerType = Type.GetType(string.Format(TypeTemplate, "Logger"));
+ TraceEventTypeType = TraceEventTypeValues.Type;
+ if (LogEntryType == null
+ || TraceEventTypeType == null
+ || LoggerType == null)
+ {
+ return;
+ }
+ WriteLogEntry = GetWriteLogEntry();
+ ShouldLogEntry = GetShouldLogEntry();
+ }
+
+ public EntLibLogProvider()
+ {
+ if (!IsLoggerAvailable())
+ {
+ throw new InvalidOperationException("Microsoft.Practices.EnterpriseLibrary.Logging.Logger not found");
+ }
+ }
+
+ public static bool ProviderIsAvailableOverride
+ {
+ get { return _providerIsAvailableOverride; }
+ set { _providerIsAvailableOverride = value; }
+ }
+
+ public override ILog GetLogger(string name)
+ {
+ return new EntLibLogger(name, WriteLogEntry, ShouldLogEntry);
+ }
+
+ internal static bool IsLoggerAvailable()
+ {
+ return ProviderIsAvailableOverride
+ && TraceEventTypeType != null
+ && LogEntryType != null;
+ }
+
+ private static Action GetWriteLogEntry()
+ {
+ // new LogEntry(...)
+ var logNameParameter = Expression.Parameter(typeof(string), "logName");
+ var messageParameter = Expression.Parameter(typeof(string), "message");
+ var severityParameter = Expression.Parameter(typeof(int), "severity");
+
+ MemberInitExpression memberInit = GetWriteLogExpression(
+ messageParameter,
+ Expression.Convert(severityParameter, TraceEventTypeType),
+ logNameParameter);
+
+ //Logger.Write(new LogEntry(....));
+ MethodInfo writeLogEntryMethod = LoggerType.GetMethodPortable("Write", new[] { LogEntryType });
+ var writeLogEntryExpression = Expression.Call(writeLogEntryMethod, memberInit);
+
+ return Expression.Lambda>(
+ writeLogEntryExpression,
+ logNameParameter,
+ messageParameter,
+ severityParameter).Compile();
+ }
+
+ private static Func GetShouldLogEntry()
+ {
+ // new LogEntry(...)
+ var logNameParameter = Expression.Parameter(typeof(string), "logName");
+ var severityParameter = Expression.Parameter(typeof(int), "severity");
+
+ MemberInitExpression memberInit = GetWriteLogExpression(
+ Expression.Constant("***dummy***"),
+ Expression.Convert(severityParameter, TraceEventTypeType),
+ logNameParameter);
+
+ //Logger.Write(new LogEntry(....));
+ MethodInfo writeLogEntryMethod = LoggerType.GetMethodPortable("ShouldLog", new[] { LogEntryType });
+ var writeLogEntryExpression = Expression.Call(writeLogEntryMethod, memberInit);
+
+ return Expression.Lambda>(
+ writeLogEntryExpression,
+ logNameParameter,
+ severityParameter).Compile();
+ }
+
+ private static MemberInitExpression GetWriteLogExpression(Expression message,
+ Expression severityParameter, ParameterExpression logNameParameter)
+ {
+ var entryType = LogEntryType;
+ MemberInitExpression memberInit = Expression.MemberInit(Expression.New(entryType), new []
+ {
+ Expression.Bind(entryType.GetPropertyPortable("Message"), message),
+ Expression.Bind(entryType.GetPropertyPortable("Severity"), severityParameter),
+ Expression.Bind(entryType.GetPropertyPortable("TimeStamp"),
+ Expression.Property(null, typeof (DateTime).GetPropertyPortable("UtcNow"))),
+ Expression.Bind(entryType.GetPropertyPortable("Categories"),
+ Expression.ListInit(
+ Expression.New(typeof (List)),
+ typeof (List).GetMethodPortable("Add", new[] {typeof (string)}),
+ logNameParameter))
+ });
+ return memberInit;
+ }
+
+ public class EntLibLogger : ILog
+ {
+ private readonly string _loggerName;
+ private readonly Action _writeLog;
+ private readonly Func _shouldLog;
+
+ internal EntLibLogger(string loggerName, Action writeLog, Func shouldLog)
+ {
+ _loggerName = loggerName;
+ _writeLog = writeLog;
+ _shouldLog = shouldLog;
+ }
+
+ public bool Log(LogLevel logLevel, Func messageFunc, Exception exception, params object[] formatParameters)
+ {
+ var severity = MapSeverity(logLevel);
+ if (messageFunc == null)
+ {
+ return _shouldLog(_loggerName, severity);
+ }
+
+
+ messageFunc = LogMessageFormatter.SimulateStructuredLogging(messageFunc, formatParameters);
+ if (exception != null)
+ {
+ return LogException(logLevel, messageFunc, exception);
+ }
+ _writeLog(_loggerName, messageFunc(), severity);
+ return true;
+ }
+
+ public bool LogException(LogLevel logLevel, Func messageFunc, Exception exception)
+ {
+ var severity = MapSeverity(logLevel);
+ var message = messageFunc() + Environment.NewLine + exception;
+ _writeLog(_loggerName, message, severity);
+ return true;
+ }
+
+ private static int MapSeverity(LogLevel logLevel)
+ {
+ switch (logLevel)
+ {
+ case LogLevel.Fatal:
+ return TraceEventTypeValues.Critical;
+ case LogLevel.Error:
+ return TraceEventTypeValues.Error;
+ case LogLevel.Warn:
+ return TraceEventTypeValues.Warning;
+ case LogLevel.Info:
+ return TraceEventTypeValues.Information;
+ default:
+ return TraceEventTypeValues.Verbose;
+ }
+ }
+ }
+ }
+
+ internal class SerilogLogProvider : LogProviderBase
+ {
+ private readonly Func _getLoggerByNameDelegate;
+ private static bool _providerIsAvailableOverride = true;
+
+ public SerilogLogProvider()
+ {
+ if (!IsLoggerAvailable())
+ {
+ throw new InvalidOperationException("Serilog.Log not found");
+ }
+ _getLoggerByNameDelegate = GetForContextMethodCall();
+ }
+
+ public static bool ProviderIsAvailableOverride
+ {
+ get { return _providerIsAvailableOverride; }
+ set { _providerIsAvailableOverride = value; }
+ }
+
+ public override ILog GetLogger(string name)
+ {
+ return new SerilogLogger(_getLoggerByNameDelegate(name));
+ }
+
+ internal static bool IsLoggerAvailable()
+ {
+ return ProviderIsAvailableOverride && GetLogManagerType() != null;
+ }
+
+ protected override OpenNdc GetOpenNdcMethod()
+ {
+ return message => GetPushProperty()("NDC", message);
+ }
+
+ protected override OpenMdc GetOpenMdcMethod()
+ {
+ return (key, value) => GetPushProperty()(key, value);
+ }
+
+ private static Func GetPushProperty()
+ {
+ Type ndcContextType = Type.GetType("Serilog.Context.LogContext, Serilog.FullNetFx");
+ MethodInfo pushPropertyMethod = ndcContextType.GetMethodPortable(
+ "PushProperty",
+ new[]
+ {
+ typeof(string),
+ typeof(object),
+ typeof(bool)
+ });
+ ParameterExpression nameParam = Expression.Parameter(typeof(string), "name");
+ ParameterExpression valueParam = Expression.Parameter(typeof(object), "value");
+ ParameterExpression destructureObjectParam = Expression.Parameter(typeof(bool), "destructureObjects");
+ MethodCallExpression pushPropertyMethodCall = Expression
+ .Call(null, pushPropertyMethod, nameParam, valueParam, destructureObjectParam);
+ var pushProperty = Expression
+ .Lambda>(
+ pushPropertyMethodCall,
+ nameParam,
+ valueParam,
+ destructureObjectParam)
+ .Compile();
+
+ return (key, value) => pushProperty(key, value, false);
+ }
+
+ private static Type GetLogManagerType()
+ {
+ return Type.GetType("Serilog.Log, Serilog");
+ }
+
+ private static Func GetForContextMethodCall()
+ {
+ Type logManagerType = GetLogManagerType();
+ MethodInfo method = logManagerType.GetMethodPortable("ForContext", new[] { typeof(string), typeof(object), typeof(bool) });
+ ParameterExpression propertyNameParam = Expression.Parameter(typeof(string), "propertyName");
+ ParameterExpression valueParam = Expression.Parameter(typeof(object), "value");
+ ParameterExpression destructureObjectsParam = Expression.Parameter(typeof(bool), "destructureObjects");
+ MethodCallExpression methodCall = Expression.Call(null, method, new Expression[]
+ {
+ propertyNameParam,
+ valueParam,
+ destructureObjectsParam
+ });
+ var func = Expression.Lambda>(
+ methodCall,
+ propertyNameParam,
+ valueParam,
+ destructureObjectsParam)
+ .Compile();
+ return name => func("Name", name, false);
+ }
+
+ public class SerilogLogger : ILog
+ {
+ private readonly object _logger;
+ private static readonly object DebugLevel;
+ private static readonly object ErrorLevel;
+ private static readonly object FatalLevel;
+ private static readonly object InformationLevel;
+ private static readonly object VerboseLevel;
+ private static readonly object WarningLevel;
+ private static readonly Func