func()

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
}