From a091d12f4efacaae0d6e564ff89338652de44ca3 Mon Sep 17 00:00:00 2001 From: hkfires <10558748+hkfires@users.noreply.github.com> Date: Sun, 28 Dec 2025 19:04:31 +0800 Subject: [PATCH 1/3] fix(logging): improve request/response capture --- sdk/api/handlers/handlers.go | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/sdk/api/handlers/handlers.go b/sdk/api/handlers/handlers.go index 86ed9276..840fd894 100644 --- a/sdk/api/handlers/handlers.go +++ b/sdk/api/handlers/handlers.go @@ -618,7 +618,23 @@ func (h *BaseAPIHandler) WriteErrorResponse(c *gin.Context, msg *interfaces.Erro } body := BuildErrorResponseBody(status, errText) - c.Set("API_RESPONSE", bytes.Clone(body)) + // Check if this error body was already recorded by the executor (to avoid duplicate logging) + // This can happen when the last retry fails and both executor and handler try to log the same error + shouldAppend := true + if existing, exists := c.Get("API_RESPONSE"); exists { + if existingBytes, ok := existing.([]byte); ok && len(existingBytes) > 0 { + trimmedBody := bytes.TrimSpace(body) + if len(trimmedBody) > 0 && bytes.Contains(existingBytes, trimmedBody) { + // Error already logged by executor, skip appending + shouldAppend = false + } + } + } + if shouldAppend { + // Use appendAPIResponse to preserve any previously captured API response data + // (such as formatted upstream response logs from logging_helpers.go) + appendAPIResponse(c, body) + } if !c.Writer.Written() { c.Writer.Header().Set("Content-Type", "application/json") From 3ca5fb104669d3fcd90f53846b3458e1d3ac8c47 Mon Sep 17 00:00:00 2001 From: hkfires <10558748+hkfires@users.noreply.github.com> Date: Sun, 28 Dec 2025 19:35:36 +0800 Subject: [PATCH 2/3] fix(handlers): match raw error text before JSON body for duplicate detection --- sdk/api/handlers/handlers.go | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/sdk/api/handlers/handlers.go b/sdk/api/handlers/handlers.go index 840fd894..f70a9dca 100644 --- a/sdk/api/handlers/handlers.go +++ b/sdk/api/handlers/handlers.go @@ -618,15 +618,21 @@ func (h *BaseAPIHandler) WriteErrorResponse(c *gin.Context, msg *interfaces.Erro } body := BuildErrorResponseBody(status, errText) - // Check if this error body was already recorded by the executor (to avoid duplicate logging) - // This can happen when the last retry fails and both executor and handler try to log the same error + // Check if this error was already recorded by the executor (to avoid duplicate logging) + // The executor logs raw error text, so match errText before falling back to the JSON body. shouldAppend := true if existing, exists := c.Get("API_RESPONSE"); exists { if existingBytes, ok := existing.([]byte); ok && len(existingBytes) > 0 { - trimmedBody := bytes.TrimSpace(body) - if len(trimmedBody) > 0 && bytes.Contains(existingBytes, trimmedBody) { + trimmedErrText := strings.TrimSpace(errText) + if trimmedErrText != "" && bytes.Contains(existingBytes, []byte(trimmedErrText)) { // Error already logged by executor, skip appending shouldAppend = false + } else { + trimmedBody := bytes.TrimSpace(body) + if len(trimmedBody) > 0 && bytes.Contains(existingBytes, trimmedBody) { + // Error already logged by executor, skip appending + shouldAppend = false + } } } } From a95428f204da76d79a94f68b3eefde4042642706 Mon Sep 17 00:00:00 2001 From: hkfires <10558748+hkfires@users.noreply.github.com> Date: Sun, 28 Dec 2025 22:35:36 +0800 Subject: [PATCH 3/3] fix(handlers): preserve upstream response logs before duplicate detection --- sdk/api/handlers/handlers.go | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/sdk/api/handlers/handlers.go b/sdk/api/handlers/handlers.go index f70a9dca..5a24c63a 100644 --- a/sdk/api/handlers/handlers.go +++ b/sdk/api/handlers/handlers.go @@ -618,28 +618,21 @@ func (h *BaseAPIHandler) WriteErrorResponse(c *gin.Context, msg *interfaces.Erro } body := BuildErrorResponseBody(status, errText) - // Check if this error was already recorded by the executor (to avoid duplicate logging) - // The executor logs raw error text, so match errText before falling back to the JSON body. - shouldAppend := true + // Append first to preserve upstream response logs, then drop duplicate payloads if already recorded. + var previous []byte if existing, exists := c.Get("API_RESPONSE"); exists { if existingBytes, ok := existing.([]byte); ok && len(existingBytes) > 0 { - trimmedErrText := strings.TrimSpace(errText) - if trimmedErrText != "" && bytes.Contains(existingBytes, []byte(trimmedErrText)) { - // Error already logged by executor, skip appending - shouldAppend = false - } else { - trimmedBody := bytes.TrimSpace(body) - if len(trimmedBody) > 0 && bytes.Contains(existingBytes, trimmedBody) { - // Error already logged by executor, skip appending - shouldAppend = false - } - } + previous = bytes.Clone(existingBytes) } } - if shouldAppend { - // Use appendAPIResponse to preserve any previously captured API response data - // (such as formatted upstream response logs from logging_helpers.go) - appendAPIResponse(c, body) + appendAPIResponse(c, body) + trimmedErrText := strings.TrimSpace(errText) + trimmedBody := bytes.TrimSpace(body) + if len(previous) > 0 { + if (trimmedErrText != "" && bytes.Contains(previous, []byte(trimmedErrText))) || + (len(trimmedBody) > 0 && bytes.Contains(previous, trimmedBody)) { + c.Set("API_RESPONSE", previous) + } } if !c.Writer.Written() {