java日志模块_Java源码初探_logging日志模块实现
一、用途
程序中記錄日志,打印到控制臺、文件等方式,記錄過程可根據(jù)日志級別做篩選,日志格式可以自定義。
大概結(jié)構(gòu)如下所示:
簡要說明各個模塊:
(1) LogManager:管理LoggerContext及Logger,可以添加、獲取Logger。
(2) LoggerContext: 保存所有Logger,用于添加及獲取Logger,由LoggerManager管理。LoggerContext中同時保存了Logger的弱引用,在釋放Logger時使用到。
(3) Logger: 記錄日志的對象,提供接口實(shí)現(xiàn)對日志消息以不同的日志級別進(jìn)行記錄,管理Handler、Formatter、Filter等。
(4) Handler: 記錄日志真正的對象,包括FileHandler(記錄到文件)、ConsoleHandler(記錄到控制臺)、StreamHandler(記錄到流)、SocketHandler(通過socket發(fā)送日志?)等。
(5) Formatter: 處理日志的格式,包括SimpleFormatter(簡單格式記錄,顯示時間、級別、線程、日志信息等)、XMLFormatter(以xml格式記錄日志)等。
(6) Filter: 實(shí)現(xiàn)日志的過濾功能,通過自定義Filter,實(shí)現(xiàn)對某些日志的過濾處理。
(7) ErrorManager: 記錄日志出錯時的處理對象?
(8) LogRecord: 對日志消息的抽象。
二、詳細(xì)介紹(結(jié)合源碼)
詳細(xì)描述如下:
(1)日志管理:
LoggerManager主要用來管理LogContext以及l(fā)ogger。
LoggerManager維護(hù)變量主要有:
(a) LogManager manager
manager對象單例,用于LogManager內(nèi)部其他方法調(diào)用。在靜態(tài)構(gòu)造函數(shù)中實(shí)例化,在getLogManager()方法被調(diào)用時初始化:
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
用于讀配置文件內(nèi)容,配合完成初始化。上述readPrimordialConfiguration()函數(shù)即使用了Props獲取配置。
主要針對配置文件中對Logger及Handler等定義,進(jìn)行動態(tài)設(shè)置。
默認(rèn)的配置文件如下:
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
主要對默認(rèn)Handler進(jìn)行配置(ConsoleHanlder,默認(rèn)只打印日志到控制臺),設(shè)置FileHandler的一些配置(文件名格式、寫文件大小限制、使用文件數(shù)量、日志格式為xml),設(shè)置ConsoleHandler控制臺打印的格式為普通格式(SimpleFormatter)、打印日志級別最低為INFO。
(c)? LggerContext userContext
LogContext是LogManager的內(nèi)部類。
LogManager中包含默認(rèn)兩個LoggerContext: userContext與systemContext,用戶添加logger皆是放入userContext。
LoggerContext內(nèi)部,Logger被放入LogNode root中以鏈表形式存儲。
該類對LogManager開放接口:
添加Logger: addLogger
synchronized boolean addLocalLogger(Logger logger, boolean addDefaultLoggersIfNeeded) { //簡要說明
final LogManager owner = getOwner(); //設(shè)置logmanager
logger.setLogManager(owner);
LoggerWeakRef ref = owner.new LoggerWeakRef(logger);
namedLoggers.put(name, ref); //保存弱引用
Level level = owner.getLevelProperty(name + ".level", null); //設(shè)置Level
if (level != null && !logger.isLevelInitialized()) {
doSetLevel(logger, level);
}
processParentHandlers(logger, name); //設(shè)置父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"); //根據(jù)配置文件加載logger對應(yīng)handler
}
}
(e) logManager.demandLogger
調(diào)用loggerContext接口,構(gòu)造logger并添加至loggerContext。
(2) 日志打印
(a) name: String
logger的名稱。
例如:Logger logger = Logger.getLogger("test"); 則,logger名稱為"test";
(b) handlers: List、addHanlder(Handler) //設(shè)置日志處理對象
Handler是日志處理類的基類,子類主要有ConsoleHandler、FileHandler、SocketHandler、StreamHandler、MemoryHandler。
Handler負(fù)責(zé)將日志消息寫到指定位置。
該變量負(fù)責(zé)維護(hù)logger上的handlers,通過addHandler(Handler)添加,removeHandler(Handler)移除
一個logger具備多個handlers,因此,一條日志可依據(jù)定制情況打印到多個位置。
例如,通過這樣,可以為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) //設(shè)置過濾器
用于過濾logRecord。
接口包含:
boolean isLoggable(in LogRecord);
實(shí)現(xiàn)Filter自定義設(shè)置過濾規(guī)則。
(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) //日志打印過程
負(fù)責(zé)將指定log內(nèi)容記錄到日志。
此處LogRecord是對日志消息的抽象,結(jié)構(gòu)如下:
主要包含日志內(nèi)容String msg、日志級別Level level
日志打印函數(shù)如下:
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處理,若否,結(jié)束流程
final boolean useParentHdls = logger.useParentHandlers;
if (!useParentHdls) {
break;
}
logger = isSystemLogger ? logger.parent : logger.getParent(); //通過parentLogger繼續(xù)處理
}
}
至此,java 的logging工具中的主要模塊描述結(jié)束。
有問題敬請反饋,多謝!
與50位技術(shù)專家面對面20年技術(shù)見證,附贈技術(shù)全景圖總結(jié)
以上是生活随笔為你收集整理的java日志模块_Java源码初探_logging日志模块实现的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java poi 设置公式_poi公式处
- 下一篇: java interface泛型_jav