Skip to content

Commit

Permalink
Merge branch 'master' into fix-awslabs#99
Browse files Browse the repository at this point in the history
  • Loading branch information
Mark Kuhn authored Aug 30, 2022
2 parents 2dc5900 + 69b3f51 commit cdcb0c6
Show file tree
Hide file tree
Showing 43 changed files with 1,332 additions and 267 deletions.
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,24 @@ config.setAgentEndpoint("udp://127.0.0.1:1000");
AWS_EMF_AGENT_ENDPOINT="udp://127.0.0.1:1000"
```

## Thread-safety

### Internal Synchronization

The MetricsLogger class is thread-safe. Specifically, the generalized multi-threading use cases for this library are:

1. Collect some metrics or metadata on a single MetricsLogger; Pass the logger into one or more async contexts where new metrics or metadata can be added concurrently; Join the async contexts (e.g. Future.get()) and flush the metrics.
2. Collect some metrics or metadata on a single MetricsLogger; Pass the logger into an async context; Flush from the async context concurrently.

Thread-safety for the first use case is achieved by introducing concurrent internal data structures and atomic operations associated with these models, to ensure the access to shared mutable resources are always synchronized.

Thread-safety for the second use case is achieved by using a ReentrantReadWriteLock. This lock is used to create an internal sync context for flush() method in multi-threading situations. `flush()` acquires write lock, while other methods (which have access to mutable shared data with `flush()`) acquires read lock. This makes sure `flush()` is always executed exclusively, while other methods can be executed concurrently.

### Use Cases that are Not Covered

With all the internal synchronization measures, however, there're still certain multi-threading use cases that are not covered by this library, which might require external synchronizations or other protection measures.
This is due to the fact that the execution order of APIs are not determined in async contexts. For example, if user needs to associate a given set of properties with a metric in each thread, the results are not guaranteed since the execution order of `putProperty()` is not determined across threads. In such cases, we recommend using a different MetricsLogger instance for different threads, so that no resources are shared and no thread-safety problem would ever happen. Note that this can often be simplified by using a ThreadLocal variable.

## Examples

Check out the [examples](https://github.com/awslabs/aws-embedded-metrics-java/tree/master/examples) directory to get started.
Expand Down Expand Up @@ -392,6 +410,14 @@ To auto fix code style, run
./gradlew :spotlessApply
```

### Benchmark

We use [JMH](https://github.com/openjdk/jmh) as our framework for concurrency performance benchmarking. Benchmarks can be run by:
```
./gradlew jmh
```
To run a single benchmark, consider using JMH plugins. For example, [JMH plugin for IntelliJ IDEA](https://github.com/artyushov/idea-jmh-plugin)

## License

This project is licensed under the Apache-2.0 License.
13 changes: 9 additions & 4 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,18 @@ plugins {
id 'com.diffplug.spotless' version '5.8.2'
id 'maven-publish'
id 'signing'
id "me.champeau.jmh" version "0.6.6"
}

group "software.amazon.cloudwatchlogs"

allprojects {
compileJava {
sourceCompatibility = '1.8'
targetCompatibility = '1.8'
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}

version = '3.0.0-beta-1'
version = '3.1.0'
}

java {
Expand Down Expand Up @@ -78,6 +79,10 @@ dependencies {
testImplementation 'software.amazon.awssdk:cloudwatch:2.13.54'
testCompileOnly 'org.projectlombok:lombok:1.18.12'
testAnnotationProcessor 'org.projectlombok:lombok:1.18.12'

implementation 'org.openjdk.jmh:jmh-core:1.29'
implementation 'org.openjdk.jmh:jmh-generator-annprocess:1.29'
jmhAnnotationProcessor 'org.openjdk.jmh:jmh-generator-annprocess:1.29'
}

spotless {
Expand Down Expand Up @@ -124,7 +129,7 @@ tasks.withType(JavaCompile) {
}

tasks.named('wrapper') {
gradleVersion = '6.5.1'
gradleVersion = '7.4.2'
distributionType = Wrapper.DistributionType.ALL
}

Expand Down
21 changes: 0 additions & 21 deletions buildspecs/buildspec.canary.yml

This file was deleted.

17 changes: 0 additions & 17 deletions buildspecs/buildspec.release.yml

This file was deleted.

21 changes: 0 additions & 21 deletions buildspecs/buildspec.yml

This file was deleted.

4 changes: 2 additions & 2 deletions examples/lambda/src/main/java/Handler.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
import java.util.HashMap;
import java.util.Map;

public class Handler implements RequestHandler<Map<String,String>, String> {
public class Handler implements RequestHandler<Map<String, String>, String> {

@Override
public String handleRequest(Map<String,String> event, Context context) {
public String handleRequest(Map<String, String> event, Context context) {
String response = "200 OK";
MetricsLogger logger = new MetricsLogger();

Expand Down
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.5.1-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Loading

0 comments on commit cdcb0c6

Please sign in to comment.