From cd3d6fbf347a008132b7299e047f29ae6dd90709 Mon Sep 17 00:00:00 2001 From: jihed-garaouch Date: Thu, 8 Jan 2026 19:36:24 +0100 Subject: [PATCH 1/2] feat: add TenantId to default logger properties --- .../Internal/LoggingLambdaContext.cs | 9 ++++++++- .../Context/LambdaContextTest.cs | 7 +++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/libraries/src/AWS.Lambda.Powertools.Logging/Internal/LoggingLambdaContext.cs b/libraries/src/AWS.Lambda.Powertools.Logging/Internal/LoggingLambdaContext.cs index 9732bad04..403f1ce48 100644 --- a/libraries/src/AWS.Lambda.Powertools.Logging/Internal/LoggingLambdaContext.cs +++ b/libraries/src/AWS.Lambda.Powertools.Logging/Internal/LoggingLambdaContext.cs @@ -53,6 +53,11 @@ internal class LoggingLambdaContext /// internal int MemoryLimitInMB { get; private set; } + /// + /// The tenant ID associated with the Lambda invocation. + /// + internal string TenantId { get; private set; } + /// /// The instance /// @@ -86,7 +91,9 @@ public static bool Extract(AspectEventArgs args) InvokedFunctionArn = x.InvokedFunctionArn, LogGroupName = x.LogGroupName, LogStreamName = x.LogStreamName, - MemoryLimitInMB = x.MemoryLimitInMB + MemoryLimitInMB = x.MemoryLimitInMB, + TenantId =x.TenantId, + }; return true; } diff --git a/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/Context/LambdaContextTest.cs b/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/Context/LambdaContextTest.cs index 31e980ba8..2c0845ef2 100644 --- a/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/Context/LambdaContextTest.cs +++ b/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/Context/LambdaContextTest.cs @@ -23,7 +23,8 @@ public void Extract_WhenHasLambdaContextArgument_InitializesLambdaContextInfo() InvokedFunctionArn = Guid.NewGuid().ToString(), LogGroupName = Guid.NewGuid().ToString(), LogStreamName = Guid.NewGuid().ToString(), - MemoryLimitInMB = new Random().Next() + MemoryLimitInMB = new Random().Next(), + TenantId = Guid.NewGuid().ToString() }; var args = Substitute.For(); @@ -52,6 +53,7 @@ public void Extract_WhenHasLambdaContextArgument_InitializesLambdaContextInfo() Assert.Equal(LoggingLambdaContext.Instance.LogGroupName, lambdaContext.LogGroupName); Assert.Equal(LoggingLambdaContext.Instance.LogStreamName, lambdaContext.LogStreamName); Assert.Equal(LoggingLambdaContext.Instance.MemoryLimitInMB, lambdaContext.MemoryLimitInMB); + Assert.Equal(LoggingLambdaContext.Instance.TenantId, lambdaContext.TenantId); LoggingLambdaContext.Clear(); Assert.Null(LoggingLambdaContext.Instance); } @@ -120,7 +122,8 @@ public void Extract_WhenInstance_Already_Created_Returns_False() InvokedFunctionArn = Guid.NewGuid().ToString(), LogGroupName = Guid.NewGuid().ToString(), LogStreamName = Guid.NewGuid().ToString(), - MemoryLimitInMB = new Random().Next() + MemoryLimitInMB = new Random().Next(), + TenantId = Guid.NewGuid().ToString() }; var args = Substitute.For(); From 05c925a5f4a329cc38df99fcd6c467a080d20f39 Mon Sep 17 00:00:00 2001 From: Henrique Graca <999396+hjgraca@users.noreply.github.com> Date: Fri, 9 Jan 2026 10:17:12 +0000 Subject: [PATCH 2/2] feat(logging): add TenantId to logger properties and enhance logging tests --- .../Internal/LoggingConstants.cs | 5 ++ .../Internal/LoggingLambdaContext.cs | 3 +- .../Internal/PowertoolsLogger.cs | 4 ++ .../LogEntryLambdaContext.cs | 5 ++ .../Attributes/LoggingAttributeTest.cs | 66 +++++++++++++++++++ .../Handlers/HandlerTests.cs | 4 +- 6 files changed, 84 insertions(+), 3 deletions(-) diff --git a/libraries/src/AWS.Lambda.Powertools.Logging/Internal/LoggingConstants.cs b/libraries/src/AWS.Lambda.Powertools.Logging/Internal/LoggingConstants.cs index 1ff29c35f..e7c0639f2 100644 --- a/libraries/src/AWS.Lambda.Powertools.Logging/Internal/LoggingConstants.cs +++ b/libraries/src/AWS.Lambda.Powertools.Logging/Internal/LoggingConstants.cs @@ -111,4 +111,9 @@ internal static class LoggingConstants /// Constant for key exception /// internal const string KeyException = "Exception"; + + /// + /// Constant for key tenant id + /// + public const string KeyFunctionTenantId = "TenantId"; } \ No newline at end of file diff --git a/libraries/src/AWS.Lambda.Powertools.Logging/Internal/LoggingLambdaContext.cs b/libraries/src/AWS.Lambda.Powertools.Logging/Internal/LoggingLambdaContext.cs index 403f1ce48..2b7e41cbe 100644 --- a/libraries/src/AWS.Lambda.Powertools.Logging/Internal/LoggingLambdaContext.cs +++ b/libraries/src/AWS.Lambda.Powertools.Logging/Internal/LoggingLambdaContext.cs @@ -92,8 +92,7 @@ public static bool Extract(AspectEventArgs args) LogGroupName = x.LogGroupName, LogStreamName = x.LogStreamName, MemoryLimitInMB = x.MemoryLimitInMB, - TenantId =x.TenantId, - + TenantId = x.TenantId, }; return true; } diff --git a/libraries/src/AWS.Lambda.Powertools.Logging/Internal/PowertoolsLogger.cs b/libraries/src/AWS.Lambda.Powertools.Logging/Internal/PowertoolsLogger.cs index 26ee5ec64..b97cbdc36 100644 --- a/libraries/src/AWS.Lambda.Powertools.Logging/Internal/PowertoolsLogger.cs +++ b/libraries/src/AWS.Lambda.Powertools.Logging/Internal/PowertoolsLogger.cs @@ -457,6 +457,9 @@ private void AddLambdaContextKeys(Dictionary logEntry) logEntry.TryAdd(LoggingConstants.KeyFunctionArn, context.InvokedFunctionArn); logEntry.TryAdd(LoggingConstants.KeyFunctionRequestId, context.AwsRequestId); logEntry.TryAdd(LoggingConstants.KeyFunctionVersion, context.FunctionVersion); + + if(!string.IsNullOrEmpty(context.TenantId)) + logEntry.TryAdd(LoggingConstants.KeyFunctionTenantId, context.TenantId); } /// @@ -474,6 +477,7 @@ private LogEntryLambdaContext CreateLambdaContext() MemoryLimitInMB = context.MemoryLimitInMB, InvokedFunctionArn = context.InvokedFunctionArn, AwsRequestId = context.AwsRequestId, + TenantId = context.TenantId }; } diff --git a/libraries/src/AWS.Lambda.Powertools.Logging/LogEntryLambdaContext.cs b/libraries/src/AWS.Lambda.Powertools.Logging/LogEntryLambdaContext.cs index b83c933ef..1547bce81 100644 --- a/libraries/src/AWS.Lambda.Powertools.Logging/LogEntryLambdaContext.cs +++ b/libraries/src/AWS.Lambda.Powertools.Logging/LogEntryLambdaContext.cs @@ -53,4 +53,9 @@ public class LogEntryLambdaContext /// CloudWatch actions. /// public string InvokedFunctionArn { get; internal set; } + + /// + /// Tenancy ID associated with the Lambda invocation. + /// + public string TenantId { get; set; } } \ No newline at end of file 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 9b0542f76..78635a4a6 100644 --- a/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/Attributes/LoggingAttributeTest.cs +++ b/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/Attributes/LoggingAttributeTest.cs @@ -119,6 +119,72 @@ public void OnEntry_WhenEventArgExist_LogEvent() ); } + [Fact] + public void OnEntry_When_TenantId_Exist_Log() + { + // Arrange + var consoleOut = GetConsoleOutput(); + var correlationId = Guid.NewGuid().ToString(); + Logger.Configure(options => + { + options.LogOutput = consoleOut; + }); + + var context = new TestLambdaContext() + { + TenantId = "Tenant-12345", + }; + + var testObj = new TestObject + { + Headers = new Header + { + MyRequestIdHeader = correlationId + } + }; + + // Act + _testHandlers.LogEvent(testObj, context); + + consoleOut.Received(1).WriteLine( + Arg.Is(i => i.Contains("TenantId\":\"Tenant-12345")) + ); + } + + [Theory] + [InlineData("")] + [InlineData(null)] + public void OnEntry_When_TenantId_Does_Not_Exist_Dont_Log(string tenantId) + { + // Arrange + var consoleOut = GetConsoleOutput(); + var correlationId = Guid.NewGuid().ToString(); + Logger.Configure(options => + { + options.LogOutput = consoleOut; + }); + + var context = new TestLambdaContext() + { + TenantId = tenantId, + }; + + var testObj = new TestObject + { + Headers = new Header + { + MyRequestIdHeader = correlationId + } + }; + + // Act + _testHandlers.LogEvent(testObj, context); + + consoleOut.DidNotReceive().WriteLine( + Arg.Is(i => i.Contains("\"TenantId\"")) + ); + } + [Fact] public void OnEntry_WhenEventArgExist_LogEvent_False_Should_Not_Log() { 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 9a4395917..b4724a79a 100644 --- a/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/Handlers/HandlerTests.cs +++ b/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/Handlers/HandlerTests.cs @@ -107,7 +107,8 @@ public void TestMethod() FunctionName = "test-function", FunctionVersion = "1", AwsRequestId = "123", - InvokedFunctionArn = "arn:aws:lambda:us-east-1:123456789012:function:test-function" + InvokedFunctionArn = "arn:aws:lambda:us-east-1:123456789012:function:test-function", + TenantId = "tenant-123" }); handler.TestMethodCorrelation(new ExampleClass @@ -131,6 +132,7 @@ public void TestMethod() Assert.Contains("\"Custom-key\": \"custom-value\"", logOutput); Assert.Contains("\"FunctionName\": \"test-function\"", logOutput); Assert.Contains("\"SamplingRate\": 0.002", logOutput); + Assert.Contains("\"TenantId\": \"tenant-123\"", logOutput); } [Fact]