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;

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

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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With