0

I'm trying to setup Azure WebJobs setup with Serilog. Here's my current exception:

Microsoft.Azure.WebJobs.Host.Indexers.FunctionIndexingException: Error indexing method 'Functions.ProcessQueueMessage' ---> System.InvalidOperationException: Cannot bind parameter 'logger' to type ILogger. Make sure the parameter Type is supported by the binding. If you're using binding extensions (e.g. Azure Storage, ServiceBus, Timers, etc.) make sure you've called the registration method for the extension(s) in your startup code (e.g. builder.AddAzureStorage(), builder.AddServiceBus(), builder.AddTimers(), etc.).

I've seen this answer, but Serilog.Extensions.WebJobs is no longer maintained.

I've attempted variations of this hosting boilerplate setup but it either results in the same exception or no consumption of the queue message.

I've also attempted to review the SDK dependencies, but I'm unaware of where I can find a definitive list of the SDK dependencies to unpick any potential versioning mismatch.

The below works as expected when ProcessQueueMessage uses Microsoft.Extensions.Logging.ILogger but not with Serilog.ILogger:

class Program
{
    static async Task Main()
    {
        var builder = new HostBuilder();
        builder.UseSerilog();
        builder.ConfigureWebJobs(b =>
        {
            b.AddAzureStorageCoreServices();
            b.AddAzureStorage();
        });
        var host = builder.Build();
        try { await host.RunAsync(); }
        catch (Exception ex) { Log.Logger.Fatal(ex.Message, ex); }
    }
}

public class Functions
{
    public static void ProcessQueueMessage([QueueTrigger("queue")] string message, ILogger logger)
    {
        logger.Information(message); // Serilog ILogger
    }
}

Project package references:

<PackageReference Include="Microsoft.Azure.WebJobs.Extensions" Version="4.0.1" />
<PackageReference Include="Microsoft.Azure.WebJobs.Extensions.Storage" Version="4.0.4" /> (Also played with prerelease)
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="5.0.0" />
<PackageReference Include="Serilog.AspNetCore" Version="4.1.0" />

mason
  • 31,774
  • 10
  • 77
  • 121
Remy
  • 822
  • 12
  • 18
  • When it fails, on your ProcessQueueMessage, what type is ILogger? Is that Microsoft.Extensions.Logging.ILogger, or is it Serilog.ILogger? – mason Apr 29 '21 at 16:27
  • I may have misunderstood your question, but it doesn't have a type, as it fails to bind, so it doesn't get as far as ProcessQueueMessage – Remy Apr 29 '21 at 16:32
  • Sure it has a type. You're getting a runtime error, but I'm not even talking about runtime. I'm talking about at compile time. When you hover over ILogger in that method's parameters, what namespace is it declared as? – mason Apr 29 '21 at 16:33
  • Ah, compile time: Serilog – Remy Apr 29 '21 at 16:34
  • Im not exactly sure what UseSerilog() does, but it may wire it up so that when you use a Microsoft.Extensions.Logging.ILogger, it ultimately writes those to Serilog. It may not necessarily wire up DI for Serilog's own ILogger. I've never written a WebJob before, but I suspect you could either switch your ProcessQueueMessage to depend on Microsoft.Extensions.Logging.ILogger, or you could eliminate the UseSerilog() and instead create your Serilog ILogger manually and register that with the DI container. Or, you could change your method not to accept ILogger at all and just the static log methods – mason Apr 29 '21 at 16:45

1 Answers1

1

Inject ILogger as a function parameter, works like a charm.

The author of Serilog.Extensions.WebJobs provided a suitable template, which I've condensed below:

class Program
{
    static async Task Main(string[] args)
    {
        Log.Logger = new LoggerConfiguration()
            .MinimumLevel.Information()
            .WriteTo.Console()
            .CreateLogger();

        IHostBuilder builder = Host.CreateDefaultBuilder(args)
            .UseSerilog(Log.Logger)
            .ConfigureServices(s => s.AddSingleton(Log.Logger))
            .ConfigureWebJobs(b =>
            {
                b.AddAzureStorageCoreServices();
                b.AddAzureStorage();
                b.AddTimers();
            });

        IHost host = builder.Build();
        try { await host.RunAsync(); }
        catch (Exception ex) { Log.Fatal(ex.Message, ex); }
        finally { Log.CloseAndFlush(); }
    }
}

public class Functions
{
    readonly ILogger _logger;

    public Functions(ILogger logger) => _logger = logger.ForContext<Functions>();

    public void ProcessQueueMessage([QueueTrigger("queue")] string message) =>
        _logger.Information(message);
}

Package References:

<PackageReference Include="Microsoft.Azure.WebJobs" Version="3.0.27" />
<PackageReference Include="Microsoft.Azure.WebJobs.Extensions" Version="4.0.1" /> <PackageReference Include="Microsoft.Azure.WebJobs.Extensions.Storage" Version="4.0.4" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="5.0.0" /> <PackageReference Include="Serilog.Extensions.Hosting" Version="4.1.2" />
<PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />

Credit: @James Skimming

Remy
  • 822
  • 12
  • 18