log4j系列一:log4j简介以及Loggers

简介

经验表明,在项目中使用日志是有很多益处的。譬如查看bug、查看应用执行的记录等。但是他也是有缺点的,典型的就是拖慢了应用系统响应的时间。

在平时开发中,任何一个中小型的项目可能都会采用自己的日志记录方式,最著名的就是System.out.println这种类似的。但是在大型的商务系统中,采用System.out.println很明显不能满足系统的需求。log4j就是在这样的情形下诞生的。

log4j是一个成熟的日志系统。经历过了1.x时代,目前我们主要使用的都是2.x,1.x至2015年8月5日起不在维护。到目前为止,log4j已被引用到C、C++、C#、Perl、Python等语言中。在此我们主要介绍Java系的。

log4j中最主要的几个概念分别是Loggers(记录器)、Appenders(输出源)和Layouts(布局器)。可分别理解为日志类别,日志要输出的地方和日志以何种形式输出。综合使用这三个组件可以轻松地记录信息的类型和级别,并可以在运行时控制日志输出的样式和位置。

首先我们来介绍Loggers。

Loggers

Logger结构

Loggers其实就是一些命名的实体。在log4j中,创建的方式为:

public class App {
    private static final Logger log = LoggerFactory.getLogger(App.class);
}

之后,log4j会将创建的Logger实例保存在一个ConcurrentMap中。以上面的代码为例,key则为App.class.getName(),value则为log实例。从这里可以看出,Logger的名字是大小写敏感的,如果key不同,则之后获取到的Logger实例则不同。Logger的名字一般为类的全限定名,当然你也可以自己指定,因为它的构造函数中可以用String来指定,但是务必要清晰明了。

log4j定义了一套结构,即一个logger A的名字为另一个logger B的名字+“.”构成的话,则B是A的祖先。如果B和A之间没有其他的logger的话,则B是A的父亲。但是,不管如何,任何一个logger都有一个共同的祖先叫root,且root是原始祖先,你不能根据名称来获取root Logger,但是你可以采用Logger.getRootLogger()来获得它。

例如,indi.latchindi.latch.training的祖先,明确的说是它的父亲。再比如说,javajava.util的父亲,是java.util.Vector的祖先。

Logger优先级

为了能更好的控制日志输出,log4j还提供了Logger的优先级。常见的级别有DEBUG、INFO、WARN、ERROR和FATAL(你也可以定义自己的级别)。其级别关系为DEBUG < INFO < WARN < ERROR < FATAL

Logger的优先级是可以传递的。如果指定的一个Logger没有赋值优先级,则会从其最近的具有优先级的祖先中获取优先级,直至到root。

以下展示了四种赋值不同优先级及获取优先级的情况:

表1:只有root具有优先级,那么其子Logger都会继承root的优先级。

Logger名称赋值优先级继承优先级
rootProotProot
indinoneProot
indi.latchnoneProot
indi.latch.trainingnoneProot

表2:各个Logger都具有自己的优先级,则无需获取其祖先类优先级

Logger名称赋值优先级继承优先级
rootProotProot
indiP1P1
indi.latchP2P2
indi.latch.trainingP3P3

表3:indi.latch的Logger没有优先级,其父亲具有优先级,则从其父亲indi中获取

Logger名称赋值优先级继承优先级
rootProotProot
indiP1P1
indi.latchnoneP1
indi.latch.trainingP3P3

表4:indi.latch和indi.latch.training的Logger没有优先级,则其最近具有优先级的祖先indi中获取

Logger名称赋值优先级继承优先级
rootProotProot
indiP1P1
indi.latchnoneP1
indi.latch.trainingnoneP1

log4j的优先级可以控制日志的输出。这很重要,因为log4j只会输出级别高于或等于设定级别的日志。Logger日志输出常见的方法如下:

package org.apache.log4j;

  public class Logger {

    // Creation & retrieval methods:
    public static Logger getRootLogger();
    public static Logger getLogger(String name);

    // printing methods:
    public void trace(Object message);
    public void debug(Object message);
    public void info(Object message);
    public void warn(Object message);
    public void error(Object message);
    public void fatal(Object message);

    // generic printing method:
    public void log(Level l, Object message);
}

debug即表示采用DEBUG级别输出日志;info表示采用INFO级别输出,其他依次类推。

最后我们给出一个设置优先级和采用优先级输出的小例子:

public class App {
    // 获取一个命名为indi.latch的Logger
    private static final Logger  logger = Logger.getLogger("indi.latch");

    // 获取一个命名为indi.latch.training的Logger
    private static final Logger trainLogger = Logger.getLogger("indi.latch.training");

    public static void main( String[] args ) {
        //加载基本的配置(后面会讲解)
        BasicConfigurator.configure();

        //设置indi.latch Logger的优先级为INFO
        logger.setLevel(Level.INFO);

        // 这次日志会输出,因为WARN>INFO
        logger.warn("Low fuel level.");

        //这次日志不会输出,因为DEBUG<INFO
        logger.debug("Starting search for nearest gas station.");

        //这次日志会输出。因为trainLogger会获取logger的优先级,即INFO
        trainLogger.info("Located nearest gas station.");

        //这次日志不会输出。因为trainLogger会获取logger的优先级,即INFO,但是DEBUG<INFO
        trainLogger.debug("Exiting gas station search");
    }
}
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值