使用 log4net 或 NLog 的 WCF 日志记录/跟踪和活动 ID 传播
Posted
技术标签:
【中文标题】使用 log4net 或 NLog 的 WCF 日志记录/跟踪和活动 ID 传播【英文标题】:WCF logging/tracing and activity id propagation using log4net or NLog 【发布时间】:2011-04-10 09:07:06 【问题描述】:我看到了许多其他有关日志记录的问题。最佳实践。什么日志平台最好。等等。这里有一些关于 SO 的链接,对这个话题进行了很好的讨论:
logging best practices
log4net vs TraceSource
best logging solution for .NET 3.5 project
.NET 3.5 logging
开始编辑:
写完这篇长文章后,我想我想弄清楚的主要问题是 WCF 日志记录/跟踪和活动 ID 传播与 System.Diagnostics 和 TraceSources 的紧密耦合程度。您能否使用第三方日志记录平台(如 log4net 或 NLog)获得“良好”的 WCF 日志记录/跟踪和活动 ID 传播。如果你这样做,你会怎么做?
有关 ServiceTraceViewer 的一些问题,请参阅本文底部,
结束编辑。
这些帖子中没有详细讨论我的问题。我对人们在日志记录和 WCF 方面所做的事情很感兴趣。如果您正在处理一个包含 WCF 服务的项目并且您已登录您的项目,您是否会特别努力使用 WCF 特定的日志记录功能。特别是,您是否尝试合并诸如活动跟踪、活动传播和端到端跟踪之类的东西?如 MSDN 的 this 文章中所述。 Here 是 MSDN 上关于传播活动的另一篇文章。
这些文章很好地解释了如何使用 System.Diagnostics TraceSources 进行活动跟踪、活动传播和端到端跟踪。它显示了如何配置 WCF 以通过 app.config/web.config 文件“打开”这些选项。 WCF 在内部使用 TraceSources 来记录通信结果。
这里是一些示例代码(来自上面链接的第二篇 MSDN 文章),它们或多或少地展示了如何通过 System.Diagnostics 和 TraceSources 实现活动传播:
TraceSource ts = new TraceSource("myUserTraceSource");
Guid oldID = Trace.CorrelationManager.ActivityId;
Guid traceID = Guid.NewGuid();
ts.TraceTransfer(0, "transfer", traceID);
Trace.CorrelationManager.ActivityId = traceID; // Trace is static
ts.TraceEvent(TraceEventType.Start, 0, "Add request");
double value1 = 100.00D;
double value2 = 15.99D;
ts.TraceInformation("Client sends message to Add " + value1 + ", " + value2);
double result = client.Add(value1, value2);
ts.TraceInformation("Client receives Add response '" + result + "'");
ts.TraceTransfer(0, "transfer", oldID);
ts.TraceEvent(TraceEventType.Stop, 0, "Add request");
Trace.CorrelationManager.ActivityId = oldID;
您可以通过以下方式从服务中判断 WCF 是否已传播活动:
// Check if an activity was set in scope by WCF, i.e., if it was
// propagated from the client. If not, i.e., ambient activity is
// equal to Guid.Empty, create a new one.
if(Trace.CorrelationManager.ActivityId == Guid.Empty)
Guid newGuid = Guid.NewGuid();
Trace.CorrelationManager.ActivityId = newGuid;
// Emit your Start trace.
ts.TraceEvent(TraceEventType.Start, 0, "Add Activity");
// Emit the processing traces for that request.
serviceTs.TraceInformation("Service receives Add "
+ n1 + ", " + n2);
// double result = n1 + n2;
serviceTs.TraceInformation("Service sends Add result" + result);
// Emit the Stop trace and exit the method scope.
ts.TraceEvent(TraceEventType.Stop, 0, "Add Activity");
// return result;
从我看到的所有示例中,活动传播是通过配置(通常通过 app.config)System.Service 模型 TraceSource 并将其propagateActivity 属性设置为“true”来实现的。活动实际上是通过在 Trace.CorrelationManager.ActivityId 上设置活动 id (guid) 来传播的。如果您使用 log4net 或 NLog,是否可以有效地使用 WCF 日志记录和活动传播?
我的项目将大量使用 WCF。我们目前正在尝试解决我们的日志记录解决方案。我认为我非常了解 WCF 日志记录和活动传播如何与 System.Diagnostics 和 TraceSources 一起使用。我想更好地了解如何/是否可以使用 log4net 和 NLog 等日志平台实现类似的功能。
他们是否提供一些“本地”支持?他们似乎更有可能提供一些基础设施,以便可以“手动”实现活动传播。也许是这样的:
//Inside client code:
ILog logger = LogManager.GetLogger("client");
Guid oldActivity = Trace.CorrelationManager.ActivityId;
if (oldActivity == Guid.Empty)
Trace.CorrelationManager.ActivityId = Guid.NewGuid();
using (LogManager.NDC.Push(Trace.CorrelationManager.ActivityId))
log.Info("Before calling WCF Service");
wcfService.Method();
log.Info("After calling WCF Service");
Trace.CorrelationManager.ActivityId = oldActivity;
如果 log4net/NLog 日志记录格式配置为记录 NDC 堆栈的顶部,则客户端记录的每条消息(当活动在范围内时)都将使用活动 ID“标记”。假设 WCF 服务的实现方式类似,那么在服务调用期间记录的所有消息也将被记录(尽管可能在单独的文件中)并使用相同的活动 id 进行标记。因此,可以将“服务”日志文件中的日志消息与“客户端”日志中的相应消息相关联。
所以,如果您使用 WCF 并且有日志记录,这里有一些问题:
-
您是否使用活动传播?
您是否使用 TraceSources 进行日志记录?
您是否使用其他一些日志记录平台(例如 log4net、NLog)?
如果您使用其他日志记录平台,您如何进行活动传播?
您是否混合使用第三方日志记录(log4net/NLog - 用于大多数日志记录)和
System.Diagnostics.TraceSource
(用于 WCF 服务边界日志记录)?
ServiceTraceViewer 呢?你用它吗?我见过的大多数示例都显示了 System.Diagnostics 通过 TraceSources 和 XmlTraceListener 生成的输出。它可以消耗来自 log4net、NLog 等的输出吗?它是否与基于 TraceSource 的日志记录“最佳”?如果是这样,那么在 WCF 服务边界(捕获一些应用程序上下文以及 WCF 通信信息)仅具有一点基于 TraceSource 的日志记录以在 ServiceTraceViewer 中查看是否“足够好”?作为我正在进行的 WCF 学习过程的一部分,我简要地使用了 ServiceTraceViewer。
如果您到此为止,感谢您的阅读。也许我过度考虑了日志记录、WCF 活动传播以及在 ServiceTraceViewer 中查看日志的能力的整个集成。在选择日志平台和/或日志策略时,这似乎是一个重要的考虑因素,但我对这些日志平台或 WCF 没有足够的经验来确定。
【问题讨论】:
你找到任何关于使用与 NLog 相关的答案了吗? 好问题。关于这个主题有很多文档,但显然信息很少:P 【参考方案1】:只是我的五分钱,我使用我自己编写/维护的基于 AOP 的日志记录,但它就像其他一些日志记录框架......我的基于装饰器,但我可以将它扩展到调用堆栈上的任何东西.
所以你有这样的东西:
using (LogManager.NDC.Push(Trace.CorrelationManager.ActivityId))
log.Info("Before calling WCF Service");
wcfService.Method();
log.Info("After calling WCF Service");
Trace.CorrelationManager.ActivityId = oldActivity;
如果您在服务器上有类似的东西,那么我的在这方面工作,但我的方法不适用于内部日志记录。我的设置是这样做的:
[LogMethod( CaptureDirection = LoggingDirection.InOut /*Optional*/, CaptureVariables = Yes /*Optional*/ )]
public ClassName MyMethodName(params)
//magic logging happens here on method entry
DoSomething();
//if you need logging here I can't do anything with my AOP system
DoSomethingElse();
//magic logging happens here on method exit
此外,您是否希望在客户端和服务器之间建立相关的日志记录?你如何谈判这两个?如何确保一个与另一个相关?
【讨论】:
是的,我们想关联客户端和服务器之间的日志记录。假设客户端实际上是 .NET 4.0 客户端(不是 Silverlight,因为 Silverlight 不支持 Trace.CorrelationManager.*)。客户端可以设置 Trace.Correlationmanager.ActivityId =article on CodeProject 描述了如何 通过创建自定义渲染器和侦听器使用 NLog 跟踪活动,并指定登录配置的内容。
Nlog 扩展的源代码可以在http://lowleveldesign.codeplex.com/releases/view/96938找到
免责声明:我没有尝试过该解决方案,只是打算使用它。
【讨论】:
以上是关于使用 log4net 或 NLog 的 WCF 日志记录/跟踪和活动 ID 传播的主要内容,如果未能解决你的问题,请参考以下文章