Enterprise รุ่น
Metering — เอกสารอ้างอิงเชิงลึก
ภาพรวมโดยย่อ
หัวข้อที่มีชื่อว่า “ภาพรวมโดยย่อ”เนมสเปซ NextPDF\Enterprise\Metering จัดส่งการวัดปริมาณการใช้งานระดับการประสานงานเพื่อ visibility ด้านการเรียกเก็บเงินและการตรวจสอบ พื้นผิวสาธารณะมีหกสัญลักษณ์ ได้แก่ MeterCollector, MeterEntry, MeteringReporter, MeteringBackendInterface, PrometheusMeteringBackend และ PrometheusPushgatewayException ตัวเก็บรวบรวมบัฟเฟอร์ entries แบบ immutable ไว้ในหน่วยความจำและ flush เป็นชุด reporter กระจายแต่ละชุดออกไปยัง backend หนึ่งตัวหรือมากกว่า พร้อม retry ต่อ backend และการแยกความล้มเหลว Metering เป็นแบบ best-effort และไม่ร้ายแรง การขัดข้องของ metering-backend ลดทอน observability ไม่เคยลดทอนการประมวลผลเอกสาร stream นี้ไม่ใช่แหล่งที่เป็นทางการสำหรับการบังคับใช้โควตา สำหรับคู่มือระดับเวิร์กโฟลว์ ดู Metering
ความพร้อมใช้งานและการให้สิทธิ์
หัวข้อที่มีชื่อว่า “ความพร้อมใช้งานและการให้สิทธิ์”ความสามารถนี้จัดส่งใน NextPDF Enterprise (nextpdf/enterprise) และเปิดใช้งานด้วย license envelope ระดับ Enterprise การนำไปใช้งานที่ไม่มีสิทธิ์ดังกล่าวจะไม่โหลดคลาสของความสามารถนี้ เปรียบเทียบรุ่นและรับ license
Metering เป็นความสามารถพื้นฐานของ Enterprise ที่พร้อมใช้งานเมื่อแพ็กเกจ Enterprise ถูกติดตั้ง ไม่มีแฟล็กต่อฟีเจอร์แยกต่างหาก NextPDF Core (Apache-2.0) และ NextPDF Pro ไม่มีพื้นผิว collector, reporter หรือ backend สัญญานี้จัดส่งใน nextpdf/enterprise เท่านั้น
พื้นผิว API สาธารณะ
หัวข้อที่มีชื่อว่า “พื้นผิว API สาธารณะ”| สัญลักษณ์ | พารามิเตอร์ | พฤติกรรมเริ่มต้น | คืนค่า | throw หรือ ล้มเหลวด้วย | หมายเหตุ |
|---|---|---|---|---|---|
MeterCollector::__construct | MeteringReporter $reporter, int $bufferSize = 100 | สร้างตัวเก็บรวบรวมพร้อมบัฟเฟอร์ในหน่วยความจำที่ว่างเปล่า | MeterCollector ตัวใหม่ | ไม่ throw | $bufferSize มีเอกสารระบุเป็น positive-int |
MeterCollector::record | string $operation, int $count, string $tenantId, string $licenseId, int $pagesProcessed = 0, float $durationMs = 0.0, array $metadata = [] | ต่อท้าย MeterEntry แบบ immutable หนึ่งรายการที่ประทับเวลาปัจจุบัน flush อัตโนมัติเมื่อบัฟเฟอร์ถึง $bufferSize | void | ไม่ throw การ flush อัตโนมัติมอบหมายให้ reporter ซึ่งไม่เคย throw | ประทับ timestamp ณ เวลาที่บันทึก |
MeterCollector::flush | — | ส่งมอบ entries ที่บัฟเฟอร์ไว้ทั้งหมดให้ reporter บัฟเฟอร์ว่างเปล่าเป็น no-op | void | ไม่ throw ความล้มเหลวของ backend ถูกดูดซับโดย reporter | บัฟเฟอร์ถูกสลับออกก่อนส่งมอบ ปลอดภัยแบบ re-entrant |
MeterCollector::bufferCount | — | คืนค่าจำนวน entries ที่บัฟเฟอร์ไว้ | int<0, max> | ไม่ throw | การวินิจฉัยและการตัดสินใจ back-pressure |
MeterCollector::registerShutdownFlush | — | ลงทะเบียน flush() ผ่าน register_shutdown_function | void | ไม่ throw | เรียกครั้งเดียวที่ bootstrap ในการนำไปใช้งานแบบ PHP-FPM |
MeterEntry::__construct | string $operation, int $count, DateTimeImmutable $timestamp, string $tenantId, string $licenseId, int $pagesProcessed = 0, float $durationMs = 0.0, array $metadata = [] | จัดเก็บค่าที่ให้มาตามเดิม | MeterEntry ตัวใหม่ | ไม่มี @throws ที่ประกาศไว้ PHP จะยก TypeError เมื่อชนิดอาร์กิวเมนต์ไม่ตรงกันภายใต้ strict_types | final readonly พรอเพอร์ตี้ที่ promote ทั้งแปดตัวเป็น public |
MeteringReporter::__construct | list<MeteringBackendInterface> $backends, int $maxRetries = 2, LoggerInterface $logger = new NullLogger() | ตรวจสอบและจัดเก็บรายการ backend | MeteringReporter ตัวใหม่ | InvalidArgumentException เมื่อ $backends ว่างเปล่า | $maxRetries นับจำนวนครั้งการส่งมอบทั้งหมดต่อ backend |
MeteringReporter::report | list<MeterEntry> $entries | ส่งมอบชุดข้อมูลให้ทุก backend อย่างเป็นอิสระ พร้อม retry ต่อ backend | void | ไม่ throw ความพยายามที่หมดลงบันทึกที่ระดับ error และทิ้งชุดข้อมูลของ backend นั้น | รายการว่างเปล่าเป็น no-op |
MeteringBackendInterface::report | list<MeterEntry> $entries | ส่งมอบชุดข้อมูลให้ backend | void | RuntimeException เมื่อ backend เข้าถึงไม่ได้ | การนำไปใช้งานต้องเป็น idempotent (dedupe ด้วย timestamp + operation + tenantId) |
MeteringBackendInterface::isHealthy | — | probe การเข้าถึงได้ | bool | ไม่มี @throws ที่ประกาศไว้ | สำหรับการวินิจฉัยเท่านั้น reporter ไม่ใช้เป็นเกต |
MeteringBackendInterface::backendName | — | ชื่อ backend สำหรับการวินิจฉัย | non-empty-string | ไม่มี @throws ที่ประกาศไว้ | ตัวอย่างเช่น "prometheus", "billing-api", "null" |
PrometheusMeteringBackend::__construct | ClientInterface $httpClient, RequestFactoryInterface $requestFactory, StreamFactoryInterface $streamFactory, string $pushgatewayUrl, string $jobName = 'nextpdf_metering' | กำหนดค่าเป้าหมาย push ของ Pushgateway | PrometheusMeteringBackend ตัวใหม่ | ไม่ throw | client PSR-18 และ factory PSR-17 ถูกฉีดเข้ามา |
PrometheusMeteringBackend::report | list<MeterEntry> $entries | รวมชุดข้อมูลตาม series ของ operation และ tenant และ POST ข้อความ exposition ไปยัง <pushgatewayUrl>/metrics/job/<jobName> | void | PrometheusPushgatewayException เมื่อสถานะไม่ใช่ 2xx หรือความล้มเหลวการขนส่ง PSR-18 | รายการว่างเปล่าเป็น no-op |
PrometheusMeteringBackend::isHealthy | — | probe endpoint สุขภาพของ Pushgateway คืนค่า true เฉพาะเมื่อ HTTP 200 | bool | ไม่ throw ความล้มเหลวใด ๆ คืนค่า false | probe GET แบบอ่านอย่างเดียว |
PrometheusMeteringBackend::backendName | — | คืนค่า "prometheus" | non-empty-string | ไม่ throw | ค่าคงที่ |
PrometheusPushgatewayException | — | ส่งสัญญาณการส่งมอบ Pushgateway ที่ล้มเหลว | — | เป็น throwable | final สืบทอดจาก 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 {}พรอเพอร์ตี้ public readonly ของ MeterEntry
| พรอเพอร์ตี้ | ชนิด | ความหมาย |
|---|---|---|
$operation | non-empty-string | ชนิดของ operation ตัวอย่างเช่น "parse", "compress", "embed", "rag_query" |
$count | positive-int | จำนวนหน่วยที่ใช้ไป |
$timestamp | DateTimeImmutable | เวลาที่ operation เกิดขึ้น ตัวเก็บรวบรวมประทับ ณ เวลาที่บันทึก |
$tenantId | non-empty-string | ตัวระบุ tenant |
$licenseId | non-empty-string | ตัวระบุ license |
$pagesProcessed | int<0, max> | หน้า PDF ที่ประมวลผล 0 สำหรับ operation ที่ไม่ใช่ PDF |
$durationMs | float | ระยะเวลา operation เป็นมิลลิวินาที |
$metadata | array<string, mixed> | metadata เฉพาะ operation แบบ free-form |
สัญญาพฤติกรรม
หัวข้อที่มีชื่อว่า “สัญญาพฤติกรรม”MeterCollector::record()สร้างMeterEntryแบบ immutable หนึ่งรายการ ประทับเวลาปัจจุบัน และต่อท้ายลงในบัฟเฟอร์ในหน่วยความจำ เมื่อบัฟเฟอร์ถึง$bufferSizeentries ตัวเก็บรวบรวมจะ flush อัตโนมัติflush()เป็น idempotent และปลอดภัยแบบ re-entrant บัฟเฟอร์ว่างเปล่าเป็น no-op บัฟเฟอร์ถูกสลับออกก่อนที่ชุดข้อมูลจะถูกส่งมอบให้ reporter ดังนั้นการ flush แบบ re-entrant จึงไม่สามารถส่งซ้ำMeteringReporterปฏิเสธการสร้างด้วยรายการ backend ที่ว่างเปล่าInvalidArgumentExceptionนั้นเป็น exception เดียวบนเส้นทาง collector/reporterMeteringReporter::report()ส่งมอบแต่ละชุดข้อมูลให้ทุก backend อย่างเป็นอิสระ backend ที่ล้มเหลวจะไม่ขัดขวาง backend อื่นไม่ให้รับชุดข้อมูลเดียวกัน$maxRetriesนับจำนวนครั้งการส่งมอบทั้งหมดต่อ backend ค่าเริ่มต้น2หมายถึงหนึ่งความพยายามแรกบวกกับหนึ่ง retry ทุกความพยายามที่ล้มเหลวบันทึก warning พร้อมชื่อ backend หมายเลขความพยายาม และจำนวน entry- เมื่อความพยายามสุดท้ายสำหรับ backend หนึ่งล้มเหลว reporter บันทึกเพิ่มเติมที่ระดับ error พร้อมจำนวน entry ที่ถูกทิ้ง แล้วดำเนินต่อไป มันไม่เคย throw จาก
report()ดังนั้นผู้เรียกต้องไม่อนุมานการส่งมอบจากการคืนค่าปกติ - backend ต้องเป็น idempotent สัญญาของอินเทอร์เฟซกำหนดให้มี deduplication ที่ใช้คีย์เป็น timestamp, operation และตัวระบุ tenant ตัว reporter เองไม่ทำ deduplication
PrometheusMeteringBackend::report()รวมชุดข้อมูลเป็น series ต่อ operation ต่อ tenant และ POST ข้อความ exposition ของ Prometheus ไปยัง<pushgatewayUrl>/metrics/job/<jobName>ด้วย Content-Typetext/plain; version=0.0.4ชื่อ job เริ่มต้นคือnextpdf_metering- payload ที่ push ถือ counter สามตัว —
nextpdf_operations_total,nextpdf_pages_processed_totalและnextpdf_operation_duration_ms_total— แต่ละตัวติดป้ายด้วย operation และ tenant - stream การ metering นี้ไม่เป็นทางการ การบังคับใช้โควตาและการ metering การประมวลผลที่เป็นทางการใช้ตัวเลขการใช้ที่เป็นทางการแยกต่างหากของการนำไปใช้งาน ไม่เคยใช้บัฟเฟอร์นี้ ช่องว่างใน metering การประสานงานคือช่องว่างด้าน observability ไม่ใช่ช่องว่างด้านความถูกต้องของการเรียกเก็บเงิน
กรณีขอบและโหมดความล้มเหลว
หัวข้อที่มีชื่อว่า “กรณีขอบและโหมดความล้มเหลว”- ชุดข้อมูลที่ซ้ำซ้อนหรือถูก replay ถูกดูดซับโดย idempotency ของ backend ตัว reporter ไม่ทำ deduplication อย่าพึ่งพาการส่งมอบแบบ exactly-once
- retry ที่หมดลง ชุดข้อมูลของ backend นั้นถูกทิ้งและบันทึกที่ระดับ error การคืนค่าปกติจาก
report()หรือflush()ไม่เคยหมายความว่ามีการส่งมอบ - process ออกก่อน flush บัฟเฟอร์อยู่ในหน่วยความจำเท่านั้น การ crash หรือการออกโดยไม่มี shutdown handler ที่ลงทะเบียนไว้จะสูญเสีย entries ที่บัฟเฟอร์ไว้
- worker-model ไม่ตรงกัน การนำไปใช้งานแบบ PHP-FPM เรียก
registerShutdownFlush()ครั้งเดียวที่ bootstrap เพื่อให้ส่วนที่เหลือ flush ที่ปลายคำขอ worker ที่ทำงานยาวนาน (Octane, Symfony worker, queue worker) ต้อง flush ด้วย timer เป็นระยะแทน มิฉะนั้น entries จะสะสมจนกระทั่ง worker process ออก $bufferSizeต่ำกว่า1ละเมิดสัญญาpositive-intที่ระบุไว้ ผลลัพธ์ที่สังเกตได้คือการ flush ในทุกการเรียกrecord()- metadata ที่อ่อนไหว
$metadataเป็น free-form และอาจถือบริบทการดำเนินการที่อ่อนไหว การจัดเก็บ การเก็บรักษา และการควบคุมการเข้าถึงเป็นความรับผิดชอบของผู้ปฏิบัติการ backend - ความล้มเหลวการส่งมอบ Pushgateway การตอบสนองที่ไม่ใช่ 2xx ยก
PrometheusPushgatewayExceptionที่ถือสถานะ HTTP และเนื้อหาการตอบสนอง ความล้มเหลวการขนส่ง PSR-18 ถูกห่อไว้ในชนิด exception เดียวกัน ลูป retry-and-isolation ของ reporter ดูดซับทั้งสองอย่าง - health probe
PrometheusMeteringBackend::isHealthy()ออก GET ไปยัง<pushgatewayUrl>/-/healthyและคืนค่าtrueเฉพาะเมื่อ HTTP 200 ข้อผิดพลาดการขนส่งใด ๆ คืนค่าfalseprobe ไม่เคย throw - ค่า label ที่เป็นภัย อักขระ backslash, double-quote และ line-feed ในค่า operation หรือ tenant ถูก escape ตอน emit ดังนั้นค่า label จึงไม่สามารถแทรกบรรทัด exposition เพิ่มเติมหรือทำให้บล็อก label เสียหาย
- FIPS-mode ตัวเก็บรวบรวมและ reporter ไม่ทำการดำเนินการเชิงการเข้ารหัสลับและไม่มีพฤติกรรมเฉพาะ FIPS backend ที่ลงลายเซ็นหรือเข้ารหัสระหว่างส่งจะสืบทอด FIPS posture ของ host crypto provider ของมัน
ความสอดคล้อง
หัวข้อที่มีชื่อว่า “ความสอดคล้อง”ไม่มีมาตรฐานภายนอกใดกำกับสัญญาของ collector, reporter หรือ backend ในกระบวนการ ไม่มีข้อกำหนดเชิงบรรทัดฐานให้อ้างอิง ดังนั้นหน้านี้จึงไม่ถือการอ้างอิง RAG โดยการออกแบบ backend ของ Prometheus emit รูปแบบ Prometheus text exposition และ push ด้วย Content-Type text/plain; version=0.0.4 รูปแบบดังกล่าวเป็นแบบแผนของ ecosystem มากกว่าจะเป็นมาตรฐาน ISO หรือ IETF และคำกล่าวอ้างนี้อ้างอิงจากซอร์สของผลิตภัณฑ์ NextPDF ไม่กล่าวอ้างความสอดคล้องหรือการรับรองใด ๆ สำหรับพื้นผิวนี้
หมายเหตุการพัฒนา
หัวข้อที่มีชื่อว่า “หมายเหตุการพัฒนา”- คลาสทั้งหมดประกาศ
strict_types=1และเป็นfinalMeterEntryเป็นfinal readonlyพร้อมพรอเพอร์ตี้ public ที่ promote ชนิดอาร์กิวเมนต์ที่ไม่ตรงกันยก PHPTypeErrorในผู้เรียก - คลาสของโมดูลถือ annotation
@sinceของแพ็กเกจเป็น2.1.0PrometheusPushgatewayExceptionถือ@since3.2.0 - logger ของ reporter มีค่าเริ่มต้นเป็น
NullLoggerของ PSR-3 ฉีด logger จริงในการใช้งานจริง มิฉะนั้นชุดข้อมูลที่ถูกทิ้งจะไม่ทิ้งร่องรอย - การทดสอบหน่วย: นำ
MeteringBackendInterfaceปลอมไปใช้และสร้างค่าMeterEntryโดยตรง backend ของ Prometheus รับ abstraction PSR-18/PSR-17 ดังนั้น mock HTTP client จึงรันเส้นทาง push เต็มรูปแบบแบบออฟไลน์ - การทดสอบขอบเขตที่แนะนำ: บัฟเฟอร์พอดีที่
$bufferSize, การ flush แบบ re-entrant, การ flush บัฟเฟอร์ว่างเปล่า, backend หนึ่งล้มเหลวขณะที่ตัวที่สองสำเร็จ และการบันทึกการหมด retry - ผู้นำ backend ไปใช้ throw
RuntimeException(หรือคลาสย่อย) เมื่อการส่งมอบล้มเหลว reporter ดูดซับมัน ปฏิบัติตามข้อกำหนด idempotency ก่อนเพิ่ม retry เพิ่มเติมที่ต้นทาง
ขอบเขตการเผยแพร่
หัวข้อที่มีชื่อว่า “ขอบเขตการเผยแพร่”หน้านี้บันทึกเฉพาะพฤติกรรมที่สังเกตได้จากภายนอกและพื้นผิว public API ที่รองรับเท่านั้น internal namespace paths, helper classes, ตารางกลไก, ชื่อไฟล์ runbook และ ticket prefixes อยู่นอกขอบเขต
ดูเพิ่มเติม
หัวข้อที่มีชื่อว่า “ดูเพิ่มเติม”- Metering — NextPDF Enterprise — หน้าความสามารถ: เวิร์กโฟลว์ การกำหนดค่า และตัวอย่างการนำไปใช้งานจริง
- Billing — เอกสารอ้างอิงเชิงลึก — ระดับแผน ความหมายของการใช้เกิน และบันไดการแจ้งเตือน
- SaaS — เอกสารอ้างอิงเชิงลึก — พื้นผิวการประสานงานแบบ multi-tenant
- Licensing — เอกสารอ้างอิงเชิงลึก — license envelope ที่เปิดใช้งานความสามารถ Enterprise