[Asp.net 5] Logging-其他日志系统的实现

8/10/2015来源:ASP.NET技巧人气:2636

[asp.net 5] Logging-其他日志系统的实现

Microsoft.Framework.Logging.NLog

使用Nlog扩展日志系统:按照我们上节说的,对于扩展的日志系统都要实现俩个接口ILogger、ILoggerPRovider。所以在当前工程中也没例外,NLogLoggerProvider实现了ILoggerProvider、内部类Logger实现了ILogger。源代码如下:

public class NLogLoggerProvider : ILoggerProvider    {        private readonly LogFactory _logFactory;        public NLogLoggerProvider(LogFactory logFactory)        {            _logFactory = logFactory;        }        public ILogger CreateLogger(string name)        {            return new Logger(_logFactory.GetLogger(name));        }        private class Logger : ILogger        {            private readonly global::NLog.Logger _logger;            public Logger(global::NLog.Logger logger)            {                _logger = logger;            }            public void Log(                LogLevel logLevel,                int eventId,                object state,                Exception exception,                Func<object, Exception, string> formatter)            {                var nLogLogLevel = GetLogLevel(logLevel);                var message = string.Empty;                if (formatter != null)                {                    message = formatter(state, exception);                }                else                {                    message = LogFormatter.Formatter(state, exception);                }                if (!string.IsNullOrEmpty(message))                {                    var eventInfo = LogEventInfo.Create(nLogLogLevel, _logger.Name, message, exception);                    eventInfo.Properties["EventId"] = eventId;                    _logger.Log(eventInfo);                }            }            public bool IsEnabled(LogLevel logLevel)            {                return _logger.IsEnabled(GetLogLevel(logLevel));            }            private global::NLog.LogLevel GetLogLevel(LogLevel logLevel)            {                switch (logLevel)                {                    case LogLevel.Verbose: return global::NLog.LogLevel.Debug;                    case LogLevel.Information: return global::NLog.LogLevel.Info;                    case LogLevel.Warning: return global::NLog.LogLevel.Warn;                    case LogLevel.Error: return global::NLog.LogLevel.Error;                    case LogLevel.Critical: return global::NLog.LogLevel.Fatal;                }                return global::NLog.LogLevel.Debug;            }            public IDisposable BeginScopeImpl([NotNull] object state)            {                return NestedDiagnosticsContext.Push(state.ToString());            }        }    }
NLog

这段代码很容易读懂,也就不过多解释了,需要注意的一点是:LogFactory是NLog的工厂。下面我们主要就NLog和大名鼎鼎的Log4net进行比较(道听途说比较多,欢迎指正)

  • 都不建议直接使用,使用门面类包装(也就是相当于本处的Microsoft.Framework.Logging.NLog的内部Logger类实际是Nlog的log的门面)
  • 如果现在系统使用了日志系统,建议使用原有的日志系统(应用log4net比较多),完全新的项目建议使用Nlog
  • 从初始化配置上看Nlog要比log4net简单
  • 从功能强大度上,基本可以平分秋色
  • 从开源代码更新程度上看:Nlog以及在github上开源(https://github.com/nlog)、log4net在Apache上开源(http://logging.apache.org/log4net/download_log4net.cgi)。但是Nlog还有更新,支持的.net版本也比较多;log4net感觉好久没更新了,核心版本还是.net2.0(此处不是道听途说,是楼猪自己下载源码得倒的结论)
  • 据说使用同步记录日志时log4net比Nlog要快,但是Nlog可以开启异步记录,并且速度会反超log4net

下面是楼主参考的一些博文

  • log4net vs. Nlog [closed](骄傲的豹子)
  • NLog 2.0.0.2000 使用实例(回复部分为主要参考,主体是介绍Nlog的使用的)
  • NLog文章系列——系列文章目录以及简要介绍(Nlog学习的参考)

测试代码:

<?xml version="1.0" encoding="utf-8" ?><nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"      autoReload="true">  <targets>    <target name="logfile"             xsi:type="File"             fileName="file.txt"             layout="${longdate}|${level:uppercase=true}|${logger}|${event-context:item=EventId}|${message}|${ndc}" />    <target name="console"             xsi:type="ColoredConsole"             layout="[${level:uppercase=true}:${logger}] ${message}"/>  </targets>  <rules>    <logger name="*" minlevel="Info" writeTo="logfile,console" />  </rules></nlog>
        public Program()        {            // a DI based application would get ILoggerFactory injected instead            var factory = new LoggerFactory();            // getting the logger immediately using the class's name is conventional            _logger = factory.CreateLogger(typeof(Program).FullName);            // providers may be added to an ILoggerFactory at any time, existing ILoggers are updated#if !DNXCORE50            factory.AddNLog(new global::NLog.LogFactory());#endif            factory.AddConsole();            factory.AddConsole((category, logLevel) => logLevel >= LogLevel.Critical && category.Equals(typeof(Program).FullName));        }

Microsoft.Framework.Logging.Console

实际上用控制台直接写日志的并不多,所以这个日志系统可能用途并不广,不过精炼的代码还是有很多可圈可点的地方:使用IConsole接口以及LogConsole类。我们一般来说肯定只会实现ILogger、ILoggerProvider俩个接口,也就是写实现类ConsoleLogger、ConsoleLoggerProvider。但是我们主要到ConsoleLogger只是负责记录的逻辑操作,具体对于介质的操作属于IConsole的职责,如果将ConsoleLogger与LogConsole柔和在一起,问题也不大;但是明显违反了面向对象设计的单一职责原则。所以麻雀虽小,五脏俱全,这几个小类也能体现面向对象的能力的。

Microsoft.Framework.Logging.TraceSource

这个对于我来说是个陌生的东西,虽然是.net自带的,并且从1.0就有了。最开始使用的时Debug和Trace进行跟踪、记录,到.net2.0时,使用TraceSource作为Debug和Trace的增强版本。

TraceSource的配置:

  • Listeners:控制跟踪信息输出的方向(可以是:TextWriterTraceListener,DefaultTraceListener,EventLogTraceListener,WebPageTraceListener等,而TextWriterTraceListener的子类又有ConsoleTraceListener, DelimitedListTraceListener,XmlWriterTraceListener,EventSchemaTraceListener)
  • Switch:筛选信息的开关,主要包括BooleanSwitch 类、TraceSwitch 类和 SourceSwitch 类

主要参考的文献:

  • Trace、Debug和TraceSource的使用以及日志设计
  • TraceSource记录程序日志
  • TraceSource 类

我们回头看Microsoft.Framework.Logging.TraceSource代码,也就一目了然了.

    public class TraceSourceLoggerProvider : ILoggerProvider    {        private readonly SourceSwitch _rootSourceSwitch;        private readonly TraceListener _rootTraceListener;        private readonly ConcurrentDictionary<string, TraceSource> _sources = new ConcurrentDictionary<string, TraceSource>(StringComparer.OrdinalIgnoreCase);        public TraceSourceLoggerProvider([NotNull]SourceSwitch rootSourceSwitch, [NotNull]TraceListener rootTraceListener)        {            _rootSourceSwitch = rootSourceSwitch;            _rootTraceListener = rootTraceListener;        }        public ILogger CreateLogger(string name)        {            return new TraceSourceLogger(GetOrAddTraceSource(name));        }        private TraceSource GetOrAddTraceSource(string name)        {            return _sources.GetOrAdd(name, InitializeTraceSource);        }        private TraceSource InitializeTraceSource(string traceSourceName)        {            var traceSource = new TraceSource(traceSourceName);            string parentSourceName = ParentSourceName(traceSourceName);            if (string.IsNullOrEmpty(parentSourceName))            {                if (HasDefaultSwitch(traceSource))                {                    traceSource.Switch = _rootSourceSwitch;                }                if (_rootTraceListener != null)                {                    traceSource.Listeners.Add(_rootTraceListener);                }            }            else