Skip to content
Permalink
Browse files
circuit breaker metrics
  • Loading branch information
rmannibucau committed Nov 27, 2018
1 parent d10f0ac commit bda1534c8b05c39e7e8e8775e7c59b0027489dfe
Showing 2 changed files with 19 additions and 16 deletions.
@@ -60,6 +60,8 @@ public Object ifNotOpen(final InvocationContext context) throws Exception {
final CircuitBreakerImpl existing = circuitBreakers.putIfAbsent(key, circuitBreaker);
if (existing != null) {
circuitBreaker = existing;
} else {
cache.postCreate(circuitBreaker, context);
}
}
if (circuitBreaker.disabled) {
@@ -76,6 +78,7 @@ public Object ifNotOpen(final InvocationContext context) throws Exception {
if (state != CheckResult.CLOSED_CHANGED) { // a change triggers a reset we want to preserve
circuitBreaker.onSuccess();
}
circuitBreaker.callsSucceeded.inc();
return result;
} catch (final Exception e) {
if (circuitBreaker.failOn.length > 0 &&
@@ -106,8 +109,8 @@ public State isStateTransition(final CircuitBreakerImpl breaker,
final CheckIntervalData nextData) {
final long now = now();
final double currentFailureRatio = getCurrentFailureRatio(nextData);
breaker.closedDuration.set(now - currentData.checkIntervalStart);
if (nextData.states.length >= breaker.volumeThreshold && currentFailureRatio >= breaker.failureRatio) {
breaker.closedDuration.set(now - currentData.checkIntervalStart);
breaker.opened.inc();
return OPEN;
}
@@ -124,13 +127,13 @@ private double getCurrentFailureRatio(final CheckIntervalData data) {
public State isStateTransition(final CircuitBreakerImpl breaker,
final CheckIntervalData currentData,
final CheckIntervalData nextData) {
breaker.halfOpenDuration.set(now() - currentData.checkIntervalStart);
if (Stream.of(nextData.states).anyMatch(it -> !it)) { // a exception was thrown
return OPEN;
}

final long successes = Stream.of(nextData.states).filter(it -> it).count();
if (successes == nextData.states.length && successes >= breaker.successThreshold) {
breaker.halfOpenDuration.set(now() - currentData.checkIntervalStart);
return CLOSED;
}
return this;
@@ -141,12 +144,11 @@ public State isStateTransition(final CircuitBreakerImpl breaker,
public State isStateTransition(final CircuitBreakerImpl breaker,
final CheckIntervalData currentData,
final CheckIntervalData nextData) {
breaker.openDuration.set(now() - currentData.checkIntervalStart);
if (nextData.checkIntervalStart != currentData.checkIntervalStart) {
breaker.openDuration.set(now() - currentData.checkIntervalStart);
return breaker.successThreshold == 1 ? CLOSED : HALF_OPEN;
}
if (Stream.of(nextData.states).filter(it -> it).count() > breaker.successThreshold) {
breaker.openDuration.set(now() - currentData.checkIntervalStart);
return breaker.successThreshold == 1 ? CLOSED : HALF_OPEN;
}
return this;
@@ -213,10 +215,8 @@ public CircuitBreakerImpl create(final InvocationContext context) {
throw new FaultToleranceDefinitionException("CircuitBreaker success threshold can't be <= 0");
}

final String metricsNameBase = "ft." + context.getMethod().getDeclaringClass().getCanonicalName() + "."
+ context.getMethod().getName() + ".circuitbreaker.";

final CircuitBreakerImpl circuitBreaker = new CircuitBreakerImpl(
final String metricsNameBase = getBaseMetricsName(context);
return new CircuitBreakerImpl(
!mapper.isEnabled(context.getMethod(), CircuitBreaker.class),
volumeThreshold, delay, successThreshold,
failOn, failureRatio, metrics.counter(metricsNameBase + "callsSucceeded.total",
@@ -227,13 +227,21 @@ public CircuitBreakerImpl create(final InvocationContext context) {
"Number of calls prevented from running by an open circuit breaker"),
metrics.counter(metricsNameBase + "opened.total",
"Number of times the circuit breaker has moved from closed state to open state"));
}

private String getBaseMetricsName(final InvocationContext context) {
return "ft." + context.getMethod().getDeclaringClass().getCanonicalName() + "."
+ context.getMethod().getName() + ".circuitbreaker.";
}

public void postCreate(final CircuitBreakerImpl circuitBreaker, final InvocationContext context) {
final String metricsNameBase = getBaseMetricsName(context);
metrics.gauge(metricsNameBase + "open.total", "Amount of time the circuit breaker has spent in open state", "nanoseconds",
circuitBreaker.openDuration::get);
metrics.gauge(metricsNameBase + "halfOpen.total", "Amount of time the circuit breaker has spent in half-open state", "nanoseconds",
circuitBreaker.halfOpenDuration::get);
metrics.gauge(metricsNameBase + "closed.total", "Amount of time the circuit breaker has spent in closed state", "nanoseconds",
circuitBreaker.closedDuration::get);
return circuitBreaker;
}
}

@@ -285,7 +293,6 @@ public static class CircuitBreakerImpl {

private void onSuccess() {
performStateCheck(CheckType.SUCCESS);
callsSucceeded.inc();
}

private void onFailure() {
@@ -25,13 +25,9 @@
</packages>
-->
<classes>
<class name="org.eclipse.microprofile.fault.tolerance.tck.visibility.retry.RetryVisibilityTest">
<methods>

</methods>
</class>
<!--
<class name="org.eclipse.microprofile.fault.tolerance.tck.metrics.CircuitBreakerMetricTest" />
<class name="org.eclipse.microprofile.fault.tolerance.tck.config.ConfigPropertyGlobalVsClassVsMethodTest" />
<class name="org.eclipse.microprofile.fault.tolerance.tck.visibility.retry.RetryVisibilityTest" />
-->
</classes>
</test>

0 comments on commit bda1534

Please sign in to comment.