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:
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.
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?
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()}";
}
}