I am having an issue with how bloated our logging looks.
We are logging every single method in a structure like this:
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;
private string _sessionId; // Set from a different part of the code
public Tracer(ILogger logger)
{
_logger = logger;
}
public Tracer TraceMethod(string methodName, Func<IDictionary<string, object>> arguments)
{
_logger.WriteVerbose($"Entering method {methodName} with arguments {arguments}", _sessionId);
_methodName = methodName;
return this;
}
public void Dispose()
{
_logger.WriteVerbose($"Exiting method {_methodName}", _sessionId);
}
}
}
So we want to log:
-
entry of method - ALWAYS
-
exit of method - ALWAYS
-
extra info - When appropriate
But, as you can see, this tiny little logic for merging 2 strings together becomes super bloated. It's very frustrating to see this kind of bloat in every single method.
We have looked into Aspects in frameworks like Fody and Postsharp. With these frameworks we would be able to add a [LogMethod] attribute on all methods and this would automatically add logging OnMethodEntry and OnMethodExit. This looks interesting but we still would have some issues.
-
How could we, on a method to method basis, log the parameters we feel appropriate? This will vary, and we certainly don't want to log all input parameters because it could be something like a huge xml. We also want to log these parameters in the same log message as the "OnMethodEntry" log.
-
We would still need to have an ILogger instance as a method injection. The sessionId that has been set at an earlier point is important. Would there be any way to solve ILogger in a different way? If we don't send in an ILogger to the constructor, how would we be able to log inside the method with the same instance of ILogger?
Aucun commentaire:
Enregistrer un commentaire