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-11
Go?并發(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-09
Go 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-01
linux中用shell快速安裝配置Go語(yǔ)言的開(kāi)發(fā)環(huán)境
相信每位開(kāi)發(fā)者都知道選擇一門開(kāi)發(fā)語(yǔ)言,免不了需要安裝配置開(kāi)發(fā)環(huán)境,所以這篇文章給大家分享了linux下使用shell一鍵安裝配置GO語(yǔ)言開(kāi)發(fā)環(huán)境的方法,有需要的朋友們可以參考借鑒,下面來(lái)一起看看吧。2016-10-10
Go語(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-03
golang 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-10
Go語(yǔ)言基礎(chǔ)知識(shí)點(diǎn)介紹
在本篇文章里小編給大家整理的是一篇關(guān)于Go語(yǔ)言基礎(chǔ)知識(shí)點(diǎn)介紹內(nèi)容,有興趣的朋友們可以跟著學(xué)習(xí)參考下。2021-07-07
golang實(shí)現(xiàn)并發(fā)數(shù)控制的方法
下面小編就為大家分享一篇golang實(shí)現(xiàn)并發(fā)數(shù)控制的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2017-12-12

