From c590ac7b326d3ee8c266a43ca116a7dd13342d05 Mon Sep 17 00:00:00 2001 From: Henrique Graca <999396+hjgraca@users.noreply.github.com> Date: Fri, 13 Oct 2023 11:52:51 +0100 Subject: [PATCH 1/7] Add support for Lambda log level --- .../Core/Constants.cs | 5 ++ .../Core/PowertoolsConfigurations.cs | 2 +- .../PowertoolsLoggerTest.cs | 84 +++++++++++++++++-- .../Utilities/SystemWrapperMock.cs | 58 +++++++++++++ 4 files changed, 142 insertions(+), 7 deletions(-) create mode 100644 libraries/tests/AWS.Lambda.Powertools.Logging.Tests/Utilities/SystemWrapperMock.cs diff --git a/libraries/src/AWS.Lambda.Powertools.Common/Core/Constants.cs b/libraries/src/AWS.Lambda.Powertools.Common/Core/Constants.cs index d4f0350f..fc234c1b 100644 --- a/libraries/src/AWS.Lambda.Powertools.Common/Core/Constants.cs +++ b/libraries/src/AWS.Lambda.Powertools.Common/Core/Constants.cs @@ -54,6 +54,11 @@ internal static class Constants /// Constant for POWERTOOLS_LOG_LEVEL environment variable /// internal const string LogLevelNameEnv = "POWERTOOLS_LOG_LEVEL"; + + /// + /// Constant for POWERTOOLS_LOG_LEVEL environment variable + /// + internal const string AwsLogLevelNameEnv = "AWS_LAMBDA_LOG_LEVEL"; /// /// Constant for POWERTOOLS_LOGGER_SAMPLE_RATE environment variable diff --git a/libraries/src/AWS.Lambda.Powertools.Common/Core/PowertoolsConfigurations.cs b/libraries/src/AWS.Lambda.Powertools.Common/Core/PowertoolsConfigurations.cs index 3ff5fd14..09e23c2d 100644 --- a/libraries/src/AWS.Lambda.Powertools.Common/Core/PowertoolsConfigurations.cs +++ b/libraries/src/AWS.Lambda.Powertools.Common/Core/PowertoolsConfigurations.cs @@ -152,7 +152,7 @@ public bool GetEnvironmentVariableOrDefault(string variable, bool defaultValue) /// /// The log level. public string LogLevel => - GetEnvironmentVariable(Constants.LogLevelNameEnv); + GetEnvironmentVariableOrDefault(Constants.AwsLogLevelNameEnv, GetEnvironmentVariable(Constants.LogLevelNameEnv)); /// /// Gets the logger sample rate. diff --git a/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/PowertoolsLoggerTest.cs b/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/PowertoolsLoggerTest.cs index c0fd3c09..0fe175ef 100644 --- a/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/PowertoolsLoggerTest.cs +++ b/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/PowertoolsLoggerTest.cs @@ -1,12 +1,12 @@ /* * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * + * * Licensed under the Apache License, Version 2.0 (the "License"). * You may not use this file except in compliance with the License. * A copy of the License is located at - * + * * http://aws.amazon.com/apache2.0 - * + * * or in the "license" file accompanying this file. This file is distributed * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * express or implied. See the License for the specific language governing @@ -21,8 +21,11 @@ using System.Text; using AWS.Lambda.Powertools.Common; using AWS.Lambda.Powertools.Logging.Internal; +using AWS.Lambda.Powertools.Logging.Tests.Utilities; using Microsoft.Extensions.Logging; using NSubstitute; +using NSubstitute.Extensions; +using NSubstitute.ReceivedExtensions; using Xunit; namespace AWS.Lambda.Powertools.Logging.Tests @@ -34,7 +37,7 @@ public PowertoolsLoggerTest() { Logger.UseDefaultFormatter(); } - + private static void Log_WhenMinimumLevelIsBelowLogLevel_Logs(LogLevel logLevel, LogLevel minimumLevel) { // Arrange @@ -1219,7 +1222,7 @@ public void Log_Set_Execution_Environment_Context() $"{Constants.FeatureContextIdentifier}/Logger/{assemblyVersion}"); env.Received(1).GetEnvironmentVariable("AWS_EXECUTION_ENV"); } - + [Fact] public void Log_Should_Serialize_DateOnly() { @@ -1260,7 +1263,7 @@ public void Log_Should_Serialize_DateOnly() ) ); } - + [Fact] public void Log_Should_Serialize_TimeOnly() { @@ -1301,5 +1304,74 @@ public void Log_Should_Serialize_TimeOnly() ) ); } + + [Theory] + [InlineData(true, LogLevel.Warning)] + [InlineData(false, LogLevel.Critical)] + public void Log_Should_Use_Lambda_Log_Level_When_Enabled(bool willLog, LogLevel logLevel) + { + // Arrange + var loggerName = Guid.NewGuid().ToString(); + + var environment = Substitute.For(); + environment.GetEnvironmentVariable("POWERTOOLS_LOG_LEVEL").Returns("Error"); + environment.GetEnvironmentVariable("AWS_LAMBDA_LOG_LEVEL").Returns(logLevel.ToString()); + + var systemWrapper = new SystemWrapperMock(environment); + var configuration = new PowertoolsConfigurations(systemWrapper); + + var logger = new PowertoolsLogger(loggerName, configuration, systemWrapper, () => + new LoggerConfiguration + { + LoggerOutputCase = LoggerOutputCase.CamelCase + }); + + var message = new + { + PropOne = "Value 1", + PropTwo = "Value 2", + Time = new TimeOnly(12, 0, 0) + }; + + logger.LogWarning(message); + + Assert.True(logger.IsEnabled(logLevel)); + Assert.Equal(logLevel.ToString(), configuration.LogLevel); + Assert.Equal(willLog, systemWrapper.LogMethodCalled); + } + + [Theory] + [InlineData(true, LogLevel.Warning)] + [InlineData(false, LogLevel.Critical)] + public void Log_Should_Use_Powertools_Log_Level_When_Lambda_Log_Level_Unavailable(bool willLog, LogLevel logLevel) + { + // Arrange + var loggerName = Guid.NewGuid().ToString(); + var environment = Substitute.For(); + environment.GetEnvironmentVariable("POWERTOOLS_LOG_LEVEL").Returns(logLevel.ToString()); + + var systemWrapper = new SystemWrapperMock(environment); + var configuration = new PowertoolsConfigurations(systemWrapper); + + var logger = new PowertoolsLogger(loggerName, configuration, systemWrapper, () => + new LoggerConfiguration + { + LoggerOutputCase = LoggerOutputCase.CamelCase + }); + + var message = new + { + PropOne = "Value 1", + PropTwo = "Value 2", + Time = new TimeOnly(12, 0, 0) + }; + + logger.LogWarning(message); + + // Assert + Assert.True(logger.IsEnabled(logLevel)); + Assert.Equal(logLevel.ToString(), configuration.LogLevel); + Assert.Equal(willLog, systemWrapper.LogMethodCalled); + } } } \ No newline at end of file diff --git a/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/Utilities/SystemWrapperMock.cs b/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/Utilities/SystemWrapperMock.cs new file mode 100644 index 00000000..f709e5e6 --- /dev/null +++ b/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/Utilities/SystemWrapperMock.cs @@ -0,0 +1,58 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +using AWS.Lambda.Powertools.Common; + +namespace AWS.Lambda.Powertools.Logging.Tests.Utilities; + +public class SystemWrapperMock : ISystemWrapper +{ + private readonly IPowertoolsEnvironment _powertoolsEnvironment; + public bool LogMethodCalled { get; private set; } + + public SystemWrapperMock(IPowertoolsEnvironment powertoolsEnvironment) + { + _powertoolsEnvironment = powertoolsEnvironment; + } + + public string GetEnvironmentVariable(string variable) + { + return _powertoolsEnvironment.GetEnvironmentVariable(variable); + } + + public void Log(string value) + { + LogMethodCalled = true; + } + + public void LogLine(string value) + { + LogMethodCalled = true; + } + + public double GetRandom() + { + throw new System.NotImplementedException(); + } + + public void SetEnvironmentVariable(string variable, string value) + { + throw new System.NotImplementedException(); + } + + public void SetExecutionEnvironment(T type) + { + } +} \ No newline at end of file From 5fb2d7752626c21b8a4f7a8598117de9739e5ab0 Mon Sep 17 00:00:00 2001 From: Henrique Graca <999396+hjgraca@users.noreply.github.com> Date: Fri, 13 Oct 2023 16:13:58 +0100 Subject: [PATCH 2/7] Map AWS Lambda LogLevel to Microsoft LogLevel --- .../Core/PowertoolsConfigurations.cs | 1 + .../Internal/PowertoolsConfigurations.cs | 18 ++++++++- .../PowertoolsLoggerTest.cs | 37 ++++++++++++++++--- 3 files changed, 50 insertions(+), 6 deletions(-) diff --git a/libraries/src/AWS.Lambda.Powertools.Common/Core/PowertoolsConfigurations.cs b/libraries/src/AWS.Lambda.Powertools.Common/Core/PowertoolsConfigurations.cs index 09e23c2d..70f3e62f 100644 --- a/libraries/src/AWS.Lambda.Powertools.Common/Core/PowertoolsConfigurations.cs +++ b/libraries/src/AWS.Lambda.Powertools.Common/Core/PowertoolsConfigurations.cs @@ -149,6 +149,7 @@ public bool GetEnvironmentVariableOrDefault(string variable, bool defaultValue) /// /// Gets the log level. + /// Dont' use this method directly use GetLogLevel extension method instead /// /// The log level. public string LogLevel => diff --git a/libraries/src/AWS.Lambda.Powertools.Logging/Internal/PowertoolsConfigurations.cs b/libraries/src/AWS.Lambda.Powertools.Logging/Internal/PowertoolsConfigurations.cs index a772003a..4e742250 100644 --- a/libraries/src/AWS.Lambda.Powertools.Logging/Internal/PowertoolsConfigurations.cs +++ b/libraries/src/AWS.Lambda.Powertools.Logging/Internal/PowertoolsConfigurations.cs @@ -14,6 +14,7 @@ */ using System; +using System.Collections.Generic; using AWS.Lambda.Powertools.Common; using Microsoft.Extensions.Logging; @@ -36,7 +37,12 @@ internal static LogLevel GetLogLevel(this IPowertoolsConfigurations powertoolsCo if (logLevel.HasValue) return logLevel.Value; - if (Enum.TryParse((powertoolsConfigurations.LogLevel ?? "").Trim(), true, out LogLevel result)) + var logFromEnv = (powertoolsConfigurations.LogLevel ?? "").Trim(); + + if (AwsLogLevelMapper.TryGetValue(logFromEnv.ToUpper(), out var awsLogLevel)) + logFromEnv = awsLogLevel; + + if (Enum.TryParse(logFromEnv, true, out LogLevel result)) return result; return LoggingConstants.DefaultLogLevel; @@ -53,4 +59,14 @@ internal static LoggerOutputCase GetLoggerOutputCase(this IPowertoolsConfigurati return LoggingConstants.DefaultLoggerOutputCase; } + + private static Dictionary AwsLogLevelMapper = new() + { + { "TRACE", "TRACE" }, + { "DEBUG", "DEBUG" }, + { "INFO", "INFORMATION" }, + { "WARN", "WARNING" }, + { "ERROR", "ERROR" }, + { "FATAL", "CRITICAL" } + }; } \ 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 0fe175ef..83a0d737 100644 --- a/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/PowertoolsLoggerTest.cs +++ b/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/PowertoolsLoggerTest.cs @@ -1306,16 +1306,16 @@ public void Log_Should_Serialize_TimeOnly() } [Theory] - [InlineData(true, LogLevel.Warning)] - [InlineData(false, LogLevel.Critical)] - public void Log_Should_Use_Lambda_Log_Level_When_Enabled(bool willLog, LogLevel logLevel) + [InlineData(true, "WARN", LogLevel.Warning)] + [InlineData(false, "Fatal", LogLevel.Critical)] + public void Log_Should_Use_Lambda_Log_Level_When_Enabled(bool willLog, string awsLogLevel, LogLevel logLevel) { // Arrange var loggerName = Guid.NewGuid().ToString(); var environment = Substitute.For(); environment.GetEnvironmentVariable("POWERTOOLS_LOG_LEVEL").Returns("Error"); - environment.GetEnvironmentVariable("AWS_LAMBDA_LOG_LEVEL").Returns(logLevel.ToString()); + environment.GetEnvironmentVariable("AWS_LAMBDA_LOG_LEVEL").Returns(awsLogLevel); var systemWrapper = new SystemWrapperMock(environment); var configuration = new PowertoolsConfigurations(systemWrapper); @@ -1333,12 +1333,38 @@ public void Log_Should_Use_Lambda_Log_Level_When_Enabled(bool willLog, LogLevel Time = new TimeOnly(12, 0, 0) }; + // Act logger.LogWarning(message); + // Assert Assert.True(logger.IsEnabled(logLevel)); - Assert.Equal(logLevel.ToString(), configuration.LogLevel); + Assert.Equal(logLevel, configuration.GetLogLevel()); Assert.Equal(willLog, systemWrapper.LogMethodCalled); } + + [Theory] + [InlineData("TRACE", LogLevel.Trace)] + [InlineData("debug", LogLevel.Debug)] + [InlineData("Info", LogLevel.Information)] + [InlineData("WARN", LogLevel.Warning)] + [InlineData("ERROR", LogLevel.Error)] + [InlineData("Fatal", LogLevel.Critical)] + [InlineData("DoesNotExist", LogLevel.Information)] + public void Should_Map_AWS_Log_Level_And_Default_To_Information(string awsLogLevel, LogLevel logLevel) + { + // Arrange + var environment = Substitute.For(); + environment.GetEnvironmentVariable("AWS_LAMBDA_LOG_LEVEL").Returns(awsLogLevel); + + var systemWrapper = new SystemWrapperMock(environment); + var configuration = new PowertoolsConfigurations(systemWrapper); + + // Act + var logLvl = configuration.GetLogLevel(); + + // Assert + Assert.Equal(logLevel, logLvl); + } [Theory] [InlineData(true, LogLevel.Warning)] @@ -1366,6 +1392,7 @@ public void Log_Should_Use_Powertools_Log_Level_When_Lambda_Log_Level_Unavailabl Time = new TimeOnly(12, 0, 0) }; + // Act logger.LogWarning(message); // Assert From fc742d71a0145351b75635b391ddf45a4a05a2fd Mon Sep 17 00:00:00 2001 From: Henrique Graca <999396+hjgraca@users.noreply.github.com> Date: Mon, 16 Oct 2023 11:24:45 +0100 Subject: [PATCH 3/7] Log level precedence --- .../Core/PowertoolsConfigurations.cs | 2 +- .../PowertoolsLoggerTest.cs | 49 +++++++++++++++++-- 2 files changed, 47 insertions(+), 4 deletions(-) diff --git a/libraries/src/AWS.Lambda.Powertools.Common/Core/PowertoolsConfigurations.cs b/libraries/src/AWS.Lambda.Powertools.Common/Core/PowertoolsConfigurations.cs index 70f3e62f..33c6132b 100644 --- a/libraries/src/AWS.Lambda.Powertools.Common/Core/PowertoolsConfigurations.cs +++ b/libraries/src/AWS.Lambda.Powertools.Common/Core/PowertoolsConfigurations.cs @@ -153,7 +153,7 @@ public bool GetEnvironmentVariableOrDefault(string variable, bool defaultValue) /// /// The log level. public string LogLevel => - GetEnvironmentVariableOrDefault(Constants.AwsLogLevelNameEnv, GetEnvironmentVariable(Constants.LogLevelNameEnv)); + GetEnvironmentVariableOrDefault(Constants.LogLevelNameEnv, GetEnvironmentVariable(Constants.AwsLogLevelNameEnv)); /// /// Gets the logger sample rate. diff --git a/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/PowertoolsLoggerTest.cs b/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/PowertoolsLoggerTest.cs index 83a0d737..298d409d 100644 --- a/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/PowertoolsLoggerTest.cs +++ b/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/PowertoolsLoggerTest.cs @@ -1305,16 +1305,59 @@ public void Log_Should_Serialize_TimeOnly() ); } + + [Theory] + [InlineData(true, "WARN", LogLevel.Warning)] + [InlineData(false, "Fatal", LogLevel.Critical)] + [InlineData(false, "NotValid", LogLevel.Critical)] + [InlineData(true, "NotValid", LogLevel.Warning)] + public void Log_Should_Use_Powertools_Log_Level_When_Lambda_Log_Level_Enabled(bool willLog, string awsLogLevel, LogLevel logLevel) + { + // Arrange + var loggerName = Guid.NewGuid().ToString(); + + var environment = Substitute.For(); + // Powertools Log Level takes precedence + environment.GetEnvironmentVariable("POWERTOOLS_LOG_LEVEL").Returns(logLevel.ToString()); + environment.GetEnvironmentVariable("AWS_LAMBDA_LOG_LEVEL").Returns(awsLogLevel); + + var systemWrapper = new SystemWrapperMock(environment); + var configuration = new PowertoolsConfigurations(systemWrapper); + + var logger = new PowertoolsLogger(loggerName, configuration, systemWrapper, () => + new LoggerConfiguration + { + LoggerOutputCase = LoggerOutputCase.CamelCase + }); + + var message = new + { + PropOne = "Value 1", + PropTwo = "Value 2", + Time = new TimeOnly(12, 0, 0) + }; + + // Act + logger.LogWarning(message); + + // Assert + Assert.True(logger.IsEnabled(logLevel)); + Assert.Equal(logLevel, configuration.GetLogLevel()); + Assert.Equal(willLog, systemWrapper.LogMethodCalled); + } + [Theory] [InlineData(true, "WARN", LogLevel.Warning)] [InlineData(false, "Fatal", LogLevel.Critical)] - public void Log_Should_Use_Lambda_Log_Level_When_Enabled(bool willLog, string awsLogLevel, LogLevel logLevel) + [InlineData(true, "NotValid", LogLevel.Information)] + public void Log_Should_Use_AWS_Lambda_Log_Level_When_Enabled(bool willLog, string awsLogLevel, LogLevel logLevel) { // Arrange var loggerName = Guid.NewGuid().ToString(); var environment = Substitute.For(); - environment.GetEnvironmentVariable("POWERTOOLS_LOG_LEVEL").Returns("Error"); + // Powertools Log Level not set, AWS Lambda Log Level is used + environment.GetEnvironmentVariable("POWERTOOLS_LOG_LEVEL").Returns(string.Empty); environment.GetEnvironmentVariable("AWS_LAMBDA_LOG_LEVEL").Returns(awsLogLevel); var systemWrapper = new SystemWrapperMock(environment); @@ -1369,7 +1412,7 @@ public void Should_Map_AWS_Log_Level_And_Default_To_Information(string awsLogLev [Theory] [InlineData(true, LogLevel.Warning)] [InlineData(false, LogLevel.Critical)] - public void Log_Should_Use_Powertools_Log_Level_When_Lambda_Log_Level_Unavailable(bool willLog, LogLevel logLevel) + public void Log_Should_Use_Powertools_Log_Level_When_Set(bool willLog, LogLevel logLevel) { // Arrange var loggerName = Guid.NewGuid().ToString(); From ca1c715ebac2e7135e38cdbc7eb514bad3cb2d00 Mon Sep 17 00:00:00 2001 From: Henrique Graca <999396+hjgraca@users.noreply.github.com> Date: Thu, 16 Nov 2023 10:34:00 +0000 Subject: [PATCH 4/7] Add warning message when lambda and PT log level different Add tests --- docs/core/logging.md | 4 + .../Core/Constants.cs | 2 +- .../Core/IPowertoolsConfigurations.cs | 8 +- .../Core/PowertoolsConfigurations.cs | 12 +- .../Core/SystemWrapper.cs | 27 +++-- .../Internal/PowertoolsConfigurations.cs | 20 +++- .../Internal/PowertoolsLogger.cs | 44 ++++++-- .../PowertoolsLoggerTest.cs | 104 +++++++++++++++++- .../Utilities/SystemWrapperMock.cs | 4 + 9 files changed, 187 insertions(+), 38 deletions(-) diff --git a/docs/core/logging.md b/docs/core/logging.md index d3d59703..63a04716 100644 --- a/docs/core/logging.md +++ b/docs/core/logging.md @@ -29,6 +29,10 @@ Setting | Description | Environment variable | Attribute parameter **Service** | Sets **Service** key that will be present across all log statements | `POWERTOOLS_SERVICE_NAME` | `Service` **Logging level** | Sets how verbose Logger should be (Information, by default) | `POWERTOOLS_LOG_LEVEL` | `LogLevel` +!!! warning "When using Lambda Log Format JSON" + - And Powertools Logger output is set to `PascalCase` **`Level`** property name will be replaced by **`LogLevel`** as a property name. + - The Lambda Application log level setting will control what is sent to CloudWatch. It takes precedence over **`POWERTOOLS_LOG_LEVEL`** and when setting it in code using **`[Logging(LogLevel = )]`** + ### Example using AWS Serverless Application Model (AWS SAM) You can override log level by setting **`POWERTOOLS_LOG_LEVEL`** environment variable in the AWS SAM template. diff --git a/libraries/src/AWS.Lambda.Powertools.Common/Core/Constants.cs b/libraries/src/AWS.Lambda.Powertools.Common/Core/Constants.cs index fc234c1b..1a15d30b 100644 --- a/libraries/src/AWS.Lambda.Powertools.Common/Core/Constants.cs +++ b/libraries/src/AWS.Lambda.Powertools.Common/Core/Constants.cs @@ -58,7 +58,7 @@ internal static class Constants /// /// Constant for POWERTOOLS_LOG_LEVEL environment variable /// - internal const string AwsLogLevelNameEnv = "AWS_LAMBDA_LOG_LEVEL"; + internal const string AWSLambdaLogLevelNameEnv = "AWS_LAMBDA_LOG_LEVEL"; /// /// Constant for POWERTOOLS_LOGGER_SAMPLE_RATE environment variable diff --git a/libraries/src/AWS.Lambda.Powertools.Common/Core/IPowertoolsConfigurations.cs b/libraries/src/AWS.Lambda.Powertools.Common/Core/IPowertoolsConfigurations.cs index f11fd344..ee95b318 100644 --- a/libraries/src/AWS.Lambda.Powertools.Common/Core/IPowertoolsConfigurations.cs +++ b/libraries/src/AWS.Lambda.Powertools.Common/Core/IPowertoolsConfigurations.cs @@ -57,10 +57,16 @@ public interface IPowertoolsConfigurations string MetricsNamespace { get; } /// - /// Gets the log level. + /// Gets the Powertools log level. /// /// The log level. string LogLevel { get; } + + /// + /// Gets the AWS Lambda log level. + /// + /// The log level. + string AWSLambdaLogLevel { get; } /// /// Gets the logger sample rate. diff --git a/libraries/src/AWS.Lambda.Powertools.Common/Core/PowertoolsConfigurations.cs b/libraries/src/AWS.Lambda.Powertools.Common/Core/PowertoolsConfigurations.cs index 33c6132b..f098d426 100644 --- a/libraries/src/AWS.Lambda.Powertools.Common/Core/PowertoolsConfigurations.cs +++ b/libraries/src/AWS.Lambda.Powertools.Common/Core/PowertoolsConfigurations.cs @@ -147,13 +147,11 @@ public bool GetEnvironmentVariableOrDefault(string variable, bool defaultValue) public string MetricsNamespace => GetEnvironmentVariable(Constants.MetricsNamespaceEnv); - /// - /// Gets the log level. - /// Dont' use this method directly use GetLogLevel extension method instead - /// - /// The log level. - public string LogLevel => - GetEnvironmentVariableOrDefault(Constants.LogLevelNameEnv, GetEnvironmentVariable(Constants.AwsLogLevelNameEnv)); + /// + public string LogLevel => GetEnvironmentVariable(Constants.LogLevelNameEnv); + + /// + public string AWSLambdaLogLevel => GetEnvironmentVariable(Constants.AWSLambdaLogLevelNameEnv); /// /// Gets the logger sample rate. diff --git a/libraries/src/AWS.Lambda.Powertools.Common/Core/SystemWrapper.cs b/libraries/src/AWS.Lambda.Powertools.Common/Core/SystemWrapper.cs index 703a0865..588ad4b6 100644 --- a/libraries/src/AWS.Lambda.Powertools.Common/Core/SystemWrapper.cs +++ b/libraries/src/AWS.Lambda.Powertools.Common/Core/SystemWrapper.cs @@ -1,12 +1,12 @@ /* * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * + * * Licensed under the Apache License, Version 2.0 (the "License"). * You may not use this file except in compliance with the License. * A copy of the License is located at - * + * * http://aws.amazon.com/apache2.0 - * + * * or in the "license" file accompanying this file. This file is distributed * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * express or implied. See the License for the specific language governing @@ -14,6 +14,7 @@ */ using System; +using System.IO; using System.Text; namespace AWS.Lambda.Powertools.Common; @@ -39,6 +40,15 @@ public SystemWrapper(IPowertoolsEnvironment powertoolsEnvironment) { _powertoolsEnvironment = powertoolsEnvironment; _instance ??= this; + + + // Clear AWS SDK Console injected parameters StdOut and StdErr + var standardOutput = new StreamWriter(Console.OpenStandardOutput()); + standardOutput.AutoFlush = true; + Console.SetOut(standardOutput); + var errordOutput = new StreamWriter(Console.OpenStandardError()); + errordOutput.AutoFlush = true; + Console.SetError(errordOutput); } /// @@ -97,21 +107,21 @@ public void SetExecutionEnvironment(T type) var envValue = new StringBuilder(); var currentEnvValue = GetEnvironmentVariable(envName); var assemblyName = ParseAssemblyName(_powertoolsEnvironment.GetAssemblyName(type)); - + // If there is an existing execution environment variable add the annotations package as a suffix. - if(!string.IsNullOrEmpty(currentEnvValue)) + if (!string.IsNullOrEmpty(currentEnvValue)) { // Avoid duplication - should not happen since the calling Instances are Singletons - defensive purposes if (currentEnvValue.Contains(assemblyName)) { return; } - + envValue.Append($"{currentEnvValue} "); } var assemblyVersion = _powertoolsEnvironment.GetAssemblyVersion(type); - + envValue.Append($"{assemblyName}/{assemblyVersion}"); SetEnvironmentVariable(envName, envValue.ToString()); @@ -127,13 +137,14 @@ private string ParseAssemblyName(string assemblyName) { try { - var parsedName = assemblyName.Substring(assemblyName.LastIndexOf(".", StringComparison.Ordinal)+1); + var parsedName = assemblyName.Substring(assemblyName.LastIndexOf(".", StringComparison.Ordinal) + 1); return $"{Constants.FeatureContextIdentifier}/{parsedName}"; } catch { //NOOP } + return $"{Constants.FeatureContextIdentifier}/{assemblyName}"; } } \ No newline at end of file diff --git a/libraries/src/AWS.Lambda.Powertools.Logging/Internal/PowertoolsConfigurations.cs b/libraries/src/AWS.Lambda.Powertools.Logging/Internal/PowertoolsConfigurations.cs index 4e742250..2b3fc3ee 100644 --- a/libraries/src/AWS.Lambda.Powertools.Logging/Internal/PowertoolsConfigurations.cs +++ b/libraries/src/AWS.Lambda.Powertools.Logging/Internal/PowertoolsConfigurations.cs @@ -37,17 +37,25 @@ internal static LogLevel GetLogLevel(this IPowertoolsConfigurations powertoolsCo if (logLevel.HasValue) return logLevel.Value; - var logFromEnv = (powertoolsConfigurations.LogLevel ?? "").Trim(); - - if (AwsLogLevelMapper.TryGetValue(logFromEnv.ToUpper(), out var awsLogLevel)) - logFromEnv = awsLogLevel; - - if (Enum.TryParse(logFromEnv, true, out LogLevel result)) + if (Enum.TryParse((powertoolsConfigurations.LogLevel ?? "").Trim(), true, out LogLevel result)) return result; return LoggingConstants.DefaultLogLevel; } + internal static LogLevel GetLambdaLogLevel(this IPowertoolsConfigurations powertoolsConfigurations) + { + AwsLogLevelMapper.TryGetValue((powertoolsConfigurations.AWSLambdaLogLevel ?? "").Trim().ToUpper(), out var awsLogLevel); + + if (Enum.TryParse(awsLogLevel, true, out LogLevel result)) + { + //Logger.LogWarning("Oopss!!"); + return result; + } + + return LogLevel.None; + } + internal static LoggerOutputCase GetLoggerOutputCase(this IPowertoolsConfigurations powertoolsConfigurations, LoggerOutputCase? loggerOutputCase = null) { diff --git a/libraries/src/AWS.Lambda.Powertools.Logging/Internal/PowertoolsLogger.cs b/libraries/src/AWS.Lambda.Powertools.Logging/Internal/PowertoolsLogger.cs index 707d4a8e..2eab0693 100644 --- a/libraries/src/AWS.Lambda.Powertools.Logging/Internal/PowertoolsLogger.cs +++ b/libraries/src/AWS.Lambda.Powertools.Logging/Internal/PowertoolsLogger.cs @@ -61,6 +61,10 @@ internal sealed class PowertoolsLogger : ILogger /// private JsonSerializerOptions _jsonSerializerOptions; + private LogLevel _lambdaLogLevel; + private LogLevel _logLevel; + private bool _lambdaLogLevelEnabled; + /// /// Initializes a new instance of the class. /// @@ -78,14 +82,17 @@ public PowertoolsLogger( powertoolsConfigurations, systemWrapper, getCurrentConfig); _powertoolsConfigurations.SetExecutionEnvironment(this); + CurrentConfig = GetCurrentConfig(); + + if (_lambdaLogLevelEnabled && _logLevel < _lambdaLogLevel) + { + var message = + $"Current log level ({_logLevel}) does not match AWS Lambda Advanced Logging Controls minimum log level ({_lambdaLogLevel}). This can lead to data loss, consider adjusting them."; + this.LogWarning(message); + } } - /// - /// Sets the current configuration. - /// - /// The current configuration. - private LoggerConfiguration CurrentConfig => - _currentConfig ??= GetCurrentConfig(); + private LoggerConfiguration CurrentConfig { get; } /// /// Sets the minimum level. @@ -255,8 +262,15 @@ private Dictionary GetLogEntry(LogLevel logLevel, DateTime times } } + var keyLogLevel = LoggingConstants.KeyLogLevel; + // If ALC is enabled and PascalCase we need to convert Level to LogLevel for it to be parsed and sent to CW + if (_lambdaLogLevelEnabled && CurrentConfig.LoggerOutputCase == LoggerOutputCase.PascalCase) + { + keyLogLevel = "LogLevel"; + } + logEntry.TryAdd(LoggingConstants.KeyTimestamp, timestamp.ToString("o")); - logEntry.TryAdd(LoggingConstants.KeyLogLevel, logLevel.ToString()); + logEntry.TryAdd(keyLogLevel, logLevel.ToString()); logEntry.TryAdd(LoggingConstants.KeyService, Service); logEntry.TryAdd(LoggingConstants.KeyLoggerName, _name); logEntry.TryAdd(LoggingConstants.KeyMessage, message); @@ -371,14 +385,22 @@ internal void ClearConfig() private LoggerConfiguration GetCurrentConfig() { var currConfig = _getCurrentConfig(); - var minimumLevel = _powertoolsConfigurations.GetLogLevel(currConfig?.MinimumLevel); + _logLevel = _powertoolsConfigurations.GetLogLevel(currConfig?.MinimumLevel); var samplingRate = currConfig?.SamplingRate ?? _powertoolsConfigurations.LoggerSampleRate; var loggerOutputCase = _powertoolsConfigurations.GetLoggerOutputCase(currConfig?.LoggerOutputCase); - + _lambdaLogLevel = _powertoolsConfigurations.GetLambdaLogLevel(); + _lambdaLogLevelEnabled = _lambdaLogLevel != LogLevel.None; + + var minLogLevel = _logLevel; + if (_lambdaLogLevelEnabled) + { + minLogLevel = _lambdaLogLevel; + } + var config = new LoggerConfiguration { Service = currConfig?.Service, - MinimumLevel = minimumLevel, + MinimumLevel = minLogLevel, SamplingRate = samplingRate, LoggerOutputCase = loggerOutputCase }; @@ -388,7 +410,7 @@ private LoggerConfiguration GetCurrentConfig() if (samplingRate.Value < 0 || samplingRate.Value > 1) { - if (minimumLevel is LogLevel.Debug or LogLevel.Trace) + if (minLogLevel is LogLevel.Debug or LogLevel.Trace) _systemWrapper.LogLine( $"Skipping sampling rate configuration because of invalid value. Sampling rate: {samplingRate.Value}"); config.SamplingRate = null; diff --git a/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/PowertoolsLoggerTest.cs b/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/PowertoolsLoggerTest.cs index 298d409d..c49852af 100644 --- a/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/PowertoolsLoggerTest.cs +++ b/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/PowertoolsLoggerTest.cs @@ -1349,7 +1349,6 @@ public void Log_Should_Use_Powertools_Log_Level_When_Lambda_Log_Level_Enabled(bo [Theory] [InlineData(true, "WARN", LogLevel.Warning)] [InlineData(false, "Fatal", LogLevel.Critical)] - [InlineData(true, "NotValid", LogLevel.Information)] public void Log_Should_Use_AWS_Lambda_Log_Level_When_Enabled(bool willLog, string awsLogLevel, LogLevel logLevel) { // Arrange @@ -1381,10 +1380,107 @@ public void Log_Should_Use_AWS_Lambda_Log_Level_When_Enabled(bool willLog, strin // Assert Assert.True(logger.IsEnabled(logLevel)); - Assert.Equal(logLevel, configuration.GetLogLevel()); + Assert.Equal(LogLevel.Information, configuration.GetLogLevel()); //default + Assert.Equal(logLevel, configuration.GetLambdaLogLevel()); Assert.Equal(willLog, systemWrapper.LogMethodCalled); } + [Fact] + public void Log_Should_Show_Warning_When_AWS_Lambda_Log_Level_Enabled() + { + // Arrange + var loggerName = Guid.NewGuid().ToString(); + + var environment = Substitute.For(); + environment.GetEnvironmentVariable("POWERTOOLS_LOG_LEVEL").Returns("Debug"); + environment.GetEnvironmentVariable("AWS_LAMBDA_LOG_LEVEL").Returns("Warn"); + + var systemWrapper = new SystemWrapperMock(environment); + var configuration = new PowertoolsConfigurations(systemWrapper); + + var logger = new PowertoolsLogger(loggerName, configuration, systemWrapper, () => + new LoggerConfiguration + { + LoggerOutputCase = LoggerOutputCase.CamelCase + }); + + var logLevel = configuration.GetLogLevel(); + var lambdaLogLevel = configuration.GetLambdaLogLevel(); + + // Assert + Assert.True(logger.IsEnabled(LogLevel.Warning)); + Assert.Equal(LogLevel.Debug, logLevel); + Assert.Equal(LogLevel.Warning, lambdaLogLevel); + Assert.True(systemWrapper.LogMethodCalled); + Assert.Contains($"Current log level ({logLevel}) does not match AWS Lambda Advanced Logging Controls minimum log level ({lambdaLogLevel}). This can lead to data loss, consider adjusting them.", + systemWrapper.LogMethodCalledWithArgument); + } + + [Theory] + [InlineData(true,"LogLevel")] + [InlineData(false,"Level")] + public void Log_PascalCase_Outputs_Correct_Level_Property_When_AWS_Lambda_Log_Level_Enabled_Or_Disabled(bool alcEnabled, string levelProp) + { + // Arrange + var loggerName = Guid.NewGuid().ToString(); + + var environment = Substitute.For(); + environment.GetEnvironmentVariable("POWERTOOLS_LOG_LEVEL").Returns("Information"); + if(alcEnabled) + environment.GetEnvironmentVariable("AWS_LAMBDA_LOG_LEVEL").Returns("Info"); + + var systemWrapper = new SystemWrapperMock(environment); + var configuration = new PowertoolsConfigurations(systemWrapper); + var logger = new PowertoolsLogger(loggerName, configuration, systemWrapper, () => + new LoggerConfiguration + { + LoggerOutputCase = LoggerOutputCase.PascalCase + }); + + var message = new + { + PropOne = "Value 1", + }; + + logger.LogInformation(message); + + // Assert + Assert.True(systemWrapper.LogMethodCalled); + Assert.Contains($"\"{levelProp}\":\"Information\"",systemWrapper.LogMethodCalledWithArgument); + } + + [Theory] + [InlineData(LoggerOutputCase.CamelCase)] + [InlineData(LoggerOutputCase.SnakeCase)] + public void Log_CamelCase_Outputs_Level_When_AWS_Lambda_Log_Level_Enabled(LoggerOutputCase casing) + { + // Arrange + var loggerName = Guid.NewGuid().ToString(); + + var environment = Substitute.For(); + environment.GetEnvironmentVariable("POWERTOOLS_LOG_LEVEL").Returns(string.Empty); + environment.GetEnvironmentVariable("AWS_LAMBDA_LOG_LEVEL").Returns("Info"); + + var systemWrapper = new SystemWrapperMock(environment); + var configuration = new PowertoolsConfigurations(systemWrapper); + var logger = new PowertoolsLogger(loggerName, configuration, systemWrapper, () => + new LoggerConfiguration + { + LoggerOutputCase = casing + }); + + var message = new + { + PropOne = "Value 1", + }; + + logger.LogInformation(message); + + // Assert + Assert.True(systemWrapper.LogMethodCalled); + Assert.Contains("\"level\":\"Information\"",systemWrapper.LogMethodCalledWithArgument); + } + [Theory] [InlineData("TRACE", LogLevel.Trace)] [InlineData("debug", LogLevel.Debug)] @@ -1392,7 +1488,7 @@ public void Log_Should_Use_AWS_Lambda_Log_Level_When_Enabled(bool willLog, strin [InlineData("WARN", LogLevel.Warning)] [InlineData("ERROR", LogLevel.Error)] [InlineData("Fatal", LogLevel.Critical)] - [InlineData("DoesNotExist", LogLevel.Information)] + [InlineData("DoesNotExist", LogLevel.None)] public void Should_Map_AWS_Log_Level_And_Default_To_Information(string awsLogLevel, LogLevel logLevel) { // Arrange @@ -1403,7 +1499,7 @@ public void Should_Map_AWS_Log_Level_And_Default_To_Information(string awsLogLev var configuration = new PowertoolsConfigurations(systemWrapper); // Act - var logLvl = configuration.GetLogLevel(); + var logLvl = configuration.GetLambdaLogLevel(); // Assert Assert.Equal(logLevel, logLvl); diff --git a/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/Utilities/SystemWrapperMock.cs b/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/Utilities/SystemWrapperMock.cs index f709e5e6..4af6e593 100644 --- a/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/Utilities/SystemWrapperMock.cs +++ b/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/Utilities/SystemWrapperMock.cs @@ -21,6 +21,7 @@ public class SystemWrapperMock : ISystemWrapper { private readonly IPowertoolsEnvironment _powertoolsEnvironment; public bool LogMethodCalled { get; private set; } + public string LogMethodCalledWithArgument { get; private set; } public SystemWrapperMock(IPowertoolsEnvironment powertoolsEnvironment) { @@ -34,14 +35,17 @@ public string GetEnvironmentVariable(string variable) public void Log(string value) { + LogMethodCalledWithArgument = value; LogMethodCalled = true; } public void LogLine(string value) { + LogMethodCalledWithArgument = value; LogMethodCalled = true; } + public double GetRandom() { throw new System.NotImplementedException(); From 45886a613b546175370565dbf0dc97aeec1fc8f2 Mon Sep 17 00:00:00 2001 From: Henrique Graca <999396+hjgraca@users.noreply.github.com> Date: Thu, 16 Nov 2023 11:02:01 +0000 Subject: [PATCH 5/7] remove comments --- .../src/AWS.Lambda.Powertools.Common/Core/SystemWrapper.cs | 3 +-- .../Internal/PowertoolsConfigurations.cs | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/libraries/src/AWS.Lambda.Powertools.Common/Core/SystemWrapper.cs b/libraries/src/AWS.Lambda.Powertools.Common/Core/SystemWrapper.cs index 588ad4b6..6389b3a0 100644 --- a/libraries/src/AWS.Lambda.Powertools.Common/Core/SystemWrapper.cs +++ b/libraries/src/AWS.Lambda.Powertools.Common/Core/SystemWrapper.cs @@ -40,8 +40,7 @@ public SystemWrapper(IPowertoolsEnvironment powertoolsEnvironment) { _powertoolsEnvironment = powertoolsEnvironment; _instance ??= this; - - + // Clear AWS SDK Console injected parameters StdOut and StdErr var standardOutput = new StreamWriter(Console.OpenStandardOutput()); standardOutput.AutoFlush = true; diff --git a/libraries/src/AWS.Lambda.Powertools.Logging/Internal/PowertoolsConfigurations.cs b/libraries/src/AWS.Lambda.Powertools.Logging/Internal/PowertoolsConfigurations.cs index 2b3fc3ee..4d39cb16 100644 --- a/libraries/src/AWS.Lambda.Powertools.Logging/Internal/PowertoolsConfigurations.cs +++ b/libraries/src/AWS.Lambda.Powertools.Logging/Internal/PowertoolsConfigurations.cs @@ -49,7 +49,6 @@ internal static LogLevel GetLambdaLogLevel(this IPowertoolsConfigurations powert if (Enum.TryParse(awsLogLevel, true, out LogLevel result)) { - //Logger.LogWarning("Oopss!!"); return result; } From bda7ca33330bb766244f2359dac6abcefb4d8418 Mon Sep 17 00:00:00 2001 From: Henrique Graca <999396+hjgraca@users.noreply.github.com> Date: Thu, 16 Nov 2023 11:34:30 +0000 Subject: [PATCH 6/7] documentation --- docs/core/logging.md | 49 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 45 insertions(+), 4 deletions(-) diff --git a/docs/core/logging.md b/docs/core/logging.md index 63a04716..5064cd30 100644 --- a/docs/core/logging.md +++ b/docs/core/logging.md @@ -29,10 +29,6 @@ Setting | Description | Environment variable | Attribute parameter **Service** | Sets **Service** key that will be present across all log statements | `POWERTOOLS_SERVICE_NAME` | `Service` **Logging level** | Sets how verbose Logger should be (Information, by default) | `POWERTOOLS_LOG_LEVEL` | `LogLevel` -!!! warning "When using Lambda Log Format JSON" - - And Powertools Logger output is set to `PascalCase` **`Level`** property name will be replaced by **`LogLevel`** as a property name. - - The Lambda Application log level setting will control what is sent to CloudWatch. It takes precedence over **`POWERTOOLS_LOG_LEVEL`** and when setting it in code using **`[Logging(LogLevel = )]`** - ### Example using AWS Serverless Application Model (AWS SAM) You can override log level by setting **`POWERTOOLS_LOG_LEVEL`** environment variable in the AWS SAM template. @@ -73,6 +69,51 @@ Here is an example using the AWS SAM [Globals section](https://docs.aws.amazon.c | **POWERTOOLS_LOGGER_LOG_EVENT** | Logs incoming event | `false` | | **POWERTOOLS_LOGGER_SAMPLE_RATE** | Debug log sampling | `0` | + +### Using AWS Lambda Advanced Logging Controls (ALC) + +With [AWS Lambda Advanced Logging Controls (ALC)](https://docs.aws.amazon.com/lambda/latest/dg/monitoring-cloudwatchlogs.html#monitoring-cloudwatchlogs-advanced), you can control the output format of your logs as either TEXT or JSON and specify the minimum accepted log level for your application. Regardless of the output format setting in Lambda, Powertools for AWS Lambda will always output JSON formatted logging messages. + +When you have this feature enabled, log messages that don’t meet the configured log level are discarded by Lambda. For example, if you set the minimum log level to WARN, you will only receive WARN and ERROR messages in your AWS CloudWatch Logs, all other log levels will be discarded by Lambda. + +!!! warning "When using AWS Lambda Advanced Logging Controls (ALC)" + - When Powertools Logger output is set to `PascalCase` **`Level`** property name will be replaced by **`LogLevel`** as a property name. + - ALC takes precedence over **`POWERTOOLS_LOG_LEVEL`** and when setting it in code using **`[Logging(LogLevel = )]`** + +```mermaid +sequenceDiagram + title Lambda ALC allows WARN logs only + participant Lambda service + participant Lambda function + participant Application Logger + + Note over Lambda service: AWS_LAMBDA_LOG_LEVEL="WARN" + Lambda service->>Lambda function: Invoke (event) + Lambda function->>Lambda function: Calls handler + Lambda function->>Application Logger: Logger.Warning("Something happened") + Lambda function-->>Application Logger: Logger.Debug("Something happened") + Lambda function-->>Application Logger: Logger.Information("Something happened") + + Lambda service->>Lambda service: DROP INFO and DEBUG logs + + Lambda service->>CloudWatch Logs: Ingest error logs +``` + +Logger will automatically listen for the AWS_LAMBDA_LOG_FORMAT and AWS_LAMBDA_LOG_LEVEL environment variables, and change behaviour if they’re found to ensure as much compatibility as possible. + +**Priority of log level settings in Powertools for AWS Lambda** + +When the Advanced Logging Controls feature is enabled, we are unable to increase the minimum log level below the AWS_LAMBDA_LOG_LEVEL environment variable value, see [AWS Lambda service documentation](https://docs.aws.amazon.com/lambda/latest/dg/monitoring-cloudwatchlogs.html#monitoring-cloudwatchlogs-log-level) for more details. + +We prioritise log level settings in this order: + +1. AWS_LAMBDA_LOG_LEVEL environment variable +2. Setting the log level in code using logger.setLevel() +3. POWERTOOLS_LOG_LEVEL environment variable + +In the event you have set POWERTOOLS_LOG_LEVEL to a level lower than the ACL setting, Powertools for AWS Lambda will output a warning log message informing you that your messages will be discarded by Lambda. + + ## Standard structured keys Your logs will always include the following keys to your structured logging: From fcb180c485270a2df1efb23760be769fca895983 Mon Sep 17 00:00:00 2001 From: Henrique Graca <999396+hjgraca@users.noreply.github.com> Date: Thu, 16 Nov 2023 14:32:30 +0000 Subject: [PATCH 7/7] remove unused --- docs/core/logging.md | 2 +- .../Internal/PowertoolsLogger.cs | 9 ++------- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/docs/core/logging.md b/docs/core/logging.md index 5064cd30..6cec97ce 100644 --- a/docs/core/logging.md +++ b/docs/core/logging.md @@ -108,7 +108,7 @@ When the Advanced Logging Controls feature is enabled, we are unable to increase We prioritise log level settings in this order: 1. AWS_LAMBDA_LOG_LEVEL environment variable -2. Setting the log level in code using logger.setLevel() +2. Setting the log level in code using `[Logging(LogLevel = )]` 3. POWERTOOLS_LOG_LEVEL environment variable In the event you have set POWERTOOLS_LOG_LEVEL to a level lower than the ACL setting, Powertools for AWS Lambda will output a warning log message informing you that your messages will be discarded by Lambda. diff --git a/libraries/src/AWS.Lambda.Powertools.Logging/Internal/PowertoolsLogger.cs b/libraries/src/AWS.Lambda.Powertools.Logging/Internal/PowertoolsLogger.cs index 2eab0693..27d7d613 100644 --- a/libraries/src/AWS.Lambda.Powertools.Logging/Internal/PowertoolsLogger.cs +++ b/libraries/src/AWS.Lambda.Powertools.Logging/Internal/PowertoolsLogger.cs @@ -50,11 +50,6 @@ internal sealed class PowertoolsLogger : ILogger /// The system wrapper /// private readonly ISystemWrapper _systemWrapper; - - /// - /// The current configuration - /// - private LoggerConfiguration _currentConfig; /// /// The JsonSerializer options @@ -92,7 +87,7 @@ public PowertoolsLogger( } } - private LoggerConfiguration CurrentConfig { get; } + private LoggerConfiguration CurrentConfig { get; set; } /// /// Sets the minimum level. @@ -375,7 +370,7 @@ private object GetFormattedLogEntry(LogLevel logLevel, DateTime timestamp, objec /// internal void ClearConfig() { - _currentConfig = null; + CurrentConfig = null; } ///