net.bull.javamelody.MonitoringSpringInterceptor.java Source code

Java tutorial

Introduction

Here is the source code for net.bull.javamelody.MonitoringSpringInterceptor.java

Source

/*
 * Copyright 2008-2014 by Emeric Vernat
 *
 *     This file is part of Java Melody.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.bull.javamelody;

import java.io.Serializable;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.support.AopUtils;

/**
 * Method interceptor that measures the duration of the intercepted call.
 *
 * Inspired by Erik van Oosten (Java Simon, Licence LGPL)
 * @author Emeric Vernat
 */
public class MonitoringSpringInterceptor implements MethodInterceptor, Serializable {
    private static final long serialVersionUID = -6594338383847482623L;
    private static final Counter SPRING_COUNTER = MonitoringProxy.getSpringCounter();
    private static final boolean COUNTER_HIDDEN = Parameters.isCounterHidden(SPRING_COUNTER.getName());
    private static final boolean DISABLED = Boolean.parseBoolean(Parameters.getParameter(Parameter.DISABLED));

    /**
     * Constructeur.
     */
    public MonitoringSpringInterceptor() {
        super();
        // quand cet intercepteur est utilis, le compteur est affich
        // sauf si le paramtre displayed-counters dit le contraire
        SPRING_COUNTER.setDisplayed(!COUNTER_HIDDEN);
        // setUsed(true) ncessaire ici si le contexte spring est initialis avant FilterContext
        // sinon les statistiques spring ne sont pas affiches
        SPRING_COUNTER.setUsed(true);
        LOG.debug("spring interceptor initialized");
    }

    /**
     * Performs method invocation.
     *
     * @param invocation method invocation
     * @return return object from the method
     * @throws Throwable anything thrown by the method
     */
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        // cette mthode est appele par spring aop
        if (DISABLED || !SPRING_COUNTER.isDisplayed()) {
            return invocation.proceed();
        }
        // nom identifiant la requte
        final String requestName = getRequestName(invocation);

        boolean systemError = false;
        try {
            SPRING_COUNTER.bindContextIncludingCpu(requestName);
            return invocation.proceed();
        } catch (final Error e) {
            // on catche Error pour avoir les erreurs systmes
            // mais pas Exception qui sont fonctionnelles en gnral
            systemError = true;
            throw e;
        } finally {
            // on enregistre la requte dans les statistiques
            SPRING_COUNTER.addRequestForCurrentContext(systemError);
        }
    }

    /**
     * Determine request name for a method invocation.
     *
     * @param invocation the method invocation (not null)
     * @return the request name for this invocation
     */
    protected String getRequestName(MethodInvocation invocation) {
        final String classPart = getClassPart(invocation);
        final String methodPart = getMethodPart(invocation);
        return classPart + '.' + methodPart;
    }

    private static String getClassPart(MethodInvocation invocation) {
        // si guice et pas Spring, alors remplacer AopUtils.getTargetClass() par getMethod().getDeclaringClass()
        // http://ninomartinez.wordpress.com/2010/05/14/guice-caching-interceptors/
        // (faire exemple avec un interceptor static)
        final Class<?> targetClass = AopUtils.getTargetClass(invocation.getThis());
        final MonitoredWithSpring classAnnotation = targetClass.getAnnotation(MonitoredWithSpring.class);
        if (classAnnotation == null || classAnnotation.name() == null || classAnnotation.name().length() == 0) {
            final Class<?> declaringClass = invocation.getMethod().getDeclaringClass();
            final MonitoredWithSpring declaringClassAnnotation = declaringClass
                    .getAnnotation(MonitoredWithSpring.class);
            if (declaringClassAnnotation == null || declaringClassAnnotation.name() == null
                    || declaringClassAnnotation.name().length() == 0) {
                return targetClass.getSimpleName();
            }
            return declaringClassAnnotation.name();
        }
        return classAnnotation.name();
    }

    private static String getMethodPart(MethodInvocation invocation) {
        final MonitoredWithSpring methodAnnotation = invocation.getMethod()
                .getAnnotation(MonitoredWithSpring.class);
        if (methodAnnotation == null || methodAnnotation.name() == null || methodAnnotation.name().length() == 0) {
            return invocation.getMethod().getName();
        }
        return methodAnnotation.name();
    }
}