Наблюдение за отрисовкой через OpenTelemetry
NextPDF включает встроенную инструментацию OpenTelemetry: 10 интервалов трассировки и 7 метрик на протяжении всего жизненного цикла создания Portable Document Format (PDF). Контракт гарантирует нулевые накладные расходы и нулевую настройку, когда OTel SDK отсутствует: без сбоев автозагрузки и потерь производительности. Установите software development kit (SDK), зарегистрируйте TracerProvider/MeterProvider глобально — и тот же код начнёт экспортировать данные автоматически. AttributeSanitizer работает по списку разрешений и обеспечивает соблюдение политики данных Zero-Trust, поэтому телеметрия никогда не содержит содержимого документа или персональных данных (PII).
Используйте эту страницу как PHP-ориентированное дополнение к концепциям OpenTelemetry, не зависящим от транспорта. Готовый к запуску пример и сопутствующий тест покрывают весь процесс.
Установка
Заголовок раздела «Установка»composer require nextpdf/core:^3Один только Core предоставляет безопасный слой инструментации, который ничего не делает при отсутствии OTel. Чтобы экспортировать данные в реальном времени, добавьте SDK и один экспортёр.
composer require open-telemetry/sdk:^1composer require open-telemetry/exporter-otlp:^1 # or zipkin / prometheusКонцептуальный обзор
Заголовок раздела «Концептуальный обзор»Используйте две точки входа:
TelemetryBridge— статический фасад.isAvailable()один раз проверяет наличие OTel и кэширует результат.startSpan()/endSpan()/recordMetric()сразу выполняются вхолостую, когда OTel отсутствует. Это и есть контракт нулевых накладных расходов. Когда OTel отсутствует, эти вызовы выполняются менее чем за микросекунду.OpenTelemetryInterceptor— путь с интеграцией SDK. Он автоматически трассирует 10 известных интервалов, записывает 7 известных метрик и пропускает каждый атрибут черезAttributeSanitizer. Он проверяет наличие SDK при создании объекта и кэширует результат. Все ссылки на классы OTel защищены проверками во время выполнения, поэтому класс загружается даже без SDK. Рекомендуемые границыBatchSpanProcessor(maxQueueSize=2048,maxExportBatchSize=512) доступны как статические методы доступа.
10 интервалов: 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 работает только по списку разрешений. Он пропускает ключи структурных метаданных, такие как pdf.page_count, pdf.file_size_bytes, pdf.output_profile и nextpdf.tier. Необработанный HTML, байтовые потоки PDF, base64-блоки и пути в файловой системе он безусловно отбрасывает. Это реализует два положения из рекомендаций NIST SP 800-92: телеметрия не должна содержать конфиденциальные данные, а конфиденциальность телеметрии должна быть явным средством контроля.
Описание 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');Пример кода — продакшен
Заголовок раздела «Пример кода — продакшен»Полный пример подтверждает путь без операций с нулевыми накладными расходами, потому что выполняется при отсутствии SDK. Он задействует список разрешений санитайзера и соблюдает выходной канал тестового стенда. Стенд проверки воспроизводимости запускает этот скрипт дважды.
<?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)),));Граничные случаи и подводные камни
Заголовок раздела «Граничные случаи и подводные камни»- Телеметрия никогда не нарушает отрисовку. И мост, и перехватчик поглощают собственные внутренние ошибки. Неправильно настроенный экспортёр ухудшает наблюдаемость, но не выходной PDF. Не оборачивайте код отрисовки в блок catch, который трактует сбой телеметрии как сбой отрисовки.
endSpan(null)безопасен.startSpan()возвращаетnull, когда OTel отсутствует, аendSpan()принимаетnullкак операцию без эффекта. Всегда используйте их в паре и никогда не выполняйте ветвление по возвращаемому значению.- Для метрик требуется зарегистрированный
MeterProvider. Если зарегистрирован толькоTracerProvider, интервалы экспортируются, но метрики молча пропускаются. Метрики носят рекомендательный характер. Для полного покрытия зарегистрируйте оба провайдера. - Санитайзер работает только по списку разрешений. Новый ключ атрибута, которого нет в списке разрешений, не будет экспортирован. Это поведение является преднамеренным. Расширьте список разрешений в движке и не обходите санитайзер.
- Распространение контекста трассировки W3C Trace Context. Межсервисное распространение трассировки использует заголовки W3C Trace Context
traceparent/tracestate. Их обрабатывают пропагаторы OTel SDK, а не NextPDF. Рекомендации W3C Trace Context нет в корпусе проверки, поэтому это замечание о распространении не подтверждено RAG и приведено как руководство по интеграции, а не как нормативное утверждение. См. боковую панель. - Оговорка о воспроизводимости. Отрисовка создаёт документ, у которого
/IDи дата изменения создаются заново при каждом сохранении (ISO 32000-2 §14.3). Захваченный PDF сравнивается с профилем semantic, который охватывает только структурное абстрактное синтаксическое дерево (AST) и метаданные.
Производительность
Заголовок раздела «Производительность»- Путь без OTel:
isAvailable()кэшируется после первого вызова. Последующие вызовы интервалов и метрик выполняют одну булеву проверку и сразу возвращаются. Инструментированный пример полностью выполняется при отсутствии SDK. - С OTel: границы
BatchSpanProcessor(maxQueueSize=2048,maxExportBatchSize=512) ограничивают объём памяти при устойчивой нагрузке, а экспорт остаётся вне горячего пути. - Параметр
performance_budget(wall_ms: 3000,peak_mb: 128) ограничивает прогон тестового стенда, а не произвольные документы. - Этот рецепт закрывает пункт #33 из списка пробелов §4.3. Раньше существовала только концептуальная страница в стиле MCP, без PHP-ориентированного примера. Были созданы новый файл
examples/33-opentelemetry-observability.phpи сопутствующий емуtests/Cookbook/Php/ObserveWithOpenTelemetryRecipeTest.php.
Заметки по безопасности
Заголовок раздела «Заметки по безопасности»- Телеметрия не должна содержать содержимое документа или PII. Список разрешений
AttributeSanitizerобеспечивает соблюдение этого правила на уровне кода. Необработанный HTML, потоки PDF, base64-блоки и пути в файловой системе отбрасываются. Это соответствует рекомендациям NIST SP 800-92 по недопущению конфиденциальных данных в журналах и телеметрии, а также по защите конфиденциальности телеметрии. - Атрибуты, которые вы добавляете сами, по-прежнему подчиняются списку разрешений. Вы всё равно отвечаете за то, чтобы не внести конфиденциальные значения под разрешённым ключом. Например, не помещайте идентификатор пользователя в
pdf.output_profile. - Диагностические сведения передаются структурированными ключами, а не произвольной полезной нагрузкой. Это тот же принцип, который PSR-3 §1.2 применяет к контексту журнала.
Соответствие
Заголовок раздела «Соответствие»| Положение | Спецификация | Раздел | reference_id (идентификатор ссылки) |
|---|---|---|---|
| Телеметрия не должна содержать конфиденциальные данные; требуется надлежащая обработка PII. | NIST SP 800-92 | §3 | |
| Конфиденциальность телеметрии и журналов должна быть явным средством контроля. | NIST SP 800-92 | §3 | |
| Подробности передаются структурированными ключами контекста, а не произвольной полезной нагрузкой. | PSR-3 | §1.2 | |
Выходные /ID и даты создаются заново при каждом сохранении → профиль semantic. | ISO 32000-2 | §14.3 |
Этот рецепт описывает инженерное поведение инструментации. Он не утверждает наличия какой-либо сертификации соответствия. Ссылки на NIST SP 800-92 обосновывают проектный принцип “без содержимого в телеметрии”, а не утверждение о соответствии.