สัญญา Observability
ภาพรวมโดยย่อ
หัวข้อที่มีชื่อว่า “ภาพรวมโดยย่อ”โดเมน observability กำหนดสัญญาที่เปิดเผยสถานะขณะทำงานของเอนจิน ได้แก่ ContextAwareExceptionInterface สำหรับบริบทข้อผิดพลาดแบบมีโครงสร้าง SpectrumInterface สำหรับ sidecar เร่งความเร็วที่เลือกใช้ได้ JobNotificationInterface สำหรับความคืบหน้าของงานแบบสตรีม และ enum DegradationPolicy สำหรับพฤติกรรมเมื่อสูญเสียความสามารถ
การติดตั้ง
หัวข้อที่มีชื่อว่า “การติดตั้ง”composer require nextpdf/core:^3ภาพรวมเชิงแนวคิด
หัวข้อที่มีชื่อว่า “ภาพรวมเชิงแนวคิด”ContextAwareExceptionInterface คือสัญญาสำหรับข้อมูลวินิจฉัย ทุก domain exception ของ NextPDF ใช้งานสัญญานี้ ผู้ใช้สามารถแปลง (cast) exception ของ NextPDF ที่ดักจับได้ให้เป็นสัญญานี้ แล้วดึงบริบทแบบมีโครงสร้างสำหรับเครื่องมือ Application Performance Monitoring (APM) ไปป์ไลน์การบันทึก หรือตัวรายงานข้อผิดพลาดได้ บริบทเป็น associative array ที่มีคีย์แบบ snake_case และมีเฉพาะค่าแบบ primitive เท่านั้น บริบทไม่มีอ็อบเจกต์ซ้อน (nested object) ด้วยเหตุนี้ บริบทจึง serialize เป็น payload แบบ JavaScript Object Notation (JSON) หรือ payload ของ APM ได้อย่างคาดเดาได้ ผู้ใช้ไม่จำเป็นต้อง parse ข้อความ exception เพื่อกู้คืนข้อมูลวินิจฉัย สัญญานี้อยู่ในสถานะ stable ตั้งแต่เวอร์ชัน 3.1.0
SpectrumInterface คือสัญญาสำหรับ sidecar เร่งความเร็วที่เลือกใช้ได้ Spectrum ประมวลผลงานแบบขนานบนหน่วยประมวลผลกลาง (CPU) โดยย้ายการตรวจหาฮาร์ดแวร์ การ parse Portable Document Format (PDF) และการบีบอัดภาพไปยังกระบวนการ sidecar ในเครื่อง สัญญารายงานความพร้อมใช้งานผ่าน circuit breaker ดังนั้นการตรวจสุขภาพบ่อยครั้งจึงไม่ทำให้ความล้มเหลวขยายวงเมื่อ sidecar หยุดทำงาน สัญญาตรวจสอบ (probe) ความสามารถของฮาร์ดแวร์และแคชผลลัพธ์ไว้ สัญญาเปิดเผยงบประมาณทรัพยากรที่ใช้งานอยู่ และยังให้ transport สำหรับการร้องขอแบบทั่วไปแก่โมดูลระดับสูงขึ้นด้วย เอนจินทำงานได้โดยไม่ต้องมี sidecar สัญญานี้ทำให้การเร่งความเร็วเป็นตัวเลือกที่ inject เข้าไปได้ ไม่ใช่ dependency ที่บังคับ JobNotificationInterface สตรีม job event แบบมีชนิดจาก endpoint แบบ server-sent-events ของ sidecar ในรูปของ generator โดย generator จะหยุดเมื่อมี terminal event มาถึงหรือเมื่อสตรีมปิด
DegradationPolicy คือ enum ที่กำหนดพฤติกรรมเมื่อสูญเสียความสามารถ เมื่อความสามารถลดทอนลง นโยบายจะตัดสินใจว่าจะ throw เตือน หรือเก็บข้อมูลแบบเงียบ ๆ โดยพิจารณาจากผลกระทบ Strict จะ throw เมื่อผลกระทบเป็นความเสี่ยงด้านการปฏิบัติตามข้อกำหนด เป็นการสูญเสียเชิงความหมาย หรือเป็นการขัดขวางการทำงาน ใช้ตัวเลือกนี้ในสภาพแวดล้อมที่มีการกำกับดูแลซึ่งความถูกต้องของผลลัพธ์เป็นข้อบังคับ Balanced ซึ่งเป็นค่าเริ่มต้น จะส่งคำเตือนแบบมีโครงสร้างและทำงานต่อสำหรับการลดทอนที่อยู่ในขอบเขต และจะ throw เฉพาะเมื่อผลกระทบเป็นการขัดขวางการทำงานเท่านั้น ใช้ตัวเลือกนี้สำหรับการ deploy ในระบบ production ส่วนใหญ่ Permissive จะเก็บทุกเหตุการณ์แบบเงียบ ๆ และไม่ throw เลย ใช้ตัวเลือกนี้สำหรับโหมดแสดงตัวอย่างหรือฉบับร่างซึ่งยอมรับผลลัพธ์แบบ best-effort ได้ ชนิด SpectrumInterface JobNotificationInterface และ DegradationPolicy อยู่ในสถานะ experimental การรับประกันความเข้ากันได้ของชนิดเหล่านี้จึงอ่อนกว่า ContextAwareExceptionInterface
พื้นผิว API
หัวข้อที่มีชื่อว่า “พื้นผิว API”| ชนิด | ประเภท | สมาชิกสำคัญ | ความเสถียร | ตั้งแต่เวอร์ชัน |
|---|---|---|---|---|
ContextAwareExceptionInterface | interface | getContext(): array<string, mixed> | stable | 3.1.0 |
SpectrumInterface | interface | isAvailable(), probe(), getBudget(), request() | experimental | 2.1.0 |
JobNotificationInterface | interface | streamEvents(string): Generator<int, JobEvent> | experimental | 2.2.0 |
DegradationPolicy | enum (string) | Strict, Balanced, Permissive | experimental | 2.3.0 |
getContext() คืนค่าเฉพาะ primitive หรือลิสต์ของ primitive เท่านั้น streamEvents() yield อ็อบเจกต์ JobEvent จนกระทั่งถึง terminal event SpectrumInterface::request() คืนเนื้อหา response แบบดิบเป็น string probe() คืนค่า HardwareReport และ getBudget() คืนค่า SpectrumBudget
ตัวอย่างโค้ด — เริ่มต้นอย่างรวดเร็ว
หัวข้อที่มีชื่อว่า “ตัวอย่างโค้ด — เริ่มต้นอย่างรวดเร็ว”<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use NextPDF\Contracts\ContextAwareExceptionInterface;use Psr\Log\LoggerInterface;
/** * Log a NextPDF exception with its structured context. * * @param \Throwable $e A caught exception. * @param LoggerInterface $logger A PSR-3 logger. */function logWithContext(\Throwable $e, LoggerInterface $logger): void{ if ($e instanceof ContextAwareExceptionInterface) { $logger->error($e->getMessage(), $e->getContext());
return; }
$logger->error($e->getMessage());}บริบทแบบมีโครงสร้างส่งต่อเข้าสู่ระเบียนบันทึก (log record) ได้โดยไม่ต้อง parse ข้อความ
ตัวอย่างโค้ด — สำหรับใช้งานจริง
หัวข้อที่มีชื่อว่า “ตัวอย่างโค้ด — สำหรับใช้งานจริง”<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use NextPDF\Contracts\DegradationPolicy;use NextPDF\Contracts\SpectrumInterface;use Psr\Log\LoggerInterface;
final readonly class AcceleratedParseService{ public function __construct( private ?SpectrumInterface $spectrum, private DegradationPolicy $policy, private LoggerInterface $logger, ) {}
/** * Send a parse batch to the sidecar when healthy, otherwise fall back. * * @param list<array{id: string, data: string}> $documents PDF binaries with caller IDs. * * @return string Raw sidecar response body; decode with a batch-result parser. */ public function parse(array $documents): string { if ($this->spectrum?->isAvailable() === true) { return $this->spectrum->request( 'POST', '/v1/parse', json: ['documents' => $documents], scope: ['parse'], ); }
if ($this->policy === DegradationPolicy::Strict) { throw new \RuntimeException('Accelerator required under strict policy.'); }
$this->logger->info('Accelerator unavailable; using PHP fallback.');
return $this->phpFallback($documents); }
/** @param list<array{id: string, data: string}> $documents @return string */ private function phpFallback(array $documents): string { // Pure-PHP parse path omitted for brevity. return ''; }}อินเทอร์เฟซ SpectrumInterface ที่เป็น nullable ทำให้การเร่งความเร็วเป็นทางเลือก สัญญาเปิดเผยเมท็อด transport เพียงหนึ่งเดียวคือ request() ซึ่งคืนเนื้อหา response แบบดิบเป็น string parser ระดับสูงขึ้นจะแปลงเนื้อหานั้นให้เป็น NextPDF\Accelerator\BatchResult SpectrumClient ตัวจริงเพิ่ม helper แบบมีชนิด เช่น parseBatch() ซึ่งห่อหุ้ม request() และคืนค่า BatchResult โดยตรง helper เหล่านั้นไม่ได้เป็นส่วนหนึ่งของสัญญาที่ตรึงไว้แล้ว (frozen contract) นโยบายการลดทอนความสามารถจะตัดสินใจว่าการไม่มี sidecar ถือเป็นความล้มเหลวร้ายแรงหรือไม่
กรณีขอบและข้อควรระวัง
หัวข้อที่มีชื่อว่า “กรณีขอบและข้อควรระวัง”- ไม่ใช่ทุก
\Throwableจะเป็น exception ของ NextPDF ใช้instanceof ContextAwareExceptionInterfaceเป็นเงื่อนไขป้องกันก่อนเรียกgetContext() getContext()คืนค่าเฉพาะ primitive เท่านั้นตามสัญญา หากคาดว่าจะมีอ็อบเจกต์ซ้อน ข้อสันนิษฐานนั้นไม่ถูกต้อง สัญญารับประกันค่าที่ปลอดภัยสำหรับ JSONSpectrumInterface::isAvailable()ทำงานผ่าน circuit breaker และเรียกบ่อย ๆ ได้อย่างปลอดภัย แต่ผลลัพธ์trueเป็นการตรวจสอบ ณ ช่วงเวลาหนึ่งเท่านั้น ต้องจัดการกรณีที่ sidecar หลุดไประหว่างการตรวจสอบกับการเรียกใช้งานJobNotificationInterface::streamEvents()เป็น generator การวนรอบ (iterate) ซ้ำเป็นครั้งที่สองจะไม่เล่นเหตุการณ์ซ้ำ จึงควรใช้งานเพียงครั้งเดียวDegradationPolicy::Permissiveไม่ throw เลย ในโหมดนั้น การลดทอนที่กระทบต่อการปฏิบัติตามข้อกำหนดจะผ่านไปอย่างเงียบ ๆ อย่าใช้โหมดนี้กับผลลัพธ์ที่อยู่ภายใต้การกำกับดูแล
ประสิทธิภาพ
หัวข้อที่มีชื่อว่า “ประสิทธิภาพ”สัญญา observability เพิ่มต้นทุนเพียงเล็กน้อยจนแทบไม่มีนัยสำคัญ getContext() คืนค่า array ที่สร้างไว้ล่วงหน้าแล้ว isAvailable() เป็นการตรวจสุขภาพแบบมีแคชและมี circuit breaker สัญญากำหนดให้การ implement ต้องแคชผลการ probe ไว้อย่างน้อย 30 วินาที เพื่อให้ hot path ไม่เรียก sidecar ซ้ำ ๆ streamEvents() ถูกจำกัดด้วยอัตราเหตุการณ์ของ sidecar ไม่ใช่ด้วยเอนจิน performance_budget ที่กำหนดไว้ 1500 ms สำหรับ wall และ 64 MB สำหรับค่าพีค ถูกกำหนดโดยงานเบื้องล่างที่สัญญาเฝ้าสังเกต ไม่ใช่โดยตัวสัญญาเอง โปรไฟล์ความสามารถในการทำซ้ำ (reproducibility profile) เป็นแบบ structural สตรีมเหตุการณ์และบริบทของ exception มี timestamp รวมอยู่ด้วย การรันสองครั้งจึงจะแตกต่างกันในฟิลด์เหล่านั้น ในขณะที่โครงสร้างยังคงเหมือนเดิม
หมายเหตุด้านความปลอดภัย
หัวข้อที่มีชื่อว่า “หมายเหตุด้านความปลอดภัย”บริบท exception แบบมีโครงสร้างเป็นช่องทางที่ข้อมูลอาจรั่วไหลออก (data-exfiltration surface) หากบริบทนั้นบรรจุข้อมูลลับไว้ สัญญาจำกัดบริบทให้มีเฉพาะ primitive ซึ่งช่วยจำกัดการรั่วไหลของอ็อบเจกต์โดยไม่ได้ตั้งใจ ผู้ใช้ยังคงต้องลบล้าง (scrub) ค่าที่ละเอียดอ่อนออกก่อนที่บริบทจะไปถึง log sink นี่คือข้อผูกพันด้าน safe-telemetry ในนโยบายการบันทึก (logging policy) ของโครงการ sidecar เร่งความเร็วเป็นกระบวนการแยกต่างหากที่เข้าถึงผ่าน transport เมท็อด request พกพา scope claim ไปสำหรับการให้สิทธิ์ (authorization) ต้องถือว่าขอบเขตของ sidecar เป็น trust boundary นโยบายการลดทอนความสามารถที่ตั้งเป็น Permissive อาจปกปิดการสูญเสียความสามารถที่เกี่ยวข้องกับความปลอดภัยได้ ใช้ Strict ในที่ที่ความถูกต้องของผลลัพธ์เป็นมาตรการควบคุม ให้ถือว่าบริบท exception, job event และ response จาก sidecar เป็นข้อมูลที่อาจถูกบันทึก และลบล้างค่าที่ละเอียดอ่อนออกตามนั้น
ความสอดคล้องตามข้อกำหนด
หัวข้อที่มีชื่อว่า “ความสอดคล้องตามข้อกำหนด”หน้านี้ไม่ได้กล่าวอ้างเชิงบรรทัดฐานโดยตรง สัญญา observability เปิดเผยสถานะของเอนจิน และไม่ได้ใช้งานโปรโตคอลมาตรฐานที่เอนจินต้องอ้างอิงข้อกำหนด ข้อผูกพันด้าน safe-telemetry และ log-scrubbing ที่อ้างถึงข้างต้นมาจากนโยบายการบันทึกภายในของโครงการ ไม่ได้มาจากมาตรฐานภายนอก เมื่อการดำเนินการที่ถูกเฝ้าสังเกตเป็นไปตามมาตรฐานในตัวเอง เช่น ลายเซ็น หรือเอกสาร PDF/A ความสอดคล้องตามข้อกำหนดของการดำเนินการนั้นจะมีการบันทึกไว้ในหน้าการลงนามหรือหน้าการสกัดข้อมูล
ดูเพิ่มเติม
หัวข้อที่มีชื่อว่า “ดูเพิ่มเติม”- Contracts: 41 อินเทอร์เฟซสาธารณะ (SPI) — ภาพรวมของ SPI และระดับชั้นความเสถียร
- Observability — โมดูลสถานะขณะทำงานที่สัญญาเหล่านี้เปิดเผย
- Accelerator — ไคลเอนต์ Spectrum sidecar ที่อยู่เบื้องหลัง
SpectrumInterface - Exception — exception ที่ใช้งาน
ContextAwareExceptionInterface - Performance — งบประมาณที่งานที่ถูกเฝ้าสังเกตต้องทำงานภายใต้