Zum Inhalt springen

Rendering mit OpenTelemetry beobachten

NextPDF bringt eine integrierte OpenTelemetry-Instrumentierung mit: 10 Trace-Spans und 7 Metriken über den gesamten Lebenszyklus der PDF-Generierung. Die Zusage lautet: kein Overhead und keine Konfiguration, wenn das OTel-SDK fehlt – kein Autoload-Fehler, keine Performance-Einbuße. Installieren Sie das SDK, registrieren Sie global einen TracerProvider/MeterProvider, und derselbe Code exportiert automatisch. Ein Allowlist-basierter AttributeSanitizer setzt eine Zero-Trust-Datenrichtlinie durch, sodass die Telemetrie nie Dokumentinhalte oder PII enthält.

Diese Seite ist das PHP-native Gegenstück zu den transportunabhängigen OpenTelemetry-Konzepten. Ein lauffähiges Beispiel und ein begleitender Test zeigen den Ablauf.

Terminal-Fenster
composer require nextpdf/core:^3

Core allein stellt Ihnen die No-op-sichere Instrumentierungsoberfläche bereit. Um Live-Daten zu exportieren, fügen Sie das SDK und einen Exporter hinzu.

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

Es gibt zwei Einstiegspunkte:

  • TelemetryBridge – eine statische Fassade. isAvailable() führt die OTel-Präsenzprüfung einmal aus und speichert das Ergebnis im Cache. startSpan() / endSpan() / recordMetric() fallen auf einen No-op zurück, wenn OTel fehlt. Das ist die Zero-Overhead-Zusage. Wenn OTel fehlt, sind diese Aufrufe in deutlich unter einer Mikrosekunde abgeschlossen.
  • OpenTelemetryInterceptor – der SDK-integrierte Pfad. Er erfasst automatisch die 10 bekannten Spans, zeichnet die 7 bekannten Metriken auf und leitet jedes Attribut durch den AttributeSanitizer. Er prüft bei der Konstruktion, ob das SDK vorhanden ist, und speichert das Ergebnis im Cache. Alle OTel-Klassenreferenzen liegen hinter Laufzeit-Guards, sodass die Klasse auch ohne das SDK geladen werden kann. Die empfohlenen BatchSpanProcessor-Grenzen (maxQueueSize=2048, maxExportBatchSize=512) werden über statische Accessor-Methoden bereitgestellt.

Die 10 Spans sind: document.build, font.resolve, html.parse, writer.serialize, image.decode, layout.pass, barcode.encode, form.build, navigation.build, attachment.embed. Die 7 Metriken sind: render.duration, render.page_count, render.warnings, render.memory_peak, render.file_size, render.font_count, render.image_count.

AttributeSanitizer arbeitet ausschließlich mit einer Allowlist. Erlaubte Schlüssel sind strukturelle Metadaten wie pdf.page_count, pdf.file_size_bytes, pdf.output_profile und nextpdf.tier. Roh-HTML, PDF-Byte-Streams, Base64-Blobs und Dateisystempfade werden bedingungslos verworfen. Damit setzt NextPDF zwei Punkte der NIST SP 800-92-Leitlinie um: Telemetrie darf keine sensiblen Inhalte enthalten, und die Vertraulichkeit der Telemetrie muss ausdrücklich geschützt werden.

Die API-Oberfläche wird aus dem PHPDoc von NextPDF\Telemetry\TelemetryBridge, NextPDF\Telemetry\OpenTelemetryInterceptor und NextPDF\Telemetry\AttributeSanitizer generiert. Die unten verwendeten zentralen Mitglieder sind TelemetryBridge::isAvailable() / startSpan() / endSpan() / recordMetric(); OpenTelemetryInterceptor::knownSpans() / knownMetrics() / maxQueueSize() / maxExportBatchSize(); sowie 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');

Das vollständige Beispiel weist den Zero-Overhead-No-op-Pfad nach, weil es auch bei fehlendem SDK läuft. Es zeigt die Sanitizer-Allowlist im Einsatz und berücksichtigt den Ausgabekanal des Test-Harnesses. Der Reproduzierbarkeits-Harness führt dieses Skript zweimal aus.

<?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)),
));
  • Telemetrie bricht nie das Rendering ab. Sowohl die Bridge als auch der Interceptor fangen ihre eigenen internen Fehler ab. Ein fehlkonfigurierter Exporter verschlechtert die Beobachtbarkeit, aber nie die PDF-Ausgabe. Umschließen Sie Render-Code nicht mit einem catch-Block, der einen Telemetrie-Fehler als Render-Fehler behandelt.
  • endSpan(null) ist sicher. startSpan() gibt null zurück, wenn OTel fehlt, und endSpan() akzeptiert null als No-op. Rufen Sie beide immer paarweise auf, und verzweigen Sie nie anhand des Rückgabewerts.
  • Metriken brauchen einen registrierten MeterProvider. Wenn nur ein TracerProvider registriert ist, werden Spans exportiert, Metriken aber stillschweigend übersprungen. Die Metriken sind beratend. Registrieren Sie beide Provider für vollständige Abdeckung.
  • Der Sanitizer arbeitet ausschließlich mit einer Allowlist. Ein neuer Attributschlüssel, der nicht in der Allowlist steht, wird nicht exportiert. Dieses Verhalten ist beabsichtigt. Erweitern Sie die Allowlist in der Engine, und umgehen Sie den Sanitizer nicht.
  • Propagierung des W3C Trace Context. Die dienstübergreifende Trace-Propagierung nutzt die W3C-Trace-Context-Header traceparent/tracestate. Die Propagatoren des OTel-SDK übernehmen das, nicht NextPDF. Die W3C-Trace-Context-Recommendation ist nicht im Verifikationskorpus, daher ist dieser Propagierungshinweis RAG-unresolved und wird als Integrationsleitlinie, nicht als normativer Anspruch, angegeben. Siehe den Sidecar.
  • Reproduzierbarkeits-Vorbehalt. Das Rendering gibt ein Dokument aus, dessen /ID und Änderungsdatum bei jedem Speichern neu erzeugt werden (ISO 32000-2 §14.3). Das erfasste PDF wird mit dem semantischen Profil verglichen, das nur den strukturellen AST und die Metadaten berücksichtigt.
  • Pfad ohne OTel: isAvailable() wird nach dem ersten Aufruf im Cache gespeichert. Nachfolgende Span- und Metrik-Aufrufe bestehen aus einer einzigen Boolean-Prüfung und anschließend einem Return. Das instrumentierte Beispiel läuft auch bei fehlendem SDK vollständig durch.
  • Mit OTel: Die BatchSpanProcessor-Grenzen (maxQueueSize=2048, maxExportBatchSize=512) begrenzen den Speicher unter Dauerlast, und der Export bleibt vom Hot Path fern.
  • Das performance_budget (wall_ms: 3000, peak_mb: 128) begrenzt den Harness-Lauf, nicht beliebige Dokumente.
  • Dieses Recipe deckt den Punkt aus der §4.3-Gap-List für #33 ab. Zuvor gab es kein PHP-natives Beispiel, nur die MCP-artige Konzeptseite. Ein neues examples/33-opentelemetry-observability.php sowie der begleitende tests/Cookbook/Php/ObserveWithOpenTelemetryRecipeTest.php wurden erstellt.
  • Telemetrie darf keine Dokumentinhalte oder PII enthalten. Die Allowlist des AttributeSanitizer setzt das im Code durch. Roh-HTML, PDF-Streams, Base64-Blobs und Dateisystempfade werden verworfen. Das steht im Einklang mit der NIST SP 800-92-Leitlinie, sensible Inhalte aus Logs und Telemetrie herauszuhalten und die Vertraulichkeit der Telemetrie zu schützen.
  • Attribute, die Sie selbst hinzufügen, unterliegen weiterhin der Allowlist. Sie bleiben dafür verantwortlich, keine sensiblen Werte unter einem erlaubten Schlüssel einzubringen. Legen Sie zum Beispiel keine Benutzerkennung in pdf.output_profile ab.
  • Strukturierte Schlüssel, nicht freie Payload, transportieren die diagnostischen Details. Das ist dieselbe Disziplin, die PSR-3 §1.2 für den Log-Kontext vorsieht.
AussageSpezifikationAbschnittreference_id
Telemetrie darf keine sensiblen Inhalte tragen; der Umgang mit PII ist verpflichtend.NIST SP 800-92§3
Vertraulichkeit von Telemetrie/Logs ist eine explizite Maßnahme.NIST SP 800-92§3
Strukturierte Kontextschlüssel tragen die Details, nicht freie Payload.PSR-3§1.2
Ausgabe-/ID und Datumsangaben werden bei jedem Speichern neu erzeugt → semantisches Profil.ISO 32000-2§14.3

Dieses Recipe beschreibt das Verhalten der technischen Instrumentierung. Es erhebt keinen Anspruch auf eine Compliance-Zertifizierung. Die NIST SP 800-92-Referenzen begründen die Designabsicht, keine Inhalte in der Telemetrie zu erfassen, und sind kein Konformitätsanspruch.