Răsfoiți Sursa

Add concise PDF generation timing log

yemeishu 2 săptămâni în urmă
părinte
comite
05a8bb9dca
1 a modificat fișierele cu 40 adăugiri și 5 ștergeri
  1. 40 5
      app/Services/ExamPdfExportService.php

+ 40 - 5
app/Services/ExamPdfExportService.php

@@ -40,6 +40,7 @@ class ExamPdfExportService
     private array $pdfImageDimensionCache = [];
     private ?bool $hasPdfImageMetricsTable = null;
     private ?array $knowledgePointMetaCache = null;
+    private ?string $lastDebugHtmlPath = null;
 
     public function __construct(
         private readonly LearningAnalyticsService $learningAnalyticsService,
@@ -147,11 +148,21 @@ class ExamPdfExportService
      */
     public function generateUnifiedPdf(string $paperId): ?string
     {
+        $flowStart = microtime(true);
+        $lastMark = $flowStart;
+        $timings = [];
+        $mark = static function (string $label) use (&$lastMark, &$timings): void {
+            $now = microtime(true);
+            $timings[$label] = round(($now - $lastMark) * 1000, 1);
+            $lastMark = $now;
+        };
+
         // 与组卷规则保持一致:仅知识点组卷类型(paper_type=2)包含知识点讲解。
         $paperType = Paper::query()
             ->where('paper_id', $paperId)
             ->value('paper_type');
         $shouldIncludeKpExplain = ((int) $paperType) === 2;
+        $mark('load_paper_type_ms');
 
         Log::info('generateUnifiedPdf 开始(终极优化版本,直接HTML合并生成PDF):', [
             'paper_id' => $paperId,
@@ -164,6 +175,7 @@ class ExamPdfExportService
             if ($shouldIncludeKpExplain) {
                 Log::info('generateUnifiedPdf: 开始获取知识点讲解HTML', ['paper_id' => $paperId]);
                 $kpExplainHtml = $this->fetchKnowledgeExplanationHtml($paperId);
+                $mark('kp_explain_html_ms');
                 if ($kpExplainHtml) {
                     // 统一在 mergeHtmlWithPageBreak()->ensureUtf8Html() 阶段处理内联与公式预渲染,
                     // 避免在此处重复处理导致额外耗时。
@@ -174,11 +186,14 @@ class ExamPdfExportService
                 } else {
                     Log::warning('generateUnifiedPdf: 知识点讲解HTML获取失败,将跳过', ['paper_id' => $paperId]);
                 }
+            } else {
+                $timings['kp_explain_html_ms'] = 0.0;
             }
 
             // 步骤1:同时渲染两个页面的HTML
             Log::info('generateUnifiedPdf: 开始渲染试卷HTML', ['paper_id' => $paperId]);
             $examHtml = $this->renderExamHtml($paperId, includeAnswer: false, useGradingView: false);
+            $mark('exam_html_ms');
             if (! $examHtml) {
                 Log::error('ExamPdfExportService: 渲染卷子HTML失败', ['paper_id' => $paperId]);
 
@@ -188,6 +203,7 @@ class ExamPdfExportService
 
             Log::info('generateUnifiedPdf: 开始渲染判卷HTML', ['paper_id' => $paperId]);
             $gradingHtml = $this->renderExamHtml($paperId, includeAnswer: true, useGradingView: true);
+            $mark('grading_html_ms');
             if (! $gradingHtml) {
                 Log::error('ExamPdfExportService: 渲染判卷HTML失败', ['paper_id' => $paperId]);
 
@@ -198,6 +214,7 @@ class ExamPdfExportService
             // 步骤2:插入分页符,合并HTML
             Log::info('generateUnifiedPdf: 开始合并HTML(保留原始样式)', ['paper_id' => $paperId]);
             $unifiedHtml = $this->mergeHtmlWithPageBreak($examHtml, $gradingHtml, $kpExplainHtml);
+            $mark('merge_html_ms');
             if (! $unifiedHtml) {
                 Log::error('ExamPdfExportService: HTML合并失败', ['paper_id' => $paperId]);
 
@@ -211,7 +228,9 @@ class ExamPdfExportService
 
             // 步骤3:一次性生成PDF(只需20-25秒,比原来节省10-25秒)
             Log::info('generateUnifiedPdf: 开始使用buildPdf直接生成PDF(不使用pdfunite)', ['paper_id' => $paperId]);
+            $this->lastDebugHtmlPath = null;
             $pdfBinary = $this->buildPdf($unifiedHtml, true, true);
+            $mark('build_pdf_ms');
             if (! $pdfBinary) {
                 Log::error('ExamPdfExportService: 生成统一PDF失败', ['paper_id' => $paperId]);
 
@@ -230,6 +249,7 @@ class ExamPdfExportService
             $path = "exams/{$allPdfName}";
             Log::info('generateUnifiedPdf: 开始保存PDF到云存储', ['paper_id' => $paperId, 'path' => $path]);
             $url = $this->pdfStorageService->put($path, $pdfBinary);
+            $mark('upload_pdf_ms');
             if (! $url) {
                 Log::error('ExamPdfExportService: 保存统一PDF失败', ['path' => $path]);
 
@@ -240,8 +260,23 @@ class ExamPdfExportService
             // 步骤5:保存URL到数据库(存储到all_pdf_url字段)
             Log::info('generateUnifiedPdf: 开始保存URL到数据库', ['paper_id' => $paperId, 'field' => 'all_pdf_url']);
             $this->savePdfUrlToDatabase($paperId, 'all_pdf_url', $url);
+            $mark('save_url_ms');
             Log::info('generateUnifiedPdf: URL保存完成', ['paper_id' => $paperId]);
 
+            Log::warning('PDF_GENERATION_TIMING', [
+                'paper_id' => $paperId,
+                'paper_type' => (int) $paperType,
+                'has_kp_explain' => ! empty($kpExplainHtml),
+                'exam_html_bytes' => strlen($examHtml),
+                'grading_html_bytes' => strlen($gradingHtml),
+                'kp_explain_html_bytes' => $kpExplainHtml ? strlen($kpExplainHtml) : 0,
+                'unified_html_bytes' => strlen($unifiedHtml),
+                'pdf_bytes' => strlen($pdfBinary),
+                'timings_ms' => $timings,
+                'total_ms' => round((microtime(true) - $flowStart) * 1000, 1),
+                'debug_html_path' => $this->lastDebugHtmlPath,
+            ]);
+
             Log::info('generateUnifiedPdf 全部完成(终极优化:直接HTML合并生成一份PDF)', [
                 'paper_id' => $paperId,
                 'url' => $url,
@@ -2736,7 +2771,8 @@ class ExamPdfExportService
         if (config('pdf.debug_save_html', false)) {
             $debugPath = storage_path('app/debug_pdf_'.date('YmdHis').'.html');
             @copy($tmpHtml, $debugPath);
-            Log::warning('ExamPdfExportService: [DEBUG] HTML副本已保存', ['path' => $debugPath]);
+            $this->lastDebugHtmlPath = $debugPath;
+            Log::debug('ExamPdfExportService: [DEBUG] HTML副本已保存', ['path' => $debugPath]);
         }
 
         // 仅使用Chrome渲染
@@ -3045,7 +3081,7 @@ class ExamPdfExportService
         $process->setTimeout(180); // 复杂学情报告页允许更长渲染时间,降低超时失败率
         $killSignal = \defined('SIGKILL') ? \SIGKILL : 9;
 
-        Log::warning('ExamPdfExportService: [调试] Chrome命令准备执行', [
+        Log::debug('ExamPdfExportService: [调试] Chrome命令准备执行', [
             'chrome_binary' => $chromeBinary,
             'html_path' => $htmlPath,
             'html_exists' => file_exists($htmlPath),
@@ -3253,8 +3289,7 @@ class ExamPdfExportService
         $hasKatexCdn = strpos($html, 'cdn.jsdelivr.net/npm/katex') !== false;
         $hasKatexLocal = strpos($html, '/js/katex.min.js') !== false || strpos($html, '/css/katex/katex.min.css') !== false;
 
-        // 【调试】记录HTML内容信息
-        Log::warning('ExamPdfExportService: inlineExternalResources', [
+        Log::debug('ExamPdfExportService: inlineExternalResources', [
             'html_length' => strlen($html),
             'has_katex_cdn' => $hasKatexCdn,
             'has_katex_local' => $hasKatexLocal,
@@ -3262,7 +3297,7 @@ class ExamPdfExportService
 
         // 如果既没有 CDN 也没有本地链接,仍尝试注入 KaTeX 关系符通用修复
         if (! $hasKatexCdn && ! $hasKatexLocal) {
-            Log::warning('ExamPdfExportService: HTML 中没有 KaTeX 资源链接,跳过内联');
+            Log::debug('ExamPdfExportService: HTML 中没有 KaTeX 资源链接,跳过内联');
 
             return $this->applyKatexRelationGlyphFixes($html);
         }