mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-06-13 10:33:35 +00:00
rebase: update kubernetes to 1.30
updating kubernetes to 1.30 release Signed-off-by: Madhu Rajanna <madhupr007@gmail.com>
This commit is contained in:
committed by
mergify[bot]
parent
62ddcf715b
commit
e727bd351e
303
vendor/k8s.io/klog/v2/internal/verbosity/verbosity.go
generated
vendored
Normal file
303
vendor/k8s.io/klog/v2/internal/verbosity/verbosity.go
generated
vendored
Normal file
@ -0,0 +1,303 @@
|
||||
/*
|
||||
Copyright 2013 Google Inc. All Rights Reserved.
|
||||
Copyright 2022 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 verbosity
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
// New returns a struct that implements -v and -vmodule support. Changing and
|
||||
// checking these settings is thread-safe, with all concurrency issues handled
|
||||
// internally.
|
||||
func New() *VState {
|
||||
vs := new(VState)
|
||||
|
||||
// The two fields must have a pointer to the overal struct for their
|
||||
// implementation of Set.
|
||||
vs.vmodule.vs = vs
|
||||
vs.verbosity.vs = vs
|
||||
|
||||
return vs
|
||||
}
|
||||
|
||||
// Value is an extension that makes it possible to use the values in pflag.
|
||||
type Value interface {
|
||||
flag.Value
|
||||
Type() string
|
||||
}
|
||||
|
||||
func (vs *VState) V() Value {
|
||||
return &vs.verbosity
|
||||
}
|
||||
|
||||
func (vs *VState) VModule() Value {
|
||||
return &vs.vmodule
|
||||
}
|
||||
|
||||
// VState contains settings and state. Some of its fields can be accessed
|
||||
// through atomic read/writes, in other cases a mutex must be held.
|
||||
type VState struct {
|
||||
mu sync.Mutex
|
||||
|
||||
// These flags are modified only under lock, although verbosity may be fetched
|
||||
// safely using atomic.LoadInt32.
|
||||
vmodule moduleSpec // The state of the -vmodule flag.
|
||||
verbosity levelSpec // V logging level, the value of the -v flag/
|
||||
|
||||
// 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
|
||||
// than zero, it means vmodule is enabled. It may be read safely
|
||||
// using sync.LoadInt32, but is only modified under mu.
|
||||
filterLength int32
|
||||
}
|
||||
|
||||
// Level must be an int32 to support atomic read/writes.
|
||||
type Level int32
|
||||
|
||||
type levelSpec struct {
|
||||
vs *VState
|
||||
l Level
|
||||
}
|
||||
|
||||
// get returns the value of the level.
|
||||
func (l *levelSpec) get() Level {
|
||||
return Level(atomic.LoadInt32((*int32)(&l.l)))
|
||||
}
|
||||
|
||||
// set sets the value of the level.
|
||||
func (l *levelSpec) set(val Level) {
|
||||
atomic.StoreInt32((*int32)(&l.l), int32(val))
|
||||
}
|
||||
|
||||
// String is part of the flag.Value interface.
|
||||
func (l *levelSpec) String() string {
|
||||
return strconv.FormatInt(int64(l.l), 10)
|
||||
}
|
||||
|
||||
// Get is part of the flag.Getter interface. It returns the
|
||||
// verbosity level as int32.
|
||||
func (l *levelSpec) Get() interface{} {
|
||||
return int32(l.l)
|
||||
}
|
||||
|
||||
// Type is part of pflag.Value.
|
||||
func (l *levelSpec) Type() string {
|
||||
return "Level"
|
||||
}
|
||||
|
||||
// Set is part of the flag.Value interface.
|
||||
func (l *levelSpec) Set(value string) error {
|
||||
v, err := strconv.ParseInt(value, 10, 32)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
l.vs.mu.Lock()
|
||||
defer l.vs.mu.Unlock()
|
||||
l.vs.set(Level(v), l.vs.vmodule.filter, false)
|
||||
return nil
|
||||
}
|
||||
|
||||
// moduleSpec represents the setting of the -vmodule flag.
|
||||
type moduleSpec struct {
|
||||
vs *VState
|
||||
filter []modulePat
|
||||
}
|
||||
|
||||
// modulePat contains a filter for the -vmodule flag.
|
||||
// It holds a verbosity level and a file pattern to match.
|
||||
type modulePat struct {
|
||||
pattern string
|
||||
literal bool // The pattern is a literal string
|
||||
level Level
|
||||
}
|
||||
|
||||
// match reports whether the file matches the pattern. It uses a string
|
||||
// comparison if the pattern contains no metacharacters.
|
||||
func (m *modulePat) match(file string) bool {
|
||||
if m.literal {
|
||||
return file == m.pattern
|
||||
}
|
||||
match, _ := filepath.Match(m.pattern, file)
|
||||
return match
|
||||
}
|
||||
|
||||
func (m *moduleSpec) String() string {
|
||||
// Lock because the type is not atomic. TODO: clean this up.
|
||||
// Empty instances don't have and don't need a lock (can
|
||||
// happen when flag uses introspection).
|
||||
if m.vs != nil {
|
||||
m.vs.mu.Lock()
|
||||
defer m.vs.mu.Unlock()
|
||||
}
|
||||
var b bytes.Buffer
|
||||
for i, f := range m.filter {
|
||||
if i > 0 {
|
||||
b.WriteRune(',')
|
||||
}
|
||||
fmt.Fprintf(&b, "%s=%d", f.pattern, f.level)
|
||||
}
|
||||
return b.String()
|
||||
}
|
||||
|
||||
// Get is part of the (Go 1.2) flag.Getter interface. It always returns nil for this flag type since the
|
||||
// struct is not exported.
|
||||
func (m *moduleSpec) Get() interface{} {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Type is part of pflag.Value
|
||||
func (m *moduleSpec) Type() string {
|
||||
return "pattern=N,..."
|
||||
}
|
||||
|
||||
var errVmoduleSyntax = errors.New("syntax error: expect comma-separated list of filename=N")
|
||||
|
||||
// Set will sets module value
|
||||
// Syntax: -vmodule=recordio=2,file=1,gfs*=3
|
||||
func (m *moduleSpec) Set(value string) error {
|
||||
var filter []modulePat
|
||||
for _, pat := range strings.Split(value, ",") {
|
||||
if len(pat) == 0 {
|
||||
// Empty strings such as from a trailing comma can be ignored.
|
||||
continue
|
||||
}
|
||||
patLev := strings.Split(pat, "=")
|
||||
if len(patLev) != 2 || len(patLev[0]) == 0 || len(patLev[1]) == 0 {
|
||||
return errVmoduleSyntax
|
||||
}
|
||||
pattern := patLev[0]
|
||||
v, err := strconv.ParseInt(patLev[1], 10, 32)
|
||||
if err != nil {
|
||||
return errors.New("syntax error: expect comma-separated list of filename=N")
|
||||
}
|
||||
if v < 0 {
|
||||
return errors.New("negative value for vmodule level")
|
||||
}
|
||||
if v == 0 {
|
||||
continue // Ignore. It's harmless but no point in paying the overhead.
|
||||
}
|
||||
// TODO: check syntax of filter?
|
||||
filter = append(filter, modulePat{pattern, isLiteral(pattern), Level(v)})
|
||||
}
|
||||
m.vs.mu.Lock()
|
||||
defer m.vs.mu.Unlock()
|
||||
m.vs.set(m.vs.verbosity.l, filter, true)
|
||||
return nil
|
||||
}
|
||||
|
||||
// isLiteral reports whether the pattern is a literal string, that is, has no metacharacters
|
||||
// that require filepath.Match to be called to match the pattern.
|
||||
func isLiteral(pattern string) bool {
|
||||
return !strings.ContainsAny(pattern, `\*?[]`)
|
||||
}
|
||||
|
||||
// set sets a consistent state for V logging.
|
||||
// The mutex must be held.
|
||||
func (vs *VState) set(l Level, filter []modulePat, setFilter bool) {
|
||||
// Turn verbosity off so V will not fire while we are in transition.
|
||||
vs.verbosity.set(0)
|
||||
// Ditto for filter length.
|
||||
atomic.StoreInt32(&vs.filterLength, 0)
|
||||
|
||||
// Set the new filters and wipe the pc->Level map if the filter has changed.
|
||||
if setFilter {
|
||||
vs.vmodule.filter = filter
|
||||
vs.vmap = make(map[uintptr]Level)
|
||||
}
|
||||
|
||||
// Things are consistent now, so enable filtering and verbosity.
|
||||
// They are enabled in order opposite to that in V.
|
||||
atomic.StoreInt32(&vs.filterLength, int32(len(filter)))
|
||||
vs.verbosity.set(l)
|
||||
}
|
||||
|
||||
// Enabled checks whether logging is enabled at the given level. This must be
|
||||
// called with depth=0 when the caller of enabled will do the logging and
|
||||
// higher values when more stack levels need to be skipped.
|
||||
//
|
||||
// The mutex will be locked only if needed.
|
||||
func (vs *VState) Enabled(level Level, depth int) bool {
|
||||
// This function tries hard to be cheap unless there's work to do.
|
||||
// The fast path is two atomic loads and compares.
|
||||
|
||||
// Here is a cheap but safe test to see if V logging is enabled globally.
|
||||
if vs.verbosity.get() >= level {
|
||||
return true
|
||||
}
|
||||
|
||||
// It's off globally but vmodule may still be set.
|
||||
// Here is another cheap but safe test to see if vmodule is enabled.
|
||||
if atomic.LoadInt32(&vs.filterLength) > 0 {
|
||||
// Now we need a proper lock to use the logging structure. The pcs field
|
||||
// is shared so we must lock before accessing it. This is fairly expensive,
|
||||
// but if V logging is enabled we're slow anyway.
|
||||
vs.mu.Lock()
|
||||
defer vs.mu.Unlock()
|
||||
if runtime.Callers(depth+2, vs.pcs[:]) == 0 {
|
||||
return false
|
||||
}
|
||||
// runtime.Callers returns "return PCs", but we want
|
||||
// to look up the symbolic information for the call,
|
||||
// so subtract 1 from the PC. runtime.CallersFrames
|
||||
// would be cleaner, but allocates.
|
||||
pc := vs.pcs[0] - 1
|
||||
v, ok := vs.vmap[pc]
|
||||
if !ok {
|
||||
v = vs.setV(pc)
|
||||
}
|
||||
return v >= level
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// setV computes and remembers the V level for a given PC
|
||||
// when vmodule is enabled.
|
||||
// File pattern matching takes the basename of the file, stripped
|
||||
// of its .go suffix, and uses filepath.Match, which is a little more
|
||||
// general than the *? matching used in C++.
|
||||
// Mutex is held.
|
||||
func (vs *VState) setV(pc uintptr) Level {
|
||||
fn := runtime.FuncForPC(pc)
|
||||
file, _ := fn.FileLine(pc)
|
||||
// The file is something like /a/b/c/d.go. We want just the d.
|
||||
file = strings.TrimSuffix(file, ".go")
|
||||
if slash := strings.LastIndex(file, "/"); slash >= 0 {
|
||||
file = file[slash+1:]
|
||||
}
|
||||
for _, filter := range vs.vmodule.filter {
|
||||
if filter.match(file) {
|
||||
vs.vmap[pc] = filter.level
|
||||
return filter.level
|
||||
}
|
||||
}
|
||||
vs.vmap[pc] = 0
|
||||
return 0
|
||||
}
|
154
vendor/k8s.io/klog/v2/textlogger/options.go
generated
vendored
Normal file
154
vendor/k8s.io/klog/v2/textlogger/options.go
generated
vendored
Normal file
@ -0,0 +1,154 @@
|
||||
/*
|
||||
Copyright 2021 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 textlogger
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"io"
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"k8s.io/klog/v2/internal/verbosity"
|
||||
)
|
||||
|
||||
// Config influences logging in a text logger. To make this configurable via
|
||||
// command line flags, instantiate this once per program and use AddFlags to
|
||||
// bind command line flags to the instance before passing it to NewTestContext.
|
||||
//
|
||||
// Must be constructed with NewConfig.
|
||||
type Config struct {
|
||||
vstate *verbosity.VState
|
||||
co configOptions
|
||||
}
|
||||
|
||||
// Verbosity returns a value instance that can be used to query (via String) or
|
||||
// modify (via Set) the verbosity threshold. This is thread-safe and can be
|
||||
// done at runtime.
|
||||
func (c *Config) Verbosity() flag.Value {
|
||||
return c.vstate.V()
|
||||
}
|
||||
|
||||
// VModule returns a value instance that can be used to query (via String) or
|
||||
// modify (via Set) the vmodule settings. This is thread-safe and can be done
|
||||
// at runtime.
|
||||
func (c *Config) VModule() flag.Value {
|
||||
return c.vstate.VModule()
|
||||
}
|
||||
|
||||
// ConfigOption implements functional parameters for NewConfig.
|
||||
type ConfigOption func(co *configOptions)
|
||||
|
||||
type configOptions struct {
|
||||
verbosityFlagName string
|
||||
vmoduleFlagName string
|
||||
verbosityDefault int
|
||||
fixedTime *time.Time
|
||||
unwind func(int) (string, int)
|
||||
output io.Writer
|
||||
}
|
||||
|
||||
// VerbosityFlagName overrides the default -v for the verbosity level.
|
||||
func VerbosityFlagName(name string) ConfigOption {
|
||||
return func(co *configOptions) {
|
||||
|
||||
co.verbosityFlagName = name
|
||||
}
|
||||
}
|
||||
|
||||
// VModulFlagName overrides the default -vmodule for the per-module
|
||||
// verbosity levels.
|
||||
func VModuleFlagName(name string) ConfigOption {
|
||||
return func(co *configOptions) {
|
||||
co.vmoduleFlagName = name
|
||||
}
|
||||
}
|
||||
|
||||
// Verbosity overrides the default verbosity level of 0.
|
||||
// See https://github.com/kubernetes/community/blob/9406b4352fe2d5810cb21cc3cb059ce5886de157/contributors/devel/sig-instrumentation/logging.md#logging-conventions
|
||||
// for log level conventions in Kubernetes.
|
||||
func Verbosity(level int) ConfigOption {
|
||||
return func(co *configOptions) {
|
||||
co.verbosityDefault = level
|
||||
}
|
||||
}
|
||||
|
||||
// Output overrides stderr as the output stream.
|
||||
func Output(output io.Writer) ConfigOption {
|
||||
return func(co *configOptions) {
|
||||
co.output = output
|
||||
}
|
||||
}
|
||||
|
||||
// FixedTime overrides the actual time with a fixed time. Useful only for testing.
|
||||
//
|
||||
// # Experimental
|
||||
//
|
||||
// Notice: This function is EXPERIMENTAL and may be changed or removed in a
|
||||
// later release.
|
||||
func FixedTime(ts time.Time) ConfigOption {
|
||||
return func(co *configOptions) {
|
||||
co.fixedTime = &ts
|
||||
}
|
||||
}
|
||||
|
||||
// Backtrace overrides the default mechanism for determining the call site.
|
||||
// The callback is invoked with the number of function calls between itself
|
||||
// and the call site. It must return the file name and line number. An empty
|
||||
// file name indicates that the information is unknown.
|
||||
//
|
||||
// # Experimental
|
||||
//
|
||||
// Notice: This function is EXPERIMENTAL and may be changed or removed in a
|
||||
// later release.
|
||||
func Backtrace(unwind func(skip int) (filename string, line int)) ConfigOption {
|
||||
return func(co *configOptions) {
|
||||
co.unwind = unwind
|
||||
}
|
||||
}
|
||||
|
||||
// NewConfig returns a configuration with recommended defaults and optional
|
||||
// modifications. Command line flags are not bound to any FlagSet yet.
|
||||
func NewConfig(opts ...ConfigOption) *Config {
|
||||
c := &Config{
|
||||
vstate: verbosity.New(),
|
||||
co: configOptions{
|
||||
verbosityFlagName: "v",
|
||||
vmoduleFlagName: "vmodule",
|
||||
verbosityDefault: 0,
|
||||
unwind: runtimeBacktrace,
|
||||
output: os.Stderr,
|
||||
},
|
||||
}
|
||||
for _, opt := range opts {
|
||||
opt(&c.co)
|
||||
}
|
||||
|
||||
// Cannot fail for this input.
|
||||
_ = c.Verbosity().Set(strconv.FormatInt(int64(c.co.verbosityDefault), 10))
|
||||
return c
|
||||
}
|
||||
|
||||
// AddFlags registers the command line flags that control the configuration.
|
||||
//
|
||||
// The default flag names are the same as in klog, so unless those defaults
|
||||
// are changed, either klog.InitFlags or Config.AddFlags can be used for the
|
||||
// same flag set, but not both.
|
||||
func (c *Config) AddFlags(fs *flag.FlagSet) {
|
||||
fs.Var(c.Verbosity(), c.co.verbosityFlagName, "number for the log level verbosity of the testing logger")
|
||||
fs.Var(c.VModule(), c.co.vmoduleFlagName, "comma-separated list of pattern=N log level settings for files matching the patterns")
|
||||
}
|
187
vendor/k8s.io/klog/v2/textlogger/textlogger.go
generated
vendored
Normal file
187
vendor/k8s.io/klog/v2/textlogger/textlogger.go
generated
vendored
Normal file
@ -0,0 +1,187 @@
|
||||
/*
|
||||
Copyright 2019 The Kubernetes Authors.
|
||||
Copyright 2020 Intel Coporation.
|
||||
|
||||
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 textlogger contains an implementation of the logr interface which is
|
||||
// producing the exact same output as klog. It does not route output through
|
||||
// klog (i.e. ignores [k8s.io/klog/v2.InitFlags]). Instead, all settings must be
|
||||
// configured through its own [NewConfig] and [Config.AddFlags].
|
||||
package textlogger
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
|
||||
"k8s.io/klog/v2/internal/buffer"
|
||||
"k8s.io/klog/v2/internal/serialize"
|
||||
"k8s.io/klog/v2/internal/severity"
|
||||
"k8s.io/klog/v2/internal/verbosity"
|
||||
)
|
||||
|
||||
var (
|
||||
// TimeNow is used to retrieve the current time. May be changed for testing.
|
||||
TimeNow = time.Now
|
||||
)
|
||||
|
||||
const (
|
||||
// nameKey is used to log the `WithName` values as an additional attribute.
|
||||
nameKey = "logger"
|
||||
)
|
||||
|
||||
// NewLogger constructs a new logger.
|
||||
//
|
||||
// Verbosity can be modified at any time through the Config.V and
|
||||
// Config.VModule API.
|
||||
func NewLogger(c *Config) logr.Logger {
|
||||
return logr.New(&tlogger{
|
||||
values: nil,
|
||||
config: c,
|
||||
})
|
||||
}
|
||||
|
||||
type tlogger struct {
|
||||
callDepth int
|
||||
|
||||
// hasPrefix is true if the first entry in values is the special
|
||||
// nameKey key/value. Such an entry gets added and later updated in
|
||||
// WithName.
|
||||
hasPrefix bool
|
||||
|
||||
values []interface{}
|
||||
groups string
|
||||
config *Config
|
||||
}
|
||||
|
||||
func (l *tlogger) Init(info logr.RuntimeInfo) {
|
||||
l.callDepth = info.CallDepth
|
||||
}
|
||||
|
||||
func (l *tlogger) WithCallDepth(depth int) logr.LogSink {
|
||||
newLogger := *l
|
||||
newLogger.callDepth += depth
|
||||
return &newLogger
|
||||
}
|
||||
|
||||
func (l *tlogger) Enabled(level int) bool {
|
||||
return l.config.vstate.Enabled(verbosity.Level(level), 1+l.callDepth)
|
||||
}
|
||||
|
||||
func (l *tlogger) Info(_ int, msg string, kvList ...interface{}) {
|
||||
l.print(nil, severity.InfoLog, msg, kvList)
|
||||
}
|
||||
|
||||
func (l *tlogger) Error(err error, msg string, kvList ...interface{}) {
|
||||
l.print(err, severity.ErrorLog, msg, kvList)
|
||||
}
|
||||
|
||||
func (l *tlogger) print(err error, s severity.Severity, msg string, kvList []interface{}) {
|
||||
// Determine caller.
|
||||
// +1 for this frame, +1 for Info/Error.
|
||||
skip := l.callDepth + 2
|
||||
file, line := l.config.co.unwind(skip)
|
||||
if file == "" {
|
||||
file = "???"
|
||||
line = 1
|
||||
} else if slash := strings.LastIndex(file, "/"); slash >= 0 {
|
||||
file = file[slash+1:]
|
||||
}
|
||||
l.printWithInfos(file, line, time.Now(), err, s, msg, kvList)
|
||||
}
|
||||
|
||||
func runtimeBacktrace(skip int) (string, int) {
|
||||
_, file, line, ok := runtime.Caller(skip + 1)
|
||||
if !ok {
|
||||
return "", 0
|
||||
}
|
||||
return file, line
|
||||
}
|
||||
|
||||
func (l *tlogger) printWithInfos(file string, line int, now time.Time, err error, s severity.Severity, msg string, kvList []interface{}) {
|
||||
// Only create a new buffer if we don't have one cached.
|
||||
b := buffer.GetBuffer()
|
||||
defer buffer.PutBuffer(b)
|
||||
|
||||
// Format header.
|
||||
if l.config.co.fixedTime != nil {
|
||||
now = *l.config.co.fixedTime
|
||||
}
|
||||
b.FormatHeader(s, file, line, now)
|
||||
|
||||
// The message is always quoted, even if it contains line breaks.
|
||||
// If developers want multi-line output, they should use a small, fixed
|
||||
// message and put the multi-line output into a value.
|
||||
b.WriteString(strconv.Quote(msg))
|
||||
if err != nil {
|
||||
serialize.KVFormat(&b.Buffer, "err", err)
|
||||
}
|
||||
serialize.MergeAndFormatKVs(&b.Buffer, l.values, kvList)
|
||||
if b.Len() == 0 || b.Bytes()[b.Len()-1] != '\n' {
|
||||
b.WriteByte('\n')
|
||||
}
|
||||
_, _ = l.config.co.output.Write(b.Bytes())
|
||||
}
|
||||
|
||||
func (l *tlogger) WriteKlogBuffer(data []byte) {
|
||||
_, _ = l.config.co.output.Write(data)
|
||||
}
|
||||
|
||||
// WithName returns a new logr.Logger with the specified name appended. klogr
|
||||
// uses '/' characters to separate name elements. Callers should not pass '/'
|
||||
// in the provided name string, but this library does not actually enforce that.
|
||||
func (l *tlogger) WithName(name string) logr.LogSink {
|
||||
clone := *l
|
||||
if l.hasPrefix {
|
||||
// Copy slice and modify value. No length checks and type
|
||||
// assertions are needed because hasPrefix is only true if the
|
||||
// first two elements exist and are key/value strings.
|
||||
v := make([]interface{}, 0, len(l.values))
|
||||
v = append(v, l.values...)
|
||||
prefix, _ := v[1].(string)
|
||||
v[1] = prefix + "." + name
|
||||
clone.values = v
|
||||
} else {
|
||||
// Preprend new key/value pair.
|
||||
v := make([]interface{}, 0, 2+len(l.values))
|
||||
v = append(v, nameKey, name)
|
||||
v = append(v, l.values...)
|
||||
clone.values = v
|
||||
clone.hasPrefix = true
|
||||
}
|
||||
return &clone
|
||||
}
|
||||
|
||||
func (l *tlogger) WithValues(kvList ...interface{}) logr.LogSink {
|
||||
clone := *l
|
||||
clone.values = serialize.WithValues(l.values, kvList)
|
||||
return &clone
|
||||
}
|
||||
|
||||
// KlogBufferWriter is implemented by the textlogger LogSink.
|
||||
type KlogBufferWriter interface {
|
||||
// WriteKlogBuffer takes a pre-formatted buffer prepared by klog and
|
||||
// writes it unchanged to the output stream. Can be used with
|
||||
// klog.WriteKlogBuffer when setting a logger through
|
||||
// klog.SetLoggerWithOptions.
|
||||
WriteKlogBuffer([]byte)
|
||||
}
|
||||
|
||||
var _ logr.LogSink = &tlogger{}
|
||||
var _ logr.CallDepthLogSink = &tlogger{}
|
||||
var _ KlogBufferWriter = &tlogger{}
|
52
vendor/k8s.io/klog/v2/textlogger/textlogger_slog.go
generated
vendored
Normal file
52
vendor/k8s.io/klog/v2/textlogger/textlogger_slog.go
generated
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
//go:build go1.21
|
||||
// +build go1.21
|
||||
|
||||
/*
|
||||
Copyright 2023 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 textlogger
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log/slog"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
|
||||
"k8s.io/klog/v2/internal/serialize"
|
||||
"k8s.io/klog/v2/internal/sloghandler"
|
||||
)
|
||||
|
||||
func (l *tlogger) Handle(ctx context.Context, record slog.Record) error {
|
||||
return sloghandler.Handle(ctx, record, l.groups, l.printWithInfos)
|
||||
}
|
||||
|
||||
func (l *tlogger) WithAttrs(attrs []slog.Attr) logr.SlogSink {
|
||||
clone := *l
|
||||
clone.values = serialize.WithValues(l.values, sloghandler.Attrs2KVList(l.groups, attrs))
|
||||
return &clone
|
||||
}
|
||||
|
||||
func (l *tlogger) WithGroup(name string) logr.SlogSink {
|
||||
clone := *l
|
||||
if clone.groups != "" {
|
||||
clone.groups += "." + name
|
||||
} else {
|
||||
clone.groups = name
|
||||
}
|
||||
return &clone
|
||||
}
|
||||
|
||||
var _ logr.SlogSink = &tlogger{}
|
Reference in New Issue
Block a user