ILogger通过构造函数为Azure函数2.x的Http触发函数注入

时间:2019-03-07 17:27:40

标签: c# azure azure-functions

可以将

ILogger注入到函数参数中,例如下面的Token方法。

但是,当将以下错误注入到构造函数参数log中时。

  

[07/03/2019 17:15:17]已执行“令牌”(失败,   id = 4e22b21f-97f0-4ab4-8f51-8651b 09aedc8)[07/03/2019 17:15:17]   Microsoft.Extensions.DependencyInjection.Abstractions:无法   解决类型为“ Microsoft.Extensions.Logging.ILogger”的服务,同时   尝试激活“功能”。

ILogger可以注入下面的Token函数参数中。但是上述错误是在将其注入构造函数参数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)
    {

    }
}

下面的依赖注入

[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

3 个答案:

答案 0 :(得分:3)

我有同样的问题。我终于发现,将这个“ logging”元素添加到host.json文件中可以为我解决。

{
    "version": "2.0",
    "logging": {
        "logLevel": {
            "default": "Trace"
        }
    }
}

现在,标准的.NET核心构造函数注入的logger方法可以正常工作。

答案 1 :(得分:0)

我也有这个问题。我可以通过致电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();
        }
}

然后,在Azure功能中,我必须传递ILoggerFactory而不是ILogger,并从ILogger获取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 :)
    }
}

答案 2 :(得分:0)

致电LogCategories.CreateFunctionUserCategory解决了我的问题。完整示例:

Azure Functions Core Tools (2.7.1158 Commit hash: f2d2a2816e038165826c7409c6d10c0527e8955b)
Function Runtime Version: 2.0.12438.0

Startup.cs

  

无需添加builder.Services.AddLogging();,它会自动导入容器中。

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

  

LogCategories.CreateFunctionUserCategory中的任何事情都可以完成。这似乎是一些WebJob的遗留要求。

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");
        }
    }
}