使用 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的主要内容,如果未能解决你的问题,请参考以下文章

Azure Function 1.x和VS17的Nuget问题

如何在 Azure Function 中使用 Azure Managed Identity 通过触发器访问 Service Bus?

通过 HTTP 调用 Azure Function 150 次导致异常

Azure Keyvault 通过 ARM 添加 Function MSI

配置服务时如何通过依赖注入在 Azure Function V3 中注入或使用 IConfiguration

Azure 应用服务Python fastapi Function在Azure