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