From 003f2157671a694aefecd4dbb7df786e27200a18 Mon Sep 17 00:00:00 2001 From: Wei Fu Date: Tue, 11 Mar 2025 13:26:55 -0400 Subject: [PATCH] *: reduce tracing events during streaming JSON objects If apiserver is handing heavy traffic volume, it's likely to trigger tracing events. After streaming JSON objects, the number of tracing events are same to object number. It's unneccessary to log each write call. This patch is to reduce tracing events. Signed-off-by: Wei Fu --- .../handlers/responsewriters/writers.go | 48 ++++++++++++------- 1 file changed, 30 insertions(+), 18 deletions(-) diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters/writers.go b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters/writers.go index ec5ff956320..c408c556df0 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters/writers.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters/writers.go @@ -200,6 +200,10 @@ type deferredResponseWriter struct { hasWritten bool hw http.ResponseWriter w io.Writer + // totalBytes is the number of bytes written to `w` and does not include buffered bytes + totalBytes int + // lastWriteErr holds the error result (if any) of the last write attempt to `w` + lastWriteErr error ctx context.Context } @@ -242,26 +246,11 @@ func (w *deferredResponseWriter) Write(p []byte) (n int, err error) { } func (w *deferredResponseWriter) unbufferedWrite(p []byte) (n int, err error) { - ctx := w.ctx - span := tracing.SpanFromContext(ctx) - // This Step usually wraps in-memory object serialization. - span.AddEvent("About to start writing response", attribute.Int("size", len(p))) - - firstWrite := !w.hasWritten defer func() { - if err != nil { - span.AddEvent("Write call failed", - attribute.String("writer", fmt.Sprintf("%T", w.w)), - attribute.Int("size", len(p)), - attribute.Bool("firstWrite", firstWrite), - attribute.String("err", err.Error())) - } else { - span.AddEvent("Write call succeeded", - attribute.String("writer", fmt.Sprintf("%T", w.w)), - attribute.Int("size", len(p)), - attribute.Bool("firstWrite", firstWrite)) - } + w.totalBytes += n + w.lastWriteErr = err }() + if w.hasWritten { return w.w.Write(p) } @@ -282,12 +271,35 @@ func (w *deferredResponseWriter) unbufferedWrite(p []byte) (n int, err error) { w.w = hw } + span := tracing.SpanFromContext(w.ctx) + span.AddEvent("About to start writing response", + attribute.String("writer", fmt.Sprintf("%T", w.w)), + attribute.Int("size", len(p)), + ) + header.Set("Content-Type", w.mediaType) hw.WriteHeader(w.statusCode) return w.w.Write(p) } func (w *deferredResponseWriter) Close() (err error) { + defer func() { + if !w.hasWritten { + return + } + + span := tracing.SpanFromContext(w.ctx) + + if w.lastWriteErr != nil { + span.AddEvent("Write call failed", + attribute.Int("size", w.totalBytes), + attribute.String("err", w.lastWriteErr.Error())) + } else { + span.AddEvent("Write call succeeded", + attribute.Int("size", w.totalBytes)) + } + }() + if !w.hasWritten { if !w.hasBuffered { return nil