Logging Serilog在达到最大文件大小之前创建文件
我使用.NETCore2.1创建了一个API,并使用Serilog在API级别记录所有方法类型的每个响应和请求:Get、Post。。。尽管有响应代码;下面是添加到中间件类的代码:Logging Serilog在达到最大文件大小之前创建文件,logging,asp.net-core-2.1,serilog,Logging,Asp.net Core 2.1,Serilog,我使用.NETCore2.1创建了一个API,并使用Serilog在API级别记录所有方法类型的每个响应和请求:Get、Post。。。尽管有响应代码;下面是添加到中间件类的代码: var request = context.Request; var stopWatch = Stopwatch.StartNew(); var requestTime = DateTime.UtcNow; var requestBodyContent = await ReadRequestBo
var request = context.Request;
var stopWatch = Stopwatch.StartNew();
var requestTime = DateTime.UtcNow;
var requestBodyContent = await ReadRequestBody(request);
var originalBodyStream = context.Response.Body;
generalError = Configuration["generalError"];
using (var memStream = new MemoryStream())
{
HttpResponse response = context.Response;
response.Body = memStream;
await next(context);
stopWatch.Stop();
string responseBodyContent = null;
responseBodyContent = ReadResponseBody(memStream);
memStream.CopyTo(originalBodyStream);
string infoToLog = "\r\n" +
"------------------------ \r\n" +
"Elapsed Milliseconds: " + stopWatch.ElapsedMilliseconds + "\r\n" +
"Status Code: " + context.Response.StatusCode + "\r\n" +
"Method: " + request.Method + "\r\n" +
"Path: " + request.Path + "\r\n" +
"QueryString: " + request.QueryString.ToString() + "\r\n" +
"Request Body: " + requestBodyContent + "\r\n" +
"Response Body: " + responseBodyContent + "\r\n" +
"------------------------" + "\r\n\r\n";
Log.Logger = new LoggerConfiguration()
.WriteTo.Async(a => a.File("Logs/myapp.log",
rollOnFileSizeLimit: true,
fileSizeLimitBytes: Convert.ToInt32(Configuration["MaxLogFileSize"])))
//shared:true,
.CreateLogger();
if (context.Response.StatusCode == 200)
{
Log.Information(infoToLog);
}
else {
Log.Error(infoToLog);
}
Log.CloseAndFlush();
context.Response.Body = originalBodyStream;
}
如您所见,我实现了一种滚动日志记录方法,该方法仅在达到最大文件大小问题后创建新文件。
主要问题是,发布后,当API从移动应用程序调用时,我们意识到许多日志文件是同时创建的,而没有达到最大文件大小,更具体地说,当多个方法应该同时记录时。我们能解决这个问题吗 您正在中间件中的每个webrequest上实例化一个新的记录器,我认为您也在使用
log.CloseAndFlush()关闭日志文件代码>,当我认为如果我回忆起文档,它应该是一个单例
根据我的记忆,您只需要在应用程序引导期间创建记录器。我就是这样做的(program.cs with.NET core 2.2):
公共类程序
{
私有静态只读字符串_applicationName=System.Reflection.Assembly.GetEntryAssembly().GetName().Name;
公共静态IConfiguration配置=新配置生成器()
.SetBasePath(目录.GetCurrentDirectory())
.AddJsonFile(“appsettings.json”,可选:true,重载更改:true)
.AddJsonFile($“appsettings.{Environment.GetEnvironmentVariable(“ASPNETCORE_Environment”)}.json),重载更改:true,可选:true)
.AddenEnvironmentVariables()
.Build();
公共静态int Main(字符串[]args)
{
//塞里洛格
Logger.Logger=新的LoggerConfiguration()
.ReadFrom.Configuration(配置)
.Enrich.FromLogContext()的
.CreateLogger();
尝试
{
if(string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable(“ASPNETCORE_Environment”))
抛出新异常(“未设置宿主环境变量”);
Log.Information($“引导应用程序:{u applicationName}”);
CreateWebHostBuilder(args.Build().Run();
Log.Information($“优雅地关闭应用程序:{u applicationName}”);
返回0;//返回0,表示成功关机。
}
捕获(例外e)
{
警告($“主机{u应用程序名}-意外终止。”);
日志。致命(e.Message);
return 1;//返回none零表示失败。
}
最后
{
Log.CloseAndFlush();
}
}
公共静态IWebHostBuilder CreateWebHostBuilder(字符串[]args)=>
WebHost.CreateDefaultBuilder(args)
.UseStartup()
.UseConfiguration(配置)
.useserlog();
}
因此,当您确实想记录一些东西时,只需使用Serilog导入
并调用Log.Information(“您的消息”)
更多信息请参见:的底部或
编辑
这是我的配置,将console指定为sink(您也可以添加更多类似文件、elasticsearch、seq…其他),我还覆盖了Microsofts的默认记录器,只显示日志级别或更高级别的警告:
"Serilog": {
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Warning",
"System": "Warning"
}
},
"WriteTo": [
{
"Name": "Console",
"Args": {
"outputTemplate": "[{Timestamp:yyyy-MM-dd HH:mm:ss} {Level:u3}] {Message:lj} {SourceContext}>{NewLine}{Exception}"
}
}
]
},
更新
那么,您将日志放在教程中说的//TODO:Save log to selected datastore
(将日志保存到所选数据存储)的位置,这在serilog术语中只是指log.Information(“您的消息”)代码>。在我的示例中,我已经用//serilog
标记了serilog部分-因此,如果您想将记录器配置为也记录到文件中,只需将您的配置部分添加到该文件中,就像您的配置部分一样:
//serilog
Logger.Logger=新的LoggerConfiguration()
.ReadFrom.Configuration(配置)
.Enrich.FromLogContext()的
.WriteTo.Async(a=>a.File(“Logs/myapp.log”,
rollOnFileSizeLimit:是的,
fileSizeLimitBytes:Convert.ToInt32(配置[“MaxLogFileSize”]))
.CreateLogger();
您还可以通过使用appsettings.json
-进行配置来添加该部分,如果您不想使用该部分.ReadFrom.configuration(configuration).exprich.FromLogContext()
只需将其删除即可
因此,您的中间件代码如下所示:
var-request=context.request;
var stopWatch=stopWatch.StartNew();
var requestTime=DateTime.UtcNow;
var requestBodyContent=await ReadRequestBody(请求);
var originalBodyStream=context.Response.Body;
generalError=配置[“generalError”];
使用(var memStream=new MemoryStream())
{
HttpResponse response=context.response;
response.Body=memStream;
等待下一个(上下文);
秒表;
字符串responseByContent=null;
responseBodyContent=ReadResponseBody(memStream);
memStream.CopyTo(originalBodyStream);
字符串infoToLog=“\r\n”+
“---------------------------\r\n”+
已用毫秒数:“+stopWatch.ElapsedMilliseconds+”\r\n+
状态代码:“+context.Response.StatusCode+”\r\n+
方法:“+请求。方法+”\r\n+
路径:“+请求。路径+”\r\n+
QueryString:“+request.QueryString.ToString()+”\r\n+
请求正文:“+requestBodyContent+”\r\n+
响应正文:“+ResponseByContent+”\r\n+
"---------------