Tian’s blog

149 阅读2分钟
原文链接: www.bluetian.net

前言

本文我将演示如何定制日志记录。默认的日志记录仅仅向控制台或者debug窗口输出日志,这样可以满足一些情况,但是你可能还需要把日志记录到一个磁盘文件或者数据库,或者你想为记录额外的信息。这样的场景你就需要知道如何修改默认的日志记录。


配置日志记录

在asp.net core 2.0以前的版本,日志记录是在Startup.cs中,从2.0开始startup.cs被简化,并且把大量的配置代码转移到了webhostBuider中(3.0 是CreateDefaultBuilder)。同样日志记录配置也被转移到了该地方。

public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); });
    }

在asp.net core 中你几乎可以修改所有的东西。所以你也能够定制日志记录。IHostBuilder有很多可以覆盖默认行为的扩展方法。我们需要用ConfigureLogging方法去覆盖日志记录的默认逻辑。下面在CreateDefaultBuilder插入的代码演示了如何配置日志记录


Host.CreateDefaultBuilder(args)
                .ConfigureLogging((hostingContext, logging) =>
                    {
                        logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
                        logging.AddConsole();
                        logging.AddDebug();
                    })
                .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); });

这个方法需要一个获取HostBuilderContext的lambda表达式,HostBuilderContext包含了用于配置日志的hosting context和一个LoggingBuilder。

创建一个自定义的logger

为了演示如何自定义logger,我创建一个简单的logger,这个logger能够把指定的日志等级用带颜色的文字输出到控制台。我们创建一个名为ColoredConsoleLogger的类,我们同样写一个LoggerProvider用来增加与创建上面的logger。为了把输出指定的颜色和日志等级,我们还需要增加一个配置类,下面代码包含了上述三部分的具体实现:

public class ColoredConsoleLoggerConfiguration
    {
        public LogLevel LogLevel { get; set; } = LogLevel.Warning;
        public int EventId { get; set; } = 0;
        public ConsoleColor Color { get; set; } = ConsoleColor.Yellow;
    }

    public class ColoredConsoleLoggerProvider : ILoggerProvider
    {
        private readonly ColoredConsoleLoggerConfiguration _config;

        private readonly ConcurrentDictionary<string, ColoredConsoleLogger> _loggers =
            new ConcurrentDictionary<string, ColoredConsoleLogger>();

        public ColoredConsoleLoggerProvider(ColoredConsoleLoggerConfiguration config)
        {
            _config = config;
        }

        public ILogger CreateLogger(string categoryName)
        {
            return _loggers.GetOrAdd(categoryName, name => new ColoredConsoleLogger(name, _config));
        }

        public void Dispose()
        {
            _loggers.Clear();
        }
    }

    public class ColoredConsoleLogger : ILogger
    {
        private static object _lock = new Object();
        private readonly string _name;
        private readonly ColoredConsoleLoggerConfiguration _config;

        public ColoredConsoleLogger(string name, ColoredConsoleLoggerConfiguration config)
        {
            _name = name;
            _config = config;
        }

        public IDisposable BeginScope<TState>(TState state)
        {
            return null;
        }

        public bool IsEnabled(LogLevel logLevel)
        {
            return logLevel == _config.LogLevel;
        }

        public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception,
            Func<TState, Exception, string> formatter)
        {
            if (!IsEnabled(logLevel))
            {
                return;
            }

            lock (_lock)
            {
                if (_config.EventId == 0 || _config.EventId == eventId.Id)
                {
                    var color = Console.ForegroundColor;
                    Console.ForegroundColor = _config.Color;
                    Console.WriteLine(
                        $"{logLevel.ToString()} - {eventId.Id} - {_name} - {formatter(state, exception)}");
                    Console.ForegroundColor = color;
                }
            }
        }
    }

我们需要对具体的控制台输出加上锁,因为控制台不是线程安全的。接下来我们就可以把自定义的logger添加到ConfigureLogging方法中了:


logging.ClearProviders();

var config = new ColoredConsoleLoggerConfiguration
{
    LogLevel = LogLevel.Information,
    Color = ConsoleColor.Red
};
logging.AddProvider(new ColoredConsoleLoggerProvider(config));

我们可以清除之前已经添加的logger provider,然后我们通过AddProvider增加一个指定对应的日志记录设置ColoredConsoleLoggerProvider实例。我们也可以增加其他不同日志记录设置的实例。下图我们就可以看到我们自定义日志记录的效果输出

avatar