Skip to content

Commit ee995f7

Browse files
authored
docs(examples): Add Bazel example for core utilities (#2022)
* Add Bazel example. * Remove double _deploy suffix. * Use default .bazelrc setting and re-enable strict dependency checks. * Remove unused log method.
1 parent e68637c commit ee995f7

File tree

10 files changed

+502
-0
lines changed

10 files changed

+502
-0
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Java compilation settings
2+
build --java_language_version=11
3+
build --java_runtime_version=11
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Bazel build outputs
2+
bazel-*
3+
MODULE.bazel.lock
4+
5+
# SAM build outputs
6+
.aws-sam/
7+
8+
# JAR files
9+
*.jar
10+
11+
# Maven lock file (generated)
12+
maven_install.json
13+
14+
# IDE files
15+
.idea/
16+
.vscode/
17+
*.iml
18+
19+
# OS files
20+
.DS_Store
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
load("@rules_java//java:defs.bzl", "java_binary", "java_library")
2+
3+
java_library(
4+
name = "powertools_sam_lib_base",
5+
srcs = glob(["src/main/java/**/*.java"]),
6+
resources = glob(["src/main/resources/**"]),
7+
deps = [
8+
"@maven//:software_amazon_lambda_powertools_tracing",
9+
"@maven//:software_amazon_lambda_powertools_logging",
10+
"@maven//:software_amazon_lambda_powertools_logging_log4j",
11+
"@maven//:software_amazon_lambda_powertools_metrics",
12+
"@maven//:com_amazonaws_aws_lambda_java_core",
13+
"@maven//:com_amazonaws_aws_lambda_java_events",
14+
"@maven//:org_aspectj_aspectjrt",
15+
"@maven//:org_slf4j_slf4j_api",
16+
"@maven//:com_fasterxml_jackson_core_jackson_databind",
17+
"@maven//:org_apache_logging_log4j_log4j_api",
18+
],
19+
)
20+
21+
genrule(
22+
name = "aspectj_weave",
23+
srcs = [
24+
":powertools_sam_lib_base",
25+
"@maven//:software_amazon_lambda_powertools_tracing",
26+
"@maven//:software_amazon_lambda_powertools_logging",
27+
"@maven//:software_amazon_lambda_powertools_metrics",
28+
"@maven//:com_amazonaws_aws_lambda_java_core",
29+
"@maven//:com_amazonaws_aws_lambda_java_events",
30+
"@maven//:org_aspectj_aspectjrt",
31+
],
32+
outs = ["powertools_sam_lib_woven.jar"],
33+
tools = [
34+
"@maven//:org_aspectj_aspectjweaver",
35+
"@maven//:org_aspectj_aspectjtools",
36+
],
37+
cmd = """
38+
# Get dependency JARs for classpath
39+
ASPECTJ_TOOLS="$$(echo $(locations @maven//:org_aspectj_aspectjtools) $(locations @maven//:org_aspectj_aspectjweaver) | tr ' ' ':')"
40+
ASPECTJ_RT="$(locations @maven//:org_aspectj_aspectjrt)"
41+
LAMBDA_JARS="$$(echo $(locations @maven//:com_amazonaws_aws_lambda_java_core) $(locations @maven//:com_amazonaws_aws_lambda_java_events) | tr ' ' ':')"
42+
ALL_DEPS="$$ASPECTJ_TOOLS:$$ASPECTJ_RT:$$LAMBDA_JARS"
43+
44+
BASE_JAR=$$(echo $(locations :powertools_sam_lib_base) | cut -d' ' -f1)
45+
POWERTOOLS_JARS="$$(echo $(locations @maven//:software_amazon_lambda_powertools_tracing) $(locations @maven//:software_amazon_lambda_powertools_logging) $(locations @maven//:software_amazon_lambda_powertools_metrics) | tr ' ' ':')"
46+
47+
java -cp "$$ALL_DEPS" \
48+
org.aspectj.tools.ajc.Main \
49+
-inpath "$$BASE_JAR" \
50+
-aspectpath "$$POWERTOOLS_JARS" \
51+
-outjar $(location powertools_sam_lib_woven.jar) \
52+
-source 11 -target 11 -nowarn
53+
""",
54+
)
55+
56+
java_import(
57+
name = "powertools_sam_lib",
58+
jars = [":powertools_sam_lib_woven.jar"],
59+
deps = [
60+
"@maven//:software_amazon_lambda_powertools_tracing",
61+
"@maven//:software_amazon_lambda_powertools_logging",
62+
"@maven//:software_amazon_lambda_powertools_logging_log4j",
63+
"@maven//:software_amazon_lambda_powertools_metrics",
64+
"@maven//:com_amazonaws_aws_lambda_java_core",
65+
"@maven//:com_amazonaws_aws_lambda_java_events",
66+
"@maven//:org_aspectj_aspectjrt",
67+
],
68+
)
69+
70+
java_binary(
71+
name = "powertools_sam",
72+
main_class = "helloworld.App",
73+
runtime_deps = [":powertools_sam_lib"],
74+
deploy_manifest_lines = [
75+
"Main-Class: helloworld.App",
76+
],
77+
create_executable = False,
78+
)
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
module(name = "powertools_sam_bazel", version = "1.0.0")
2+
3+
bazel_dep(name = "rules_java", version = "8.12.0")
4+
bazel_dep(name = "rules_jvm_external", version = "6.3")
5+
6+
maven = use_extension("@rules_jvm_external//:extensions.bzl", "maven")
7+
8+
maven.install(
9+
artifacts = [
10+
"software.amazon.lambda:powertools-tracing:2.2.1",
11+
"software.amazon.lambda:powertools-logging:2.2.1",
12+
"software.amazon.lambda:powertools-logging-log4j:2.2.1",
13+
"software.amazon.lambda:powertools-metrics:2.2.1",
14+
"com.amazonaws:aws-lambda-java-core:1.3.0",
15+
"com.amazonaws:aws-lambda-java-events:3.16.1",
16+
"org.aspectj:aspectjrt:1.9.22",
17+
"org.aspectj:aspectjweaver:1.9.22",
18+
"org.aspectj:aspectjtools:1.9.22",
19+
"org.slf4j:slf4j-api:2.0.16",
20+
],
21+
repositories = [
22+
"https://repo1.maven.org/maven2",
23+
],
24+
lock_file = "//:maven_install.json",
25+
)
26+
27+
use_repo(maven, "maven")
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# Powertools for AWS Lambda (Java) - Core Utilities Example with Bazel
2+
3+
This project demonstrates the Lambda for Powertools Java module deployed using [Serverless Application Model](https://aws.amazon.com/serverless/sam/) and built with Bazel.
4+
5+
For general information on the deployed example itself, you can refer to the parent [README](../README.md)
6+
7+
## Configuration
8+
9+
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.
10+
11+
## Deploy the sample application
12+
13+
To deploy the example, check out the instructions for getting started with SAM in [the examples directory](../../README.md)
14+
15+
## Build and deploy
16+
17+
```bash
18+
# Build the application
19+
bazel build //:powertools_sam_deploy.jar
20+
21+
# Deploy the application
22+
sam deploy --guided
23+
```
24+
25+
## Local testing
26+
27+
```bash
28+
# Build the application
29+
bazel build //:powertools_sam_deploy.jar
30+
31+
# Test a single function locally
32+
sam local invoke HelloWorldFunction --event events/event.json
33+
34+
# Start the local API
35+
sam local start-api
36+
37+
# Test the API endpoints
38+
curl http://127.0.0.1:3000/hello
39+
curl http://127.0.0.1:3000/hellostream
40+
```
41+
42+
## Additional notes
43+
44+
You can watch the trace information or log information using the SAM CLI:
45+
46+
```bash
47+
# Tail the logs
48+
sam logs --tail $MY_STACK
49+
50+
# Tail the traces
51+
sam traces --tail
52+
```
53+
54+
### Pinning Maven versions
55+
56+
To ensure reproducible builds, you can pin Maven dependency versions:
57+
58+
```bash
59+
# Generate lock file for reproducible builds
60+
bazel run @maven//:pin
61+
```
62+
63+
This creates `maven_install.json` which locks dependency versions and should be committed to version control.
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
{
2+
"body": "{\"message\": \"hello world\"}",
3+
"resource": "/{proxy+}",
4+
"path": "/path/to/resource",
5+
"httpMethod": "POST",
6+
"isBase64Encoded": false,
7+
"queryStringParameters": {
8+
"foo": "bar"
9+
},
10+
"pathParameters": {
11+
"proxy": "/path/to/resource"
12+
},
13+
"stageVariables": {
14+
"baz": "qux"
15+
},
16+
"headers": {
17+
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
18+
"Accept-Encoding": "gzip, deflate, sdch",
19+
"Accept-Language": "en-US,en;q=0.8",
20+
"Cache-Control": "max-age=0",
21+
"CloudFront-Forwarded-Proto": "https",
22+
"CloudFront-Is-Desktop-Viewer": "true",
23+
"CloudFront-Is-Mobile-Viewer": "false",
24+
"CloudFront-Is-SmartTV-Viewer": "false",
25+
"CloudFront-Is-Tablet-Viewer": "false",
26+
"CloudFront-Viewer-Country": "US",
27+
"Host": "1234567890.execute-api.us-east-1.amazonaws.com",
28+
"Upgrade-Insecure-Requests": "1",
29+
"User-Agent": "Custom User Agent String",
30+
"Via": "1.1 08f323deadbeefa7af34d5feb414ce27.cloudfront.net (CloudFront)",
31+
"X-Amz-Cf-Id": "cDehVQoZnx43VYQb9j2-nvCh-9z396Uhbp027Y2JvkCPNLmGJHqlaA==",
32+
"X-Forwarded-For": "127.0.0.1, 127.0.0.2",
33+
"X-Forwarded-Port": "443",
34+
"X-Forwarded-Proto": "https"
35+
},
36+
"requestContext": {
37+
"accountId": "123456789012",
38+
"resourceId": "123456",
39+
"stage": "prod",
40+
"requestId": "c6af9ac6-7b61-11e6-9a41-93e8deadbeef",
41+
"requestTime": "09/Apr/2015:12:34:56 +0000",
42+
"requestTimeEpoch": 1428582896000,
43+
"identity": {
44+
"cognitoIdentityPoolId": null,
45+
"accountId": null,
46+
"cognitoIdentityId": null,
47+
"caller": null,
48+
"accessKey": null,
49+
"sourceIp": "127.0.0.1",
50+
"cognitoAuthenticationType": null,
51+
"cognitoAuthenticationProvider": null,
52+
"userArn": null,
53+
"userAgent": "Custom User Agent String",
54+
"user": null
55+
},
56+
"path": "/prod/path/to/resource",
57+
"resourcePath": "/{proxy+}",
58+
"httpMethod": "POST",
59+
"apiId": "1234567890",
60+
"protocol": "HTTP/1.1"
61+
}
62+
}
63+
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
/*
2+
* Copyright 2023 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+
15+
package helloworld;
16+
17+
import static software.amazon.lambda.powertools.logging.argument.StructuredArguments.entry;
18+
import static software.amazon.lambda.powertools.tracing.TracingUtils.putMetadata;
19+
20+
import java.io.BufferedReader;
21+
import java.io.IOException;
22+
import java.io.InputStreamReader;
23+
import java.net.URL;
24+
import java.util.HashMap;
25+
import java.util.Map;
26+
import java.util.stream.Collectors;
27+
28+
import org.slf4j.Logger;
29+
import org.slf4j.LoggerFactory;
30+
import org.slf4j.MDC;
31+
32+
import com.amazonaws.services.lambda.runtime.Context;
33+
import com.amazonaws.services.lambda.runtime.RequestHandler;
34+
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
35+
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;
36+
37+
import software.amazon.lambda.powertools.logging.Logging;
38+
import software.amazon.lambda.powertools.metrics.FlushMetrics;
39+
import software.amazon.lambda.powertools.metrics.Metrics;
40+
import software.amazon.lambda.powertools.metrics.MetricsFactory;
41+
import software.amazon.lambda.powertools.metrics.model.DimensionSet;
42+
import software.amazon.lambda.powertools.metrics.model.MetricResolution;
43+
import software.amazon.lambda.powertools.metrics.model.MetricUnit;
44+
import software.amazon.lambda.powertools.tracing.CaptureMode;
45+
import software.amazon.lambda.powertools.tracing.Tracing;
46+
import software.amazon.lambda.powertools.tracing.TracingUtils;
47+
48+
/**
49+
* Handler for requests to Lambda function.
50+
*/
51+
public class App implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {
52+
private static final Logger log = LoggerFactory.getLogger(App.class);
53+
private static final Metrics metrics = MetricsFactory.getMetricsInstance();
54+
55+
@Logging(logEvent = true, samplingRate = 0.7)
56+
@Tracing(captureMode = CaptureMode.RESPONSE_AND_ERROR)
57+
@FlushMetrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true)
58+
public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) {
59+
Map<String, String> headers = new HashMap<>();
60+
61+
headers.put("Content-Type", "application/json");
62+
headers.put("X-Custom-Header", "application/json");
63+
64+
metrics.addMetric("CustomMetric1", 1, MetricUnit.COUNT);
65+
66+
DimensionSet dimensionSet = new DimensionSet();
67+
dimensionSet.addDimension("AnotherService", "CustomService");
68+
dimensionSet.addDimension("AnotherService1", "CustomService1");
69+
metrics.flushSingleMetric("CustomMetric2", 1, MetricUnit.COUNT, "Another", dimensionSet);
70+
71+
metrics.addMetric("CustomMetric3", 1, MetricUnit.COUNT, MetricResolution.HIGH);
72+
73+
MDC.put("test", "willBeLogged");
74+
75+
APIGatewayProxyResponseEvent response = new APIGatewayProxyResponseEvent()
76+
.withHeaders(headers);
77+
try {
78+
final String pageContents = this.getPageContents("https://checkip.amazonaws.com");
79+
log.info("", entry("ip", pageContents));
80+
TracingUtils.putAnnotation("Test", "New");
81+
String output = String.format("{ \"message\": \"hello world\", \"location\": \"%s\" }", pageContents);
82+
83+
TracingUtils.withSubsegment("loggingResponse", subsegment -> {
84+
String sampled = "log something out";
85+
log.info(sampled);
86+
log.info(output);
87+
});
88+
89+
log.info("After output");
90+
return response
91+
.withStatusCode(200)
92+
.withBody(output);
93+
} catch (RuntimeException | IOException e) {
94+
return response
95+
.withBody("{}")
96+
.withStatusCode(500);
97+
}
98+
}
99+
100+
@Tracing(namespace = "getPageContents", captureMode = CaptureMode.DISABLED)
101+
private String getPageContents(String address) throws IOException {
102+
URL url = new URL(address);
103+
putMetadata("getPageContents", address);
104+
try (BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream()))) {
105+
return br.lines().collect(Collectors.joining(System.lineSeparator()));
106+
}
107+
}
108+
}

0 commit comments

Comments
 (0)