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 }