问题描述
我想创建一个自定义的 log4j2 滚动文件附加程序.我需要创建这个自定义 appender,因为我想用我的应用程序独有的一些信息来包装 log4j 日志事件.例如userId,托管应用程序名称.
I want to create a custom log4j2 rolling file appender. I need to create this custom appender because I want to wrap the log4j log event with some information unique to my application. Such as userId, hosted application name.
我有一个扩展 Log4jLogEvent 实现 LogEvent 的类.这个类有我需要用日志事件包装的信息.请参阅此代码:
I have a class which extends Log4jLogEvent implements LogEvent. This class has information that I need to wrap with the log event.Please see this code :
public class CustomLogEvent extends Log4jLogEvent implements LogEvent {
private String userId;
private String applicationName;
private static final long serialVersionUID = 1L;
public CustomLogEvent(String loggerName, Marker marker, String loggerFQCN, Level level, Message message, Throwable t, Map<String, String> mdc, ThreadContext.ContextStack ndc, String threadName, StackTraceElement location, long timestamp){
super(loggerName,marker,loggerFQCN,level,message,t,mdc,ndc,threadName,location,timestamp);
}
//Getters and setters for user Id and app name
}
在 log4j2 中,由于我们无法像使用 log4j 1.2 那样扩展滚动文件附加程序,因此我通过查看原始滚动文件附加程序的源代码创建了新的滚动文件附加程序.此类扩展 AbstractOutputStreamAppender.
In log4j2 since we cannot extend rolling file appender like we did with log4j 1.2, I created new rolling file appender by seeing the source code of original rolling file appender. This class extends AbstractOutputStreamAppender.
这是我为滚动文件追加器编写的代码.
This is the code I have written for rolling file appender.
@Plugin(name = "MyRollingFileAppender", category = "Core", elementType = "appender", printObject = true)
public class MyRollingFileAppender extends AbstractOutputStreamAppender<RollingFileManager> {
private static final int DEFAULT_BUFFER_SIZE = 8192;
private static final long serialVersionUID = 1L;
private final String fileName;
private final String filePattern;
private Object advertisement;
private final Advertiser advertiser;
private MyRollingFileAppender(final String name, final Layout<? extends Serializable> layout, final Filter filter,
final RollingFileManager manager, final String fileName, final String filePattern,
final boolean ignoreExceptions, final boolean immediateFlush, final Advertiser advertiser) {
super(name, layout, filter, ignoreExceptions, immediateFlush, manager);
if (advertiser != null) {
final Map<String, String> configuration = new HashMap<String, String>(layout.getContentFormat());
configuration.put("contentType", layout.getContentType());
configuration.put("name", name);
advertisement = advertiser.advertise(configuration);
}
this.fileName = fileName;
this.filePattern = filePattern;
this.advertiser = advertiser;
}
@Override
public void append(final LogEvent logEvent) {
int userId = //get user Id
String appplicatinName = //get application name
GetLoggingEvent myLogEvent = new GetLoggingEvent();
LogEvent customLogEvent = myLogEvent.getCustomLogEvent(logEvent, userId, applicationName);
getManager().checkRollover(customLogEvent);
super.append(customLogEvent);
}
@PluginFactory
public static MyRollingFileAppender createAppender(
@PluginAttribute("fileName") final String fileName,
@PluginAttribute("filePattern") final String filePattern,
@PluginAttribute("append") final String append,
@PluginAttribute("name") final String name,
@PluginAttribute("bufferedIO") final String bufferedIO,
@PluginAttribute("bufferSize") final String bufferSizeStr,
@PluginAttribute("immediateFlush") final String immediateFlush,
@PluginElement("Policy") final TriggeringPolicy policy,
@PluginElement("Strategy") RolloverStrategy strategy,
@PluginElement("Layout") Layout<? extends Serializable> layout,
@PluginElement("Filter") final Filter filter,
@PluginAttribute("ignoreExceptions") final String ignore,
@PluginAttribute("advertise") final String advertise,
@PluginAttribute("advertiseURI") final String advertiseURI,
@PluginConfiguration final Configuration config) {
final boolean isAppend = Booleans.parseBoolean(append, true);
final boolean ignoreExceptions = Booleans.parseBoolean(ignore, true);
final boolean isBuffered = Booleans.parseBoolean(bufferedIO, true);
final boolean isFlush = Booleans.parseBoolean(immediateFlush, true);
final boolean isAdvertise = Boolean.parseBoolean(advertise);
final int bufferSize = Integers.parseInt(bufferSizeStr, DEFAULT_BUFFER_SIZE);
if (!isBuffered && bufferSize > 0) {
LOGGER.warn("The bufferSize is set to {} but bufferedIO is not true: {}", bufferSize, bufferedIO);
}
if (name == null) {
LOGGER.error("No name provided for FileAppender");
return null;
}
if (fileName == null) {
LOGGER.error("No filename was provided for FileAppender with name " + name);
return null;
}
if (filePattern == null) {
LOGGER.error("No filename pattern provided for FileAppender with name " + name);
return null;
}
if (policy == null) {
LOGGER.error("A TriggeringPolicy must be provided");
return null;
}
if (strategy == null) {
strategy = DefaultRolloverStrategy.createStrategy(null, null, null,
String.valueOf(Deflater.DEFAULT_COMPRESSION), config);
}
if (layout == null) {
layout = PatternLayout.createDefaultLayout();
}
final RollingFileManager manager = RollingFileManager.getFileManager(fileName, filePattern, isAppend,
isBuffered, policy, strategy, advertiseURI, layout, bufferSize);
if (manager == null) {
return null;
}
return new MyRollingFileAppender(name, layout, filter, manager, fileName, filePattern,
ignoreExceptions, isFlush, isAdvertise ? config.getAdvertiser() : null);
}
}
我从 log4j 1.2 升级到 log4j2 的应用程序使用 Apache commons API,因此我无法使用线程上下文映射来添加信息.
The application I'm upgrading from log4j 1.2 to log4j2 uses Apache commons API therefore I cannot use thread context maps to add information.
这个 appender 目前工作正常.但是我对我的程序有些困惑.
This appender works fine for now.However I have some confusions of my procedure.
我想确保我这样做的方式(即用自定义信息包装日志事件并为自定义信息创建滚动文件附加程序)是正确的,并且由于我们无法扩展现有的滚动文件附加程序,我需要重新在我的自定义类中编写滚动文件附加程序的所有代码,以便在日志事件中再添加两个字段?有没有简单的方法来做同样的事情?
I want to make sure that the way I'm doing this (i.e wrapping log event with custom information and creating the rolling file appender for custom information) is correct and since we cannot extend existing rolling file appender do I need to re write all the code of rolling file appender in my custom class to just add two more fields in to the log event?Is there any easy way to do the same ?
谢谢!
推荐答案
您要升级的应用程序使用 Apache Commons Logging,并且 Commons Logging API 中没有 ThreadContext 映射.
The application you are upgrading uses Apache Commons Logging, and there is no ThreadContext map in the Commons Logging API.
但是,您可以通过在应用程序中简单地使用 log4j2 ThreadContext 映射来完成您的对象.这样你就不需要任何自定义日志事件或 appender 子类.
However, you can accomplish your object by simply using the log4j2 ThreadContext map in your application. That way you don't need any custom log events or appender subclasses.
您的应用程序中应该只有少数几个地方可以设置或修改用户 ID.在这些地方,添加以下代码行:
There should only be a few places in your application where the userID is set or modified. In those places, add these lines of code:
int userId = //get user Id
String appplicationName = //get application name
ThreadContext.put("userID", String.valueOf(userId));
ThreadContext.put("appplicationName", appplicationName);
// ... your business logic
如果将 Commons Logging 委托给 log4j2,您可以配置如下模式布局:"%-5p [%t] %c: %X{userID}/%{appplicationName} %m%n"代码> 使您的值出现在日志中.
If Commons Logging is delegated to log4j2, you can configure a pattern layout like: "%-5p [%t] %c: %X{userID}/%{appplicationName} %m%n"
to make your values appear in the log.
这篇关于如何在 log4j2 中创建滚动文件 appender 插件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!