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 }