Changeset 1073
- Timestamp:
- 06/07/08 19:37:37 (3 months ago)
- Files:
-
- trunk/mango/net/servlet/Servlet.d (modified) (6 diffs)
- trunk/mango/net/servlet/ServletProvider.d (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/mango/net/servlet/Servlet.d
r1069 r1073 15 15 private import tango.time.Time; 16 16 17 private import tango.time.StopWatch; 18 17 19 public import tango.util.log.Log; 18 20 … … 50 52 /********************************************************************** 51 53 54 Servlet metrics 55 56 **********************************************************************/ 57 58 struct Metrics 59 { 60 char[] name; 61 double time = 0, 62 average = 0, 63 average2 = 0, 64 average4 = 0, 65 average8 = 0; 66 ulong requests = 0, 67 failures = 0; 68 69 70 void update (double time) 71 { 72 ++requests; 73 this.time = time; 74 average2 = (average2 + time) / 2.0; 75 average4 = (average4 + average2) / 2.0; 76 average8 = (average8 + average4) / 2.0; 77 average = (average + average8) / 2.0; 78 } 79 } 80 81 /********************************************************************** 82 52 83 Init is called when the servlet is first registered. 53 84 … … 56 87 void init (ServletConfig config) 57 88 { 58 }59 60 /**********************************************************************61 62 return an optional logger instance63 64 **********************************************************************/65 66 Logger logger ()67 {68 return null;69 89 } 70 90 } … … 80 100 class MethodServlet : Servlet 81 101 { 102 Logger log; 103 Metrics[] metrics; 104 105 private alias void delegate (IServletRequest, IServletResponse) Handler; 82 106 83 107 /********************************************************************** 84 108 85 Default response for unimplemented requests. 86 87 **********************************************************************/ 88 89 static private void error (IServletResponse response) 90 { 91 response.sendError (HttpResponses.MethodNotAllowed); 109 110 **********************************************************************/ 111 112 this (char[] log = null) 113 { 114 if (log.length) 115 this.log = Log.lookup (log); 116 117 metrics = new Metrics [7]; 118 } 119 120 /********************************************************************** 121 122 return an optional logger instance 123 124 **********************************************************************/ 125 126 Logger logger () 127 { 128 return log; 92 129 } 93 130 … … 220 257 void service (IServletRequest request, IServletResponse response) 221 258 { 222 char[] method = request.method; 259 StopWatch timer; 260 Metrics* metric; 261 Handler handler; 262 char[] method = request.method; 263 264 // begin timer 265 timer.start; 223 266 224 267 switch (method[0]) 225 268 { 226 269 case 'G': 227 get (request, response); 270 handler = &get; 271 metric = &metrics [0]; 228 272 break; 229 273 230 274 case 'H': 231 doHead (request, response); 275 handler = &doHead; 276 metric = &metrics [1]; 232 277 break; 233 278 234 279 case 'O': 235 doOptions (request, response); 280 handler = &doOptions; 281 metric = &metrics [2]; 236 282 break; 237 283 238 284 case 'T': 239 doTrace (request, response); 285 handler = &doTrace; 286 metric = &metrics [3]; 240 287 break; 241 288 242 289 case 'D': 243 doDelete (request, response); 290 handler = &doDelete; 291 metric = &metrics [4]; 244 292 break; 245 293 246 294 case 'P': 247 295 if (method[1] == 'O') 248 doPost (request, response); 296 { 297 handler = &doPost; 298 metric = &metrics [5]; 299 } 249 300 else 250 doPut (request, response); 301 { 302 handler = &doPut; 303 metric = &metrics [6]; 304 } 251 305 break; 252 306 … … 255 309 break; 256 310 } 311 312 // log execution time 313 auto log = logger; 314 try { 315 // invoke handler 316 handler (request, response); 317 318 // update metrics 319 metric.update (timer.stop); 320 321 if (log) 322 log.trace (Log.format() ("{} {}, {} failures, {} requests, average {}us", 323 method, request.path, metric.failures, metric.requests, 324 metric.average * 1_000_000)); 325 326 } catch (Exception e) 327 { 328 ++metric.failures; 329 if (log) 330 log.error (Log.format() ("{} {}, {} failures: {}", 331 method, request.path, metric.failures, e)); 332 throw e; 333 } 334 335 } 336 337 /********************************************************************** 338 339 Default response for unimplemented requests. 340 341 **********************************************************************/ 342 343 private static void error (IServletResponse response) 344 { 345 response.sendError (HttpResponses.MethodNotAllowed); 257 346 } 258 347 } 259 348 260 349 261 /****************************************************************************** 262 263 This class is intended to be compatible with a Java GenericServlet. 264 Note that the ServletContext is available from the ServletRequest 265 class, so this error-prone approach of accessing context via the 266 configuration is rendered totally redundant. 267 268 ******************************************************************************/ 269 270 class CompatibleServlet : MethodServlet 271 { 272 private ServletConfig config; 273 274 /********************************************************************** 275 276 Servlet must implement the init() method 277 278 **********************************************************************/ 279 280 abstract void init (); 281 282 /********************************************************************** 283 284 Optional init() with ServletConfig passed to it. 285 286 **********************************************************************/ 287 288 void init (ServletConfig config) 289 { 290 this.config = config; 291 init (); 292 } 293 294 /********************************************************************** 295 296 Return the configuration passed with init() 297 298 **********************************************************************/ 299 300 ServletConfig getConfig () 301 { 302 return config; 303 } 304 } 305 306 350 trunk/mango/net/servlet/ServletProvider.d
r1069 r1073 16 16 17 17 private import tango.util.log.Log; 18 19 private import tango.time.StopWatch;20 18 21 19 private import tango.text.Regex, … … 384 382 PathMapping pm; 385 383 char[] path; 386 StopWatch timer;387 384 ServletRequest request; 388 385 ServletResponse response; 389 386 bool addToCache; 390 387 391 // begin timer392 timer.start;393 394 388 // we know what these are since we created them (above) 395 389 request = cast(ServletRequest) req; … … 423 417 424 418 // execute servlet 425 auto servlet = pm.mapping.proxy.getServlet; 426 servlet.service (request, response); 427 428 // log execution time 429 auto log = servlet.logger; 430 if (log) 431 log.info (Log.format() ("took {}us", timer.microsec)); 432 419 pm.mapping.proxy.getServlet.service (request, response); 420 433 421 // flush output on behalf of servlet ... 434 422 response.flush; … … 438 426 cache.put (pm.path, pm); 439 427 440 } catch (UnavailableException ux) 441 response.sendError (HttpResponses.ServiceUnavailable, ux.toString); 442 443 catch (ServletException sx) 444 error (response, sx); 445 446 catch (Object ex) 447 error (response, ex); 448 } 449 450 /********************************************************************** 451 452 handle internal errors 453 454 **********************************************************************/ 455 456 private void error (ServletResponse response, Object x) 457 { 458 response.sendError (HttpResponses.InternalServerError, x.toString); 459 getDefaultContext.log ("Internal error:", x); 428 } catch (ServletException sx) 429 response.sendError (HttpResponses.ServiceUnavailable, "please retry"); 430 431 catch (Object o) 432 { 433 response.sendError (HttpResponses.InternalServerError, o.toString); 434 getDefaultContext.log ("Internal exception: ", o); 435 } 460 436 } 461 437 }
