Telemetry: cầu nối OpenTelemetry và phương án dự phòng no-op
Tổng quan nhanh
Phần tiêu đề “Tổng quan nhanh”Mô-đun Telemetry là cầu nối tùy chọn giữa engine và SDK OpenTelemetry (OTel). Khi SDK được cài đặt, mô-đun phát các span và metric với thuộc tính đã được làm sạch. Khi không có SDK, một bộ đối tượng tracer và meter no-op đầy đủ giúp các lệnh gọi đo lường vẫn hợp lệ và gần như không tốn chi phí. Bạn có thể yên tâm giữ phần đo lường trong luồng mã.
Cài đặt
Phần tiêu đề “Cài đặt”composer require nextpdf/core:^3Tổng quan khái niệm
Phần tiêu đề “Tổng quan khái niệm”Mục tiêu thiết kế là cung cấp khả năng quan sát mà không phát sinh chi phí khi không có SDK. Các đường dẫn nóng của engine gọi tracer và meter mà không cần kiểm tra trước. Việc các lệnh gọi đó có thực hiện công việc hay không phụ thuộc vào môi trường chạy, chứ không dựa trên điều kiện tại từng nơi gọi.
OpenTelemetryInterceptor là cầu nối. isAvailable() cho biết SDK OTel có hiện diện hay không. startSpan(string $name, array $attributes = []) / endSpan(?object $span) bao quanh một thao tác được theo dõi, còn recordMetric() ghi lại một giá trị counter hoặc gauge. Khi không có OTel, interceptor báo không khả dụng, và các lệnh gọi trở thành no-op. TelemetryBridge kết nối interceptor với các điểm quan sát của engine.
AttributeSanitizer là lớp an toàn. sanitize(array $attributes) làm sạch bản đồ thuộc tính trước khi dữ liệu rời khỏi tiến trình. Các thuộc tính telemetry là kênh thường vô tình làm lộ thông tin nhận dạng cá nhân (PII), nên việc làm sạch là một phần của hợp đồng, không phải tính năng bổ sung. Bộ làm sạch, interceptor và cầu nối đều là @since 2.3.0.
NullTracer, NullSpanBuilder, NullSpan, NullMeter, NullCounter và NullHistogram là phương án dự phòng no-op. Chúng khớp với các dạng lệnh gọi mà SDK OTel cung cấp: spanBuilder(), setAttribute() (có thể nối chuỗi), startSpan(), end(), createHistogram(), createUpDownCounter(), add() và record(). Chúng không làm gì cả. Vì phương án dự phòng đã đầy đủ, mã được đo lường không cần rẽ nhánh theo trạng thái khả dụng; mã chỉ gọi tracer, còn no-op hấp thụ lệnh gọi đó.
Bề mặt API
Phần tiêu đề “Bề mặt API”| Lớp | Thành viên chính | Vai trò |
|---|---|---|
OpenTelemetryInterceptor | isAvailable(), startSpan(), endSpan(), recordMetric() | Cầu nối span và metric OTel (@since 2.3.0) |
TelemetryBridge | kết nối engine | Kết nối interceptor tới các điểm quan sát của engine (@since 2.3.0) |
AttributeSanitizer | sanitize(array $attributes): array | Làm sạch thuộc tính để bảo đảm an toàn PII (@since 2.3.0) |
NullTracer | spanBuilder(string $name): NullSpanBuilder | Tracer no-op |
NullSpanBuilder | setAttribute(), startSpan(): NullSpan | Span builder no-op (có thể nối chuỗi) |
NullSpan | end() | Span no-op |
NullMeter | createHistogram(), createUpDownCounter() | Meter no-op |
NullCounter / NullHistogram | add(), record() | Công cụ đo no-op |
Chạy composer docs:generate-api-php -- --module=Telemetry để tạo bảng PHPDoc đầy đủ.
Mã ví dụ — bắt đầu nhanh
Phần tiêu đề “Mã ví dụ — bắt đầu nhanh”Nguồn: 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']);Khi không có SDK OTel, mọi lệnh gọi ở trên đều là no-op. Mã vẫn giữ nguyên, và chi phí là bằng không.
Mã ví dụ — sản xuất
Phần tiêu đề “Mã ví dụ — sản xuất”Bao bọc một thao tác kết xuất bằng các thuộc tính đã được làm sạch để siêu dữ liệu do bên gọi cung cấp không thể lọt vào 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); } }}Trường hợp đặc biệt & điểm cần lưu ý
Phần tiêu đề “Trường hợp đặc biệt & điểm cần lưu ý”- Phương án dự phòng no-op được thiết kế đầy đủ. Đừng bảo vệ phần đo lường bằng
isAvailable()“để tiết kiệm công sức”. No-op vốn đã không tốn gì, còn lớp bảo vệ lại thêm đúng nhánh mà thiết kế này loại bỏ. - Luôn đưa các thuộc tính do bên gọi cung cấp qua
AttributeSanitizertrước khi bạn gắn chúng vào span hoặc metric. Các thuộc tính telemetry là một kênh có thể vô tình làm lộ PII. endSpan(null)là hợp lệ: một span null chính là trường hợp no-op. Hãy ghép mỗistartSpan()với mộtendSpan()trong một khốifinally.NullSpanBuilder::setAttribute()trả vềstaticđể nối chuỗi. Trong chế độ no-op, chuỗi này được thiết kế là vô tác dụng.- Hồ sơ khả năng tái lập là
structural: các span mang dấu thời gian và định danh trace, nên hai lần chạy sẽ khác nhau tại những trường đó.
Hiệu năng
Phần tiêu đề “Hiệu năng”Khi không có OTel, chi phí chỉ là một lệnh gọi phương thức vào no-op, gần như không tốn gì. Khi có OTel, chi phí đến từ SDK OTel; cầu nối thêm bước làm sạch thuộc tính, vốn tuyến tính theo số lượng thuộc tính. performance_budget 1500 ms wall / 64 MB đỉnh là ngân sách tham chiếu của engine, không phải thỏa thuận mức dịch vụ (SLA) cho telemetry.
Ghi chú bảo mật
Phần tiêu đề “Ghi chú bảo mật”Telemetry là bề mặt đưa dữ liệu ra ngoài. AttributeSanitizer giữ cho bí mật và PII không lọt vào các span và metric. Hãy xem việc làm sạch là bắt buộc đối với bất kỳ thuộc tính nào chịu ảnh hưởng từ bên gọi; đó là nghĩa vụ telemetry an toàn của dự án. Bộ xuất OTel gửi dữ liệu tới backend bên ngoài, và backend đó là một ranh giới tin cậy. Hãy cấu hình endpoint và thông tin xác thực của nó từ trình quản lý bí mật, không phải từ cấu hình đã commit. Hãy giả định dữ liệu span và metric sẽ đến nơi nhận nhật ký, rồi làm sạch dữ liệu cho phù hợp. Xem mô hình mối đe dọa của engine tại /modules/core/security/.
Tuân thủ
Phần tiêu đề “Tuân thủ”Mô-đun này không đưa ra tuyên bố quy chuẩn nào theo đặc tả Portable Document Format (PDF). Nó kết nối tới mô hình dữ liệu OpenTelemetry, một đặc tả khả năng quan sát bên ngoài, chứ không phải một điều khoản PDF. Phương án dự phòng no-op phản ánh bề mặt giao diện lập trình ứng dụng (API) của OpenTelemetry để mã được đo lường vẫn có tính di động. Đây là đặc tính tương thích API, không phải tuyên bố tuân thủ PDF. Tính tuân thủ của engine được kiểm chứng bằng bộ oracle và bộ golden được mô tả trong /modules/core/conformance/.
Xem thêm
Phần tiêu đề “Xem thêm”- Mô-đun Observability — bề mặt trạng thái chạy rộng hơn.
- Mô-đun Performance — công cụ chẩn đoán bộ nhớ đi kèm với telemetry.
- Contracts / Observability — các hợp đồng ngoại lệ có cấu trúc và suy giảm dịch vụ.
- Mô hình bảo mật của engine