From 9ff9bbbc478811d9ab7cb756a8489477e286d36f 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 Kubernetes-commit: 003f2157671a694aefecd4dbb7df786e27200a18 --- .../handlers/responsewriters/writers.go | 48 ++++++++++++------- 1 file changed, 30 insertions(+), 18 deletions(-) diff --git a/pkg/endpoints/handlers/responsewriters/writers.go b/pkg/endpoints/handlers/responsewriters/writers.go index e1d440f4a..55f8b657a 100644 --- a/pkg/endpoints/handlers/responsewriters/writers.go +++ b/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