Enterprise edisi
Metering — Referensi Mendalam
Sekilas pandang
Bagian berjudul “Sekilas pandang”Namespace NextPDF\Enterprise\Metering menyediakan metering penggunaan tingkat orkestrasi untuk visibilitas penagihan dan audit. Permukaan publiknya terdiri dari enam simbol: MeterCollector, MeterEntry, MeteringReporter, MeteringBackendInterface, PrometheusMeteringBackend, dan PrometheusPushgatewayException. Collector menyangga entri imutabel di memori dan mem-flush-nya dalam batch. Reporter menyebarkan setiap batch ke satu atau lebih backend dengan retry per-backend dan isolasi kegagalan. Metering bersifat best-effort dan non-fatal: pemadaman metering-backend menurunkan observability, tidak pernah pemrosesan dokumen. Aliran ini bukan sumber otoritatif untuk penegakan kuota. Untuk panduan tingkat workflow, lihat Metering.
Ketersediaan & lisensi
Bagian berjudul “Ketersediaan & lisensi”Kapabilitas ini dikirimkan dalam NextPDF Enterprise (nextpdf/enterprise) dan aktif dengan envelope lisensi tier Enterprise. Deployment tanpa entitlement tersebut tidak memuat kelas-kelas kapabilitas ini. Bandingkan edisi dan dapatkan lisensi.
Metering adalah kapabilitas dasar Enterprise, tersedia begitu paket Enterprise terpasang; tidak ada flag per-fitur terpisah. NextPDF Core (Apache-2.0) dan NextPDF Pro tidak memiliki permukaan collector, reporter, atau backend; kontraknya hanya dikirimkan dalam nextpdf/enterprise.
Permukaan API publik
Bagian berjudul “Permukaan API publik”| Simbol | Parameter | Perilaku default | Mengembalikan | Melempar atau gagal dengan | Catatan |
|---|---|---|---|---|---|
MeterCollector::__construct | MeteringReporter $reporter, int $bufferSize = 100 | Membuat collector dengan buffer in-memory kosong | MeterCollector baru | Tidak melempar | $bufferSize didokumentasikan positive-int |
MeterCollector::record | string $operation, int $count, string $tenantId, string $licenseId, int $pagesProcessed = 0, float $durationMs = 0.0, array $metadata = [] | Menambahkan satu MeterEntry imutabel yang distempel dengan waktu saat ini; auto-flush ketika buffer mencapai $bufferSize | void | Tidak melempar; auto-flush mendelegasikan ke reporter, yang tidak pernah melempar | Timestamp diambil pada waktu record |
MeterCollector::flush | — | Menyerahkan seluruh entri tersangga ke reporter; buffer kosong adalah no-op | void | Tidak melempar; kegagalan backend diserap oleh reporter | Buffer ditukar keluar sebelum diserahkan; aman re-entrant |
MeterCollector::bufferCount | — | Mengembalikan jumlah entri tersangga | int<0, max> | Tidak melempar | Untuk keputusan diagnostik dan back-pressure |
MeterCollector::registerShutdownFlush | — | Mendaftarkan flush() melalui register_shutdown_function | void | Tidak melempar | Panggil sekali saat bootstrap pada deployment PHP-FPM |
MeterEntry::__construct | string $operation, int $count, DateTimeImmutable $timestamp, string $tenantId, string $licenseId, int $pagesProcessed = 0, float $durationMs = 0.0, array $metadata = [] | Menyimpan nilai yang diberikan apa adanya | MeterEntry baru | Tidak ada @throws yang dideklarasikan; PHP memunculkan TypeError pada tipe argumen yang tidak cocok di bawah strict_types | final readonly; kedelapan properti terpromosi bersifat public |
MeteringReporter::__construct | list<MeteringBackendInterface> $backends, int $maxRetries = 2, LoggerInterface $logger = new NullLogger() | Memvalidasi dan menyimpan daftar backend | MeteringReporter baru | InvalidArgumentException ketika $backends kosong | $maxRetries menghitung total percobaan pengiriman per backend |
MeteringReporter::report | list<MeterEntry> $entries | Mengirim batch ke setiap backend secara independen, dengan retry per-backend | void | Tidak melempar; percobaan yang habis dicatat di level error dan batch backend tersebut di-drop | Daftar kosong adalah no-op |
MeteringBackendInterface::report | list<MeterEntry> $entries | Mengirim batch ke backend | void | RuntimeException ketika backend tidak dapat dijangkau | Implementasi HARUS idempoten (dedupe berdasarkan timestamp + operation + tenantId) |
MeteringBackendInterface::isHealthy | — | Probe keterjangkauan | bool | Tidak ada @throws yang dideklarasikan | Hanya diagnostik; reporter tidak bergantung padanya |
MeteringBackendInterface::backendName | — | Nama backend diagnostik | non-empty-string | Tidak ada @throws yang dideklarasikan | Misalnya "prometheus", "billing-api", "null" |
PrometheusMeteringBackend::__construct | ClientInterface $httpClient, RequestFactoryInterface $requestFactory, StreamFactoryInterface $streamFactory, string $pushgatewayUrl, string $jobName = 'nextpdf_metering' | Mengonfigurasi target push Pushgateway | PrometheusMeteringBackend baru | Tidak melempar | Klien PSR-18 dan factory PSR-17 di-inject |
PrometheusMeteringBackend::report | list<MeterEntry> $entries | Mengagregasi batch berdasarkan seri operation-dan-tenant dan mem-POST teks eksposisi ke <pushgatewayUrl>/metrics/job/<jobName> | void | PrometheusPushgatewayException pada status non-2xx atau kegagalan transport PSR-18 | Daftar kosong adalah no-op |
PrometheusMeteringBackend::isHealthy | — | Menguji endpoint health Pushgateway; true hanya pada HTTP 200 | bool | Tidak melempar; setiap kegagalan mengembalikan false | Probe GET read-only |
PrometheusMeteringBackend::backendName | — | Mengembalikan "prometheus" | non-empty-string | Tidak melempar | Konstanta |
PrometheusPushgatewayException | — | Menandakan pengiriman Pushgateway yang gagal | — | Adalah throwable-nya | final; memperluas RuntimeException |
public function __construct( private readonly MeteringReporter $reporter, private readonly int $bufferSize = 100,) {}
public function record( string $operation, int $count, string $tenantId, string $licenseId, int $pagesProcessed = 0, float $durationMs = 0.0, array $metadata = [],): void
public function flush(): void
public function bufferCount(): int
public function registerShutdownFlush(): voidpublic function __construct( public string $operation, public int $count, public DateTimeImmutable $timestamp, public string $tenantId, public string $licenseId, public int $pagesProcessed = 0, public float $durationMs = 0.0, public array $metadata = [],) {}public function report(array $entries): void;
public function isHealthy(): bool;
public function backendName(): string;public function __construct( array $backends, private readonly int $maxRetries = 2, private readonly LoggerInterface $logger = new NullLogger(),)
public function report(array $entries): voidpublic function __construct( private readonly ClientInterface $httpClient, private readonly RequestFactoryInterface $requestFactory, private readonly StreamFactoryInterface $streamFactory, private readonly string $pushgatewayUrl, private readonly string $jobName = self::DEFAULT_JOB_NAME,) {}final class PrometheusPushgatewayException extends RuntimeException {}Properti public readonly MeterEntry
| Properti | Tipe | Makna |
|---|---|---|
$operation | non-empty-string | Jenis operasi, misalnya "parse", "compress", "embed", "rag_query" |
$count | positive-int | Jumlah unit yang dikonsumsi |
$timestamp | DateTimeImmutable | Kapan operasi terjadi; collector menstempelnya pada waktu record |
$tenantId | non-empty-string | Pengenal tenant |
$licenseId | non-empty-string | Pengenal lisensi |
$pagesProcessed | int<0, max> | Halaman PDF yang diproses; 0 untuk operasi non-PDF |
$durationMs | float | Durasi operasi dalam milidetik |
$metadata | array<string, mixed> | Metadata spesifik-operasi berbentuk bebas |
Kontrak perilaku
Bagian berjudul “Kontrak perilaku”MeterCollector::record()membangun satuMeterEntryimutabel, menstempelnya dengan waktu saat ini, dan menambahkannya ke buffer in-memory. Ketika buffer mencapai$bufferSizeentri, collector melakukan auto-flush.flush()bersifat idempoten dan aman re-entrant. Buffer kosong adalah no-op. Buffer ditukar keluar sebelum batch diserahkan ke reporter, sehingga flush re-entrant tidak dapat mengirim ganda.MeteringReportermenolak konstruksi dengan daftar backend kosong.InvalidArgumentExceptiontersebut adalah satu-satunya eksepsi pada jalur collector/reporter.MeteringReporter::report()mengirim setiap batch ke setiap backend secara independen. Backend yang gagal tidak pernah mencegah backend lain menerima batch yang sama.$maxRetriesmenghitung total percobaan pengiriman per backend; default2berarti satu percobaan awal ditambah satu retry. Setiap percobaan yang gagal mencatat peringatan dengan nama backend, nomor percobaan, dan jumlah entri.- Ketika percobaan terakhir untuk suatu backend gagal, reporter tambahan mencatat di level error dengan jumlah entri yang di-drop, lalu melanjutkan. Ia tidak pernah melempar dari
report(), jadi pemanggil tidak boleh menyimpulkan pengiriman dari return normal. - Backend HARUS idempoten. Kontrak interface mengharuskan deduplikasi berkunci pada timestamp, operation, dan pengenal tenant. Reporter sendiri tidak melakukan deduplikasi.
PrometheusMeteringBackend::report()mengagregasi batch ke dalam seri per-operation, per-tenant dan mem-POST teks eksposisi Prometheus ke<pushgatewayUrl>/metrics/job/<jobName>dengan Content-Typetext/plain; version=0.0.4. Nama job default adalahnextpdf_metering.- Payload yang di-push membawa tiga counter —
nextpdf_operations_total,nextpdf_pages_processed_total, dannextpdf_operation_duration_ms_total— masing-masing diberi label berdasarkan operation dan tenant. - Aliran metering ini non-otoritatif. Penegakan kuota dan metering komputasi otoritatif mengonsumsi angka penggunaan otoritatif deployment yang terpisah, tidak pernah buffer ini. Celah dalam metering orkestrasi adalah celah observability, bukan celah kebenaran penagihan.
Kasus tepi & mode kegagalan
Bagian berjudul “Kasus tepi & mode kegagalan”- Batch terduplikasi atau ter-replay. Diserap oleh idempotensi backend; reporter tidak melakukan deduplikasi. Jangan mengandalkan pengiriman exactly-once.
- Retry yang habis. Batch untuk backend tersebut di-drop dan dicatat di level error. Return normal dari
report()atauflush()tidak pernah menyiratkan pengiriman. - Proses keluar sebelum flush. Buffer hanya di memori. Sebuah crash, atau keluar tanpa handler shutdown terdaftar, kehilangan entri tersangga.
- Ketidakcocokan model worker. Deployment PHP-FPM memanggil
registerShutdownFlush()sekali saat bootstrap sehingga sisanya di-flush di akhir request. Worker berjalan-lama (Octane, Symfony worker, queue worker) harus mem-flush pada timer periodik; jika tidak, entri menumpuk sampai proses worker keluar. $bufferSizedi bawah1. Melanggar kontrakpositive-intyang didokumentasikan; hasil yang teramati adalah flush pada setiap panggilanrecord().- Metadata sensitif.
$metadataberbentuk bebas dan dapat membawa konteks operasi sensitif. Penyimpanan, retensi, dan kontrol akses adalah tanggung jawab operator backend. - Kegagalan pengiriman Pushgateway. Respons non-2xx memunculkan
PrometheusPushgatewayExceptionyang membawa status HTTP dan body respons; kegagalan transport PSR-18 dibungkus dalam tipe eksepsi yang sama. Loop retry-dan-isolasi reporter menyerap keduanya. - Probe health.
PrometheusMeteringBackend::isHealthy()mengeluarkan GET terhadap<pushgatewayUrl>/-/healthydan mengembalikantruehanya pada HTTP 200. Setiap error transport mengembalikanfalse; probe tidak pernah melempar. - Nilai label yang berbahaya. Karakter backslash, tanda kutip ganda, dan line-feed dalam nilai operation atau tenant di-escape saat emisi, sehingga sebuah nilai label tidak dapat menyisipkan baris eksposisi tambahan atau merusak blok label.
- Mode FIPS. Collector dan reporter tidak melakukan operasi kriptografis dan tidak memiliki perilaku spesifik-FIPS. Backend yang menandatangani atau mengenkripsi saat transit mewarisi postur FIPS penyedia crypto host-nya.
Konformansi
Bagian berjudul “Konformansi”Tidak ada standar eksternal yang mengatur kontrak collector, reporter, atau backend in-process; tidak ada spesifikasi normatif untuk dikutip, sehingga halaman ini tidak membawa kutipan RAG secara desain. Backend Prometheus memancarkan format teks eksposisi Prometheus dan mem-push dengan Content-Type text/plain; version=0.0.4; format tersebut adalah konvensi ekosistem, bukan standar ISO atau IETF, dan klaimnya didasarkan pada sumber produk. NextPDF tidak membuat klaim konformansi atau sertifikasi untuk permukaan ini.
Catatan pengembangan
Bagian berjudul “Catatan pengembangan”- Semua kelas mendeklarasikan
strict_types=1dan bersifatfinal;MeterEntryadalahfinal readonlydengan properti public terpromosi. Tipe argumen yang tidak cocok memunculkanTypeErrorPHP di pemanggil. - Kelas-kelas modul membawa anotasi paket
@since2.1.0;PrometheusPushgatewayExceptionmembawa@since3.2.0. - Logger reporter default ke
NullLoggerPSR-3. Inject logger nyata di produksi, atau batch yang di-drop tidak meninggalkan jejak. - Unit testing: implementasikan
MeteringBackendInterfacepalsu dan konstruksi nilaiMeterEntrysecara langsung. Backend Prometheus mengambil abstraksi PSR-18/PSR-17, sehingga klien HTTP mock menjalankan seluruh jalur push secara offline. - Uji batas yang direkomendasikan: buffer tepat pada
$bufferSize, flush re-entrant, flush buffer kosong, satu backend gagal sementara backend kedua berhasil, dan pencatatan retry-exhaustion. - Pengimplementasi backend melempar
RuntimeException(atau subkelasnya) pada kegagalan pengiriman; reporter menyerapnya. Hormati persyaratan idempotensi sebelum menambahkan retry lebih lanjut di hulu.
Batas publikasi
Bagian berjudul “Batas publikasi”Halaman ini hanya mendokumentasikan perilaku yang teramati secara eksternal dan permukaan API publik yang didukung. Jalur namespace internal, kelas helper, tabel mekanisme, nama file runbook, dan prefiks tiket berada di luar cakupan.
Lihat juga
Bagian berjudul “Lihat juga”- Metering — NextPDF Enterprise — halaman kapabilitas: workflow, konfigurasi, dan contoh deployment yang dikerjakan.
- Billing — Referensi Mendalam — tier paket, semantik overage, dan tangga alert.
- SaaS — Referensi Mendalam — permukaan orkestrasi multi-tenant.
- Licensing — Referensi Mendalam — envelope lisensi yang mengaktifkan kapabilitas Enterprise.