我对我们的日志记录看起来多么臃肿有疑问。
我们在这样的结构中记录每个方法:
namespace MyNamespace
{
public class MyClass
{
private readonly ILogger _logger;
public MyClass(ILogger logger)
{
_logger = logger;
}
public string AppendString(string originalText, string addedText)
{
using (new Tracer(_logger).TraceMethod(
"MyNameSpace.MyClass.MyMethod()",
() => new Dictionary<string, object>
{
{"originalText", originalText},
{"addedText", addedText}
}))
{
_logger.WriteInformation("Some extra info");
return originalText + addedText;
}
}
}
public class Tracer : IDisposable
{
private readonly ILogger _logger;
private string _methodName;
public Tracer(ILogger logger)
{
_logger = logger;
}
public Tracer TraceMethod(string methodName, Func<IDictionary<string, object>> arguments)
{
_logger.WriteVerbose($"Entering method {methodName} with arguments {arguments}");
_methodName = methodName;
return this;
}
public void Dispose()
{
_logger.WriteVerbose($"Exiting method {_methodName}");
}
}
}
所以我们要记录:
方法的输入 - 总是
方法的退出 - 总是
额外信息 - 适当时
但是,正如你所看到的,这个将 2 个字符串合并在一起的小逻辑变得非常臃肿。在每一种方法中看到这种膨胀是非常令人沮丧的。
我们已经研究了 Fody 和 Postsharp 等框架中的 Aspects。使用这些框架,我们将能够在所有方法上添加 [LogMethod] 属性,这将自动添加日志记录 OnMethodEntry 和 OnMethodExit。这看起来很有趣,但我们仍然会遇到一些问题。
我们如何才能在方法对方法的基础上记录我们认为合适的参数?这会有所不同,我们当然不想记录所有输入参数,因为它可能是一个巨大的 xml。我们还希望将这些参数记录在与“OnMethodEntry”日志相同的日志消息中。
我们仍然需要一个 ILogger 实例作为方法注入。ILogger 的实例化添加了一个会话 ID。这个之前设置的 sessionId 很重要。有没有办法以不同的方式解决 ILogger?如果我们不将 ILogger 发送到构造函数,我们如何能够使用相同的 ILogger 实例在方法内部登录?