zoukankan      html  css  js  c++  java
  • 日志工具全面理解及配置应用---以Log4j例子

    一.日志系统基本常识

    1.日志系统作用:将日志信息输出到控制台和文本文件,以追踪代码运行信息。

    2.日志系统操作的是什么?日志系统打印信息,也是调用日志系统的log.Info(),log.Warn()这些方法的,调用方法就要消耗cpu和栈,尤其日志系统的输入参数和输出参数都是字符串,日志系统输出的都是字符串信息,否则怎么显示在控制台和保存在文本文件中嘛,所以就更消耗cpu了和内存了。因为涉及很多字符串的拼接操作,在log的info和warn()入参中。且,在log的info和warn()入参中,我们还经常调用其他方法,所以日志系统的输出方法,是很消耗cpu和内存的。

    3.那么应该如何避免日志系统影响程序运行效率呢?

    常用方法:1.避免log.info(),debug()入参提前生成,免去无用功,通过加入判断日志系统级别的代码,即if(logger.isInfoEnabled()).避免日志输出方法参数的提前生成。因为logger.info方法内部有判断输出级别的代码。但是在进入logger.info函数之前,("User " + userId + " is using app " + appId) 这个表达式已经通过运算拼接成了一个字符串;而如果事先使用 if (logger.isInfoEnabled())进行判断,那么当log级别在INFO以上时,就能省去上述的字符串操作,在高并发和复杂log信息拼接的情况下,使用这种标准的方法输出log能够省去不小的系统开销。另外,如果构造log信息的过程需要大量字符串操作,建议使用StringBuilder来完成字符串拼接。---防止更高日志输出级别时,判断了低级别但不输出。

    2.java正确声明实例化new logger。尽量将所有logger是声明为static静态的保证内存中只声明一份。否则多次创建同一个对象,就白白创建了多个logger实例。

    3.log.info(),log.debug()这些传参中,尽量避免一些复杂的调用,比如Log.info()里再连接数据库读取user的名字。

    4.日志系统是已经写好了的功能代码:是一段JDK里或者其他JAR包里已经写好的代码,是代码,才能执行输入输出嘛。JAVA有自己实现的日志系统,就在java.util包里,叫java.util.logging。这是JDK自带的日志系统,还有常用的Apache log4j,第三方日志工具。

    5.我们常用的日志工具有三种:jdk自带的日志工具,第三方日志工具Apache log4J,和第三方SLF4J。Apache log4J要引用jar包到buildpath。这里重点讲一下slf4j,这个才是最常用的。

    6. slf4j并不能真正提供打印功能,它只是其他日志工具的封装,将不同的日志工具接口抽象出来。提供真正打印功能的还是log4j或者jdk日志工具。Slf4j的使用,使我们可以跨越和随意更换不同的具体日志实现工具,而不必更改代码和jar包import引用语句。

    用途:比如,你想写一个jar包供其他人使用,jar包里的类和方法要打印一些信息,因为你不知道具体系统究竟用什么日志工具,所以在你jar包里,就可以完全使用slf4j打印。等他人系统调用你jar包时,你jar包里的打印方法会由具体的本地系统所有的日志工具实现。

    如果你开发的是类库或者供其他人使用的组件,那么就应该考虑采用SLF4J,因为不可能影响最终用户选择哪种日志系统。

    7.使用SLF4J项目的日志结构,具体项目,就要有log4j日志实现工具jar包,和slf4j实现工具jar包。

    8.日志工具的几个输出级别:日志系统有5个输出级别,debug,info,warn,error,fatal,一个等级比一个等级高。

    Debug,最低级别,一般在生产环境,是不进行输出的,只在测试环境输出,任何在调试代码时,一些必要的信息,输出来都行。

    Info输出级别:info输出的信息是可以给使用人员顾客看的,在生产环境中是肯定要输出info级别的日志的。某种程度来讲,info级别的日志输出,是可以当做软件的一部分的。

    Warn,error,fatal:这三个级别都是很高的级别。

    9.日志级别规则:低级别的日志输出,会一并输出比目前级别高的输出。比如,日志输出级别定为debug,debug是最低级别,所以一定会打印出info,warn,error,fatal都会输出。

    答:因为 Info 的级别是如此之低,所以为了让用户能够看到有效的输出信息,必须将日志级别开放到 Info 级别。但是 Warn 的级别比 Info 要高,所以用户不得不被迫看到一些 Warn 的信息。而我们其实已经假定,Warn 信息其实并不影响系统的正常运行,这一般只代表系统中存在一些还没有被发现或者修改的小 Bug。这些 Warn 信息会让最终用户困惑甚至恐慌,系统发出警告了,该怎么办?

    10.日志系统只有1个:因为进行控制台输出嘛,相当于打印机一样,多个logger只能按序输出。多线程调用日志系统时候,两行日志输出之间有可能会被插入其他线程的日志记录,不会按照我们的意愿顺序输出。

    11.判断日志界别,避免生成无效入参。这完全是防止当目前日志级别log输出所用级别高时,做的无效入参形成。记住,是防止防止当目前日志级别log输出所用级别高时。因为判断日志级别的代码,是在log,info(),debug()这里方法里的代码,参数已经被形成了。

    二.在代码哪里使用日志,及怎么使用?

    1.一定要日志对象logger,声明为static静态的,保证一个类只有一个logger对象,避免多次创建对象时多次创建logger,造成内存浪费。

    private static org.slf4j.Logger logger = LoggerFactory.getLogger(APPMain.class);

     

    2.一定要加入日志级别判断java代码,logger.isInfoEnabled(),避免入参无效形成,做无用功。提高效率。(在调用任何方法前,都是先执行和生成方法的入参,再去执行方法里的代码,这涉及到创建栈,一个方法被调用时,就创建一个新的栈空间,就会先创建方法入参。)---防止更高日志输出级别时,判断了低级别但不输出。

     

    3. 系统启动的参数、配置、环境变量、System.Properties等信息一定要打印日志:对于软件的正常运行至关重要,这些信息的输出有助于安装配置人员通过日志快速定位问题,所以程序有必要在启动过程中把使用到的关键参数、变量在日志中输出出来。

     

    4. 关键步骤增删改查一定要打印日志:比如,增删改查地方一定要添加打印。因为这涉及到数据是否更改成功。用于提示程序员。

     

    5.捕获异常处一定要打印日志且不要再向外抛出异常,打印内容是stacktrace堆栈信息。堆栈信息描述了发生异常时候的瞬间堆栈信息。会指出报错位置和地方。既然你已经打印了日志信息,就不要再抛出异常了。异常处直接用looger.error()方法输出。

    catch (Exception e) {

                         if(logger.isErrorEnabled()) {

                                logger.error("init um2UserService error", e);

                         }

    三.怎样配置使用日志工具?

    1.配置Log4j:Log4j配置文件,就是个properties文件,里面是keyvalue键值对,等号相连。Appender 为日志输出目的地,Log4j提供的appender有以下几种:

    能够输出到控制台,文件,每日输出文件,文件到指定大小时候产生新文件,发送日志。

    org.apache.log4j.ConsoleAppender(控制台),
    org.apache.log4j.FileAppender(文件),
    org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件),
    org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件),
    org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方)

    2)为不同的 Appender 设置日志输出级别:

    ### 输出到日志文件 ###
    log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
    log4j.appender.D.File = logs/log.log
    log4j.appender.D.Append = true
    log4j.appender.D.Threshold = DEBUG ## 输出DEBUG级别以上的日志
    log4j.appender.D.layout = org.apache.log4j.PatternLayout
    log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n

    ### 保存异常信息到单独文件 ###
    log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
    log4j.appender.D.File = logs/error.log ## 异常日志文件名
    log4j.appender.D.Append = true
    log4j.appender.D.Threshold = ERROR ## 只输出ERROR级别以上的日志!!!
    log4j.appender.D.layout = org.apache.log4j.PatternLayout
    og4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n

    2.项目中怎样启动Log4j?

    答:将jar包引入buildpath,并配置好log4j.properties配置文件后。就可以直接使用logger了,logger类的第一次加载时候,会自动初始化lo4j的配置文件,通过static代码块的方式。

    注:但凡自动读取配置文件,全都是用static初始化块来调用的,初始化快用来执行配置文件的读取。

  • 相关阅读:
    ZABBIX实现原理及架构详解
    for(;;)和while(true)的区别
    JVM
    javap的基本用法
    Java VisualVM添加Visual GC插件
    Java虚拟机监控命令
    数据类型 原始类型的方法
    数据类型 数字类型
    Object(对象):基础知识 原型对象prototype
    Object(对象):基础知识 对象方法,"this"
  • 原文地址:https://www.cnblogs.com/panxuejun/p/6425744.html
Copyright © 2011-2022 走看看