001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018 package org.apache.commons.monitoring.aop; 019 020 import org.apache.commons.monitoring.Role; 021 import org.apache.commons.monitoring.counters.Counter; 022 import org.apache.commons.monitoring.repositories.Repository; 023 import org.apache.commons.monitoring.stopwatches.StopWatch; 024 025 import java.io.ByteArrayOutputStream; 026 import java.io.PrintStream; 027 import java.lang.reflect.Method; 028 029 /** 030 * A method interceptor that compute method invocation performances. 031 * <p/> 032 * Concrete implementation will adapt the method interception API to 033 * this class requirement. 034 * 035 * @author <a href="mailto:nicolas@apache.org">Nicolas De Loof</a> 036 */ 037 public abstract class AbstractPerformanceInterceptor<T> { 038 039 protected MonitorNameExtractor monitorNameExtractor; 040 041 public AbstractPerformanceInterceptor() { 042 setMonitorNameExtractor(DefaultMonitorNameExtractor.INSTANCE); 043 } 044 045 /** 046 * API neutral method invocation 047 */ 048 protected Object doInvoke(final T invocation) throws Throwable { 049 final String name = getCounterName(invocation); 050 if (name == null) { 051 return proceed(invocation); 052 } 053 054 final Counter monitor = Repository.INSTANCE.getCounter(new Counter.Key(Role.PERFORMANCES, name)); 055 final StopWatch stopwatch = Repository.INSTANCE.start(monitor); 056 Throwable error = null; 057 try { 058 return proceed(invocation); 059 } catch (final Throwable t) { 060 error = t; 061 throw t; 062 } finally { 063 stopwatch.stop(); 064 if (error != null) { 065 final ByteArrayOutputStream writer = new ByteArrayOutputStream(); 066 error.printStackTrace(new PrintStream(writer)); 067 Repository.INSTANCE.getCounter(new Counter.Key(Role.FAILURES, writer.toString())).add(stopwatch.getElapsedTime()); 068 } 069 } 070 } 071 072 protected abstract Object proceed(T invocation) throws Throwable; 073 074 protected abstract String getCounterName(T invocation); 075 076 /** 077 * Compute the counter name associated to this method invocation 078 * 079 * @param method method being invoked 080 * @return counter name. If <code>null</code>, nothing will be monitored 081 */ 082 protected String getCounterName(final Object instance, final Method method) { 083 return monitorNameExtractor.getMonitorName(instance, method); 084 } 085 086 public void setMonitorNameExtractor(final MonitorNameExtractor monitorNameExtractor) { 087 this.monitorNameExtractor = monitorNameExtractor; 088 } 089 }