摘要:?jiǎn)栴}描述監(jiān)控系統(tǒng)新系統(tǒng)起步,旨在監(jiān)控原有系統(tǒng)的各種問(wèn)題。實(shí)現(xiàn)思考日志問(wèn)題與之前的映射問(wèn)題不同。定義用對(duì)該日志對(duì)象進(jìn)行裝飾。然后就可以在相應(yīng)的方法中添加我們的邏輯,如在的方法中向我們的日志監(jiān)控服務(wù)推送消息。
問(wèn)題描述 監(jiān)控系統(tǒng)
新系統(tǒng)起步,旨在監(jiān)控原有系統(tǒng)的各種問(wèn)題。主要的一部分,就是監(jiān)視原有系統(tǒng)的日志。
日志,是Java企業(yè)級(jí)應(yīng)用開(kāi)發(fā)必不可少的一部分,市場(chǎng)上有諸多日志框架。我們選用slf4j。
日志有以下級(jí)別:
TRACE, DEBUG, INFO, WARN, ERROR
我們期待,當(dāng)系統(tǒng)運(yùn)行時(shí)打印了WARN或ERROR級(jí)別的日志時(shí),向我們的服務(wù)器推送消息。使得我們可以分析日志,構(gòu)造更完整的系統(tǒng)。
實(shí)現(xiàn) 思考日志問(wèn)題與之前的Hibernate映射問(wèn)題不同。
Hibernate映射問(wèn)題是默認(rèn)用這個(gè)類(lèi),然后我們可以利用Spring Boot為我們提供的配置,當(dāng)去映射名稱(chēng)的時(shí)候調(diào)用我這個(gè)類(lèi)。
我們的日志是這么寫(xiě)的:
private static final Logger logger = LoggerFactory.getLogger(xxxx.class);
對(duì)象都是從LoggerFactory那創(chuàng)建出來(lái)的,我們根本沒(méi)辦法從配置中下手。
自定義日志新建日志類(lèi)YunzhiLogger,去實(shí)現(xiàn)org.slf4j.Logger接口。
這是Logger接口的源碼,一共有61個(gè)方法,我們一一去實(shí)現(xiàn)是不現(xiàn)實(shí)的,根據(jù)面向?qū)ο蟠蠓?,我們?yīng)該去找一個(gè)合適的父類(lèi)去繼承,然后重寫(xiě)不符合我們要求的方法。
package org.slf4j; public interface Logger { final public String ROOT_LOGGER_NAME = "ROOT"; public String getName(); public boolean isTraceEnabled(); public void trace(String msg); public void trace(String format, Object arg); public void trace(String format, Object arg1, Object arg2); public void trace(String format, Object... arguments); public void trace(String msg, Throwable t); public boolean isTraceEnabled(Marker marker); public void trace(Marker marker, String msg); public void trace(Marker marker, String format, Object arg); public void trace(Marker marker, String format, Object arg1, Object arg2); public void trace(Marker marker, String format, Object... argArray); public void trace(Marker marker, String msg, Throwable t); public boolean isDebugEnabled(); public void debug(String msg); public void debug(String format, Object arg); public void debug(String format, Object arg1, Object arg2); public void debug(String format, Object... arguments); public void debug(String msg, Throwable t); public boolean isDebugEnabled(Marker marker); public void debug(Marker marker, String msg); public void debug(Marker marker, String format, Object arg); public void debug(Marker marker, String format, Object arg1, Object arg2); public void debug(Marker marker, String format, Object... arguments); public void debug(Marker marker, String msg, Throwable t); public boolean isInfoEnabled(); public void info(String msg); public void info(String format, Object arg); public void info(String format, Object arg1, Object arg2); public void info(String format, Object... arguments); public void info(String msg, Throwable t); public boolean isInfoEnabled(Marker marker); public void info(Marker marker, String msg); public void info(Marker marker, String format, Object arg); public void info(Marker marker, String format, Object arg1, Object arg2); public void info(Marker marker, String format, Object... arguments); public void info(Marker marker, String msg, Throwable t); public boolean isWarnEnabled(); public void warn(String msg); public void warn(String format, Object arg); public void warn(String format, Object... arguments); public void warn(String format, Object arg1, Object arg2); public void warn(String msg, Throwable t); public boolean isWarnEnabled(Marker marker); public void warn(Marker marker, String msg); public void warn(Marker marker, String format, Object arg); public void warn(Marker marker, String format, Object arg1, Object arg2); public void warn(Marker marker, String format, Object... arguments); public void warn(Marker marker, String msg, Throwable t); public boolean isErrorEnabled(); public void error(String msg); public void error(String format, Object arg); public void error(String format, Object arg1, Object arg2); public void error(String format, Object... arguments); public void error(String msg, Throwable t); public boolean isErrorEnabled(Marker marker); public void error(Marker marker, String msg); public void error(Marker marker, String format, Object arg); public void error(Marker marker, String format, Object arg1, Object arg2); public void error(Marker marker, String format, Object... arguments); public void error(Marker marker, String msg, Throwable t); }找父類(lèi)
粗略地閱讀了一下LoggerFactory中getLogger的源代碼。
里面有很多的條件,先根據(jù)條件獲取ILoggerFactory,該接口一共有三個(gè)實(shí)現(xiàn)類(lèi),實(shí)現(xiàn)類(lèi)中再去定義不同的getLogger方法,不同的工廠獲取出來(lái)的日志對(duì)象是不同的。
因?yàn)閷?duì)日志框架不是很了解,如果我們隨便找一個(gè)類(lèi)繼承,那slf4j的判斷就失去意義了,所以此種方法行不通。
裝飾器模式我們想到了裝飾器模式。
將一個(gè)對(duì)象進(jìn)行裝飾,完善其方法。
先將Logger中的方法都實(shí)現(xiàn)掉,然后定義私有變量logger,定義有參構(gòu)造函數(shù)。
定義logger用YunzhiLogger對(duì)該日志對(duì)象進(jìn)行裝飾。
private static final Logger logger = new YunzhiLogger(LoggerFactory.getLogger(xxxx.class));
借此,也理解了裝飾器模式的應(yīng)用場(chǎng)景。原來(lái)就想,裝飾器實(shí)現(xiàn)的功能用繼承不就能實(shí)現(xiàn)嗎?為什么還要去裝飾對(duì)象呢?直接繼承父類(lèi)然后調(diào)用super上的方法再加新功能不和這一樣嗎?
現(xiàn)在也明白了,有時(shí)候,我們找不到合適的父類(lèi)(因?yàn)閯?chuàng)造出的日志對(duì)象是根據(jù)不同條件new不同的類(lèi)創(chuàng)造出來(lái)的),然后我們又想去給這個(gè)對(duì)象添加方法,沒(méi)辦法,只能修飾對(duì)象了。
或者有時(shí)候,找到父類(lèi),但是父類(lèi)是final,沒(méi)法繼承,才用的裝飾器模式。
裝飾方法首先,調(diào)用原logger方法進(jìn)行默認(rèn)實(shí)現(xiàn)。
package com.mengyunzhi.measurement.log; import org.slf4j.Logger; import org.slf4j.Marker; /** * @author zhangxishuo on 2018/11/15 */ public class YunzhiLogger implements Logger { private Logger logger; public YunzhiLogger(Logger logger) { this.logger = logger; } @Override public String getName() { return this.logger.getName(); } @Override public boolean isTraceEnabled() { return this.logger.isTraceEnabled(); } @Override public void trace(String msg) { this.logger.trace(msg); } @Override public void trace(String format, Object arg) { this.logger.trace(format, arg); } @Override public void trace(String format, Object arg1, Object arg2) { this.logger.trace(format, arg1, arg2); } @Override public void trace(String format, Object... arguments) { this.logger.trace(format, arguments); } @Override public void trace(String msg, Throwable t) { this.logger.trace(msg, t); } @Override public boolean isTraceEnabled(Marker marker) { return this.logger.isTraceEnabled(marker); } @Override public void trace(Marker marker, String msg) { this.logger.trace(marker, msg); } @Override public void trace(Marker marker, String format, Object arg) { this.logger.trace(marker, format, arg); } @Override public void trace(Marker marker, String format, Object arg1, Object arg2) { this.logger.trace(marker, format, arg1, arg2); } @Override public void trace(Marker marker, String format, Object... argArray) { this.logger.trace(marker, format, argArray); } @Override public void trace(Marker marker, String msg, Throwable t) { this.logger.trace(marker, msg, t); } @Override public boolean isDebugEnabled() { return this.logger.isDebugEnabled(); } @Override public void debug(String msg) { this.logger.debug(msg); } @Override public void debug(String format, Object arg) { this.logger.debug(format, arg); } @Override public void debug(String format, Object arg1, Object arg2) { this.logger.debug(format, arg1, arg2); } @Override public void debug(String format, Object... arguments) { this.logger.debug(format, arguments); } @Override public void debug(String msg, Throwable t) { this.logger.debug(msg, t); } @Override public boolean isDebugEnabled(Marker marker) { return this.logger.isDebugEnabled(marker); } @Override public void debug(Marker marker, String msg) { this.logger.debug(marker, msg); } @Override public void debug(Marker marker, String format, Object arg) { this.logger.debug(marker, format, arg); } @Override public void debug(Marker marker, String format, Object arg1, Object arg2) { this.logger.debug(marker, format, arg1, arg2); } @Override public void debug(Marker marker, String format, Object... arguments) { this.logger.debug(marker, format, arguments); } @Override public void debug(Marker marker, String msg, Throwable t) { this.logger.debug(marker, msg, t); } @Override public boolean isInfoEnabled() { return this.logger.isInfoEnabled(); } @Override public void info(String msg) { this.logger.info(msg); } @Override public void info(String format, Object arg) { this.logger.info(format, arg); } @Override public void info(String format, Object arg1, Object arg2) { this.logger.info(format, arg1, arg2); } @Override public void info(String format, Object... arguments) { this.logger.info(format, arguments); } @Override public void info(String msg, Throwable t) { this.logger.info(msg, t); } @Override public boolean isInfoEnabled(Marker marker) { return this.logger.isInfoEnabled(marker); } @Override public void info(Marker marker, String msg) { this.logger.info(marker, msg); } @Override public void info(Marker marker, String format, Object arg) { this.logger.info(marker, format, arg); } @Override public void info(Marker marker, String format, Object arg1, Object arg2) { this.logger.info(marker, format, arg1, arg2); } @Override public void info(Marker marker, String format, Object... arguments) { this.logger.info(marker, format, arguments); } @Override public void info(Marker marker, String msg, Throwable t) { this.logger.info(marker, msg, t); } @Override public boolean isWarnEnabled() { return this.logger.isWarnEnabled(); } @Override public void warn(String msg) { this.logger.warn(msg); } @Override public void warn(String format, Object arg) { this.logger.warn(format, arg); } @Override public void warn(String format, Object... arguments) { this.logger.warn(format, arguments); } @Override public void warn(String format, Object arg1, Object arg2) { this.logger.warn(format, arg1, arg2); } @Override public void warn(String msg, Throwable t) { this.logger.warn(msg, t); } @Override public boolean isWarnEnabled(Marker marker) { return this.logger.isWarnEnabled(marker); } @Override public void warn(Marker marker, String msg) { this.logger.warn(marker, msg); } @Override public void warn(Marker marker, String format, Object arg) { this.logger.warn(marker, format, arg); } @Override public void warn(Marker marker, String format, Object arg1, Object arg2) { this.logger.warn(marker, format, arg1, arg2); } @Override public void warn(Marker marker, String format, Object... arguments) { this.logger.warn(marker, format, arguments); } @Override public void warn(Marker marker, String msg, Throwable t) { this.logger.warn(marker, msg, t); } @Override public boolean isErrorEnabled() { return this.logger.isErrorEnabled(); } @Override public void error(String msg) { this.logger.error(msg); } @Override public void error(String format, Object arg) { this.logger.error(format, arg); } @Override public void error(String format, Object arg1, Object arg2) { this.logger.error(format, arg1, arg2); } @Override public void error(String format, Object... arguments) { this.logger.error(format, arguments); } @Override public void error(String msg, Throwable t) { this.logger.error(msg, t); } @Override public boolean isErrorEnabled(Marker marker) { return this.logger.isErrorEnabled(marker); } @Override public void error(Marker marker, String msg) { this.logger.error(marker, msg); } @Override public void error(Marker marker, String format, Object arg) { this.logger.error(marker, format, arg); } @Override public void error(Marker marker, String format, Object arg1, Object arg2) { this.logger.error(marker, format, arg1, arg2); } @Override public void error(Marker marker, String format, Object... arguments) { this.logger.error(marker, format, arguments); } @Override public void error(Marker marker, String msg, Throwable t) { this.logger.error(marker, msg, t); } }
這是我為裝飾器添加的默認(rèn)實(shí)現(xiàn),如有錯(cuò)誤,歡迎批評(píng)指正。
然后就可以在相應(yīng)的方法中添加我們的邏輯,如在error的方法中向我們的日志監(jiān)控服務(wù)推送消息。
總結(jié)通過(guò)對(duì)slf4j源碼的學(xué)習(xí)大致學(xué)習(xí)了日志框架slf4j的運(yùn)行原理。
通過(guò)找接口與父類(lèi)理解了裝飾器模式的應(yīng)用場(chǎng)景。
本文只是實(shí)現(xiàn)了基本的功能,因?yàn)?b>error方法與warn方法有很多重載的方法,所以我們期待可以實(shí)現(xiàn)對(duì)該日志類(lèi)中所有名為error與warn的方法進(jìn)行切面處理。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/72208.html
摘要:這篇文章是邊聽(tīng)尚硅谷的課程邊記的筆記,也是為了之后方便查看,視頻鏈接精彩的故事小張負(fù)責(zé)一個(gè)大型系統(tǒng)的開(kāi)發(fā),為了監(jiān)控系統(tǒng)的運(yùn)行狀況,系統(tǒng)中包含大量的語(yǔ)句,為了更好地管理呢,小張決定寫(xiě)一個(gè)日志框架對(duì)日志進(jìn)行管理,他設(shè)想的日志框架應(yīng)該包含以下幾個(gè) 這篇文章是邊聽(tīng)尚硅谷的課程邊記的筆記,也是為了之后方便查看,視頻鏈接:https://www.bilibili.com/vide... 1. 精彩...
摘要:本文主要介紹如何使用這個(gè)可以直接顯示完整的日志框架,希望對(duì)大家能有所幫助。當(dāng)設(shè)置為或時(shí),意味關(guān)閉記錄。 在常規(guī)項(xiàng)目的開(kāi)發(fā)中可能最容易出問(wèn)題的地方就在于對(duì)數(shù)據(jù)庫(kù)的處理了,在大部分的環(huán)境下,我們對(duì)數(shù)據(jù)庫(kù)的操作都是使用流行的框架,比如 Hibernate 、 MyBatis 等。由于各種原因,我們有時(shí)會(huì)想知道在這些框架下實(shí)際執(zhí)行的 SQL 究竟是什么。 雖然 Hibernate 可以在配置...
摘要:本文主要介紹如何使用這個(gè)可以直接顯示完整的日志框架,希望對(duì)大家能有所幫助。當(dāng)設(shè)置為或時(shí),意味關(guān)閉記錄。 在常規(guī)項(xiàng)目的開(kāi)發(fā)中可能最容易出問(wèn)題的地方就在于對(duì)數(shù)據(jù)庫(kù)的處理了,在大部分的環(huán)境下,我們對(duì)數(shù)據(jù)庫(kù)的操作都是使用流行的框架,比如 Hibernate 、 MyBatis 等。由于各種原因,我們有時(shí)會(huì)想知道在這些框架下實(shí)際執(zhí)行的 SQL 究竟是什么。 雖然 Hibernate 可以在配置...
閱讀 2589·2021-11-23 09:51
閱讀 3385·2021-11-22 15:22
閱讀 1903·2021-11-18 13:22
閱讀 2319·2021-09-24 09:48
閱讀 1338·2019-08-29 13:58
閱讀 1332·2019-08-26 13:39
閱讀 2474·2019-08-26 10:48
閱讀 3063·2019-08-26 10:21