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