日志组件可以将方法中的日志存储到某个地方(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)