Skip to content

Commit 0dc57a4

Browse files
authored
Merge branch 'v2' into chore/remove-java-8
2 parents 7190546 + 1317da4 commit 0dc57a4

File tree

12 files changed

+128
-94
lines changed

12 files changed

+128
-94
lines changed

docs/core/metrics.md

Lines changed: 37 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,7 @@ If you're new to Amazon CloudWatch, there are two terminologies you must be awar
2828

2929
## Install
3030

31-
Depending on your version of Java (either Java 1.8 or 11+), the configuration slightly changes.
32-
33-
=== "Maven Java 11+"
31+
=== "Maven"
3432

3533
```xml hl_lines="3-7 16 18 24-27"
3634
<dependencies>
@@ -75,52 +73,7 @@ If you're new to Amazon CloudWatch, there are two terminologies you must be awar
7573
</build>
7674
```
7775

78-
=== "Maven Java 1.8"
79-
80-
```xml hl_lines="3-7 16 18 24-27"
81-
<dependencies>
82-
...
83-
<dependency>
84-
<groupId>software.amazon.lambda</groupId>
85-
<artifactId>powertools-metrics</artifactId>
86-
<version>{{ powertools.version }}</version>
87-
</dependency>
88-
...
89-
</dependencies>
90-
...
91-
<!-- configure the aspectj-maven-plugin to compile-time weave (CTW) the aws-lambda-powertools-java aspects into your project -->
92-
<build>
93-
<plugins>
94-
...
95-
<plugin>
96-
<groupId>org.codehaus.mojo</groupId>
97-
<artifactId>aspectj-maven-plugin</artifactId>
98-
<version>1.14.0</version>
99-
<configuration>
100-
<source>1.8</source>
101-
<target>1.8</target>
102-
<complianceLevel>1.8</complianceLevel>
103-
<aspectLibraries>
104-
<aspectLibrary>
105-
<groupId>software.amazon.lambda</groupId>
106-
<artifactId>powertools-metrics</artifactId>
107-
</aspectLibrary>
108-
</aspectLibraries>
109-
</configuration>
110-
<executions>
111-
<execution>
112-
<goals>
113-
<goal>compile</goal>
114-
</goals>
115-
</execution>
116-
</executions>
117-
</plugin>
118-
...
119-
</plugins>
120-
</build>
121-
```
122-
123-
=== "Gradle Java 11+"
76+
=== "Gradle"
12477

12578
```groovy hl_lines="3 11"
12679
plugins {
@@ -140,34 +93,14 @@ If you're new to Amazon CloudWatch, there are two terminologies you must be awar
14093
targetCompatibility = 11
14194
```
14295

143-
=== "Gradle Java 1.8"
144-
145-
```groovy hl_lines="3 11"
146-
plugins {
147-
id 'java'
148-
id 'io.freefair.aspectj.post-compile-weaving' version '6.6.3'
149-
}
150-
151-
repositories {
152-
mavenCentral()
153-
}
154-
155-
dependencies {
156-
aspect 'software.amazon.lambda:powertools-metrics:{{ powertools.version }}'
157-
}
158-
159-
sourceCompatibility = 1.8
160-
targetCompatibility = 1.8
161-
```
162-
16396
## Getting started
16497

16598
Metric has two global settings that will be used across all metrics emitted:
16699

167-
Setting | Description | Environment variable | Constructor parameter
168-
------------------------------------------------- | ------------------------------------------------- | ------------------------------------------------- | -------------------------------------------------
169-
**Metric namespace** | Logical container where all metrics will be placed e.g. `ServerlessAirline` | `POWERTOOLS_METRICS_NAMESPACE` | `namespace`
170-
**Service** | Optionally, sets **service** metric dimension across all metrics e.g. `payment` | `POWERTOOLS_SERVICE_NAME` | `service`
100+
| Setting | Description | Environment variable | Constructor parameter |
101+
|----------------------|---------------------------------------------------------------------------------|--------------------------------|-----------------------|
102+
| **Metric namespace** | Logical container where all metrics will be placed e.g. `ServerlessAirline` | `POWERTOOLS_METRICS_NAMESPACE` | `namespace` |
103+
| **Service** | Optionally, sets **service** metric dimension across all metrics e.g. `payment` | `POWERTOOLS_SERVICE_NAME` | `service` |
171104

172105
!!! tip "Use your application or main service as the metric namespace to easily group all metrics"
173106

@@ -198,7 +131,7 @@ Setting | Description | Environment variable | Constructor parameter
198131
@Override
199132
@Metrics(namespace = "ExampleApplication", service = "booking")
200133
public Object handleRequest(Object input, Context context) {
201-
...
134+
// ...
202135
}
203136
}
204137
```
@@ -224,7 +157,7 @@ You can create metrics using `putMetric`, and manually create dimensions for all
224157
public Object handleRequest(Object input, Context context) {
225158
metricsLogger.putDimensions(DimensionSet.of("environment", "prod"));
226159
metricsLogger.putMetric("SuccessfulBooking", 1, Unit.COUNT);
227-
...
160+
// ...
228161
}
229162
}
230163
```
@@ -234,6 +167,35 @@ You can create metrics using `putMetric`, and manually create dimensions for all
234167
!!! note "Metrics overflow"
235168
CloudWatch EMF supports a max of 100 metrics. Metrics utility will flush all metrics when adding the 100th metric while subsequent metrics will be aggregated into a new EMF object, for your convenience.
236169

170+
171+
### Adding high-resolution metrics
172+
173+
You can create [high-resolution metrics](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/publishingMetrics.html#high-resolution-metrics)
174+
passing a `storageResolution` to the `putMetric` method:
175+
176+
=== "HigResMetricsHandler.java"
177+
178+
```java hl_lines="3 13"
179+
import software.amazon.lambda.powertools.metrics.Metrics;
180+
import software.amazon.cloudwatchlogs.emf.logger.MetricsLogger;
181+
import software.amazon.cloudwatchlogs.emf.model.StorageResolution;
182+
183+
public class MetricsEnabledHandler implements RequestHandler<Object, Object> {
184+
185+
MetricsLogger metricsLogger = MetricsUtils.metricsLogger();
186+
187+
@Override
188+
@Metrics(namespace = "ExampleApplication", service = "booking")
189+
public Object handleRequest(Object input, Context context) {
190+
// ...
191+
metricsLogger.putMetric("SuccessfulBooking", 1, Unit.COUNT, StorageResolution.HIGH);
192+
}
193+
}
194+
```
195+
196+
!!! info "When is it useful?"
197+
High-resolution metrics are data with a granularity of one second and are very useful in several situations such as telemetry, time series, real-time incident management, and others.
198+
237199
### Flushing metrics
238200

239201
The `@Metrics` annotation **validates**, **serializes**, and **flushes** all your metrics. During metrics validation,

examples/powertools-examples-batch/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
<maven.compiler.source>11</maven.compiler.source>
1515
<maven.compiler.target>11</maven.compiler.target>
1616
<aspectj.version>1.9.20.1</aspectj.version>
17-
<sdk.version>2.25.26</sdk.version>
17+
<sdk.version>2.26.7</sdk.version>
1818
</properties>
1919

2020
<dependencies>

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import org.slf4j.LoggerFactory;
3535
import org.slf4j.MDC;
3636
import software.amazon.cloudwatchlogs.emf.model.DimensionSet;
37+
import software.amazon.cloudwatchlogs.emf.model.StorageResolution;
3738
import software.amazon.cloudwatchlogs.emf.model.Unit;
3839
import software.amazon.lambda.powertools.logging.Logging;
3940
import software.amazon.lambda.powertools.metrics.Metrics;
@@ -64,6 +65,8 @@ public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEv
6465
metric.setDimensions(DimensionSet.of("AnotherService1", "CustomService1"));
6566
});
6667

68+
metricsLogger().putMetric("CustomMetric3", 1, Unit.COUNT, StorageResolution.HIGH);
69+
6770
MDC.put("test", "willBeLogged");
6871

6972
APIGatewayProxyResponseEvent response = new APIGatewayProxyResponseEvent()

pom.xml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,10 @@
7070
<log4j.version>2.20.0</log4j.version>
7171
<log4j.version>2.23.1</log4j.version>
7272
<slf4j.version>2.0.7</slf4j.version>
73-
<jackson.version>2.17.0</jackson.version>
73+
<jackson.version>2.17.1</jackson.version>
7474
<aws.sdk.version>2.25.35</aws.sdk.version>
75-
<aws.xray.recorder.version>2.15.1</aws.xray.recorder.version>
76-
<payloadoffloading-common.version>2.1.3</payloadoffloading-common.version>
75+
<aws.xray.recorder.version>2.16.0</aws.xray.recorder.version>
76+
<payloadoffloading-common.version>2.2.0</payloadoffloading-common.version>
7777
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
7878
<lambda.core.version>1.2.3</lambda.core.version>
7979
<lambda.events.version>3.11.2</lambda.events.version>
@@ -88,7 +88,7 @@
8888
<maven-source-plugin.version>3.3.0</maven-source-plugin.version>
8989
<maven-gpg-plugin.version>3.2.4</maven-gpg-plugin.version>
9090
<junit.version>5.10.2</junit.version>
91-
<aws-embedded-metrics.version>1.0.6</aws-embedded-metrics.version>
91+
<aws-embedded-metrics.version>4.1.2</aws-embedded-metrics.version>
9292
<jmespath.version>0.6.0</jmespath.version>
9393
<elastic.version>1.6.0</elastic.version>
9494

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

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,15 @@
1818
import com.amazonaws.services.lambda.runtime.RequestHandler;
1919
import software.amazon.cloudwatchlogs.emf.logger.MetricsLogger;
2020
import software.amazon.cloudwatchlogs.emf.model.DimensionSet;
21+
import software.amazon.cloudwatchlogs.emf.model.StorageResolution;
2122
import software.amazon.cloudwatchlogs.emf.model.Unit;
2223
import software.amazon.lambda.powertools.metrics.Metrics;
2324
import software.amazon.lambda.powertools.metrics.MetricsUtils;
25+
import java.time.LocalDateTime;
26+
import java.time.ZoneOffset;
27+
import java.time.temporal.ChronoUnit;
28+
import java.time.Instant;
29+
2430

2531
public class Function implements RequestHandler<Input, String> {
2632

@@ -29,11 +35,17 @@ public class Function implements RequestHandler<Input, String> {
2935
@Metrics(captureColdStart = true)
3036
public String handleRequest(Input input, Context context) {
3137

38+
Instant currentTimeTruncatedPlusThirty =
39+
LocalDateTime.now().truncatedTo(ChronoUnit.MINUTES).toInstant(ZoneOffset.UTC).plusSeconds(30);
40+
metricsLogger.setTimestamp(currentTimeTruncatedPlusThirty);
41+
3242
DimensionSet dimensionSet = new DimensionSet();
3343
input.getDimensions().forEach((key, value) -> dimensionSet.addDimension(key, value));
3444
metricsLogger.putDimensions(dimensionSet);
3545

36-
input.getMetrics().forEach((key, value) -> metricsLogger.putMetric(key, value, Unit.COUNT));
46+
input.getMetrics().forEach((key, value) -> metricsLogger.putMetric(key, value, Unit.COUNT,
47+
input.getHighResolution().equalsIgnoreCase("true") ? StorageResolution.HIGH :
48+
StorageResolution.STANDARD));
3749

3850
return "OK";
3951
}

powertools-e2e-tests/handlers/metrics/src/main/java/software/amazon/lambda/powertools/e2e/Input.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ public class Input {
2121

2222
private Map<String, String> dimensions;
2323

24+
private String highResolution;
25+
2426
public Input() {
2527
}
2628

@@ -32,6 +34,14 @@ public void setMetrics(Map<String, Double> metrics) {
3234
this.metrics = metrics;
3335
}
3436

37+
public String getHighResolution() {
38+
return highResolution;
39+
}
40+
41+
public void setHighResolution(String highResolution) {
42+
this.highResolution = highResolution;
43+
}
44+
3545
public Map<String, String> getDimensions() {
3646
return dimensions;
3747
}

powertools-e2e-tests/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@
8484
<dependency>
8585
<groupId>com.amazonaws</groupId>
8686
<artifactId>amazon-sqs-java-extended-client-lib</artifactId>
87-
<version>2.0.4</version>
87+
<version>2.1.0</version>
8888
<scope>test</scope>
8989
</dependency>
9090

powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/MetricsE2ET.java

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@
1818
import static software.amazon.lambda.powertools.testutils.Infrastructure.FUNCTION_NAME_OUTPUT;
1919
import static software.amazon.lambda.powertools.testutils.lambda.LambdaInvoker.invokeFunction;
2020

21+
import java.time.Instant;
22+
import java.time.LocalDateTime;
23+
import java.time.ZoneOffset;
24+
import java.time.temporal.ChronoUnit;
2125
import java.util.Collections;
2226
import java.util.List;
2327
import java.util.Map;
@@ -66,12 +70,20 @@ public static void tearDown() {
6670
@Test
6771
public void test_recordMetrics() {
6872
// GIVEN
73+
74+
Instant currentTimeTruncatedToMinutes =
75+
LocalDateTime.now().truncatedTo(ChronoUnit.MINUTES).toInstant(ZoneOffset.UTC);
76+
6977
String event1 =
70-
"{ \"metrics\": {\"orders\": 1, \"products\": 4}, \"dimensions\": { \"Environment\": \"test\"} }";
78+
"{ \"metrics\": {\"orders\": 1, \"products\": 4}, \"dimensions\": { \"Environment\": \"test\"}, \"highResolution\": \"false\"}";
7179

80+
String event2 =
81+
"{ \"metrics\": {\"orders\": 1, \"products\": 8}, \"dimensions\": { \"Environment\": \"test\"}, \"highResolution\": \"true\"}";
7282
// WHEN
7383
InvocationResult invocationResult = invokeFunction(functionName, event1);
7484

85+
invokeFunction(functionName, event2);
86+
7587
// THEN
7688
MetricsFetcher metricsFetcher = new MetricsFetcher();
7789
List<Double> coldStart =
@@ -84,18 +96,35 @@ public void test_recordMetrics() {
8496
List<Double> orderMetrics =
8597
metricsFetcher.fetchMetrics(invocationResult.getStart(), invocationResult.getEnd(), 60, namespace,
8698
"orders", Collections.singletonMap("Environment", "test"));
87-
assertThat(orderMetrics.get(0)).isEqualTo(1);
99+
assertThat(orderMetrics.get(0)).isEqualTo(2);
88100
List<Double> productMetrics =
89101
metricsFetcher.fetchMetrics(invocationResult.getStart(), invocationResult.getEnd(), 60, namespace,
90102
"products", Collections.singletonMap("Environment", "test"));
91-
assertThat(productMetrics.get(0)).isEqualTo(4);
103+
104+
// When searching across a 1 minute time period with a period of 60 we find both metrics and the sum is 12
105+
106+
assertThat(productMetrics.get(0)).isEqualTo(12);
107+
92108
orderMetrics =
93109
metricsFetcher.fetchMetrics(invocationResult.getStart(), invocationResult.getEnd(), 60, namespace,
94110
"orders", Collections.singletonMap("Service", service));
95-
assertThat(orderMetrics.get(0)).isEqualTo(1);
111+
assertThat(orderMetrics.get(0)).isEqualTo(2);
96112
productMetrics =
97113
metricsFetcher.fetchMetrics(invocationResult.getStart(), invocationResult.getEnd(), 60, namespace,
98114
"products", Collections.singletonMap("Service", service));
99-
assertThat(productMetrics.get(0)).isEqualTo(4);
115+
assertThat(productMetrics.get(0)).isEqualTo(12);
116+
117+
Instant searchStartTime = currentTimeTruncatedToMinutes.plusSeconds(15);
118+
Instant searchEndTime = currentTimeTruncatedToMinutes.plusSeconds(45);
119+
120+
List<Double> productMetricDataResult =
121+
metricsFetcher.fetchMetrics(searchStartTime, searchEndTime, 1, namespace,
122+
"products", Collections.singletonMap("Environment", "test"));
123+
124+
// We are searching across the time period the metric was created but with a period of 1 second. Only the high resolution metric will be available at this point
125+
126+
assertThat(productMetricDataResult.get(0)).isEqualTo(8);
127+
128+
100129
}
101130
}

powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/MetricsLoggerTest.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
import com.fasterxml.jackson.databind.ObjectMapper;
2626
import java.io.ByteArrayOutputStream;
2727
import java.io.PrintStream;
28+
import java.util.ArrayList;
29+
import java.util.LinkedHashMap;
2830
import java.util.Map;
2931
import java.util.function.Consumer;
3032
import org.junit.jupiter.api.AfterEach;
@@ -35,6 +37,7 @@
3537
import software.amazon.cloudwatchlogs.emf.config.SystemWrapper;
3638
import software.amazon.cloudwatchlogs.emf.logger.MetricsLogger;
3739
import software.amazon.cloudwatchlogs.emf.model.DimensionSet;
40+
import software.amazon.cloudwatchlogs.emf.model.StorageResolution;
3841
import software.amazon.cloudwatchlogs.emf.model.Unit;
3942

4043
class MetricsLoggerTest {
@@ -245,6 +248,7 @@ private void testLogger(Consumer<Consumer<MetricsLogger>> methodToTest) {
245248
{
246249
metricsLogger.setDimensions(DimensionSet.of("Dimension1", "Value1"));
247250
metricsLogger.putMetric("Metric1", 1, Unit.COUNT);
251+
metricsLogger.putMetric("Metric2", 1, Unit.COUNT, StorageResolution.HIGH);
248252
});
249253

250254
assertThat(out.toString())
@@ -263,6 +267,13 @@ private void testLogger(Consumer<Consumer<MetricsLogger>> methodToTest) {
263267
assertThat(aws.get("CloudWatchMetrics"))
264268
.asString()
265269
.contains("Namespace=GlobalName");
270+
271+
ArrayList cloudWatchMetrics = (ArrayList) aws.get("CloudWatchMetrics");
272+
LinkedHashMap<String, Object> values =
273+
(java.util.LinkedHashMap<String, Object>) cloudWatchMetrics.get(0);
274+
ArrayList metricArray = (ArrayList) values.get("Metrics");
275+
LinkedHashMap<String, Object> metricValues = (LinkedHashMap<String, Object>) metricArray.get(1);
276+
assertThat(metricValues).containsEntry("StorageResolution", 1);
266277
});
267278
}
268279
}

0 commit comments

Comments
 (0)