Skip to content

Commit 8e6a266

Browse files
committed
fix json log verbose
remove vmodule support; add klog v test case;some refactor update follow review comment add enabled test case, and some nit fix enabled func fix as review comment
1 parent 6cedc08 commit 8e6a266

File tree

5 files changed

+120
-69
lines changed

5 files changed

+120
-69
lines changed

staging/src/k8s.io/component-base/logs/json/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ go_test(
2424
"//vendor/github.com/stretchr/testify/assert:go_default_library",
2525
"//vendor/go.uber.org/zap:go_default_library",
2626
"//vendor/go.uber.org/zap/zapcore:go_default_library",
27+
"//vendor/k8s.io/klog/v2:go_default_library",
2728
],
2829
)
2930

staging/src/k8s.io/component-base/logs/json/json.go

Lines changed: 23 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -40,35 +40,38 @@ type zapLogger struct {
4040
// NB: this looks very similar to zap.SugaredLogger, but
4141
// deals with our desire to have multiple verbosity levels.
4242
l *zap.Logger
43-
lvl zapcore.Level
43+
lvl int
4444
}
4545

4646
// implement logr.Logger
4747
var _ logr.Logger = &zapLogger{}
4848

49+
// Enabled should always return true
4950
func (l *zapLogger) Enabled() bool {
50-
return l.l.Core().Enabled(l.lvl)
51+
return true
5152
}
5253

5354
// Info write message to error level log
5455
func (l *zapLogger) Info(msg string, keysAndVals ...interface{}) {
55-
if checkedEntry := l.l.Check(l.lvl, msg); checkedEntry != nil {
56-
checkedEntry.Time = timeNow()
57-
checkedEntry.Write(l.handleFields(keysAndVals)...)
56+
entry := zapcore.Entry{
57+
Time: timeNow(),
58+
Message: msg,
5859
}
60+
checkedEntry := l.l.Core().Check(entry, nil)
61+
checkedEntry.Write(l.handleFields(keysAndVals)...)
5962
}
6063

6164
// dPanic write message to DPanicLevel level log
6265
// we need implement this because unit test case need stub time.Now
6366
// otherwise the ts field always changed
64-
func (l *zapLogger) dPanic(msg string, keysAndVals ...interface{}) {
67+
func (l *zapLogger) dPanic(msg string) {
6568
entry := zapcore.Entry{
6669
Level: zapcore.DPanicLevel,
6770
Time: timeNow(),
6871
Message: msg,
6972
}
7073
checkedEntry := l.l.Core().Check(entry, nil)
71-
checkedEntry.Write(l.handleFields(keysAndVals)...)
74+
checkedEntry.Write(zap.Int("v", l.lvl))
7275
}
7376

7477
// handleFields converts a bunch of arbitrary key-value pairs into Zap fields. It takes
@@ -78,18 +81,19 @@ func (l *zapLogger) handleFields(args []interface{}, additional ...zap.Field) []
7881
// a slightly modified version of zap.SugaredLogger.sweetenFields
7982
if len(args) == 0 {
8083
// fast-return if we have no suggared fields.
81-
return additional
84+
return append(additional, zap.Int("v", l.lvl))
8285
}
8386

8487
// unlike Zap, we can be pretty sure users aren't passing structured
8588
// fields (since logr has no concept of that), so guess that we need a
8689
// little less space.
87-
fields := make([]zap.Field, 0, len(args)/2+len(additional))
90+
fields := make([]zap.Field, 0, len(args)/2+len(additional)+1)
91+
fields = append(fields, zap.Int("v", l.lvl))
8892
for i := 0; i < len(args)-1; i += 2 {
8993
// check just in case for strongly-typed Zap fields, which is illegal (since
9094
// it breaks implementation agnosticism), so we can give a better error message.
9195
if _, ok := args[i].(zap.Field); ok {
92-
l.dPanic("strongly-typed Zap Field passed to logr", zap.Any("zap field", args[i]))
96+
l.dPanic("strongly-typed Zap Field passed to logr")
9397
break
9498
}
9599

@@ -98,8 +102,8 @@ func (l *zapLogger) handleFields(args []interface{}, additional ...zap.Field) []
98102
key, val := args[i], args[i+1]
99103
keyStr, isString := key.(string)
100104
if !isString {
101-
// if the key isn't a string, DPanic and stop logging
102-
l.dPanic("non-string key argument passed to logging, ignoring all later arguments", zap.Any("invalid key", key))
105+
// if the key isn't a string, stop logging
106+
l.dPanic("non-string key argument passed to logging, ignoring all later arguments")
103107
break
104108
}
105109

@@ -120,10 +124,10 @@ func (l *zapLogger) Error(err error, msg string, keysAndVals ...interface{}) {
120124
checkedEntry.Write(l.handleFields(keysAndVals, handleError(err))...)
121125
}
122126

123-
// V return info logr.Logger with specified level
127+
// V return info logr.Logger with specified level
124128
func (l *zapLogger) V(level int) logr.Logger {
125129
return &zapLogger{
126-
lvl: l.lvl - zapcore.Level(level),
130+
lvl: l.lvl + level,
127131
l: l.l,
128132
}
129133
}
@@ -140,19 +144,17 @@ func (l *zapLogger) WithName(name string) logr.Logger {
140144
return l
141145
}
142146

143-
// encoderConfig config zap json encoder key format, and encodetime format
147+
// encoderConfig config zap encodetime format
144148
var encoderConfig = zapcore.EncoderConfig{
145149
MessageKey: "msg",
146150

147-
LevelKey: "v",
148-
EncodeLevel: int8LevelEncoder,
149-
150151
TimeKey: "ts",
151152
EncodeTime: zapcore.EpochMillisTimeEncoder,
152153
}
153154

154155
// NewJSONLogger creates a new json logr.Logger using the given Zap Logger to log.
155-
func NewJSONLogger(l *zap.Logger, w zapcore.WriteSyncer) logr.Logger {
156+
func NewJSONLogger(w zapcore.WriteSyncer) logr.Logger {
157+
l, _ := zap.NewProduction()
156158
if w == nil {
157159
w = os.Stdout
158160
}
@@ -162,24 +164,14 @@ func NewJSONLogger(l *zap.Logger, w zapcore.WriteSyncer) logr.Logger {
162164
return zapcore.NewCore(zapcore.NewJSONEncoder(encoderConfig), zapcore.AddSync(w), zapcore.DebugLevel)
163165
}))
164166
return &zapLogger{
165-
l: log,
166-
lvl: zap.DebugLevel,
167-
}
168-
}
169-
170-
func int8LevelEncoder(l zapcore.Level, enc zapcore.PrimitiveArrayEncoder) {
171-
lvl := int8(l)
172-
if lvl < 0 {
173-
lvl = -lvl
167+
l: log,
174168
}
175-
enc.AppendInt8(lvl)
176169
}
177170

178171
func handleError(err error) zap.Field {
179172
return zap.NamedError("err", err)
180173
}
181174

182175
func init() {
183-
l, _ := zap.NewProduction()
184-
JSONLogger = NewJSONLogger(l, nil)
176+
JSONLogger = NewJSONLogger(nil)
185177
}

staging/src/k8s.io/component-base/logs/json/json_benchmark_test.go

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@ import (
2121
"fmt"
2222
"testing"
2323
"time"
24-
25-
"go.uber.org/zap"
2624
)
2725

2826
var record = struct {
@@ -61,7 +59,7 @@ var record = struct {
6159
func BenchmarkInfoLoggerInfo(b *testing.B) {
6260
b.RunParallel(func(pb *testing.PB) {
6361
for pb.Next() {
64-
jLogger := NewJSONLogger(zap.NewExample(), nil)
62+
jLogger := NewJSONLogger(nil)
6563
jLogger.Info("test",
6664
"str", "foo",
6765
"int64-1", int64(1),
@@ -98,7 +96,7 @@ func BenchmarkInfoLoggerInfoStandardJSON(b *testing.B) {
9896
func BenchmarkZapLoggerError(b *testing.B) {
9997
b.RunParallel(func(pb *testing.PB) {
10098
for pb.Next() {
101-
jLogger := NewJSONLogger(zap.NewExample(), nil)
99+
jLogger := NewJSONLogger(nil)
102100
jLogger.Error(fmt.Errorf("test for error:%s", "default"),
103101
"test",
104102
"str", "foo",
@@ -135,7 +133,7 @@ func BenchmarkZapLoggerErrorStandardJSON(b *testing.B) {
135133
func BenchmarkZapLoggerV(b *testing.B) {
136134
b.RunParallel(func(pb *testing.PB) {
137135
for pb.Next() {
138-
jLogger := NewJSONLogger(zap.NewExample(), nil)
136+
jLogger := NewJSONLogger(nil)
139137
jLogger.V(1).Info("test",
140138
"str", "foo",
141139
"int64-1", int64(1),

staging/src/k8s.io/component-base/logs/json/json_test.go

Lines changed: 91 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package logs
1919
import (
2020
"bufio"
2121
"bytes"
22+
"flag"
2223
"fmt"
2324
"testing"
2425
"time"
@@ -27,10 +28,12 @@ import (
2728

2829
"go.uber.org/zap"
2930
"go.uber.org/zap/zapcore"
31+
32+
"k8s.io/klog/v2"
3033
)
3134

32-
// TestInfoLoggerInfo test infologger json info format
33-
func TestInfoLoggerInfo(t *testing.T) {
35+
// TestZapLoggerInfo test ZapLogger json info format
36+
func TestZapLoggerInfo(t *testing.T) {
3437
timeNow = func() time.Time {
3538
return time.Date(1970, time.January, 1, 0, 0, 0, 123, time.UTC)
3639
}
@@ -41,30 +44,29 @@ func TestInfoLoggerInfo(t *testing.T) {
4144
}{
4245
{
4346
msg: "test",
44-
format: "{\"v\":1,\"ts\":%f,\"msg\":\"test\",\"ns\":\"default\",\"podnum\":2}\n",
47+
format: "{\"ts\":%f,\"msg\":\"test\",\"v\":0,\"ns\":\"default\",\"podnum\":2}\n",
4548
keysValues: []interface{}{"ns", "default", "podnum", 2},
4649
},
4750
{
4851
msg: "test for strongly typed Zap field",
49-
format: "{\"v\":3,\"ts\":%f,\"msg\":\"strongly-typed Zap Field passed to logr\"}\n{\"v\":1,\"ts\":0.000123,\"msg\":\"test for strongly typed Zap field\",\"ns\":\"default\",\"podnum\":2}\n",
52+
format: "{\"ts\":%f,\"msg\":\"strongly-typed Zap Field passed to logr\",\"v\":0}\n{\"ts\":0.000123,\"msg\":\"test for strongly typed Zap field\",\"v\":0,\"ns\":\"default\",\"podnum\":2}\n",
5053
keysValues: []interface{}{"ns", "default", "podnum", 2, zap.Int("attempt", 3), "attempt", "Running", 10},
5154
},
5255
{
5356
msg: "test for non-string key argument",
54-
format: "{\"v\":3,\"ts\":%f,\"msg\":\"non-string key argument passed to logging, ignoring all later arguments\"}\n{\"v\":1,\"ts\":0.000123,\"msg\":\"test for non-string key argument\",\"ns\":\"default\",\"podnum\":2}\n",
57+
format: "{\"ts\":%f,\"msg\":\"non-string key argument passed to logging, ignoring all later arguments\",\"v\":0}\n{\"ts\":0.000123,\"msg\":\"test for non-string key argument\",\"v\":0,\"ns\":\"default\",\"podnum\":2}\n",
5558
keysValues: []interface{}{"ns", "default", "podnum", 2, 200, "replica", "Running", 10},
5659
},
5760
}
5861

59-
for i, data := range testDataInfo {
62+
for _, data := range testDataInfo {
6063
var buffer bytes.Buffer
6164
writer := bufio.NewWriter(&buffer)
62-
var sampleInfoLogger = NewJSONLogger(zap.NewExample(), zapcore.AddSync(writer))
65+
var sampleInfoLogger = NewJSONLogger(zapcore.AddSync(writer))
6366
sampleInfoLogger.Info(data.msg, data.keysValues...)
6467
writer.Flush()
6568
logStr := buffer.String()
6669
var ts float64
67-
fmt.Println(i, logStr)
6870
n, err := fmt.Sscanf(logStr, data.format, &ts)
6971
if n != 1 || err != nil {
7072
t.Errorf("log format error: %d elements, error %s:\n%s", n, err, logStr)
@@ -76,49 +78,60 @@ func TestInfoLoggerInfo(t *testing.T) {
7678
}
7779
}
7880

79-
// TestInfoLoggerEnabled test jsonlogger should always enabled
80-
func TestInfoLoggerEnabled(t *testing.T) {
81-
var sampleInfoLogger = NewJSONLogger(zap.NewExample(), nil)
82-
if !sampleInfoLogger.Enabled() {
83-
t.Error("info logger should always enabled")
81+
// TestZapLoggerEnabled test ZapLogger enabled
82+
func TestZapLoggerEnabled(t *testing.T) {
83+
var sampleInfoLogger = NewJSONLogger(nil)
84+
for i := 0; i < 11; i++ {
85+
if !sampleInfoLogger.V(i).Enabled() {
86+
t.Errorf("V(%d).Info should be enabled", i)
87+
}
8488
}
8589
}
8690

87-
// TestInfoLoggerInfo test infologger V set log level func
91+
// TestZapLoggerV test ZapLogger V set log level func
8892
func TestZapLoggerV(t *testing.T) {
89-
var buffer bytes.Buffer
90-
writer := bufio.NewWriter(&buffer)
9193
timeNow = func() time.Time {
9294
return time.Date(1970, time.January, 1, 0, 0, 0, 123, time.UTC)
9395
}
94-
var sampleInfoLogger = NewJSONLogger(zap.NewExample(), zapcore.AddSync(writer))
95-
sampleInfoLogger.V(2).Info("test", "ns", "default", "podnum", 2)
96-
writer.Flush()
97-
logStr := buffer.String()
98-
var ts float64
99-
expectFormat := `{"v":1,"ts":%f,"msg":"test","ns":"default","podnum":2}`
100-
n, err := fmt.Sscanf(logStr, expectFormat, &ts)
101-
if n != 0 || err == nil {
102-
t.Errorf("log format error: %d elements, error %s:\n%s", n, err, logStr)
103-
}
104-
if !assert.Empty(t, logStr) {
105-
t.Errorf("Info log: %s should empty", logStr)
96+
97+
for i := 0; i < 11; i++ {
98+
var buffer bytes.Buffer
99+
writer := bufio.NewWriter(&buffer)
100+
var sampleInfoLogger = NewJSONLogger(zapcore.AddSync(writer))
101+
sampleInfoLogger.V(i).Info("test", "ns", "default", "podnum", 2)
102+
writer.Flush()
103+
logStr := buffer.String()
104+
var v int
105+
var expectFormat string
106+
expectFormat = "{\"ts\":0.000123,\"msg\":\"test\",\"v\":%d,\"ns\":\"default\",\"podnum\":2}\n"
107+
n, err := fmt.Sscanf(logStr, expectFormat, &v)
108+
if n != 1 || err != nil {
109+
t.Errorf("log format error: %d elements, error %s:\n%s", n, err, logStr)
110+
}
111+
if v != i {
112+
t.Errorf("V(%d).Info...) returned v=%d. expected v=%d", i, v, i)
113+
}
114+
expect := fmt.Sprintf(expectFormat, v)
115+
if !assert.Equal(t, logStr, expect) {
116+
t.Errorf("V(%d).Info has wrong format \n expect:%s\n got:%s", i, expect, logStr)
117+
}
118+
buffer.Reset()
106119
}
107120
}
108121

109-
// TestZapLoggerError test infologger json error format
122+
// TestZapLoggerError test ZapLogger json error format
110123
func TestZapLoggerError(t *testing.T) {
111124
var buffer bytes.Buffer
112125
writer := bufio.NewWriter(&buffer)
113126
timeNow = func() time.Time {
114127
return time.Date(1970, time.January, 1, 0, 0, 0, 123, time.UTC)
115128
}
116-
var sampleInfoLogger = NewJSONLogger(zap.NewExample(), zapcore.AddSync(writer))
129+
var sampleInfoLogger = NewJSONLogger(zapcore.AddSync(writer))
117130
sampleInfoLogger.Error(fmt.Errorf("ivailid namespace:%s", "default"), "wrong namespace", "ns", "default", "podnum", 2)
118131
writer.Flush()
119132
logStr := buffer.String()
120133
var ts float64
121-
expectFormat := `{"v":2,"ts":%f,"msg":"wrong namespace","ns":"default","podnum":2,"err":"ivailid namespace:default"}`
134+
expectFormat := `{"ts":%f,"msg":"wrong namespace","v":0,"ns":"default","podnum":2,"err":"ivailid namespace:default"}`
122135
n, err := fmt.Sscanf(logStr, expectFormat, &ts)
123136
if n != 1 || err != nil {
124137
t.Errorf("log format error: %d elements, error %s:\n%s", n, err, logStr)
@@ -128,3 +141,50 @@ func TestZapLoggerError(t *testing.T) {
128141
t.Errorf("Info has wrong format \n expect:%s\n got:%s", expect, logStr)
129142
}
130143
}
144+
145+
// TestKlogV test klog -v(--verbose) func available with json logger
146+
func TestKlogV(t *testing.T) {
147+
var buffer testBuff
148+
logger := NewJSONLogger(&buffer)
149+
klog.SetLogger(logger)
150+
defer klog.SetLogger(nil)
151+
fs := flag.FlagSet{}
152+
klog.InitFlags(&fs)
153+
totalLogsWritten := 0
154+
155+
defer fs.Set("v", "0")
156+
157+
for i := 0; i < 11; i++ {
158+
err := fs.Set("v", fmt.Sprintf("%d", i))
159+
if err != nil {
160+
t.Fatalf("Failed to set verbosity")
161+
}
162+
for j := 0; j < 11; j++ {
163+
klog.V(klog.Level(j)).Info("test")
164+
logWritten := buffer.writeCount > 0
165+
totalLogsWritten += buffer.writeCount
166+
buffer.writeCount = 0
167+
if logWritten == (i < j) {
168+
t.Errorf("klog.V(%d).Info(...) wrote log when -v=%d", j, i)
169+
}
170+
}
171+
}
172+
if totalLogsWritten != 66 {
173+
t.Fatalf("Unexpected number of logs written, got %d, expected 66", totalLogsWritten)
174+
}
175+
}
176+
177+
type testBuff struct {
178+
writeCount int
179+
}
180+
181+
// Sync syncs data to file
182+
func (b *testBuff) Sync() error {
183+
return nil
184+
}
185+
186+
// Write writes data to buffer
187+
func (b *testBuff) Write(p []byte) (int, error) {
188+
b.writeCount++
189+
return len(p), nil
190+
}

staging/src/k8s.io/component-base/logs/options.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ const (
3434

3535
// List of logs (k8s.io/klog + k8s.io/component-base/logs) flags supported by all logging formats
3636
var supportedLogsFlags = map[string]struct{}{
37-
"v": {},
38-
"vmodule": {},
37+
"v": {},
38+
// TODO: support vmodule after 1.19 Alpha
3939
}
4040

4141
// Options has klog format parameters

0 commit comments

Comments
 (0)