Не удается заставить Serilog.Sinks.File, завернутый в Serilog.Sinks.Async, работать в двухэтапном подходе к инициализации.

Serilog не регистрируется в приемнике файлов, заключенном в приемник Async, при использовании двухэтапной инициализации с конфигурацией appSettings. Я использую следующие пакеты NuGet Serilog:

      Serilog - 2.10.0
Serilog.Settings.Configuration - 3.1.0
Serilog.AspNetCore - 4.1.0
Serilog.Sinks.Console - 4.0.0
Serilog.Sinks.File - 5.0.0
Serilog.Sinks.Async - 1.5.0
Serilog.Enrichers.Environment - 2.1.3
Serilog.Enrichers.Thread - 3.1.0

Я хочу использовать конфигурацию appSettings.json с двухэтапной инициализацией . Точка входа в мое приложение ниже:

      using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
using Serilog;
using Serilog.Events;
using System;

namespace FooApi
{
    public class Program
    {
        public static int Main(string[] args)
        {
            Log.Logger = new LoggerConfiguration()
                .MinimumLevel.Information()
                .MinimumLevel.Override("Microsoft.AspNetCore", LogEventLevel.Warning)
                .MinimumLevel.Override("Microsoft.Hosting.Lifetime", LogEventLevel.Information)
                .MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
                .Enrich.FromLogContext()
                .Enrich.WithMachineName()
                .Enrich.WithThreadId()
                .WriteTo.Console(
                    outputTemplate: "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} {Level:u3}] {Message:lj} <s:{SourceContext}>{NewLine}{Properties:j}{NewLine}{Exception}"
                )
                .WriteTo.Async(a => a.File(
                    outputTemplate: "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} {Level:u3}] {Message:lj} <s:{SourceContext}>{NewLine}{Properties:j}{NewLine}{Exception}",
                    path: "logs/log-.txt",
                    rollingInterval: RollingInterval.Day
                )).CreateBootstrapLogger();

            try
            {
                Log.Information("Starting up the host");
                CreateHostBuilder(args).Build().Run();
                return 0;
            }
            catch (Exception ex)
            {
                Log.Fatal(ex, "Host start-up failed");
                return 1;
            }
            finally
            {
                Log.CloseAndFlush();
            }
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .UseSerilog((context, services, configuration) =>
                {
                    configuration
                        .ReadFrom.Configuration(context.Configuration)
                        .ReadFrom.Services(services);
                })
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });
    }
}

а мой appSettings.json (у меня пока нет версий .Development и .Release):

      {
  "Serilog": {
    "MinimumLevel": {
      "Default": "Information",
      "Override": {
        "Microsoft.AspNetCore": "Warning",
        "Microsoft.Hosting.Lifetime": "Information",
        "Microsoft": "Warning"
      }
    },
    "WriteTo": [
      {
        "Name": "Async",
        "Args": {
          "configure": [
            {
              "Name": "File",
              "Args": {
                "path": "logs/log-.txt",
                "rollingInterval": "Day",
                "outputTemplate": "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} {Level:u3}] {Message:lj} <s:{SourceContext}>{NewLine}{Properties:j}{NewLine}{Exception}"
              }
            }
          ]
        }
      },
      {
        "Name": "Console",
        "Args": {
          "outputTemplate": "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} {Level:u3}] {Message:lj} <s:{SourceContext}>{NewLine}{Properties:j}{NewLine}{Exception}",
          "theme": "Serilog.Sinks.SystemConsole.Themes.AnsiConsoleTheme::Code, Serilog.Sinks.Console"
        }
      }
    ],
    "Enrich": [ "WithMachineName", "WithThreadId", "FromLogContext" ]
  },
  "AllowedHosts": "*"
}

При такой конфигурации даже после бомбардировки API 100 000 запросов в файле журнала отображается только сообщение из начальной загрузки:

      [2021-07-13 18:00:04.642 +02:00 INF] Starting up the host <s:>
{"MachineName":"FooMachine","ThreadId":1}

Пока консоль показывает (сокращено для краткости):

      [2021-07-13 18:00:04.642 +02:00 INF] Starting up the host <s:>
{"MachineName": "FooMachine", "ThreadId": 1}
[2021-07-13 18:00:07.059 +02:00 INF] Now listening on: https://localhost:5001 <s:Microsoft.Hosting.Lifetime>
{"MachineName": "FooMachine", "ThreadId": 1}
[2021-07-13 18:00:07.065 +02:00 INF] Now listening on: http://localhost:5000 <s:Microsoft.Hosting.Lifetime>
{"MachineName": "FooMachine", "ThreadId": 1}
[2021-07-13 18:00:07.065 +02:00 INF] Application started. Press Ctrl+C to shut down. <s:Microsoft.Hosting.Lifetime>
{"MachineName": "FooMachine", "ThreadId": 1}
[2021-07-13 18:00:07.065 +02:00 INF] Hosting environment: Development <s:Microsoft.Hosting.Lifetime>
{"MachineName": "FooMachine", "ThreadId": 1}
[2021-07-13 18:00:07.066 +02:00 INF] Content root path: C:\Rules.Api <s:Microsoft.Hosting.Lifetime>
{"MachineName": "FooMachine", "ThreadId": 1}
[2021-07-13 18:00:08.770 +02:00 INF] HTTP GET / responded 200 in 80.4108 ms <s:Serilog.AspNetCore.RequestLoggingMiddleware>
{"MachineName": "FooMachine", "ThreadId": 11, "RequestId": "0HMA62T4HESK3:00000001", "ConnectionId": "0HMA62T4HESK3"}
[2021-07-13 18:00:10.951 +02:00 INF] HTTP GET / responded 200 in 0.4243 ms <s:Serilog.AspNetCore.RequestLoggingMiddleware>
{"MachineName": "FooMachine", "ThreadId": 17, "RequestId": "0HMA62T4HESK3:00000003", "ConnectionId": "0HMA62T4HESK3"}
[2021-07-13 18:00:11.366 +02:00 INF] HTTP GET / responded 200 in 0.1562 ms <s:Serilog.AspNetCore.RequestLoggingMiddleware>
{"MachineName": "FooMachine", "ThreadId": 8, "RequestId": "0HMA62T4HESK3:00000005", "ConnectionId": "0HMA62T4HESK3"}
[2021-07-13 18:00:15.385 +02:00 INF] HTTP GET /call responded 200 in 1814.5944 ms <s:Serilog.AspNetCore.RequestLoggingMiddleware>
{"MachineName": "FooMachine", "ThreadId": 6, "RequestId": "0HMA62T4HESK3:00000007", "ConnectionId": "0HMA62T4HESK3"}

Я не могу заставить Serilog записывать сообщения в файл после начальной загрузки, консоль работает нормально.

1 ответ

Оказывается, что при двухэтапной инициализации BootstrapLogger, вероятно, не размещает свой дескриптор в файле, и когда фактический регистратор получает экземпляр, он не может получить доступ к файлу. В итоге я использовал только консольный приемник на первом этапе и добавил приемник файлов только на втором этапе.

Другие вопросы по тегам