Reputation:
Can someone please tell me if it's possible to add >>> and <<< to the log entries made by PostSharp Logging at method entry and exit? If it's possible, can someone please help get me started?
Google has not been a friend and PostSharp's documentation hasn't been helpful, either. I see where I can create a custom formatter or backend, but I don't see in those examples how to customize the log entry for method entry versus method exit.
Actual PostSharp Log Output w/ NLog
2021-10-01 16:29:16.5539|DEBUG|jaslibdss.libddss| libddss.get_Database()|Starting.
2021-10-01 16:29:16.5539|DEBUG|jaslibdss.libddss| libddss.get_Database()|Succeeded: returnValue = "master", executionTime = 0.11 ms.
Desired PostSharp Log Output w/ NLog
2021-10-01 16:29:16.5539|DEBUG|jaslibdss.libddss| >>> libddss.get_Database()|Starting.
2021-10-01 16:29:16.5539|DEBUG|jaslibdss.libddss| <<< libddss.get_Database()|Succeeded: returnValue = "master", executionTime = 0.11 ms.
I'm using the following:
NLog nuget 4.7.11
PostSharp nuget 6.9.9
PostSharp.Patterns.Diagnostics nuget 6.9.9
PostSharp.Patterns.Diagnostics.NLog nuget 6.9.9
I'm using NLog configuration pulled straight from their example:
// Configure NLog.
var nlogConfig = new LoggingConfiguration();
var fileTarget = new FileTarget("file")
{
FileName = "nlog.log",
KeepFileOpen = true,
ConcurrentWrites = false
};
nlogConfig.AddTarget(fileTarget);
nlogConfig.LoggingRules.Add(new LoggingRule("*", LogLevel.Debug, fileTarget));
var consoleTarget = new ConsoleTarget("console");
nlogConfig.AddTarget(consoleTarget);
nlogConfig.LoggingRules.Add(new LoggingRule("*", LogLevel.Debug, consoleTarget));
// Configure PostSharp Logging to use NLog.
LoggingServices.DefaultBackend = new NLogLoggingBackend(new LogFactory(nlogConfig));
LogManager.EnableLogging();
I don't have any other code to show because I don't know where to begin to code this.
*** Edit ***
internal class MyBackend : NLogLoggingBackend
{
public override MyLogBuilder CreateRecordBuilder()
{
return new MyLogBuilder(this);
}
}
internal class MyLogBuilder : NLogLogRecordBuilder
{
public MyLogBuilder(NLogLoggingBackend backend) : base(backend)
{
}
protected override void Write()
{
}
}
Tried this so far but "protected override void Write()" is telling me there is no suitable Write method to override. I do see a WriteCustomString method, however. Is that what you meant?
*** Edit #2 ***
internal class MyBackend : NLogLoggingBackend
{
public MyBackend(LoggingConfiguration config) : base(new LogFactory(config))
{
}
public override MyLogRecordBuilder CreateRecordBuilder()
{
return new MyLogRecordBuilder(this);
}
}
internal class MyLogRecordBuilder : NLogLogRecordBuilder
{
public MyLogRecordBuilder(NLogLoggingBackend backend) : base(backend)
{
}
public void Write()
{
if (this.RecordKind == LogRecordKind.MethodEntry)
{
base.Write(new PostSharp.Patterns.Formatters.UnsafeString(">>> Hello, world!"));
}
if (this.RecordKind == LogRecordKind.MethodSuccess)
{
base.Write(new PostSharp.Patterns.Formatters.UnsafeString("<<< Hello, world!"));
}
}
}
then
// Configure NLog.
var nlogConfig = new LoggingConfiguration();
var fileTarget = new FileTarget("file")
{
FileName = "nlog.log",
KeepFileOpen = true,
ConcurrentWrites = false,
};
nlogConfig.AddTarget(fileTarget);
nlogConfig.LoggingRules.Add(new LoggingRule("*", LogLevel.Debug, fileTarget));
var consoleTarget = new ConsoleTarget("console");
nlogConfig.AddTarget(consoleTarget);
nlogConfig.LoggingRules.Add(new LoggingRule("*", LogLevel.Debug, consoleTarget));
LogManager.EnableLogging();
// Configure PostSharp Logging to use NLog.
NLogLoggingBackend b = new MyBackend(nlogConfig);
//b.Options.IndentSpaces = 0;
LoggingServices.DefaultBackend = b;
With this, however, I'm getting a stack overflow error. :/
*** Edit 3 ***
public class MyBackend : NLogLoggingBackend
{
public MyBackend(LoggingConfiguration config) : base(new LogFactory(config))
{
Options.IndentSpaces = 4;
Options.Delimiter = " - ";
Options.IncludeType = false;
}
public override MyLogRecordBuilder CreateRecordBuilder()
{
return new MyLogRecordBuilder(this);
}
}
[Log(AttributeExclude = true)]
public class MyLogRecordBuilder : NLogLogRecordBuilder
{
public MyLogRecordBuilder(NLogLoggingBackend backend) : base(backend)
{
System.Console.WriteLine(@"DEBUG---" + backend.Options.Delimiter);
System.Console.WriteLine(@"DEBUG---" + backend.Options.IndentSpaces);
}
protected override void Write(UnsafeString message)
{
if (this.RecordKind == LogRecordKind.MethodEntry)
{
base.Write(new PostSharp.Patterns.Formatters.UnsafeString(">>> Hello, world!"));
}
if (this.RecordKind == LogRecordKind.MethodSuccess)
{
base.Write(new PostSharp.Patterns.Formatters.UnsafeString("<<< Hello, world!"));
}
}
}
Edit #3 is my current code that works. I'm getting log output now with <<< and >>> in the log entry text. However, I can't get any of the backend.Options to apply. For example, I'm stuck with the default delimiter of | and I'm not getting any indentation at all.
Note: In my two DEBUG WriteLine's above I do see the expected Option values of " - " and 4 spaces for indenting.
Question: When I overwrite the Write method do I need to add anything special to make use of these Options or should these be applying and I'm doing something else wrong?
Upvotes: 2
Views: 355
Reputation: 6857
You have to create a custom logging back-end derived from NLogLoggingBackend
.
Create a class derived from NLogLoggingBackend
.
Create a class derived from NLogLogRecordBuilder
.
Override NLogLoggingBackend.CreateRecordBuilder
so that it returns a new instance of your NLogLogRecordBuilder
.
Override NLogLogRecordBuilder.Write
. You can call the base NLogLogRecordBuilder.Write
method with your own string.
((NLogLoggingTypeSource) this.TypeSource).Logger
.LogRecordBuilder.RecordKind
Alternatively you can override AppendProlog
and insert your >>>
or <<<
before you call base.AppendProlog
(by appending it to this.StringBuilder
), but then your characters will be inserted even before the indentation.
Upvotes: 2