Last active
August 29, 2015 14:08
-
-
Save azzlack/d5dfb5a2dbd134284dc8 to your computer and use it in GitHub Desktop.
Log4Net logger for Common.Logging
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<configuration> | |
<configSections> | |
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" /> | |
<sectionGroup name="common"> | |
<section name="logging" type="Common.Logging.ConfigurationSectionHandler, Common.Logging" /> | |
</sectionGroup> | |
</configSections> | |
<common> | |
<logging> | |
<factoryAdapter type="{your-namespace}.Log4NetLoggerFactoryAdapter, {your-assembly-name}"> | |
<arg key="configType" value="INLINE" /> | |
</factoryAdapter> | |
</logging> | |
</common> | |
<log4net> | |
<appender name="FileAppender" type="log4net.Appender.RollingFileAppender"> | |
<param name="File" value="App_Data\Root.log"/> | |
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" /> | |
<appendToFile value="true" /> | |
<rollingStyle value="Size" /> | |
<maxSizeRollBackups value="2" /> | |
<maximumFileSize value="1MB" /> | |
<staticLogFileName value="true" /> | |
<layout type="log4net.Layout.PatternLayout"> | |
<param name="ConversionPattern" value="%date [%thread] %-5level %logger - %message%newline" /> | |
</layout> | |
</appender> | |
<root> | |
<level value="ALL" /> | |
<appender-ref ref="FileAppender" /> | |
</root> | |
</log4net> | |
</configuration> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace Common.Logging.Log4Net2 | |
{ | |
using System; | |
using System.Diagnostics; | |
using Common.Logging; | |
using Common.Logging.Factory; | |
using log4net.Core; | |
/// <summary> | |
/// Concrete implementation of <see cref="ILog"/> interface specific to log4net 1.2.10. | |
/// </summary> | |
/// <remarks> | |
/// Log4net is capable of outputting extended debug information about where the current | |
/// message was generated: class name, method name, file, line, etc. Log4net assumes that the location | |
/// information should be gathered relative to where Debug() was called. | |
/// When using Common.Logging, Debug() is called in Common.Logging.Log4Net.Log4NetLogger. This means that | |
/// the location information will indicate that Common.Logging.Log4Net.Log4NetLogger always made | |
/// the call to Debug(). We need to know where Common.Logging.ILog.Debug() | |
/// was called. To do this we need to use the log4net.ILog.Logger.Log method and pass in a Type telling | |
/// log4net where in the stack to begin looking for location information. | |
/// </remarks> | |
/// <author>Gilles Bayon</author> | |
/// <author>Erich Eichinger</author> | |
public class Log4NetLogger : AbstractLogger | |
{ | |
#region Fields | |
private readonly ILogger _logger = null; | |
private static Type callerStackBoundaryType; | |
#endregion | |
/// <summary> | |
/// Constructor | |
/// </summary> | |
/// <param name="log"></param> | |
internal protected Log4NetLogger(ILoggerWrapper log) | |
{ | |
this._logger = log.Logger; | |
} | |
#region ILog Members | |
/// <summary> | |
/// Checks if this logger is enabled for the <see cref="F:Common.Logging.LogLevel.Trace" /> level. | |
/// </summary> | |
public override bool IsTraceEnabled | |
{ | |
get { return this._logger.IsEnabledFor(Level.Trace); } | |
} | |
/// <summary> | |
/// Checks if this logger is enabled for the <see cref="F:Common.Logging.LogLevel.Debug" /> level. | |
/// </summary> | |
public override bool IsDebugEnabled | |
{ | |
get { return this._logger.IsEnabledFor(Level.Debug); } | |
} | |
/// <summary> | |
/// Checks if this logger is enabled for the <see cref="F:Common.Logging.LogLevel.Info" /> level. | |
/// </summary> | |
public override bool IsInfoEnabled | |
{ | |
get { return this._logger.IsEnabledFor(Level.Info); } | |
} | |
/// <summary> | |
/// Checks if this logger is enabled for the <see cref="F:Common.Logging.LogLevel.Warn" /> level. | |
/// </summary> | |
public override bool IsWarnEnabled | |
{ | |
get { return this._logger.IsEnabledFor(Level.Warn); } | |
} | |
/// <summary> | |
/// Checks if this logger is enabled for the <see cref="F:Common.Logging.LogLevel.Error" /> level. | |
/// </summary> | |
public override bool IsErrorEnabled | |
{ | |
get { return this._logger.IsEnabledFor(Level.Error); } | |
} | |
/// <summary> | |
/// Checks if this logger is enabled for the <see cref="F:Common.Logging.LogLevel.Fatal" /> level. | |
/// </summary> | |
public override bool IsFatalEnabled | |
{ | |
get { return this._logger.IsEnabledFor(Level.Fatal); } | |
} | |
/// <summary> | |
/// Sends the message to the underlying log4net system. | |
/// </summary> | |
/// <param name="logLevel">the level of this log event.</param> | |
/// <param name="message">the message to log</param> | |
/// <param name="exception">the exception to log (may be null)</param> | |
protected override void WriteInternal(LogLevel logLevel, object message, Exception exception) | |
{ | |
// determine correct caller - this might change due to jit optimizations with method inlining | |
if (callerStackBoundaryType == null) | |
{ | |
lock (this.GetType()) | |
{ | |
var stack = new StackTrace(); | |
var thisType = this.GetType(); | |
callerStackBoundaryType = typeof(AbstractLogger); | |
for (int i = 1; i < stack.FrameCount; i++) | |
{ | |
if (!this.IsInTypeHierarchy(thisType, stack.GetFrame(i).GetMethod().DeclaringType)) | |
{ | |
callerStackBoundaryType = stack.GetFrame(i - 1).GetMethod().DeclaringType; | |
break; | |
} | |
} | |
} | |
} | |
Level level = GetLevel(logLevel); | |
this._logger.Log(callerStackBoundaryType, level, message, exception); | |
} | |
private bool IsInTypeHierarchy(Type currentType, Type checkType) | |
{ | |
while (currentType != null && currentType != typeof(object)) | |
{ | |
if (currentType == checkType) | |
{ | |
return true; | |
} | |
currentType = currentType.BaseType; | |
} | |
return false; | |
} | |
/// <summary> | |
/// Maps <see cref="LogLevel"/> to log4net's <see cref="Level"/> | |
/// </summary> | |
/// <param name="logLevel"></param> | |
public static Level GetLevel(LogLevel logLevel) | |
{ | |
switch (logLevel) | |
{ | |
case LogLevel.All: | |
return Level.All; | |
case LogLevel.Trace: | |
return Level.Trace; | |
case LogLevel.Debug: | |
return Level.Debug; | |
case LogLevel.Info: | |
return Level.Info; | |
case LogLevel.Warn: | |
return Level.Warn; | |
case LogLevel.Error: | |
return Level.Error; | |
case LogLevel.Fatal: | |
return Level.Fatal; | |
default: | |
throw new ArgumentOutOfRangeException("logLevel", logLevel, "unknown log level"); | |
} | |
} | |
#endregion | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace Common.Logging.Log4Net2 | |
{ | |
using System; | |
using System.IO; | |
using Common.Logging; | |
using Common.Logging.Configuration; | |
using Common.Logging.Factory; | |
using log4net.Config; | |
/// <summary> | |
/// Concrete subclass of ILoggerFactoryAdapter specific to log4net 1.2.10. | |
/// </summary> | |
/// <remarks> | |
/// The following configuration property values may be configured: | |
/// <list type="bullet"> | |
/// <item><c>configType</c>: <c>INLINE|FILE|FILE-WATCH|EXTERNAL</c></item> | |
/// <item><c>configFile</c>: log4net configuration file path in case of FILE or FILE-WATCH</item> | |
/// </list> | |
/// The configType values have the following implications: | |
/// <list type="bullet"> | |
/// <item>INLINE: simply calls <c>XmlConfigurator.Configure()</c></item> | |
/// <item>FILE: calls <c>XmlConfigurator.Configure(System.IO.FileInfo)</c> using <c>configFile</c>.</item> | |
/// <item>FILE-WATCH: calls <c>XmlConfigurator.ConfigureAndWatch(System.IO.FileInfo)</c> using <c>configFile</c>.</item> | |
/// <item>EXTERNAL: does nothing and expects log4net to be configured elsewhere.</item> | |
/// <item><any>: calls <c>BasicConfigurator.Configure()</c></item> | |
/// </list> | |
/// </remarks> | |
/// <example> | |
/// The following snippet shows an example of how to configure log4net logging with Common.Logging: | |
/// <code> | |
/// <configuration> | |
/// <configSections> | |
/// <sectionGroup name="common"> | |
/// <section name="logging" | |
/// type="Common.Logging.ConfigurationSectionHandler, Common.Logging" | |
/// requirePermission="false" /> | |
/// </sectionGroup> | |
/// <section name="log4net" | |
/// type="log4net.Config.Log4NetConfigurationSectionHandler" | |
/// requirePermission="false" /> | |
/// </configSections> | |
/// | |
/// <common> | |
/// <logging> | |
/// <factoryAdapter type="Common.Logging.Log4Net.Log4NetLoggerFactoryAdapter, Common.Logging.Log4Net"> | |
/// <arg key="level" value="ALL" /> | |
/// <arg key="configType" value="INLINE" /> | |
/// </factoryAdapter> | |
/// </logging> | |
/// </common> | |
/// | |
/// <log4net debug="false"> | |
/// | |
/// <appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender, log4net"> | |
/// <param name="File" value="./Web.log" /> | |
/// <param name="AppendToFile" value="true" /> | |
/// <param name="MaxSizeRollBackups" value="1" /> | |
/// <param name="MaximumFileSize" value="1GB" /> | |
/// <param name="RollingStyle" value="Date" /> | |
/// <param name="StaticLogFileName" value="false" /> | |
/// | |
/// <layout type="log4net.Layout.PatternLayout, log4net"> | |
/// <param name="ConversionPattern" value="%d [%t] %-5p %c - %m%n" /> | |
/// </layout> | |
/// | |
/// </appender> | |
/// | |
/// <appender name="TraceAppender" type="log4net.Appender.TraceAppender"> | |
/// <layout type="log4net.Layout.PatternLayout"> | |
/// <param name="ConversionPattern" value="%-5p: %m" /> | |
/// </layout> | |
/// </appender> | |
/// | |
/// <root> | |
/// <level value="ALL" /> | |
/// <appender-ref ref="TraceAppender" /> | |
/// <appender-ref ref="RollingLogFileAppender" /> | |
/// </root> | |
/// | |
/// </log4net> | |
/// </configuration> | |
/// </code> | |
/// </example> | |
/// <author>Gilles Bayon</author> | |
/// <author>Erich Eichinger</author> | |
public class Log4NetLoggerFactoryAdapter : AbstractCachingLoggerFactoryAdapter | |
{ | |
/// <summary> | |
/// Abstract interface to the underlying log4net runtime | |
/// </summary> | |
public interface ILog4NetRuntime | |
{ | |
/// <summary>Calls <see cref="XmlConfigurator.Configure()"/></summary> | |
void XmlConfiguratorConfigure(); | |
/// <summary>Calls <see cref="XmlConfigurator.Configure(System.IO.FileInfo)"/></summary> | |
void XmlConfiguratorConfigure(string configFile); | |
/// <summary>Calls <see cref="XmlConfigurator.ConfigureAndWatch(System.IO.FileInfo)"/></summary> | |
void XmlConfiguratorConfigureAndWatch(string configFile); | |
/// <summary>Calls <see cref="BasicConfigurator.Configure()"/></summary> | |
void BasicConfiguratorConfigure(); | |
/// <summary>Calls <see cref="LogManager.GetLogger(string)"/></summary> | |
log4net.ILog GetLogger(string name); | |
} | |
private class Log4NetRuntime : ILog4NetRuntime | |
{ | |
public void XmlConfiguratorConfigure() | |
{ | |
XmlConfigurator.Configure(); | |
} | |
public void XmlConfiguratorConfigure(string configFile) | |
{ | |
XmlConfigurator.Configure(new FileInfo(configFile)); | |
} | |
public void XmlConfiguratorConfigureAndWatch(string configFile) | |
{ | |
XmlConfigurator.ConfigureAndWatch(new FileInfo(configFile)); | |
} | |
public void BasicConfiguratorConfigure() | |
{ | |
BasicConfigurator.Configure(); | |
} | |
public log4net.ILog GetLogger(string name) | |
{ | |
return log4net.LogManager.GetLogger(name); | |
} | |
} | |
private readonly ILog4NetRuntime _runtime; | |
/// <summary> | |
/// Constructor | |
/// </summary> | |
/// <param name="properties">configuration properties, see <see cref="Log4NetLoggerFactoryAdapter"/> for more.</param> | |
public Log4NetLoggerFactoryAdapter(Common.Logging.Configuration.NameValueCollection properties) | |
: this(properties, new Log4NetRuntime()) | |
{ } | |
/// <summary> | |
/// Constructor accepting configuration properties and an arbitrary | |
/// <see cref="ILog4NetRuntime"/> instance. | |
/// </summary> | |
/// <param name="properties">configuration properties, see <see cref="Log4NetLoggerFactoryAdapter"/> for more.</param> | |
/// <param name="runtime">a log4net runtime adapter</param> | |
protected Log4NetLoggerFactoryAdapter(Common.Logging.Configuration.NameValueCollection properties, ILog4NetRuntime runtime) | |
: base(true) | |
{ | |
if (runtime == null) | |
{ | |
throw new ArgumentNullException("runtime"); | |
} | |
this._runtime = runtime; | |
// parse config properties | |
string configType = ArgUtils.GetValue(properties, "configType", string.Empty).ToUpper(); | |
string configFile = ArgUtils.GetValue(properties, "configFile", string.Empty); | |
// app-relative path? | |
if (configFile.StartsWith("~/") || configFile.StartsWith("~\\")) | |
{ | |
configFile = string.Format("{0}/{1}", AppDomain.CurrentDomain.BaseDirectory.TrimEnd('/', '\\'), configFile.Substring(2)); | |
} | |
if (configType == "FILE" || configType == "FILE-WATCH") | |
{ | |
if (configFile == string.Empty) | |
{ | |
throw new ConfigurationException("Configuration property 'configFile' must be set for log4Net configuration of type 'FILE' or 'FILE-WATCH'."); | |
} | |
if (!File.Exists(configFile)) | |
{ | |
throw new ConfigurationException("log4net configuration file '" + configFile + "' does not exists"); | |
} | |
} | |
switch (configType) | |
{ | |
case "INLINE": | |
this._runtime.XmlConfiguratorConfigure(); | |
break; | |
case "FILE": | |
this._runtime.XmlConfiguratorConfigure(configFile); | |
break; | |
case "FILE-WATCH": | |
this._runtime.XmlConfiguratorConfigureAndWatch(configFile); | |
break; | |
case "EXTERNAL": | |
// Log4net will be configured outside of Common.Logging | |
break; | |
default: | |
this._runtime.BasicConfiguratorConfigure(); | |
break; | |
} | |
} | |
/// <summary> | |
/// Create a ILog instance by name | |
/// </summary> | |
/// <param name="name"></param> | |
/// <returns></returns> | |
protected override ILog CreateLogger(string name) | |
{ | |
return new Log4NetLogger(this._runtime.GetLogger(name)); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<packages> | |
<package id="Common.Logging" version="2.2.0" targetFramework="net451" /> | |
<package id="Common.Logging.Core" version="2.2.0" targetFramework="net451" /> | |
<package id="log4net" version="2.0.3" targetFramework="net451" /> | |
</packages> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment