rebase: bump k8s.io/klog/v2 from 2.60.1 to 2.70.1

Bumps [k8s.io/klog/v2](https://github.com/kubernetes/klog) from 2.60.1 to 2.70.1.
- [Release notes](https://github.com/kubernetes/klog/releases)
- [Changelog](https://github.com/kubernetes/klog/blob/main/RELEASE.md)
- [Commits](https://github.com/kubernetes/klog/compare/v2.60.1...v2.70.1)

---
updated-dependencies:
- dependency-name: k8s.io/klog/v2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
This commit is contained in:
dependabot[bot] 2022-07-07 15:31:05 +00:00 committed by mergify[bot]
parent f171143135
commit f8c8ff6c70
10 changed files with 405 additions and 180 deletions

2
go.mod
View File

@ -32,7 +32,7 @@ require (
k8s.io/apimachinery v0.24.2 k8s.io/apimachinery v0.24.2
k8s.io/client-go v12.0.0+incompatible k8s.io/client-go v12.0.0+incompatible
k8s.io/cloud-provider v0.24.2 k8s.io/cloud-provider v0.24.2
k8s.io/klog/v2 v2.60.1 k8s.io/klog/v2 v2.70.1
// //
// when updating k8s.io/kubernetes, make sure to update the replace section too // when updating k8s.io/kubernetes, make sure to update the replace section too
// //

3
go.sum
View File

@ -1781,8 +1781,9 @@ k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
k8s.io/klog/v2 v2.9.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= k8s.io/klog/v2 v2.9.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec=
k8s.io/klog/v2 v2.30.0/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/klog/v2 v2.30.0/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
k8s.io/klog/v2 v2.60.1 h1:VW25q3bZx9uE3vvdL6M8ezOX79vA2Aq1nEWLqNQclHc=
k8s.io/klog/v2 v2.60.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/klog/v2 v2.60.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
k8s.io/klog/v2 v2.70.1 h1:7aaoSdahviPmR+XkS7FyxlkkXs6tHISSG03RxleQAVQ=
k8s.io/klog/v2 v2.70.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
k8s.io/kube-aggregator v0.24.2/go.mod h1:Ju2jNDixn+vqeeKEBfjfpc204bO1pbdXX0N9knCxeMQ= k8s.io/kube-aggregator v0.24.2/go.mod h1:Ju2jNDixn+vqeeKEBfjfpc204bO1pbdXX0N9knCxeMQ=
k8s.io/kube-controller-manager v0.24.2/go.mod h1:KDE0yqiEvxYiO0WRpPA4rVx8AcK1vsWydUF37AJ9lTI= k8s.io/kube-controller-manager v0.24.2/go.mod h1:KDE0yqiEvxYiO0WRpPA4rVx8AcK1vsWydUF37AJ9lTI=
k8s.io/kube-openapi v0.0.0-20180731170545-e3762e86a74c/go.mod h1:BXM9ceUBTj2QnfH2MK1odQs778ajze1RxcmP6S8RVVc= k8s.io/kube-openapi v0.0.0-20180731170545-e3762e86a74c/go.mod h1:BXM9ceUBTj2QnfH2MK1odQs778ajze1RxcmP6S8RVVc=

1
vendor/k8s.io/klog/v2/README.md generated vendored
View File

@ -28,7 +28,6 @@ Historical context is available here:
Semantic versioning is used in this repository. It contains several Go modules Semantic versioning is used in this repository. It contains several Go modules
with different levels of stability: with different levels of stability:
- `k8s.io/klog/v2` - stable API, `vX.Y.Z` tags - `k8s.io/klog/v2` - stable API, `vX.Y.Z` tags
- `k8s.io/hack/tools` - no stable API yet (may change eventually or get moved to separate repo), `hack/tools/v0.Y.Z` tags
- `examples` - no stable API, no tags, no intention to ever stabilize - `examples` - no stable API, no tags, no intention to ever stabilize
Exempt from the API stability guarantee are items (packages, functions, etc.) Exempt from the API stability guarantee are items (packages, functions, etc.)

38
vendor/k8s.io/klog/v2/contextual.go generated vendored
View File

@ -34,18 +34,6 @@ import (
// mutex locking. // mutex locking.
var ( var (
// contextualLoggingEnabled controls whether contextual logging is
// active. Disabling it may have some small performance benefit.
contextualLoggingEnabled = true
// globalLogger is the global Logger chosen by users of klog, nil if
// none is available.
globalLogger *Logger
// globalLoggerOptions contains the options that were supplied for
// globalLogger.
globalLoggerOptions loggerOptions
// klogLogger is used as fallback for logging through the normal klog code // klogLogger is used as fallback for logging through the normal klog code
// when no Logger is set. // when no Logger is set.
klogLogger logr.Logger = logr.New(&klogger{}) klogLogger logr.Logger = logr.New(&klogger{})
@ -81,10 +69,10 @@ func SetLogger(logger logr.Logger) {
// routing log entries through klogr into klog and then into the actual Logger // routing log entries through klogr into klog and then into the actual Logger
// backend. // backend.
func SetLoggerWithOptions(logger logr.Logger, opts ...LoggerOption) { func SetLoggerWithOptions(logger logr.Logger, opts ...LoggerOption) {
globalLogger = &logger logging.logger = &logger
globalLoggerOptions = loggerOptions{} logging.loggerOptions = loggerOptions{}
for _, opt := range opts { for _, opt := range opts {
opt(&globalLoggerOptions) opt(&logging.loggerOptions)
} }
} }
@ -119,8 +107,8 @@ type loggerOptions struct {
// Modifying the logger is not thread-safe and should be done while no other // Modifying the logger is not thread-safe and should be done while no other
// goroutines invoke log calls, usually during program initialization. // goroutines invoke log calls, usually during program initialization.
func ClearLogger() { func ClearLogger() {
globalLogger = nil logging.logger = nil
globalLoggerOptions = loggerOptions{} logging.loggerOptions = loggerOptions{}
} }
// EnableContextualLogging controls whether contextual logging is enabled. // EnableContextualLogging controls whether contextual logging is enabled.
@ -132,14 +120,14 @@ func ClearLogger() {
// //
// This must be called during initialization before goroutines are started. // This must be called during initialization before goroutines are started.
func EnableContextualLogging(enabled bool) { func EnableContextualLogging(enabled bool) {
contextualLoggingEnabled = enabled logging.contextualLoggingEnabled = enabled
} }
// FromContext retrieves a logger set by the caller or, if not set, // FromContext retrieves a logger set by the caller or, if not set,
// falls back to the program's global logger (a Logger instance or klog // falls back to the program's global logger (a Logger instance or klog
// itself). // itself).
func FromContext(ctx context.Context) Logger { func FromContext(ctx context.Context) Logger {
if contextualLoggingEnabled { if logging.contextualLoggingEnabled {
if logger, err := logr.FromContext(ctx); err == nil { if logger, err := logr.FromContext(ctx); err == nil {
return logger return logger
} }
@ -160,10 +148,10 @@ func TODO() Logger {
// better receive a logger via its parameters. TODO can be used as a temporary // better receive a logger via its parameters. TODO can be used as a temporary
// solution for such code. // solution for such code.
func Background() Logger { func Background() Logger {
if globalLoggerOptions.contextualLogger { if logging.loggerOptions.contextualLogger {
// Is non-nil because globalLoggerOptions.contextualLogger is // Is non-nil because logging.loggerOptions.contextualLogger is
// only true if a logger was set. // only true if a logger was set.
return *globalLogger return *logging.logger
} }
return klogLogger return klogLogger
@ -172,7 +160,7 @@ func Background() Logger {
// LoggerWithValues returns logger.WithValues(...kv) when // LoggerWithValues returns logger.WithValues(...kv) when
// contextual logging is enabled, otherwise the logger. // contextual logging is enabled, otherwise the logger.
func LoggerWithValues(logger Logger, kv ...interface{}) Logger { func LoggerWithValues(logger Logger, kv ...interface{}) Logger {
if contextualLoggingEnabled { if logging.contextualLoggingEnabled {
return logger.WithValues(kv...) return logger.WithValues(kv...)
} }
return logger return logger
@ -181,7 +169,7 @@ func LoggerWithValues(logger Logger, kv ...interface{}) Logger {
// LoggerWithName returns logger.WithName(name) when contextual logging is // LoggerWithName returns logger.WithName(name) when contextual logging is
// enabled, otherwise the logger. // enabled, otherwise the logger.
func LoggerWithName(logger Logger, name string) Logger { func LoggerWithName(logger Logger, name string) Logger {
if contextualLoggingEnabled { if logging.contextualLoggingEnabled {
return logger.WithName(name) return logger.WithName(name)
} }
return logger return logger
@ -190,7 +178,7 @@ func LoggerWithName(logger Logger, name string) Logger {
// NewContext returns logr.NewContext(ctx, logger) when // NewContext returns logr.NewContext(ctx, logger) when
// contextual logging is enabled, otherwise ctx. // contextual logging is enabled, otherwise ctx.
func NewContext(ctx context.Context, logger Logger) context.Context { func NewContext(ctx context.Context, logger Logger) context.Context {
if contextualLoggingEnabled { if logging.contextualLoggingEnabled {
return logr.NewContext(ctx, logger) return logr.NewContext(ctx, logger)
} }
return ctx return ctx

42
vendor/k8s.io/klog/v2/internal/dbg/dbg.go generated vendored Normal file
View File

@ -0,0 +1,42 @@
// Go support for leveled logs, analogous to https://code.google.com/p/google-glog/
//
// Copyright 2013 Google Inc. All Rights Reserved.
//
// 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 dbg provides some helper code for call traces.
package dbg
import (
"runtime"
)
// Stacks is a wrapper for runtime.Stack that attempts to recover the data for
// all goroutines or the calling one.
func Stacks(all bool) []byte {
// We don't know how big the traces are, so grow a few times if they don't fit. Start large, though.
n := 10000
if all {
n = 100000
}
var trace []byte
for i := 0; i < 5; i++ {
trace = make([]byte, n)
nbytes := runtime.Stack(trace, all)
if nbytes < len(trace) {
return trace[:nbytes]
}
n *= 2
}
return trace
}

View File

@ -20,6 +20,8 @@ import (
"bytes" "bytes"
"fmt" "fmt"
"strconv" "strconv"
"github.com/go-logr/logr"
) )
// WithValues implements LogSink.WithValues. The old key/value pairs are // WithValues implements LogSink.WithValues. The old key/value pairs are
@ -44,53 +46,49 @@ func WithValues(oldKV, newKV []interface{}) []interface{} {
return kv return kv
} }
// TrimDuplicates deduplicates elements provided in multiple key/value tuple // MergeKVs deduplicates elements provided in two key/value slices.
// slices, whilst maintaining the distinction between where the items are //
// contained. // Keys in each slice are expected to be unique, so duplicates can only occur
func TrimDuplicates(kvLists ...[]interface{}) [][]interface{} { // when the first and second slice contain the same key. When that happens, the
// maintain a map of all seen keys // key/value pair from the second slice is used. The first slice must be well-formed
seenKeys := map[interface{}]struct{}{} // (= even key/value pairs). The second one may have a missing value, in which
// build the same number of output slices as inputs // case the special "missing value" is added to the result.
outs := make([][]interface{}, len(kvLists)) func MergeKVs(first, second []interface{}) []interface{} {
// iterate over the input slices backwards, as 'later' kv specifications maxLength := len(first) + (len(second)+1)/2*2
// of the same key will take precedence over earlier ones if maxLength == 0 {
for i := len(kvLists) - 1; i >= 0; i-- { // Nothing to do at all.
// initialise this output slice return nil
outs[i] = []interface{}{}
// obtain a reference to the kvList we are processing
// and make sure it has an even number of entries
kvList := kvLists[i]
if len(kvList)%2 != 0 {
kvList = append(kvList, missingValue)
}
// start iterating at len(kvList) - 2 (i.e. the 2nd last item) for
// slices that have an even number of elements.
// We add (len(kvList) % 2) here to handle the case where there is an
// odd number of elements in a kvList.
// If there is an odd number, then the last element in the slice will
// have the value 'null'.
for i2 := len(kvList) - 2 + (len(kvList) % 2); i2 >= 0; i2 -= 2 {
k := kvList[i2]
// if we have already seen this key, do not include it again
if _, ok := seenKeys[k]; ok {
continue
}
// make a note that we've observed a new key
seenKeys[k] = struct{}{}
// attempt to obtain the value of the key
var v interface{}
// i2+1 should only ever be out of bounds if we handling the first
// iteration over a slice with an odd number of elements
if i2+1 < len(kvList) {
v = kvList[i2+1]
}
// add this KV tuple to the *start* of the output list to maintain
// the original order as we are iterating over the slice backwards
outs[i] = append([]interface{}{k, v}, outs[i]...)
}
} }
return outs
if len(first) == 0 && len(second)%2 == 0 {
// Nothing to be overridden, second slice is well-formed
// and can be used directly.
return second
}
// Determine which keys are in the second slice so that we can skip
// them when iterating over the first one. The code intentionally
// favors performance over completeness: we assume that keys are string
// constants and thus compare equal when the string values are equal. A
// string constant being overridden by, for example, a fmt.Stringer is
// not handled.
overrides := map[interface{}]bool{}
for i := 0; i < len(second); i += 2 {
overrides[second[i]] = true
}
merged := make([]interface{}, 0, maxLength)
for i := 0; i+1 < len(first); i += 2 {
key := first[i]
if overrides[key] {
continue
}
merged = append(merged, key, first[i+1])
}
merged = append(merged, second...)
if len(merged)%2 != 0 {
merged = append(merged, missingValue)
}
return merged
} }
const missingValue = "(MISSING)" const missingValue = "(MISSING)"
@ -111,10 +109,10 @@ func KVListFormat(b *bytes.Buffer, keysAndValues ...interface{}) {
// https://github.com/kubernetes/community/blob/master/contributors/devel/sig-instrumentation/migration-to-structured-logging.md#name-arguments // https://github.com/kubernetes/community/blob/master/contributors/devel/sig-instrumentation/migration-to-structured-logging.md#name-arguments
// for the sake of performance. Keys with spaces, // for the sake of performance. Keys with spaces,
// special characters, etc. will break parsing. // special characters, etc. will break parsing.
if k, ok := k.(string); ok { if sK, ok := k.(string); ok {
// Avoid one allocation when the key is a string, which // Avoid one allocation when the key is a string, which
// normally it should be. // normally it should be.
b.WriteString(k) b.WriteString(sK)
} else { } else {
b.WriteString(fmt.Sprintf("%s", k)) b.WriteString(fmt.Sprintf("%s", k))
} }
@ -131,6 +129,24 @@ func KVListFormat(b *bytes.Buffer, keysAndValues ...interface{}) {
writeStringValue(b, true, v) writeStringValue(b, true, v)
case error: case error:
writeStringValue(b, true, ErrorToString(v)) writeStringValue(b, true, ErrorToString(v))
case logr.Marshaler:
value := MarshalerToValue(v)
// A marshaler that returns a string is useful for
// delayed formatting of complex values. We treat this
// case like a normal string. This is useful for
// multi-line support.
//
// We could do this by recursively formatting a value,
// but that comes with the risk of infinite recursion
// if a marshaler returns itself. Instead we call it
// only once and rely on it returning the intended
// value directly.
switch value := value.(type) {
case string:
writeStringValue(b, true, value)
default:
writeStringValue(b, false, fmt.Sprintf("%+v", v))
}
case []byte: case []byte:
// In https://github.com/kubernetes/klog/pull/237 it was decided // In https://github.com/kubernetes/klog/pull/237 it was decided
// to format byte slices with "%+q". The advantages of that are: // to format byte slices with "%+q". The advantages of that are:
@ -163,6 +179,18 @@ func StringerToString(s fmt.Stringer) (ret string) {
return return
} }
// MarshalerToValue invokes a marshaler and catches
// panics.
func MarshalerToValue(m logr.Marshaler) (ret interface{}) {
defer func() {
if err := recover(); err != nil {
ret = fmt.Sprintf("<panic: %s>", err)
}
}()
ret = m.MarshalLog()
return
}
// ErrorToString converts an error to a string, // ErrorToString converts an error to a string,
// handling panics if they occur. // handling panics if they occur.
func ErrorToString(err error) (ret string) { func ErrorToString(err error) (ret string) {

View File

@ -77,6 +77,8 @@ func KRef(namespace, name string) ObjectRef {
} }
// KObjs returns slice of ObjectRef from an slice of ObjectMeta // KObjs returns slice of ObjectRef from an slice of ObjectMeta
//
// DEPRECATED: Use KObjSlice instead, it has better performance.
func KObjs(arg interface{}) []ObjectRef { func KObjs(arg interface{}) []ObjectRef {
s := reflect.ValueOf(arg) s := reflect.ValueOf(arg)
if s.Kind() != reflect.Slice { if s.Kind() != reflect.Slice {
@ -92,3 +94,65 @@ func KObjs(arg interface{}) []ObjectRef {
} }
return objectRefs return objectRefs
} }
// KObjSlice takes a slice of objects that implement the KMetadata interface
// and returns an object that gets logged as a slice of ObjectRef values or a
// string containing those values, depending on whether the logger prefers text
// output or structured output.
//
// An error string is logged when KObjSlice is not passed a suitable slice.
//
// Processing of the argument is delayed until the value actually gets logged,
// in contrast to KObjs where that overhead is incurred regardless of whether
// the result is needed.
func KObjSlice(arg interface{}) interface{} {
return kobjSlice{arg: arg}
}
type kobjSlice struct {
arg interface{}
}
var _ fmt.Stringer = kobjSlice{}
var _ logr.Marshaler = kobjSlice{}
func (ks kobjSlice) String() string {
objectRefs, err := ks.process()
if err != nil {
return err.Error()
}
return fmt.Sprintf("%v", objectRefs)
}
func (ks kobjSlice) MarshalLog() interface{} {
objectRefs, err := ks.process()
if err != nil {
return err.Error()
}
return objectRefs
}
func (ks kobjSlice) process() ([]interface{}, error) {
s := reflect.ValueOf(ks.arg)
switch s.Kind() {
case reflect.Invalid:
// nil parameter, print as nil.
return nil, nil
case reflect.Slice:
// Okay, handle below.
default:
return nil, fmt.Errorf("<KObjSlice needs a slice, got type %T>", ks.arg)
}
objectRefs := make([]interface{}, 0, s.Len())
for i := 0; i < s.Len(); i++ {
item := s.Index(i).Interface()
if item == nil {
objectRefs = append(objectRefs, nil)
} else if v, ok := item.(KMetadata); ok {
objectRefs = append(objectRefs, KObj(v))
} else {
return nil, fmt.Errorf("<KObjSlice needs a slice of values implementing KMetadata, got type %T>", item)
}
}
return objectRefs, nil
}

300
vendor/k8s.io/klog/v2/klog.go generated vendored
View File

@ -41,6 +41,10 @@
// //
// -logtostderr=true // -logtostderr=true
// Logs are written to standard error instead of to files. // Logs are written to standard error instead of to files.
// This shortcuts most of the usual output routing:
// -alsologtostderr, -stderrthreshold and -log_dir have no
// effect and output redirection at runtime with SetOutput is
// ignored.
// -alsologtostderr=false // -alsologtostderr=false
// Logs are written to standard error as well as to files. // Logs are written to standard error as well as to files.
// -stderrthreshold=ERROR // -stderrthreshold=ERROR
@ -92,6 +96,7 @@ import (
"k8s.io/klog/v2/internal/buffer" "k8s.io/klog/v2/internal/buffer"
"k8s.io/klog/v2/internal/clock" "k8s.io/klog/v2/internal/clock"
"k8s.io/klog/v2/internal/dbg"
"k8s.io/klog/v2/internal/serialize" "k8s.io/klog/v2/internal/serialize"
"k8s.io/klog/v2/internal/severity" "k8s.io/klog/v2/internal/severity"
) )
@ -242,6 +247,10 @@ func (m *moduleSpec) String() string {
// Lock because the type is not atomic. TODO: clean this up. // Lock because the type is not atomic. TODO: clean this up.
logging.mu.Lock() logging.mu.Lock()
defer logging.mu.Unlock() defer logging.mu.Unlock()
return m.serialize()
}
func (m *moduleSpec) serialize() string {
var b bytes.Buffer var b bytes.Buffer
for i, f := range m.filter { for i, f := range m.filter {
if i > 0 { if i > 0 {
@ -263,6 +272,17 @@ var errVmoduleSyntax = errors.New("syntax error: expect comma-separated list of
// Set will sets module value // Set will sets module value
// Syntax: -vmodule=recordio=2,file=1,gfs*=3 // Syntax: -vmodule=recordio=2,file=1,gfs*=3
func (m *moduleSpec) Set(value string) error { func (m *moduleSpec) Set(value string) error {
filter, err := parseModuleSpec(value)
if err != nil {
return err
}
logging.mu.Lock()
defer logging.mu.Unlock()
logging.setVState(logging.verbosity, filter, true)
return nil
}
func parseModuleSpec(value string) ([]modulePat, error) {
var filter []modulePat var filter []modulePat
for _, pat := range strings.Split(value, ",") { for _, pat := range strings.Split(value, ",") {
if len(pat) == 0 { if len(pat) == 0 {
@ -271,15 +291,15 @@ func (m *moduleSpec) Set(value string) error {
} }
patLev := strings.Split(pat, "=") patLev := strings.Split(pat, "=")
if len(patLev) != 2 || len(patLev[0]) == 0 || len(patLev[1]) == 0 { if len(patLev) != 2 || len(patLev[0]) == 0 || len(patLev[1]) == 0 {
return errVmoduleSyntax return nil, errVmoduleSyntax
} }
pattern := patLev[0] pattern := patLev[0]
v, err := strconv.ParseInt(patLev[1], 10, 32) v, err := strconv.ParseInt(patLev[1], 10, 32)
if err != nil { if err != nil {
return errors.New("syntax error: expect comma-separated list of filename=N") return nil, errors.New("syntax error: expect comma-separated list of filename=N")
} }
if v < 0 { if v < 0 {
return errors.New("negative value for vmodule level") return nil, errors.New("negative value for vmodule level")
} }
if v == 0 { if v == 0 {
continue // Ignore. It's harmless but no point in paying the overhead. continue // Ignore. It's harmless but no point in paying the overhead.
@ -287,10 +307,7 @@ func (m *moduleSpec) Set(value string) error {
// TODO: check syntax of filter? // TODO: check syntax of filter?
filter = append(filter, modulePat{pattern, isLiteral(pattern), Level(v)}) filter = append(filter, modulePat{pattern, isLiteral(pattern), Level(v)})
} }
logging.mu.Lock() return filter, nil
defer logging.mu.Unlock()
logging.setVState(logging.verbosity, filter, true)
return nil
} }
// isLiteral reports whether the pattern is a literal string, that is, has no metacharacters // isLiteral reports whether the pattern is a literal string, that is, has no metacharacters
@ -404,19 +421,19 @@ func InitFlags(flagset *flag.FlagSet) {
flagset = flag.CommandLine flagset = flag.CommandLine
} }
flagset.StringVar(&logging.logDir, "log_dir", logging.logDir, "If non-empty, write log files in this directory") flagset.StringVar(&logging.logDir, "log_dir", logging.logDir, "If non-empty, write log files in this directory (no effect when -logtostderr=true)")
flagset.StringVar(&logging.logFile, "log_file", logging.logFile, "If non-empty, use this log file") flagset.StringVar(&logging.logFile, "log_file", logging.logFile, "If non-empty, use this log file (no effect when -logtostderr=true)")
flagset.Uint64Var(&logging.logFileMaxSizeMB, "log_file_max_size", logging.logFileMaxSizeMB, flagset.Uint64Var(&logging.logFileMaxSizeMB, "log_file_max_size", logging.logFileMaxSizeMB,
"Defines the maximum size a log file can grow to. Unit is megabytes. "+ "Defines the maximum size a log file can grow to (no effect when -logtostderr=true). Unit is megabytes. "+
"If the value is 0, the maximum file size is unlimited.") "If the value is 0, the maximum file size is unlimited.")
flagset.BoolVar(&logging.toStderr, "logtostderr", logging.toStderr, "log to standard error instead of files") flagset.BoolVar(&logging.toStderr, "logtostderr", logging.toStderr, "log to standard error instead of files")
flagset.BoolVar(&logging.alsoToStderr, "alsologtostderr", logging.alsoToStderr, "log to standard error as well as files") flagset.BoolVar(&logging.alsoToStderr, "alsologtostderr", logging.alsoToStderr, "log to standard error as well as files (no effect when -logtostderr=true)")
flagset.Var(&logging.verbosity, "v", "number for the log level verbosity") flagset.Var(&logging.verbosity, "v", "number for the log level verbosity")
flagset.BoolVar(&logging.addDirHeader, "add_dir_header", logging.addDirHeader, "If true, adds the file directory to the header of the log messages") flagset.BoolVar(&logging.addDirHeader, "add_dir_header", logging.addDirHeader, "If true, adds the file directory to the header of the log messages")
flagset.BoolVar(&logging.skipHeaders, "skip_headers", logging.skipHeaders, "If true, avoid header prefixes in the log messages") flagset.BoolVar(&logging.skipHeaders, "skip_headers", logging.skipHeaders, "If true, avoid header prefixes in the log messages")
flagset.BoolVar(&logging.oneOutput, "one_output", logging.oneOutput, "If true, only write logs to their native severity level (vs also writing to each lower severity level)") flagset.BoolVar(&logging.oneOutput, "one_output", logging.oneOutput, "If true, only write logs to their native severity level (vs also writing to each lower severity level; no effect when -logtostderr=true)")
flagset.BoolVar(&logging.skipLogHeaders, "skip_log_headers", logging.skipLogHeaders, "If true, avoid headers when opening log files") flagset.BoolVar(&logging.skipLogHeaders, "skip_log_headers", logging.skipLogHeaders, "If true, avoid headers when opening log files (no effect when -logtostderr=true)")
flagset.Var(&logging.stderrThreshold, "stderrthreshold", "logs at or above this threshold go to stderr") flagset.Var(&logging.stderrThreshold, "stderrthreshold", "logs at or above this threshold go to stderr when writing to files and stderr (no effect when -logtostderr=true or -alsologtostderr=false)")
flagset.Var(&logging.vmodule, "vmodule", "comma-separated list of pattern=N settings for file-filtered logging") flagset.Var(&logging.vmodule, "vmodule", "comma-separated list of pattern=N settings for file-filtered logging")
flagset.Var(&logging.traceLocation, "log_backtrace_at", "when logging hits line file:N, emit a stack trace") flagset.Var(&logging.traceLocation, "log_backtrace_at", "when logging hits line file:N, emit a stack trace")
} }
@ -426,8 +443,20 @@ func Flush() {
logging.lockAndFlushAll() logging.lockAndFlushAll()
} }
// loggingT collects all the global state of the logging setup. // settings collects global settings.
type loggingT struct { type settings struct {
// contextualLoggingEnabled controls whether contextual logging is
// active. Disabling it may have some small performance benefit.
contextualLoggingEnabled bool
// logger is the global Logger chosen by users of klog, nil if
// none is available.
logger *Logger
// loggerOptions contains the options that were supplied for
// globalLogger.
loggerOptions loggerOptions
// Boolean flags. Not handled atomically because the flag.Value interface // Boolean flags. Not handled atomically because the flag.Value interface
// does not let us avoid the =true, and that shorthand is necessary for // does not let us avoid the =true, and that shorthand is necessary for
// compatibility. TODO: does this matter enough to fix? Seems unlikely. // compatibility. TODO: does this matter enough to fix? Seems unlikely.
@ -437,26 +466,14 @@ type loggingT struct {
// Level flag. Handled atomically. // Level flag. Handled atomically.
stderrThreshold severityValue // The -stderrthreshold flag. stderrThreshold severityValue // The -stderrthreshold flag.
// bufferCache maintains the free list. It uses its own mutex // Access to all of the following fields must be protected via a mutex.
// so buffers can be grabbed and printed to without holding the main lock,
// for better parallelization.
bufferCache buffer.Buffers
// mu protects the remaining elements of this structure and is
// used to synchronize logging.
mu sync.Mutex
// file holds writer for each of the log types. // file holds writer for each of the log types.
file [severity.NumSeverity]flushSyncWriter file [severity.NumSeverity]flushSyncWriter
// flushD holds a flushDaemon that frequently flushes log file buffers.
flushD *flushDaemon
// flushInterval is the interval for periodic flushing. If zero, // flushInterval is the interval for periodic flushing. If zero,
// the global default will be used. // the global default will be used.
flushInterval time.Duration flushInterval time.Duration
// pcs is used in V to avoid an allocation when computing the caller's PC.
pcs [1]uintptr
// vmap is a cache of the V Level for each V() call site, identified by PC.
// It is wiped whenever the vmodule flag changes state.
vmap map[uintptr]Level
// filterLength stores the length of the vmodule filter chain. If greater // filterLength stores the length of the vmodule filter chain. If greater
// than zero, it means vmodule is enabled. It may be read safely // than zero, it means vmodule is enabled. It may be read safely
// using sync.LoadInt32, but is only modified under mu. // using sync.LoadInt32, but is only modified under mu.
@ -496,7 +513,48 @@ type loggingT struct {
filter LogFilter filter LogFilter
} }
var logging loggingT // deepCopy creates a copy that doesn't share anything with the original
// instance.
func (s settings) deepCopy() settings {
// vmodule is a slice and would be shared, so we have copy it.
filter := make([]modulePat, len(s.vmodule.filter))
for i := range s.vmodule.filter {
filter[i] = s.vmodule.filter[i]
}
s.vmodule.filter = filter
return s
}
// loggingT collects all the global state of the logging setup.
type loggingT struct {
settings
// bufferCache maintains the free list. It uses its own mutex
// so buffers can be grabbed and printed to without holding the main lock,
// for better parallelization.
bufferCache buffer.Buffers
// flushD holds a flushDaemon that frequently flushes log file buffers.
// Uses its own mutex.
flushD *flushDaemon
// mu protects the remaining elements of this structure and the fields
// in settingsT which need a mutex lock.
mu sync.Mutex
// pcs is used in V to avoid an allocation when computing the caller's PC.
pcs [1]uintptr
// vmap is a cache of the V Level for each V() call site, identified by PC.
// It is wiped whenever the vmodule flag changes state.
vmap map[uintptr]Level
}
var logging = loggingT{
settings: settings{
contextualLoggingEnabled: true,
},
}
// setVState sets a consistent state for V logging. // setVState sets a consistent state for V logging.
// l.mu is held. // l.mu is held.
@ -520,6 +578,55 @@ func (l *loggingT) setVState(verbosity Level, filter []modulePat, setFilter bool
var timeNow = time.Now // Stubbed out for testing. var timeNow = time.Now // Stubbed out for testing.
// CaptureState gathers information about all current klog settings.
// The result can be used to restore those settings.
func CaptureState() State {
logging.mu.Lock()
defer logging.mu.Unlock()
return &state{
settings: logging.settings.deepCopy(),
flushDRunning: logging.flushD.isRunning(),
maxSize: MaxSize,
}
}
// State stores a snapshot of klog settings. It gets created with CaptureState
// and can be used to restore the entire state. Modifying individual settings
// is supported via the command line flags.
type State interface {
// Restore restore the entire state. It may get called more than once.
Restore()
}
type state struct {
settings
flushDRunning bool
maxSize uint64
}
func (s *state) Restore() {
// This needs to be done before mutex locking.
if s.flushDRunning && !logging.flushD.isRunning() {
// This is not quite accurate: StartFlushDaemon might
// have been called with some different interval.
interval := s.flushInterval
if interval == 0 {
interval = flushInterval
}
logging.flushD.run(interval)
} else if !s.flushDRunning && logging.flushD.isRunning() {
logging.flushD.stop()
}
logging.mu.Lock()
defer logging.mu.Unlock()
logging.settings = s.settings
logging.setVState(s.verbosity, s.vmodule.filter, true)
MaxSize = s.maxSize
}
/* /*
header formats a log header as defined by the C++ implementation. header formats a log header as defined by the C++ implementation.
It returns a buffer containing the formatted header and the user's file and line number. It returns a buffer containing the formatted header and the user's file and line number.
@ -688,7 +795,7 @@ func (l *loggingT) printS(err error, s severity.Severity, depth int, msg string,
serialize.KVListFormat(&b.Buffer, "err", err) serialize.KVListFormat(&b.Buffer, "err", err)
} }
serialize.KVListFormat(&b.Buffer, keysAndValues...) serialize.KVListFormat(&b.Buffer, keysAndValues...)
l.printDepth(s, globalLogger, nil, depth+1, &b.Buffer) l.printDepth(s, logging.logger, nil, depth+1, &b.Buffer)
// Make the buffer available for reuse. // Make the buffer available for reuse.
l.bufferCache.PutBuffer(b) l.bufferCache.PutBuffer(b)
} }
@ -757,7 +864,7 @@ func (l *loggingT) output(s severity.Severity, log *logr.Logger, buf *buffer.Buf
if l.traceLocation.isSet() { if l.traceLocation.isSet() {
if l.traceLocation.match(file, line) { if l.traceLocation.match(file, line) {
buf.Write(stacks(false)) buf.Write(dbg.Stacks(false))
} }
} }
data := buf.Bytes() data := buf.Bytes()
@ -765,7 +872,7 @@ func (l *loggingT) output(s severity.Severity, log *logr.Logger, buf *buffer.Buf
// TODO: set 'severity' and caller information as structured log info // TODO: set 'severity' and caller information as structured log info
// keysAndValues := []interface{}{"severity", severityName[s], "file", file, "line", line} // keysAndValues := []interface{}{"severity", severityName[s], "file", file, "line", line}
if s == severity.ErrorLog { if s == severity.ErrorLog {
globalLogger.WithCallDepth(depth+3).Error(nil, string(data)) logging.logger.WithCallDepth(depth+3).Error(nil, string(data))
} else { } else {
log.WithCallDepth(depth + 3).Info(string(data)) log.WithCallDepth(depth + 3).Info(string(data))
} }
@ -822,12 +929,15 @@ func (l *loggingT) output(s severity.Severity, log *logr.Logger, buf *buffer.Buf
OsExit(1) OsExit(1)
} }
// Dump all goroutine stacks before exiting. // Dump all goroutine stacks before exiting.
trace := stacks(true) // First, make sure we see the trace for the current goroutine on standard error.
// Write the stack trace for all goroutines to the stderr. // If -logtostderr has been specified, the loop below will do that anyway
if l.toStderr || l.alsoToStderr || s >= l.stderrThreshold.get() || alsoToStderr { // as the first stack in the full dump.
os.Stderr.Write(trace) if !l.toStderr {
os.Stderr.Write(dbg.Stacks(false))
} }
// Write the stack trace for all goroutines to the files. // Write the stack trace for all goroutines to the files.
trace := dbg.Stacks(true)
logExitFunc = func(error) {} // If we get a write error, we'll still exit below. logExitFunc = func(error) {} // If we get a write error, we'll still exit below.
for log := severity.FatalLog; log >= severity.InfoLog; log-- { for log := severity.FatalLog; log >= severity.InfoLog; log-- {
if f := l.file[log]; f != nil { // Can be nil if -logtostderr is set. if f := l.file[log]; f != nil { // Can be nil if -logtostderr is set.
@ -847,25 +957,6 @@ func (l *loggingT) output(s severity.Severity, log *logr.Logger, buf *buffer.Buf
} }
} }
// stacks is a wrapper for runtime.Stack that attempts to recover the data for all goroutines.
func stacks(all bool) []byte {
// We don't know how big the traces are, so grow a few times if they don't fit. Start large, though.
n := 10000
if all {
n = 100000
}
var trace []byte
for i := 0; i < 5; i++ {
trace = make([]byte, n)
nbytes := runtime.Stack(trace, all)
if nbytes < len(trace) {
return trace[:nbytes]
}
n *= 2
}
return trace
}
// logExitFunc provides a simple mechanism to override the default behavior // logExitFunc provides a simple mechanism to override the default behavior
// of exiting on error. Used in testing and to guarantee we reach a required exit // of exiting on error. Used in testing and to guarantee we reach a required exit
// for fatal logs. Instead, exit could be a function rather than a method but that // for fatal logs. Instead, exit could be a function rather than a method but that
@ -1077,9 +1168,9 @@ func (f *flushDaemon) isRunning() bool {
return f.stopC != nil return f.stopC != nil
} }
// StopFlushDaemon stops the flush daemon, if running. // StopFlushDaemon stops the flush daemon, if running, and flushes once.
// This prevents klog from leaking goroutines on shutdown. After stopping // This prevents klog from leaking goroutines on shutdown. After stopping
// the daemon, you can still manually flush buffers by calling Flush(). // the daemon, you can still manually flush buffers again by calling Flush().
func StopFlushDaemon() { func StopFlushDaemon() {
logging.flushD.stop() logging.flushD.stop()
} }
@ -1109,8 +1200,8 @@ func (l *loggingT) flushAll() {
file.Sync() // ignore error file.Sync() // ignore error
} }
} }
if globalLoggerOptions.flush != nil { if logging.loggerOptions.flush != nil {
globalLoggerOptions.flush() logging.loggerOptions.flush()
} }
} }
@ -1158,7 +1249,7 @@ func (lb logBridge) Write(b []byte) (n int, err error) {
} }
// printWithFileLine with alsoToStderr=true, so standard log messages // printWithFileLine with alsoToStderr=true, so standard log messages
// always appear on standard error. // always appear on standard error.
logging.printWithFileLine(severity.Severity(lb), globalLogger, logging.filter, file, line, true, text) logging.printWithFileLine(severity.Severity(lb), logging.logger, logging.filter, file, line, true, text)
return len(b), nil return len(b), nil
} }
@ -1196,10 +1287,10 @@ type Verbose struct {
} }
func newVerbose(level Level, b bool) Verbose { func newVerbose(level Level, b bool) Verbose {
if globalLogger == nil { if logging.logger == nil {
return Verbose{b, nil} return Verbose{b, nil}
} }
v := globalLogger.V(int(level)) v := logging.logger.V(int(level))
return Verbose{b, &v} return Verbose{b, &v}
} }
@ -1318,7 +1409,7 @@ func (v Verbose) InfoS(msg string, keysAndValues ...interface{}) {
// InfoSDepth acts as InfoS but uses depth to determine which call frame to log. // InfoSDepth acts as InfoS but uses depth to determine which call frame to log.
// InfoSDepth(0, "msg") is the same as InfoS("msg"). // InfoSDepth(0, "msg") is the same as InfoS("msg").
func InfoSDepth(depth int, msg string, keysAndValues ...interface{}) { func InfoSDepth(depth int, msg string, keysAndValues ...interface{}) {
logging.infoS(globalLogger, logging.filter, depth, msg, keysAndValues...) logging.infoS(logging.logger, logging.filter, depth, msg, keysAndValues...)
} }
// InfoSDepth is equivalent to the global InfoSDepth function, guarded by the value of v. // InfoSDepth is equivalent to the global InfoSDepth function, guarded by the value of v.
@ -1347,37 +1438,37 @@ func (v Verbose) ErrorS(err error, msg string, keysAndValues ...interface{}) {
// Info logs to the INFO log. // Info logs to the INFO log.
// Arguments are handled in the manner of fmt.Print; a newline is appended if missing. // Arguments are handled in the manner of fmt.Print; a newline is appended if missing.
func Info(args ...interface{}) { func Info(args ...interface{}) {
logging.print(severity.InfoLog, globalLogger, logging.filter, args...) logging.print(severity.InfoLog, logging.logger, logging.filter, args...)
} }
// InfoDepth acts as Info but uses depth to determine which call frame to log. // InfoDepth acts as Info but uses depth to determine which call frame to log.
// InfoDepth(0, "msg") is the same as Info("msg"). // InfoDepth(0, "msg") is the same as Info("msg").
func InfoDepth(depth int, args ...interface{}) { func InfoDepth(depth int, args ...interface{}) {
logging.printDepth(severity.InfoLog, globalLogger, logging.filter, depth, args...) logging.printDepth(severity.InfoLog, logging.logger, logging.filter, depth, args...)
} }
// Infoln logs to the INFO log. // Infoln logs to the INFO log.
// Arguments are handled in the manner of fmt.Println; a newline is always appended. // Arguments are handled in the manner of fmt.Println; a newline is always appended.
func Infoln(args ...interface{}) { func Infoln(args ...interface{}) {
logging.println(severity.InfoLog, globalLogger, logging.filter, args...) logging.println(severity.InfoLog, logging.logger, logging.filter, args...)
} }
// InfolnDepth acts as Infoln but uses depth to determine which call frame to log. // InfolnDepth acts as Infoln but uses depth to determine which call frame to log.
// InfolnDepth(0, "msg") is the same as Infoln("msg"). // InfolnDepth(0, "msg") is the same as Infoln("msg").
func InfolnDepth(depth int, args ...interface{}) { func InfolnDepth(depth int, args ...interface{}) {
logging.printlnDepth(severity.InfoLog, globalLogger, logging.filter, depth, args...) logging.printlnDepth(severity.InfoLog, logging.logger, logging.filter, depth, args...)
} }
// Infof logs to the INFO log. // Infof logs to the INFO log.
// Arguments are handled in the manner of fmt.Printf; a newline is appended if missing. // Arguments are handled in the manner of fmt.Printf; a newline is appended if missing.
func Infof(format string, args ...interface{}) { func Infof(format string, args ...interface{}) {
logging.printf(severity.InfoLog, globalLogger, logging.filter, format, args...) logging.printf(severity.InfoLog, logging.logger, logging.filter, format, args...)
} }
// InfofDepth acts as Infof but uses depth to determine which call frame to log. // InfofDepth acts as Infof but uses depth to determine which call frame to log.
// InfofDepth(0, "msg", args...) is the same as Infof("msg", args...). // InfofDepth(0, "msg", args...) is the same as Infof("msg", args...).
func InfofDepth(depth int, format string, args ...interface{}) { func InfofDepth(depth int, format string, args ...interface{}) {
logging.printfDepth(severity.InfoLog, globalLogger, logging.filter, depth, format, args...) logging.printfDepth(severity.InfoLog, logging.logger, logging.filter, depth, format, args...)
} }
// InfoS structured logs to the INFO log. // InfoS structured logs to the INFO log.
@ -1389,79 +1480,79 @@ func InfofDepth(depth int, format string, args ...interface{}) {
// output: // output:
// >> I1025 00:15:15.525108 1 controller_utils.go:116] "Pod status updated" pod="kubedns" status="ready" // >> I1025 00:15:15.525108 1 controller_utils.go:116] "Pod status updated" pod="kubedns" status="ready"
func InfoS(msg string, keysAndValues ...interface{}) { func InfoS(msg string, keysAndValues ...interface{}) {
logging.infoS(globalLogger, logging.filter, 0, msg, keysAndValues...) logging.infoS(logging.logger, logging.filter, 0, msg, keysAndValues...)
} }
// Warning logs to the WARNING and INFO logs. // Warning logs to the WARNING and INFO logs.
// Arguments are handled in the manner of fmt.Print; a newline is appended if missing. // Arguments are handled in the manner of fmt.Print; a newline is appended if missing.
func Warning(args ...interface{}) { func Warning(args ...interface{}) {
logging.print(severity.WarningLog, globalLogger, logging.filter, args...) logging.print(severity.WarningLog, logging.logger, logging.filter, args...)
} }
// WarningDepth acts as Warning but uses depth to determine which call frame to log. // WarningDepth acts as Warning but uses depth to determine which call frame to log.
// WarningDepth(0, "msg") is the same as Warning("msg"). // WarningDepth(0, "msg") is the same as Warning("msg").
func WarningDepth(depth int, args ...interface{}) { func WarningDepth(depth int, args ...interface{}) {
logging.printDepth(severity.WarningLog, globalLogger, logging.filter, depth, args...) logging.printDepth(severity.WarningLog, logging.logger, logging.filter, depth, args...)
} }
// Warningln logs to the WARNING and INFO logs. // Warningln logs to the WARNING and INFO logs.
// Arguments are handled in the manner of fmt.Println; a newline is always appended. // Arguments are handled in the manner of fmt.Println; a newline is always appended.
func Warningln(args ...interface{}) { func Warningln(args ...interface{}) {
logging.println(severity.WarningLog, globalLogger, logging.filter, args...) logging.println(severity.WarningLog, logging.logger, logging.filter, args...)
} }
// WarninglnDepth acts as Warningln but uses depth to determine which call frame to log. // WarninglnDepth acts as Warningln but uses depth to determine which call frame to log.
// WarninglnDepth(0, "msg") is the same as Warningln("msg"). // WarninglnDepth(0, "msg") is the same as Warningln("msg").
func WarninglnDepth(depth int, args ...interface{}) { func WarninglnDepth(depth int, args ...interface{}) {
logging.printlnDepth(severity.WarningLog, globalLogger, logging.filter, depth, args...) logging.printlnDepth(severity.WarningLog, logging.logger, logging.filter, depth, args...)
} }
// Warningf logs to the WARNING and INFO logs. // Warningf logs to the WARNING and INFO logs.
// Arguments are handled in the manner of fmt.Printf; a newline is appended if missing. // Arguments are handled in the manner of fmt.Printf; a newline is appended if missing.
func Warningf(format string, args ...interface{}) { func Warningf(format string, args ...interface{}) {
logging.printf(severity.WarningLog, globalLogger, logging.filter, format, args...) logging.printf(severity.WarningLog, logging.logger, logging.filter, format, args...)
} }
// WarningfDepth acts as Warningf but uses depth to determine which call frame to log. // WarningfDepth acts as Warningf but uses depth to determine which call frame to log.
// WarningfDepth(0, "msg", args...) is the same as Warningf("msg", args...). // WarningfDepth(0, "msg", args...) is the same as Warningf("msg", args...).
func WarningfDepth(depth int, format string, args ...interface{}) { func WarningfDepth(depth int, format string, args ...interface{}) {
logging.printfDepth(severity.WarningLog, globalLogger, logging.filter, depth, format, args...) logging.printfDepth(severity.WarningLog, logging.logger, logging.filter, depth, format, args...)
} }
// Error logs to the ERROR, WARNING, and INFO logs. // Error logs to the ERROR, WARNING, and INFO logs.
// Arguments are handled in the manner of fmt.Print; a newline is appended if missing. // Arguments are handled in the manner of fmt.Print; a newline is appended if missing.
func Error(args ...interface{}) { func Error(args ...interface{}) {
logging.print(severity.ErrorLog, globalLogger, logging.filter, args...) logging.print(severity.ErrorLog, logging.logger, logging.filter, args...)
} }
// ErrorDepth acts as Error but uses depth to determine which call frame to log. // ErrorDepth acts as Error but uses depth to determine which call frame to log.
// ErrorDepth(0, "msg") is the same as Error("msg"). // ErrorDepth(0, "msg") is the same as Error("msg").
func ErrorDepth(depth int, args ...interface{}) { func ErrorDepth(depth int, args ...interface{}) {
logging.printDepth(severity.ErrorLog, globalLogger, logging.filter, depth, args...) logging.printDepth(severity.ErrorLog, logging.logger, logging.filter, depth, args...)
} }
// Errorln logs to the ERROR, WARNING, and INFO logs. // Errorln logs to the ERROR, WARNING, and INFO logs.
// Arguments are handled in the manner of fmt.Println; a newline is always appended. // Arguments are handled in the manner of fmt.Println; a newline is always appended.
func Errorln(args ...interface{}) { func Errorln(args ...interface{}) {
logging.println(severity.ErrorLog, globalLogger, logging.filter, args...) logging.println(severity.ErrorLog, logging.logger, logging.filter, args...)
} }
// ErrorlnDepth acts as Errorln but uses depth to determine which call frame to log. // ErrorlnDepth acts as Errorln but uses depth to determine which call frame to log.
// ErrorlnDepth(0, "msg") is the same as Errorln("msg"). // ErrorlnDepth(0, "msg") is the same as Errorln("msg").
func ErrorlnDepth(depth int, args ...interface{}) { func ErrorlnDepth(depth int, args ...interface{}) {
logging.printlnDepth(severity.ErrorLog, globalLogger, logging.filter, depth, args...) logging.printlnDepth(severity.ErrorLog, logging.logger, logging.filter, depth, args...)
} }
// Errorf logs to the ERROR, WARNING, and INFO logs. // Errorf logs to the ERROR, WARNING, and INFO logs.
// Arguments are handled in the manner of fmt.Printf; a newline is appended if missing. // Arguments are handled in the manner of fmt.Printf; a newline is appended if missing.
func Errorf(format string, args ...interface{}) { func Errorf(format string, args ...interface{}) {
logging.printf(severity.ErrorLog, globalLogger, logging.filter, format, args...) logging.printf(severity.ErrorLog, logging.logger, logging.filter, format, args...)
} }
// ErrorfDepth acts as Errorf but uses depth to determine which call frame to log. // ErrorfDepth acts as Errorf but uses depth to determine which call frame to log.
// ErrorfDepth(0, "msg", args...) is the same as Errorf("msg", args...). // ErrorfDepth(0, "msg", args...) is the same as Errorf("msg", args...).
func ErrorfDepth(depth int, format string, args ...interface{}) { func ErrorfDepth(depth int, format string, args ...interface{}) {
logging.printfDepth(severity.ErrorLog, globalLogger, logging.filter, depth, format, args...) logging.printfDepth(severity.ErrorLog, logging.logger, logging.filter, depth, format, args...)
} }
// ErrorS structured logs to the ERROR, WARNING, and INFO logs. // ErrorS structured logs to the ERROR, WARNING, and INFO logs.
@ -1474,52 +1565,63 @@ func ErrorfDepth(depth int, format string, args ...interface{}) {
// output: // output:
// >> E1025 00:15:15.525108 1 controller_utils.go:114] "Failed to update pod status" err="timeout" // >> E1025 00:15:15.525108 1 controller_utils.go:114] "Failed to update pod status" err="timeout"
func ErrorS(err error, msg string, keysAndValues ...interface{}) { func ErrorS(err error, msg string, keysAndValues ...interface{}) {
logging.errorS(err, globalLogger, logging.filter, 0, msg, keysAndValues...) logging.errorS(err, logging.logger, logging.filter, 0, msg, keysAndValues...)
} }
// ErrorSDepth acts as ErrorS but uses depth to determine which call frame to log. // ErrorSDepth acts as ErrorS but uses depth to determine which call frame to log.
// ErrorSDepth(0, "msg") is the same as ErrorS("msg"). // ErrorSDepth(0, "msg") is the same as ErrorS("msg").
func ErrorSDepth(depth int, err error, msg string, keysAndValues ...interface{}) { func ErrorSDepth(depth int, err error, msg string, keysAndValues ...interface{}) {
logging.errorS(err, globalLogger, logging.filter, depth, msg, keysAndValues...) logging.errorS(err, logging.logger, logging.filter, depth, msg, keysAndValues...)
} }
// Fatal logs to the FATAL, ERROR, WARNING, and INFO logs, // Fatal logs to the FATAL, ERROR, WARNING, and INFO logs,
// including a stack trace of all running goroutines, then calls OsExit(255). // prints stack trace(s), then calls OsExit(255).
//
// Stderr only receives a dump of the current goroutine's stack trace. Log files,
// if there are any, receive a dump of the stack traces in all goroutines.
//
// Callers who want more control over handling of fatal events may instead use a
// combination of different functions:
// - some info or error logging function, optionally with a stack trace
// value generated by github.com/go-logr/lib/dbg.Backtrace
// - Flush to flush pending log data
// - panic, os.Exit or returning to the caller with an error
//
// Arguments are handled in the manner of fmt.Print; a newline is appended if missing. // Arguments are handled in the manner of fmt.Print; a newline is appended if missing.
func Fatal(args ...interface{}) { func Fatal(args ...interface{}) {
logging.print(severity.FatalLog, globalLogger, logging.filter, args...) logging.print(severity.FatalLog, logging.logger, logging.filter, args...)
} }
// FatalDepth acts as Fatal but uses depth to determine which call frame to log. // FatalDepth acts as Fatal but uses depth to determine which call frame to log.
// FatalDepth(0, "msg") is the same as Fatal("msg"). // FatalDepth(0, "msg") is the same as Fatal("msg").
func FatalDepth(depth int, args ...interface{}) { func FatalDepth(depth int, args ...interface{}) {
logging.printDepth(severity.FatalLog, globalLogger, logging.filter, depth, args...) logging.printDepth(severity.FatalLog, logging.logger, logging.filter, depth, args...)
} }
// Fatalln logs to the FATAL, ERROR, WARNING, and INFO logs, // Fatalln logs to the FATAL, ERROR, WARNING, and INFO logs,
// including a stack trace of all running goroutines, then calls OsExit(255). // including a stack trace of all running goroutines, then calls OsExit(255).
// Arguments are handled in the manner of fmt.Println; a newline is always appended. // Arguments are handled in the manner of fmt.Println; a newline is always appended.
func Fatalln(args ...interface{}) { func Fatalln(args ...interface{}) {
logging.println(severity.FatalLog, globalLogger, logging.filter, args...) logging.println(severity.FatalLog, logging.logger, logging.filter, args...)
} }
// FatallnDepth acts as Fatalln but uses depth to determine which call frame to log. // FatallnDepth acts as Fatalln but uses depth to determine which call frame to log.
// FatallnDepth(0, "msg") is the same as Fatalln("msg"). // FatallnDepth(0, "msg") is the same as Fatalln("msg").
func FatallnDepth(depth int, args ...interface{}) { func FatallnDepth(depth int, args ...interface{}) {
logging.printlnDepth(severity.FatalLog, globalLogger, logging.filter, depth, args...) logging.printlnDepth(severity.FatalLog, logging.logger, logging.filter, depth, args...)
} }
// Fatalf logs to the FATAL, ERROR, WARNING, and INFO logs, // Fatalf logs to the FATAL, ERROR, WARNING, and INFO logs,
// including a stack trace of all running goroutines, then calls OsExit(255). // including a stack trace of all running goroutines, then calls OsExit(255).
// Arguments are handled in the manner of fmt.Printf; a newline is appended if missing. // Arguments are handled in the manner of fmt.Printf; a newline is appended if missing.
func Fatalf(format string, args ...interface{}) { func Fatalf(format string, args ...interface{}) {
logging.printf(severity.FatalLog, globalLogger, logging.filter, format, args...) logging.printf(severity.FatalLog, logging.logger, logging.filter, format, args...)
} }
// FatalfDepth acts as Fatalf but uses depth to determine which call frame to log. // FatalfDepth acts as Fatalf but uses depth to determine which call frame to log.
// FatalfDepth(0, "msg", args...) is the same as Fatalf("msg", args...). // FatalfDepth(0, "msg", args...) is the same as Fatalf("msg", args...).
func FatalfDepth(depth int, format string, args ...interface{}) { func FatalfDepth(depth int, format string, args ...interface{}) {
logging.printfDepth(severity.FatalLog, globalLogger, logging.filter, depth, format, args...) logging.printfDepth(severity.FatalLog, logging.logger, logging.filter, depth, format, args...)
} }
// fatalNoStacks is non-zero if we are to exit without dumping goroutine stacks. // fatalNoStacks is non-zero if we are to exit without dumping goroutine stacks.
@ -1530,41 +1632,41 @@ var fatalNoStacks uint32
// Arguments are handled in the manner of fmt.Print; a newline is appended if missing. // Arguments are handled in the manner of fmt.Print; a newline is appended if missing.
func Exit(args ...interface{}) { func Exit(args ...interface{}) {
atomic.StoreUint32(&fatalNoStacks, 1) atomic.StoreUint32(&fatalNoStacks, 1)
logging.print(severity.FatalLog, globalLogger, logging.filter, args...) logging.print(severity.FatalLog, logging.logger, logging.filter, args...)
} }
// ExitDepth acts as Exit but uses depth to determine which call frame to log. // ExitDepth acts as Exit but uses depth to determine which call frame to log.
// ExitDepth(0, "msg") is the same as Exit("msg"). // ExitDepth(0, "msg") is the same as Exit("msg").
func ExitDepth(depth int, args ...interface{}) { func ExitDepth(depth int, args ...interface{}) {
atomic.StoreUint32(&fatalNoStacks, 1) atomic.StoreUint32(&fatalNoStacks, 1)
logging.printDepth(severity.FatalLog, globalLogger, logging.filter, depth, args...) logging.printDepth(severity.FatalLog, logging.logger, logging.filter, depth, args...)
} }
// Exitln logs to the FATAL, ERROR, WARNING, and INFO logs, then calls OsExit(1). // Exitln logs to the FATAL, ERROR, WARNING, and INFO logs, then calls OsExit(1).
func Exitln(args ...interface{}) { func Exitln(args ...interface{}) {
atomic.StoreUint32(&fatalNoStacks, 1) atomic.StoreUint32(&fatalNoStacks, 1)
logging.println(severity.FatalLog, globalLogger, logging.filter, args...) logging.println(severity.FatalLog, logging.logger, logging.filter, args...)
} }
// ExitlnDepth acts as Exitln but uses depth to determine which call frame to log. // ExitlnDepth acts as Exitln but uses depth to determine which call frame to log.
// ExitlnDepth(0, "msg") is the same as Exitln("msg"). // ExitlnDepth(0, "msg") is the same as Exitln("msg").
func ExitlnDepth(depth int, args ...interface{}) { func ExitlnDepth(depth int, args ...interface{}) {
atomic.StoreUint32(&fatalNoStacks, 1) atomic.StoreUint32(&fatalNoStacks, 1)
logging.printlnDepth(severity.FatalLog, globalLogger, logging.filter, depth, args...) logging.printlnDepth(severity.FatalLog, logging.logger, logging.filter, depth, args...)
} }
// Exitf logs to the FATAL, ERROR, WARNING, and INFO logs, then calls OsExit(1). // Exitf logs to the FATAL, ERROR, WARNING, and INFO logs, then calls OsExit(1).
// Arguments are handled in the manner of fmt.Printf; a newline is appended if missing. // Arguments are handled in the manner of fmt.Printf; a newline is appended if missing.
func Exitf(format string, args ...interface{}) { func Exitf(format string, args ...interface{}) {
atomic.StoreUint32(&fatalNoStacks, 1) atomic.StoreUint32(&fatalNoStacks, 1)
logging.printf(severity.FatalLog, globalLogger, logging.filter, format, args...) logging.printf(severity.FatalLog, logging.logger, logging.filter, format, args...)
} }
// ExitfDepth acts as Exitf but uses depth to determine which call frame to log. // ExitfDepth acts as Exitf but uses depth to determine which call frame to log.
// ExitfDepth(0, "msg", args...) is the same as Exitf("msg", args...). // ExitfDepth(0, "msg", args...) is the same as Exitf("msg", args...).
func ExitfDepth(depth int, format string, args ...interface{}) { func ExitfDepth(depth int, format string, args ...interface{}) {
atomic.StoreUint32(&fatalNoStacks, 1) atomic.StoreUint32(&fatalNoStacks, 1)
logging.printfDepth(severity.FatalLog, globalLogger, logging.filter, depth, format, args...) logging.printfDepth(severity.FatalLog, logging.logger, logging.filter, depth, format, args...)
} }
// LogFilter is a collection of functions that can filter all logging calls, // LogFilter is a collection of functions that can filter all logging calls,

8
vendor/k8s.io/klog/v2/klogr.go generated vendored
View File

@ -43,11 +43,11 @@ func (l *klogger) Init(info logr.RuntimeInfo) {
} }
func (l klogger) Info(level int, msg string, kvList ...interface{}) { func (l klogger) Info(level int, msg string, kvList ...interface{}) {
trimmed := serialize.TrimDuplicates(l.values, kvList) merged := serialize.MergeKVs(l.values, kvList)
if l.prefix != "" { if l.prefix != "" {
msg = l.prefix + ": " + msg msg = l.prefix + ": " + msg
} }
V(Level(level)).InfoSDepth(l.callDepth+1, msg, append(trimmed[0], trimmed[1]...)...) V(Level(level)).InfoSDepth(l.callDepth+1, msg, merged...)
} }
func (l klogger) Enabled(level int) bool { func (l klogger) Enabled(level int) bool {
@ -55,11 +55,11 @@ func (l klogger) Enabled(level int) bool {
} }
func (l klogger) Error(err error, msg string, kvList ...interface{}) { func (l klogger) Error(err error, msg string, kvList ...interface{}) {
trimmed := serialize.TrimDuplicates(l.values, kvList) merged := serialize.MergeKVs(l.values, kvList)
if l.prefix != "" { if l.prefix != "" {
msg = l.prefix + ": " + msg msg = l.prefix + ": " + msg
} }
ErrorSDepth(l.callDepth+1, err, msg, append(trimmed[0], trimmed[1]...)...) ErrorSDepth(l.callDepth+1, err, msg, merged...)
} }
// WithName returns a new logr.Logger with the specified name appended. klogr // WithName returns a new logr.Logger with the specified name appended. klogr

3
vendor/modules.txt vendored
View File

@ -1185,11 +1185,12 @@ k8s.io/component-base/version
k8s.io/component-helpers/node/util/sysctl k8s.io/component-helpers/node/util/sysctl
k8s.io/component-helpers/scheduling/corev1 k8s.io/component-helpers/scheduling/corev1
k8s.io/component-helpers/scheduling/corev1/nodeaffinity k8s.io/component-helpers/scheduling/corev1/nodeaffinity
# k8s.io/klog/v2 v2.60.1 # k8s.io/klog/v2 v2.70.1
## explicit; go 1.13 ## explicit; go 1.13
k8s.io/klog/v2 k8s.io/klog/v2
k8s.io/klog/v2/internal/buffer k8s.io/klog/v2/internal/buffer
k8s.io/klog/v2/internal/clock k8s.io/klog/v2/internal/clock
k8s.io/klog/v2/internal/dbg
k8s.io/klog/v2/internal/serialize k8s.io/klog/v2/internal/serialize
k8s.io/klog/v2/internal/severity k8s.io/klog/v2/internal/severity
# k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42 # k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42