- 刚好这周的一项任务是把Druid平台的Log4j2的xml配置文件翻译成properties,原因是xml格式的配置文件看着不舒服
- 在网上查了下资料,Log4j进入2.x版本后,一开始就抛弃了properties格式的配置文件,到2.4版本的时候才又重新支持,猜测是Log4j1.x时代养成了用户的习惯,不好改了,所以发觉这任务还有点意义
- 本文写作的时候Log4j2已经发布到
2.8.2
的版本了,但是Druid用的是2.5
,所以按照2.5的规则来配置,ps: 2.x版本的properties的语法和1.x的差别很大- 没有完美的资料,即使是官网也没能讲全properties的语法规则,只能靠自己灵光咋现的顿悟一点点爬行
官网上给了一串的if-else的说明,概括起来就是一条读取顺序链
System Property -> properties -> YAML -> JSON -> XML -> Default Configuration
.yaml
和.yml
.json
和.jsn
Appenders are responsible for delivering LogEvents to their destination.
简单理解一下,就是决定Log4j2产生的日志要发到什么地方
我们设置了两处用来保留Druid的日志,一个是服务器集群的本地文件,另一个是Kafka
# 采用RollingFile类型的Appender
appender.rolling.type = RollingFile
# 本appender的名字,以便在Logger的配置项中能够调用
appender.rolling.name = broker
# 当前正在操作的日志文件的文件名
appender.rolling.fileName = /druid/log/broker.log
# 归档后的日志文件的文件名格式,其中`%d{yyyy-MM-dd-HH}`用来自动填充日期
appender.rolling.filePattern = /druid/log/broker-%d{yyyy-MM-dd-HH}.log.gz
appender.rolling.layout.type = PatternLayout
# 对应输出的每条日志的日志头
appender.rolling.layout.pattern = %date- %c{2}: %m%n
appender.rolling.policies.type = Policies
# 基于时间进行日志的切割
appender.rolling.policies.time.type = TimeBasedTriggeringPolicy
# 切割的间隔为1小时, 即每小时进行一次日志的归档
appender.rolling.policies.time.interval = 1
# 修正时间范围, 从0时开始计数
appender.rolling.policies.time.modulate = true
除了时间之外还可以基于文件的大小进行切割,相关的策略类为SizeBasedTriggeringPolicy
配置Strategy用来删除过多的日志归档文件
appender.rolling.strategy.type = DefaultRolloverStrategy
appender.rolling.strategy.delete.type = Delete
# 删除哪个目录下的日志归档文件
appender.rolling.strategy.delete.basePath = /druid/log
# 从basePath起向下遍历几级子文件夹?
appender.rolling.strategy.delete.maxDepth = 1
appender.rolling.strategy.delete.iffile.type = IfFileName
# 删除符合该模式文件名的归档日志文件
appender.rolling.strategy.delete.iffile.glob = broker-*.log.gz
appender.rolling.strategy.delete.iflastmodify.type = IfLastModified
# 保留多少天的日志?
appender.rolling.strategy.delete.iflastmodify.age = 2d
appender.kafka.type = Kafka
appender.kafka.topic = druid-log
appender.kafka.brokers = :9092
因为propertie文件的弱表达性不支持Kafka的
bootstrap.servers
这种带有.
的属性,所以对Loger4j2中的KafkaManager类
做了一点修改,改成了通过broker
属性获取值,然后再转换成bootstrap.servers
写入Kafka配置
rootLogger
作为属性# 自定义的logger名字
logger.emitter.name = com.metamx.emitter.core.LoggingEmitter
# 该logger的日志级别
logger.emitter.level = info
logger.emitter.additivity = true
# 该logger通过什么类型的appender来输出
logger.emitter.appenderRefs = kafka
# 该logger通过该类型具体的哪个appender来输出
logger.emitter.appenderRef.kafka.ref = kafka-monitor
# root的配置和自定义Logger一样
rootLogger.level = info
rootLogger.appenderRefs = rolling
rootLogger.appenderRef.rolling.ref = middleManager
- 这个钻研了很久,官方的文档翻阅了很多遍,只能看出一些端倪来
- Google的结果基本只有一两篇有价值的
- 读了一小部分Log4j2的源代码,了解了propertie文件的解析方式
- 最后终于在各种连蒙带猜中,顿悟除了规则来
Log4j-2.5对properties文件的解析位于PropertiesConfigurationFactory类
中
appenders键
、loggers键
,获得所有的appender和loggerrootLogger键
是另外单独解析的createAppender()方法
,为每个logger调用createLogger()方法
.
来进行区分的,一个.
隔开了上下层的级联,在createAppender()方法
和createLogger()方法
中,就是一层一层的递归遍历来获取有级联关系的配置type
,然后就可以在这一层定义属性键
= 对应的值遍历配置的代码如下, 不包括一些默认的属性键
private void processRemainingProperties(ComponentBuilder> builder, String name, Properties properties) {
while (properties.size() > 0) {
String propertyName = properties.stringPropertyNames().iterator().next();
int index = propertyName.indexOf('.');
if (index > 0) {
String prefix = propertyName.substring(0, index);
Properties componentProperties = PropertiesUtil.extractSubset(properties, prefix);
builder.addComponent(createComponent(builder, prefix, componentProperties));
} else {
builder.addAttribute(propertyName, properties.getProperty(propertyName));
properties.remove(propertyName);
}
}
}
一开始没能理解官网给的例子,后来顿悟的关键点就在这个type
上
举个例子, 有appender的切割策略配置如下:
<Policies>
<TimeBasedTriggeringPolicy intervel = "2" modulate="true"/>
<SizeBasedTriggeringPolicy size="100 MB"/>
Policies>
# 对应Policies标签
appender.rolling.policies.type = Policies
# 对应TimeBasedTriggeringPolicy
appender.rolling.policies.time.type = TimeBasedTriggeringPolicy
appender.rolling.policies.time.interval = 2
appender.rolling.policies.time.modulate = true
# 对应SizeBasedTriggeringPolicy
appender.rolling.policies.size.type = SizeBasedTriggeringPolicy
appender.rolling.policies.size.size=100MB