Merge pull request #91608 from yuzhiquan/feature-implement-json-logformat

Feature implement json logformat
This commit is contained in:
Kubernetes Prow Robot 2020-06-15 23:26:03 -07:00 committed by GitHub
commit fd61c3149c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 582 additions and 2 deletions

View File

@ -31,7 +31,6 @@ require (
github.com/stretchr/testify v1.4.0
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 // indirect
go.etcd.io/etcd v0.5.0-alpha.5.0.20200520232829-54ba9589114f
go.uber.org/atomic v1.4.0 // indirect
go.uber.org/zap v1.10.0
golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e

View File

@ -200,6 +200,9 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=

View File

@ -17,6 +17,9 @@ require (
github.com/prometheus/procfs v0.0.11
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.4.0
go.uber.org/atomic v1.4.0 // indirect
go.uber.org/multierr v1.1.0 // indirect
go.uber.org/zap v1.10.0
k8s.io/apimachinery v0.0.0
k8s.io/client-go v0.0.0
k8s.io/klog/v2 v2.1.0

View File

@ -207,6 +207,12 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=

View File

@ -16,6 +16,7 @@ go_library(
importpath = "k8s.io/component-base/logs",
deps = [
"//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",
"//staging/src/k8s.io/component-base/logs/json:go_default_library",
"//vendor/github.com/go-logr/logr:go_default_library",
"//vendor/github.com/spf13/pflag:go_default_library",
"//vendor/k8s.io/klog/v2:go_default_library",
@ -33,6 +34,7 @@ filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//staging/src/k8s.io/component-base/logs/json:all-srcs",
"//staging/src/k8s.io/component-base/logs/logreduction:all-srcs",
],
tags = ["automanaged"],

View File

@ -0,0 +1,42 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = ["json.go"],
importmap = "k8s.io/kubernetes/vendor/k8s.io/component-base/logs/json",
importpath = "k8s.io/component-base/logs/json",
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/go-logr/logr:go_default_library",
"//vendor/go.uber.org/zap:go_default_library",
"//vendor/go.uber.org/zap/zapcore:go_default_library",
],
)
go_test(
name = "go_default_test",
srcs = [
"json_benchmark_test.go",
"json_test.go",
],
embed = [":go_default_library"],
deps = [
"//vendor/github.com/stretchr/testify/assert:go_default_library",
"//vendor/go.uber.org/zap:go_default_library",
"//vendor/go.uber.org/zap/zapcore:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -0,0 +1,212 @@
/*
Copyright 2020 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package logs
import (
"os"
"time"
"github.com/go-logr/logr"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
// Inspired from https://github.com/go-logr/zapr, some functions is copy from the repo.
var (
// JSONLogger is global json log format logr
JSONLogger logr.Logger
// timeNow stubbed out for testing
timeNow = time.Now
)
type noopInfoLogger struct{}
// Enabled func in noopInfoLogger always return false
func (l *noopInfoLogger) Enabled() bool {
return false
}
func (l *noopInfoLogger) Info(_ string, _ ...interface{}) {}
var disabledInfoLogger = &noopInfoLogger{}
type infoLogger struct {
lvl zapcore.Level
l *zap.Logger
}
// implement logr.InfoLogger
var _ logr.InfoLogger = &infoLogger{}
// Enabled always return true
func (l *infoLogger) Enabled() bool {
return true
}
// Info write message to error level log
func (l *infoLogger) Info(msg string, keysAndVals ...interface{}) {
if checkedEntry := l.l.Check(l.lvl, msg); checkedEntry != nil {
checkedEntry.Time = timeNow()
checkedEntry.Write(l.handleFields(keysAndVals)...)
}
}
// dPanic write message to DPanicLevel level log
// we need implement this because unit test case need stub time.Now
// otherwise the ts field always changed
func (l *infoLogger) dPanic(msg string, keysAndVals ...interface{}) {
entry := zapcore.Entry{
Level: zapcore.DPanicLevel,
Time: timeNow(),
Message: msg,
}
checkedEntry := l.l.Core().Check(entry, nil)
checkedEntry.Write(l.handleFields(keysAndVals)...)
}
// handleFields converts a bunch of arbitrary key-value pairs into Zap fields. It takes
// additional pre-converted Zap fields, for use with automatically attached fields, like
// `error`.
func (l *infoLogger) handleFields(args []interface{}, additional ...zap.Field) []zap.Field {
// a slightly modified version of zap.SugaredLogger.sweetenFields
if len(args) == 0 {
// fast-return if we have no suggared fields.
return additional
}
// unlike Zap, we can be pretty sure users aren't passing structured
// fields (since logr has no concept of that), so guess that we need a
// little less space.
fields := make([]zap.Field, 0, len(args)/2+len(additional))
for i := 0; i < len(args)-1; i += 2 {
// check just in case for strongly-typed Zap fields, which is illegal (since
// it breaks implementation agnosticism), so we can give a better error message.
if _, ok := args[i].(zap.Field); ok {
l.dPanic("strongly-typed Zap Field passed to logr", zap.Any("zap field", args[i]))
break
}
// process a key-value pair,
// ensuring that the key is a string
key, val := args[i], args[i+1]
keyStr, isString := key.(string)
if !isString {
// if the key isn't a string, DPanic and stop logging
l.dPanic("non-string key argument passed to logging, ignoring all later arguments", zap.Any("invalid key", key))
break
}
fields = append(fields, zap.Any(keyStr, val))
}
return append(fields, additional...)
}
// zapLogger is a logr.Logger that uses Zap to record log.
type zapLogger struct {
// NB: this looks very similar to zap.SugaredLogger, but
// deals with our desire to have multiple verbosity levels.
l *zap.Logger
infoLogger
}
// implement logr.Logger
var _ logr.Logger = &zapLogger{}
// Error write log message to error level
func (l *zapLogger) Error(err error, msg string, keysAndVals ...interface{}) {
entry := zapcore.Entry{
Level: zapcore.ErrorLevel,
Time: timeNow(),
Message: msg,
}
checkedEntry := l.l.Core().Check(entry, nil)
checkedEntry.Write(l.handleFields(keysAndVals, handleError(err))...)
}
// V return info logr.Logger with specified level
func (l *zapLogger) V(level int) logr.InfoLogger {
lvl := zapcore.Level(-1 * level)
if l.l.Core().Enabled(lvl) {
return &infoLogger{
l: l.l,
lvl: lvl,
}
}
return disabledInfoLogger
}
// WithValues return logr.Logger with some keys And Values
func (l *zapLogger) WithValues(keysAndValues ...interface{}) logr.Logger {
l.l = l.l.With(l.handleFields(keysAndValues)...)
return l
}
// WithName return logger Named with specified name
func (l *zapLogger) WithName(name string) logr.Logger {
l.l = l.l.Named(name)
return l
}
// encoderConfig config zap json encoder key format, and encodetime format
var encoderConfig = zapcore.EncoderConfig{
MessageKey: "msg",
LevelKey: "v",
EncodeLevel: int8LevelEncoder,
TimeKey: "ts",
EncodeTime: zapcore.EpochMillisTimeEncoder,
}
// NewJSONLogger creates a new json logr.Logger using the given Zap Logger to log.
func NewJSONLogger(l *zap.Logger, w zapcore.WriteSyncer) logr.Logger {
if w == nil {
w = os.Stdout
}
log := l.WithOptions(zap.AddCallerSkip(1),
zap.WrapCore(
func(zapcore.Core) zapcore.Core {
return zapcore.NewCore(zapcore.NewJSONEncoder(encoderConfig), zapcore.AddSync(w), zapcore.DebugLevel)
}))
return &zapLogger{
l: log,
infoLogger: infoLogger{
l: log,
lvl: zap.DebugLevel,
},
}
}
func int8LevelEncoder(l zapcore.Level, enc zapcore.PrimitiveArrayEncoder) {
lvl := int8(l)
if lvl < 0 {
lvl = -lvl
}
enc.AppendInt8(lvl)
}
func handleError(err error) zap.Field {
return zap.NamedError("err", err)
}
func init() {
l, _ := zap.NewProduction()
JSONLogger = NewJSONLogger(l, nil)
}

View File

@ -0,0 +1,161 @@
/*
Copyright 2020 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package logs
import (
"encoding/json"
"fmt"
"testing"
"time"
"go.uber.org/zap"
)
var record = struct {
Error error `json:"err"`
Level int `json:"v"`
Message string `json:"msg"`
Time time.Time `json:"ts"`
Fields map[string]interface{} `json:"fields"`
}{
Error: fmt.Errorf("test for error:%s", "default"),
Level: 2,
Message: "test",
Time: time.Unix(0, 123),
Fields: map[string]interface{}{
"str": "foo",
"int64-1": int64(1),
"int64-2": int64(1),
"float64": float64(1.0),
"string1": "\n",
"string2": "💩",
"string3": "🤔",
"string4": "🙊",
"bool": true,
"request": struct {
Method string `json:"method"`
Timeout int `json:"timeout"`
secret string `json:"secret"`
}{
Method: "GET",
Timeout: 10,
secret: "pony",
},
},
}
func BenchmarkInfoLoggerInfo(b *testing.B) {
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
jLogger := NewJSONLogger(zap.NewExample(), nil)
jLogger.Info("test",
"str", "foo",
"int64-1", int64(1),
"int64-2", int64(1),
"float64", float64(1.0),
"string1", "\n",
"string2", "💩",
"string3", "🤔",
"string4", "🙊",
"bool", true,
"request", struct {
Method string `json:"method"`
Timeout int `json:"timeout"`
secret string `json:"secret"`
}{
Method: "GET",
Timeout: 10,
secret: "pony",
},
)
}
})
}
func BenchmarkInfoLoggerInfoStandardJSON(b *testing.B) {
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
json.Marshal(record)
}
})
}
func BenchmarkZapLoggerError(b *testing.B) {
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
jLogger := NewJSONLogger(zap.NewExample(), nil)
jLogger.Error(fmt.Errorf("test for error:%s", "default"),
"test",
"str", "foo",
"int64-1", int64(1),
"int64-2", int64(1),
"float64", float64(1.0),
"string1", "\n",
"string2", "💩",
"string3", "🤔",
"string4", "🙊",
"bool", true,
"request", struct {
Method string `json:"method"`
Timeout int `json:"timeout"`
secret string `json:"secret"`
}{
Method: "GET",
Timeout: 10,
secret: "pony",
},
)
}
})
}
func BenchmarkZapLoggerErrorStandardJSON(b *testing.B) {
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
json.Marshal(record)
}
})
}
func BenchmarkZapLoggerV(b *testing.B) {
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
jLogger := NewJSONLogger(zap.NewExample(), nil)
jLogger.V(1).Info("test",
"str", "foo",
"int64-1", int64(1),
"int64-2", int64(1),
"float64", float64(1.0),
"string1", "\n",
"string2", "💩",
"string3", "🤔",
"string4", "🙊",
"bool", true,
"request", struct {
Method string `json:"method"`
Timeout int `json:"timeout"`
secret string `json:"secret"`
}{
Method: "GET",
Timeout: 10,
secret: "pony",
},
)
}
})
}

View File

@ -0,0 +1,130 @@
/*
Copyright 2020 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package logs
import (
"bufio"
"bytes"
"fmt"
"testing"
"time"
"github.com/stretchr/testify/assert"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
// TestInfoLoggerInfo test infologger json info format
func TestInfoLoggerInfo(t *testing.T) {
timeNow = func() time.Time {
return time.Date(1970, time.January, 1, 0, 0, 0, 123, time.UTC)
}
var testDataInfo = []struct {
msg string
format string
keysValues []interface{}
}{
{
msg: "test",
format: "{\"v\":1,\"ts\":%f,\"msg\":\"test\",\"ns\":\"default\",\"podnum\":2}\n",
keysValues: []interface{}{"ns", "default", "podnum", 2},
},
{
msg: "test for strongly typed Zap field",
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",
keysValues: []interface{}{"ns", "default", "podnum", 2, zap.Int("attempt", 3), "attempt", "Running", 10},
},
{
msg: "test for non-string key argument",
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",
keysValues: []interface{}{"ns", "default", "podnum", 2, 200, "replica", "Running", 10},
},
}
for i, data := range testDataInfo {
var buffer bytes.Buffer
writer := bufio.NewWriter(&buffer)
var sampleInfoLogger = NewJSONLogger(zap.NewExample(), zapcore.AddSync(writer))
sampleInfoLogger.Info(data.msg, data.keysValues...)
writer.Flush()
logStr := buffer.String()
var ts float64
fmt.Println(i, logStr)
n, err := fmt.Sscanf(logStr, data.format, &ts)
if n != 1 || err != nil {
t.Errorf("log format error: %d elements, error %s:\n%s", n, err, logStr)
}
expect := fmt.Sprintf(data.format, ts)
if !assert.Equal(t, expect, logStr) {
t.Errorf("Info has wrong format \n expect:%s\n got:%s", expect, logStr)
}
}
}
// TestInfoLoggerEnabled test jsonlogger should always enabled
func TestInfoLoggerEnabled(t *testing.T) {
var sampleInfoLogger = NewJSONLogger(zap.NewExample(), nil)
if !sampleInfoLogger.Enabled() {
t.Error("info logger should always enabled")
}
}
// TestInfoLoggerInfo test infologger V set log level func
func TestZapLoggerV(t *testing.T) {
var buffer bytes.Buffer
writer := bufio.NewWriter(&buffer)
timeNow = func() time.Time {
return time.Date(1970, time.January, 1, 0, 0, 0, 123, time.UTC)
}
var sampleInfoLogger = NewJSONLogger(zap.NewExample(), zapcore.AddSync(writer))
sampleInfoLogger.V(2).Info("test", "ns", "default", "podnum", 2)
writer.Flush()
logStr := buffer.String()
var ts float64
expectFormat := `{"v":1,"ts":%f,"msg":"test","ns":"default","podnum":2}`
n, err := fmt.Sscanf(logStr, expectFormat, &ts)
if n != 0 || err == nil {
t.Errorf("log format error: %d elements, error %s:\n%s", n, err, logStr)
}
if !assert.Empty(t, logStr) {
t.Errorf("Info log: %s should empty", logStr)
}
}
// TestZapLoggerError test infologger json error format
func TestZapLoggerError(t *testing.T) {
var buffer bytes.Buffer
writer := bufio.NewWriter(&buffer)
timeNow = func() time.Time {
return time.Date(1970, time.January, 1, 0, 0, 0, 123, time.UTC)
}
var sampleInfoLogger = NewJSONLogger(zap.NewExample(), zapcore.AddSync(writer))
sampleInfoLogger.Error(fmt.Errorf("ivailid namespace:%s", "default"), "wrong namespace", "ns", "default", "podnum", 2)
writer.Flush()
logStr := buffer.String()
var ts float64
expectFormat := `{"v":2,"ts":%f,"msg":"wrong namespace","ns":"default","podnum":2,"err":"ivailid namespace:default"}`
n, err := fmt.Sscanf(logStr, expectFormat, &ts)
if n != 1 || err != nil {
t.Errorf("log format error: %d elements, error %s:\n%s", n, err, logStr)
}
expect := fmt.Sprintf(expectFormat, ts)
if !assert.JSONEq(t, expect, logStr) {
t.Errorf("Info has wrong format \n expect:%s\n got:%s", expect, logStr)
}
}

View File

@ -21,6 +21,11 @@ import (
"sync"
"github.com/go-logr/logr"
json "k8s.io/component-base/logs/json"
)
const (
jsonLogFormat = "json"
)
var logRegistry = NewLogFormatRegistry()
@ -77,5 +82,6 @@ func (lfr *LogFormatRegistry) Delete(name string) {
func init() {
// Text format is default klog format
logRegistry.Register("text", nil)
logRegistry.Register(defaultLogFormat, nil)
logRegistry.Register(jsonLogFormat, json.JSONLogger)
}

View File

@ -183,6 +183,9 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=

View File

@ -182,6 +182,9 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=

View File

@ -182,6 +182,9 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=

View File

@ -182,6 +182,9 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=

View File

@ -185,6 +185,9 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=

1
vendor/modules.txt vendored
View File

@ -1678,6 +1678,7 @@ k8s.io/component-base/configz
k8s.io/component-base/featuregate
k8s.io/component-base/featuregate/testing
k8s.io/component-base/logs
k8s.io/component-base/logs/json
k8s.io/component-base/logs/logreduction
k8s.io/component-base/metrics
k8s.io/component-base/metrics/legacyregistry