178
vendor/k8s.io/component-base/logs/json/json.go
generated
vendored
Normal file
178
vendor/k8s.io/component-base/logs/json/json.go
generated
vendored
Normal file
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
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
|
||||
)
|
||||
|
||||
// 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
|
||||
lvl int
|
||||
}
|
||||
|
||||
// implement logr.Logger
|
||||
var _ logr.Logger = &zapLogger{}
|
||||
|
||||
// Enabled should always return true
|
||||
func (l *zapLogger) Enabled() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// Info write message to error level log
|
||||
func (l *zapLogger) Info(msg string, keysAndVals ...interface{}) {
|
||||
entry := zapcore.Entry{
|
||||
Time: timeNow(),
|
||||
Message: msg,
|
||||
}
|
||||
checkedEntry := l.l.Core().Check(entry, nil)
|
||||
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 *zapLogger) dPanic(msg string) {
|
||||
entry := zapcore.Entry{
|
||||
Level: zapcore.DPanicLevel,
|
||||
Time: timeNow(),
|
||||
Message: msg,
|
||||
}
|
||||
checkedEntry := l.l.Core().Check(entry, nil)
|
||||
checkedEntry.Write(zap.Int("v", l.lvl))
|
||||
}
|
||||
|
||||
// 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 *zapLogger) 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 append(additional, zap.Int("v", l.lvl))
|
||||
}
|
||||
|
||||
// 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)+1)
|
||||
fields = append(fields, zap.Int("v", l.lvl))
|
||||
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")
|
||||
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, stop logging
|
||||
l.dPanic("non-string key argument passed to logging, ignoring all later arguments")
|
||||
break
|
||||
}
|
||||
|
||||
fields = append(fields, zap.Any(keyStr, val))
|
||||
}
|
||||
|
||||
return append(fields, additional...)
|
||||
}
|
||||
|
||||
// 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.Logger {
|
||||
return &zapLogger{
|
||||
lvl: l.lvl + level,
|
||||
l: l.l,
|
||||
}
|
||||
}
|
||||
|
||||
// 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 encodetime format
|
||||
var encoderConfig = zapcore.EncoderConfig{
|
||||
MessageKey: "msg",
|
||||
|
||||
TimeKey: "ts",
|
||||
EncodeTime: zapcore.EpochMillisTimeEncoder,
|
||||
EncodeDuration: zapcore.StringDurationEncoder,
|
||||
}
|
||||
|
||||
// NewJSONLogger creates a new json logr.Logger using the given Zap Logger to log.
|
||||
func NewJSONLogger(w zapcore.WriteSyncer) logr.Logger {
|
||||
l, _ := zap.NewProduction()
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
||||
func handleError(err error) zap.Field {
|
||||
return zap.NamedError("err", err)
|
||||
}
|
||||
|
||||
func init() {
|
||||
JSONLogger = NewJSONLogger(nil)
|
||||
}
|
||||
Reference in New Issue
Block a user