[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 类
主要参考的文献:
我们回头看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-其他日志系统的实现的更多相关文章
- logbook日志系统
python中替代logging的日志系统. 不过比之前的logging难理解. 先上打印到屏幕上的代码和存到日志文件中的代码: #!/usr/bin/env python3 # -*- coding ...
- Python logging日志系统
写我小小的日志系统 配置logging有以下几种方式: 1)使用Python代码显式的创建loggers, handlers和formatters并分别调用它们的配置函数: 2)创建一个日志配置文件, ...
- .NET 黑魔法 - asp.net core 日志系统
asp.net core 里如何记录日志呢? 这要从asp.net core的依赖注入说起,在asp.net core里的依赖注入真是无所不在,各种面向切面的接口与事件. 好吧,来点干货. 首先,我们 ...
- ASP.NET Core分布式日志系统ELK实战演练
一.ELK简介 ELK是Elasticsearch.Logstash和Kibana首字母的缩写.这三者均是开源软件,这三套开源工具组合起来形成了一套强大的集中式日志管理平台. • Elastics ...
- 配置Tomcat的日志系统
成功配置tomcat的log4j日志系统,格式:HTML+每天以yyyy-mm-dd.log命名的日志文件 一.引言: 实习单位让用log4j配置webapp的日志系统,要求产生的日志文件是html格 ...
- ASP.NET Core Logging in Elasticsearch with Kibana
在微服务化盛行的今天,日志的收集.分析越来越重要.ASP.NET Core 提供了一个统一的,轻量级的Logining系统,并可以很方便的与第三方日志框架集成.我们也可以根据不同的场景进行扩展,因为A ...
- 玩转ASP.NET Core中的日志组件
简介 日志组件,作为程序员使用频率最高的组件,给程序员开发调试程序提供了必要的信息.ASP.NET Core中内置了一个通用日志接口ILogger,并实现了多种内置的日志提供器,例如 Console ...
- .Net core的日志系统
.net core是内置了日志系统的,本文这里简单的介绍一下它的基本用法.如下是一个简单的示例: var service = new ServiceCollection() .AddLogging(l ...
- .NET下使用 Seq结构化日志系统
前言 我们公司在日志管理方面一直没有统一,主要痛点有: 每个开发人员都是各用各的,存储日志的形式也是五花八门,如:本地文件,数据库,Redis,MongoDB 由于公司访问服务器要通过堡垒机,所以本机 ...
随机推荐
- SQL Server 数据变更时间戳(timestamp)在复制中的运用
一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 背景(Contexts) 方案(Solution) 方案一(Solution One) 方案二(Solution Two ...
- Linux 创建修改删除用户和组
200 ? "200px" : this.width)!important;} --> 介绍 在日常的维护过程中创建用户操作用的相对会多一些,但是在这个过程中涉及到的知识点就 ...
- SQL语句到底是怎么执行的
写在前面的话:有时不理解SQL语句各个部分执行顺序,导致理解上出现偏差,或者是书写SQL语句时随心所欲,所以有必要了解一下sql语句的执行顺序.可以有时间自己写一个简单的数据库,理解会更加深入.下面就 ...
- 60分钟Python快速学习(给发哥一个交代)
60分钟Python快速学习 之前和同事谈到Python,每次下班后跑步都是在听他说,例如Python属于“胶水语言啦”,属于“解释型语言啦!”,是“面向对象的语言啦!”,另外没有数据类型,逻辑全靠空 ...
- iOS------苹果设备处理器指令集(iPhone初代到iPhone5s)
(via 雅香小筑) Arm处理器,因为其低功耗和小尺寸而闻名,几乎所有的手机处理器都基于arm,其在嵌入式系统中的应用非常广泛,它的性能在同等功耗产品中也很出色. Armv6.armv7.armv7 ...
- Juint整合Log4j
一般Log4j配置在web.xml中,在单元测试时,不需要启动Tomcat,所有Log4j找不到配置文件 在测试类中手动加载 配置文件 PropertyConfigurator.configure(& ...
- 09 web开发高级应用(1)
- 1 <base> 标签用法 ```base: 为页面上的所有链接规定默认地址或默认目标target: 跳转到的目标页 <base target=_blank> <!- ...
- 使H1 H2等标签不换行
在网页优化中,经常要使用H标签对关键字进行优化, 可是如果是一行文字中的某个词加上了H1标记,就会换行. 可以使用下面的方法,H标签就不会强制换行了. <style type="tex ...
- 在 ML2 中 enable local network - 每天5分钟玩转 OpenStack(79)
前面完成了一系列准备工作,本节开始将创建各种 Neutorn 网络,我们首先讨论 local network. local network 的特点是不会与宿主机的任何物理网卡相连,也不关联任何的 VL ...
- EntityFramework之原始查询如何查询未映射的值,你又知道多少?
前言 今天又倒腾了下EF,如题所示,遇到了一些问题,并最终通过尝试找到了解决方案,可能不是最终的解决方案,若你有更好的解决方案,望告知,同时通过阅读此文,定让你收获不少. 引入 当我们查询时一直是中规 ...