[Asp.net 5] Logging-日志系统的基本架构(上)
本节主要介绍解决方案中的Microsoft.Framework.Logging.Abstractions、Microsoft.Framework.Logging俩个工程。
这俩个工程中所有类的关系如下图所示:
首先我们可以发现处于核心的是中间的四个接口:ILogger、ILoggerFactory、ILoggerProvider、ILogValues。
- ILogger:记录日志的接口,所以写日志的类都该实现该接口,工程中有俩个类实现了该接口:Logger、Logger<T>
- ILoggerFactory:创建ILogger的工厂。负责创建工厂的逻辑,但是一般不直接创建,而是调用内部ILoggerProvider去完成。
- ILoggerProvider:能够直接创建ILogger实例,做为属性添加到ILoggerFactory中,ILogger的具体逻辑受控制ILoggerFactory。
- ILogValues:在Logger的扩展方法中作为特殊类型的object传入,作为日志的数据源。
接口的定义源码如下:
public interface ILogger
{
void Log(LogLevel logLevel, int eventId, object state, Exception exception, Func<object, Exception, string> formatter); bool IsEnabled(LogLevel logLevel); IDisposable BeginScopeImpl(object state);
}
ILogger
public interface ILoggerFactory
{
LogLevel MinimumLevel { get; set; } ILogger CreateLogger(string categoryName); void AddProvider(ILoggerProvider provider);
}
ILoggerFactory
public interface ILoggerProvider
{
ILogger CreateLogger(string name);
}
ILoggerProvider
public interface ILogValues
{
IEnumerable<KeyValuePair<string, object>> GetValues();
}
ILogValues
ILogger以及实现类
ILogger接口、ILogger<TCategoryName>(没有任何定义)、Logger<T>这种泛型继承是否有相识之感,之前的博客文章中已经对于这种情况有所介绍([Asp.net 5] Localization-resx资源文件的管理中IStringLocalizer 、IStringLocalizer<T> 、StringLocalizer<TResourceSource>是一致的)。实际Logger<T>中T是ILogger的实例子类,实际就是使用代理模式,内部包含ILogger实例,并且所有对外的方法都仅仅是内部ILogger实例的封装。
public class Logger<T> : ILogger<T>
{
private readonly ILogger _logger; /// <summary>
/// Creates a new <see cref="Logger{T}"/>.
/// </summary>
/// <param name="factory">The factory.</param>
public Logger(ILoggerFactory factory)
{
_logger = factory.CreateLogger<T>();
} IDisposable ILogger.BeginScopeImpl(object state)
{
return _logger.BeginScopeImpl(state);
} bool ILogger.IsEnabled(LogLevel logLevel)
{
return _logger.IsEnabled(logLevel);
} void ILogger.Log(LogLevel logLevel, int eventId, object state, Exception exception, Func<object, Exception, string> formatter)
{
_logger.Log(logLevel, eventId, state, exception, formatter);
}
}
Logger
Logger类同样实现了ILogger接口,也同样使用了代理模式,不过不同于Logger<T>泛型,Logger类有自己的内部逻辑。而是在内部封装了 ILogger[] _loggers对象。使得Logger更像LoggerManage。但是由于Logger同样实现Logger接口,所以Logger类是管理其它Logger类的代理。而Logger内部的_loggers是通过LoggerFactory对象封装的。当记录日志时,依次遍历内部的 _loggers对象,进行写日志操作。
internal class Logger : ILogger
{
private readonly LoggerFactory _loggerFactory;
private readonly string _name;
private ILogger[] _loggers = new ILogger[]; public Logger(LoggerFactory loggerFactory, string name)
{
_loggerFactory = loggerFactory;
_name = name; var providers = loggerFactory.GetProviders();
_loggers = new ILogger[providers.Length];
for (var index = ; index != providers.Length; index++)
{
_loggers[index] = providers[index].CreateLogger(name);
}
} public void Log(LogLevel logLevel, int eventId, object state, Exception exception, Func<object, Exception, string> formatter)
{
if (logLevel >= _loggerFactory.MinimumLevel)
{
foreach (var logger in _loggers)
{
logger.Log(logLevel, eventId, state, exception, formatter);
}
}
} public bool IsEnabled(LogLevel logLevel)
{
if (logLevel < _loggerFactory.MinimumLevel)
{
return false;
}
foreach (var logger in _loggers)
{
if (logger.IsEnabled(logLevel))
{
return true;
}
}
return false;
} public IDisposable BeginScopeImpl(object state)
{
var loggers = _loggers;
var scope = new Scope(loggers.Length);
for (var index = ; index != loggers.Length; index++)
{
scope.SetDisposable(index, loggers[index].BeginScopeImpl(state));
}
return scope;
} internal void AddProvider(ILoggerProvider provider)
{
var logger = provider.CreateLogger(_name);
_loggers = _loggers.Concat(new[] { logger }).ToArray();
} private class Scope : IDisposable
{
private bool _isDisposed; private IDisposable _disposable0;
private IDisposable _disposable1;
private readonly IDisposable[] _disposable; public Scope(int count)
{
if (count > )
{
_disposable = new IDisposable[count - ];
}
} public void SetDisposable(int index, IDisposable disposable)
{
if (index == )
{
_disposable0 = disposable;
}
else if (index == )
{
_disposable1 = disposable;
}
else
{
_disposable[index - ] = disposable;
}
} protected virtual void Dispose(bool disposing)
{
if (!_isDisposed)
{
if (disposing)
{
if (_disposable0 != null)
{
_disposable0.Dispose();
}
if (_disposable1 != null)
{
_disposable1.Dispose();
}
if (_disposable != null)
{
var count = _disposable.Length;
for (var index = ; index != count; ++index)
{
if (_disposable[index] != null)
{
_disposable[index].Dispose();
}
}
}
} _isDisposed = true;
}
} // This code added to correctly implement the disposable pattern.
public void Dispose()
{
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
Dispose(true);
// TODO: tell GC not to call its finalizer when the above finalizer is overridden.
// GC.SuppressFinalize(this);
} internal void Add(IDisposable disposable)
{
throw new NotImplementedException();
}
}
}
Logger
ILoggerFactory以及实现类
ILoggerFactory主要有俩个作用,添加新的ILoggerProvider,创建ILogger。而ILoggerFactory的唯一实现类LoggerFactory,简单实现了上面两个功能,并且在LoggerFactory内部额外维护_loggers副本,该处loggers都是Logger类型(非泛型),只是categoryName不同。所以通过LoggerFactory创建的Logger如下图所示:

public class LoggerFactory : ILoggerFactory
{
private readonly Dictionary<string, Logger> _loggers = new Dictionary<string, Logger>(StringComparer.Ordinal);
private ILoggerProvider[] _providers = new ILoggerProvider[];
private readonly object _sync = new object(); public ILogger CreateLogger(string categoryName)
{
Logger logger;
lock (_sync)
{
if (!_loggers.TryGetValue(categoryName, out logger))
{
logger = new Logger(this, categoryName);
_loggers[categoryName] = logger;
}
}
return logger;
} public LogLevel MinimumLevel { get; set; } = LogLevel.Verbose; public void AddProvider(ILoggerProvider provider)
{
lock (_sync)
{
_providers = _providers.Concat(new[] { provider }).ToArray();
foreach (var logger in _loggers)
{
logger.Value.AddProvider(provider);
}
}
} internal ILoggerProvider[] GetProviders()
{
return _providers;
}
}
LoggerFactory
[Asp.net 5] Logging-日志系统的基本架构(上)的更多相关文章
- Python logging日志系统
写我小小的日志系统 配置logging有以下几种方式: 1)使用Python代码显式的创建loggers, handlers和formatters并分别调用它们的配置函数: 2)创建一个日志配置文件, ...
- ASP.NET Core分布式日志系统ELK实战演练
一.ELK简介 ELK是Elasticsearch.Logstash和Kibana首字母的缩写.这三者均是开源软件,这三套开源工具组合起来形成了一套强大的集中式日志管理平台. • Elastics ...
- Elasticsearch,Kibana,Logstash,NLog实现ASP.NET Core 分布式日志系统
Elasticsearch - 简介 Elasticsearch 作为核心的部分,是一个具有强大索引功能的文档存储库,并且可以通过 REST API 来搜索数据.它使用 Java 编写,基于 Apac ...
- Asp.net core logging 日志
1 基本概念 Dotnet core 一个重要的特征是 Dependency injection ,中文一般是依赖注入,可以简单理解为一个集合,在应用程序启动时,定义各种具体的实现类型并将其放到集合中 ...
- [Asp.net 5] Logging-日志系统的基本架构(下)
接上节内容,我们继续讲解日志的其他部分. ILoggerProvider以及扩展类 我们在上节的架构图上并没有看到有直接实现该接口的实现类.那么如果将Logger类直接使用会有什么结果呢? var f ...
- [Asp.net 5] Logging-其他日志系统的实现
Microsoft.Framework.Logging.NLog 使用Nlog扩展日志系统:按照我们上节说的,对于扩展的日志系统都要实现俩个接口ILogger.ILoggerProvider.所以在当 ...
- [Asp.net 5] Logging-新日志系统目录
楼主有个美好的愿望——把asp.net 5所有能看懂的代码一一呈现给大家(比如C++,楼主就看不懂).现在已经做完了依赖注入.多语言.配置文件三部分,比较基础的日志就成为了楼主的下一个目标.下面是楼主 ...
- Python logging(日志)模块
python日志模块 内容简介 1.日志相关概念 2.logging模块简介 3.logging模块函数使用 4.logging模块日志流处理流程 5.logging模块组件使用 6.logging配 ...
- pyhton——logging日志模块的学习
https://www.cnblogs.com/yyds/p/6901864.html 本节内容 日志相关概念 logging模块简介 使用logging提供的模块级别的函数记录日志 logging模 ...
随机推荐
- review简历之感想和建议
最近帮很多朋友review他们的简历,总结起来存在以下问题: 1,简历太多页了.请尽量不超过两页.一般地,每个hr阅读简历的时间大概在20s甚至更少,写那么多页不仅毫无必要,而且有害. 而且我怀疑一般 ...
- 浅谈Android应用保护(零):出发点和背景
近几年来,无线平台特别是Android平台的安全逐渐成为各厂商关注的重点.各种新的思路和玩法层出不穷.所以,笔者基于前一段时间的学习和整理,写了这系列关于Android应用安全和保护的文章. 这5篇文 ...
- ASP.NET MVC学前篇之Ninject的初步了解
ASP.NET MVC学前篇之Ninject的初步了解 1.介绍 废话几句,Ninject是一种轻量级的.基础.NET的一个开源IoC框架,在对于MVC框架的学习中会用到IoC框架的,因为这种IoC开 ...
- Nodejs初阶之express
PS: 2014/09/24 更新<Express 4.X 启航指南>,欢迎阅读和评论:) 老规矩,开头部分都是些自娱自乐的随想,想到哪写到哪... 到今天俺已经在俺厂工作俩年零几天了 ...
- MA均线组合
MA5.MA13.MA21.MA34.MA55.MA90.MA120.MA250
- 携程App的网络性能优化实践
首先介绍一下携程App的网络服务架构.由于携程业务众多,开发资源导致无法全部使用Native来实现业务逻辑,因此有相当一部分频道基于Hybrid实现.网络通讯属于基础&业务框架层中基础设施的一 ...
- 浅谈JavaScript的New关键字
原型和闭包算是JavaScript中最常见,最难以理解,最容易被当做问题的两个部分,当然还有它们的延伸,如作用域链,继承等等吧,我最近也是各种看,各种翻,记录点自己的心得,写写总会让自己的理解更深一些 ...
- CSS系列:CSS选择器
选择器(selector)是CSS中很重要的概念,所有HTML语言中的标记样式都是通过不同的CSS选择器来控制的.用户只需要通过选择对不同的HTML标签进行选择,并赋予各种样式声明,即可实现各种效果. ...
- SqlServer性能检测和优化工具使用详细
工具概要 如果你的数据库应用系统中,存在有大量表,视图,索引,触发器,函数,存储过程,sql语句等等,又性能低下,而苦逼的你又要对其优化,那么你该怎么办?哥教你,首先你要知道问题出在哪里?如果想知道问 ...
- OpenCASCADE Interpolation - Lagrange
OpenCASCADE Interpolation - Lagrange eryar@163.com Abstract. Power basis polynomial is the most simp ...