[英]Logging in a C# library
关于在图书馆内登录的最佳做法是什么?
我正在创建一个供用户使用的 C# 库,有时我想记录错误或警告。 使用 log4net 并登录文件是一个好习惯吗?
我在我自己的库中使用 log4net,但如果我的库应该被其他人使用(即我的组织之外),我不会这样做。 在这种情况下,我将使用一个接口进行日志记录,在单独的程序集中提供基于 log4net 的默认实现,并使用一种或另一种方式允许库的用户注入他们自己的实现。
话虽如此:我真的很喜欢 log4net,不会使用其他任何东西,但我认为强迫他人必须使用您选择的日志记录框架是错误的。
编辑:
这里的所有答案似乎都过时了。 我会做一个新的:
我的库要求使用可选的Microsoft.Extensions.Logging.ILogger
对象来写入日志消息。 如果没有ILogger
对象,它就不会记录任何内容。
消费者应用程序可以使用 NLog、Log4Net 或 SeriLog 创建这个ILogger
对象。我的库可以在没有日志框架锁定的 ASP.NET 核心应用程序中使用。
使用其他 lggging 框架创建 Microsoft ILogger 的示例
private static readonly ILoggerFactory loggerFactory = LoggerFactory.Create(builder =>
{
builder.AddNLog(); //=>install NLog.Extensions.Logging nuget
//or builder.AddSerilog(); => install Serilog.Extensions.Logging nuget
//or builder.AddLog4Net() //=> Microsoft.Extensions.Logging.Log4Net.AspNetCore
});
private static readonly ILogger<Program> log = loggerFactory.CreateLogger<Program>();
//configure nlog/serilog/log4net normally then
log.LogInformation("Hello");
在 Log4Net 的情况下,您还可以
ILoggerFactory loggerFactory = new LoggerFactory();
loggerFactory.AddLog4Net(); //load log4net.config by default
我会警惕在通用类库中引入对 3rd 方库(例如 log4net)的依赖:我更愿意将其留给调用者来决定如何进行日志记录。 如果库的用户已经在使用不同的日志框架怎么办?
一些替代方案是:
对于错误,抛出一个Exception
或允许一个Exception
传播,让调用者处理它并做任何日志记录。
对于警告(例如,您在库中处理的异常),您可以考虑引发一个事件,如果他想记录它,调用者可以处理该事件。 例如,您可以引发一个Error
事件,该事件采用带有错误详细信息的System.IO.ErrorEventArgs
(或类似的自定义EventArgs
)。
如果您觉得库需要更多检测,您可以在库中的战略点引发更多事件,调用者可以处理这些事件来进行日志记录。
或者,您可以在您的类库( ILogging
或类似的)中定义一个接口,如果他们想要记录,调用者必须实现该接口。 让调用者将此接口的实例传递给类构造函数以启用日志记录。
您可以执行类似于登录AWS SDK for .NET 的操作,即支持多个日志记录框架,但使用反射加载第 3 方框架以避免创建依赖项。 我个人不喜欢这个,但这是一种有效的方法,特别是如果您的库足够大以证明详细的检测是合理的。
log4net 只是一个 3rd 方库,在使用 C# 时必须将其用作日志库并不是最佳实践。 我的建议是始终将日志保存到某个地方(最常见的是文本文件)。 但是,还有事件日志(需要一些额外的设置)。
我倾向于使用NLog ,我发现它非常易于使用且易于设置。 至于在您的类库中登录,您认为哪种方法最适合您的应用程序。 有些人会创造1个日志和它向下传递到类,其他人会创造每一个单独的记录loggable
类。 我倾向于为每个类创建一个静态记录器,它工作正常。
练习虎钳的一个好方法是引入一个 Logging 门面,这样你就不用关心你使用的记录器,你有一个一致的记录器通用接口。
例如,你可以试试这个,或者干脆自己写。
在我看来,将日志记录在您自己的小适配器中永远不会有什么坏处,例如,以后可以轻松地从生产中剥离日志记录。 我为此创建了一个小的日志包装器,它的 API 如下所示:
Log.d("I'm a log message");
Log.w("I'm a warning with parmas", "param 1", 2, "..");
Log.e("I'm an error");
Log.e(new Exception("I'm an exception"));
AssertV2.IsTrue(1 + 1 == 3, "This assertion will fail");
有关更多示例,请参阅https://github.com/cs-util-com/cscore#logging
您可以登录到控制台、文件、Unity,并且可以轻松添加更复杂的日志记录目标,例如 Serilog
如果您有任何建议或其他反馈,请告诉我,我想让它尽可能小,但想了解它尚未涵盖的用例💚
这取决于你想做什么。
您是否想为纯技术内容提供一个日志记录机制,您可以使用不同的详细程度(用于支持活动)打开/关闭? 或者您想记录更多旨在供图书馆用户阅读的业务相关内容?
您应该先回答这些问题,然后才能决定要记录的内容、存储位置以及如何格式化...
无论如何,log4net 是用于所有这些目的的良好、成熟和稳定的日志记录框架。 并且记录到滚动文件是常见的做法(但到目前为止不是唯一的选择......)。
问候托马斯
您的用户使用什么进行日志记录?
这是您需要回答以确定正确框架的问题。
从我的观点来看,Log4net 功能强大且相对容易。 如果没有指定其他内容,您也可以使用它来登录流编写器。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.