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