user17055229
user17055229

Reputation:

PostSharp Logging Add >>> and <<< to Method Entry/Exit Log Entries

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

Answers (1)

Gael Fraiteur
Gael Fraiteur

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.

    • Alternatively, you can also call directly NLog.Logger, which you can get from the expression ((NLogLoggingTypeSource) this.TypeSource).Logger.
    • To determine the kind of message (entry, success, failure), use 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

Related Questions