Search code examples
c#.net-coreamazon-cloudwatchserilogtext-formatting

How to create a Custom text formatter for Cloudwatch?


I don't understand how to create a custom text formatter for Amazon Cloudwatch as mentioned:

var formatter = new MyCustomTextFormatter();

I am trying to write Serilog logs to Amazon CloudWatch instead of the local hard disk. To do that I am following this repo:

https://github.com/Cimpress-MCP/serilog-sinks-awscloudwatch

private readonly ITextFormatter textFormatter;

public ILoggerFactory ConfigureLogger()
{
    LoggerFactory factory = new LoggerFactory();

    var logGroupName = "myLoggrouName";
    var region = Amazon.RegionEndpoint.EUWest1;
    var client = new AmazonCloudWatchLogsClient(region);
   //var formatter = new MyCustomTextFormatter();

    var options = new CloudWatchSinkOptions()
    {
        LogGroupName = logGroupName,
        //TextFormatter = formatter,
     
        MinimumLogEventLevel = LogEventLevel.Information,
        BatchSizeLimit = 100,
        QueueSizeLimit = 10000,
        Period = TimeSpan.FromSeconds(10),
        CreateLogGroup = true,
        LogStreamNameProvider = new DefaultLogStreamProvider(),
        RetryAttempts = 5
    };

      Log.Logger = new LoggerConfiguration()
            .WriteTo.AmazonCloudWatch(options, client)
            .CreateLogger();

    return factory;
}

To be able to write the Serilogs to Cloudwatch.


Solution

  • I passed for the same situation today and what I figure out is that custom formatter - which no one is set by default - its to set how the log will be write and consequently it will appear in the AWS Logs.

    You can start creating a simple formatter using the interface that Serilog provides and adapt to the best fit in your situation.

    public class AWSTextFormatter : ITextFormatter
    {
        public void Format(LogEvent logEvent, TextWriter output)
        {
            output.Write("Timestamp - {0} | Level - {1} | Message {2} {3}", logEvent.Timestamp, logEvent.Level, logEvent.MessageTemplate, output.NewLine);
            if (logEvent.Exception != null)
            {
                output.Write("Exception - {0}", logEvent.Exception);
            }
        }
    }
    

    Using it

    var customFormatter = new AWSTextFormatter();
    
     var options = new CloudWatchSinkOptions
    {
      // the name of the CloudWatch Log group for logging
      LogGroupName = logGroupName,
    
      // the main formatter of the log event
      TextFormatter = customFormatter,
    
      // other defaults defaults
      MinimumLogEventLevel = LogEventLevel.Information,
      BatchSizeLimit = 100,
      QueueSizeLimit = 10000,
      Period = TimeSpan.FromSeconds(10),
      CreateLogGroup = true,
      LogStreamNameProvider = new DefaultLogStreamProvider(),
      RetryAttempts = 5
    };
    

    In the method you can acces the LogEvent and get all information you need. This one is similar to what they use in the lib, writing the event, exception and some detail.

    A suggestion is to test the custom formatter locally writing the log in some file

    Log.Logger = new LoggerConfiguration()
         .MinimumLevel.Debug()
         .WriteTo.RollingFile(customFormatter, Path.Combine(env.ContentRootPath, "Logs", "Log-{Date}.txt"))
         .WriteTo.AmazonCloudWatch(options, client)
         .CreateLogger();
    

    What the log shows:

    Timestamp - 1/9/2019 11:52:11 AM -02:00 | Level - Fatal | Message PROBLEM STARTING 
     APPLICATION 
     Exception - Couchbase.Configuration.Server.Serialization.BootstrapException: Could not 
     bootstrap - check inner exceptions for details.