Hello

I'm trying to create a structured logging format and have a conversion pattern 
with a custom converter like this:

      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%date [%2thread] %-5level [%property{NDC}] 
%username - type=%message_checksum %message%newline" />
        <converter>
          <name value="message_checksum" />
          <type value="TestBed.MessageChecksumConverter" />
        </converter>
      </layout>

The interesting part of course is the message_checksum. For example, I am 
logging like this:

                Log.Debug("some debugging message");
                Log.Info(new { Id = 1, Name = "the name" });
                Log.InfoFormat("Logging msg {0}", 1);
                Log.InfoFormat("Logging msg {0}", 2);
                Log.InfoFormat("Logging msg {0}", 3);

I would like the output to be something like this

2018-10-26 11:06:44,564 [ 1] DEBUG [(null)] XXX - type=f6d5 some debugging 
message
2018-10-26 11:06:44,638 [ 1] INFO  [(null)] XXX - type=e0e3 { Id = 1, Name = 
the name }
2018-10-26 11:06:44,648 [ 1] INFO  [(null)] XXX - type=32a6 Logging msg 1
2018-10-26 11:06:44,656 [ 1] INFO  [(null)] XXX - type=32a6 Logging msg 2
2018-10-26 11:06:44,663 [ 1] INFO  [(null)] XXX - type=32a6 Logging msg 3

As you can see, I am getting the type=32a6 for the last 3 logging messages. 
This allows me to search for all of those, regardless of the parameters given.
For example, I can now search and group the number of errors by their unique 
type.

To implement this, I did the following:

    public class MessageChecksumConverter : PatternLayoutConverter
    {
        private static readonly MD5 ChecksumGenerator = MD5.Create();

        protected override void Convert(TextWriter writer, LoggingEvent 
loggingEvent)
        {
            byte[] hash;
            if (loggingEvent.MessageObject is SystemStringFormat fmt)
            {
                // read fmt.m_format and use that as input for hash
                var systemStringFormatType = typeof(SystemStringFormat);
                var fieldInfo =
                    systemStringFormatType.GetField("m_format", 
BindingFlags.NonPublic | BindingFlags.Instance);
                var formatString = fieldInfo.GetValue(fmt) as string;
                hash = 
ChecksumGenerator.ComputeHash(Encoding.ASCII.GetBytes(formatString));
            }
            else
            {
                var messageObject = loggingEvent.MessageObject.ToString();
                hash = 
ChecksumGenerator.ComputeHash(Encoding.ASCII.GetBytes(messageObject));
            }

            var builder = new StringBuilder();
            foreach (var b in hash.Take(2))
            {
                builder.Append(b.ToString("x2"));
            }

            var output = builder.ToString();
            writer.Write(output);
        }
    }

I am reading SystemStringFormat.m_format by using reflection.

Now to my feature request: please expose the internals of SystemStringFormat so 
that I can do this in a safe way.
What do you think?

Regards,
Daniel Lidström



General Information


The information contained in this e-mail message may be privileged, 
confidential, and protected from disclosure. Any unauthorized use, printing, 
copying, disclosure or dissemination of this communication may be subject to 
legal restriction or sanction. If you think that you have received this e-mail 
message in error, please reply to the sender and delete this message from your 
computer.

Reply via email to