-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfields.go
More file actions
95 lines (82 loc) · 1.81 KB
/
fields.go
File metadata and controls
95 lines (82 loc) · 1.81 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
84
85
86
87
88
89
90
91
92
93
94
95
package blip
import (
"context"
"sync"
)
// Field is a key-value pair that is used to add structured data to log entries.
type Field struct {
Key string
Value any
}
// F is a convenient alias for a map of fields.
type F map[string]any
// makeFields creates a slice of fields from the given context and field sets.
// Explicitly logged fields take precedence over context fields. Last field set
// wins if there are duplicates.
func makeFields(ctx context.Context, ff []F) *[]Field {
cf := FieldsFromContext(ctx)
n := len(cf)
for _, f := range ff {
n += len(f)
}
if n == 0 {
return nil
}
fields := getFields()
for k, v := range cf {
addField(fields, k, v)
}
for _, f := range ff {
for k, v := range f {
addField(fields, k, v)
}
}
return fields
}
func addField(f *[]Field, key string, val any) {
// Update existing entry if exists
for i := range *f {
if (*f)[i].Key == key {
(*f)[i].Value = val
return
}
}
// Add new entry
(*f) = append(*f, Field{key, val})
}
func sortFields(f []Field) {
if len(f) > 1 {
insertionSort(f)
}
}
// insertionSort is great for small slices. Using this custom function instead
// of sort.Slice() reduces the number of allocations to zero.
func insertionSort(f []Field) {
for i := 1; i < len(f); i++ {
for j := i; j > 0 && f[j].Key < f[j-1].Key; j-- {
f[j], f[j-1] = f[j-1], f[j]
}
}
}
//
// Fields pool
//
// Fields are pooled to reduce allocations.
// Preallocated slices of 20 fields should be enough for most cases, in worst
// case the slice will grow.
var fieldsPool = sync.Pool{
New: func() any {
fields := make([]Field, 0, 20)
return &fields
},
}
func getFields() *[]Field {
return fieldsPool.Get().(*[]Field)
}
func putFields(fields *[]Field) {
if fields == nil {
return
}
*fields = (*fields)[:0] // Reset
fieldsPool.Put(fields)
}