Search in sources :

Example 1 with Timeout

use of io.helidon.faulttolerance.Timeout in project helidon by oracle.

the class MethodInvoker method updateMetricsAfter.

/**
 * Update metrics after method is called and depending on outcome.
 *
 * @param cause Mapped cause or {@code null} if successful.
 */
private void updateMetricsAfter(Throwable cause) {
    if (!isFaultToleranceMetricsEnabled()) {
        return;
    }
    methodState.lock.lock();
    try {
        // Calculate execution time
        long executionTime = System.nanoTime() - handlerStartNanos;
        // Retries
        if (introspector.hasRetry()) {
            long retryCounter = methodState.retry.retryCounter();
            boolean wasRetried = retryCounter > 0;
            Counter retryRetriesTotal = RetryRetriesTotal.get(introspector.getMethodNameTag());
            // Update retry counter
            if (wasRetried) {
                retryRetriesTotal.inc(retryCounter);
            }
            // Update retry metrics based on outcome
            if (cause == null) {
                RetryCallsTotal.get(introspector.getMethodNameTag(), wasRetried ? RetryRetried.TRUE.get() : RetryRetried.FALSE.get(), RetryResult.VALUE_RETURNED.get()).inc();
            } else if (cause instanceof RetryTimeoutException) {
                RetryCallsTotal.get(introspector.getMethodNameTag(), wasRetried ? RetryRetried.TRUE.get() : RetryRetried.FALSE.get(), RetryResult.MAX_DURATION_REACHED.get()).inc();
            } else {
                // Exception thrown but not RetryTimeoutException
                int maxRetries = introspector.getRetry().maxRetries();
                if (maxRetries == -1) {
                    maxRetries = Integer.MAX_VALUE;
                }
                if (retryCounter == maxRetries) {
                    RetryCallsTotal.get(introspector.getMethodNameTag(), wasRetried ? RetryRetried.TRUE.get() : RetryRetried.FALSE.get(), RetryResult.MAX_RETRIES_REACHED.get()).inc();
                } else if (retryCounter < maxRetries) {
                    RetryCallsTotal.get(introspector.getMethodNameTag(), wasRetried ? RetryRetried.TRUE.get() : RetryRetried.FALSE.get(), RetryResult.EXCEPTION_NOT_RETRYABLE.get()).inc();
                }
            }
        }
        // Timeout
        if (introspector.hasTimeout()) {
            if (cause instanceof org.eclipse.microprofile.faulttolerance.exceptions.TimeoutException) {
                TimeoutCallsTotal.get(introspector.getMethodNameTag(), TimeoutTimedOut.TRUE.get()).inc();
            } else {
                TimeoutCallsTotal.get(introspector.getMethodNameTag(), TimeoutTimedOut.FALSE.get()).inc();
            }
            TimeoutExecutionDuration.get(introspector.getMethodNameTag()).update(executionTime);
        }
        // CircuitBreaker
        if (introspector.hasCircuitBreaker()) {
            Objects.requireNonNull(methodState.breaker);
            if (methodState.lastBreakerState == State.OPEN) {
                CircuitBreakerCallsTotal.get(introspector.getMethodNameTag(), CircuitBreakerResult.CIRCUIT_BREAKER_OPEN.get()).inc();
            } else if (methodState.breaker.state() == State.OPEN) {
                // closed -> open
                CircuitBreakerOpenedTotal.get(introspector.getMethodNameTag()).inc();
            }
            if (cause == null) {
                CircuitBreakerCallsTotal.get(introspector.getMethodNameTag(), CircuitBreakerResult.SUCCESS.get()).inc();
            } else if (!(cause instanceof CircuitBreakerOpenException)) {
                boolean skipOnThrowable = Arrays.stream(introspector.getCircuitBreaker().skipOn()).anyMatch(c -> c.isAssignableFrom(cause.getClass()));
                boolean failOnThrowable = Arrays.stream(introspector.getCircuitBreaker().failOn()).anyMatch(c -> c.isAssignableFrom(cause.getClass()));
                if (skipOnThrowable || !failOnThrowable) {
                    CircuitBreakerCallsTotal.get(introspector.getMethodNameTag(), CircuitBreakerResult.SUCCESS.get()).inc();
                } else {
                    CircuitBreakerCallsTotal.get(introspector.getMethodNameTag(), CircuitBreakerResult.FAILURE.get()).inc();
                }
            }
            // Update times for gauges
            switch(methodState.lastBreakerState) {
                case OPEN:
                    methodState.breakerTimerOpen += System.nanoTime() - methodState.startNanos;
                    break;
                case CLOSED:
                    methodState.breakerTimerClosed += System.nanoTime() - methodState.startNanos;
                    break;
                case HALF_OPEN:
                    methodState.breakerTimerHalfOpen += System.nanoTime() - methodState.startNanos;
                    break;
                default:
                    throw new IllegalStateException("Unknown breaker state " + methodState.lastBreakerState);
            }
            // Update internal state
            methodState.lastBreakerState = methodState.breaker.state();
            methodState.startNanos = System.nanoTime();
        }
        // Bulkhead
        if (introspector.hasBulkhead()) {
            Objects.requireNonNull(methodState.bulkhead);
            Bulkhead.Stats stats = methodState.bulkhead.stats();
            Counter bulkheadAccepted = BulkheadCallsTotal.get(introspector.getMethodNameTag(), BulkheadResult.ACCEPTED.get());
            if (stats.callsAccepted() > bulkheadAccepted.getCount()) {
                bulkheadAccepted.inc(stats.callsAccepted() - bulkheadAccepted.getCount());
            }
            Counter bulkheadRejected = BulkheadCallsTotal.get(introspector.getMethodNameTag(), BulkheadResult.REJECTED.get());
            if (stats.callsRejected() > bulkheadRejected.getCount()) {
                bulkheadRejected.inc(stats.callsRejected() - bulkheadRejected.getCount());
            }
            // Update histograms if task accepted
            if (!(cause instanceof BulkheadException)) {
                long waitingTime = invocationStartNanos - handlerStartNanos;
                BulkheadRunningDuration.get(introspector.getMethodNameTag()).update(executionTime - waitingTime);
                if (introspector.isAsynchronous()) {
                    BulkheadWaitingDuration.get(introspector.getMethodNameTag()).update(waitingTime);
                }
            }
        }
        // Global method counters
        if (cause == null) {
            InvocationsTotal.get(introspector.getMethodNameTag(), VALUE_RETURNED.get(), introspector.getFallbackTag(fallbackCalled.get())).inc();
        } else {
            InvocationsTotal.get(introspector.getMethodNameTag(), EXCEPTION_THROWN.get(), introspector.getFallbackTag(fallbackCalled.get())).inc();
        }
    } finally {
        methodState.lock.unlock();
    }
}
Also used : Arrays(java.util.Arrays) InvocationsTotal(io.helidon.microprofile.faulttolerance.FaultToleranceMetrics.InvocationsTotal) VALUE_RETURNED(io.helidon.microprofile.faulttolerance.FaultToleranceMetrics.InvocationResult.VALUE_RETURNED) BulkheadExecutionsRunning(io.helidon.microprofile.faulttolerance.FaultToleranceMetrics.BulkheadExecutionsRunning) Retry(io.helidon.faulttolerance.Retry) Future(java.util.concurrent.Future) Duration(java.time.Duration) State(io.helidon.faulttolerance.CircuitBreaker.State) BulkheadExecutionsWaiting(io.helidon.microprofile.faulttolerance.FaultToleranceMetrics.BulkheadExecutionsWaiting) CircuitBreakerResult(io.helidon.microprofile.faulttolerance.FaultToleranceMetrics.CircuitBreakerResult) Method(java.lang.reflect.Method) Bulkhead(io.helidon.faulttolerance.Bulkhead) FaultTolerance(io.helidon.faulttolerance.FaultTolerance) FaultToleranceExtension.isFaultToleranceMetricsEnabled(io.helidon.microprofile.faulttolerance.FaultToleranceExtension.isFaultToleranceMetricsEnabled) CancellationException(java.util.concurrent.CancellationException) RetryRetriesTotal(io.helidon.microprofile.faulttolerance.FaultToleranceMetrics.RetryRetriesTotal) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) CircuitBreakerOpenException(org.eclipse.microprofile.faulttolerance.exceptions.CircuitBreakerOpenException) ThrowableMapper.mapTypes(io.helidon.microprofile.faulttolerance.ThrowableMapper.mapTypes) Objects(java.util.Objects) CompletionStage(java.util.concurrent.CompletionStage) ThrowableMapper.map(io.helidon.microprofile.faulttolerance.ThrowableMapper.map) RetryTimeoutException(io.helidon.faulttolerance.RetryTimeoutException) BulkheadException(org.eclipse.microprofile.faulttolerance.exceptions.BulkheadException) CircuitBreakerOpenedTotal(io.helidon.microprofile.faulttolerance.FaultToleranceMetrics.CircuitBreakerOpenedTotal) TimeoutCallsTotal(io.helidon.microprofile.faulttolerance.FaultToleranceMetrics.TimeoutCallsTotal) CircuitBreakerStateTotal(io.helidon.microprofile.faulttolerance.FaultToleranceMetrics.CircuitBreakerStateTotal) CircuitBreaker(io.helidon.faulttolerance.CircuitBreaker) Context(io.helidon.common.context.Context) CircuitBreakerCallsTotal(io.helidon.microprofile.faulttolerance.FaultToleranceMetrics.CircuitBreakerCallsTotal) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) CompletableFuture(java.util.concurrent.CompletableFuture) InvocationContext(jakarta.interceptor.InvocationContext) CircuitBreakerState(io.helidon.microprofile.faulttolerance.FaultToleranceMetrics.CircuitBreakerState) Supplier(java.util.function.Supplier) TimeoutTimedOut(io.helidon.microprofile.faulttolerance.FaultToleranceMetrics.TimeoutTimedOut) Fallback(io.helidon.faulttolerance.Fallback) Counter(org.eclipse.microprofile.metrics.Counter) BulkheadCallsTotal(io.helidon.microprofile.faulttolerance.FaultToleranceMetrics.BulkheadCallsTotal) BulkheadResult(io.helidon.microprofile.faulttolerance.FaultToleranceMetrics.BulkheadResult) Single(io.helidon.common.reactive.Single) FtHandlerTyped(io.helidon.faulttolerance.FtHandlerTyped) BulkheadWaitingDuration(io.helidon.microprofile.faulttolerance.FaultToleranceMetrics.BulkheadWaitingDuration) RetryCallsTotal(io.helidon.microprofile.faulttolerance.FaultToleranceMetrics.RetryCallsTotal) Timeout(io.helidon.faulttolerance.Timeout) ReentrantLock(java.util.concurrent.locks.ReentrantLock) RetryRetried(io.helidon.microprofile.faulttolerance.FaultToleranceMetrics.RetryRetried) RetryResult(io.helidon.microprofile.faulttolerance.FaultToleranceMetrics.RetryResult) Contexts(io.helidon.common.context.Contexts) EXCEPTION_THROWN(io.helidon.microprofile.faulttolerance.FaultToleranceMetrics.InvocationResult.EXCEPTION_THROWN) ExecutionException(java.util.concurrent.ExecutionException) TimeUnit(java.util.concurrent.TimeUnit) TimeoutExecutionDuration(io.helidon.microprofile.faulttolerance.FaultToleranceMetrics.TimeoutExecutionDuration) BulkheadRunningDuration(io.helidon.microprofile.faulttolerance.FaultToleranceMetrics.BulkheadRunningDuration) Async(io.helidon.faulttolerance.Async) RetryTimeoutException(io.helidon.faulttolerance.RetryTimeoutException) CircuitBreakerOpenException(org.eclipse.microprofile.faulttolerance.exceptions.CircuitBreakerOpenException) Counter(org.eclipse.microprofile.metrics.Counter) Bulkhead(io.helidon.faulttolerance.Bulkhead) BulkheadException(org.eclipse.microprofile.faulttolerance.exceptions.BulkheadException) RetryTimeoutException(io.helidon.faulttolerance.RetryTimeoutException)

Aggregations

Context (io.helidon.common.context.Context)1 Contexts (io.helidon.common.context.Contexts)1 Single (io.helidon.common.reactive.Single)1 Async (io.helidon.faulttolerance.Async)1 Bulkhead (io.helidon.faulttolerance.Bulkhead)1 CircuitBreaker (io.helidon.faulttolerance.CircuitBreaker)1 State (io.helidon.faulttolerance.CircuitBreaker.State)1 Fallback (io.helidon.faulttolerance.Fallback)1 FaultTolerance (io.helidon.faulttolerance.FaultTolerance)1 FtHandlerTyped (io.helidon.faulttolerance.FtHandlerTyped)1 Retry (io.helidon.faulttolerance.Retry)1 RetryTimeoutException (io.helidon.faulttolerance.RetryTimeoutException)1 Timeout (io.helidon.faulttolerance.Timeout)1 FaultToleranceExtension.isFaultToleranceMetricsEnabled (io.helidon.microprofile.faulttolerance.FaultToleranceExtension.isFaultToleranceMetricsEnabled)1 BulkheadCallsTotal (io.helidon.microprofile.faulttolerance.FaultToleranceMetrics.BulkheadCallsTotal)1 BulkheadExecutionsRunning (io.helidon.microprofile.faulttolerance.FaultToleranceMetrics.BulkheadExecutionsRunning)1 BulkheadExecutionsWaiting (io.helidon.microprofile.faulttolerance.FaultToleranceMetrics.BulkheadExecutionsWaiting)1 BulkheadResult (io.helidon.microprofile.faulttolerance.FaultToleranceMetrics.BulkheadResult)1 BulkheadRunningDuration (io.helidon.microprofile.faulttolerance.FaultToleranceMetrics.BulkheadRunningDuration)1 BulkheadWaitingDuration (io.helidon.microprofile.faulttolerance.FaultToleranceMetrics.BulkheadWaitingDuration)1