.NET 8使用日志功能以及自定义日志提供程序
日志级别
下表列出了 LogLevel 值、方便的 Log{LogLevel}
扩展方法以及建议的用法:
展开表
LogLevel | “值” | 方法 | 描述 |
---|---|---|---|
Trace | 0 | LogTrace | 包含最详细的消息。 这些消息可能包含敏感的应用数据。 这些消息默认情况下处于禁用状态,并且不应在生产中启用。 |
调试 | 1 | LogDebug | 用于调试和开发。 由于量大,请在生产中小心使用。 |
信息 | 2 | LogInformation | 跟踪应用的常规流。 可能具有长期值。 |
警告 | 3 | LogWarning | 对于异常事件或意外事件。 通常包括不会导致应用失败的错误或情况。 |
错误 | 4 | LogError | 表示无法处理的错误和异常。 这些消息表示当前操作或请求失败,而不是整个应用失败。 |
严重 | 5 | LogCritical | 需要立即关注的失败。 例如数据丢失、磁盘空间不足。 |
无 | 6 | 指定不应写入任何消息。 |
一、使用log4net
1、安装需要的Nuget包
在项目中使用程序包管理器控制台安装log4net包
Install-Package log4net
如果在AspNetCore项目还需要安装 Microsoft.Extensions.Logging.Log4Net.AspNetCore
Install-Package Microsoft.Extensions.Logging.Log4Net.AspNetCore
也可以使在Nuget管理程序中,搜索 “Microsoft.Extensions.Logging.Log4Net.AspNetCore”,然后点击安装。
2、代码中使用log4net日志组件
2.1、新建一个log4net.config配置文件
配置文件参考如下
2.2、设置文件为始终复制
2.3、在控制台中使用
using log4net.Config;
using log4net;
using System.Reflection;
namespace Test.ConsoleApp
{
internal class Program
{
static void Main(string[] args)
{
var log4netRepository = LogManager.GetRepository(Assembly.GetEntryAssembly());
XmlConfigurator.Configure(log4netRepository, new FileInfo("log4net.config"));
var log = LogManager.GetLogger(log4netRepository.Name, "NETCorelog4net");
log.Info("NETCorelog4net log");
log.Info("test log");
log.Error("error");
log.Info("linezero");
Console.ReadKey();
}
}
}
2.4、在AspNetCore项目中使用
方式一
//默认路径是根目录的log4net.config,也可以更改log4net.config路径,和名称
builder.Logging.AddLog4Net("Configs/log4net.config");
方式二
builder.Services.AddLogging(logging =>
{
//默认的配置文件路径是在根目录,且文件名为log4net.config
//logging.AddLog4Net();
logging.AddLog4Net("Configs/log4net.config");
//如果文件路径或名称有变化,需要重新设置其路径或名称
//比如在项目根目录下创建一个名为cfg的文件夹,将log4net.config文件移入其中,并改名为log.config
//则需要使用下面的代码来进行配置
//logging.AddLog4Net(new Log4NetProviderOptions()
//{
// Log4NetConfigFileName = "cfg/log.config",
// Watch = true
//});
});
方式三(有问题,在.NET6之前的Startup类Configure方法注入有用)
//也可以使用ILoggerFactory注入log4net
//loggerFactory.AddLog4Net();
using ILoggerFactory loggerFactory = LoggerFactory.Create(builder =>
{
builder.AddLog4Net("Configs/log4net.config");
});
参考文档:
https://www.cnblogs.com/wei325/p/16000271.html
https://github.com/huorswords/Microsoft.Extensions.Logging.Log4Net.AspNetCore
https://www.cnblogs.com/shangec/p/14666007.html
https://www.cnblogs.com/vvull/p/17967654
https://docs.meowv.com/stack/dotnetcore/log4net-in-dotnet.html
二、使用Nlog
1、控制台项目
1.1、安装如下Nuget包
Install-Package Microsoft.Extensions.Configuration.Json
Install-Package NLog
Install-Package NLog.Extensions.Logging
1.2、在控制台项目创建appsetting.json文件,文件内容如下
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*"
}
1.3、创建nlog.config文件,并设置属性为始终复制,下面是config文件参考
1.4、添加一个类Runner.cs
using Microsoft.Extensions.Logging;
namespace ConsoleDemo
{
public class Runner
{
private readonly ILogger _logger;
public Runner(ILogger logger)
{
_logger = logger;
}
public void DoAction(string name)
{
_logger.LogDebug(20, "Doing hard work! {Action}", name);
}
}
}
1.5、通过注入的方式调用。
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using NLog;
using NLog.Extensions.Logging;
using System;
namespace Test.ConsoleApp
{
internal class Program
{
private static void Main(string[] args)
{
#region nlog
var logger = LogManager.GetCurrentClassLogger();
try
{
var config = new ConfigurationBuilder()
.SetBasePath(System.IO.Directory.GetCurrentDirectory()) //From NuGet Package Microsoft.Extensions.Configuration.Json
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.Build();
using var servicesProvider = new ServiceCollection()
.AddTransient() // Runner is the custom class
.AddLogging(loggingBuilder =>
{
// configure Logging with NLog
loggingBuilder.ClearProviders();
loggingBuilder.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace);
loggingBuilder.AddNLog(config);
}).BuildServiceProvider();
var runner = servicesProvider.GetRequiredService();
runner.DoAction("Action1");
Console.WriteLine("Press ANY key to exit");
Console.ReadKey();
}
catch (Exception ex)
{
// NLog: catch any exception and log it.
logger.Error(ex, "Stopped program because of exception");
throw;
}
finally
{
LogManager.Shutdown();
}
Console.ReadKey();
}
}
}
1.6、最简单的示例
using Microsoft.Extensions.Logging;
using NLog.Extensions.Logging;
namespace ConsoleExample
{
internal static class Program
{
private static void Main()
{
var logger = LoggerFactory.Create(builder => builder.AddNLog()).CreateLogger();
logger.LogInformation("Program has started.");
Console.ReadKey();
}
}
}
2、在ASP.NET CORE项目中使用NLog
2.1、在Web项目中添加包
Install-Package NLog
Install-Package NLog.Web.AspNetCore
2.2、在appsetting.json文件如下配置
{
"Logging": {
"LogLevel": {
"Default": "Trace",
"Microsoft": "Warning",
服务器托管 "Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*"
}
2.3、 创建 nlog.config 文件。
在项目的根目录中创建 nlog.config(全部小写)文件
创建nlog.config文件,并设置属性为始终复制,下面是config文件参考
上面的c:temp可以改成nlog
2.4、program.cs代码如下
using NLog;
using NLog.Web;
// Early init of NLog to allow startup and exception logging, before host is built
var logger = NLog.LogManager.Setup().LoadConfigurationFromAppSettings().GetCurrentClassLogger();
logger.Debug("init main");
try
{
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllersWithViews();
// NLog: Setup NLog for Dependency injection
builder.Logging.ClearProviders();
//如果使用Configs文件夹下的配置使用builder.Logging.AddNLog注入
//builder.Logging.AddNLog("Configs/nlog.config");
//如果是在根目录可以直接使用builder.Host.UseNLog();
builder.Host.UseNLog();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.Run();
}
catch (Exception exception)
{
// NLog: catch setup errors
logger.Error(exception, "Stopped program because of exception");
throw;
}
finally
{
// Ensure to flush and stop internal timers/threads before application-exit (Avoid segmentation fault on Linux)
NLog.LogManager.Shutdown();
}
2.5、 Microsoft日志记录过滤器
使用 NLog 5.0 时,默认情况下会忽略 Microsoft 日志记录筛选器。只需确保正确配置 NLog 配置规则即可。appsettings.json
写入日志
在控制器中注入 ILogger:
using Microsoft.Extensions.Logging;
public class HomeController : Controller
{
private readonly ILogger _logger;
public HomeController(ILogger logger)
{
_logger = logger;
_logger.LogDebug(1, "NLog injected into HomeController");
}
public IActionResult Index()
{
_logger.LogInformation("Hello, this is the index!");
return View();
}
}
参考文档:
Getting started with .NET Core 2 Console application NLog/NLog Wiki GitHub
Getting started with ASP.NET Core 6 NLog/NLog Wiki GitHub
https://docs.meowv.com/stack/dotnetcore/nlog-in-dotnet.html
https://zhuanlan.zhihu.com/p/35469359
https://www.cjavapy.com/article/3102/
https://www.cnblogs.com/haiouxiangyun/p/15921375.html
三、使用Serlog
1、控制台项目
1.1、在项目中添加下面几个组件包
Install-Package Serilog.Extensions.Logging
Install-Package Serilog
Install-Package Serilog.Sinks.Console
Install-Package Serilog.Sinks.File
1.2、Program.cs代码参考如下
using System;
using Serilog;
class Program
{
static async Task Main()
{
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.WriteTo.Console()
.WriteTo.File("logs/myapp.txt", rollingInterval: RollingInterval.Day)
.CreateLogger();
//上面和下面的都可以
// Log.Logger = new LoggerConfiguration()
// .MinimumLevel.Information()
// .MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
//#if DEBUG
// .MinimumLevel.Override("Xxx", LogEventLevel.Debug)
//#else
// .MinimumLevel.Override("Xxx", LogEventLevel.Information)
//#endif
// .Enrich.FromLogContext()
// .WriteTo.Console()
// .WriteTo.File(Path.Combine(Directory.GetCurrentDirectory(), "logs/logs.txt"))
// .CreateLogger();
Log.Information("Hello, world!");
int a = 10, b = 0;
try
{
Log.Debug("Dividing {A} by {B}", a, b);
Console.WriteLine(a / b);
}
catch (Exception ex)
{
Log.Error(ex, "Something went wrong");
}
finally
{
await Log.CloseAndFlushAsync();
}
}
}
2、AspNetCore项目
2.1、在项目中添加下面几个组件包
Install-Package Serilog.AspNetCore
Install-Package Serilog.Sinks.Async
Install-Package Serilog.Sinks.File
2.2、Program.cs代码参考:
using Serilog;
Log.Logger = new LoggerConfiguration()
.WriteTo.Console()
.CreateLogger();
try
{
Log.Information("Starting web application");
var builder = WebApplication.CreateBuilder(args);
builder.Host.UseSerilog(); // "Hello World!");
app.Run();
}
catch (Exception ex)
{
Log.Fatal(ex, "Application terminated unexpectedly");
}
finally
{
Log.CloseAndFlush();
}
//Serilog.Sinks.Http
//Serilog.Sinks.Seq
//Log.Logger = new LoggerConfiguration()
// .MinimumLevel.Verbose()
// .Enrich.WithProperty("ApplicationContext", Program.AppName)
// .Enrich.FromLogContext()
// .WriteTo.Console()
// .WriteTo.Seq(string.IsNullOrWhiteSpace(seqServerUrl) ? "http://seq" : seqServerUrl)
// .WriteTo.Http(string.IsNullOrWhiteSpace(logstashUrl) ? "http://logstash:8080" : logstashUrl)
// .ReadFrom.Configuration(configuration)
// .CreateLogger();
使用的的话直接注入ILogger就可以使用了
参考文档:
官网:https://serilog.net/
官方文档:
控制台:https://github.com/serilog/serilog/wiki/Getting-Started
web:https://github.com/serilog/serilog-aspnetcore#serilogaspnetcore—
配置:Configuration Basics serilog/serilog Wiki GitHub
https://docs.meowv.com/stack/dotnetcore/serilog-in-dotnet.html
https://maomi.whuanle.cn/3.2.serilog.html
https://github.com/serilog/serilog-aspnetcore
https://www.cnblogs.com/ireadme/p/14509704.html
四、自定义日志提供程序
实现自定义日志提供程序主要需要实现两个接口
1、ILogger 支持高性能结构化日志记录,输出日志的地方,其中log方法是Logger对日志消息的写入实现
2、ILoggerProvider
日志记录器提供程序,ILoggerProvider 的实现将通过其 ILoggerProvider.CreateLogger 方法创建 ILogger
需安装以下Nuget包
下面是官方的示例:
有很多日志记录提供程序可用于常见日志记录需求。 如果某个可用的提供程序不满足你的应用程序需要,则你可能需要实现自定义的 ILoggerProvider。 在本文中,你将学习如何实现可用于在控制台中为日志着色的自定义日志记录提供程序。
Docs Github 存储库中提供了自定义日志记录提供程序示例源代码。 有关详细信息,请参阅 GitHub:.NET Docs – 控制台自定义日志记录。
示例自定义记录器配置
此示例会使用以下配置类型为每个日志级别和事件 ID 创建不同的颜色控制台条目:
using Microsoft.Extensions.Logging;
public sealed class ColorConsoleLoggerConfiguration
{
public int EventId { get; set; }
public Dictionary LogLevelToColorMap { get; set; } = new()
{
[LogLevel.Information] =服务器托管 ConsoleColor.Green
};
}
前面的代码将默认级别设置为 Information
,将颜色设置为 Green
,而且 EventId
隐式设置为 0
。
创建自定义记录器
ILogger
实现类别名称通常是日志记录源。 例如,创建记录器的类型:
C#
using Microsoft.Extensions.Logging;
public sealed class ColorConsoleLogger(
string name,
Func getCurrentConfig) : ILogger
{
public IDisposable? BeginScope(TState state) where TState : notnull => default!;
public bool IsEnabled(LogLevel logLevel) =>
getCurrentConfig().LogLevelToColorMap.ContainsKey(logLevel);
public void Log(
LogLevel logLevel,
EventId eventId,
TState state,
Exception? exception,
Func formatter)
{
if (!IsEnabled(logLevel))
{
return;
}
ColorConsoleLoggerConfiguration config = getCurrentConfig();
if (config.EventId == 0 || config.EventId == eventId.Id)
{
ConsoleColor originalColor = Console.ForegroundColor;
Console.ForegroundColor = config.LogLevelToColorMap[logLevel];
Console.WriteLine($"[{eventId.Id,2}: {logLevel,-12}]");
Console.ForegroundColor = originalColor;
Console.Write($" {name} - ");
Console.ForegroundColor = config.LogLevelToColorMap[logLevel];
Console.Write($"{formatter(state, exception)}");
Console.ForegroundColor = originalColor;
Console.WriteLine();
}
}
}
前面的代码:
- 为每个类别名称创建一个记录器实例。
- 在
IsEnabled
中检查_getCurrentConfig().LogLevelToColorMap.ContainsKey(logLevel)
,因此每个logLevel
都有一个唯一的记录器。 在此实现中,每个日志级别都需要显式配置条目才能记录。
最好是在 ILogger.Log 实现中调用 ILogger.IsEnabled,因为 Log
可由任何使用者调用,并且不能保证之前已检查过。 方法 IsEnabled
在大多数实现中应非常快。
C#
TState state,
Exception? exception,
记录器使用 name
和 Func
进行实例化,这将返回当前配置 – 这会处理对通过 IOptionsMonitor.OnChange 回调监视的配置值的更新。
重要
ILogger.Log 实现检查是否设置了 config.EventId
值。 未设置 config.EventId
或与确切的 logEntry.EventId
匹配时,记录器会以颜色记录。
自定义记录器提供程序
ILoggerProvider
对象负责创建记录器实例。 不需要为每个类别创建一个记录器实例,但这对于某些记录器(例如 NLog 或 log4net)来说是需要的。 借助此策略可以为每个类别选择不同的日志记录输出目标,如以下示例中所示:
C#
using System.Collections.Concurrent;
using System.Runtime.Versioning;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
[UnsupportedOSPlatform("browser")]
[ProviderAlias("ColorConsole")]
public sealed class ColorConsoleLoggerProvider : ILoggerProvider
{
private readonly IDisposable? _onChangeToken;
private ColorConsoleLoggerConfiguration _currentConfig;
private readonly ConcurrentDictionary _loggers =
new(StringComparer.OrdinalIgnoreCase);
public ColorConsoleLoggerProvider(
IOptionsMonitor config)
{
_currentConfig = config.CurrentValue;
_onChangeToken = config.OnChange(updatedConfig => _currentConfig = updatedConfig);
}
public ILogger CreateLogger(string categoryName) =>
_loggers.GetOrAdd(categoryName, name => new ColorConsoleLogger(name, GetCurrentConfig));
private ColorConsoleLoggerConfiguration GetCurrentConfig() => _currentConfig;
public void Dispose()
{
_loggers.Clear();
_onChangeToken?.Dispose();
}
}
在前面的代码中,CreateLogger 会为每个类别名称创建一个 ColorConsoleLogger
实例并将其存储在 ConcurrentDictionary
中。 此外,还需要 IOptionsMonitor 接口才能更新对基础 ColorConsoleLoggerConfiguration
对象的更改。
若要控制 ColorConsoleLogger
的配置,请在其提供程序上定义别名:
C#
[UnsupportedOSPlatform("browser")]
[ProviderAlias("ColorConsole")]
public sealed class ColorConsoleLoggerProvider : ILoggerProvider
ColorConsoleLoggerProvider
类定义了两个类范围的属性:
-
UnsupportedOSPlatformAttribute:
"browser"
中不支持ColorConsoleLogger
类型。 -
ProviderAliasAttribute:配置节可使用
"ColorConsole"
键定义选项。
可通过任何有效的配置提供程序指定配置。 请考虑使用以下 appsettings.json 文件:
JSON
{
"Logging": {
"ColorConsole": {
"LogLevelToColorMap": {
"Information": "DarkGreen",
"Warning": "Cyan",
"Error": "Red"
}
}
}
}
这会将日志级别配置为以下值:
- LogLevel.Information: ConsoleColor.DarkGreen
- LogLevel.Warning: ConsoleColor.Cyan
- LogLevel.Error: ConsoleColor.Red
Information 日志级别设置为 DarkGreen,这将覆盖在 ColorConsoleLoggerConfiguration
对象中设置的默认值。
自定义记录器的使用和注册
根据约定,在应用程序启动例程中注册服务以进行依赖项注入。 注册在 Program
类中进行,还可能委托给 Startup
类。 本示例将直接从 Program.cs 进行注册。
若要添加自定义日志记录提供程序和相应的记录器,请从 HostingHostBuilderExtensions.ConfigureLogging(IHostBuilder, Action) 使用 ILoggingBuilder 添加 ILoggerProvider:
C#
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Logging.ClearProviders();
builder.Logging.AddColorConsoleLogger(configuration =>
{
// Replace warning value from appsettings.json of "Cyan"
configuration.LogLevelToColorMap[LogLevel.Warning] = ConsoleColor.DarkCyan;
// Replace warning value from appsettings.json of "Red"
configuration.LogLevelToColorMap[LogLevel.Error] = ConsoleColor.DarkRed;
});
using IHost host = builder.Build();
var logger = host.Services.GetRequiredService>();
logger.LogDebug(1, "Does this line get hit?"); // Not logged
logger.LogInformation(3, "Nothing to see here."); // Logs in ConsoleColor.DarkGreen
logger.LogWarning(5, "Warning... that was odd."); // Logs in ConsoleColor.DarkCyan
logger.LogError(7, "Oops, there was an error."); // Logs in ConsoleColor.DarkRed
logger.LogTrace(5, "== 120."); // Not logged
await host.RunAsync();
ILoggingBuilder
创建一个或多个 ILogger
实例。 框架使用 ILogger
实例记录信息。
appsettings.json 文件中的配置会替代以下值:
- LogLevel.Warning: ConsoleColor.DarkCyan
- LogLevel.Error: ConsoleColor.DarkRed
按照约定,ILoggingBuilder
上的扩展方法用于注册自定义提供程序:
C#
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Configuration;
public static class ColorConsoleLoggerExtensions
{
public static ILoggingBuilder AddColorConsoleLogger(
this ILoggingBuilder builder)
{
builder.AddConfiguration();
builder.Services.TryAddEnumerable(
ServiceDescriptor.Singleton());
LoggerProviderOptions.RegisterProviderOptions
(builder.Services);
return builder;
}
public static ILoggingBuilder AddColorConsoleLogger(
this ILoggingBuilder builder,
Action configure)
{
builder.AddColorConsoleLogger();
builder.Services.Configure(configure);
return builder;
}
}
运行此简单应用程序将把颜色输出呈现到控制台窗口,如下图所示:
自定义日志功能参考文档:
https://learn.microsoft.com/zh-cn/dotnet/core/extensions/logging-providers
在 .NET 中实现自定义日志记录提供程序 – .NET | Microsoft Learn
使用SignalR推送服务器日志
https://learn.microsoft.com/zh-cn/aspnet/core/fundamentals/logging/?view=aspnetcore-8.0
https://maomi.whuanle.cn/3.1.design_log.html
https://www.cnblogs.com/jackyfei/p/16287326.html
https://www.cnblogs.com/chenyishi/p/18068309
Microsoft.Extensions 探索 / 日志 Logger – 知乎 (zhihu.com)
.Net Core Logging模块源码阅读 – 李正浩 – 博客园 (cnblogs.com)
.NET Core下的日志(2):日志模型详解 – Artech – 博客园 (cnblogs.com)
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
机房租用,北京机房租用,IDC机房托管, http://www.fwqtg.net
相关推荐: 16. 从零用Rust编写正反向代理, 反向代理upstream源码实现
wmproxy wmproxy是由Rust编写,已实现http/https代理,socks5代理, 反向代理,静态文件服务器,内网穿透,配置热更新等, 后续将实现websocket代理等,同时会将实现过程分享出来, 感兴趣的可以一起造个轮子法 项目 wmpro…