
com.sghd.logging.ServerFileAppender Maven / Gradle / Ivy
package com.sghd.logging;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import org.apache.log4j.Appender;
import org.apache.log4j.AppenderSkeleton;
import org.apache.log4j.DailyRollingFileAppender;
import org.apache.log4j.Layout;
import org.apache.log4j.Priority;
import org.apache.log4j.helpers.LogLog;
import org.apache.log4j.helpers.OnlyOnceErrorHandler;
import org.apache.log4j.spi.ErrorHandler;
import org.apache.log4j.spi.Filter;
import org.apache.log4j.spi.LoggingEvent;
import org.apache.log4j.spi.OptionHandler;
public class ServerFileAppender implements Appender, OptionHandler {
private final static Field MESSAGE_FIELD;
static {
try {
MESSAGE_FIELD = LoggingEvent.class.getDeclaredField("renderedMessage");
MESSAGE_FIELD.setAccessible(true);
} catch (Exception exception) {
throw new RuntimeException(exception);
}
}
/**
* The layout variable does not need to be set if the appender implementation has its own layout.
*/
private Layout layout;
/** Appenders are named. */
private String name;
/**
* There is no level threshold filtering by default.
*/
private Priority threshold;
/**
* It is assumed and enforced that errorHandler is never null.
*/
private ErrorHandler errorHandler = new OnlyOnceErrorHandler();
/**
* Is this appender closed?
*/
private boolean closed = false;
/**
* 自定义的Appender映射,每个服对应各自的Appender
*/
private Map appenderMap = new HashMap();
private String datePattern;
private String directoryName;
/**
* Derived appenders should override this method if option structure requires it.
*/
public void activateOptions() {
}
/**
* Add a filter to end of the filter list.
* @since 0.9.0
*/
public void addFilter(Filter newFilter) {
throw new UnsupportedOperationException();
}
/**
* Clear the filters chain.
* @since 0.9.0
*/
public void clearFilters() {
throw new UnsupportedOperationException();
}
/**
* Finalize this appender by calling the derived class' close
method.
* @since 0.8.4
*/
public void finalize() {
// An appender might be closed then garbage collected. There is no
// point in closing twice.
if (this.closed)
return;
LogLog.debug("Finalizing appender named [" + name + "].");
close();
}
/**
* Return the currently set {@link ErrorHandler} for this Appender.
* @since 0.9.0
*/
public synchronized ErrorHandler getErrorHandler() {
return this.errorHandler;
}
/**
* Returns the head Filter.
* @since 1.1
*/
public Filter getFilter() {
throw new UnsupportedOperationException();
}
/**
* Return the first filter in the filter chain for this Appender. The return value may be null
if no is
* filter is set.
*/
public final Filter getFirstFilter() {
throw new UnsupportedOperationException();
}
/**
* Returns the layout of this appender. The value may be null.
*/
public Layout getLayout() {
return layout;
}
/**
* Returns the name of this FileAppender.
*/
public final String getName() {
return this.name;
}
/**
* Returns this appenders threshold level. See the {@link #setThreshold} method for the meaning of this option.
* @since 1.1
*/
public Priority getThreshold() {
return threshold;
}
/**
* Check whether the message level is below the appender's threshold. If there is no threshold set, then the return
* value is always true
.
*/
public boolean isAsSevereAsThreshold(Priority priority) {
return ((threshold == null) || priority.isGreaterOrEqual(threshold));
}
/**
* This method performs threshold checks and invokes filters before delegating actual logging to the subclasses
* specific {@link AppenderSkeleton#append} method.
*/
public synchronized void doAppend(LoggingEvent event) {
if (closed) {
LogLog.error("Attempted to append to closed appender named [" + name + "].");
return;
}
if (!isAsSevereAsThreshold(event.getLevel())) {
return;
}
final String rawMessage = event.getRenderedMessage();
final int sharpIndex = rawMessage.indexOf('#');
final String appenderName = rawMessage.substring(0, sharpIndex);
final String logMessage = rawMessage.substring(sharpIndex + 1);
try {
MESSAGE_FIELD.set(event, logMessage);
} catch (Exception exception) {
throw new RuntimeException(exception);
}
final Appender appender;
if (this.appenderMap.get(appenderName) != null) {
appender = this.appenderMap.get(appenderName);
} else {
final String fileName = this.directoryName + '/' + appenderName + ".log";
try {
appender = new DailyRollingFileAppender(layout, fileName, datePattern);
this.appenderMap.put(appenderName, appender);
} catch (IOException exception) {
exception.printStackTrace();
throw new RuntimeException(exception);
}
}
appender.doAppend(event);
}
/**
* Set the {@link ErrorHandler} for this Appender.
* @since 0.9.0
*/
public synchronized void setErrorHandler(ErrorHandler eh) {
if (eh == null) {
// We do not throw exception here since the cause is probably a
// bad config file.
LogLog.warn("You have tried to set a null error-handler.");
} else {
this.errorHandler = eh;
}
}
/**
* Set the layout for this appender. Note that some appenders have their own (fixed) layouts or do not use one. For
* example, the {@link org.apache.log4j.net.SocketAppender} ignores the layout set here.
*/
public void setLayout(Layout layout) {
this.layout = layout;
}
/**
* Set the name of this Appender.
*/
public void setName(String name) {
this.name = name;
}
/**
* Set the threshold level. All log events with lower level than the threshold level are ignored by the appender.
*
* In configuration files this option is specified by setting the value of the Threshold option to a level
* string, such as "DEBUG", "INFO" and so on.
* @since 0.8.3
*/
public void setThreshold(Priority threshold) {
this.threshold = threshold;
}
@Override
public void close() {
for (Appender appender : this.appenderMap.values()) {
appender.close();
}
}
@Override
public boolean requiresLayout() {
return true;
}
public void setDatePattern(String pattern) {
datePattern = pattern;
}
public String getDatePattern() {
return datePattern;
}
public String getDirectoryName() {
return directoryName;
}
public void setDirectoryName(String directoryName) {
this.directoryName = directoryName;
}
}