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 }