Fields Summary |
---|
private static org.apache.juli.logging.Log | log |
private String | dateStampThe as-of date for the currently open log file, or a zero-length
string if there is no open log file. |
private String | directoryThe directory in which log files are created. |
protected static final String | infoThe descriptive information about this implementation. |
protected org.apache.catalina.util.LifecycleSupport | lifecycleThe lifecycle event support for this component. |
protected static final String[] | monthsThe set of month abbreviations for log messages. |
protected boolean | enabledenabled this component |
protected String | patternThe pattern used to format our access log lines. |
protected String | prefixThe prefix that is added to log file filenames. |
protected boolean | rotatableShould we rotate our log file? Default is true (like old behavior) |
private boolean | bufferedBuffered logging. |
protected org.apache.catalina.util.StringManager | smThe string manager for this package. |
protected boolean | startedHas this component been started yet? |
protected String | suffixThe suffix that is added to log file filenames. |
protected PrintWriter | writerThe PrintWriter to which we are currently logging, if any. |
protected SimpleDateFormat | fileDateFormatterA date formatter to format a Date into a date in the format
"yyyy-MM-dd". |
private SimpleDateFormat | dayFormatterA date formatter to format Dates into a day string in the format
"dd". |
private SimpleDateFormat | monthFormatterA date formatter to format a Date into a month string in the format
"MM". |
private SimpleDateFormat | yearFormatterA date formatter to format a Date into a year string in the format
"yyyy". |
private SimpleDateFormat | timeFormatterA date formatter to format a Date into a time in the format
"kk:mm:ss" (kk is a 24-hour representation of the hour). |
private TimeZone | timezoneThe system timezone. |
private String | timeZoneNoDSTThe time zone offset relative to GMT in text form when daylight saving
is not in operation. |
private String | timeZoneDSTThe time zone offset relative to GMT in text form when daylight saving
is in operation. |
protected File | currentLogFileThe current log file we are writing to. Helpful when checkExists
is true. |
private Date | currentDateThe system time when we last updated the Date that this valve
uses for log lines. |
private long | currentMillis |
private boolean | resolveHostsResolve hosts. |
private long | rotationLastCheckedInstant when the log daily rotation was last checked. |
private boolean | checkExistsDo we check for log file existence? Helpful if an external
agent renames the log file so we can automagically recreate it. |
protected String | conditionAre we doing conditional logging. default false. |
protected String | fileDateFormatDate format to place in log file name. Use at your own risk! |
protected AccessLogElement[] | logElementsArray of AccessLogElement, they will be used to make log message. |
Methods Summary |
---|
public void | addLifecycleListener(org.apache.catalina.LifecycleListener listener)Add a lifecycle event listener to this component.
lifecycle.addLifecycleListener(listener);
|
public void | backgroundProcess()Execute a periodic task, such as reloading, etc. This method will be
invoked inside the classloading context of this container. Unexpected
throwables will be caught and logged.
if (started && getEnabled() && writer != null && buffered) {
writer.flush();
}
|
private java.lang.String | calculateTimeZoneOffset(long offset)
StringBuffer tz = new StringBuffer();
if ((offset < 0)) {
tz.append("-");
offset = -offset;
} else {
tz.append("+");
}
long hourOffset = offset / (1000 * 60 * 60);
long minuteOffset = (offset / (1000 * 60)) % 60;
if (hourOffset < 10)
tz.append("0");
tz.append(hourOffset);
if (minuteOffset < 10)
tz.append("0");
tz.append(minuteOffset);
return tz.toString();
|
private synchronized void | close()Close the currently open log file (if any)
if (writer == null) {
return;
}
writer.flush();
writer.close();
writer = null;
dateStamp = "";
currentLogFile = null;
|
private org.apache.catalina.valves.AccessLogValve$AccessLogElement | createAccessLogElement(java.lang.String header, char pattern)create an AccessLogElement implementation which needs header string
switch (pattern) {
case 'i":
return new HeaderElement(header);
case 'c":
return new CookieElement(header);
case 'r":
return new RequestAttributeElement(header);
case 's":
return new SessionAttributeElement(header);
default:
return new StringElement("???");
}
|
private org.apache.catalina.valves.AccessLogValve$AccessLogElement | createAccessLogElement(char pattern)create an AccessLogElement implementation
switch (pattern) {
case 'a":
return new RemoteAddrElement();
case 'A":
return new LocalAddrElement();
case 'b":
return new ByteSentElement(true);
case 'B":
return new ByteSentElement(false);
case 'D":
return new ElapsedTimeElement(true);
case 'h":
return new HostElement();
case 'H":
return new ProtocolElement();
case 'l":
return new LogicalUserNameElement();
case 'm":
return new MethodElement();
case 'p":
return new LocalPortElement();
case 'q":
return new QueryElement();
case 'r":
return new RequestElement();
case 's":
return new HttpStatusCodeElement();
case 'S":
return new SessionIdElement();
case 't":
return new DateAndTimeElement();
case 'T":
return new ElapsedTimeElement(false);
case 'u":
return new UserElement();
case 'U":
return new RequestURIElement();
case 'v":
return new LocalServerNameElement();
default:
return new StringElement("???" + pattern + "???");
}
|
protected org.apache.catalina.valves.AccessLogValve$AccessLogElement[] | createLogElements()parse pattern string and create the array of AccessLogElement
List<AccessLogElement> list = new ArrayList<AccessLogElement>();
boolean replace = false;
StringBuffer buf = new StringBuffer();
for (int i = 0; i < pattern.length(); i++) {
char ch = pattern.charAt(i);
if (replace) {
/*
* For code that processes {, the behavior will be ... if I do
* not enounter a closing } - then I ignore the {
*/
if ('{" == ch) {
StringBuffer name = new StringBuffer();
int j = i + 1;
for (; j < pattern.length() && '}" != pattern.charAt(j); j++) {
name.append(pattern.charAt(j));
}
if (j + 1 < pattern.length()) {
/* the +1 was to account for } which we increment now */
j++;
list.add(createAccessLogElement(name.toString(),
pattern.charAt(j)));
i = j; /* Since we walked more than one character */
} else {
// D'oh - end of string - pretend we never did this
// and do processing the "old way"
list.add(createAccessLogElement(ch));
}
} else {
list.add(createAccessLogElement(ch));
}
replace = false;
} else if (ch == '%") {
replace = true;
list.add(new StringElement(buf.toString()));
buf = new StringBuffer();
} else {
buf.append(ch);
}
}
if (buf.length() > 0) {
list.add(new StringElement(buf.toString()));
}
return (AccessLogElement[]) list.toArray(new AccessLogElement[0]);
|
public org.apache.catalina.LifecycleListener[] | findLifecycleListeners()Get the lifecycle listeners associated with this lifecycle. If this
Lifecycle has no listeners registered, a zero-length array is returned.
return lifecycle.findLifecycleListeners();
|
public java.lang.String | getCondition()Return whether the attribute name to look for when
performing conditional loggging. If null, every
request is logged.
return condition;
|
private java.util.Date | getDate()This method returns a Date object that is accurate to within one second.
If a thread calls this method to get a Date and it's been less than 1
second since a new Date was created, this method simply gives out the
same Date again so that the system doesn't spend time creating Date
objects unnecessarily.
// Only create a new Date once per second, max.
long systime = System.currentTimeMillis();
if ((systime - currentMillis) > 1000) {
synchronized (this) {
if ((systime - currentMillis) > 1000) {
currentDate = new Date(systime);
currentMillis = systime;
}
}
}
return currentDate;
|
public java.lang.String | getDirectory()Return the directory in which we create log files.
return (directory);
|
public boolean | getEnabled()
// ------------------------------------------------------------- Properties
return enabled;
|
public java.lang.String | getFileDateFormat()Return the date format date based log rotation.
return fileDateFormat;
|
public java.lang.String | getInfo()Return descriptive information about this implementation.
return (info);
|
public java.lang.String | getPattern()Return the format pattern.
return (this.pattern);
|
public java.lang.String | getPrefix()Return the log file prefix.
return (prefix);
|
public java.lang.String | getSuffix()Return the log file suffix.
return (suffix);
|
private java.lang.String | getTimeZone(java.util.Date date)
if (timezone.inDaylightTime(date)) {
return timeZoneDST;
} else {
return timeZoneNoDST;
}
|
public void | invoke(org.apache.catalina.connector.Request request, org.apache.catalina.connector.Response response)Log a message summarizing the specified request and response, according
to the format specified by the pattern property.
if (started && getEnabled()) {
// Pass this request on to the next valve in our pipeline
long t1 = System.currentTimeMillis();
getNext().invoke(request, response);
long t2 = System.currentTimeMillis();
long time = t2 - t1;
if (logElements == null || condition != null
&& null != request.getRequest().getAttribute(condition)) {
return;
}
Date date = getDate();
StringBuffer result = new StringBuffer();
for (int i = 0; i < logElements.length; i++) {
logElements[i].addElement(result, date, request, response, time);
}
log(result.toString());
} else
getNext().invoke(request, response);
|
public boolean | isBuffered()Is the logging buffered
return buffered;
|
public boolean | isCheckExists()Check for file existence before logging.
return checkExists;
|
public boolean | isResolveHosts()Get the value of the resolve hosts flag.
return resolveHosts;
|
public boolean | isRotatable()Should we rotate the logs
return rotatable;
|
public void | log(java.lang.String message)Log the specified message to the log file, switching files if the date
has changed since the previous log call.
if (rotatable) {
// Only do a logfile switch check once a second, max.
long systime = System.currentTimeMillis();
if ((systime - rotationLastChecked) > 1000) {
// We need a new currentDate
currentDate = new Date(systime);
rotationLastChecked = systime;
// Check for a change of date
String tsDate = fileDateFormatter.format(currentDate);
// If the date has changed, switch log files
if (!dateStamp.equals(tsDate)) {
synchronized (this) {
if (!dateStamp.equals(tsDate)) {
close();
dateStamp = tsDate;
open();
}
}
}
}
}
/* In case something external rotated the file instead */
if (checkExists) {
synchronized (this) {
if (currentLogFile != null && !currentLogFile.exists()) {
try {
close();
} catch (Throwable e) {
log.info("at least this wasn't swallowed", e);
}
/* Make sure date is correct */
currentDate = new Date(System.currentTimeMillis());
dateStamp = fileDateFormatter.format(currentDate);
open();
}
}
}
// Log this message
if (writer != null) {
writer.println(message);
if (!buffered) {
writer.flush();
}
}
|
private java.lang.String | lookup(java.lang.String month)Return the month abbreviation for the specified month, which must
be a two-digit String.
int index;
try {
index = Integer.parseInt(month) - 1;
} catch (Throwable t) {
index = 0; // Can not happen, in theory
}
return (months[index]);
|
protected synchronized void | open()Open the new log file for the date specified by dateStamp .
// Create the directory if necessary
File dir = new File(directory);
if (!dir.isAbsolute())
dir = new File(System.getProperty("catalina.base"), directory);
dir.mkdirs();
// Open the current log file
try {
String pathname;
// If no rotate - no need for dateStamp in fileName
if (rotatable) {
pathname = dir.getAbsolutePath() + File.separator + prefix
+ dateStamp + suffix;
} else {
pathname = dir.getAbsolutePath() + File.separator + prefix
+ suffix;
}
writer = new PrintWriter(new BufferedWriter(new FileWriter(
pathname, true), 128000), false);
currentLogFile = new File(pathname);
} catch (IOException e) {
writer = null;
currentLogFile = null;
}
|
public void | removeLifecycleListener(org.apache.catalina.LifecycleListener listener)Remove a lifecycle event listener from this component.
lifecycle.removeLifecycleListener(listener);
|
public synchronized boolean | rotate(java.lang.String newFileName)Rename the existing log file to something else. Then open the
old log file name up once again. Intended to be called by a JMX
agent.
if (currentLogFile != null) {
File holder = currentLogFile;
close();
try {
holder.renameTo(new File(newFileName));
} catch (Throwable e) {
log.error("rotate failed", e);
}
/* Make sure date is correct */
currentDate = new Date(System.currentTimeMillis());
dateStamp = fileDateFormatter.format(currentDate);
open();
return true;
} else {
return false;
}
|
public void | setBuffered(boolean buffered)Set the value if the logging should be buffered
this.buffered = buffered;
|
public void | setCheckExists(boolean checkExists)Set whether to check for log file existence before logging.
this.checkExists = checkExists;
|
public void | setCondition(java.lang.String condition)Set the ServletRequest.attribute to look for to perform
conditional logging. Set to null to log everything.
this.condition = condition;
|
public void | setDirectory(java.lang.String directory)Set the directory in which we create log files.
this.directory = directory;
|
public void | setEnabled(boolean enabled)
this.enabled = enabled;
|
public void | setFileDateFormat(java.lang.String fileDateFormat)Set the date format date based log rotation.
this.fileDateFormat = fileDateFormat;
|
public void | setPattern(java.lang.String pattern)Set the format pattern, first translating any recognized alias.
if (pattern == null)
pattern = "";
if (pattern.equals(Constants.AccessLog.COMMON_ALIAS))
pattern = Constants.AccessLog.COMMON_PATTERN;
if (pattern.equals(Constants.AccessLog.COMBINED_ALIAS))
pattern = Constants.AccessLog.COMBINED_PATTERN;
this.pattern = pattern;
logElements = createLogElements();
|
public void | setPrefix(java.lang.String prefix)Set the log file prefix.
this.prefix = prefix;
|
public void | setResolveHosts(boolean resolveHosts)Set the resolve hosts flag.
this.resolveHosts = resolveHosts;
|
public void | setRotatable(boolean rotatable)Set the value is we should we rotate the logs
this.rotatable = rotatable;
|
public void | setSuffix(java.lang.String suffix)Set the log file suffix.
this.suffix = suffix;
|
public void | start()Prepare for the beginning of active use of the public methods of this
component. This method should be called after configure() ,
and before any of the public methods of the component are utilized.
// Validate and update our current component state
if (started)
throw new LifecycleException(sm
.getString("accessLogValve.alreadyStarted"));
lifecycle.fireLifecycleEvent(START_EVENT, null);
started = true;
// Initialize the timeZone, Date formatters, and currentDate
timezone = TimeZone.getDefault();
timeZoneNoDST = calculateTimeZoneOffset(timezone.getRawOffset());
Calendar calendar = Calendar.getInstance(timezone);
int offset = calendar.get(Calendar.DST_OFFSET);
timeZoneDST = calculateTimeZoneOffset(timezone.getRawOffset() + offset);
if (fileDateFormat == null || fileDateFormat.length() == 0)
fileDateFormat = "yyyy-MM-dd";
fileDateFormatter = new SimpleDateFormat(fileDateFormat);
fileDateFormatter.setTimeZone(timezone);
dayFormatter = new SimpleDateFormat("dd");
dayFormatter.setTimeZone(timezone);
monthFormatter = new SimpleDateFormat("MM");
monthFormatter.setTimeZone(timezone);
yearFormatter = new SimpleDateFormat("yyyy");
yearFormatter.setTimeZone(timezone);
timeFormatter = new SimpleDateFormat("HH:mm:ss");
timeFormatter.setTimeZone(timezone);
currentDate = new Date();
dateStamp = fileDateFormatter.format(currentDate);
open();
|
public void | stop()Gracefully terminate the active use of the public methods of this
component. This method should be the last one called on a given
instance of this component.
// Validate and update our current component state
if (!started)
throw new LifecycleException(sm
.getString("accessLogValve.notStarted"));
lifecycle.fireLifecycleEvent(STOP_EVENT, null);
started = false;
close();
|