Используйте Serilog в библиотеке классов из внешней сборки, без внедрения зависимостей в основное приложение.

Я работаю над проектом, в котором основное приложение (приложение Windows Forms) уже доступно и не использует внедрение зависимостей. Это основное приложение создает экземпляры некоторых внешних компонентов (доступных во внешней сборке библиотеки классов, на которую ссылается основное приложение), напрямую вызывая их конструктор. С другой стороны, эти компоненты используют внедрение зависимостей для создания экземпляров своих дальнейших зависимостей. Основное приложение:

      public MainForm()
{
    InitializeComponent();

    var appName = "abc";
    var myExtComp = new MyExtComponent(appName);
    ...
}

или

      public MainForm()
{
    InitializeComponent();

    var appName = "abc";
    var myExtWebComp = new MyExtWebComponent(appName);
    ...
}

Существует 2 вида внешних компонентов, один из которых является «обычным» внешним вспомогательным компонентом:

      public MyExtComponent(string appName)
{
    Log.Logger = ConfigureLogger(appName);

    IHostBuilder builder = = Host.CreateDefaultBuilder();

    builder.UseSerilog();

    InitMyExtCompServices(builder);

    IHost host = builder.Build();
    host.RunAsync();
}

private void InitMyExtCompServices(IHostBuilder builder)
{
    builder
        .ConfigureServices((context, services) =>
        {
            services.AddSingleton<IMyService, MyService>();
            ...
        }
}

public class MyService: IMyService
{
    private readonly ILoggerFactory loggerFactory;
    private readonly ILogger<MyService> logger;

    public MyService(ILoggerFactory LoggerFactory)
    {
        loggerFactory = LoggerFactory ?? throw new ArgumentNullException(nameof(LoggerFactory));
        logger = loggerFactory.CreateLogger<MyService>();
    }
    ...
}

а другой содержит несколько веб-контроллеров:

      public MyExtWebComponent(string appName)
{
    Log.Logger = ConfigureLogger(appName);

    WebApplicationBuilder webBuilder = WebApplication.CreateBuilder();
    IHostBuilder builder = webBuilder.Host;
    builder.UseSerilog();

    InitMyExtWebCompServices(webBuilder);

    var app = webBuilder.Build();
    InitWebServerApplication(app);

    app.RunAsync();
}

private void InitMyExtWebCompServices(WebApplicationBuilder webBuilder)
{
    var webHostBuilder = webBuilder.WebHost;
    webHostBuilder.ConfigureKestrel(o =>
    {
        ...
    });

    // Add services to the container
    var services = webBuilder.Services;

    services.AddCors(...);
    ...
    services.AddMvc().AddApplicationPart(...);
    services.AddControllers();
    ... 
}


private void InitWebServerApplication(WebApplication app)
{
    app.UseCors(...);

    app.UseRouting();
    app.UseAuthentication();
    app.UseAuthorization();

    app.UseEndpoints(endpoints => { endpoints.MapControllers(); });
}


[ApiController]
public class MyController : ControllerBase
{
    private readonly ILoggerFactory loggerFactory;
    private readonly ILogger<MyController> _logger;

    public MyController(ILoggerFactory loggerFactory)
    {
        loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory));
        _logger = loggerFactory.CreateLogger<MyController>();
    }

    ... 
}

В обоих случаях настроен регистратор serilog:

      public ILogger ConfigureLogger(string appName)
{
    var logPath = Environment.GetEnvironmentVariable("LOG_PATH", EnvironmentVariableTarget.Machine) ??
                  $@"c:\Logs\{appName}";
    var logFileNameFormat =
        Environment.GetEnvironmentVariable("LOG_FILE_NAME_FORMAT", EnvironmentVariableTarget.Machine) ??
        $@"traces.log";
    var logLevelFileStr =
        Environment.GetEnvironmentVariable("LOG_LEVEL_FILE", EnvironmentVariableTarget.Machine) ?? $"Debug";
    var logLevelFile = LogEventLevel.Debug;
    try
    {
        logLevelFile = (LogEventLevel)Enum.Parse(typeof(LogEventLevel), logLevelFileStr);
    }
    catch (Exception exc)
    {
    }

    var logFileNameTemplate = $@"{logPath}\{logFileNameFormat}";
    var fileOutputTemplate = "{Timestamp:dd-MM-yyyy HH:mm:ss.fff zzz}:: {Level:u3}:: {Message:lj}{NewLine}";
    var consoleOutputTemplate =
        "{Timestamp:dd-MM-yyyy HH:mm:ss.fff zzz}:: {Level:u3}:: {Message:lj}{Properties}{NewLine}";

    // defining Serilog configs
    return new LoggerConfiguration()
        .MinimumLevel.Debug()
        .MinimumLevel.Override("Microsoft.AspNetCore", LogEventLevel.Warning)
        .Enrich.WithExceptionDetails()
        .Enrich.FromLogContext()
        .WriteTo.Async(a => a.Console(outputTemplate: consoleOutputTemplate, theme: SystemConsoleTheme.Colored))
        .WriteTo.Async(a => a.File(
            path: logFileNameTemplate,
            restrictedToMinimumLevel: LogEventLevel.Debug,
            rollingInterval: RollingInterval.Day,
            retainedFileCountLimit: 30,
            shared: true,
            flushToDiskInterval: TimeSpan.FromSeconds(3),
            outputTemplate: fileOutputTemplate
        )) // Wrap any file sinks in an Async sink
        .CreateLogger();
}

Во внешних компонентах все выполняется нормально, но я не могу ничего зарегистрировать в serilog. Сгенерированные файлы журнала, например, не имеют записей журнала, хотя logger.LogDebug() (и т. д.) вызывается во внешних компонентах. Как должен быть настроен serilog в приведенном выше сценарии, чтобы получать журналы из внешних сборок, содержащих указанные компоненты?

0 ответов

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