Telemetria: bridge OpenTelemetry e fallback no-op
In sintesi
Sezione intitolata “In sintesi”Il modulo Telemetry è il bridge OpenTelemetry opzionale del motore. Quando l’SDK OpenTelemetry è installato, emette span e metriche con attributi sanitizzati. Quando non lo è, un insieme completo di oggetti tracer e meter no-op mantiene valide e a costo nullo le chiamate di strumentazione. La strumentazione può quindi rimanere sempre in sicurezza nel percorso del codice.
Installazione
Sezione intitolata “Installazione”composer require nextpdf/core:^3Panoramica concettuale
Sezione intitolata “Panoramica concettuale”L’obiettivo progettuale è garantire un’osservabilità a costo zero quando OTel è assente. I percorsi critici del motore chiamano un tracer e un meter senza condizioni. Che tali chiamate producano effetti dipende dal runtime, non da un condizionale in ogni punto di chiamata.
OpenTelemetryInterceptor è il bridge. isAvailable() segnala se l’SDK OTel è presente. startSpan(string $name, array $attributes = []) / endSpan(?object $span) racchiudono un’operazione tracciata, mentre recordMetric() registra il valore di un contatore o di un gauge. Quando OTel è assente, l’interceptor si segnala come non disponibile e le chiamate restano inerti. TelemetryBridge collega l’interceptor ai punti di osservazione del motore.
AttributeSanitizer è il livello di sicurezza. sanitize(array $attributes) ripulisce la mappa degli attributi prima che lasci il processo. Gli attributi di telemetria sono un classico canale di PII involontaria, quindi la sanitizzazione fa parte del contratto, non è un’aggiunta successiva. È @since 2.3.0, così come l’interceptor e il bridge.
NullTracer, NullSpanBuilder, NullSpan, NullMeter, NullCounter e NullHistogram sono il fallback no-op. Implementano le stesse forme esposte dall’SDK OTel — spanBuilder(), setAttribute() (concatenabile), startSpan(), end(), createHistogram(), createUpDownCounter(), add(), record() — e non fanno nulla. Poiché il fallback è completo, il codice strumentato non introduce diramazioni in base alla disponibilità; chiama il tracer e il no-op assorbe la chiamata.
Superficie API
Sezione intitolata “Superficie API”| Classe | Membri principali | Ruolo |
|---|---|---|
OpenTelemetryInterceptor | isAvailable(), startSpan(), endSpan(), recordMetric() | Bridge span/metric OTel (@since 2.3.0) |
TelemetryBridge | cablaggio del motore | Collega l’interceptor ai punti di osservazione (@since 2.3.0) |
AttributeSanitizer | sanitize(array $attributes): array | Scrubber degli attributi per proteggere le PII (@since 2.3.0) |
NullTracer | spanBuilder(string $name): NullSpanBuilder | Tracer no-op |
NullSpanBuilder | setAttribute(), startSpan(): NullSpan | Span builder no-op (concatenabile) |
NullSpan | end() | Span no-op |
NullMeter | createHistogram(), createUpDownCounter() | Meter no-op |
NullCounter / NullHistogram | add(), record() | Strumenti no-op |
Eseguire composer docs:generate-api-php -- --module=Telemetry per ottenere la tabella PHPDoc completa.
Esempio di codice — Avvio rapido
Sezione intitolata “Esempio di codice — Avvio rapido”Sorgente: 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']);Quando l’SDK OTel è assente, ogni chiamata qui sopra è un no-op — il codice è identico, il costo è zero.
Esempio di codice — Produzione
Sezione intitolata “Esempio di codice — Produzione”Avvolgere un rendering con attributi sanitizzati in modo che i metadati forniti dal chiamante non possano trapelare in uno span.
<?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); } }}Casi limite e insidie
Sezione intitolata “Casi limite e insidie”- Il fallback no-op è completo per progettazione. Non proteggere la strumentazione con
isAvailable()«per risparmiare lavoro». Il no-op è già a costo nullo, e la protezione aggiunge una diramazione che il design esiste per rimuovere. - Far passare sempre gli attributi forniti dal chiamante attraverso
AttributeSanitizerprima di uno span o di una metrica. Gli attributi di telemetria sono un canale di PII accidentale. endSpan(null)è valido — uno span null è il caso no-op. Abbinare ognistartSpan()a unendSpan()in unfinally.NullSpanBuilder::setAttribute()restituiscestaticper la concatenazione; la catena resta inerte con il no-op, il che è intenzionale, non un bug.- Il profilo di riproducibilità è
structural: gli span portano timestamp e ID di traccia, quindi due esecuzioni differiscono in tali campi.
Prestazioni
Sezione intitolata “Prestazioni”Quando OTel è assente, il costo è una chiamata di metodo a un no-op — di fatto gratuito. Quando è presente, il costo è quello dell’SDK OTel, non di questo modulo; il bridge aggiunge la sanitizzazione degli attributi, che è lineare rispetto al numero di attributi. Il performance_budget di 1500 ms wall / 64 MB di picco è il riferimento del motore, non uno SLA di telemetria.
Note sulla sicurezza
Sezione intitolata “Note sulla sicurezza”La telemetria è una superficie di uscita dei dati. AttributeSanitizer è il controllo che tiene segreti e PII fuori da span e metriche. Considerare obbligatoria la sanitizzazione per qualsiasi attributo influenzato dal chiamante: è il requisito di telemetria sicura del progetto. L’exporter OTel invia i dati a un backend esterno. Il confine con quel backend è un confine di fiducia. Configurare il suo endpoint e le credenziali da un gestore di segreti, non da configurazione versionata. Si deve presumere che i dati di span e metriche raggiungano un sink di log. Ripulire di conseguenza. Consultare il modello delle minacce del motore in /modules/core/security/.
Conformità
Sezione intitolata “Conformità”Questo modulo non formula alcuna asserzione normativa sulla specifica PDF. Funge da bridge verso il modello dati OpenTelemetry, che è una specifica di osservabilità esterna, non una clausola PDF. Il fallback no-op rispecchia la superficie API OTel in modo che il codice strumentato sia portabile; questa è una proprietà di compatibilità API, non una dichiarazione di conformità PDF. La conformità del motore è validata dalle suite oracle e golden descritte in /modules/core/conformance/.
Vedere anche
Sezione intitolata “Vedere anche”- Modulo Observability — la superficie più ampia dello stato di runtime.
- Modulo Performance — diagnostica della memoria da affiancare alla telemetria.
- Contracts / Observability — i contratti per eccezioni strutturate e degradazione.
- Modello di sicurezza del motore