From 01fdaaf60c237240e98358259bae084d4045664d Mon Sep 17 00:00:00 2001 From: bartpio Date: Tue, 7 May 2019 21:48:40 -0400 Subject: [PATCH] User-defined log stream prefix (issue #83) --- .../AWSLoggerConfigSection.cs | 5 +++++ src/AWS.Logger.Core/AWSLoggerConfig.cs | 12 +++++++++++- src/AWS.Logger.Core/Core/AWSLoggerCore.cs | 18 +++++++++++++++++- src/AWS.Logger.Log4net/AWSAppender.cs | 18 ++++++++++++++++-- .../AWSLoggerSeriLogExtension.cs | 5 +++++ src/NLog.AWS.Logger/AWSTarget.cs | 18 ++++++++++++++++-- .../appsettings.json | 1 + test/AWS.Logger.Log4Net.Tests/log4net.config | 7 ++++--- test/AWS.Logger.NLog.Tests/Regular.config | 2 +- .../AWSSeriLogGroup.json | 1 + test/AWS.Logger.TestUtils/BaseTestClass.cs | 4 ++++ 11 files changed, 81 insertions(+), 10 deletions(-) diff --git a/src/AWS.Logger.AspNetCore/AWSLoggerConfigSection.cs b/src/AWS.Logger.AspNetCore/AWSLoggerConfigSection.cs index 5400c84..c244a44 100644 --- a/src/AWS.Logger.AspNetCore/AWSLoggerConfigSection.cs +++ b/src/AWS.Logger.AspNetCore/AWSLoggerConfigSection.cs @@ -62,6 +62,7 @@ public class AWSLoggerConfigSection internal const string LOG_LEVEL = "LogLevel"; internal const string MAX_QUEUED_MESSAGES = "MaxQueuedMessages"; internal const string LOG_STREAM_NAME_SUFFIX = "LogStreamNameSuffix"; + internal const string LOG_STREAM_NAME_PREFIX = "LogStreamNamePrefix"; internal const string LIBRARY_LOG_FILE_NAME = "LibraryLogFileName"; internal const string INCLUDE_SCOPES_NAME = "IncludeScopes"; @@ -96,6 +97,10 @@ public AWSLoggerConfigSection(IConfiguration loggerConfigSection) { Config.LogStreamNameSuffix = loggerConfigSection[LOG_STREAM_NAME_SUFFIX]; } + if (loggerConfigSection[LOG_STREAM_NAME_PREFIX] != null) + { + Config.LogStreamNamePrefix = loggerConfigSection[LOG_STREAM_NAME_PREFIX]; + } if (loggerConfigSection[LIBRARY_LOG_FILE_NAME] != null) { Config.LibraryLogFileName = loggerConfigSection[LIBRARY_LOG_FILE_NAME]; diff --git a/src/AWS.Logger.Core/AWSLoggerConfig.cs b/src/AWS.Logger.Core/AWSLoggerConfig.cs index 30ffc35..c25a6e3 100644 --- a/src/AWS.Logger.Core/AWSLoggerConfig.cs +++ b/src/AWS.Logger.Core/AWSLoggerConfig.cs @@ -129,13 +129,23 @@ public AWSLoggerConfig(string logGroup) /// /// Gets and sets the LogStreamNameSuffix property. The LogStreamName consists of a DateTimeStamp as the prefix and a user defined suffix value that can /// be set using the LogStreamNameSuffix property defined here. - /// The LogstreamName then follows the pattern '[DateTime.Now.ToString("yyyy/MM/ddTHH.mm.ss")]-[LogstreamNameSuffix]' + /// The LogstreamName then follows the pattern '[LogStreamNamePrefix]-[DateTime.Now.ToString("yyyy/MM/ddTHH.mm.ss")]-[LogStreamNameSuffix]' /// /// The default is going to a Guid. /// /// public string LogStreamNameSuffix { get; set; } = Guid.NewGuid().ToString(); + /// + /// Gets and sets the LogStreamNamePrefix property. The LogStreamName consists of an optional user-defined LogStreamNamePrefix (that can be set here) + /// followed by a DateTimeStamp as the prefix, and a user defined suffix value + /// The LogstreamName then follows the pattern '[LogStreamNamePrefix]-[DateTime.Now.ToString("yyyy/MM/ddTHH.mm.ss")]-[LogStreamNameSuffix]' + /// + /// The default is an empty string. + /// + /// + public string LogStreamNamePrefix { get; set; } = string.Empty; + /// /// Gets and sets the LibraryLogFileName property. This is the name of the file into which errors from the AWS.Logger.Core library will be wriiten into. /// diff --git a/src/AWS.Logger.Core/Core/AWSLoggerCore.cs b/src/AWS.Logger.Core/Core/AWSLoggerCore.cs index c25acb3..3281194 100644 --- a/src/AWS.Logger.Core/Core/AWSLoggerCore.cs +++ b/src/AWS.Logger.Core/Core/AWSLoggerCore.cs @@ -444,7 +444,7 @@ private async Task LogEventTransmissionSetup(CancellationToken token) } } - var currentStreamName = DateTime.Now.ToString("yyyy/MM/ddTHH.mm.ss") + " - " + _config.LogStreamNameSuffix; + var currentStreamName = GenerateStreamName(); var streamResponse = await _client.CreateLogStreamAsync(new CreateLogStreamRequest { @@ -461,6 +461,22 @@ private async Task LogEventTransmissionSetup(CancellationToken token) return currentStreamName; } + /// + /// generate a logstream name + /// + /// logstream name that ALWAYS includes a unique date-based segment + private string GenerateStreamName() + { + var suffix = _config.LogStreamNameSuffix; + var prefix = _config.LogStreamNamePrefix ?? string.Empty; + if (!string.IsNullOrEmpty(prefix)) + { + prefix += " - "; //if there WAS a user-specified prefix, let's use it, followed by a separator + } + + return prefix + DateTime.Now.ToString("yyyy/MM/ddTHH.mm.ss") + " - " + suffix; + } + private static bool IsSuccessStatusCode(AmazonWebServiceResponse serviceResponse) { return (int)serviceResponse.HttpStatusCode >= 200 && (int)serviceResponse.HttpStatusCode <= 299; diff --git a/src/AWS.Logger.Log4net/AWSAppender.cs b/src/AWS.Logger.Log4net/AWSAppender.cs index 1c36136..b036641 100644 --- a/src/AWS.Logger.Log4net/AWSAppender.cs +++ b/src/AWS.Logger.Log4net/AWSAppender.cs @@ -128,8 +128,8 @@ public int MaxQueuedMessages } /// - /// Gets and sets the LogStreamNameSuffix property. The LogStreamName consists of a DateTimeStamp as the prefix and a user defined suffix value that can - /// be set using the LogStreamNameSuffix property defined here. + /// Gets and sets the LogStreamNameSuffix property. The LogStreamName consists of an optional user-defined prefix segment, then a DateTimeStamp as the + /// system-defined prefix segment, and a user defined suffix value that can be set using the LogStreamNameSuffix property defined here. /// /// The default is going to a Guid. /// @@ -140,6 +140,19 @@ public string LogStreamNameSuffix set { _config.LogStreamNameSuffix = value; } } + /// + /// Gets and sets the LogStreamNamePrefix property. The LogStreamName consists of an optional user-defined prefix segment (defined here), then a + /// DateTimeStamp as the system-defined prefix segment, and a user defined suffix value that can be set using the LogStreamNameSuffix property. + /// + /// The default will use an empty string for this user-defined portion, meaning the log stream name will start with the system-defined portion of the prefix (yyyy/MM/dd ... ) + /// + /// + public string LogStreamNamePrefix + { + get { return _config.LogStreamNamePrefix; } + set { _config.LogStreamNamePrefix = value; } + } + /// /// Gets and sets the LibraryLogFileName property. This is the name of the file into which errors from the AWS.Logger.Core library will be wriiten into. /// @@ -173,6 +186,7 @@ public override void ActivateOptions() BatchSizeInBytes = BatchSizeInBytes, MaxQueuedMessages = MaxQueuedMessages, LogStreamNameSuffix = LogStreamNameSuffix, + LogStreamNamePrefix = LogStreamNamePrefix, LibraryLogFileName = LibraryLogFileName }; _core = new AWSLoggerCore(config, "Log4net"); diff --git a/src/AWS.Logger.SeriLog/AWSLoggerSeriLogExtension.cs b/src/AWS.Logger.SeriLog/AWSLoggerSeriLogExtension.cs index 8588266..05305ac 100644 --- a/src/AWS.Logger.SeriLog/AWSLoggerSeriLogExtension.cs +++ b/src/AWS.Logger.SeriLog/AWSLoggerSeriLogExtension.cs @@ -18,6 +18,7 @@ public static class AWSLoggerSeriLogExtension internal const string BATCH_PUSH_SIZE_IN_BYTES = "Serilog:BatchPushSizeInBytes"; internal const string MAX_QUEUED_MESSAGES = "Serilog:MaxQueuedMessages"; internal const string LOG_STREAM_NAME_SUFFIX = "Serilog:LogStreamNameSuffix"; + internal const string LOG_STREAM_NAME_PREFIX = "Serilog:LogStreamNamePrefix"; internal const string LIBRARY_LOG_FILE_NAME = "Serilog:LibraryLogFileName"; /// @@ -58,6 +59,10 @@ public static LoggerConfiguration AWSSeriLog( { config.LogStreamNameSuffix = configuration[LOG_STREAM_NAME_SUFFIX]; } + if (configuration[LOG_STREAM_NAME_PREFIX] != null) + { + config.LogStreamNamePrefix = configuration[LOG_STREAM_NAME_PREFIX]; + } if (configuration[LIBRARY_LOG_FILE_NAME] != null) { config.LibraryLogFileName = configuration[LIBRARY_LOG_FILE_NAME]; diff --git a/src/NLog.AWS.Logger/AWSTarget.cs b/src/NLog.AWS.Logger/AWSTarget.cs index e8b7347..3506c11 100644 --- a/src/NLog.AWS.Logger/AWSTarget.cs +++ b/src/NLog.AWS.Logger/AWSTarget.cs @@ -132,8 +132,8 @@ public int MaxQueuedMessages } /// - /// Gets and sets the LogStreamNameSuffix property. The LogStreamName consists of a DateTimeStamp as the prefix and a user defined suffix value that can - /// be set using the LogStreamNameSuffix property defined here. + /// Gets and sets the LogStreamNameSuffix property. The LogStreamName consists of an optional user-defined prefix segment, then a DateTimeStamp as the + /// system-defined prefix segment, and a user defined suffix value that can be set using the LogStreamNameSuffix property defined here. /// /// The default is going to a Guid. /// @@ -144,6 +144,19 @@ public string LogStreamNameSuffix set { _config.LogStreamNameSuffix = value; } } + /// + /// Gets and sets the LogStreamNamePrefix property. The LogStreamName consists of an optional user-defined prefix segment (defined here), then a + /// DateTimeStamp as the system-defined prefix segment, and a user defined suffix value that can be set using the LogStreamNameSuffix property. + /// + /// The default will use an empty string for this user-defined portion, meaning the log stream name will start with the system-defined portion of the prefix (yyyy/MM/dd ... ) + /// + /// + public string LogStreamNamePrefix + { + get { return _config.LogStreamNamePrefix; } + set { _config.LogStreamNamePrefix = value; } + } + /// /// Gets and sets the LibraryLogFileName property. This is the name of the file into which errors from the AWS.Logger.Core library will be wriiten into. /// @@ -175,6 +188,7 @@ protected override void InitializeTarget() BatchSizeInBytes = BatchSizeInBytes, MaxQueuedMessages = MaxQueuedMessages, LogStreamNameSuffix = RenderSimpleLayout(LogStreamNameSuffix, nameof(LogStreamNameSuffix)), + LogStreamNamePrefix = RenderSimpleLayout(LogStreamNamePrefix, nameof(LogStreamNamePrefix)), LibraryLogFileName = LibraryLogFileName }; _core = new AWSLoggerCore(config, "NLog"); diff --git a/test/AWS.Logger.AspNetCore.Tests/appsettings.json b/test/AWS.Logger.AspNetCore.Tests/appsettings.json index cf5c46f..0475eaa 100644 --- a/test/AWS.Logger.AspNetCore.Tests/appsettings.json +++ b/test/AWS.Logger.AspNetCore.Tests/appsettings.json @@ -3,6 +3,7 @@ "LogGroup": "AWSILogger", "Region": "us-west-2", "LogStreamNameSuffix": "Custom", + "LogStreamNamePrefix": "CustomPrefix", "LogLevel": { "Default": "Debug", "System": "Information", diff --git a/test/AWS.Logger.Log4Net.Tests/log4net.config b/test/AWS.Logger.Log4Net.Tests/log4net.config index f14999b..18456a0 100644 --- a/test/AWS.Logger.Log4Net.Tests/log4net.config +++ b/test/AWS.Logger.Log4Net.Tests/log4net.config @@ -7,16 +7,17 @@ AWSLog4NetGroupLog4Net us-west-2 Custom - + CustomPrefix + - + - + \ No newline at end of file diff --git a/test/AWS.Logger.NLog.Tests/Regular.config b/test/AWS.Logger.NLog.Tests/Regular.config index 941492a..1312b8a 100644 --- a/test/AWS.Logger.NLog.Tests/Regular.config +++ b/test/AWS.Logger.NLog.Tests/Regular.config @@ -5,7 +5,7 @@ - + diff --git a/test/AWS.Logger.SeriLog.Tests/AWSSeriLogGroup.json b/test/AWS.Logger.SeriLog.Tests/AWSSeriLogGroup.json index fe80b70..956c3c4 100644 --- a/test/AWS.Logger.SeriLog.Tests/AWSSeriLogGroup.json +++ b/test/AWS.Logger.SeriLog.Tests/AWSSeriLogGroup.json @@ -5,6 +5,7 @@ "LogGroup": "AWSSeriLogGroup", "Region": "us-west-2", "LogStreamNameSuffix": "Custom", + "LogStreamNamePrefix": "CustomPrefix", "Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ] } } \ No newline at end of file diff --git a/test/AWS.Logger.TestUtils/BaseTestClass.cs b/test/AWS.Logger.TestUtils/BaseTestClass.cs index 991ad6c..699706e 100644 --- a/test/AWS.Logger.TestUtils/BaseTestClass.cs +++ b/test/AWS.Logger.TestUtils/BaseTestClass.cs @@ -19,6 +19,7 @@ public abstract class BaseTestClass : IClassFixture public const int THREAD_COUNT = 2; public const string LASTMESSAGE = "LASTMESSAGE"; public const string CUSTOMSTREAMSUFFIX = "Custom"; + public const string CUSTOMSTREAMPREFIX = "CustomPrefix"; public TestFixture _testFixture; public AmazonCloudWatchLogsClient Client; @@ -105,12 +106,15 @@ protected void SimpleLoggingTest(string logGroupName) var customStreamSuffix = describeLogstreamsResponse.LogStreams[0].LogStreamName.Split('-').Last().Trim(); Assert.Equal(CUSTOMSTREAMSUFFIX, customStreamSuffix); + var customStreamPrefix = describeLogstreamsResponse.LogStreams[0].LogStreamName.Split('-').First().Trim(); + Assert.Equal(CUSTOMSTREAMPREFIX, customStreamPrefix); } Assert.Equal(SIMPLELOGTEST_COUNT, getLogEventsResponse.Events.Count()); _testFixture.LogGroupNameList.Add(logGroupName); } + protected void MultiThreadTestGroup(string logGroupName) {