1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
| package main
import ( "context" "fmt" "github.com/sirupsen/logrus" "io" "os" "path/filepath" "runtime" "strings" )
const logPath = "./log.txt"
var log = New()
func New() *Logger { return &Logger{logger: logrus.New()} }
type Logger struct { ctx context.Context logger *logrus.Logger }
func (l *Logger) SetFormatter(formatter logrus.Formatter) { l.logger.SetFormatter(formatter) }
func (l *Logger) SetOutput(output io.Writer) { l.logger.SetOutput(output) }
func (l *Logger) SetLevel(level logrus.Level) { l.logger.SetLevel(level) }
func (l *Logger) WithContext(ctx context.Context) *Logger { return &Logger{ctx: ctx, logger: l.logger} }
func (l *Logger) Debug(format string, args ...any) { l.log(logrus.DebugLevel, format, args...) }
func (l *Logger) Info(format string, args ...any) { l.log(logrus.InfoLevel, format, args...) }
func (l *Logger) Warn(format string, args ...any) { l.log(logrus.WarnLevel, format, args...) }
func (l *Logger) Error(format string, args ...any) { l.log(logrus.ErrorLevel, format, args...) }
func (l *Logger) Fatal(format string, args ...any) { l.log(logrus.FatalLevel, format, args...) }
func (l *Logger) log(level logrus.Level, format string, args ...any) { format = fmt.Sprintf("[%s] %s", GetCallerShort(3), format) l.logger.WithContext(l.ctx).Logf(level, format, args...) }
type Formatter struct{}
func (f *Formatter) Format(entry *logrus.Entry) ([]byte, error) { pid := os.Getpid() time := entry.Time.Format("2006-01-02T15:04:05.000000") level := strings.ToUpper(entry.Level.String()) traceId := GetTraceIdFromCtx(entry.Context)
content := fmt.Sprintf("%s %s %d %s %s\n", time, level, pid, traceId, entry.Message) return []byte(content), nil }
func GetCallerShort(skip int) string { _, file, line, ok := runtime.Caller(skip + 1) if !ok { return "" } _, file = filepath.Split(file) return fmt.Sprintf("%s:%d", file, line) }
func CtxSetTraceId(ctx context.Context) context.Context { return context.WithValue(ctx, "trace_id", "id1") }
func GetTraceIdFromCtx(ctx context.Context) string { if ctx == nil { return "-" }
val := ctx.Value("trace_id") if traceId, ok := val.(string); ok { return fmt.Sprintf("trace-%s", traceId) } else { return "-" } }
func init() { f, err := os.OpenFile(logPath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0o640) if err != nil { panic(err) }
log.SetFormatter(&Formatter{}) log.SetOutput(io.MultiWriter(os.Stdout, f)) log.SetLevel(logrus.DebugLevel) }
func main() { ctx := context.Background() ctx = CtxSetTraceId(ctx) log.WithContext(ctx).Info("main failed: %s", "detail") }
|