Layout 布局
Appender使用Layout将LogEvent格式化为一种表单,以满足将要消费日志事件的任何需求。
在Log4j中。x和Logback布局被期望将事件转换为字符串。
在Log4j 2布局返回一个字节数组。这使得Layout的结果可以在更多类型的appender中使用。然而,这意味着您需要配置大多数布局与Charset,以确保字节数组包含正确的值。
使用Charset的布局的根类是org.apache.logging.log4j.core.layout。其中默认是UTF-8。每个扩展AbstractStringLayout的布局都可以提供自己的默认值。请参阅下面的每个布局。
Log4j 2.4.1为ISO-8859-1和US-ASCII字符集添加了一个自定义字符编码器,以便将Java 8内置的一些性能改进带到Log4j中,以便在Java 7上使用。对于只记录ISO-8859-1字符的应用程序,指定此字符集将显著提高性能。
CSV布局
该布局创建逗号分隔值(CSV)记录,并需要Apache Commons CSV。
CSV布局可以以两种方式使用:首先,使用CsvParameterLayout记录事件参数,以创建自定义数据库,通常记录到为此目的唯一配置的日志记录器和文件附加程序。其次,使用CsvLogEventLayout记录事件以创建数据库,作为使用完整的DBMS或使用支持CSV格式的JDBC驱动程序的替代方案。
CsvParameterLayout将事件的参数转换为CSV记录,忽略消息。
要记录CSV记录,您可以使用常用的Logger方法info(), debug()等:
logger.info("Ignored", value1, value2, value3);
得到 csv 格式:
value1, value2, value3
个人理解
csv 格式不太适合,因为日志中很多信息都会出现。
JSON布局
注意:JsonTemplate被认为已弃用。JsonTemplateLayout 提供了更多的功能,应该使用它。
附加一系列JSON事件作为序列化为字节的字符串。
完整格式良好的JSON vs.片段JSON
如果配置complete=“true”,则追加器输出格式良好的JSON文档。
默认情况下,使用complete=“false”,您应该将输出作为外部文件包含在单独的文件中,以形成格式良好的JSON文档。
如果complete=“false”,则appender不会在文档的开头、“]“和末尾写入JSON开放数组字符”[”,也不会在记录之间写入逗号","。
模式
日志事件遵循以下模式:
{
"instant" : {
"epochSecond" : 1493121664,
"nanoOfSecond" : 118000000
},
"thread" : "main",
"level" : "INFO",
"loggerName" : "HelloWorld",
"marker" : {
"name" : "child",
"parents" : [ {
"name" : "parent",
"parents" : [ {
"name" : "grandparent"
} ]
} ]
},
"message" : "Hello, world!",
"thrown" : {
"commonElementCount" : 0,
"message" : "error message",
"name" : "java.lang.RuntimeException",
"extendedStackTrace" : [ {
"class" : "logtest.Main",
"method" : "main",
"file" : "Main.java",
"line" : 29,
"exact" : true,
"location" : "classes/",
"version" : "?"
} ]
},
"contextStack" : [ "one", "two" ],
"endOfBatch" : false,
"loggerFqcn" : "org.apache.logging.log4j.spi.AbstractLogger",
"contextMap" : {
"bar" : "BAR",
"foo" : "FOO"
},
"threadId" : 1,
"threadPriority" : 5,
"source" : {
"class" : "logtest.Main",
"method" : "main",
"file" : "Main.java",
"line" : 29
}
}
个人理解
如果我们相对日志进行分析处理,那么输出 json 格式,其实还是很方便的。
不过 json 相对 pattern 而言,内容会多一些。
一般可以把固定的内容放在前面,从而直接截断解析即可。
模式布局 Pattern Layout
灵活的布局,可配置模式字符串。这个类的目标是格式化LogEvent并返回结果。结果的格式取决于转换模式。
转换模式与c语言中printf函数的转换模式密切相关。转换模式由字面文本和称为转换说明符的格式控制表达式组成。
注意,任何文本,包括特殊字符,都可以包含在转换模式中。特殊字符包括 \t、\n、\r、\f
。使用 \\
在输出中插入一个反斜杠。
每个转换说明符都以百分号(%)开头,后跟可选的格式修饰符和转换字符。转换字符指定数据的类型,例如类别、优先级、日期、线程名称。格式修饰符控制诸如字段宽度、填充、左右对齐等内容。下面是一个简单的例子。
让转换模式为 %-5p [%t]: %m%n
,并假设Log4j环境被设置为使用PatternLayout。然后是语句
Logger logger = LogManager.getLogger("MyLogger");
logger.debug("Message 1");
logger.warn("Message 2");
可以得到:
DEBUG [main]: Message 1
WARN [main]: Message 2
PatternLayout Parameters
Parameter Name | Type | Description |
---|---|---|
charset | String | 将syslog字符串转换为字节数组时使用的字符集。字符串必须是有效的字符集。如果未指定,此布局将使用平台默认字符集。 |
pattern | String | 由下表中的一个或多个转换模式组成的组合模式字符串。不能用模式选择器指定。 |
patternSelector | PatternSelector | 一个组件,用于分析LogEvent中的信息并确定应该使用哪种模式来格式化事件。pattern和patternSelector参数是互斥的。 |
replace | RegexReplacement | 允许替换部分结果字符串。如果已配置,则replace元素必须指定要匹配的正则表达式和替换。它执行一个类似于RegexReplacement转换器的功能,但是它应用于整个消息,而转换器仅应用于其模式生成的String。 |
alwaysWriteExceptions | boolean | 如果为真(默认情况下是这样),即使模式不包含异常转换,也总是写入异常。这意味着,如果您没有在模式中包含输出异常的方法,那么默认的异常格式化程序将被添加到模式的末尾。将其设置为false将禁用此行为,并允许您从模式输出中排除异常。 |
header | String | 要包含在每个日志文件顶部的可选头字符串。 |
footer | String | 要包含在每个日志文件底部的可选页脚字符串。 |
disableAnsi | boolean | 如果为true(默认为false),则不输出ANSI转义码。 |
noConsoleNoAnsi | boolean | 如果为true(默认为false)且System.console()为null,则不输出ANSI转义码。 |
个人理解
这里可以指定自己的 replace 策略。
然后 RewriteAppender 也支持,我们可以有多种方式实现。
灵活性
@Plugin(
name = "replace",
category = "Core",
printObject = true
)
public final class RegexReplacement {
private static final Logger LOGGER = StatusLogger.getLogger();
private final Pattern pattern;
private final String substitution;
private RegexReplacement(Pattern pattern, String substitution) {
this.pattern = pattern;
this.substitution = substitution;
}
public String format(String msg) {
return this.pattern.matcher(msg).replaceAll(this.substitution);
}
这里是直接把 regex 对应的信息转换为固定的 substitution。
如果我们想把手机号掩盖中间4位,感觉就不是很适合。
应该还是重写 RewritePolicy
比较灵活。
RFC5424布局
顾名思义,Rfc5424Layout按照RFC 5424(增强的Syslog规范)格式化LogEvents。
尽管该规范主要针对通过Syslog发送消息,但这种格式对于其他目的非常有用,因为项目在消息中作为自描述键/值对传递。
序列化的布局
SerializedLayout使用Java序列化简单地将LogEvent序列化为字节数组。SerializedLayout不接受任何参数。
此布局自2.9版起已弃用。Java序列化具有固有的安全性弱点,不再推荐使用这种布局。另一个包含相同信息的布局是JsonLayout,配置了properties=“true”。
Syslog布局
SyslogLayout将LogEvent格式化为与Log4j 1.2使用的相同格式匹配的BSD Syslog记录。
参考资料
https://logging.apache.org/log4j/2.x/manual/layouts.html