Reputation: 8019
ILogger
can be injected to function parameter, like Token
method below.
However, the error below occurred when it is injected to constructor parameter log
.
[07/03/2019 17:15:17] Executed 'Token' (Failed, Id=4e22b21f-97f0-4ab4-8f51-8651b 09aedc8) [07/03/2019 17:15:17] Microsoft.Extensions.DependencyInjection.Abstractions: Una ble to resolve service for type 'Microsoft.Extensions.Logging.ILogger' while attempting to activate 'Functions'.
ILogger
can be injected to Token
function parameter below. But the error above occurred when it is injected to constructor parameter log
.
public class Functions
{
private HttpClient _httpClient;
private IAppSettings _appSettings;
private ILogger _log;
public Functions(HttpClient httpClient, IAppSettings appSettings //working for these two
, ILogger log //not working, errors
)
{
_log = log;
}
[FunctionName("Token")]
public async Task<IActionResult> Token(
[HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "Token")]
HttpRequest httpRequest,
ILogger log)
{
}
}
Dependence injection below
[assembly: WebJobsStartup(typeof(Startup))]
namespace MyApp
{
public class Startup : IWebJobsStartup
{
public void Configure(IWebJobsBuilder builder)
{
builder.Services.AddHttpClient();
builder.Services.AddTransient<IAppSettings, AppSettings>();
//builder.Services.AddLogging(); //not working
//builder.Services.AddSingleton<ILogger>() //not working
}
}
Visual studio 2017
Upvotes: 10
Views: 8205
Reputation: 452
If you want to get away with not using LoggerFactory then you need to change "ILogger log" to "ILogger log".
public class Functions
{
private HttpClient _httpClient;
private IAppSettings _appSettings;
private ILogger _log;
public Functions(HttpClient httpClient, IAppSettings appSettings
, ILogger<Program> log
)
{
_log = log;
}
}
Upvotes: 0
Reputation: 190
Calling LogCategories.CreateFunctionUserCategory
fixed my problem. Complete example:
Azure Functions Core Tools (2.7.1158 Commit hash: f2d2a2816e038165826c7409c6d10c0527e8955b)
Function Runtime Version: 2.0.12438.0
Startup.cs
No need to add
builder.Services.AddLogging();
it's imported automatically in the container.
using Microsoft.Azure.Functions.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;
[assembly: FunctionsStartup(typeof(MyFunctionsNamespace.Startup))]
namespace MyFunctionsNamespace
{
public class Startup : FunctionsStartup
{
public override void Configure(IFunctionsHostBuilder builder)
{
builder.Services.AddTransient<IMyService, MyService>();
}
}
}
MyFunkyFunction.cs
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Extensions.Logging;
namespace MyFunctionsNamespace
{
public class MyFunkyFunction
{
private readonly IMyService _myService;
public MyFunkyFunction(IMyService myService)
{
_myService = myService;
}
[FunctionName("FunkyFunc")]
public async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]
HttpRequest req
, ILogger log
)
{
log.LogInformation("C# HTTP trigger function processed a request.");
_myService.Do();
return new OkObjectResult("Hello");
}
}
}
IMyService.cs
Anything in
LogCategories.CreateFunctionUserCategory
will do the job. It seems to be some WebJob legacy requirement.
using Microsoft.Azure.WebJobs.Logging;
using Microsoft.Extensions.Logging;
namespace MyFunctionsNamespace
{
public interface IMyService
{
void Do();
}
public class MyService : IMyService
{
private readonly ILogger _log;
public MyService(ILoggerFactory loggerFactory)
{
// Important: Call CreateFunctionUserCategory, otherwise log entries might be filtered out
// I guess it comes from Microsoft.Azure.WebJobs.Logging
_log = loggerFactory.CreateLogger(LogCategories.CreateFunctionUserCategory("Common"));
}
public void Do()
{
_log.Log(LogLevel.Information, "Hello from MyService");
}
}
}
Upvotes: 11
Reputation: 8402
I had this problem as well. I was able to fix it by calling AddLogging()
:
[assembly: WebJobsStartup(typeof(Startup))]
namespace MyApp
{
public class Startup : IWebJobsStartup
{
public void Configure(IWebJobsBuilder builder)
{
builder.Services.AddHttpClient();
builder.Services.AddTransient<IAppSettings, AppSettings>();
builder.Services.AddLogging();
}
}
And then, in the Azure Function, I had to do pass a ILoggerFactory
instead of an ILogger
and get the ILogger
instance from the loggerFactory
:
public class Functions
{
private HttpClient _httpClient;
private IAppSettings _appSettings;
private ILogger _log;
public Functions(HttpClient httpClient, IAppSettings appSettings, ILoggerFactory loggerFactory)
{
_log = loggerFactory.CreateLogger<Functions>();
}
[FunctionName("Token")]
public async Task<IActionResult> Token(
[HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "Token")]
HttpRequest httpRequest)
{
// No need to keep getting the ILogger from the Run method anymore :)
}
}
Upvotes: 8