3.1,自定义日志框架

进行本章的学习时,请使用 learn 分支。

https://github.com/whuanle/maomi/tree/learn


本节示例项目在 Demo2.MyLogger.Console 中。

创建控制台项目后,添加 Microsoft.Extensions.Logging.Console 引用。

创建 MyLoggerOptions ,存储日志配置:

public class MyLoggerOptions
{
    /// <summary>
    /// 最小日志等级
    /// </summary>
    public LogLevel DefaultLevel { get; set; } = LogLevel.Debug;
}


创建自定义日志记录器:

/// <summary>
/// 自定义的日志记录器
/// </summary>
public class MyConsoleLogger : ILogger
{
    // 日志名称
    private readonly string _name;
    private readonly MyLoggerOptions _options;

    public MyConsoleLogger(string name, MyLoggerOptions options)
    {
        _name = name;
        _options = options;
    }

    public IDisposable? BeginScope<TState>(TState state) where TState : notnull => default!;

    // 判断是否启用日志等级
    public bool IsEnabled(LogLevel logLevel)
    {
        return logLevel >= _options.DefaultLevel;
    }

    // 记录日志,formatter 由框架提供的字符串格式化器
    public void Log<TState>(
        LogLevel logLevel,
        EventId eventId,
        TState state,
        Exception? exception,
        Func<TState, Exception?, string> formatter)
    {
        if (!IsEnabled(logLevel))
        {
            return;
        }
        if (logLevel == LogLevel.Critical)
        {
            System.Console.ForegroundColor = System.ConsoleColor.Red;
            System.Console.WriteLine($"[{logLevel}] {_name} {formatter(state, exception)} {exception}");
            System.Console.ResetColor();
        }
        else if (logLevel == LogLevel.Error)
        {
            System.Console.ForegroundColor = System.ConsoleColor.DarkRed;
            System.Console.WriteLine($"[{logLevel}] {_name} {formatter(state, exception)} {exception}");
            System.Console.ResetColor();
        }
        else
        {
            System.Console.WriteLine($"[{logLevel}] {_name} {formatter(state, exception)} {exception}");
        }
    }
}


创建自定义日志提供器:

[ProviderAlias("MyConsole")]
public sealed class MyLoggerProvider : ILoggerProvider
{
    private MyLoggerOptions _options;
    private readonly ConcurrentDictionary<string, MyConsoleLogger> _loggers =
        new(StringComparer.OrdinalIgnoreCase);

    public MyLoggerProvider(MyLoggerOptions options)
    {
        _options = options;
    }

    public ILogger CreateLogger(string categoryName) =>
        _loggers.GetOrAdd(categoryName, name => new MyConsoleLogger(name, _options));

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


编写扩展函数,注入自定义日志提供器:

public static class MyLoggerExtensions
{
    public static ILoggingBuilder AddMyConsoleLogger(
        this ILoggingBuilder builder, Action<MyLoggerOptions> action)
    {
        MyLoggerOptions options = new();
        if (action != null)
        {
            action.Invoke(options);
        }

        builder.AddConfiguration();
        builder.Services.TryAddEnumerable(
            ServiceDescriptor.Singleton<ILoggerProvider>(new MyLoggerProvider(options)));
        return builder;
    }
}


最后使用 Microsoft.Extensions.Logging 中的 LoggerFactory,构建日志工厂,从中生成 ILogger 对象,最后打印日志:

static void Main(string[] args)
{
    using ILoggerFactory factory = LoggerFactory.Create(builder =>
    {
        builder.AddConsole();
        builder.AddMyConsoleLogger(options =>
        {
            options.DefaultLevel = LogLevel.Debug;
        });
    });
    ILogger logger1 = factory.CreateLogger("Program");
    ILogger logger2 = factory.CreateLogger<Program>();

    logger1.LogError(new Exception("报错了"), message: "Hello World! Logging is {Description}.", args: "error");
    logger2.LogError(new Exception("报错了"), message: "Hello World! Logging is {Description}.", args: "error");
}

image-20240104185853068

Copyright © 痴者工良 2024 all right reserved,powered by Gitbook文档最后更新时间: 2025-01-09 18:51:58

results matching ""

    No results matching ""