Pular para o conteúdo

Observe a renderização com OpenTelemetry

O NextPDF inclui instrumentação OpenTelemetry integrada: 10 spans de trace e 7 métricas ao longo do ciclo de vida de geração do Portable Document Format (PDF). O contrato é zero overhead e zero configuração quando o SDK do OTel está ausente — sem falha de autoload e sem penalidade de desempenho. Instale o software development kit (SDK), registre um TracerProvider/MeterProvider globalmente, e o mesmo código passa a exportar automaticamente. Um AttributeSanitizer baseado em allowlist aplica uma Zero-Trust Data Policy, para que a telemetria nunca carregue conteúdo do documento nem informações de identificação pessoal (PII).

Use esta página como o complemento nativo em PHP para os conceitos de OpenTelemetry independentes de transporte. Um exemplo executável e o teste de apoio cobrem o fluxo.

Terminal window
composer require nextpdf/core:^3

Só o Core já oferece a superfície de instrumentação no-op-safe. Para exportar dados ao vivo, adicione o SDK e um exporter.

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

Use dois pontos de entrada:

  • TelemetryBridge — uma facade estática. isAvailable() verifica a presença do OTel uma vez e armazena o resultado em cache. startSpan() / endSpan() / recordMetric() fazem curto-circuito para um no-op quando o OTel está ausente. Esse é o contrato de zero overhead. Quando o OTel está ausente, essas chamadas terminam em bem menos de um microssegundo.
  • OpenTelemetryInterceptor — o caminho integrado ao SDK. Ele rastreia automaticamente os 10 spans conhecidos, registra as 7 métricas conhecidas e passa cada atributo por AttributeSanitizer. Ele verifica a presença do SDK na construção e armazena o resultado em cache. Todas as referências a classes do OTel ficam atrás de guardas de runtime, de modo que a classe é carregada mesmo sem o SDK. Os limites recomendados do BatchSpanProcessor (maxQueueSize=2048, maxExportBatchSize=512) são expostos como acessadores estáticos.

Os 10 spans: document.build, font.resolve, html.parse, writer.serialize, image.decode, layout.pass, barcode.encode, form.build, navigation.build, attachment.embed. As 7 métricas: render.duration, render.page_count, render.warnings, render.memory_peak, render.file_size, render.font_count, render.image_count.

AttributeSanitizer é exclusivamente baseado em allowlist. Ele permite chaves de metadados estruturais como pdf.page_count, pdf.file_size_bytes, pdf.output_profile e nextpdf.tier. Ele descarta, incondicionalmente, HTML bruto, fluxos de bytes de PDF, blobs base64 e caminhos do sistema de arquivos. Isso implementa dois pontos das diretrizes do NIST SP 800-92: a telemetria não deve carregar conteúdo sensível, e a confidencialidade da telemetria é um controle explícito.

A superfície da application programming interface (API) é gerada a partir do PHPDoc em NextPDF\Telemetry\TelemetryBridge, NextPDF\Telemetry\OpenTelemetryInterceptor e NextPDF\Telemetry\AttributeSanitizer. Os membros-chave usados abaixo são TelemetryBridge::isAvailable() / startSpan() / endSpan() / recordMetric(); OpenTelemetryInterceptor::knownSpans() / knownMetrics() / maxQueueSize() / maxExportBatchSize(); e 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');

O exemplo completo comprova o caminho no-op de zero overhead porque é executado com o SDK ausente. Ele exercita a allowlist do sanitizer e respeita o canal de saída do harness. O harness de reprodutibilidade executa esse script duas vezes.

<?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)),
));
  • A telemetria nunca quebra a renderização. Tanto o bridge quanto o interceptor engolem seus próprios erros internos. Um exporter mal configurado degrada a observabilidade, nunca a saída do PDF. Não envolva o código de renderização em um catch que trate uma falha de telemetria como falha de renderização.
  • endSpan(null) é seguro. startSpan() retorna null quando o OTel está ausente, e endSpan() aceita null como um no-op. Sempre pareie as chamadas e nunca ramifique com base no valor de retorno.
  • As métricas precisam de um MeterProvider registrado. Se apenas um TracerProvider estiver registrado, os spans serão exportados, mas as métricas serão ignoradas silenciosamente. As métricas são consultivas. Registre ambos os providers para ter cobertura completa.
  • O sanitizer é exclusivamente baseado em allowlist. Uma nova chave de atributo que não esteja na allowlist não será exportada. Esse comportamento é intencional. Estenda a allowlist no engine e não contorne o sanitizer.
  • Propagação de W3C Trace Context. A propagação de trace entre serviços usa os cabeçalhos traceparent/tracestate do W3C Trace Context. Os propagadores do SDK do OTel cuidam deles, não o NextPDF. A Recommendation do W3C Trace Context não está no corpus de verificação; portanto, esta nota de propagação está RAG-unresolved e é apresentada como orientação de integração, não como afirmação normativa. Consulte o sidecar.
  • Ressalva de reprodutibilidade. A renderização emite um documento cujo /ID e cuja data de modificação são regenerados a cada save (ISO 32000-2 §14.3). O PDF capturado é comparado com o perfil semantic, que cobre apenas a abstract syntax tree (AST) estrutural e os metadados.
  • Caminho sem OTel: isAvailable() é armazenado em cache após a primeira chamada. As chamadas posteriores de span e métrica fazem uma verificação booleana e retornam. O exemplo instrumentado é executado até o fim com o SDK ausente.
  • Com OTel: os limites do BatchSpanProcessor (maxQueueSize=2048, maxExportBatchSize=512) limitam o uso de memória sob carga sustentada, e a exportação permanece fora do hot path.
  • O performance_budget (wall_ms: 3000, peak_mb: 128) limita a execução do harness, não documentos arbitrários.
  • Esta receita cobre a gap-list do §4.3 para o #33. Antes, existia apenas a página de conceito no estilo MCP, sem exemplo nativo em PHP. Foram criados um novo examples/33-opentelemetry-observability.php e o tests/Cookbook/Php/ObserveWithOpenTelemetryRecipeTest.php de apoio.
  • A telemetria não deve carregar conteúdo do documento nem PII. A allowlist do AttributeSanitizer impõe isso em código. HTML bruto, fluxos de PDF, blobs base64 e caminhos do sistema de arquivos são descartados. Isso está alinhado às diretrizes do NIST SP 800-92 sobre manter conteúdo sensível fora de logs e telemetria e sobre proteger a confidencialidade da telemetria.
  • Os atributos que você mesmo adiciona ainda estão sujeitos à allowlist. Você continua responsável por não introduzir valores sensíveis em uma chave permitida. Por exemplo, não coloque um identificador de usuário em pdf.output_profile.
  • As chaves estruturadas, e não payloads de forma livre, carregam o detalhe de diagnóstico. Esta é a mesma disciplina que o PSR-3 §1.2 aplica ao contexto de log.
DeclaraçãoEspecificaçãoCláusulareference_id
A telemetria não deve carregar conteúdo sensível; o tratamento de PII é obrigatório.NIST SP 800-92§3
A confidencialidade da telemetria/log é um controle explícito.NIST SP 800-92§3
As chaves de contexto estruturadas carregam o detalhe, não o payload de forma livre.PSR-3§1.2
O /ID de saída e as datas são regenerados a cada save → perfil semantic.ISO 32000-2§14.3

Esta receita descreve o comportamento de instrumentação de engenharia. Ela não afirma qualquer certificação de conformidade. As referências ao NIST SP 800-92 fundamentam a intenção de design de não incluir conteúdo na telemetria, não uma afirmação de conformidade.