All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.glassfish.jersey.server.internal.monitoring.MonitoringEventListener Maven / Gradle / Ivy

Go to download

A bundle project producing JAX-RS RI bundles. The primary artifact is an "all-in-one" OSGi-fied JAX-RS RI bundle (jaxrs-ri.jar). Attached to that are two compressed JAX-RS RI archives. The first archive (jaxrs-ri.zip) consists of binary RI bits and contains the API jar (under "api" directory), RI libraries (under "lib" directory) as well as all external RI dependencies (under "ext" directory). The secondary archive (jaxrs-ri-src.zip) contains buildable JAX-RS RI source bundle and contains the API jar (under "api" directory), RI sources (under "src" directory) as well as all external RI dependencies (under "ext" directory). The second archive also contains "build.xml" ANT script that builds the RI sources. To build the JAX-RS RI simply unzip the archive, cd to the created jaxrs-ri directory and invoke "ant" from the command line.

There is a newer version: 3.1.6
Show newest version
/*
 * Copyright (c) 2013, 2020 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package org.glassfish.jersey.server.internal.monitoring;

import java.util.Collections;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;

import jakarta.ws.rs.ProcessingException;

import jakarta.annotation.Priority;
import jakarta.inject.Inject;

import org.glassfish.jersey.internal.inject.InjectionManager;
import org.glassfish.jersey.server.internal.LocalizationMessages;
import org.glassfish.jersey.server.model.ResourceMethod;
import org.glassfish.jersey.server.monitoring.ApplicationEvent;
import org.glassfish.jersey.server.monitoring.ApplicationEventListener;
import org.glassfish.jersey.server.monitoring.DestroyListener;
import org.glassfish.jersey.server.monitoring.RequestEvent;
import org.glassfish.jersey.server.monitoring.RequestEventListener;
import org.glassfish.jersey.uri.UriTemplate;

/**
 * {@link ApplicationEventListener application event listener} that listens to {@link ApplicationEvent application}
 * and {@link RequestEvent request} events and supplies data to {@link MonitoringStatisticsProcessor} which
 * produces {@link org.glassfish.jersey.server.monitoring.MonitoringStatistics monitoring statistics}.
 * 

* The {@link MonitoringStatisticsProcessor} is started by this class after the first application event * comes. *

*

* This event listener must be registered as a standard provider when monitoring statistics are required * in the runtime. *

* * @author Miroslav Fuksa * @see MonitoringStatisticsProcessor */ @Priority(ApplicationInfoListener.PRIORITY + 100) public final class MonitoringEventListener implements ApplicationEventListener { private static final Logger LOGGER = Logger.getLogger(MonitoringEventListener.class.getName()); private static final int EVENT_QUEUE_SIZE = 500_000; @Inject private InjectionManager injectionManager; private final Queue requestQueuedItems = new ArrayBlockingQueue<>(EVENT_QUEUE_SIZE); private final Queue responseStatuses = new ArrayBlockingQueue<>(EVENT_QUEUE_SIZE); private final Queue exceptionMapperEvents = new ArrayBlockingQueue<>(EVENT_QUEUE_SIZE); private volatile MonitoringStatisticsProcessor monitoringStatisticsProcessor; /** * Time statistics. */ static class TimeStats { private final long duration; private final long startTime; private TimeStats(final long startTime, final long requestDuration) { this.duration = requestDuration; this.startTime = startTime; } /** * Get duration. * * @return Duration in milliseconds. */ long getDuration() { return duration; } /** * Get start time. * * @return Start time (Unix timestamp format). */ long getStartTime() { return startTime; } } /** * Method statistics. */ static class MethodStats extends TimeStats { private final ResourceMethod method; private MethodStats(final ResourceMethod method, final long startTime, final long requestDuration) { super(startTime, requestDuration); this.method = method; } /** * Get the resource method executed. * * @return resource method. */ ResourceMethod getMethod() { return method; } } /** * Request statistics. */ static class RequestStats { private final TimeStats requestStats; private final MethodStats methodStats; // might be null if a method was not executed during a request private final String requestUri; private RequestStats(final TimeStats requestStats, final MethodStats methodStats, final String requestUri) { this.requestStats = requestStats; this.methodStats = methodStats; this.requestUri = requestUri; } /** * Get request statistics. * * @return request statistics. */ TimeStats getRequestStats() { return requestStats; } /** * Get method statistics. * * @return method statistics. */ MethodStats getMethodStats() { return methodStats; } /** * Get the request uri. * * @return request uri. */ String getRequestUri() { return requestUri; } } @Override public ReqEventListener onRequest(final RequestEvent requestEvent) { switch (requestEvent.getType()) { case START: return new ReqEventListener(); } return null; } @Override public void onEvent(final ApplicationEvent event) { final ApplicationEvent.Type type = event.getType(); switch (type) { case INITIALIZATION_START: break; case RELOAD_FINISHED: case INITIALIZATION_FINISHED: this.monitoringStatisticsProcessor = new MonitoringStatisticsProcessor(injectionManager, this); this.monitoringStatisticsProcessor.startMonitoringWorker(); break; case DESTROY_FINISHED: if (monitoringStatisticsProcessor != null) { try { monitoringStatisticsProcessor.shutDown(); } catch (final InterruptedException e) { Thread.currentThread().interrupt(); throw new ProcessingException(LocalizationMessages.ERROR_MONITORING_SHUTDOWN_INTERRUPTED(), e); } } // onDestroy final List listeners = injectionManager.getAllInstances(DestroyListener.class); for (final DestroyListener listener : listeners) { try { listener.onDestroy(); } catch (final Exception e) { LOGGER.log(Level.WARNING, LocalizationMessages.ERROR_MONITORING_STATISTICS_LISTENER_DESTROY(listener.getClass()), e); } } break; } } private class ReqEventListener implements RequestEventListener { private final long requestTimeStart; private volatile long methodTimeStart; private volatile MethodStats methodStats; public ReqEventListener() { this.requestTimeStart = System.currentTimeMillis(); } @Override public void onEvent(final RequestEvent event) { final long now = System.currentTimeMillis(); switch (event.getType()) { case RESOURCE_METHOD_START: this.methodTimeStart = now; break; case RESOURCE_METHOD_FINISHED: final ResourceMethod method = event.getUriInfo().getMatchedResourceMethod(); methodStats = new MethodStats(method, methodTimeStart, now - methodTimeStart); break; case EXCEPTION_MAPPING_FINISHED: if (!exceptionMapperEvents.offer(event)) { LOGGER.warning(LocalizationMessages.ERROR_MONITORING_QUEUE_MAPPER()); } break; case FINISHED: if (event.isResponseWritten()) { if (!responseStatuses.offer(event.getContainerResponse().getStatus())) { LOGGER.warning(LocalizationMessages.ERROR_MONITORING_QUEUE_RESPONSE()); } } final StringBuilder sb = new StringBuilder(); final List orderedTemplates = event.getUriInfo().getMatchedTemplates() .stream() .collect(Collectors.collectingAndThen(Collectors.toList(), uriTemplates -> { Collections.reverse(uriTemplates); return uriTemplates; })); for (final UriTemplate uriTemplate : orderedTemplates) { sb.append(uriTemplate.getTemplate()); if (!uriTemplate.endsWithSlash()) { sb.append("/"); } sb.setLength(sb.length() - 1); } if (!requestQueuedItems.offer(new RequestStats(new TimeStats(requestTimeStart, now - requestTimeStart), methodStats, sb.toString()))) { LOGGER.warning(LocalizationMessages.ERROR_MONITORING_QUEUE_REQUEST()); } } } } /** * Get the exception mapper event queue. * * @return Exception mapper event queue. */ Queue getExceptionMapperEvents() { return exceptionMapperEvents; } /** * Get the request event queue. * * @return Request event queue. */ Queue getRequestQueuedItems() { return requestQueuedItems; } /** * Get the queue with response status codes. * * @return response status queue. */ Queue getResponseStatuses() { return responseStatuses; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy