From ed91c59aa332738bd0ac4b994aeec2cdf193a068 Mon Sep 17 00:00:00 2001 From: Stojan Dimitrovski Date: Tue, 24 Sep 2024 09:16:43 +0200 Subject: [PATCH] feat: add `x-sb-error-code` header, show error code in logs (#1765) Adds the `x-sb-error-code` header to non-2XX responses if the error has an error code determined. This is picked up by the request logger which includes it in the request completed log. Furthermore, the same header can be picked up by the API gateway (Supabase world) without having to parse the response to include the error code in request logs too. --- internal/api/errors.go | 6 ++++++ internal/observability/request-logger.go | 11 +++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/internal/api/errors.go b/internal/api/errors.go index 308a85a0f4..17c1474284 100644 --- a/internal/api/errors.go +++ b/internal/api/errors.go @@ -226,6 +226,8 @@ func HandleResponseError(err error, w http.ResponseWriter, r *http.Request) { output.Message = e.Message output.Payload.Reasons = e.Reasons + w.Header().Set("x-sb-error-code", output.ErrorCode) + if jsonErr := sendJSON(w, output.HTTPStatus, output); jsonErr != nil && jsonErr != context.DeadlineExceeded { log.WithError(jsonErr).Warn("Failed to send JSON on ResponseWriter") } @@ -243,6 +245,10 @@ func HandleResponseError(err error, w http.ResponseWriter, r *http.Request) { log.WithError(e.Cause()).Info(e.Error()) } + if e.ErrorCode != "" { + w.Header().Set("x-sb-error-code", e.ErrorCode) + } + if apiVersion.Compare(APIVersion20240101) >= 0 { resp := HTTPErrorResponse20240101{ Code: e.ErrorCode, diff --git a/internal/observability/request-logger.go b/internal/observability/request-logger.go index 804feca3b9..6eeffd6ea1 100644 --- a/internal/observability/request-logger.go +++ b/internal/observability/request-logger.go @@ -69,10 +69,17 @@ type logEntry struct { } func (e *logEntry) Write(status, bytes int, header http.Header, elapsed time.Duration, extra interface{}) { - entry := e.Entry.WithFields(logrus.Fields{ + fields := logrus.Fields{ "status": status, "duration": elapsed.Nanoseconds(), - }) + } + + errorCode := header.Get("x-sb-error-code") + if errorCode != "" { + fields["error_code"] = errorCode + } + + entry := e.Entry.WithFields(fields) entry.Info("request completed") e.Entry = entry }