ASP.NET Core 5 API属性中的常规日志记录



我正在用ASP.NET Core 5实现一个API,并且我已经使用Attribute添加了响应缓存。现在,为了调试和跟踪目的,我想将日志记录添加到该属性中。

所以我的代码看起来像这个

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class CachedAttribute : Attribute, IAsyncActionFilter
{
private readonly int _timeToLiveSeconds;
public CachedAttribute(int timeToLiveSeconds)
{
_timeToLiveSeconds = timeToLiveSeconds;
}
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
//Get cache setting, check if enabled
//get cache & logger services
var cacheService = context.HttpContext.RequestServices.GetRequiredService<IResponseCacheService>();
var loggerService = context.HttpContext.RequestServices.GetRequiredService<ILogger<ProductController>>();
loggerService.LogDebug("Debug message");
//Do work here
loggerService.LogTrace("tracing message");
//Do more work here
}
}

这很好用,没问题。

现在我希望在多个控制器中重用这个属性。所以我需要把这条线改成更通用的

var loggerService = context.HttpContext.RequestServices.GetRequiredService<ILogger<ProductController>>();

所以我试着从ProductController改为ControllerBase

var loggerService = context.HttpContext.RequestServices.GetRequiredService<ILogger<ControllerBase>>();

但这行不通!我没有收到任何错误,但也没有生成日志记录。

那么,如何使这种日志记录更通用,以便与不同的控制器一起工作呢?

如果有什么不同的话,我正在使用SeriLog。

根据Ihusan Ahmed的评论,我能够按照以下解决问题

var loggerFactory = context.HttpContext.RequestServices.GetRequiredService<ILoggerFactory>();
var loggerService = loggerFactory.CreateLogger(context.Controller.GetType());

然后将其用作正常

loggerService.LogDebug("Debug message");
//Do work here
loggerService.LogTrace("tracing message");

不是一个具体的解决方案,而是一个粗略的草图:

问题是,您需要知道应用了属性的类型才能使用正确的泛型参数。

不完全确定,但我认为你应该从context.Controller.GetType()获得这些信息。

这样,就可以使用MakeGenericType()通过反射来形成方法调用。返回值在第一步object中,但您应该能够将其强制转换为ILogger,并根据需要使用方法。

ILogger<T>中的T只是对记录器实例生成的日志消息进行分类的一种方法。它没有其他意义,也没有什么可以阻止您在类Bar中使用ILogger<Foo>

在您的案例中,您已经在CachedAttribute中使用了ILogger<ProductController>。这意味着在属性内生成的日志消息现在被标记为属于ProductController。根据您的设置,这可能有意义,也可能没有意义。

通常,您会看到记录器总是被检索到属于您正在使用它的类。因此,在您的情况下,检索ILogger<CachedAttribute>可能更有意义。这样,就可以很容易地识别缓存机制产生的日志消息,而不是控制器或其他东西产生的消息。


现在,回到您所观察到的问题。如上所述,没有什么可以阻止您在属性中使用ILogger<ControllerBase>。那么这里发生了什么?这里的问题是ControllerBase属于名称空间Microsoft.AspNetCore.Mvc

ASP.NET Core日志记录系统中的类别有一个有趣的地方:它允许按类别全名(包括名称空间(过滤日志消息。因此,当您使用ILogger<ProductController>记录消息时,分配的类别可能是MyApp.Controllers.ProductController,但对于ILogger<ControllerBase>,类别现在是Microsoft.AspNetCore.Mvc.ControllerBase。ASP.NET Core中的默认配置将"Microsoft"类别配置为仅显示警告:

{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
}
}

因此,如果您使用的是ILogger<ControllerBase>记录器,那么您现在处于"Microsoft"日志记录类别领域,这意味着日志记录配置可能会影响您在输出中看到的内容。但是,如果您使用ILogger<ProductController>ILogger<CachedAttribute>,那么您就在"MyApp"内部,因此将应用默认的日志级别过滤器。

最新更新