golang結(jié)構(gòu)化日志log/slog包之LogValuer的用法簡(jiǎn)介
上一篇文章講解了 log/slog 包中的分組、上下文和屬性值類型,本文講解下 LogValuer 和日志記錄函數(shù)的正確包裝方法。
slog.LogValuer
如果想改變或者自定義一個(gè)類型的日志記錄行為,可以通過(guò)實(shí)現(xiàn) slog.LogValuer 接口來(lái)實(shí)現(xiàn),slog.LogValuer 接口的定義如下:
type LogValuer interface { LogValue() Value }
定義了一個(gè) LogValue 方法,返回一個(gè) Value 類型的對(duì)象。如果一個(gè)類型實(shí)現(xiàn)了 LogValuer 接口,那么從它的 LogValue 方法返回的 Value 將被用于日志記錄,可以用來(lái)控制該類型的值在日志中的顯示方式??磦€(gè)簡(jiǎn)單示例:
package main import ( "log/slog" "os" ) type Token string // 實(shí)現(xiàn) slog.LogValuer 接口 // 避免泄露 token func (Token) LogValue() slog.Value { return slog.StringValue("******") } func main() { t := Token("shhhh!") logger := slog.New(slog.NewTextHandler(os.Stdout, nil)) logger.Info("生成 token", "用戶", "路多辛的博客", "token", t) }
輸出內(nèi)容如下:
time=2023-10-15T15:06:58.253+08:00 level=INFO msg="生成 token" 用戶=路多辛的博客 token=******
從安全角度看,密碼或者token 等敏感信息是不能被記錄在日志里面的,可以使用自定義的并且實(shí)現(xiàn)了 LogValue 的類型來(lái)避免這種情況產(chǎn)生。在這個(gè)例子中,當(dāng)記錄 token 日志時(shí),token 會(huì)被轉(zhuǎn)換為“******”后記錄在日志里面。再看一個(gè)結(jié)合字段分組使用的示例:
package main import ( "log/slog" ) type Name struct { First, Last string } func (n Name) LogValue() slog.Value { return slog.GroupValue( slog.String("first", n.First), slog.String("last", n.Last)) } func main() { n := Name{"路多辛的博客", "路多辛的所思所想"} slog.Info("任務(wù)結(jié)束", "agent", n) }
輸出內(nèi)容如下:
2023/10/15 15:06:09 INFO 任務(wù)結(jié)束 agent.first=路多辛的博客 agent.last=路多辛的所思所想
包裝輸出函數(shù)
日志記錄函數(shù)使用調(diào)用堆棧上的反射來(lái)查找應(yīng)用程序中日志記錄調(diào)用的文件名和行號(hào),這可能會(huì)導(dǎo)致包裝 slog 的函數(shù)記錄錯(cuò)誤的的源信息。舉個(gè)例子,如果在 mylog.go 中定義了一個(gè)日志記錄函數(shù) Infof,然后在 main.go 中調(diào)用了此函數(shù),這種情況下,日志會(huì)將把源文件記錄為 mylog.go 而不是 main.go。正確實(shí)現(xiàn) Infof 函數(shù)的方式是將獲取的源信息傳遞給 NewRecord 函數(shù),示例代碼如下:
package main import ( "context" "fmt" "log/slog" "os" "path/filepath" "runtime" "time" ) func Infof(logger *slog.Logger, format string, args ...any) { if !logger.Enabled(context.Background(), slog.LevelInfo) { return } var pcs [1]uintptr runtime.Callers(2, pcs[:]) // skip [Callers, Infof] r := slog.NewRecord(time.Now(), slog.LevelInfo, fmt.Sprintf(format, args...), pcs[0]) _ = logger.Handler().Handle(context.Background(), r) } func main() { replace := func(groups []string, a slog.Attr) slog.Attr { // Remove time. if a.Key == slog.TimeKey && len(groups) == 0 { return slog.Attr{} } // Remove the directory from the source's filename. if a.Key == slog.SourceKey { source := a.Value.Any().(*slog.Source) source.File = filepath.Base(source.File) } return a } logger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{AddSource: true, ReplaceAttr: replace})) Infof(logger, "message, %s", "formatted") }
到此這篇關(guān)于golang結(jié)構(gòu)化日志log/slog包之LogValuer的用法簡(jiǎn)介的文章就介紹到這了,更多相關(guān)go slog內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Go中的Context實(shí)現(xiàn)原理以及正確使用方式
在 Go 語(yǔ)言中,Context 包是一種非常常用的工具,它被用來(lái)管理 goroutine 之間的通信和取消,本文將深入探討Context 包的基本原理,包括使用場(chǎng)景、原理和一些最佳實(shí)踐,感興趣的小伙伴跟著小編一起來(lái)看看吧2024-11-11Go?并發(fā)編程協(xié)程及調(diào)度機(jī)制詳情
這篇文章主要介紹了Go并發(fā)編程協(xié)程及調(diào)度機(jī)制詳情,協(xié)程是Go語(yǔ)言最大的特色之一,goroutine的實(shí)現(xiàn)其實(shí)是通過(guò)協(xié)程,更多相關(guān)內(nèi)容需要的朋友可以參考一下2022-09-09Go http client 連接池不復(fù)用的問(wèn)題
這篇文章主要介紹了Go http client 連接池不復(fù)用的問(wèn)題,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01linux中用shell快速安裝配置Go語(yǔ)言的開(kāi)發(fā)環(huán)境
相信每位開(kāi)發(fā)者都知道選擇一門(mén)開(kāi)發(fā)語(yǔ)言,免不了需要安裝配置開(kāi)發(fā)環(huán)境,所以這篇文章給大家分享了linux下使用shell一鍵安裝配置GO語(yǔ)言開(kāi)發(fā)環(huán)境的方法,有需要的朋友們可以參考借鑒,下面來(lái)一起看看吧。2016-10-10Go語(yǔ)言狀態(tài)機(jī)的實(shí)現(xiàn)
本文主要介紹了Go語(yǔ)言狀態(tài)機(jī)的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-03-03golang MarshalJson的實(shí)現(xiàn)
本文主要介紹了golang MarshalJson的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2025-03-03淺析Go中函數(shù)的健壯性,panic異常處理和defer機(jī)制
這篇文章主要為大家詳細(xì)介紹了Go中函數(shù)的健壯性,panic異常處理和defer機(jī)制的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下2023-10-10Go語(yǔ)言基礎(chǔ)知識(shí)點(diǎn)介紹
在本篇文章里小編給大家整理的是一篇關(guān)于Go語(yǔ)言基礎(chǔ)知識(shí)點(diǎn)介紹內(nèi)容,有興趣的朋友們可以跟著學(xué)習(xí)參考下。2021-07-07golang實(shí)現(xiàn)并發(fā)數(shù)控制的方法
下面小編就為大家分享一篇golang實(shí)現(xiàn)并發(fā)數(shù)控制的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2017-12-12