Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
io.smallrye.faulttolerance.metrics.MicroProfileMetricsProvider Maven / Gradle / Ivy
package io.smallrye.faulttolerance.metrics;
import static io.smallrye.faulttolerance.metrics.MetricConstants.BULKHEAD_CALLS_TOTAL;
import static io.smallrye.faulttolerance.metrics.MetricConstants.BULKHEAD_EXECUTIONS_RUNNING;
import static io.smallrye.faulttolerance.metrics.MetricConstants.BULKHEAD_EXECUTIONS_WAITING;
import static io.smallrye.faulttolerance.metrics.MetricConstants.CIRCUIT_BREAKER_CALLS_TOTAL;
import static io.smallrye.faulttolerance.metrics.MetricConstants.CIRCUIT_BREAKER_OPENED_TOTAL;
import static io.smallrye.faulttolerance.metrics.MetricConstants.CIRCUIT_BREAKER_STATE_CURRENT;
import static io.smallrye.faulttolerance.metrics.MetricConstants.CIRCUIT_BREAKER_STATE_TOTAL;
import static io.smallrye.faulttolerance.metrics.MetricConstants.INVOCATIONS_TOTAL;
import static io.smallrye.faulttolerance.metrics.MetricConstants.RATE_LIMIT_CALLS_TOTAL;
import static io.smallrye.faulttolerance.metrics.MetricConstants.RETRY_CALLS_TOTAL;
import static io.smallrye.faulttolerance.metrics.MetricConstants.RETRY_RETRIES_TOTAL;
import static io.smallrye.faulttolerance.metrics.MetricConstants.TIMEOUT_CALLS_TOTAL;
import java.util.function.BooleanSupplier;
import java.util.function.LongSupplier;
import jakarta.inject.Inject;
import jakarta.inject.Singleton;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.eclipse.microprofile.metrics.Metadata;
import org.eclipse.microprofile.metrics.MetricRegistry;
import org.eclipse.microprofile.metrics.MetricUnits;
import org.eclipse.microprofile.metrics.Tag;
import org.eclipse.microprofile.metrics.annotation.RegistryType;
import io.smallrye.faulttolerance.SpecCompatibility;
import io.smallrye.faulttolerance.config.FaultToleranceOperation;
import io.smallrye.faulttolerance.core.circuit.breaker.CircuitBreakerEvents;
import io.smallrye.faulttolerance.core.metrics.MetricsRecorder;
@Singleton
public class MicroProfileMetricsProvider implements MetricsProvider {
static final Metadata TIMEOUT_EXECUTION_DURATION_METADATA = Metadata.builder()
.withName(MetricConstants.TIMEOUT_EXECUTION_DURATION)
.withUnit(MetricUnits.NANOSECONDS)
.build();
static final Metadata BULKHEAD_RUNNING_DURATION_METADATA = Metadata.builder()
.withName(MetricConstants.BULKHEAD_RUNNING_DURATION)
.withUnit(MetricUnits.NANOSECONDS)
.build();
static final Metadata BULKHEAD_WAITING_DURATION_METADATA = Metadata.builder()
.withName(MetricConstants.BULKHEAD_WAITING_DURATION)
.withUnit(MetricUnits.NANOSECONDS)
.build();
static final Tag RESULT_VALUE_RETURNED = new Tag("result", "valueReturned");
static final Tag RESULT_EXCEPTION_THROWN = new Tag("result", "exceptionThrown");
static final Tag FALLBACK_APPLIED = new Tag("fallback", "applied");
static final Tag FALLBACK_NOT_APPLIED = new Tag("fallback", "notApplied");
static final Tag FALLBACK_NOT_DEFINED = new Tag("fallback", "notDefined");
static final Tag RETRIED_TRUE = new Tag("retried", "true");
static final Tag RETRIED_FALSE = new Tag("retried", "false");
static final Tag RETRY_RESULT_VALUE_RETURNED = new Tag("retryResult", "valueReturned");
static final Tag RETRY_RESULT_EXCEPTION_NOT_RETRYABLE = new Tag("retryResult", "exceptionNotRetryable");
static final Tag RETRY_RESULT_MAX_RETRIES_REACHED = new Tag("retryResult", "maxRetriesReached");
static final Tag RETRY_RESULT_MAX_DURATION_REACHED = new Tag("retryResult", "maxDurationReached");
static final Tag TIMED_OUT_TRUE = new Tag("timedOut", "true");
static final Tag TIMED_OUT_FALSE = new Tag("timedOut", "false");
static final Tag CIRCUIT_BREAKER_RESULT_SUCCESS = new Tag("circuitBreakerResult", "success");
static final Tag CIRCUIT_BREAKER_RESULT_FAILURE = new Tag("circuitBreakerResult", "failure");
static final Tag CIRCUIT_BREAKER_RESULT_CB_OPEN = new Tag("circuitBreakerResult", "circuitBreakerOpen");
static final Tag CIRCUIT_BREAKER_STATE_CLOSED = new Tag("state", "closed");
static final Tag CIRCUIT_BREAKER_STATE_OPEN = new Tag("state", "open");
static final Tag CIRCUIT_BREAKER_STATE_HALF_OPEN = new Tag("state", "halfOpen");
static final Tag BULKHEAD_RESULT_ACCEPTED = new Tag("bulkheadResult", "accepted");
static final Tag BULKHEAD_RESULT_REJECTED = new Tag("bulkheadResult", "rejected");
static final Tag RATE_LIMIT_RESULT_PERMITTED = new Tag("rateLimitResult", "permitted");
static final Tag RATE_LIMIT_RESULT_REJECTED = new Tag("rateLimitResult", "rejected");
@Inject
@RegistryType(type = MetricRegistry.Type.BASE)
MetricRegistry registry;
@Inject
@ConfigProperty(name = "MP_Fault_Tolerance_Metrics_Enabled", defaultValue = "true")
boolean metricsEnabled;
@Inject
SpecCompatibility specCompatibility;
public MetricsRecorder create(FaultToleranceOperation operation) {
if (metricsEnabled) {
return new MetricsRecorderImpl(registry, specCompatibility, operation);
} else {
return MetricsRecorder.NOOP;
}
}
public boolean isEnabled() {
return metricsEnabled;
}
private static class MetricsRecorderImpl implements MetricsRecorder {
private final MetricRegistry registry;
private final Tag methodTag;
MetricsRecorderImpl(MetricRegistry registry, SpecCompatibility specCompatibility, FaultToleranceOperation operation) {
this.registry = registry;
this.methodTag = new Tag("method", operation.getName());
registerMetrics(specCompatibility, operation);
}
private void registerMetrics(SpecCompatibility specCompatibility, FaultToleranceOperation operation) {
// make sure all applicable metrics for given method are registered eagerly
// we only touch counters and histograms, because gauges are registered eagerly otherwise
if (operation.hasFallback()) {
registry.counter(INVOCATIONS_TOTAL, methodTag, RESULT_VALUE_RETURNED, FALLBACK_NOT_APPLIED).getCount();
registry.counter(INVOCATIONS_TOTAL, methodTag, RESULT_VALUE_RETURNED, FALLBACK_APPLIED).getCount();
registry.counter(INVOCATIONS_TOTAL, methodTag, RESULT_EXCEPTION_THROWN, FALLBACK_NOT_APPLIED).getCount();
registry.counter(INVOCATIONS_TOTAL, methodTag, RESULT_EXCEPTION_THROWN, FALLBACK_APPLIED).getCount();
} else {
registry.counter(INVOCATIONS_TOTAL, methodTag, RESULT_VALUE_RETURNED, FALLBACK_NOT_DEFINED).getCount();
registry.counter(INVOCATIONS_TOTAL, methodTag, RESULT_EXCEPTION_THROWN, FALLBACK_NOT_DEFINED).getCount();
}
if (operation.hasRetry()) {
registry.counter(RETRY_RETRIES_TOTAL, methodTag).getCount();
registry.counter(RETRY_CALLS_TOTAL, methodTag, RETRIED_FALSE, RETRY_RESULT_VALUE_RETURNED).getCount();
registry.counter(RETRY_CALLS_TOTAL, methodTag, RETRIED_FALSE, RETRY_RESULT_EXCEPTION_NOT_RETRYABLE).getCount();
registry.counter(RETRY_CALLS_TOTAL, methodTag, RETRIED_FALSE, RETRY_RESULT_MAX_RETRIES_REACHED).getCount();
registry.counter(RETRY_CALLS_TOTAL, methodTag, RETRIED_FALSE, RETRY_RESULT_MAX_DURATION_REACHED).getCount();
registry.counter(RETRY_CALLS_TOTAL, methodTag, RETRIED_TRUE, RETRY_RESULT_VALUE_RETURNED).getCount();
registry.counter(RETRY_CALLS_TOTAL, methodTag, RETRIED_TRUE, RETRY_RESULT_EXCEPTION_NOT_RETRYABLE).getCount();
registry.counter(RETRY_CALLS_TOTAL, methodTag, RETRIED_TRUE, RETRY_RESULT_MAX_RETRIES_REACHED).getCount();
registry.counter(RETRY_CALLS_TOTAL, methodTag, RETRIED_TRUE, RETRY_RESULT_MAX_DURATION_REACHED).getCount();
}
if (operation.hasTimeout()) {
registry.counter(TIMEOUT_CALLS_TOTAL, methodTag, TIMED_OUT_TRUE).getCount();
registry.counter(TIMEOUT_CALLS_TOTAL, methodTag, TIMED_OUT_FALSE).getCount();
registry.histogram(TIMEOUT_EXECUTION_DURATION_METADATA, methodTag).getCount();
}
if (operation.hasCircuitBreaker()) {
registry.counter(CIRCUIT_BREAKER_CALLS_TOTAL, methodTag, CIRCUIT_BREAKER_RESULT_SUCCESS).getCount();
registry.counter(CIRCUIT_BREAKER_CALLS_TOTAL, methodTag, CIRCUIT_BREAKER_RESULT_FAILURE).getCount();
registry.counter(CIRCUIT_BREAKER_CALLS_TOTAL, methodTag, CIRCUIT_BREAKER_RESULT_CB_OPEN).getCount();
registry.counter(CIRCUIT_BREAKER_OPENED_TOTAL, methodTag).getCount();
}
if (operation.hasBulkhead()) {
registry.counter(BULKHEAD_CALLS_TOTAL, methodTag, BULKHEAD_RESULT_ACCEPTED).getCount();
registry.counter(BULKHEAD_CALLS_TOTAL, methodTag, BULKHEAD_RESULT_REJECTED).getCount();
registry.histogram(BULKHEAD_RUNNING_DURATION_METADATA, methodTag).getCount();
if (specCompatibility.isOperationTrulyOrPseudoAsynchronous(operation)) {
registry.histogram(BULKHEAD_WAITING_DURATION_METADATA, methodTag).getCount();
}
}
if (operation.hasRateLimit()) {
registry.counter(RATE_LIMIT_CALLS_TOTAL, methodTag, RATE_LIMIT_RESULT_PERMITTED).getCount();
registry.counter(RATE_LIMIT_CALLS_TOTAL, methodTag, RATE_LIMIT_RESULT_REJECTED).getCount();
}
}
private void registerGauge(BooleanSupplier supplier, String name, String unit, Tag... tags) {
registerGauge(() -> supplier.getAsBoolean() ? 1L : 0L, name, unit, tags);
}
private void registerGauge(LongSupplier supplier, String name, String unit, Tag... tags) {
Metadata metadata = Metadata.builder()
.withName(name)
.withUnit(unit)
.build();
registry.gauge(metadata, supplier::getAsLong, tags);
}
// ---
@Override
public void executionFinished(boolean succeeded, boolean fallbackDefined, boolean fallbackApplied) {
Tag resultTag = succeeded ? RESULT_VALUE_RETURNED : RESULT_EXCEPTION_THROWN;
Tag fallbackTag = fallbackDefined
? (fallbackApplied ? FALLBACK_APPLIED : FALLBACK_NOT_APPLIED)
: FALLBACK_NOT_DEFINED;
registry.counter(INVOCATIONS_TOTAL, methodTag, resultTag, fallbackTag).inc();
}
@Override
public void retryAttempted() {
registry.counter(RETRY_RETRIES_TOTAL, methodTag).inc();
}
@Override
public void retryValueReturned(boolean retried) {
registry.counter(RETRY_CALLS_TOTAL, methodTag, retried ? RETRIED_TRUE : RETRIED_FALSE,
RETRY_RESULT_VALUE_RETURNED).inc();
}
@Override
public void retryExceptionNotRetryable(boolean retried) {
registry.counter(RETRY_CALLS_TOTAL, methodTag, retried ? RETRIED_TRUE : RETRIED_FALSE,
RETRY_RESULT_EXCEPTION_NOT_RETRYABLE).inc();
}
@Override
public void retryMaxRetriesReached(boolean retried) {
registry.counter(RETRY_CALLS_TOTAL, methodTag, retried ? RETRIED_TRUE : RETRIED_FALSE,
RETRY_RESULT_MAX_RETRIES_REACHED).inc();
}
@Override
public void retryMaxDurationReached(boolean retried) {
registry.counter(RETRY_CALLS_TOTAL, methodTag, retried ? RETRIED_TRUE : RETRIED_FALSE,
RETRY_RESULT_MAX_DURATION_REACHED).inc();
}
@Override
public void timeoutFinished(boolean timedOut, long time) {
registry.counter(TIMEOUT_CALLS_TOTAL, methodTag, timedOut ? TIMED_OUT_TRUE : TIMED_OUT_FALSE).inc();
registry.histogram(TIMEOUT_EXECUTION_DURATION_METADATA, methodTag).update(time);
}
@Override
public void circuitBreakerFinished(CircuitBreakerEvents.Result result) {
Tag circuitBreakerResultTag = null;
switch (result) {
case SUCCESS:
circuitBreakerResultTag = CIRCUIT_BREAKER_RESULT_SUCCESS;
break;
case FAILURE:
circuitBreakerResultTag = CIRCUIT_BREAKER_RESULT_FAILURE;
break;
case PREVENTED:
circuitBreakerResultTag = CIRCUIT_BREAKER_RESULT_CB_OPEN;
break;
}
registry.counter(CIRCUIT_BREAKER_CALLS_TOTAL, methodTag, circuitBreakerResultTag).inc();
}
@Override
public void circuitBreakerMovedToOpen() {
registry.counter(CIRCUIT_BREAKER_OPENED_TOTAL, methodTag).inc();
}
@Override
public void registerCircuitBreakerIsClosed(BooleanSupplier supplier) {
registerGauge(supplier, CIRCUIT_BREAKER_STATE_CURRENT, MetricUnits.NONE,
methodTag, CIRCUIT_BREAKER_STATE_CLOSED);
}
@Override
public void registerCircuitBreakerIsOpen(BooleanSupplier supplier) {
registerGauge(supplier, CIRCUIT_BREAKER_STATE_CURRENT, MetricUnits.NONE,
methodTag, CIRCUIT_BREAKER_STATE_OPEN);
}
@Override
public void registerCircuitBreakerIsHalfOpen(BooleanSupplier supplier) {
registerGauge(supplier, CIRCUIT_BREAKER_STATE_CURRENT, MetricUnits.NONE,
methodTag, CIRCUIT_BREAKER_STATE_HALF_OPEN);
}
@Override
public void registerCircuitBreakerTimeSpentInClosed(LongSupplier supplier) {
registerGauge(supplier, CIRCUIT_BREAKER_STATE_TOTAL, MetricUnits.NANOSECONDS,
methodTag, CIRCUIT_BREAKER_STATE_CLOSED);
}
@Override
public void registerCircuitBreakerTimeSpentInOpen(LongSupplier supplier) {
registerGauge(supplier, CIRCUIT_BREAKER_STATE_TOTAL, MetricUnits.NANOSECONDS,
methodTag, CIRCUIT_BREAKER_STATE_OPEN);
}
@Override
public void registerCircuitBreakerTimeSpentInHalfOpen(LongSupplier supplier) {
registerGauge(supplier, CIRCUIT_BREAKER_STATE_TOTAL, MetricUnits.NANOSECONDS,
methodTag, CIRCUIT_BREAKER_STATE_HALF_OPEN);
}
@Override
public void bulkheadDecisionMade(boolean accepted) {
Tag bulkheadResultTag = accepted ? BULKHEAD_RESULT_ACCEPTED : BULKHEAD_RESULT_REJECTED;
registry.counter(BULKHEAD_CALLS_TOTAL, methodTag, bulkheadResultTag).inc();
}
@Override
public void registerBulkheadExecutionsRunning(LongSupplier supplier) {
registerGauge(supplier, BULKHEAD_EXECUTIONS_RUNNING, MetricUnits.NONE, methodTag);
}
@Override
public void registerBulkheadExecutionsWaiting(LongSupplier supplier) {
registerGauge(supplier, BULKHEAD_EXECUTIONS_WAITING, MetricUnits.NONE, methodTag);
}
@Override
public void updateBulkheadRunningDuration(long time) {
registry.histogram(BULKHEAD_RUNNING_DURATION_METADATA, methodTag).update(time);
}
@Override
public void updateBulkheadWaitingDuration(long time) {
registry.histogram(BULKHEAD_WAITING_DURATION_METADATA, methodTag).update(time);
}
@Override
public void rateLimitDecisionMade(boolean permitted) {
Tag rateLimitResultTag = permitted ? RATE_LIMIT_RESULT_PERMITTED : RATE_LIMIT_RESULT_REJECTED;
registry.counter(RATE_LIMIT_CALLS_TOTAL, methodTag, rateLimitResultTag).inc();
}
}
}