When a client disconnects mid-request, the server handler observes the cancelled request context and typically returns an error, which our handlers surface as a 500. otelhttp then records http.response.status_code=500 and sets the span status to Error, because serveHTTP reads the status from RespWriterWrapper (which defaults to 200 and only records what the handler wrote) and never inspects r.Context().Err().
No response reached the client, so per the HTTP semantic conventions http.response.status_code should arguably be absent, since it is required only if a status was received or sent, and error.type should carry a low cardinality identifier instead. The client side already does this in transport.go via semconv.ErrorType, but the server path never sets error.type at all. Is the current server behaviour intentional, and would a check on the request context after next.ServeHTTP to distinguish a client disconnect from a genuine 500 be in scope?
When a client disconnects mid-request, the server handler observes the cancelled request context and typically returns an error, which our handlers surface as a 500. otelhttp then records
http.response.status_code=500and sets the span status to Error, becauseserveHTTPreads the status fromRespWriterWrapper(which defaults to 200 and only records what the handler wrote) and never inspectsr.Context().Err().No response reached the client, so per the HTTP semantic conventions
http.response.status_codeshould arguably be absent, since it is required only if a status was received or sent, anderror.typeshould carry a low cardinality identifier instead. The client side already does this intransport.goviasemconv.ErrorType, but the server path never setserror.typeat all. Is the current server behaviour intentional, and would a check on the request context afternext.ServeHTTPto distinguish a client disconnect from a genuine 500 be in scope?