mirror of
https://github.com/apache/cloudstack.git
synced 2025-12-15 18:12:35 +01:00
242 lines
7.2 KiB
Java
242 lines
7.2 KiB
Java
/*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
* this work for additional information regarding copyright ownership.
|
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
|
* (the "License"); you may not use this file except in compliance with
|
|
* the License. You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
|
|
|
|
package org.apache.log4j;
|
|
|
|
import java.io.IOException;
|
|
import java.io.Writer;
|
|
import java.io.FileWriter;
|
|
import java.io.File;
|
|
import java.io.OutputStream;
|
|
import java.io.OutputStreamWriter;
|
|
import java.text.SimpleDateFormat;
|
|
import java.util.Date;
|
|
import org.apache.log4j.helpers.OptionConverter;
|
|
import org.apache.log4j.helpers.QuietWriter;
|
|
import org.apache.log4j.helpers.CountingQuietWriter;
|
|
import org.apache.log4j.spi.LoggingEvent;
|
|
import org.apache.log4j.spi.ErrorCode;
|
|
|
|
/**
|
|
DailyFileAppender extends FileAppender to use filenames formatted with
|
|
date/time information. The filename is recomputed every day at midnight.
|
|
Note that the filename doesn't have to change every day, making it possible
|
|
to have logfiles which are per-week or per-month.
|
|
|
|
The appender computes the proper filename using the formats specified in
|
|
<a href="http://java.sun.com/j2se/1.3/docs/api/java/text/SimpleDateFormat.html">
|
|
java.text.SimpleDateFormat</a>. The format requires that most static text is
|
|
enclosed in single quotes, which are removed. The examples below show how
|
|
quotes are used to embed static information in the format.
|
|
|
|
Sample filenames:
|
|
|
|
<code>
|
|
Filename pattern Filename
|
|
"'/logs/trace-'yyyy-MM-dd'.log'" /logs/trace-2000-12-31.log
|
|
"'/logs/trace-'yyyy-ww'.log'" /logs/trace-2000-52.log
|
|
</code>
|
|
|
|
@author <a HREF="mailto:eirik.lygre@evita.no">Eirik Lygre</a>
|
|
*/
|
|
public class DailyFileAppender extends FileAppender {
|
|
|
|
/**
|
|
A string constant used in naming the option for setting the
|
|
filename pattern. Current value of this string constant is
|
|
<strong>FileNamePattern</strong>.
|
|
*/
|
|
static final public String FILE_NAME_PATTERN_OPTION = "FilePattern";
|
|
|
|
/**
|
|
The filename pattern
|
|
*/
|
|
private String fileNamePattern = null;
|
|
|
|
/**
|
|
The actual formatted filename that is currently being written to
|
|
*/
|
|
private String currentFileName = null;
|
|
|
|
/**
|
|
The timestamp when we shall next recompute the filename
|
|
*/
|
|
private long nextFilenameComputingMillis = System.currentTimeMillis () - 1;
|
|
|
|
/**
|
|
The default constructor does no longer set a default layout nor a
|
|
default output target. */
|
|
public
|
|
DailyFileAppender() {
|
|
}
|
|
|
|
/**
|
|
Instantiate a RollingFileAppender and open the file designated by
|
|
<code>filename</code>. The opened filename will become the ouput
|
|
destination for this appender.
|
|
|
|
<p>If the <code>append</code> parameter is true, the file will be
|
|
appended to. Otherwise, the file desginated by
|
|
<code>filename</code> will be truncated before being opened.
|
|
*/
|
|
public DailyFileAppender (Layout layout,String filename,boolean append) throws IOException {
|
|
super(layout, filename, append);
|
|
}
|
|
|
|
/**
|
|
Instantiate a FileAppender and open the file designated by
|
|
<code>filename</code>. The opened filename will become the output
|
|
destination for this appender.
|
|
|
|
<p>The file will be appended to. */
|
|
public DailyFileAppender (Layout layout,String filename) throws IOException {
|
|
super(layout, filename);
|
|
}
|
|
|
|
/**
|
|
Set the current output file.
|
|
|
|
The function will compute a new filename, and open a new file only
|
|
when the name has changed.
|
|
|
|
The function is automatically called once a day, to allow for
|
|
daily files -- the purpose of this class.
|
|
*/
|
|
|
|
public
|
|
synchronized
|
|
void setFile(String fileName, boolean append) throws IOException {
|
|
|
|
/* Compute filename, but only if fileNamePattern is specified */
|
|
if (fileNamePattern == null) {
|
|
errorHandler.error("Missing file pattern (" + FILE_NAME_PATTERN_OPTION + ") in setFile().");
|
|
return;
|
|
}
|
|
|
|
Date now = new Date();
|
|
|
|
fileName = new SimpleDateFormat(fileNamePattern).format (now);
|
|
if (fileName.equals(currentFileName))
|
|
return;
|
|
|
|
/* Set up next filename checkpoint */
|
|
DailyFileAppenderCalendar c = new DailyFileAppenderCalendar();
|
|
c.rollToNextDay ();
|
|
nextFilenameComputingMillis = c.getTimeInMillis ();
|
|
|
|
currentFileName = fileName;
|
|
|
|
super.setFile(fileName, append);
|
|
}
|
|
|
|
/**
|
|
This method differentiates RollingFileAppender from its super
|
|
class.
|
|
|
|
*/
|
|
protected
|
|
void subAppend(LoggingEvent event) {
|
|
|
|
if (System.currentTimeMillis () >= nextFilenameComputingMillis) {
|
|
try {
|
|
setFile (super.fileName, super.fileAppend);
|
|
}
|
|
catch(IOException e) {
|
|
System.err.println("setFile(null, false) call failed.");
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
|
|
super.subAppend(event);
|
|
}
|
|
|
|
/**
|
|
Retuns the option names for this component, namely {@link
|
|
#FILE_NAME_PATTERN_OPTION} in
|
|
addition to the options of {@link FileAppender#getOptionStrings
|
|
FileAppender}.
|
|
*/
|
|
public
|
|
String[] getOptionStrings() {
|
|
|
|
return OptionConverter.concatanateArrays(super.getOptionStrings(),
|
|
new String[] {FILE_NAME_PATTERN_OPTION});
|
|
}
|
|
|
|
/**
|
|
Set the options for the appender
|
|
*/
|
|
public
|
|
void setOption(String key, String value) {
|
|
super.setOption(key, value);
|
|
if(key.equalsIgnoreCase(FILE_NAME_PATTERN_OPTION)) {
|
|
fileNamePattern = value;
|
|
}
|
|
}
|
|
|
|
/**
|
|
If the a value for {@link #FILE_OPTION} is non-null, then {@link
|
|
#setFile} is called with the values of {@link #FILE_OPTION} and
|
|
{@link #APPEND_OPTION}.
|
|
|
|
@since 0.8.1 */
|
|
public
|
|
void activateOptions() {
|
|
try {
|
|
setFile(null, super.fileAppend);
|
|
}
|
|
catch(java.io.IOException e) {
|
|
errorHandler.error("setFile(null,"+fileAppend+") call failed.",
|
|
e, ErrorCode.FILE_OPEN_FAILURE);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
DailyFileAppenderCalendar is a helper class to DailyFileAppender. Using
|
|
this class, it is easy to compute and access the next Millis()
|
|
|
|
It subclasses the standard
|
|
<a href="http://java.sun.com/j2se/1.3/docs/api/java/text/GregorianCalendar.html">
|
|
java.util.GregorianCalendar</a>-object, to allow access to the protected
|
|
function getTimeInMillis(), which it then exports.
|
|
|
|
@author <a HREF="mailto:eirik.lygre@evita.no">Eirik Lygre</a>
|
|
*/
|
|
class DailyFileAppenderCalendar extends java.util.GregorianCalendar
|
|
{
|
|
/**
|
|
Returns the current time in Millis
|
|
*/
|
|
public long getTimeInMillis() {
|
|
return super.getTimeInMillis();
|
|
}
|
|
|
|
/**
|
|
Roll the date to the next hour, with minute, second and millisecond
|
|
set to zero.
|
|
*/
|
|
public void rollToNextDay () {
|
|
this.add(java.util.Calendar.DATE, 0);
|
|
this.add(java.util.Calendar.HOUR, 0);
|
|
this.set(java.util.Calendar.MINUTE, 0);
|
|
this.set(java.util.Calendar.SECOND, 0);
|
|
this.set(java.util.Calendar.MILLISECOND, 0);
|
|
}
|
|
} |