mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-06-13 10:33:35 +00:00
rebase: update to latest github.com/openshift/api version
Also vendor all dependencies. Signed-off-by: Niels de Vos <ndevos@ibm.com>
This commit is contained in:
committed by
mergify[bot]
parent
ab87045afb
commit
ce603fb47e
184
api/vendor/k8s.io/klog/v2/internal/buffer/buffer.go
generated
vendored
Normal file
184
api/vendor/k8s.io/klog/v2/internal/buffer/buffer.go
generated
vendored
Normal file
@ -0,0 +1,184 @@
|
||||
// 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 buffer provides a cache for byte.Buffer instances that can be reused
|
||||
// to avoid frequent allocation and deallocation. It also has utility code
|
||||
// for log header formatting that use these buffers.
|
||||
package buffer
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"k8s.io/klog/v2/internal/severity"
|
||||
)
|
||||
|
||||
var (
|
||||
// Pid is inserted into log headers. Can be overridden for tests.
|
||||
Pid = os.Getpid()
|
||||
|
||||
// Time, if set, will be used instead of the actual current time.
|
||||
Time *time.Time
|
||||
)
|
||||
|
||||
// Buffer holds a single byte.Buffer for reuse. The zero value is ready for
|
||||
// use. It also provides some helper methods for output formatting.
|
||||
type Buffer struct {
|
||||
bytes.Buffer
|
||||
Tmp [64]byte // temporary byte array for creating headers.
|
||||
}
|
||||
|
||||
var buffers = sync.Pool{
|
||||
New: func() interface{} {
|
||||
return new(Buffer)
|
||||
},
|
||||
}
|
||||
|
||||
// GetBuffer returns a new, ready-to-use buffer.
|
||||
func GetBuffer() *Buffer {
|
||||
b := buffers.Get().(*Buffer)
|
||||
b.Reset()
|
||||
return b
|
||||
}
|
||||
|
||||
// PutBuffer returns a buffer to the free list.
|
||||
func PutBuffer(b *Buffer) {
|
||||
if b.Len() >= 256 {
|
||||
// Let big buffers die a natural death, without relying on
|
||||
// sync.Pool behavior. The documentation implies that items may
|
||||
// get deallocated while stored there ("If the Pool holds the
|
||||
// only reference when this [= be removed automatically]
|
||||
// happens, the item might be deallocated."), but
|
||||
// https://github.com/golang/go/issues/23199 leans more towards
|
||||
// having such a size limit.
|
||||
return
|
||||
}
|
||||
|
||||
buffers.Put(b)
|
||||
}
|
||||
|
||||
// Some custom tiny helper functions to print the log header efficiently.
|
||||
|
||||
const digits = "0123456789"
|
||||
|
||||
// twoDigits formats a zero-prefixed two-digit integer at buf.Tmp[i].
|
||||
func (buf *Buffer) twoDigits(i, d int) {
|
||||
buf.Tmp[i+1] = digits[d%10]
|
||||
d /= 10
|
||||
buf.Tmp[i] = digits[d%10]
|
||||
}
|
||||
|
||||
// nDigits formats an n-digit integer at buf.Tmp[i],
|
||||
// padding with pad on the left.
|
||||
// It assumes d >= 0.
|
||||
func (buf *Buffer) nDigits(n, i, d int, pad byte) {
|
||||
j := n - 1
|
||||
for ; j >= 0 && d > 0; j-- {
|
||||
buf.Tmp[i+j] = digits[d%10]
|
||||
d /= 10
|
||||
}
|
||||
for ; j >= 0; j-- {
|
||||
buf.Tmp[i+j] = pad
|
||||
}
|
||||
}
|
||||
|
||||
// someDigits formats a zero-prefixed variable-width integer at buf.Tmp[i].
|
||||
func (buf *Buffer) someDigits(i, d int) int {
|
||||
// Print into the top, then copy down. We know there's space for at least
|
||||
// a 10-digit number.
|
||||
j := len(buf.Tmp)
|
||||
for {
|
||||
j--
|
||||
buf.Tmp[j] = digits[d%10]
|
||||
d /= 10
|
||||
if d == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
return copy(buf.Tmp[i:], buf.Tmp[j:])
|
||||
}
|
||||
|
||||
// FormatHeader formats a log header using the provided file name and line number
|
||||
// and writes it into the buffer.
|
||||
func (buf *Buffer) FormatHeader(s severity.Severity, file string, line int, now time.Time) {
|
||||
if line < 0 {
|
||||
line = 0 // not a real line number, but acceptable to someDigits
|
||||
}
|
||||
if s > severity.FatalLog {
|
||||
s = severity.InfoLog // for safety.
|
||||
}
|
||||
|
||||
// Avoid Fprintf, for speed. The format is so simple that we can do it quickly by hand.
|
||||
// It's worth about 3X. Fprintf is hard.
|
||||
if Time != nil {
|
||||
now = *Time
|
||||
}
|
||||
_, month, day := now.Date()
|
||||
hour, minute, second := now.Clock()
|
||||
// Lmmdd hh:mm:ss.uuuuuu threadid file:line]
|
||||
buf.Tmp[0] = severity.Char[s]
|
||||
buf.twoDigits(1, int(month))
|
||||
buf.twoDigits(3, day)
|
||||
buf.Tmp[5] = ' '
|
||||
buf.twoDigits(6, hour)
|
||||
buf.Tmp[8] = ':'
|
||||
buf.twoDigits(9, minute)
|
||||
buf.Tmp[11] = ':'
|
||||
buf.twoDigits(12, second)
|
||||
buf.Tmp[14] = '.'
|
||||
buf.nDigits(6, 15, now.Nanosecond()/1000, '0')
|
||||
buf.Tmp[21] = ' '
|
||||
buf.nDigits(7, 22, Pid, ' ') // TODO: should be TID
|
||||
buf.Tmp[29] = ' '
|
||||
buf.Write(buf.Tmp[:30])
|
||||
buf.WriteString(file)
|
||||
buf.Tmp[0] = ':'
|
||||
n := buf.someDigits(1, line)
|
||||
buf.Tmp[n+1] = ']'
|
||||
buf.Tmp[n+2] = ' '
|
||||
buf.Write(buf.Tmp[:n+3])
|
||||
}
|
||||
|
||||
// SprintHeader formats a log header and returns a string. This is a simpler
|
||||
// version of FormatHeader for use in ktesting.
|
||||
func (buf *Buffer) SprintHeader(s severity.Severity, now time.Time) string {
|
||||
if s > severity.FatalLog {
|
||||
s = severity.InfoLog // for safety.
|
||||
}
|
||||
|
||||
// Avoid Fprintf, for speed. The format is so simple that we can do it quickly by hand.
|
||||
// It's worth about 3X. Fprintf is hard.
|
||||
if Time != nil {
|
||||
now = *Time
|
||||
}
|
||||
_, month, day := now.Date()
|
||||
hour, minute, second := now.Clock()
|
||||
// Lmmdd hh:mm:ss.uuuuuu threadid file:line]
|
||||
buf.Tmp[0] = severity.Char[s]
|
||||
buf.twoDigits(1, int(month))
|
||||
buf.twoDigits(3, day)
|
||||
buf.Tmp[5] = ' '
|
||||
buf.twoDigits(6, hour)
|
||||
buf.Tmp[8] = ':'
|
||||
buf.twoDigits(9, minute)
|
||||
buf.Tmp[11] = ':'
|
||||
buf.twoDigits(12, second)
|
||||
buf.Tmp[14] = '.'
|
||||
buf.nDigits(6, 15, now.Nanosecond()/1000, '0')
|
||||
buf.Tmp[21] = ']'
|
||||
return string(buf.Tmp[:22])
|
||||
}
|
7
api/vendor/k8s.io/klog/v2/internal/clock/README.md
generated
vendored
Normal file
7
api/vendor/k8s.io/klog/v2/internal/clock/README.md
generated
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
# Clock
|
||||
|
||||
This package provides an interface for time-based operations. It allows
|
||||
mocking time for testing.
|
||||
|
||||
This is a copy of k8s.io/utils/clock. We have to copy it to avoid a circular
|
||||
dependency (k8s.io/klog -> k8s.io/utils -> k8s.io/klog).
|
161
api/vendor/k8s.io/klog/v2/internal/clock/clock.go
generated
vendored
Normal file
161
api/vendor/k8s.io/klog/v2/internal/clock/clock.go
generated
vendored
Normal file
@ -0,0 +1,161 @@
|
||||
/*
|
||||
Copyright 2014 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 clock
|
||||
|
||||
import "time"
|
||||
|
||||
// PassiveClock allows for injecting fake or real clocks into code
|
||||
// that needs to read the current time but does not support scheduling
|
||||
// activity in the future.
|
||||
type PassiveClock interface {
|
||||
Now() time.Time
|
||||
Since(time.Time) time.Duration
|
||||
}
|
||||
|
||||
// Clock allows for injecting fake or real clocks into code that
|
||||
// needs to do arbitrary things based on time.
|
||||
type Clock interface {
|
||||
PassiveClock
|
||||
// After returns the channel of a new Timer.
|
||||
// This method does not allow to free/GC the backing timer before it fires. Use
|
||||
// NewTimer instead.
|
||||
After(d time.Duration) <-chan time.Time
|
||||
// NewTimer returns a new Timer.
|
||||
NewTimer(d time.Duration) Timer
|
||||
// Sleep sleeps for the provided duration d.
|
||||
// Consider making the sleep interruptible by using 'select' on a context channel and a timer channel.
|
||||
Sleep(d time.Duration)
|
||||
// NewTicker returns a new Ticker.
|
||||
NewTicker(time.Duration) Ticker
|
||||
}
|
||||
|
||||
// WithDelayedExecution allows for injecting fake or real clocks into
|
||||
// code that needs to make use of AfterFunc functionality.
|
||||
type WithDelayedExecution interface {
|
||||
Clock
|
||||
// AfterFunc executes f in its own goroutine after waiting
|
||||
// for d duration and returns a Timer whose channel can be
|
||||
// closed by calling Stop() on the Timer.
|
||||
AfterFunc(d time.Duration, f func()) Timer
|
||||
}
|
||||
|
||||
// WithTickerAndDelayedExecution allows for injecting fake or real clocks
|
||||
// into code that needs Ticker and AfterFunc functionality
|
||||
type WithTickerAndDelayedExecution interface {
|
||||
Clock
|
||||
// AfterFunc executes f in its own goroutine after waiting
|
||||
// for d duration and returns a Timer whose channel can be
|
||||
// closed by calling Stop() on the Timer.
|
||||
AfterFunc(d time.Duration, f func()) Timer
|
||||
}
|
||||
|
||||
// Ticker defines the Ticker interface.
|
||||
type Ticker interface {
|
||||
C() <-chan time.Time
|
||||
Stop()
|
||||
}
|
||||
|
||||
var _ Clock = RealClock{}
|
||||
|
||||
// RealClock really calls time.Now()
|
||||
type RealClock struct{}
|
||||
|
||||
// Now returns the current time.
|
||||
func (RealClock) Now() time.Time {
|
||||
return time.Now()
|
||||
}
|
||||
|
||||
// Since returns time since the specified timestamp.
|
||||
func (RealClock) Since(ts time.Time) time.Duration {
|
||||
return time.Since(ts)
|
||||
}
|
||||
|
||||
// After is the same as time.After(d).
|
||||
// This method does not allow to free/GC the backing timer before it fires. Use
|
||||
// NewTimer instead.
|
||||
func (RealClock) After(d time.Duration) <-chan time.Time {
|
||||
return time.After(d)
|
||||
}
|
||||
|
||||
// NewTimer is the same as time.NewTimer(d)
|
||||
func (RealClock) NewTimer(d time.Duration) Timer {
|
||||
return &realTimer{
|
||||
timer: time.NewTimer(d),
|
||||
}
|
||||
}
|
||||
|
||||
// AfterFunc is the same as time.AfterFunc(d, f).
|
||||
func (RealClock) AfterFunc(d time.Duration, f func()) Timer {
|
||||
return &realTimer{
|
||||
timer: time.AfterFunc(d, f),
|
||||
}
|
||||
}
|
||||
|
||||
// NewTicker returns a new Ticker.
|
||||
func (RealClock) NewTicker(d time.Duration) Ticker {
|
||||
return &realTicker{
|
||||
ticker: time.NewTicker(d),
|
||||
}
|
||||
}
|
||||
|
||||
// Sleep is the same as time.Sleep(d)
|
||||
// Consider making the sleep interruptible by using 'select' on a context channel and a timer channel.
|
||||
func (RealClock) Sleep(d time.Duration) {
|
||||
time.Sleep(d)
|
||||
}
|
||||
|
||||
// Timer allows for injecting fake or real timers into code that
|
||||
// needs to do arbitrary things based on time.
|
||||
type Timer interface {
|
||||
C() <-chan time.Time
|
||||
Stop() bool
|
||||
Reset(d time.Duration) bool
|
||||
}
|
||||
|
||||
var _ = Timer(&realTimer{})
|
||||
|
||||
// realTimer is backed by an actual time.Timer.
|
||||
type realTimer struct {
|
||||
timer *time.Timer
|
||||
}
|
||||
|
||||
// C returns the underlying timer's channel.
|
||||
func (r *realTimer) C() <-chan time.Time {
|
||||
return r.timer.C
|
||||
}
|
||||
|
||||
// Stop calls Stop() on the underlying timer.
|
||||
func (r *realTimer) Stop() bool {
|
||||
return r.timer.Stop()
|
||||
}
|
||||
|
||||
// Reset calls Reset() on the underlying timer.
|
||||
func (r *realTimer) Reset(d time.Duration) bool {
|
||||
return r.timer.Reset(d)
|
||||
}
|
||||
|
||||
type realTicker struct {
|
||||
ticker *time.Ticker
|
||||
}
|
||||
|
||||
func (r *realTicker) C() <-chan time.Time {
|
||||
return r.ticker.C
|
||||
}
|
||||
|
||||
func (r *realTicker) Stop() {
|
||||
r.ticker.Stop()
|
||||
}
|
42
api/vendor/k8s.io/klog/v2/internal/dbg/dbg.go
generated
vendored
Normal file
42
api/vendor/k8s.io/klog/v2/internal/dbg/dbg.go
generated
vendored
Normal 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
|
||||
}
|
292
api/vendor/k8s.io/klog/v2/internal/serialize/keyvalues.go
generated
vendored
Normal file
292
api/vendor/k8s.io/klog/v2/internal/serialize/keyvalues.go
generated
vendored
Normal file
@ -0,0 +1,292 @@
|
||||
/*
|
||||
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 serialize
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
)
|
||||
|
||||
type textWriter interface {
|
||||
WriteText(*bytes.Buffer)
|
||||
}
|
||||
|
||||
// WithValues implements LogSink.WithValues. The old key/value pairs are
|
||||
// assumed to be well-formed, the new ones are checked and padded if
|
||||
// necessary. It returns a new slice.
|
||||
func WithValues(oldKV, newKV []interface{}) []interface{} {
|
||||
if len(newKV) == 0 {
|
||||
return oldKV
|
||||
}
|
||||
newLen := len(oldKV) + len(newKV)
|
||||
hasMissingValue := newLen%2 != 0
|
||||
if hasMissingValue {
|
||||
newLen++
|
||||
}
|
||||
// The new LogSink must have its own slice.
|
||||
kv := make([]interface{}, 0, newLen)
|
||||
kv = append(kv, oldKV...)
|
||||
kv = append(kv, newKV...)
|
||||
if hasMissingValue {
|
||||
kv = append(kv, missingValue)
|
||||
}
|
||||
return kv
|
||||
}
|
||||
|
||||
// MergeKVs deduplicates elements provided in two key/value slices.
|
||||
//
|
||||
// Keys in each slice are expected to be unique, so duplicates can only occur
|
||||
// when the first and second slice contain the same key. When that happens, the
|
||||
// key/value pair from the second slice is used. The first slice must be well-formed
|
||||
// (= even key/value pairs). The second one may have a missing value, in which
|
||||
// case the special "missing value" is added to the result.
|
||||
func MergeKVs(first, second []interface{}) []interface{} {
|
||||
maxLength := len(first) + (len(second)+1)/2*2
|
||||
if maxLength == 0 {
|
||||
// Nothing to do at all.
|
||||
return nil
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
type Formatter struct {
|
||||
AnyToStringHook AnyToStringFunc
|
||||
}
|
||||
|
||||
type AnyToStringFunc func(v interface{}) string
|
||||
|
||||
// MergeKVsInto is a variant of MergeKVs which directly formats the key/value
|
||||
// pairs into a buffer.
|
||||
func (f Formatter) MergeAndFormatKVs(b *bytes.Buffer, first, second []interface{}) {
|
||||
if len(first) == 0 && len(second) == 0 {
|
||||
// Nothing to do at all.
|
||||
return
|
||||
}
|
||||
|
||||
if len(first) == 0 && len(second)%2 == 0 {
|
||||
// Nothing to be overridden, second slice is well-formed
|
||||
// and can be used directly.
|
||||
for i := 0; i < len(second); i += 2 {
|
||||
f.KVFormat(b, second[i], second[i+1])
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
for i := 0; i < len(first); i += 2 {
|
||||
key := first[i]
|
||||
if overrides[key] {
|
||||
continue
|
||||
}
|
||||
f.KVFormat(b, key, first[i+1])
|
||||
}
|
||||
// Round down.
|
||||
l := len(second)
|
||||
l = l / 2 * 2
|
||||
for i := 1; i < l; i += 2 {
|
||||
f.KVFormat(b, second[i-1], second[i])
|
||||
}
|
||||
if len(second)%2 == 1 {
|
||||
f.KVFormat(b, second[len(second)-1], missingValue)
|
||||
}
|
||||
}
|
||||
|
||||
func MergeAndFormatKVs(b *bytes.Buffer, first, second []interface{}) {
|
||||
Formatter{}.MergeAndFormatKVs(b, first, second)
|
||||
}
|
||||
|
||||
const missingValue = "(MISSING)"
|
||||
|
||||
// KVListFormat serializes all key/value pairs into the provided buffer.
|
||||
// A space gets inserted before the first pair and between each pair.
|
||||
func (f Formatter) KVListFormat(b *bytes.Buffer, keysAndValues ...interface{}) {
|
||||
for i := 0; i < len(keysAndValues); i += 2 {
|
||||
var v interface{}
|
||||
k := keysAndValues[i]
|
||||
if i+1 < len(keysAndValues) {
|
||||
v = keysAndValues[i+1]
|
||||
} else {
|
||||
v = missingValue
|
||||
}
|
||||
f.KVFormat(b, k, v)
|
||||
}
|
||||
}
|
||||
|
||||
func KVListFormat(b *bytes.Buffer, keysAndValues ...interface{}) {
|
||||
Formatter{}.KVListFormat(b, keysAndValues...)
|
||||
}
|
||||
|
||||
func KVFormat(b *bytes.Buffer, k, v interface{}) {
|
||||
Formatter{}.KVFormat(b, k, v)
|
||||
}
|
||||
|
||||
// formatAny is the fallback formatter for a value. It supports a hook (for
|
||||
// example, for YAML encoding) and itself uses JSON encoding.
|
||||
func (f Formatter) formatAny(b *bytes.Buffer, v interface{}) {
|
||||
b.WriteRune('=')
|
||||
if f.AnyToStringHook != nil {
|
||||
b.WriteString(f.AnyToStringHook(v))
|
||||
return
|
||||
}
|
||||
formatAsJSON(b, v)
|
||||
}
|
||||
|
||||
func formatAsJSON(b *bytes.Buffer, v interface{}) {
|
||||
encoder := json.NewEncoder(b)
|
||||
l := b.Len()
|
||||
if err := encoder.Encode(v); err != nil {
|
||||
// This shouldn't happen. We discard whatever the encoder
|
||||
// wrote and instead dump an error string.
|
||||
b.Truncate(l)
|
||||
b.WriteString(fmt.Sprintf(`"<internal error: %v>"`, err))
|
||||
return
|
||||
}
|
||||
// Remove trailing newline.
|
||||
b.Truncate(b.Len() - 1)
|
||||
}
|
||||
|
||||
// StringerToString converts a Stringer to a string,
|
||||
// handling panics if they occur.
|
||||
func StringerToString(s fmt.Stringer) (ret string) {
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
ret = fmt.Sprintf("<panic: %s>", err)
|
||||
}
|
||||
}()
|
||||
ret = s.String()
|
||||
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,
|
||||
// handling panics if they occur.
|
||||
func ErrorToString(err error) (ret string) {
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
ret = fmt.Sprintf("<panic: %s>", err)
|
||||
}
|
||||
}()
|
||||
ret = err.Error()
|
||||
return
|
||||
}
|
||||
|
||||
func writeTextWriterValue(b *bytes.Buffer, v textWriter) {
|
||||
b.WriteByte('=')
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
fmt.Fprintf(b, `"<panic: %s>"`, err)
|
||||
}
|
||||
}()
|
||||
v.WriteText(b)
|
||||
}
|
||||
|
||||
func writeStringValue(b *bytes.Buffer, v string) {
|
||||
data := []byte(v)
|
||||
index := bytes.IndexByte(data, '\n')
|
||||
if index == -1 {
|
||||
b.WriteByte('=')
|
||||
// Simple string, quote quotation marks and non-printable characters.
|
||||
b.WriteString(strconv.Quote(v))
|
||||
return
|
||||
}
|
||||
|
||||
// Complex multi-line string, show as-is with indention like this:
|
||||
// I... "hello world" key=<
|
||||
// <tab>line 1
|
||||
// <tab>line 2
|
||||
// >
|
||||
//
|
||||
// Tabs indent the lines of the value while the end of string delimiter
|
||||
// is indented with a space. That has two purposes:
|
||||
// - visual difference between the two for a human reader because indention
|
||||
// will be different
|
||||
// - no ambiguity when some value line starts with the end delimiter
|
||||
//
|
||||
// One downside is that the output cannot distinguish between strings that
|
||||
// end with a line break and those that don't because the end delimiter
|
||||
// will always be on the next line.
|
||||
b.WriteString("=<\n")
|
||||
for index != -1 {
|
||||
b.WriteByte('\t')
|
||||
b.Write(data[0 : index+1])
|
||||
data = data[index+1:]
|
||||
index = bytes.IndexByte(data, '\n')
|
||||
}
|
||||
if len(data) == 0 {
|
||||
// String ended with line break, don't add another.
|
||||
b.WriteString(" >")
|
||||
} else {
|
||||
// No line break at end of last line, write rest of string and
|
||||
// add one.
|
||||
b.WriteByte('\t')
|
||||
b.Write(data)
|
||||
b.WriteString("\n >")
|
||||
}
|
||||
}
|
97
api/vendor/k8s.io/klog/v2/internal/serialize/keyvalues_no_slog.go
generated
vendored
Normal file
97
api/vendor/k8s.io/klog/v2/internal/serialize/keyvalues_no_slog.go
generated
vendored
Normal file
@ -0,0 +1,97 @@
|
||||
//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 serialize
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
)
|
||||
|
||||
// KVFormat serializes one key/value pair into the provided buffer.
|
||||
// A space gets inserted before the pair.
|
||||
func (f Formatter) KVFormat(b *bytes.Buffer, k, v interface{}) {
|
||||
// This is the version without slog support. Must be kept in sync with
|
||||
// the version in keyvalues_slog.go.
|
||||
|
||||
b.WriteByte(' ')
|
||||
// Keys are assumed to be well-formed according to
|
||||
// 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,
|
||||
// special characters, etc. will break parsing.
|
||||
if sK, ok := k.(string); ok {
|
||||
// Avoid one allocation when the key is a string, which
|
||||
// normally it should be.
|
||||
b.WriteString(sK)
|
||||
} else {
|
||||
b.WriteString(fmt.Sprintf("%s", k))
|
||||
}
|
||||
|
||||
// The type checks are sorted so that more frequently used ones
|
||||
// come first because that is then faster in the common
|
||||
// cases. In Kubernetes, ObjectRef (a Stringer) is more common
|
||||
// than plain strings
|
||||
// (https://github.com/kubernetes/kubernetes/pull/106594#issuecomment-975526235).
|
||||
switch v := v.(type) {
|
||||
case textWriter:
|
||||
writeTextWriterValue(b, v)
|
||||
case fmt.Stringer:
|
||||
writeStringValue(b, StringerToString(v))
|
||||
case string:
|
||||
writeStringValue(b, v)
|
||||
case error:
|
||||
writeStringValue(b, 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, value)
|
||||
default:
|
||||
f.formatAny(b, value)
|
||||
}
|
||||
case []byte:
|
||||
// In https://github.com/kubernetes/klog/pull/237 it was decided
|
||||
// to format byte slices with "%+q". The advantages of that are:
|
||||
// - readable output if the bytes happen to be printable
|
||||
// - non-printable bytes get represented as unicode escape
|
||||
// sequences (\uxxxx)
|
||||
//
|
||||
// The downsides are that we cannot use the faster
|
||||
// strconv.Quote here and that multi-line output is not
|
||||
// supported. If developers know that a byte array is
|
||||
// printable and they want multi-line output, they can
|
||||
// convert the value to string before logging it.
|
||||
b.WriteByte('=')
|
||||
b.WriteString(fmt.Sprintf("%+q", v))
|
||||
default:
|
||||
f.formatAny(b, v)
|
||||
}
|
||||
}
|
155
api/vendor/k8s.io/klog/v2/internal/serialize/keyvalues_slog.go
generated
vendored
Normal file
155
api/vendor/k8s.io/klog/v2/internal/serialize/keyvalues_slog.go
generated
vendored
Normal file
@ -0,0 +1,155 @@
|
||||
//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 serialize
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"strconv"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
)
|
||||
|
||||
// KVFormat serializes one key/value pair into the provided buffer.
|
||||
// A space gets inserted before the pair.
|
||||
func (f Formatter) KVFormat(b *bytes.Buffer, k, v interface{}) {
|
||||
// This is the version without slog support. Must be kept in sync with
|
||||
// the version in keyvalues_slog.go.
|
||||
|
||||
b.WriteByte(' ')
|
||||
// Keys are assumed to be well-formed according to
|
||||
// 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,
|
||||
// special characters, etc. will break parsing.
|
||||
if sK, ok := k.(string); ok {
|
||||
// Avoid one allocation when the key is a string, which
|
||||
// normally it should be.
|
||||
b.WriteString(sK)
|
||||
} else {
|
||||
b.WriteString(fmt.Sprintf("%s", k))
|
||||
}
|
||||
|
||||
// The type checks are sorted so that more frequently used ones
|
||||
// come first because that is then faster in the common
|
||||
// cases. In Kubernetes, ObjectRef (a Stringer) is more common
|
||||
// than plain strings
|
||||
// (https://github.com/kubernetes/kubernetes/pull/106594#issuecomment-975526235).
|
||||
//
|
||||
// slog.LogValuer does not need to be handled here because the handler will
|
||||
// already have resolved such special values to the final value for logging.
|
||||
switch v := v.(type) {
|
||||
case textWriter:
|
||||
writeTextWriterValue(b, v)
|
||||
case slog.Value:
|
||||
// This must come before fmt.Stringer because slog.Value implements
|
||||
// fmt.Stringer, but does not produce the output that we want.
|
||||
b.WriteByte('=')
|
||||
generateJSON(b, v)
|
||||
case fmt.Stringer:
|
||||
writeStringValue(b, StringerToString(v))
|
||||
case string:
|
||||
writeStringValue(b, v)
|
||||
case error:
|
||||
writeStringValue(b, 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, value)
|
||||
default:
|
||||
f.formatAny(b, value)
|
||||
}
|
||||
case slog.LogValuer:
|
||||
value := slog.AnyValue(v).Resolve()
|
||||
if value.Kind() == slog.KindString {
|
||||
writeStringValue(b, value.String())
|
||||
} else {
|
||||
b.WriteByte('=')
|
||||
generateJSON(b, value)
|
||||
}
|
||||
case []byte:
|
||||
// In https://github.com/kubernetes/klog/pull/237 it was decided
|
||||
// to format byte slices with "%+q". The advantages of that are:
|
||||
// - readable output if the bytes happen to be printable
|
||||
// - non-printable bytes get represented as unicode escape
|
||||
// sequences (\uxxxx)
|
||||
//
|
||||
// The downsides are that we cannot use the faster
|
||||
// strconv.Quote here and that multi-line output is not
|
||||
// supported. If developers know that a byte array is
|
||||
// printable and they want multi-line output, they can
|
||||
// convert the value to string before logging it.
|
||||
b.WriteByte('=')
|
||||
b.WriteString(fmt.Sprintf("%+q", v))
|
||||
default:
|
||||
f.formatAny(b, v)
|
||||
}
|
||||
}
|
||||
|
||||
// generateJSON has the same preference for plain strings as KVFormat.
|
||||
// In contrast to KVFormat it always produces valid JSON with no line breaks.
|
||||
func generateJSON(b *bytes.Buffer, v interface{}) {
|
||||
switch v := v.(type) {
|
||||
case slog.Value:
|
||||
switch v.Kind() {
|
||||
case slog.KindGroup:
|
||||
// Format as a JSON group. We must not involve f.AnyToStringHook (if there is any),
|
||||
// because there is no guarantee that it produces valid JSON.
|
||||
b.WriteByte('{')
|
||||
for i, attr := range v.Group() {
|
||||
if i > 0 {
|
||||
b.WriteByte(',')
|
||||
}
|
||||
b.WriteString(strconv.Quote(attr.Key))
|
||||
b.WriteByte(':')
|
||||
generateJSON(b, attr.Value)
|
||||
}
|
||||
b.WriteByte('}')
|
||||
case slog.KindLogValuer:
|
||||
generateJSON(b, v.Resolve())
|
||||
default:
|
||||
// Peel off the slog.Value wrapper and format the actual value.
|
||||
generateJSON(b, v.Any())
|
||||
}
|
||||
case fmt.Stringer:
|
||||
b.WriteString(strconv.Quote(StringerToString(v)))
|
||||
case logr.Marshaler:
|
||||
generateJSON(b, MarshalerToValue(v))
|
||||
case slog.LogValuer:
|
||||
generateJSON(b, slog.AnyValue(v).Resolve().Any())
|
||||
case string:
|
||||
b.WriteString(strconv.Quote(v))
|
||||
case error:
|
||||
b.WriteString(strconv.Quote(v.Error()))
|
||||
default:
|
||||
formatAsJSON(b, v)
|
||||
}
|
||||
}
|
58
api/vendor/k8s.io/klog/v2/internal/severity/severity.go
generated
vendored
Normal file
58
api/vendor/k8s.io/klog/v2/internal/severity/severity.go
generated
vendored
Normal file
@ -0,0 +1,58 @@
|
||||
// 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 severity provides definitions for klog severity (info, warning, ...)
|
||||
package severity
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// severity identifies the sort of log: info, warning etc. The binding to flag.Value
|
||||
// is handled in klog.go
|
||||
type Severity int32 // sync/atomic int32
|
||||
|
||||
// These constants identify the log levels in order of increasing severity.
|
||||
// A message written to a high-severity log file is also written to each
|
||||
// lower-severity log file.
|
||||
const (
|
||||
InfoLog Severity = iota
|
||||
WarningLog
|
||||
ErrorLog
|
||||
FatalLog
|
||||
NumSeverity = 4
|
||||
)
|
||||
|
||||
// Char contains one shortcut letter per severity level.
|
||||
const Char = "IWEF"
|
||||
|
||||
// Name contains one name per severity level.
|
||||
var Name = []string{
|
||||
InfoLog: "INFO",
|
||||
WarningLog: "WARNING",
|
||||
ErrorLog: "ERROR",
|
||||
FatalLog: "FATAL",
|
||||
}
|
||||
|
||||
// ByName looks up a severity level by name.
|
||||
func ByName(s string) (Severity, bool) {
|
||||
s = strings.ToUpper(s)
|
||||
for i, name := range Name {
|
||||
if name == s {
|
||||
return Severity(i), true
|
||||
}
|
||||
}
|
||||
return 0, false
|
||||
}
|
96
api/vendor/k8s.io/klog/v2/internal/sloghandler/sloghandler_slog.go
generated
vendored
Normal file
96
api/vendor/k8s.io/klog/v2/internal/sloghandler/sloghandler_slog.go
generated
vendored
Normal file
@ -0,0 +1,96 @@
|
||||
//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 sloghandler
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log/slog"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"k8s.io/klog/v2/internal/severity"
|
||||
)
|
||||
|
||||
func Handle(_ context.Context, record slog.Record, groups string, printWithInfos func(file string, line int, now time.Time, err error, s severity.Severity, msg string, kvList []interface{})) error {
|
||||
now := record.Time
|
||||
if now.IsZero() {
|
||||
// This format doesn't support printing entries without a time.
|
||||
now = time.Now()
|
||||
}
|
||||
|
||||
// slog has numeric severity levels, with 0 as default "info", negative for debugging, and
|
||||
// positive with some pre-defined levels for more important. Those ranges get mapped to
|
||||
// the corresponding klog levels where possible, with "info" the default that is used
|
||||
// also for negative debug levels.
|
||||
level := record.Level
|
||||
s := severity.InfoLog
|
||||
switch {
|
||||
case level >= slog.LevelError:
|
||||
s = severity.ErrorLog
|
||||
case level >= slog.LevelWarn:
|
||||
s = severity.WarningLog
|
||||
}
|
||||
|
||||
var file string
|
||||
var line int
|
||||
if record.PC != 0 {
|
||||
// Same as https://cs.opensource.google/go/x/exp/+/642cacee:slog/record.go;drc=642cacee5cc05231f45555a333d07f1005ffc287;l=70
|
||||
fs := runtime.CallersFrames([]uintptr{record.PC})
|
||||
f, _ := fs.Next()
|
||||
if f.File != "" {
|
||||
file = f.File
|
||||
if slash := strings.LastIndex(file, "/"); slash >= 0 {
|
||||
file = file[slash+1:]
|
||||
}
|
||||
line = f.Line
|
||||
}
|
||||
} else {
|
||||
file = "???"
|
||||
line = 1
|
||||
}
|
||||
|
||||
kvList := make([]interface{}, 0, 2*record.NumAttrs())
|
||||
record.Attrs(func(attr slog.Attr) bool {
|
||||
kvList = appendAttr(groups, kvList, attr)
|
||||
return true
|
||||
})
|
||||
|
||||
printWithInfos(file, line, now, nil, s, record.Message, kvList)
|
||||
return nil
|
||||
}
|
||||
|
||||
func Attrs2KVList(groups string, attrs []slog.Attr) []interface{} {
|
||||
kvList := make([]interface{}, 0, 2*len(attrs))
|
||||
for _, attr := range attrs {
|
||||
kvList = appendAttr(groups, kvList, attr)
|
||||
}
|
||||
return kvList
|
||||
}
|
||||
|
||||
func appendAttr(groups string, kvList []interface{}, attr slog.Attr) []interface{} {
|
||||
var key string
|
||||
if groups != "" {
|
||||
key = groups + "." + attr.Key
|
||||
} else {
|
||||
key = attr.Key
|
||||
}
|
||||
return append(kvList, key, attr.Value)
|
||||
}
|
Reference in New Issue
Block a user