View Javadoc

1   package org.apache.fulcrum.yaafi.interceptor.performance;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
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      // Avalon Service Lifecycle Implementation
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      // Service interface implementation
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     // Service Implementation
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 }