-
Notifications
You must be signed in to change notification settings - Fork 90
feat(v2): Add GraalVM reachability metadata for core utilities #1753
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 14 commits
Commits
Show all changes
24 commits
Select commit
Hold shift + click to select a range
fd40160
Initial version of PT common GraalVM reachability metadata
rr-on-gh ee03ae4
Initial version of PT logging GraalVM reachability metadata
rr-on-gh 866fd82
Initial version of PT serialization GraalVM reachability metadata
rr-on-gh b72280f
Initial version of PT logging log4j GraalVM reachability metadata
rr-on-gh 97650c0
Initial version of PT logging log4j GraalVM reachability metadata
rr-on-gh 276984d
Initial version of PT logging logback GraalVM reachability metadata
rr-on-gh 63105bf
Example of PT logging with GraalVM
rr-on-gh 1a2cad2
Added GRM for powertools-metrics and update the example
rr-on-gh 90fe66e
Added GRM for powertools-metrics and update the example
rr-on-gh 617a57c
Cleanup of junit and mockito references
rr-on-gh a0791a4
Cleanup of junit and mockito references
rr-on-gh 7bfedb3
Added documentation
rr-on-gh e867523
Added GraalVM documentation
rr-on-gh 9b0b623
Added GraalVM documentation
rr-on-gh 9759aad
Merge branch 'v2' into graalvm-logging-v2
phipag 13f5cc4
Added GRM files for tracing module. Also changed the tests to use @Se…
rr-on-gh c45325a
Merge remote-tracking branch 'origin/graalvm-logging-v2' into graalvm…
rr-on-gh a969e3c
Switch commons module to use JUnit Pioneer
rr-on-gh ea9a1a2
Switch logging module to use JUnit Pioneer
rr-on-gh d96539b
Switch logging-log4j module to use JUnit Pioneer
rr-on-gh d186e91
Switch metrics module to use JUnit Pioneer
rr-on-gh e879e06
Fix testGetVersionFromProperties_InvalidFile test when running as nat…
phipag a1651ae
Cleaned up documentation and fixed review comments
rr-on-gh 9b2b6e8
Cosmetic fixes/formatting. Re-order imports in changed test files, fi…
phipag File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,188 @@ | ||
# GraalVM Compatibility for AWS Lambda Powertools Java | ||
|
||
## Table of Contents | ||
- [Overview](#overview) | ||
- [Prerequisites](#prerequisites) | ||
- [General Implementation Steps](#general-implementation-steps) | ||
- [Known Issues and Solutions](#known-issues-and-solutions) | ||
- [Reference Implementation](#reference-implementation) | ||
- [Module-Specific Implementation](#module-specific-implementation) | ||
- [1. Powertools Common](#1-powertools-common) | ||
- [2. Powertools Logging](#2-powertools-logging) | ||
- [2.1 Powertools Logging (log4j)](#21-powertools-logging-log4j) | ||
- [2.2 Powertools Logging (logback)](#22-powertools-logging-logback) | ||
- [3. Powertools Metrics](#3-powertools-metrics) | ||
|
||
## Overview | ||
This documentation provides guidance for adding GraalVM support for AWS Lambda Powertools Java modules and using the modules in Lambda functions. | ||
|
||
## Prerequisites | ||
- GraalVM 21+ installation | ||
- Maven 3.x | ||
|
||
## General Implementation Steps | ||
GraalVM native image compilation requires complete knowledge of an application's dynamic features at build time. The GraalVM reachability metadata (GRM) JSON files are essential because Java applications often use features that are determined at runtime, such as reflection, dynamic proxy classes, resource loading, and JNI (Java Native Interface). The metadata files tell GraalVM which classes need reflection access, which resources need to be included in the native image, and which proxy classes need to be generated. | ||
|
||
In order to generate the metadata reachability files for Powertools for Lambda, follow these general steps. | ||
|
||
1. **Add Maven Profiles** | ||
- Add profile for generating GraalVM reachability metadata files. You can find an example of this in profile `generate-graalvm-files` of this [pom.xml](powertools-common/pom.xml). | ||
- Add another profile for running the tests in the native image. You can find and example of this in profile `graalvm-native` of this [pom.xml](powertools-common/pom.xml). | ||
|
||
2. **Generate Reachability Metadata** | ||
- Set the `JAVA_HOME` environment variable to use GraalVM | ||
- Run tests with `-Pgenerate-graalvm-files` profile. You can find module specific commands in the [Module-Specific Implementation](#module-specific-implementation) section | ||
- Some tests may need to be skipped depending on the module | ||
|
||
3. **Validate Native Image Tests** | ||
- Set the `JAVA_HOME` environment variable to use GraalVM | ||
- Run tests with `-Pgraalvm-native` profile. This will build a GraalVM native image and run the JUnit tests. You can find module specific commands in the [Module-Specific Implementation](#module-specific-implementation) section | ||
- Verify test execution in native mode | ||
|
||
4. **Clean Up Metadata** | ||
- GraalVM metadata reachability files generated in Step 2 contains references to the test scoped dependencies as well. | ||
- Remove the references in generated metadata files for the following (and any other references to test scoped resources and classes): | ||
- JUnit | ||
- Mockito | ||
- ByteBuddy | ||
|
||
## Known Issues and Solutions | ||
|
||
1. **Mockito Compatibility** | ||
- Powertools uses Mockito 5.x which uses “inline mock maker” as the default. This mock maker does not play well with GraalVM. Mockito [recommends](https://github.com/mockito/mockito/releases/tag/v5.0.0) using subclass mock maker with GraalVM. | ||
- However, subclass mock maker does not support testing static methods. Some test cases in Powertools uses inline mock maker to mock static methods. These tests have to be skipped while generating the GraalVM reachability metadata files. | ||
- This obviously affects the coverage and possibility of missing a required entry in GRM files. At this point we are relying on community to report any missing entries and will update the GRM based on the reports. | ||
- This issue remains open until ability of test static methods in Mockito 5.x/inline mock maker is available. | ||
|
||
2. **Log4j Compatibility** | ||
- Version 2.22.1 fails with this error | ||
``` | ||
java.lang.InternalError: com.oracle.svm.core.jdk.UnsupportedFeatureError: Defining hidden classes at runtime is not supported. | ||
``` | ||
- This has been [fixed](https://github.com/apache/logging-log4j2/discussions/2364#discussioncomment-8950077) in Log4j 2.24.0. PT has been updated to use this version of Log4j | ||
|
||
|
||
## Reference Implementation | ||
Working example is available in the [examples](examples/powertools-examples-core-utilities/sam-graalvm). | ||
|
||
## Module-Specific Implementation | ||
Due to the Mockito issues described in the [Known Issues and Solutions](#known-issues-and-solutions) section, some tests needs to be skipped when generating the GRM files. This section shows the commands that need to be used for the modules. | ||
|
||
### 1. Powertools Common | ||
|
||
Generate metadata files | ||
```shell | ||
|
||
mvn \ | ||
-Dtest=\ | ||
\!UserAgentConfiguratorTest#testGetVersionFromProperties_InvalidFile,\ | ||
\!UserAgentConfiguratorTest#testGetVersion,\ | ||
\!UserAgentConfiguratorTest#testGetUserAgent_SetAWSExecutionEnv,\ | ||
\!LambdaHandlerProcessorTest#serviceName_Undefined,\ | ||
\!LambdaHandlerProcessorTest#serviceName,\ | ||
\!LambdaHandlerProcessorTest#isSamLocal,\ | ||
\!LambdaHandlerProcessorTest#getXrayTraceId_present,\ | ||
\!LambdaHandlerProcessorTest#getXrayTraceId_notPresent \ | ||
-Pgenerate-graalvm-files clean test | ||
``` | ||
|
||
Run native tests | ||
```shell | ||
|
||
mvn \ | ||
-Dtest=\ | ||
\!UserAgentConfiguratorTest#testGetVersionFromProperties_InvalidFile,\ | ||
\!UserAgentConfiguratorTest#testGetVersion,\ | ||
\!UserAgentConfiguratorTest#testGetUserAgent_SetAWSExecutionEnv,\ | ||
\!LambdaHandlerProcessorTest#serviceName_Undefined,\ | ||
\!LambdaHandlerProcessorTest#serviceName,\ | ||
\!LambdaHandlerProcessorTest#isSamLocal,\ | ||
\!LambdaHandlerProcessorTest#getXrayTraceId_present,\ | ||
\!LambdaHandlerProcessorTest#getXrayTraceId_notPresent \ | ||
-Pgraalvm-native clean test | ||
|
||
``` | ||
|
||
### 2. Powertools Logging | ||
|
||
Generate metadata files | ||
```shell | ||
|
||
mvn -Dtest=\!LambdaLoggingAspectTest#shouldLogxRayTraceIdEnvVarSet,\ | ||
\!LambdaLoggingAspectTest#shouldLogxRayTraceIdSystemPropertySet \ | ||
-Pgenerate-graalvm-files clean test | ||
|
||
``` | ||
|
||
Run native tests | ||
```shell | ||
|
||
mvn -Dtest=\!LambdaLoggingAspectTest#shouldLogxRayTraceIdEnvVarSet,\ | ||
\!LambdaLoggingAspectTest#shouldLogxRayTraceIdSystemPropertySet \ | ||
-Pgraalvm-native clean test | ||
|
||
``` | ||
#### 2.1 Powertools Logging (log4j) | ||
|
||
Generate metadata files | ||
```shell | ||
|
||
mvn -Dtest=\!PowertoolsResolverTest#shouldResolveRegion \ | ||
-Pgenerate-graalvm-files clean test | ||
|
||
``` | ||
|
||
Run native tests | ||
```shell | ||
|
||
mvn -Dtest=\!PowertoolsResolverTest#shouldResolveRegion \ | ||
-Pgraalvm-native clean test | ||
|
||
``` | ||
|
||
#### 2.2 Powertools Logging (logback) | ||
|
||
Generate metadata files | ||
```shell | ||
|
||
mvn -Dtest=\!MetricsLoggerTest#shouldLogxRayTraceIdEnvVarSet,\ | ||
\!MetricsLoggerTest#shouldLogxRayTraceIdSystemPropertySet \ | ||
-Pgenerate-graalvm-files clean test | ||
|
||
``` | ||
|
||
Run native tests | ||
```shell | ||
|
||
mvn -Dtest=\!MetricsLoggerTest#shouldLogxRayTraceIdEnvVarSet,\ | ||
\!MetricsLoggerTest#shouldLogxRayTraceIdSystemPropertySet \ | ||
-Pgraalvm-native clean test | ||
``` | ||
|
||
### 3. Powertools Metrics | ||
* All tests need to mock static methods. | ||
* Comment out the references to `mockStatic` in the JUnits and set the env variables explicitly | ||
* Also pass the system property via mvn build cli | ||
|
||
Generate metadata files | ||
```shell | ||
|
||
export AWS_EMF_ENVIRONMENT="Lambda" | ||
export _X_AMZN_TRACE_ID="Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1" | ||
export POWERTOOLS_METRICS_NAMESPACE="GlobalName" | ||
|
||
mvn -Dcom.amazonaws.xray.traceHeader="Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1" \ | ||
-Pgenerate-graalvm-files clean test | ||
``` | ||
|
||
Run native tests | ||
```shell | ||
|
||
export AWS_EMF_ENVIRONMENT="Lambda" | ||
export _X_AMZN_TRACE_ID="Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1" | ||
export POWERTOOLS_METRICS_NAMESPACE="GlobalName" | ||
|
||
mvn -Dcom.amazonaws.xray.traceHeader="Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1" \ | ||
-Pgraalvm-native clean test | ||
|
||
``` |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
14 changes: 14 additions & 0 deletions
14
examples/powertools-examples-core-utilities/sam-graalvm/Dockerfile
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
#Use the official AWS SAM base image for Java 21 | ||
FROM public.ecr.aws/sam/build-java21:latest | ||
|
||
#Install GraalVM dependencies | ||
RUN curl -4 -L curl https://download.oracle.com/graalvm/21/latest/graalvm-jdk-21_linux-x64_bin.tar.gz | tar -xvz | ||
RUN mv graalvm-jdk-21.* /usr/lib/graalvm | ||
|
||
#Make native image and mvn available on CLI | ||
RUN ln -s /usr/lib/graalvm/bin/native-image /usr/bin/native-image | ||
RUN ln -s /usr/lib/maven/bin/mvn /usr/bin/mvn | ||
|
||
#Set GraalVM as default | ||
ENV JAVA_HOME=/usr/lib/graalvm | ||
ENV PATH=/usr/lib/graalvm/bin:$PATH |
6 changes: 6 additions & 0 deletions
6
examples/powertools-examples-core-utilities/sam-graalvm/Makefile
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
build-HelloWorldFunction: | ||
mvn clean package -P native-image | ||
chmod +x target/hello-world | ||
cp target/hello-world $(ARTIFACTS_DIR) # (ARTIFACTS_DIR --> https://github.com/aws/aws-lambda-builders/blob/develop/aws_lambda_builders/workflows/custom_make/DESIGN.md#implementation) | ||
chmod +x src/main/config/bootstrap | ||
cp src/main/config/bootstrap $(ARTIFACTS_DIR) |
56 changes: 56 additions & 0 deletions
56
examples/powertools-examples-core-utilities/sam-graalvm/README.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
# Powertools for AWS Lambda (Java) - Core Utilities Example with SAM on GraalVM | ||
|
||
This project demonstrates the Lambda for Powertools Java module deployed using [Serverless Application Model](https://aws.amazon.com/serverless/sam/) running as a GraalVM native image. | ||
|
||
For general information on the deployed example itself, you can refer to the parent [README](../README.md) | ||
|
||
## Configuration | ||
- SAM uses [template.yaml](template.yaml) to define the application's AWS resources. | ||
This file defines the Lambda function to be deployed as well as API Gateway for it. | ||
|
||
- Set the environment to use GraalVM | ||
|
||
```shell | ||
export JAVA_HOME=<path to GraalVM> | ||
```` | ||
|
||
## Build the sample application | ||
|
||
- Build the Docker image that will be used as the environment for SAM build: | ||
```shell | ||
docker build --platform linux/amd64 . -t powertools-examples-core-sam-graalvm | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please remove indentation. |
||
``` | ||
|
||
- Build the SAM project using the docker image | ||
```shell | ||
sam build --use-container --build-image powertools-examples-core-sam-graalvm | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please remove indentation. |
||
|
||
``` | ||
#### [Optional] Building with -SNAPSHOT versions of PowerTools | ||
- If you are testing the example with a -SNAPSHOT version of PowerTools, the maven build inside the docker image will fail. This is because the -SNAPSHOT version of the PowerTools library that you are working on is still not available in maven central/snapshot repository. | ||
To get around this, follow these steps: | ||
- Create the native image using the `docker` command below on your development machine. The native image is created in the `target` directory. | ||
- ```docker run --platform linux/amd64 -it -v `pwd`:`pwd` -w `pwd` -v ~/.m2:/root/.m2 powertools-examples-core-sam-graalvm mvn clean -Pnative-image package -DskipTests``` | ||
- Edit the [`Makefile`](Makefile) remove this line | ||
- ```mvn clean package -P native-image``` | ||
- Build the SAM project using the docker image | ||
- ```sam build --use-container --build-image powertools-examples-core-sam-graalvm``` | ||
|
||
## Deploy the sample application | ||
- SAM deploy | ||
|
||
sam deploy | ||
|
||
To deploy the example, check out the instructions for getting | ||
started with SAM in [the examples directory](../../README.md) | ||
|
||
## Additional notes | ||
|
||
You can watch the trace information or log information using the SAM CLI: | ||
```bash | ||
# Tail the logs | ||
sam logs --tail $MY_STACK | ||
|
||
# Tail the traces | ||
sam traces --tail | ||
``` |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is one backtick too much at the end. And can you remove the indentation inside the code block?