一、用途

程序中记录日志,打印到控制台、文件等方式,记录过程可根据日志级别做筛选,日志格式可以自定义。

大概结构如下所示:

java系统日志框架 java搭建日志模块_记录日志

简要说明各个模块:

(1) LogManager:管理LoggerContext及Logger,可以添加、获取Logger。

(2) LoggerContext: 保存所有Logger,用于添加及获取Logger,由LoggerManager管理。LoggerContext中同时保存了Logger的弱引用,在释放Logger时使用到。

(3) Logger: 记录日志的对象,提供接口实现对日志消息以不同的日志级别进行记录,管理Handler、Formatter、Filter等。

(4) Handler: 记录日志真正的对象,包括FileHandler(记录到文件)、ConsoleHandler(记录到控制台)、StreamHandler(记录到流)、SocketHandler(通过socket发送日志?)等。

(5) Formatter: 处理日志的格式,包括SimpleFormatter(简单格式记录,显示时间、级别、线程、日志信息等)、XMLFormatter(以xml格式记录日志)等。

(6) Filter: 实现日志的过滤功能,通过自定义Filter,实现对某些日志的过滤处理。

(7) ErrorManager: 记录日志出错时的处理对象?

(8) LogRecord: 对日志消息的抽象。

二、详细介绍(结合源码)

详细描述如下:

(1)日志管理:

java系统日志框架 java搭建日志模块_xml_02

LoggerManager主要用来管理LogContext以及logger。

LoggerManager维护变量主要有:

(a) LogManager manager

manager对象单例,用于LogManager内部其他方法调用。在静态构造函数中实例化,在getLogManager()方法被调用时初始化:

1 public staticLogManager getLogManager() {2 if (manager != null) {3 manager.ensureLogManagerInitialized();4 }5 returnmanager;6 }7
8
9 public voidensureLogManagerInitialized() //简要描述10 {11 //若未初始化
12 synchronized(this)13 {14 owner.readPrimordialConfiguration(); //读配置文件初始化manager
15 owner.rootLogger = owner.new RootLogger(); //添加rootLogger
16 owner.addLogger(owner.rootLogger);17 final Logger global = Logger.global; //添加globalLogger
18 owner.addLogger(global);19 }20 }
(b) Properties props

用于读配置文件内容,配合完成初始化。上述readPrimordialConfiguration()函数即使用了Props获取配置。

主要针对配置文件中对Logger及Handler等定义,进行动态设置。

默认的配置文件如下:

handlers=java.util.logging.ConsoleHandler
.level=INFO
java.util.logging.FileHandler.pattern= %h/java%u.log
java.util.logging.FileHandler.limit= 50000java.util.logging.FileHandler.count= 1java.util.logging.FileHandler.formatter=java.util.logging.XMLFormatter
java.util.logging.ConsoleHandler.level=INFO
java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter
com.xyz.foo.level= SEVERE

主要对默认Handler进行配置(ConsoleHanlder,默认只打印日志到控制台),设置FileHandler的一些配置(文件名格式、写文件大小限制、使用文件数量、日志格式为xml),设置ConsoleHandler控制台打印的格式为普通格式(SimpleFormatter)、打印日志级别最低为INFO。

(c)  LggerContext userContext

LogContext是LogManager的内部类。

LogManager中包含默认两个LoggerContext: userContext与systemContext,用户添加logger皆是放入userContext。

java系统日志框架 java搭建日志模块_java_03

LoggerContext内部,Logger被放入LogNode root中以链表形式存储。

该类对LogManager开放接口:

添加Logger: addLogger

synchronized boolean addLocalLogger(Logger logger, boolean addDefaultLoggersIfNeeded) { //简要说明
final LogManager owner = getOwner(); //设置logmanager
logger.setLogManager(owner);
LoggerWeakRef ref = owner.new LoggerWeakRef(logger);
namedLoggers.put(name, ref); //保存弱引用
Level level = owner.getLevelProperty(name + ".level", null); //设置Level
if (level != null && !logger.isLevelInitialized()) {
doSetLevel(logger, level);
}
processParentHandlers(logger, name); //设置父Logger(rootLogger)
Logger parent = getParentLogger();
if (parent != null) {
doSetParent(logger, parent);
}
return true;
}
查找Logger: findLogger
(d) logManager.addLogger(Logger logger)方法
void addLogger(Logger logger)
{
final String name = logger.getName();
if (name == null) {
throw new NullPointerException();
}
LoggerContext cx = getUserContext();
if (cx.addLocalLogger(logger)) {
loadLoggerHandlers(logger, name, name + ".handlers"); //根据配置文件加载logger对应handler
}
}

(e) logManager.demandLogger

调用loggerContext接口,构造logger并添加至loggerContext。

(2) 日志打印

java系统日志框架 java搭建日志模块_java系统日志框架_04

(a) name: String

logger的名称。

例如:Logger logger = Logger.getLogger("test"); 则,logger名称为"test";

(b) handlers: List、addHanlder(Handler) //设置日志处理对象

Handler是日志处理类的基类,子类主要有ConsoleHandler、FileHandler、SocketHandler、StreamHandler、MemoryHandler。

Handler负责将日志消息写到指定位置。

该变量负责维护logger上的handlers,通过addHandler(Handler)添加,removeHandler(Handler)移除

一个logger具备多个handlers,因此,一条日志可依据定制情况打印到多个位置。

例如,通过这样,可以为logger添加具备特定formatter、loglevel的handlers:

Logger logger = Logger.getLogger(loggerName);
logger.setLevel(Level.INFO);
//添加文件输出xml格式
Handler fileXMLhandler = new FileHandler("E:\\logging_XMLFormat.file");
Formatter xmlFormatter = new XMLFormatter();
fileXMLhandler.setFormatter(xmlFormatter);
handler.setLevel(Level.WARNING);
logger.addHandler(handler);
//添加文件输出普通格式
Handler fileSimpleHandler = new FileHandler("E:\\logging_simpleFormat.file");
Formatter formatter = new SimpleFormatter();
handler.setFormatter(formatter);
handler.setLevel(Level.INFO);
logger.addHandler(handler);
//添加控制台输出
Handler consoleHandler = new ConsoleHandler();
logger.addHandler(consoleHandler);

(c) Filter、Handler.setFilter(Filter) //设置过滤器

用于过滤logRecord。

接口包含:

boolean isLoggable(in LogRecord);

实现Filter自定义设置过滤规则。

(d) Logger.getLogger(String name) //获取logger

获取logger(若无,则先添加后返回)

eg.

Logger logger = Logger.getLogger("testLogger");
logger.info("this is a test msg");

(e) Logger.log(LogRecord record) //日志打印过程

负责将指定log内容记录到日志。

此处LogRecord是对日志消息的抽象,结构如下:

java系统日志框架 java搭建日志模块_记录日志_05

主要包含日志内容String msg、日志级别Level level

日志打印函数如下:

public void log(LogRecord record) {
//检查level
if (!isLoggable(record.getLevel())) {
return;
}
//检查过滤
Filter theFilter = filter;
if (theFilter != null && !theFilter.isLoggable(record)) {
return;
}
//处理日志打印
Logger logger = this;
while (logger != null) {
//获取所有Handlers
final Handler[] loggerHandlers = Logger.getHandlers();
//遍历所有Handlers,处理logRecord
for (Handler handler : loggerHandlers) {
handler.publish(record);
}
//判断是否使用parentLogger处理,若否,结束流程
final boolean useParentHdls = logger.useParentHandlers;
if (!useParentHdls) {
break;
}
logger = isSystemLogger ? logger.parent : logger.getParent(); //通过parentLogger继续处理
}
}

至此,java 的logging工具中的主要模块描述结束。

有问题敬请反馈,多谢!