diff --git a/CHANGELOG.md b/CHANGELOG.md index c0e43b54906..fade99a2389 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,10 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - The deprecated `ResponseContentLength` constant in `go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp` is removed. (#4894) - The deprecated `ServerLatency` constant in `go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp` is removed. (#4894) +### Fixed + +- Retrieving the body bytes count in `go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp` does not cause a data race anymore. (#5080) + ## [1.23.0/0.48.0/0.17.0/0.3.0] - 2024-02-06 ### Added diff --git a/instrumentation/net/http/otelhttp/handler.go b/instrumentation/net/http/otelhttp/handler.go index 3d292dab6d3..1fc15019e65 100644 --- a/instrumentation/net/http/otelhttp/handler.go +++ b/instrumentation/net/http/otelhttp/handler.go @@ -224,7 +224,7 @@ func (h *middleware) serveHTTP(w http.ResponseWriter, r *http.Request, next http next.ServeHTTP(w, r.WithContext(ctx)) - setAfterServeAttributes(span, bw.read, rww.written, rww.statusCode, bw.err, rww.err) + setAfterServeAttributes(span, bw.read.Load(), rww.written, rww.statusCode, bw.err, rww.err) // Add metrics attributes := append(labeler.Get(), semconvutil.HTTPServerRequestMetrics(h.server, r)...) @@ -232,7 +232,7 @@ func (h *middleware) serveHTTP(w http.ResponseWriter, r *http.Request, next http attributes = append(attributes, semconv.HTTPStatusCode(rww.statusCode)) } o := metric.WithAttributes(attributes...) - h.requestBytesCounter.Add(ctx, bw.read, o) + h.requestBytesCounter.Add(ctx, bw.read.Load(), o) h.responseBytesCounter.Add(ctx, rww.written, o) // Use floating point division here for higher precision (instead of Millisecond method). diff --git a/instrumentation/net/http/otelhttp/transport.go b/instrumentation/net/http/otelhttp/transport.go index 8d850df3baa..43e937a67a6 100644 --- a/instrumentation/net/http/otelhttp/transport.go +++ b/instrumentation/net/http/otelhttp/transport.go @@ -182,7 +182,7 @@ func (t *Transport) RoundTrip(r *http.Request) (*http.Response, error) { metricAttrs = append(metricAttrs, semconv.HTTPStatusCode(res.StatusCode)) } o := metric.WithAttributes(metricAttrs...) - t.requestBytesCounter.Add(ctx, bw.read, o) + t.requestBytesCounter.Add(ctx, bw.read.Load(), o) // For handling response bytes we leverage a callback when the client reads the http response readRecordFunc := func(n int64) { t.responseBytesCounter.Add(ctx, n, o) diff --git a/instrumentation/net/http/otelhttp/wrap.go b/instrumentation/net/http/otelhttp/wrap.go index 11a35ed167f..2852ec97171 100644 --- a/instrumentation/net/http/otelhttp/wrap.go +++ b/instrumentation/net/http/otelhttp/wrap.go @@ -18,6 +18,7 @@ import ( "context" "io" "net/http" + "sync/atomic" "go.opentelemetry.io/otel/propagation" ) @@ -30,14 +31,14 @@ type bodyWrapper struct { io.ReadCloser record func(n int64) // must not be nil - read int64 + read atomic.Int64 err error } func (w *bodyWrapper) Read(b []byte) (int, error) { n, err := w.ReadCloser.Read(b) n1 := int64(n) - w.read += n1 + w.read.Add(n1) w.err = err w.record(n1) return n, err