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