github.com/neatlab/neatio@v1.7.3-0.20220425043230-d903e92fcc75/chain/log/logger.go (about)

     1  package log
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"time"
     7  
     8  	"github.com/go-stack/stack"
     9  )
    10  
    11  const timeKey = "t"
    12  const lvlKey = "lvl"
    13  const msgKey = "msg"
    14  const ctxKey = "ctx"
    15  const errorKey = "LOG15_ERROR"
    16  const skipLevel = 2
    17  
    18  type Lvl int
    19  
    20  const (
    21  	LvlCrit Lvl = iota
    22  	LvlError
    23  	LvlWarn
    24  	LvlInfo
    25  	LvlDebug
    26  	LvlTrace
    27  )
    28  
    29  func (l Lvl) AlignedString() string {
    30  	switch l {
    31  	case LvlTrace:
    32  		return "TRACE"
    33  	case LvlDebug:
    34  		return "DEBUG"
    35  	case LvlInfo:
    36  		return "INFO "
    37  	case LvlWarn:
    38  		return "WARN "
    39  	case LvlError:
    40  		return "ERROR"
    41  	case LvlCrit:
    42  		return "CRIT "
    43  	default:
    44  		panic("bad level")
    45  	}
    46  }
    47  
    48  func (l Lvl) String() string {
    49  	switch l {
    50  	case LvlTrace:
    51  		return "trce"
    52  	case LvlDebug:
    53  		return "dbug"
    54  	case LvlInfo:
    55  		return "info"
    56  	case LvlWarn:
    57  		return "warn"
    58  	case LvlError:
    59  		return "eror"
    60  	case LvlCrit:
    61  		return "crit"
    62  	default:
    63  		panic("bad level")
    64  	}
    65  }
    66  
    67  func LvlFromString(lvlString string) (Lvl, error) {
    68  	switch lvlString {
    69  	case "trace", "trce":
    70  		return LvlTrace, nil
    71  	case "debug", "dbug":
    72  		return LvlDebug, nil
    73  	case "info":
    74  		return LvlInfo, nil
    75  	case "warn":
    76  		return LvlWarn, nil
    77  	case "error", "eror":
    78  		return LvlError, nil
    79  	case "crit":
    80  		return LvlCrit, nil
    81  	default:
    82  		return LvlDebug, fmt.Errorf("Unknown level: %v", lvlString)
    83  	}
    84  }
    85  
    86  type Record struct {
    87  	Time     time.Time
    88  	Lvl      Lvl
    89  	Msg      string
    90  	Ctx      []interface{}
    91  	Call     stack.Call
    92  	KeyNames RecordKeyNames
    93  }
    94  
    95  type RecordKeyNames struct {
    96  	Time string
    97  	Msg  string
    98  	Lvl  string
    99  	Ctx  string
   100  }
   101  
   102  type Logger interface {
   103  	New(ctx ...interface{}) Logger
   104  
   105  	GetHandler() Handler
   106  
   107  	SetHandler(h Handler)
   108  
   109  	Trace(msg string, ctx ...interface{})
   110  	Debug(msg string, ctx ...interface{})
   111  	Info(msg string, ctx ...interface{})
   112  	Warn(msg string, ctx ...interface{})
   113  	Error(msg string, ctx ...interface{})
   114  	Crit(msg string, ctx ...interface{})
   115  
   116  	Debugf(format string, args ...interface{})
   117  	Infof(format string, args ...interface{})
   118  	Warnf(format string, args ...interface{})
   119  	Errorf(format string, args ...interface{})
   120  	Critf(msg string, ctx ...interface{})
   121  }
   122  
   123  type logger struct {
   124  	ctx []interface{}
   125  	h   *swapHandler
   126  }
   127  
   128  func (l *logger) write(msg string, lvl Lvl, ctx []interface{}, skip int) {
   129  	l.h.Log(&Record{
   130  		Time: time.Now(),
   131  		Lvl:  lvl,
   132  		Msg:  msg,
   133  		Ctx:  newContext(l.ctx, ctx),
   134  		Call: stack.Caller(skip),
   135  		KeyNames: RecordKeyNames{
   136  			Time: timeKey,
   137  			Msg:  msgKey,
   138  			Lvl:  lvlKey,
   139  			Ctx:  ctxKey,
   140  		},
   141  	})
   142  }
   143  
   144  func (l *logger) New(ctx ...interface{}) Logger {
   145  	side := &logger{newContext(l.ctx, ctx), new(swapHandler)}
   146  	side.SetHandler(l.h)
   147  	return side
   148  }
   149  
   150  func newContext(prefix []interface{}, suffix []interface{}) []interface{} {
   151  	normalizedSuffix := normalize(suffix)
   152  	newCtx := make([]interface{}, len(prefix)+len(normalizedSuffix))
   153  	n := copy(newCtx, prefix)
   154  	copy(newCtx[n:], normalizedSuffix)
   155  	return newCtx
   156  }
   157  
   158  func (l *logger) Trace(msg string, ctx ...interface{}) {
   159  	l.write(msg, LvlTrace, ctx, skipLevel)
   160  }
   161  
   162  func (l *logger) Debug(msg string, ctx ...interface{}) {
   163  	l.write(msg, LvlDebug, ctx, skipLevel)
   164  }
   165  
   166  func (l *logger) Info(msg string, ctx ...interface{}) {
   167  	l.write(msg, LvlInfo, ctx, skipLevel)
   168  }
   169  
   170  func (l *logger) Warn(msg string, ctx ...interface{}) {
   171  	l.write(msg, LvlWarn, ctx, skipLevel)
   172  }
   173  
   174  func (l *logger) Error(msg string, ctx ...interface{}) {
   175  	l.write(msg, LvlError, ctx, skipLevel)
   176  }
   177  
   178  func (l *logger) Crit(msg string, ctx ...interface{}) {
   179  	l.write(msg, LvlCrit, ctx, skipLevel)
   180  	os.Exit(1)
   181  }
   182  
   183  func (l *logger) Debugf(format string, args ...interface{}) {
   184  	l.write(fmt.Sprintf(format, args...), LvlDebug, nil, skipLevel)
   185  }
   186  
   187  func (l *logger) Infof(format string, args ...interface{}) {
   188  	l.write(fmt.Sprintf(format, args...), LvlInfo, nil, skipLevel)
   189  }
   190  
   191  func (l *logger) Warnf(format string, args ...interface{}) {
   192  	l.write(fmt.Sprintf(format, args...), LvlWarn, nil, skipLevel)
   193  }
   194  
   195  func (l *logger) Errorf(format string, args ...interface{}) {
   196  	l.write(fmt.Sprintf(format, args...), LvlError, nil, skipLevel)
   197  }
   198  
   199  func (l *logger) Critf(format string, args ...interface{}) {
   200  	l.write(fmt.Sprintf(format, args...), LvlCrit, nil, skipLevel)
   201  }
   202  
   203  func (l *logger) GetHandler() Handler {
   204  	return l.h.Get()
   205  }
   206  
   207  func (l *logger) SetHandler(h Handler) {
   208  	l.h.Swap(h)
   209  }
   210  
   211  func normalize(ctx []interface{}) []interface{} {
   212  
   213  	if len(ctx) == 1 {
   214  		if ctxMap, ok := ctx[0].(Ctx); ok {
   215  			ctx = ctxMap.toArray()
   216  		}
   217  	}
   218  
   219  	if len(ctx)%2 != 0 {
   220  		ctx = append(ctx, nil, errorKey, "Normalized odd number of arguments by adding nil")
   221  	}
   222  
   223  	return ctx
   224  }
   225  
   226  type Lazy struct {
   227  	Fn interface{}
   228  }
   229  
   230  type Ctx map[string]interface{}
   231  
   232  func (c Ctx) toArray() []interface{} {
   233  	arr := make([]interface{}, len(c)*2)
   234  
   235  	i := 0
   236  	for k, v := range c {
   237  		arr[i] = k
   238  		arr[i+1] = v
   239  		i += 2
   240  	}
   241  
   242  	return arr
   243  }