System.Diagnostics.Debug 命名空间与其他日志记录解决方案(log4net、MS Enterprise Library 等)

发布于 2024-09-09 16:18:30 字数 647 浏览 8 评论 0原文

我目前正在研究 .net 项目的各种日志记录可能性,但无法在 System.Diagnostics.Debug/Trace 功能和第三方库(如 log4net、MS Enterprise Library、NLog 等)之间做出决定。
目前我发现:

  • System.Diagnostics 相当难以配置和使用,因为您需要显式配置所有侦听器、过滤器、源等。似乎它也缺乏对数据库的批量插入(想想大约写入 100,000 个日志条目,每个日志条目都有自己的插入,这很可怕,不是吗?)。但有些人认为不使用额外的库来完成诸如日志记录之类的“基本”事情是“很酷”的(当然,在某些时候,减少项目依赖的第三方库的数量是有意义的,但我想这次不是)
  • 第 3 方更强大,通常更快,更容易使用,但配置有时也很痛苦,而且这些库通常不太可靠(例如 EntLib 神秘地突然停止日志记录等)
  • Common.Logging 怎么样?是否值得尝试(因为据我所知,它提供了插入各种日志框架并充当应用程序和所需库之间的接口)?


如果有人能为我指出正确的方向或纠正(或添加一些内容)上面给出的比较,我将非常感激!也许如果您鼓励我使用第三方,您可以建议一些特定的第三方(考虑到我们的应用程序很可能不需要任何花哨的东西,如 UDP、滚动文件等 - 只需纯文件、电子邮件、数据库和事件日志)?
提前致谢!

I'm currently investigating various logging possibilities for .net projects and I can't decide between System.Diagnostics.Debug/Trace features and third party libraries like log4net, MS Enterprise Library, NLog, etc.
At the moment I have found out this:

  • System.Diagnostics is rather difficult to configure and to use since you need to explicitly configure all the listeners, filters, sources, etc. It seems that it also lacks the bulk insertion to the DB (think about writing 100'000 log entries each with its own Insert, horrifying, isn't it?). But by some people it is considered to be 'cool' not to use additional libs for such a "rudimentary" thing as Logging (of course, at some point, it makes sense to reduce the amount of 3rd party libraries your project relies on, but not this time, I suppose)
  • 3rd parties are much more powerful, often quicker, much easier to use, but configuration sometimes can be also painful and often these libs are less reliable (like mysterious sudden stop of logging by EntLib, etc.)
  • what about Common.Logging? is it worth trying (since, as I've heard, it offers plugging-in various logging frameworks and act like an interface between the app and the desired lib)?

I would be really grateful if somebody could point me to the right direction or correct (or add something) to my comparison given above! Maybe if you would encourage me to use 3rd parties, you could advise some particular one (taking into account that our applications most probably won't need any fancy stuff like UDP, rolling files, etc.- just plain file, email, DB and eventlog)?

Thanks in advance!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

空‖城人不在 2024-09-16 16:18:30

您可以通过更广泛的谷歌搜索在 StackOverflow 上找到有关 log4net 和 NLog 的大量信息。

您还可以找到很多有关 System.Diagnostics 的信息。关于 System.Diagnostics 需要注意的一件事是,我认为您会在 StackOverflow 上找到很多有关使用 Debug.Write/WriteLine 和 Trace.Write/WriteLine 的参考资料。可以说“更好”的方法是使用 TraceSources。 TraceSources 类似于 log4net 和 NLog 中的记录器。 TraceSources 允许您对日志消息有更高的粒度,从而更容易地打开和关闭一些日志记录(除了按级别之外,还按类别或类别)。与 log4net 和 NLog 相比,TraceSource 确实有一个缺点,即您在代码中创建的每个 TraceSource 都必须在 app.config 中显式配置(如果您希望它实际记录)。

log4net 和 NLog 有一个分层概念,如果您请求的确切记录器未明确配置,则会检查其“祖先”以查看是否配置了任何“祖先”,如果配置了,则请求的记录器“继承”这些设置。祖先只是记录器名称中由“.”分隔的部分。 (因此,如果您请求名为 "ABC.DEF.GHI" 的记录器,祖先将是 "ABC.DEF""ABC")。也可以(必需?)在 app.config 中有一个“根”记录器配置,如果未显式配置且未配置祖先,则所有记录器请求都将回退到该配置。因此,您可以仅配置“根”记录器以在特定级别进行记录,并且代码中的所有记录器都将在该级别进行记录。或者,您可以将“根”记录器配置为“关闭”,然后显式打开一个或多个记录器(或通过配置祖先)。通过这种方式,除了那些已配置的记录器之外,没有记录器会记录日志。

如果您查看此处 ,您会发现 System.Diagnostics TraceSources 周围有一个有趣的包装器,它提供了与 log4net 和 NLog 非常相似的继承功能。

举例说明:

log4net 和 NLog 中记录器的常见使用模式是获取如下记录器:

//log4net
static ILog logger = LogManager.GetLogger(
                     System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 

//NLog
static Logger logger = LogManager.GetCurrentClassLogger();

在这两种情况下,记录器的名称都将是完全限定的类型名称。

在 app.config 文件中,如果需要,您可以仅配置“根”记录器,并且两个记录器都将继承根记录器的设置(级别、附加程序/目标等)。或者,您可以为某些名称空间配置记录器。在该命名空间中定义类型的任何记录器都将继承这些记录器设置。

log4net 和 NLog 已经讲够了,您可能已经知道它们是如何工作的。

上面的链接说明了一个基于 TraceSource 的包装器,它允许类似的配置。因此,如果您愿意,您可以在类中执行类似的操作:

static TraceSource ts = new TraceSource(
               System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

通过上面链接的包装器,您可以在更高级别(类/命名空间层次结构,而不是级别)配置 TraceSource 并继承较低级别记录器中的这些设置。

因此,如果您的完全限定类型名称类似于:ABC.DEF.GHI,那么您可以为 ABC 或 ABC.DEF(命名空间级别)配置 TraceSource,并且类“GHI”将继承这些设置。这确实可以减少您必须执行的配置量。

请注意,您不限于(使用任何这些日志记录平台)使用类的类型或类型名称来获取记录器。您可以定义自己的记录器命名方案,可能基于功能区域(“通信”、“通信.发送”、“通信.接收”等)。同样,您可以以最高粒度(或不是最高粒度)请求记录器/TraceSource,然后以任何有意义的粒度级别进行配置。

因此,您可以像这样在代码中请求记录器:

ILog logger = LogManager.GetLogger("Communication.Receive");
ILog logger = LogManager.GetLogger("Communication.Send");

Logger logger = LogManager.GetLogger("Communication.Receive");
Logger logger = LogManager.GetLogger("Communication.Send");

TraceSource ts = new TraceSource("Communication.Receive");
TraceSource ts = new TraceSource("Communication.Send");

如果您在 app.config 文件中仅配置“通信”,则所有记录器都将继承这些设置(因为它们是“通信”的后代)。如果仅配置“Communication.Receive”,则仅“Communication.Receive”记录器会进行记录。 “通信.发送”记录器将被禁用。如果同时配置“Communication”和“Communication.Receive”,则“Communication.Receive”记录器将在“Communication.Receive”设置中记录,而“Communication.Sender”记录器将在“Communication”设置中记录。在 log4net 和 NLog 中,继承的内容可能不止这些,但我了解的还不够多,无法深入探讨。

使用 System.Diagnostics 时您错过的一件事是非常轻松地格式化日志输出格式的灵活性。有一个第三方库为基于 TraceSource 的日志记录提供了非常好的可配置格式。您可以在此处找到它。

我使用过一些 Common.Logging 。主要用于原型设计,但我可能会在下一个项目中使用它。它工作得很好,并且编写自己的日志记录抽象来插入它相对容易(例如,如果您想编写类似于我上面链接的 TraceSource 抽象)。 Common.Logging 现在缺少的两个重要的东西(尽管他们的网站说它们计划在“下一个”版本中发布)是日志记录上下文(例如 log4net 和 NLog NDC/MDC/GDC 对象以及 System.Diagnostics.CorrelationManger.LogicalOperationStack) )和 Silverlight 兼容性。使用 Common.Logging 时,您仍然可以与代码中的 log4net 或 NLog 上下文对象进行交互,但这违背了它的目的,不是吗?

不知道有没有帮到你!

以下是我对 log4net、NLog 和 TraceSource 的一些要点:

log4net - 非常流行,可能需要一些更新 - 至少是基于 .NET 4.0 构建的,最后一个版本是在几年前,非常灵活。

NLog - 在很多方面与 log4net 非常相似,现在的新版本(NLog 2.0 的测试版刚刚推出)

TraceSource - 没有第三方依赖,不需要你(或某人)的一些努力,不像 log4net 或 NLog 那样强大(关键缺陷 -记录器层次结构、输出格式 - 都可以通过上面的链接轻松寻址),Microsoft 使用 System.Diagnostics 检测其许多组件,以便您可以获得 Microsoft 的日志输出和交错的日志输出。 (通常,在其他日志系统中捕获 System.Diagnostics 很容易,因此可能不是大问题)。

虽然我没有经常使用 log4net 或 NLog,但在两者之间我会倾向于 NLog,主要是因为刚刚发布的新版本(测试版)。我认为 TraceSource 也是一个合理的(如果更基本的)选择,特别是如果您实现记录器层次结构并使用上面链接的 Ukadc.Diagnostics 库。

或者,使用 Common.Logging,您可以避免或延迟为底层日志记录平台做出决定,直到您准备好为止。无论如何,对我来说,Common.Logging 的一个非常有用的方面是,您可以在开发产品时“测试驱动”日志平台,而无需更改任何应用程序代码。您不必等到决定使用特定的日志记录平台才能将日志记录添加到代码中。现在通过 Common.Logging api 添加它。当您接近交付时,您应该缩小日志平台的选择范围。使用该平台进行交付(如果您重新分发日志记录平台),就完成了。如果您愿意,以后仍然可以更改。

You can find plenty of information about log4net and NLog either here on StackOverflow on by more generally googling.

You can also find a lot of info about System.Diagnostics. One thing to note about System.Diagnostics, I think that you will find a lot of references here on StackOverflow about using Debug.Write/WriteLine and Trace.Write/WriteLine. An arguably "better" way is to use TraceSources. TraceSources are analogous to loggers in log4net and NLog. TraceSources allow you to have a higher degree of granularity for your logging messages, making it easier to turn some logging on and some off (by class or category, in addition to by level). TraceSources do have a drawback, as compared to log4net and NLog, in that each TraceSource that you create in your code must be explicitly configured in the app.config (if you want it to actually log).

log4net and NLog have a hierarchical concept where if the exact logger you asked for is not explicitly configured, its "ancestry" is checked to see if any "ancestors" are configured and, if so, the requested logger "inherits" those settings. Ancestors are simply the portions of the logger name delimited by ".". (So, if you request a logger called "ABC.DEF.GHI", the ancestors would be "ABC.DEF", and "ABC"). It is also possible (required?) to have a "root" logger configuration in the app.config that ALL logger requests will fall back to if they are not explicitly configured and no ancestors are configured. So, you could configure only a "root" logger to log at a certain level and all of your loggers in your code would log at that level. Alternatively, you could configure the "root" logger to be "off" and then turn on one or more loggers explicitly (or by configuring an ancestor). In this way, NO loggers would log EXCEPT for those that are configured.

If you look here, you will find an interesting wrapper around System.Diagnostics TraceSources that provides an inheritance capability very similar to log4net and NLog.

To illustrate:

A common usage pattern for loggers in log4net and NLog is to get a logger like this:

//log4net
static ILog logger = LogManager.GetLogger(
                     System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 

//NLog
static Logger logger = LogManager.GetCurrentClassLogger();

In both cases the logger's name will be the fully qualified type name.

In the app.config file, you can, if you desire, configure just the "root" logger and both loggers would inherit the root logger's settings (level, appenders/targets, etc). Alternatively you could configure a logger for some namespace. Any loggers whose type is defined in that namespace will inherit those logger settings.

Enough of log4net and NLog, you probably already know how they work.

The link above illustrates a TraceSource-based wrapper that allows similar configuration. So, if you wanted, you could do something like this in your classes:

static TraceSource ts = new TraceSource(
               System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

With the wrapper linked above, you could configure a TraceSource at a higher level (class/namespace hierarchy-wise, not level) and inherit those settings in lower level loggers.

So, if your full-qualified type name is something like this: ABC.DEF.GHI, then you can configure a TraceSource for ABC or ABC.DEF (namespace level) and class "GHI" would inherit the settings. This could really reduce the amount of configuration that you have to do.

Note that you are not limited (with any of these logging platforms) to using the class's type or type name to get the logger. You could define your own logger naming scheme, possibly based on functional areas ("Communication", "Communication.Send", "Communication.Receive", etc). Again, you could request a logger/TraceSource at the highest degree of granualarity (or not) and then configure at whatever level of granularity makes sense.

So, you could request loggers in your code like this:

ILog logger = LogManager.GetLogger("Communication.Receive");
ILog logger = LogManager.GetLogger("Communication.Send");

Logger logger = LogManager.GetLogger("Communication.Receive");
Logger logger = LogManager.GetLogger("Communication.Send");

TraceSource ts = new TraceSource("Communication.Receive");
TraceSource ts = new TraceSource("Communication.Send");

If you configure only "Communication" in your app.config file, then all loggers will inherit those settings (since they are descendents of "Communication"). If you configure only "Commuincation.Receive", then only the "Communication.Receive" loggers will log. The "Communication.Send" loggers will be disabled. If you configure both "Communication" and "Commuincation.Receive", then the "Communication.Receive" loggers will log at the "Communication.Receive" settings while the "Communication.Sender" loggers will log at the "Communication" settings. In log4net and NLog there can be more to inheritance than that, but I don't know enough to go into it.

One thing that you miss when using System.Diagnostics is the flexibility to format your logging output format very easily. There is a third party library that provides very nice configurable formatting for TraceSource-based logging. You can find it here.

I have used Common.Logging some. Mainly in prototyping, but I might use it in our next project. It works pretty well and it is relatively easy to write your own logging abstraction to plug into it (such as if you wanted to write a TraceSource abstraction similar to what I linked above). Two important things that are missing from Common.Logging right now (although their website says that they are scheduled for the "next" release) are logging contexts (like log4net and NLog NDC/MDC/GDC objects and System.Diagnostics.CorrelationManger.LogicalOperationStack) and Silverlight compatibility. You can still interact with the log4net or NLog context objects in your code while using Common.Logging, but that kind of defeats the purpose of it, doesn't it.

I don't know if I helped or not!

Here are some main points that I would make about log4net, NLog, and TraceSource:

log4net - very popular, probably in need of some updates - at least being built on .NET 4.0, last release a few years ago, very flexible.

NLog - very similar to log4net in many respects, new version now (beta of NLog 2.0 just came out)

TraceSource - no third party dependency, without some effort on your part (or someone's) not as powerful as log4net or NLog (key deficiencies - logger hierarchy, output formatting - both easily addressable via a links above), Microsoft instruments a many of their components with System.Diagnostics so you can get Microsoft's logging output and your logging output interleaved. (Generally, it is easy enough to capture System.Diagnostics in other logging systems so might not be huge issue).

While I have not used either log4net or NLog a lot, between the two I would lean towards NLog, mainly because of the new version that just came out (beta). I think that TraceSource is also a reasonable, if more rudimentary, choice, especially if you implement the logger hierarchy and use the Ukadc.Diagnostics libary linked above.

Or, use Common.Logging and you can avoid or delay making the decision for your underlying logging platform until you are ready. One very useful aspect of Common.Logging, to me anyway, is that you can "test-drive" logging platforms as you are developing your product without every having to change any of your application code. You don't have to wait until you have decided on a specific logging platform to add logging to your code. Add it now via the Common.Logging api. When you get close to delivery, you should have narrowed down your logging platform choice. Deliver with that platform (if you redistribute the logging platform) and you are done. You can still change later on if you want to.

枉心 2024-09-16 16:18:30

我知道这已经很旧了,但是如果保持简单,System.Diagnostics.Trace 就很容易配置。我多年来一直使用简单的文本编写器配置块,直接从 MSDN 文档中复制。

没有人经常提到这一点,但在代码中,您可以使用内置的 Trace.TraceInformation、Trace.TraceWarning 和 Trace.TraceError 轻松隔离 3 个级别的跟踪输出,然后在配置文件选择要输出的级别(请参见下面的配置)。如果您在配置的“EventTypeFilter”中选择信息,您将在输出中获得所有 3 个信息。如果选择“错误”,则输出中只会收到 TraceError 消息。大多数时候,我只是将我的错误保留在错误状态,因此如果我的应用程序中发生了某些情况,我的跟踪文件中已经有该输出。在我的 Catch 块中,我将添加 TraceError 代码以输出有用的信息。
TraceInformation 非常适合输出您所经过的代码中的时间或点等内容,以及沿途转储变量值。 TraceWarning 对于可以处理但不理想的事情很有用 - 例如 Web 服务可能需要很长时间才能完成,或者返回的数据记录数量超过可能导致未来问题的阈值。

有一个小缺点,即无论编译级别如何,所有这些跟踪代码行仍然会执行。如果它们设置为不输出,那应该会大大减少开销。但如果您正在编写高性能代码,您可能需要将这些行包装在条件编译标记中。

<system.diagnostics>
  <sharedListeners>
    <add name="MyTraceListener" traceOutputOptions="DateTime" type="System.Diagnostics.TextWriterTraceListener, System, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" initializeData="MyApplicationName_Trace.log">
     <!--
        Off - Does not allow any events through. 
        Error - Allows Error events through. 
        Warning - Allows Error, and Warning events through. 
        Information - Allows Error, Warning, and Information events through. 
     -->
     <filter type="System.Diagnostics.EventTypeFilter" initializeData="Error" />
    </add>
  </sharedListeners>
  <trace autoflush="true" indentsize="4">
    <listeners>
       <add name="MyTraceListener" />
    </listeners>
  </trace>
</system.diagnostics>

I know this is old, but System.Diagnostics.Trace is pretty easy to configure if you keep it simple. I've been using the simple text writer config block for years, copied right out of the MSDN docs.

No one mentions this very often, but in your code, you can use the built-in Trace.TraceInformation, Trace.TraceWarning, and Trace.TraceError to easily segregate 3 levels of trace output and then in the config file choose which level to output (see config below). If you choose Information in the config's "EventTypeFilter", you get all 3 in your output. If you choose Error, you'll only get TraceError messages in your output. Most of the time, I just leave mine on Error, so if something does happen in my application, I'll already have that output in my trace file. Inside my Catch blocks, I'll add TraceError code to output useful info.
TraceInformation is good for outputting things like timing or spots in code which you've passed through, and dumping variable values along the way. TraceWarning is good for things which are handleable, but not desirable - like maybe a web service is taking a long time to complete, or the number of data records returned exceeds a threshold that might cause future issues.

There is a small downside, in that all these lines of trace code still execute regardless of compile level. If they are set to not output, that should reduce the overhead quite a bit. But if you're writing high-performance code, you may want to wrap those lines in conditional compile markers.

<system.diagnostics>
  <sharedListeners>
    <add name="MyTraceListener" traceOutputOptions="DateTime" type="System.Diagnostics.TextWriterTraceListener, System, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" initializeData="MyApplicationName_Trace.log">
     <!--
        Off - Does not allow any events through. 
        Error - Allows Error events through. 
        Warning - Allows Error, and Warning events through. 
        Information - Allows Error, Warning, and Information events through. 
     -->
     <filter type="System.Diagnostics.EventTypeFilter" initializeData="Error" />
    </add>
  </sharedListeners>
  <trace autoflush="true" indentsize="4">
    <listeners>
       <add name="MyTraceListener" />
    </listeners>
  </trace>
</system.diagnostics>
心病无药医 2024-09-16 16:18:30

从开发人员的角度来看,诸如日志记录之类的问题(类似于 orm)不应该是手写的。有很多优秀的第三方库。当然,有时需要完成一些配置工作,但与手动滚动您自己的解决方案相比,这只是九牛一毛。

我个人偏好是 log4net,但这取决于您的需求。我最好的建议是查看 log4net 或 EntLib Logging Application Block 等解决方案的文档,并决定什么最适合您。

From a developer point of view concerns like logging, similar to orm, shouldn't be hand written. There are plenty of good solid third party libraries. Sure there is sometimes a bit of configuration work to be done but compare that to hand rolling you're own solutions it's a mere drop in the water.

My personal preference is log4net but it depends on your needs. My best advice is have a look at the documentation of solutions such as log4net or EntLib Logging Application Block and make a decision about what is best for you.

青萝楚歌 2024-09-16 16:18:30

日志记录和跟踪是不同的关注点。日志记录与操作反馈有关。跟踪(包括由 Debug 方法提供的跟踪)与开发和测试有关。跟踪代码不应编译到发布程序集中。 Trace 和 Debug 类通过编译器注释 (ConditionalAttribute) 实现此目的。此类代码应该优化以收集大量数据,而不是为了性能。另一方面,操作日志记录需要根据系统管理员/操作团队的要求针对性能和更广泛的存储机制进行优化。

因此,我建议使用 Trace/Debug 进行开发,并使用更强大的日志记录包进行操作。

Logging and tracing are different concerns. Logging pertains to operational feedback. Tracing (including that provided by the Debug methods) pertain to development and testing. Tracing code shouldn't be compiled into the release assemblies. The Trace and Debug classes achieve this with compiler annotations (ConditionalAttribute). Such code should be optimized to collect lots of data, not for performance. On the other hand, operational logging needs to be optimized for performance and for a wider variety of storage mechanisms as required by the sysadmin/operations team.

So I recommend using both Trace/Debug for development as well as more robust logging packages for operations.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文