Repository navigation
Expand file tree
/
Copy pathlogger.go
More file actions
83 lines (74 loc) · 2.13 KB
/
Copy pathlogger.go
File metadata and controls
83 lines (74 loc) · 2.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
package log
import "sync"
// scratchPool provides encode buffers (stack buffers would escape to the
// heap via the encode helpers). Producers hand the buffer over with the
// record; the consumer returns it here after writing.
var scratchPool = sync.Pool{New: func() any { b := make([]byte, 0, 512); return &b }}
// Logger is the native front-end: no time.Now, no runtime.Callers, no
// formatting — it stamps RDTSC, packs the record into a pooled buffer and
// enqueues it. Safe for concurrent use by any goroutine.
type Logger struct {
core *Core
q *mailbox // cached from Core so the hot path never touches Core
min Level
}
func (l *Logger) Debug(msg string, fields ...Field) {
if LevelDebug >= l.min {
l.enqueue(LevelDebug, msg, fields)
}
}
func (l *Logger) Info(msg string, fields ...Field) {
if LevelInfo >= l.min {
l.enqueue(LevelInfo, msg, fields)
}
}
func (l *Logger) Warn(msg string, fields ...Field) {
if LevelWarn >= l.min {
l.enqueue(LevelWarn, msg, fields)
}
}
func (l *Logger) Error(msg string, fields ...Field) {
if LevelError >= l.min {
l.enqueue(LevelError, msg, fields)
}
}
func (l *Logger) Log(level Level, msg string, fields ...Field) {
if level >= l.min {
l.enqueue(level, msg, fields)
}
}
func (l *Logger) enqueue(level Level, msg string, fields []Field) {
sp := scratchPool.Get().(*[]byte)
b := (*sp)[:0]
b = append(b, 0, 0, 0, 0) // size, patched below
b = append(b, recTypeNative, 0)
b = le.AppendUint16(b, uint16(int16(level)))
b = le.AppendUint64(b, now())
b = le.AppendUint32(b, 0) // hidx unused
m := truncStr(msg, maxStrLen)
b = le.AppendUint16(b, uint16(len(m)))
b = append(b, m...)
nf := len(fields)
if nf > maxFieldsPerRecord {
nf = maxFieldsPerRecord
}
nfPos := len(b)
b = le.AppendUint16(b, uint16(nf))
cnt := 0
for i := 0; i < nf; i++ {
m := len(b)
b = appendFieldWire(b, &fields[i])
if len(b) > maxNativeRecordLen { // cap: groups can nest past any per-value limit
b = b[:m]
break
}
cnt++
}
le.PutUint16(b[nfPos:], uint16(cnt))
for len(b)&3 != 0 {
b = append(b, 0)
}
le.PutUint32(b, uint32(len(b)))
*sp = b
l.q.push(sp) // ownership moves; the consumer pools sp
}