Resih problem, pa rekoh, mozda ce nekom nekada trebati.
Napravio sam svoj Appender, slican RollingFileAppender-u:
Code:
package com.wm.sdf.logging.log4j;
import java.io.IOException;
import java.io.Writer;
import java.io.File;
import org.apache.commons.io.FileUtils;
import org.apache.log4j.FileAppender;
import org.apache.log4j.Layout;
import org.apache.log4j.helpers.LogLog;
import org.apache.log4j.spi.LoggingEvent;
/**
* RollingFileAppender extends FileAppender to backup the log files when they
* reach a certain number of lines.
*
* @author nemanjar
*/
public class SDFRollingFileAppender extends FileAppender {
/**
* The default maximum number of lines per file.
*/
protected int maxFileLines = 5;
/**
* There is one backup file by default.
*/
protected int maxBackupIndex = 1;
private long nextRollover = 0;
/**
* The default constructor simply calls its
* {@link FileAppender#FileAppender parents constructor}.
*/
public SDFRollingFileAppender() {
super();
}
/**
* 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 SDFRollingFileAppender(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 SDFRollingFileAppender(Layout layout, String filename) throws IOException {
super(layout, filename);
}
/**
* Implements the usual roll over behaviour.
* <p>
* If <code>MaxBackupIndex</code> is equal to zero, then the
* <code>File</code> is truncated with no backup files created.
*/
public// synchronization not necessary since doAppend is alreasy synched
void rollOver() {
File target;
File file;
if (qw != null) {
long size = ((SDFCountingQuietWriter) qw).getCount();
LogLog.debug("rolling over count=" + size);
// if operation fails, do not roll again until
// maxFileLines are exceeded
nextRollover = size + maxFileLines;
}
LogLog.debug("maxBackupIndex=" + maxBackupIndex);
boolean renameSucceeded = true;
// If maxBackups <= 0, then there is no file renaming to be done.
if (maxBackupIndex > 0) {
// Delete the oldest file, to keep Windows happy.
file = new File(fileName + '.' + maxBackupIndex);
if (file.exists())
renameSucceeded = file.delete();
// Map {(maxBackupIndex - 1), ..., 2, 1} to {maxBackupIndex, ..., 3,
// 2}
for (int i = maxBackupIndex - 1; i >= 1 && renameSucceeded; i--) {
file = new File(fileName + "." + i);
if (file.exists()) {
target = new File(fileName + '.' + (i + 1));
LogLog.debug("Renaming file " + file + " to " + target);
renameSucceeded = file.renameTo(target);
}
}
if (renameSucceeded) {
// Rename fileName to fileName.1
target = new File(fileName + "." + 1);
this.closeFile(); // keep windows happy.
file = new File(fileName);
LogLog.debug("Renaming file " + file + " to " + target);
renameSucceeded = file.renameTo(target);
//
// if file rename failed, reopen file with append = true
//
if (!renameSucceeded) {
try {
this.setFile(fileName, true, bufferedIO, bufferSize);
}
catch (IOException e) {
LogLog.error("setFile(" + fileName + ", true) call failed.", e);
}
}
}
}
// if all renames were successful, then
if (renameSucceeded) {
try {
// This will also close the file. This is OK since multiple
// close operations are safe.
this.setFile(fileName, false, bufferedIO, bufferSize);
nextRollover = 0;
}
catch (IOException e) {
LogLog.error("setFile(" + fileName + ", false) call failed.", e);
}
}
}
public synchronized void setFile(String fileName, boolean append, boolean bufferedIO, int bufferSize)
throws IOException {
super.setFile(fileName, append, this.bufferedIO, this.bufferSize);
if (append) {
File f = new File(fileName);
((SDFCountingQuietWriter) qw).setCount(FileUtils.readLines(f).size());
}
}
/**
* Returns the value of the <b>MaxBackupIndex</b> option.
*/
public int getMaxBackupIndex() {
return maxBackupIndex;
}
/**
* Set the maximum number of backup files to keep around.
*
* <p>
* The <b>MaxBackupIndex</b> option determines how many backup files are
* kept before the oldest is erased. This option takes a positive integer
* value. If set to zero, then there will be no backup files and the log
* file will be truncated when it reaches <code>MaxFileLines</code>.
*/
public void setMaxBackupIndex(int maxBackups) {
this.maxBackupIndex = maxBackups;
}
/**
* Returns the value of the <b>MaxFileLines</b> option.
*/
public int getMaxFileLines() {
return maxFileLines;
}
/**
* Set the maximum number of lines
*
* <p>
* The <b>MaxFileLines</b> option determines how lines would be written
* before making a new file. This option takes a positive integer
* value.
*/
public void setMaxFileLines(int maxFileLines) {
this.maxFileLines = maxFileLines;
}
protected void setQWForFiles(Writer writer) {
this.qw = new SDFCountingQuietWriter(writer, errorHandler);
}
/**
* This method differentiates SDFRollingFileAppender from its super class.
*/
protected void subAppend(LoggingEvent event) {
super.subAppend(event);
if (fileName != null && qw != null) {
long size = ((SDFCountingQuietWriter) qw).getCount();
if (size >= maxFileLines && size >= nextRollover) {
rollOver();
}
}
}
}
A onda sam napravio i svoj Writer:
Code:
package com.wm.sdf.logging.log4j;
import java.io.Writer;
import java.io.IOException;
import org.apache.log4j.helpers.QuietWriter;
import org.apache.log4j.spi.ErrorHandler;
import org.apache.log4j.spi.ErrorCode;
/**
* Counts the number of bytes written.
*
* @author Heinz Richter,
[email protected]
* @since 0.8.1
*/
public class SDFCountingQuietWriter extends QuietWriter {
protected long count;
public SDFCountingQuietWriter(Writer writer, ErrorHandler eh) {
super(writer, eh);
}
public void write(String string) {
try {
out.write(string);
count++;
}
catch (IOException e) {
errorHandler.error("Write failure.", e, ErrorCode.WRITE_FAILURE);
}
}
public long getCount() {
return count;
}
public void setCount(long count) {
this.count = count;
}
}
I naravno, deo datoteke log4j.properties ima sledeci izgled:
Code:
log4j.logger.log2file = INFO, report-file
log4j.appender.report-file=com.wm.sdf.logging.log4j.SDFRollingFileAppender
log4j.appender.report-file.File=sdf-report.log
log4j.appender.report-file.MaxFileLines=4
log4j.appender.report-file.MaxBackupIndex=5
log4j.appender.report-file.layout=org.apache.log4j.PatternLayout
log4j.appender.report-file.layout.ConversionPattern=%m
Nadam se da ce nekom koristiti. :)