我现在正在使用ASP.NET Core LoggerFactory
(Serilog扩展名)进行日志记录。我想将日志放在控制器和业务服务方法中。我已经通过构造函数注入ILogger
这样做了
在控制器中:
ILogger<HomeController> _logger
在服务中:
ILogger<ServiceName> _logger
我相信这将在每个请求中实例化,因此对于每个HTTP请求,它将创建多个Logger
实例。比如每个控制器和每个服务类,但它与以前的日志记录方法有点不同,我们以前只创建一个记录器实例,并用它来记录任何地方的内容。
有什么缺点吗?
答案 0 :(得分:3)
这完全没问题。通常情况下,实例化记录器很便宜,所以完全可以像表现那样做。
仍然,考虑(1)使用Serilog所具有的全局日志实例,或者(2)使用在字段声明中初始化的静态字段。同样,不是出于性能原因,而是为了避免使用不那么相关的东西来污染你的构造函数。
UPD 有关实施(1)的更新
基本上,只需确定将记录器初始化代码放入何处即可。在ASP.NET Core中,它将是Main
方法的第一行(Log
是来自Serilog
命名空间的静态类):
Log.Logger = new LoggerConfiguration().WriteTo.LiterateConsole(LogEventLevel.Debug, LogTemplate)
.WriteTo.File(@"C:\logs\elbakogdabot.log", LogEventLevel.Debug, LogTemplate)
.Enrich.FromLogContext()
.CreateLogger();
(为了清楚起见:我从我的一个真实项目中获取了代码,但是你的记录器的实际配置可能会有所不同。)
然后我会在任何地方使用它:
Log.Warning($"got a message for an unknown user: userid=[{userId}]");
这一行可以被抛入任何类,你不必为该类进行任何额外的初始化。
UPD 有关实施(2)的更新
我想在一个典型的企业应用程序中,每次记录某些东西时总是记得将类名放在消息中是不方便的。所以我大部分时间都会去static readonly
场。使用Serilog你可以这样做:
public class XYZService
{
private static readonly Serilog.ILogger log = Log.ForContext<XYZService>();
...
这样,您既不会污染构造函数,也会自动获取所有日志消息中的类名。我以前在ReSharper片段中有这一行,所以我不得不在每个新类中键入lg<TAB>
。