001package org.javasimon.spring;
002
003import org.aopalliance.intercept.MethodInvocation;
004import org.javasimon.Manager;
005import org.javasimon.SimonManager;
006import org.javasimon.Split;
007import org.javasimon.source.MonitorSource;
008import org.javasimon.source.StopwatchSource;
009
010/**
011 * Method interceptor that measures the duration of the intercepted call with a Stopwatch and treats failure
012 * cases (exceptions) separately. By default exceptional flow reports to "stopwatch.failed" ({@link #EXCEPTION_TAG}),
013 * but setting
014 *
015 * @author <a href="mailto:virgo47@gmail.com">Richard "Virgo" Richter</a>
016 */
017public class MonitoringInterceptor extends BasicMonitoringInterceptor {
018
019        public static final String EXCEPTION_TAG = "failed";
020
021        private boolean tagByExceptionType;
022
023        /**
024         * Constructor with specified {@link MonitorSource}.
025         *
026         * @param stopwatchSource stopwatch provider for method invocation
027         */
028        public MonitoringInterceptor(StopwatchSource<MethodInvocation> stopwatchSource) {
029                super(stopwatchSource);
030        }
031
032        /** Constructor with specified {@link Manager}. */
033        public MonitoringInterceptor(Manager manager) {
034                super(new SpringStopwatchSource(manager));
035        }
036
037        /** Default constructor using {@link SimonManager#manager}. */
038        public MonitoringInterceptor() {
039                super(new SpringStopwatchSource(SimonManager.manager()));
040        }
041
042        /**
043         * Sets whether all exceptions should report to {@link #EXCEPTION_TAG} sub-simon or sub-simon for each
044         * exception type should be introduced (based on exception's simple name).
045         *
046         * @param tagByExceptionType {@code true} for fine grained exception-class-name-based sub-simons
047         */
048        public void setTagByExceptionType(boolean tagByExceptionType) {
049                this.tagByExceptionType = tagByExceptionType;
050        }
051
052        /**
053         * Method stops the split
054         *
055         * @param invocation method invocation
056         * @param split running split for this monitored action
057         * @return return object from the method
058         */
059        protected Object processInvoke(MethodInvocation invocation, Split split) throws Throwable {
060                try {
061                        return invocation.proceed();
062                } catch (Throwable t) {
063                        split.stop(tagByExceptionType ? t.getClass().getSimpleName() : EXCEPTION_TAG);
064                        throw t;
065                }
066        }
067}