Skip to content

Commit febb4f5

Browse files
author
Pankaj Agrawal
committed
feat: ability to clear state of logger on each request for custom keys
1 parent 2ebe301 commit febb4f5

File tree

4 files changed

+76
-0
lines changed

4 files changed

+76
-0
lines changed

powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/Logging.java

+7
Original file line numberDiff line numberDiff line change
@@ -73,4 +73,11 @@
7373
* @see <a href=https://datatracker.ietf.org/doc/html/draft-ietf-appsawg-json-pointer-03/>
7474
*/
7575
String correlationIdPath() default "";
76+
77+
/**
78+
* Logger is commonly initialized in the global scope.
79+
* Due to Lambda Execution Context reuse, this means that custom keys can be persisted across invocations.
80+
* Set this attribute to true if you want all custom keys to be deleted on each request.
81+
*/
82+
boolean clearState() default false;
7683
}

powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspect.java

+5
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.apache.logging.log4j.Level;
3030
import org.apache.logging.log4j.LogManager;
3131
import org.apache.logging.log4j.Logger;
32+
import org.apache.logging.log4j.ThreadContext;
3233
import org.apache.logging.log4j.core.LoggerContext;
3334
import org.apache.logging.log4j.core.config.Configurator;
3435
import org.apache.logging.log4j.core.util.IOUtils;
@@ -103,6 +104,10 @@ public Object around(ProceedingJoinPoint pjp,
103104

104105
Object proceed = pjp.proceed(proceedArgs);
105106

107+
if(logging.clearState()) {
108+
ThreadContext.clearMap();
109+
}
110+
106111
coldStartDone();
107112
return proceed;
108113
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
* Copyright 2020 Amazon.com, Inc. or its affiliates.
3+
* Licensed under the Apache License, Version 2.0 (the
4+
* "License"); you may not use this file except in compliance
5+
* with the License. You may obtain a copy of the License at
6+
* http://www.apache.org/licenses/LICENSE-2.0
7+
* Unless required by applicable law or agreed to in writing, software
8+
* distributed under the License is distributed on an "AS IS" BASIS,
9+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10+
* See the License for the specific language governing permissions and
11+
* limitations under the License.
12+
*
13+
*/
14+
package software.amazon.lambda.powertools.logging.handlers;
15+
16+
import com.amazonaws.services.lambda.runtime.Context;
17+
import com.amazonaws.services.lambda.runtime.RequestHandler;
18+
import org.apache.logging.log4j.LogManager;
19+
import org.apache.logging.log4j.Logger;
20+
import software.amazon.lambda.powertools.logging.Logging;
21+
import software.amazon.lambda.powertools.logging.LoggingUtils;
22+
23+
public class PowerLogToolEnabledWithClearState implements RequestHandler<Object, Object> {
24+
private final Logger LOG = LogManager.getLogger(PowerLogToolEnabledWithClearState.class);
25+
public static int COUNT = 1;
26+
@Override
27+
@Logging(clearState = true)
28+
public Object handleRequest(Object input, Context context) {
29+
if(COUNT == 1) {
30+
LoggingUtils.appendKey("TestKey", "TestValue");
31+
}
32+
LOG.info("Test event");
33+
COUNT++;
34+
return null;
35+
}
36+
37+
@Logging
38+
public void anotherMethod() {
39+
System.out.println("test");
40+
}
41+
}

powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspectTest.java

+23
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@
2525
import java.nio.file.Files;
2626
import java.nio.file.Paths;
2727
import java.nio.file.StandardOpenOption;
28+
import java.util.List;
2829
import java.util.Map;
30+
import java.util.stream.Collectors;
2931

3032
import com.amazonaws.services.lambda.runtime.Context;
3133
import com.amazonaws.services.lambda.runtime.RequestHandler;
@@ -52,6 +54,7 @@
5254
import software.amazon.lambda.powertools.logging.handlers.PowerLogToolApiGatewayRestApiCorrelationId;
5355
import software.amazon.lambda.powertools.logging.handlers.PowerLogToolEnabled;
5456
import software.amazon.lambda.powertools.logging.handlers.PowerLogToolEnabledForStream;
57+
import software.amazon.lambda.powertools.logging.handlers.PowerLogToolEnabledWithClearState;
5558
import software.amazon.lambda.powertools.logging.handlers.PowerToolDisabled;
5659
import software.amazon.lambda.powertools.logging.handlers.PowerToolDisabledForStream;
5760
import software.amazon.lambda.powertools.logging.handlers.PowerToolLogEventEnabled;
@@ -289,6 +292,26 @@ void shouldLogCorrelationIdOnALBEvent(ApplicationLoadBalancerRequestEvent event)
289292
.containsEntry("correlation_id", event.getHeaders().get("x-amzn-trace-id"));
290293
}
291294

295+
@Test
296+
void shouldLogAndClearLogContextOnEachRequest() throws IOException {
297+
requestHandler = new PowerLogToolEnabledWithClearState();
298+
S3EventNotification s3EventNotification = s3EventNotification();
299+
300+
requestHandler.handleRequest(s3EventNotification, context);
301+
requestHandler.handleRequest(s3EventNotification, context);
302+
303+
List<String> logLines = Files.lines(Paths.get("target/logfile.json")).collect(Collectors.toList());
304+
Map<String, Object> invokeLog = parseToMap(logLines.get(0));
305+
306+
assertThat(invokeLog)
307+
.containsEntry("TestKey", "TestValue");
308+
309+
invokeLog = parseToMap(logLines.get(1));
310+
311+
assertThat(invokeLog)
312+
.doesNotContainKey("TestKey");
313+
}
314+
292315
private void setupContext() {
293316
when(context.getFunctionName()).thenReturn("testFunction");
294317
when(context.getInvokedFunctionArn()).thenReturn("testArn");

0 commit comments

Comments
 (0)