




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
第Go語言編程實現(xiàn)支持六種級別的日志庫目錄前言初始需求技術(shù)實現(xiàn)類型定義日志級別寫到文件默認(rèn)實現(xiàn)
前言
Golang標(biāo)準(zhǔn)日志庫提供的日志輸出方法有Print、Fatal、Panic等,沒有常見的Debug、Info、Error等日志級別,用起來不太順手。這篇文章就來手?jǐn)]一個自己的日志庫,可以記錄不同級別的日志。
其實對于追求簡單來說,Golang標(biāo)準(zhǔn)日志庫的三個輸出方法也夠用了,理解起來也很容易:
Print用于記錄一個普通的程序日志,開發(fā)者想記點什么都可以。Fatal用于記錄一個導(dǎo)致程序崩潰的日志,并會退出程序。Panic用于記錄一個異常日志,并觸發(fā)panic。
不過對于用慣了Debug、Info、Error的人來說,還是有點不習(xí)慣;對于想更細(xì)致的區(qū)分日志級別的需求,標(biāo)準(zhǔn)日志庫還提供了一個通用的Output方法,開發(fā)者在要輸出的字符串中加入級別也是可以的,但總是有點別扭,不夠直接。
目前市面上也已經(jīng)有很多優(yōu)秀的三方日志庫,比如uber開源的zap,常見的還有zerolog、logrus等。不過我這里還是想自己手?jǐn)]一個,因為大多數(shù)開源產(chǎn)品都不會完全貼合自己的需求,有很多自己用不上的功能,這會增加系統(tǒng)的復(fù)雜性,有沒有隱藏的坑也很難說,當(dāng)然自己入坑的可能性也很大;再者看了官方日志庫的實現(xiàn)之后,感覺可以簡單封裝下即可實現(xiàn)自己想要的功能,能夠hold住。
初始需求
我這里的初始需求是:
將日志寫入磁盤文件,每個月一個文件夾,每個小時一個文件。支持常見日志級別:Trace、Debug、Info、Warn、Error、Fatal,并且程序能夠設(shè)置日志級別。
我給這個日志庫取名為ylog,預(yù)期的使用方法如下:
ylog.SetLevel(LevelInfo)
ylog.Debug("Iamadebuglog.")
ylog.Info("IamaInfolog.")
技術(shù)實現(xiàn)
類型定義
需要定義一個結(jié)構(gòu)體,保存日志級別、要寫入的文件等信息。
typeFileLoggerstruct{
lastHourint64
file*os.File
LevelLogLevel
musync.Mutex
iLogger*log.Logger
Pathstring
來看一下這幾個參數(shù):
lastHour用來記錄創(chuàng)建日志文件時的小時數(shù),如果小時變了,就要創(chuàng)建新的日志文件。
file當(dāng)前使用的日志文件。
Level當(dāng)前使用的日志級別。
mu因為可能在不同的goroutine中寫日志,需要一個互斥體保證日志文件不會重復(fù)創(chuàng)建。
iLogger標(biāo)準(zhǔn)日志庫實例,因為這里是封裝了標(biāo)準(zhǔn)日志庫。
Path日志輸出的最上層目錄,比如程序根目錄下的logs目錄,這里就保存一個字符串:logs。
日志級別
先把日志級別定義出來,這里日志級別其實是int類型,從0到5,級別不斷升高。
如果設(shè)置為ToInfo,則Info級別及比Info級別高的日志都能輸出。
typeLogLevelint
const(
LevelTraceLogLevel=iota
LevelDebug
LevelInfo
LevelWarn
LevelError
LevelFatal
上文提到可以在Output方法的參數(shù)中加入日志級別,這里就通過封裝Output方法來實現(xiàn)不同級別的日志記錄方法。這里貼出其中一個方法,封裝的方式都一樣,就不全都貼出來了:
func(l*FileLogger)CanInfo()bool{
returnl.Level=LevelInfo
func(l*FileLogger)Info(v...any){
ifl.CanInfo(){
l.ensureFile()
v=append([]any{"Info"},v...)
l.iLogger.Output(2,fmt.Sprintln(v...))
輸出日志前做了三件事:
判斷日志級別,如果設(shè)置的日志級別小于等于當(dāng)前輸出級別,則可以輸出。確保日志文件已經(jīng)創(chuàng)建好,后邊會講如何確保。將日志級別前插到日志字符串中。
然后調(diào)用標(biāo)準(zhǔn)庫的Output函數(shù)輸出日志,這里第一個參數(shù)是為了獲取到當(dāng)前正在寫日志的程序文件名,傳入的是在程序調(diào)用棧中進(jìn)行查找的深度值,這里用2就正好。
寫到文件
標(biāo)準(zhǔn)庫的log是支持輸出到多種目標(biāo)的,只要實現(xiàn)了io.Write接口:
typeWriterinterface{
Write(p[]byte)(nint,errerror)
因為文件對象也實現(xiàn)了這個接口,所以這里可以創(chuàng)建os.File的實例,并把它設(shè)置到內(nèi)嵌的標(biāo)準(zhǔn)日志庫實例,也就是設(shè)置到前邊創(chuàng)建的FileLogger中的iLogger中。這個操作在ensureFile方法中,看一下這個文件的實現(xiàn):
func(l*FileLogger)ensureFile()(errerror){
currentTime:=time.Now()
ifl.file==nil{
l.mu.Lock()
deferl.mu.Unlock()
ifl.file==nil{
l.file,err=createFile(l.Path,currentTime)
l.iLogger.SetOutput(l.file)
l.iLogger.SetFlags(log.Lshortfile|log.Ldate|log.Ltime|log.Lmicroseconds)
l.lastHour=getTimeHour(currentTime)
return
currentHour:=getTimeHour(currentTime)
ifl.lastHour!=currentHour{
l.mu.Lock()
deferl.mu.Unlock()
ifl.lastHour!=currentHour{
_=l.file.Close()
l.file,err=createFile(l.Path,currentTime)
l.iLogger.SetOutput(l.file)
l.iLogger.SetFlags(log.Llongfile|log.Ldate|log.Ltime)
l.lastHour=getTimeHour(currentTime)
return
這里稍微有點復(fù)雜,基本邏輯是:如果文件實例不存在,則創(chuàng)建;如果需要創(chuàng)建新的文件,則先關(guān)閉舊的文件再創(chuàng)建新的文件。
更改文件實例時需要加鎖,否則可能多次操作,出現(xiàn)預(yù)期之外的情況。
設(shè)置輸出到文件后,標(biāo)準(zhǔn)log庫的Output方法就會將日志輸出到這個文件了。
默認(rèn)實現(xiàn)
經(jīng)過上邊一系列操作,這個FileLogger就可以使用了:
varlogger=NewFileLogger(LevelInfo,"logs")
logger.Info("Thisisainfo.")
不過和最初設(shè)想的用法有點差別:ylog.Info(xxxx)
這需要在ylog包中再定義一個名為Info的公開函數(shù),可以在這個公開函數(shù)中調(diào)用一個默認(rèn)創(chuàng)建的FileLogger實例,代碼是這樣的:
varstdPath="logs"
varstd=NewFileLogger(LevelInfo,stdPath)
funcTrace(v...any){
ifstd.CanTrace(){
std.ensureFile()
v=append([]any{"Trace"},v...)
std.iLogger.Output(2,fmt.Sprintln(v...))
注意這里沒有調(diào)用std的Trace方法,這是因為Output中的第一個參數(shù),如果嵌套調(diào)用std.Trace,則多了一層,這個參數(shù)就得設(shè)置為3,但是自己創(chuàng)建實例調(diào)用Trace時這個參數(shù)需要為2,這就產(chǎn)生沖突了。
經(jīng)過以上這些操作,就可以實現(xiàn)預(yù)期的日志操作了:
ylo
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 元宇宙虛擬數(shù)字貨幣兌換與交易服務(wù)協(xié)議
- 樣板間室內(nèi)外綠化及裝修工程施工合同
- 兒童用品電商平臺全渠道運營合作協(xié)議
- 同聲傳譯租賃合同終止條件補(bǔ)充協(xié)議
- 醫(yī)療機(jī)構(gòu)廢棄藥品及生物安全廢物回收協(xié)議
- 直播平臺提詞器租賃與直播節(jié)目制作服務(wù)協(xié)議
- 零售商智能電子價簽租賃與智能數(shù)據(jù)分析合同
- 電子商務(wù)網(wǎng)站技術(shù)維護(hù)及安全保障合同
- 企業(yè)管理公司創(chuàng)業(yè)路徑規(guī)劃
- 影視基地電力設(shè)施投資與運營管理合同
- 我的家鄉(xiāng)江西吉安
- 肺栓塞病人的術(shù)后護(hù)理
- 電力運維管理平臺方案設(shè)計
- 機(jī)場地震應(yīng)急處理與疏散預(yù)案
- 《阻燃材料與技術(shù)》課件 顏龍 第3、4講 阻燃基本理論、阻燃劑性能與應(yīng)用
- 服務(wù)禮儀培訓(xùn)課件
- 外研版小升初必背詞匯
- 咪咕在線測評題
- 2024年全國《勞動教育》基礎(chǔ)知識考試題庫與答案
- 維修電工二實操評分表講解
- 8d報告空白表格模板
評論
0/150
提交評論