]> WPIA git - gigi.git/blob - lib/jetty/org/eclipse/jetty/server/AbstractNCSARequestLog.java
updating jetty to jetty-9.2.16.v2016040
[gigi.git] / lib / jetty / org / eclipse / jetty / server / AbstractNCSARequestLog.java
1 //
2 //  ========================================================================
3 //  Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
4 //  ------------------------------------------------------------------------
5 //  All rights reserved. This program and the accompanying materials
6 //  are made available under the terms of the Eclipse Public License v1.0
7 //  and Apache License v2.0 which accompanies this distribution.
8 //
9 //      The Eclipse Public License is available at
10 //      http://www.eclipse.org/legal/epl-v10.html
11 //
12 //      The Apache License v2.0 is available at
13 //      http://www.opensource.org/licenses/apache2.0.php
14 //
15 //  You may elect to redistribute this code under either of these licenses.
16 //  ========================================================================
17 //
18
19 package org.eclipse.jetty.server;
20
21 import java.io.IOException;
22 import java.util.Locale;
23
24 import javax.servlet.http.Cookie;
25
26 import org.eclipse.jetty.http.HttpHeader;
27 import org.eclipse.jetty.http.PathMap;
28 import org.eclipse.jetty.util.DateCache;
29 import org.eclipse.jetty.util.annotation.ManagedAttribute;
30 import org.eclipse.jetty.util.component.AbstractLifeCycle;
31 import org.eclipse.jetty.util.log.Log;
32 import org.eclipse.jetty.util.log.Logger;
33
34 /**
35  * Base implementation of the {@link RequestLog} outputs logs in the pseudo-standard NCSA common log format.
36  * Configuration options allow a choice between the standard Common Log Format (as used in the 3 log format) and the
37  * Combined Log Format (single log format). This log format can be output by most web servers, and almost all web log
38  * analysis software can understand these formats.
39  */
40 public abstract class AbstractNCSARequestLog extends AbstractLifeCycle implements RequestLog
41 {
42     protected static final Logger LOG = Log.getLogger(AbstractNCSARequestLog.class);
43
44     private static ThreadLocal<StringBuilder> _buffers = new ThreadLocal<StringBuilder>()
45     {
46         @Override
47         protected StringBuilder initialValue()
48         {
49             return new StringBuilder(256);
50         }
51     };
52
53
54     private String[] _ignorePaths;
55     private boolean _extended;
56     private transient PathMap<String> _ignorePathMap;
57     private boolean _logLatency = false;
58     private boolean _logCookies = false;
59     private boolean _logServer = false;
60     private boolean _preferProxiedForAddress;
61     private transient DateCache _logDateCache;
62     private String _logDateFormat = "dd/MMM/yyyy:HH:mm:ss Z";
63     private Locale _logLocale = Locale.getDefault();
64     private String _logTimeZone = "GMT";
65
66     /* ------------------------------------------------------------ */
67
68     /**
69      * Is logging enabled
70      */
71     protected abstract boolean isEnabled();
72     
73     /* ------------------------------------------------------------ */
74
75     /**
76      * Write requestEntry out. (to disk or slf4j log)
77      */
78     public abstract void write(String requestEntry) throws IOException;
79
80     /* ------------------------------------------------------------ */
81
82     /**
83      * Writes the request and response information to the output stream.
84      *
85      * @see org.eclipse.jetty.server.RequestLog#log(org.eclipse.jetty.server.Request,
86      *      org.eclipse.jetty.server.Response)
87      */
88     @Override
89     public void log(Request request, Response response)
90     {
91         try
92         {
93             if (_ignorePathMap != null && _ignorePathMap.getMatch(request.getRequestURI()) != null)
94                 return;
95
96             if (!isEnabled())
97                 return;
98
99             StringBuilder buf = _buffers.get();
100             buf.setLength(0);
101
102             if (_logServer)
103             {
104                 buf.append(request.getServerName());
105                 buf.append(' ');
106             }
107
108             String addr = null;
109             if (_preferProxiedForAddress)
110             {
111                 addr = request.getHeader(HttpHeader.X_FORWARDED_FOR.toString());
112             }
113
114             if (addr == null)
115                 addr = request.getRemoteAddr();
116
117             buf.append(addr);
118             buf.append(" - ");
119             Authentication authentication = request.getAuthentication();
120             if (authentication instanceof Authentication.User)
121                 buf.append(((Authentication.User)authentication).getUserIdentity().getUserPrincipal().getName());
122             else
123                 buf.append("-");
124
125             buf.append(" [");
126             if (_logDateCache != null)
127                 buf.append(_logDateCache.format(request.getTimeStamp()));
128             else
129                 buf.append(request.getTimeStamp());
130
131             buf.append("] \"");
132             buf.append(request.getMethod());
133             buf.append(' ');
134             buf.append(request.getUri().toString());
135             buf.append(' ');
136             buf.append(request.getProtocol());
137             buf.append("\" ");
138
139             int status = response.getStatus();
140             if (status <= 0)
141                 status = 404;
142             buf.append((char)('0' + ((status / 100) % 10)));
143             buf.append((char)('0' + ((status / 10) % 10)));
144             buf.append((char)('0' + (status % 10)));
145
146             long responseLength = response.getLongContentLength();
147             if (responseLength >= 0)
148             {
149                 buf.append(' ');
150                 if (responseLength > 99999)
151                     buf.append(responseLength);
152                 else
153                 {
154                     if (responseLength > 9999)
155                         buf.append((char)('0' + ((responseLength / 10000) % 10)));
156                     if (responseLength > 999)
157                         buf.append((char)('0' + ((responseLength / 1000) % 10)));
158                     if (responseLength > 99)
159                         buf.append((char)('0' + ((responseLength / 100) % 10)));
160                     if (responseLength > 9)
161                         buf.append((char)('0' + ((responseLength / 10) % 10)));
162                     buf.append((char)('0' + (responseLength) % 10));
163                 }
164                 buf.append(' ');
165             }
166             else
167                 buf.append(" - ");
168
169
170             if (_extended)
171                 logExtended(request, response, buf);
172
173             if (_logCookies)
174             {
175                 Cookie[] cookies = request.getCookies();
176                 if (cookies == null || cookies.length == 0)
177                     buf.append(" -");
178                 else
179                 {
180                     buf.append(" \"");
181                     for (int i = 0; i < cookies.length; i++)
182                     {
183                         if (i != 0)
184                             buf.append(';');
185                         buf.append(cookies[i].getName());
186                         buf.append('=');
187                         buf.append(cookies[i].getValue());
188                     }
189                     buf.append('\"');
190                 }
191             }
192
193             if (_logLatency)
194             {
195                 long now = System.currentTimeMillis();
196
197                 if (_logLatency)
198                 {
199                     buf.append(' ');
200                     buf.append(now - request.getTimeStamp());
201                 }
202             }
203
204             String log = buf.toString();
205             write(log);
206         }
207         catch (IOException e)
208         {
209             LOG.warn(e);
210         }
211     }
212     
213     /* ------------------------------------------------------------ */
214
215     /**
216      * Writes extended request and response information to the output stream.
217      *
218      * @param request  request object
219      * @param response response object
220      * @param b        StringBuilder to write to
221      * @throws IOException
222      */
223     protected void logExtended(Request request,
224                                Response response,
225                                StringBuilder b) throws IOException
226     {
227         String referer = request.getHeader(HttpHeader.REFERER.toString());
228         if (referer == null)
229             b.append("\"-\" ");
230         else
231         {
232             b.append('"');
233             b.append(referer);
234             b.append("\" ");
235         }
236
237         String agent = request.getHeader(HttpHeader.USER_AGENT.toString());
238         if (agent == null)
239             b.append("\"-\" ");
240         else
241         {
242             b.append('"');
243             b.append(agent);
244             b.append('"');
245         }
246     }
247
248
249     /**
250      * Set request paths that will not be logged.
251      *
252      * @param ignorePaths array of request paths
253      */
254     public void setIgnorePaths(String[] ignorePaths)
255     {
256         _ignorePaths = ignorePaths;
257     }
258
259     /**
260      * Retrieve the request paths that will not be logged.
261      *
262      * @return array of request paths
263      */
264     public String[] getIgnorePaths()
265     {
266         return _ignorePaths;
267     }
268
269     /**
270      * Controls logging of the request cookies.
271      *
272      * @param logCookies true - values of request cookies will be logged, false - values of request cookies will not be
273      *                   logged
274      */
275     public void setLogCookies(boolean logCookies)
276     {
277         _logCookies = logCookies;
278     }
279
280     /**
281      * Retrieve log cookies flag
282      *
283      * @return value of the flag
284      */
285     public boolean getLogCookies()
286     {
287         return _logCookies;
288     }
289
290     /**
291      * Controls logging of the request hostname.
292      *
293      * @param logServer true - request hostname will be logged, false - request hostname will not be logged
294      */
295     public void setLogServer(boolean logServer)
296     {
297         _logServer = logServer;
298     }
299
300     /**
301      * Retrieve log hostname flag.
302      *
303      * @return value of the flag
304      */
305     public boolean getLogServer()
306     {
307         return _logServer;
308     }
309
310     /**
311      * Controls logging of request processing time.
312      *
313      * @param logLatency true - request processing time will be logged false - request processing time will not be
314      *                   logged
315      */
316     public void setLogLatency(boolean logLatency)
317     {
318         _logLatency = logLatency;
319     }
320
321     /**
322      * Retrieve log request processing time flag.
323      *
324      * @return value of the flag
325      */
326     public boolean getLogLatency()
327     {
328         return _logLatency;
329     }
330
331     /**
332      * @deprecated use {@link StatisticsHandler}
333      */
334     public void setLogDispatch(boolean value)
335     {
336     }
337
338     /**
339      * @deprecated use {@link StatisticsHandler}
340      */
341     public boolean isLogDispatch()
342     {
343         return false;
344     }
345
346     /**
347      * Controls whether the actual IP address of the connection or the IP address from the X-Forwarded-For header will
348      * be logged.
349      *
350      * @param preferProxiedForAddress true - IP address from header will be logged, false - IP address from the
351      *                                connection will be logged
352      */
353     public void setPreferProxiedForAddress(boolean preferProxiedForAddress)
354     {
355         _preferProxiedForAddress = preferProxiedForAddress;
356     }
357
358     /**
359      * Retrieved log X-Forwarded-For IP address flag.
360      *
361      * @return value of the flag
362      */
363     public boolean getPreferProxiedForAddress()
364     {
365         return _preferProxiedForAddress;
366     }
367
368     /**
369      * Set the extended request log format flag.
370      *
371      * @param extended true - log the extended request information, false - do not log the extended request information
372      */
373     public void setExtended(boolean extended)
374     {
375         _extended = extended;
376     }
377
378     /**
379      * Retrieve the extended request log format flag.
380      *
381      * @return value of the flag
382      */
383     @ManagedAttribute("use extended NCSA format")
384     public boolean isExtended()
385     {
386         return _extended;
387     }
388
389     /**
390      * Set up request logging and open log file.
391      *
392      * @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStart()
393      */
394     @Override
395     protected synchronized void doStart() throws Exception
396     {
397         if (_logDateFormat != null)
398         {
399             _logDateCache = new DateCache(_logDateFormat, _logLocale ,_logTimeZone);
400         }
401
402         if (_ignorePaths != null && _ignorePaths.length > 0)
403         {
404             _ignorePathMap = new PathMap<>();
405             for (int i = 0; i < _ignorePaths.length; i++)
406                 _ignorePathMap.put(_ignorePaths[i], _ignorePaths[i]);
407         }
408         else
409             _ignorePathMap = null;
410
411         super.doStart();
412     }
413
414     @Override
415     protected void doStop() throws Exception
416     {
417         _logDateCache = null;
418         super.doStop();
419     }
420
421     /**
422      * Set the timestamp format for request log entries in the file. If this is not set, the pre-formated request
423      * timestamp is used.
424      *
425      * @param format timestamp format string
426      */
427     public void setLogDateFormat(String format)
428     {
429         _logDateFormat = format;
430     }
431
432     /**
433      * Retrieve the timestamp format string for request log entries.
434      *
435      * @return timestamp format string.
436      */
437     public String getLogDateFormat()
438     {
439         return _logDateFormat;
440     }
441
442     /**
443      * Set the locale of the request log.
444      *
445      * @param logLocale locale object
446      */
447     public void setLogLocale(Locale logLocale)
448     {
449         _logLocale = logLocale;
450     }
451
452     /**
453      * Retrieve the locale of the request log.
454      *
455      * @return locale object
456      */
457     public Locale getLogLocale()
458     {
459         return _logLocale;
460     }
461
462     /**
463      * Set the timezone of the request log.
464      *
465      * @param tz timezone string
466      */
467     public void setLogTimeZone(String tz)
468     {
469         _logTimeZone = tz;
470     }
471
472     /**
473      * Retrieve the timezone of the request log.
474      *
475      * @return timezone string
476      */
477     @ManagedAttribute("the timezone")
478     public String getLogTimeZone()
479     {
480         return _logTimeZone;
481     }
482 }