-
Notifications
You must be signed in to change notification settings - Fork 66
/
global.go
71 lines (62 loc) · 2.28 KB
/
global.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
// Copyright 2020-2024 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package plog
import (
"context"
"fmt"
"net/url"
"sync"
"github.com/go-logr/logr"
"go.uber.org/zap"
"k8s.io/component-base/logs"
"k8s.io/klog/v2"
)
//nolint:gochecknoglobals
var (
// note that these globals have no locks on purpose - they are expected to be set at init and then again after config parsing.
globalLevel zap.AtomicLevel
globalLogger logr.Logger
globalFlush func()
// used as a temporary storage for a buffer per call of newLogr. see the init function below for more details.
sinkMap sync.Map
)
//nolint:gochecknoinits
func init() {
// make sure we always have a functional global logger
globalLevel = zap.NewAtomicLevelAt(0) // log at the 0 verbosity level to start with, i.e. the "always" logs
// use json encoding to start with
// the context here is just used for test injection and thus can be ignored
log, flush, err := newLogr(context.Background(), "json", 0)
if err != nil {
panic(err) // default logging config must always work
}
setGlobalLoggers(log, flush)
// this is a little crazy but zap's builder code does not allow us to directly specify what
// writer we want to use as our log sink. to get around this limitation in tests, we use a
// global map to temporarily hold the writer (the key is a random string that is generated
// per invocation of newLogr). we register a fake "pinniped" scheme so that we can lookup
// the writer via pinniped:///<per newLogr invocation random string>.
if err := zap.RegisterSink("pinniped", func(u *url.URL) (zap.Sink, error) {
value, ok := sinkMap.Load(u.Path)
if !ok {
return nil, fmt.Errorf("key %q not in global sink", u.Path)
}
return value.(zap.Sink), nil
}); err != nil {
panic(err) // custom sink must always work
}
}
func Setup() func() {
logs.InitLogs()
return func() {
logs.FlushLogs()
globalFlush()
}
}
// setGlobalLoggers sets the plog and klog global loggers. it is *not* go routine safe.
func setGlobalLoggers(log logr.Logger, flush func()) {
// a contextual logger does its own level based enablement checks, which is true for all of our loggers
klog.SetLoggerWithOptions(log, klog.ContextualLogger(true), klog.FlushLogger(flush))
globalLogger = log
globalFlush = flush
}