github.com/mailru/activerecord@v1.12.2/pkg/activerecord/logger.go (about) 1 package activerecord 2 3 import ( 4 "context" 5 "fmt" 6 "log" 7 8 "github.com/mailru/activerecord/pkg/iproto/iproto" 9 ) 10 11 type ctxKey uint8 12 type ValueLogPrefix map[string]interface{} 13 type DefaultLogger struct { 14 level uint32 15 Fields ValueLogPrefix 16 } 17 18 const ( 19 PanicLoggerLevel uint32 = iota 20 FatalLoggerLevel 21 ErrorLoggerLevel 22 WarnLoggerLevel 23 InfoLoggerLevel 24 DebugLoggerLevel 25 TraceLoggerLevel 26 ) 27 28 const ( 29 ContextLogprefix ctxKey = iota 30 ) 31 32 const ( 33 ValueContextErrorField = "context" 34 ) 35 36 func NewLogger() *DefaultLogger { 37 return &DefaultLogger{ 38 level: InfoLoggerLevel, 39 Fields: ValueLogPrefix{"orm": "activerecord"}, 40 } 41 } 42 43 func (l *DefaultLogger) getLoggerFromContext(ctx context.Context) LoggerInterface { 44 return l.getLoggerFromContextAndValue(ctx, ValueLogPrefix{}) 45 } 46 47 func (l *DefaultLogger) SetLoggerValueToContext(ctx context.Context, val ValueLogPrefix) context.Context { 48 ctxVal := ctx.Value(ContextLogprefix) 49 if ctxVal != nil { 50 lprefix, ok := ctxVal.(ValueLogPrefix) 51 if !ok { 52 val["logger.context.error"] = ValueContextErrorField 53 val["logger.context.valueType"] = fmt.Sprintf("%T", ctxVal) 54 } else { 55 for k, v := range lprefix { 56 if _, ok := val[k]; !ok { 57 val[k] = v 58 } 59 } 60 } 61 } 62 63 return context.WithValue(ctx, ContextLogprefix, val) 64 } 65 66 func (l *DefaultLogger) getLoggerFromContextAndValue(ctx context.Context, addVal ValueLogPrefix) LoggerInterface { 67 // Думаю что надо закешировать один раз инстанс логгера для контекста 68 // Но надо учитывать, что мог измениться уровень логирования хотим ли мы в рамках одного запроса 69 // менять уровни логирования? 70 // Еще надо добавить в логгер конфигурацию, что бы уровни ролирования можно было 71 // настраивать на уровне моделей 72 nl := NewLogger() 73 nl.level = l.level 74 75 for k, v := range l.Fields { 76 nl.Fields[k] = v 77 } 78 79 for k, v := range addVal { 80 nl.Fields[k] = v 81 } 82 83 ctxVal := ctx.Value(ContextLogprefix) 84 if ctxVal == nil { 85 nl.Fields["logger.context"] = "empty" 86 } else { 87 lprefix, ok := ctxVal.(ValueLogPrefix) 88 if !ok { 89 nl.Fields["logger.context.error"] = ValueContextErrorField 90 nl.Fields["logger.context.valueType"] = fmt.Sprintf("%T", ctxVal) 91 } else { 92 for k, v := range lprefix { 93 nl.Fields[k] = v 94 } 95 } 96 } 97 98 return nl 99 } 100 101 func (l *DefaultLogger) SetLogLevel(level uint32) { 102 l.level = level 103 } 104 105 func (l *DefaultLogger) loggerPrint(level uint32, lprefix string, args ...interface{}) { 106 if l.level < level { 107 return 108 } 109 110 log.Print(lprefix, l.Fields, args) 111 } 112 113 func (l *DefaultLogger) Debug(ctx context.Context, args ...interface{}) { 114 l.getLoggerFromContext(ctx).(*DefaultLogger).loggerPrint(DebugLoggerLevel, "DEBUG: ", args) 115 } 116 117 func (l *DefaultLogger) Trace(ctx context.Context, args ...interface{}) { 118 l.getLoggerFromContext(ctx).(*DefaultLogger).loggerPrint(TraceLoggerLevel, "TRACE: ", args) 119 } 120 121 func (l *DefaultLogger) Info(ctx context.Context, args ...interface{}) { 122 l.getLoggerFromContext(ctx).(*DefaultLogger).loggerPrint(InfoLoggerLevel, "INFO: ", args) 123 } 124 125 func (l *DefaultLogger) Error(ctx context.Context, args ...interface{}) { 126 l.getLoggerFromContext(ctx).(*DefaultLogger).loggerPrint(ErrorLoggerLevel, "ERROR: ", args) 127 } 128 129 func (l *DefaultLogger) Warn(ctx context.Context, args ...interface{}) { 130 l.getLoggerFromContext(ctx).(*DefaultLogger).loggerPrint(WarnLoggerLevel, "WARN: ", args) 131 } 132 133 func (l *DefaultLogger) Fatal(ctx context.Context, args ...interface{}) { 134 log.Fatal("FATAL: ", l.Fields, args) 135 } 136 137 func (l *DefaultLogger) Panic(ctx context.Context, args ...interface{}) { 138 log.Panic("PANIC; ", l.Fields, args) 139 } 140 141 func (l *DefaultLogger) CollectQueries(ctx context.Context, f func() (MockerLogger, error)) { 142 } 143 144 type IprotoLogger struct{} 145 146 var _ iproto.Logger = IprotoLogger{} 147 148 func (IprotoLogger) Printf(ctx context.Context, fmtStr string, v ...interface{}) { 149 ctx = Logger().SetLoggerValueToContext(ctx, map[string]interface{}{"iproto": "client"}) 150 Logger().Info(ctx, fmt.Sprintf(fmtStr, v...)) 151 } 152 153 func (IprotoLogger) Debugf(ctx context.Context, fmtStr string, v ...interface{}) { 154 ctx = Logger().SetLoggerValueToContext(ctx, map[string]interface{}{"iproto": "client"}) 155 Logger().Debug(ctx, fmt.Sprintf(fmtStr, v...)) 156 }