日志输出规范

 

1log4j日志参数说明

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{yyyy MM dd HH:mm:ss,SS},可不带后面的日期格式字符。

m  log事件的消息内容

根据所运行的平台输出相应的行分隔字符。

 

 

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.printlnSystem.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级别的日志输出或者去掉无意义的日志输出:

 

 

 

 

7log4j日志级别说明

log4j定义了8个级别的log(除去OFFALL,可以说分为6个级别),优先级从高到低依次为:OFFFATALERRORWARNINFODEBUGTRACEALL

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 最高等级的,用于关闭所有日志记录。

posted @ 2020-04-09 10:34  黄进广寒  阅读(2368)  评论(0编辑  收藏  举报