Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to show log message with substituted parameters in structured logging output from Serilog on AWS Cloudwatch

I'm using AWS Cloudwatch for my application logging. I recently learned that I could use structured logging to make my logs more searchable. I did a little research and decided to go with Serilog for my logging tool.

One difficulty I'm having is, although I'm seeing the structured logging message in Cloudwatch, it's not showing a fully formatted log message.

For example, when I send this to the logs:

_logger.LogError("Hello {person}, {question} are you {time}?", "Dave", "how", "today");

I see this message in the Cloudwatch logs output

Hello {person}, {question} are you {time}?

But I don't see the fully substituted version of the string anywhere i.e.

Hello Dave how are you today?

I followed this walkthrough on setting up Serilog for structured logging in AWS https://martinjt.me/2020/02/16/serilog-and-cloudwatch-with-inbuilt-credentials/ and ended up with this code.

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
    .ConfigureWebHostDefaults(webBuilder =>
    {
        webBuilder.UseStartup<Startup>()
        .UseSerilog(SetupAWSLogging);
    });

public class LoggingSettings
{
    public string LogGroup { get; set; }
}

public static void SetupAWSLogging(WebHostBuilderContext hostingContext, LoggerConfiguration loggerConfiguration)
{
    var config = hostingContext.Configuration;
    var settings = config.GetSection("Logging").Get<LoggingSettings>();

    loggerConfiguration
        .MinimumLevel.Information()
        .Enrich.FromLogContext()
        .WriteTo.Console();

    if (!string.IsNullOrEmpty(settings.LogGroup))
    {
        var options = new CloudWatchSinkOptions
        {
            LogGroupName = settings.LogGroup,
            CreateLogGroup = true,
            MinimumLogEventLevel = LogEventLevel.Information,
            TextFormatter = new JsonFormatter()
        };
        var awsOptions = config.GetAWSOptions();
        var cloudwatchClient = awsOptions.CreateServiceClient<IAmazonCloudWatchLogs>();
        loggerConfiguration
            .WriteTo.AmazonCloudWatch(options, cloudwatchClient);
    }

}

Here's the full entry found in Cloudwatch

{
    "Timestamp": "2021-07-05T09:08:32.5118371-06:00",
    "Level": "Error",
    "MessageTemplate": "Hello {person}, {question} are you {time}?",
    "Properties": {
        "person": "Dave",
        "question": "how",
        "time": "today",
        "SourceContext": "Testing",
        "ActionId": "54758041-ee5f-4297-a7b3-adaa5e675901",
        "ActionName": "Testing.Ping (TestController)",
        "RequestId": "80000007-0005-ff00-b63f-84710c7967bb",
        "RequestPath": "/Testing/Ping"
    }
}

All the information we need to construct the message ourselves is there, but the log is not as readable as if I could see the substituted string as well. Is there something I'm missing or doing wrong? Maybe it's just a configuration in Cloudwatch to show the string with substitutions? It would be better if it were done there I guess to cut down on the log sizes.

Appreciate the help all.

like image 650
omatase Avatar asked Oct 30 '25 10:10

omatase


1 Answers

Simplest fix is:

            TextFormatter = new JsonFormatter(renderMessage: true)

Note true to render the message.

like image 128
Nicholas Blumhardt Avatar answered Nov 01 '25 06:11

Nicholas Blumhardt



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!