github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/log/logger.go (about)

     1  
     2  //<developer>
     3  //    <name>linapex 曹一峰</name>
     4  //    <email>linapex@163.com</email>
     5  //    <wx>superexc</wx>
     6  //    <qqgroup>128148617</qqgroup>
     7  //    <url>https://jsq.ink</url>
     8  //    <role>pku engineer</role>
     9  //    <date>2019-03-16 12:09:41</date>
    10  //</624342646705360896>
    11  
    12  package log
    13  
    14  import (
    15  	"fmt"
    16  	"os"
    17  	"time"
    18  
    19  	"github.com/go-stack/stack"
    20  )
    21  
    22  const timeKey = "t"
    23  const lvlKey = "lvl"
    24  const msgKey = "msg"
    25  const ctxKey = "ctx"
    26  const errorKey = "LOG15_ERROR"
    27  const skipLevel = 2
    28  
    29  type Lvl int
    30  
    31  const (
    32  	LvlCrit Lvl = iota
    33  	LvlError
    34  	LvlWarn
    35  	LvlInfo
    36  	LvlDebug
    37  	LvlTrace
    38  )
    39  
    40  //AlignedString返回包含lvl名称的5个字符的字符串。
    41  func (l Lvl) AlignedString() string {
    42  	switch l {
    43  	case LvlTrace:
    44  		return "TRACE"
    45  	case LvlDebug:
    46  		return "DEBUG"
    47  	case LvlInfo:
    48  		return "INFO "
    49  	case LvlWarn:
    50  		return "WARN "
    51  	case LvlError:
    52  		return "ERROR"
    53  	case LvlCrit:
    54  		return "CRIT "
    55  	default:
    56  		panic("bad level")
    57  	}
    58  }
    59  
    60  //字符串返回LVL的名称。
    61  func (l Lvl) String() string {
    62  	switch l {
    63  	case LvlTrace:
    64  		return "trce"
    65  	case LvlDebug:
    66  		return "dbug"
    67  	case LvlInfo:
    68  		return "info"
    69  	case LvlWarn:
    70  		return "warn"
    71  	case LvlError:
    72  		return "eror"
    73  	case LvlCrit:
    74  		return "crit"
    75  	default:
    76  		panic("bad level")
    77  	}
    78  }
    79  
    80  //lvl from string从字符串名称返回适当的lvl。
    81  //用于分析命令行参数和配置文件。
    82  func LvlFromString(lvlString string) (Lvl, error) {
    83  	switch lvlString {
    84  	case "trace", "trce":
    85  		return LvlTrace, nil
    86  	case "debug", "dbug":
    87  		return LvlDebug, nil
    88  	case "info":
    89  		return LvlInfo, nil
    90  	case "warn":
    91  		return LvlWarn, nil
    92  	case "error", "eror":
    93  		return LvlError, nil
    94  	case "crit":
    95  		return LvlCrit, nil
    96  	default:
    97  		return LvlDebug, fmt.Errorf("Unknown level: %v", lvlString)
    98  	}
    99  }
   100  
   101  //记录是记录器要求其处理程序写入的内容。
   102  type Record struct {
   103  	Time     time.Time
   104  	Lvl      Lvl
   105  	Msg      string
   106  	Ctx      []interface{}
   107  	Call     stack.Call
   108  	KeyNames RecordKeyNames
   109  }
   110  
   111  //当执行写入函数时,recordkeynames存储在记录中。
   112  type RecordKeyNames struct {
   113  	Time string
   114  	Msg  string
   115  	Lvl  string
   116  	Ctx  string
   117  }
   118  
   119  //记录器将键/值对写入处理程序
   120  type Logger interface {
   121  //new返回一个新的记录器,该记录器的上下文加上给定的上下文
   122  	New(ctx ...interface{}) Logger
   123  
   124  //GetHandler获取与记录器关联的处理程序。
   125  	GetHandler() Handler
   126  
   127  //sethandler更新记录器以将记录写入指定的处理程序。
   128  	SetHandler(h Handler)
   129  
   130  //使用上下文键/值对在给定级别记录消息
   131  	Trace(msg string, ctx ...interface{})
   132  	Debug(msg string, ctx ...interface{})
   133  	Info(msg string, ctx ...interface{})
   134  	Warn(msg string, ctx ...interface{})
   135  	Error(msg string, ctx ...interface{})
   136  	Crit(msg string, ctx ...interface{})
   137  }
   138  
   139  type logger struct {
   140  	ctx []interface{}
   141  	h   *swapHandler
   142  }
   143  
   144  func (l *logger) write(msg string, lvl Lvl, ctx []interface{}, skip int) {
   145  	l.h.Log(&Record{
   146  		Time: time.Now(),
   147  		Lvl:  lvl,
   148  		Msg:  msg,
   149  		Ctx:  newContext(l.ctx, ctx),
   150  		Call: stack.Caller(skip),
   151  		KeyNames: RecordKeyNames{
   152  			Time: timeKey,
   153  			Msg:  msgKey,
   154  			Lvl:  lvlKey,
   155  			Ctx:  ctxKey,
   156  		},
   157  	})
   158  }
   159  
   160  func (l *logger) New(ctx ...interface{}) Logger {
   161  	child := &logger{newContext(l.ctx, ctx), new(swapHandler)}
   162  	child.SetHandler(l.h)
   163  	return child
   164  }
   165  
   166  func newContext(prefix []interface{}, suffix []interface{}) []interface{} {
   167  	normalizedSuffix := normalize(suffix)
   168  	newCtx := make([]interface{}, len(prefix)+len(normalizedSuffix))
   169  	n := copy(newCtx, prefix)
   170  	copy(newCtx[n:], normalizedSuffix)
   171  	return newCtx
   172  }
   173  
   174  func (l *logger) Trace(msg string, ctx ...interface{}) {
   175  	l.write(msg, LvlTrace, ctx, skipLevel)
   176  }
   177  
   178  func (l *logger) Debug(msg string, ctx ...interface{}) {
   179  	l.write(msg, LvlDebug, ctx, skipLevel)
   180  }
   181  
   182  func (l *logger) Info(msg string, ctx ...interface{}) {
   183  	l.write(msg, LvlInfo, ctx, skipLevel)
   184  }
   185  
   186  func (l *logger) Warn(msg string, ctx ...interface{}) {
   187  	l.write(msg, LvlWarn, ctx, skipLevel)
   188  }
   189  
   190  func (l *logger) Error(msg string, ctx ...interface{}) {
   191  	l.write(msg, LvlError, ctx, skipLevel)
   192  }
   193  
   194  func (l *logger) Crit(msg string, ctx ...interface{}) {
   195  	l.write(msg, LvlCrit, ctx, skipLevel)
   196  	os.Exit(1)
   197  }
   198  
   199  func (l *logger) GetHandler() Handler {
   200  	return l.h.Get()
   201  }
   202  
   203  func (l *logger) SetHandler(h Handler) {
   204  	l.h.Swap(h)
   205  }
   206  
   207  func normalize(ctx []interface{}) []interface{} {
   208  //如果调用方传递了CTX对象,则展开它
   209  	if len(ctx) == 1 {
   210  		if ctxMap, ok := ctx[0].(Ctx); ok {
   211  			ctx = ctxMap.toArray()
   212  		}
   213  	}
   214  
   215  //CTX必须是偶数,因为它是一系列键/值对
   216  //没有人想检查日志功能的错误,
   217  //因此,我们不必担心输入错误,只需确保
   218  //事情是正确的长度,用户可以修复错误
   219  //当他们看到输出看起来错误时
   220  	if len(ctx)%2 != 0 {
   221  		ctx = append(ctx, nil, errorKey, "Normalized odd number of arguments by adding nil")
   222  	}
   223  
   224  	return ctx
   225  }
   226  
   227  //Lazy允许您延迟计算昂贵的日志值
   228  //计算,直到确定必须使用给定的过滤器对其进行评估。
   229  //
   230  //lazy还可以与记录器的new()函数一起使用。
   231  //生成始终报告更改的当前值的子记录器
   232  //状态。
   233  //
   234  //您可以包装任何不带参数的函数。它可以返回任何
   235  //任何类型的值的数目。
   236  type Lazy struct {
   237  	Fn interface{}
   238  }
   239  
   240  //CTX是作为上下文传递给日志函数的键/值对的映射
   241  //只有当你真的需要在你传递的参数周围更大的安全性时才使用这个
   242  //到日志功能。
   243  type Ctx map[string]interface{}
   244  
   245  func (c Ctx) toArray() []interface{} {
   246  	arr := make([]interface{}, len(c)*2)
   247  
   248  	i := 0
   249  	for k, v := range c {
   250  		arr[i] = k
   251  		arr[i+1] = v
   252  		i += 2
   253  	}
   254  
   255  	return arr
   256  }
   257