我使用.NET核心2.1创建了一个API,并使用Serilog记录所有方法类型的每个响应和请求: Get、Post .尽管有响应代码,下面是添加到中间件类中的代码:
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时,我们意识到许多日志文件是同时创建的,而没有达到最大文件大小,更具体地说,应该同时记录多个方法。我们能解决这个问题吗?
发布于 2020-03-23 09:48:23
您正在您的中间件中的每个when请求上实例化一个新的记录器,我认为您也在用Log.CloseAndFlush();关闭日志文件,而我认为如果我回忆起这些文档,它应该是一个独立的日志文件。
据我所知,您只需要在应用程序引导过程中创建记录器。我就是这样做的(program.cs和.NET核心2.2):
public class Program
{
private static readonly string _applicationName = System.Reflection.Assembly.GetEntryAssembly().GetName().Name;
public static IConfiguration Configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")}.json", reloadOnChange: true, optional: true)
.AddEnvironmentVariables()
.Build();
public static int Main(string[] args)
{
// serilog
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(Configuration)
.Enrich.FromLogContext()
.CreateLogger();
try
{
if (string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")))
throw new Exception("Hosting environment variable not set");
Log.Information($"Bootstrapping application: {_applicationName}");
CreateWebHostBuilder(args).Build().Run();
Log.Information($"Gracefully closing application: {_applicationName}");
return 0; // returning a zero, indicates a successful shutdown.
}
catch (Exception e)
{
Log.Warning($"Host {_applicationName} - terminated unexpectedly.");
Log.Fatal(e.Message);
return 1; // returning a none-zero, indicates failure.
}
finally
{
Log.CloseAndFlush();
}
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.UseConfiguration(Configuration)
.UseSerilog();
}因此,当您想要记录某件事时,只需导入using Serilog;并调用Log.Information("Your message.")
更多信息可以在https://serilog.net/或https://github.com/serilog/serilog的底部找到。
编辑
这是我的配置,指定控制台为接收器(您可以添加更类似的文件,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 chosen datastore中,这仅仅意味着Log.Information("Your message");。在我的示例中,我用// serilog标记了serilog部分-因此,如果您想配置记录器来登录文件,只需像您的配置部分一样将配置部分添加到文件中:
// serilog
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(Configuration)
.Enrich.FromLogContext()
.WriteTo.Async(a => a.File("Logs/myapp.log",
rollOnFileSizeLimit: true,
fileSizeLimitBytes: Convert.ToInt32(Configuration["MaxLogFileSize"])))
.CreateLogger();您还可以通过使用appsettings.json进行配置来添加该部件--如果您不想要这个部分,.ReadFrom.Configuration(Configuration).Enrich.FromLogContext()只需删除它。
因此,您的中间件代码将如下所示:
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";
if (context.Response.StatusCode == 200)
{
Log.Information(infoToLog);
}
else
{
Log.Error(infoToLog);
}
context.Response.Body = originalBodyStream;
}还请注意,我在此方法上调用.UseSerilog();,在program.cs中使用public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>来覆盖Microsft默认记录器(我更喜欢用于所有日志的serilog )。
https://stackoverflow.com/questions/60810479
复制相似问题