Why is the ILogger injected in my Azure Function v2 missing the APPINSIGHTS_INSTRUMENTATIONKEY?
I got confused with different variants of setup (ILogger
vs ILoggerFactory
vs other stuff).
In my Startup
class, it is correct to call AddLogging
(with a minimum level or not, as long as it is defined somewhere here or in the host.json
file).
using InjectionHttpClientFactory;using Microsoft.Azure.WebJobs;using Microsoft.Azure.WebJobs.Hosting;using Microsoft.Extensions.DependencyInjection;using Microsoft.Extensions.Logging;[assembly: WebJobsStartup(typeof(Startup))]namespace InjectionHttpClientFactory{ public sealed class Startup : IWebJobsStartup { public void Configure(IWebJobsBuilder webJobsBuilder) { webJobsBuilder.Services.AddLogging(); } }}
In the Azure Function, I have an error if I specify HttpClient
as a parameter:
Microsoft.Extensions.DependencyInjection.Abstractions: Unable to resolve service for type 'Microsoft.Extensions.Logging.ILogger' while attempting to activate 'XXX'
However, it does work if I specify an ILoggerFactory
. The instrumentation key property that was empty somehow has no impact.
I have updated the host.json
file to include the logging information with the minimum severity level as well as configuration information for Application Insights:
{ "version": "2.0", "logging": { "fileLoggingMode": "debugOnly", "logLevel": { "default": "Trace" }, "applicationInsights": { "samplingSettings": { "isEnabled": true, "maxTelemetryItemsPerSecond" : 5 } } }}
Update
As mentioned in comments, Microsoft released an update which introduces the FunctionsStartup
class which should be the preferred way of doing this.
[assembly: FunctionsStartup(typeof(MyNamespace.Startup))]namespace MyNamespace{ public class Startup : FunctionsStartup { public override void Configure(IFunctionsHostBuilder builder) { builder.Services.AddHttpClient(); builder.Services.AddSingleton((s) => { return new CosmosClient(Environment.GetEnvironmentVariable("COSMOSDB_CONNECTIONSTRING")); }); builder.Services.AddSingleton<ILoggerProvider, MyLoggerProvider>(); } }}
services.AddSingleton(context => { var factory = context.GetRequiredService<ILoggerFactory>(); var loggingConfiguration = <get your app insights's instrumentation key from your configuration provider>; var logger = new LoggerConfiguration() .WriteTo .ApplicationInsightsEvents(loggingConfiguration.ApplicationInsightsKey) .CreateLogger(); return factory.AddSerilog(logger).CreateLogger("MyLogger"); });
Logger needs to be configured prior to ingest telemetry with your app-insights. Design Usage(Serilog) pattern may be different as this is just a stub to explain.
Logger is passed as a function argument:
public async Task<IActionResult> Run( [HttpTrigger(AuthorizationLevel.Function, Verbs.Get, Route = "v1/accounts/")] HttpRequest httpRequest, ILogger log){ // ...}