Consider this:
var myArray = new int[] { 1, 2, 3, 4 };
logger.Debug("Array content: {0}", myArray);
Actual output (using object.ToString()
):
Array content: System.Int32[]
Desired output:
Array content: 1, 2, 3, 4
Of course, this may be done by manually converting the int[]
to a string
before passing it to NLog like this:
logger.Debug("Array content: {0}", string.Join(", ", myArray));
However, I only want the array content string to be generated if the message is actually logged (in this case if Debug level is enabled) because of possible performance impact for larger arrays.
--> Question: Is there a way to tell NLog to log the contents of an array rather than its type name?
I have read a lot about renderers and so on, but did not find a way how to tell NLog to render arguments in a different way. Another approach would be a custom string format for arrays, e.g. {0:X}
, but obviously arrays do not support any formats. Another idea would be to pass a delegate instead of the parameter itself, so that the string conversion would only happen if the delegate is actually called. However, no such overload seems to exist.
CodePudding user response:
@Ralf is close. NLog supports structured logging. With structured logging it also performs some special formatting for certain data types. However, for some backwards compatibility (that I don't know the details of) if you use indexed logging like in your example it'll skip the special formatting.
Instead you should do something like:
// Name your parameter vvvvvvv
logger.Debug("Array content: {content}", myArray);
NLog checks the message-template and when detecting positional-placeholders, then it uses string.Format
that supports repeated positional values. Ex. string.Format("{1}{0}{2}{0}", Environment.NewLine, "Hello", "World");
. Message Template for structured-logging does not support repeated positional values.