一般情况下,我们不需要关注log4j的使用,只需要写配置文件就可以实现定制。例如在spring boot的工程中,我们只需要在resource中通过logback.xml文件来配置就可以使用日志系统,但是很多时候,我们需要自我定制日志的配置。例如,我们的程序是一个二方包提供给别人使用的时候,我们该怎么定制我们的二方包的日志呢? 本文要解决的就是这个问题
先回忆下基本概念,先分清楚java现有的几个log系统
common-logging 是一个日志接口,背后可以接具体的实现,使得业务方只依赖于common-logging,而可以方便的更换背后的实现
slf4j : 同common-logging也是日志的一个接口的封装
log4j:日志的具体实现
logback: 日志的另一个实现
具体的详细的区别,网络上有很多资料,可以自行了解,不是本文的重点。
我们看一下在一个spring boot中,配置一个每天回滚的日志是怎样的, 其中maxHistory是保留多少天的日志,日志每天凌晨会产出一份新文件。
<appender name="SELECT" class="ch.qos.logback.core.rolling.RollingFileAppender" additivity="false"> <file>logs/select_task.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>logs/select_task.log.%d{yyyy-MM-dd}</fileNamePattern> <maxHistory>30</maxHistory> </rollingPolicy> <encoder> <charset>UTF-8</charset> <pattern>%d{yyyy-MM-dd HH:mm:ss} %-5p %c{0}.%M:%L # %m%n</pattern> </encoder> <!-- append 是否接着往文件里写 --> <append>true</append> </appender> <logger name="top.huster.service.strategy.Select" additivity="false"> <level value="INFO"/> <appender-ref ref="SELECT"/> </logger>
具体的不详细解释,下面是本文的重点,如果你是以二方包的形式提供服务,那么怎么才能打自己的log而不依赖于别人项目工程的配置呢? 这里就要解释这几个类了. FileAppender的类的职责就是把日志按照一定的格式,追加到日志文件中。
RollingFileAppender: 可以按照大小将文件进行切割,当日志文件达到一定大小以后则重新创建新文件
DailyRollingFileAppender: 逐日生成日志文件,具体的切换的时间也可以自定义
PatternLayout: 则是定义日志的输出格式
下面的表格解释了上面模式中用到的字符,以及所有定制模式时能用到的字符:
转换字符 | 含义 |
---|---|
c | 使用它为输出的日志事件分类,比如对于分类 "a.b.c",模式 %c{2} 会输出 "b.c" 。 |
C | 使用它输出发起记录日志请求的类的全名。比如对于类 "org.apache.xyz.SomeClass",模式 %C{1} 会输出 "SomeClass"。 |
d | 使用它输出记录日志的日期,比如 %d{HH:mm:ss,SSS} 或 %d{dd MMM yyyy HH:mm:ss,SSS}。 |
F | 在记录日志时,使用它输出文件名。 |
l | 用它输出生成日志的调用者的地域信息。 |
L | 使用它输出发起日志请求的行号。 |
m | 使用它输出和日志事件关联的,由应用提供的信息。 |
M | 使用它输出发起日志请求的方法名。 |
n | 输出平台相关的换行符。 |
p | 输出日志事件的优先级。 |
r | 使用它输出从构建布局到生成日志事件所花费的时间,以毫秒为单位。 |
t | 输出生成日志事件的线程名。 |
x | 输出和生成日志事件线程相关的 NDC (嵌套诊断上下文)。 |
X | 该字符后跟 MDC 键,比如 X{clientIP} 会输出保存在 MDC 中键 clientIP 对应的值。 |
% | 百分号, %% 会输出一个 %。 |
详细的可以参考: http://wiki.jikexueyuan.com/project/log4j/log4j-patternlayout.html
我们通过具体的代码来演示在你的二方包中如何打印自己的日志:
public class MyClassLog { //保证全局唯一 static public Logger logger() { return MyClassLog.logger; } static final Logger logger; static { FileAppender appender = new DailyRollingFileAppender(); appender.setAppend(true);//不设置会覆盖 appender.setEncoding("GBK");//设置编码 appender.setFile("~/log");//设置路径 appender.setLayout(new PatternLayout("%d %-5p - %m%n%n"));//设置格式,格式参考上面的表格 appender.activateOptions(); logger = Logger.getLogger("top.huster.myTest"); logger.setLevel(Level.INFO); logger.setAdditivity(false); logger.addAppender(appender); //设置append,默认是覆盖 } }