Skip to content

Commit

Permalink
STNG-33 Move to Structured Logging in AWS Lambda (#185)
Browse files Browse the repository at this point in the history
  • Loading branch information
jkosternl authored Oct 10, 2024
1 parent ab2039b commit a026676
Show file tree
Hide file tree
Showing 8 changed files with 125 additions and 34 deletions.
2 changes: 1 addition & 1 deletion cdk/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
<dependency>
<groupId>software.amazon.awscdk</groupId>
<artifactId>aws-cdk-lib</artifactId>
<version>2.159.1</version>
<version>2.161.1</version>
<scope>compile</scope>
</dependency>
</dependencies>
Expand Down
82 changes: 77 additions & 5 deletions lambda/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@
<name>dcsa-conformance-lambda</name>
<description>DCSA Conformance Lambda</description>

<properties>
<aspectj.version>1.9.21.2</aspectj.version>
</properties>

<dependencyManagement>
<dependencies>
<dependency>
Expand All @@ -39,18 +43,31 @@
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-events</artifactId>
<version>3.13.0</version>
<version>3.14.0</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-lambda</artifactId>
<version>1.12.771</version>
<version>1.12.773</version>
</dependency>

<!-- AWS Lambda Powertools, for logging, tracing -->
<dependency>
<groupId>software.amazon.lambda</groupId>
<artifactId>powertools-logging</artifactId>
<version>1.18.0</version>
</dependency>
<dependency>
<groupId>software.amazon.lambda</groupId>
<artifactId>powertools-metrics</artifactId>
<version>1.18.0</version>
</dependency>
<!-- Use specific Java 21+ version -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>2.0.16</version>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj.version}</version>
<scope>runtime</scope>
</dependency>

<dependency>
Expand All @@ -61,13 +78,61 @@

<build>
<plugins>
<plugin>
<groupId>dev.aspectj</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.14</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<complianceLevel>${java.version}</complianceLevel>
<forceAjcCompile>true</forceAjcCompile><!-- Enable Lombok in Lambda -->
<sources/>
<weaveDirectories>
<weaveDirectory>${project.build.directory}/classes</weaveDirectory>
</weaveDirectories><!-- end Enable Lombok -->
<aspectLibraries>
<aspectLibrary>
<groupId>software.amazon.lambda</groupId>
<artifactId>powertools-logging</artifactId>
</aspectLibrary>
<aspectLibrary>
<groupId>software.amazon.lambda</groupId>
<artifactId>powertools-metrics</artifactId>
</aspectLibrary>
</aspectLibraries>
</configuration>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>${aspectj.version}</version>
</dependency>
</dependencies>
<executions>
<execution>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.6.0</version>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<finalName>conformance-lambda</finalName>
<transformers>
<transformer implementation="org.apache.logging.log4j.maven.plugins.shade.transformer.Log4j2PluginCacheFileTransformer"/>
</transformers>
<relocations><!-- Fixing 'WARNING: sun.reflect.Reflection.getCallerClass is not supported. This will impact performance. -->
<relocation>
<pattern>META-INF/versions/9/org/apache/logging/log4j/</pattern>
<shadedPattern>org/apache/logging/log4j/</shadedPattern>
</relocation>
</relocations><!-- end fixing WARNING -->
</configuration>
<executions>
<execution>
Expand All @@ -77,6 +142,13 @@
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-transform-maven-shade-plugin-extensions</artifactId>
<version>0.1.0</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
Expand Down
12 changes: 7 additions & 5 deletions lambda/src/main/java/org/dcsa/conformance/lambda/ApiLambda.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,24 @@
import java.util.List;
import java.util.Map;
import java.util.Objects;
import lombok.extern.slf4j.Slf4j;
import lombok.extern.log4j.Log4j2;
import org.dcsa.conformance.sandbox.ConformanceSandbox;
import org.dcsa.conformance.sandbox.ConformanceWebRequest;
import org.dcsa.conformance.sandbox.ConformanceWebResponse;
import org.dcsa.conformance.sandbox.state.ConformancePersistenceProvider;
import software.amazon.lambda.powertools.logging.Logging;

@Slf4j
@Log4j2
public class ApiLambda
implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {

@Logging
public APIGatewayProxyResponseEvent handleRequest(
final APIGatewayProxyRequestEvent event, final Context context) {
try {
System.out.println("event = " + event + ", context = " + context);
log.info("event = {}", event);
JsonNode jsonEvent = OBJECT_MAPPER.valueToTree(event);
log.info("jsonEvent = " + jsonEvent.toPrettyString());
log.debug("jsonEvent = {}", jsonEvent);

ConformancePersistenceProvider persistenceProvider =
LambdaToolkit.createPersistenceProvider();
Expand All @@ -51,7 +53,7 @@ public APIGatewayProxyResponseEvent handleRequest(
.withStatusCode(conformanceWebResponse.statusCode())
.withBody(conformanceWebResponse.body());
} catch (RuntimeException | Error e) {
log.error("Unhandled exception: " + e, e);
log.error("Unhandled exception: ", e);
throw e;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,20 @@
import com.fasterxml.jackson.databind.node.ObjectNode;
import java.io.*;
import java.nio.charset.StandardCharsets;
import lombok.extern.slf4j.Slf4j;
import lombok.extern.log4j.Log4j2;
import org.dcsa.conformance.core.toolkit.JsonToolkit;
import org.dcsa.conformance.sandbox.ConformanceSandbox;
import org.dcsa.conformance.sandbox.state.ConformancePersistenceProvider;
import software.amazon.lambda.powertools.logging.Logging;

@Slf4j
@Log4j2
public class SandboxTaskLambda implements RequestStreamHandler {

@Logging
public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context) {
try {
JsonNode jsonInput = JsonToolkit.inputStreamToJsonNode(inputStream);
log.info("jsonInput = " + jsonInput.toPrettyString());
log.info("jsonInput = {}", jsonInput);

try {
Thread.sleep(100); // for consistency with the local app
Expand All @@ -36,17 +38,13 @@ public void handleRequest(InputStream inputStream, OutputStream outputStream, Co
jsonInput);

ObjectNode jsonOutput = OBJECT_MAPPER.createObjectNode();
log.info("jsonOutput = " + jsonOutput.toPrettyString());
try (BufferedWriter writer =
new BufferedWriter(new OutputStreamWriter(outputStream, StandardCharsets.UTF_8))) {
writer.write(jsonOutput.toPrettyString());
writer.flush();
}
log.debug("jsonOutput = {}", jsonOutput);
outputStream.write(jsonOutput.toString().getBytes(StandardCharsets.UTF_8));
} catch (RuntimeException | Error e) {
log.error("Unhandled exception: " + e, e);
log.error("Unhandled exception: ", e);
throw e;
} catch (IOException e) {
log.error("Unhandled exception: " + e, e);
log.error("Unhandled exception: ", e);
throw new RuntimeException(e);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,25 @@
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;
import com.fasterxml.jackson.databind.JsonNode;
import java.util.*;
import lombok.extern.slf4j.Slf4j;
import lombok.extern.log4j.Log4j2;
import org.dcsa.conformance.core.toolkit.JsonToolkit;
import org.dcsa.conformance.sandbox.ConformanceAccessException;
import org.dcsa.conformance.sandbox.ConformanceWebuiHandler;
import org.dcsa.conformance.sandbox.state.ConformancePersistenceProvider;
import software.amazon.lambda.powertools.logging.Logging;

@Slf4j
@Log4j2
public class WebuiLambda
implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {

@Logging
public APIGatewayProxyResponseEvent handleRequest(
final APIGatewayProxyRequestEvent event, final Context context) {
try {
System.out.println("event = " + event + ", context = " + context);
log.info("event.getPath() = " + event.getPath());
log.info("event = {}", event);

JsonNode jsonEvent = OBJECT_MAPPER.valueToTree(event);
log.info("JSON event = " + jsonEvent.toString());
log.debug("JSON event = {}", jsonEvent);

String cognitoIdAsEnvironmentId =
jsonEvent
Expand All @@ -35,7 +36,7 @@ public APIGatewayProxyResponseEvent handleRequest(
.get("claims")
.get("cognito:username")
.asText();
log.info("cognitoIdAsEnvironmentId='%s'".formatted(cognitoIdAsEnvironmentId));
log.debug("cognitoIdAsEnvironmentId='{}'", cognitoIdAsEnvironmentId);

ConformancePersistenceProvider persistenceProvider =
LambdaToolkit.createPersistenceProvider();
Expand All @@ -53,7 +54,7 @@ public APIGatewayProxyResponseEvent handleRequest(
webuiHandler
.handleRequest(
cognitoIdAsEnvironmentId, JsonToolkit.stringToJsonNode(event.getBody()))
.toPrettyString();
.toString();
} catch (ConformanceAccessException e) {
return new APIGatewayProxyResponseEvent()
.withMultiValueHeaders(Map.of("Content-Type", List.of(JsonToolkit.JSON_UTF_8)))
Expand All @@ -66,7 +67,7 @@ public APIGatewayProxyResponseEvent handleRequest(
.withStatusCode(200)
.withBody(responseBody);
} catch (RuntimeException | Error e) {
log.error("Unhandled exception: " + e, e);
log.error("Unhandled exception: ", e);
throw e;
}
}
Expand Down
17 changes: 17 additions & 0 deletions lambda/src/main/resources/log4j2.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<Appenders>
<Console name="JsonAppender" target="SYSTEM_OUT">
<JsonTemplateLayout eventTemplateUri="classpath:LambdaJsonLayout.json"/>
</Console>
</Appenders>
<Loggers>
<Logger name="JsonLogger" level="INFO" additivity="false">
<AppenderRef ref="JsonAppender"/>
</Logger>
<Root level="info">
<AppenderRef ref="JsonAppender"/>
</Root>
<Logger name="org.dcsa.conformance" level="INFO"/>
</Loggers>
</Configuration>
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

<spring.boot.version>3.3.4</spring.boot.version>
<log4j.version>2.20.0</log4j.version>
<junit.version>5.11.1</junit.version>
<junit.version>5.11.2</junit.version>
<lombok.version>1.18.34</lombok.version>

<sonar.host.url>https://sonarcloud.io</sonar.host.url>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,14 @@ public JsonNode handleRequest(String userId, JsonNode requestNode) {
node.put("exception", e.getClass().getName())
.put("message", e.getMessage());
}
log.warn("Internal Server Error: {}; Message: {}", e.getClass().getName(), e.getMessage());
return node;
}
}
}

public JsonNode _doHandleRequest(String userId, JsonNode requestNode) {
log.info("ConformanceWebuiHandler.handleRequest(%s)".formatted(requestNode.toPrettyString()));
log.info("ConformanceWebuiHandler.handleRequest({})", requestNode.toPrettyString());
String operation = requestNode.get("operation").asText();
JsonNode resultNode = switch (operation) {
case "createSandbox" -> _createSandbox(userId, requestNode);
Expand All @@ -85,7 +86,7 @@ public JsonNode _doHandleRequest(String userId, JsonNode requestNode) {
case "completeCurrentAction" -> _completeCurrentAction(userId, requestNode);
default -> throw new UnsupportedOperationException(operation);
};
log.debug("ConformanceWebuiHandler.handleRequest() returning: %s".formatted(resultNode.toPrettyString()));
log.debug("ConformanceWebuiHandler.handleRequest() returning: {}", resultNode.toPrettyString());
return resultNode;
}

Expand Down Expand Up @@ -294,7 +295,7 @@ private JsonNode _updateSandboxConfig(String userId, JsonNode requestNode) {

ConformanceSandbox.saveSandboxConfiguration(persistenceProvider, userId, sandboxConfiguration);

log.info("Updated sandbox: " + sandboxConfiguration.toJsonNode().toPrettyString());
log.info("Updated sandbox: {}", sandboxConfiguration.toJsonNode().toPrettyString());

return OBJECT_MAPPER.createObjectNode();
}
Expand Down

0 comments on commit a026676

Please sign in to comment.