.Net 8 进阶——日志组件

69 阅读1分钟

日志组件可以将方法中的日志存储到某个地方(Console控制台、文件、数据库)

1. 控制台日志输出

Install-Package Microsoft.Extensions.Logging
Install-Package Microsoft.Extensions.Logging.Console
var logger = LoggerFactory.Create(builder =>
{
    builder.AddConsole();
});
​
ILogger<Program> log = logger.CreateLogger<Program>();
​
log.LogInformation("Hello Logger Console");
info: Program[0]
      Hello Logger Console

2. 日志文件输出

Install-Package Microsoft.Extensions.Logging
Karambolo.Extensions.Logging.File
var logger = LoggerFactory.Create(builder =>
{
    builder.AddFile(options =>
    {
        options.RootPath = AppContext.BaseDirectory;
        options.Files = [new LogFileOptions { Path = "logs/log.txt" }];
    });
});
​
ILogger<Program> log = logger.CreateLogger<Program>();
​
log.LogInformation("Hello Logger Console");
​
Console.ReadKey();
// 路径:logs/log.txt
info: Program[0] @ 2024-09-06T09:47:58.9652349+08:00
      Hello Logger Console

3. 日志写入数据库

// 需要新增一个日志功能扩展, 传入一个connectString
internal static class MySQLLoggerExtensions
{
    public static ILoggingBuilder AddMySQLogger(this ILoggingBuilder builder, string connectString)
    {
        // todo 处理MySQL日志打印的逻辑,入参connectString
        // builder.AddProvider(new MySQLoggerProvider(connectString));
        return builder;
    } 
}
// 还得处理获取到的connectString
public static ILoggingBuilder AddProvider(this ILoggingBuilder builder, ILoggerProvider provider)
{
    builder.Services.AddSingleton(provider);
    return builder;
}
internal class MySQLoggerProvider : ILoggerProvider
{
    private string _ConnectionString {  get; set; }
​
    public MySQLoggerProvider(string connectionString)
    {
        this._ConnectionString = connectionString;
    }
​
    public ILogger CreateLogger(string categoryName)
    {
        return new MySQLogger(_ConnectionString);
    }
​
    public void Dispose()
    {
        
    }
}
internal class MySQLogger : ILogger
{
    public string _connectionString { get; set; }
​
    public MySQLogger(string connectionString) 
    {
        this._connectionString = connectionString;
    }
​
    public IDisposable? BeginScope<TState>(TState state) where TState : notnull
    {
        return null;
    }
​
    public bool IsEnabled(LogLevel logLevel)
    {
        return true;
    }
​
    public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState, Exception?, string> formatter)
    {
        if (!IsEnabled(logLevel))
        {
            return;
        }
​
        var message = formatter(state, exception);
​
        using (var connection = new MySqlConnection(_connectionString))
        {
            var command = connection.CreateCommand();
​
            command.CommandText = "INSERT INTO Logs (Message, LogLevel, CreatedTime) VALUES (@message, @logLevel, @createdTime)";
            command.Parameters.AddWithValue("@message", message);
            command.Parameters.AddWithValue("@logLevel", logLevel.ToString());
            command.Parameters.AddWithValue("@createdTime", DateTime.UtcNow);
​
            connection.Open();
            command.ExecuteNonQuery();
        }
    }
}

4. 日志级别与配置

从源码得知,日志的等级有Trace, Debug, Information, Warning, Error, Critical

// Microsoft.Extensions.Logging.LogLevel
public enum LogLevel
{
    Trace, Debug, Information, Warning, Error, Critical, None
}
// Microsoft.Extensions.Logging.LoggingBuilderExtensions
using System;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
​
public static class LoggingBuilderExtensions
{
    public static ILoggingBuilder SetMinimumLevel(this ILoggingBuilder builder, LogLevel level)
    {
        builder.Services.Add(ServiceDescriptor.Singleton((IConfigureOptions<LoggerFilterOptions>)new DefaultLoggerLevelConfigureOptions(level)));
        return builder;
    }
​
    public static ILoggingBuilder AddProvider(this ILoggingBuilder builder, ILoggerProvider provider)
    {
        builder.Services.AddSingleton(provider);
        return builder;
    }
​
    public static ILoggingBuilder ClearProviders(this ILoggingBuilder builder)
    {
        builder.Services.RemoveAll<ILoggerProvider>();
        return builder;
    }
​
    public static ILoggingBuilder Configure(this ILoggingBuilder builder, Action<LoggerFactoryOptions> action)
    {
        builder.Services.Configure(action);
        return builder;
    }
}

设置ILoggingBuilder.SetMinimumLevel(builder, LogLevel.Debug)