تخطَّ إلى المحتوى

عقود إمكانية المراقبة

يُعرِّف مجال إمكانية المراقبة العقود التي تكشف حالة المحرك أثناء التشغيل: ContextAwareExceptionInterface لسياق الأخطاء المنظَّم، وSpectrumInterface لملحق التسريع الاختياري، وJobNotificationInterface لتدفُّق تقدُّم المهام، وتعداد DegradationPolicy لسلوك فقدان القدرات.

Terminal window
composer require nextpdf/core:^3

ContextAwareExceptionInterface هو عقد التشخيص. تُنفِّذه جميع استثناءات المجال في ⁨NextPDF.⁩ يمكنك تحويل أي استثناء تلتقطه من ⁨NextPDF⁩ إلى هذا العقد، ثم استرجاع سياق منظَّم لأداة مراقبة أداء التطبيقات (⁨APM⁩)، أو لخط أنابيب تسجيل، أو لمُبلِّغ أخطاء. السياق مصفوفة ترابطية بمفاتيح ⁨snake_case⁩ وقيم أوَّلية فقط. ولا يحتوي على كائنات متداخلة. لذلك، يُسلسَل على نحو متوقَّع إلى حمولة بترميز كائنات جافاسكريبت (⁨JSON⁩) أو حمولة ⁨APM.⁩ لن تحتاج إلى تحليل رسالة الاستثناء لاستعادة بيانات التشخيص. وهو stable منذ 3.1.0.

SpectrumInterface هو عقد ملحق التسريع الاختياري. يُشغِّل ⁨Spectrum⁩ العمل بالتوازي على وحدة المعالجة المركزية (⁨CPU⁩)، وينقل اكتشاف العتاد وتحليل تنسيق المستندات المحمولة (⁨PDF⁩) وضغط الصور إلى عملية ملحق محلية. يُبلِّغ العقد عن التوافر من خلف قاطع دائرة، حتى لا تُفاقِم فحوص السلامة المتكررة العطل عندما يكون الملحق متوقفًا. يفحص العقد قدرات العتاد ويُخزِّن النتيجة في ذاكرة مؤقتة. ويكشف ميزانية الموارد النشطة. كما يوفِّر وسيلة نقل طلبات عامة للوحدات الأعلى مستوى. يعمل المحرك بدون الملحق. يجعل العقد التسريع خيارًا قابلًا للحقن، لا اعتمادًا إلزاميًّا. يُدفِّق JobNotificationInterface أحداث مهام مُصنَّفة من نقطة نهاية الأحداث المُرسَلة من الخادم في الملحق على هيئة مُولِّد. يتوقف المُولِّد عند وصول حدث نهائي أو عند إغلاق الدفق.

DegradationPolicy هو تعداد يحدد السلوك عند فقدان القدرات. عندما تتدهور قدرة ما، تُقرِّر السياسة، بناءً على الأثر، هل يجب إطلاق استثناء أم إصدار تحذير أم التجميع بصمت. يُطلِق Strict استثناءً عندما يكون الأثر خطرًا على الامتثال، أو فقدانًا دلاليًّا، أو مُعطِّلًا. استخدمه في البيئات الخاضعة للتنظيم حيث تكون صحة المخرجات إلزامية. أمّا Balanced، وهو الافتراضي، فيُصدِر تحذيرات منظَّمة ويُكمِل عند التدهور المحدود، ولا يُطلِق استثناءً إلّا عند الأثر المُعطِّل. استخدمه لمعظم عمليات النشر الإنتاجية. يجمع Permissive كل حدث بصمت ولا يُطلِق استثناءً أبدًا. استخدمه لوضع المعاينة أو المسودة حيث تكون المخرجات بأفضل جهد مقبولة. أنواع SpectrumInterface وJobNotificationInterface وDegradationPolicy هي experimental. لذلك يكون وعد التوافق الخاص بها أضعف من ContextAwareExceptionInterface.

النوعالصنفالأعضاء الرئيسيةالاستقرارمنذ
ContextAwareExceptionInterfaceواجهةgetContext(): array<string, mixed>مستقر3.1.0
SpectrumInterfaceواجهةisAvailable(), probe(), getBudget(), request()تجريبي2.1.0
JobNotificationInterfaceواجهةstreamEvents(string): Generator<int, JobEvent>تجريبي2.2.0
DegradationPolicyتعداد (سلسلة)Strict, Balanced, Permissiveتجريبي2.3.0

يُعيد getContext() قيمًا أوَّلية أو قوائم من القيم الأوَّلية فقط. ويُنتِج streamEvents() كائنات JobEvent حتى يصل حدث نهائي. يُعيد SpectrumInterface::request() جسم الاستجابة الخام على هيئة string. ويُعيد probe() كائن HardwareReport، فيما يُعيد getBudget() كائن SpectrumBudget.

عيِّنة برمجية — بداية سريعة

قسم بعنوان «عيِّنة برمجية — بداية سريعة»
examples/contracts/observability-quickstart.php
<?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());
}

يُمرَّر السياق المنظَّم إلى سجل التسجيل دون تحليل الرسائل.

examples/contracts/observability-production.php
<?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 القابل للقيمة الفارغة التسريعَ اختياريًّا. يكشف العقد وسيلة نقل واحدة، request()، تُعيد جسم الاستجابة الخام على هيئة string. يُحوِّل مُحلِّل أعلى مستوى ذلك الجسم إلى NextPDF\Accelerator\BatchResult. يُضيف SpectrumClient الملموس مساعِدات مُصنَّفة مثل parseBatch() تُغلِّف request() وتُعيد BatchResult مباشرةً. هذه المساعِدات ليست جزءًا من العقد المُجمَّد. تُقرِّر سياسة التدهور ما إذا كان غياب الملحق خطأً قاتلًا.

الحالات الحدِّية والمزالق

قسم بعنوان «الحالات الحدِّية والمزالق»
  • ليس كل \Throwable استثناءً من ⁨NextPDF.⁩ تحقَّق باستخدام instanceof ContextAwareExceptionInterface قبل أن تستدعي getContext().
  • يُعيد getContext() قيمًا أوَّلية فقط بحكم العقد. إذا كنت تتوقع كائنات متداخلة، فهذا افتراض خاطئ؛ فالعقد يضمن قيمًا آمنة لـ ⁨JSON.⁩
  • يعمل SpectrumInterface::isAvailable() خلف قاطع دائرة، ومن الآمن استدعاؤه كثيرًا، لكن نتيجة true فحص للحظة بعينها. تعامَل مع احتمال سقوط الملحق بين الفحص والاستدعاء.
  • JobNotificationInterface::streamEvents() هو مُولِّد. التكرار عليه مرتين لا يُعيد تشغيل الأحداث. استهلكه مرة واحدة.
  • DegradationPolicy::Permissive لا يُطلِق استثناءً أبدًا. في ذلك الوضع، يمرُّ التدهور الذي يؤثِّر في الامتثال بصمت. لا تستخدمه للمخرجات الخاضعة للتنظيم.

تُضيف عقود إمكانية المراقبة تكلفة لا تُذكَر. يُعيد getContext() مصفوفة مُجهَّزة مسبقًا. isAvailable() هو فحص سلامة مُخزَّن في ذاكرة مؤقتة ويعمل خلف قاطع دائرة. يتطلَّب العقد من التنفيذات تخزين نتيجة الفحص في ذاكرة مؤقتة لمدة 30 ثانية على الأقل، حتى لا يستدعي المسار الساخن الملحق على نحو متكرر. streamEvents() محدود بمعدل أحداث الملحق، لا بالمحرك. performance_budget البالغ 1500 ⁨ms⁩ زمن جدار و64 ⁨MB⁩ ذروة محدَّد من العمل الأساسي الذي تراقبه العقود، لا من العقود نفسها. ملف إعادة الإنتاج هو structural. تتضمَّن تدفُّقات الأحداث وسياقات الاستثناءات طوابع زمنية. لذلك يختلف تشغيلان في تلك الحقول بينما تبقى البنية متطابقة.

سياق الاستثناء المنظَّم سطح محتمل لتسريب البيانات إذا حمل أسرارًا. يقصر العقد السياق على القيم الأوَّلية، مما يحدُّ من التسريب العَرَضي للكائنات. ومع ذلك، يجب عليك تنقية القيم الحساسة قبل أن يصل السياق إلى مَصرف تسجيل. هذا هو التزام القياس الآمن في سياسة التسجيل الخاصة بالمشروع. ملحق التسريع عملية منفصلة يُوصَل إليها عبر وسيلة نقل. تحمل وسيلة الطلب مطالبات نطاق للتفويض. يجب عليك معاملة حدِّ الملحق بوصفه حدَّ ثقة. يمكن لسياسة تدهور مضبوطة على Permissive أن تُخفي فقدان قدرة ذات صلة بالأمان. استخدم Strict حيث تكون صحة المخرجات ضابطًا. تعامَل مع سياق الاستثناء وأحداث المهام واستجابات الملحق بوصفها بيانات قد تُسجَّل، ونقِّها وفقًا لذلك.

لا تؤكِّد هذه الصفحة أي ادعاء معياري مباشر. تكشف عقود إمكانية المراقبة حالة المحرك، ولا تُنفِّذ بروتوكولًا مُعيَّرًا يجب على المحرك الاستشهاد ببنوده. التزامات القياس الآمن وتنقية السجلات المُشار إليها أعلاه مُشتقَّة من سياسة التسجيل الداخلية للمشروع، لا من معيار خارجي. عندما تكون العملية المُراقَبة مُعيَّرة بذاتها — مثل توقيع أو مستند ⁨PDF/A⁩ — تكون مطابقتها مُوثَّقة في صفحة التوقيع أو الاستخراج.