<?xml version="1.0" encoding="UTF-8"?> <Configurationstatus="OFF"> <Appenders> <Routingname="Routing"> <Routespattern="$${ctx:ROUTINGKEY}"> <!-- This route is chosen if ThreadContext has value 'special' for key ROUTINGKEY. --> <Routekey="special"> <RollingFilename="Rolling-${ctx:ROUTINGKEY}"fileName="logs/special-${ctx:ROUTINGKEY}.log" filePattern="./logs/${date:yyyy-MM}/${ctx:ROUTINGKEY}-special-%d{yyyy-MM-dd}-%i.log.gz"> <PatternLayout> <Pattern>%d{ISO8601} [%t] %p %c{3} - %m%n</Pattern> </PatternLayout> <Policies> <TimeBasedTriggeringPolicyinterval="6"modulate="true"/> <SizeBasedTriggeringPolicysize="10 MB"/> </Policies> </RollingFile> </Route> <!-- This route is chosen if ThreadContext has no value for key ROUTINGKEY. --> <Routekey="$${ctx:ROUTINGKEY}"> <RollingFilename="Rolling-default"fileName="logs/default.log" filePattern="./logs/${date:yyyy-MM}/default-%d{yyyy-MM-dd}-%i.log.gz"> <PatternLayout> <pattern>%d{ISO8601} [%t] %p %c{3} - %m%n</pattern> </PatternLayout> <Policies> <TimeBasedTriggeringPolicyinterval="6"modulate="true"/> <SizeBasedTriggeringPolicysize="10 MB"/> </Policies> </RollingFile> </Route> <!-- This route is chosen if ThreadContext has a value for ROUTINGKEY (other than the value 'special' which had its own route above). The value dynamically determines the name of the log file. --> <Route> <RollingFilename="Rolling-${ctx:ROUTINGKEY}"fileName="logs/other-${ctx:ROUTINGKEY}.log" filePattern="./logs/${date:yyyy-MM}/${ctx:ROUTINGKEY}-other-%d{yyyy-MM-dd}-%i.log.gz"> <PatternLayout> <pattern>%d{ISO8601} [%t] %p %c{3} - %m%n</pattern> </PatternLayout> <Policies> <TimeBasedTriggeringPolicyinterval="6"modulate="true"/> <SizeBasedTriggeringPolicysize="10 MB"/> </Policies> </RollingFile> </Route> </Routes> </Routing> <!-- 很直白,Console 指定了结果输出到控制台 --> <Consolename="ConsolePrint"target="SYSTEM_OUT"> <PatternLayoutpattern="%d{yyyy.MM.dd HH:mm:ss z} %t %-5level %class{36} %L %M - %msg%xEx%n"/> </Console> </Appenders> <Loggers> <!-- 级别顺序(低到高):TRACE < DEBUG < INFO < WARN < ERROR < FATAL --> <Rootlevel="DEBUG"includeLocation="true"> <!-- AppenderRef 中的 ref 值必须是在前面定义的 appender --> <AppenderRefref="Routing"/> <AppenderRefref="ConsolePrint"/> </Root> </Loggers> </Configuration>
<RollingFilename="RollingFileInfo"fileName="${logFilePath}/${logFileName}-info.log" filePattern="${logFilePath}/$${date:yyyy-MM}/${logFileName}-%d{yyyy-MM-dd}_%i.log.gz"> <Filters> <!-- onMatch:Action to take when the filter matches. The default value is NEUTRAL --> <!-- onMismatch: Action to take when the filter does not match. The default value is DENY --> <!-- 级别在 ERROR 之上的都拒绝输出 --> <!-- 在组合过滤器中,接受使用 NEUTRAL(中立),被第一个过滤器接受的日志信息,会继续用后面的过滤器进行过滤,只有符合所有过滤器条件的日志信息,才会被最终写入日志文件 --> <ThresholdFilterlevel="ERROR"onMatch="DENY"onMismatch="NEUTRAL"/> <ThresholdFilterlevel="INFO"onMatch="ACCEPT"onMismatch="DENY"/> </Filters> <PatternLayoutpattern="%d{yyyy.MM.dd HH:mm:ss z} %-5level %class{36} %L %M - %msg%xEx%n"/> <Policies> <TimeBasedTriggeringPolicy/> <SizeBasedTriggeringPolicysize="30MB"/> </Policies> </RollingFile>
<Routingname="RollingFileInfo_${thread:threadName}"> <Routespattern="$${thread:threadName}"> <Route> <RollingFilename="RollingFileInfo_${thread:threadName}" fileName="${logFilePath}/${logFileName}_${thread:threadName}_info.log" filePattern="${logFilePath}/$${date:yyyy-MM}/${logFileName}-%d{yyyy-MM-dd}-${thread:threadName}-info_%i.log.gz"> <Filters> <!-- onMatch:Action to take when the filter matches. The default value is NEUTRAL --> <!-- onMismatch: Action to take when the filter does not match. The default value is DENY --> <!-- 级别在 ERROR 之上的都拒绝输出 --> <!-- 在组合过滤器中,接受使用 NEUTRAL(中立),被第一个过滤器接受的日志信息,会继续用后面的过滤器进行过滤,只有符合所有过滤器条件的日志信息,才会被最终写入日志文件 --> <ThresholdFilterlevel="ERROR"onMatch="DENY"onMismatch="NEUTRAL"/> <ThresholdFilterlevel="INFO"onMatch="ACCEPT"onMismatch="DENY"/> </Filters> <PatternLayoutpattern="%d{yyyy.MM.dd HH:mm:ss z} %-5level %class{36} %L %M - %msg%xEx%n"/> <Policies> <TimeBasedTriggeringPolicy/> <SizeBasedTriggeringPolicysize="30MB"/> </Policies> </RollingFile> </Route> </Routes> </Routing>
When AsyncLoggerContextSelector is used to make all loggers asynchronous, make sure to use normal <root> and <logger> elements in the configuration. The AsyncLoggerContextSelector will ensure that all loggers are asynchronous, using a mechanism that is different from what happens when you configure <asyncRoot> or <asyncLogger>. The latter elements are intended for mixing async with sync loggers. If you use both mechanisms together you will end up with two background threads, where your application passes the log message to thread A, which passes the message to thread B, which then finally logs the message to disk. This works, but there will be an unnecessary step in the middle. Making All Loggers Asynchronous
<?xml version="1.0" encoding="UTF-8"?> <!-- No need to set system property "Log4jContextSelector" to any value when using <asyncLogger> or <asyncRoot>. --> <Configurationstatus="WARN"> <Appenders> <!-- Async Loggers will auto-flush in batches, so switch off immediateFlush. --> <RandomAccessFilename="RandomAccessFile"fileName="asyncWithLocation.log" immediateFlush="false"append="false"> <PatternLayout> <Pattern>%d %p %class{1.} [%t] %location %m %ex%n</Pattern> </PatternLayout> </RandomAccessFile> </Appenders> <Loggers> <!-- pattern layout actually uses location, so we need to include it --> <AsyncLoggername="com.foo.Bar"level="trace"includeLocation="true"> <AppenderRefref="RandomAccessFile"/> </AsyncLogger> <Rootlevel="info"includeLocation="true"> <AppenderRefref="RandomAccessFile"/> </Root> </Loggers> </Configuration>