ข้ามไปยังเนื้อหา

ติดตามการเรนเดอร์ด้วย OpenTelemetry

NextPDF มี OpenTelemetry instrumentation ในตัว: 10 trace span และ 7 เมตริกตลอดวงจรชีวิตการสร้าง Portable Document Format (PDF) สัญญาของระบบคือ ไม่มีโอเวอร์เฮดและไม่ต้องตั้งค่าใดๆ เมื่อไม่มี OTel SDK — ไม่มีการล้มเหลวของ autoload และไม่มีผลเสียต่อประสิทธิภาพ ติดตั้ง software development kit (SDK) แล้วลงทะเบียน TracerProvider/MeterProvider ในระดับโกลบอล โค้ดเดิมก็จะส่งออกข้อมูลโดยอัตโนมัติ AttributeSanitizer แบบอิง allowlist บังคับใช้ Zero-Trust Data Policy ดังนั้น telemetry จึงไม่ส่งเนื้อหาเอกสารหรือข้อมูลที่ระบุตัวบุคคลได้ (personally identifiable information หรือ PII) ออกไปเลย

ใช้หน้านี้เป็นคู่มือเฉพาะ PHP คู่กับแนวคิด OpenTelemetry ที่ไม่ผูกกับ transport มีตัวอย่างที่รันได้จริงและชุดทดสอบที่ครอบคลุมขั้นตอนนี้

Terminal window
composer require nextpdf/core:^3

Core เพียงอย่างเดียวมีพื้นผิว instrumentation ที่ปลอดภัยแบบ no-op ให้ใช้งาน หากต้องการส่งออกข้อมูลแบบสด ให้เพิ่ม SDK และ exporter หนึ่งตัว

Terminal window
composer require open-telemetry/sdk:^1
composer require open-telemetry/exporter-otlp:^1 # or zipkin / prometheus

ใช้จุดเข้าใช้งานสองจุด:

  • TelemetryBridge — facade แบบ static isAvailable() ตรวจสอบ OTel เพียงครั้งเดียวและแคชผลลัพธ์ startSpan() / endSpan() / recordMetric() จะลัดวงจรเป็น no-op เมื่อไม่มี OTel นี่คือสัญญาแบบไม่มีโอเวอร์เฮด เมื่อไม่มี OTel การเรียกเหล่านี้จะใช้เวลาต่ำกว่าหนึ่งไมโครวินาทีมาก
  • OpenTelemetryInterceptor — เส้นทางการผสานรวมกับ SDK ตัวนี้จะ trace 10 span ที่รู้จักโดยอัตโนมัติ บันทึก 7 เมตริกที่รู้จัก และส่งทุกแอตทริบิวต์ผ่าน AttributeSanitizer โดยจะตรวจสอบว่ามี SDK หรือไม่ตอนสร้างออบเจ็กต์และแคชผลลัพธ์ การอ้างอิงคลาส OTel ทั้งหมดอยู่หลัง runtime guard ดังนั้นคลาสจึงโหลดได้แม้ไม่มี SDK ขอบเขตของ BatchSpanProcessor ที่แนะนำ (maxQueueSize=2048, maxExportBatchSize=512) ถูกเปิดเผยผ่าน static accessor

10 span ได้แก่ document.build, font.resolve, html.parse, writer.serialize, image.decode, layout.pass, barcode.encode, form.build, navigation.build, attachment.embed 7 เมตริก ได้แก่ render.duration, render.page_count, render.warnings, render.memory_peak, render.file_size, render.font_count, render.image_count ตามลำดับ

AttributeSanitizer ใช้เฉพาะ allowlist เท่านั้น โดยอนุญาตคีย์ metadata เชิงโครงสร้าง เช่น pdf.page_count, pdf.file_size_bytes, pdf.output_profile และ nextpdf.tier และตัด HTML ดิบ สตรีมไบต์ของ PDF, blob แบบ base64 และเส้นทางในระบบไฟล์ออกโดยไม่มีเงื่อนไข การออกแบบนี้นำสองประเด็นจากแนวทาง NIST SP 800-92 มาใช้: telemetry ต้องไม่นำพาเนื้อหาที่อ่อนไหว และความลับของ telemetry เป็นมาตรการควบคุมที่กำหนดไว้อย่างชัดเจน

พื้นผิว application programming interface (API) อ้างอิงจาก PHPDoc บน NextPDF\Telemetry\TelemetryBridge, NextPDF\Telemetry\OpenTelemetryInterceptor และ NextPDF\Telemetry\AttributeSanitizer สมาชิกหลักที่ใช้ด้านล่างคือ TelemetryBridge::isAvailable() / startSpan() / endSpan() / recordMetric(); OpenTelemetryInterceptor::knownSpans() / knownMetrics() / maxQueueSize() / maxExportBatchSize(); และ AttributeSanitizer::sanitize() ตามลำดับ

<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
use NextPDF\Telemetry\TelemetryBridge;
$span = TelemetryBridge::startSpan('document.build', [
'pdf.page_count' => 1,
'nextpdf.tier' => 'core',
]);
$doc = Document::createStandalone();
$doc->addPage();
$doc->setFont('helvetica', '', 12);
$doc->cell(0, 10, 'Observed render');
$pdf = $doc->getPdfData();
TelemetryBridge::recordMetric('render.file_size', strlen($pdf), []);
TelemetryBridge::endSpan($span); // null-safe when OTel is absent
$doc->save(getenv('NEXTPDF_COOKBOOK_OUTPUT') ?: __DIR__ . '/out.pdf');

ตัวอย่างฉบับสมบูรณ์พิสูจน์เส้นทาง no-op ที่ไม่มีโอเวอร์เฮด เพราะรันในสภาพแวดล้อมที่ไม่มี SDK ตัวอย่างนี้ทดสอบการทำงานของ allowlist ใน sanitizer และใช้ช่องทางเอาต์พุตของ harness ตามที่กำหนดไว้ reproducibility harness จะรันสคริปต์นี้สองครั้ง

<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
use NextPDF\Telemetry\AttributeSanitizer;
use NextPDF\Telemetry\OpenTelemetryInterceptor;
use NextPDF\Telemetry\TelemetryBridge;
// Discover the surface — static, dependency-free, SDK-optional.
$spans = OpenTelemetryInterceptor::knownSpans();
$metrics = OpenTelemetryInterceptor::knownMetrics();
// Zero-Trust Data Policy: the sanitizer drops anything off the allowlist
// and anything that looks like a payload.
$sanitizer = new AttributeSanitizer();
$exported = $sanitizer->sanitize([
'pdf.page_count' => 1,
'pdf.output_profile' => 'PDF/A-4',
'document.raw_html' => '<html><body>secret</body></html>', // dropped
'source.path' => '/var/secret/invoice.pdf', // dropped
]);
$span = TelemetryBridge::startSpan('document.build', [
'pdf.page_count' => 1,
'nextpdf.tier' => 'core',
]);
$doc = Document::createStandalone();
$doc->setTitle('Observability demo');
$doc->addPage();
$doc->setFont('helvetica', 'B', 16);
$doc->cell(0, 12, 'Observe rendering with OpenTelemetry', newLine: true);
$pdf = $doc->getPdfData();
TelemetryBridge::recordMetric('render.page_count', 1, []);
TelemetryBridge::recordMetric('render.file_size', strlen($pdf), []);
TelemetryBridge::endSpan($span);
$doc->save(getenv('NEXTPDF_COOKBOOK_OUTPUT') ?: __DIR__ . '/out.pdf');
fwrite(STDERR, sprintf(
"spans=%d metrics=%d otel_available=%s sanitized_keys=%s\n",
count($spans),
count($metrics),
TelemetryBridge::isAvailable() ? 'yes' : 'no',
implode(',', array_keys($exported)),
));
  • telemetry ไม่เคยทำให้การเรนเดอร์ล้มเหลว ทั้ง bridge และ interceptor จะกลืนข้อผิดพลาดภายในของตนเอง exporter ที่ตั้งค่าผิดจะทำให้ observability ด้อยลง แต่จะไม่กระทบเอาต์พุต PDF เลย อย่าครอบโค้ดเรนเดอร์ด้วย catch ที่ถือว่าความล้มเหลวของ telemetry เป็นความล้มเหลวของการเรนเดอร์
  • endSpan(null) ปลอดภัย startSpan() จะคืนค่า null เมื่อไม่มี OTel และ endSpan() รับ null เป็น no-op เรียกใช้คู่กันเสมอ และอย่าแยกเส้นทางการทำงานตามค่าที่คืนกลับมา
  • เมตริกต้องมี MeterProvider ที่ลงทะเบียนไว้ หากลงทะเบียนไว้เฉพาะ TracerProvider span จะถูกส่งออก แต่เมตริกจะถูกข้ามโดยไม่แจ้งข้อผิดพลาด เมตริกเป็นข้อมูลเชิงคำแนะนำ ลงทะเบียน provider ทั้งสองตัวเพื่อให้ครอบคลุมครบถ้วน
  • sanitizer ใช้เฉพาะ allowlist เท่านั้น คีย์แอตทริบิวต์ใหม่ที่ไม่อยู่ใน allowlist จะไม่ถูกส่งออก พฤติกรรมนี้เป็นไปตามที่ออกแบบไว้ ให้ขยาย allowlist ในเอนจิน และอย่าข้าม sanitizer
  • การกระจาย W3C Trace Context การกระจาย trace ข้ามบริการใช้เฮดเดอร์ traceparent/tracestate เฮดเดอร์เหล่านี้จัดการโดย W3C Trace Context propagator ของ OTel SDK ไม่ใช่ NextPDF W3C Trace Context Recommendation ไม่ได้อยู่ใน verification corpus ดังนั้นบันทึกเรื่องการกระจายนี้จึงเป็น RAG-unresolved และระบุไว้ในฐานะแนวทางการผสานรวมมากกว่าจะเป็นข้ออ้างเชิงบรรทัดฐาน ดูที่ sidecar
  • ข้อควรระวังด้าน reproducibility การเรนเดอร์สร้างเอกสารโดยที่ /ID และวันที่แก้ไขถูกสร้างใหม่ในการบันทึกแต่ละครั้ง (ISO 32000-2 §14.3) PDF ที่เก็บจากการรันจะถูกเปรียบเทียบด้วยโปรไฟล์ semantic ซึ่งครอบคลุมเฉพาะ abstract syntax tree (AST) เชิงโครงสร้างและ metadata เท่านั้น
  • เส้นทางที่ไม่มี OTel: isAvailable() จะถูกแคชหลังการเรียกครั้งแรก การเรียก span และเมตริกในภายหลังจะตรวจสอบ boolean หนึ่งครั้งแล้วคืนค่ากลับ ตัวอย่างที่มีการ instrument รันจนจบในสภาพแวดล้อมที่ไม่มี SDK
  • เมื่อมี OTel: ขอบเขตของ BatchSpanProcessor (maxQueueSize=2048, maxExportBatchSize=512) จะจำกัดการใช้หน่วยความจำภายใต้โหลดที่ต่อเนื่อง และการส่งออกจะอยู่นอก hot path
  • ค่า performance_budget (wall_ms: 3000, peak_mb: 128) กำหนดขอบเขตการรันของ harness ไม่ใช่ข้อจำกัดของเอกสารทั่วไป
  • recipe นี้ครอบคลุม gap-list §4.3 สำหรับ #33 ก่อนหน้านี้มีเพียงหน้าแนวคิดแบบ MCP เท่านั้น โดยไม่มีตัวอย่างเฉพาะ PHP มีการเขียน examples/33-opentelemetry-observability.php ขึ้นใหม่ พร้อมกับ tests/Cookbook/Php/ObserveWithOpenTelemetryRecipeTest.php ที่เป็นชุดทดสอบประกอบ
  • telemetry ต้องไม่นำพาเนื้อหาเอกสารหรือ PII allowlist ของ AttributeSanitizer บังคับใช้ข้อนี้ในระดับโค้ด HTML ดิบ สตรีม PDF, blob แบบ base64 และเส้นทางในระบบไฟล์จะถูกตัดออก การทำเช่นนี้สอดคล้องกับแนวทาง NIST SP 800-92 ในการเก็บเนื้อหาที่อ่อนไหวไว้นอก log และ telemetry และในการปกป้องความลับของ telemetry
  • แอตทริบิวต์ที่เพิ่มเองยังคงอยู่ภายใต้ allowlist ยังต้องรับผิดชอบในการไม่นำ ค่า ที่อ่อนไหวมาใส่ภายใต้คีย์ที่ได้รับอนุญาต ตัวอย่างเช่น อย่าใส่ตัวระบุผู้ใช้ลงใน pdf.output_profile เป็นต้น
  • คีย์ที่มีโครงสร้าง ไม่ใช่ payload แบบอิสระ เป็นตัวนำพารายละเอียดเชิงวินิจฉัย แนวทางนี้เป็นวินัยเดียวกับที่ PSR-3 §1.2 นำไปใช้กับ context ของ log
ข้อความที่ระบุมาตรฐานข้อกำหนดรหัสอ้างอิง (reference_id)
telemetry ต้องไม่นำพาเนื้อหาที่อ่อนไหว ต้องจัดการ PIINIST SP 800-92§3
ความลับของ telemetry/log เป็นมาตรการควบคุมที่กำหนดไว้อย่างชัดเจนNIST SP 800-92§3
คีย์ context ที่มีโครงสร้างเป็นตัวนำพารายละเอียด ไม่ใช่ payload แบบอิสระPSR-3§1.2
เอาต์พุต /ID และวันที่ถูกสร้างใหม่ในการบันทึกแต่ละครั้ง → โปรไฟล์ semanticISO 32000-2§14.3

recipe นี้อธิบายพฤติกรรมของ instrumentation เชิงวิศวกรรม และไม่ได้อ้างการรับรองความสอดคล้องใดๆ การอ้างอิง NIST SP 800-92 ใช้รองรับเจตนาการออกแบบที่ไม่ให้มีเนื้อหาใน telemetry ไม่ใช่ข้ออ้างด้านความสอดคล้อง