From a512d6d7cb0f1d9fb97dbc890aa18572e54d723c Mon Sep 17 00:00:00 2001 From: Henrique Graca <999396+hjgraca@users.noreply.github.com> Date: Fri, 15 May 2026 15:38:08 +0100 Subject: [PATCH] fix(logging): POWERTOOLS_LOG_LEVEL=Trace/Debug no longer ignored (#1205) When no explicit MinimumLogLevel was configured, the Microsoft.Extensions.Logging factory defaulted to Information, silently filtering Trace/Debug before they reached the PowertoolsLoggerProvider. Set the factory minimum to Trace so the provider's env-var-derived filtering is the single source of truth. --- .../Internal/Helpers/LoggerFactoryHelper.cs | 7 ++ .../PowertoolsLoggingBuilderExtensions.cs | 5 +- .../Attributes/LoggingAttributeTest.cs | 38 ++++++++ .../Handlers/HandlerTests.cs | 92 +++++++++++++++++++ .../Handlers/TestHandlers.cs | 11 +++ 5 files changed, 152 insertions(+), 1 deletion(-) diff --git a/libraries/src/AWS.Lambda.Powertools.Logging/Internal/Helpers/LoggerFactoryHelper.cs b/libraries/src/AWS.Lambda.Powertools.Logging/Internal/Helpers/LoggerFactoryHelper.cs index 17fc402ac..c5969615b 100644 --- a/libraries/src/AWS.Lambda.Powertools.Logging/Internal/Helpers/LoggerFactoryHelper.cs +++ b/libraries/src/AWS.Lambda.Powertools.Logging/Internal/Helpers/LoggerFactoryHelper.cs @@ -45,6 +45,13 @@ internal static ILoggerFactory CreateAndConfigureFactory(PowertoolsLoggerConfigu builder.AddFilter(null, configuration.MinimumLogLevel); builder.SetMinimumLevel(configuration.MinimumLogLevel); } + else + { + // No explicit level configured — let everything through the factory + // so the provider can filter based on POWERTOOLS_LOG_LEVEL env var + builder.AddFilter(null, LogLevel.Trace); + builder.SetMinimumLevel(LogLevel.Trace); + } }); LoggerFactoryHolder.SetFactory(factory); diff --git a/libraries/src/AWS.Lambda.Powertools.Logging/PowertoolsLoggingBuilderExtensions.cs b/libraries/src/AWS.Lambda.Powertools.Logging/PowertoolsLoggingBuilderExtensions.cs index 6725f0395..1f91e42a9 100644 --- a/libraries/src/AWS.Lambda.Powertools.Logging/PowertoolsLoggingBuilderExtensions.cs +++ b/libraries/src/AWS.Lambda.Powertools.Logging/PowertoolsLoggingBuilderExtensions.cs @@ -97,6 +97,10 @@ public static ILoggingBuilder AddPowertoolsLogger( builder.Services.TryAddSingleton(provider => provider.GetRequiredService().CreatePowertoolsLogger()); + // Default the factory minimum to Trace so the framework doesn't filter + // before our provider. The provider handles env-var-derived level filtering. + builder.SetMinimumLevel(LogLevel.Trace); + builder.Services.TryAddEnumerable( ServiceDescriptor.Singleton(provider => { @@ -174,7 +178,6 @@ public static ILoggingBuilder AddPowertoolsLogger( var options = new PowertoolsLoggerConfiguration(); configure(options); - // IMPORTANT: Set the minimum level directly on the builder if (options.MinimumLogLevel != LogLevel.None) { builder.SetMinimumLevel(options.MinimumLogLevel); diff --git a/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/Attributes/LoggingAttributeTest.cs b/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/Attributes/LoggingAttributeTest.cs index 78635a4a6..2667d446b 100644 --- a/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/Attributes/LoggingAttributeTest.cs +++ b/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/Attributes/LoggingAttributeTest.cs @@ -727,6 +727,44 @@ public void LoggingAspect_ShouldImmediatelyApplyFilterLevelChanges() s.Contains("\"message\":\"This should NOT be logged\""))); } + [Theory] + // Reproduces issue #1205 test matrix + [InlineData(null, "information,warning,error,critical", "trace,debug")] + [InlineData("Trace", "trace,debug,information,warning,error,critical", "")] + [InlineData("Debug", "debug,information,warning,error,critical", "trace")] + [InlineData("Information", "information,warning,error,critical", "trace,debug")] + [InlineData("Warning", "warning,error,critical", "trace,debug,information")] + [InlineData("Error", "error,critical", "trace,debug,information,warning")] + [InlineData("Critical", "critical", "trace,debug,information,warning,error")] + public void LoggingAttribute_ShouldRespectEnvVarLogLevel(string envLogLevel, string expectedCsv, string missingCsv) + { + // Reproduces issue #1205: POWERTOOLS_LOG_LEVEL=Trace/Debug ignored when using [Logging] attribute + Environment.SetEnvironmentVariable("POWERTOOLS_LOG_LEVEL", envLogLevel); + + var consoleOut = new TestLoggerOutput(); + Logger.Configure(options => + { + options.LogOutput = consoleOut; + }); + + _testHandlers.TestMethodAllLevels(); + + var logOutput = consoleOut.ToString(); + + foreach (var level in expectedCsv.Split(',')) + { + Assert.Contains($"LEVELTEST {level}", logOutput); + } + + if (!string.IsNullOrEmpty(missingCsv)) + { + foreach (var level in missingCsv.Split(',')) + { + Assert.DoesNotContain($"LEVELTEST {level}", logOutput); + } + } + } + public void Dispose() { ResetAllState(); diff --git a/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/Handlers/HandlerTests.cs b/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/Handlers/HandlerTests.cs index 3aa20a417..f0f700413 100644 --- a/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/Handlers/HandlerTests.cs +++ b/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/Handlers/HandlerTests.cs @@ -517,6 +517,98 @@ public void EnvironmentVariableSampling_HandlerWithFullSampling_ShouldAlwaysElev } } + [Theory] + [InlineData("Trace", "LEVELTEST trace", true)] + [InlineData("Trace", "LEVELTEST debug", true)] + [InlineData("Trace", "LEVELTEST information", true)] + [InlineData("Debug", "LEVELTEST debug", true)] + [InlineData("Debug", "LEVELTEST information", true)] + [InlineData("Debug", "LEVELTEST trace", false)] + [InlineData("Information", "LEVELTEST trace", false)] + [InlineData("Information", "LEVELTEST debug", false)] + [InlineData("Information", "LEVELTEST information", true)] + public void PowertoolsLogLevel_EnvVar_ShouldFilterCorrectly(string envLogLevel, string expectedMessage, bool shouldAppear) + { + var originalLogLevel = Environment.GetEnvironmentVariable("POWERTOOLS_LOG_LEVEL"); + + try + { + Environment.SetEnvironmentVariable("POWERTOOLS_LOG_LEVEL", envLogLevel); + + var output = new TestLoggerOutput(); + Logger.Reset(); + Logger.Configure(options => + { + options.LogOutput = output; + options.Service = "LevelTestService"; + }); + + Logger.LogTrace("LEVELTEST trace"); + Logger.LogDebug("LEVELTEST debug"); + Logger.LogInformation("LEVELTEST information"); + + var logOutput = output.ToString(); + _output.WriteLine(logOutput); + + if (shouldAppear) + { + Assert.Contains(expectedMessage, logOutput); + } + else + { + Assert.DoesNotContain(expectedMessage, logOutput); + } + } + finally + { + Environment.SetEnvironmentVariable("POWERTOOLS_LOG_LEVEL", originalLogLevel); + Logger.Reset(); + } + } + + [Fact] + public void PowertoolsLogLevel_Trace_ViaLoggerFactory_ShouldEmitAllLevels() + { + var originalLogLevel = Environment.GetEnvironmentVariable("POWERTOOLS_LOG_LEVEL"); + + try + { + Environment.SetEnvironmentVariable("POWERTOOLS_LOG_LEVEL", "Trace"); + + var output = new TestLoggerOutput(); + var logger = LoggerFactory.Create(builder => + { + builder.AddPowertoolsLogger(config => + { + config.Service = "LevelTestService"; + config.LogOutput = output; + }); + }).CreatePowertoolsLogger(); + + logger.LogTrace("LEVELTEST trace"); + logger.LogDebug("LEVELTEST debug"); + logger.LogInformation("LEVELTEST information"); + logger.LogWarning("LEVELTEST warning"); + logger.LogError("LEVELTEST error"); + logger.LogCritical("LEVELTEST critical"); + + var logOutput = output.ToString(); + _output.WriteLine(logOutput); + + Assert.Contains("LEVELTEST trace", logOutput); + Assert.Contains("LEVELTEST debug", logOutput); + Assert.Contains("LEVELTEST information", logOutput); + Assert.Contains("LEVELTEST warning", logOutput); + Assert.Contains("LEVELTEST error", logOutput); + Assert.Contains("LEVELTEST critical", logOutput); + } + finally + { + Environment.SetEnvironmentVariable("POWERTOOLS_LOG_LEVEL", originalLogLevel); + Logger.Reset(); + } + } + /// /// Test with 0% sampling rate to ensure info logs are not elevated /// diff --git a/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/Handlers/TestHandlers.cs b/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/Handlers/TestHandlers.cs index 9154eaf04..1fe1edc0c 100644 --- a/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/Handlers/TestHandlers.cs +++ b/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/Handlers/TestHandlers.cs @@ -24,6 +24,17 @@ public void TestMethodDebug() { } + [Logging(ClearState = true)] + public void TestMethodAllLevels() + { + Logger.LogTrace("LEVELTEST trace"); + Logger.LogDebug("LEVELTEST debug"); + Logger.LogInformation("LEVELTEST information"); + Logger.LogWarning("LEVELTEST warning"); + Logger.LogError("LEVELTEST error"); + Logger.LogCritical("LEVELTEST critical"); + } + [Logging(LogEvent = true)] public void LogEventNoArgs() {