aws-logging-dotnet retrieve the AWS Logger LogStreamName value at runtime

35 views Asked by At

I am using the aws-logging-dotnet library to write the application logs to AWS Cloudwatch.

The logger is configured via a json file:

{
  "Serilog": {
    "Using": [ "AWS.Logger.SeriLog", "Serilog.Exceptions" ],

    "MinimumLevel": {
      "Default": "Information",
      "Override": {
        "Hangfire": "Warning",
        "Microsoft.AspNetCore": "Warning",
        "Serilog.AspNetCore": "Warning",
        "System": "Warning"
      }
    },
    "Enrich": [ "WithMachineName", "WithProcessId", "WithProcessName", "FromLogContext", "WithExceptionDetails" ],
    "Properties": {
      "Application": "My Application Name"
    },
    "Region": "My AWS Region", 
    "LogGroup": "My AWS LogGroup", 
    "WriteTo": [
      {
        "Name": "Console",
        "Args": {
          "outputTemplate": "[{SourceContext}] [{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}"
        }
      }
    ],
    "WriteTo:Async": {
      "Name": "Async",
      "Args": {
        "configure": [
          {
            "Name": "AWSSeriLog",
            "Args": {
              "textFormatter": "Serilog.Formatting.Compact.CompactJsonFormatter, Serilog.Formatting.Compact"
            }
          }
        ]
      }
    }
  }
}

As soon as the app starts logging in AWS CW, it creates a dedicated stream, like this:

enter image description here

I am interested in getting the runtime value of the LogStreamName. The application is running on many nodes, hence each instance logs into its own stream.

I can see that the LogStreamName name is managed internally by the logger. However it seems there is no way to get that value.

https://github.com/aws/aws-logging-dotnet/blob/d59d7c855d5bccc4fd60d3435893152dfbf11b17/src/AWS.Logger.Core/Core/AWSLoggerCore.cs#L605C26-L605C40

public PutLogEventsRequest _request = new PutLogEventsRequest();
            public LogEventBatch(string logGroupName, string streamName, int timeIntervalBetweenPushes, int maxBatchSize)
            {
                _request.LogGroupName = logGroupName;
                _request.LogStreamName = streamName;
                TimeIntervalBetweenPushes = TimeSpan.FromSeconds(timeIntervalBetweenPushes);
                MaxBatchSize = maxBatchSize;
                Reset(null);
            }

Before I invent hacky solutions, does anyone know if there is a clean way to read it?

1

There are 1 answers

0
MiTV23572282 On BEST ANSWER

The short answer is no. The log stream name is managed internally by the AWSLoggerCore class. The logger API doesn't provide any public accessor to read or override it.

However there is an open request for it: https://github.com/aws/aws-logging-dotnet/issues/195

You may consider opting for this alternative library: serilog-sinks-awscloudwatch https://github.com/Cimpress-MCP/serilog-sinks-awscloudwatch

This gives you the possibility to set the Log Stream Name you prefer by implementing your own LogStreamNameProvider:

var options = new CloudWatchSinkOptions
  {
    // the name of the CloudWatch Log group for logging
    LogGroupName = logGroupName,

    // the main formatter of the log event
    TextFormatter = formatter,
    
    // other defaults defaults
    MinimumLogEventLevel = LogEventLevel.Information,
    BatchSizeLimit = 100,
    QueueSizeLimit = 10000,
    Period = TimeSpan.FromSeconds(10),
    CreateLogGroup = true,
    LogStreamNameProvider = new MyLogStreamProvider(),
    RetryAttempts = 5
  };

...

    public class MyLogStreamProvider : ILogStreamNameProvider
    {
        private readonly string DATETIME_FORMAT = "yyyy-MM-dd-hh-mm-ss";

        // Customise your log stream name
        public string GetLogStreamName()
        {
            return $"{DateTime.UtcNow.ToString(DATETIME_FORMAT)}_{Dns.GetHostName()}_{Guid.NewGuid()}";
        }
    }