ASP.NET Core 3 supports logging via DI in its Configure method. Does Azure Functions allow the same?
Obviously, you cannot inject an ILogger into the override of FunctionsStartup.Configure because it does not have such a parameter.
The following also doesn't work:
public class Startup : FunctionsStartup
{
public override void Configure(IFunctionsHostBuilder builder)
{
// stuff...
using (var provider = builder.Services.BuildServiceProvider())
{
var logger = provider.GetRequiredService<ILogger>(); // ILogger<Startup> doesn't work either
logger.LogWarning(...);
}
}
}
yielding the error:
Microsoft.Extensions.DependencyInjection.Abstractions: No service for type 'Microsoft.Extensions.Logging.ILogger' has been registered.
This works, but is clunky as all heck as I have to explicitly manage my dependencies, and of course it only logs once the requested dependency is resolved, not when configured:
public class Startup : FunctionsStartup
{
public override void Configure(IFunctionsHostBuilder builder)
{
builder.Services.AddScoped<IMyInterface>(provider =>
{
var logger = provider.GetRequiredService<ILogger<Startup>>();
logger.LogWarning(...);
var dependency1 = provider.GetRequiredService<IFirstDependency>();
var dependency2 = provider.GetRequiredService<ISecondDependency>();
return new MyImplementation(dependency1, dependency2);
}
}
}
Is it also possible to enable us to actually get a logger in the Startup? At some point we need to log more info during the startup and our only possibility is to create a logger manually by bypassing every previously added settings using the builder.
If we try to get a ILogger<Startup>, that raised this following exception:
System.InvalidOperationException: 'Unable to resolve service for type 'Microsoft.Azure.WebJobs.Script.IFileLoggingStatusManager' while attempting to activate 'Microsoft.Azure.WebJobs.Script.Diagnostics.HostFileLoggerProvider'.'
I'm aware that during the Configure not all dependencies are already there and more could be added later on. But this statement doesn't solve what everybody is always asking: have logging in the startup.
This is what we need to do to "fix" this issue:
var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole());
logger = loggerFactory.CreateLogger<Startup>();
Any updates for logging in the Startup class?
I'm struggling with the same.
@brettsam @fabiocav Thoughts on whether we can support logging here like aspnet鈥榮 Configure method?
The problem here is that an ILogger is a registered DI service, so using it to log DI registration is a bit of a "chicken-and-egg" problem. We'd need to pre-construct an ILogger to pass it in to you, then dispose it and re-create it when registration is complete. We may be able to do something like this and have App Insights and file logging configured but we'd need to think through the implications of that (startup could be slower; we'd need to manage the lifetime of that logger, etc).
My recommendation has been to write these logs out explicitly if you need to. For example, you can create your own TelemetryClient and write directly to App Insights if you have an exception. I put a snippet here -- https://github.com/Azure/azure-functions-host/issues/4705#issuecomment-669195112.
For some background --
Logging in ASP.NET's Configure method is different than ours. I'll need to look at it but I believe that that in ASP.NET this call occurs after DI registration has completed. While our call is part of registration. If anyone else has a pointer to the code that wires it up in ASP.NET, that'd help, but I'll investigate. You can see notes in their topic that explain that logging is explicitly not supported when registering services.
From: https://docs.microsoft.com/en-gb/aspnet/core/fundamentals/logging/?view=aspnetcore-3.1#create-logs-in-startup
Writing logs before completion of the DI container setup in the Startup.ConfigureServices method is not supported:
- Logger injection into the Startup constructor is not supported.
- Logger injection into the Startup.ConfigureServices method signature is not supported
The reason for this restriction is that logging depends on DI and on configuration, which in turns depends on DI. The DI container isn't set up until ConfigureServices finishes.
ASP.NET also used to allow you to inject a logger into Startup but no longer do -- here's an explanation of why this used to work (in short, they used to create a container just for Startup): https://docs.microsoft.com/en-gb/aspnet/core/fundamentals/logging/?view=aspnetcore-3.1#configure-a-service-that-depends-on-ilogger
@IanKemp , Let us know if you have any further queries related to this issue.
This issue has been automatically marked as stale because it has been marked as requiring author feedback but has not had any activity for 4 days. It will be closed if no further activity occurs within 3 days of this comment.
Most helpful comment
Is it also possible to enable us to actually get a logger in the Startup? At some point we need to log more info during the startup and our only possibility is to create a logger manually by bypassing every previously added settings using the builder.
If we try to get a
ILogger<Startup>, that raised this following exception:I'm aware that during the
Configurenot all dependencies are already there and more could be added later on. But this statement doesn't solve what everybody is always asking: have logging in the startup.This is what we need to do to "fix" this issue: