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

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

测试代码:

<?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 类

主要参考的文献:

我们回头看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
{
if (HasDefaultListeners(traceSource))
{
TraceSource parentTraceSource = GetOrAddTraceSource(parentSourceName);
traceSource.Listeners.Clear();
traceSource.Listeners.AddRange(parentTraceSource.Listeners);
} if (HasDefaultSwitch(traceSource))
{
TraceSource parentTraceSource = GetOrAddTraceSource(parentSourceName);
traceSource.Switch = parentTraceSource.Switch;
}
} return traceSource;
} private static string ParentSourceName(string traceSourceName)
{
int indexOfLastDot = traceSourceName.LastIndexOf('.');
return indexOfLastDot == - ? null : traceSourceName.Substring(, indexOfLastDot);
} private static bool HasDefaultListeners(TraceSource traceSource)
{
return traceSource.Listeners.Count == && traceSource.Listeners[] is DefaultTraceListener;
} private static bool HasDefaultSwitch(TraceSource traceSource)
{
return string.IsNullOrEmpty(traceSource.Switch.DisplayName) == string.IsNullOrEmpty(traceSource.Name) &&
traceSource.Switch.Level == SourceLevels.Off;
}
}

TraceSourceLoggerProvider

    internal class TraceSourceLogger : ILogger
{
private readonly TraceSource _traceSource; public TraceSourceLogger(TraceSource traceSource)
{
_traceSource = traceSource;
} public void Log(LogLevel logLevel, int eventId, object state, Exception exception, Func<object, Exception, string> formatter)
{
if (!IsEnabled(logLevel))
{
return;
}
var message = string.Empty;
if (formatter != null)
{
message = formatter(state, exception);
}
else
{
if (state != null)
{
message += state;
}
if (exception != null)
{
message += Environment.NewLine + exception;
}
}
if (!string.IsNullOrEmpty(message))
{
_traceSource.TraceEvent(GetEventType(logLevel), eventId, message);
}
} public bool IsEnabled(LogLevel logLevel)
{
var traceEventType = GetEventType(logLevel);
return _traceSource.Switch.ShouldTrace(traceEventType);
} private static TraceEventType GetEventType(LogLevel logLevel)
{
switch (logLevel)
{
case LogLevel.Critical: return TraceEventType.Critical;
case LogLevel.Error: return TraceEventType.Error;
case LogLevel.Warning: return TraceEventType.Warning;
case LogLevel.Information: return TraceEventType.Information;
case LogLevel.Verbose:
default: return TraceEventType.Verbose;
}
} public IDisposable BeginScopeImpl(object state)
{
return new TraceSourceScope(state);
}
}

TraceSourceLogger

        [Fact]
public static void IsEnabledReturnsCorrectValue()
{
// Arrange
var testSwitch = new SourceSwitch("TestSwitch", "Level will be set to warning for this test");
testSwitch.Level = SourceLevels.Warning; var factory = new LoggerFactory();
var logger = factory.CreateLogger("Test"); // Act
factory.AddTraceSource(testSwitch, new ConsoleTraceListener()); // Assert
Assert.True(logger.IsEnabled(LogLevel.Critical));
Assert.True(logger.IsEnabled(LogLevel.Error));
Assert.True(logger.IsEnabled(LogLevel.Warning));
Assert.False(logger.IsEnabled(LogLevel.Information));
Assert.False(logger.IsEnabled(LogLevel.Verbose));
} [Theory]
[InlineData(SourceLevels.Warning, SourceLevels.Information, true)]
[InlineData(SourceLevels.Information, SourceLevels.Information, true)]
[InlineData(SourceLevels.Information, SourceLevels.Warning, true)]
[InlineData(SourceLevels.Warning, SourceLevels.Warning, false)]
public static void MultipleLoggers_IsEnabledReturnsCorrectValue(SourceLevels first, SourceLevels second, bool expected)
{
// Arrange
var firstSwitch = new SourceSwitch("FirstSwitch", "First Test Switch");
firstSwitch.Level = first; var secondSwitch = new SourceSwitch("SecondSwitch", "Second Test Switch");
secondSwitch.Level = second; var factory = new LoggerFactory();
var logger = factory.CreateLogger("Test"); // Act
factory.AddTraceSource(firstSwitch, new ConsoleTraceListener());
factory.AddTraceSource(secondSwitch, new ConsoleTraceListener()); // Assert
Assert.Equal(expected, logger.IsEnabled(LogLevel.Information));
}
}

[Asp.net 5] Logging-其他日志系统的实现的更多相关文章

  1. logbook日志系统

    python中替代logging的日志系统. 不过比之前的logging难理解. 先上打印到屏幕上的代码和存到日志文件中的代码: #!/usr/bin/env python3 # -*- coding ...

  2. Python logging日志系统

    写我小小的日志系统 配置logging有以下几种方式: 1)使用Python代码显式的创建loggers, handlers和formatters并分别调用它们的配置函数: 2)创建一个日志配置文件, ...

  3. .NET 黑魔法 - asp.net core 日志系统

    asp.net core 里如何记录日志呢? 这要从asp.net core的依赖注入说起,在asp.net core里的依赖注入真是无所不在,各种面向切面的接口与事件. 好吧,来点干货. 首先,我们 ...

  4. ASP.NET Core分布式日志系统ELK实战演练

    一.ELK简介  ELK是Elasticsearch.Logstash和Kibana首字母的缩写.这三者均是开源软件,这三套开源工具组合起来形成了一套强大的集中式日志管理平台. •  Elastics ...

  5. 配置Tomcat的日志系统

    成功配置tomcat的log4j日志系统,格式:HTML+每天以yyyy-mm-dd.log命名的日志文件 一.引言: 实习单位让用log4j配置webapp的日志系统,要求产生的日志文件是html格 ...

  6. ASP.NET Core Logging in Elasticsearch with Kibana

    在微服务化盛行的今天,日志的收集.分析越来越重要.ASP.NET Core 提供了一个统一的,轻量级的Logining系统,并可以很方便的与第三方日志框架集成.我们也可以根据不同的场景进行扩展,因为A ...

  7. 玩转ASP.NET Core中的日志组件

    简介 日志组件,作为程序员使用频率最高的组件,给程序员开发调试程序提供了必要的信息.ASP.NET Core中内置了一个通用日志接口ILogger,并实现了多种内置的日志提供器,例如 Console ...

  8. .Net core的日志系统

    .net core是内置了日志系统的,本文这里简单的介绍一下它的基本用法.如下是一个简单的示例: var service = new ServiceCollection() .AddLogging(l ...

  9. .NET下使用 Seq结构化日志系统

    前言 我们公司在日志管理方面一直没有统一,主要痛点有: 每个开发人员都是各用各的,存储日志的形式也是五花八门,如:本地文件,数据库,Redis,MongoDB 由于公司访问服务器要通过堡垒机,所以本机 ...

随机推荐

  1. xcodebuild命令行打包发布ipa

    配置好证书,然后在命令行转到项目目录 1.清除 EthantekiiMac:CTest ethan$ xcodebuild clean 2.编译 EthantekiiMac:CTest ethan$ ...

  2. SQL Server 2008, 2008 R2, 2012 and 2014 完全支持TLS1.2加密传输

    SQL Server 2008, 2008 R2, 2012 and 2014 完全支持TLS1.2加密传输 微软高兴地宣布所有主流SQL Server客户端驱动和SQL Server发行版已经支持T ...

  3. 拥抱.NET Core,学习.NET Core的基础知识补遗

    前言 .NET Core的新特性之一就是跨平台,但由于对之前框架的兼容导致编写一个.NET Core类库变得相当复杂,主要体现为相当多的框架目标和支持平台,今天我们就对.NET Core的跨平台特性进 ...

  4. Java NIO5:选择器1---理论篇

    选择器 最后,我们探索一下选择器.由于选择器内容比较多,所以本篇先偏理论地讲一下,后一篇讲代码,文章也没有什么概括.总结的,写到哪儿算哪儿了,只求能将选择器写明白,并且将一些相对重要的内容加粗标红. ...

  5. python3.5 正则表达式

    我们平时上网的时候,经常需要在一些网站上注册帐号,而注册帐号的时候对帐号名称会有一些要求. 比如: 上面的图片中,输入的邮件地址.密码.手机号 才可以注册成功. 我们需要匹配用户输入的内容,判断用户输 ...

  6. API调试工具推荐 - httpie

    API调试工具推荐 - httpie <HelloGitHub>第07期上面看到这个python项目,好东西 文档地址 但是安装的时候报错,google之后发现是个已知的bug,直接使用p ...

  7. SQL中Group By的使用

    1.概述 2.原始表 3.简单Group By 4.Group By 和 Order By 5.Group By中Select指定的字段限制 6.Group By All 7.Group By与聚合函 ...

  8. easyui-combobox实现省-市-区县级联菜单

    省:<input id="sheng" class="easyui-combobox" style="width:100px" dat ...

  9. python发送邮件及附件

    今天给大伙说说python发送邮件,官方的多余的话自己去百度好了,还有一大堆文档说实话不到万不得已的时候一般人都不会去看,回归主题: 本人是mac如果没有按照依赖模块的请按照下面的截图安装 导入模块如 ...

  10. 2014 年最热门的国人开发开源软件 TOP 100 - 开源中国社区

    不知道从什么时候开始,很多一说起国产好像就非常愤慨,其实大可不必.做开源中国六年有余,这六年时间国内的开源蓬勃发展,从一开始的使用到贡献,到推出自己很多的开源软件,而且还有很多软件被国外的认可.中国是 ...