Skip to content

Commit 7821abf

Browse files
committed
client-go/rest: finish conversion to contextual logging
The remaining calls can be converted without API changes.
1 parent b15a194 commit 7821abf

File tree

9 files changed

+53
-36
lines changed

9 files changed

+53
-36
lines changed

hack/golangci-hints.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ linters-settings: # please keep this alphabetized
143143
contextual k8s.io/api/.*
144144
contextual k8s.io/apimachinery/pkg/util/runtime/.*
145145
contextual k8s.io/client-go/metadata/.*
146+
contextual k8s.io/client-go/rest/.*
146147
contextual k8s.io/client-go/tools/cache/.*
147148
contextual k8s.io/client-go/tools/events/.*
148149
contextual k8s.io/client-go/tools/record/.*

hack/golangci-strict.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ linters-settings: # please keep this alphabetized
189189
contextual k8s.io/api/.*
190190
contextual k8s.io/apimachinery/pkg/util/runtime/.*
191191
contextual k8s.io/client-go/metadata/.*
192+
contextual k8s.io/client-go/rest/.*
192193
contextual k8s.io/client-go/tools/cache/.*
193194
contextual k8s.io/client-go/tools/events/.*
194195
contextual k8s.io/client-go/tools/record/.*

hack/golangci.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@ linters-settings: # please keep this alphabetized
191191
contextual k8s.io/api/.*
192192
contextual k8s.io/apimachinery/pkg/util/runtime/.*
193193
contextual k8s.io/client-go/metadata/.*
194+
contextual k8s.io/client-go/rest/.*
194195
contextual k8s.io/client-go/tools/cache/.*
195196
contextual k8s.io/client-go/tools/events/.*
196197
contextual k8s.io/client-go/tools/record/.*

hack/logcheck.conf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ structured k8s.io/apiserver/pkg/server/options/encryptionconfig/.*
2727
contextual k8s.io/api/.*
2828
contextual k8s.io/apimachinery/pkg/util/runtime/.*
2929
contextual k8s.io/client-go/metadata/.*
30+
contextual k8s.io/client-go/rest/.*
3031
contextual k8s.io/client-go/tools/cache/.*
3132
contextual k8s.io/client-go/tools/events/.*
3233
contextual k8s.io/client-go/tools/record/.*

staging/src/k8s.io/client-go/rest/config.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -558,6 +558,7 @@ func InClusterConfig() (*Config, error) {
558558
tlsClientConfig := TLSClientConfig{}
559559

560560
if _, err := certutil.NewPool(rootCAFile); err != nil {
561+
//nolint:logcheck // The decision to log this instead of returning an error goes back to ~2016. It's part of the client-go API now, so not changing it just to support contextual logging.
561562
klog.Errorf("Expected to load root CA config from %s, but got err: %v", rootCAFile, err)
562563
} else {
563564
tlsClientConfig.CAFile = rootCAFile

staging/src/k8s.io/client-go/rest/plugin.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@ import (
2121
"net/http"
2222
"sync"
2323

24-
"k8s.io/klog/v2"
25-
2624
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
2725
)
2826

@@ -65,7 +63,10 @@ func RegisterAuthProviderPlugin(name string, plugin Factory) error {
6563
if _, found := plugins[name]; found {
6664
return fmt.Errorf("auth Provider Plugin %q was registered twice", name)
6765
}
68-
klog.V(4).Infof("Registered Auth Provider Plugin %q", name)
66+
// RegisterAuthProviderPlugin gets called during the init phase before
67+
// logging is initialized and therefore should not emit logs. If you
68+
// need this message for debugging something, then uncomment it.
69+
// klog.V(4).Infof("Registered Auth Provider Plugin %q", name)
6970
plugins[name] = plugin
7071
return nil
7172
}

staging/src/k8s.io/client-go/rest/request.go

Lines changed: 40 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ import (
5454
"k8s.io/utils/clock"
5555
)
5656

57-
var (
57+
const (
5858
// longThrottleLatency defines threshold for logging requests. All requests being
5959
// throttled (via the provided rateLimiter) for more than longThrottleLatency will
6060
// be logged.
@@ -676,21 +676,17 @@ func (r *Request) tryThrottleWithInfo(ctx context.Context, retryInfo string) err
676676
}
677677
latency := time.Since(now)
678678

679-
var message string
680-
switch {
681-
case len(retryInfo) > 0:
682-
message = fmt.Sprintf("Waited for %v, %s - request: %s:%s", latency, retryInfo, r.verb, r.URL().String())
683-
default:
684-
message = fmt.Sprintf("Waited for %v due to client-side throttling, not priority and fairness, request: %s:%s", latency, r.verb, r.URL().String())
685-
}
686-
687679
if latency > longThrottleLatency {
688-
klog.V(3).Info(message)
689-
}
690-
if latency > extraLongThrottleLatency {
691-
// If the rate limiter latency is very high, the log message should be printed at a higher log level,
692-
// but we use a throttled logger to prevent spamming.
693-
globalThrottledLogger.Infof("%s", message)
680+
if retryInfo == "" {
681+
retryInfo = "client-side throttling, not priority and fairness"
682+
}
683+
klog.FromContext(ctx).V(3).Info("Waited before sending request", "delay", latency, "reason", retryInfo, "verb", r.verb, "URL", r.URL())
684+
685+
if latency > extraLongThrottleLatency {
686+
// If the rate limiter latency is very high, the log message should be printed at a higher log level,
687+
// but we use a throttled logger to prevent spamming.
688+
globalThrottledLogger.info(klog.FromContext(ctx), "Waited before sending request", "delay", latency, "reason", retryInfo, "verb", r.verb, "URL", r.URL())
689+
}
694690
}
695691
metrics.RateLimiterLatency.Observe(ctx, r.verb, r.finalURLTemplate(), latency)
696692

@@ -702,7 +698,7 @@ func (r *Request) tryThrottle(ctx context.Context) error {
702698
}
703699

704700
type throttleSettings struct {
705-
logLevel klog.Level
701+
logLevel int
706702
minLogInterval time.Duration
707703

708704
lastLogTime time.Time
@@ -727,9 +723,9 @@ var globalThrottledLogger = &throttledLogger{
727723
},
728724
}
729725

730-
func (b *throttledLogger) attemptToLog() (klog.Level, bool) {
726+
func (b *throttledLogger) attemptToLog(logger klog.Logger) (int, bool) {
731727
for _, setting := range b.settings {
732-
if bool(klog.V(setting.logLevel).Enabled()) {
728+
if bool(logger.V(setting.logLevel).Enabled()) {
733729
// Return early without write locking if possible.
734730
if func() bool {
735731
setting.lock.RLock()
@@ -751,9 +747,9 @@ func (b *throttledLogger) attemptToLog() (klog.Level, bool) {
751747

752748
// Infof will write a log message at each logLevel specified by the receiver's throttleSettings
753749
// as long as it hasn't written a log message more recently than minLogInterval.
754-
func (b *throttledLogger) Infof(message string, args ...interface{}) {
755-
if logLevel, ok := b.attemptToLog(); ok {
756-
klog.V(logLevel).Infof(message, args...)
750+
func (b *throttledLogger) info(logger klog.Logger, message string, kv ...any) {
751+
if logLevel, ok := b.attemptToLog(logger); ok {
752+
logger.V(logLevel).Info(message, kv...)
757753
}
758754
}
759755

@@ -1000,7 +996,7 @@ func (r *Request) newStreamWatcher(ctx context.Context, resp *http.Response) (wa
1000996
contentType := resp.Header.Get("Content-Type")
1001997
mediaType, params, err := mime.ParseMediaType(contentType)
1002998
if err != nil {
1003-
klog.V(4).Infof("Unexpected content type from the server: %q: %v", contentType, err)
999+
klog.FromContext(ctx).V(4).Info("Unexpected content type from the server", "contentType", contentType, "err", err)
10041000
}
10051001
objectDecoder, streamingSerializer, framer, err := r.contentConfig.Negotiator.StreamDecoder(mediaType, params)
10061002
if err != nil {
@@ -1202,7 +1198,7 @@ func (r *Request) request(ctx context.Context, fn func(*http.Request, *http.Resp
12021198
}()
12031199

12041200
if r.err != nil {
1205-
klog.V(4).Infof("Error in request: %v", r.err)
1201+
klog.FromContext(ctx).V(4).Info("Error in request", "err", r.err)
12061202
return r.err
12071203
}
12081204

@@ -1303,7 +1299,7 @@ func (r *Request) Do(ctx context.Context) Result {
13031299
result = r.transformResponse(ctx, resp, req)
13041300
})
13051301
if err != nil {
1306-
return Result{err: err}
1302+
return Result{err: err, loggingCtx: context.WithoutCancel(ctx)}
13071303
}
13081304
if result.err == nil || len(result.body) > 0 {
13091305
metrics.ResponseSize.Observe(ctx, r.verb, r.URL().Host, float64(len(result.body)))
@@ -1350,16 +1346,18 @@ func (r *Request) transformResponse(ctx context.Context, resp *http.Response, re
13501346
// 2. Apiserver sends back the headers and then part of the body
13511347
// 3. Apiserver closes connection.
13521348
// 4. client-go should catch this and return an error.
1353-
klog.V(2).Infof("Stream error %#v when reading response body, may be caused by closed connection.", err)
1349+
klog.FromContext(ctx).V(2).Info("Stream error when reading response body, may be caused by closed connection", "err", err)
13541350
streamErr := fmt.Errorf("stream error when reading response body, may be caused by closed connection. Please retry. Original error: %w", err)
13551351
return Result{
1356-
err: streamErr,
1352+
err: streamErr,
1353+
loggingCtx: context.WithoutCancel(ctx),
13571354
}
13581355
default:
1359-
klog.Errorf("Unexpected error when reading response body: %v", err)
1356+
klog.FromContext(ctx).Error(err, "Unexpected error when reading response body")
13601357
unexpectedErr := fmt.Errorf("unexpected error when reading response body. Please retry. Original error: %w", err)
13611358
return Result{
1362-
err: unexpectedErr,
1359+
err: unexpectedErr,
1360+
loggingCtx: context.WithoutCancel(ctx),
13631361
}
13641362
}
13651363
}
@@ -1377,7 +1375,7 @@ func (r *Request) transformResponse(ctx context.Context, resp *http.Response, re
13771375
var err error
13781376
mediaType, params, err := mime.ParseMediaType(contentType)
13791377
if err != nil {
1380-
return Result{err: errors.NewInternalError(err)}
1378+
return Result{err: errors.NewInternalError(err), loggingCtx: context.WithoutCancel(ctx)}
13811379
}
13821380
decoder, err = r.contentConfig.Negotiator.Decoder(mediaType, params)
13831381
if err != nil {
@@ -1386,13 +1384,14 @@ func (r *Request) transformResponse(ctx context.Context, resp *http.Response, re
13861384
case resp.StatusCode == http.StatusSwitchingProtocols:
13871385
// no-op, we've been upgraded
13881386
case resp.StatusCode < http.StatusOK || resp.StatusCode > http.StatusPartialContent:
1389-
return Result{err: r.transformUnstructuredResponseError(resp, req, body)}
1387+
return Result{err: r.transformUnstructuredResponseError(resp, req, body), loggingCtx: context.WithoutCancel(ctx)}
13901388
}
13911389
return Result{
13921390
body: body,
13931391
contentType: contentType,
13941392
statusCode: resp.StatusCode,
13951393
warnings: handleWarnings(ctx, resp.Header, r.warningHandler),
1394+
loggingCtx: context.WithoutCancel(ctx),
13961395
}
13971396
}
13981397
}
@@ -1412,6 +1411,7 @@ func (r *Request) transformResponse(ctx context.Context, resp *http.Response, re
14121411
decoder: decoder,
14131412
err: err,
14141413
warnings: handleWarnings(ctx, resp.Header, r.warningHandler),
1414+
loggingCtx: context.WithoutCancel(ctx),
14151415
}
14161416
}
14171417

@@ -1421,6 +1421,7 @@ func (r *Request) transformResponse(ctx context.Context, resp *http.Response, re
14211421
statusCode: resp.StatusCode,
14221422
decoder: decoder,
14231423
warnings: handleWarnings(ctx, resp.Header, r.warningHandler),
1424+
loggingCtx: context.WithoutCancel(ctx),
14241425
}
14251426
}
14261427

@@ -1552,6 +1553,10 @@ type Result struct {
15521553
err error
15531554
statusCode int
15541555

1556+
// Log calls in Result methods use the same context for logging as the
1557+
// method which created the Result. This context has no cancellation.
1558+
loggingCtx context.Context
1559+
15551560
decoder runtime.Decoder
15561561
}
15571562

@@ -1656,7 +1661,11 @@ func (r Result) Error() error {
16561661
// to be backwards compatible with old servers that do not return a version, default to "v1"
16571662
out, _, err := r.decoder.Decode(r.body, &schema.GroupVersionKind{Version: "v1"}, nil)
16581663
if err != nil {
1659-
klog.V(5).Infof("body was not decodable (unable to check for Status): %v", err)
1664+
ctx := r.loggingCtx
1665+
if ctx == nil {
1666+
ctx = context.Background()
1667+
}
1668+
klog.FromContext(ctx).V(5).Info("Body was not decodable (unable to check for Status)", "err", err)
16601669
return r.err
16611670
}
16621671
switch t := out.(type) {

staging/src/k8s.io/client-go/rest/request_test.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2476,6 +2476,7 @@ func TestRequestPreflightCheck(t *testing.T) {
24762476
}
24772477

24782478
func TestThrottledLogger(t *testing.T) {
2479+
logger := klog.Background()
24792480
now := time.Now()
24802481
oldClock := globalThrottledLogger.clock
24812482
defer func() {
@@ -2490,7 +2491,7 @@ func TestThrottledLogger(t *testing.T) {
24902491
wg.Add(10)
24912492
for j := 0; j < 10; j++ {
24922493
go func() {
2493-
if _, ok := globalThrottledLogger.attemptToLog(); ok {
2494+
if _, ok := globalThrottledLogger.attemptToLog(logger); ok {
24942495
logMessages++
24952496
}
24962497
wg.Done()
@@ -4175,6 +4176,7 @@ warnings.go] "Warning: warning 2" logger="TestLogger"
41754176
}
41764177

41774178
for name, tc := range testcases {
4179+
//nolint:logcheck // Intentionally testing with plain klog here.
41784180
t.Run(name, func(t *testing.T) {
41794181
state := klog.CaptureState()
41804182
defer state.Restore()

staging/src/k8s.io/client-go/rest/with_retry.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ func (r *withRetry) Before(ctx context.Context, request *Request) error {
231231
return err
232232
}
233233

234-
klog.V(4).Infof("Got a Retry-After %s response for attempt %d to %v", r.retryAfter.Wait, r.retryAfter.Attempt, request.URL().String())
234+
klog.FromContext(ctx).V(4).Info("Got a Retry-After response", "delay", r.retryAfter.Wait, "attempt", r.retryAfter.Attempt, "url", request.URL())
235235
return nil
236236
}
237237

0 commit comments

Comments
 (0)