您的位置:首页 > 其它

log4j系列一:log4j简介以及Loggers

2016-05-19 19:40 369 查看

简介

经验表明,在项目中使用日志是有很多益处的。譬如查看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.latch
indi.latch.training
的祖先,明确的说是它的父亲。再比如说,
java
java.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");
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: