Logger
日志中应该使用SLF4J中的API:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private static final Logger logger = LoggerFactory.getLogger(Xxx.class);
参考:http://www.importnew.com/7450.html
log4j配置及加载
配置Log4j.properties就是定义Appender以及Logger
定义Appender
Appender定义包含AppenderName、输出级别ThreadHold、输出target、日志LayOut,以及Appender的实现类
常用输出目的地: System.out/System.err/File/Mail
对应的Appender实现类:
- org.apache.log4j.ConsoleAppender
- org.apache.log4j.DailyRollingFileAppender
- org.apache.log4j.net.SMTPAppender
根据实现类不通,需要配置不通的属性参数,比如DailyRollingFileAppender需配置日志文件路径及Rolling时间格式:
//定义名为DRFA的Appender
log4j.appender.DRFA=org.apache.log4j.DailyRollingFileAppender
log4j.appender.DRFA.File=${hive.log.dir}/${hive.log.file}
log4j.appender.DRFA.DatePattern=.yyyy-MM-dd
//定义名为console的Appender
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.target=System.err
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d{yy/MM/dd HH:mm:ss} [%t]: %p %c{2}: %m%n
log4j.appender.console.encoding=UTF-8
Appender的layout一般有以下几种:
- org.apache.log4j.HTMLLayout(以HTML表格形式布局)
- org.apache.log4j.PatternLayout(可以灵活地指定布局模式)
- org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串)
- org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等信息)
PatternLayout可使用log4j.appender.AppenderName.Layout.ConversionPattern定义Pattern:
log4j.appender.DRFA.layout=org.apache.log4j.PatternLayout
log4j.appender.DRFA.layout.ConversionPattern=%d{ISO8601} %-5p [%t]: %c{2} (%F:%M(%L)) - %m%n
Pattern格式化参数说明:
%c Fully class name. 输出所属的类目,通常就是所在类的全名;
%d Default is ISO8601. Custom:%d{yyy-MM-dd HH:mm:ss }, output example:2002-10-18 22:10:28
%f Class name.
%l Location and line number 输出日志事件的发生位置,及在代码中的行数;
%m Message 输出代码中指定的消息;
%n Nextline 输出一个回车换行符,Windows平台为"rn”,Unix平台为"n”;
%p Log priority 输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL;
%r Log consumed time 输出自应用启动到输出该log信息耗费的毫秒数;
%t Thread name 输出产生该日志事件的线程名;
定义Logger
定义Logger就是定义LoggerName、Logger Level以及与之关联的Appender。
rootLogger
一般首先定义rootLogger, LoggerFactory默认获取的都是rootLogger:
log4j.rootLogger=WARN,DRFA,Console,AppenderX...
一个Logger可关联多个Appender,这样就能输出到多个target。
custom Logger
有时需要将某个业务日志独立出来方便进行检索,比如监控、数据库操作日志等,此时可自定义Logger,一般LoggerName定义为类名或PackageName。
自定义Logger Level:
log4j.logger.org.apache.hadoop.hive.ql.Driver=INFO
log4j.logger.org.apache.hadoop.hive.ql.log.PerfLogger=DEBUG
自定义Logger Appender:
log4j.logger.org.apache.hadoop.hive.ql.Driver=INFO,AppenderXX
注意自定义Logger同时会继承rootLogger 的Appender,也就是日志同样会输出到rootLogger 的Appender中,这样会重复输出,因此最好禁止继承rootLogger Apperder:
log4j.additivity.logger.org.apache.hadoop.hive.ql.Driver=false
加载:
log4j配置文件名如果是log4j.properties或log4j.xml并且在classpath下则会被org.apache.log4j.LogManager自动加载,如果名称不符或不在classpath下则手动加载:
PropertyConfigurator.configure(String log4j_config_path);
也可以直接定义环境变量log4j.configuration指定log4j.properties的位置,org.apache.log4j.LogManager会从此变量定义处加载log4j配置
Ali日志规约
【强制】应用中不可直接使用日志系统(Log4j、Logback)中的API,而应依赖使用日志框架SLF4J中的API,使用门面模式的日志框架,有利于维护和各个类的日志处理方式统一。
import org.slf4j.Logger; import org.slf4j.LoggerFactory; private static final Logger logger = LoggerFactory.getLogger(Abc.class);
【强制】日志文件推荐至少保存15天,因为有些异常具备以“周”为频次发生的特点。
【强制】应用中的扩展日志(如打点、临时监控、访问日志等)命名方式:appName_logType_logName.log。
logType:日志类型,推荐分类有stats/desc/monitor/visit等;
logName:日志描述。这种命名的好处:通过文件名就可知道日志文件属于什么应用,什么类型,什么目的,也有利于归类查找。
正例:mppserver应用中单独监控时区转换异常,如: mppserver_monitor_timeZoneConvert.log
说明:推荐对日志进行分类,错误日志和业务日志尽量分开存放,便于开发人员查看,也便于通过日志对系统进行及时监控。
【强制】对trace/debug/info级别的日志输出,必须使用条件输出形式或者使用占位符的方式。
说明:logger.debug(“Processing trade with id: ” + id + ” symbol: ” + symbol);
如果日志级别是warn,上述日志不会打印,但是会执行字符串拼接操作,如果symbol是对象,会执行toString()方法,浪费了系统资源,执行了上述操作,最终日志却没有打印。
正例:(条件)
if (logger.isDebugEnabled()) { logger.debug("Processing trade with id: " + id + " symbol: " + symbol); }
正例:(占位符)
logger.debug("Processing trade with id: {} symbol : {} ", id, symbol);
【强制】避免重复打印日志,浪费磁盘空间,务必在log4j.property中设置additivity=false。
正例: logger name=”com.taobao.dubbo.config” additivity=”false”
【强制】异常信息应该包括两类信息:案发现场信息和异常堆栈信息。如果不处理,那么往上抛。
正例:logger.error(各类参数或者对象toString + “_” + e.getMessage(), e);
【推荐】可以使用warn日志级别来记录用户输入参数错误的情况,避免用户投诉时,无所适从。注意日志输出的级别,error级别只记录系统逻辑出错、异常等重要的错误信息。如非必要,请不要在此场景打出error级别。
【推荐】谨慎地记录日志。生产环境禁止输出debug日志;有选择地输出info日志;如果使用warn来记录刚上线时的业务行为信息,一定要注意日志输出量的问题,避免把服务器磁盘撑爆,并记得及时删除这些观察日志。 说明:大量地输出无效日志,不利于系统性能提升,也不利于快速定位错误点。记录日志时请思考:这些日志真的有人看吗?看到这条日志你能做什么?能不能给问题排查带来好处?