log4j2 自定义layout 出错 error RollingFile contains an invalid element or attribute FLayout
使用的是log4j2 -2.8.1版本。
自定义了一个FLayout如下package com.common;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.Date;
import java.util.List;import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.Node;
import org.apache.logging.log4j.core.Layout;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
import org.apache.logging.log4j.core.config.plugins.PluginFactory;
import org.apache.logging.log4j.core.layout.AbstractStringLayout;
import org.apache.logging.log4j.core.pattern.LogEventPatternConverter;
import org.apache.logging.log4j.core.pattern.PatternFormatter;
import org.apache.logging.log4j.core.pattern.PatternParser;@Plugin(name = "FLayout", category = Node.CATEGORY, elementType = Layout.ELEMENT_TYPE, printObject = true)
public final class FLayout extends AbstractStringLayout {
private static final String KEY = "Converter";
private final PatternSerializer fPatternSerializer; private FLayout(final Configuration config,final Charset charset,final String pattern,final String headerPattern,
final String footerPattern) {
super(config,charset,new PatternSerializer(getPatternFormatter(config,headerPattern)),
new PatternSerializer(getPatternFormatter(config,footerPattern)));
this.fPatternSerializer=new PatternSerializer(getPatternFormatter(config,pattern));
} @PluginFactory
public static FLayout createLayout( @PluginConfiguration final Configuration config,
@PluginAttribute(value = "charset", defaultString = "UTF-8") final Charset charset,
@PluginAttribute("pattern")String pattern,
@PluginAttribute("header") String headerPattern,
@PluginAttribute("footer") String footerPattern) {
if(pattern==null){
pattern="%d{yyyy/MM/dd HH:mm:ss.SSS} : %m%n";
}
if(headerPattern==null){
headerPattern="%m%n";
}
if(footerPattern==null){
footerPattern="%m%n";
}
return new FLayout(config,charset,pattern,headerPattern,footerPattern);
}
@Override
public String toSerializable(final LogEvent event) {
return this.fPatternSerializer.toSerializable(event);
}
public static PatternFormatter[] getPatternFormatter(final Configuration config,final String pattern){
final PatternParser parser = createPatternParser(config);
final List<PatternFormatter> list = parser.parse(pattern);
final PatternFormatter[] formatters = list.toArray(new PatternFormatter[0]);
return formatters;
}
public static PatternParser createPatternParser(final Configuration config) {
if (config == null) {
return new PatternParser(config, KEY, LogEventPatternConverter.class);
}
PatternParser parser = config.getComponent(KEY);
if (parser == null) {
parser = new PatternParser(config, KEY, LogEventPatternConverter.class);
config.addComponent(KEY, parser);
parser = config.getComponent(KEY);
}
return parser;
} @Override
public byte[] toByteArray(LogEvent loge) {
if ((loge == null)) {
return null;
}
String formatLoge =toSerializable(loge);
return formatLoge.getBytes();
} }package com.common;import java.util.Arrays;import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.layout.AbstractStringLayout.Serializer;
import org.apache.logging.log4j.core.layout.AbstractStringLayout.Serializer2;
import org.apache.logging.log4j.core.pattern.PatternFormatter;
import org.apache.logging.log4j.util.PropertiesUtil;public class PatternSerializer implements Serializer, Serializer2 { public final PatternFormatter[] formatters;
public PatternSerializer(final PatternFormatter[] formatters) {
super();
this.formatters = formatters; }
protected static final int DEFAULT_STRING_BUILDER_SIZE = 1024; protected static final int MAX_STRING_BUILDER_SIZE = Math.max(DEFAULT_STRING_BUILDER_SIZE,
size("log4j.layoutStringBuilder.maxSize", 2 * 1024));
private static final ThreadLocal<StringBuilder> threadLocal = new ThreadLocal<>(); /**
* Returns a {@code StringBuilder} that this Layout implementation can use to write the formatted log event to.
*
* @return a {@code StringBuilder}
*/
protected static StringBuilder getStringBuilder() {
StringBuilder result = threadLocal.get();
if (result == null) {
result = new StringBuilder(DEFAULT_STRING_BUILDER_SIZE);
threadLocal.set(result);
}
trimToMaxSize(result);
result.setLength(0);
return result;
}
@Override
public String toSerializable( LogEvent event) {
final StringBuilder sb = getStringBuilder();
try {
return toSerializable(event, sb).toString();
} finally {
trimToMaxSize(sb);
}
}
private static int size(final String property, final int defaultValue) {
return PropertiesUtil.getProperties().getIntegerProperty(property, defaultValue);
}
protected static void trimToMaxSize(final StringBuilder stringBuilder) {
if (stringBuilder.length() > MAX_STRING_BUILDER_SIZE) {
stringBuilder.setLength(MAX_STRING_BUILDER_SIZE);
stringBuilder.trimToSize();
}
}
@Override
public StringBuilder toSerializable(final LogEvent event, final StringBuilder buffer) {
final int len = formatters.length;
for (int i = 0; i < len; i++) {
formatters[i].format(event, buffer);
}
String str = buffer.toString();
buffer.setLength(0);
buffer.append(str); return buffer;
}
@Override
public String toString() {
final StringBuilder builder = new StringBuilder();
builder.append(super.toString());
builder.append("[formatters=");
builder.append(Arrays.toString(formatters));
builder.append("]");
return builder.toString();
}
}使用路径来加载配置文件,配置文件如下
<?xml version="1.0" encoding="Shift_JIS"?> <Configuration packages="com.common">
<Properties>
<Property name="log_path">C:/workspace/logs/</Property>
<!-- 部署到server上更换为具体的log路径-->
</Properties>
<Appenders>
<RollingFile name="RollingFile" fileName="${log_path}/f.log" append="true"
filePattern="${log_path}/f.log.%d{yyyyMMdd}">
<FLayout charset="Shift_JIS" pattern="%d{yyyy/MM/dd HH:mm:ss.SSS} : %m%n"/>
<Policies>
<TimeBasedTriggeringPolicy interval="1"/>
<SizeBasedTriggeringPolicy size="1000 MB" />
</Policies>
</RollingFile>
</Appenders> <loggers>
<Logger name="TestLogger" level="DEBUG" additivity="false">
<AppenderRef ref="RollingFile" />
</Logger>
<root level="INFO">
</root>
</loggers></Configuration>
自己在eclipse上测试运行能输出想要格式的log,打成包部署到server上,出此error RollingFile contains an invalid element or attribute FLayout 的错。请各路大神指教是什么地方出了问题。
使用的是log4j2 -2.8.1版本。
自定义了一个FLayout如下package com.common;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.Date;
import java.util.List;import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.Node;
import org.apache.logging.log4j.core.Layout;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
import org.apache.logging.log4j.core.config.plugins.PluginFactory;
import org.apache.logging.log4j.core.layout.AbstractStringLayout;
import org.apache.logging.log4j.core.pattern.LogEventPatternConverter;
import org.apache.logging.log4j.core.pattern.PatternFormatter;
import org.apache.logging.log4j.core.pattern.PatternParser;@Plugin(name = "FLayout", category = Node.CATEGORY, elementType = Layout.ELEMENT_TYPE, printObject = true)
public final class FLayout extends AbstractStringLayout {
private static final String KEY = "Converter";
private final PatternSerializer fPatternSerializer; private FLayout(final Configuration config,final Charset charset,final String pattern,final String headerPattern,
final String footerPattern) {
super(config,charset,new PatternSerializer(getPatternFormatter(config,headerPattern)),
new PatternSerializer(getPatternFormatter(config,footerPattern)));
this.fPatternSerializer=new PatternSerializer(getPatternFormatter(config,pattern));
} @PluginFactory
public static FLayout createLayout( @PluginConfiguration final Configuration config,
@PluginAttribute(value = "charset", defaultString = "UTF-8") final Charset charset,
@PluginAttribute("pattern")String pattern,
@PluginAttribute("header") String headerPattern,
@PluginAttribute("footer") String footerPattern) {
if(pattern==null){
pattern="%d{yyyy/MM/dd HH:mm:ss.SSS} : %m%n";
}
if(headerPattern==null){
headerPattern="%m%n";
}
if(footerPattern==null){
footerPattern="%m%n";
}
return new FLayout(config,charset,pattern,headerPattern,footerPattern);
}
@Override
public String toSerializable(final LogEvent event) {
return this.fPatternSerializer.toSerializable(event);
}
public static PatternFormatter[] getPatternFormatter(final Configuration config,final String pattern){
final PatternParser parser = createPatternParser(config);
final List<PatternFormatter> list = parser.parse(pattern);
final PatternFormatter[] formatters = list.toArray(new PatternFormatter[0]);
return formatters;
}
public static PatternParser createPatternParser(final Configuration config) {
if (config == null) {
return new PatternParser(config, KEY, LogEventPatternConverter.class);
}
PatternParser parser = config.getComponent(KEY);
if (parser == null) {
parser = new PatternParser(config, KEY, LogEventPatternConverter.class);
config.addComponent(KEY, parser);
parser = config.getComponent(KEY);
}
return parser;
} @Override
public byte[] toByteArray(LogEvent loge) {
if ((loge == null)) {
return null;
}
String formatLoge =toSerializable(loge);
return formatLoge.getBytes();
} }package com.common;import java.util.Arrays;import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.layout.AbstractStringLayout.Serializer;
import org.apache.logging.log4j.core.layout.AbstractStringLayout.Serializer2;
import org.apache.logging.log4j.core.pattern.PatternFormatter;
import org.apache.logging.log4j.util.PropertiesUtil;public class PatternSerializer implements Serializer, Serializer2 { public final PatternFormatter[] formatters;
public PatternSerializer(final PatternFormatter[] formatters) {
super();
this.formatters = formatters; }
protected static final int DEFAULT_STRING_BUILDER_SIZE = 1024; protected static final int MAX_STRING_BUILDER_SIZE = Math.max(DEFAULT_STRING_BUILDER_SIZE,
size("log4j.layoutStringBuilder.maxSize", 2 * 1024));
private static final ThreadLocal<StringBuilder> threadLocal = new ThreadLocal<>(); /**
* Returns a {@code StringBuilder} that this Layout implementation can use to write the formatted log event to.
*
* @return a {@code StringBuilder}
*/
protected static StringBuilder getStringBuilder() {
StringBuilder result = threadLocal.get();
if (result == null) {
result = new StringBuilder(DEFAULT_STRING_BUILDER_SIZE);
threadLocal.set(result);
}
trimToMaxSize(result);
result.setLength(0);
return result;
}
@Override
public String toSerializable( LogEvent event) {
final StringBuilder sb = getStringBuilder();
try {
return toSerializable(event, sb).toString();
} finally {
trimToMaxSize(sb);
}
}
private static int size(final String property, final int defaultValue) {
return PropertiesUtil.getProperties().getIntegerProperty(property, defaultValue);
}
protected static void trimToMaxSize(final StringBuilder stringBuilder) {
if (stringBuilder.length() > MAX_STRING_BUILDER_SIZE) {
stringBuilder.setLength(MAX_STRING_BUILDER_SIZE);
stringBuilder.trimToSize();
}
}
@Override
public StringBuilder toSerializable(final LogEvent event, final StringBuilder buffer) {
final int len = formatters.length;
for (int i = 0; i < len; i++) {
formatters[i].format(event, buffer);
}
String str = buffer.toString();
buffer.setLength(0);
buffer.append(str); return buffer;
}
@Override
public String toString() {
final StringBuilder builder = new StringBuilder();
builder.append(super.toString());
builder.append("[formatters=");
builder.append(Arrays.toString(formatters));
builder.append("]");
return builder.toString();
}
}使用路径来加载配置文件,配置文件如下
<?xml version="1.0" encoding="Shift_JIS"?> <Configuration packages="com.common">
<Properties>
<Property name="log_path">C:/workspace/logs/</Property>
<!-- 部署到server上更换为具体的log路径-->
</Properties>
<Appenders>
<RollingFile name="RollingFile" fileName="${log_path}/f.log" append="true"
filePattern="${log_path}/f.log.%d{yyyyMMdd}">
<FLayout charset="Shift_JIS" pattern="%d{yyyy/MM/dd HH:mm:ss.SSS} : %m%n"/>
<Policies>
<TimeBasedTriggeringPolicy interval="1"/>
<SizeBasedTriggeringPolicy size="1000 MB" />
</Policies>
</RollingFile>
</Appenders> <loggers>
<Logger name="TestLogger" level="DEBUG" additivity="false">
<AppenderRef ref="RollingFile" />
</Logger>
<root level="INFO">
</root>
</loggers></Configuration>
自己在eclipse上测试运行能输出想要格式的log,打成包部署到server上,出此error RollingFile contains an invalid element or attribute FLayout 的错。请各路大神指教是什么地方出了问题。
解决方案 »
免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货