英文:
Adding traceId from header to logs sent to Loki server in Golang
问题
我有一个名为LokiLogs的函数,它将日志发送到Loki服务器。我想在每个API调用中将一个名为traceId的标识符作为头部X-Trace-ID传递给日志。以下是我目前的代码:
type StdoutLogger struct {
io.Writer
}
func (l *StdoutLogger) Print(v ...interface{}) {
vv := LogFormatter(v...) //这个函数只是美化日志字符串,不会影响功能
log.Println(vv)
if len(vv.Message) > 0 {
slice := vv.Message[0]
LokiLogs(slice.Sql + " " + slice.SqlMessage)
}
}
func main() {
router := gin.Default()
.
.
db.LogMode(true)
db.SetLogger(&StdoutLogger{os.Stdout})
}
func LokiLogs(msg string) {
v := strconv.FormatInt(time.Now().UnixNano(), 10)
msg = msg + " " + "traceId="
Lokijson := map[string]interface{}{
"streams": []interface{}{
map[string]interface{}{
"stream": map[string]interface{}{
"message": msg,
"client_ip": GetOutboundIP(),
"level": "info",
"job": "Test",
},
"values": []interface{}{
[]interface{}{
string(v),
msg,
},
},
},
},
}
jsonValue, _ := json.Marshal(Lokijson)
url := os.Getenv("LOKI_URL")
resp, err := http.Post(url, "application/json", bytes.NewBuffer(jsonValue))
fmt.Println(resp, err)
}
我已经使用一个日志中间件为每个API调用设置了一个名为traceId的头部,类似于c.Request.Header.Set("X-Trace-ID", traceID)
。如何将这个traceId值传递给LokiLogs函数,以便它可以连接到msg字符串中,类似于traceId=Some UUID
?
英文:
I have a function called LokiLogs which sends logs to the Loki server. I want to add a traceId to the logs that gets passed as a header X-Trace-ID in every API call. Here's the code I have so far:
type StdoutLogger struct {
io.Writer
}
func (l *StdoutLogger) Print(v ...interface{}) {
vv := LogFormatter(v...) //This function is just beautify the log string, it will not affect the functionality
log.Println(vv)
if len(vv.Message) > 0 {
slice := vv.Message[0]
LokiLogs(slice.Sql + " " + slice.SqlMessage)
}
}
func main() {
router := gin.Default()
.
.
db.LogMode(true)
db.SetLogger(&StdoutLogger{os.Stdout})
}
func LokiLogs(msg string) {
v := strconv.FormatInt(time.Now().UnixNano(), 10)
msg = msg + " " + "traceId="
Lokijson := map[string]interface{}{
"streams": []interface{}{
map[string]interface{}{
"stream": map[string]interface{}{
"message": msg,
"client_ip": GetOutboundIP(),
"level": "info",
"job": "Test",
},
"values": []interface{}{
[]interface{}{
string(v),
msg,
},
},
},
},
}
jsonValue, _ := json.Marshal(Lokijson)
url := os.Getenv("LOKI_URL")
resp, err := http.Post(url, "application/json", bytes.NewBuffer(jsonValue))
fmt.Println(resp, err)
}
I have set a traceId header for every API call like this c.Request.Header.Set("X-Trace-ID", traceID) using a log middleware. How can I pass this traceId value to the LokiLogs function so that it can be concatenated to the msg string like this traceId=Some UUID?
答案1
得分: 1
看起来你的db.SetLogger
可能来自jinzhu/gorm。那里的Logger接口实际上不允许你通过除了日志记录器实例之外的方式传递额外的细节,所以我认为你需要像这样的东西:
type StdoutLogger struct {
io.Writer
TraceID string
}
然后你的gin HandlerFunc需要使用gin.Context中的GetHeader从头部提取信息,并使用该信息构建一个特定于该请求的日志记录器实例,类似于这样:
func (s *mystruct) MyHandler(c *gin.Context) {
thisTraceID := c.GetHeader("X-Trace-ID")
...
db.SetLogger(&StdoutLogger{Writer: os.Stdout, TraceID: thisTraceID})
// db.Find/Exec/Save/...
}
然后是
func (l *StdoutLogger) Print(v ...interface{}) {
vv := LogFormatter(v...) //这个函数只是美化日志字符串,不会影响功能
log.Println(vv)
if len(vv.Message) > 0 {
slice := vv.Message[0]
LokiLogs(l.TraceID, slice.Sql + " " + slice.SqlMessage)
}
}
func LokiLogs(traceID, msg string) {
...
}
英文:
It looks like your db.SetLogger
is probably from jinzhu/gorm. The Logger interface there doesn't really allow you to pass additional details except through the logger instance, so I think you'd need something a bit like:
type StdoutLogger struct {
io.Writer
TraceID string
}
Then your gin HandlerFunc would need to extract the header from gin.Context using GetHeader, and use that to construct a logger instance specific to that request, something like:
func (s *mystruct) MyHandler(c *gin.Context) {
thisTraceID := c.GetHeader("X-Trace-ID")
...
db.SetLogger(&StdoutLogger{Writer: os.Stdout, TraceID: thisTraceID})
// db.Find/Exec/Save/...
}
and then
func (l *StdoutLogger) Print(v ...interface{}) {
vv := LogFormatter(v...) //This function is just beautify the log string, it will not affect the functionality
log.Println(vv)
if len(vv.Message) > 0 {
slice := vv.Message[0]
LokiLogs(l.TraceID, slice.Sql + " " + slice.SqlMessage)
}
}
func LokiLogs(traceID, msg string) {
...
}
```
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论