使用log4net或NLog进行WCF日志记录/跟踪和活动ID传播

时间:2010-09-09 17:05:18

标签: wcf logging log4net nlog system.diagnostics

我在日志记录方面看到了许多其他问题。最佳做法。什么日志记录平台最好。等等。这里有一些关于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并且你有日志记录,这里有一些问题:

  1. 您是否使用活动传播?
  2. 您是否使用TraceSources进行日志记录?
  3. 您是否使用其他一些日志记录平台(例如log4net,NLog)?
  4. 如果您使用其他日志记录平台,那么如何进行活动传播?
  5. 您是否混合使用第三方日志记录(log4net / NLog - 用于大多数日志记录)和System.Diagnostics.TraceSource(用于WCF服务边界日志记录)?
  6. ServiceTraceViewer怎么样?你用它吗?我见过的大多数示例都显示了System.Diagnostics通过TraceSources和XmlTraceListener生成的输出。它可以消耗log4net,NLog等的输出吗?基于TraceSource的日志记录是否“最佳”?如果是这样,在WCF服务边界(捕获一些应用程序上下文以及WCF通信信息)只需要一点基于TraceSource的日志记录,以便在ServiceTraceViewer中查看,这是否“足够好”?我简要地使用了ServiceTraceViewer,这是我正在进行的WCF学习过程的一部分。

    如果你走到这一步,感谢阅读。也许我正在过度思考日志记录,WCF活动传播的整体集成以及在ServiceTraceViewer中查看日志的能力。在选择日志记录平台和/或日志记录策略时,这似乎是一个重要的考虑因素,但我对这些日志记录平台或WCF没有足够的经验来确定。

2 个答案:

答案 0 :(得分:3)

只是我的镍币价值,我使用基于AOP的日志记录,我自己编写/维护,但它就像其他一些日志框架...我的是基于装饰器,但我可以将它扩展到任何进入callstack的东西

所以你有这样的地方:

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
}

此外,您是否希望在客户端和服务器之间进行相关日志记录?你如何谈判这两个?你怎么能确保一个人与另一个人有关系?

答案 1 :(得分:0)

article on CodeProject描述了如何操作 通过创建自定义渲染器和侦听器来跟踪NLog的活动,并指定登录配置的内容。

可以在http://lowleveldesign.codeplex.com/releases/view/96938

找到Nlog扩展的源代码

免责声明:我没有尝试过该解决方案,只计划使用它。