Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Serilog written to the ILogger does not appear (Azure Functions V2)

I've installed Serilog and configured to write the log event data to a table in MS SQL Server for Azure Function.

System logs and logs that have been written by the static class itself appears on the table but when I try to use Extensions.Logging.ILogger, messages are not appear in the table even if I can see the Serilog provider in the ILogger.

Startup.cs configuration;

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;
        }

    }
}

Creation of ILogger in 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!

        }


    } 

Also, receiving ILogger itself into cons is not working ..

Weird part is only system logs are being logged into table;

enter image description here

And Serilog provider is already exists in not working ILogger instance;

enter image description here

like image 604
Kadir Ercetin Avatar asked Jan 30 '26 06:01

Kadir Ercetin


1 Answers

I had exactly the same issue but solved it in the end. The official documentation has a hint:

The startup class is meant for only setup and registration. Avoid using services registered at startup during the startup process. For instance, don't try to log a message in a logger that is being registered during startup. This point of the registration process is too early for your services to be available for use. After the Configure method is run, the Functions runtime continues to register additional dependencies, which can affect how your services operate.

So, when you call the following code, this logger is only used until it is overwritten by the host internal configuration.

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

You need to register Serilog just as a logger provider. That will include it in the following configuration as one of the providers.

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

In my experience the behaviour is different in local azure functions emulator, so try it with the deployed instance.

like image 182
Martin Cerny Avatar answered Feb 02 '26 22:02

Martin Cerny