in internal/httplog/roundtripper.go [92:145]
func (rt *LoggingRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
// Create a child logger for this request.
txID := rt.nextTxID()
log := rt.txLog.With(
slog.String("transaction.id", txID),
)
if v := req.Context().Value(TraceIDKey); v != nil {
if traceID, ok := v.(string); ok {
log = log.With(slog.String("trace.id", traceID))
}
}
req, respParts, errorsMessages := logRequest(log, req, rt.maxBodyLen)
resp, err := rt.transport.RoundTrip(req)
if err != nil {
return resp, err
}
if resp == nil {
return resp, err
}
respParts = append(respParts,
slog.Int("http.response.status_code", resp.StatusCode),
)
errorsMessages = errorsMessages[:0]
var body []byte
resp.Body, body, err = copyBody(resp.Body)
if err != nil {
errorsMessages = append(errorsMessages, fmt.Sprintf("failed to read response body: %s", err))
}
respParts = append(respParts,
slog.Any("http.response.body.content", byteString(body[:min(len(body), rt.maxBodyLen)])),
slog.Bool("http.response.body.truncated", rt.maxBodyLen < len(body)),
slog.Int("http.response.body.bytes", len(body)),
slog.String("http.response.mime_type", resp.Header.Get("Content-Type")),
)
message, err := httputil.DumpResponse(resp, false)
if err != nil {
errorsMessages = append(errorsMessages, fmt.Sprintf("failed to dump response: %s", err))
} else {
respParts = append(respParts, slog.Any("event.original", byteString(message)))
}
switch len(errorsMessages) {
case 0:
case 1:
respParts = append(respParts, slog.String("error.message", errorsMessages[0]))
default:
respParts = append(respParts, slog.Any("error.message", errorsMessages))
}
log.LogAttrs(context.Background(), slog.LevelInfo, "HTTP response", respParts...)
return resp, err
}