From e3a596d1f341f5753476bbe0b18e2fbb09456a08 Mon Sep 17 00:00:00 2001 From: Amir Khairalomoum Date: Wed, 23 Feb 2022 16:08:02 +0000 Subject: [PATCH 1/9] extend logging functionality to accept extra keys --- .../Internal/PowertoolsLogger.cs | 60 +++++- .../Internal/PowertoolsLoggerScope.cs | 21 ++ .../AWS.Lambda.Powertools.Logging/Logger.cs | 82 +++++++ .../LoggerExtensions.cs | 89 ++++++++ .../PowertoolsLoggerTest.cs | 203 ++++++++++++++++-- 5 files changed, 433 insertions(+), 22 deletions(-) create mode 100644 libraries/src/AWS.Lambda.Powertools.Logging/Internal/PowertoolsLoggerScope.cs diff --git a/libraries/src/AWS.Lambda.Powertools.Logging/Internal/PowertoolsLogger.cs b/libraries/src/AWS.Lambda.Powertools.Logging/Internal/PowertoolsLogger.cs index abe523d2d..aa8f16b78 100644 --- a/libraries/src/AWS.Lambda.Powertools.Logging/Internal/PowertoolsLogger.cs +++ b/libraries/src/AWS.Lambda.Powertools.Logging/Internal/PowertoolsLogger.cs @@ -94,6 +94,8 @@ public PowertoolsLogger( ? CurrentConfig.Service : _powertoolsConfigurations.Service; + internal PowertoolsLoggerScope CurrentScope { get; private set; } + /// /// Begins the scope. /// @@ -102,7 +104,53 @@ public PowertoolsLogger( /// System.IDisposable. public IDisposable BeginScope(TState state) { - return default!; + CurrentScope = new PowertoolsLoggerScope(this, GetScopeKeys(state)); + return CurrentScope; + } + + internal void EndScope() + { + CurrentScope = null; + } + + private static Dictionary GetScopeKeys(TState state) + { + var keys = new Dictionary(); + + if (state is null) + return keys; + + switch (state) + { + case IEnumerable> pairs: + { + foreach (var (key, value) in pairs) + { + if (!string.IsNullOrWhiteSpace(key)) + keys.TryAdd(key, value); + } + break; + } + case IEnumerable> pairs: + { + foreach (var (key, value) in pairs) + { + if (!string.IsNullOrWhiteSpace(key)) + keys.TryAdd(key, value); + } + break; + } + default: + { + foreach (var property in state.GetType().GetProperties()) + { + keys.TryAdd(property.Name, property.GetValue(state)); + } + break; + } + } + + return keys; } /// @@ -149,6 +197,16 @@ public void Log(LogLevel logLevel, EventId eventId, TState state, Except message.TryAdd(LoggingConstants.KeyFunctionRequestId, PowertoolsLambdaContext.Instance.AwsRequestId); } + // Add Extra Fields + if (CurrentScope?.ExtraKeys is not null) + { + foreach (var (key, value) in CurrentScope.ExtraKeys) + { + if (!string.IsNullOrWhiteSpace(key)) + message.TryAdd(key, value); + } + } + message.TryAdd(LoggingConstants.KeyTimestamp, DateTime.UtcNow.ToString("o")); message.TryAdd(LoggingConstants.KeyLogLevel, logLevel.ToString()); message.TryAdd(LoggingConstants.KeyService, Service); diff --git a/libraries/src/AWS.Lambda.Powertools.Logging/Internal/PowertoolsLoggerScope.cs b/libraries/src/AWS.Lambda.Powertools.Logging/Internal/PowertoolsLoggerScope.cs new file mode 100644 index 000000000..99d71e0a9 --- /dev/null +++ b/libraries/src/AWS.Lambda.Powertools.Logging/Internal/PowertoolsLoggerScope.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; + +namespace AWS.Lambda.Powertools.Logging.Internal; + +internal class PowertoolsLoggerScope : IDisposable +{ + private readonly PowertoolsLogger _logger; + internal Dictionary ExtraKeys { get; } + + internal PowertoolsLoggerScope(PowertoolsLogger logger, Dictionary extraKeys) + { + _logger = logger; + ExtraKeys = extraKeys; + } + + public void Dispose() + { + _logger?.EndScope(); + } +} \ No newline at end of file diff --git a/libraries/src/AWS.Lambda.Powertools.Logging/Logger.cs b/libraries/src/AWS.Lambda.Powertools.Logging/Logger.cs index 4b2189fc0..b6a932d88 100644 --- a/libraries/src/AWS.Lambda.Powertools.Logging/Logger.cs +++ b/libraries/src/AWS.Lambda.Powertools.Logging/Logger.cs @@ -676,6 +676,88 @@ public static void Log(LogLevel logLevel, object message) LoggerInstance.Log(logLevel, message); } + #endregion + + #region ExtraKeys Logger Extentions + + /// + /// Formats and writes a log message at the specified log level. + /// + /// Additional keys will be appended to the log entry. + /// Format string of the log message. + /// An object array that contains zero or more objects to format. + public static void LogTrace(T extraKeys, string message, params object[] args) where T : class + { + LoggerInstance.LogTrace(extraKeys, message, args); + } + + /// + /// Formats and writes a log message at the specified log level. + /// + /// Additional keys will be appended to the log entry. + /// Format string of the log message. + /// An object array that contains zero or more objects to format. + public static void LogDebug(T extraKeys, string message, params object[] args) where T : class + { + LoggerInstance.LogDebug(extraKeys, message, args); + } + + /// + /// Formats and writes a log message at the specified log level. + /// + /// Additional keys will be appended to the log entry. + /// Format string of the log message. + /// An object array that contains zero or more objects to format. + public static void LogInformation(T extraKeys, string message, params object[] args) where T : class + { + LoggerInstance.LogInformation(extraKeys, message, args); + } + + /// + /// Formats and writes a log message at the specified log level. + /// + /// Additional keys will be appended to the log entry. + /// Format string of the log message. + /// An object array that contains zero or more objects to format. + public static void LogWarning(T extraKeys, string message, params object[] args) where T : class + { + LoggerInstance.LogWarning(extraKeys, message, args); + } + + /// + /// Formats and writes a log message at the specified log level. + /// + /// Additional keys will be appended to the log entry. + /// Format string of the log message. + /// An object array that contains zero or more objects to format. + public static void LogError(T extraKeys, string message, params object[] args) where T : class + { + LoggerInstance.LogError(extraKeys, message, args); + } + + /// + /// Formats and writes a log message at the specified log level. + /// + /// Additional keys will be appended to the log entry. + /// Format string of the log message. + /// An object array that contains zero or more objects to format. + public static void LogCritical(T extraKeys, string message, params object[] args) where T : class + { + LoggerInstance.LogCritical(extraKeys, message, args); + } + + /// + /// Formats and writes a log message at the specified log level. + /// + /// Entry will be written on this level. + /// Additional keys will be appended to the log entry. + /// Format string of the log message. + /// An object array that contains zero or more objects to format. + public static void Log(LogLevel logLevel, T extraKeys, string message, params object[] args) where T : class + { + LoggerInstance.Log(logLevel, message, args); + } + #endregion #endregion diff --git a/libraries/src/AWS.Lambda.Powertools.Logging/LoggerExtensions.cs b/libraries/src/AWS.Lambda.Powertools.Logging/LoggerExtensions.cs index 574c4aa73..adc483011 100644 --- a/libraries/src/AWS.Lambda.Powertools.Logging/LoggerExtensions.cs +++ b/libraries/src/AWS.Lambda.Powertools.Logging/LoggerExtensions.cs @@ -100,4 +100,93 @@ public static void Log(this ILogger logger, LogLevel logLevel, object message) { logger.Log(logLevel, LoggingConstants.KeyJsonFormatter, message); } + + /// + /// Formats and writes a log message at the specified log level. + /// + /// The to write to. + /// Additional keys will be appended to the log entry. + /// Format string of the log message. + /// An object array that contains zero or more objects to format. + public static void LogTrace(this ILogger logger, T extraKeys, string message, params object[] args) where T : class + { + Log(logger, LogLevel.Trace, extraKeys, message, args); + } + + /// + /// Formats and writes a log message at the specified log level. + /// + /// The to write to. + /// Additional keys will be appended to the log entry. + /// Format string of the log message. + /// An object array that contains zero or more objects to format. + public static void LogDebug(this ILogger logger, T extraKeys, string message, params object[] args) where T : class + { + Log(logger, LogLevel.Debug, extraKeys, message, args); + } + + /// + /// Formats and writes a log message at the specified log level. + /// + /// The to write to. + /// Additional keys will be appended to the log entry. + /// Format string of the log message. + /// An object array that contains zero or more objects to format. + public static void LogInformation(this ILogger logger, T extraKeys, string message, params object[] args) where T : class + { + Log(logger, LogLevel.Information, extraKeys, message, args); + } + + /// + /// Formats and writes a log message at the specified log level. + /// + /// The to write to. + /// Additional keys will be appended to the log entry. + /// Format string of the log message. + /// An object array that contains zero or more objects to format. + public static void LogWarning(this ILogger logger, T extraKeys, string message, params object[] args) where T : class + { + Log(logger, LogLevel.Warning, extraKeys, message, args); + } + + /// + /// Formats and writes a log message at the specified log level. + /// + /// The to write to. + /// Additional keys will be appended to the log entry. + /// Format string of the log message. + /// An object array that contains zero or more objects to format. + public static void LogError(this ILogger logger, T extraKeys, string message, params object[] args) where T : class + { + Log(logger, LogLevel.Error, extraKeys, message, args); + } + + /// + /// Formats and writes a log message at the specified log level. + /// + /// The to write to. + /// Additional keys will be appended to the log entry. + /// Format string of the log message. + /// An object array that contains zero or more objects to format. + public static void LogCritical(this ILogger logger, T extraKeys, string message, params object[] args) where T : class + { + Log(logger, LogLevel.Critical, extraKeys, message, args); + } + + /// + /// Formats and writes a log message at the specified log level. + /// + /// The to write to. + /// Entry will be written on this level. + /// Additional keys will be appended to the log entry. + /// Format string of the log message. + /// An object array that contains zero or more objects to format. + public static void Log(this ILogger logger, LogLevel logLevel, T extraKeys, string message, params object[] args) where T : class + { + if (extraKeys is not null) + using (logger.BeginScope(extraKeys)) + logger.Log(logLevel, message, args); + else + logger.Log(logLevel, message, args); + } } \ No newline at end of file diff --git a/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/PowertoolsLoggerTest.cs b/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/PowertoolsLoggerTest.cs index d2c78dad1..3aa1be773 100644 --- a/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/PowertoolsLoggerTest.cs +++ b/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/PowertoolsLoggerTest.cs @@ -14,7 +14,9 @@ */ using System; +using System.Collections.Generic; using System.Globalization; +using System.Linq; using AWS.Lambda.Powertools.Common; using AWS.Lambda.Powertools.Logging.Internal; using Microsoft.Extensions.Logging; @@ -25,7 +27,7 @@ namespace AWS.Lambda.Powertools.Logging.Tests { public class PowertoolsLoggerTest { - private void Log_WhenMinimumLevelIsBelowLogLevel_Logs(LogLevel logLevel, LogLevel minimumLevel) + private static void Log_WhenMinimumLevelIsBelowLogLevel_Logs(LogLevel logLevel, LogLevel minimumLevel) { // Arrange var loggerName = Guid.NewGuid().ToString(); @@ -45,22 +47,22 @@ private void Log_WhenMinimumLevelIsBelowLogLevel_Logs(LogLevel logLevel, LogLeve { // Act case LogLevel.Critical: - LoggerExtensions.LogCritical(logger, "Test"); + logger.LogCritical("Test"); break; case LogLevel.Debug: - LoggerExtensions.LogDebug(logger, "Test"); + logger.LogDebug("Test"); break; case LogLevel.Error: - LoggerExtensions.LogError(logger, "Test"); + logger.LogError("Test"); break; case LogLevel.Information: - LoggerExtensions.LogInformation(logger, "Test"); + logger.LogInformation("Test"); break; case LogLevel.Trace: - LoggerExtensions.LogTrace(logger, "Test"); + logger.LogTrace("Test"); break; case LogLevel.Warning: - LoggerExtensions.LogWarning(logger, "Test"); + logger.LogWarning("Test"); break; case LogLevel.None: break; @@ -76,7 +78,7 @@ private void Log_WhenMinimumLevelIsBelowLogLevel_Logs(LogLevel logLevel, LogLeve } - private void Log_WhenMinimumLevelIsAboveLogLevel_DoesNotLog(LogLevel logLevel, LogLevel minimumLevel) + private static void Log_WhenMinimumLevelIsAboveLogLevel_DoesNotLog(LogLevel logLevel, LogLevel minimumLevel) { // Arrange var loggerName = Guid.NewGuid().ToString(); @@ -96,22 +98,22 @@ private void Log_WhenMinimumLevelIsAboveLogLevel_DoesNotLog(LogLevel logLevel, L { // Act case LogLevel.Critical: - LoggerExtensions.LogCritical(logger, "Test"); + logger.LogCritical("Test"); break; case LogLevel.Debug: - LoggerExtensions.LogDebug(logger, "Test"); + logger.LogDebug("Test"); break; case LogLevel.Error: - LoggerExtensions.LogError(logger, "Test"); + logger.LogError("Test"); break; case LogLevel.Information: - LoggerExtensions.LogInformation(logger, "Test"); + logger.LogInformation("Test"); break; case LogLevel.Trace: - LoggerExtensions.LogTrace(logger, "Test"); + logger.LogTrace("Test"); break; case LogLevel.Warning: - LoggerExtensions.LogWarning(logger, "Test"); + logger.LogWarning("Test"); break; case LogLevel.None: break; @@ -268,7 +270,7 @@ public void Log_ConfigurationIsNotProvided_ReadsFromEnvironmentVariables() MinimumLevel = null }); - LoggerExtensions.LogInformation(logger, "Test"); + logger.LogInformation("Test"); // Assert systemWrapper.Verify(v => @@ -306,7 +308,7 @@ public void Log_SamplingRateGreaterThanRandom_ChangedLogLevelToDebug() MinimumLevel = null }); - LoggerExtensions.LogInformation(logger, "Test"); + logger.LogInformation("Test"); // Assert systemWrapper.Verify(v => @@ -342,7 +344,7 @@ public void Log_SamplingRateGreaterThanOne_SkipsSamplingRateConfiguration() MinimumLevel = null }); - LoggerExtensions.LogInformation(logger, "Test"); + logger.LogInformation("Test"); // Assert systemWrapper.Verify(v => @@ -384,7 +386,7 @@ public void Log_SetsCaseToCamelCase_OutputsCamelCaseLog() PropTwo = "Value 2" }; - LoggerExtensions.LogInformation(logger, message); + logger.LogInformation(message); // Assert systemWrapper.Verify(v => @@ -426,7 +428,7 @@ public void Log_SetsCaseToPascalCase_OutputsPascalCaseLog() PropTwo = "Value 2" }; - LoggerExtensions.LogInformation(logger, message); + logger.LogInformation(message); // Assert systemWrapper.Verify(v => @@ -468,7 +470,7 @@ public void Log_SetsCaseToSnakeCase_OutputsSnakeCaseLog() PropTwo = "Value 2" }; - LoggerExtensions.LogInformation(logger, message); + logger.LogInformation(message); // Assert systemWrapper.Verify(v => @@ -509,7 +511,7 @@ public void Log_NoOutputCaseSet_OutputDefaultsToSnakeCaseLog() PropTwo = "Value 2" }; - LoggerExtensions.LogInformation(logger, message); + logger.LogInformation(message); // Assert systemWrapper.Verify(v => @@ -520,5 +522,164 @@ public void Log_NoOutputCaseSet_OutputDefaultsToSnakeCaseLog() ) ), Times.Once); } + + [Fact] + public void BeginScope_WhenScopeIsObject_ExtractScopeKeys() + { + // Arrange + var loggerName = Guid.NewGuid().ToString(); + var service = Guid.NewGuid().ToString(); + var logLevel = LogLevel.Information; + + var configurations = new Mock(); + configurations.Setup(c => c.Service).Returns(service); + configurations.Setup(c => c.LogLevel).Returns(logLevel.ToString); + var systemWrapper = new Mock(); + + var logger = new PowertoolsLogger(loggerName,configurations.Object, systemWrapper.Object, () => + new LoggerConfiguration + { + Service = service, + MinimumLevel = logLevel + }); + + var scopeKeys = new + { + PropOne = "Value 1", + PropTwo = "Value 2" + }; + + using (var loggerScope = logger.BeginScope(scopeKeys) as PowertoolsLoggerScope) + { + Assert.NotNull(loggerScope); + Assert.NotNull(loggerScope.ExtraKeys); + Assert.True(loggerScope.ExtraKeys.Count == 2); + Assert.True(loggerScope.ExtraKeys.ContainsKey("PropOne")); + Assert.True((string)loggerScope.ExtraKeys["PropOne"] == scopeKeys.PropOne); + Assert.True(loggerScope.ExtraKeys.ContainsKey("PropTwo")); + Assert.True((string)loggerScope.ExtraKeys["PropTwo"] == scopeKeys.PropTwo); + } + Assert.Null(logger.CurrentScope?.ExtraKeys); + } + + [Fact] + public void BeginScope_WhenScopeIsDictionary_ExtractScopeKeys() + { + // Arrange + var loggerName = Guid.NewGuid().ToString(); + var service = Guid.NewGuid().ToString(); + var logLevel = LogLevel.Information; + + var configurations = new Mock(); + configurations.Setup(c => c.Service).Returns(service); + configurations.Setup(c => c.LogLevel).Returns(logLevel.ToString); + var systemWrapper = new Mock(); + + var logger = new PowertoolsLogger(loggerName,configurations.Object, systemWrapper.Object, () => + new LoggerConfiguration + { + Service = service, + MinimumLevel = logLevel + }); + + var scopeKeys = new Dictionary + { + { "PropOne", "Value 1" }, + { "PropTwo", "Value 2" } + }; + + using (var loggerScope = logger.BeginScope(scopeKeys) as PowertoolsLoggerScope) + { + Assert.NotNull(loggerScope); + Assert.NotNull(loggerScope.ExtraKeys); + Assert.True(loggerScope.ExtraKeys.Count == 2); + Assert.True(loggerScope.ExtraKeys.ContainsKey("PropOne")); + Assert.True((string)loggerScope.ExtraKeys["PropOne"] == scopeKeys["PropOne"]); + Assert.True(loggerScope.ExtraKeys.ContainsKey("PropTwo")); + Assert.True((string)loggerScope.ExtraKeys["PropTwo"] == scopeKeys["PropTwo"]); + } + Assert.Null(logger.CurrentScope?.ExtraKeys); + } + + [Theory] + [InlineData(LogLevel.Trace, true)] + [InlineData(LogLevel.Debug, true)] + [InlineData(LogLevel.Information, true)] + [InlineData(LogLevel.Warning, true)] + [InlineData(LogLevel.Error, true)] + [InlineData(LogLevel.Critical, true)] + [InlineData(LogLevel.Trace, false)] + [InlineData(LogLevel.Debug, false)] + [InlineData(LogLevel.Information, false)] + [InlineData(LogLevel.Warning, false)] + [InlineData(LogLevel.Error, false)] + [InlineData(LogLevel.Critical, false)] + public void Log_WhenExtraKeysIsProvided_AppendExtraKeys(LogLevel logLevel, bool logMethod) + { + // Arrange + var loggerName = Guid.NewGuid().ToString(); + var service = Guid.NewGuid().ToString(); + var message = Guid.NewGuid().ToString(); + + var configurations = new Mock(); + configurations.Setup(c => c.Service).Returns(service); + configurations.Setup(c => c.LogLevel).Returns(logLevel.ToString); + configurations.Setup(c => c.LoggerOutputCase).Returns("PascalCase"); + var systemWrapper = new Mock(); + + var logger = new PowertoolsLogger(loggerName,configurations.Object, systemWrapper.Object, () => + new LoggerConfiguration + { + Service = service, + MinimumLevel = LogLevel.Trace, + }); + + var scopeKeys = new Dictionary + { + { "PropOne", "Value 1" }, + { "PropTwo", "Value 2" } + }; + + if(logMethod) + logger.Log(logLevel, scopeKeys, message); + else switch (logLevel) + { + case LogLevel.Trace: + logger.LogTrace(scopeKeys, message); + break; + case LogLevel.Debug: + logger.LogDebug(scopeKeys, message); + break; + case LogLevel.Information: + logger.LogInformation(scopeKeys, message); + break; + case LogLevel.Warning: + logger.LogWarning(scopeKeys, message); + break; + case LogLevel.Error: + logger.LogError(scopeKeys, message); + break; + case LogLevel.Critical: + logger.LogCritical(scopeKeys, message); + break; + case LogLevel.None: + break; + default: + throw new ArgumentOutOfRangeException(nameof(logLevel), logLevel, null); + } + + systemWrapper.Verify(v => + v.LogLine( + It.Is + (s=> + s.Contains(scopeKeys.Keys.First()) && + s.Contains(scopeKeys.Keys.Last()) && + s.Contains(scopeKeys.Values.First()) && + s.Contains(scopeKeys.Values.Last()) + ) + ), Times.Once); + + Assert.Null(logger.CurrentScope?.ExtraKeys); + } } } \ No newline at end of file From e5d022e08b38d13f52a81594289cb2765c666d61 Mon Sep 17 00:00:00 2001 From: Amir Khairalomoum Date: Wed, 23 Feb 2022 16:25:53 +0000 Subject: [PATCH 2/9] add documentations --- .../Internal/PowertoolsLogger.cs | 9 + .../Internal/PowertoolsLoggerScope.cs | 16 ++ .../PowertoolsLoggerTest.cs | 164 +++++++++++++++++- 3 files changed, 188 insertions(+), 1 deletion(-) diff --git a/libraries/src/AWS.Lambda.Powertools.Logging/Internal/PowertoolsLogger.cs b/libraries/src/AWS.Lambda.Powertools.Logging/Internal/PowertoolsLogger.cs index aa8f16b78..c7696a6b8 100644 --- a/libraries/src/AWS.Lambda.Powertools.Logging/Internal/PowertoolsLogger.cs +++ b/libraries/src/AWS.Lambda.Powertools.Logging/Internal/PowertoolsLogger.cs @@ -108,11 +108,20 @@ public IDisposable BeginScope(TState state) return CurrentScope; } + /// + /// Ends the scope. + /// internal void EndScope() { CurrentScope = null; } + /// + /// Extract provided scope keys + /// + /// The type of the t state. + /// The state. + /// Key/Value pair of provided scope keys private static Dictionary GetScopeKeys(TState state) { var keys = new Dictionary(); diff --git a/libraries/src/AWS.Lambda.Powertools.Logging/Internal/PowertoolsLoggerScope.cs b/libraries/src/AWS.Lambda.Powertools.Logging/Internal/PowertoolsLoggerScope.cs index 99d71e0a9..006f62938 100644 --- a/libraries/src/AWS.Lambda.Powertools.Logging/Internal/PowertoolsLoggerScope.cs +++ b/libraries/src/AWS.Lambda.Powertools.Logging/Internal/PowertoolsLoggerScope.cs @@ -3,17 +3,33 @@ namespace AWS.Lambda.Powertools.Logging.Internal; +/// +/// Class PowertoolsLoggerScope. +/// internal class PowertoolsLoggerScope : IDisposable { + /// + /// The associated logger + /// private readonly PowertoolsLogger _logger; + + /// + /// The provided extra keys + /// internal Dictionary ExtraKeys { get; } + /// + /// Creates a PowertoolsLoggerScope object + /// internal PowertoolsLoggerScope(PowertoolsLogger logger, Dictionary extraKeys) { _logger = logger; ExtraKeys = extraKeys; } + /// + /// Implements IDisposable interface + /// public void Dispose() { _logger?.EndScope(); diff --git a/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/PowertoolsLoggerTest.cs b/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/PowertoolsLoggerTest.cs index 3aa1be773..608d1ae64 100644 --- a/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/PowertoolsLoggerTest.cs +++ b/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/PowertoolsLoggerTest.cs @@ -614,7 +614,88 @@ public void BeginScope_WhenScopeIsDictionary_ExtractScopeKeys() [InlineData(LogLevel.Warning, false)] [InlineData(LogLevel.Error, false)] [InlineData(LogLevel.Critical, false)] - public void Log_WhenExtraKeysIsProvided_AppendExtraKeys(LogLevel logLevel, bool logMethod) + public void Log_WhenExtraKeysIsStringDictionary_AppendExtraKeys(LogLevel logLevel, bool logMethod) + { + // Arrange + var loggerName = Guid.NewGuid().ToString(); + var service = Guid.NewGuid().ToString(); + var message = Guid.NewGuid().ToString(); + + var configurations = new Mock(); + configurations.Setup(c => c.Service).Returns(service); + configurations.Setup(c => c.LogLevel).Returns(logLevel.ToString); + configurations.Setup(c => c.LoggerOutputCase).Returns("PascalCase"); + var systemWrapper = new Mock(); + + var logger = new PowertoolsLogger(loggerName,configurations.Object, systemWrapper.Object, () => + new LoggerConfiguration + { + Service = service, + MinimumLevel = LogLevel.Trace, + }); + + var scopeKeys = new Dictionary + { + { "PropOne", "Value 1" }, + { "PropTwo", "Value 2" } + }; + + if(logMethod) + logger.Log(logLevel, scopeKeys, message); + else switch (logLevel) + { + case LogLevel.Trace: + logger.LogTrace(scopeKeys, message); + break; + case LogLevel.Debug: + logger.LogDebug(scopeKeys, message); + break; + case LogLevel.Information: + logger.LogInformation(scopeKeys, message); + break; + case LogLevel.Warning: + logger.LogWarning(scopeKeys, message); + break; + case LogLevel.Error: + logger.LogError(scopeKeys, message); + break; + case LogLevel.Critical: + logger.LogCritical(scopeKeys, message); + break; + case LogLevel.None: + break; + default: + throw new ArgumentOutOfRangeException(nameof(logLevel), logLevel, null); + } + + systemWrapper.Verify(v => + v.LogLine( + It.Is + (s=> + s.Contains(scopeKeys.Keys.First()) && + s.Contains(scopeKeys.Keys.Last()) && + s.Contains(scopeKeys.Values.First().ToString()) && + s.Contains(scopeKeys.Values.Last().ToString()) + ) + ), Times.Once); + + Assert.Null(logger.CurrentScope?.ExtraKeys); + } + + [Theory] + [InlineData(LogLevel.Trace, true)] + [InlineData(LogLevel.Debug, true)] + [InlineData(LogLevel.Information, true)] + [InlineData(LogLevel.Warning, true)] + [InlineData(LogLevel.Error, true)] + [InlineData(LogLevel.Critical, true)] + [InlineData(LogLevel.Trace, false)] + [InlineData(LogLevel.Debug, false)] + [InlineData(LogLevel.Information, false)] + [InlineData(LogLevel.Warning, false)] + [InlineData(LogLevel.Error, false)] + [InlineData(LogLevel.Critical, false)] + public void Log_WhenExtraKeysIsObjectDictionary_AppendExtraKeys(LogLevel logLevel, bool logMethod) { // Arrange var loggerName = Guid.NewGuid().ToString(); @@ -681,5 +762,86 @@ public void Log_WhenExtraKeysIsProvided_AppendExtraKeys(LogLevel logLevel, bool Assert.Null(logger.CurrentScope?.ExtraKeys); } + + [Theory] + [InlineData(LogLevel.Trace, true)] + [InlineData(LogLevel.Debug, true)] + [InlineData(LogLevel.Information, true)] + [InlineData(LogLevel.Warning, true)] + [InlineData(LogLevel.Error, true)] + [InlineData(LogLevel.Critical, true)] + [InlineData(LogLevel.Trace, false)] + [InlineData(LogLevel.Debug, false)] + [InlineData(LogLevel.Information, false)] + [InlineData(LogLevel.Warning, false)] + [InlineData(LogLevel.Error, false)] + [InlineData(LogLevel.Critical, false)] + public void Log_WhenExtraKeysAsObject_AppendExtraKeys(LogLevel logLevel, bool logMethod) + { + // Arrange + var loggerName = Guid.NewGuid().ToString(); + var service = Guid.NewGuid().ToString(); + var message = Guid.NewGuid().ToString(); + + var configurations = new Mock(); + configurations.Setup(c => c.Service).Returns(service); + configurations.Setup(c => c.LogLevel).Returns(logLevel.ToString); + configurations.Setup(c => c.LoggerOutputCase).Returns("PascalCase"); + var systemWrapper = new Mock(); + + var logger = new PowertoolsLogger(loggerName,configurations.Object, systemWrapper.Object, () => + new LoggerConfiguration + { + Service = service, + MinimumLevel = LogLevel.Trace, + }); + + var scopeKeys = new + { + PropOne = "Value 1", + PropTwo = "Value 2" + }; + + if(logMethod) + logger.Log(logLevel, scopeKeys, message); + else switch (logLevel) + { + case LogLevel.Trace: + logger.LogTrace(scopeKeys, message); + break; + case LogLevel.Debug: + logger.LogDebug(scopeKeys, message); + break; + case LogLevel.Information: + logger.LogInformation(scopeKeys, message); + break; + case LogLevel.Warning: + logger.LogWarning(scopeKeys, message); + break; + case LogLevel.Error: + logger.LogError(scopeKeys, message); + break; + case LogLevel.Critical: + logger.LogCritical(scopeKeys, message); + break; + case LogLevel.None: + break; + default: + throw new ArgumentOutOfRangeException(nameof(logLevel), logLevel, null); + } + + systemWrapper.Verify(v => + v.LogLine( + It.Is + (s=> + s.Contains("PropOne") && + s.Contains("PropTwo") && + s.Contains(scopeKeys.PropOne) && + s.Contains(scopeKeys.PropTwo) + ) + ), Times.Once); + + Assert.Null(logger.CurrentScope?.ExtraKeys); + } } } \ No newline at end of file From 4d373461101165643d45e8d445c08fe437dfb016 Mon Sep 17 00:00:00 2001 From: Amir Khairalomoum Date: Wed, 23 Feb 2022 16:32:35 +0000 Subject: [PATCH 3/9] clean up --- .../PowertoolsLoggerTest.cs | 45 +++++++++++++++++-- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/PowertoolsLoggerTest.cs b/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/PowertoolsLoggerTest.cs index 608d1ae64..0c44f05e6 100644 --- a/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/PowertoolsLoggerTest.cs +++ b/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/PowertoolsLoggerTest.cs @@ -563,7 +563,46 @@ public void BeginScope_WhenScopeIsObject_ExtractScopeKeys() } [Fact] - public void BeginScope_WhenScopeIsDictionary_ExtractScopeKeys() + public void BeginScope_WhenScopeIsObjectDictionary_ExtractScopeKeys() + { + // Arrange + var loggerName = Guid.NewGuid().ToString(); + var service = Guid.NewGuid().ToString(); + var logLevel = LogLevel.Information; + + var configurations = new Mock(); + configurations.Setup(c => c.Service).Returns(service); + configurations.Setup(c => c.LogLevel).Returns(logLevel.ToString); + var systemWrapper = new Mock(); + + var logger = new PowertoolsLogger(loggerName,configurations.Object, systemWrapper.Object, () => + new LoggerConfiguration + { + Service = service, + MinimumLevel = logLevel + }); + + var scopeKeys = new Dictionary + { + { "PropOne", "Value 1" }, + { "PropTwo", "Value 2" } + }; + + using (var loggerScope = logger.BeginScope(scopeKeys) as PowertoolsLoggerScope) + { + Assert.NotNull(loggerScope); + Assert.NotNull(loggerScope.ExtraKeys); + Assert.True(loggerScope.ExtraKeys.Count == 2); + Assert.True(loggerScope.ExtraKeys.ContainsKey("PropOne")); + Assert.True(loggerScope.ExtraKeys["PropOne"] == scopeKeys["PropOne"]); + Assert.True(loggerScope.ExtraKeys.ContainsKey("PropTwo")); + Assert.True(loggerScope.ExtraKeys["PropTwo"] == scopeKeys["PropTwo"]); + } + Assert.Null(logger.CurrentScope?.ExtraKeys); + } + + [Fact] + public void BeginScope_WhenScopeIsStringDictionary_ExtractScopeKeys() { // Arrange var loggerName = Guid.NewGuid().ToString(); @@ -614,7 +653,7 @@ public void BeginScope_WhenScopeIsDictionary_ExtractScopeKeys() [InlineData(LogLevel.Warning, false)] [InlineData(LogLevel.Error, false)] [InlineData(LogLevel.Critical, false)] - public void Log_WhenExtraKeysIsStringDictionary_AppendExtraKeys(LogLevel logLevel, bool logMethod) + public void Log_WhenExtraKeysIsObjectDictionary_AppendExtraKeys(LogLevel logLevel, bool logMethod) { // Arrange var loggerName = Guid.NewGuid().ToString(); @@ -695,7 +734,7 @@ public void Log_WhenExtraKeysIsStringDictionary_AppendExtraKeys(LogLevel logLeve [InlineData(LogLevel.Warning, false)] [InlineData(LogLevel.Error, false)] [InlineData(LogLevel.Critical, false)] - public void Log_WhenExtraKeysIsObjectDictionary_AppendExtraKeys(LogLevel logLevel, bool logMethod) + public void Log_WhenExtraKeysIsStringDictionary_AppendExtraKeys(LogLevel logLevel, bool logMethod) { // Arrange var loggerName = Guid.NewGuid().ToString(); From 81cea8b66532e7708f1301d6c2f755c922b5f682 Mon Sep 17 00:00:00 2001 From: Amir Khairalomoum Date: Wed, 23 Feb 2022 16:43:41 +0000 Subject: [PATCH 4/9] move logger functions into their specific region --- .../AWS.Lambda.Powertools.Logging/Logger.cs | 142 +++++++++--------- 1 file changed, 69 insertions(+), 73 deletions(-) diff --git a/libraries/src/AWS.Lambda.Powertools.Logging/Logger.cs b/libraries/src/AWS.Lambda.Powertools.Logging/Logger.cs index b6a932d88..5121d1a8a 100644 --- a/libraries/src/AWS.Lambda.Powertools.Logging/Logger.cs +++ b/libraries/src/AWS.Lambda.Powertools.Logging/Logger.cs @@ -222,6 +222,17 @@ public static void LogDebug(object message) { LoggerInstance.LogDebug(message); } + + /// + /// Formats and writes a log message at the specified log level. + /// + /// Additional keys will be appended to the log entry. + /// Format string of the log message. + /// An object array that contains zero or more objects to format. + public static void LogDebug(T extraKeys, string message, params object[] args) where T : class + { + LoggerInstance.LogDebug(extraKeys, message, args); + } #endregion @@ -296,6 +307,17 @@ public static void LogTrace(object message) { LoggerInstance.LogTrace(message); } + + /// + /// Formats and writes a log message at the specified log level. + /// + /// Additional keys will be appended to the log entry. + /// Format string of the log message. + /// An object array that contains zero or more objects to format. + public static void LogTrace(T extraKeys, string message, params object[] args) where T : class + { + LoggerInstance.LogTrace(extraKeys, message, args); + } #endregion @@ -370,6 +392,17 @@ public static void LogInformation(object message) { LoggerInstance.LogInformation(message); } + + /// + /// Formats and writes a log message at the specified log level. + /// + /// Additional keys will be appended to the log entry. + /// Format string of the log message. + /// An object array that contains zero or more objects to format. + public static void LogInformation(T extraKeys, string message, params object[] args) where T : class + { + LoggerInstance.LogInformation(extraKeys, message, args); + } #endregion @@ -444,6 +477,17 @@ public static void LogWarning(object message) { LoggerInstance.LogWarning(message); } + + /// + /// Formats and writes a log message at the specified log level. + /// + /// Additional keys will be appended to the log entry. + /// Format string of the log message. + /// An object array that contains zero or more objects to format. + public static void LogWarning(T extraKeys, string message, params object[] args) where T : class + { + LoggerInstance.LogWarning(extraKeys, message, args); + } #endregion @@ -519,6 +563,17 @@ public static void LogError(object message) { LoggerInstance.LogError(message); } + + /// + /// Formats and writes a log message at the specified log level. + /// + /// Additional keys will be appended to the log entry. + /// Format string of the log message. + /// An object array that contains zero or more objects to format. + public static void LogError(T extraKeys, string message, params object[] args) where T : class + { + LoggerInstance.LogError(extraKeys, message, args); + } #endregion @@ -593,6 +648,17 @@ public static void LogCritical(object message) { LoggerInstance.LogCritical(message); } + + /// + /// Formats and writes a log message at the specified log level. + /// + /// Additional keys will be appended to the log entry. + /// Format string of the log message. + /// An object array that contains zero or more objects to format. + public static void LogCritical(T extraKeys, string message, params object[] args) where T : class + { + LoggerInstance.LogCritical(extraKeys, message, args); + } #endregion @@ -675,77 +741,7 @@ public static void Log(LogLevel logLevel, object message) { LoggerInstance.Log(logLevel, message); } - - #endregion - - #region ExtraKeys Logger Extentions - - /// - /// Formats and writes a log message at the specified log level. - /// - /// Additional keys will be appended to the log entry. - /// Format string of the log message. - /// An object array that contains zero or more objects to format. - public static void LogTrace(T extraKeys, string message, params object[] args) where T : class - { - LoggerInstance.LogTrace(extraKeys, message, args); - } - - /// - /// Formats and writes a log message at the specified log level. - /// - /// Additional keys will be appended to the log entry. - /// Format string of the log message. - /// An object array that contains zero or more objects to format. - public static void LogDebug(T extraKeys, string message, params object[] args) where T : class - { - LoggerInstance.LogDebug(extraKeys, message, args); - } - - /// - /// Formats and writes a log message at the specified log level. - /// - /// Additional keys will be appended to the log entry. - /// Format string of the log message. - /// An object array that contains zero or more objects to format. - public static void LogInformation(T extraKeys, string message, params object[] args) where T : class - { - LoggerInstance.LogInformation(extraKeys, message, args); - } - - /// - /// Formats and writes a log message at the specified log level. - /// - /// Additional keys will be appended to the log entry. - /// Format string of the log message. - /// An object array that contains zero or more objects to format. - public static void LogWarning(T extraKeys, string message, params object[] args) where T : class - { - LoggerInstance.LogWarning(extraKeys, message, args); - } - /// - /// Formats and writes a log message at the specified log level. - /// - /// Additional keys will be appended to the log entry. - /// Format string of the log message. - /// An object array that contains zero or more objects to format. - public static void LogError(T extraKeys, string message, params object[] args) where T : class - { - LoggerInstance.LogError(extraKeys, message, args); - } - - /// - /// Formats and writes a log message at the specified log level. - /// - /// Additional keys will be appended to the log entry. - /// Format string of the log message. - /// An object array that contains zero or more objects to format. - public static void LogCritical(T extraKeys, string message, params object[] args) where T : class - { - LoggerInstance.LogCritical(extraKeys, message, args); - } - /// /// Formats and writes a log message at the specified log level. /// @@ -755,10 +751,10 @@ public static void LogCritical(T extraKeys, string message, params object[] a /// An object array that contains zero or more objects to format. public static void Log(LogLevel logLevel, T extraKeys, string message, params object[] args) where T : class { - LoggerInstance.Log(logLevel, message, args); + LoggerInstance.Log(logLevel, extraKeys, message, args); } - - #endregion #endregion + + #endregion } \ No newline at end of file From 4705ef142d06fbc80ae8b2866773e3139244bc45 Mon Sep 17 00:00:00 2001 From: Amir Khairalomoum Date: Thu, 24 Feb 2022 17:28:09 +0000 Subject: [PATCH 5/9] change logger outputcase from string to enum --- .../Internal/LoggingAspectHandler.cs | 11 +++- .../Internal/LoggingConstants.cs | 5 ++ .../Internal/PowertoolsConfigurations.cs | 12 ++++ .../Internal/PowertoolsLogger.cs | 55 ++++++++----------- .../LoggerConfiguration.cs | 2 +- .../LoggingAttribute.cs | 17 ++++++ .../LoggingAttributeTest.cs | 12 ++-- .../PowertoolsLoggerTest.cs | 12 ++-- 8 files changed, 81 insertions(+), 45 deletions(-) diff --git a/libraries/src/AWS.Lambda.Powertools.Logging/Internal/LoggingAspectHandler.cs b/libraries/src/AWS.Lambda.Powertools.Logging/Internal/LoggingAspectHandler.cs index ae7b421f6..2e649e297 100644 --- a/libraries/src/AWS.Lambda.Powertools.Logging/Internal/LoggingAspectHandler.cs +++ b/libraries/src/AWS.Lambda.Powertools.Logging/Internal/LoggingAspectHandler.cs @@ -58,6 +58,11 @@ internal class LoggingAspectHandler : IMethodAspectHandler /// The log level /// private readonly LogLevel? _logLevel; + + /// + /// The logger output case + /// + private readonly LoggerOutputCase? _loggerOutputCase; /// /// The Powertools configurations @@ -94,6 +99,7 @@ internal class LoggingAspectHandler : IMethodAspectHandler /// /// Service name /// The log level. + /// The logger output case. /// The sampling rate. /// if set to true [log event]. /// The correlation identifier path. @@ -104,6 +110,7 @@ internal LoggingAspectHandler ( string service, LogLevel? logLevel, + LoggerOutputCase? loggerOutputCase, double? samplingRate, bool? logEvent, string correlationIdPath, @@ -114,6 +121,7 @@ ISystemWrapper systemWrapper { _service = service; _logLevel = logLevel; + _loggerOutputCase = loggerOutputCase; _samplingRate = samplingRate; _logEvent = logEvent; _clearState = clearState; @@ -135,7 +143,8 @@ public void OnEntry(AspectEventArgs eventArgs) { Service = _service, MinimumLevel = _logLevel, - SamplingRate = _samplingRate + SamplingRate = _samplingRate, + LoggerOutputCase = _loggerOutputCase }; switch (Logger.LoggerProvider) diff --git a/libraries/src/AWS.Lambda.Powertools.Logging/Internal/LoggingConstants.cs b/libraries/src/AWS.Lambda.Powertools.Logging/Internal/LoggingConstants.cs index babe5aa51..1ff29c35f 100644 --- a/libraries/src/AWS.Lambda.Powertools.Logging/Internal/LoggingConstants.cs +++ b/libraries/src/AWS.Lambda.Powertools.Logging/Internal/LoggingConstants.cs @@ -26,6 +26,11 @@ internal static class LoggingConstants /// Constant for default log level /// internal const LogLevel DefaultLogLevel = LogLevel.Information; + + /// + /// Constant for default log output case + /// + internal const LoggerOutputCase DefaultLoggerOutputCase = LoggerOutputCase.SnakeCase; /// /// Constant for key json formatter diff --git a/libraries/src/AWS.Lambda.Powertools.Logging/Internal/PowertoolsConfigurations.cs b/libraries/src/AWS.Lambda.Powertools.Logging/Internal/PowertoolsConfigurations.cs index b56a82889..f05eca49c 100644 --- a/libraries/src/AWS.Lambda.Powertools.Logging/Internal/PowertoolsConfigurations.cs +++ b/libraries/src/AWS.Lambda.Powertools.Logging/Internal/PowertoolsConfigurations.cs @@ -41,4 +41,16 @@ internal static LogLevel GetLogLevel(this IPowertoolsConfigurations powertoolsCo return LoggingConstants.DefaultLogLevel; } + + internal static LoggerOutputCase GetLoggerOutputCase(this IPowertoolsConfigurations powertoolsConfigurations, + LoggerOutputCase? loggerOutputCase = null) + { + if (loggerOutputCase.HasValue) + return loggerOutputCase.Value; + + if (Enum.TryParse((powertoolsConfigurations.LoggerOutputCase ?? "").Trim(), true, out LoggerOutputCase result)) + return result; + + return LoggingConstants.DefaultLoggerOutputCase; + } } \ No newline at end of file diff --git a/libraries/src/AWS.Lambda.Powertools.Logging/Internal/PowertoolsLogger.cs b/libraries/src/AWS.Lambda.Powertools.Logging/Internal/PowertoolsLogger.cs index c7696a6b8..947dfb771 100644 --- a/libraries/src/AWS.Lambda.Powertools.Logging/Internal/PowertoolsLogger.cs +++ b/libraries/src/AWS.Lambda.Powertools.Logging/Internal/PowertoolsLogger.cs @@ -233,35 +233,28 @@ public void Log(LogLevel logLevel, EventId eventId, TState state, Except _systemWrapper.LogLine(JsonSerializer.Serialize(message, options)); } - internal JsonSerializerOptions BuildCaseSerializerOptions(){ - object LogCase; - Enum.TryParse(typeof(LoggerOutputCase), _currentConfig.LogOutputCase, true, out LogCase); - - if(LogCase != null){ - switch (LogCase) - { - case LoggerOutputCase.CamelCase: - return new(JsonSerializerDefaults.Web){ - PropertyNamingPolicy = JsonNamingPolicy.CamelCase, - DictionaryKeyPolicy = JsonNamingPolicy.CamelCase - }; - case LoggerOutputCase.PascalCase: - return new() { - PropertyNamingPolicy = PascalCaseNamingPolicy.Instance, - DictionaryKeyPolicy = PascalCaseNamingPolicy.Instance - }; - default: // Snake case is the default - return new() { - PropertyNamingPolicy = SnakeCaseNamingPolicy.Instance, - DictionaryKeyPolicy = SnakeCaseNamingPolicy.Instance - }; - } - } - else { - return new() { - PropertyNamingPolicy = SnakeCaseNamingPolicy.Instance, - DictionaryKeyPolicy = SnakeCaseNamingPolicy.Instance - }; + private JsonSerializerOptions BuildCaseSerializerOptions() + { + switch (CurrentConfig.LoggerOutputCase) + { + case LoggerOutputCase.CamelCase: + return new(JsonSerializerDefaults.Web) + { + PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + DictionaryKeyPolicy = JsonNamingPolicy.CamelCase + }; + case LoggerOutputCase.PascalCase: + return new() + { + PropertyNamingPolicy = PascalCaseNamingPolicy.Instance, + DictionaryKeyPolicy = PascalCaseNamingPolicy.Instance + }; + default: // Snake case is the default + return new() + { + PropertyNamingPolicy = SnakeCaseNamingPolicy.Instance, + DictionaryKeyPolicy = SnakeCaseNamingPolicy.Instance + }; } } @@ -282,14 +275,14 @@ private LoggerConfiguration GetCurrentConfig() var currConfig = _getCurrentConfig(); var minimumLevel = _powertoolsConfigurations.GetLogLevel(currConfig?.MinimumLevel); var samplingRate = currConfig?.SamplingRate ?? _powertoolsConfigurations.LoggerSampleRate; - var logOutputCase = _powertoolsConfigurations.LoggerOutputCase; + var loggerOutputCase = _powertoolsConfigurations.GetLoggerOutputCase(currConfig?.LoggerOutputCase); var config = new LoggerConfiguration { Service = currConfig?.Service, MinimumLevel = minimumLevel, SamplingRate = samplingRate, - LogOutputCase = logOutputCase + LoggerOutputCase = loggerOutputCase }; if (!samplingRate.HasValue) diff --git a/libraries/src/AWS.Lambda.Powertools.Logging/LoggerConfiguration.cs b/libraries/src/AWS.Lambda.Powertools.Logging/LoggerConfiguration.cs index c86b0f53d..54ef27a25 100644 --- a/libraries/src/AWS.Lambda.Powertools.Logging/LoggerConfiguration.cs +++ b/libraries/src/AWS.Lambda.Powertools.Logging/LoggerConfiguration.cs @@ -58,5 +58,5 @@ public class LoggerConfiguration : IOptions /// This can be also set using the environment variable POWERTOOLS_LOGGER_CASE. /// /// The logger output case. - public string LogOutputCase { get; set; } + public LoggerOutputCase? LoggerOutputCase { get; set; } } \ No newline at end of file diff --git a/libraries/src/AWS.Lambda.Powertools.Logging/LoggingAttribute.cs b/libraries/src/AWS.Lambda.Powertools.Logging/LoggingAttribute.cs index c898f752d..80c26aa0f 100644 --- a/libraries/src/AWS.Lambda.Powertools.Logging/LoggingAttribute.cs +++ b/libraries/src/AWS.Lambda.Powertools.Logging/LoggingAttribute.cs @@ -37,6 +37,11 @@ public class LoggingAttribute : MethodAspectAttribute /// The log level /// private LogLevel? _logLevel; + + /// + /// The logger output case + /// + private LoggerOutputCase? _loggerOutputCase; /// /// The sampling rate @@ -100,6 +105,17 @@ public bool LogEvent /// /// true if [clear state]; otherwise, false. public bool ClearState { get; set; } = false; + + /// + /// Specify output case for logging (SnakeCase, by default). + /// This can be also set using the environment variable POWERTOOLS_LOGGER_CASE. + /// + /// The log level. + public LoggerOutputCase LoggerOutputCase + { + get => _loggerOutputCase ?? LoggingConstants.DefaultLoggerOutputCase; + set => _loggerOutputCase = value; + } /// /// Creates the handler. @@ -111,6 +127,7 @@ protected override IMethodAspectHandler CreateHandler() ( Service, _logLevel, + _loggerOutputCase, _samplingRate, _logEvent, CorrelationIdPath, diff --git a/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/LoggingAttributeTest.cs b/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/LoggingAttributeTest.cs index 3f82643ff..55b0134b7 100644 --- a/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/LoggingAttributeTest.cs +++ b/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/LoggingAttributeTest.cs @@ -49,7 +49,7 @@ public void OnEntry_WhenLambdaContextDoesNotExist_IgnoresLambdaContext() }; LoggingAspectHandler.ResetForTest(); - var handler = new LoggingAspectHandler(service, logLevel, null, true, null, true, configurations.Object, + var handler = new LoggingAspectHandler(service, logLevel, null, null, true, null, true, configurations.Object, systemWrapper.Object); // Act @@ -95,7 +95,7 @@ public void OnEntry_WhenLambdaContextDoesNotExist_IgnoresLambdaContextAndLogDebu }; LoggingAspectHandler.ResetForTest(); - var handler = new LoggingAspectHandler(service, logLevel, null, true, null, true, configurations.Object, + var handler = new LoggingAspectHandler(service, logLevel, null, null, true, null, true, configurations.Object, systemWrapper.Object); // Act @@ -141,7 +141,7 @@ public void OnEntry_WhenEventArgDoesNotExist_DoesNotLogEventArg() }; LoggingAspectHandler.ResetForTest(); - var handler = new LoggingAspectHandler(service, logLevel, null, true, null, true, configurations.Object, + var handler = new LoggingAspectHandler(service, logLevel, null, null, true, null, true, configurations.Object, systemWrapper.Object); // Act @@ -175,7 +175,7 @@ public void OnEntry_WhenEventArgDoesNotExist_DoesNotLogEventArgAndLogDebug() }; LoggingAspectHandler.ResetForTest(); - var handler = new LoggingAspectHandler(service, logLevel, null, true, null, true, configurations.Object, + var handler = new LoggingAspectHandler(service, logLevel, null, null, true, null, true, configurations.Object, systemWrapper.Object); // Act @@ -209,7 +209,7 @@ public void OnExit_WhenHandler_ClearKeys() }; LoggingAspectHandler.ResetForTest(); - var handler = new LoggingAspectHandler(service, logLevel, null, true, null, true, configurations.Object, + var handler = new LoggingAspectHandler(service, logLevel, null, null, true, null, true, configurations.Object, systemWrapper.Object); // Act @@ -248,7 +248,7 @@ protected void OnEntry_WhenEventArgExists_CapturesCorrelationIdBase(string corre }; LoggingAspectHandler.ResetForTest(); - var handler = new LoggingAspectHandler(service, logLevel, null, false, correlationIdPath, + var handler = new LoggingAspectHandler(service, logLevel, null, null, false, correlationIdPath, true, configurations.Object, systemWrapper.Object); diff --git a/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/PowertoolsLoggerTest.cs b/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/PowertoolsLoggerTest.cs index 0c44f05e6..4dc00716e 100644 --- a/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/PowertoolsLoggerTest.cs +++ b/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/PowertoolsLoggerTest.cs @@ -369,7 +369,7 @@ public void Log_SetsCaseToCamelCase_OutputsCamelCaseLog() var configurations = new Mock(); configurations.Setup(c => c.Service).Returns(service); configurations.Setup(c => c.LogLevel).Returns(logLevel.ToString); - configurations.Setup(c => c.LoggerOutputCase).Returns("CamelCase"); + configurations.Setup(c => c.LoggerOutputCase).Returns(LoggerOutputCase.CamelCase.ToString); var systemWrapper = new Mock(); systemWrapper.Setup(c => c.GetRandom()).Returns(randomSampleRate); @@ -410,7 +410,7 @@ public void Log_SetsCaseToPascalCase_OutputsPascalCaseLog() var configurations = new Mock(); configurations.Setup(c => c.Service).Returns(service); configurations.Setup(c => c.LogLevel).Returns(logLevel.ToString); - configurations.Setup(c => c.LoggerOutputCase).Returns("PascalCase"); + configurations.Setup(c => c.LoggerOutputCase).Returns(LoggerOutputCase.PascalCase.ToString); var systemWrapper = new Mock(); systemWrapper.Setup(c => c.GetRandom()).Returns(randomSampleRate); @@ -452,7 +452,7 @@ public void Log_SetsCaseToSnakeCase_OutputsSnakeCaseLog() var configurations = new Mock(); configurations.Setup(c => c.Service).Returns(service); configurations.Setup(c => c.LogLevel).Returns(logLevel.ToString); - configurations.Setup(c => c.LoggerOutputCase).Returns("SnakeCase"); + configurations.Setup(c => c.LoggerOutputCase).Returns(LoggerOutputCase.SnakeCase.ToString); var systemWrapper = new Mock(); systemWrapper.Setup(c => c.GetRandom()).Returns(randomSampleRate); @@ -663,7 +663,7 @@ public void Log_WhenExtraKeysIsObjectDictionary_AppendExtraKeys(LogLevel logLeve var configurations = new Mock(); configurations.Setup(c => c.Service).Returns(service); configurations.Setup(c => c.LogLevel).Returns(logLevel.ToString); - configurations.Setup(c => c.LoggerOutputCase).Returns("PascalCase"); + configurations.Setup(c => c.LoggerOutputCase).Returns(LoggerOutputCase.PascalCase.ToString); var systemWrapper = new Mock(); var logger = new PowertoolsLogger(loggerName,configurations.Object, systemWrapper.Object, () => @@ -744,7 +744,7 @@ public void Log_WhenExtraKeysIsStringDictionary_AppendExtraKeys(LogLevel logLeve var configurations = new Mock(); configurations.Setup(c => c.Service).Returns(service); configurations.Setup(c => c.LogLevel).Returns(logLevel.ToString); - configurations.Setup(c => c.LoggerOutputCase).Returns("PascalCase"); + configurations.Setup(c => c.LoggerOutputCase).Returns(LoggerOutputCase.PascalCase.ToString); var systemWrapper = new Mock(); var logger = new PowertoolsLogger(loggerName,configurations.Object, systemWrapper.Object, () => @@ -825,7 +825,7 @@ public void Log_WhenExtraKeysAsObject_AppendExtraKeys(LogLevel logLevel, bool lo var configurations = new Mock(); configurations.Setup(c => c.Service).Returns(service); configurations.Setup(c => c.LogLevel).Returns(logLevel.ToString); - configurations.Setup(c => c.LoggerOutputCase).Returns("PascalCase"); + configurations.Setup(c => c.LoggerOutputCase).Returns(LoggerOutputCase.PascalCase.ToString); var systemWrapper = new Mock(); var logger = new PowertoolsLogger(loggerName,configurations.Object, systemWrapper.Object, () => From a25991850d45efe1cada409af344e6f924c202e6 Mon Sep 17 00:00:00 2001 From: Amir Khairalomoum Date: Thu, 24 Feb 2022 21:37:09 +0000 Subject: [PATCH 6/9] change the documentation text to fix the warning --- .../src/AWS.Lambda.Powertools.Logging/LoggerConfiguration.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/src/AWS.Lambda.Powertools.Logging/LoggerConfiguration.cs b/libraries/src/AWS.Lambda.Powertools.Logging/LoggerConfiguration.cs index 54ef27a25..da2297939 100644 --- a/libraries/src/AWS.Lambda.Powertools.Logging/LoggerConfiguration.cs +++ b/libraries/src/AWS.Lambda.Powertools.Logging/LoggerConfiguration.cs @@ -48,7 +48,7 @@ public class LoggerConfiguration : IOptions public double? SamplingRate { get; set; } /// - /// The default configured instance + /// The default configured options instance /// /// The value. LoggerConfiguration IOptions.Value => this; From a7d2e22111b8ab0bfc9c39348d66d20b0aaf8610 Mon Sep 17 00:00:00 2001 From: Amir Khairalomoum Date: Fri, 25 Feb 2022 15:28:37 +0000 Subject: [PATCH 7/9] add extra keys section to the documentation --- docs/core/logging.md | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/docs/core/logging.md b/docs/core/logging.md index f129f22ba..407c3c872 100644 --- a/docs/core/logging.md +++ b/docs/core/logging.md @@ -255,6 +255,39 @@ You can remove any additional key from entry using `Logger.RemoveKeys()`. } ``` +## Extra Keys + +Extra keys argument is available for all log levels' methods, as implemented in the standard logging library - e.g. Logger.Information, Logger.Warning. + +It accepts any dictionary, and all keyword arguments will be added as part of the root structure of the logs for that log statement. + +!!! info + Any keyword argument added using extra keys will not be persisted for subsequent messages. + +=== "Function.cs" + + ```c# hl_lines="16" + /** + * Handler for requests to Lambda function. + */ + public class Function + { + [Logging(LogEvent = true)] + public async Task FunctionHandler + (APIGatewayProxyRequest apigProxyEvent, ILambdaContext context) + { + ... + var extraKeys = new Dictionary + { + {"test1", "value1"} + }; + + Logger.LogInformation(extraKeys, "Collecting payment"); + ... + } + } + ``` + ### Clearing all state Logger is commonly initialized in the global scope. Due to [Lambda Execution Context reuse](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-context.html), this means that custom keys can be persisted across invocations. If you want all custom keys to be deleted, you can use `ClearState=true` attribute on `[Logging]` attribute. From fc2abadb53effefb83a0d6bacbaa5e35937ccdd9 Mon Sep 17 00:00:00 2001 From: Amir Khairalomoum Date: Fri, 25 Feb 2022 15:33:54 +0000 Subject: [PATCH 8/9] rename extra key variable --- docs/core/logging.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/core/logging.md b/docs/core/logging.md index 407c3c872..b9ca2a17d 100644 --- a/docs/core/logging.md +++ b/docs/core/logging.md @@ -279,7 +279,7 @@ It accepts any dictionary, and all keyword arguments will be added as part of th ... var extraKeys = new Dictionary { - {"test1", "value1"} + {"extraKey1", "value1"} }; Logger.LogInformation(extraKeys, "Collecting payment"); From 235c5134c4bf581edcdde2fd6e1dcb8c7ae39cec Mon Sep 17 00:00:00 2001 From: Amir Khairalomoum Date: Fri, 25 Feb 2022 21:20:37 +0000 Subject: [PATCH 9/9] extend extra keys functionalities to cover all methids, fix the exception serialization error --- examples/Logging/src/HelloWorld/Function.cs | 4 +- .../AWS.Lambda.Powertools.Logging/Logger.cs | 659 ++++++++++++++---- .../LoggerExtensions.cs | 491 ++++++++++++- .../Serializer/StringEnumConverter.cs | 2 +- 4 files changed, 1000 insertions(+), 156 deletions(-) diff --git a/examples/Logging/src/HelloWorld/Function.cs b/examples/Logging/src/HelloWorld/Function.cs index 4c8e9d085..4ef91a25a 100644 --- a/examples/Logging/src/HelloWorld/Function.cs +++ b/examples/Logging/src/HelloWorld/Function.cs @@ -91,12 +91,12 @@ public async Task FunctionHandler(APIGatewayProxyReques try { - Logger.LogInformation("Calling Check IP API "); + Logger.LogInformation("Calling Check IP API"); var response = await _httpClient.GetStringAsync("https://checkip.amazonaws.com/").ConfigureAwait(false); var ip = response.Replace("\n", ""); - Logger.LogInformation("API response returned {}", ip); + Logger.LogInformation($"API response returned {ip}"); return ip; } diff --git a/libraries/src/AWS.Lambda.Powertools.Logging/Logger.cs b/libraries/src/AWS.Lambda.Powertools.Logging/Logger.cs index 5121d1a8a..0989abac4 100644 --- a/libraries/src/AWS.Lambda.Powertools.Logging/Logger.cs +++ b/libraries/src/AWS.Lambda.Powertools.Logging/Logger.cs @@ -149,7 +149,7 @@ internal static void RemoveAllKeys() #endregion - #region Logger Functions + #region Core Logger Methods #region Debug @@ -213,27 +213,6 @@ public static void LogDebug(string message, params object[] args) LoggerInstance.LogDebug(message, args); } - /// - /// Formats and writes a debug log message as JSON. - /// - /// The object to be serialized as JSON. - /// Logger.LogDebug(new {User = user, Address = address}) - public static void LogDebug(object message) - { - LoggerInstance.LogDebug(message); - } - - /// - /// Formats and writes a log message at the specified log level. - /// - /// Additional keys will be appended to the log entry. - /// Format string of the log message. - /// An object array that contains zero or more objects to format. - public static void LogDebug(T extraKeys, string message, params object[] args) where T : class - { - LoggerInstance.LogDebug(extraKeys, message, args); - } - #endregion #region Trace @@ -298,27 +277,6 @@ public static void LogTrace(string message, params object[] args) LoggerInstance.LogTrace(message, args); } - /// - /// Formats and writes a trace log message as JSON. - /// - /// The object to be serialized as JSON. - /// Logger.LogTrace(new {User = user, Address = address}) - public static void LogTrace(object message) - { - LoggerInstance.LogTrace(message); - } - - /// - /// Formats and writes a log message at the specified log level. - /// - /// Additional keys will be appended to the log entry. - /// Format string of the log message. - /// An object array that contains zero or more objects to format. - public static void LogTrace(T extraKeys, string message, params object[] args) where T : class - { - LoggerInstance.LogTrace(extraKeys, message, args); - } - #endregion #region Information @@ -383,27 +341,6 @@ public static void LogInformation(string message, params object[] args) LoggerInstance.LogInformation(message, args); } - /// - /// Formats and writes an informational log message as JSON. - /// - /// The object to be serialized as JSON. - /// Logger.LogInformation(new {User = user, Address = address}) - public static void LogInformation(object message) - { - LoggerInstance.LogInformation(message); - } - - /// - /// Formats and writes a log message at the specified log level. - /// - /// Additional keys will be appended to the log entry. - /// Format string of the log message. - /// An object array that contains zero or more objects to format. - public static void LogInformation(T extraKeys, string message, params object[] args) where T : class - { - LoggerInstance.LogInformation(extraKeys, message, args); - } - #endregion #region Warning @@ -467,28 +404,7 @@ public static void LogWarning(string message, params object[] args) { LoggerInstance.LogWarning(message, args); } - - /// - /// Formats and writes a warning log message as JSON. - /// - /// The object to be serialized as JSON. - /// Logger.LogWarning(new {User = user, Address = address}) - public static void LogWarning(object message) - { - LoggerInstance.LogWarning(message); - } - /// - /// Formats and writes a log message at the specified log level. - /// - /// Additional keys will be appended to the log entry. - /// Format string of the log message. - /// An object array that contains zero or more objects to format. - public static void LogWarning(T extraKeys, string message, params object[] args) where T : class - { - LoggerInstance.LogWarning(extraKeys, message, args); - } - #endregion #region Error @@ -554,27 +470,6 @@ public static void LogError(string message, params object[] args) LoggerInstance.LogError(message, args); } - /// - /// Formats and writes an error log message as JSON. - /// - /// The object to be serialized as JSON. - /// Logger.LogError(new {User = user, Address = address}) - public static void LogError(object message) - { - LoggerInstance.LogError(message); - } - - /// - /// Formats and writes a log message at the specified log level. - /// - /// Additional keys will be appended to the log entry. - /// Format string of the log message. - /// An object array that contains zero or more objects to format. - public static void LogError(T extraKeys, string message, params object[] args) where T : class - { - LoggerInstance.LogError(extraKeys, message, args); - } - #endregion #region Critical @@ -638,28 +533,7 @@ public static void LogCritical(string message, params object[] args) { LoggerInstance.LogCritical(message, args); } - - /// - /// Formats and writes a critical log message as JSON. - /// - /// The object to be serialized as JSON. - /// Logger.LogCritical(new {User = user, Address = address}) - public static void LogCritical(object message) - { - LoggerInstance.LogCritical(message); - } - /// - /// Formats and writes a log message at the specified log level. - /// - /// Additional keys will be appended to the log entry. - /// Format string of the log message. - /// An object array that contains zero or more objects to format. - public static void LogCritical(T extraKeys, string message, params object[] args) where T : class - { - LoggerInstance.LogCritical(extraKeys, message, args); - } - #endregion #region Log @@ -731,30 +605,553 @@ public static void Log(LogLevel logLevel, EventId eventId, TState state, LoggerInstance.Log(logLevel, eventId, state, exception, formatter); } + #endregion + + #endregion + + #region JSON Logger Methods + + /// + /// Formats and writes a trace log message as JSON. + /// + /// The object to be serialized as JSON. + /// logger.LogTrace(new {User = user, Address = address}) + public static void LogTrace(object message) + { + LoggerInstance.LogTrace(message); + } + + /// + /// Formats and writes an trace log message. + /// + /// The exception to log. + /// logger.LogTrace(exception) + public static void LogTrace(Exception exception) + { + LoggerInstance.LogTrace(exception); + } + + /// + /// Formats and writes a debug log message as JSON. + /// + /// The object to be serialized as JSON. + /// logger.LogDebug(new {User = user, Address = address}) + public static void LogDebug(object message) + { + LoggerInstance.LogDebug(message); + } + + /// + /// Formats and writes an debug log message. + /// + /// The exception to log. + /// logger.LogDebug(exception) + public static void LogDebug(Exception exception) + { + LoggerInstance.LogDebug(exception); + } + + /// + /// Formats and writes an information log message as JSON. + /// + /// The object to be serialized as JSON. + /// logger.LogInformation(new {User = user, Address = address}) + public static void LogInformation(object message) + { + LoggerInstance.LogInformation(message); + } + + /// + /// Formats and writes an information log message. + /// + /// The exception to log. + /// logger.LogInformation(exception) + public static void LogInformation(Exception exception) + { + LoggerInstance.LogInformation(exception); + } + + /// + /// Formats and writes a warning log message as JSON. + /// + /// The object to be serialized as JSON. + /// logger.LogWarning(new {User = user, Address = address}) + public static void LogWarning(object message) + { + LoggerInstance.LogWarning(message); + } + + /// + /// Formats and writes an warning log message. + /// + /// The exception to log. + /// logger.LogWarning(exception) + public static void LogWarning(Exception exception) + { + LoggerInstance.LogWarning(exception); + } + + /// + /// Formats and writes a error log message as JSON. + /// + /// The object to be serialized as JSON. + /// logger.LogCritical(new {User = user, Address = address}) + public static void LogError(object message) + { + LoggerInstance.LogError(message); + } + + /// + /// Formats and writes an error log message. + /// + /// The exception to log. + /// logger.LogError(exception) + public static void LogError(Exception exception) + { + LoggerInstance.LogError(exception); + } + + /// + /// Formats and writes a critical log message as JSON. + /// + /// The object to be serialized as JSON. + /// logger.LogCritical(new {User = user, Address = address}) + public static void LogCritical(object message) + { + LoggerInstance.LogCritical(message); + } + + /// + /// Formats and writes an critical log message. + /// + /// The exception to log. + /// logger.LogCritical(exception) + public static void LogCritical(Exception exception) + { + LoggerInstance.LogCritical(exception); + } + /// /// Formats and writes a log message as JSON at the specified log level. /// /// Entry will be written on this level. /// The object to be serialized as JSON. - /// Logger.Log(LogLevel.Information, new {User = user, Address = address}) + /// logger.Log(LogLevel.Information, new {User = user, Address = address}) public static void Log(LogLevel logLevel, object message) { LoggerInstance.Log(logLevel, message); } + + /// + /// Formats and writes a log message at the specified log level. + /// + /// Entry will be written on this level. + /// The exception to log. + /// logger.Log(LogLevel.Information, exception) + public static void Log(LogLevel logLevel, Exception exception) + { + LoggerInstance.Log(logLevel, exception); + } + + #endregion + + #region ExtraKeys Logger Methods + + #region Debug + + /// + /// Formats and writes a debug log message. + /// + /// Additional keys will be appended to the log entry. + /// The event id associated with the log. + /// The exception to log. + /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" + /// An object array that contains zero or more objects to format. + /// logger.LogDebug(extraKeys, 0, exception, "Error while processing request from {Address}", address) + public static void LogDebug(T extraKeys, EventId eventId, Exception exception, string message, params object[] args) where T : class + { + LoggerInstance.LogDebug(extraKeys, eventId, exception, message, args); + } + + /// + /// Formats and writes a debug log message. + /// + /// Additional keys will be appended to the log entry. + /// The event id associated with the log. + /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" + /// An object array that contains zero or more objects to format. + /// logger.LogDebug(extraKeys, 0, "Processing request from {Address}", address) + public static void LogDebug(T extraKeys, EventId eventId, string message, params object[] args) where T : class + { + LoggerInstance.LogDebug(extraKeys, eventId, message, args); + } + + /// + /// Formats and writes a debug log message. + /// + /// Additional keys will be appended to the log entry. + /// The exception to log. + /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" + /// An object array that contains zero or more objects to format. + /// logger.LogDebug(extraKeys, exception, "Error while processing request from {Address}", address) + public static void LogDebug(T extraKeys, Exception exception, string message, params object[] args) where T : class + { + LoggerInstance.LogDebug(extraKeys, exception, message, args); + } + + /// + /// Formats and writes a debug log message. + /// + /// Additional keys will be appended to the log entry. + /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" + /// An object array that contains zero or more objects to format. + /// logger.LogDebug(extraKeys, "Processing request from {Address}", address) + public static void LogDebug(T extraKeys, string message, params object[] args) where T : class + { + LoggerInstance.LogDebug(extraKeys, message, args); + } + + #endregion + + #region Trace + + /// + /// Formats and writes a trace log message. + /// + /// Additional keys will be appended to the log entry. + /// The event id associated with the log. + /// The exception to log. + /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" + /// An object array that contains zero or more objects to format. + /// logger.LogTrace(extraKeys, 0, exception, "Error while processing request from {Address}", address) + public static void LogTrace(T extraKeys, EventId eventId, Exception exception, string message, params object[] args) where T : class + { + LoggerInstance.LogTrace(extraKeys, eventId, exception, message, args); + } + + /// + /// Formats and writes a trace log message. + /// + /// Additional keys will be appended to the log entry. + /// The event id associated with the log. + /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" + /// An object array that contains zero or more objects to format. + /// logger.LogTrace(extraKeys, 0, "Processing request from {Address}", address) + public static void LogTrace(T extraKeys, EventId eventId, string message, params object[] args) where T : class + { + LoggerInstance.LogTrace(extraKeys, eventId, message, args); + } + + /// + /// Formats and writes a trace log message. + /// + /// Additional keys will be appended to the log entry. + /// The exception to log. + /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" + /// An object array that contains zero or more objects to format. + /// logger.LogTrace(extraKeys, exception, "Error while processing request from {Address}", address) + public static void LogTrace(T extraKeys, Exception exception, string message, params object[] args) where T : class + { + LoggerInstance.LogTrace(extraKeys, exception, message, args); + } + + /// + /// Formats and writes a trace log message. + /// + /// Additional keys will be appended to the log entry. + /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" + /// An object array that contains zero or more objects to format. + /// logger.LogTrace(extraKeys, "Processing request from {Address}", address) + public static void LogTrace(T extraKeys, string message, params object[] args) where T : class + { + LoggerInstance.LogTrace(extraKeys, message, args); + } + + #endregion + + #region Information + + /// + /// Formats and writes an informational log message. + /// + /// Additional keys will be appended to the log entry. + /// The event id associated with the log. + /// The exception to log. + /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" + /// An object array that contains zero or more objects to format. + /// logger.LogInformation(extraKeys, 0, exception, "Error while processing request from {Address}", address) + public static void LogInformation(T extraKeys, EventId eventId, Exception exception, string message, params object[] args) where T : class + { + LoggerInstance.LogInformation(extraKeys, eventId, exception, message, args); + } + + /// + /// Formats and writes an informational log message. + /// + /// Additional keys will be appended to the log entry. + /// The event id associated with the log. + /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" + /// An object array that contains zero or more objects to format. + /// logger.LogInformation(extraKeys, 0, "Processing request from {Address}", address) + public static void LogInformation(T extraKeys, EventId eventId, string message, params object[] args) where T : class + { + LoggerInstance.LogInformation(extraKeys, eventId, message, args); + } + + /// + /// Formats and writes an informational log message. + /// + /// Additional keys will be appended to the log entry. + /// The exception to log. + /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" + /// An object array that contains zero or more objects to format. + /// logger.LogInformation(extraKeys, exception, "Error while processing request from {Address}", address) + public static void LogInformation(T extraKeys, Exception exception, string message, params object[] args) where T : class + { + LoggerInstance.LogInformation(extraKeys, exception, message, args); + } + + /// + /// Formats and writes an informational log message. + /// + /// Additional keys will be appended to the log entry. + /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" + /// An object array that contains zero or more objects to format. + /// logger.LogInformation(extraKeys, "Processing request from {Address}", address) + public static void LogInformation(T extraKeys, string message, params object[] args) where T : class + { + LoggerInstance.LogInformation(extraKeys, message, args); + } + + #endregion + + #region Warning + + /// + /// Formats and writes a warning log message. + /// + /// Additional keys will be appended to the log entry. + /// The event id associated with the log. + /// The exception to log. + /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" + /// An object array that contains zero or more objects to format. + /// logger.LogWarning(extraKeys, 0, exception, "Error while processing request from {Address}", address) + public static void LogWarning(T extraKeys, EventId eventId, Exception exception, string message, params object[] args) where T : class + { + LoggerInstance.LogWarning(extraKeys, eventId, exception, message, args); + } + + /// + /// Formats and writes a warning log message. + /// + /// Additional keys will be appended to the log entry. + /// The event id associated with the log. + /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" + /// An object array that contains zero or more objects to format. + /// logger.LogWarning(extraKeys, 0, "Processing request from {Address}", address) + public static void LogWarning(T extraKeys, EventId eventId, string message, params object[] args) where T : class + { + LoggerInstance.LogWarning(extraKeys, eventId, message, args); + } + + /// + /// Formats and writes a warning log message. + /// + /// Additional keys will be appended to the log entry. + /// The exception to log. + /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" + /// An object array that contains zero or more objects to format. + /// logger.LogWarning(extraKeys, exception, "Error while processing request from {Address}", address) + public static void LogWarning(T extraKeys, Exception exception, string message, params object[] args) where T : class + { + LoggerInstance.LogWarning(extraKeys, exception, message, args); + } + + /// + /// Formats and writes a warning log message. + /// + /// Additional keys will be appended to the log entry. + /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" + /// An object array that contains zero or more objects to format. + /// logger.LogWarning(extraKeys, "Processing request from {Address}", address) + public static void LogWarning(T extraKeys, string message, params object[] args) where T : class + { + LoggerInstance.LogWarning(extraKeys, message, args); + } + + #endregion + + #region Error + + /// + /// Formats and writes an error log message. + /// + /// Additional keys will be appended to the log entry. + /// The event id associated with the log. + /// The exception to log. + /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" + /// An object array that contains zero or more objects to format. + /// logger.LogError(extraKeys, 0, exception, "Error while processing request from {Address}", address) + public static void LogError(T extraKeys, EventId eventId, Exception exception, string message, params object[] args) where T : class + { + LoggerInstance.LogError(extraKeys, eventId, exception, message, args); + } + + /// + /// Formats and writes an error log message. + /// + /// Additional keys will be appended to the log entry. + /// The event id associated with the log. + /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" + /// An object array that contains zero or more objects to format. + /// logger.LogError(extraKeys, 0, "Processing request from {Address}", address) + public static void LogError(T extraKeys, EventId eventId, string message, params object[] args) where T : class + { + LoggerInstance.LogError(extraKeys, eventId, message, args); + } + + /// + /// Formats and writes an error log message. + /// + /// Additional keys will be appended to the log entry. + /// The exception to log. + /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" + /// An object array that contains zero or more objects to format. + /// logger.LogError(extraKeys, exception, "Error while processing request from {Address}", address) + public static void LogError(T extraKeys, Exception exception, string message, params object[] args) where T : class + { + LoggerInstance.LogError(extraKeys, exception, message, args); + } + + /// + /// Formats and writes an error log message. + /// + /// Additional keys will be appended to the log entry. + /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" + /// An object array that contains zero or more objects to format. + /// logger.LogError(extraKeys, "Processing request from {Address}", address) + public static void LogError(T extraKeys, string message, params object[] args) where T : class + { + LoggerInstance.LogError(extraKeys, message, args); + } + + #endregion + + #region Critical + + /// + /// Formats and writes a critical log message. + /// + /// Additional keys will be appended to the log entry. + /// The event id associated with the log. + /// The exception to log. + /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" + /// An object array that contains zero or more objects to format. + /// logger.LogCritical(extraKeys, 0, exception, "Error while processing request from {Address}", address) + public static void LogCritical(T extraKeys, EventId eventId, Exception exception, string message, params object[] args) where T : class + { + LoggerInstance.LogCritical(extraKeys, eventId, exception, message, args); + } + + /// + /// Formats and writes a critical log message. + /// + /// Additional keys will be appended to the log entry. + /// The event id associated with the log. + /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" + /// An object array that contains zero or more objects to format. + /// logger.LogCritical(extraKeys, 0, "Processing request from {Address}", address) + public static void LogCritical(T extraKeys, EventId eventId, string message, params object[] args) where T : class + { + LoggerInstance.LogCritical(extraKeys, eventId, message, args); + } + + /// + /// Formats and writes a critical log message. + /// + /// Additional keys will be appended to the log entry. + /// The exception to log. + /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" + /// An object array that contains zero or more objects to format. + /// logger.LogCritical(extraKeys, exception, "Error while processing request from {Address}", address) + public static void LogCritical(T extraKeys, Exception exception, string message, params object[] args) where T : class + { + LoggerInstance.LogCritical(extraKeys, exception, message, args); + } + + /// + /// Formats and writes a critical log message. + /// + /// Additional keys will be appended to the log entry. + /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" + /// An object array that contains zero or more objects to format. + /// logger.LogCritical(extraKeys, "Processing request from {Address}", address) + public static void LogCritical(T extraKeys, string message, params object[] args) where T : class + { + LoggerInstance.LogCritical(extraKeys, message, args); + } + + #endregion + + #region Log /// /// Formats and writes a log message at the specified log level. /// /// Entry will be written on this level. /// Additional keys will be appended to the log entry. - /// Format string of the log message. + /// The event id associated with the log. + /// The exception to log. + /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" /// An object array that contains zero or more objects to format. + /// logger.Log(LogLevel.Information, extraKeys, 0, exception, "Error while processing request from {Address}", address) + public static void Log(LogLevel logLevel, T extraKeys, EventId eventId, Exception exception, string message, params object[] args) where T : class + { + LoggerInstance.Log(logLevel, extraKeys, eventId, exception, message, args); + } + + /// + /// Formats and writes a log message at the specified log level. + /// + /// Entry will be written on this level. + /// Additional keys will be appended to the log entry. + /// The event id associated with the log. + /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" + /// An object array that contains zero or more objects to format. + /// logger.Log(LogLevel.Information, extraKeys, 0, "Processing request from {Address}", address) + public static void Log(LogLevel logLevel, T extraKeys, EventId eventId, string message, params object[] args) where T : class + { + LoggerInstance.Log(logLevel, extraKeys, eventId, message, args); + } + + /// + /// Formats and writes a log message at the specified log level. + /// + /// Entry will be written on this level. + /// Additional keys will be appended to the log entry. + /// The exception to log. + /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" + /// An object array that contains zero or more objects to format. + /// logger.Log(LogLevel.Information, extraKeys, exception, "Error while processing request from {Address}", address) + public static void Log(LogLevel logLevel, T extraKeys, Exception exception, string message, params object[] args) where T : class + { + LoggerInstance.Log(logLevel, extraKeys, exception, message, args); + } + + /// + /// Formats and writes a log message at the specified log level. + /// + /// Entry will be written on this level. + /// Additional keys will be appended to the log entry. + /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" + /// An object array that contains zero or more objects to format. + /// logger.Log(LogLevel.Information, extraKeys, "Processing request from {Address}", address) public static void Log(LogLevel logLevel, T extraKeys, string message, params object[] args) where T : class { LoggerInstance.Log(logLevel, extraKeys, message, args); } - - #endregion #endregion + + #endregion } \ No newline at end of file diff --git a/libraries/src/AWS.Lambda.Powertools.Logging/LoggerExtensions.cs b/libraries/src/AWS.Lambda.Powertools.Logging/LoggerExtensions.cs index adc483011..3c22c3da0 100644 --- a/libraries/src/AWS.Lambda.Powertools.Logging/LoggerExtensions.cs +++ b/libraries/src/AWS.Lambda.Powertools.Logging/LoggerExtensions.cs @@ -13,6 +13,7 @@ * permissions and limitations under the License. */ +using System; using AWS.Lambda.Powertools.Logging.Internal; using Microsoft.Extensions.Logging; @@ -23,6 +24,8 @@ namespace AWS.Lambda.Powertools.Logging; /// public static class LoggerExtensions { + #region JSON Logger Extentions + /// /// Formats and writes a trace log message as JSON. /// @@ -34,6 +37,17 @@ public static void LogTrace(this ILogger logger, object message) logger.LogTrace(LoggingConstants.KeyJsonFormatter, message); } + /// + /// Formats and writes an trace log message. + /// + /// The to write to. + /// The exception to log. + /// logger.LogTrace(exception) + public static void LogTrace(this ILogger logger, Exception exception) + { + logger.LogTrace(exception: exception, message: exception.Message); + } + /// /// Formats and writes a debug log message as JSON. /// @@ -45,6 +59,17 @@ public static void LogDebug(this ILogger logger, object message) logger.LogDebug(LoggingConstants.KeyJsonFormatter, message); } + /// + /// Formats and writes an debug log message. + /// + /// The to write to. + /// The exception to log. + /// logger.LogDebug(exception) + public static void LogDebug(this ILogger logger, Exception exception) + { + logger.LogDebug(exception: exception, message: exception.Message); + } + /// /// Formats and writes an information log message as JSON. /// @@ -56,6 +81,17 @@ public static void LogInformation(this ILogger logger, object message) logger.LogInformation(LoggingConstants.KeyJsonFormatter, message); } + /// + /// Formats and writes an information log message. + /// + /// The to write to. + /// The exception to log. + /// logger.LogInformation(exception) + public static void LogInformation(this ILogger logger, Exception exception) + { + logger.LogInformation(exception: exception, message: exception.Message); + } + /// /// Formats and writes a warning log message as JSON. /// @@ -68,16 +104,38 @@ public static void LogWarning(this ILogger logger, object message) } /// - /// Formats and writes an error log message as JSON. + /// Formats and writes an warning log message. + /// + /// The to write to. + /// The exception to log. + /// logger.LogWarning(exception) + public static void LogWarning(this ILogger logger, Exception exception) + { + logger.LogWarning(exception: exception, message: exception.Message); + } + + /// + /// Formats and writes a error log message as JSON. /// /// The to write to. /// The object to be serialized as JSON. - /// logger.LogError(new {User = user, Address = address}) + /// logger.LogCritical(new {User = user, Address = address}) public static void LogError(this ILogger logger, object message) { logger.LogError(LoggingConstants.KeyJsonFormatter, message); } + /// + /// Formats and writes an error log message. + /// + /// The to write to. + /// The exception to log. + /// logger.LogError(exception) + public static void LogError(this ILogger logger, Exception exception) + { + logger.LogError(exception: exception, message: exception.Message); + } + /// /// Formats and writes a critical log message as JSON. /// @@ -89,6 +147,17 @@ public static void LogCritical(this ILogger logger, object message) logger.LogCritical(LoggingConstants.KeyJsonFormatter, message); } + /// + /// Formats and writes an critical log message. + /// + /// The to write to. + /// The exception to log. + /// logger.LogCritical(exception) + public static void LogCritical(this ILogger logger, Exception exception) + { + logger.LogCritical(exception: exception, message: exception.Message); + } + /// /// Formats and writes a log message as JSON at the specified log level. /// @@ -102,91 +171,469 @@ public static void Log(this ILogger logger, LogLevel logLevel, object message) } /// - /// Formats and writes a log message at the specified log level. + /// Formats and writes a log message at the specified log level. + /// + /// The to write to. + /// Entry will be written on this level. + /// The exception to log. + /// logger.Log(LogLevel.Information, exception) + public static void Log(this ILogger logger, LogLevel logLevel, Exception exception) + { + logger.Log(logLevel, exception: exception, message: exception.Message); + } + + #endregion + + #region ExtraKeys Logger Extentions + + #region Debug + + /// + /// Formats and writes a debug log message. /// /// The to write to. /// Additional keys will be appended to the log entry. - /// Format string of the log message. + /// The event id associated with the log. + /// The exception to log. + /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" /// An object array that contains zero or more objects to format. - public static void LogTrace(this ILogger logger, T extraKeys, string message, params object[] args) where T : class + /// logger.LogDebug(extraKeys, 0, exception, "Error while processing request from {Address}", address) + public static void LogDebug(this ILogger logger, T extraKeys, EventId eventId, Exception exception, + string message, params object[] args) where T : class { - Log(logger, LogLevel.Trace, extraKeys, message, args); + Log(logger, LogLevel.Debug, extraKeys, eventId, exception, message, args); } - + /// - /// Formats and writes a log message at the specified log level. + /// Formats and writes a debug log message. + /// + /// The to write to. + /// Additional keys will be appended to the log entry. + /// The event id associated with the log. + /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" + /// An object array that contains zero or more objects to format. + /// logger.LogDebug(extraKeys, 0, "Processing request from {Address}", address) + public static void LogDebug(this ILogger logger, T extraKeys, EventId eventId, string message, + params object[] args) where T : class + { + Log(logger, LogLevel.Debug, extraKeys, eventId, message, args); + } + + /// + /// Formats and writes a debug log message. + /// + /// The to write to. + /// Additional keys will be appended to the log entry. + /// The exception to log. + /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" + /// An object array that contains zero or more objects to format. + /// logger.LogDebug(extraKeys, exception, "Error while processing request from {Address}", address) + public static void LogDebug(this ILogger logger, T extraKeys, Exception exception, string message, + params object[] args) where T : class + { + Log(logger, LogLevel.Debug, extraKeys, exception, message, args); + } + + /// + /// Formats and writes a debug log message. /// /// The to write to. /// Additional keys will be appended to the log entry. - /// Format string of the log message. + /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" /// An object array that contains zero or more objects to format. + /// logger.LogDebug(extraKeys, "Processing request from {Address}", address) public static void LogDebug(this ILogger logger, T extraKeys, string message, params object[] args) where T : class { Log(logger, LogLevel.Debug, extraKeys, message, args); } + #endregion + + #region Trace + /// - /// Formats and writes a log message at the specified log level. + /// Formats and writes a trace log message. + /// + /// The to write to. + /// Additional keys will be appended to the log entry. + /// The event id associated with the log. + /// The exception to log. + /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" + /// An object array that contains zero or more objects to format. + /// logger.LogTrace(extraKeys, 0, exception, "Error while processing request from {Address}", address) + public static void LogTrace(this ILogger logger, T extraKeys, EventId eventId, Exception exception, + string message, params object[] args) where T : class + { + Log(logger, LogLevel.Trace, extraKeys, eventId, exception, message, args); + } + + /// + /// Formats and writes a trace log message. + /// + /// The to write to. + /// Additional keys will be appended to the log entry. + /// The event id associated with the log. + /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" + /// An object array that contains zero or more objects to format. + /// logger.LogTrace(extraKeys, 0, "Processing request from {Address}", address) + public static void LogTrace(this ILogger logger, T extraKeys, EventId eventId, string message, + params object[] args) where T : class + { + Log(logger, LogLevel.Trace, extraKeys, eventId, message, args); + } + + /// + /// Formats and writes a trace log message. + /// + /// The to write to. + /// Additional keys will be appended to the log entry. + /// The exception to log. + /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" + /// An object array that contains zero or more objects to format. + /// logger.LogTrace(extraKeys, exception, "Error while processing request from {Address}", address) + public static void LogTrace(this ILogger logger, T extraKeys, Exception exception, string message, + params object[] args) where T : class + { + Log(logger, LogLevel.Trace, extraKeys, exception, message, args); + } + + /// + /// Formats and writes a trace log message. + /// + /// The to write to. + /// Additional keys will be appended to the log entry. + /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" + /// An object array that contains zero or more objects to format. + /// logger.LogTrace(extraKeys, "Processing request from {Address}", address) + public static void LogTrace(this ILogger logger, T extraKeys, string message, params object[] args) where T : class + { + Log(logger, LogLevel.Trace, extraKeys, message, args); + } + + #endregion + + #region Information + + /// + /// Formats and writes an informational log message. + /// + /// The to write to. + /// Additional keys will be appended to the log entry. + /// The event id associated with the log. + /// The exception to log. + /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" + /// An object array that contains zero or more objects to format. + /// logger.LogInformation(extraKeys, 0, exception, "Error while processing request from {Address}", address) + public static void LogInformation(this ILogger logger, T extraKeys, EventId eventId, Exception exception, + string message, params object[] args) where T : class + { + Log(logger, LogLevel.Information, extraKeys, eventId, exception, message, args); + } + + /// + /// Formats and writes an informational log message. + /// + /// The to write to. + /// Additional keys will be appended to the log entry. + /// The event id associated with the log. + /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" + /// An object array that contains zero or more objects to format. + /// logger.LogInformation(extraKeys, 0, "Processing request from {Address}", address) + public static void LogInformation(this ILogger logger, T extraKeys, EventId eventId, string message, + params object[] args) where T : class + { + Log(logger, LogLevel.Information, extraKeys, eventId, message, args); + } + + /// + /// Formats and writes an informational log message. + /// + /// The to write to. + /// Additional keys will be appended to the log entry. + /// The exception to log. + /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" + /// An object array that contains zero or more objects to format. + /// logger.LogInformation(extraKeys, exception, "Error while processing request from {Address}", address) + public static void LogInformation(this ILogger logger, T extraKeys, Exception exception, string message, + params object[] args) where T : class + { + Log(logger, LogLevel.Information, extraKeys, exception, message, args); + } + + /// + /// Formats and writes an informational log message. /// /// The to write to. /// Additional keys will be appended to the log entry. - /// Format string of the log message. + /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" /// An object array that contains zero or more objects to format. + /// logger.LogInformation(extraKeys, "Processing request from {Address}", address) public static void LogInformation(this ILogger logger, T extraKeys, string message, params object[] args) where T : class { Log(logger, LogLevel.Information, extraKeys, message, args); } + #endregion + + #region Warning + /// - /// Formats and writes a log message at the specified log level. + /// Formats and writes a warning log message. + /// + /// The to write to. + /// Additional keys will be appended to the log entry. + /// The event id associated with the log. + /// The exception to log. + /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" + /// An object array that contains zero or more objects to format. + /// logger.LogWarning(extraKeys, 0, exception, "Error while processing request from {Address}", address) + public static void LogWarning(this ILogger logger, T extraKeys, EventId eventId, Exception exception, + string message, params object[] args) where T : class + { + Log(logger, LogLevel.Warning, extraKeys, eventId, exception, message, args); + } + + /// + /// Formats and writes a warning log message. + /// + /// The to write to. + /// Additional keys will be appended to the log entry. + /// The event id associated with the log. + /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" + /// An object array that contains zero or more objects to format. + /// logger.LogWarning(extraKeys, 0, "Processing request from {Address}", address) + public static void LogWarning(this ILogger logger, T extraKeys, EventId eventId, string message, + params object[] args) where T : class + { + Log(logger, LogLevel.Warning, extraKeys, eventId, message, args); + } + + /// + /// Formats and writes a warning log message. /// /// The to write to. /// Additional keys will be appended to the log entry. - /// Format string of the log message. + /// The exception to log. + /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" /// An object array that contains zero or more objects to format. + /// logger.LogWarning(extraKeys, exception, "Error while processing request from {Address}", address) + public static void LogWarning(this ILogger logger, T extraKeys, Exception exception, string message, + params object[] args) where T : class + { + Log(logger, LogLevel.Warning, extraKeys, exception, message, args); + } + + /// + /// Formats and writes a warning log message. + /// + /// The to write to. + /// Additional keys will be appended to the log entry. + /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" + /// An object array that contains zero or more objects to format. + /// logger.LogWarning(extraKeys, "Processing request from {Address}", address) public static void LogWarning(this ILogger logger, T extraKeys, string message, params object[] args) where T : class { Log(logger, LogLevel.Warning, extraKeys, message, args); } + #endregion + + #region Error + /// - /// Formats and writes a log message at the specified log level. + /// Formats and writes an error log message. + /// + /// The to write to. + /// Additional keys will be appended to the log entry. + /// The event id associated with the log. + /// The exception to log. + /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" + /// An object array that contains zero or more objects to format. + /// logger.LogError(extraKeys, 0, exception, "Error while processing request from {Address}", address) + public static void LogError(this ILogger logger, T extraKeys, EventId eventId, Exception exception, + string message, params object[] args) where T : class + { + Log(logger, LogLevel.Error, extraKeys, eventId, exception, message, args); + } + + /// + /// Formats and writes an error log message. /// /// The to write to. /// Additional keys will be appended to the log entry. - /// Format string of the log message. + /// The event id associated with the log. + /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" /// An object array that contains zero or more objects to format. + /// logger.LogError(extraKeys, 0, "Processing request from {Address}", address) + public static void LogError(this ILogger logger, T extraKeys, EventId eventId, string message, + params object[] args) where T : class + { + Log(logger, LogLevel.Error, extraKeys, eventId, message, args); + } + + /// + /// Formats and writes an error log message. + /// + /// The to write to. + /// Additional keys will be appended to the log entry. + /// The exception to log. + /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" + /// An object array that contains zero or more objects to format. + /// logger.LogError(extraKeys, exception, "Error while processing request from {Address}", address) + public static void LogError(this ILogger logger, T extraKeys, Exception exception, string message, + params object[] args) where T : class + { + Log(logger, LogLevel.Error, extraKeys, exception, message, args); + } + + /// + /// Formats and writes an error log message. + /// + /// The to write to. + /// Additional keys will be appended to the log entry. + /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" + /// An object array that contains zero or more objects to format. + /// logger.LogError(extraKeys, "Processing request from {Address}", address) public static void LogError(this ILogger logger, T extraKeys, string message, params object[] args) where T : class { Log(logger, LogLevel.Error, extraKeys, message, args); } - + + #endregion + + #region Critical + /// - /// Formats and writes a log message at the specified log level. + /// Formats and writes a critical log message. + /// + /// The to write to. + /// Additional keys will be appended to the log entry. + /// The event id associated with the log. + /// The exception to log. + /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" + /// An object array that contains zero or more objects to format. + /// logger.LogCritical(extraKeys, 0, exception, "Error while processing request from {Address}", address) + public static void LogCritical(this ILogger logger, T extraKeys, EventId eventId, Exception exception, + string message, params object[] args) where T : class + { + Log(logger, LogLevel.Critical, extraKeys, eventId, exception, message, args); + } + + /// + /// Formats and writes a critical log message. + /// + /// The to write to. + /// Additional keys will be appended to the log entry. + /// The event id associated with the log. + /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" + /// An object array that contains zero or more objects to format. + /// logger.LogCritical(extraKeys, 0, "Processing request from {Address}", address) + public static void LogCritical(this ILogger logger, T extraKeys, EventId eventId, string message, + params object[] args) where T : class + { + Log(logger, LogLevel.Critical, extraKeys, eventId, message, args); + } + + /// + /// Formats and writes a critical log message. + /// + /// The to write to. + /// Additional keys will be appended to the log entry. + /// The exception to log. + /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" + /// An object array that contains zero or more objects to format. + /// logger.LogCritical(extraKeys, exception, "Error while processing request from {Address}", address) + public static void LogCritical(this ILogger logger, T extraKeys, Exception exception, string message, + params object[] args) where T : class + { + Log(logger, LogLevel.Critical, extraKeys, exception, message, args); + } + + /// + /// Formats and writes a critical log message. /// /// The to write to. /// Additional keys will be appended to the log entry. - /// Format string of the log message. + /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" /// An object array that contains zero or more objects to format. + /// logger.LogCritical(extraKeys, "Processing request from {Address}", address) public static void LogCritical(this ILogger logger, T extraKeys, string message, params object[] args) where T : class { Log(logger, LogLevel.Critical, extraKeys, message, args); } + #endregion + + #region Log + /// /// Formats and writes a log message at the specified log level. /// /// The to write to. /// Entry will be written on this level. /// Additional keys will be appended to the log entry. - /// Format string of the log message. + /// The event id associated with the log. + /// The exception to log. + /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" /// An object array that contains zero or more objects to format. - public static void Log(this ILogger logger, LogLevel logLevel, T extraKeys, string message, params object[] args) where T : class + /// logger.Log(LogLevel.Information, extraKeys, 0, exception, "Error while processing request from {Address}", address) + public static void Log(this ILogger logger, LogLevel logLevel, T extraKeys, EventId eventId, Exception exception, + string message, params object[] args) where T : class { if (extraKeys is not null) using (logger.BeginScope(extraKeys)) - logger.Log(logLevel, message, args); + logger.Log(logLevel, eventId, exception, message, args); else - logger.Log(logLevel, message, args); + logger.Log(logLevel, eventId, exception, message, args); } + + /// + /// Formats and writes a log message at the specified log level. + /// + /// The to write to. + /// Entry will be written on this level. + /// Additional keys will be appended to the log entry. + /// The event id associated with the log. + /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" + /// An object array that contains zero or more objects to format. + /// logger.Log(LogLevel.Information, extraKeys, 0, "Processing request from {Address}", address) + public static void Log(this ILogger logger, LogLevel logLevel, T extraKeys, EventId eventId, string message, + params object[] args) where T : class + { + Log(logger, logLevel, extraKeys, eventId, null, message, args); + } + + /// + /// Formats and writes a log message at the specified log level. + /// + /// The to write to. + /// Entry will be written on this level. + /// Additional keys will be appended to the log entry. + /// The exception to log. + /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" + /// An object array that contains zero or more objects to format. + /// logger.Log(LogLevel.Information, extraKeys, exception, "Error while processing request from {Address}", address) + public static void Log(this ILogger logger, LogLevel logLevel, T extraKeys, Exception exception, string message, + params object[] args) where T : class + { + Log(logger, logLevel, extraKeys, 0, exception, message, args); + } + + /// + /// Formats and writes a log message at the specified log level. + /// + /// The to write to. + /// Entry will be written on this level. + /// Additional keys will be appended to the log entry. + /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" + /// An object array that contains zero or more objects to format. + /// logger.Log(LogLevel.Information, extraKeys, "Processing request from {Address}", address) + public static void Log(this ILogger logger, LogLevel logLevel, T extraKeys, string message, params object[] args) where T : class + { + Log(logger, logLevel, extraKeys, 0, null, message, args); + } + + #endregion + + #endregion } \ No newline at end of file diff --git a/libraries/src/AWS.Lambda.Powertools.Metrics/Serializer/StringEnumConverter.cs b/libraries/src/AWS.Lambda.Powertools.Metrics/Serializer/StringEnumConverter.cs index 063c02335..28c0d54b9 100644 --- a/libraries/src/AWS.Lambda.Powertools.Metrics/Serializer/StringEnumConverter.cs +++ b/libraries/src/AWS.Lambda.Powertools.Metrics/Serializer/StringEnumConverter.cs @@ -82,7 +82,7 @@ public override bool CanConvert(Type typeToConvert) /// /// The type handled by the converter. /// The serialization options to use. - /// A converter for which is compatible with . + /// A converter for which type is compatible with . public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options) { var query = from field in typeToConvert.GetFields(BindingFlags.Public | BindingFlags.Static)