




版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領
文檔簡介
第Go語言編程實現(xiàn)支持六種級別的日志庫目錄前言初始需求技術實現(xiàn)類型定義日志級別寫到文件默認實現(xiàn)
前言
Golang標準日志庫提供的日志輸出方法有Print、Fatal、Panic等,沒有常見的Debug、Info、Error等日志級別,用起來不太順手。這篇文章就來手擼一個自己的日志庫,可以記錄不同級別的日志。
其實對于追求簡單來說,Golang標準日志庫的三個輸出方法也夠用了,理解起來也很容易:
Print用于記錄一個普通的程序日志,開發(fā)者想記點什么都可以。Fatal用于記錄一個導致程序崩潰的日志,并會退出程序。Panic用于記錄一個異常日志,并觸發(fā)panic。
不過對于用慣了Debug、Info、Error的人來說,還是有點不習慣;對于想更細致的區(qū)分日志級別的需求,標準日志庫還提供了一個通用的Output方法,開發(fā)者在要輸出的字符串中加入級別也是可以的,但總是有點別扭,不夠直接。
目前市面上也已經(jīng)有很多優(yōu)秀的三方日志庫,比如uber開源的zap,常見的還有zerolog、logrus等。不過我這里還是想自己手擼一個,因為大多數(shù)開源產(chǎn)品都不會完全貼合自己的需求,有很多自己用不上的功能,這會增加系統(tǒng)的復雜性,有沒有隱藏的坑也很難說,當然自己入坑的可能性也很大;再者看了官方日志庫的實現(xiàn)之后,感覺可以簡單封裝下即可實現(xiàn)自己想要的功能,能夠hold住。
初始需求
我這里的初始需求是:
將日志寫入磁盤文件,每個月一個文件夾,每個小時一個文件。支持常見日志級別:Trace、Debug、Info、Warn、Error、Fatal,并且程序能夠設置日志級別。
我給這個日志庫取名為ylog,預期的使用方法如下:
ylog.SetLevel(LevelInfo)
ylog.Debug("Iamadebuglog.")
ylog.Info("IamaInfolog.")
技術實現(xiàn)
類型定義
需要定義一個結構體,保存日志級別、要寫入的文件等信息。
typeFileLoggerstruct{
lastHourint64
file*os.File
LevelLogLevel
musync.Mutex
iLogger*log.Logger
Pathstring
來看一下這幾個參數(shù):
lastHour用來記錄創(chuàng)建日志文件時的小時數(shù),如果小時變了,就要創(chuàng)建新的日志文件。
file當前使用的日志文件。
Level當前使用的日志級別。
mu因為可能在不同的goroutine中寫日志,需要一個互斥體保證日志文件不會重復創(chuàng)建。
iLogger標準日志庫實例,因為這里是封裝了標準日志庫。
Path日志輸出的最上層目錄,比如程序根目錄下的logs目錄,這里就保存一個字符串:logs。
日志級別
先把日志級別定義出來,這里日志級別其實是int類型,從0到5,級別不斷升高。
如果設置為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...))
輸出日志前做了三件事:
判斷日志級別,如果設置的日志級別小于等于當前輸出級別,則可以輸出。確保日志文件已經(jīng)創(chuàng)建好,后邊會講如何確保。將日志級別前插到日志字符串中。
然后調(diào)用標準庫的Output函數(shù)輸出日志,這里第一個參數(shù)是為了獲取到當前正在寫日志的程序文件名,傳入的是在程序調(diào)用棧中進行查找的深度值,這里用2就正好。
寫到文件
標準庫的log是支持輸出到多種目標的,只要實現(xiàn)了io.Write接口:
typeWriterinterface{
Write(p[]byte)(nint,errerror)
因為文件對象也實現(xiàn)了這個接口,所以這里可以創(chuàng)建os.File的實例,并把它設置到內(nèi)嵌的標準日志庫實例,也就是設置到前邊創(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
這里稍微有點復雜,基本邏輯是:如果文件實例不存在,則創(chuàng)建;如果需要創(chuàng)建新的文件,則先關閉舊的文件再創(chuàng)建新的文件。
更改文件實例時需要加鎖,否則可能多次操作,出現(xiàn)預期之外的情況。
設置輸出到文件后,標準log庫的Output方法就會將日志輸出到這個文件了。
默認實現(xiàn)
經(jīng)過上邊一系列操作,這個FileLogger就可以使用了:
varlogger=NewFileLogger(LevelInfo,"logs")
logger.Info("Thisisainfo.")
不過和最初設想的用法有點差別:ylog.Info(xxxx)
這需要在ylog包中再定義一個名為Info的公開函數(shù),可以在這個公開函數(shù)中調(diào)用一個默認創(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ù)就得設置為3,但是自己創(chuàng)建實例調(diào)用Trace時這個參數(shù)需要為2,這就產(chǎn)生沖突了。
經(jīng)過以上這些操作,就可以實現(xiàn)預期的日志操作了:
ylo
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 護理專業(yè)中的科研探索與應用前景試題及答案
- 2025年衛(wèi)生資格考試一站式復習全攻略試題及答案
- 就執(zhí)業(yè)藥師考試中的生物倫理問題展開討論及試題答案
- 行政法中的法規(guī)適用問題試題及答案
- 護士執(zhí)業(yè)考試重點試題及答案復習
- 眾多考生的執(zhí)業(yè)藥師考試試題及答案
- 常見行政法學錯誤及試題及答案反饋
- 行政法學考試知識框架與試題答案
- 深度分析執(zhí)業(yè)醫(yī)師試題及答案
- 外科臨床操作試題及答案
- 維修電工二實操評分表講解
- 8d報告空白表格模板
- 全冊備課(教案)2023-2024學年數(shù)學五年級下冊
- 江西中煙工業(yè)有限責任公司招聘筆試題庫2024
- 大學生心理健康智慧樹知到期末考試答案章節(jié)答案2024年西安電子科技大學
- 大熊貓簡介完整版本
- 高階數(shù)獨解題技巧講解
- GB/T 22581-2024混流式水泵水輪機基本技術條件
- 2023-2024學年人教版八年級下冊數(shù)學期末復習試題
- 第03講三步解決一次函數(shù)的行程問題(原卷版+解析)
- 2024年社會工作者《社會工作實務(中級)》考試真題必考題
評論
0/150
提交評論