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  }