github.com/lingyao2333/mo-zero@v1.4.1/core/logx/richlogger.go (about) 1 package logx 2 3 import ( 4 "context" 5 "fmt" 6 "time" 7 8 "github.com/lingyao2333/mo-zero/core/timex" 9 "go.opentelemetry.io/otel/trace" 10 ) 11 12 // WithCallerSkip returns a Logger with given caller skip. 13 func WithCallerSkip(skip int) Logger { 14 if skip <= 0 { 15 return new(richLogger) 16 } 17 18 return &richLogger{ 19 callerSkip: skip, 20 } 21 } 22 23 // WithContext sets ctx to log, for keeping tracing information. 24 func WithContext(ctx context.Context) Logger { 25 return &richLogger{ 26 ctx: ctx, 27 } 28 } 29 30 // WithDuration returns a Logger with given duration. 31 func WithDuration(d time.Duration) Logger { 32 return &richLogger{ 33 fields: []LogField{Field(durationKey, timex.ReprOfDuration(d))}, 34 } 35 } 36 37 type richLogger struct { 38 ctx context.Context 39 callerSkip int 40 fields []LogField 41 } 42 43 func (l *richLogger) Debug(v ...interface{}) { 44 l.debug(fmt.Sprint(v...)) 45 } 46 47 func (l *richLogger) Debugf(format string, v ...interface{}) { 48 l.debug(fmt.Sprintf(format, v...)) 49 } 50 51 func (l *richLogger) Debugv(v interface{}) { 52 l.debug(v) 53 } 54 55 func (l *richLogger) Debugw(msg string, fields ...LogField) { 56 l.debug(msg, fields...) 57 } 58 59 func (l *richLogger) Error(v ...interface{}) { 60 l.err(fmt.Sprint(v...)) 61 } 62 63 func (l *richLogger) Errorf(format string, v ...interface{}) { 64 l.err(fmt.Sprintf(format, v...)) 65 } 66 67 func (l *richLogger) Errorv(v interface{}) { 68 l.err(fmt.Sprint(v)) 69 } 70 71 func (l *richLogger) Errorw(msg string, fields ...LogField) { 72 l.err(msg, fields...) 73 } 74 75 func (l *richLogger) Info(v ...interface{}) { 76 l.info(fmt.Sprint(v...)) 77 } 78 79 func (l *richLogger) Infof(format string, v ...interface{}) { 80 l.info(fmt.Sprintf(format, v...)) 81 } 82 83 func (l *richLogger) Infov(v interface{}) { 84 l.info(v) 85 } 86 87 func (l *richLogger) Infow(msg string, fields ...LogField) { 88 l.info(msg, fields...) 89 } 90 91 func (l *richLogger) Slow(v ...interface{}) { 92 l.slow(fmt.Sprint(v...)) 93 } 94 95 func (l *richLogger) Slowf(format string, v ...interface{}) { 96 l.slow(fmt.Sprintf(format, v...)) 97 } 98 99 func (l *richLogger) Slowv(v interface{}) { 100 l.slow(v) 101 } 102 103 func (l *richLogger) Sloww(msg string, fields ...LogField) { 104 l.slow(msg, fields...) 105 } 106 107 func (l *richLogger) WithCallerSkip(skip int) Logger { 108 if skip <= 0 { 109 return l 110 } 111 112 l.callerSkip = skip 113 return l 114 } 115 116 func (l *richLogger) WithContext(ctx context.Context) Logger { 117 l.ctx = ctx 118 return l 119 } 120 121 func (l *richLogger) WithDuration(duration time.Duration) Logger { 122 l.fields = append(l.fields, Field(durationKey, timex.ReprOfDuration(duration))) 123 return l 124 } 125 126 func (l *richLogger) WithFields(fields ...LogField) Logger { 127 l.fields = append(l.fields, fields...) 128 return l 129 } 130 131 func (l *richLogger) buildFields(fields ...LogField) []LogField { 132 fields = append(l.fields, fields...) 133 fields = append(fields, Field(callerKey, getCaller(callerDepth+l.callerSkip))) 134 135 if l.ctx == nil { 136 return fields 137 } 138 139 traceID := traceIdFromContext(l.ctx) 140 if len(traceID) > 0 { 141 fields = append(fields, Field(traceKey, traceID)) 142 } 143 144 spanID := spanIdFromContext(l.ctx) 145 if len(spanID) > 0 { 146 fields = append(fields, Field(spanKey, spanID)) 147 } 148 149 val := l.ctx.Value(fieldsContextKey) 150 if val != nil { 151 if arr, ok := val.([]LogField); ok { 152 fields = append(fields, arr...) 153 } 154 } 155 156 return fields 157 } 158 159 func (l *richLogger) debug(v interface{}, fields ...LogField) { 160 if shallLog(DebugLevel) { 161 getWriter().Debug(v, l.buildFields(fields...)...) 162 } 163 } 164 165 func (l *richLogger) err(v interface{}, fields ...LogField) { 166 if shallLog(ErrorLevel) { 167 getWriter().Error(v, l.buildFields(fields...)...) 168 } 169 } 170 171 func (l *richLogger) info(v interface{}, fields ...LogField) { 172 if shallLog(InfoLevel) { 173 getWriter().Info(v, l.buildFields(fields...)...) 174 } 175 } 176 177 func (l *richLogger) slow(v interface{}, fields ...LogField) { 178 if shallLog(ErrorLevel) { 179 getWriter().Slow(v, l.buildFields(fields...)...) 180 } 181 } 182 183 func spanIdFromContext(ctx context.Context) string { 184 spanCtx := trace.SpanContextFromContext(ctx) 185 if spanCtx.HasSpanID() { 186 return spanCtx.SpanID().String() 187 } 188 189 return "" 190 } 191 192 func traceIdFromContext(ctx context.Context) string { 193 spanCtx := trace.SpanContextFromContext(ctx) 194 if spanCtx.HasTraceID() { 195 return spanCtx.TraceID().String() 196 } 197 198 return "" 199 }