View Javadoc

1   // ========================================================================
2   // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd.
3   // ------------------------------------------------------------------------
4   // All rights reserved. This program and the accompanying materials
5   // are made available under the terms of the Eclipse Public License v1.0
6   // and Apache License v2.0 which accompanies this distribution.
7   // The Eclipse Public License is available at 
8   // http://www.eclipse.org/legal/epl-v10.html
9   // The Apache License v2.0 is available at
10  // http://www.opensource.org/licenses/apache2.0.php
11  // You may elect to redistribute this code under either of these licenses. 
12  // ========================================================================
13  
14  package org.eclipse.jetty.server.handler;
15  
16  import java.io.IOException;
17  
18  import javax.servlet.ServletException;
19  import javax.servlet.http.HttpServletRequest;
20  import javax.servlet.http.HttpServletResponse;
21  
22  import org.eclipse.jetty.server.AsyncContinuation;
23  import org.eclipse.jetty.server.HttpConnection;
24  import org.eclipse.jetty.server.Request;
25  import org.eclipse.jetty.server.Response;
26  import org.eclipse.jetty.util.LazyList;
27  
28  public class StatisticsHandler extends HandlerWrapper implements CompleteHandler
29  {
30      transient long _statsStartedAt;
31      
32      transient int _requests;
33      
34      transient long _requestsDurationMin;         // min request duration
35      transient long _requestsDurationMax;         // max request duration
36      transient long _requestsDurationTotal;       // total request duration
37      transient long _requestsActiveDurationMin;   // min request active duration
38      transient long _requestsActiveDurationMax;   // max request active duration
39      transient long _requestsActiveDurationTotal; // total request active duration
40      
41      transient int _requestsActive;
42      transient int _requestsActiveMin;            // min number of connections handled simultaneously
43      transient int _requestsActiveMax;
44      transient int _requestsResumed;
45      transient int _requestsTimedout;             // requests that timed out while suspended
46      transient int _responses1xx; // Informal
47      transient int _responses2xx; // Success
48      transient int _responses3xx; // Redirection
49      transient int _responses4xx; // Client Error
50      transient int _responses5xx; // Server Error
51      
52      transient long _responsesBytesTotal;
53         
54      /* ------------------------------------------------------------ */
55      public void statsReset()
56      {
57          synchronized(this)
58          {
59              if (isStarted())
60                  _statsStartedAt=System.currentTimeMillis();
61              _requests=0;
62              _responses1xx=0;
63              _responses2xx=0;
64              _responses3xx=0;
65              _responses4xx=0;
66              _responses5xx=0;
67            
68              _requestsActiveMin=_requestsActive;
69              _requestsActiveMax=_requestsActive;
70  
71              _requestsDurationMin=0;
72              _requestsDurationMax=0;
73              _requestsDurationTotal=0;
74              
75              _requestsActiveDurationMin=0;
76              _requestsActiveDurationMax=0;
77              _requestsActiveDurationTotal=0;
78          }
79      }
80  
81  
82      /* ------------------------------------------------------------ */
83      public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
84      {
85          final Response base_response=baseRequest.getResponse();
86          
87          long timestamp0=baseRequest.getTimeStamp();
88          long timestamp1=timestamp0;
89          try
90          {
91              AsyncContinuation asyncContextState=baseRequest.getAsyncContinuation();
92              synchronized(this)
93              {
94                  if(asyncContextState==null)
95                  {
96                      _requests++;
97                  }
98                  else
99                  {
100                     if(asyncContextState.isInitial())
101                         _requests++;
102                     else
103                     {
104                         timestamp1=System.currentTimeMillis();
105                         /*
106                         if (asyncContextState.isTimeout())
107                             _requestsTimedout++;
108                         if(asyncContextState.isResumed())
109                             _requestsResumed++;
110                         */
111                     }
112                 }
113 
114                 _requestsActive++;
115                 if (_requestsActive>_requestsActiveMax)
116                     _requestsActiveMax=_requestsActive;
117             }
118             
119             super.handle(target, baseRequest, request, response);
120         }
121         finally
122         {
123             synchronized(this)
124             {
125                 _requestsActive--;
126                 if (_requestsActive<0)
127                     _requestsActive=0;
128                 if (_requestsActive < _requestsActiveMin)
129                     _requestsActiveMin=_requestsActive;
130 
131                 long duration = System.currentTimeMillis()-timestamp1;
132                 _requestsActiveDurationTotal+=duration;
133                 if (_requestsActiveDurationMin==0 || duration<_requestsActiveDurationMin)
134                     _requestsActiveDurationMin=duration;
135                 if (duration>_requestsActiveDurationMax)
136                     _requestsActiveDurationMax=duration;
137 
138                 
139                 if(baseRequest.isAsyncStarted())
140                 {
141                     Object list = baseRequest.getAttribute(COMPLETE_HANDLER_ATTR);
142                     baseRequest.setAttribute(COMPLETE_HANDLER_ATTR, LazyList.add(list, this));
143                 }
144                 else
145                 {
146                     duration = System.currentTimeMillis()-timestamp0;                    
147                     addRequestsDurationTotal(duration);
148                     
149                     switch(base_response.getStatus()/100)
150                     {
151                         case 1: _responses1xx++;break;
152                         case 2: _responses2xx++;break;
153                         case 3: _responses3xx++;break;
154                         case 4: _responses4xx++;break;
155                         case 5: _responses5xx++;break;
156                     }
157                     
158                     _responsesBytesTotal += base_response.getContentCount();
159                 }                                            
160             }
161         }
162     }
163 
164     /* ------------------------------------------------------------ */
165     protected void doStart() throws Exception
166     {
167         super.doStart();
168         _statsStartedAt=System.currentTimeMillis();
169     }
170 
171     /* ------------------------------------------------------------ */
172     protected void doStop() throws Exception
173     {
174         super.doStop();
175     }
176     
177     /* ------------------------------------------------------------ */
178     /**
179      * @return Get the number of requests handled by this context
180      * since last call of statsReset(), not counting resumed requests.
181      * If setStatsOn(false) then this is undefined.
182      */
183     public int getRequests() {return _requests;}
184 
185     /* ------------------------------------------------------------ */
186     /**
187      * @return Number of requests currently active.
188      * Undefined if setStatsOn(false).
189      */
190     public int getRequestsActive() {return _requestsActive;}
191 
192     /* ------------------------------------------------------------ */
193     /**
194      * @return Number of requests that have been resumed.
195      * Undefined if setStatsOn(false).
196      */
197     public int getRequestsResumed() {return _requestsResumed;}
198 
199     /* ------------------------------------------------------------ */
200     /**
201      * @return Number of requests that timed out while suspended.
202      * Undefined if setStatsOn(false).
203      */
204     public int getRequestsTimedout() {return _requestsTimedout;}
205 
206     /* ------------------------------------------------------------ */
207     /**
208      * @return Maximum number of active requests
209      * since statsReset() called. Undefined if setStatsOn(false).
210      */
211     public int getRequestsActiveMax() {return _requestsActiveMax;}
212 
213     /* ------------------------------------------------------------ */
214     /**
215      * @return Get the number of responses with a 2xx status returned
216      * by this context since last call of statsReset(). Undefined if
217      * if setStatsOn(false).
218      */
219     public int getResponses1xx() {return _responses1xx;}
220 
221     /* ------------------------------------------------------------ */
222     /**
223      * @return Get the number of responses with a 100 status returned
224      * by this context since last call of statsReset(). Undefined if
225      * if setStatsOn(false).
226      */
227     public int getResponses2xx() {return _responses2xx;}
228 
229     /* ------------------------------------------------------------ */
230     /**
231      * @return Get the number of responses with a 3xx status returned
232      * by this context since last call of statsReset(). Undefined if
233      * if setStatsOn(false).
234      */
235     public int getResponses3xx() {return _responses3xx;}
236 
237     /* ------------------------------------------------------------ */
238     /**
239      * @return Get the number of responses with a 4xx status returned
240      * by this context since last call of statsReset(). Undefined if
241      * if setStatsOn(false).
242      */
243     public int getResponses4xx() {return _responses4xx;}
244 
245     /* ------------------------------------------------------------ */
246     /**
247      * @return Get the number of responses with a 5xx status returned
248      * by this context since last call of statsReset(). Undefined if
249      * if setStatsOn(false).
250      */
251     public int getResponses5xx() {return _responses5xx;}
252 
253     /* ------------------------------------------------------------ */
254     /** 
255      * @return Timestamp stats were started at.
256      */
257     public long getStatsOnMs()
258     {
259         return System.currentTimeMillis()-_statsStartedAt;
260     }
261 
262     /* ------------------------------------------------------------ */
263     /**
264      * @return Returns the requestsActiveMin.
265      */
266     public int getRequestsActiveMin()
267     {
268         return _requestsActiveMin;
269     }
270 
271     /* ------------------------------------------------------------ */
272     /**
273      * @return Returns the requestsDurationMin.
274      */
275     public long getRequestsDurationMin()
276     {
277         return _requestsDurationMin;
278     }
279 
280     /* ------------------------------------------------------------ */
281     /**
282      * @return Returns the requestsDurationTotal.
283      */
284     public long getRequestsDurationTotal()
285     {
286         return _requestsDurationTotal;
287     }
288 
289     /* ------------------------------------------------------------ */
290     /** 
291      * @return Average duration of request handling in milliseconds 
292      * since statsReset() called. Undefined if setStatsOn(false).
293      */
294     public long getRequestsDurationAve() {return _requests==0?0:(_requestsDurationTotal/_requests);}
295 
296     /* ------------------------------------------------------------ */
297     /** 
298      * @return Get maximum duration in milliseconds of request handling
299      * since statsReset() called. Undefined if setStatsOn(false).
300      */
301     public long getRequestsDurationMax() {return _requestsDurationMax;}
302     
303     /* ------------------------------------------------------------ */
304     /**
305      * @return Returns the requestsActiveDurationMin.
306      */
307     public long getRequestsActiveDurationMin()
308     {
309         return _requestsActiveDurationMin;
310     }
311 
312     /* ------------------------------------------------------------ */
313     /**
314      * @return Returns the requestsActiveDurationTotal.
315      */
316     public long getRequestsActiveDurationTotal()
317     {
318         return _requestsActiveDurationTotal;
319     }
320 
321     /* ------------------------------------------------------------ */
322     /** 
323      * @return Average duration of request handling in milliseconds 
324      * since statsReset() called. Undefined if setStatsOn(false).
325      */
326     public long getRequestsActiveDurationAve() {return _requests==0?0:(_requestsActiveDurationTotal/_requests);}
327 
328     /* ------------------------------------------------------------ */
329     /** 
330      * @return Get maximum duration in milliseconds of request handling
331      * since statsReset() called. Undefined if setStatsOn(false).
332      */
333     public long getRequestsActiveDurationMax() {return _requestsActiveDurationMax;}
334     
335     /* ------------------------------------------------------------ */
336     /** 
337      * @return Total bytes of content sent in responses
338      */
339     public long getResponsesBytesTotal() {return _responsesBytesTotal; }
340     
341     private void addRequestsDurationTotal(long duration) 
342     {
343         synchronized(this)
344         {
345             _requestsDurationTotal+=duration;
346             if (_requestsDurationMin==0 || duration<_requestsDurationMin)
347                 _requestsDurationMin=duration;
348             if (duration>_requestsDurationMax)
349                 _requestsDurationMax=duration;
350         }
351     }
352 
353     
354     /* ------------------------------------------------------------ */
355     /**
356      * Handle completed requests.
357      * 
358      * @param request
359      *                the request which has just completed
360      */
361     public void complete(Request request)
362     {
363         long duration = System.currentTimeMillis() - request.getTimeStamp();
364         addRequestsDurationTotal(duration);
365     }
366 
367 }