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

Posted

技术标签:

【中文标题】使用 Azure Function 2.x 通过构造函数为 Http 触发函数注入 ILogger【英文标题】:ILogger injected via constructor for Http trigger functions with Azure Function 2.x 【发布时间】:2019-07-29 16:29:51 【问题描述】:

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
        

视觉工作室 2017

【问题讨论】:

【参考方案1】:

致电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");
        
    

【讨论】:

LogCategories.CreateFunctionUserCategory() 成功了【参考方案2】:

我也有这个问题。我可以通过调用 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 并从 loggerFactory 获取 ILogger 实例:

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 :)
    

【讨论】:

这对我有用——但前提是我用loggerFactory.CreateLogger("Function.Token.User"); 实例化ILogger 您无权访问 CreateLogger() 的通用版本? 我想将调试级别的应用程序日志事件记录到每个函数的文件中。磁盘上的位置是/LogFiles/Application/Functions/Function/TokenFunction/2019-03-11T00-00-00Z-012345abcd.log。仅当 categoryName 以 Function. 开头并附加后缀 .User 时,Azure Functions 框架才会在此处记录。因此,如果我有 [FunctionName("Token")] 和 categoryName Function.Token.User 的记录器,我可以通过日志记录配置进行过滤。 "logging": "logLevel": "fileLoggingMode": "always", "Function": "Warning", "Function.Token.User": "Debug" 通用的 CreateLogger 会创建一个 categoryName Namespace.ClassName

以上是关于使用 Azure Function 2.x 通过构造函数为 Http 触发函数注入 ILogger的主要内容,如果未能解决你的问题,请参考以下文章