diff --git a/backend/services/data-management-service/src/main/java/com/datamate/datamanagement/application/PdfTextExtractAsyncService.java b/backend/services/data-management-service/src/main/java/com/datamate/datamanagement/application/PdfTextExtractAsyncService.java index 69bf2c6..c9aef15 100644 --- a/backend/services/data-management-service/src/main/java/com/datamate/datamanagement/application/PdfTextExtractAsyncService.java +++ b/backend/services/data-management-service/src/main/java/com/datamate/datamanagement/application/PdfTextExtractAsyncService.java @@ -4,6 +4,8 @@ import com.datamate.common.infrastructure.common.Response; import com.datamate.datamanagement.infrastructure.client.PdfTextExtractClient; import com.datamate.datamanagement.infrastructure.client.dto.PdfTextExtractRequest; import com.datamate.datamanagement.infrastructure.client.dto.PdfTextExtractResponse; +import feign.FeignException; +import feign.Request; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.scheduling.annotation.Async; @@ -47,8 +49,71 @@ public class PdfTextExtractAsyncService { } else { log.info("PdfTextExtract succeeded, datasetId={}, fileId={}", datasetId, fileId); } + } catch (FeignException feignException) { + logFeignException(datasetId, fileId, feignException); } catch (Exception e) { log.error("PdfTextExtract call failed, datasetId={}, fileId={}", datasetId, fileId, e); } } + + private void logFeignException(String datasetId, String fileId, FeignException feignException) { + Request request = feignException.request(); + String httpMethod = request == null || request.httpMethod() == null + ? "UNKNOWN" + : request.httpMethod().name(); + String requestUrl = request == null || request.url() == null + ? "UNKNOWN" + : request.url(); + String responseBody = resolveFeignResponseBody(feignException); + String rootCauseChain = buildCauseChain(feignException, 12); + log.error( + "PdfTextExtract call failed with FeignException, datasetId={}, fileId={}, status={}, method={}, url={}, responseBody=\n{}\nrootCauseChain={}", + datasetId, + fileId, + feignException.status(), + httpMethod, + requestUrl, + responseBody, + rootCauseChain, + feignException + ); + } + + private String resolveFeignResponseBody(FeignException feignException) { + String responseBody = feignException.contentUTF8(); + if (responseBody == null || responseBody.isBlank()) { + responseBody = feignException.getMessage(); + } + if (responseBody == null || responseBody.isBlank()) { + return "EMPTY_RESPONSE_BODY"; + } + return responseBody; + } + + private String buildCauseChain(Throwable throwable, int maxDepth) { + StringBuilder causeChain = new StringBuilder(); + Throwable current = throwable; + int depth = 0; + while (current != null && depth < maxDepth) { + if (causeChain.length() > 0) { + causeChain.append(" <- "); + } + causeChain.append(current.getClass().getSimpleName()) + .append(": ") + .append(normalizeCauseMessage(current.getMessage())); + current = current.getCause(); + depth++; + } + if (current != null) { + causeChain.append(" <- ..."); + } + return causeChain.toString(); + } + + private String normalizeCauseMessage(String message) { + if (message == null || message.isBlank()) { + return "EMPTY_MESSAGE"; + } + return message.replace("\r", " ").replace("\n", " ").trim(); + } }