Skip to content

Commit b738646

Browse files
committed
client-go rest: store logger in Result
Storing a context and making sure that it never gets canceled also has overhead. We might as well just do the klog.FromContext when constructing the Result and store the logger for later use.
1 parent 7821abf commit b738646

File tree

1 file changed

+25
-30
lines changed

1 file changed

+25
-30
lines changed

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

Lines changed: 25 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -762,7 +762,7 @@ func (r *Request) Watch(ctx context.Context) (watch.Interface, error) {
762762

763763
func (r *Request) watchInternal(ctx context.Context) (watch.Interface, runtime.Decoder, error) {
764764
if r.body == nil {
765-
logBody(ctx, 2, "Request Body", r.bodyBytes)
765+
logBody(klog.FromContext(ctx), 2, "Request Body", r.bodyBytes)
766766
}
767767

768768
// We specifically don't want to rate limit watches, so we
@@ -921,7 +921,7 @@ func (r WatchListResult) Into(obj runtime.Object) error {
921921
// to see what parameters are currently required.
922922
func (r *Request) WatchList(ctx context.Context) WatchListResult {
923923
if r.body == nil {
924-
logBody(ctx, 2, "Request Body", r.bodyBytes)
924+
logBody(klog.FromContext(ctx), 2, "Request Body", r.bodyBytes)
925925
}
926926

927927
if !clientfeatures.FeatureGates().Enabled(clientfeatures.WatchListClient) {
@@ -1054,7 +1054,7 @@ func sanitize(req *Request, resp *http.Response, err error) (string, string) {
10541054
// If we can, we return that as an error. Otherwise, we create an error that lists the http status and the content of the response.
10551055
func (r *Request) Stream(ctx context.Context) (io.ReadCloser, error) {
10561056
if r.body == nil {
1057-
logBody(ctx, 2, "Request Body", r.bodyBytes)
1057+
logBody(klog.FromContext(ctx), 2, "Request Body", r.bodyBytes)
10581058
}
10591059

10601060
if r.err != nil {
@@ -1290,16 +1290,17 @@ func (r *Request) request(ctx context.Context, fn func(*http.Request, *http.Resp
12901290
// - If the server responds with a status: *errors.StatusError or *errors.UnexpectedObjectError
12911291
// - http.Client.Do errors are returned directly.
12921292
func (r *Request) Do(ctx context.Context) Result {
1293+
logger := klog.FromContext(ctx)
12931294
if r.body == nil {
1294-
logBody(ctx, 2, "Request Body", r.bodyBytes)
1295+
logBody(logger, 2, "Request Body", r.bodyBytes)
12951296
}
12961297

12971298
var result Result
12981299
err := r.request(ctx, func(req *http.Request, resp *http.Response) {
12991300
result = r.transformResponse(ctx, resp, req)
13001301
})
13011302
if err != nil {
1302-
return Result{err: err, loggingCtx: context.WithoutCancel(ctx)}
1303+
return Result{err: err, logger: logger}
13031304
}
13041305
if result.err == nil || len(result.body) > 0 {
13051306
metrics.ResponseSize.Observe(ctx, r.verb, r.URL().Host, float64(len(result.body)))
@@ -1309,14 +1310,15 @@ func (r *Request) Do(ctx context.Context) Result {
13091310

13101311
// DoRaw executes the request but does not process the response body.
13111312
func (r *Request) DoRaw(ctx context.Context) ([]byte, error) {
1313+
logger := klog.FromContext(ctx)
13121314
if r.body == nil {
1313-
logBody(ctx, 2, "Request Body", r.bodyBytes)
1315+
logBody(logger, 2, "Request Body", r.bodyBytes)
13141316
}
13151317

13161318
var result Result
13171319
err := r.request(ctx, func(req *http.Request, resp *http.Response) {
13181320
result.body, result.err = io.ReadAll(resp.Body)
1319-
logBody(ctx, 2, "Response Body", result.body)
1321+
logBody(logger, 2, "Response Body", result.body)
13201322
if resp.StatusCode < http.StatusOK || resp.StatusCode > http.StatusPartialContent {
13211323
result.err = r.transformUnstructuredResponseError(resp, req, result.body)
13221324
}
@@ -1332,6 +1334,7 @@ func (r *Request) DoRaw(ctx context.Context) ([]byte, error) {
13321334

13331335
// transformResponse converts an API response into a structured API object
13341336
func (r *Request) transformResponse(ctx context.Context, resp *http.Response, req *http.Request) Result {
1337+
logger := klog.FromContext(ctx)
13351338
var body []byte
13361339
if resp.Body != nil {
13371340
data, err := io.ReadAll(resp.Body)
@@ -1346,24 +1349,24 @@ func (r *Request) transformResponse(ctx context.Context, resp *http.Response, re
13461349
// 2. Apiserver sends back the headers and then part of the body
13471350
// 3. Apiserver closes connection.
13481351
// 4. client-go should catch this and return an error.
1349-
klog.FromContext(ctx).V(2).Info("Stream error when reading response body, may be caused by closed connection", "err", err)
1352+
logger.V(2).Info("Stream error when reading response body, may be caused by closed connection", "err", err)
13501353
streamErr := fmt.Errorf("stream error when reading response body, may be caused by closed connection. Please retry. Original error: %w", err)
13511354
return Result{
1352-
err: streamErr,
1353-
loggingCtx: context.WithoutCancel(ctx),
1355+
err: streamErr,
1356+
logger: logger,
13541357
}
13551358
default:
1356-
klog.FromContext(ctx).Error(err, "Unexpected error when reading response body")
1359+
logger.Error(err, "Unexpected error when reading response body")
13571360
unexpectedErr := fmt.Errorf("unexpected error when reading response body. Please retry. Original error: %w", err)
13581361
return Result{
1359-
err: unexpectedErr,
1360-
loggingCtx: context.WithoutCancel(ctx),
1362+
err: unexpectedErr,
1363+
logger: logger,
13611364
}
13621365
}
13631366
}
13641367

13651368
// Call depth is tricky. This one is okay for Do and DoRaw.
1366-
logBody(ctx, 7, "Response Body", body)
1369+
logBody(logger, 7, "Response Body", body)
13671370

13681371
// verify the content type is accurate
13691372
var decoder runtime.Decoder
@@ -1375,7 +1378,7 @@ func (r *Request) transformResponse(ctx context.Context, resp *http.Response, re
13751378
var err error
13761379
mediaType, params, err := mime.ParseMediaType(contentType)
13771380
if err != nil {
1378-
return Result{err: errors.NewInternalError(err), loggingCtx: context.WithoutCancel(ctx)}
1381+
return Result{err: errors.NewInternalError(err), logger: logger}
13791382
}
13801383
decoder, err = r.contentConfig.Negotiator.Decoder(mediaType, params)
13811384
if err != nil {
@@ -1384,14 +1387,14 @@ func (r *Request) transformResponse(ctx context.Context, resp *http.Response, re
13841387
case resp.StatusCode == http.StatusSwitchingProtocols:
13851388
// no-op, we've been upgraded
13861389
case resp.StatusCode < http.StatusOK || resp.StatusCode > http.StatusPartialContent:
1387-
return Result{err: r.transformUnstructuredResponseError(resp, req, body), loggingCtx: context.WithoutCancel(ctx)}
1390+
return Result{err: r.transformUnstructuredResponseError(resp, req, body), logger: logger}
13881391
}
13891392
return Result{
13901393
body: body,
13911394
contentType: contentType,
13921395
statusCode: resp.StatusCode,
13931396
warnings: handleWarnings(ctx, resp.Header, r.warningHandler),
1394-
loggingCtx: context.WithoutCancel(ctx),
1397+
logger: logger,
13951398
}
13961399
}
13971400
}
@@ -1411,7 +1414,7 @@ func (r *Request) transformResponse(ctx context.Context, resp *http.Response, re
14111414
decoder: decoder,
14121415
err: err,
14131416
warnings: handleWarnings(ctx, resp.Header, r.warningHandler),
1414-
loggingCtx: context.WithoutCancel(ctx),
1417+
logger: logger,
14151418
}
14161419
}
14171420

@@ -1421,7 +1424,7 @@ func (r *Request) transformResponse(ctx context.Context, resp *http.Response, re
14211424
statusCode: resp.StatusCode,
14221425
decoder: decoder,
14231426
warnings: handleWarnings(ctx, resp.Header, r.warningHandler),
1424-
loggingCtx: context.WithoutCancel(ctx),
1427+
logger: logger,
14251428
}
14261429
}
14271430

@@ -1449,8 +1452,7 @@ func truncateBody(logger klog.Logger, body string) string {
14491452
// whether the body is printable.
14501453
//
14511454
// It needs to be called by all functions which send or receive the data.
1452-
func logBody(ctx context.Context, callDepth int, prefix string, body []byte) {
1453-
logger := klog.FromContext(ctx)
1455+
func logBody(logger klog.Logger, callDepth int, prefix string, body []byte) {
14541456
if loggerV := logger.V(8); loggerV.Enabled() {
14551457
loggerV := loggerV.WithCallDepth(callDepth)
14561458
if bytes.IndexFunc(body, func(r rune) bool {
@@ -1552,10 +1554,7 @@ type Result struct {
15521554
contentType string
15531555
err error
15541556
statusCode int
1555-
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
1557+
logger klog.Logger
15591558

15601559
decoder runtime.Decoder
15611560
}
@@ -1661,11 +1660,7 @@ func (r Result) Error() error {
16611660
// to be backwards compatible with old servers that do not return a version, default to "v1"
16621661
out, _, err := r.decoder.Decode(r.body, &schema.GroupVersionKind{Version: "v1"}, nil)
16631662
if err != nil {
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)
1663+
r.logger.V(5).Info("Body was not decodable (unable to check for Status)", "err", err)
16691664
return r.err
16701665
}
16711666
switch t := out.(type) {

0 commit comments

Comments
 (0)