参见log4j官网:https://logging.apache.org/log4j/2.x
注意:log4j2官网展现的是最新版的内容。因此有的内容变更参见ChangeLog:
https://logging.apache.org/log4j/2.x/changes-report.html
注意:
type在非strict xml中不识别,会报错
<Filter type="MarkerFilter" marker="FLOW" onMatch="DENY" onMismatch="NEUTRAL"/>
一般会不被识别,报出语法错误,使用下面的语句。
<MarkerFilter marker="FLOW" onMatch="DENY" onMismatch="NEUTRAL"/>
<Appender type="Console" name="STDOUT">
转变为
<Console name="STDOUT">
使用script,不能使用return,添加var变量,将结果赋值给变量即可。
Quick-Starter
maven依赖:
点击查看代码
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.17.1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.17.1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.17.1</version>
</dependency>
Resources下创建log4j2.xml文件
点击查看代码
<Configuration status="trace" monitorInterval="5">
<Appenders>
<Console name="Out" target="SYSTEM_OUT">
<PatternLayout pattern="%m%n"/>
</Console>
</Appenders>
<Loggers>
<Root level="debug">
<AppenderRef ref="Out"/>
</Root>
</Loggers>
</Configuration>
应用引入Logger使用
点击查看代码
private static final Logger log = LoggerFactory.getLogger(App.class);
public static void main( String[] args ) {
log.info("1232132131");
}
Configuration
Automatic Configuration
log4j会自动查找其配置文件,查找顺序:
- 系统属性指定:log4j2.configurationFile 如下所示:
System.setProperty("log4j2.configurationFile", "classpath:log4j2-aaa.xml");
但是在spring中因采用logging-starter驱动,application.properties中配置为
logging.config = classpath:log4j2-aaa.xml
- log4j2-test.properties > log4j2-test.yaml > log4j2-test.json > log4j2-test.xml
- log4j2.properties > log4j2.yaml > log4j2.json > log4j2.xml
Arbiter 仲裁 2.15.0+
代码处添加:
static {
System.setProperty("env", "uat");
}
SystemPropertyArbiter
<SystemPropertyArbiter propertyName="env" propertyValue="dev">
<Console name="Out">
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} %m%n"/>
</Console>
</SystemPropertyArbiter>
<SystemPropertyArbiter propertyName="env" propertyValue="prod">
<Console name="Out">
<PatternLayout pattern="%d{yyyy/MM/dd HH:mm:ss.SSS} %m%n"/>
</Console>
</SystemPropertyArbiter>
Select - DefaultArbiter
<Select>
<SystemPropertyArbiter propertyName="env" propertyValue="dev">
<Console name="Out">
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} %m%n"/>
</Console>
</SystemPropertyArbiter>
<SystemPropertyArbiter propertyName="env" propertyValue="prod">
<Console name="Out">
<PatternLayout pattern="%d{yyyy/MM/dd HH:mm:ss.SSS} %m%n"/>
</Console>
</SystemPropertyArbiter>
<DefaultArbiter>
<Console name="Out">
<PatternLayout pattern="%d{HH:mm:ss.SSS} %m%n"/>
</Console>
</DefaultArbiter>
</Select>
Additivity
additivity默认为true,例如以下的配置,目的是对于org.example包下的日志level级别是ERROR,如果有满足要求的内容,输出依托Root的AppenderRef。
<Logger name="org.example" level="ERROR" />
<Root level="INFO">
<AppenderRef ref="Out"/>
</Root>
再比如以下的配置,目的是对于org.example包下输出的内容,采用Out2的AppenderRef,和Root区分开,多用于error文件的单独输出。此时,需要添加additivity="false",不然会在Root中也会输出一遍。
<Logger name="org.example" level="ERROR" additivity="false">
<AppenderRef ref="Out2"/>
</Logger>
<Root level="INFO">
<AppenderRef ref="Out"/>
</Root>
maven Testing
java testUsing
@Rule
public LoggerContextRule init = new LoggerContextRule("MyTestConfig.xml");
@Test
public void testSomeAwesomeFeature() {
final LoggerContext ctx = init.getLoggerContext();
final Logger logger = init.getLogger("org.apache.logging.log4j.my.awesome.test.logger");
final Configuration cfg = init.getConfiguration();
final ListAppender app = init.getListAppender("List");
logger.warn("Test message");
final List<LogEvent> events = app.getEvents();
// etc.
}
System Properties
log4j2的Configuration,MessageFactory都可以通过变量形式配置:
环境变量 <- log4j2.component.properties <- SystemProperties 可配置项参照官方文档。
※注意: 其中漏洞问题:log4j2.formatMsgNoLookups已在2.15.0+版本移除,变为默认关闭。可使用%m{lookups} 或 %m{nolookups}。
LookUps
所有的LookUps都必须实现StrLookup类,因此可参见StrLookup的实现类了解各自用途。
由于部分lookUp是直接静态化可直接使用,部分从properties获取信息。不可随便new出来。
参见:Interpolator类100行strLookup的创建加载过程。
Context Map Lookup
在PatternLayout中用 %X{}或${ctx:}表示。
java代码:
ThreadContext.put("loginId", "zhangsan");
或者
MDC.put("loginId", "zhangsan");
log4j2.xml代码:
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} ${ctx:loginId} %X{loginId} %m%n"/>
Kubernetes Lookup 2.13.0+
Docker Lookup 2.12.0+
Main Arguments Lookup
启动命令,其中[]:
java -jar ****.jar [main0] [main1]
例:java -jar ****.jar name 张三
main方法中:
MainMapLookup.setMainArguments(args);
log4j2.xml配置:
<PatternLayout pattern="${main:1} ${main:name} %d{yyyy-MM-dd HH:mm:ss.SSS} %m%n"/>
Map Lookup
MapLookup默认从properties中获取属性。因此,采用new的方式不能传导到configuration中。但是mapLookup内容来自于properties中。
java代码:
LoggerContext.getContext(false).getConfiguration().getProperties().put("name","王麻子");
log4j2.xml:
<Properties>
<property name="myname" value="周星星"></property>
</Properties>
<PatternLayout pattern="${map:myname} ${map:name} %d{yyyy-MM-dd HH:mm:ss.SSS} %m%n"/>
MarkerLookup
MarkerLookup 采用 MarkerManager中的数据,因此使用MarkerFactory构造Marker。
private static final Marker TEST = MarkerFactory.getMarker("TEST");
log.error(TEST, "1232132131");
log.error("abcdddd");
可用于filter,routers路由分流log信息到不同的文件。
<MarkerFilter marker="SQL" onMatch="ACCEPT" onMismatch="DENY"/>
Structured Data Lookup
sd需要采用StructuredDataMessage 才可以其效果。${sd:***}
Appenders
Routing 路由
大多用于Marker的数据分流写入文件
log4j2.xml写法
<Appenders>
<Console name="console" target="SYSTEM_OUT">
<PatternLayout pattern="2 %d %-5level %m%n" />
</Console>
<RollingFile name="RollingFileInfo" fileName="log/info.log"
filePattern="/log/info-INFO-%d{yyyy-MM-dd}_%i.log.gz">
<PatternLayout pattern="%m%n"/>
<!-- <Filters>
<MarkerFilter marker="FLOW" onMatch="DENY" onMismatch="NEUTRAL"/>
</Filters>-->
<Policies>
<!--interval属性用来指定多久滚动一次,默认是1 hour-->
<TimeBasedTriggeringPolicy interval="1"/>
<SizeBasedTriggeringPolicy size="10MB"/>
</Policies>
<!-- DefaultRolloverStrategy同一文件夹下15个文件开始覆盖-->
<DefaultRolloverStrategy max="15"/>
</RollingFile>
<Routing name="routing">
<Routes>
<Script name="RoutingInit" language="JavaScript"><![CDATA[
var result = ''; //赋初值没有用
if (logEvent.getMarker() != null && logEvent.getMarker().isInstanceOf("TEST")) {
result = 'RollingFile';
}else{
result = 'CONSOLE';
}
]]>
</Script>
<Route ref="console" key="CONSOLE"/>
<Route ref="RollingFileInfo" key="RollingFile"/>
</Routes>
</Routing>
</Appenders>
<Loggers>
<Root level="INFO">
<AppenderRef ref="routing"/>
</Root>
</Loggers>
java部分代码:
private static final Marker TEST = MarkerFactory.getMarker("TEST");
log.error(TEST, "1232132131");
Layout
PatternLayout
类型 | 说明 | 注意 |
---|---|---|
%d | 时间 | %date等同 |
%d | 格式化时间 | |
%c | 类名 | %logger %C %class 等同 |
%c | Short类名 | 数值越大,类名越长 |
%M | 方法名 | %method等同,注意是大写,小写是message |
%L | %line等同,行号 | 注意%l为location |
%l | %location等同,位置 | 注意%L为line,示例:org.example.App.main(App.java:39) |
%m | 消息 | %msg %message等同 |
%m | message内部解析 | 默认不解析信息:%m |
%t | 线程名 | %tn, %thread,%threadName |
%T | 线程ID | %tn, %tid,%threadId |
%highlight{pattern} | 高亮 | |
%p | 日志级别 | %level等同 |
%n | 换行 | 常常放在末尾 |
%5 | 左padding5位 | 用于对齐,示例:%5c |
%-5 | 右padding5位 | 用于右对齐,示例:%-5level |
%maxLen{%m} | 用于限制method最多输出20个字符 | |
%throwable | 异常抛出设置 | 等同于%xEx,%xEx{none} or %xEx{0} or %xEx{short} 值范围:["none" |
Filters
过滤器可以在任何地方添加。在Configuration下添加的默认会控制所有。
也可自定义自己的过滤器,参照:扩展Filter
在Appender下添加的Filter控制当前的Appender,在Logger中添加的Filter控制当前的Filter。
BurstFilter
用于限流,控制秒级的输出量。用的不多。
CompositeFilter
复合过滤器其实就是Filter集合,用于对多条数据进行过滤,如果Deny直接拒绝,Accept直接接收,后面的过滤器不用考虑,NEUTRAL中立,不管由后面的过滤器决定。
<Filters>
....//FilterA
....//FilterB
</Filters>
DynamicThresholdFilter
The DynamicThresholdFilter allows filtering by log level based on specific attributes。需要结合ThreadContext Map.
不同的ThreadContext使用不同的level级别。实用性不强。
<DynamicThresholdFilter key="loginId" defaultThreshold="ERROR"
onMatch="ACCEPT" onMismatch="NEUTRAL">
<KeyValuePair key="User1" value="DEBUG"/>
</DynamicThresholdFilter>
MapFilter
实用性不强。
<MapFilter onMatch="ACCEPT" onMismatch="NEUTRAL" operator="or">
<KeyValuePair key="eventId" value="Login"/>
<KeyValuePair key="eventId" value="Logout"/>
</MapFilter>
MarkerFilter
根据Marker标记,来区分过滤数据。对业务中有部分特殊代码记录可这样用。比如发送对方信息,本地存证并保存数据,防止对方要求重发。
NoMarkerFilter
RegexFilter
正则匹配,太损耗性能,一般不用。
ThresholdFilter
这个比较实用,通过level区分,比如将error单独创建一个文件保留。
TimeFilter
将部分时间段的日志分离出来。不常有用。
Asynchronous Loggers
可通过系统配置直接生效。
抑或:
※注意:async 默认没有记录location信息,因此class,method,line 为空。需要设置 includeLocation="true".
※注意:异步日志依赖jar包:disruptor-3.3.4.jar
变量
- 因log4j2.xml在应用启动时就会加载进来,因此一般要使用环境变量或者系统变量。
${sys:value:-defaultValue}
${env:value:-defaultValue}
其中 value表示当前值,defaultValue表示默认值,注意默认值前要有-,不然会被当成一个字符串。
- 文本中定义的变量,需要提前在 Properties 中定义后,可直接使用。
${value}
- 如果数据有部分来自于maven,比如应用名称,版本等,可通过mvn的变量模式
@project.name@
@project.version@
但此种模式需要在maven的build中定义resources.
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>