github.com/nikandfor/tlog@v0.21.3/tlog.go (about)

     1  package tlog
     2  
     3  import (
     4  	"io"
     5  	"os"
     6  	"sync"
     7  	"time"
     8  	"unsafe"
     9  
    10  	"github.com/nikandfor/hacked/htime"
    11  	"github.com/nikandfor/loc"
    12  
    13  	"github.com/nikandfor/tlog/tlwire"
    14  )
    15  
    16  type (
    17  	Logger struct {
    18  		io.Writer // protected by Mutex below
    19  
    20  		tlwire.Encoder
    21  
    22  		NewID func() ID `deep:"compare=pointer"` // must be threadsafe
    23  
    24  		now  func() time.Time `deep:"compare=pointer"`
    25  		nano func() int64     `deep:"compare=pointer"`
    26  
    27  		callers     func(skip int, pc *loc.PC, len, cap int) int `deep:"compare=pointer"`
    28  		callersSkip int
    29  
    30  		filter *filter // atomic access
    31  
    32  		sync.Mutex
    33  
    34  		b  []byte
    35  		ls []byte
    36  	}
    37  
    38  	Span struct {
    39  		*Logger
    40  		ID        ID
    41  		StartedAt time.Time
    42  	}
    43  
    44  	LogLevel int
    45  
    46  	EventKind rune
    47  
    48  	// for like stdlib log.SetOutput(l).
    49  	writeWrapper struct {
    50  		Span
    51  
    52  		d int
    53  	}
    54  )
    55  
    56  var (
    57  	Stdout = os.Stdout
    58  	Stderr = os.Stderr
    59  )
    60  
    61  // Log levels.
    62  const (
    63  	Info LogLevel = iota
    64  	Warn
    65  	Error
    66  	Fatal
    67  
    68  	Debug LogLevel = -1
    69  )
    70  
    71  // Predefined keys.
    72  var (
    73  	KeySpan      = "_s"
    74  	KeyParent    = "_p"
    75  	KeyTimestamp = "_t"
    76  	KeyElapsed   = "_e"
    77  	KeyCaller    = "_c"
    78  	KeyMessage   = "_m"
    79  	KeyEventKind = "_k"
    80  	KeyLogLevel  = "_l"
    81  )
    82  
    83  // Event kinds.
    84  const (
    85  	EventSpanStart  EventKind = 's'
    86  	EventSpanFinish EventKind = 'f'
    87  	EventMetric     EventKind = 'm'
    88  )
    89  
    90  var DefaultLogger = New(NewConsoleWriter(os.Stderr, LdetFlags))
    91  
    92  func Root() Span { return Span{Logger: DefaultLogger} }
    93  
    94  func (l *Logger) Root() Span { return Span{Logger: l} }
    95  
    96  func New(w io.Writer) *Logger {
    97  	return &Logger{
    98  		Writer:  w,
    99  		NewID:   MathRandID,
   100  		now:     time.Now,
   101  		nano:    htime.UnixNano,
   102  		callers: caller1,
   103  	}
   104  }
   105  
   106  func (l *Logger) Copy() *Logger {
   107  	return l.CopyWriter(l.Writer)
   108  }
   109  
   110  func (l *Logger) CopyWriter(w io.Writer) *Logger {
   111  	return &Logger{
   112  		Writer:      w,
   113  		Encoder:     l.Encoder,
   114  		NewID:       l.NewID,
   115  		now:         l.now,
   116  		nano:        l.nano,
   117  		callers:     l.callers,
   118  		callersSkip: l.callersSkip,
   119  		filter:      l.getfilter(),
   120  	}
   121  }
   122  
   123  func (s Span) Copy() Span {
   124  	r := s
   125  	r.Logger = r.Logger.Copy()
   126  	return r
   127  }
   128  
   129  func (s Span) CopyWriter(w io.Writer) Span {
   130  	r := s
   131  	r.Logger = r.Logger.CopyWriter(w)
   132  	return r
   133  }
   134  
   135  func message(l *Logger, id ID, d int, msg interface{}, kvs []interface{}) {
   136  	if l == nil {
   137  		return
   138  	}
   139  
   140  	defer l.Unlock()
   141  	l.Lock()
   142  
   143  	l.b = l.Encoder.AppendMap(l.b[:0], -1)
   144  
   145  	if id != (ID{}) {
   146  		l.b = l.Encoder.AppendString(l.b, KeySpan)
   147  		l.b = id.TlogAppend(l.b)
   148  	}
   149  
   150  	if l.nano != nil {
   151  		now := l.nano()
   152  
   153  		l.b = l.Encoder.AppendString(l.b, KeyTimestamp)
   154  		l.b = l.Encoder.AppendTimestamp(l.b, now)
   155  	}
   156  
   157  	var c loc.PC
   158  
   159  	if d >= 0 && l.callers != nil && l.callers(2+d+l.callersSkip, (*loc.PC)(noescape(unsafe.Pointer(&c))), 1, 1) != 0 {
   160  		l.b = l.Encoder.AppendKey(l.b, KeyCaller)
   161  		l.b = l.Encoder.AppendCaller(l.b, c)
   162  	}
   163  
   164  	if msg != nil {
   165  		l.b = l.Encoder.AppendKey(l.b, KeyMessage)
   166  		l.b = l.Encoder.AppendSemantic(l.b, WireMessage)
   167  
   168  		switch msg := msg.(type) {
   169  		case string:
   170  			l.b = l.Encoder.AppendString(l.b, msg)
   171  		case []byte:
   172  			l.b = l.Encoder.AppendTagBytes(l.b, tlwire.String, msg)
   173  		case format:
   174  			l.b = l.Encoder.AppendFormat(l.b, msg.Fmt, msg.Args...)
   175  		default:
   176  			l.b = l.Encoder.AppendFormat(l.b, "%v", msg)
   177  		}
   178  	}
   179  
   180  	l.b = AppendKVs(l.b, kvs)
   181  
   182  	l.b = append(l.b, l.ls...)
   183  
   184  	l.b = l.Encoder.AppendBreak(l.b)
   185  
   186  	_, _ = l.Writer.Write(l.b)
   187  }
   188  
   189  func newspan(l *Logger, par ID, d int, n string, kvs []interface{}) (s Span) {
   190  	if l == nil {
   191  		return
   192  	}
   193  
   194  	s.Logger = l
   195  	s.ID = l.NewID()
   196  	if l.now != nil {
   197  		s.StartedAt = l.now()
   198  	}
   199  
   200  	defer l.Unlock()
   201  	l.Lock()
   202  
   203  	l.b = l.Encoder.AppendMap(l.b[:0], -1)
   204  
   205  	l.b = l.Encoder.AppendString(l.b, KeySpan)
   206  	l.b = s.ID.TlogAppend(l.b)
   207  
   208  	if l.now != nil {
   209  		l.b = l.Encoder.AppendString(l.b, KeyTimestamp)
   210  		l.b = l.Encoder.AppendTimestamp(l.b, s.StartedAt.UnixNano())
   211  	}
   212  
   213  	if d >= 0 {
   214  		var c loc.PC
   215  		caller1(2+d, &c, 1, 1)
   216  
   217  		l.b = e.AppendKey(l.b, KeyCaller)
   218  		l.b = e.AppendCaller(l.b, c)
   219  	}
   220  
   221  	l.b = l.Encoder.AppendString(l.b, KeyEventKind)
   222  	l.b = EventSpanStart.TlogAppend(l.b)
   223  
   224  	if par != (ID{}) {
   225  		l.b = l.Encoder.AppendString(l.b, KeyParent)
   226  		l.b = par.TlogAppend(l.b)
   227  	}
   228  
   229  	if n != "" {
   230  		l.b = l.Encoder.AppendString(l.b, KeyMessage)
   231  		l.b = l.Encoder.AppendSemantic(l.b, WireMessage)
   232  		l.b = l.Encoder.AppendString(l.b, n)
   233  	}
   234  
   235  	l.b = AppendKVs(l.b, kvs)
   236  
   237  	l.b = append(l.b, l.ls...)
   238  
   239  	l.b = l.Encoder.AppendBreak(l.b)
   240  
   241  	_, _ = l.Writer.Write(l.b)
   242  
   243  	return
   244  }
   245  
   246  func (s Span) Finish(kvs ...interface{}) {
   247  	if s.Logger == nil {
   248  		return
   249  	}
   250  
   251  	l := s.Logger
   252  
   253  	defer l.Unlock()
   254  	l.Lock()
   255  
   256  	l.b = l.Encoder.AppendTag(l.b[:0], tlwire.Map, -1)
   257  
   258  	if s.ID != (ID{}) {
   259  		l.b = l.Encoder.AppendString(l.b, KeySpan)
   260  		l.b = s.ID.TlogAppend(l.b)
   261  	}
   262  
   263  	var now time.Time
   264  	if l.now != nil {
   265  		now = l.now()
   266  
   267  		l.b = l.Encoder.AppendString(l.b, KeyTimestamp)
   268  		l.b = l.Encoder.AppendTimestamp(l.b, now.UnixNano())
   269  	}
   270  
   271  	l.b = l.Encoder.AppendString(l.b, KeyEventKind)
   272  	l.b = EventSpanFinish.TlogAppend(l.b)
   273  
   274  	if l.now != nil {
   275  		l.b = l.Encoder.AppendString(l.b, KeyElapsed)
   276  		l.b = l.Encoder.AppendDuration(l.b, now.Sub(s.StartedAt))
   277  	}
   278  
   279  	l.b = AppendKVs(l.b, kvs)
   280  
   281  	l.b = append(l.b, l.ls...)
   282  
   283  	l.b = l.Encoder.AppendBreak(l.b)
   284  
   285  	_, _ = l.Writer.Write(l.b)
   286  }
   287  
   288  func SetLabels(kvs ...interface{}) {
   289  	DefaultLogger.SetLabels(kvs...)
   290  }
   291  
   292  func (l *Logger) SetLabels(kvs ...interface{}) {
   293  	if l == nil {
   294  		return
   295  	}
   296  
   297  	defer l.Unlock()
   298  	l.Lock()
   299  
   300  	l.ls = AppendLabels(l.ls[:0], kvs)
   301  }
   302  
   303  func (l *Logger) Labels() RawMessage {
   304  	return l.ls
   305  }
   306  
   307  func Start(name string, kvs ...interface{}) Span {
   308  	return newspan(DefaultLogger, ID{}, 0, name, kvs)
   309  }
   310  
   311  func (l *Logger) Or(l2 *Logger) *Logger {
   312  	if l != nil {
   313  		return l
   314  	}
   315  
   316  	return l2
   317  }
   318  
   319  func (s Span) Or(s2 Span) Span {
   320  	if s.Logger != nil {
   321  		return s
   322  	}
   323  
   324  	return s2
   325  }
   326  
   327  func (l *Logger) Event(kvs ...interface{}) (err error) {
   328  	if l == nil {
   329  		return nil
   330  	}
   331  
   332  	defer l.Unlock()
   333  	l.Lock()
   334  
   335  	l.b = l.AppendMap(l.b[:0], -1)
   336  
   337  	l.b = AppendKVs(l.b, kvs)
   338  
   339  	l.b = append(l.b, l.ls...)
   340  
   341  	l.b = l.AppendBreak(l.b)
   342  
   343  	_, err = l.Writer.Write(l.b)
   344  
   345  	return
   346  }
   347  
   348  func (s Span) Event(kvs ...interface{}) (err error) {
   349  	if s.Logger == nil {
   350  		return nil
   351  	}
   352  
   353  	defer s.Unlock()
   354  	s.Lock()
   355  
   356  	s.b = s.AppendMap(s.b[:0], -1)
   357  
   358  	if s.ID != (ID{}) {
   359  		s.b = s.AppendString(s.b, KeySpan)
   360  		s.b = s.ID.TlogAppend(s.b)
   361  	}
   362  
   363  	s.b = AppendKVs(s.b, kvs)
   364  
   365  	s.b = append(s.b, s.ls...)
   366  
   367  	s.b = s.AppendBreak(s.b)
   368  
   369  	_, err = s.Writer.Write(s.b)
   370  
   371  	return
   372  }
   373  
   374  func (l *Logger) NewSpan(d int, par ID, name string, kvs ...interface{}) Span {
   375  	return newspan(l, par, d, name, kvs)
   376  }
   377  
   378  func (l *Logger) NewMessage(d int, id ID, msg interface{}, kvs ...interface{}) {
   379  	message(l, id, d, msg, kvs)
   380  }
   381  
   382  func (s Span) NewMessage(d int, msg interface{}, kvs ...interface{}) {
   383  	message(s.Logger, s.ID, d, msg, kvs)
   384  }
   385  
   386  func (l *Logger) Start(name string, kvs ...interface{}) Span {
   387  	return newspan(l, ID{}, 0, name, kvs)
   388  }
   389  
   390  func (s Span) Spawn(name string, kvs ...interface{}) Span {
   391  	return newspan(s.Logger, s.ID, 0, name, kvs)
   392  }
   393  
   394  func Printw(msg string, kvs ...interface{}) {
   395  	message(DefaultLogger, ID{}, 0, msg, kvs)
   396  }
   397  
   398  func (l *Logger) Printw(msg string, kvs ...interface{}) {
   399  	message(l, ID{}, 0, msg, kvs)
   400  }
   401  
   402  func (s Span) Printw(msg string, kvs ...interface{}) {
   403  	message(s.Logger, s.ID, 0, msg, kvs)
   404  }
   405  
   406  func Printf(fmt string, args ...interface{}) {
   407  	message(DefaultLogger, ID{}, 0, format{Fmt: fmt, Args: args}, nil)
   408  }
   409  
   410  func (l *Logger) Printf(fmt string, args ...interface{}) {
   411  	message(l, ID{}, 0, format{Fmt: fmt, Args: args}, nil)
   412  }
   413  
   414  func (s Span) Printf(fmt string, args ...interface{}) {
   415  	message(s.Logger, s.ID, 0, format{Fmt: fmt, Args: args}, nil)
   416  }
   417  
   418  func (l *Logger) IOWriter(d int) io.Writer {
   419  	return writeWrapper{
   420  		Span: Span{
   421  			Logger: l,
   422  		},
   423  		d: d,
   424  	}
   425  }
   426  
   427  func (s Span) IOWriter(d int) io.Writer {
   428  	return writeWrapper{
   429  		Span: s,
   430  		d:    d,
   431  	}
   432  }
   433  
   434  func (w writeWrapper) Write(p []byte) (int, error) {
   435  	message(w.Logger, w.ID, w.d, p, nil)
   436  
   437  	return len(p), nil
   438  }
   439  
   440  func (l *Logger) Write(p []byte) (int, error) {
   441  	if l == nil || l.Writer == nil {
   442  		return len(p), nil
   443  	}
   444  
   445  	defer l.Unlock()
   446  	l.Lock()
   447  
   448  	return l.Writer.Write(p)
   449  }
   450  
   451  func LoggerSetTimeNow(l *Logger, now func() time.Time, nano func() int64) {
   452  	l.now = now
   453  	l.nano = nano
   454  }
   455  
   456  func LoggerSetCallers(l *Logger, skip int, callers func(skip int, pc []uintptr) int) {
   457  	l.callers = *(*func(int, *loc.PC, int, int) int)(unsafe.Pointer(&callers))
   458  	l.callersSkip = skip + 1
   459  	/*
   460  		l.callers = func(skip int, pc *loc.PC, len, cap int) int {
   461  			return callers(skip+2, *(*[]uintptr)(unsafe.Pointer(&struct {
   462  				Ptr *loc.PC
   463  				Len int
   464  				Cap int
   465  			}{
   466  				Ptr: pc,
   467  				Len: len,
   468  				Cap: cap,
   469  			})))
   470  		}
   471  	*/
   472  }