From db4155c36d44ff581bbead77a6033b988ea9b852 Mon Sep 17 00:00:00 2001 From: joungmin Date: Thu, 9 Apr 2026 18:38:23 +0000 Subject: [PATCH] Add error logging and improve HTTP handling for YouTube transcript fetching Co-Authored-By: Claude Opus 4.6 (1M context) --- .../controller/KnowledgeController.java | 12 +++++++++--- .../service/YouTubeTranscriptService.java | 19 +++++++++++++++---- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/sundol-backend/src/main/java/com/sundol/controller/KnowledgeController.java b/sundol-backend/src/main/java/com/sundol/controller/KnowledgeController.java index 1926d6a..2db63a6 100644 --- a/sundol-backend/src/main/java/com/sundol/controller/KnowledgeController.java +++ b/sundol-backend/src/main/java/com/sundol/controller/KnowledgeController.java @@ -3,6 +3,8 @@ package com.sundol.controller; import com.sundol.dto.IngestRequest; import com.sundol.service.KnowledgeService; import com.sundol.service.YouTubeTranscriptService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.core.annotation.AuthenticationPrincipal; @@ -16,6 +18,8 @@ import java.util.Map; @RequestMapping("/api/knowledge") public class KnowledgeController { + private static final Logger log = LoggerFactory.getLogger(KnowledgeController.class); + private final KnowledgeService knowledgeService; private final YouTubeTranscriptService youTubeTranscriptService; @@ -50,9 +54,11 @@ public class KnowledgeController { @RequestParam String url) { return Mono.fromCallable(() -> youTubeTranscriptService.fetchTranscript(url)) .map(transcript -> ResponseEntity.ok(Map.of("transcript", transcript))) - .onErrorResume(e -> Mono.just( - ResponseEntity.status(HttpStatus.BAD_REQUEST) - .body(Map.of("error", e.getMessage() != null ? e.getMessage() : "트랜스크립트를 가져올 수 없습니다")))); + .onErrorResume(e -> { + log.error("YouTube transcript error: {}", e.getMessage(), e); + return Mono.just(ResponseEntity.status(HttpStatus.BAD_REQUEST) + .body(Map.of("error", e.getMessage() != null ? e.getMessage() : "트랜스크립트를 가져올 수 없습니다"))); + }); } @GetMapping("/{id}") diff --git a/sundol-backend/src/main/java/com/sundol/service/YouTubeTranscriptService.java b/sundol-backend/src/main/java/com/sundol/service/YouTubeTranscriptService.java index e71276b..a792e45 100644 --- a/sundol-backend/src/main/java/com/sundol/service/YouTubeTranscriptService.java +++ b/sundol-backend/src/main/java/com/sundol/service/YouTubeTranscriptService.java @@ -156,20 +156,31 @@ public class YouTubeTranscriptService { log.info("Fetching caption XML from: {}", captionUrl); // 자막 XML 가져오기 + log.info("Attempting to fetch caption XML..."); String xml; try { - xml = new java.net.URI(captionUrl).toURL().openConnection() - .getInputStream().readAllBytes().toString(); - // Use simple HTTP fetch - var conn = new java.net.URI(captionUrl).toURL().openConnection(); + var conn = (java.net.HttpURLConnection) new java.net.URI(captionUrl).toURL().openConnection(); conn.setRequestProperty("User-Agent", "Mozilla/5.0"); + conn.setConnectTimeout(15_000); + conn.setReadTimeout(15_000); + int responseCode = conn.getResponseCode(); + log.info("Caption XML response code: {}", responseCode); + if (responseCode != 200) { + String errorBody = new String(conn.getErrorStream().readAllBytes(), StandardCharsets.UTF_8); + log.error("Caption XML error response: {}", errorBody); + throw new IOException("자막 XML 응답 코드: " + responseCode); + } xml = new String(conn.getInputStream().readAllBytes(), StandardCharsets.UTF_8); + log.info("Caption XML fetched: {} chars", xml.length()); } catch (Exception e) { + log.error("Failed to fetch caption XML: {}", e.getMessage(), e); throw new IOException("자막 XML을 가져올 수 없습니다: " + e.getMessage(), e); } String transcript = parseTranscriptXml(xml); + log.info("Parsed transcript: {} chars (blank={})", transcript.length(), transcript.isBlank()); if (transcript.isBlank()) { + log.error("Transcript XML content (first 500 chars): {}", xml.substring(0, Math.min(500, xml.length()))); throw new IOException("자막 텍스트를 파싱할 수 없습니다."); }