转载

Log4j 实践

Log4j 似乎已经被淘汰了为什么还要写这篇文章?

log4j、log4j2、logback 从基础思想上三者的实现是一致的,无非就是输出内容到文件,且看配置文件也都大同小异(logger、appender、layout),无非后两者比前者具有更多的高级功能,此块可以单独拎出讲。所以如果想了解本质,从最开始的版本开始会比较好下手。

简单体验

<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>
复制代码

测试类:

public static void main(String[] args) {
    Logger logger = Logger.getLogger(Log4jTest.class);
    logger.debug("log4j debug");
    logger.info("log4j info");
    logger.error("log4j error");
}
复制代码

输出到控制台:log4j.properties

log4j.rootLogger=debug,consoleAppender

log4j.appender.csAppender=org.apache.log4j.ConsoleAppender
log4j.appender.csAppender.Threshold=INFO
log4j.appender.csAppender.Target=System.out
log4j.appender.csAppender.layout=org.apache.log4j.PatternLayout
log4j.appender.csAppender.layout.ConversionPattern=[%d] [%t] [%c.%M:%L] [%-5p]: %m%n
复制代码

输出到文件:log4j.properties

log4j.rootLogger=debug,fileAppender

log4j.appender.fileAppender=org.apache.log4j.DailyRollingFileAppender
log4j.appender.fileAppender.Threshold=INFO
log4j.appender.fileAppender.File=D://data//usr//local//logs//home//log4j-log.log
log4j.appender.fileAppender.DatePattern = '.'yyyy-MM-dd'.log'
log4j.appender.fileAppender.Encoding=UTF-8
log4j.appender.fileAppender.Append=true
log4j.appender.fileAppender.layout=org.apache.log4j.PatternLayout
log4j.appender.fileAppender.layout.ConversionPattern=[%d] [%t] [%-5p] [%c.%M:%L]: %m%n
复制代码

上面示例配置中的 root 日志实例分别使用 csAppender(控制台)、fileAppender(文件)附加器将日志内容输出到目的地。当然也可以同时输出。log4j 官网并没有对配置进行说明,但在 org.apache.log4j.PropertyConfigurator#doConfigure 方法注释上可看到完整的说明。

第一步需要配置根 Logger 格式如下:

log4j.rootLogger = [level] , appenderName1, appenderName2, …
复制代码
  • level设定日志记录的最低级别,可设的值有 OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL或者自定义的级别,比如在这里设定了INFO级别,则应用程序中所有DEBUG级别的日志信息将不会被打印出来。

  • appenderName

    就是指定日志信息要输出到哪里。可以同时指定多个输出目的地,用逗号隔开。 例如:log4j.rootLogger=INFO,A1,B2,C3

第二步配置日志信息输出目的地(appender)格式如下:

# For appender named
log4j.appender.appenderName=fully.qualified.name.of.appender.class
# Set appender specific options.
log4j.appender.appenderName.option1=value1
...
log4j.appender.appenderName.optionN=valueN
复制代码

三大组件

Log4j 实践

Log4j has three main components: loggers , appenders and layouts . These three types of components work together to enable developers to log messages according to message type and level, and to control at runtime how these messages are formatted and where they are reported.

Log4j 有三个主要的组件:Loggers(记录器),Appenders (输出源)和 Layouts(布局)。这里可简单理解为日志类别,日志要输出的地方和日志以何种形式输出。综合使用这三个组件可以轻松地记录信息的类型和级别,并可以在运行时控制日志输出的样式和位置。

Logger

Loggers 组件在此系统中被分为五个级别:DEBUG、INFO、WARN、ERROR和FATAL。这五个级别是有顺序的, DEBUG < INFO < WARN < ERROR < FATAL ,分别用来指定这条日志信息的重要程度。Log4j 有一个规则: 只输出级别不低于设定级别的日志信息 。假设 Loggers 级别设定为 INFO,则 INFO、WARN、ERROR 和 FATAL 级别的日志信息都会输出,而级别比 INFO 低的 DEBUG 则不会输出。

定义 logger

Log4J 中总是存在一个 rootLogger ,即使没有显示配置也是存在的,并且默认输出级别为 DEBUG 。其它的 logger 都继承自这个 rootLogger (如果其他logger未单独定义其输出级别)。

其次,Log4J 中的层次( Hierarchy )是用 '.' 来分隔的,如 log4j.logger.com.example.test ,并不是说 log4j.logger 后面一定是具体的包名乃至类名,这个名称可以自定义,我们甚至可以定义一个log4j.logger.A.B.C,如下例所示,建立了 3 个 logger 实例,它们分别是 AA.BA.B.C

## log4j.properties
log4j.logger.A.B.C = ERROR,appenderName
## 在代码中获取名为 A.B 的日志对象
Logger logger = Logger.getLogger("A.B")
复制代码

继承

log4j.rootLogger=DEBUG,consoleAppender
log4j.logger.A=DEBUG,consoleAppender
log4j.logger.A.B=INFO,consoleAppender
复制代码

对于名为 A.B 的 logger 输出的日志会往控制台输出三次,原因是 A.B 继承 A 的以及A 的父 logger 的所有 appender,这种继承关系仅仅是把父 logger 的 appender 添加到自己的 appender 列表中,父 logger 的输出 level 不会影响子 logger 的输出。

log4j.rootLogger=DEBUG,consoleAppender
log4j.logger.A=DEBUG,consoleAppender
log4j.logger.A.B=INFO,consoleAppender
log4j.additivity.A.B=false
复制代码

名为 A.B 的 logger 日志仅会输出到自己的 appender 中,不会继承任何父 logger 的 appender。

Appender

若想对输出到 appender 中的日志级别进行限制的话,就需要用到 threshold 来控制。

log4j.threshold=ERROR
复制代码

用来控制所有的 appender,即输出到所有appender的日志,不管原来是什么级别的,都不能低于threshold所规定的级别。

log4j.appender.Console.threshold=ERROR 
复制代码

用来控制指定的 appender 的输出级别。

Log4j 日志系统还提供许多强大的功能,比如允许把日志输出到不同的地方,如控制台(Console)、文件(Files)等,可以根据天数或者文件大小产生新的文件,可以以流的形式发送到其它地方等等。

控制台(console)

log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.Threshold=DEBUG
log4j.appender.console.ImmediateFlush=true
log4j.appender.console.Target=System.err
log4j.appender.console.layout=org.apache.log4j.PatternLayout
复制代码

日志文件(logFile)

log4j.appender.logFile=org.apache.log4j.FileAppender
log4j.appender.logFile.Threshold=DEBUG
log4j.appender.logFile.ImmediateFlush=true
log4j.appender.logFile.Append=true
log4j.appender.logFile.File=D:/logs/log.log4j
log4j.appender.logFile.layout=org.apache.log4j.PatternLayout
复制代码

回滚文件(rollingFile)

  • Threshold=WARN:指定日志信息的最低输出级别,默认为DEBUG
  • ImmediateFlush=true:表示所有消息都会被立即输出,设为false则不输出,默认值是true。
  • Append=false:true表示消息增加到指定文件中,false则将消息覆盖指定的文件内容,默认值是true。
  • File=D:/logs/logging.log4j:指定消息输出到logging.log4j文件中。
  • MaxFileSize=100KB:后缀可以是KB, MB 或者GB。在日志文件到达该大小时,将会自动滚动,即将原来的内容移到logging.log4j.1文件中。
  • MaxBackupIndex=2:指定可以产生的滚动文件的最大数,例如,设为2则可以产生logging.log4j.1,logging.log4j.2两个滚动文件和一个logging.log4j文件。
log4j.appender.rollingFile=org.apache.log4j.RollingFileAppender
log4j.appender.rollingFile.Threshold=DEBUG
log4j.appender.rollingFile.ImmediateFlush=true
log4j.appender.rollingFile.Append=true
log4j.appender.rollingFile.File=D:/logs/log.log4j
log4j.appender.rollingFile.MaxFileSize=200KB
log4j.appender.rollingFile.MaxBackupIndex=50
log4j.appender.rollingFile.layout=org.apache.log4j.PatternLayout
复制代码

定期回滚日志文件(dailyFile)

DatePattern='.'yyyy-MM :即每月产生一个新的日志文件。当前月的日志文件名为 logging.log4j,前一个月的日志文件名为 logging.log4j.yyyy-MM。另外,也可以指定按周、天、时、分等来滚动日志文件,对应的格式如下:

- yyyy-MM:每月
- yyyy-ww:每周
- yyyy-MM-dd:每天
- yyyy-MM-dd-a:每天两次
- yyyy-MM-dd-HH:每小时
- yyyy-MM-dd-HH-mm:每分钟
复制代码
log4j.appender.dailyFile=org.apache.log4j.DailyRollingFileAppender
log4j.appender.dailyFile.Threshold=DEBUG
log4j.appender.dailyFile.ImmediateFlush=true
log4j.appender.dailyFile.Append=true
log4j.appender.dailyFile.File=D:/logs/log.log4j
log4j.appender.dailyFile.DatePattern='.'yyyy-MM-dd
log4j.appender.dailyFile.layout=org.apache.log4j.PatternLayout
复制代码

应用于 socket

log4j.appender.socket=org.apache.log4j.RollingFileAppender
log4j.appender.socket.RemoteHost=localhost
log4j.appender.socket.Port=5001
log4j.appender.socket.LocationInfo=true
复制代码

发送日志到指定邮件

log4j.appender.mail=org.apache.log4j.net.SMTPAppender
log4j.appender.mail.Threshold=FATAL
log4j.appender.mail.BufferSize=10
log4j.appender.mail.From = xxx@mail.com
log4j.appender.mail.SMTPHost=mail.com
log4j.appender.mail.Subject=Log4J Message
log4j.appender.mail.To= xxx@mail.com
log4j.appender.mail.layout=org.apache.log4j.PatternLayout
复制代码

应用于数据库

log4j.appender.database=org.apache.log4j.jdbc.JDBCAppender
log4j.appender.database.URL=jdbc:mysql://localhost:3306/test
log4j.appender.database.driver=com.mysql.jdbc.Driver
log4j.appender.database.user=root
log4j.appender.database.password=
log4j.appender.database.sql=INSERT INTO LOG4J (Message) VALUES('=[%-5p] %d(%r) --> [%t] %l: %m %x %n')
log4j.appender.database.layout=org.apache.log4j.PatternLayout
复制代码

自定义 Appender

log4j.appender.im = xxx.logger.appender.IMAppender
log4j.appender.im.host = mail.cybercorlin.net
log4j.appender.im.username = username
log4j.appender.im.password = password
log4j.appender.im.recipient = 邮箱
log4j.appender.im.layout=org.apache.log4j.PatternLayout
复制代码

Layout

有时用户希望根据自己的喜好格式化自己的日志输出,Log4j 可以在 Appenders 的后面附加Layouts来完成这个功能。Layouts 提供四种日志输出样式,如根据HTML样式、自由指定样式、包含日志级别与信息的样式和包含日志时间、线程、类别等信息的样式。常使用的类如下:

- org.apache.log4j.HTMLLayout(以HTML表格形式布局)
- org.apache.log4j.PatternLayout(可以灵活地指定布局模式)
- org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串)
- org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等信息)
复制代码

格式化符号说明

%p:输出日志信息的优先级,即DEBUG,INFO,WARN,ERROR,FATAL。
%d:输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,如:%d{yyyy/MM/dd HH:mm:ss,SSS}。
%r:输出自应用程序启动到输出该log信息耗费的毫秒数。
%t:输出产生该日志事件的线程名。
%l:输出日志事件的发生位置,相当于%c.%M(%F:%L)的组合,包括类全名、方法、文件名以及在代码中的行数。例如:test.TestLog4j.main(TestLog4j.java:10)。
%c:输出日志信息所属的类目,通常就是所在类的全名。
%M:输出产生日志信息的方法名。
%F:输出日志消息产生时所在的文件名称。
%L::输出代码中的行号。
%m::输出代码中指定的具体日志信息。
%n:输出一个回车换行符,Windows平台为"rn",Unix平台为"n"。
%x:输出和当前线程相关联的NDC(嵌套诊断环境),尤其用到像java servlets这样的多客户多线程的应用中。
%%:输出一个"%"字符。
另外,还可以在%与格式字符之间加上修饰符来控制其最小长度、最大长度、和文本的对齐方式。如:
1) c:指定输出category的名称,最小的长度是20,如果category的名称长度小于20的话,默认的情况下右对齐。
2)%-20c:"-"号表示左对齐。
3)%.30c:指定输出category的名称,最大的长度是30,如果category的名称长度大于30的话,就会将左边多出的字符截掉,但小于30的话也不会补空格。
复制代码

实战分析

log4j.rootLogger=debug,console,file
log4j.additivity=true

log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.Threshold=ERROR
log4j.appender.console.Target=System.out
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=[%d] [%t] [%-5p] [%c.%M:%L]: %m%n

log4j.appender.file=org.apache.log4j.DailyRollingFileAppender
log4j.appender.file.Threshold=INFO
log4j.appender.file.File=日志文件路径
log4j.appender.file.DatePattern = '.'yyyy-MM-dd'.log'
log4j.appender.file.Encoding=UTF-8
log4j.appender.file.Append=true
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=[%d] [%t] [%-5p] [%c.%M:%L]: %m%n

log4j.logger.com.fingard.rh.rhf.ryb.manager.UnifiedServiceManager=ERROR,console,file
log4j.additivity.com.fingard.rh.rhf.ryb.manager.UnifiedServiceManager=false
复制代码

定义两个 appender 分别输出到控制台和文件,针对名为 com.fingard.rh.rhf.ryb.manager.UnifiedServiceManager 日志输出级别调成 ERROR,且禁用 appender 继承,只在当前 logger 的 appender 中输出。在类 UnifiedServiceManager 中若是使用如下方式获取 logger 则日志只有在 ERROR 级别及以上会输出

Logger logger1 = Logger.getLogger(UnifiedServiceManager.class)
复制代码

分析 Logger getLogger(Class clazz) 源码可知, 默认使用类全路径作为 loggerName 传入 。故获取到的 logger1 即为配置文件中指定名为 com.fingard.rh.rhf.ryb.manager.UnifiedServiceManager 的日志对象。

原文  https://juejin.im/post/5db158edf265da4d513341a5
正文到此结束
Loading...