ติดตามการเรนเดอร์ด้วย 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 มีตัวอย่างที่รันได้จริงและชุดทดสอบที่ครอบคลุมขั้นตอนนี้
การติดตั้ง
หัวข้อที่มีชื่อว่า “การติดตั้ง”composer require nextpdf/core:^3Core เพียงอย่างเดียวมีพื้นผิว instrumentation ที่ปลอดภัยแบบ no-op ให้ใช้งาน หากต้องการส่งออกข้อมูลแบบสด ให้เพิ่ม SDK และ exporter หนึ่งตัว
composer require open-telemetry/sdk:^1composer require open-telemetry/exporter-otlp:^1 # or zipkin / prometheusภาพรวมเชิงแนวคิด
หัวข้อที่มีชื่อว่า “ภาพรวมเชิงแนวคิด”ใช้จุดเข้าใช้งานสองจุด:
TelemetryBridge— facade แบบ staticisAvailable()ตรวจสอบ 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 เป็นมาตรการควบคุมที่กำหนดไว้อย่างชัดเจน
พื้นผิว API
หัวข้อที่มีชื่อว่า “พื้นผิว API”พื้นผิว 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ที่ลงทะเบียนไว้ หากลงทะเบียนไว้เฉพาะTracerProviderspan จะถูกส่งออก แต่เมตริกจะถูกข้ามโดยไม่แจ้งข้อผิดพลาด เมตริกเป็นข้อมูลเชิงคำแนะนำ ลงทะเบียน 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 ต้องไม่นำพาเนื้อหาที่อ่อนไหว ต้องจัดการ PII | NIST SP 800-92 | §3 | |
| ความลับของ telemetry/log เป็นมาตรการควบคุมที่กำหนดไว้อย่างชัดเจน | NIST SP 800-92 | §3 | |
| คีย์ context ที่มีโครงสร้างเป็นตัวนำพารายละเอียด ไม่ใช่ payload แบบอิสระ | PSR-3 | §1.2 | |
เอาต์พุต /ID และวันที่ถูกสร้างใหม่ในการบันทึกแต่ละครั้ง → โปรไฟล์ semantic | ISO 32000-2 | §14.3 |
recipe นี้อธิบายพฤติกรรมของ instrumentation เชิงวิศวกรรม และไม่ได้อ้างการรับรองความสอดคล้องใดๆ การอ้างอิง NIST SP 800-92 ใช้รองรับเจตนาการออกแบบที่ไม่ให้มีเนื้อหาใน telemetry ไม่ใช่ข้ออ้างด้านความสอดคล้อง