Search code examples
c#nlogamazon-cloudwatchlogs

Multiline strings in CloudWatch


I have the following NLog setup:

// Custom serializer for exceptions
LogManager.Setup().SetupSerialization(s =>
   s.RegisterObjectTransformation<Exception>(ex => new {
       Data = ex.ToBetterString()
   })
);

// In the layout I configure the exception like this:
jsonLayout.Attributes.Add(new JsonAttribute("exception", "${exception:format=@}"));

So this gets my exception and parses the exception text in a more beautiful way, then put it in an anonymous object in a Data property. So this property is a multiline string.

When the log arrives at CloudWatch, I get the following result:

enter image description here

As you can see in the image, there are two problems:

  1. the property is being recognized as a string instead of an object
  2. the \r\n characters are not being parsed as newline characters

Is there any way to properly see this in CloudWatch?

---------------- UPDATE -----------------

As pointed by @Stefan adding encode = false helped a little bit. Now the exception property is recognized as json, just the multiline string is not being rendered properly:

enter image description here


Solution

  • Just for future reference, for someone that might have the same issue, this was my solution:

    I updated the custom serializer to this:

    LogManager.Setup().SetupSerialization(s =>
        s.RegisterObjectTransformation<Exception>(ex => new ExceptionData(ex))
    );
    

    And the ExceptionData class:

    public class ExceptionData
    {
        public ExceptionData(Exception exception)
        {
            Message = exception.Message;
            HResult = exception.HResult;
            Source = exception.Source;
            StackTrace = exception.StackTrace.Replace("\r", "").Split('\n');
    
            foreach (var item in exception.Data)
            {
                if (Data == null)
                {
                    Data = new Dictionary<string, object>();
                }
                var dictionaryEntry = (DictionaryEntry)item;
                Data.Add(dictionaryEntry.Key.ToString(), dictionaryEntry.Value);
            }
    
            if (exception.InnerException != null)
            {
                InnerException = new ExceptionData(exception.InnerException);
            }
        }
    
        public string Message { get; set; }
        public long HResult { get; set; }
        public string Source { get; set; }
        public string[] StackTrace { get; set; }
        public ExceptionData InnerException { get; set; }
        public Dictionary<string, object> Data { get; set; }
    }
    

    It seems CloudWatch doesn't support displaying strings in multiple lines, so for the stacktrace I opted to use an array of strings. Now the logs looks like this:

    enter image description here