【发布时间】:2013-07-11 11:51:57
【问题描述】:
我正在编写类似this blog by Pieter de Rycke 的日志记录行为,但针对的是 NLog。我想出了这段代码:
public class NLogLogger : IParameterInspector
{
private void Log(Type instanceType, string operationName, string msg)
{
NLog.Logger logger = LogManager.GetLogger(
instanceType.FullName, instanceType);
logger.Info(msg, instanceType);
}
public object BeforeCall(string operationName, object[] inputs)
{
// Retrieve the service instance type for the logger then log the call.
OperationContext operationContext = OperationContext.Current;
Type instanceType = operationContext.InstanceContext
.GetServiceInstance().GetType();
Log(instanceType, operationName, "BeforeCall");
return instanceType;
}
public void AfterCall(
string operationName, object[] outputs,
object returnValue, object correlationState
)
{
if (correlationState is Type)
Log(correlationState as Type, operationName, "AfterCall");
}
}
日志记录行为正常。我使用 Pieter 描述的属性将其注入到服务 Example.MyService 中。我在 NLog 目标中有这个布局:
${longdate} ${callsite} ${level:uppercase=true} ${message}
但是GetContacts 操作的调用点是错误的:
2013-07-11 13:32:53.1379 Common.NLogLogger.Log INFO BeforeCall
2013-07-11 13:32:53.7121 Common.NLogLogger.Log INFO AfterCall
正确的是:
2013-07-11 13:32:53.1379 Example.MyService.GetContacts INFO BeforeCall
2013-07-11 13:32:53.7121 Example.MyService.GetContacts INFO AfterCall
我尝试了什么?
NLog 为记录包装器或外观提供了调用站点的特殊处理,如 StackOverflow answer 中所述:将调用站点的类传递给记录方法。
事实上,我在上面的Log() 方法中使用logger.Info(msg, instanceType) 做到了这一点。但是,这不起作用,因为当行为的 BeforeCall() 方法正在运行时,调用站点尚未在堆栈跟踪中。 WCF 甚至还没有开始运行操作。 NLog 在堆栈跟踪中找不到调用点,并且无法解开堆栈跟踪。
如何伪造呼叫站点?或者如何显示日志记录行为的“正确”调用站点?
【问题讨论】:
-
你需要使用Log方式。您不能编写包装器并简单地委托给 NLog 的 Info/Debug/Trace/etc 方法。如果您再次查看您发布的链接(指向我一段时间前发布的答案),您会看到我展示了如何使用 Log 方法编写包装器(保留呼叫站点信息)。
-
我尝试了不同的东西,其中还有
Log方法和LogEventInfo类。问题是NLogLogger并不是真正的包装器。请重新阅读有关堆栈跟踪的内容。 -
你是对的,我误读了你想要做的事情。我再补充一个建议。我并没有声称它是一个好方法,但它可能会有所帮助。