15

Given a File->New->Azure Functions v2 App, I'm trying to get a reference to either an ILoggerFactory or an ILogger<T>.

I'm doing this in the StartUp.cs class which is ran on the function app start.

Given the following code a weird exception is thrown:

var serviceProvider = builder.Services.BuildServiceProvider();
var loggerFactory = serviceProvider.GetService<ILoggerFactory>();         

with the following exception:

enter image description here

 A host error has occurred
[27/02/2019 8:21:22 AM] Microsoft.Extensions.DependencyInjection: Unable to resolve service for type 'Microsoft.Azure.WebJobs.Script.IFileLoggingStatusManager' while attempting to activate 'Microsoft.Azure.WebJobs.Script.Diagnostics.HostFileLoggerProvider'.
Value cannot be null.
Parameter name: provider

What is going on?

The full test repo/code can be found here on GitHub.

halfer
  • 19,824
  • 17
  • 99
  • 186
Pure.Krome
  • 84,693
  • 113
  • 396
  • 647
  • 1
    I'm getting the same error, but well into the execution of the function, in a service which I have injected for the Azure Function to use. Were you able to figure this out? – Anthony Potts Sep 24 '19 at 17:15
  • The same here. Could you figure out what caused this error message? – AndrasCsanyi Oct 12 '19 at 15:10
  • Did you figure out your issue @AnthonyPotts? I just upgraded a function from V2 to V3 and am having this issue now also well into the execution of the function – Adrian Jun 27 '20 at 20:44
  • @Adrian No, I ended up using the IOC that I had hand rolled from a couple of blog posts. – Anthony Potts Jul 01 '20 at 15:01
  • We had the same problem trying to access our logger in Startup. We ended up registering it twice, one within a logger factory: `var loggerFactory = LoggerFactory.Create(loggingBuilder => // register your loggers for use in Startup here again);` – Kiechlus Feb 14 '22 at 14:10

3 Answers3

7

It seems that some infrastructure (e.g. IFileLoggingStatusManager) necessary for HostFileLoggerProvider is not set up yet at the time you are creating the dependency injection container and attempt to resolve the logger in the StartUp class. I think you should delay logging until after the application has fully started.

If you look at the startup code of WebJobs you'll see that the logger gets added first, after that the external startup gets executed and finally the required logging services gets added. Which is the wrong order for your case.

Henk Mollema
  • 44,194
  • 12
  • 93
  • 104
  • 9
    Henk: Do you know about a workaround for this sitaution? I would like to be able to inject the ILogger to a dependency which is bootstrapped in Startup (builder.Services.AddSingleton...) preferably as part of the Startup in my Azure Function – Markus Foss Aug 14 '19 at 12:46
  • According to [this](https://github.com/simpleinjector/SimpleInjector/issues/749): "You can't request an ILogger<> during service initialization -- some of the loggers haven't had all of their dependencies registered at this point." In [this post](https://github.com/simpleinjector/SimpleInjector/issues/536) it is suggested to use the [Humble Objects](http://xunitpatterns.com/Humble%20Object.html) design pattern instead. – Vince Horst Dec 31 '19 at 01:57
0

I've been looking for a solution for a while then I end up creating another service container for the startup class, but it'll need to register the required services to this container.

   public class Startup : FunctionsStartup
   {
        public override void Configure(IFunctionsHostBuilder builder)
        {
           var services = builder.Services;
           IConfiguration configuration = services.BuildServiceProvider().GetService<IConfiguration>();
           var tempServiceContainer = new ServiceCollection()
                .AddScoped(_ => configuration);
           tempServiceContainer.AddSingleton<IYourService, YourService>();
        }
    }

Or maybe you could try using lazy Dependency Injection, but I haven't test it yet on the cloud server.

service.AddSingleton<IYourService, YourService>();
service.AddSingleton(provider => new Lazy<IYourService>(provider.GetService<IYourService>));

var yourService = serviceProvider.GetService<Lazy<IYourService>>();
  • @infansoetedja this question is really old now. Also, Azure Functions are up to version 4 (this question was targeting v2). Are you still having a problem? have you tried working with v4 Azure Functions? – Pure.Krome Apr 11 '22 at 08:11
0

This doesn't work, at least not yet. (link)

The services getting registered at startup are not fully ready to be used inside the Configure method itself. Read the section 'Caveats' here: https://learn.microsoft.com/en-us/azure/azure-functions/functions-dotnet-dependency-injection

"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."

Ε Г И І И О
  • 11,199
  • 1
  • 48
  • 63