无法使用通过DI提供的ILogger实例

时间:2019-07-16 00:32:14

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

从本质上讲,有两种方法可以获取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 Portal控制台。我发现的每个日志文件都有上述工作情况的日志,而没有其他情况的日志。

2 个答案:

答案 0 :(得分:0)

显示的当前语法对此注入的依赖项有一些问题。

SELECT `id`, CONCAT(id, "-", `name`, "-", phone) as text
FROM `sma_companies`
WHERE `id` LIKE '3%' AND `group_name` = 'customer'
ORDER BY `id`;

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

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

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

引用Use dependency injection in .NET Azure Functions

答案 1 :(得分:0)

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

查看以下GitHub问题:

在函数方法中注入的记录器由函数运行时完成,该运行时将创建类别设置为Function.<FunctionName>.User的记录器。因此,这将正确记录。但是注入到构造函数中的记录器是由asp.net核心DI框架完成的,该框架将记录器的类别名称设置为Type.FullName(在您的示例情况下,类型为SomeClass)。因为它的全名不是以Function开头,所以此类别记录的行将被过滤掉。

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

选项1:更改host.json以不过滤名称空间中的日志

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

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

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的回答所述),因此可以删除这些行。