網(wǎng)站首頁 編程語言 正文
問題描述
在使用 gin-swagger
的過程中, 經(jīng)常會發(fā)生因為缺少 json
等 tag
而導(dǎo)致的異常。 由于 gin-swagger
是并發(fā)執(zhí)行的, 輸出的日志本身是錯位的。 這就導(dǎo)致無法定義是哪一個結(jié)構(gòu)體缺少 tag
導(dǎo)致的。
一般而言, 這種時候只能一個個點開去檢查。
解決方案
思路 : 要是每行日志帶當前 goroutine_id
的話, 是不是就可以準確定位到報錯的 goroutine
他打印的日志是哪些了呢!
說做就做
實現(xiàn)思路
- 查看當前日志是怎么打印的
發(fā)現(xiàn) gin-swagger
日志直接調(diào)用的 golang
的標準庫 log
由于沒有對log初始化, 所以默認使用的是 stdout
。
log.Printf("Picking operation from %s\n", aurora.Blue(funType.FullName()))
- 如果想要給日志中添加
goroutine_id
的話, 就需要在調(diào)用log.Printf
的時候獲取當前goroutine
的 id , 所以首先要解決的是怎么獲取goroutine_id
的問題。
調(diào)研后發(fā)現(xiàn)了集中常見的獲取 goroutine_id
的方法:
2.1 通過棧信息解析后獲取
func GetGID() uint64 { b := make([]byte, 64) b = b[:runtime.Stack(b, false)] b = bytes.TrimPrefix(b, []byte("goroutine ")) b = b[:bytes.IndexByte(b, ' ')] n, _ := strconv.ParseUint(string(b), 10, 64) return n }
2.2 修改 Go 源碼獲取
# src/runtime/runtime2.go func Goid() int64 { _g_ := getg() return _g_.goid }
2.3 通過 CGO 獲取
文件 id.c
#include "runtime.h" int64 ·Id(void) { return g->goid; }
文件 id.go
package id func Id() int64
另外還可以通過匯編獲取 goroutine_id
由于go的版本不同,goroutine的結(jié)構(gòu)也可能不同, 所以此處我直接調(diào)用一個開源實現(xiàn):
https://github.com/petermattis/goid
- 修改
gin-swagger
main.go
源碼, 修改log
Write
的實現(xiàn)
修改前
func main() { cmd.Execute() }
修改后
type Out os.File func (o Out) Write(b []byte) (int, error) { prefix := fmt.Sprintf("gid-%d: ", goid.Get()) all := make([]byte, len(b)+len(prefix)) all = []byte(prefix) all = append(all, b...) f := os.File(o) return f.Write(all) } func main() { var out Out out = Out(os.Stdout) log.SetOutput(out) cmd.Execute()
這樣修改后,每次 gin-swagger
調(diào)用 log
打印日志都時候, 都會使用我定義的 Write
方法, Write
方法中每次打印前都會先查詢出當前的 goroutine_id
,然后作為日志的前綴。
修改后的日志效果
從中可以看到每行日志開頭,都已經(jīng)加上了 goroutine_id
。 只要使用 panic
goroutine
的 id
做一次 grep
, 即可篩選出需要的日志了,極大的方便了定位問題。
cat /tmp/gin-swagger.log | grep 7647
原文鏈接:https://juejin.cn/post/7075159546393542686
相關(guān)推薦
- 2022-08-11 TypeScript中的裝飾器用法_基礎(chǔ)知識
- 2023-03-16 ProxyWidget和Element更新的正確方式詳解_Android
- 2022-04-18 html2canvas 不支持圖片的object-fit樣式
- 2023-12-08 maven中mybatis-generator插件執(zhí)行報錯:Cannot resolve class
- 2024-01-15 spring boot jpa 執(zhí)行test測試,發(fā)現(xiàn)執(zhí)行未報錯但是事務(wù)會自動回滾
- 2022-02-24 詳細整理Oracle中常用函數(shù)_oracle
- 2023-01-26 Android?源碼淺析RecyclerView?Adapter_Android
- 2022-05-06 mac goland 常用快捷鍵
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支