日志输出规范
1、log4j日志参数说明
log4j.appender.ERROR.layout.ConversionPattern=[%p][%l] %d{yyyy-MM-dd HH:mm:ss} %m%n
格式输出修改成:
log4j.appender.INFO.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} - [%p] - [%l] - [ %m ]%n
时间-事件级别-打印日志的详细信息-消息内容
p log事件的级别。
l log发生位置的详细描述,包括方法名、文件名及行号。
d 时间和日期的输出格式,例如:%d{yyyy MM dd HH:mm:ss,SS},可不带后面的日期格式字符。
m log事件的消息内容
n 根据所运行的平台输出相应的行分隔字符。
2、在一个对象中通常只使用一个Logger对象,Logger应该是static final的,只有在少数需要在构造函数中传递logger的情况下才使用private final。
private static final org.slf4j.Logger logger =
LoggerFactory.getLogger(TemperatureDetectionController.class);
如果使用com.leelen.esafe.utils.Logger,则日志输出的具体类将不能体现。
之前写法:Logger.info(TAG + ":" + JSON.toJSONString(cmds));
调用LoggerUtil的类,并且要手动获取类名,拼接字符串才能显示具体的类名
3.输出Exceptions的全部Throwable信息,因为logger.error(msg)和logger.error(msg,e.getMessage())这样的日志输出方法会丢失掉最重要的StackTrace信息。
try {
throw new Exception("测试日志");
}catch (Exception e){
logger.info(e.getMessage());//错误
logger.info("输入日志1",e.getMessage());//错误
logger.info("输入日志2",e);//正确
}
4、不允许记录日志后又抛出异常,因为这样会多次记录日志,只允许记录一次日志。
try {
}catch (Exception e){
logger.info("输入日志",e);
throw new BusinessException(1,e.getMessage());
}
5、不允许出现System print(包括System.out.println和System.error.println)语句。
System.out.println(e.getMessage());//错误
System.err.println(e.getMessage());//错误
logger.info("输入日志",e);//正确
System.out日志打印不可控制、打印时间无法确定、不能添加过滤器、日志没有级别区分4、不允许出现printStackTrace。
try {
throw new Exception("222");
}catch (Exception e){
e.printStackTrace();//错误
logger.info("输入日志",e);//正确
}
为什么尽量不用e.printStackTrace
主要原因有以下几点:
1、占用太多内存,造成锁死
要打印字符串输出到控制台上,需要字符串常量池所在的内存块有足够的空间。然而,因为e.printStackTrace() 语句要产生的字符串记录的是堆栈信息,太长太多,内存被填满了!大量线程产出字符串产出到一半,等待有内存被释放,锁死了,导致整个应用挂掉了。
代码本身有问题,很多情况下抛异常 -> e.printStackTrace() 来打印异常到控制台 -> 产生错误堆栈字符串到字符串池内存空间 -> 此内存空间一下子被占满了 -> 开始在此内存空间产出字符串的线程还没完全生产完整,就没空间了 -> 大量线程产出字符串产出到一半,等在这儿(等有内存了继续搞啊)-> 相互等待,等内存,锁死了,整个应用挂掉了。
2、日志交错混合,不易读
printStackTrace()默认使用了System.err输出流进行输出,与System.out是两个不同的输出流,那么在打印时自然就形成了交叉。再就是输出流是有缓冲区的,所以对于什么时候具体输出也形成了随机。
6、日志正确的写法
logger.error("测试日志{}{}",”参数1”, "参数2");//正确
logger.error("测试日志{}",”参数1”, e);//正确
logger.error("测试日志"+”参数1”);//错误
Logger.info("读取字节数组成文件失败:" + e);//错误
//错误,重复输出日志
//错误,不用+号拼接字符串的方式 改用占位符{}
可以减少参数构造的开销。
调试阶段的日志可用DEBUG级别的日志输出或者去掉无意义的日志输出:
7、log4j日志级别说明
log4j定义了8个级别的log(除去OFF和ALL,可以说分为6个级别),优先级从高到低依次为:OFF、FATAL、ERROR、WARN、INFO、DEBUG、TRACE、 ALL。
ALL 最低等级的,用于打开所有日志记录。
TRACE designates finer-grained informational events than the DEBUG.Since:1.2.12,很低的日志级别,一般不会使用。
DEBUG 指出细粒度信息事件对调试应用程序是非常有帮助的,主要用于开发过程中打印一些运行信息。
INFO 消息在粗粒度级别上突出强调应用程序的运行过程。打印一些你感兴趣的或者重要的信息,这个可以用于生产环境中输出程序运行的一些重要信息,但是不能滥用,避免打印过多的日志。
WARN 表明会出现潜在错误的情形,有些信息不是错误信息,但是也要给程序员的一些提示。
ERROR 指出虽然发生错误事件,但仍然不影响系统的继续运行。打印错误和异常信息,如果不想输出太多的日志,可以使用这个级别。
FATAL 指出每个严重的错误事件将会导致应用程序的退出。这个级别比较高了。重大错误,这种级别你可以直接停止程序了。
OFF 最高等级的,用于关闭所有日志记录。
1、log4j日志参数说明log4j.appender.ERROR.layout.ConversionPattern=[%p][%l] %d{yyyy-MM-dd HH:mm:ss} %m%n
格式输出修改成:log4j.appender.INFO.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} - [%p] - [%l] - [ %m ]%n
时间-事件级别-打印日志的详细信息-消息内容
p log事件的级别。l log发生位置的详细描述,包括方法名、文件名及行号。d 时间和日期的输出格式,例如:%d{yyyy MM dd HH:mm:ss,SS},可不带后面的日期格式字符。m log事件的消息内容n 根据所运行的平台输出相应的行分隔字符。
在一个对象中通常只使用一个Logger对象,Logger应该是static final的,只有在少数需要在构造函数中传递logger的情况下才使用private final。
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(TemperatureDetectionController.class);
如果使用com.leelen.esafe.utils.Logger,则日志输出的具体类将不能体现。
之前写法:Logger.info(TAG + ":" + JSON.toJSONString(cmds));调用LoggerUtil的类,并且要手动获取类名,拼接字符串才能显示具体的类名
3.输出Exceptions的全部Throwable信息,因为logger.error(msg)和logger.error(msg,e.getMessage())这样的日志输出方法会丢失掉最重要的StackTrace信息。
try { throw new Exception("测试日志");}catch (Exception e){ logger.info(e.getMessage());//错误 logger.info("输入日志1",e.getMessage());//错误 logger.info("输入日志2",e);//正确}
4、不允许记录日志后又抛出异常,因为这样会多次记录日志,只允许记录一次日志。try { }catch (Exception e){ logger.info("输入日志",e); throw new BusinessException(1,e.getMessage());}
5、不允许出现System print(包括System.out.println和System.error.println)语句。System.out.println(e.getMessage());//错误System.err.println(e.getMessage());//错误logger.info("输入日志",e);//正确
System.out日志打印不可控制、打印时间无法确定、不能添加过滤器、日志没有级别区分4、不允许出现printStackTrace。try { throw new Exception("222");}catch (Exception e){ e.printStackTrace();//错误 logger.info("输入日志",e);//正确}
为什么尽量不用e.printStackTrace主要原因有以下几点:1、占用太多内存,造成锁死要打印字符串输出到控制台上,需要字符串常量池所在的内存块有足够的空间。然而,因为e.printStackTrace() 语句要产生的字符串记录的是堆栈信息,太长太多,内存被填满了!大量线程产出字符串产出到一半,等待有内存被释放,锁死了,导致整个应用挂掉了。
代码本身有问题,很多情况下抛异常 -> e.printStackTrace() 来打印异常到控制台 -> 产生错误堆栈字符串到字符串池内存空间 -> 此内存空间一下子被占满了 -> 开始在此内存空间产出字符串的线程还没完全生产完整,就没空间了 -> 大量线程产出字符串产出到一半,等在这儿(等有内存了继续搞啊)-> 相互等待,等内存,锁死了,整个应用挂掉了。
2、日志交错混合,不易读printStackTrace()默认使用了System.err输出流进行输出,与System.out是两个不同的输出流,那么在打印时自然就形成了交叉。再就是输出流是有缓冲区的,所以对于什么时候具体输出也形成了随机。
6、日志正确的写法logger.error("测试日志{}{}",”参数1”, "参数2");//正确logger.error("测试日志{}",”参数1”, e);//正确
logger.error("测试日志"+”参数1”);//错误Logger.info("读取字节数组成文件失败:" + e);//错误
//错误,重复输出日志//错误,不用+号拼接字符串的方式 改用占位符{}可以减少参数构造的开销。
调试阶段的日志可用DEBUG级别的日志输出或者去掉无意义的日志输出:
7、log4j日志级别说明log4j定义了8个级别的log(除去OFF和ALL,可以说分为6个级别),优先级从高到低依次为:OFF、FATAL、ERROR、WARN、INFO、DEBUG、TRACE、 ALL。ALL 最低等级的,用于打开所有日志记录。TRACE designates finer-grained informational events than the DEBUG.Since:1.2.12,很低的日志级别,一般不会使用。DEBUG 指出细粒度信息事件对调试应用程序是非常有帮助的,主要用于开发过程中打印一些运行信息。INFO 消息在粗粒度级别上突出强调应用程序的运行过程。打印一些你感兴趣的或者重要的信息,这个可以用于生产环境中输出程序运行的一些重要信息,但是不能滥用,避免打印过多的日志。WARN 表明会出现潜在错误的情形,有些信息不是错误信息,但是也要给程序员的一些提示。ERROR 指出虽然发生错误事件,但仍然不影响系统的继续运行。打印错误和异常信息,如果不想输出太多的日志,可以使用这个级别。FATAL 指出每个严重的错误事件将会导致应用程序的退出。这个级别比较高了。重大错误,这种级别你可以直接停止程序了。OFF 最高等级的,用于关闭所有日志记录。