Skip to content

Commit 7dff30c

Browse files
feat: advanced logging (#1539)
* improve logging * adding arguments to log events * !update ObjectMapper configuration * remove LoggingUtils appendKey, use standard MDC * examples in the end * clean sonar warnings * clean spotbugs issues * code review comments * update documentation * remove LoggingUtils --------- Co-authored-by: Scott Gerring <[email protected]>
1 parent 5bf9b3d commit 7dff30c

File tree

58 files changed

+2538
-1348
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+2538
-1348
lines changed

docs/core/logging.md

+133-226
Large diffs are not rendered by default.

examples/powertools-examples-core-utilities/cdk/app/src/main/java/helloworld/App.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,10 @@
3131
import java.util.stream.Collectors;
3232
import org.slf4j.Logger;
3333
import org.slf4j.LoggerFactory;
34+
import org.slf4j.MDC;
3435
import software.amazon.cloudwatchlogs.emf.model.DimensionSet;
3536
import software.amazon.cloudwatchlogs.emf.model.Unit;
3637
import software.amazon.lambda.powertools.logging.Logging;
37-
import software.amazon.lambda.powertools.logging.LoggingUtils;
3838
import software.amazon.lambda.powertools.metrics.Metrics;
3939
import software.amazon.lambda.powertools.tracing.CaptureMode;
4040
import software.amazon.lambda.powertools.tracing.Tracing;
@@ -62,7 +62,7 @@ public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEv
6262
metric.setDimensions(DimensionSet.of("AnotherService1", "CustomService1"));
6363
});
6464

65-
LoggingUtils.appendKey("test", "willBeLogged");
65+
MDC.put("test", "willBeLogged");
6666

6767
APIGatewayProxyResponseEvent response = new APIGatewayProxyResponseEvent()
6868
.withHeaders(headers);

examples/powertools-examples-core-utilities/gradle/src/main/java/helloworld/App.java

+4-3
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
package helloworld;
1616

17+
import static software.amazon.lambda.powertools.logging.argument.StructuredArguments.entry;
1718
import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger;
1819
import static software.amazon.lambda.powertools.metrics.MetricsUtils.withSingleMetric;
1920
import static software.amazon.lambda.powertools.tracing.TracingUtils.putMetadata;
@@ -31,10 +32,10 @@
3132
import java.util.stream.Collectors;
3233
import org.slf4j.Logger;
3334
import org.slf4j.LoggerFactory;
35+
import org.slf4j.MDC;
3436
import software.amazon.cloudwatchlogs.emf.model.DimensionSet;
3537
import software.amazon.cloudwatchlogs.emf.model.Unit;
3638
import software.amazon.lambda.powertools.logging.Logging;
37-
import software.amazon.lambda.powertools.logging.LoggingUtils;
3839
import software.amazon.lambda.powertools.metrics.Metrics;
3940
import software.amazon.lambda.powertools.tracing.CaptureMode;
4041
import software.amazon.lambda.powertools.tracing.Tracing;
@@ -63,13 +64,13 @@ public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEv
6364
metric.setDimensions(DimensionSet.of("AnotherService1", "CustomService1"));
6465
});
6566

66-
LoggingUtils.appendKey("test", "willBeLogged");
67+
MDC.put("test", "willBeLogged");
6768

6869
APIGatewayProxyResponseEvent response = new APIGatewayProxyResponseEvent()
6970
.withHeaders(headers);
7071
try {
7172
final String pageContents = this.getPageContents("https://checkip.amazonaws.com");
72-
log.info(pageContents);
73+
log.info("", entry("ip", pageContents));
7374
TracingUtils.putAnnotation("Test", "New");
7475
String output = String.format("{ \"message\": \"hello world\", \"location\": \"%s\" }", pageContents);
7576

examples/powertools-examples-core-utilities/kotlin/src/main/kotlin/helloworld/App.kt

+4-7
Original file line numberDiff line numberDiff line change
@@ -18,23 +18,21 @@ import com.amazonaws.services.lambda.runtime.RequestHandler
1818
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent
1919
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent
2020
import com.amazonaws.xray.entities.Subsegment
21-
import org.slf4j.Logger
2221
import org.slf4j.LoggerFactory
22+
import org.slf4j.MDC
2323
import software.amazon.cloudwatchlogs.emf.logger.MetricsLogger
2424
import software.amazon.cloudwatchlogs.emf.model.DimensionSet
2525
import software.amazon.cloudwatchlogs.emf.model.Unit
2626
import software.amazon.lambda.powertools.logging.Logging
27-
import software.amazon.lambda.powertools.logging.LoggingUtils
27+
import software.amazon.lambda.powertools.logging.argument.StructuredArguments.entry
2828
import software.amazon.lambda.powertools.metrics.Metrics
2929
import software.amazon.lambda.powertools.metrics.MetricsUtils
3030
import software.amazon.lambda.powertools.tracing.CaptureMode
3131
import software.amazon.lambda.powertools.tracing.Tracing
3232
import software.amazon.lambda.powertools.tracing.TracingUtils
33-
import java.io.BufferedReader
3433
import java.io.IOException
3534
import java.io.InputStreamReader
3635
import java.net.URL
37-
import java.util.stream.Collectors
3836

3937
/**
4038
* Handler for requests to Lambda function.
@@ -44,19 +42,18 @@ class App : RequestHandler<APIGatewayProxyRequestEvent?, APIGatewayProxyResponse
4442
@Logging(logEvent = true, samplingRate = 0.7)
4543
@Tracing(captureMode = CaptureMode.RESPONSE_AND_ERROR)
4644
@Metrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true)
47-
4845
override fun handleRequest(input: APIGatewayProxyRequestEvent?, context: Context?): APIGatewayProxyResponseEvent {
4946
val headers = mapOf("Content-Type" to "application/json", "X-Custom-Header" to "application/json")
5047
MetricsUtils.metricsLogger().putMetric("CustomMetric1", 1.0, Unit.COUNT)
5148
MetricsUtils.withSingleMetric("CustomMetrics2", 1.0, Unit.COUNT, "Another") { metric: MetricsLogger ->
5249
metric.setDimensions(DimensionSet.of("AnotherService", "CustomService"))
5350
metric.setDimensions(DimensionSet.of("AnotherService1", "CustomService1"))
5451
}
55-
LoggingUtils.appendKey("test", "willBeLogged")
52+
MDC.put("test", "willBeLogged")
5653
val response = APIGatewayProxyResponseEvent().withHeaders(headers)
5754
return try {
5855
val pageContents = getPageContents("https://checkip.amazonaws.com")
59-
log.info(pageContents)
56+
log.info("", entry("ip", pageContents));
6057
TracingUtils.putAnnotation("Test", "New")
6158
val output = """
6259
{

examples/powertools-examples-core-utilities/sam/src/main/java/helloworld/App.java

+4-3
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
package helloworld;
1616

17+
import static software.amazon.lambda.powertools.logging.argument.StructuredArguments.entry;
1718
import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger;
1819
import static software.amazon.lambda.powertools.metrics.MetricsUtils.withSingleMetric;
1920
import static software.amazon.lambda.powertools.tracing.TracingUtils.putMetadata;
@@ -31,10 +32,10 @@
3132
import java.util.stream.Collectors;
3233
import org.slf4j.Logger;
3334
import org.slf4j.LoggerFactory;
35+
import org.slf4j.MDC;
3436
import software.amazon.cloudwatchlogs.emf.model.DimensionSet;
3537
import software.amazon.cloudwatchlogs.emf.model.Unit;
3638
import software.amazon.lambda.powertools.logging.Logging;
37-
import software.amazon.lambda.powertools.logging.LoggingUtils;
3839
import software.amazon.lambda.powertools.metrics.Metrics;
3940
import software.amazon.lambda.powertools.tracing.CaptureMode;
4041
import software.amazon.lambda.powertools.tracing.Tracing;
@@ -63,13 +64,13 @@ public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEv
6364
metric.setDimensions(DimensionSet.of("AnotherService1", "CustomService1"));
6465
});
6566

66-
LoggingUtils.appendKey("test", "willBeLogged");
67+
MDC.put("test", "willBeLogged");
6768

6869
APIGatewayProxyResponseEvent response = new APIGatewayProxyResponseEvent()
6970
.withHeaders(headers);
7071
try {
7172
final String pageContents = this.getPageContents("https://checkip.amazonaws.com");
72-
log.info(pageContents);
73+
log.info("", entry("ip", pageContents));
7374
TracingUtils.putAnnotation("Test", "New");
7475
String output = String.format("{ \"message\": \"hello world\", \"location\": \"%s\" }", pageContents);
7576

examples/powertools-examples-core-utilities/serverless/src/main/java/helloworld/App.java

+8-4
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
package helloworld;
1616

17+
import static software.amazon.lambda.powertools.logging.argument.StructuredArguments.entry;
1718
import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger;
1819
import static software.amazon.lambda.powertools.metrics.MetricsUtils.withSingleMetric;
1920
import static software.amazon.lambda.powertools.tracing.TracingUtils.putMetadata;
@@ -31,10 +32,10 @@
3132
import java.util.stream.Collectors;
3233
import org.apache.logging.log4j.LogManager;
3334
import org.apache.logging.log4j.Logger;
35+
import org.slf4j.MDC;
3436
import software.amazon.cloudwatchlogs.emf.model.DimensionSet;
3537
import software.amazon.cloudwatchlogs.emf.model.Unit;
3638
import software.amazon.lambda.powertools.logging.Logging;
37-
import software.amazon.lambda.powertools.logging.LoggingUtils;
3839
import software.amazon.lambda.powertools.metrics.Metrics;
3940
import software.amazon.lambda.powertools.tracing.CaptureMode;
4041
import software.amazon.lambda.powertools.tracing.Tracing;
@@ -44,8 +45,11 @@
4445
* Handler for requests to Lambda function.
4546
*/
4647
public class App implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {
47-
private final static Logger log = LogManager.getLogger(App.class);
48+
private static final Logger log = LogManager.getLogger(App.class);
49+
50+
@Logging(logEvent = true, samplingRate = 0.7)
4851
@Tracing(captureMode = CaptureMode.RESPONSE_AND_ERROR)
52+
@Metrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true)
4953
public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) {
5054
Map<String, String> headers = new HashMap<>();
5155

@@ -60,13 +64,13 @@ public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEv
6064
metric.setDimensions(DimensionSet.of("AnotherService1", "CustomService1"));
6165
});
6266

63-
LoggingUtils.appendKey("test", "willBeLogged");
67+
MDC.put("test", "willBeLogged");
6468

6569
APIGatewayProxyResponseEvent response = new APIGatewayProxyResponseEvent()
6670
.withHeaders(headers);
6771
try {
6872
final String pageContents = this.getPageContents("https://checkip.amazonaws.com");
69-
log.info(pageContents);
73+
log.info("", entry("ip", pageContents));
7074
TracingUtils.putAnnotation("Test", "New");
7175
String output = String.format("{ \"message\": \"hello world\", \"location\": \"%s\" }", pageContents);
7276

examples/powertools-examples-core-utilities/terraform/src/main/java/helloworld/App.java

+7-9
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
package helloworld;
1616

17+
import static software.amazon.lambda.powertools.logging.argument.StructuredArguments.entry;
1718
import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger;
1819
import static software.amazon.lambda.powertools.metrics.MetricsUtils.withSingleMetric;
1920
import static software.amazon.lambda.powertools.tracing.TracingUtils.putMetadata;
@@ -31,10 +32,10 @@
3132
import java.util.stream.Collectors;
3233
import org.apache.logging.log4j.LogManager;
3334
import org.apache.logging.log4j.Logger;
35+
import org.slf4j.MDC;
3436
import software.amazon.cloudwatchlogs.emf.model.DimensionSet;
3537
import software.amazon.cloudwatchlogs.emf.model.Unit;
3638
import software.amazon.lambda.powertools.logging.Logging;
37-
import software.amazon.lambda.powertools.logging.LoggingUtils;
3839
import software.amazon.lambda.powertools.metrics.Metrics;
3940
import software.amazon.lambda.powertools.tracing.CaptureMode;
4041
import software.amazon.lambda.powertools.tracing.Tracing;
@@ -44,14 +45,11 @@
4445
* Handler for requests to Lambda function.
4546
*/
4647
public class App implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {
47-
private final static Logger log = LogManager.getLogger(App.class);
48+
private static final Logger log = LogManager.getLogger(App.class);
4849

49-
// This is controlled by POWERTOOLS_LOGGER_SAMPLE_RATE environment variable
50-
// @Logging(logEvent = true, samplingRate = 0.7)
51-
// This is controlled by POWERTOOLS_METRICS_NAMESPACE environment variable
52-
// @Metrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true)
53-
// This is controlled by POWERTOOLS_TRACER_CAPTURE_ERROR environment variable
50+
@Logging(logEvent = true, samplingRate = 0.7)
5451
@Tracing(captureMode = CaptureMode.RESPONSE_AND_ERROR)
52+
@Metrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true)
5553
public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) {
5654
Map<String, String> headers = new HashMap<>();
5755

@@ -66,13 +64,13 @@ public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEv
6664
metric.setDimensions(DimensionSet.of("AnotherService1", "CustomService1"));
6765
});
6866

69-
LoggingUtils.appendKey("test", "willBeLogged");
67+
MDC.put("test", "willBeLogged");
7068

7169
APIGatewayProxyResponseEvent response = new APIGatewayProxyResponseEvent()
7270
.withHeaders(headers);
7371
try {
7472
final String pageContents = this.getPageContents("https://checkip.amazonaws.com");
75-
log.info(pageContents);
73+
log.info("", entry("ip", pageContents));
7674
TracingUtils.putAnnotation("Test", "New");
7775
String output = String.format("{ \"message\": \"hello world\", \"location\": \"%s\" }", pageContents);
7876

pom.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,12 @@
5555
<module>powertools-large-messages</module>
5656
<module>powertools-e2e-tests</module>
5757
<module>powertools-batch</module>
58-
<module>examples</module>
5958
<module>powertools-parameters/powertools-parameters-ssm</module>
6059
<module>powertools-parameters/powertools-parameters-secrets</module>
6160
<module>powertools-parameters/powertools-parameters-dynamodb</module>
6261
<module>powertools-parameters/powertools-parameters-appconfig</module>
6362
<module>powertools-parameters/powertools-parameters-tests</module>
63+
<module>examples</module>
6464
</modules>
6565

6666
<properties>

powertools-e2e-tests/handlers/logging/src/main/java/software/amazon/lambda/powertools/e2e/Function.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,15 @@
1818
import com.amazonaws.services.lambda.runtime.RequestHandler;
1919
import org.slf4j.Logger;
2020
import org.slf4j.LoggerFactory;
21+
import org.slf4j.MDC;
2122
import software.amazon.lambda.powertools.logging.Logging;
22-
import software.amazon.lambda.powertools.logging.LoggingUtils;
2323

2424
public class Function implements RequestHandler<Input, String> {
2525
private static final Logger LOG = LoggerFactory.getLogger(Function.class);
2626

2727
@Logging
2828
public String handleRequest(Input input, Context context) {
29-
LoggingUtils.appendKeys(input.getKeys());
29+
input.getKeys().forEach(MDC::put);
3030
LOG.info(input.getMessage());
3131

3232
return "OK";

0 commit comments

Comments
 (0)