1   package com.atlassian.performance;
2   
3   import org.aopalliance.intercept.MethodInterceptor;
4   import org.aopalliance.intercept.MethodInvocation;
5   import org.slf4j.Logger;
6   import org.slf4j.LoggerFactory;
7   import org.slf4j.MarkerFactory;
8   import org.slf4j.Marker;
9   
10  import java.lang.reflect.Method;
11  import java.util.Iterator;
12  
13  public class TimeMethodInterceptor implements MethodInterceptor
14  {
15      private static final String PERF_MARKER_TOKEN = "com.atlassian.performance.TestMarker";
16  
17      Logger log = LoggerFactory.getLogger("com.atlassian.performance.");
18  
19      public Object invoke(MethodInvocation invocation) throws Throwable {
20  	TimedMethodInvocation tmi = new TimedMethodInvocation(invocation);
21  	EventTime et = EventTime.timeEvent(eventKey(invocation), false, tmi);
22  	
23  	if(et.getTime() > 1) {
24  	    log.debug(MarkerFactory.getMarker(PERF_MARKER_TOKEN),
25  		      "{}, {}", new Object[]{argsToString(invocation.getArguments()), et.getTime()});
26  	}
27  
28  	if(tmi.throwable == null) {
29  	    return tmi.val;
30  	} else {
31  	    throw tmi.throwable;
32  	}
33      }
34  
35      private static String eventKey(MethodInvocation invocation)
36      {
37  	return trimMethod(invocation.getMethod()) + " " + argsToString(invocation.getArguments());
38      }
39  
40      private static String trimMethod(Method method) {
41  	String rawMethStr =  method.toString();
42  	int methodStart = rawMethStr.lastIndexOf(" ");
43  	if(methodStart > -1) 
44  	{
45  	    return rawMethStr.substring(methodStart);
46  	} else {
47  	    return rawMethStr;
48  	}
49      }
50      
51      private static String argsToString(Object[] args) 
52      {
53  	StringBuffer buf = new StringBuffer();
54  	for(Object arg : args) 
55  	{
56  	    buf.append(arg);
57  	    buf.append("*");
58  	}
59  	return buf.toString();
60      }
61  	    
62  
63      public class TimedMethodInvocation implements EventTime.TimedEvent
64      {
65          Object val;
66          Throwable throwable;
67          MethodInvocation invocation;
68  
69          TimedMethodInvocation(MethodInvocation invocation)
70          {
71              this.invocation = invocation;
72          }
73  
74          public boolean run()
75          {
76              try
77              {
78                  val = invocation.proceed();
79              }
80              catch (Throwable t)
81              {
82                  throwable = t;
83              }
84              finally
85              {
86                  return true;
87              }
88          }
89  
90      }
91  
92  }