-
Notifications
You must be signed in to change notification settings - Fork 54
Using a JSON formatter
This library does not send JSON to CloudWatch by default. That is a separate concern of the library and also closely coupled with the usage of the library in an application. Such can be seen from asking the question:
Assuming the payload sent to CloudWatch must be wrapped, what would you like the wrapper to be?
The reason for not providing a specific JSON, XML or other custom renderer is that this library is about forwarding logs to cloud watch, and additional dependencies should be avoided for simplicity, single responsibility but also library size perspective.
That said, it's very easy to inject a custom ITextFormatter
. One example is a JSON text formatter. To provide a specific example, below some sample code.
In Startup.cs
, configure the renderer like this:
var options = new CloudWatchSinkOptions
{
LogGroupName = logGroupName,
LogEventRenderer = new JsonTextFormatter()
};
AmazonCloudWatchLogs client = new AmazonCloudWatchLogsClient(settings.GetAwsCredentials(), settings.GetRegionEndpoint());
var loggerConfig = new LoggerConfiguration()
.MinimumLevel.Information()
.Destructure.AsScalar<JObject>()
.Destructure.AsScalar<JArray>()
.Enrich.FromLogContext()
//.Enrich.WithWhateverOtherData()
.WriteTo.AmazonCloudWatch(options, client);
Create a custom rendering class, for example JsonTextFormmatter.cs
, and base it on the following idea:
public class JsonTextFormatter : ITextFormatter
{
// the cached host name which is part of every log message
private readonly string hostname;
public JsonTextFormatter()
{
hostname = Dns.GetHostName();
}
public void Format(LogEvent logEvent, TextWriter output)
{
try
{
// flatten the message as a simpler option to look at it within the RenderedMessage property of the JSON file
var renderedMessage = logEvent.RenderMessage();
// create the message object
var message = new {logEvent.MessageTemplate, logEvent.Properties, RenderedMessage = renderedMessage, Level = logEvent.Level.ToString(), Exception = logEvent.Exception?.ToString(), Hostname = hostname};
// serialize the object as JSON
output.Write(JsonConvert.SerializeObject(message));
}
catch (Exception exception)
{
try
{
var message = new {RenderedMessage = "Failed to render log message.", MessageTemplate = logEvent.MessageTemplate.Text, Exception = exception.ToString()};
output.Write(JsonConvert.SerializeObject(message));
}
catch (Exception ex)
{
// fallback to just return the fact that we were unable to render the log message
output.Write($"Unable to render log message. Reason was {ex}");
}
}
}
}
Based on above example, it should be straight forward to create additional custom renderers, be it JSON, XML or any other custom format.