java日志模块_Java源码初探_logging日志模块实现

一、用途

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

大概结构如下所示:

80c01e1b7acbab31957334f6b930d5d3.png

简要说明各个模块:

(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)日志管理:

ae7656ed23b58ba15809a66edff57eba.png

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。

2d581bf320f7231b5bacc83b333652b5.png

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) 日志打印

ed0877b42a0a4e9bb097201810efd17f.png

(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是对日志消息的抽象,结构如下:

bcea5704bcf4883852f7b2150c494de8.png

主要包含日志内容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工具中的主要模块描述结束。

有问题敬请反馈,多谢!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值