Как настроить поставщика ведения журналов EventLog через мой файл appsettings.json

В консольном приложении My .net core 6 я создаю хост-строитель

      var builder = Host.CreateDefaultBuilder(args);

Это дает мне экземпляр HostBuilder с фабрикой ведения журналов, настроенной для поставщиков консоли, отладки, журнала событий и источников событий, а также поставщиков конфигурации для переменных пользовательской/системной среды, appsettings.json, appsettings..json и т. д.

Я могу внедрить ILogger или ILoggingFactory в свой класс и писать во все поставщики журналов, используя функцию ILogger.Log.

      public class BusinessLogic
{
    private IHostEnvironment _env;
    private ILogger _logger;

    public BusinessLogic(
        IHostEnvironment env, 
        ILoggerFactory loggerFactor)
    {       
        _env = env;

        _logger = loggerFactor.CreateLogger<BusinessLogic>();
    }

    public void Run()
    {    
        foreach (var level in Enum.GetValues<LogLevel>())
        {
            _logger.Log(level, $"Test logging at level {level}.");
        }

        Console.WriteLine("Hello, World!  Press any key...");    
        Console.ReadLine();
    }
}

Теперь я хочу настроить имя приложения журнала событий и имя источника, в которое будет записывать провайдер журнала событий. Я бы не хотел жестко кодировать это, поэтому я надеялся сделать это через файл appsettings.json. Кажется, я не могу заставить это подействовать. Мой файл appsettings.json выглядит так:

      {
    "Logging":
    {
        //Settings for the windows event log logging provider
        "EventLog":
        {
            "LogName": "Application",
            "SourceName": "MySource",
      
            "LogLevel":
            {
                "Default": "Trace"
            }
        }
    }
}

Вышеупомянутые настройки приложения не влияют, поэтому я решил попробовать добавить нового провайдера EventLog и передать ему конфигурацию.

      var builder = Host.CreateDefaultBuilder(args);
builder.ConfigureAppConfiguration((context, builder) =>
{
    var eventLogConfiguration = context.Configuration.GetSection("Logging:EventLog").Get<EventLogSettings>();
    builder.AddEventLog(eventLogConfiguration);
});

Это тоже не сработало, поэтому я попытался очистить поставщиков журналов на случай, если добавление дубликатов будет проблемой.

      var builder = Host.CreateDefaultBuilder(args);
builder.ConfigureAppConfiguration((context, builder) =>
{
    builder.ClearProviders();
    var eventLogConfiguration = context.Configuration.GetSection("Logging:EventLog").Get<EventLogSettings>();
    builder.AddEventLog(eventLogConfiguration);
});

Это работает, но что, если я хочу, чтобы все остальные существующие поставщики были сохранены? Могу ли я просто заменить один или каким-то образом применить конфигурацию к существующему провайдеру, или есть какой-то другой/лучший способ сделать это?

1 ответ

Если вы посмотрите на источник , он уже делает все это:

      // HostingHostBuilderExtensions.cs > AddDefaultServices
bool isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
...

logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
...

if (isWindows)
    // Add the EventLogLoggerProvider on windows machines
    logging.AddEventLog();

При условииAddConfigurationЗвонок вам не нужен.

Учитывая этот вызов, вам не нужно вызывать его снова.

Поскольку это работает только тогда, когда вы сначала звоните, я думаюCreateDefaultBuilderдолжно быть, неправильно настроен журнал событий. Но, если бы это было такGetSection("Logging:EventLog")завершится ошибкой или вы увидите сообщение об ошибке (как это происходит, если вы используете нераспознанный источник или имя журнала).

Интересно, если что-то вLoggingэтого нет вLogging:EventLogможет быть проблема?

У меня похожая проблема , но мне не нужно звонитьClearProviders()- добавлениеAddEventLogмне достаточно, но это ничего не улавливаетappsettings.jsonесли я не добавлю это явно.

Обновлять

Я думаю, что это может быть ошибка (или, возможно,LogNameиSourceNameпросто не поддерживаются из конфигурации). У меня есть обходной путь на данный момент.

По сути, я вручную устанавливаю конфигурацию (как и вы), но с проверкой ОС, которую понимает анализ кода, и с лямбдой, которая изменяет конфигурацию, а не применяет ее снова.

      [System.Runtime.Versioning.SupportedOSPlatform("windows")]
public static void SetEventLogConfig(WebApplicationBuilder builder) {
    string? eventLog = builder.Configuration["Logging:EventLog:SourceName"];
    if(eventLog is not null)
        builder.Logging.AddEventLog(c => c.SourceName = eventLog);
}

// then in program.cs
if(RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
    SetEventLogConfig(builder);

Это работает для моего приложения, но я до сих пор не уверен, зачем вам нужно звонитьClearProvidersв вашей реализации.

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