Zum Inhalt springen

Telemetrie: OpenTelemetry-Bridge und No-op-Fallback

Das Telemetrie-Modul ist die optionale OpenTelemetry-Bridge der Engine. Wenn das OpenTelemetry-SDK installiert ist, gibt es Spans und Metriken mit bereinigten Attributen aus. Wenn es nicht installiert ist, hält ein vollständiger Satz aus No-op-Tracer- und No-op-Meter-Objekten die Instrumentierungsaufrufe valide und ohne Laufzeitkosten. Die Instrumentierung kann daher jederzeit gefahrlos im Codepfad verbleiben.

Terminal-Fenster
composer require nextpdf/core:^3

Das Designziel ist Observability, die ohne Laufzeitkosten bleibt, wenn die zugrunde liegende Unterstützung fehlt. Die Hot Paths der Engine rufen einen Tracer und einen Meter bedingungslos auf. Ob diese Aufrufe etwas bewirken, hängt von der Laufzeitumgebung ab, nicht von Prüfungen an jeder Aufrufstelle.

OpenTelemetryInterceptor ist die Bridge. isAvailable() meldet, ob das OTel-SDK vorhanden ist. startSpan(string $name, array $attributes = []) / endSpan(?object $span) beginnen und beenden eine getracete Operation, und recordMetric() erfasst einen Counter- oder Gauge-Wert. Wenn OTel nicht vorhanden ist, meldet der Interceptor Nichtverfügbarkeit, und die Aufrufe bleiben wirkungslos. TelemetryBridge verdrahtet den Interceptor mit den Beobachtungspunkten der Engine.

AttributeSanitizer ist die Sicherheitsschicht. sanitize(array $attributes) bereinigt die Attribut-Map, bevor sie den Prozess verlässt. Telemetrie-Attribute sind ein typischer Kanal, über den versehentlich PII austreten kann; daher ist die Bereinigung Teil des Vertrags und kein optionaler Zusatz. Sie ist @since 2.3.0, ebenso wie der Interceptor und die Bridge.

NullTracer, NullSpanBuilder, NullSpan, NullMeter, NullCounter und NullHistogram bilden den No-op-Fallback. Sie stellen dieselben API-Formen bereit wie das OTel-SDK — spanBuilder(), setAttribute() (verkettbar), startSpan(), end(), createHistogram(), createUpDownCounter(), add(), record() — und tun nichts. Da der Fallback vollständig ist, verzweigt instrumentierter Code nicht nach Verfügbarkeit; er ruft den Tracer auf, und die No-op-Implementierung absorbiert den Aufruf.

KlasseWichtige MemberRolle
OpenTelemetryInterceptorisAvailable(), startSpan(), endSpan(), recordMetric()OTel-Span-/Metrik-Bridge (@since 2.3.0)
TelemetryBridgeEngine-VerdrahtungVerbindet den Interceptor mit den Beobachtungspunkten (@since 2.3.0)
AttributeSanitizersanitize(array $attributes): arrayPII-sicherer Attribut-Scrubber (@since 2.3.0)
NullTracerspanBuilder(string $name): NullSpanBuilderNo-op-Tracer
NullSpanBuildersetAttribute(), startSpan(): NullSpanNo-op-Span-Builder (verkettbar)
NullSpanend()No-op-Span
NullMetercreateHistogram(), createUpDownCounter()No-op-Meter
NullCounter / NullHistogramadd(), record()No-op-Instrumente

Führen Sie composer docs:generate-api-php -- --module=Telemetry aus, um die vollständige PHPDoc-Tabelle zu erhalten.

Quelle: examples/33-opentelemetry-observability.php.

<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Telemetry\OpenTelemetryInterceptor;
$otel = new OpenTelemetryInterceptor(/* optional OTel tracer/meter */);
$span = $otel->startSpan('pdf.render', ['doc.pages' => 12]);
// ... render work ...
$otel->endSpan($span);
$otel->recordMetric('pdf.render.bytes', 482_113, ['profile' => 'pdfa4']);

Wenn das OTel-SDK nicht vorhanden ist, ist jeder oben gezeigte Aufruf ein No-op — der Code ist identisch, die Kosten bleiben null.

Umschließen Sie einen Rendering-Vorgang mit bereinigten Attributen, damit vom Aufrufer bereitgestellte Metadaten nicht in einen Span gelangen können.

<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Telemetry\AttributeSanitizer;
use NextPDF\Telemetry\OpenTelemetryInterceptor;
final readonly class InstrumentedRenderer
{
public function __construct(
private OpenTelemetryInterceptor $otel,
private AttributeSanitizer $sanitizer,
) {}
/**
* @param callable():string $render Returns the rendered PDF bytes.
* @param array<string, mixed> $attributes Caller-supplied span attributes.
*/
public function render(callable $render, array $attributes): string
{
$span = $this->otel->startSpan('pdf.render', $this->sanitizer->sanitize($attributes));
try {
return $render();
} finally {
$this->otel->endSpan($span);
}
}
}
  • Der No-op-Fallback ist bewusst vollständig. Schützen Sie die Instrumentierung nicht mit isAvailable(), „um Arbeit zu sparen“. Das No-op kostet bereits nichts, und der Schutz fügt eine Verzweigung hinzu, die das Design gerade vermeiden soll.
  • Führen Sie vom Aufrufer bereitgestellte Attribute stets durch AttributeSanitizer, bevor sie in einen Span oder eine Metrik gelangen. Telemetrie-Attribute sind ein Kanal für versehentliche PII.
  • endSpan(null) ist gültig — ein Null-Span ist der No-op-Fall. Paaren Sie jeden startSpan() mit einem endSpan() in einem finally.
  • NullSpanBuilder::setAttribute() gibt static für die Verkettung zurück; die Kette ist im No-op-Fall wirkungslos, was beabsichtigt und kein Fehler ist.
  • Das Reproduzierbarkeitsprofil ist structural: Spans tragen Zeitstempel und Trace-IDs, sodass sich zwei Läufe in diesen Feldern unterscheiden.

Wenn OTel nicht vorhanden ist, beschränken sich die Kosten auf einen Methodenaufruf in eine No-op-Implementierung — praktisch kostenlos. Wenn es vorhanden ist, fallen die Kosten beim OTel-SDK an, nicht bei diesem Modul; die Bridge fügt eine Attribut-Bereinigung hinzu, die linear zur Anzahl der Attribute ist. Das performance_budget von 1500 ms Wall / 64 MB Peak ist die Engine-Referenz, keine Telemetrie-SLA.

Telemetrie ist eine Datenausgabeoberfläche. AttributeSanitizer ist die Schutzmaßnahme, die Geheimnisse und PII aus Spans und Metriken heraushält. Behandeln Sie die Bereinigung als verpflichtend für jedes vom Aufrufer beeinflusste Attribut. Das entspricht der Verpflichtung des Projekts zu sicherer Telemetrie. Der OTel-Exporter sendet Daten an ein externes Backend. Diese Backend-Grenze ist eine Vertrauensgrenze. Konfigurieren Sie den Endpunkt und die Anmeldeinformationen des Backends über einen Secret-Manager, nicht über eingecheckte Konfiguration. Span- und Metrikdaten sollten so behandelt werden, als erreichten sie eine Log-Senke. Bereinigen Sie entsprechend. Siehe das Bedrohungsmodell der Engine in /modules/core/security/.

Dieses Modul erhebt keinen normativen Anspruch nach der PDF-Spezifikation. Es bildet eine Bridge zum OpenTelemetry-Datenmodell, das eine externe Observability-Spezifikation ist und nicht aus einer PDF-Klausel stammt. Der No-op-Fallback bildet die OTel-API-Oberfläche ab, sodass instrumentierter Code portabel ist; das ist eine API-Kompatibilitätseigenschaft, keine PDF-Konformitätsaussage. Die Engine-Konformität wird durch die Oracle- und Golden-Suiten validiert, die in /modules/core/conformance/ beschrieben sind.