Skip to content

Commit 40df063

Browse files
committed
PR comments addressed
1 parent f1ac254 commit 40df063

File tree

8 files changed

+123
-122
lines changed

8 files changed

+123
-122
lines changed

docs/supported-libraries.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ These are the supported libraries and frameworks:
6565
| [Elasticsearch API Client](https://www.elastic.co/guide/en/elasticsearch/client/java-api-client/current/index.html) | 7.16 - 7.17.19,<br>8.0 - 8.9.+ [4] | N/A | [Elasticsearch Client Spans] |
6666
| [Elasticsearch REST Client](https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/index.html) | 5.0+ | N/A | [Database Client Spans], [Database Client Metrics]&nbsp;[6] |
6767
| [Elasticsearch Transport Client](https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/index.html) | 5.0+ | N/A | [Database Client Spans], [Database Client Metrics]&nbsp;[6] |
68+
| [Failsafe](https://failsafe.dev/) | 3.0.1+ | N/A | none |
6869
| [Finagle](https://github.com/twitter/finagle) | 23.11+ | N/A | none |
6970
| [Finatra](https://github.com/twitter/finatra) | 2.9+ | N/A | Provides `http.route` [2], Controller Spans [3] |
7071
| [Geode Client](https://geode.apache.org/) | 1.4+ | N/A | [Database Client Spans], [Database Client Metrics]&nbsp;[6] |
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Library Instrumentation for Failsafe version 3.0.1 and higher
2+
3+
Provides OpenTelemetry instrumentation for [Failsafe](https://failsafe.dev/).
4+
5+
## Quickstart
6+
7+
### Add these dependencies to your project
8+
9+
Replace `OPENTELEMETRY_VERSION` with the [latest release](https://search.maven.org/search?q=g:io.opentelemetry.instrumentation%20AND%20a:opentelemetry-failsafe-3.0).
10+
11+
For Maven, add to your `pom.xml` dependencies:
12+
13+
```xml
14+
<dependencies>
15+
<dependency>
16+
<groupId>io.opentelemetry.instrumentation</groupId>
17+
<artifactId>opentelemetry-failsafe-3.0</artifactId>
18+
<version>OPENTELEMETRY_VERSION</version>
19+
</dependency>
20+
</dependencies>
21+
```
22+
23+
For Gradle, add to your dependencies:
24+
25+
```groovy
26+
implementation("io.opentelemetry.instrumentation:opentelemetry-failsafe-3.0:OPENTELEMETRY_VERSION")
27+
```
28+
29+
### Usage
30+
31+
The instrumentation library allows creating instrumented `CircuitBreaker` instances for collecting
32+
OpenTelemetry-based metrics.
33+
34+
```java
35+
<R> CircuitBreaker<R> configure(OpenTelemetry openTelemetry, CircuitBreaker<R> circuitBreaker) {
36+
FailsafeTelemetry failsafeTelemetry = FailsafeTelemetry.create(openTelemetry);
37+
return failsafeTelemetry.createCircuitBreaker(circuitBreaker, "my-circuit-breaker");
38+
}
39+
```

instrumentation/failsafe-3.0/library/build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@ plugins {
55
dependencies {
66
library("dev.failsafe:failsafe:3.0.1")
77

8-
testImplementation(project(":instrumentation:failsafe-3.0:testing"))
8+
testImplementation(project(":testing-common"))
99
}

instrumentation/failsafe-3.0/library/src/main/java/io/opentelemetry/instrumentation/failsafe/v3_0/CircuitBreakerEventListenerBuilders.java

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,14 @@
1414
import io.opentelemetry.api.metrics.Meter;
1515

1616
final class CircuitBreakerEventListenerBuilders {
17-
private CircuitBreakerEventListenerBuilders() {
18-
throw new AssertionError();
19-
}
17+
private CircuitBreakerEventListenerBuilders() {}
2018

2119
static <R> EventListener<ExecutionCompletedEvent<R>> buildInstrumentedFailureListener(
2220
CircuitBreakerConfig<R> userConfig, Meter meter, Attributes attributes) {
2321
LongCounter failureCounter =
2422
meter
2523
.counterBuilder("failsafe.circuitbreaker.failure.count")
26-
.setDescription("Count of failed circuit breaker executions")
24+
.setDescription("Count of failed circuit breaker executions.")
2725
.build();
2826
EventListener<ExecutionCompletedEvent<R>> failureListener = userConfig.getFailureListener();
2927
return e -> {
@@ -39,7 +37,7 @@ static <R> EventListener<ExecutionCompletedEvent<R>> buildInstrumentedSuccessLis
3937
LongCounter successCounter =
4038
meter
4139
.counterBuilder("failsafe.circuitbreaker.success.count")
42-
.setDescription("Count of successful circuit breaker executions")
40+
.setDescription("Count of successful circuit breaker executions.")
4341
.build();
4442
EventListener<ExecutionCompletedEvent<R>> successListener = userConfig.getSuccessListener();
4543
return e -> {
@@ -55,7 +53,7 @@ static <R> EventListener<CircuitBreakerStateChangedEvent> buildInstrumentedOpenL
5553
LongCounter openCircuitBreakerCounter =
5654
meter
5755
.counterBuilder("failsafe.circuitbreaker.open.count")
58-
.setDescription("Count of times that circuit breaker was opened")
56+
.setDescription("Count of times that circuit breaker was opened.")
5957
.build();
6058
EventListener<CircuitBreakerStateChangedEvent> openListener = userConfig.getOpenListener();
6159
return e -> {
@@ -69,7 +67,7 @@ static <R> EventListener<CircuitBreakerStateChangedEvent> buildInstrumentedHalfO
6967
LongCounter halfOpenCircuitBreakerCounter =
7068
meter
7169
.counterBuilder("failsafe.circuitbreaker.halfopen.count")
72-
.setDescription("Count of times that circuit breaker was half-opened")
70+
.setDescription("Count of times that circuit breaker was half-opened.")
7371
.build();
7472
EventListener<CircuitBreakerStateChangedEvent> halfOpenListener =
7573
userConfig.getHalfOpenListener();
@@ -84,7 +82,7 @@ static <R> EventListener<CircuitBreakerStateChangedEvent> buildInstrumentedClose
8482
LongCounter closedCircuitBreakerCounter =
8583
meter
8684
.counterBuilder("failsafe.circuitbreaker.closed.count")
87-
.setDescription("Count of times that circuit breaker was closed")
85+
.setDescription("Count of times that circuit breaker was closed.")
8886
.build();
8987
EventListener<CircuitBreakerStateChangedEvent> closeListener = userConfig.getCloseListener();
9088
return e -> {

instrumentation/failsafe-3.0/library/src/test/java/io/opentelemetry/instrumentation/failsafe/v3_0/FailsafeTelemetryTest.java

Lines changed: 75 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,89 @@
55

66
package io.opentelemetry.instrumentation.failsafe.v3_0;
77

8-
import dev.failsafe.CircuitBreaker;
8+
import static org.hamcrest.CoreMatchers.equalTo;
9+
import static org.hamcrest.MatcherAssert.assertThat;
10+
import static org.junit.jupiter.api.Assertions.assertTrue;
11+
12+
import dev.failsafe.CircuitBreakerOpenException;
13+
import dev.failsafe.Failsafe;
14+
import io.opentelemetry.api.common.AttributeKey;
15+
import io.opentelemetry.api.common.Attributes;
916
import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
1017
import io.opentelemetry.instrumentation.testing.junit.LibraryInstrumentationExtension;
18+
import io.opentelemetry.sdk.metrics.data.LongPointData;
19+
import io.opentelemetry.sdk.metrics.data.MetricData;
20+
import io.opentelemetry.sdk.testing.assertj.MetricAssert;
21+
import java.time.Duration;
22+
import java.util.Objects;
23+
import org.junit.jupiter.api.Nested;
24+
import org.junit.jupiter.api.Test;
1125
import org.junit.jupiter.api.extension.RegisterExtension;
1226

13-
final class FailsafeTelemetryTest extends AbstractFailsafeTest {
27+
final class FailsafeTelemetryTest {
1428
@RegisterExtension
1529
static final InstrumentationExtension testing = LibraryInstrumentationExtension.create();
1630

17-
@Override
18-
protected InstrumentationExtension testing() {
19-
return testing;
31+
@Nested
32+
final class CircuitBreaker {
33+
@Test
34+
void should_Capture_CircuitBreaker_Metrics() {
35+
// given
36+
dev.failsafe.CircuitBreaker<Object> userCircuitBreaker =
37+
dev.failsafe.CircuitBreaker.builder()
38+
.handleResultIf(Objects::isNull)
39+
.withFailureThreshold(2)
40+
.withDelay(Duration.ZERO)
41+
.withSuccessThreshold(2)
42+
.build();
43+
FailsafeTelemetry failsafeTelemetry = FailsafeTelemetry.create(testing.getOpenTelemetry());
44+
dev.failsafe.CircuitBreaker<Object> instrumentedCircuitBreaker =
45+
failsafeTelemetry.createCircuitBreaker(userCircuitBreaker, "testing");
46+
47+
// when
48+
for (int i = 0; i < 5; i++) {
49+
try {
50+
int temp = i;
51+
Failsafe.with(instrumentedCircuitBreaker)
52+
.get(
53+
() -> {
54+
if (temp < 2) {
55+
return null;
56+
} else {
57+
return new Object();
58+
}
59+
});
60+
} catch (CircuitBreakerOpenException e) {
61+
assertThat(i, equalTo(2));
62+
}
63+
}
64+
65+
// then
66+
testing.waitAndAssertMetrics(
67+
"io.opentelemetry.failsafe-3.0",
68+
metricAssert ->
69+
assertCircuitBreakerMetric(metricAssert, "failsafe.circuitbreaker.failure.count", 2),
70+
metricAssert ->
71+
assertCircuitBreakerMetric(metricAssert, "failsafe.circuitbreaker.success.count", 3),
72+
metricAssert ->
73+
assertCircuitBreakerMetric(metricAssert, "failsafe.circuitbreaker.open.count", 1),
74+
metricAssert ->
75+
assertCircuitBreakerMetric(metricAssert, "failsafe.circuitbreaker.halfopen.count", 1),
76+
metricAssert ->
77+
assertCircuitBreakerMetric(metricAssert, "failsafe.circuitbreaker.closed.count", 1));
78+
}
2079
}
2180

22-
@Override
23-
protected CircuitBreaker<Object> configure(CircuitBreaker<Object> circuitBreaker) {
24-
return FailsafeTelemetry.create(testing.getOpenTelemetry())
25-
.createCircuitBreaker(circuitBreaker, "testing");
81+
private static void assertCircuitBreakerMetric(
82+
MetricAssert metricAssert, String counterName, long expectedValue) {
83+
MetricData closeCountData = metricAssert.actual();
84+
assertThat(closeCountData.getName(), equalTo(counterName));
85+
assertTrue(closeCountData.getData().getPoints().stream().findFirst().isPresent());
86+
LongPointData closeCountLongPointData =
87+
(LongPointData) closeCountData.getData().getPoints().stream().findFirst().get();
88+
assertThat(
89+
closeCountLongPointData.getAttributes(),
90+
equalTo(Attributes.of(AttributeKey.stringKey("name"), "testing")));
91+
assertThat(closeCountLongPointData.getValue(), equalTo(expectedValue));
2692
}
2793
}

instrumentation/failsafe-3.0/testing/build.gradle.kts

Lines changed: 0 additions & 9 deletions
This file was deleted.

instrumentation/failsafe-3.0/testing/src/main/java/io/opentelemetry/instrumentation/failsafe/v3_0/AbstractFailsafeTest.java

Lines changed: 0 additions & 93 deletions
This file was deleted.

settings.gradle.kts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,7 @@ include(":instrumentation:executors:jdk21-testing")
224224
include(":instrumentation:executors:testing")
225225
include(":instrumentation:external-annotations:javaagent")
226226
include(":instrumentation:external-annotations:javaagent-unit-tests")
227+
include(":instrumentation:failsafe-3.0:library")
227228
include(":instrumentation:finagle-http-23.11:javaagent")
228229
include(":instrumentation:finatra-2.9:javaagent")
229230
include(":instrumentation:geode-1.4:javaagent")
@@ -626,8 +627,6 @@ include(":instrumentation:xxl-job:xxl-job-2.3.0:javaagent")
626627
include(":instrumentation:xxl-job:xxl-job-common:javaagent")
627628
include(":instrumentation:xxl-job:xxl-job-common:testing")
628629
include(":instrumentation:zio:zio-2.0:javaagent")
629-
include("instrumentation:failsafe-3.0:library")
630-
include("instrumentation:failsafe-3.0:testing")
631630
// benchmark
632631
include(":benchmark-overhead-jmh")
633632
include(":benchmark-jfr-analyzer")

0 commit comments

Comments
 (0)