使用 Serilog 仅将此信息记录到另一个文件
Log just this information to a other file with Serilog
我有一个带有 Serilog 块的 .NET 5.0 控制台应用程序。 appsettings.json 的 serilog 部分如下所示:
"Enrich": [ "FromLogContext", "WithMachineName", "WithProcessId", "WithThreadId" ],
"WriteTo": [
{
"Name": "Console",
"Args": {
"outputTemplate": "[{Timestamp:HH:mm:ss.fff} [{Level}] {SourceContext} {Message}{NewLine}{Exception}",
"theme": "Serilog.Sinks.SystemConsole.Themes.AnsiConsoleTheme::Code, Serilog.Sinks.Console"
}
},
{
"Name": "File",
"Args": {
"path": "/Logs/SharedTreatment_logs.txt",
"outputTemplate": "{Timestamp:G} {SourceContext} [{Level}] {Message}{NewLine:1}{Exception:1}",
"formatter": "Serilog.Formatting.Json.JsonFormatter, Serilog",
"fileSizeLimitBytes": 1000000,
"rollOnFileSizeLimit": "true",
"shared": "true",
"flushToDiskInterval": 3
}
}
]
已加载此代码:
Serilog.Debugging.SelfLog.Enable(Console.Error);
var configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.Build();
var logger = loggerConfiguration.ReadFrom.Configuration(configuration).CreateLogger();
Log.Logger = logger?.ForContext<T>() ?? throw new ArgumentNullException(nameof(logger));
Host.CreateDefaultBuilder(args).UseSerilog((hostingContext, loggerConfiguration) => loggerConfiguration.ReadFrom.Configuration(hostingContext.Configuration))
解决方案中的每个 class 都进行了 ILogger 注入,例如 ILogger<MyClass> logger
。
问题是我如何创建一个新的记录器,该记录器使用 appsettings.json 中的另一个日志配置部分来记录到另一个文件 class?
更新:
经过大量搜索和测试后,我想我找到了一种方法来做到这一点。我仍然不确定这是正确的方法还是最好的方法?
我必须创建 2 个子记录器,一个用于排除文件的主日志记录,另一个只记录这样的文件:
{
"Serilog": {
"Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File" ],
"MinimumLevel": "Debug",
"Enrich": [ "FromLogContext" ],
"WriteTo": [
{
"Name": "Console",
"Args": {
"outputTemplate": "[{Timestamp:HH:mm:ss.fff} [{Level}] {SourceContext} {Message}{NewLine}{Exception}",
"theme": "Serilog.Sinks.SystemConsole.Themes.AnsiConsoleTheme::Code, Serilog.Sinks.Console"
}
},
{
"Name": "Logger",
"Args": {
"configureLogger": {
"Filter": [
{
"Name": "ByIncludingOnly",
"Args": {
"expression": "@p['LogToFile']"
}
}
],
"WriteTo": [
{
"Name": "File",
"Args": {
"path": "Logs/SharedTreatment_logs_Second.txt",
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} [{Level:u3}] {Message:lj}{NewLine}{Exception}"
}
}
]
}
}
},
{
"Name": "Logger",
"Args": {
"configureLogger": {
"Filter": [
{
"Name": "ByExcluding",
"Args": {
"expression": "@p['LogToFile']"
}
}
],
"WriteTo": [
{
"Name": "File",
"Args": {
"path": "Logs/SharedTreatment_logs.txt",
"outputTemplate": "{Timestamp:G} {SourceContext} [{Level}] {Message}{NewLine:1}{Exception:1}",
"formatter": "Serilog.Formatting.Json.JsonFormatter, Serilog",
"fileSizeLimitBytes": 1000000,
"rollOnFileSizeLimit": "true",
"shared": "true",
"flushToDiskInterval": 3
}
}
]
}
}
}
]
}
}
这是 C# 代码的样子:
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
Log.Logger = new LoggerConfiguration().DefaultLoggerSetup<Program>();
using (LogContext.PushProperty("LogToFile", true))
{
Log.Information("LogToFileTest");
}
Log.Information("Just log");
Log.CloseAndFlush();
}
创建了两个文件,过滤后的日志在它们应该在的地方。
您不必使用另一个 ILogger 单独注入。 Serilog 自行处理。
只需使用 sub-loggers 并添加一些 WriteTo.Logger
。然后您可以在代码中的某处使用 ILogger,它会根据您的配置自动保存日志。
例如:
Log.Logger = new LoggerConfiguration()
.WriteTo.Logger(lc => lc
.Filter.ByExcluding(Matching.FromSource("AnySource"))
.WriteTo.File("first.txt", new JsonFormatter()))
.WriteTo.Logger(lc => lc
.Filter.ByIncludingOnly(Matching.FromSource("AnySource"))
.WriteTo.File("second.txt", new JsonFormatter()))
.WriteTo.Logger(config => config
.Filter.ByIncludingOnly(e => e.Level == LogEventLevel.Debug)
.WriteTo.File("third.txt", new JsonFormatter()))
(...)
.CreateLogger();
您还可以使用应用程序设置配置来告诉 Verilog 这样做:
{
"Serilog": {
"Using": ["Serilog.Settings.Configuration"],
"Filter": [
{
"Name": "ByExcluding",
"Args": {
"expression": "EndsWith(RequestPath, '/SomeEndpoint')"
}
}
]
ILogger
是一个 Singleton
& issue here ILogger<T>
更好的选择,更简单恕我直言,是在 appsettings.json
中创建 多个 单独的 sections
,例如ErrorLog
、SecondErrorLog
和 AuditLog
。
- Step 1 Create sections within the
appsettings.json
like so
"ErrorLog": {
"Using": [ "Serilog.Sinks.File" ],
"MinimumLevel": "Debug",
"WriteTo": [
{
"Name": "File",
"Args": {
"path": "c:\temp\error1-.log",
"rollingInterval": "Day",
"restrictedToMinimumLevel": "Error"
}
}
]
},
"SecondErrorLog": {
"Using": [ "Serilog.Sinks.File" ],
"MinimumLevel": "Debug",
"WriteTo": [
{
"Name": "File",
"Args": {
// your Second Error Log or Audit Log etc.
"path": "c:\temp\error2-.log",
"rollingInterval": "Day",
"restrictedToMinimumLevel": "Information"
}
}
]
}
- Step 2, and now inside your code, you can access, audit etc.
var myDualErrorLogConfiguration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production"}.json", optional: true)
.AddEnvironmentVariables()
.Build();
// now get your First Error Log or Audit Log etc.
var errorSection = myDualErrorLogConfiguration.GetSection("ErrorLog");
// your Second Error Log or Audit Log etc.
var auditSection = myDualErrorLogConfiguration.GetSection("SecondErrorLog");
_log = new LoggerConfiguration()
.ReadFrom
.ConfigurationSection(errorSection)
.CreateLogger();
_secondLog = new LoggerConfiguration()
.ReadFrom
.ConfigurationSection(auditSection)
.CreateLogger();
更新 2:
让我们退后一步,对于您正在尝试做的事情,即 multiple loggers
使用不同的配置,您 需要 一个 ILoggerFactory
来创建和配置这些,请参阅下面的示例 credit 。这将帮助您根据需要创建不同的记录器。
ILoggerFactory factory = new LoggerFactory().AddConsole(); // add console provider
factory.AddProvider(new LoggerFileProvider("c:\FirstErrorLog.txt")); // add file provider
Logger logger = factory.CreateLogger(); // <-- creates a console logger & file logger
现在你可以将它注入你的构造函数
public SomeController(ISomeRepository someRepository, ILoggerFactory logger)
{
_someRepository = someRepository;
_logger = logger.CreateLogger("SomeApi.Controllers.TodoController");
}
为了解决这个问题,我不得不在 appsettings.json 中创建一个单独的日志条目,如下所示:
{
"Name": "Logger",
"Args": {
"configureLogger": {
"Filter": [
{
"Name": "ByIncludingOnly",
"Args": {
"expression": "@p['LogToFile']"
}
}
],
"WriteTo": [
{
"Name": "File",
"Args": {
"path": "Logs/SharedTreatment_logs_Second.txt",
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} [{Level:u3}] {Message:lj}{NewLine}{Exception}"
}
}
]
}
}
},
我不得不像这样将特定的日志记录推送到此记录器:
using (LogContext.PushProperty("LogToFile", true))
{ _logger.LogInformation("Incoming Message MessageGuid : {MessageGuid} , MessageChainGuid : {MessageChainGuid}, SharedTreatment : {SharedTreatment}", incomingMessage.MessageGuid, incomingMessage.MessageChainGuid, incomingMessage.SharedTreatment); }
我有一个带有 Serilog 块的 .NET 5.0 控制台应用程序。 appsettings.json 的 serilog 部分如下所示:
"Enrich": [ "FromLogContext", "WithMachineName", "WithProcessId", "WithThreadId" ],
"WriteTo": [
{
"Name": "Console",
"Args": {
"outputTemplate": "[{Timestamp:HH:mm:ss.fff} [{Level}] {SourceContext} {Message}{NewLine}{Exception}",
"theme": "Serilog.Sinks.SystemConsole.Themes.AnsiConsoleTheme::Code, Serilog.Sinks.Console"
}
},
{
"Name": "File",
"Args": {
"path": "/Logs/SharedTreatment_logs.txt",
"outputTemplate": "{Timestamp:G} {SourceContext} [{Level}] {Message}{NewLine:1}{Exception:1}",
"formatter": "Serilog.Formatting.Json.JsonFormatter, Serilog",
"fileSizeLimitBytes": 1000000,
"rollOnFileSizeLimit": "true",
"shared": "true",
"flushToDiskInterval": 3
}
}
]
已加载此代码:
Serilog.Debugging.SelfLog.Enable(Console.Error);
var configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.Build();
var logger = loggerConfiguration.ReadFrom.Configuration(configuration).CreateLogger();
Log.Logger = logger?.ForContext<T>() ?? throw new ArgumentNullException(nameof(logger));
Host.CreateDefaultBuilder(args).UseSerilog((hostingContext, loggerConfiguration) => loggerConfiguration.ReadFrom.Configuration(hostingContext.Configuration))
解决方案中的每个 class 都进行了 ILogger 注入,例如 ILogger<MyClass> logger
。
问题是我如何创建一个新的记录器,该记录器使用 appsettings.json 中的另一个日志配置部分来记录到另一个文件 class?
更新: 经过大量搜索和测试后,我想我找到了一种方法来做到这一点。我仍然不确定这是正确的方法还是最好的方法?
我必须创建 2 个子记录器,一个用于排除文件的主日志记录,另一个只记录这样的文件:
{
"Serilog": {
"Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File" ],
"MinimumLevel": "Debug",
"Enrich": [ "FromLogContext" ],
"WriteTo": [
{
"Name": "Console",
"Args": {
"outputTemplate": "[{Timestamp:HH:mm:ss.fff} [{Level}] {SourceContext} {Message}{NewLine}{Exception}",
"theme": "Serilog.Sinks.SystemConsole.Themes.AnsiConsoleTheme::Code, Serilog.Sinks.Console"
}
},
{
"Name": "Logger",
"Args": {
"configureLogger": {
"Filter": [
{
"Name": "ByIncludingOnly",
"Args": {
"expression": "@p['LogToFile']"
}
}
],
"WriteTo": [
{
"Name": "File",
"Args": {
"path": "Logs/SharedTreatment_logs_Second.txt",
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} [{Level:u3}] {Message:lj}{NewLine}{Exception}"
}
}
]
}
}
},
{
"Name": "Logger",
"Args": {
"configureLogger": {
"Filter": [
{
"Name": "ByExcluding",
"Args": {
"expression": "@p['LogToFile']"
}
}
],
"WriteTo": [
{
"Name": "File",
"Args": {
"path": "Logs/SharedTreatment_logs.txt",
"outputTemplate": "{Timestamp:G} {SourceContext} [{Level}] {Message}{NewLine:1}{Exception:1}",
"formatter": "Serilog.Formatting.Json.JsonFormatter, Serilog",
"fileSizeLimitBytes": 1000000,
"rollOnFileSizeLimit": "true",
"shared": "true",
"flushToDiskInterval": 3
}
}
]
}
}
}
]
}
}
这是 C# 代码的样子:
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
Log.Logger = new LoggerConfiguration().DefaultLoggerSetup<Program>();
using (LogContext.PushProperty("LogToFile", true))
{
Log.Information("LogToFileTest");
}
Log.Information("Just log");
Log.CloseAndFlush();
}
创建了两个文件,过滤后的日志在它们应该在的地方。
您不必使用另一个 ILogger 单独注入。 Serilog 自行处理。
只需使用 sub-loggers 并添加一些 WriteTo.Logger
。然后您可以在代码中的某处使用 ILogger,它会根据您的配置自动保存日志。
例如:
Log.Logger = new LoggerConfiguration()
.WriteTo.Logger(lc => lc
.Filter.ByExcluding(Matching.FromSource("AnySource"))
.WriteTo.File("first.txt", new JsonFormatter()))
.WriteTo.Logger(lc => lc
.Filter.ByIncludingOnly(Matching.FromSource("AnySource"))
.WriteTo.File("second.txt", new JsonFormatter()))
.WriteTo.Logger(config => config
.Filter.ByIncludingOnly(e => e.Level == LogEventLevel.Debug)
.WriteTo.File("third.txt", new JsonFormatter()))
(...)
.CreateLogger();
您还可以使用应用程序设置配置来告诉 Verilog 这样做:
{
"Serilog": {
"Using": ["Serilog.Settings.Configuration"],
"Filter": [
{
"Name": "ByExcluding",
"Args": {
"expression": "EndsWith(RequestPath, '/SomeEndpoint')"
}
}
]
ILogger
是一个 Singleton
ILogger<T>
更好的选择,更简单恕我直言,是在 appsettings.json
中创建 多个 单独的 sections
,例如ErrorLog
、SecondErrorLog
和 AuditLog
。
- Step 1 Create sections within the
appsettings.json
like so
"ErrorLog": {
"Using": [ "Serilog.Sinks.File" ],
"MinimumLevel": "Debug",
"WriteTo": [
{
"Name": "File",
"Args": {
"path": "c:\temp\error1-.log",
"rollingInterval": "Day",
"restrictedToMinimumLevel": "Error"
}
}
]
},
"SecondErrorLog": {
"Using": [ "Serilog.Sinks.File" ],
"MinimumLevel": "Debug",
"WriteTo": [
{
"Name": "File",
"Args": {
// your Second Error Log or Audit Log etc.
"path": "c:\temp\error2-.log",
"rollingInterval": "Day",
"restrictedToMinimumLevel": "Information"
}
}
]
}
- Step 2, and now inside your code, you can access, audit etc.
var myDualErrorLogConfiguration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production"}.json", optional: true)
.AddEnvironmentVariables()
.Build();
// now get your First Error Log or Audit Log etc.
var errorSection = myDualErrorLogConfiguration.GetSection("ErrorLog");
// your Second Error Log or Audit Log etc.
var auditSection = myDualErrorLogConfiguration.GetSection("SecondErrorLog");
_log = new LoggerConfiguration()
.ReadFrom
.ConfigurationSection(errorSection)
.CreateLogger();
_secondLog = new LoggerConfiguration()
.ReadFrom
.ConfigurationSection(auditSection)
.CreateLogger();
更新 2:
让我们退后一步,对于您正在尝试做的事情,即 multiple loggers
使用不同的配置,您 需要 一个 ILoggerFactory
来创建和配置这些,请参阅下面的示例 credit
ILoggerFactory factory = new LoggerFactory().AddConsole(); // add console provider
factory.AddProvider(new LoggerFileProvider("c:\FirstErrorLog.txt")); // add file provider
Logger logger = factory.CreateLogger(); // <-- creates a console logger & file logger
现在你可以将它注入你的构造函数
public SomeController(ISomeRepository someRepository, ILoggerFactory logger)
{
_someRepository = someRepository;
_logger = logger.CreateLogger("SomeApi.Controllers.TodoController");
}
为了解决这个问题,我不得不在 appsettings.json 中创建一个单独的日志条目,如下所示:
{
"Name": "Logger",
"Args": {
"configureLogger": {
"Filter": [
{
"Name": "ByIncludingOnly",
"Args": {
"expression": "@p['LogToFile']"
}
}
],
"WriteTo": [
{
"Name": "File",
"Args": {
"path": "Logs/SharedTreatment_logs_Second.txt",
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} [{Level:u3}] {Message:lj}{NewLine}{Exception}"
}
}
]
}
}
},
我不得不像这样将特定的日志记录推送到此记录器:
using (LogContext.PushProperty("LogToFile", true))
{ _logger.LogInformation("Incoming Message MessageGuid : {MessageGuid} , MessageChainGuid : {MessageChainGuid}, SharedTreatment : {SharedTreatment}", incomingMessage.MessageGuid, incomingMessage.MessageChainGuid, incomingMessage.SharedTreatment); }