Conversation
private final Meter overallMeter; | ||
private String identifier; | ||
|
||
public FailsafeBreaker(final MetricRegistry metricRegistry, final String identifier) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm thinking if we should provide an abstraction layer around the metrics registry that would allow the users to plugin a different metrics collector, eg. prometheus.
For doing so we would need to introduce apart from the registry interface a Meter interface as well which would encapsulate the meter than.
As the default I would propose to provide a DropWizard Metrics implementation.
WDYT?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Spring supports PublicMetrics for this.
public CircuitBreakerRegistry circuitBreakerRegistry() { | ||
circuitBreakerRegistry = new CircuitBreakerRegistry(); | ||
circuitBreakerRegistry = new CircuitBreakerRegistry(this.metricRegistry); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You shouldn't assign to instance variables here, but rather take metricsRegistry
as a parameter.
} | ||
|
||
@Override | ||
public void recordResult(Object result) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this should be done with event listeners rather than subclassing.
…cubator/failsafe-actuator into enhancement/gather-statistics
Thanks for you input @whiskeysierra. Should all be considered in my last commits. |
@@ -44,7 +46,12 @@ | |||
<scope>provided</scope> | |||
<version>1.16.18</version> | |||
</dependency> | |||
<dependency> | |||
<dependency> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do you still need this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because Spring default metrics doesn't support Meter
. But maybe you are right and we should rely on Spring defaults here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The less dependencies the better. Gives your clients more freedom.
@@ -31,12 +34,24 @@ | |||
private CircuitBreakerRegistry circuitBreakerRegistry; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here, shouldn't be needed to have this assigned to an instance field.
public CircuitBreakerRegistry circuitBreakerRegistry() { | ||
circuitBreakerRegistry = new CircuitBreakerRegistry(); | ||
return circuitBreakerRegistry; | ||
} | ||
|
||
@Bean | ||
@DependsOn("metricRegistry") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not needed.
return new DropwizardMetric(metricRegistry, circuitBreakerRegistry); | ||
} | ||
|
||
@Bean | ||
@DependsOn("circuitBreakerRegistry") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Replace with parameter.
final Meter failureMeter = metricRegistry.meter(identifier + FAILURE); | ||
metricMap.put(identifier, Arrays.asList(successMeter, failureMeter)); | ||
Failsafe.with(circuitBreakerRegistry.getConcurrentBreakerMap().get(identifier)) | ||
.with(new DropwizardListener(failureMeter, successMeter)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This probably won't work as expected.
@@ -34,9 +32,9 @@ | |||
|
|||
@Bean | |||
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Misleading because your registry actually implements a singleton pattern. Couldn't you delegate all of this work to spring?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, we could do this. But I would prefer to do this change in another PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See #45
…cubator/failsafe-actuator into enhancement/gather-statistics
a058618
to
3b6b530
Compare
@whiskeysierra @coders-kitchen can you have another look? |
pom.xml
Outdated
|
||
<modelVersion>4.0.0</modelVersion> | ||
|
||
<groupId>org.zalando</groupId> | ||
<artifactId>failsafe-actuator</artifactId> | ||
<version>0.4.1</version> | ||
<version>0.5.1</version> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should a bump of the minor version set the patch back to 0, i.e. 0.5.0
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, will change that
@@ -1,29 +1,42 @@ | |||
/** | |||
* The MIT License (MIT) | |||
* Copyright (c) 2016 Zalando SE | |||
* The MIT License (MIT) Copyright (c) 2016 Zalando SE |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't believe that you actually need to put the header in every file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
True, see #52
private CircuitBreakerRegistry circuitBreakerRegistry; | ||
@Bean | ||
@ConditionalOnMissingBean(MetricWriter.class) | ||
public MetricWriter metricWriter() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wouldn't create those in here. The better approach would be to degrade and perform retries and manage circuit breakers without recording metrics.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 a noop implementation in this case makes more sense
}); | ||
} catch (RuntimeException e) { | ||
.with(new CountingListener<>(counterService, breaker.value())) | ||
.get( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This won't work for methods that return a Future.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should file a new Issue for that since this logic wasn't introduced by this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See #58
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @whiskeysierra now as I am looking into it, it's not really clear to me what you mean here. Could maybe explain a bit more in detail or extend the issue? Would be awesome!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are two kinds of methods, sync and async. get
is for synchronous methods. For something that returns a future, you should use future
: https://github.com/jhalterman/failsafe#completablefuture-integration
Let's say you have a method that performs a remote request asynchronously and returns a Future<User>
.
get
would only retry the synchronous part of that, i.e. if anything failed during the creation of the future, but not duringfuture
would be aware that the operation is asynchronous and it would correctly retry the asynchronous operation
try { | ||
return methodInvocation.proceed(); | ||
} catch (final Throwable throwable) { | ||
throw new FailsafeBreakerWrappedException(throwable); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this custom exception type needed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@coders-kitchen should know. Depending on the outcome we should also tackle this on a separate issue as already mentioned before.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I prefer to have explicit exceptions in cases like this, to make it clear what the cause in case anything unexpected happen.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@coders-kitchen But you're deviating from the normal behaviour of failsafe. If a user would migrate from manually using failsafe to this annotation+advice, then he/she would experience a different behaviour. I believe it would be in the best interest of everybody if both ways are 100% compatible.
@whiskeysierra @coders-kitchen I would consider this PR as done. Any further feedback? |
@MALPI Fine from my side |
👍 |
Fixes #23
WIP
Extends Failsafe Actuator by the feature to provide failure/success metrics for the used Circuit Breakers.
Still open:
Readme.md
.