Search in sources :

Example 1 with RequestTraceSpan

use of fish.payara.notification.requesttracing.RequestTraceSpan in project Payara by payara.

the class StandardWrapper method constructWebServiceRequestSpan.

// END IASRI 4665318
private RequestTraceSpan constructWebServiceRequestSpan(HttpServletRequest httpServletRequest) {
    RequestTraceSpan span = new RequestTraceSpan("processWebserviceRequest");
    span.addSpanTag("URL", httpServletRequest.getRequestURL().toString());
    Enumeration<String> headerNames = httpServletRequest.getHeaderNames();
    while (headerNames.hasMoreElements()) {
        String headerName = headerNames.nextElement();
        span.addSpanTag(headerName, list(httpServletRequest.getHeaders(headerName)).toString());
    }
    span.addSpanTag("Method", httpServletRequest.getMethod());
    return span;
}
Also used : RequestTraceSpan(fish.payara.notification.requesttracing.RequestTraceSpan)

Example 2 with RequestTraceSpan

use of fish.payara.notification.requesttracing.RequestTraceSpan in project Payara by payara.

the class BulkheadInterceptor method bulkhead.

/**
 * Proceeds the context under Bulkhead semantics.
 * @param invocationContext The context to proceed.
 * @return The outcome of the invocationContext
 * @throws Exception
 */
private Object bulkhead(InvocationContext invocationContext) throws Exception {
    Object proceededInvocationContext = null;
    FaultToleranceService faultToleranceService = Globals.getDefaultBaseServiceLocator().getService(FaultToleranceService.class);
    Bulkhead bulkhead = FaultToleranceCdiUtils.getAnnotation(beanManager, Bulkhead.class, invocationContext);
    Config config = null;
    try {
        config = ConfigProvider.getConfig();
    } catch (IllegalArgumentException ex) {
        logger.log(Level.INFO, "No config could be found", ex);
    }
    int value = (Integer) FaultToleranceCdiUtils.getOverrideValue(config, Bulkhead.class, "value", invocationContext, Integer.class).orElse(bulkhead.value());
    int waitingTaskQueue = (Integer) FaultToleranceCdiUtils.getOverrideValue(config, Bulkhead.class, "waitingTaskQueue", invocationContext, Integer.class).orElse(bulkhead.waitingTaskQueue());
    InvocationManager invocationManager = Globals.getDefaultBaseServiceLocator().getService(InvocationManager.class);
    String appName = faultToleranceService.getApplicationName(invocationManager, invocationContext);
    Semaphore bulkheadExecutionSemaphore = faultToleranceService.getBulkheadExecutionSemaphore(appName, invocationContext.getMethod(), value);
    // If the Asynchronous annotation is present, use threadpool style, otherwise use semaphore style
    if (FaultToleranceCdiUtils.getAnnotation(beanManager, Asynchronous.class, invocationContext) != null) {
        Semaphore bulkheadExecutionQueueSemaphore = faultToleranceService.getBulkheadExecutionQueueSemaphore(appName, invocationContext.getMethod(), waitingTaskQueue);
        // Check if there are any free permits for concurrent execution
        if (!bulkheadExecutionSemaphore.tryAcquire(0, TimeUnit.SECONDS)) {
            logger.log(Level.FINER, "Attempting to acquire bulkhead queue semaphore.");
            // If there aren't any free permits, see if there are any free queue permits
            if (bulkheadExecutionQueueSemaphore.tryAcquire(0, TimeUnit.SECONDS)) {
                logger.log(Level.FINER, "Acquired bulkhead queue semaphore.");
                // If there is a free queue permit, queue for an executor permit
                try {
                    logger.log(Level.FINER, "Attempting to acquire bulkhead execution semaphore.");
                    faultToleranceService.startFaultToleranceSpan(new RequestTraceSpan("obtainBulkheadSemaphore"), invocationManager, invocationContext);
                    try {
                        bulkheadExecutionSemaphore.acquire();
                    } finally {
                        // Make sure we end the trace right here
                        faultToleranceService.endFaultToleranceSpan();
                    }
                    logger.log(Level.FINER, "Acquired bulkhead queue semaphore.");
                    // Release the queue permit
                    bulkheadExecutionQueueSemaphore.release();
                    // Proceed the invocation and wait for the response
                    try {
                        logger.log(Level.FINER, "Proceeding bulkhead context");
                        proceededInvocationContext = invocationContext.proceed();
                    } catch (Exception ex) {
                        logger.log(Level.FINE, "Exception proceeding Bulkhead context", ex);
                        // Generic catch, as we need to release the semaphore permits
                        bulkheadExecutionSemaphore.release();
                        bulkheadExecutionQueueSemaphore.release();
                        // Let the exception propagate further up - we just want to release the semaphores
                        throw ex;
                    }
                    // Release the execution permit
                    bulkheadExecutionSemaphore.release();
                } catch (InterruptedException ex) {
                    logger.log(Level.INFO, "Interrupted acquiring bulkhead semaphore", ex);
                    throw new BulkheadException(ex);
                }
            } else {
                throw new BulkheadException("No free work or queue permits.");
            }
        } else {
            // Proceed the invocation and wait for the response
            try {
                logger.log(Level.FINER, "Proceeding bulkhead context");
                proceededInvocationContext = invocationContext.proceed();
            } catch (Exception ex) {
                logger.log(Level.FINE, "Exception proceeding Bulkhead context", ex);
                // Generic catch, as we need to release the semaphore permits
                bulkheadExecutionSemaphore.release();
                // Let the exception propagate further up - we just want to release the semaphores
                throw ex;
            }
            // Release the permit
            bulkheadExecutionSemaphore.release();
        }
    } else {
        // Try to get an execution permit
        if (bulkheadExecutionSemaphore.tryAcquire(0, TimeUnit.SECONDS)) {
            // Proceed the invocation and wait for the response
            try {
                logger.log(Level.FINER, "Proceeding bulkhead context");
                proceededInvocationContext = invocationContext.proceed();
            } catch (Exception ex) {
                logger.log(Level.FINE, "Exception proceeding Bulkhead context", ex);
                // Generic catch, as we need to release the semaphore permits
                bulkheadExecutionSemaphore.release();
                // Let the exception propagate further up - we just want to release the semaphores
                throw ex;
            }
            // Release the permit
            bulkheadExecutionSemaphore.release();
        } else {
            throw new BulkheadException("No free work permits.");
        }
    }
    return proceededInvocationContext;
}
Also used : Asynchronous(org.eclipse.microprofile.faulttolerance.Asynchronous) Config(org.eclipse.microprofile.config.Config) InvocationManager(org.glassfish.api.invocation.InvocationManager) RequestTraceSpan(fish.payara.notification.requesttracing.RequestTraceSpan) Semaphore(java.util.concurrent.Semaphore) FaultToleranceService(fish.payara.microprofile.faulttolerance.FaultToleranceService) BulkheadException(org.eclipse.microprofile.faulttolerance.exceptions.BulkheadException) Bulkhead(org.eclipse.microprofile.faulttolerance.Bulkhead) BulkheadException(org.eclipse.microprofile.faulttolerance.exceptions.BulkheadException)

Example 3 with RequestTraceSpan

use of fish.payara.notification.requesttracing.RequestTraceSpan in project Payara by payara.

the class RetryInterceptor method retry.

/**
 * Proceeds the given invocation context with Retry semantics.
 * @param invocationContext The invocation context to proceed
 * @return The proceeded invocation context
 * @throws Exception If the invocation throws an exception that shouldn't be retried, or if all retry attempts are
 * expended
 */
private Object retry(InvocationContext invocationContext) throws Exception {
    Object proceededInvocationContext = null;
    Retry retry = FaultToleranceCdiUtils.getAnnotation(beanManager, Retry.class, invocationContext);
    FaultToleranceService faultToleranceService = Globals.getDefaultBaseServiceLocator().getService(FaultToleranceService.class);
    InvocationManager invocationManager = Globals.getDefaultBaseServiceLocator().getService(InvocationManager.class);
    try {
        proceededInvocationContext = invocationContext.proceed();
    } catch (Exception ex) {
        Config config = null;
        try {
            config = ConfigProvider.getConfig();
        } catch (IllegalArgumentException iae) {
            logger.log(Level.INFO, "No config could be found", ex);
        }
        Class<? extends Throwable>[] retryOn = retry.retryOn();
        try {
            String retryOnString = ((String) FaultToleranceCdiUtils.getOverrideValue(config, Retry.class, "retryOn", invocationContext, String.class).get());
            List<Class> classList = new ArrayList<>();
            // Remove any curly or square brackets from the string, as well as any spaces and ".class"es
            for (String className : retryOnString.replaceAll("[\\{\\[ \\]\\}]", "").replaceAll("\\.class", "").split(",")) {
                classList.add(Class.forName(className));
            }
            retryOn = classList.toArray(retryOn);
        } catch (NoSuchElementException nsee) {
            logger.log(Level.FINER, "Could not find element in config", nsee);
        } catch (ClassNotFoundException cnfe) {
            logger.log(Level.INFO, "Could not find class from retryOn config, defaulting to annotation. " + "Make sure you give the full canonical class name.", cnfe);
        }
        Class<? extends Throwable>[] abortOn = retry.abortOn();
        try {
            String abortOnString = (String) FaultToleranceCdiUtils.getOverrideValue(config, Retry.class, "abortOn", invocationContext, String.class).get();
            List<Class> classList = new ArrayList<>();
            // Remove any curly or square brackets from the string, as well as any spaces and ".class"es
            for (String className : abortOnString.replaceAll("[\\{\\[ \\]\\}]", "").replaceAll("\\.class", "").split(",")) {
                classList.add(Class.forName(className));
            }
            abortOn = classList.toArray(abortOn);
        } catch (NoSuchElementException nsee) {
            logger.log(Level.FINER, "Could not find element in config", nsee);
        } catch (ClassNotFoundException cnfe) {
            logger.log(Level.INFO, "Could not find class from abortOn config, defaulting to annotation. " + "Make sure you give the full canonical class name.", cnfe);
        }
        if (!shouldRetry(retryOn, abortOn, ex)) {
            logger.log(Level.FINE, "Exception is contained in retryOn or abortOn, not retrying.", ex);
            throw ex;
        }
        int maxRetries = (Integer) FaultToleranceCdiUtils.getOverrideValue(config, Retry.class, "maxRetries", invocationContext, Integer.class).orElse(retry.maxRetries());
        long delay = (Long) FaultToleranceCdiUtils.getOverrideValue(config, Retry.class, "delay", invocationContext, Long.class).orElse(retry.delay());
        ChronoUnit delayUnit = (ChronoUnit) FaultToleranceCdiUtils.getOverrideValue(config, Retry.class, "delayUnit", invocationContext, ChronoUnit.class).orElse(retry.delayUnit());
        long maxDuration = (Long) FaultToleranceCdiUtils.getOverrideValue(config, Retry.class, "maxDuration", invocationContext, Long.class).orElse(retry.maxDuration());
        ChronoUnit durationUnit = (ChronoUnit) FaultToleranceCdiUtils.getOverrideValue(config, Retry.class, "durationUnit", invocationContext, ChronoUnit.class).orElse(retry.durationUnit());
        long jitter = (Long) FaultToleranceCdiUtils.getOverrideValue(config, Retry.class, "jitter", invocationContext, Long.class).orElse(retry.jitter());
        ChronoUnit jitterDelayUnit = (ChronoUnit) FaultToleranceCdiUtils.getOverrideValue(config, Retry.class, "jitterDelayUnit", invocationContext, ChronoUnit.class).orElse(retry.jitterDelayUnit());
        long delayMillis = Duration.of(delay, delayUnit).toMillis();
        long jitterMillis = Duration.of(jitter, jitterDelayUnit).toMillis();
        long timeoutTime = System.currentTimeMillis() + Duration.of(maxDuration, durationUnit).toMillis();
        Exception retryException = ex;
        faultToleranceService.startFaultToleranceSpan(new RequestTraceSpan("retryMethod"), invocationManager, invocationContext);
        try {
            if (maxRetries == -1 && maxDuration > 0) {
                logger.log(Level.FINER, "Retrying until maxDuration is breached.");
                while (System.currentTimeMillis() < timeoutTime) {
                    try {
                        proceededInvocationContext = invocationContext.proceed();
                        break;
                    } catch (Exception caughtException) {
                        retryException = caughtException;
                        if (!shouldRetry(retryOn, abortOn, caughtException)) {
                            break;
                        }
                        if (delayMillis > 0 || jitterMillis > 0) {
                            faultToleranceService.startFaultToleranceSpan(new RequestTraceSpan("delayRetry"), invocationManager, invocationContext);
                            try {
                                Thread.sleep(delayMillis + ThreadLocalRandom.current().nextLong(0, jitterMillis));
                            } finally {
                                faultToleranceService.endFaultToleranceSpan();
                            }
                        }
                    }
                }
            } else if (maxRetries == -1 && maxDuration == 0) {
                logger.log(Level.INFO, "Retrying potentially forever!");
                while (true) {
                    try {
                        proceededInvocationContext = invocationContext.proceed();
                        break;
                    } catch (Exception caughtException) {
                        retryException = caughtException;
                        if (!shouldRetry(retryOn, abortOn, caughtException)) {
                            break;
                        }
                        if (delayMillis > 0 || jitterMillis > 0) {
                            faultToleranceService.startFaultToleranceSpan(new RequestTraceSpan("delayRetry"), invocationManager, invocationContext);
                            try {
                                Thread.sleep(delayMillis + ThreadLocalRandom.current().nextLong(0, jitterMillis));
                            } finally {
                                faultToleranceService.endFaultToleranceSpan();
                            }
                        }
                    }
                }
            } else if (maxRetries != -1 && maxDuration > 0) {
                logger.log(Level.INFO, "Retrying as long as maxDuration ({0}ms) isn''t breached, and no more than {1} times", new Object[] { Duration.of(maxDuration, durationUnit).toMillis(), maxRetries });
                while (maxRetries > 0 && System.currentTimeMillis() < timeoutTime) {
                    try {
                        proceededInvocationContext = invocationContext.proceed();
                        break;
                    } catch (Exception caughtException) {
                        retryException = caughtException;
                        if (!shouldRetry(retryOn, abortOn, caughtException)) {
                            break;
                        }
                        if (delayMillis > 0 || jitterMillis > 0) {
                            faultToleranceService.startFaultToleranceSpan(new RequestTraceSpan("delayRetry"), invocationManager, invocationContext);
                            try {
                                Thread.sleep(delayMillis + ThreadLocalRandom.current().nextLong(0, jitterMillis));
                            } finally {
                                faultToleranceService.endFaultToleranceSpan();
                            }
                        }
                        maxRetries--;
                    }
                }
            } else {
                logger.log(Level.INFO, "Retrying no more than {0} times", maxRetries);
                while (maxRetries > 0) {
                    try {
                        proceededInvocationContext = invocationContext.proceed();
                        break;
                    } catch (Exception caughtException) {
                        retryException = caughtException;
                        if (!shouldRetry(retryOn, abortOn, caughtException)) {
                            break;
                        }
                        if (delayMillis > 0 || jitterMillis > 0) {
                            faultToleranceService.startFaultToleranceSpan(new RequestTraceSpan("delayRetry"), invocationManager, invocationContext);
                            try {
                                Thread.sleep(delayMillis + ThreadLocalRandom.current().nextLong(0, jitterMillis));
                            } finally {
                                faultToleranceService.endFaultToleranceSpan();
                            }
                        }
                        maxRetries--;
                    }
                }
            }
        } finally {
            faultToleranceService.endFaultToleranceSpan();
        }
        if (proceededInvocationContext == null) {
            throw retryException;
        }
    }
    return proceededInvocationContext;
}
Also used : Config(org.eclipse.microprofile.config.Config) InvocationManager(org.glassfish.api.invocation.InvocationManager) RequestTraceSpan(fish.payara.notification.requesttracing.RequestTraceSpan) FaultToleranceService(fish.payara.microprofile.faulttolerance.FaultToleranceService) NoSuchElementException(java.util.NoSuchElementException) ArrayList(java.util.ArrayList) List(java.util.List) Retry(org.eclipse.microprofile.faulttolerance.Retry) NoSuchElementException(java.util.NoSuchElementException) ChronoUnit(java.time.temporal.ChronoUnit)

Example 4 with RequestTraceSpan

use of fish.payara.notification.requesttracing.RequestTraceSpan in project Payara by payara.

the class ContextSetupProviderImpl method constructConcurrentContextSpan.

private RequestTraceSpan constructConcurrentContextSpan(ComponentInvocation invocation) {
    RequestTraceSpan span = new RequestTraceSpan(EventType.TRACE_START, "executeConcurrentContext");
    span.addSpanTag("App Name", invocation.getAppName());
    span.addSpanTag("Component ID", invocation.getComponentId());
    span.addSpanTag("Module Name", invocation.getModuleName());
    Object instance = invocation.getInstance();
    if (instance != null) {
        span.addSpanTag("Class Name", instance.getClass().getName());
    }
    span.addSpanTag("Thread Name", Thread.currentThread().getName());
    return span;
}
Also used : RequestTraceSpan(fish.payara.notification.requesttracing.RequestTraceSpan)

Example 5 with RequestTraceSpan

use of fish.payara.notification.requesttracing.RequestTraceSpan in project Payara by payara.

the class ContextSetupProviderImpl method setup.

@Override
public ContextHandle setup(ContextHandle contextHandle) throws IllegalStateException {
    if (!(contextHandle instanceof InvocationContext)) {
        logger.log(Level.SEVERE, LogFacade.UNKNOWN_CONTEXT_HANDLE);
        return null;
    }
    InvocationContext handle = (InvocationContext) contextHandle;
    String appName = null;
    if (handle.getInvocation() != null) {
        appName = handle.getInvocation().getAppName();
    }
    if (appName == null && handle.getInvocation().getJNDIEnvironment() != null) {
        appName = DOLUtils.getApplicationFromEnv((JndiNameEnvironment) handle.getInvocation().getJNDIEnvironment()).getName();
    }
    ClassLoader backupClassLoader = null;
    if (appName == null) {
        // try to get environment from component ID
        if (handle.getInvocation().getComponentId() != null && compEnvMgr != null) {
            JndiNameEnvironment currJndiEnv = compEnvMgr.getJndiNameEnvironment(handle.getInvocation().getComponentId());
            if (currJndiEnv != null) {
                com.sun.enterprise.deployment.Application appInfo = DOLUtils.getApplicationFromEnv(currJndiEnv);
                if (appInfo != null) {
                    appName = appInfo.getName();
                    // cache JNDI environment
                    handle.getInvocation().setJNDIEnvironment(currJndiEnv);
                    backupClassLoader = appInfo.getClassLoader();
                }
            }
        }
    }
    // Check whether the application component submitting the task is still running. Throw IllegalStateException if not.
    if (!isApplicationEnabled(appName)) {
        throw new IllegalStateException("Module " + appName + " is disabled");
    }
    ClassLoader resetClassLoader = null;
    SecurityContext resetSecurityContext = null;
    if (handle.getContextClassLoader() != null) {
        resetClassLoader = Utility.setContextClassLoader(handle.getContextClassLoader());
    } else if (backupClassLoader != null) {
        resetClassLoader = Utility.setContextClassLoader(backupClassLoader);
    }
    if (handle.getSecurityContext() != null) {
        resetSecurityContext = SecurityContext.getCurrent();
        SecurityContext.setCurrent(handle.getSecurityContext());
    }
    ComponentInvocation invocation = handle.getInvocation();
    if (invocation != null && !handle.isUseTransactionOfExecutionThread()) {
        // Each invocation needs a ResourceTableKey that returns a unique hashCode for TransactionManager
        invocation.setResourceTableKey(new PairKey(invocation.getInstance(), Thread.currentThread()));
        invocationManager.preInvoke(invocation);
    }
    // Ensure that there is no existing transaction in the current thread
    if (transactionManager != null) {
        transactionManager.clearThreadTx();
    }
    if (requestTracing != null && requestTracing.isRequestTracingEnabled()) {
        RequestTraceSpan span = constructConcurrentContextSpan(invocation);
        requestTracing.startTrace(span);
    }
    if (stuckThreads != null) {
        stuckThreads.registerThread(Thread.currentThread().getId());
    }
    return new InvocationContext(invocation, resetClassLoader, resetSecurityContext, handle.isUseTransactionOfExecutionThread());
}
Also used : JndiNameEnvironment(com.sun.enterprise.deployment.JndiNameEnvironment) ComponentInvocation(org.glassfish.api.invocation.ComponentInvocation) SecurityContext(com.sun.enterprise.security.SecurityContext) RequestTraceSpan(fish.payara.notification.requesttracing.RequestTraceSpan)

Aggregations

RequestTraceSpan (fish.payara.notification.requesttracing.RequestTraceSpan)30 Test (org.junit.Test)13 FaultToleranceService (fish.payara.microprofile.faulttolerance.FaultToleranceService)3 RequestTrace (fish.payara.notification.requesttracing.RequestTrace)3 UUID (java.util.UUID)3 InvocationManager (org.glassfish.api.invocation.InvocationManager)3 Principal (java.security.Principal)2 ServletException (javax.servlet.ServletException)2 Config (org.eclipse.microprofile.config.Config)2 Endpoint (org.glassfish.webservices.monitoring.Endpoint)2 JndiNameEnvironment (com.sun.enterprise.deployment.JndiNameEnvironment)1 WebServiceEndpoint (com.sun.enterprise.deployment.WebServiceEndpoint)1 SecurityContext (com.sun.enterprise.security.SecurityContext)1 WebPrincipal (com.sun.enterprise.security.web.integration.WebPrincipal)1 ServletAdapter (com.sun.xml.ws.transport.http.servlet.ServletAdapter)1 RequestTracingService (fish.payara.nucleus.requesttracing.RequestTracingService)1 IOException (java.io.IOException)1 StringReader (java.io.StringReader)1 URL (java.net.URL)1 ChronoUnit (java.time.temporal.ChronoUnit)1