-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathlogger.go
134 lines (122 loc) · 4.25 KB
/
logger.go
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
125
126
127
128
129
130
131
132
133
134
package ginlogrus
import (
"fmt"
"github.com/gin-gonic/gin"
"github.com/google/uuid"
opentracing "github.com/opentracing/opentracing-go"
"github.com/sirupsen/logrus"
)
// SetCtxLoggerHeader - if aggregate logging, add header info... otherwise just info log the data passed
func SetCtxLoggerHeader(c *gin.Context, name string, data interface{}) {
logger := GetCtxLogger(c)
_, found := c.Get("aggregate-logger")
if found {
logger.Logger.Out.(*LogBuffer).StoreHeader(name, data)
}
if !found {
logger.Infof("%s: %v", name, data)
}
}
// SetCtxLogger - used when you want to set the *logrus.Entry with new logrus.WithFields{} for this request in the gin.Context so it can be used going forward for the request
func SetCtxLogger(c *gin.Context, logger *logrus.Entry) *logrus.Entry {
log, found := c.Get("aggregate-logger")
if found {
logger.Logger = log.(*logrus.Logger)
logger = logger.WithFields(logrus.Fields{}) // no need to add additional fields when aggregate logging
}
if !found {
// not aggregate logging, so make sure to add some needed fields
logger = logger.WithFields(logrus.Fields{
"requestID": CxtRequestID(c),
"method": c.Request.Method,
"path": c.Request.URL.Path})
}
c.Set("ctxLogger", logger)
return logger
}
// GetCtxLogger - get the *logrus.Entry for this request from the gin.Context
func GetCtxLogger(c *gin.Context) *logrus.Entry {
l, ok := c.Get("ctxLogger")
if ok {
return l.(*logrus.Entry)
}
var logger *logrus.Entry
log, found := c.Get("aggregate-logger")
if found {
logger = logrus.WithFields(logrus.Fields{})
logger.Logger = log.(*logrus.Logger)
}
if !found {
// not aggregate logging, so make sure to add some needed fields
logger = logrus.WithFields(logrus.Fields{
"requestID": CxtRequestID(c),
"method": c.Request.Method,
"path": c.Request.URL.Path,
})
}
c.Set("ctxLogger", logger)
return logger
}
// CxtRequestID - if not already set, then add logrus Field to the entry with the tracing ID for the request.
// then return the trace/request id
func CxtRequestID(c *gin.Context) string {
// already setup, so we're done
if id, found := c.Get("RequestID"); found == true {
return id.(string)
}
// see if we're using github.com/Bose/go-gin-opentracing which will set a span in "tracing-context"
if s, foundSpan := c.Get("tracing-context"); foundSpan {
span := s.(opentracing.Span)
requestID := fmt.Sprintf("%v", span)
c.Set("RequestID", requestID)
return requestID
}
// some other process might have stuck it in a header
if len(ContextTraceIDField) != 0 {
if s, ok := c.Get(ContextTraceIDField); ok {
span := s.(opentracing.Span)
requestID := fmt.Sprintf("%v", span)
c.Set("RequestID", requestID)
return requestID
}
}
if requestID := c.Request.Header.Get("uber-trace-id"); len(requestID) != 0 {
c.Set("RequestID", requestID)
return requestID
}
// finally, just create a fake request id...
requestID := uuid.New().String()
c.Set("RequestID", requestID)
return requestID
}
// GetCxtRequestID - dig the request ID out of the *logrus.Entry in the gin.Context
func GetCxtRequestID(c *gin.Context) string {
return CxtRequestID(c)
}
// NewBuffer - create a new aggregate logging buffer for the *logrus.Entry , which can be flushed by the consumer
// how-to, when to use this:
// the request level log entry is written when the request is over, so you need this thing to
// write go routine logs that complete AFTER the request is completed.
// careful: the loggers will share a ref to the same Header (writes to one will affect the other)
// example:
// go func() {
// buff := NewBuffer(logger) // logger is an existing *logrus.Entry
// // do somem work here and write some logs via the logger. Like logger.Info("hi mom! I'm a go routine that finished after the request")
// fmt.Printf(buff.String()) // this will write the aggregated buffered logs to stdout
// }()
//
func NewBuffer(l *logrus.Entry) *LogBuffer {
buff := NewLogBuffer()
if l, ok := l.Logger.Out.(*LogBuffer); ok {
CopyHeader(&buff, l)
buff.AddBanner = l.AddBanner
}
// buff.Header = l.Logger.Out.(*ginlogrus.LogBuffer).Header
l.Logger = &logrus.Logger{
Out: &buff,
Formatter: new(logrus.JSONFormatter),
Hooks: make(logrus.LevelHooks),
Level: logrus.DebugLevel,
}
return &buff
}