Serilog 不写入文件(.net 核心 2.2)
Serilog not writing to File (.net core 2.2)
我正在编写一个使用 Serilog 的 Web 服务。我在写出文件时遇到问题(但控制台日志记录有效)。我注意到根据 this and this 页面的解释,当 .net core 2.0 出来时设置发生了变化。
但是,现在,我看不到 任何 日志记录(也许在过去,默认的 M$ 记录器实际上就是我所看到的)。
program.cs
的设置方式如下:
public class Program
{
public static IConfiguration Configuration { get; } = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")}.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables()
.AddUserSecrets<Startup>()
.Build();
public static int Main(string[] args)
{
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(Configuration.GetSection("Serilog"))
.CreateLogger();
try
{
Log.Information("Starting webhost...");
BuildWebHost(args).Run();
return 0;
}
catch (Exception ex)
{
Log.Fatal(ex, "Host terminated unexpectedly");
return 1;
}
finally
{
Log.CloseAndFlush();
}
}
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.UseConfiguration(Configuration)
.UseSerilog()
.Build();
}
我的 appsettings.json 在根目录中有这个部分:
"Serilog": {
"Using" : ["Serilog.Sinks.Console", "Serilog.Sinks.File"],
"MinimumLevel": {
"Default": "Debug",
"Override": {
"Microsoft": "Warning",
"System": "Warning"
},
"Enrich" : ["FromLogContext"],
"WriteTo": [
{"Name": "Console" },
{"Name": "Debug" },
{"Name": "File", "Args": {"path": "%LogDir%\sampleapp\log-{Date}.txt", "rollingInterval": "Day", "shared": true } }
]
},
"Properties": {
"Application": "sampleapp"
}
},
请注意,%LogDir%
是我机器上的一个环境变量,在其他应用程序中解析得很好。该路径已创建,并且 Logs 文件夹对此应用程序使用的凭据具有完全 RW 权限。
我这样调用日志...
private readonly ILogger<PartnerController> _logger;
private readonly IPartnerDao _partnerDao;
public PartnerController(ILogger<PartnerController> logger, IPartnerDao partnerDao)
{
_logger = logger;
_partnerDao = partnerDao;
}
[HttpGet]
[Route("{titleCode}")]
public async Task<IActionResult> Get(string titleCode)
{
_logger.LogInformation("Test logging");
}
然而,ASP.NET Core Web Server
window 中没有任何显示,当 运行 服务时,我的机器上没有创建文件。
我是不是遗漏了什么明显的东西?
原来我错误地从文档中复制了一些 JSON。很难说,但在最初的问题中,我实际上在 MinimumLevel
部分中嵌入了 Enrich
、WriteTo
和 Properties
部分。
显然这会阻止 Serilog 正确地知道要写入哪些接收器。
这是我更正的设置 JSON:
"Serilog": {
"Using": ["Serilog.Sinks.Console", "Serilog.Sinks.File"],
"MinimumLevel": {
"Default": "Debug",
"Override": {
"Microsoft": "Warning",
"System": "Warning"
}
},
"Enrich": ["FromLogContext"],
"WriteTo": [
{ "Name": "Console" },
{ "Name": "Debug" },
{
"Name": "File",
"Args": {
"path": "%LogDir%\sampleapp\log-.txt",
"rollingInterval": "Day",
"shared": true
}
}
],
"Properties": {
"Application": "sampleapp"
}
},
请注意,我还从文件名中删除了 {Date}
。显然,如果您将滚动间隔设置为一天,它会解决这个问题....
appsettings.Development.json
覆盖appsettings.json
中的设置
我再说一遍,appsettings.Development.json
中的配置将 优先于 而不是 appsettings.json
。我知道这听起来很明显,但我敢打赌将来有人会像我一样忽略这一点。
我花了将近一个小时挠头为什么没有日志被写入文件,后来才注意到我的 appsettings.Development.json
中只有 Console
sink(有效地删除了我的 File
陷入 appsettings.json
啊!)。
这里是一个正确的配置示例(根据您的需要修改):
ASP.NET核心3.1
Program.cs
using Microsoft.AspNetCore.Hosting;
using Serilog;
using System;
using System.IO;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Serilog.Core;
namespace My.App
{
public class Program
{
private static bool IsDevelopment =>
Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == "Development";
public static IConfiguration Configuration { get; } = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", false, true)
.AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production"}.json", true)
.AddEnvironmentVariables()
.Build();
public static Logger Logger { get; } = new LoggerConfiguration()
.ReadFrom.Configuration(Configuration)
.Enrich.FromLogContext()
.CreateLogger();
public static int Main(string[] args)
{
Log.Logger = Logger;
try
{
Log.Information("Starting...");
var host = CreateHostBuilder(args).Build();
host.Run();
return 0;
}
catch (Exception ex)
{
Log.Fatal(ex, "Host terminated unexpectedly");
return 1;
}
finally
{
Log.CloseAndFlush();
}
}
public static IHostBuilder CreateHostBuilder(string[] args)
{
var host = Host.CreateDefaultBuilder(args)
.UseSerilog()
.UseServiceProviderFactory(
new AutofacMultitenantServiceProviderFactory(Startup.ConfigureMultitenantContainer))
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>();
});
return host;
}
}
}
ASP.NET核心2.2
Program.cs
public class Program
{
public static IConfiguration Configuration { get; } = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production"}.json", optional: true)
.AddEnvironmentVariables()
.Build();
public static void Main(string[] args)
{
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(Configuration)
.Enrich.FromLogContext()
.CreateLogger();
try
{
Log.Information("Starting...");
CreateWebHostBuilder(args).Run();
}
catch (Exception ex)
{
Log.Fatal(ex, "Host terminated unexpectedly");
}
finally
{
Log.CloseAndFlush();
}
}
public static IWebHost CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.UseSerilog()
.Build();
}
appsettings.json
{
"Serilog": {
"MinimumLevel": {
"Default": "Debug",
"Override": {
"Microsoft": "Warning",
"System": "Warning"
}
},
"Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ]
}
}
appsettings.Development.json
{
"Serilog": {
"WriteTo": [
{
"Name": "Async",
"Args": {
"configure": [
{
"Name": "Console"
},
{
"Name": "Debug"
},
{
"Name": "DiagnosticTrace"
},
{
"Name": "File",
"Args": {
"path": "/home/log/api-log-.txt",
"rollingInterval": "Day",
"retainedFileCountLimit": 7,
"buffered": true
}
}
]
}
}
]
}
}
appsettings.Production.json
{
"Serilog": {
"MinimumLevel": {
"Default": "Information"
},
"WriteTo": [
{
"Name": "Async",
"Args": {
"configure": [
{
"Name": "ApplicationInsights",
"Args": {
"restrictedToMinimumLevel": "Information",
"telemetryConverter": "Serilog.Sinks.ApplicationInsights.Sinks.ApplicationInsights.TelemetryConverters.TraceTelemetryConverter, Serilog.Sinks.ApplicationInsights"
}
},
{
"Name": "Email",
"Args": {
"EmailConnectionInfo": {
"EmailSubject": "PRODUCTION error logs",
"FromEmail": "xxxxxxx",
"ToEmail": "xxxxxxx",
"MailServer": "xxxx",
"NetworkCredentials": {
"username": "xxxxxx",
"password": "xxxxxx",
"domain": "xxxxx"
},
"Port": 25
},
"restrictedToMinimumLevel": "Error"
}
},
{
"Name": "File",
"Args": {
"path": "/home/log/api-log-.txt",
"rollingInterval": "Day",
"retainedFileCountLimit": 15,
"buffered": true
}
}
]
}
}
]
}
}
这是我更正的设置 JSON:
在启动 class:
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(config)
.Enrich.With<EventTypeEnricher>()
.CreateLogger();
在appsettings.json
{
"Serilog": {
"Using": [
"Serilog.Sinks.Console",
"Serilog.Sinks.Seq",
"Serilog.Sinks.Async",
"Serilog.Sinks.File",
"Serilog.Sinks.Debug"
],
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Warning",
"System": "Warning"
}
},
"Enrich": [
"FromLogContext",
"WithMachineName"
],
"Properties": {
"ApplicationName": "AppSim Crawler"
},
"WriteTo": [
{
"Name": "Seq",
"Args": {
"serverUrl": "http://localhost:5341",
"apiKey": "none"
}
},
{
"Name": "Debug",
"Args": {
"outputTemplate": "{Timestamp:dd-MM-yyyy HH:mm:ss.fff} [{EventType:x8} {Level:u3}] <s:[{SourceContext}]> <method:[{FileName} > {MemberName}]>{NewLine}at {FilePath}:{LineNumber}{NewLine}{Message:lj}{NewLine}{Exception}{NewLine}"
}
},
{
"Name": "Async",
"Args": {
"configure": [
{
"Name": "Console",
"Args": {
"theme": "Serilog.Sinks.SystemConsole.Themes.AnsiConsoleTheme::Code, Serilog.Sinks.Console",
"outputTemplate": "{Timestamp:dd-MM-yyyy HH:mm:ss.fff} [{EventType:x8} {Level:u3}] <c:[%COMPUTERNAME%]> <s:[{SourceContext}]> <method:[{FileName} > {MemberName}]>{NewLine}at {FilePath}:{LineNumber}{NewLine}{Message:lj}{NewLine}{Exception}{NewLine}"
}
}
]
}
},
{
"Name": "Async",
"Args": {
"configure": [
{
"Name": "File",
"Args": {
"path": "C:/appsim/logs/appSimCrawler.log",
"outputTemplate": "{Timestamp:dd-MM-yyyy HH:mm:ss.fff} [{EventType:x8} {Level:u3}] <s:[{SourceContext}]> <method:[{FileName} > {MemberName}]>{NewLine}at {FilePath}:{LineNumber}{NewLine}{Message:lj}{NewLine}{Exception}{NewLine}",
"rollingInterval": "Day",
"retainedFileCountLimit": 30,
"shared": true,
"rollOnFileSizeLimit": true
}
}
]
}
}
]
}
}
对我来说,serilog 没有写入日志文件,因为我缺少许多 nuget 包之一 (Serilog.Sinks.Async)。因此,除了确保您在 appsettings.json 中的配置是正确的 - 并且您为开发与生产使用了正确的文件外,还有:
我建议再次查看文档或教程,并确保添加说明中说明的每个 nuget 包。
我正在编写一个使用 Serilog 的 Web 服务。我在写出文件时遇到问题(但控制台日志记录有效)。我注意到根据 this and this 页面的解释,当 .net core 2.0 出来时设置发生了变化。
但是,现在,我看不到 任何 日志记录(也许在过去,默认的 M$ 记录器实际上就是我所看到的)。
program.cs
的设置方式如下:
public class Program
{
public static IConfiguration Configuration { get; } = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")}.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables()
.AddUserSecrets<Startup>()
.Build();
public static int Main(string[] args)
{
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(Configuration.GetSection("Serilog"))
.CreateLogger();
try
{
Log.Information("Starting webhost...");
BuildWebHost(args).Run();
return 0;
}
catch (Exception ex)
{
Log.Fatal(ex, "Host terminated unexpectedly");
return 1;
}
finally
{
Log.CloseAndFlush();
}
}
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.UseConfiguration(Configuration)
.UseSerilog()
.Build();
}
我的 appsettings.json 在根目录中有这个部分:
"Serilog": {
"Using" : ["Serilog.Sinks.Console", "Serilog.Sinks.File"],
"MinimumLevel": {
"Default": "Debug",
"Override": {
"Microsoft": "Warning",
"System": "Warning"
},
"Enrich" : ["FromLogContext"],
"WriteTo": [
{"Name": "Console" },
{"Name": "Debug" },
{"Name": "File", "Args": {"path": "%LogDir%\sampleapp\log-{Date}.txt", "rollingInterval": "Day", "shared": true } }
]
},
"Properties": {
"Application": "sampleapp"
}
},
请注意,%LogDir%
是我机器上的一个环境变量,在其他应用程序中解析得很好。该路径已创建,并且 Logs 文件夹对此应用程序使用的凭据具有完全 RW 权限。
我这样调用日志...
private readonly ILogger<PartnerController> _logger;
private readonly IPartnerDao _partnerDao;
public PartnerController(ILogger<PartnerController> logger, IPartnerDao partnerDao)
{
_logger = logger;
_partnerDao = partnerDao;
}
[HttpGet]
[Route("{titleCode}")]
public async Task<IActionResult> Get(string titleCode)
{
_logger.LogInformation("Test logging");
}
然而,ASP.NET Core Web Server
window 中没有任何显示,当 运行 服务时,我的机器上没有创建文件。
我是不是遗漏了什么明显的东西?
原来我错误地从文档中复制了一些 JSON。很难说,但在最初的问题中,我实际上在 MinimumLevel
部分中嵌入了 Enrich
、WriteTo
和 Properties
部分。
显然这会阻止 Serilog 正确地知道要写入哪些接收器。
这是我更正的设置 JSON:
"Serilog": {
"Using": ["Serilog.Sinks.Console", "Serilog.Sinks.File"],
"MinimumLevel": {
"Default": "Debug",
"Override": {
"Microsoft": "Warning",
"System": "Warning"
}
},
"Enrich": ["FromLogContext"],
"WriteTo": [
{ "Name": "Console" },
{ "Name": "Debug" },
{
"Name": "File",
"Args": {
"path": "%LogDir%\sampleapp\log-.txt",
"rollingInterval": "Day",
"shared": true
}
}
],
"Properties": {
"Application": "sampleapp"
}
},
请注意,我还从文件名中删除了 {Date}
。显然,如果您将滚动间隔设置为一天,它会解决这个问题....
appsettings.Development.json
覆盖appsettings.json
我再说一遍,appsettings.Development.json
中的配置将 优先于 而不是 appsettings.json
。我知道这听起来很明显,但我敢打赌将来有人会像我一样忽略这一点。
我花了将近一个小时挠头为什么没有日志被写入文件,后来才注意到我的 appsettings.Development.json
中只有 Console
sink(有效地删除了我的 File
陷入 appsettings.json
啊!)。
这里是一个正确的配置示例(根据您的需要修改):
ASP.NET核心3.1
Program.cs
using Microsoft.AspNetCore.Hosting;
using Serilog;
using System;
using System.IO;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Serilog.Core;
namespace My.App
{
public class Program
{
private static bool IsDevelopment =>
Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == "Development";
public static IConfiguration Configuration { get; } = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", false, true)
.AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production"}.json", true)
.AddEnvironmentVariables()
.Build();
public static Logger Logger { get; } = new LoggerConfiguration()
.ReadFrom.Configuration(Configuration)
.Enrich.FromLogContext()
.CreateLogger();
public static int Main(string[] args)
{
Log.Logger = Logger;
try
{
Log.Information("Starting...");
var host = CreateHostBuilder(args).Build();
host.Run();
return 0;
}
catch (Exception ex)
{
Log.Fatal(ex, "Host terminated unexpectedly");
return 1;
}
finally
{
Log.CloseAndFlush();
}
}
public static IHostBuilder CreateHostBuilder(string[] args)
{
var host = Host.CreateDefaultBuilder(args)
.UseSerilog()
.UseServiceProviderFactory(
new AutofacMultitenantServiceProviderFactory(Startup.ConfigureMultitenantContainer))
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>();
});
return host;
}
}
}
ASP.NET核心2.2
Program.cs
public class Program
{
public static IConfiguration Configuration { get; } = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production"}.json", optional: true)
.AddEnvironmentVariables()
.Build();
public static void Main(string[] args)
{
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(Configuration)
.Enrich.FromLogContext()
.CreateLogger();
try
{
Log.Information("Starting...");
CreateWebHostBuilder(args).Run();
}
catch (Exception ex)
{
Log.Fatal(ex, "Host terminated unexpectedly");
}
finally
{
Log.CloseAndFlush();
}
}
public static IWebHost CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.UseSerilog()
.Build();
}
appsettings.json
{
"Serilog": {
"MinimumLevel": {
"Default": "Debug",
"Override": {
"Microsoft": "Warning",
"System": "Warning"
}
},
"Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ]
}
}
appsettings.Development.json
{
"Serilog": {
"WriteTo": [
{
"Name": "Async",
"Args": {
"configure": [
{
"Name": "Console"
},
{
"Name": "Debug"
},
{
"Name": "DiagnosticTrace"
},
{
"Name": "File",
"Args": {
"path": "/home/log/api-log-.txt",
"rollingInterval": "Day",
"retainedFileCountLimit": 7,
"buffered": true
}
}
]
}
}
]
}
}
appsettings.Production.json
{
"Serilog": {
"MinimumLevel": {
"Default": "Information"
},
"WriteTo": [
{
"Name": "Async",
"Args": {
"configure": [
{
"Name": "ApplicationInsights",
"Args": {
"restrictedToMinimumLevel": "Information",
"telemetryConverter": "Serilog.Sinks.ApplicationInsights.Sinks.ApplicationInsights.TelemetryConverters.TraceTelemetryConverter, Serilog.Sinks.ApplicationInsights"
}
},
{
"Name": "Email",
"Args": {
"EmailConnectionInfo": {
"EmailSubject": "PRODUCTION error logs",
"FromEmail": "xxxxxxx",
"ToEmail": "xxxxxxx",
"MailServer": "xxxx",
"NetworkCredentials": {
"username": "xxxxxx",
"password": "xxxxxx",
"domain": "xxxxx"
},
"Port": 25
},
"restrictedToMinimumLevel": "Error"
}
},
{
"Name": "File",
"Args": {
"path": "/home/log/api-log-.txt",
"rollingInterval": "Day",
"retainedFileCountLimit": 15,
"buffered": true
}
}
]
}
}
]
}
}
这是我更正的设置 JSON:
在启动 class:
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(config)
.Enrich.With<EventTypeEnricher>()
.CreateLogger();
在appsettings.json
{
"Serilog": {
"Using": [
"Serilog.Sinks.Console",
"Serilog.Sinks.Seq",
"Serilog.Sinks.Async",
"Serilog.Sinks.File",
"Serilog.Sinks.Debug"
],
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Warning",
"System": "Warning"
}
},
"Enrich": [
"FromLogContext",
"WithMachineName"
],
"Properties": {
"ApplicationName": "AppSim Crawler"
},
"WriteTo": [
{
"Name": "Seq",
"Args": {
"serverUrl": "http://localhost:5341",
"apiKey": "none"
}
},
{
"Name": "Debug",
"Args": {
"outputTemplate": "{Timestamp:dd-MM-yyyy HH:mm:ss.fff} [{EventType:x8} {Level:u3}] <s:[{SourceContext}]> <method:[{FileName} > {MemberName}]>{NewLine}at {FilePath}:{LineNumber}{NewLine}{Message:lj}{NewLine}{Exception}{NewLine}"
}
},
{
"Name": "Async",
"Args": {
"configure": [
{
"Name": "Console",
"Args": {
"theme": "Serilog.Sinks.SystemConsole.Themes.AnsiConsoleTheme::Code, Serilog.Sinks.Console",
"outputTemplate": "{Timestamp:dd-MM-yyyy HH:mm:ss.fff} [{EventType:x8} {Level:u3}] <c:[%COMPUTERNAME%]> <s:[{SourceContext}]> <method:[{FileName} > {MemberName}]>{NewLine}at {FilePath}:{LineNumber}{NewLine}{Message:lj}{NewLine}{Exception}{NewLine}"
}
}
]
}
},
{
"Name": "Async",
"Args": {
"configure": [
{
"Name": "File",
"Args": {
"path": "C:/appsim/logs/appSimCrawler.log",
"outputTemplate": "{Timestamp:dd-MM-yyyy HH:mm:ss.fff} [{EventType:x8} {Level:u3}] <s:[{SourceContext}]> <method:[{FileName} > {MemberName}]>{NewLine}at {FilePath}:{LineNumber}{NewLine}{Message:lj}{NewLine}{Exception}{NewLine}",
"rollingInterval": "Day",
"retainedFileCountLimit": 30,
"shared": true,
"rollOnFileSizeLimit": true
}
}
]
}
}
]
}
}
对我来说,serilog 没有写入日志文件,因为我缺少许多 nuget 包之一 (Serilog.Sinks.Async)。因此,除了确保您在 appsettings.json 中的配置是正确的 - 并且您为开发与生产使用了正确的文件外,还有:
我建议再次查看文档或教程,并确保添加说明中说明的每个 nuget 包。