GoLang實(shí)現(xiàn)日志收集器流程講解
Go自己動(dòng)手實(shí)現(xiàn)日志收集
看日志是開(kāi)發(fā)者平時(shí)排查BUG所必須的掌握的技能,但是日志是如何來(lái)的呢?通過(guò)平時(shí)開(kāi)發(fā)者自己打日志,經(jīng)過(guò)日志包進(jìn)行處理,打印日志到控制臺(tái)還是記錄日志到文件中!
下面咱就來(lái)學(xué)一下日志是如何記錄下來(lái)的

1. 日志器的接口
? 以下日志器定義了各類(lèi)日志器的行為,通過(guò)RegisterWriter注冊(cè)實(shí)現(xiàn)了日志器的子類(lèi)日志器,然后通過(guò)Log方法來(lái)進(jìn)行循環(huán)調(diào)用注冊(cè)進(jìn)來(lái)的日志收集器的write寫(xiě)日志方法。
// 聲明日志寫(xiě)入器接口
type LogWriter interface {
Write(data interface{}) error
}
// 日志器
type Logger struct {
// 這個(gè)日志器用到的日志寫(xiě)入器
writerList []LogWriter
}
// 注冊(cè)一個(gè)日志寫(xiě)入器
func (l *Logger) RegisterWriter(writer LogWriter) {
l.writerList = append(l.writerList, writer)
}
// 將一個(gè)data類(lèi)型的數(shù)據(jù)寫(xiě)入日志
func (l *Logger) Log(data interface{}) {
// 遍歷所有注冊(cè)的寫(xiě)入器
for _, writer := range l.writerList {
// 將日志輸出到每一個(gè)寫(xiě)入器中
writer.Write(data)
}
}
// 創(chuàng)建日志器的實(shí)例
func NewLogger() *Logger {
return &Logger{}
}2. 命令寫(xiě)入日志器
? 這個(gè)日志器實(shí)現(xiàn)了日志器的接口行為write,可以進(jìn)行日志的寫(xiě)入,其寫(xiě)入手法是通過(guò)Os包來(lái)寫(xiě)入到命令行(控制臺(tái))中!
// 命令行寫(xiě)入器
type consoleWriter struct {
}
// 實(shí)現(xiàn)LogWriter的Write()方法
func (f *consoleWriter) Write(data interface{}) error {
// 將數(shù)據(jù)序列化為字符串
str := fmt.Sprintf("%v\n", data)
// 將數(shù)據(jù)以字節(jié)數(shù)組寫(xiě)入命令行中
_, err := os.Stdout.Write([]byte(str))
return err
}
// 創(chuàng)建命令行寫(xiě)入器實(shí)例
func NewConsoleWriter() *consoleWriter {
return &consoleWriter{}
}3. 文件寫(xiě)入日志器
這也是實(shí)現(xiàn)了日志器的一個(gè)實(shí)現(xiàn)類(lèi),文件日志器,一種常見(jiàn)的將日志寫(xiě)入文件記錄的日志收集器。使用前需要先SetFile設(shè)置好日志文件名,最后將日志作為字節(jié)寫(xiě)入到文件中。
// 聲明文件寫(xiě)入器
type fileWriter struct {
file *os.File
}
// 設(shè)置文件寫(xiě)入器寫(xiě)入的文件名
func (f *fileWriter) SetFile(filename string) (err error) {
// 如果文件已經(jīng)打開(kāi), 關(guān)閉前一個(gè)文件
if f.file != nil {
f.file.Close()
}
// 創(chuàng)建一個(gè)文件并保存文件句柄
f.file, err = os.Create(filename)
// 如果創(chuàng)建的過(guò)程出現(xiàn)錯(cuò)誤, 則返回錯(cuò)誤
return err
}
// 實(shí)現(xiàn)LogWriter的Write()方法
func (f *fileWriter) Write(data interface{}) error {
// 日志文件可能沒(méi)有創(chuàng)建成功
if f.file == nil {
// 日志文件沒(méi)有準(zhǔn)備好
return errors.New("file not created")
}
// 將數(shù)據(jù)序列化為字符串
str := fmt.Sprintf("%v\n", data)
// 將數(shù)據(jù)以字節(jié)數(shù)組寫(xiě)入文件中
_, err := f.file.Write([]byte(str))
return err
}
// 創(chuàng)建文件寫(xiě)入器實(shí)例
func NewFileWriter() *fileWriter {
return &fileWriter{}
}4. Demo演示
通過(guò)New的方式創(chuàng)建日志器,進(jìn)行注冊(cè)到日志器集合中,下面演示了兩種日志器如何使用?。?!
// 創(chuàng)建日志器
func createLogger() *Logger {
// 創(chuàng)建日志器
l := NewLogger()
// 創(chuàng)建命令行寫(xiě)入器
cw := cmdwriter.NewConsoleWriter()
// 注冊(cè)命令行寫(xiě)入器到日志器中,cw實(shí)現(xiàn)了LogWriter接口,故可作為RegisterWriter函數(shù)的參數(shù),類(lèi)型為L(zhǎng)ogwriter
l.RegisterWriter(cw)
// 創(chuàng)建文件寫(xiě)入器
fw := filerwriter.NewFileWriter()
// 設(shè)置文件名
if err := fw.SetFile("log.log"); err != nil {
fmt.Println(err)
}
// 注冊(cè)文件寫(xiě)入器到日志器中,fw實(shí)現(xiàn)了LogWriter接口
l.RegisterWriter(fw)
return l
}
func main() {
// 準(zhǔn)備日志器
l := createLogger()
// 寫(xiě)一個(gè)日志
l.Log("hello")
}
5. 總結(jié)和提高
一個(gè)好的日志器功能是可擴(kuò)展的,上述例子僅只是可以擴(kuò)展不同種類(lèi)的日志收集器。
在官方的logger中是可以進(jìn)行選擇寫(xiě)入級(jí)別的,可以定義一個(gè)枚舉,在對(duì)應(yīng)的枚舉寫(xiě)入級(jí)別下,進(jìn)行對(duì)應(yīng)的權(quán)限寫(xiě)入,可以改造write方法,而不只是簡(jiǎn)單的寫(xiě)入就完事了。
到此這篇關(guān)于GoLang實(shí)現(xiàn)日志收集器流程講解的文章就介紹到這了,更多相關(guān)Go日志收集內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
基于gin的golang web開(kāi)發(fā):路由示例詳解
這篇文章主要介紹了基于gin的golang web開(kāi)發(fā):路由示例詳解,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-10-10
Go語(yǔ)言Gin框架前后端分離項(xiàng)目開(kāi)發(fā)實(shí)例
本文主要介紹了Go語(yǔ)言Gin框架前后端分離項(xiàng)目開(kāi)發(fā)工程化實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-11-11
GoLang并發(fā)編程中條件變量sync.Cond的使用
Go標(biāo)準(zhǔn)庫(kù)提供Cond原語(yǔ)的目的是,為等待/通知場(chǎng)景下的并發(fā)問(wèn)題提供支持,本文主要介紹了Go并發(fā)編程sync.Cond的具體使用,具有一定的參考價(jià)值,感興趣的可以了解一下2023-01-01
Go?Web編程添加服務(wù)器錯(cuò)誤和訪問(wèn)日志
這篇文章主要為大家介紹了Go?Web編程添加服務(wù)器錯(cuò)誤日志和訪問(wèn)日志的示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06
golang常見(jiàn)接口限流算法的實(shí)現(xiàn)
本文主要介紹了golang常見(jiàn)接口限流算法的實(shí)現(xiàn),包含固定窗口、滑動(dòng)窗口、漏桶和令牌桶,具有一定的參考價(jià)值,感興趣的可以了解一下2025-03-03
golang NewRequest/gorequest實(shí)現(xiàn)http請(qǐng)求的示例代碼
本文主要介紹了golang NewRequest/gorequest實(shí)現(xiàn)http請(qǐng)求的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08
go實(shí)現(xiàn)整型的二進(jìn)制轉(zhuǎn)化的方法
這篇文章主要介紹了go實(shí)現(xiàn)整型的二進(jìn)制轉(zhuǎn)化的方法,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值 ,需要的朋友可以參考下2019-07-07

