JAVA日志框架

JAVA日志框架

  • 常见日志框架
  • 日志级别
  • 阿里日志规约
  • 什么时候打印日志
  • 配置文件
    • log4j.properties
    • logback-spring.xml
    • logback的默认配置
  • 导入依赖
  • 日志使用方式,引入slf4j的API
  • 输出用户日志

常见日志框架

日志框架:Log4j 、Logback 。
日志门面:Slf4j。
Logback 是 Slf4j 的原生实现框架,同样也是出自 Log4j 一个人之手,但拥有比 log4j 更多的优点、特性和更做强的性能,现在基本都用来代替 log4j 成为主流。

SLF4J只是日志标准,还是需要实际日志框架。日志框架本身未实现SLF4J API,所以需要有个前置转换。例如log4j需要slf4j-log4j2的依赖
Logback本身就按SLF4J API标准实现,所以无需绑定模块做转换。
JAVA日志框架_第1张图片

日志级别

日志级别 描述
OFF 关闭:最高级别,不输出日志。
FATAL 致命:输出非常严重的可能会导致应用程序终止的错误。
ERROR 错误:输出错误,但应用还能继续运行。
WARN 警告:输出可能潜在的危险状况。
INFO 信息:输出应用运行过程的详细信息。
DEBUG 调试:输出更细致的对调试应用有用的信息。
TRACE 跟踪:输出更细致的程序运行轨迹。
ALL 所有:输出所有级别信息。

阿里日志规约

  1. 【强制】应用中不可直接使用日志系统(Log4j、Logback)中的 API,而应依赖使用日志框架
    (SLF4J、JCL–Jakarta Commons Logging)中的 API,使用门面模式的日志框架,有利于维护和
    各个类的日志处理方式统一。
    说明:日志框架(SLF4J、JCL–Jakarta Commons Logging)的使用方式(推荐使用 SLF4J)
    使用 SLF4J:
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    private static final Logger logger = LoggerFactory.getLogger(Test.class);
    使用 JCL:
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    private static final Log log = LogFactory.getLog(Test.class);

  2. 【强制】所有日志文件至少保存 15 天,因为有些异常具备以“周”为频次发生的特点。对于
    当天日志,以“应用名.log”来保存,保存在/home/admin/应用名/logs/目录下,
    过往日志格式为: {logname}.log.{保存日期},日期格式:yyyy-MM-dd
    说明:以 mppserver 应用为例,日志保存在/home/admin/mppserver/logs/mppserver.log,历史日志
    名称为 mppserver.log.2016-08-01

  3. 【强制】应用中的扩展日志(如打点、临时监控、访问日志等)命名方式:
    appName_logType_logName.log。logType:日志类型,如 stats/monitor/access 等;logName:日志描
    Java 开发手册
    31/57
    述。这种命名的好处:通过文件名就可知道日志文件属于什么应用,什么类型,什么目的,也有利于归类查
    找。
    说明:推荐对日志进行分类,如将错误日志和业务日志分开存放,便于开发人员查看,也便于通过日志对系
    统进行及时监控。
    正例:mppserver 应用中单独监控时区转换异常,如:mppserver_monitor_timeZoneConvert.log

  4. 【强制】在日志输出时,字符串变量之间的拼接使用占位符的方式。
    说明:因为 String 字符串的拼接会使用 StringBuilder 的 append()方式,有一定的性能损耗。使用占位符仅
    是替换动作,可以有效提升性能。
    正例:logger.debug(“Processing trade with id: {} and symbol: {}”, id, symbol);

  5. 【强制】对于 trace/debug/info 级别的日志输出,必须进行日志级别的开关判断。
    说明:虽然在 debug(参数)的方法体内第一行代码 isDisabled(Level.DEBUG_INT)为真时(Slf4j 的常见实现
    Log4j 和 Logback),就直接 return,但是参数可能会进行字符串拼接运算。此外,如果 debug(getName())
    这种参数内有 getName()方法调用,无谓浪费方法调用的开销。
    正例:
    // 如果判断为真,那么可以输出 trace 和 debug 级别的日志
    if (logger.isDebugEnabled()) {
    logger.debug(“Current ID is: {} and name is: {}”, id, getName());
    }

  6. 【强制】避免重复打印日志,浪费磁盘空间,务必在 log4j.xml 中设置 additivity=false。
    正例:

  7. 【强制】生产环境禁止直接使用 System.out 或 System.err 输出日志或使用
    e.printStackTrace()打印异常堆栈。
    说明:标准日志输出与标准错误输出文件每次 Jboss 重启时才滚动,如果大量输出送往这两个文件,容易
    造成文件大小超过操作系统大小限制。
    public void printStackTrace() {
    printStackTrace(System.err);
    }它其实也是利用 System.err 输出到了 tomcat 控制台。

  8. 【强制】异常信息应该包括两类信息:案发现场信息和异常堆栈信息。如果不处理,那么通过
    关键字 throws 往上抛出。
    正例:logger.error(各类参数或者对象 toString() + “_” + e.getMessage(), e);

  9. 【强制】日志打印时禁止直接用 JSON 工具将对象转换成 String。
    说明:如果对象里某些 get 方法被重写,存在抛出异常的情况,则可能会因为打印日志而影响正常业务流
    程的执行。
    正例:打印日志时仅打印出业务相关属性值或者调用其对象的 toString()方法。
    10.【推荐】谨慎地记录日志。生产环境禁止输出 debug 日志;有选择地输出 info 日志;如果使用
    warn 来记录刚上线时的业务行为信息,一定要注意日志输出量的问题,避免把服务器磁盘撑
    爆,并记得及时删除这些观察日志。
    Java 开发手册
    32/57
    说明:大量地输出无效日志,不利于系统性能提升,也不利于快速定位错误点。记录日志时请思考:这些
    日志真的有人看吗?看到这条日志你能做什么?能不能给问题排查带来好处?
    11.【推荐】可以使用 warn 日志级别来记录用户输入参数错误的情况,避免用户投诉时,无所适
    从。如非必要,请不要在此场景打出 error 级别,避免频繁报警。
    说明:注意日志输出的级别,error 级别只记录系统逻辑出错、异常或者重要的错误信息。
    12.【推荐】尽量用英文来描述日志错误信息,如果日志中的错误信息用英文描述不清楚的话使用
    中文描述即可,否则容易产生歧义。
    说明:国际化团队或海外部署的服务器由于字符集问题,使用全英文来注释和描述日志错误信息

什么时候打印日志

1、当你遇到问题的时候,只能通过debug功能来确定问题,你应该考虑打日志,良好的系统,是可以通过日志进行问题定为的。
2、当你碰到if…else 或者 switch这样的分支时,要在分支的首行打印日志,用来确定进入了哪个分支
3、经常以功能为核心进行开发,你应该在提交代码前,可以确定通过日志可以看到整个流程
4、不要在循环中打印日志。
5、接口的入参,出参打印日志。
6、禁止在生产环境中开启debug日志。
7、error 异常或者重要的错误信息
8、warn 日志级别来记录用户输入参数错误的情况,例如else用户名不存在,记录刚上线时的业务行为信息,一定要注意日志输出量的问题,避免把服务器磁盘撑
爆,并记得及时删除这些观察日志
9、info,记录传参数信息,进入那个条件分支

配置文件

log4j.properties

###配置日志根Logger
log4j.rootLogger=DEBUG,stdout,D,E,I,file
#ERROR 为严重错误 主要是程序的错误
#WARN 为一般警告,比如session丢失
#INFO 为一般要显示的信息,比如登录登出
#DEBUG 为程序的调试信息
log4j.additivity.org.apache=true
###配置日志信息输出目的地Appender
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
### 输出到日志文件 ###
#org.apache.log4j.ConsoleAppender(控制台)
#org.apache.log4j.FileAppender(文件)
#org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件)
#org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件)
#org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方)
#log4j.appender.error.Target=System.out
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = /data/log/bill.debug.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.DatePattern='.'yyyy-MM-dd-HH-mm
# '.'yyyy-MM:每月
# '.'yyyy-ww:每周
# '.'yyyy-MM-dd:每天
# '.'yyyy-MM-dd-a:每天两次
# '.'yyyy-MM-dd-HH:每小时
# '.'yyyy-MM-dd-HH-mm:每分钟
#log4j.appender.file.MaxFileSize=1MB
###滚动文件的最大数
#log4j.appender.file.MaxBackupIndex=8
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} [%-5p](%-30c{1}) [TxId : %X{PtxId} , SpanId : %X{PspanId}] [ET:%X{ENV_TYPE},AN:%X{APP_NAME},SN:%X{SERVICE_NAME},CN:%X{CONTAINER_NAME},CI:%X{CONTAINER_IP}] %m%n
log4j.appender.file.Threshold=DEBUG
###将消息增加到指定文件中,false指将消息覆盖指定的文件内容
log4j.appender.file.append=true
###日志的保存位置
#log4j.appender.file.File=E:/logs/file-debug-log.log
log4j.appender.file.File=E:/logs/debug-debug.log
###每天产生一个日志文件
#log4j.appender.file=org.apache.log4j.DailyRollingFileAppender
#log4j.appender.file.layout=org.apache.log4j.PatternLayout
#log4j.appender.file.maxFileSize=100
#log4j.appender.file.maxBackupIndex=5
#log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} [%-5p](%-30c{1}) [TxId : %X{PtxId} , SpanId : %X{PspanId}] [ET:%X{ENV_TYPE},AN:%X{APP_NAME},SN:%X{SERVICE_NAME},CN:%X{CONTAINER_NAME},CI:%X{CONTAINER_IP}] %m%n
#log4j.appender.file.Threshold=DEBUG
#log4j.appender.file.append=true
#log4j.appender.file.File=E:/logs/debug-log.log
 
 
 
log4j.appender.D.Append = true
log4j.appender.D.Threshold = DEBUG
###配置日志信息的格式(布局)
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
#org.apache.log4j.HTMLLayout(以HTML表格形式布局)
#org.apache.log4j.PatternLayout(可以灵活地指定布局模式)
#org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串)
#org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等等信息)
log4j.appender.D.layout = org.apache.log4j.PatternLayout
###配置日志打印的格式格式化日志信息
#%m   输出代码中指定的消息
#%p   输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL
#%r   输出自应用启动到输出该log信息耗费的毫秒数
#%c   输出所属的类目,通常就是所在类的全名
#%t   输出产生该日志事件的线程名
#%n   输出一个回车换行符,Windows平台为“\r\n”,Unix平台为“\n”
#%d   输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss , SSS}
#%l   输出日志事件的发生位置,包括类目名、发生的线程,以及在代码中的行数
 
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [%t:%r] - [%p] %m%n
 
### 输出到日志文件 ###
log4j.appender.I = org.apache.log4j.DailyRollingFileAppender
log4j.appender.I.File = /data/log/bill.info.log
log4j.appender.I.Append = true
log4j.appender.I.Threshold = INFO
log4j.appender.I.layout = org.apache.log4j.PatternLayout
log4j.appender.I.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [%t:%r] - [%p] %m%n
 
### 保存异常信息到单独文件 ###
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File = /data/log/bill.error.log
log4j.appender.E.Append = true
log4j.appender.E.Threshold = ERROR
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern =%-d{yyyy-MM-dd HH:mm:ss} [%t:%r] - [%p] %m%

logback-spring.xml



     
    
    
    
       
    
    

    
    
    
    
    
    
    
    
    

    
        
            
                ${CONSOLE_LOG_PATTERN}
                utf-8
            
        
    

    
    
        ${LOG_PATH}/aipbcp_oauth_${logName}.log
        
            ${LOG_PATH}/aipbcp_oauth_${logName}.%d{yyyy-MM-dd}.%i.log
            
            
                ${LOG_FILE_SIZE}
            
        
        
            
            ${FILE_LOG_PATTERN}
            utf-8
        
    

    
    
    

    
    
        
        
    


日志配置文件概念
appender:追加日志类,ConsoleAppender,RollingFileAppender
rollingPolicy:appender的方法,回滚属性,可以设置日志保存时间,日志文件名,日志大小
encoder:appender的方法,日志的编码方式,日志输出的格式
filter:appender的方法,可以过滤不同级别的日志,日志分级别输出

root:可以用来注册appender,例如:STDOUT,error_file,info_file,可以将不同级别的日志输出到文件控制台

logback的默认配置

springboot2.x默认记录控制台日志。

logging:
  config: classpath:logback-spring.xml
  level:
  	com.fang: debug

导入依赖

一般启动器都含有spring-boot-starter. -------->. spring-boot-starter-logging. ---------> logback,因此不需要再手动的导入依赖
在Spring Boot 2.x及以上版本中,默认使用logback作为日志记录框架。

当logback和log4j同时存在于类路径上时,Spring Boot会自动屏蔽log4j,并使用logback进行日志记录。这是因为Spring Boot会检测到logback的存在并优先选择使用它。这样可以避免潜在的冲突和兼容性问题

日志使用方式,引入slf4j的API

方式一:
private final Logger logger = LoggerFactory.getLogger(RequestInterceptor.class);
方式二:使用lombok的注解
@Slf4j

输出用户日志

1、每个类都可以配置自己的logger

private static final Logger logger = LoggerFactory.getLogger("sys-user");
或者
private static final Logger logger = LoggerFactory.getLogger(this.CLASS);

2、每个logger都可以设置自己的输出日志级别


   
       
   
   

这里制定logger的输出级别为info,即使在代码中logger.debug,也不会输出对应的日志
3、root logger也可以设置自己的级别,root logger的输出级别优先于logger生效


    
    

4、给logger绑定appender,


   
   ${log.path}/sys-user.log
       
           
           ${log.path}/sys-user.%d{yyyy-MM-dd}.log
           
           60
       
       
           ${log.pattern}
       
   

5、root logger可以统一绑定appender输出不同级别日志,但是需要给appender设置filter,因为输出debug日志的同时会输出info级别的


    ${log.path}/sys-error.log
       
       
           
           ${log.path}/sys-error.%d{yyyy-MM-dd}.log
      
      60
       
       
           ${log.pattern}
       
       
           
           ERROR
      
           ACCEPT
      
           DENY
       
   

你可能感兴趣的:(java基础深挖,java,log4j,apache)