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