JonasH
JonasH

Reputation: 4490

Azure Functions V3: Unable to get ILogger working with DI

We have an Azure Function v3 and would like to inject an ILogger<MyFunction> logger into our function classes via constructor. We are struggling to get it to work with Serilog as the default logger.

I have tried different ways as shown below with different errors.

Startup.cs:

public class Startup : FunctionsStartup
{
    public override void Configure(IFunctionsHostBuilder builder)
    {
        builder.Services.AddSingleton<ILoggerFactory, LoggerFactory>();
        builder.Services.AddSingleton<ILoggerProvider>(sp =>
        {
            var logger = new LoggerConfiguration().WriteTo.Elasticsearch(
                new ElasticsearchSinkOptions(...)
                .CreateLogger();
            return new SerilogLoggerProvider(logger, dispose: true);
        });
    }
}

However, I get following error:

Method Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton: type argument 'Microsoft.Extensions.Logging.LoggerFactory' violates the constraint of type parameter 'TImplementation'. Value cannot be null. (Parameter 'provider')

If I try to add the factory like following: builder.Services.AddSingleton<ILoggerFactory>(sp => new LoggerFactory());

The error is:

Microsoft.Azure.WebJobs.Script.WebHost: Registered factory delegate returns service Microsoft.Extensions.Logging.LoggerFactory is not assignable to container. Value cannot be null. (Parameter 'provider')

Trying to add the logger into a provider into a factory in one go when adding the IFactoryLogger results in following error:

Method not found: 'Void Microsoft.Extensions.Logging.LoggerFactory..ctor(System.Collections.Generic.IEnumerable`1<Microsoft.Extensions.Logging.ILoggerProvider>)'. Value cannot be null. (Parameter 'provider')

I've also tried to add the default logging without declaring a factory:

builder.Services.Add(ServiceDescriptor.Describe(typeof(ILogger<>), typeof(Logger<>), ServiceLifetime.Scoped));

The error is:

Microsoft.Extensions.Logging.Abstractions: Value cannot be null. (Parameter 'factory').

Am I missing something crucial here?

Upvotes: 0

Views: 2101

Answers (1)

Harshita Singh
Harshita Singh

Reputation: 4870

Below is the way to add Serilog in Azure Functions V3:

  • Create an instance the Serilog logger, with all the configuration for console and file sinks.
  • Register this logger in the builder.Services.AddLogging method.

Related Code:

// Startup.cs - Registering a third party logging provider
var logger = new LoggerConfiguration()
                .WriteTo.Console()
                .WriteTo.File("log.txt", rollingInterval: RollingInterval.Day)
                .CreateLogger();
builder.Services.AddLogging(lb => lb.AddSerilog(logger));

Complete Startup.cs:

// Startup.cs
using AzureFunctionDependencyInjection.Configurations;
using AzureFunctionDependencyInjection.Services;
using Microsoft.Azure.Functions.Extensions.DependencyInjection;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Serilog;
[assembly: FunctionsStartup(typeof(AzureFunctionDependencyInjection.Startup))]
namespace AzureFunctionDependencyInjection
{
    public class Startup : FunctionsStartup
    {
        public override void Configure(IFunctionsHostBuilder builder)
        {
            // Registering Configurations (IOptions pattern)
            builder
                .Services
                .AddOptions<MessageResponderConfiguration>()
                .Configure<IConfiguration>((messageResponderSettings, configuration) =>
                {
                    configuration
                    .GetSection("MessageResponder")
                    .Bind(messageResponderSettings);
                });
// Registering Serilog provider
            var logger = new LoggerConfiguration()
                .WriteTo.Console()
                .WriteTo.File("log.txt", rollingInterval: RollingInterval.Day)
                .CreateLogger();
            builder.Services.AddLogging(lb => lb.AddSerilog(logger));
// Registering services
            builder
                .Services
                .AddSingleton<IMessageResponderService, MessageResponderService>();
        }
    }
}

Check out this detailed and great article: Dependency Injection in Azure Functions V3 on this.

Upvotes: 1

Related Questions