首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Serilog在达到最大文件大小之前创建文件。

Serilog在达到最大文件大小之前创建文件。
EN

Stack Overflow用户
提问于 2020-03-23 09:02:22
回答 1查看 1.1K关注 0票数 1

我使用.NET核心2.1创建了一个API,并使用Serilog记录所有方法类型的每个响应和请求: Get、Post .尽管有响应代码,下面是添加到中间件类中的代码:

代码语言:javascript
复制
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时,我们意识到许多日志文件是同时创建的,而没有达到最大文件大小,更具体地说,应该同时记录多个方法。我们能解决这个问题吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-03-23 09:48:23

您正在您的中间件中的每个when请求上实例化一个新的记录器,我认为您也在用Log.CloseAndFlush();关闭日志文件,而我认为如果我回忆起这些文档,它应该是一个独立的日志文件。

据我所知,您只需要在应用程序引导过程中创建记录器。我就是这样做的(program.cs和.NET核心2.2):

代码语言:javascript
复制
    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默认日志记录器重写为只显示日志级别警告或更高的日志级别:

代码语言:javascript
复制
  "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部分-因此,如果您想配置记录器来登录文件,只需像您的配置部分一样将配置部分添加到文件中:

代码语言:javascript
复制
// 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()只需删除它。

因此,您的中间件代码将如下所示:

代码语言:javascript
复制
    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 )。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60810479

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档