File tree Expand file tree Collapse file tree 2 files changed +47
-0
lines changed Expand file tree Collapse file tree 2 files changed +47
-0
lines changed Original file line number Diff line number Diff line change @@ -72,8 +72,10 @@ func (p *loggerPromise) Fulfill(parentLogger logr.Logger) {
72
72
logger = logger .WithValues (p .tags ... )
73
73
}
74
74
75
+ p .logger .lock .Lock ()
75
76
p .logger .Logger = logger
76
77
p .logger .promise = nil
78
+ p .logger .lock .Unlock ()
77
79
78
80
for _ , childPromise := range p .childPromises {
79
81
childPromise .Fulfill (logger )
@@ -86,12 +88,16 @@ func (p *loggerPromise) Fulfill(parentLogger logr.Logger) {
86
88
// logger. It expects to have *some* logr.Logger set at all times (generally
87
89
// a no-op logger before the promises are fulfilled).
88
90
type DelegatingLogger struct {
91
+ lock sync.Mutex
89
92
logr.Logger
90
93
promise * loggerPromise
91
94
}
92
95
93
96
// WithName provides a new Logger with the name appended
94
97
func (l * DelegatingLogger ) WithName (name string ) logr.Logger {
98
+ l .lock .Lock ()
99
+ defer l .lock .Unlock ()
100
+
95
101
if l .promise == nil {
96
102
return l .Logger .WithName (name )
97
103
}
@@ -105,6 +111,9 @@ func (l *DelegatingLogger) WithName(name string) logr.Logger {
105
111
106
112
// WithValues provides a new Logger with the tags appended
107
113
func (l * DelegatingLogger ) WithValues (tags ... interface {}) logr.Logger {
114
+ l .lock .Lock ()
115
+ defer l .lock .Unlock ()
116
+
108
117
if l .promise == nil {
109
118
return l .Logger .WithValues (tags ... )
110
119
}
Original file line number Diff line number Diff line change @@ -162,6 +162,44 @@ var _ = Describe("logging", func() {
162
162
))
163
163
})
164
164
165
+ // This test in itself will always succeed, a failure will be indicated by the
166
+ // race detector going off
167
+ It ("should be threadsafe" , func () {
168
+ fulfillDone := make (chan struct {})
169
+ withNameDone := make (chan struct {})
170
+ withValuesDone := make (chan struct {})
171
+ grandChildDone := make (chan struct {})
172
+
173
+ // Constructing the child in the goroutine does not reliably
174
+ // trigger the race detector
175
+ child := delegLog .WithName ("child" )
176
+ go func () {
177
+ defer GinkgoRecover ()
178
+ delegLog .Fulfill (NullLogger {})
179
+ close (fulfillDone )
180
+ }()
181
+ go func () {
182
+ defer GinkgoRecover ()
183
+ delegLog .WithName ("with-name" )
184
+ close (withNameDone )
185
+ }()
186
+ go func () {
187
+ defer GinkgoRecover ()
188
+ delegLog .WithValues ("with-value" )
189
+ close (withValuesDone )
190
+ }()
191
+ go func () {
192
+ defer GinkgoRecover ()
193
+ child .WithValues ("grandchild" )
194
+ close (grandChildDone )
195
+ }()
196
+
197
+ <- fulfillDone
198
+ <- withNameDone
199
+ <- withValuesDone
200
+ <- grandChildDone
201
+ })
202
+
165
203
It ("should delegate with tags" , func () {
166
204
By ("asking for a logger with a name before fulfill, and logging" )
167
205
befFulfill1 := delegLog .WithValues ("tag1" , "val1" )
You can’t perform that action at this time.
0 commit comments