mirror of https://github.com/knative/caching.git
upgrade to latest dependencies (#664)
bumping k8s.io/api e08b72c...f89a761: > f89a761 Update dependencies to v0.23.9 tag bumping k8s.io/client-go 14fa49e...11f68c5: > 11f68c5 Update dependencies to v0.23.9 tag bumping knative.dev/pkg 6c9c1c6...a01dfed: > a01dfed bump to k8s 0.23.9 (# 2565) > 449f7e6 Update community files (# 2564) > ed7ab1d upgrade to latest dependencies (# 2559) bumping k8s.io/apimachinery 276a8a7...276a8a7: bumping k8s.io/code-generator 31c00a6...31c00a6: bumping knative.dev/hack 782bbaa...9dabf7c: > 9dabf7c Update community files (# 206) Signed-off-by: Knative Automation <automation@knative.team>
This commit is contained in:
parent
a0fb648e0c
commit
c920610465
12
go.mod
12
go.mod
|
@ -5,11 +5,11 @@ go 1.15
|
||||||
require (
|
require (
|
||||||
github.com/google/go-cmp v0.5.6
|
github.com/google/go-cmp v0.5.6
|
||||||
go.uber.org/zap v1.19.1
|
go.uber.org/zap v1.19.1
|
||||||
k8s.io/api v0.23.8
|
k8s.io/api v0.23.9
|
||||||
k8s.io/apimachinery v0.23.8
|
k8s.io/apimachinery v0.23.9
|
||||||
k8s.io/client-go v0.23.8
|
k8s.io/client-go v0.23.9
|
||||||
k8s.io/code-generator v0.23.8
|
k8s.io/code-generator v0.23.9
|
||||||
k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65
|
k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65
|
||||||
knative.dev/hack v0.0.0-20220725145124-782bbaabb8a1
|
knative.dev/hack v0.0.0-20220728013938-9dabf7cf62e3
|
||||||
knative.dev/pkg v0.0.0-20220722175921-6c9c1c6098d5
|
knative.dev/pkg v0.0.0-20220802185824-a01dfedb0486
|
||||||
)
|
)
|
||||||
|
|
38
go.sum
38
go.sum
|
@ -1119,36 +1119,36 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
|
||||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||||
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||||
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||||
k8s.io/api v0.23.8 h1:tBMQ7z7s1NUUii649OaGe962xPacUzHwnGEj6Ahneu0=
|
k8s.io/api v0.23.9 h1:v7Ee2CZuyb6rVm1q4bUe7ZonWleLsrvgcOTxPGjQVa4=
|
||||||
k8s.io/api v0.23.8/go.mod h1:26VNldp5fRyiZ/tEO/3V8RJW+In1Aay3YkxsDzkvuWU=
|
k8s.io/api v0.23.9/go.mod h1:r4g0GrGdLgwSYB90qgO4tBrbKtALBhUfut+oFt4ikCc=
|
||||||
k8s.io/apiextensions-apiserver v0.23.8/go.mod h1:pcYtXkSRncXGgCCQSbTqppO3XMaLWdqlDisD4dUKQ/U=
|
k8s.io/apiextensions-apiserver v0.23.9/go.mod h1:uu79PjF1T6YbfFqL5kVTmEdxb40Z0eHM7MfHDHz9dho=
|
||||||
k8s.io/apimachinery v0.23.8 h1:6Z+0LLvvPnAF6GXbUcBmzB1+b/AnDZpVd2N0MxUJcl0=
|
k8s.io/apimachinery v0.23.9 h1:u9Pu7Ffe+9+QJUemtNjuCwvHSnOUeYEwgSHV+88Ne0g=
|
||||||
k8s.io/apimachinery v0.23.8/go.mod h1:BEuFMMBaIbcOqVIJqNZJXGFTP4W6AycEpb5+m/97hrM=
|
k8s.io/apimachinery v0.23.9/go.mod h1:BEuFMMBaIbcOqVIJqNZJXGFTP4W6AycEpb5+m/97hrM=
|
||||||
k8s.io/apiserver v0.23.8/go.mod h1:/WVQG619hfUCgp3pazpqVspyC83NJemH5B0qxlZjNpw=
|
k8s.io/apiserver v0.23.9/go.mod h1:vIXpgCnHep34bP/y+wGhYdn1NgxAvWtntxfEjst0e74=
|
||||||
k8s.io/client-go v0.23.8 h1:0POvFP1/bN0DQYO41ks1tdzIBf9I+afqpUUNedyZ3T4=
|
k8s.io/client-go v0.23.9 h1:OKxNCL+nhw7UBB5b01OVuAV4Db/AdBdaV6/GYpucuOw=
|
||||||
k8s.io/client-go v0.23.8/go.mod h1:m9GosuTn6NlShCjb5XvrRlNDuHeIbGrsDLxjDoS6gec=
|
k8s.io/client-go v0.23.9/go.mod h1:sNo0X0MZqo4Uu0qDY5Fl5Y60cJFinBDWWUBOAM5JUCM=
|
||||||
k8s.io/code-generator v0.23.8 h1:YHHiSaUd2uzLhUpzh1Wlsz20ah0BG6V3gYjkYSte8Gs=
|
k8s.io/code-generator v0.23.9 h1:nCvstXOrfWAbxcmrUzJ+TpRsbPHh2XVDNKxqzkH/nH4=
|
||||||
k8s.io/code-generator v0.23.8/go.mod h1:S0Q1JVA+kSzTI1oUvbKAxZY/DYbA/ZUb4Uknog12ETk=
|
k8s.io/code-generator v0.23.9/go.mod h1:S0Q1JVA+kSzTI1oUvbKAxZY/DYbA/ZUb4Uknog12ETk=
|
||||||
k8s.io/component-base v0.23.8/go.mod h1:rCj6EeaYLsNneVoFuSPL/AlEWmomc39j9M9i4NpR8r0=
|
k8s.io/component-base v0.23.9/go.mod h1:WUNtIRIMd9WBS2r5LCSNZoh6f/Uh+8O+aGuZUG5t428=
|
||||||
k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
|
k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
|
||||||
k8s.io/gengo v0.0.0-20220307231824-4627b89bbf1b h1:vEhKDJESYfeRiaBNmRvO+/12RAo1cFeu6vGm1fBFY34=
|
k8s.io/gengo v0.0.0-20220613173612-397b4ae3bce7 h1:RGb68G3yotdQggcyenx9y0+lnVJCXXcLa6geXOMlf5o=
|
||||||
k8s.io/gengo v0.0.0-20220307231824-4627b89bbf1b/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
|
k8s.io/gengo v0.0.0-20220613173612-397b4ae3bce7/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
|
||||||
k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
|
k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
|
||||||
k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
|
k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
|
||||||
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-0.20220317184644-43cc75f9ae89 h1:bUNlsw5yb353zbKMj8srOr6V2Ajhz1VkTKonP1L8r2o=
|
k8s.io/klog/v2 v2.70.2-0.20220707122935-0990e81f1a8f h1:dltw7bAn8bCrQ2CmzzhgoieUZEbWqrvIGVdHGioP5nY=
|
||||||
k8s.io/klog/v2 v2.60.1-0.20220317184644-43cc75f9ae89/go.mod h1:N3kgBtsFxMb4nQ0eBDgbHEt/dtxBuTkSFQ+7K5OUoz4=
|
k8s.io/klog/v2 v2.70.2-0.20220707122935-0990e81f1a8f/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
|
||||||
k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65 h1:E3J9oCLlaobFUqsjG9DfKbP2BmgwBL2p7pn0A3dG9W4=
|
k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65 h1:E3J9oCLlaobFUqsjG9DfKbP2BmgwBL2p7pn0A3dG9W4=
|
||||||
k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65/go.mod h1:sX9MT8g7NVZM5lVL/j8QyCCJe8YSMW30QvGZWaCIDIk=
|
k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65/go.mod h1:sX9MT8g7NVZM5lVL/j8QyCCJe8YSMW30QvGZWaCIDIk=
|
||||||
k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
||||||
k8s.io/utils v0.0.0-20211116205334-6203023598ed/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
k8s.io/utils v0.0.0-20211116205334-6203023598ed/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
||||||
k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9 h1:HNSDgDCrr/6Ly3WEGKZftiE7IY19Vz2GdbOCyI4qqhc=
|
k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9 h1:HNSDgDCrr/6Ly3WEGKZftiE7IY19Vz2GdbOCyI4qqhc=
|
||||||
k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
||||||
knative.dev/hack v0.0.0-20220721014222-a6450400b5f1/go.mod h1:PHt8x8yX5Z9pPquBEfIj0X66f8iWkWfR0S/sarACJrI=
|
|
||||||
knative.dev/hack v0.0.0-20220725145124-782bbaabb8a1 h1:90z6q68YSEUuPR5P5j8W6viTO8Pi/MhNnHEIhX3Uvnk=
|
|
||||||
knative.dev/hack v0.0.0-20220725145124-782bbaabb8a1/go.mod h1:t/azP8I/Cygaw+87O7rkAPrNRjCelmtfSzWzu/9TM7I=
|
knative.dev/hack v0.0.0-20220725145124-782bbaabb8a1/go.mod h1:t/azP8I/Cygaw+87O7rkAPrNRjCelmtfSzWzu/9TM7I=
|
||||||
knative.dev/pkg v0.0.0-20220722175921-6c9c1c6098d5 h1:wfxvM/LiVcnHxZCOeBQwFcjJxIGIhhNglK0uj3dwmms=
|
knative.dev/hack v0.0.0-20220728013938-9dabf7cf62e3 h1:1JsQ8ylMK+9yQfuxXvGBux+NOzvNLQyoyTXlupBrfHE=
|
||||||
knative.dev/pkg v0.0.0-20220722175921-6c9c1c6098d5/go.mod h1:zaGmg6so9RiTx8Fu6vCSUClfVtOBtCrsD/j3c2y+no8=
|
knative.dev/hack v0.0.0-20220728013938-9dabf7cf62e3/go.mod h1:t/azP8I/Cygaw+87O7rkAPrNRjCelmtfSzWzu/9TM7I=
|
||||||
|
knative.dev/pkg v0.0.0-20220802185824-a01dfedb0486 h1:eWw7LtEIq2GjR9Z5Uw86BlVYyLh50ueJfcXV0SQiMWc=
|
||||||
|
knative.dev/pkg v0.0.0-20220802185824-a01dfedb0486/go.mod h1:nBMKMJvyoaJdkpUrjwLVs/DwaP6d73R3UkXK6lblJyE=
|
||||||
pgregory.net/rapid v0.3.3/go.mod h1:UYpPVyjFHzYBGHIxLFoupi8vwk6rXNzRY9OMvVxFIOU=
|
pgregory.net/rapid v0.3.3/go.mod h1:UYpPVyjFHzYBGHIxLFoupi8vwk6rXNzRY9OMvVxFIOU=
|
||||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||||
|
|
|
@ -28,12 +28,14 @@ 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/tools` - no stable API yet (may change eventually), `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.)
|
||||||
which are marked explicitly as `EXPERIMENTAL` in their docs comment. Those
|
which are marked explicitly as `EXPERIMENTAL` in their docs comment. Those
|
||||||
may still change in incompatible ways or get removed entirely.
|
may still change in incompatible ways or get removed entirely. This can only
|
||||||
|
be used for code that is used in tests to avoid situations where non-test
|
||||||
|
code from two different Kubernetes dependencies depends on incompatible
|
||||||
|
releases of klog because an experimental API was changed.
|
||||||
|
|
||||||
----
|
----
|
||||||
|
|
||||||
|
|
|
@ -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{})
|
||||||
|
@ -80,27 +68,17 @@ func SetLogger(logger logr.Logger) {
|
||||||
// Supporting direct calls is recommended because it avoids the overhead of
|
// Supporting direct calls is recommended because it avoids the overhead of
|
||||||
// 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.
|
||||||
//
|
|
||||||
// Experimental
|
|
||||||
//
|
|
||||||
// Notice: This function is EXPERIMENTAL and may be changed or removed in a
|
|
||||||
// later release.
|
|
||||||
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ContextualLogger determines whether the logger passed to
|
// ContextualLogger determines whether the logger passed to
|
||||||
// SetLoggerWithOptions may also get called directly. Such a logger cannot rely
|
// SetLoggerWithOptions may also get called directly. Such a logger cannot rely
|
||||||
// on verbosity checking in klog.
|
// on verbosity checking in klog.
|
||||||
//
|
|
||||||
// Experimental
|
|
||||||
//
|
|
||||||
// Notice: This function is EXPERIMENTAL and may be changed or removed in a
|
|
||||||
// later release.
|
|
||||||
func ContextualLogger(enabled bool) LoggerOption {
|
func ContextualLogger(enabled bool) LoggerOption {
|
||||||
return func(o *loggerOptions) {
|
return func(o *loggerOptions) {
|
||||||
o.contextualLogger = enabled
|
o.contextualLogger = enabled
|
||||||
|
@ -108,11 +86,6 @@ func ContextualLogger(enabled bool) LoggerOption {
|
||||||
}
|
}
|
||||||
|
|
||||||
// FlushLogger provides a callback for flushing data buffered by the logger.
|
// FlushLogger provides a callback for flushing data buffered by the logger.
|
||||||
//
|
|
||||||
// Experimental
|
|
||||||
//
|
|
||||||
// Notice: This function is EXPERIMENTAL and may be changed or removed in a
|
|
||||||
// later release.
|
|
||||||
func FlushLogger(flush func()) LoggerOption {
|
func FlushLogger(flush func()) LoggerOption {
|
||||||
return func(o *loggerOptions) {
|
return func(o *loggerOptions) {
|
||||||
o.flush = flush
|
o.flush = flush
|
||||||
|
@ -121,11 +94,6 @@ func FlushLogger(flush func()) LoggerOption {
|
||||||
|
|
||||||
// LoggerOption implements the functional parameter paradigm for
|
// LoggerOption implements the functional parameter paradigm for
|
||||||
// SetLoggerWithOptions.
|
// SetLoggerWithOptions.
|
||||||
//
|
|
||||||
// Experimental
|
|
||||||
//
|
|
||||||
// Notice: This type is EXPERIMENTAL and may be changed or removed in a
|
|
||||||
// later release.
|
|
||||||
type LoggerOption func(o *loggerOptions)
|
type LoggerOption func(o *loggerOptions)
|
||||||
|
|
||||||
type loggerOptions struct {
|
type loggerOptions struct {
|
||||||
|
@ -139,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.
|
||||||
|
@ -151,25 +119,15 @@ func ClearLogger() {
|
||||||
// to avoid the additional overhead for contextual logging.
|
// to avoid the additional overhead for contextual logging.
|
||||||
//
|
//
|
||||||
// This must be called during initialization before goroutines are started.
|
// This must be called during initialization before goroutines are started.
|
||||||
//
|
|
||||||
// Experimental
|
|
||||||
//
|
|
||||||
// Notice: This function is EXPERIMENTAL and may be changed or removed in a
|
|
||||||
// later release.
|
|
||||||
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).
|
||||||
//
|
|
||||||
// Experimental
|
|
||||||
//
|
|
||||||
// Notice: This function is EXPERIMENTAL and may be changed or removed in a
|
|
||||||
// later release.
|
|
||||||
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
|
||||||
}
|
}
|
||||||
|
@ -181,11 +139,6 @@ func FromContext(ctx context.Context) Logger {
|
||||||
// TODO can be used as a last resort by code that has no means of
|
// TODO can be used as a last resort by code that has no means of
|
||||||
// receiving a logger from its caller. FromContext or an explicit logger
|
// receiving a logger from its caller. FromContext or an explicit logger
|
||||||
// parameter should be used instead.
|
// parameter should be used instead.
|
||||||
//
|
|
||||||
// Experimental
|
|
||||||
//
|
|
||||||
// Notice: This function is EXPERIMENTAL and may be changed or removed in a
|
|
||||||
// later release.
|
|
||||||
func TODO() Logger {
|
func TODO() Logger {
|
||||||
return Background()
|
return Background()
|
||||||
}
|
}
|
||||||
|
@ -194,16 +147,11 @@ func TODO() Logger {
|
||||||
// that logger was initialized by the program and not by code that should
|
// that logger was initialized by the program and not by code that should
|
||||||
// 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.
|
||||||
//
|
|
||||||
// Experimental
|
|
||||||
//
|
|
||||||
// Notice: This function is EXPERIMENTAL and may be changed or removed in a
|
|
||||||
// later release.
|
|
||||||
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
|
||||||
|
@ -211,13 +159,8 @@ 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.
|
||||||
//
|
|
||||||
// Experimental
|
|
||||||
//
|
|
||||||
// Notice: This function is EXPERIMENTAL and may be changed or removed in a
|
|
||||||
// later release.
|
|
||||||
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
|
||||||
|
@ -225,13 +168,8 @@ 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.
|
||||||
//
|
|
||||||
// Experimental
|
|
||||||
//
|
|
||||||
// Notice: This function is EXPERIMENTAL and may be changed or removed in a
|
|
||||||
// later release.
|
|
||||||
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
|
||||||
|
@ -239,13 +177,8 @@ 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.
|
||||||
//
|
|
||||||
// Experimental
|
|
||||||
//
|
|
||||||
// Notice: This function is EXPERIMENTAL and may be changed or removed in a
|
|
||||||
// later release.
|
|
||||||
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
|
||||||
|
|
|
@ -2,7 +2,4 @@ module k8s.io/klog/v2
|
||||||
|
|
||||||
go 1.13
|
go 1.13
|
||||||
|
|
||||||
require (
|
require github.com/go-logr/logr v1.2.0
|
||||||
github.com/go-logr/logr v1.2.0
|
|
||||||
k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9
|
|
||||||
)
|
|
||||||
|
|
|
@ -1,13 +1,2 @@
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
|
||||||
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
|
|
||||||
github.com/go-logr/logr v1.2.0 h1:QK40JKJyMdUDz+h+xvCsru/bJhvG0UxvePV0ufL/AcE=
|
github.com/go-logr/logr v1.2.0 h1:QK40JKJyMdUDz+h+xvCsru/bJhvG0UxvePV0ufL/AcE=
|
||||||
github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
|
||||||
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
|
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
|
||||||
k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
|
|
||||||
k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9 h1:HNSDgDCrr/6Ly3WEGKZftiE7IY19Vz2GdbOCyI4qqhc=
|
|
||||||
k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
|
||||||
|
|
|
@ -24,35 +24,15 @@ import (
|
||||||
// without directly importing it.
|
// without directly importing it.
|
||||||
|
|
||||||
// Logger in this package is exactly the same as logr.Logger.
|
// Logger in this package is exactly the same as logr.Logger.
|
||||||
//
|
|
||||||
// Experimental
|
|
||||||
//
|
|
||||||
// Notice: This type is EXPERIMENTAL and may be changed or removed in a
|
|
||||||
// later release.
|
|
||||||
type Logger = logr.Logger
|
type Logger = logr.Logger
|
||||||
|
|
||||||
// LogSink in this package is exactly the same as logr.LogSink.
|
// LogSink in this package is exactly the same as logr.LogSink.
|
||||||
//
|
|
||||||
// Experimental
|
|
||||||
//
|
|
||||||
// Notice: This type is EXPERIMENTAL and may be changed or removed in a
|
|
||||||
// later release.
|
|
||||||
type LogSink = logr.LogSink
|
type LogSink = logr.LogSink
|
||||||
|
|
||||||
// Runtimeinfo in this package is exactly the same as logr.RuntimeInfo.
|
// Runtimeinfo in this package is exactly the same as logr.RuntimeInfo.
|
||||||
//
|
|
||||||
// Experimental
|
|
||||||
//
|
|
||||||
// Notice: This type is EXPERIMENTAL and may be changed or removed in a
|
|
||||||
// later release.
|
|
||||||
type RuntimeInfo = logr.RuntimeInfo
|
type RuntimeInfo = logr.RuntimeInfo
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// New is an alias for logr.New.
|
// New is an alias for logr.New.
|
||||||
//
|
|
||||||
// Experimental
|
|
||||||
//
|
|
||||||
// Notice: This variable is EXPERIMENTAL and may be changed or removed in a
|
|
||||||
// later release.
|
|
||||||
New = logr.New
|
New = logr.New
|
||||||
)
|
)
|
||||||
|
|
|
@ -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).
|
|
@ -0,0 +1,178 @@
|
||||||
|
/*
|
||||||
|
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)
|
||||||
|
// Tick returns the channel of a new Ticker.
|
||||||
|
// This method does not allow to free/GC the backing ticker. Use
|
||||||
|
// NewTicker from WithTicker instead.
|
||||||
|
Tick(d time.Duration) <-chan time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithTicker allows for injecting fake or real clocks into code that
|
||||||
|
// needs to do arbitrary things based on time.
|
||||||
|
type WithTicker interface {
|
||||||
|
Clock
|
||||||
|
// 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 {
|
||||||
|
WithTicker
|
||||||
|
// 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 _ = WithTicker(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),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tick is the same as time.Tick(d)
|
||||||
|
// This method does not allow to free/GC the backing ticker. Use
|
||||||
|
// NewTicker instead.
|
||||||
|
func (RealClock) Tick(d time.Duration) <-chan time.Time {
|
||||||
|
return time.Tick(d)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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()
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
|
@ -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
|
if len(first) == 0 && len(second)%2 == 0 {
|
||||||
// slices that have an even number of elements.
|
// Nothing to be overridden, second slice is well-formed
|
||||||
// We add (len(kvList) % 2) here to handle the case where there is an
|
// and can be used directly.
|
||||||
// odd number of elements in a kvList.
|
return second
|
||||||
// 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 {
|
// Determine which keys are in the second slice so that we can skip
|
||||||
k := kvList[i2]
|
// them when iterating over the first one. The code intentionally
|
||||||
// if we have already seen this key, do not include it again
|
// favors performance over completeness: we assume that keys are string
|
||||||
if _, ok := seenKeys[k]; ok {
|
// 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
|
continue
|
||||||
}
|
}
|
||||||
// make a note that we've observed a new key
|
merged = append(merged, key, first[i+1])
|
||||||
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
|
merged = append(merged, second...)
|
||||||
// the original order as we are iterating over the slice backwards
|
if len(merged)%2 != 0 {
|
||||||
outs[i] = append([]interface{}{k, v}, outs[i]...)
|
merged = append(merged, missingValue)
|
||||||
}
|
}
|
||||||
}
|
return merged
|
||||||
return outs
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
@ -91,9 +95,10 @@ import (
|
||||||
"github.com/go-logr/logr"
|
"github.com/go-logr/logr"
|
||||||
|
|
||||||
"k8s.io/klog/v2/internal/buffer"
|
"k8s.io/klog/v2/internal/buffer"
|
||||||
|
"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/utils/clock"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// severityValue identifies the sort of log: info, warning etc. It also implements
|
// severityValue identifies the sort of log: info, warning etc. It also implements
|
||||||
|
@ -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,
|
||||||
|
|
|
@ -25,11 +25,6 @@ import (
|
||||||
// NewKlogr returns a logger that is functionally identical to
|
// NewKlogr returns a logger that is functionally identical to
|
||||||
// klogr.NewWithOptions(klogr.FormatKlog), i.e. it passes through to klog. The
|
// klogr.NewWithOptions(klogr.FormatKlog), i.e. it passes through to klog. The
|
||||||
// difference is that it uses a simpler implementation.
|
// difference is that it uses a simpler implementation.
|
||||||
//
|
|
||||||
// Experimental
|
|
||||||
//
|
|
||||||
// Notice: This function is EXPERIMENTAL and may be changed or removed in a
|
|
||||||
// later release.
|
|
||||||
func NewKlogr() Logger {
|
func NewKlogr() Logger {
|
||||||
return New(&klogger{})
|
return New(&klogger{})
|
||||||
}
|
}
|
||||||
|
@ -48,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 {
|
||||||
|
@ -60,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
|
||||||
|
|
|
@ -314,7 +314,7 @@ gopkg.in/inf.v0
|
||||||
gopkg.in/yaml.v2
|
gopkg.in/yaml.v2
|
||||||
# gopkg.in/yaml.v3 v3.0.1
|
# gopkg.in/yaml.v3 v3.0.1
|
||||||
gopkg.in/yaml.v3
|
gopkg.in/yaml.v3
|
||||||
# k8s.io/api v0.23.8
|
# k8s.io/api v0.23.9
|
||||||
## explicit
|
## explicit
|
||||||
k8s.io/api/admissionregistration/v1
|
k8s.io/api/admissionregistration/v1
|
||||||
k8s.io/api/admissionregistration/v1beta1
|
k8s.io/api/admissionregistration/v1beta1
|
||||||
|
@ -361,7 +361,7 @@ k8s.io/api/scheduling/v1beta1
|
||||||
k8s.io/api/storage/v1
|
k8s.io/api/storage/v1
|
||||||
k8s.io/api/storage/v1alpha1
|
k8s.io/api/storage/v1alpha1
|
||||||
k8s.io/api/storage/v1beta1
|
k8s.io/api/storage/v1beta1
|
||||||
# k8s.io/apimachinery v0.23.8
|
# k8s.io/apimachinery v0.23.9
|
||||||
## explicit
|
## explicit
|
||||||
k8s.io/apimachinery/pkg/api/equality
|
k8s.io/apimachinery/pkg/api/equality
|
||||||
k8s.io/apimachinery/pkg/api/errors
|
k8s.io/apimachinery/pkg/api/errors
|
||||||
|
@ -410,7 +410,7 @@ k8s.io/apimachinery/pkg/version
|
||||||
k8s.io/apimachinery/pkg/watch
|
k8s.io/apimachinery/pkg/watch
|
||||||
k8s.io/apimachinery/third_party/forked/golang/json
|
k8s.io/apimachinery/third_party/forked/golang/json
|
||||||
k8s.io/apimachinery/third_party/forked/golang/reflect
|
k8s.io/apimachinery/third_party/forked/golang/reflect
|
||||||
# k8s.io/client-go v0.23.8
|
# k8s.io/client-go v0.23.9
|
||||||
## explicit
|
## explicit
|
||||||
k8s.io/client-go/applyconfigurations/admissionregistration/v1
|
k8s.io/client-go/applyconfigurations/admissionregistration/v1
|
||||||
k8s.io/client-go/applyconfigurations/admissionregistration/v1beta1
|
k8s.io/client-go/applyconfigurations/admissionregistration/v1beta1
|
||||||
|
@ -536,7 +536,7 @@ k8s.io/client-go/util/homedir
|
||||||
k8s.io/client-go/util/keyutil
|
k8s.io/client-go/util/keyutil
|
||||||
k8s.io/client-go/util/retry
|
k8s.io/client-go/util/retry
|
||||||
k8s.io/client-go/util/workqueue
|
k8s.io/client-go/util/workqueue
|
||||||
# k8s.io/code-generator v0.23.8
|
# k8s.io/code-generator v0.23.9
|
||||||
## explicit
|
## explicit
|
||||||
k8s.io/code-generator
|
k8s.io/code-generator
|
||||||
k8s.io/code-generator/cmd/client-gen
|
k8s.io/code-generator/cmd/client-gen
|
||||||
|
@ -571,7 +571,7 @@ k8s.io/code-generator/cmd/set-gen
|
||||||
k8s.io/code-generator/pkg/namer
|
k8s.io/code-generator/pkg/namer
|
||||||
k8s.io/code-generator/pkg/util
|
k8s.io/code-generator/pkg/util
|
||||||
k8s.io/code-generator/third_party/forked/golang/reflect
|
k8s.io/code-generator/third_party/forked/golang/reflect
|
||||||
# k8s.io/gengo v0.0.0-20220307231824-4627b89bbf1b
|
# k8s.io/gengo v0.0.0-20220613173612-397b4ae3bce7
|
||||||
k8s.io/gengo/args
|
k8s.io/gengo/args
|
||||||
k8s.io/gengo/examples/deepcopy-gen/generators
|
k8s.io/gengo/examples/deepcopy-gen/generators
|
||||||
k8s.io/gengo/examples/defaulter-gen/generators
|
k8s.io/gengo/examples/defaulter-gen/generators
|
||||||
|
@ -582,9 +582,11 @@ k8s.io/gengo/generator
|
||||||
k8s.io/gengo/namer
|
k8s.io/gengo/namer
|
||||||
k8s.io/gengo/parser
|
k8s.io/gengo/parser
|
||||||
k8s.io/gengo/types
|
k8s.io/gengo/types
|
||||||
# k8s.io/klog/v2 v2.60.1-0.20220317184644-43cc75f9ae89
|
# k8s.io/klog/v2 v2.70.2-0.20220707122935-0990e81f1a8f
|
||||||
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/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-20211115234752-e816edb12b65
|
# k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65
|
||||||
|
@ -606,10 +608,10 @@ k8s.io/utils/integer
|
||||||
k8s.io/utils/internal/third_party/forked/golang/net
|
k8s.io/utils/internal/third_party/forked/golang/net
|
||||||
k8s.io/utils/net
|
k8s.io/utils/net
|
||||||
k8s.io/utils/trace
|
k8s.io/utils/trace
|
||||||
# knative.dev/hack v0.0.0-20220725145124-782bbaabb8a1
|
# knative.dev/hack v0.0.0-20220728013938-9dabf7cf62e3
|
||||||
## explicit
|
## explicit
|
||||||
knative.dev/hack
|
knative.dev/hack
|
||||||
# knative.dev/pkg v0.0.0-20220722175921-6c9c1c6098d5
|
# knative.dev/pkg v0.0.0-20220802185824-a01dfedb0486
|
||||||
## explicit
|
## explicit
|
||||||
knative.dev/pkg/apis
|
knative.dev/pkg/apis
|
||||||
knative.dev/pkg/apis/duck
|
knative.dev/pkg/apis/duck
|
||||||
|
|
Loading…
Reference in New Issue