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 public class NCSARequestLog extends AbstractLifeCycle implements RequestLog
45 {
46 private String _filename;
47 private boolean _extended;
48 private boolean _append;
49 private int _retainDays;
50 private boolean _closeOut;
51 private boolean _preferProxiedForAddress;
52 private String _logDateFormat = "dd/MMM/yyyy:HH:mm:ss Z";
53 private String _filenameDateFormat = null;
54 private Locale _logLocale = Locale.getDefault();
55 private String _logTimeZone = "GMT";
56 private String[] _ignorePaths;
57 private boolean _logLatency = false;
58 private boolean _logCookies = false;
59 private boolean _logServer = false;
60
61 private transient OutputStream _out;
62 private transient OutputStream _fileOut;
63 private transient DateCache _logDateCache;
64 private transient PathMap _ignorePathMap;
65 private transient Writer _writer;
66 private transient ArrayList _buffers;
67 private transient char[] _copy;
68
69 public NCSARequestLog()
70 {
71 _extended = true;
72 _append = true;
73 _retainDays = 31;
74 }
75
76
77
78
79
80
81
82 public NCSARequestLog(String filename)
83 {
84 _extended = true;
85 _append = true;
86 _retainDays = 31;
87 setFilename(filename);
88 }
89
90
91
92
93
94
95
96 public void setFilename(String filename)
97 {
98 if (filename != null)
99 {
100 filename = filename.trim();
101 if (filename.length() == 0)
102 filename = null;
103 }
104 _filename = filename;
105 }
106
107 public String getFilename()
108 {
109 return _filename;
110 }
111
112 public String getDatedFilename()
113 {
114 if (_fileOut instanceof RolloverFileOutputStream)
115 return ((RolloverFileOutputStream)_fileOut).getDatedFilename();
116 return null;
117 }
118
119
120
121
122
123
124
125 public void setLogDateFormat(String format)
126 {
127 _logDateFormat = format;
128 }
129
130 public String getLogDateFormat()
131 {
132 return _logDateFormat;
133 }
134
135 public void setLogLocale(Locale logLocale)
136 {
137 _logLocale = logLocale;
138 }
139
140 public Locale getLogLocale()
141 {
142 return _logLocale;
143 }
144
145 public void setLogTimeZone(String tz)
146 {
147 _logTimeZone = tz;
148 }
149
150 public String getLogTimeZone()
151 {
152 return _logTimeZone;
153 }
154
155 public void setRetainDays(int retainDays)
156 {
157 _retainDays = retainDays;
158 }
159
160 public int getRetainDays()
161 {
162 return _retainDays;
163 }
164
165 public void setExtended(boolean extended)
166 {
167 _extended = extended;
168 }
169
170 public boolean isExtended()
171 {
172 return _extended;
173 }
174
175 public void setAppend(boolean append)
176 {
177 _append = append;
178 }
179
180 public boolean isAppend()
181 {
182 return _append;
183 }
184
185 public void setIgnorePaths(String[] ignorePaths)
186 {
187 _ignorePaths = ignorePaths;
188 }
189
190 public String[] getIgnorePaths()
191 {
192 return _ignorePaths;
193 }
194
195 public void setLogCookies(boolean logCookies)
196 {
197 _logCookies = logCookies;
198 }
199
200 public boolean getLogCookies()
201 {
202 return _logCookies;
203 }
204
205 public boolean getLogServer()
206 {
207 return _logServer;
208 }
209
210 public void setLogServer(boolean logServer)
211 {
212 _logServer = logServer;
213 }
214
215 public void setLogLatency(boolean logLatency)
216 {
217 _logLatency = logLatency;
218 }
219
220 public boolean getLogLatency()
221 {
222 return _logLatency;
223 }
224
225 public void setPreferProxiedForAddress(boolean preferProxiedForAddress)
226 {
227 _preferProxiedForAddress = preferProxiedForAddress;
228 }
229
230
231 public void log(Request request, Response response)
232 {
233 if (!isStarted())
234 return;
235
236 try
237 {
238 if (_ignorePathMap != null && _ignorePathMap.getMatch(request.getRequestURI()) != null)
239 return;
240
241 if (_fileOut == null)
242 return;
243
244 Utf8StringBuilder u8buf;
245 StringBuilder buf;
246 synchronized(_writer)
247 {
248 int size=_buffers.size();
249 u8buf = size==0?new Utf8StringBuilder(160):(Utf8StringBuilder)_buffers.remove(size-1);
250 buf = u8buf.getStringBuilder();
251 }
252
253 if (_logServer)
254 {
255 buf.append(request.getServerName());
256 buf.append(' ');
257 }
258
259 String addr = null;
260 if (_preferProxiedForAddress)
261 {
262 addr = request.getHeader(HttpHeaders.X_FORWARDED_FOR);
263 }
264
265 if (addr == null)
266 addr = request.getRemoteAddr();
267
268 buf.append(addr);
269 buf.append(" - ");
270 Authentication authentication=request.getAuthentication();
271 if (authentication instanceof Authentication.User)
272 buf.append(((Authentication.User)authentication).getUserIdentity().getUserPrincipal().getName());
273 else
274 buf.append(" - ");
275
276 buf.append(" [");
277 if (_logDateCache != null)
278 buf.append(_logDateCache.format(request.getTimeStamp()));
279 else
280 buf.append(request.getTimeStampBuffer().toString());
281
282 buf.append("] \"");
283 buf.append(request.getMethod());
284 buf.append(' ');
285
286 request.getUri().writeTo(u8buf);
287
288 buf.append(' ');
289 buf.append(request.getProtocol());
290 buf.append("\" ");
291 if (request.getAsyncContinuation().isInitial())
292 {
293 int status = response.getStatus();
294 if (status <= 0)
295 status = 404;
296 buf.append((char)('0' + ((status / 100) % 10)));
297 buf.append((char)('0' + ((status / 10) % 10)));
298 buf.append((char)('0' + (status % 10)));
299 }
300 else
301 buf.append("Async");
302
303 long responseLength = response.getContentCount();
304 if (responseLength >= 0)
305 {
306 buf.append(' ');
307 if (responseLength > 99999)
308 buf.append(responseLength);
309 else
310 {
311 if (responseLength > 9999)
312 buf.append((char)('0' + ((responseLength / 10000) % 10)));
313 if (responseLength > 999)
314 buf.append((char)('0' + ((responseLength / 1000) % 10)));
315 if (responseLength > 99)
316 buf.append((char)('0' + ((responseLength / 100) % 10)));
317 if (responseLength > 9)
318 buf.append((char)('0' + ((responseLength / 10) % 10)));
319 buf.append((char)('0' + (responseLength) % 10));
320 }
321 buf.append(' ');
322 }
323 else
324 buf.append(" - ");
325
326 if (!_extended && !_logCookies && !_logLatency)
327 {
328 synchronized(_writer)
329 {
330 buf.append(StringUtil.__LINE_SEPARATOR);
331 int l=buf.length();
332 if (l>_copy.length)
333 l=_copy.length;
334 buf.getChars(0,l,_copy,0);
335 _writer.write(_copy,0,l);
336 _writer.flush();
337 u8buf.reset();
338 _buffers.add(u8buf);
339 }
340 }
341 else
342 {
343 synchronized(_writer)
344 {
345 int l=buf.length();
346 if (l>_copy.length)
347 l=_copy.length;
348 buf.getChars(0,l,_copy,0);
349 _writer.write(_copy,0,l);
350 u8buf.reset();
351 _buffers.add(u8buf);
352
353
354 if (_extended)
355 logExtended(request, response, _writer);
356
357
358 if (_logCookies)
359 {
360 Cookie[] cookies = request.getCookies();
361 if (cookies == null || cookies.length == 0)
362 _writer.write(" -");
363 else
364 {
365 _writer.write(" \"");
366 for (int i = 0; i < cookies.length; i++)
367 {
368 if (i != 0)
369 _writer.write(';');
370 _writer.write(cookies[i].getName());
371 _writer.write('=');
372 _writer.write(cookies[i].getValue());
373 }
374 _writer.write('\"');
375 }
376 }
377
378 if (_logLatency)
379 {
380 _writer.write(' ');
381 _writer.write(Long.toString(System.currentTimeMillis() - request.getTimeStamp()));
382 }
383
384 _writer.write(StringUtil.__LINE_SEPARATOR);
385 _writer.flush();
386 }
387 }
388 }
389 catch (IOException e)
390 {
391 Log.warn(e);
392 }
393
394 }
395
396
397 protected void logExtended(Request request,
398 Response response,
399 Writer writer) throws IOException
400 {
401 String referer = request.getHeader(HttpHeaders.REFERER);
402 if (referer == null)
403 writer.write("\"-\" ");
404 else
405 {
406 writer.write('"');
407 writer.write(referer);
408 writer.write("\" ");
409 }
410
411 String agent = request.getHeader(HttpHeaders.USER_AGENT);
412 if (agent == null)
413 writer.write("\"-\" ");
414 else
415 {
416 writer.write('"');
417 writer.write(agent);
418 writer.write('"');
419 }
420 }
421
422
423 @Override
424 protected void doStart() throws Exception
425 {
426 if (_logDateFormat != null)
427 {
428 _logDateCache = new DateCache(_logDateFormat,_logLocale);
429 _logDateCache.setTimeZoneID(_logTimeZone);
430 }
431
432 if (_filename != null)
433 {
434 _fileOut = new RolloverFileOutputStream(_filename,_append,_retainDays,TimeZone.getTimeZone(_logTimeZone),_filenameDateFormat,null);
435 _closeOut = true;
436 Log.info("Opened " + getDatedFilename());
437 }
438 else
439 _fileOut = System.err;
440
441 _out = _fileOut;
442
443 if (_ignorePaths != null && _ignorePaths.length > 0)
444 {
445 _ignorePathMap = new PathMap();
446 for (int i = 0; i < _ignorePaths.length; i++)
447 _ignorePathMap.put(_ignorePaths[i],_ignorePaths[i]);
448 }
449 else
450 _ignorePathMap = null;
451
452 _writer = new OutputStreamWriter(_out);
453 _buffers = new ArrayList();
454 _copy = new char[1024];
455 super.doStart();
456 }
457
458
459 @Override
460 protected void doStop() throws Exception
461 {
462 super.doStop();
463 try
464 {
465 if (_writer != null)
466 _writer.flush();
467 }
468 catch (IOException e)
469 {
470 Log.ignore(e);
471 }
472 if (_out != null && _closeOut)
473 try
474 {
475 _out.close();
476 }
477 catch (IOException e)
478 {
479 Log.ignore(e);
480 }
481
482 _out = null;
483 _fileOut = null;
484 _closeOut = false;
485 _logDateCache = null;
486 _writer = null;
487 _buffers = null;
488 _copy = null;
489 }
490
491
492
493
494
495 public String getFilenameDateFormat()
496 {
497 return _filenameDateFormat;
498 }
499
500
501
502
503
504
505
506
507
508
509 public void setFilenameDateFormat(String logFileDateFormat)
510 {
511 _filenameDateFormat = logFileDateFormat;
512 }
513
514 }