美文网首页
2020-03-29 09:00 EFCore的日志系统

2020-03-29 09:00 EFCore的日志系统

作者: daiwei_9b9c | 来源:发表于2020-03-29 16:40 被阅读0次

提纲

  1. 构建 ILoggerFactory 的实例
  2. 此实例中, 添加 ILoggerProvider 接口的实例到 ILoggerProvider的枚举
  3. 通过 ILoggerProvider的枚举创建 ILogger的实例的枚举,并通过 Composite 模式将日志写入到各个 ILogger 中
  4. 各个 ILogger 实例根据日志级别判断是否应该写入日志, 准备写入日志(返回 Dispose实例),写入日志,释放 Dispose实例;

EFCore的Logging项目

[https://github.com/dotnet/EntityFramework.Docs/tree/master/samples/core/Miscellaneous/Logging]

注意这个项目不能使用 add-migration InitiateContext 方式去创建数据库和表,

因为其在构造函数中调用了 OnConfigure 方法,而此方法会创建 日志工厂的实例,但貌似在 NPM中创建日志工厂的实例将失败,因为NPM并没有加载所有的库而抛出一个未找到方法的异常;
所以,这儿有一行代码

创建数据库(如果数据库不存在,则创建数据库和所有的表,如果数据库存在,则不继续处理,也不会根据当前类型变动表结构
db.Database.EnsureCreated();  

主要代码如下

 public static readonly ILoggerFactory MyLoggerFactory
            = LoggerFactory.Create(builder => { builder.AddConsole();
            });
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
            => optionsBuilder
                .UseLoggerFactory(MyLoggerFactory) // Warning: 应该使用静态实例
                .UseSqlServer(
                    @"Server=(localdb)\mssqllocaldb;Database=EFLogging;Trusted_Connection=True;ConnectRetryCount=0");

主要逻辑就是, 使用静态方法构建 Microsoft.Extensions.Logging.LoggerFactory.Create 构架 ILoggerFactory 的实例,
使用包 Microsoft.Extensions.Logging.Console 内的扩展方法 (AddConsole) 使得日志消息输出到 Console
扩展方法定义

估计,这个方法是再 ILoggingBuider中添加了一个  ConsoleLoggerProvider 的实例,
并且为了支持链式调用,又返回了 传入ILoggingBuilder 实例
public static ILoggingBuilder AddConsole(this ILoggingBuilder builder);
public static ILoggingBuilder AddConsole(this ILoggingBuilder builder, Action<ConsoleLoggerOptions> configure);

从上面,至少我们看到了2个类, ILoggingBuilder, ILoggerFactory,

LoggerFactory 类

public class LoggerFactory : ILoggerFactory, IDisposable
{
        public LoggerFactory();
        public LoggerFactory(IEnumerable<ILoggerProvider> providers);
        public LoggerFactory(IEnumerable<ILoggerProvider> providers, LoggerFilterOptions filterOptions);
        public LoggerFactory(IEnumerable<ILoggerProvider> providers, IOptionsMonitor<LoggerFilterOptions> filterOption);
        public static ILoggerFactory Create(Action<ILoggingBuilder> configure);
        public void AddProvider(ILoggerProvider provider);
        下面这个创建 Microsoft.Extensions.Logging.ILogger 的实例,  并指定此实例记录的消息的分类名称
        public ILogger CreateLogger(string categoryName);

上面代码又引入了更多的类, ILoggerProvider, ILogger
如果继续往下理,可能会更多更复杂的类出来,我们只看最基础的,也就是 Microsoft.Extensions.Logging
这个命名空间内的内容;

Microsoft.Extensions.Logging.LogLevel 定义日志级别,

更有7个日志级别,从低到高,越低日志记录就越详细

        // 摘要:记录最详细的信息
       Trace = 0,
        // 摘要:记录调试的信息
        Debug = 1,
        // 摘要:记录调用工作流信息,
        Information = 2,
        // 摘要:记录不正常或者非预期的事件
        Warning = 3,
        // 摘要:记录异常
        Error = 4,
        // 摘要:记录应用奔溃
        Critical = 5,
        // 摘要:
        None = 6

直接使用日志级别的是 ILogger 接口, 实现 ILogger 接口的类是 Logger<T> 的类,但是这个类的构造函数需要传入 ILoggerFactory 接口的实例,

ILoggerFactory 接口

代表一个配置日志系统和根据已注册的 ILoggerProvider 创建ILogger实例的类
ILoggerFactory 很简单

    public interface ILoggerFactory : IDisposable
    {
        void AddProvider(ILoggerProvider provider);
        ILogger CreateLogger(string categoryName);
    }

这儿很明显会根据已注册的 ILoggerProvider 列表,
创建一个 ILogger的实例,当然对于这个 ILogger的实例, 里面应该会遍历调用已注册的 ILoggerProvider列表的里面的方法(所以 ILoggerProvider 应该也有 CreateLogger 的方法) ,然后写日志时,再遍历调用 ILogger 实例里面的日志记录方法

ILoggerProvider接口

    public interface ILoggerProvider : IDisposable
   {
        ILogger CreateLogger(string categoryName);
   }

ILogger 接口

这个接口应该是真正将日志进行处理的接口(例如写文件\写控制台\或者啥都不干,例如 NullLogger)
表示一个处理日志的类型

         /**开始记录一个逻辑操作区间(基本上就是写日志之前做点事情,写完日志之后再调用这个东东返回的 Dispose 方法**/
        IDisposable BeginScope<TState>(TState state);
      
       /** 摘要:对于给定的日志级别,是否记录日志**/
        bool IsEnabled(LogLevel logLevel);

      /**写日志的方法
      logLevel 日志级别
      eventId 事件Id
      state 被写入的对象
      exception 和对象相关的异常 
      formatter 转换 state 和 exception 转换为字符串的方法,以便写入日志内容 **/
        void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter);
    }

写日志时还会写入日志的事件Id

EventId 接口

    // 日志事件Id ( 结构 ),主要有 Id 和 Name属性
    public readonly struct EventId
    {    
       public EventId(int id, string name = null);
       public int Id { get; }
       public string Name { get; }
       public static implicit operator EventId(int i);
     ...
  }

相关文章

  • 2020-03-29 09:00 EFCore的日志系统

    提纲 构建 ILoggerFactory 的实例 此实例中, 添加 ILoggerProvider 接口的实例到 ...

  • weblogic日志异常排查[时区错误]

    问题:weblogic打印日志时间比系统时间晚8小时。 系统时间:2018-10-23 09:53 日志时间:...

  • 日志排查命令

    搜索按照多个条件搜索,查找某个时间段的日志 sed -n '/2020-07-09 18:00:00/, /202...

  • efcore 新特性 SaveChanges Events

    efcore 新特性 SaveChanges Events Intro 昨天早上看到之前关注的一个 efcore ...

  • linux 更改系统时间

    查看系统时间 date 更改系统时间sudo date -s "2016-12-24 09:18:00"修改完后,...

  • 2018-06-09

    6.8日志 平淡是福1188 2018-06-09 00:45 · 字数 435 · 阅读 0 · 日记本 《给予...

  • 2018-06-09

    6.8日志 平淡是福1188 2018-06-09 00:45 · 字数 435 · 阅读 0 · 日记本 《给予...

  • 2020-03-28 EFCore 的教程 -- 提纲2

    EFCore入门配置数据库连接字符串EFCore 如何自动获知数据库主键将项目的变动更新到数据库安装 EFCore...

  • EFCore记录慢查询日志

    在生产环境中,通常有DBA同事对数据库进行监控,在发现如慢查询等问题时反馈给开发团队进行解决。 .NET平台提供了...

  • Funboot开发:系统日志组件

    系统日志组件 目录 系统日志 使用MongoDb存储日志 系统日志 系统日志分为操作日志、错误日志、登录日志、数据...

网友评论

      本文标题:2020-03-29 09:00 EFCore的日志系统

      本文链接:https://www.haomeiwen.com/subject/knuyuhtx.html