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