From 96e73dd22aee69d4e4828f636b63477d01384ed5 Mon Sep 17 00:00:00 2001 From: Jeevan Yewale Date: Wed, 21 Jan 2026 12:17:55 +0530 Subject: [PATCH] Add TenantId to Logger default properties Signed-off-by: Jeevan Yewale --- .../json/resolver/PowertoolsResolver.java | 18 ++++++++++++++++ .../src/main/resources/LambdaEcsLayout.json | 4 ++++ .../src/main/resources/LambdaJsonLayout.json | 4 ++++ .../logging/logback/LambdaEcsEncoder.java | 7 +++++++ .../logging/logback/LambdaJsonEncoder.java | 1 + .../internal/PowertoolsLoggedFields.java | 21 ++++++++++++++++++- 6 files changed, 54 insertions(+), 1 deletion(-) diff --git a/powertools-logging/powertools-logging-log4j/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsResolver.java b/powertools-logging/powertools-logging-log4j/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsResolver.java index cef5b86ee..8d7252093 100644 --- a/powertools-logging/powertools-logging-log4j/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsResolver.java +++ b/powertools-logging/powertools-logging-log4j/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsResolver.java @@ -25,6 +25,7 @@ import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_VERSION; import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.SAMPLING_RATE; import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.SERVICE; +import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.TENANT_ID; import java.io.IOException; import java.util.Collections; @@ -168,6 +169,22 @@ public void resolve(LogEvent logEvent, JsonWriter jsonWriter) { private static final EventResolver REGION_RESOLVER = (final LogEvent logEvent, final JsonWriter jsonWriter) -> jsonWriter.writeString(SystemWrapper.getenv(LambdaConstants.AWS_REGION_ENV)); + + private static final EventResolver TENANT_ID_RESOLVER = new EventResolver() { + @Override + public boolean isResolvable(LogEvent logEvent) { + final String tenantId = + logEvent.getContextData().getValue(PowertoolsLoggedFields.TENANT_ID.getName()); + return null != tenantId; + } + + @Override + public void resolve(LogEvent logEvent, JsonWriter jsonWriter) { + final String tenantId = + logEvent.getContextData().getValue(PowertoolsLoggedFields.TENANT_ID.getName()); + jsonWriter.writeString(tenantId); + } + }; public static final String LAMBDA_ARN_REGEX = "^arn:(aws|aws-us-gov|aws-cn):lambda:[a-zA-Z0-9-]+:\\d{12}:function:[a-zA-Z0-9-_]+(:[a-zA-Z0-9-_]+)?$"; @@ -233,6 +250,7 @@ public void resolve(LogEvent logEvent, JsonWriter jsonWriter) { { FUNCTION_TRACE_ID.getName(), XRAY_TRACE_RESOLVER }, { CORRELATION_ID.getName(), CORRELATION_ID_RESOLVER }, { SAMPLING_RATE.getName(), SAMPLING_RATE_RESOLVER }, + { TENANT_ID.getName(), TENANT_ID_RESOLVER }, { "region", REGION_RESOLVER }, { "account_id", ACCOUNT_ID_RESOLVER } }).collect(Collectors.toMap(data -> (String) data[0], data -> (EventResolver) data[1]))); diff --git a/powertools-logging/powertools-logging-log4j/src/main/resources/LambdaEcsLayout.json b/powertools-logging/powertools-logging-log4j/src/main/resources/LambdaEcsLayout.json index 58b30f60e..a54d8f8b6 100644 --- a/powertools-logging/powertools-logging-log4j/src/main/resources/LambdaEcsLayout.json +++ b/powertools-logging/powertools-logging-log4j/src/main/resources/LambdaEcsLayout.json @@ -87,6 +87,10 @@ "$resolver": "powertools", "field": "correlation_id" }, + "tenant.id": { + "$resolver": "powertools", + "field": "tenant_id" + }, "": { "$resolver": "powertools" } diff --git a/powertools-logging/powertools-logging-log4j/src/main/resources/LambdaJsonLayout.json b/powertools-logging/powertools-logging-log4j/src/main/resources/LambdaJsonLayout.json index 793006502..e9991638c 100644 --- a/powertools-logging/powertools-logging-log4j/src/main/resources/LambdaJsonLayout.json +++ b/powertools-logging/powertools-logging-log4j/src/main/resources/LambdaJsonLayout.json @@ -69,6 +69,10 @@ "$resolver": "powertools", "field": "correlation_id" }, + "tenant_id": { + "$resolver": "powertools", + "field": "tenant_id" + }, "": { "$resolver": "powertools" } diff --git a/powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/LambdaEcsEncoder.java b/powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/LambdaEcsEncoder.java index 6a82d8e67..d4c78340e 100644 --- a/powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/LambdaEcsEncoder.java +++ b/powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/LambdaEcsEncoder.java @@ -23,6 +23,7 @@ import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_REQUEST_ID; import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_TRACE_ID; import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_VERSION; +import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.TENANT_ID; import static software.amazon.lambda.powertools.logging.logback.JsonUtils.serializeArguments; import static software.amazon.lambda.powertools.logging.logback.JsonUtils.serializeMDCEntries; import static software.amazon.lambda.powertools.logging.logback.JsonUtils.serializeTimestamp; @@ -74,6 +75,7 @@ public class LambdaEcsEncoder extends EncoderBase { protected static final String FUNCTION_MEMORY_ATTR_NAME = "faas.memory"; protected static final String FUNCTION_TRACE_ID_ATTR_NAME = "trace.id"; protected static final String CORRELATION_ID_ATTR_NAME = "correlation.id"; + protected static final String TENANT_ID_ATTR_NAME = "tenant.id"; protected static final String ECS_VERSION = "1.2.0"; protected static final String CLOUD_PROVIDER = "aws"; @@ -163,6 +165,11 @@ private void serializeFunctionInfo(JsonSerializer serializer, String arn, Mapxray_trace_id *
  • sampling_rate
  • *
  • service
  • + *
  • tenant_id
  • * *
    * We strongly recommend to keep these information. diff --git a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/PowertoolsLoggedFields.java b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/PowertoolsLoggedFields.java index 2545396d2..7b08021d8 100644 --- a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/PowertoolsLoggedFields.java +++ b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/PowertoolsLoggedFields.java @@ -15,6 +15,7 @@ package software.amazon.lambda.powertools.logging.internal; import com.amazonaws.services.lambda.runtime.Context; +import java.lang.reflect.Method; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -35,7 +36,8 @@ public enum PowertoolsLoggedFields { FUNCTION_TRACE_ID("xray_trace_id"), SAMPLING_RATE("sampling_rate"), CORRELATION_ID("correlation_id"), - SERVICE("service"); + SERVICE("service"), + TENANT_ID("tenant_id"); private final String name; @@ -55,9 +57,26 @@ public static Map setValuesFromLambdaContext(Context context) { hashMap.put(FUNCTION_ARN.name, context.getInvokedFunctionArn()); hashMap.put(FUNCTION_MEMORY_SIZE.name, String.valueOf(context.getMemoryLimitInMB())); hashMap.put(FUNCTION_REQUEST_ID.name, String.valueOf(context.getAwsRequestId())); + + // Add TenantId if available (Lambda Tenant Isolation feature) + String tenantId = getTenantId(context); + if (tenantId != null) { + hashMap.put(TENANT_ID.name, tenantId); + } return hashMap; } + + private static String getTenantId(Context context) { + try { + Method getTenantIdMethod = context.getClass().getMethod("getTenantId"); + Object tenantId = getTenantIdMethod.invoke(context); + return tenantId != null ? tenantId.toString() : null; + } catch (Exception e) { + // TenantId method not available or failed to invoke + return null; + } + } public String getName() { return name;