1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.server;
20
21 import java.io.IOException;
22 import java.io.OutputStream;
23 import java.io.OutputStreamWriter;
24 import java.io.Writer;
25 import java.util.Locale;
26 import java.util.TimeZone;
27
28 import javax.servlet.http.Cookie;
29
30 import org.eclipse.jetty.http.HttpHeader;
31 import org.eclipse.jetty.http.PathMap;
32 import org.eclipse.jetty.util.DateCache;
33 import org.eclipse.jetty.util.RolloverFileOutputStream;
34 import org.eclipse.jetty.util.StringUtil;
35 import org.eclipse.jetty.util.annotation.ManagedAttribute;
36 import org.eclipse.jetty.util.annotation.ManagedObject;
37 import org.eclipse.jetty.util.component.AbstractLifeCycle;
38 import org.eclipse.jetty.util.log.Log;
39 import org.eclipse.jetty.util.log.Logger;
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54 @ManagedObject("NCSA standard format request log")
55 public class NCSARequestLog extends AbstractLifeCycle implements RequestLog
56 {
57 private static final Logger LOG = Log.getLogger(NCSARequestLog.class);
58
59 private String _filename;
60 private boolean _extended;
61 private boolean _append;
62 private int _retainDays;
63 private boolean _closeOut;
64 private boolean _preferProxiedForAddress;
65 private String _logDateFormat = "dd/MMM/yyyy:HH:mm:ss Z";
66 private String _filenameDateFormat = null;
67 private Locale _logLocale = Locale.getDefault();
68 private String _logTimeZone = "GMT";
69 private String[] _ignorePaths;
70 private boolean _logLatency = false;
71 private boolean _logCookies = false;
72 private boolean _logServer = false;
73 private boolean _logDispatch = false;
74
75 private transient OutputStream _out;
76 private transient OutputStream _fileOut;
77 private transient DateCache _logDateCache;
78 private transient PathMap _ignorePathMap;
79 private transient Writer _writer;
80
81
82
83
84
85 public NCSARequestLog()
86 {
87 _extended = true;
88 _append = true;
89 _retainDays = 31;
90 }
91
92
93
94
95
96
97
98
99
100 public NCSARequestLog(String filename)
101 {
102 _extended = true;
103 _append = true;
104 _retainDays = 31;
105 setFilename(filename);
106 }
107
108
109
110
111
112
113
114
115
116
117 public void setFilename(String filename)
118 {
119 if (filename != null)
120 {
121 filename = filename.trim();
122 if (filename.length() == 0)
123 filename = null;
124 }
125 _filename = filename;
126 }
127
128
129
130
131
132
133
134 @ManagedAttribute("file of log")
135 public String getFilename()
136 {
137 return _filename;
138 }
139
140
141
142
143
144
145
146
147
148 public String getDatedFilename()
149 {
150 if (_fileOut instanceof RolloverFileOutputStream)
151 return ((RolloverFileOutputStream)_fileOut).getDatedFilename();
152 return null;
153 }
154
155
156
157
158
159
160
161
162 public void setLogDateFormat(String format)
163 {
164 _logDateFormat = format;
165 }
166
167
168
169
170
171
172
173 public String getLogDateFormat()
174 {
175 return _logDateFormat;
176 }
177
178
179
180
181
182
183
184 public void setLogLocale(Locale logLocale)
185 {
186 _logLocale = logLocale;
187 }
188
189
190
191
192
193
194
195 public Locale getLogLocale()
196 {
197 return _logLocale;
198 }
199
200
201
202
203
204
205
206 public void setLogTimeZone(String tz)
207 {
208 _logTimeZone = tz;
209 }
210
211
212
213
214
215
216
217 @ManagedAttribute("the timezone")
218 public String getLogTimeZone()
219 {
220 return _logTimeZone;
221 }
222
223
224
225
226
227
228
229 public void setRetainDays(int retainDays)
230 {
231 _retainDays = retainDays;
232 }
233
234
235
236
237
238
239
240 @ManagedAttribute("number of days that log files are kept")
241 public int getRetainDays()
242 {
243 return _retainDays;
244 }
245
246
247
248
249
250
251
252
253 public void setExtended(boolean extended)
254 {
255 _extended = extended;
256 }
257
258
259
260
261
262
263
264 @ManagedAttribute("use extended NCSA format")
265 public boolean isExtended()
266 {
267 return _extended;
268 }
269
270
271
272
273
274
275
276
277 public void setAppend(boolean append)
278 {
279 _append = append;
280 }
281
282
283
284
285
286
287
288 @ManagedAttribute("existing log files are appends to the new one")
289 public boolean isAppend()
290 {
291 return _append;
292 }
293
294
295
296
297
298
299
300 public void setIgnorePaths(String[] ignorePaths)
301 {
302 _ignorePaths = ignorePaths;
303 }
304
305
306
307
308
309
310
311 public String[] getIgnorePaths()
312 {
313 return _ignorePaths;
314 }
315
316
317
318
319
320
321
322
323 public void setLogCookies(boolean logCookies)
324 {
325 _logCookies = logCookies;
326 }
327
328
329
330
331
332
333
334 public boolean getLogCookies()
335 {
336 return _logCookies;
337 }
338
339
340
341
342
343
344
345
346 public void setLogServer(boolean logServer)
347 {
348 _logServer = logServer;
349 }
350
351
352
353
354
355
356
357 public boolean getLogServer()
358 {
359 return _logServer;
360 }
361
362
363
364
365
366
367
368
369 public void setLogLatency(boolean logLatency)
370 {
371 _logLatency = logLatency;
372 }
373
374
375
376
377
378
379
380 public boolean getLogLatency()
381 {
382 return _logLatency;
383 }
384
385
386
387
388
389
390
391
392
393 public void setPreferProxiedForAddress(boolean preferProxiedForAddress)
394 {
395 _preferProxiedForAddress = preferProxiedForAddress;
396 }
397
398
399
400
401
402
403
404 public boolean getPreferProxiedForAddress()
405 {
406 return _preferProxiedForAddress;
407 }
408
409
410
411
412
413
414
415
416 public void setFilenameDateFormat(String logFileDateFormat)
417 {
418 _filenameDateFormat = logFileDateFormat;
419 }
420
421
422
423
424
425
426
427 public String getFilenameDateFormat()
428 {
429 return _filenameDateFormat;
430 }
431
432
433
434
435
436
437
438
439 public void setLogDispatch(boolean value)
440 {
441 _logDispatch = value;
442 }
443
444
445
446
447
448
449
450 public boolean isLogDispatch()
451 {
452 return _logDispatch;
453 }
454
455
456
457
458
459
460
461 public void log(Request request, Response response)
462 {
463 try
464 {
465 if (_ignorePathMap != null && _ignorePathMap.getMatch(request.getRequestURI()) != null)
466 return;
467
468 if (_fileOut == null)
469 return;
470
471 StringBuilder buf= new StringBuilder(256);
472
473 if (_logServer)
474 {
475 buf.append(request.getServerName());
476 buf.append(' ');
477 }
478
479 String addr = null;
480 if (_preferProxiedForAddress)
481 {
482 addr = request.getHeader(HttpHeader.X_FORWARDED_FOR.toString());
483 }
484
485 if (addr == null)
486 addr = request.getRemoteAddr();
487
488 buf.append(addr);
489 buf.append(" - ");
490 Authentication authentication=request.getAuthentication();
491 if (authentication instanceof Authentication.User)
492 buf.append(((Authentication.User)authentication).getUserIdentity().getUserPrincipal().getName());
493 else
494 buf.append(" - ");
495
496 buf.append(" [");
497 if (_logDateCache != null)
498 buf.append(_logDateCache.format(request.getTimeStamp()));
499 else
500 buf.append(request.getTimeStamp());
501
502 buf.append("] \"");
503 buf.append(request.getMethod());
504 buf.append(' ');
505 buf.append(request.getUri().toString());
506 buf.append(' ');
507 buf.append(request.getProtocol());
508 buf.append("\" ");
509 if (request.getHttpChannelState().isInitial())
510 {
511 int status = response.getStatus();
512 if (status <= 0)
513 status = 404;
514 buf.append((char)('0' + ((status / 100) % 10)));
515 buf.append((char)('0' + ((status / 10) % 10)));
516 buf.append((char)('0' + (status % 10)));
517 }
518 else
519 buf.append("Async");
520
521 long responseLength = response.getLongContentLength();
522 if (responseLength >= 0)
523 {
524 buf.append(' ');
525 if (responseLength > 99999)
526 buf.append(responseLength);
527 else
528 {
529 if (responseLength > 9999)
530 buf.append((char)('0' + ((responseLength / 10000) % 10)));
531 if (responseLength > 999)
532 buf.append((char)('0' + ((responseLength / 1000) % 10)));
533 if (responseLength > 99)
534 buf.append((char)('0' + ((responseLength / 100) % 10)));
535 if (responseLength > 9)
536 buf.append((char)('0' + ((responseLength / 10) % 10)));
537 buf.append((char)('0' + (responseLength) % 10));
538 }
539 buf.append(' ');
540 }
541 else
542 buf.append(" - ");
543
544
545 if (_extended)
546 logExtended(request, response, buf);
547
548 if (_logCookies)
549 {
550 Cookie[] cookies = request.getCookies();
551 if (cookies == null || cookies.length == 0)
552 buf.append(" -");
553 else
554 {
555 buf.append(" \"");
556 for (int i = 0; i < cookies.length; i++)
557 {
558 if (i != 0)
559 buf.append(';');
560 buf.append(cookies[i].getName());
561 buf.append('=');
562 buf.append(cookies[i].getValue());
563 }
564 buf.append('\"');
565 }
566 }
567
568 if (_logDispatch || _logLatency)
569 {
570 long now = System.currentTimeMillis();
571
572 if (_logDispatch)
573 {
574 long d = request.getDispatchTime();
575 buf.append(' ');
576 buf.append(now - (d==0 ? request.getTimeStamp():d));
577 }
578
579 if (_logLatency)
580 {
581 buf.append(' ');
582 buf.append(now - request.getTimeStamp());
583 }
584 }
585
586 buf.append(StringUtil.__LINE_SEPARATOR);
587 String log = buf.toString();
588 synchronized(this)
589 {
590 if (_writer==null)
591 return;
592 _writer.write(log);
593 _writer.flush();
594 }
595 }
596 catch (IOException e)
597 {
598 LOG.warn(e);
599 }
600
601 }
602
603
604
605
606
607
608
609
610
611
612 protected void logExtended(Request request,
613 Response response,
614 StringBuilder b) throws IOException
615 {
616 String referer = request.getHeader(HttpHeader.REFERER.toString());
617 if (referer == null)
618 b.append("\"-\" ");
619 else
620 {
621 b.append('"');
622 b.append(referer);
623 b.append("\" ");
624 }
625
626 String agent = request.getHeader(HttpHeader.USER_AGENT.toString());
627 if (agent == null)
628 b.append("\"-\" ");
629 else
630 {
631 b.append('"');
632 b.append(agent);
633 b.append('"');
634 }
635 }
636
637
638
639
640
641
642
643 @Override
644 protected synchronized void doStart() throws Exception
645 {
646 if (_logDateFormat != null)
647 {
648 _logDateCache = new DateCache(_logDateFormat,_logLocale);
649 _logDateCache.setTimeZoneID(_logTimeZone);
650 }
651
652 if (_filename != null)
653 {
654 _fileOut = new RolloverFileOutputStream(_filename,_append,_retainDays,TimeZone.getTimeZone(_logTimeZone),_filenameDateFormat,null);
655 _closeOut = true;
656 LOG.info("Opened " + getDatedFilename());
657 }
658 else
659 _fileOut = System.err;
660
661 _out = _fileOut;
662
663 if (_ignorePaths != null && _ignorePaths.length > 0)
664 {
665 _ignorePathMap = new PathMap();
666 for (int i = 0; i < _ignorePaths.length; i++)
667 _ignorePathMap.put(_ignorePaths[i],_ignorePaths[i]);
668 }
669 else
670 _ignorePathMap = null;
671
672 _writer = new OutputStreamWriter(_out);
673 super.doStart();
674 }
675
676
677
678
679
680
681
682 @Override
683 protected void doStop() throws Exception
684 {
685 synchronized (this)
686 {
687 super.doStop();
688 try
689 {
690 if (_writer != null)
691 _writer.flush();
692 }
693 catch (IOException e)
694 {
695 LOG.ignore(e);
696 }
697 if (_out != null && _closeOut)
698 try
699 {
700 _out.close();
701 }
702 catch (IOException e)
703 {
704 LOG.ignore(e);
705 }
706
707 _out = null;
708 _fileOut = null;
709 _closeOut = false;
710 _logDateCache = null;
711 _writer = null;
712 }
713 }
714 }