Skip to content

Instantly share code, notes, and snippets.

@lwydyby
Last active September 12, 2021 08:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lwydyby/58700d6ea1082d25ecc46049633243c7 to your computer and use it in GitHub Desktop.
Save lwydyby/58700d6ea1082d25ecc46049633243c7 to your computer and use it in GitHub Desktop.
logrus hook concurrent map iteration and map write error
package main
import (
"bytes"
"context"
"fmt"
log "github.com/sirupsen/logrus"
"path/filepath"
"runtime"
"strconv"
"sync"
"time"
)
func main() {
log.SetFormatter(&LogFormatter{})
go func() {
for {
func(){
defer func() {
// 处理所有异常,防止panic导致程序关闭
if p := recover(); p != nil {
}
}()
hook:=AddTraceIdHook("123")
defer RemoveTraceHook(hook)
log.Infof("test why ")
}()
}
}()
go func() {
for {
func(){
defer func() {
// 处理所有异常,防止panic导致程序关闭
if p := recover(); p != nil {
}
}()
hook:=AddTraceIdHook("1233")
defer RemoveTraceHook(hook)
log.Infof("test why 2")
}()
}
}()
c:=make(chan int)
<-c
}
var traceLock = &sync.Mutex{}
func AddTraceIdHook(traceId string) log.Hook {
defer traceLock.Unlock()
traceLock.Lock()
traceHook := newTraceIdHook(traceId)
if log.StandardLogger().Hooks == nil {
hooks := new(log.LevelHooks)
log.StandardLogger().ReplaceHooks(*hooks)
}
log.AddHook(traceHook)
return traceHook
}
func RemoveTraceHook(hook log.Hook) {
defer traceLock.Unlock()
traceLock.Lock()
allHooks := log.StandardLogger().Hooks
for key, hooks := range allHooks {
replaceHooks := hooks
for index, h := range hooks {
if h == hook {
replaceHooks = append(hooks[:index], hooks[index+1:]...)
break
}
}
allHooks[key] = replaceHooks
}
log.StandardLogger().ReplaceHooks(allHooks)
}
type TraceIdHook struct {
TraceId string
GID uint64
}
func newTraceIdHook(traceId string) log.Hook {
return &TraceIdHook{
TraceId: traceId,
GID: getGID(),
}
}
func (t TraceIdHook) Levels() []log.Level {
return log.AllLevels
}
func (t TraceIdHook) Fire(entry *log.Entry) error {
if getGID() == t.GID {
entry.Context = context.WithValue(context.Background(), "trace_id", t.TraceId)
}
return nil
}
type LogFormatter struct{}
//格式详情
func (s *LogFormatter) Format(entry *log.Entry) ([]byte, error) {
timestamp := time.Now().Format("2006-01-02 15:04:05")
var file string
var line int
if entry.Caller != nil {
file = filepath.Base(entry.Caller.File)
line = entry.Caller.Line
}
level := entry.Level.String()
if entry.Context == nil || entry.Context.Value("trace_id") == "" {
uuid:= "NO UUID"
entry.Context = context.WithValue(context.Background(), "trace_id", uuid)
}
msg := fmt.Sprintf("%-15s [%-3d] [%-5s] [%s] %s:%d %s\n", timestamp, getGID(), level, entry.Context.Value("trace_id"), file, line, entry.Message)
return []byte(msg), nil
}
// 获取当前协程id
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
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment