1 package org.apache.fulcrum.yaafi.interceptor.performance;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.lang.reflect.Method;
23
24 import org.apache.avalon.framework.configuration.Configuration;
25 import org.apache.avalon.framework.configuration.ConfigurationException;
26 import org.apache.avalon.framework.configuration.Reconfigurable;
27 import org.apache.avalon.framework.context.Contextualizable;
28 import org.apache.avalon.framework.thread.ThreadSafe;
29 import org.apache.fulcrum.yaafi.framework.interceptor.AvalonInterceptorContext;
30 import org.apache.fulcrum.yaafi.interceptor.baseservice.BaseInterceptorServiceImpl;
31 import org.apache.fulcrum.yaafi.interceptor.util.ArgumentToStringBuilderImpl;
32 import org.apache.fulcrum.yaafi.interceptor.util.MethodToStringBuilderImpl;
33 import org.apache.fulcrum.yaafi.interceptor.util.StopWatch;
34
35 /**
36 * A service logging the execution time of service invocations.
37 *
38 * @author <a href="mailto:siegfried.goeschl@it20one.at">Siegfried Goeschl</a>
39 */
40
41 public class PerformanceInterceptorServiceImpl
42 extends BaseInterceptorServiceImpl
43 implements PerformanceInterceptorService, Reconfigurable, Contextualizable, ThreadSafe
44 {
45 /** the maximum length of a dumped argument */
46 private static final int MAX_ARG_LENGTH = 100;
47
48 /** default length of the StringBuffer */
49 private static final int BUFFER_LENGTH = 2000;
50
51 /** seperator for the arguments in the logfile */
52 private static final String SEPERATOR = ";";
53
54 /** the tresholds in milliseconds to determine the loglevel */
55 private int[] tresholdList;
56
57 /** maximum argument length for dumping arguments */
58 private int maxArgLength;
59
60
61
62
63
64 /**
65 * Constructor
66 */
67 public PerformanceInterceptorServiceImpl()
68 {
69 super();
70 this.tresholdList = new int[5];
71 }
72
73 /**
74 * @see org.apache.avalon.framework.configuration.Configurable#configure(org.apache.avalon.framework.configuration.Configuration)
75 */
76 public void configure(Configuration configuration) throws ConfigurationException
77 {
78 super.configure(configuration);
79
80 this.maxArgLength = configuration.getChild("maxArgLength").getValueAsInteger(MAX_ARG_LENGTH);
81 Configuration tresholdConfiguration = configuration.getChild("tresholds");
82 this.tresholdList[0] = tresholdConfiguration.getChild("fatal").getAttributeAsInteger("millis", 5000);
83 this.tresholdList[1] = tresholdConfiguration.getChild("error").getAttributeAsInteger("millis", 1000);
84 this.tresholdList[2] = tresholdConfiguration.getChild("warn").getAttributeAsInteger("millis", 500);
85 this.tresholdList[3] = tresholdConfiguration.getChild("info").getAttributeAsInteger("millis", 100);
86 this.tresholdList[4] = tresholdConfiguration.getChild("debug").getAttributeAsInteger("millis", 10);
87 }
88
89 /**
90 * @see org.apache.avalon.framework.configuration.Reconfigurable#reconfigure(org.apache.avalon.framework.configuration.Configuration)
91 */
92 public void reconfigure(Configuration configuration) throws ConfigurationException
93 {
94 super.reconfigure(configuration);
95 this.configure(configuration);
96 }
97
98
99
100
101
102 /**
103 * @see org.apache.fulcrum.yaafi.framework.interceptor.AvalonInterceptorService#onEntry(org.apache.fulcrum.yaafi.framework.interceptor.AvalonInterceptorContext)
104 */
105 public void onEntry(AvalonInterceptorContext interceptorContext)
106 {
107 if( this.isServiceMonitored(interceptorContext ) )
108 {
109 this.createStopWatch(interceptorContext);
110 }
111 }
112
113 /**
114 * @see org.apache.fulcrum.yaafi.framework.interceptor.AvalonInterceptorService#onError(org.apache.fulcrum.yaafi.framework.interceptor.AvalonInterceptorContext, java.lang.Throwable)
115 */
116 public void onError(AvalonInterceptorContext interceptorContext,Throwable t)
117 {
118 if( this.isServiceMonitored(interceptorContext) )
119 {
120 StopWatch stopWatch = this.getStopWatch(interceptorContext);
121 stopWatch.stop();
122 this.log( ON_ERROR, interceptorContext, stopWatch );
123 }
124 }
125
126 /**
127 * @see org.apache.fulcrum.yaafi.framework.interceptor.AvalonInterceptorService#onExit(org.apache.fulcrum.yaafi.framework.interceptor.AvalonInterceptorContext, java.lang.Object)
128 */
129 public void onExit(AvalonInterceptorContext interceptorContext, Object result)
130 {
131 if( this.isServiceMonitored(interceptorContext) )
132 {
133 if( this.isServiceMonitored(interceptorContext) )
134 {
135 StopWatch stopWatch = this.getStopWatch(interceptorContext);
136 stopWatch.stop();
137 this.log( ON_EXIT, interceptorContext, stopWatch );
138 }
139 }
140 }
141
142
143
144
145
146 /**
147 * Creates a stop watch
148 *
149 * @param interceptorContext the current interceptor context
150 */
151 protected void createStopWatch(
152 AvalonInterceptorContext interceptorContext )
153 {
154 StopWatch stopWatch = new StopWatch();
155 stopWatch.start();
156 interceptorContext.getRequestContext().put(this.getServiceName(),stopWatch);
157 }
158
159 /**
160 * Gets the stop watch
161 *
162 * @param interceptorContext the current interceptor context
163 * @return the stop watch
164 */
165 protected StopWatch getStopWatch(
166 AvalonInterceptorContext interceptorContext )
167 {
168 return (StopWatch) interceptorContext.getRequestContext().remove(
169 this.getServiceName()
170 );
171 }
172
173 /**
174 * Logs the execution time.
175 *
176 * @param mode the invocation mode (onEntry, onExit, onError)
177 * @param interceptorContext the current interceptor context
178 * @param stopWatch the stop watch
179 */
180 protected void log(
181 int mode,
182 AvalonInterceptorContext interceptorContext,
183 StopWatch stopWatch
184 )
185 {
186 String msg = null;
187 long time = stopWatch.getTime();
188
189 if( time >= tresholdList[0] )
190 {
191 if( this.getLogger().isFatalErrorEnabled() )
192 {
193 msg = this.toString(interceptorContext,stopWatch,mode);
194 this.getLogger().fatalError(msg);
195 }
196 }
197 else if( time >= tresholdList[1] )
198 {
199 if( this.getLogger().isErrorEnabled() )
200 {
201 msg = this.toString(interceptorContext,stopWatch,mode);
202 this.getLogger().error(msg);
203 }
204 }
205 else if( time >= tresholdList[2] )
206 {
207 if( this.getLogger().isWarnEnabled() )
208 {
209 msg = this.toString(interceptorContext,stopWatch,mode);
210 this.getLogger().warn(msg);
211 }
212 }
213 else if( time >= tresholdList[3] )
214 {
215 if( this.getLogger().isInfoEnabled() )
216 {
217 msg = this.toString(interceptorContext,stopWatch,mode);
218 this.getLogger().info(msg);
219 }
220 }
221 else if( time >= tresholdList[4] )
222 {
223 if( this.getLogger().isDebugEnabled() )
224 {
225 msg = this.toString(interceptorContext,stopWatch,mode);
226 this.getLogger().debug(msg);
227 }
228 }
229 }
230
231 /**
232 * Create the log message for the performance logfile.
233 *
234 * @param interceptorContext the context
235 * @param stopWatch the stopwatch
236 * @param mode the mode (onEntry, onExit, onError)
237 * @return the log message
238 */
239 protected String toString(
240 AvalonInterceptorContext interceptorContext,
241 StopWatch stopWatch,
242 int mode
243 )
244 {
245 Method method = interceptorContext.getMethod();
246 Object[] args = interceptorContext.getArgs();
247 MethodToStringBuilderImpl methodToStringBuilder = new MethodToStringBuilderImpl(method);
248 StringBuffer result = new StringBuffer(BUFFER_LENGTH);
249
250 result.append(interceptorContext.getTransactionId());
251 result.append(SEPERATOR);
252 result.append(interceptorContext.getInvocationId());
253 result.append(SEPERATOR);
254 result.append(interceptorContext.getInvocationDepth());
255 result.append(SEPERATOR);
256 result.append(mode);
257 result.append(SEPERATOR);
258 result.append(interceptorContext.getServiceShorthand());
259 result.append(SEPERATOR);
260 result.append(method.getName());
261 result.append(SEPERATOR);
262 result.append(stopWatch.getTime());
263 result.append(SEPERATOR);
264 result.append(methodToStringBuilder.toString());
265 result.append(SEPERATOR);
266 result.append(this.toString(args));
267
268 return result.toString();
269 }
270
271 /**
272 * Prints the argument list.
273 *
274 * @return the debug output
275 */
276 protected String toString( Object[] args )
277 {
278 StringBuffer result = new StringBuffer();
279 ArgumentToStringBuilderImpl toStringBuilder = null;
280
281 if( args == null )
282 {
283 args = new Object[0];
284 }
285
286 for( int i=0; i<args.length; i++ )
287 {
288 toStringBuilder = new ArgumentToStringBuilderImpl(args[i],this.maxArgLength,1);
289 result.append("arg[" + i + "]:={");
290 result.append( toStringBuilder.toString());
291 result.append("}");
292
293 if( i<args.length-1)
294 {
295 result.append(SEPERATOR);
296 }
297 }
298
299 return result.toString();
300 }
301
302 }