Bỏ qua để đến nội dung

Quan sát quá trình kết xuất bằng OpenTelemetry

NextPDF tích hợp sẵn công cụ đo lường OpenTelemetry: 10 trace span và 7 metric trải khắp vòng đời tạo Portable Document Format (PDF). Cam kết là không tốn thêm chi phí và không cần cấu hình khi không có OTel SDK — không lỗi autoload, không suy giảm hiệu năng. Cài đặt software development kit (SDK), đăng ký một TracerProvider/MeterProvider ở phạm vi toàn cục, và cùng đoạn mã đó sẽ tự động xuất dữ liệu. AttributeSanitizer thực thi Chính sách dữ liệu Zero-Trust bằng danh sách cho phép, nên telemetry không bao giờ mang theo nội dung tài liệu hay thông tin nhận dạng cá nhân (PII).

Hãy dùng trang này như tài liệu đồng hành dành riêng cho PHP, đi kèm các khái niệm OpenTelemetry không phụ thuộc vào lớp truyền tải. Một ví dụ chạy được và bài kiểm thử hỗ trợ bao phủ toàn bộ luồng này.

Terminal window
composer require nextpdf/core:^3

Chỉ cần Core, bạn đã có bề mặt đo lường an toàn ở chế độ no-op. Để xuất dữ liệu trực tiếp, hãy thêm SDK và một exporter.

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

Sử dụng hai điểm vào:

  • TelemetryBridge — một facade tĩnh. isAvailable() kiểm tra OTel một lần rồi lưu cache kết quả. startSpan() / endSpan() / recordMetric() trở thành no-op khi không có OTel. Đây chính là cam kết không tốn thêm chi phí. Khi không có OTel, các lệnh gọi này hoàn tất nhanh hơn nhiều so với một micro giây.
  • OpenTelemetryInterceptor — đường dẫn tích hợp với SDK. Nó tự động ghi trace cho 10 span đã biết, ghi lại 7 metric đã biết, và định tuyến mọi thuộc tính qua AttributeSanitizer. Nó kiểm tra sự hiện diện của SDK ngay khi khởi tạo và lưu cache kết quả. Mọi tham chiếu đến lớp OTel đều được bảo vệ ở thời điểm chạy, nên lớp này vẫn nạp được kể cả khi không có SDK. Các giới hạn được khuyến nghị của BatchSpanProcessor (maxQueueSize=2048, maxExportBatchSize=512) được cung cấp qua các accessor tĩnh.

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

AttributeSanitizer chỉ hoạt động theo danh sách cho phép. Nó cho phép các khóa siêu dữ liệu có cấu trúc như pdf.page_count, pdf.file_size_bytes, pdf.output_profile, và nextpdf.tier. Nó loại bỏ vô điều kiện HTML thô, luồng byte PDF, dữ liệu base64 và đường dẫn tệp. Điều này hiện thực hóa hai điểm trong hướng dẫn của NIST SP 800-92: telemetry không được mang theo nội dung nhạy cảm, và tính bảo mật của telemetry là một biện pháp kiểm soát rõ ràng.

Bề mặt application programming interface (API) được tạo từ PHPDoc của NextPDF\Telemetry\TelemetryBridge, NextPDF\Telemetry\OpenTelemetryInterceptor, và NextPDF\Telemetry\AttributeSanitizer. Các thành viên chính được dùng bên dưới là TelemetryBridge::isAvailable() / startSpan() / endSpan() / recordMetric(); OpenTelemetryInterceptor::knownSpans() / knownMetrics() / maxQueueSize() / maxExportBatchSize(); và 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');

Ví dụ hoàn chỉnh này chứng minh đường dẫn no-op không tốn thêm chi phí: nó chạy được khi không có SDK. Ví dụ vận dụng danh sách cho phép của sanitizer và tuân thủ kênh đầu ra của harness. Harness tái lập kết quả bằng cách chạy script này hai lần.

<?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)),
));
  • Telemetry không bao giờ làm hỏng quá trình kết xuất. Cả bridge lẫn interceptor đều tự xử lý và bỏ qua các lỗi nội bộ của chính chúng. Một exporter cấu hình sai chỉ làm suy giảm khả năng quan sát, không bao giờ ảnh hưởng đến đầu ra PDF. Đừng bọc mã kết xuất trong một khối catch coi lỗi telemetry là lỗi kết xuất.
  • endSpan(null) là an toàn. startSpan() trả về null khi không có OTel, và endSpan() chấp nhận null như một no-op. Luôn dùng chúng theo cặp, và đừng bao giờ rẽ nhánh dựa trên giá trị trả về.
  • Metric cần một MeterProvider đã đăng ký. Nếu chỉ đăng ký một TracerProvider, span sẽ được xuất nhưng metric bị bỏ qua âm thầm. Các metric chỉ mang tính tham khảo. Hãy đăng ký cả hai provider để có độ bao phủ đầy đủ.
  • Sanitizer chỉ hoạt động theo danh sách cho phép. Một khóa thuộc tính mới không nằm trong danh sách cho phép sẽ không được xuất. Hành vi này là cố ý theo thiết kế. Hãy mở rộng danh sách cho phép trong engine, và đừng bỏ qua sanitizer.
  • Truyền ngữ cảnh W3C Trace Context. Việc truyền trace giữa các dịch vụ sử dụng các header W3C Trace Context traceparent/tracestate. Các propagator của OTel SDK xử lý chúng, không phải NextPDF. Khuyến nghị W3C Trace Context không nằm trong tập tài liệu kiểm chứng, nên ghi chú truyền ngữ cảnh này chưa được RAG xác nhận và được nêu như hướng dẫn tích hợp chứ không phải một tuyên bố quy phạm. Xem phần sidecar.
  • Lưu ý về khả năng tái lập. Quá trình kết xuất phát ra một tài liệu có /ID và ngày sửa đổi được tạo lại sau mỗi lần lưu (ISO 32000-2 §14.3). PDF được chụp lại sẽ được so sánh theo hồ sơ semantic, vốn chỉ bao gồm cây cú pháp trừu tượng (AST) có cấu trúc và siêu dữ liệu.
  • Đường dẫn không có OTel: isAvailable() được lưu cache sau lần gọi đầu tiên. Các lệnh gọi span và metric về sau chỉ thực hiện một phép kiểm tra boolean rồi trả về. Ví dụ có đo lường vẫn chạy đến khi hoàn tất ngay cả khi không có SDK.
  • Khi có OTel: các giới hạn của BatchSpanProcessor (maxQueueSize=2048, maxExportBatchSize=512) giới hạn bộ nhớ khi tải kéo dài, và việc xuất dữ liệu vẫn nằm ngoài đường dẫn nóng.
  • Tham số performance_budget (wall_ms: 3000, peak_mb: 128) giới hạn lần chạy của harness, chứ không phải các tài liệu tùy ý.
  • Công thức này là phần bao phủ cho mục thiếu sót §4.3 của #33. Trước đây, chỉ có trang khái niệm theo kiểu MCP tồn tại, mà không có ví dụ dành riêng cho PHP. Một examples/33-opentelemetry-observability.php mới cùng với tests/Cookbook/Php/ObserveWithOpenTelemetryRecipeTest.php hỗ trợ đã được bổ sung.
  • Telemetry không được mang theo nội dung tài liệu hay PII. Danh sách cho phép của AttributeSanitizer thực thi điều này trong mã. HTML thô, luồng PDF, dữ liệu base64 và đường dẫn tệp đều bị loại bỏ. Điều này phù hợp với hướng dẫn của NIST SP 800-92 về việc giữ nội dung nhạy cảm nằm ngoài log và telemetry, cũng như về việc bảo vệ tính bảo mật của telemetry.
  • Các thuộc tính bạn tự thêm vào vẫn phải tuân theo danh sách cho phép. Bạn vẫn chịu trách nhiệm không đưa các giá trị nhạy cảm vào dưới một khóa được phép. Ví dụ, đừng đặt định danh người dùng vào pdf.output_profile.
  • Các khóa có cấu trúc, chứ không phải dữ liệu dạng tự do, mới mang chi tiết chẩn đoán. Đây cũng chính là nguyên tắc mà PSR-3 §1.2 áp dụng cho ngữ cảnh log.
Tuyên bốĐặc tảĐiều khoảnreference_id
Telemetry không được mang theo nội dung nhạy cảm; bắt buộc xử lý PII đúng cách.NIST SP 800-92§3
Tính bảo mật của telemetry/log là một biện pháp kiểm soát rõ ràng.NIST SP 800-92§3
Các khóa ngữ cảnh có cấu trúc mới mang chi tiết, không phải dữ liệu dạng tự do.PSR-3§1.2
Đầu ra /ID và các ngày tháng được tạo lại sau mỗi lần lưu → hồ sơ semantic.ISO 32000-2§14.3

Công thức này mô tả hành vi của công cụ đo lường kỹ thuật. Nó không khẳng định bất kỳ chứng nhận tuân thủ nào. Các tham chiếu NIST SP 800-92 củng cố ý định thiết kế giữ nội dung nằm ngoài telemetry, chứ không phải một tuyên bố tuân thủ.