Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Java compilation settings
build --java_language_version=11
build --java_runtime_version=11
20 changes: 20 additions & 0 deletions examples/powertools-examples-core-utilities/sam-bazel/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Bazel build outputs
bazel-*
MODULE.bazel.lock

# SAM build outputs
.aws-sam/

# JAR files
*.jar

# Maven lock file (generated)
maven_install.json

# IDE files
.idea/
.vscode/
*.iml

# OS files
.DS_Store
78 changes: 78 additions & 0 deletions examples/powertools-examples-core-utilities/sam-bazel/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
load("@rules_java//java:defs.bzl", "java_binary", "java_library")

java_library(
name = "powertools_sam_lib_base",
srcs = glob(["src/main/java/**/*.java"]),
resources = glob(["src/main/resources/**"]),
deps = [
"@maven//:software_amazon_lambda_powertools_tracing",
"@maven//:software_amazon_lambda_powertools_logging",
"@maven//:software_amazon_lambda_powertools_logging_log4j",
"@maven//:software_amazon_lambda_powertools_metrics",
"@maven//:com_amazonaws_aws_lambda_java_core",
"@maven//:com_amazonaws_aws_lambda_java_events",
"@maven//:org_aspectj_aspectjrt",
"@maven//:org_slf4j_slf4j_api",
"@maven//:com_fasterxml_jackson_core_jackson_databind",
"@maven//:org_apache_logging_log4j_log4j_api",
],
)

genrule(
name = "aspectj_weave",
srcs = [
":powertools_sam_lib_base",
"@maven//:software_amazon_lambda_powertools_tracing",
"@maven//:software_amazon_lambda_powertools_logging",
"@maven//:software_amazon_lambda_powertools_metrics",
"@maven//:com_amazonaws_aws_lambda_java_core",
"@maven//:com_amazonaws_aws_lambda_java_events",
"@maven//:org_aspectj_aspectjrt",
],
outs = ["powertools_sam_lib_woven.jar"],
tools = [
"@maven//:org_aspectj_aspectjweaver",
"@maven//:org_aspectj_aspectjtools",
],
cmd = """
# Get dependency JARs for classpath
ASPECTJ_TOOLS="$$(echo $(locations @maven//:org_aspectj_aspectjtools) $(locations @maven//:org_aspectj_aspectjweaver) | tr ' ' ':')"
ASPECTJ_RT="$(locations @maven//:org_aspectj_aspectjrt)"
LAMBDA_JARS="$$(echo $(locations @maven//:com_amazonaws_aws_lambda_java_core) $(locations @maven//:com_amazonaws_aws_lambda_java_events) | tr ' ' ':')"
ALL_DEPS="$$ASPECTJ_TOOLS:$$ASPECTJ_RT:$$LAMBDA_JARS"

BASE_JAR=$$(echo $(locations :powertools_sam_lib_base) | cut -d' ' -f1)
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 ' ' ':')"

java -cp "$$ALL_DEPS" \
org.aspectj.tools.ajc.Main \
-inpath "$$BASE_JAR" \
-aspectpath "$$POWERTOOLS_JARS" \
-outjar $(location powertools_sam_lib_woven.jar) \
-source 11 -target 11 -nowarn
""",
)

java_import(
name = "powertools_sam_lib",
jars = [":powertools_sam_lib_woven.jar"],
deps = [
"@maven//:software_amazon_lambda_powertools_tracing",
"@maven//:software_amazon_lambda_powertools_logging",
"@maven//:software_amazon_lambda_powertools_logging_log4j",
"@maven//:software_amazon_lambda_powertools_metrics",
"@maven//:com_amazonaws_aws_lambda_java_core",
"@maven//:com_amazonaws_aws_lambda_java_events",
"@maven//:org_aspectj_aspectjrt",
],
)

java_binary(
name = "powertools_sam",
main_class = "helloworld.App",
runtime_deps = [":powertools_sam_lib"],
deploy_manifest_lines = [
"Main-Class: helloworld.App",
],
create_executable = False,
)
27 changes: 27 additions & 0 deletions examples/powertools-examples-core-utilities/sam-bazel/MODULE.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
module(name = "powertools_sam_bazel", version = "1.0.0")

bazel_dep(name = "rules_java", version = "8.12.0")
bazel_dep(name = "rules_jvm_external", version = "6.3")

maven = use_extension("@rules_jvm_external//:extensions.bzl", "maven")

maven.install(
artifacts = [
"software.amazon.lambda:powertools-tracing:2.2.1",
"software.amazon.lambda:powertools-logging:2.2.1",
"software.amazon.lambda:powertools-logging-log4j:2.2.1",
"software.amazon.lambda:powertools-metrics:2.2.1",
"com.amazonaws:aws-lambda-java-core:1.3.0",
"com.amazonaws:aws-lambda-java-events:3.16.1",
"org.aspectj:aspectjrt:1.9.22",
"org.aspectj:aspectjweaver:1.9.22",
"org.aspectj:aspectjtools:1.9.22",
"org.slf4j:slf4j-api:2.0.16",
],
repositories = [
"https://repo1.maven.org/maven2",
],
lock_file = "//:maven_install.json",
)

use_repo(maven, "maven")
63 changes: 63 additions & 0 deletions examples/powertools-examples-core-utilities/sam-bazel/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Powertools for AWS Lambda (Java) - Core Utilities Example with Bazel

This project demonstrates the Lambda for Powertools Java module deployed using [Serverless Application Model](https://aws.amazon.com/serverless/sam/) and built with Bazel.

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.

## Deploy the sample application

To deploy the example, check out the instructions for getting started with SAM in [the examples directory](../../README.md)

## Build and deploy

```bash
# Build the application
bazel build //:powertools_sam_deploy.jar

# Deploy the application
sam deploy --guided
```

## Local testing

```bash
# Build the application
bazel build //:powertools_sam_deploy.jar

# Test a single function locally
sam local invoke HelloWorldFunction --event events/event.json

# Start the local API
sam local start-api

# Test the API endpoints
curl http://127.0.0.1:3000/hello
curl http://127.0.0.1:3000/hellostream
```

## 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
```

### Pinning Maven versions

To ensure reproducible builds, you can pin Maven dependency versions:

```bash
# Generate lock file for reproducible builds
bazel run @maven//:pin
```

This creates `maven_install.json` which locks dependency versions and should be committed to version control.
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
{
"body": "{\"message\": \"hello world\"}",
"resource": "/{proxy+}",
"path": "/path/to/resource",
"httpMethod": "POST",
"isBase64Encoded": false,
"queryStringParameters": {
"foo": "bar"
},
"pathParameters": {
"proxy": "/path/to/resource"
},
"stageVariables": {
"baz": "qux"
},
"headers": {
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
"Accept-Encoding": "gzip, deflate, sdch",
"Accept-Language": "en-US,en;q=0.8",
"Cache-Control": "max-age=0",
"CloudFront-Forwarded-Proto": "https",
"CloudFront-Is-Desktop-Viewer": "true",
"CloudFront-Is-Mobile-Viewer": "false",
"CloudFront-Is-SmartTV-Viewer": "false",
"CloudFront-Is-Tablet-Viewer": "false",
"CloudFront-Viewer-Country": "US",
"Host": "1234567890.execute-api.us-east-1.amazonaws.com",
"Upgrade-Insecure-Requests": "1",
"User-Agent": "Custom User Agent String",
"Via": "1.1 08f323deadbeefa7af34d5feb414ce27.cloudfront.net (CloudFront)",
"X-Amz-Cf-Id": "cDehVQoZnx43VYQb9j2-nvCh-9z396Uhbp027Y2JvkCPNLmGJHqlaA==",
"X-Forwarded-For": "127.0.0.1, 127.0.0.2",
"X-Forwarded-Port": "443",
"X-Forwarded-Proto": "https"
},
"requestContext": {
"accountId": "123456789012",
"resourceId": "123456",
"stage": "prod",
"requestId": "c6af9ac6-7b61-11e6-9a41-93e8deadbeef",
"requestTime": "09/Apr/2015:12:34:56 +0000",
"requestTimeEpoch": 1428582896000,
"identity": {
"cognitoIdentityPoolId": null,
"accountId": null,
"cognitoIdentityId": null,
"caller": null,
"accessKey": null,
"sourceIp": "127.0.0.1",
"cognitoAuthenticationType": null,
"cognitoAuthenticationProvider": null,
"userArn": null,
"userAgent": "Custom User Agent String",
"user": null
},
"path": "/prod/path/to/resource",
"resourcePath": "/{proxy+}",
"httpMethod": "POST",
"apiId": "1234567890",
"protocol": "HTTP/1.1"
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/*
* Copyright 2023 Amazon.com, Inc. or its affiliates.
* Licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package helloworld;

import static software.amazon.lambda.powertools.logging.argument.StructuredArguments.entry;
import static software.amazon.lambda.powertools.tracing.TracingUtils.putMetadata;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;

import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;

import software.amazon.lambda.powertools.logging.Logging;
import software.amazon.lambda.powertools.metrics.FlushMetrics;
import software.amazon.lambda.powertools.metrics.Metrics;
import software.amazon.lambda.powertools.metrics.MetricsFactory;
import software.amazon.lambda.powertools.metrics.model.DimensionSet;
import software.amazon.lambda.powertools.metrics.model.MetricResolution;
import software.amazon.lambda.powertools.metrics.model.MetricUnit;
import software.amazon.lambda.powertools.tracing.CaptureMode;
import software.amazon.lambda.powertools.tracing.Tracing;
import software.amazon.lambda.powertools.tracing.TracingUtils;

/**
* Handler for requests to Lambda function.
*/
public class App implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {
private static final Logger log = LoggerFactory.getLogger(App.class);
private static final Metrics metrics = MetricsFactory.getMetricsInstance();

@Logging(logEvent = true, samplingRate = 0.7)
@Tracing(captureMode = CaptureMode.RESPONSE_AND_ERROR)
@FlushMetrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true)
public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) {
Map<String, String> headers = new HashMap<>();

headers.put("Content-Type", "application/json");
headers.put("X-Custom-Header", "application/json");

metrics.addMetric("CustomMetric1", 1, MetricUnit.COUNT);

DimensionSet dimensionSet = new DimensionSet();
dimensionSet.addDimension("AnotherService", "CustomService");
dimensionSet.addDimension("AnotherService1", "CustomService1");
metrics.flushSingleMetric("CustomMetric2", 1, MetricUnit.COUNT, "Another", dimensionSet);

metrics.addMetric("CustomMetric3", 1, MetricUnit.COUNT, MetricResolution.HIGH);

MDC.put("test", "willBeLogged");

APIGatewayProxyResponseEvent response = new APIGatewayProxyResponseEvent()
.withHeaders(headers);
try {
final String pageContents = this.getPageContents("https://checkip.amazonaws.com");
log.info("", entry("ip", pageContents));
TracingUtils.putAnnotation("Test", "New");
String output = String.format("{ \"message\": \"hello world\", \"location\": \"%s\" }", pageContents);

TracingUtils.withSubsegment("loggingResponse", subsegment -> {
String sampled = "log something out";
log.info(sampled);
log.info(output);
});

log.info("After output");
return response
.withStatusCode(200)
.withBody(output);
} catch (RuntimeException | IOException e) {
return response
.withBody("{}")
.withStatusCode(500);
}
}

@Tracing(namespace = "getPageContents", captureMode = CaptureMode.DISABLED)
private String getPageContents(String address) throws IOException {
URL url = new URL(address);
putMetadata("getPageContents", address);
try (BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream()))) {
return br.lines().collect(Collectors.joining(System.lineSeparator()));
}
}
}
Loading
Loading