【问题标题】:Unable to use ILogger instance provided via DI无法使用通过 DI 提供的 ILogger 实例
【发布时间】:2019-11-24 16:22:08
【问题描述】:

基本上,我有两种不同的方式获取 ILogger 实例。一个工作得很好,另一个不行。

我有一个这样的 Azure 函数:

class AzureFunctionClass {

     private readonly ISomeClass _someclass;

     public AzureFunctionClass(ISomeClass someClass){
          _someclass = someClass;
     }

     public Task<IActionResult> AzureFunction(ILogger log){
             log.LogInformation("This works, I see this message when run");
             _someclass.ExecuteMethod();
     }
}

另一个类,不包含 Azure 函数,如下所示:

class SomeClass : ISomeClass {

     private readonly ILogger<SomeClass> _log;

     public SomeClass(ILogger log){
           _log = log;
     }

     public void ExecuteMethod(){
           _log.LogInformation("This doesn't crash so _log isn't null, but it 
                                doesn't write anything");
     }
}

Startup.cs:

class Startup : IWebJobsStartup {

     public void Configure(IWebJobsBuilder builder){
          builder.Services.AddScoped<ISomeClass, SomeClass>();
          builder.Services.AddTransient(typeof(ILogger<>), typeof(Logger<>));
          builder.Services.AddScoped<ILogger<SomeClass>, Logger<SomeClass>>();
     }
}

不,恐怕 AzureFunctionClass 不能只将其 ILogger 实例作为参数传递给 ISomeClass。 我还到处寻找日志文件,例如在 Azure 存储资源管理器中,看看它是否可能只是没有写入 Azure 门户控制台。我找到的每个日志文件都有上述工作案例的日志,而没有一个有其他案例的日志。

【问题讨论】:

    标签: c# dependency-injection .net-core azure-functions


    【解决方案1】:

    当前显示的语法与此注入的依赖项存在一些问题。

    class SomeClass : ISomeClass {
        private readonly ILogger _log;
    
        public SomeClass(ILogger<SomeClass> log) {
            _log = log;
        }
    
        public void ExecuteMethod() {
            _log.LogInformation("This doesn't crash so _log isn't null, but it doesn't write anything");
        }
    }
    

    第二个问题是默认情况下会添加日志记录,而您手动添加的设置会覆盖默认设置。

    class Startup : FunctionsStartup {
    
        public override void Configure(IFunctionsHostBuilder builder) {
            builder.Services.AddScoped<AzureFunctionClass>();
            builder.Services.AddScoped<ISomeClass, SomeClass>();
    
            //...
         }
    }
    

    从技术上讲,您需要添加的只是您的函数类及其依赖项。

    参考Use dependency injection in .NET Azure Functions

    【讨论】:

    • 嗯,做了这些更改,恐怕SomeClass 仍然没有登录。
    【解决方案2】:

    目前,函数运行时存在一个错误,由于该错误它会过滤掉任何使用不以字符串 Function. 开头的类别创建的日志。

    查看这些 GitHub 问题:

    在函数方法中注入的记录器由函数运行时完成,它创建类别设置为Function.&lt;FunctionName&gt;.User的记录器。所以这会被正确记录。但是注入构造函数的记录器是由 asp.net 核心 DI 框架完成的,它将记录器的类别名称设置为Type.FullName(在您的示例中输入为SomeClass)。因为它的全名不是以Function 开头的,所以用这个类别记录的行被过滤掉了。

    有两种方法可以解决这个问题。

    选项 1:更改 host.json 以不过滤来自您的命名空间的日志

    {
      "version": "2.0",
      "logging": {
        "logLevel": {
          "<YourNameSpace>": "Information"
        }
      }
    }
    

    选项 2:在您的 ctor 中注入 ILoggerFactory,并创建一个类别不会被过滤的记录器

    class SomeClass : ISomeClass {
    
         private readonly ILogger _log;
    
         public SomeClass(ILoggerFactory loggerFactory){  // Note that we inject ILoggerFactory
               this._log = loggerFactory.CreateLogger(
                LogCategories.CreateFunctionUserCategory(this.GetType().FullName));  // Must use CreateFunctionUserCategory to create the log category name otherwise the log gets filtered out.
         }
    
         public void ExecuteMethod(){
               _log.LogInformation("This should get logged correctly.");
         }
    }
    

    请注意,ILogger 已由函数运行时注册到 DI 框架中(如 NKosi 的回答中所述),因此可以删除这些行。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-07-26
      • 2017-08-15
      • 1970-01-01
      • 1970-01-01
      • 2020-01-17
      • 2018-10-25
      • 1970-01-01
      相关资源
      最近更新 更多