Przejdź do głównej zawartości

Obserwuj renderowanie za pomocą OpenTelemetry

NextPDF zawiera wbudowaną instrumentację OpenTelemetry: 10 zakresów śladów i 7 metryk w całym cyklu generowania dokumentu Portable Document Format (PDF). Kontrakt brzmi: zerowy narzut i zerowa konfiguracja, gdy brakuje OTel SDK — bez błędu autoładowania i bez kosztu wydajnościowego. Zainstaluj zestaw narzędzi programistycznych (SDK), zarejestruj globalnie TracerProvider/MeterProvider, a ten sam kod będzie automatycznie eksportować dane. Oparty na liście dozwolonych AttributeSanitizer wymusza politykę danych Zero-Trust, dzięki czemu telemetria nigdy nie przenosi zawartości dokumentu ani informacji umożliwiających identyfikację osoby (PII).

Traktuj tę stronę jako uzupełnienie dla PHP do niezależnych od transportu koncepcji OpenTelemetry. Uruchamialny przykład i towarzyszący mu test obejmują cały przepływ.

Okno terminala
composer require nextpdf/core:^3

Sam Core udostępnia powierzchnię instrumentacji bezpieczną w trybie no-op. Aby eksportować dane na żywo, dodaj SDK oraz jeden eksporter.

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

Korzystaj z dwóch punktów wejścia:

  • TelemetryBridge — statyczna fasada. isAvailable() sprawdza obecność OTel jednokrotnie i buforuje wynik. startSpan() / endSpan() / recordMetric() natychmiast przechodzą do trybu no-op, gdy brakuje OTel. To jest kontrakt zerowego narzutu. Przy braku OTel wywołania te kończą się znacznie poniżej jednej mikrosekundy.
  • OpenTelemetryInterceptor — ścieżka zintegrowana z SDK. Automatycznie śledzi 10 znanych zakresów, rejestruje 7 znanych metryk i kieruje każdy atrybut przez AttributeSanitizer. Sprawdza obecność SDK podczas tworzenia obiektu i buforuje wynik. Wszystkie odwołania do klas OTel chronią strażniki czasu wykonania, więc klasa ładuje się nawet bez SDK. Zalecane limity BatchSpanProcessor (maxQueueSize=2048, maxExportBatchSize=512) są udostępniane jako statyczne metody dostępowe.

10 zakresów: document.build, font.resolve, html.parse, writer.serialize, image.decode, layout.pass, barcode.encode, form.build, navigation.build, attachment.embed. 7 metryk: render.duration, render.page_count, render.warnings, render.memory_peak, render.file_size, render.font_count, render.image_count.

AttributeSanitizer działa wyłącznie na liście dozwolonych. Zezwala na klucze metadanych strukturalnych, takie jak pdf.page_count, pdf.file_size_bytes, pdf.output_profile oraz nextpdf.tier. Bezwarunkowo odrzuca surowy HTML, strumienie bajtowe PDF, dane base64 oraz ścieżki systemu plików. Realizuje dwa punkty wytycznych NIST SP 800-92: telemetria nie może przenosić treści wrażliwych, a poufność telemetrii jest jawnym mechanizmem kontroli.

Powierzchnia API jest generowana z PHPDoc w klasach NextPDF\Telemetry\TelemetryBridge, NextPDF\Telemetry\OpenTelemetryInterceptor oraz NextPDF\Telemetry\AttributeSanitizer. Kluczowe elementy używane poniżej to TelemetryBridge::isAvailable() / startSpan() / endSpan() / recordMetric(); OpenTelemetryInterceptor::knownSpans() / knownMetrics() / maxQueueSize() / maxExportBatchSize(); oraz 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');

Kompletny przykład potwierdza ścieżkę no-op o zerowym narzucie, ponieważ działa także bez SDK. Sprawdza działanie listy dozwolonych w sanityzerze i respektuje kanał wyjściowy uprzęży testowej. Uprząż powtarzalności uruchamia ten skrypt dwukrotnie.

<?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)),
));
  • Telemetria nigdy nie psuje renderowania. Zarówno mostek, jak i interceptor pochłaniają własne błędy wewnętrzne. Źle skonfigurowany eksporter pogarsza obserwowalność, ale nigdy nie wpływa na wynikowy PDF. Nie opakowuj kodu renderowania w blok catch, który traktuje awarię telemetrii jak awarię renderowania.
  • endSpan(null) jest bezpieczne. startSpan() zwraca null, gdy brakuje OTel, a endSpan() przyjmuje null jako operację no-op. Zawsze stosuj je parami i nigdy nie rozgałęziaj logiki na podstawie zwracanej wartości.
  • Metryki wymagają zarejestrowanego MeterProvider. Jeśli zarejestrowany jest tylko TracerProvider, zakresy są eksportowane, ale metryki są po cichu pomijane. Metryki mają charakter pomocniczy. Zarejestruj obu dostawców, aby uzyskać pełne pokrycie.
  • Sanityzer działa wyłącznie na liście dozwolonych. Nowy klucz atrybutu, którego nie ma na liście dozwolonych, nie zostanie wyeksportowany. Takie zachowanie jest zamierzone. Rozszerz listę dozwolonych w silniku i nie omijaj sanityzera.
  • Propagacja W3C Trace Context. Propagacja śladu między usługami wykorzystuje nagłówki W3C Trace Context traceparent/tracestate. Obsługują je propagatory OTel SDK, a nie NextPDF. Rekomendacja W3C Trace Context nie znajduje się w korpusie weryfikacyjnym, więc ta uwaga o propagacji nie została rozstrzygnięta przez RAG i jest podana jako wskazówka integracyjna, a nie twierdzenie normatywne. Zobacz panel boczny.
  • Zastrzeżenie dotyczące powtarzalności. Renderowanie generuje dokument, którego /ID i data modyfikacji są generowane na nowo przy każdym zapisie (ISO 32000-2 §14.3). Przechwycony PDF jest porównywany z profilem semantycznym, który obejmuje wyłącznie strukturalne abstrakcyjne drzewo składniowe (AST) i metadane.
  • Ścieżka bez OTel: wynik isAvailable() jest buforowany po pierwszym wywołaniu. Późniejsze wywołania zakresów i metryk wykonują jedno sprawdzenie logiczne, po czym zwracają sterowanie. Zinstrumentowany przykład wykonuje się do końca przy braku SDK.
  • Z OTel: limity BatchSpanProcessor (maxQueueSize=2048, maxExportBatchSize=512) ograniczają zużycie pamięci przy stałym obciążeniu, a eksport pozostaje poza ścieżką krytyczną.
  • Wartość performance_budget (wall_ms: 3000, peak_mb: 128) ogranicza przebieg uprzęży, a nie dowolne dokumenty.
  • Ten przepis zapewnia pokrycie z listy luk §4.3 dla pozycji #33. Wcześniej istniała wyłącznie koncepcyjna strona w stylu MCP, bez przykładu natywnego dla PHP. Utworzono nowy plik examples/33-opentelemetry-observability.php oraz wspierający go tests/Cookbook/Php/ObserveWithOpenTelemetryRecipeTest.php.
  • Telemetria nie może przenosić zawartości dokumentu ani PII. Lista dozwolonych AttributeSanitizer wymusza to w kodzie. Surowy HTML, strumienie PDF, dane base64 oraz ścieżki systemu plików są odrzucane. Jest to zgodne z wytycznymi NIST SP 800-92 dotyczącymi nieumieszczania treści wrażliwych w dziennikach i telemetrii oraz ochrony poufności telemetrii.
  • Samodzielnie dodane atrybuty nadal podlegają liście dozwolonych. Nadal odpowiadasz za to, aby nie wprowadzać wrażliwych wartości pod dozwolonym kluczem. Na przykład nie umieszczaj identyfikatora użytkownika w pdf.output_profile.
  • Szczegóły diagnostyczne są przenoszone przez klucze strukturalne, a nie przez dowolne ładunki danych. Jest to ta sama dyscyplina, którą PSR-3 §1.2 stosuje do kontekstu dziennika.
StwierdzenieSpecyfikacjaKlauzulareference_id
Telemetria nie może przenosić treści wrażliwych; obsługa PII jest wymagana.NIST SP 800-92§3
Poufność telemetrii/dzienników jest jawnym mechanizmem kontroli.NIST SP 800-92§3
Strukturalne klucze kontekstu przenoszą szczegóły, a nie dowolny ładunek danych.PSR-3§1.2
Wyjściowe /ID i daty są generowane na nowo przy każdym zapisie → profil semantyczny.ISO 32000-2§14.3

Ten przepis opisuje inżynieryjne zachowanie instrumentacji. Nie stanowi deklaracji żadnej certyfikacji zgodności. Odwołania do NIST SP 800-92 uzasadniają zamysł projektowy nieumieszczania treści w telemetrii, a nie twierdzenie o zgodności.