...
1
16
17 package json
18
19 import (
20 "io"
21 "sync/atomic"
22 "time"
23
24 "github.com/go-logr/logr"
25 "github.com/go-logr/zapr"
26 "go.uber.org/zap"
27 "go.uber.org/zap/zapcore"
28
29 "k8s.io/component-base/featuregate"
30 logsapi "k8s.io/component-base/logs/api/v1"
31 )
32
33 var (
34
35 timeNow = time.Now
36 )
37
38 type runtime struct {
39 v uint32
40 }
41
42 func (r *runtime) ZapV() zapcore.Level {
43
44 return -zapcore.Level(atomic.LoadUint32(&r.v))
45 }
46
47
48 func (r *runtime) Enabled(level zapcore.Level) bool {
49 return level >= r.ZapV()
50 }
51
52 func (r *runtime) SetVerbosityLevel(v uint32) error {
53 atomic.StoreUint32(&r.v, v)
54 return nil
55 }
56
57 var _ zapcore.LevelEnabler = &runtime{}
58
59
60
61
62 func NewJSONLogger(v logsapi.VerbosityLevel, infoStream, errorStream zapcore.WriteSyncer, encoderConfig *zapcore.EncoderConfig) (logr.Logger, logsapi.RuntimeControl) {
63 r := &runtime{v: uint32(v)}
64
65 if encoderConfig == nil {
66 encoderConfig = &zapcore.EncoderConfig{
67 MessageKey: "msg",
68 CallerKey: "caller",
69 NameKey: "logger",
70 TimeKey: "ts",
71 EncodeTime: epochMillisTimeEncoder,
72 EncodeDuration: zapcore.StringDurationEncoder,
73 EncodeCaller: zapcore.ShortCallerEncoder,
74 }
75 }
76
77 encoder := zapcore.NewJSONEncoder(*encoderConfig)
78 var core zapcore.Core
79 if errorStream == nil {
80 core = zapcore.NewCore(encoder, infoStream, r)
81 } else {
82 highPriority := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
83 return lvl >= zapcore.ErrorLevel && r.Enabled(lvl)
84 })
85 lowPriority := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
86 return lvl < zapcore.ErrorLevel && r.Enabled(lvl)
87 })
88 core = zapcore.NewTee(
89 zapcore.NewCore(encoder, errorStream, highPriority),
90 zapcore.NewCore(encoder, infoStream, lowPriority),
91 )
92 }
93 l := zap.New(core, zap.WithCaller(true))
94 return zapr.NewLoggerWithOptions(l, zapr.LogInfoLevel("v"), zapr.ErrorKey("err")),
95 logsapi.RuntimeControl{
96 SetVerbosityLevel: r.SetVerbosityLevel,
97 Flush: func() {
98 _ = l.Sync()
99 },
100 }
101 }
102
103 func epochMillisTimeEncoder(_ time.Time, enc zapcore.PrimitiveArrayEncoder) {
104 nanos := timeNow().UnixNano()
105 millis := float64(nanos) / float64(time.Millisecond)
106 enc.AppendFloat64(millis)
107 }
108
109
110 type Factory struct{}
111
112 var _ logsapi.LogFormatFactory = Factory{}
113
114 func (f Factory) Feature() featuregate.Feature {
115 return logsapi.LoggingBetaOptions
116 }
117
118 func (f Factory) Create(c logsapi.LoggingConfiguration, o logsapi.LoggingOptions) (logr.Logger, logsapi.RuntimeControl) {
119
120
121
122
123
124
125
126
127 stderr := zapcore.Lock(AddNopSync(o.ErrorStream))
128 if c.Options.JSON.SplitStream {
129 stdout := zapcore.Lock(AddNopSync(o.InfoStream))
130 size := c.Options.JSON.InfoBufferSize.Value()
131 if size > 0 {
132
133 if size > 2*1024*1024*1024 {
134 size = 2 * 1024 * 1024 * 1024
135 }
136 stdout = &zapcore.BufferedWriteSyncer{
137 WS: stdout,
138 Size: int(size),
139 }
140 }
141
142 return NewJSONLogger(c.Verbosity, stdout, stderr, nil)
143 }
144
145 return NewJSONLogger(c.Verbosity, stderr, nil, nil)
146 }
147
148
149 func AddNopSync(writer io.Writer) zapcore.WriteSyncer {
150 return nopSync{Writer: writer}
151 }
152
153 type nopSync struct {
154 io.Writer
155 }
156
157 func (f nopSync) Sync() error {
158 return nil
159 }
160
View as plain text