Serilog, записанный в ILogger, не отображается (функции Azure V2)

Я установил Serilog и настроил запись данных событий журнала в таблицу в MS SQL Server для Azure Function.

Системные журналы и журналы, которые были записаны самим статическим классом, появляются в таблице, но когда я пытаюсь использовать Extensions.Logging.ILogger, сообщения не появляются в таблице, даже если я вижу поставщика Serilog в ILogger.

Конфигурация Startup.cs;

using Microsoft.ApplicationInsights.Extensibility;
using Microsoft.Azure.WebJobs.Hosting;
using Serilog;
using Serilog.Events;
using Serilog.Sinks.MSSqlServer;
using Microsoft.Azure.WebJobs;

[assembly: FunctionsStartup(typeof(Rubix.FunctionApp.Startup))]
namespace Rubix.FunctionApp
{
    public class Startup : IWebJobsStartup
    {

        public Startup()
        {
            var config = new ConfigurationBuilder()
               .AddJsonFile("local.settings.json", optional: true, reloadOnChange: true)
               .AddEnvironmentVariables()
               .Build();

            var logDbConnectionString = "connectionString";
            var logTable = "LogEntry";
            var columnOptions = new ColumnOptions()
            {
                AdditionalColumns = new Collection<SqlColumn>
                {
                    new SqlColumn
                        {ColumnName = "Filter", DataType = SqlDbType.NVarChar, DataLength = 50},

                    new SqlColumn
                        {ColumnName = "JsonType", DataType = SqlDbType.NVarChar, DataLength = 50},
                }
            };
            // we don't need XML data
            columnOptions.Store.Remove(StandardColumn.Properties);
            // we do want JSON data
            columnOptions.Store.Add(StandardColumn.LogEvent);
            // exclude standard columns from the json output
            columnOptions.LogEvent.ExcludeStandardColumns = true;

            Log.Logger = new LoggerConfiguration()
                .ReadFrom.Configuration(config)
                .Enrich.FromLogContext()
                .WriteTo.MSSqlServer(
                    connectionString: logDbConnectionString,
                    tableName: logTable,
                    columnOptions: columnOptions
                )
                .WriteTo.ApplicationInsights(TelemetryConfiguration.Active, TelemetryConverter.Traces, LogEventLevel.Information)
                .CreateLogger();
        }



        public void Configure(IWebJobsBuilder builder)
        {
            ConfigureServices(builder.Services).BuildServiceProvider(true);
        }

        private IServiceCollection ConfigureServices(IServiceCollection services)
        {
             services
                .AddLogging(loggingBuilder =>
                    loggingBuilder.AddSerilog(dispose: true)
                );

            return services;
        }

    }
}

Создание ILogger в Azure Function;

public class Function
    {
        private readonly ILogger<Function> _logger;      

        public Function(ILoggerFactory loggerFactory)
        {
            _logger = loggerFactory.CreateLogger<Function>();
        }

        [FunctionName("Function1")]
        public async Task Run([ServiceBusTrigger("topic-name", "subscription-name", Connection = "AzureServiceBus")]string message)
        {
            Log.Logger.Information("Function invoked");// ---->  WORKING!

            _logger.LogInformation("Function invoked by ILogger");// ----> NOT WORKING!

        }


    } 

Кроме того, получение самого ILogger в минусы не работает..

Странная часть - только системные журналы регистрируются в таблице;

И поставщик Serilog уже существует в не работающем экземпляре ILogger;

3 ответа

У меня была точно такая же проблема, но в конце концов я ее решил. В официальной документации есть подсказка:

Класс запуска предназначен только для настройки и регистрации. Избегайте использования служб, зарегистрированных при запуске, во время процесса запуска. Например, не пытайтесь регистрировать сообщение в регистраторе, который регистрируется во время запуска . На этом этапе процесса регистрации еще слишком рано, чтобы ваши услуги были доступны для использования. После запуска метода Configure среда выполнения функций продолжает регистрировать дополнительные зависимости, которые могут повлиять на работу ваших служб.

Итак, когда вы вызываете следующий код, этот регистратор используется только до тех пор, пока он не будет перезаписан внутренней конфигурацией хоста.

      services.AddLogging(loggingBuilder =>
    loggingBuilder.AddSerilog(dispose: true)
);

Вам необходимо зарегистрировать Serilog как поставщик регистратора . Это будет включать его в следующую конфигурацию в качестве одного из поставщиков.

      builder.Services
    .AddSingleton<ILoggerProvider>(new Serilog.Extensions.Logging.SerilogLoggerProvider(Log.Logger));

По моему опыту, поведение локального эмулятора функций Azure отличается, поэтому попробуйте его с развернутым экземпляром.

Я думаю, ваша проблема в том, что время выполнения функций фильтрует ваши журналы и публикует только системные в serilog. Измените свойhost.json config, чтобы разрешить прохождение всех журналов на уровне трассировки и выше:

{
  "version": "2.0",
  "logging": {
    "fileLoggingMode": "debugOnly",
    "logLevel": {
      // For all functions. Can also specify function name
      "Function": "Trace",
      // Default settings, e.g. for host
      "default": "Trace"
    }
  }
}

Дополнительные документы на https://docs.microsoft.com/en-us/azure/azure-functions/functions-host-json

Я полагаю, что вы хотите Fatal логи, потому что я не нахожу Critical уровень в логах serilog wiki. И описание о Fatal это критические ошибки, вызывающие полный сбой приложения.

Ниже мой тест кода с Serilog.Sinks.MSSqlServer пакет, и это работает хорошо. И вот подробности об этом пакете: Serilog.Sinks.MSSqlServer.

        var logDB = "Server=xxxxxxx";
        var logTable = "Logs";
        var options = new ColumnOptions();
        options.Store.Remove(StandardColumn.Properties);
        options.Store.Add(StandardColumn.LogEvent);


        var log = new LoggerConfiguration()
            .WriteTo.MSSqlServer(
                connectionString: logDB,
                tableName: logTable,
                autoCreateSqlTable:true,
                restrictedToMinimumLevel:Serilog.Events.LogEventLevel.Verbose,
                columnOptions: options
            ).CreateLogger();

        log.Information("C# HTTP trigger function processed a request.");
        log.Fatal("Here is a fatal log meesage");
        log.Warning("Here is a warning log message");
        log.Error("Here is an error log message");

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