/
private_field.go
144 lines (111 loc) · 2.56 KB
/
private_field.go
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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
package logutil
import (
crand "crypto/rand"
"crypto/sha256"
"encoding/hex"
"fmt"
"sync"
"go.uber.org/zap"
)
var (
global *PrivateField
mu sync.RWMutex
)
type PrivateField struct {
Namespace []byte
Enabled bool
}
func (p *PrivateField) hash(value string) string {
hash := sha256.New()
if _, err := hash.Write(p.Namespace); err != nil {
return "unrepresentable"
}
if _, err := hash.Write([]byte(value)); err != nil {
return "unrepresentable"
}
hashed := hash.Sum(nil)
return hex.EncodeToString(hashed)
}
func (p *PrivateField) PrivateString(key string, value string) zap.Field {
if p.Enabled {
return zap.String(key, p.hash(value))
}
return zap.String(key, value)
}
func (p *PrivateField) PrivateStringer(key string, value fmt.Stringer) zap.Field {
if p.Enabled {
return zap.String(key, p.hash(value.String()))
}
return zap.Stringer(key, value)
}
func (p *PrivateField) PrivateStrings(key string, values []string) zap.Field {
if p.Enabled {
strings := make([]string, len(values))
for i := range values {
strings[i] = p.hash(values[i])
}
return zap.Strings(key, strings)
}
return zap.Strings(key, values)
}
func (p *PrivateField) PrivateAny(key string, value interface{}) zap.Field {
if p.Enabled {
return zap.String(key, p.hash(fmt.Sprintf("%+v", value)))
}
return zap.Any(key, value)
}
func (p *PrivateField) PrivateBinary(key string, value []byte) zap.Field {
if p.Enabled {
return zap.String(key, p.hash(hex.EncodeToString(value)))
}
return zap.Binary(key, value)
}
func PrivateStrings(key string, value []string) zap.Field {
mu.RLock()
g := global
mu.RUnlock()
return g.PrivateStrings(key, value)
}
func PrivateString(key string, value string) zap.Field {
mu.RLock()
g := global
mu.RUnlock()
return g.PrivateString(key, value)
}
func PrivateStringer(key string, value fmt.Stringer) zap.Field {
mu.RLock()
g := global
mu.RUnlock()
return g.PrivateStringer(key, value)
}
func PrivateAny(key string, value interface{}) zap.Field {
mu.RLock()
g := global
mu.RUnlock()
return g.PrivateAny(key, value)
}
func PrivateBinary(key string, value []byte) zap.Field {
mu.RLock()
g := global
mu.RUnlock()
return g.PrivateBinary(key, value)
}
func SetGlobal(namespace []byte, enabled bool) {
mu.Lock()
global = &PrivateField{
Enabled: enabled,
Namespace: namespace,
}
mu.Unlock()
}
func DisablePrivateFields() {
SetGlobal(nil, false)
}
func init() { // nolint:gochecknoinits
namespace := make([]byte, 32)
_, err := crand.Reader.Read(namespace)
if err != nil {
panic(err)
}
SetGlobal(namespace, true)
}