Nlog: Formatting properties

Created on 6 Nov 2018  路  13Comments  路  Source: NLog/NLog

I have a question regarding the formatting of the log message. If I log the following:

IList<string> list = new List<string>();
list.Add("A");
list.Add("B");
list.Add("C");
logManager.Fatal("List Properties {data}", list);

Using the default layout, I get a nicely formatted log message:

List Properties "A", "B", "C"

I'm storing all properties on each log message in a separate store. In my target, I iterate through the Properties property on LogEventInfo and store each property. My challenge here is that I store both they key and value as a string and simply call the ToString-method on each item. This result in the following being stored:

data = System.Collections.Generic.List`1[System.String]

In other places in my code, I'm using different layout renderers to generate a correct username, machine name, etc. But can I somehow use a generic renderer, similar to the one NLog uses for the log message? Would like to render all property values, without knowing what's inside each value really.

question

Most helpful comment

ValueFormatter will handle enumerables and anything else already supported on the log message.

Yes ValueFormatter will handle everything. But to avoid always allocating a StringBuilder (even for string-values), then I have made it a special case for IEnumerable-only.

All 13 comments

I think you're looking for the default IValueFormatter.

example:

c# var valueFormatter = ConfigurationItemFactory.Default.ValueFormatter; var sb = new StringBuilder(); valueFormatter.FormatValue(list, null, CaptureType.Normal, null, sb); var text = sb.ToString();

I guess you can do this:

c# string ConvertToString(object value) { if (Convert.GetTypeCode(value)==TypeCode.Object && value is System.Collections.IEnumerable) { var sb = new StringBuilder(); // Consider saving for reuse NLog.Config.ConfigurationItemFactory.Default.ValueFormatter.FormatValue(value, null, NLog.MessageTemplates.CaptureType.Normal, null, sb); return sb.ToString(); } return value?.ToString(); }

yes 8 seconds earlier 馃槃

But mine has less overhead for non-collections :)

Simple vs optimized example 馃憤

@304NotModified @snakefoot You guys rock. I can see how the second proposal will be good for a list, but I was chasing a solution working for everything really.

@ThomasArdal The second option will work for "everything". What do you feel that is missing?

Maybe I am missing something. Will it work for non-IEnumerable types?

Maybe I am missing something. Will it work for non-IEnumerable types?

As you can read from the very simple code-snippet, then it will call ToString on non-IEnumerable types.

Are you looking for JSON serialization? (Doesn't happen by default for message-templates)

Nope, but I guess NLog.Config.ConfigurationItemFactory.Default.ValueFormatter will handle enumerables and anything else already supported on the log message.

ValueFormatter will handle enumerables and anything else already supported on the log message.

Yes ValueFormatter will handle everything. But to avoid always allocating a StringBuilder (even for string-values), then I have made it a special case for IEnumerable-only.

@ThomasArdal Guess the issue can be closed as Resolved?

Absolutely 馃憤

Was this page helpful?
0 / 5 - 0 ratings