zoukankan      html  css  js  c++  java
  • 如何正确使用log4j

     

    如何正确使用log4j?

    关键字: 如何正确使用log4j?

    Java Web开发的过程中,通过会采用输出log的方式来进行调试,产品上线之后,也通常使用log来记录系统的运行状态。最简单的输出log的方式就是使用System.out.println(String msg)和System.err.println(String msg),然而这种方式的弊端是显而易见的,例如:
    1. 调试期输出log的代码,在上线运行前需要注释掉,否则可能会影响系统性能或者造成日志文件过于庞大。当出现问题需要跟踪的时候,又需要修改代码,删除注释符以打开这些debug的log,非常不方便;
    2. 所有的业务的log都会输出到一个文件中去,查看起来很不方便。
     
        多亏apache开源社区为所有Java开发者提供了Log4j这个非常弓虽大的log工具,把我们从 维护log的繁重工作中解脱了出来。Log4j可能通过配置文件实现多logger,每个logger可以有不同的输出文件、输出格式和log级别,具体 细节我就不再赘述,不了解的同学可以参考相关的文档或者示例代码。
     
        这里主要总结几点Log4j使用过程中的常见问题和注意事项,阅读一下内容之前,下面的文章将假设你已经有一定的Log4j使用经验了。
     
    • 1. 获取Logger实例的方法:
    protected static final Logger logger = Logger.getLogger("logger_name");
    private static final Logger logger = Logger.getLogger("logger_name");
     
    还有一个获取Logger的方法:
    Logger.getLogger(Class clazz);
     
    1.1 为什么要加“static”?
        因为同一个logger name对应唯一的Logger实例,而Logger.getLogger方法在从logger容器中取logger的过程中,有一个步骤被加了同步锁, 这就造成了如果在多线程的竞争环境中频繁地调用getLogger操作,有可能会造成堵塞。而且这种操作是没有价值的,所以使用static来保证需要需 用Logger的类所有的对象共享一个Logger的引用,并且只获取一次就可以了。
    1.2 为什么要加“final”
        防止多logger同时使用时,Logger引用不小心被赋值,这是一个良好的编程习惯。
    1.3 Logger.getLogger(String loggerName)与Logger.getLogger(Class clazz)有什么区别?
        本质上是一样的,Logger.getLogger(Class clazz)方法实际上是调用了Logger.getLogger(clazz.getName())来获取Logger的。
    1.4 log4j配置文件中没有配置logger_name对应的logger怎么办?
        如果没有logger_name对应的配置,则Logger.getLogger方法返回默认的logger。
     
    •  2. Logger共有6个log级别,按优先级由低到高排序分别是:
        TRACE < DEBUG < INFO < WARN < ERROR < FATAL
        他们分别对应Logger的trace, debug, info, warn, error和fatal方法进行输出,但是我们通常只使用debug、info和error这三个最常用的级别。运行时的log输出级别可以通过更改log4j配置文件来进行配置,就免去了注释掉debug代码的尴尬。
     
    • 3. 输出log的正确方式:
        if (logger.isInfoEnabled()) {
            logger.info("User " + userId + " is using app " + appId);
        }
    3.1 为什么要加上logger.isInfoEnabled()?
        直接使用logger.info("User " + userId + " is using app " + appId)来输出log,也能够达到log级别为INFO或在INFO以下时才输出:("User " + userId + " is using app " + appId),因为logger.info方法内部有判断输出级别的代码。但是在进入logger.info函数之前,("User " + userId + " is using app " + appId) 这个表达式已经通过运算拼接成了一个字符串;而如果事先使用 if (logger.isInfoEnabled())进行判断,那么当log级别在INFO以上时,就能省去上述的字符串操作,在高并发和复杂log信息拼 接的情况下,使用这种标准的方法输出log能够省去不小的系统开销。另外,如果构造log信息的过程需要大量字符串操作,建议使用 StringBuilder来完成字符串拼接。
    3.2 ERROR及其以上级别的log信息是一定会被输出的,所以只有logger.isDebugEnabled和logger.isInfoEnabled方法,而没有logger.isErrorEnabled方法。
     
    • 4. debug、info、error等输出log的方法是线程安全的,请放心使用。
     
    • 5. log有风险,输出需谨慎!由于输出log过程需要进行磁盘操作,且log4j为了保证log输出过程的线程安全性而使用同步锁,就使得输出log成为很耗时的操作,所以log信息一定要言简意赅,不要输出一些无用的log。
     
        以上为我个人的使用经验,欢迎大家指教和补充。
     
        最后,祝愿log4j给大家带来更加愉快的开发体验。
  • 相关阅读:
    八数码难题 (codevs 1225)题解
    小木棍 (codevs 3498)题解
    sliding windows (poj 2823) 题解
    集合删数 (vijos 1545) 题解
    合并果子 (codevs 1063) 题解
    等价表达式 (codevs 1107)题解
    生理周期 (poj 1006) 题解
    区间 (vijos 1439) 题解
    区间覆盖问题 题解
    种树 (codevs 1653) 题解
  • 原文地址:https://www.cnblogs.com/strive-study/p/5076762.html
Copyright © 2011-2022 走看看