I'm using OpenTelemetry Go SDK and I'm trying to set http.response.body.size
attribute in my parent span.
I'm using otelhttp.NewHandler()
to serve the HTTP request:
func NewHTTPHandler(name string, handler http.Handler, tp Provider, attr ...Attribute) http.Handler {
opts := []otelhttp.Option{
otelhttp.WithSpanNameFormatter(httpSpanNameFormatter),
}
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
attr = append(attr, NewAttribute("http.request.body.size", r.ContentLength))
opts = append(opts, otelhttp.WithSpanOptions(
trace.WithAttributes(attr...),
))
otelhttp.NewHandler(handler, name, opts...).ServeHTTP(w, r)
})
}
At the moment, I could store the http.request.body.size
value before processing the HTTP request, but I don't know how to do something similar with the response size.
I tried to wrap the response writer with a callback in order to store the size bytes, and it's working, but when I try to get the span using the request context in order to store this attribute, the span is empty (SpanID is "000000000000"), I could notice it by printing it:
type responseWriterWrapper struct {
http.ResponseWriter
contentLength int
onWrite func(int) // callback for when Write is called
}
func (rw *responseWriterWrapper) Write(b []byte) (int, error) {
n, err := rw.ResponseWriter.Write(b)
rw.contentLength += n
rw.onWrite(rw.contentLength)
return n, err
}
func NewHTTPHandler(name string, handler http.Handler, tp Provider, attr ...Attribute) http.Handler {
opts := []otelhttp.Option{
otelhttp.WithSpanNameFormatter(httpSpanNameFormatter),
}
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
attr = append(attr, NewAttribute("http.request.body.size", r.ContentLength))
opts = append(opts, otelhttp.WithSpanOptions(
trace.WithAttributes(attr...),
))
// Setup callback for when Write is called
rwWrapper := &responseWriterWrapper{
ResponseWriter: w,
onWrite: func(length int) {
span := trace.SpanFromContext(r.Context())
fmt.Println("SPAN ID:", span.SpanContext().SpanID())
if span != nil {
span.SetAttributes(NewAttribute("http.response.body.size", int64(length)))
}
},
}
otelhttp.NewHandler(handler, name, opts...).ServeHTTP(rwWrapper, r)
})
}