@@ -200,6 +200,10 @@ type deferredResponseWriter struct {
200
200
hasWritten bool
201
201
hw http.ResponseWriter
202
202
w io.Writer
203
+ // totalBytes is the number of bytes written to `w` and does not include buffered bytes
204
+ totalBytes int
205
+ // lastWriteErr holds the error result (if any) of the last write attempt to `w`
206
+ lastWriteErr error
203
207
204
208
ctx context.Context
205
209
}
@@ -242,26 +246,11 @@ func (w *deferredResponseWriter) Write(p []byte) (n int, err error) {
242
246
}
243
247
244
248
func (w * deferredResponseWriter ) unbufferedWrite (p []byte ) (n int , err error ) {
245
- ctx := w .ctx
246
- span := tracing .SpanFromContext (ctx )
247
- // This Step usually wraps in-memory object serialization.
248
- span .AddEvent ("About to start writing response" , attribute .Int ("size" , len (p )))
249
-
250
- firstWrite := ! w .hasWritten
251
249
defer func () {
252
- if err != nil {
253
- span .AddEvent ("Write call failed" ,
254
- attribute .String ("writer" , fmt .Sprintf ("%T" , w .w )),
255
- attribute .Int ("size" , len (p )),
256
- attribute .Bool ("firstWrite" , firstWrite ),
257
- attribute .String ("err" , err .Error ()))
258
- } else {
259
- span .AddEvent ("Write call succeeded" ,
260
- attribute .String ("writer" , fmt .Sprintf ("%T" , w .w )),
261
- attribute .Int ("size" , len (p )),
262
- attribute .Bool ("firstWrite" , firstWrite ))
263
- }
250
+ w .totalBytes += n
251
+ w .lastWriteErr = err
264
252
}()
253
+
265
254
if w .hasWritten {
266
255
return w .w .Write (p )
267
256
}
@@ -282,12 +271,35 @@ func (w *deferredResponseWriter) unbufferedWrite(p []byte) (n int, err error) {
282
271
w .w = hw
283
272
}
284
273
274
+ span := tracing .SpanFromContext (w .ctx )
275
+ span .AddEvent ("About to start writing response" ,
276
+ attribute .String ("writer" , fmt .Sprintf ("%T" , w .w )),
277
+ attribute .Int ("size" , len (p )),
278
+ )
279
+
285
280
header .Set ("Content-Type" , w .mediaType )
286
281
hw .WriteHeader (w .statusCode )
287
282
return w .w .Write (p )
288
283
}
289
284
290
285
func (w * deferredResponseWriter ) Close () (err error ) {
286
+ defer func () {
287
+ if ! w .hasWritten {
288
+ return
289
+ }
290
+
291
+ span := tracing .SpanFromContext (w .ctx )
292
+
293
+ if w .lastWriteErr != nil {
294
+ span .AddEvent ("Write call failed" ,
295
+ attribute .Int ("size" , w .totalBytes ),
296
+ attribute .String ("err" , w .lastWriteErr .Error ()))
297
+ } else {
298
+ span .AddEvent ("Write call succeeded" ,
299
+ attribute .Int ("size" , w .totalBytes ))
300
+ }
301
+ }()
302
+
291
303
if ! w .hasWritten {
292
304
if ! w .hasBuffered {
293
305
return nil
0 commit comments