Enterprise editie
Metering — Diepe referentie
In één oogopslag
Sectie met titel “In één oogopslag”De NextPDF\Enterprise\Metering-namespace levert usage-metering op orchestratieniveau voor billing-zichtbaarheid en audit. Het publieke oppervlak bestaat uit zes symbolen: MeterCollector, MeterEntry, MeteringReporter, MeteringBackendInterface, PrometheusMeteringBackend, en PrometheusPushgatewayException. De collector buffert onveranderlijke entries in het geheugen en flusht ze in batches. De reporter verspreidt elke batch naar een of meer backends met retry en failure-isolatie per backend. Metering is best-effort en niet-fataal: een uitval van een metering-backend degradeert de waarneembaarheid, nooit de documentverwerking. Deze stream is niet de gezaghebbende bron voor quota-handhaving. Zie voor de gids op workflow-niveau Metering.
Beschikbaarheid en licentie
Sectie met titel “Beschikbaarheid en licentie”Deze capaciteit wordt meegeleverd in NextPDF Enterprise (nextpdf/enterprise) en activeert met een licentie-envelope op Enterprise-niveau. Een deployment zonder dat recht laadt de klassen van de capaciteit niet. Vergelijk edities en vraag een licentie aan.
Metering is een basis-Enterprise-capaciteit die beschikbaar is zodra het Enterprise-pakket is geïnstalleerd; er is geen afzonderlijke flag per functie. NextPDF Core (Apache-2.0) en NextPDF Pro hebben geen collector-, reporter- of backend-oppervlak; het contract wordt alleen meegeleverd in nextpdf/enterprise.
Publiek API-oppervlak
Sectie met titel “Publiek API-oppervlak”| Symbool | Parameters | Standaardgedrag | Retourneert | Gooit of faalt met | Notities |
|---|---|---|---|---|---|
MeterCollector::__construct | MeteringReporter $reporter, int $bufferSize = 100 | Maakt een collector met een lege in-memory buffer | Nieuwe MeterCollector | Gooit niet | $bufferSize is gedocumenteerd als positive-int |
MeterCollector::record | string $operation, int $count, string $tenantId, string $licenseId, int $pagesProcessed = 0, float $durationMs = 0.0, array $metadata = [] | Voegt één onveranderlijke MeterEntry toe, gestempeld met de huidige tijd; flusht automatisch wanneer de buffer $bufferSize bereikt | void | Gooit niet; een auto-flush delegeert naar de reporter, die nooit gooit | Timestamp wordt genomen op het moment van record |
MeterCollector::flush | — | Draagt alle gebufferde entries over aan de reporter; lege buffer is een no-op | void | Gooit niet; backend-fouten worden geabsorbeerd door de reporter | Buffer wordt verwisseld vóór de overdracht; re-entrant veilig |
MeterCollector::bufferCount | — | Retourneert het aantal gebufferde entries | int<0, max> | Gooit niet | Diagnostiek en back-pressure-beslissingen |
MeterCollector::registerShutdownFlush | — | Registreert flush() via register_shutdown_function | void | Gooit niet | Roep één keer aan bij de bootstrap in PHP-FPM-deployments |
MeterEntry::__construct | string $operation, int $count, DateTimeImmutable $timestamp, string $tenantId, string $licenseId, int $pagesProcessed = 0, float $durationMs = 0.0, array $metadata = [] | Slaat de opgegeven waarden letterlijk op | Nieuwe MeterEntry | Geen gedeclareerde @throws; PHP werpt TypeError bij niet-overeenkomende argumenttypen onder strict_types | final readonly; alle acht gepromoveerde properties zijn public |
MeteringReporter::__construct | list<MeteringBackendInterface> $backends, int $maxRetries = 2, LoggerInterface $logger = new NullLogger() | Valideert en bewaart de backend-lijst | Nieuwe MeteringReporter | InvalidArgumentException wanneer $backends leeg is | $maxRetries telt het totale aantal leverpogingen per backend |
MeteringReporter::report | list<MeterEntry> $entries | Levert de batch onafhankelijk aan elke backend, met retry per backend | void | Gooit niet; uitgeputte pogingen loggen op error-niveau en droppen de batch van die backend | Lege lijst is een no-op |
MeteringBackendInterface::report | list<MeterEntry> $entries | Levert een batch aan de backend | void | RuntimeException wanneer de backend onbereikbaar is | Implementaties MOETEN idempotent zijn (dedupe op timestamp + operation + tenantId) |
MeteringBackendInterface::isHealthy | — | Bereikbaarheidsprobe | bool | Geen gedeclareerde @throws | Alleen diagnostiek; de reporter gatet er niet op |
MeteringBackendInterface::backendName | — | Diagnostische backend-naam | non-empty-string | Geen gedeclareerde @throws | Bijvoorbeeld "prometheus", "billing-api", "null" |
PrometheusMeteringBackend::__construct | ClientInterface $httpClient, RequestFactoryInterface $requestFactory, StreamFactoryInterface $streamFactory, string $pushgatewayUrl, string $jobName = 'nextpdf_metering' | Configureert een Pushgateway-push-target | Nieuwe PrometheusMeteringBackend | Gooit niet | PSR-18-client en PSR-17-factories worden geïnjecteerd |
PrometheusMeteringBackend::report | list<MeterEntry> $entries | Aggregeert de batch per operation-en-tenant-serie en POST’t expositietekst naar <pushgatewayUrl>/metrics/job/<jobName> | void | PrometheusPushgatewayException bij een niet-2xx-status of een PSR-18-transportfout | Lege lijst is een no-op |
PrometheusMeteringBackend::isHealthy | — | Probeert het Pushgateway-health-endpoint; true alleen bij HTTP 200 | bool | Gooit niet; elke fout retourneert false | Read-only GET-probe |
PrometheusMeteringBackend::backendName | — | Retourneert "prometheus" | non-empty-string | Gooit niet | Constant |
PrometheusPushgatewayException | — | Signaleert een mislukte Pushgateway-levering | — | Is de throwable | final; extends 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 {}Publieke readonly properties van MeterEntry
| Property | Type | Betekenis |
|---|---|---|
$operation | non-empty-string | Operatietype, bijvoorbeeld "parse", "compress", "embed", "rag_query" |
$count | positive-int | Aantal verbruikte units |
$timestamp | DateTimeImmutable | Wanneer de operatie plaatsvond; de collector stempelt het op het moment van record |
$tenantId | non-empty-string | Tenant-identifier |
$licenseId | non-empty-string | Licentie-identifier |
$pagesProcessed | int<0, max> | Verwerkte PDF-pagina’s; 0 voor niet-PDF-operaties |
$durationMs | float | Operatieduur in milliseconden |
$metadata | array<string, mixed> | Vormvrije operatiespecifieke metadata |
Gedragscontract
Sectie met titel “Gedragscontract”MeterCollector::record()construeert één onveranderlijkeMeterEntry, stempelt deze met de huidige tijd, en voegt deze toe aan de in-memory buffer. Wanneer de buffer$bufferSizeentries bereikt, flusht de collector automatisch.flush()is idempotent en re-entrant veilig. Een lege buffer is een no-op. De buffer wordt verwisseld voordat de batch aan de reporter wordt overgedragen, zodat een re-entrante flush niet dubbel kan verzenden.MeteringReporterweigert constructie met een lege backend-lijst. DieInvalidArgumentExceptionis de enige exceptie op het collector-/reporter-pad.MeteringReporter::report()levert elke batch onafhankelijk aan elke backend. Een falende backend verhindert nooit dat een andere backend dezelfde batch ontvangt.$maxRetriestelt het totale aantal leverpogingen per backend; de standaard van2betekent één initiële poging plus één retry. Elke mislukte poging logt een waarschuwing met de backend-naam, het pogingnummer en het aantal entries.- Wanneer de laatste poging voor een backend faalt, logt de reporter aanvullend op error-niveau met het aantal gedropte entries en gaat dan verder. Deze gooit nooit vanuit
report(), dus aanroepers mogen levering niet afleiden uit een normale retour. - Backends MOETEN idempotent zijn. Het interfacecontract vereist deduplicatie op basis van timestamp, operation en tenant-identifier. De reporter zelf dedupliceert niet.
PrometheusMeteringBackend::report()aggregeert de batch in series per operatie en per tenant en POST’t Prometheus-tekstexpositie naar<pushgatewayUrl>/metrics/job/<jobName>met Content-Typetext/plain; version=0.0.4. De standaard job-naam isnextpdf_metering.- De gepushte payload draagt drie counters —
nextpdf_operations_total,nextpdf_pages_processed_totalennextpdf_operation_duration_ms_total— elk gelabeld per operatie en tenant. - Deze meteringstream is niet-gezaghebbend. Quota-handhaving en gezaghebbende compute-metering consumeren het afzonderlijke gezaghebbende gebruikscijfer van de deployment, nooit deze buffer. Een gat in de orchestratiemetering is een waarneembaarheidsgat, geen billing-correctheidsgat.
Randgevallen en foutmodi
Sectie met titel “Randgevallen en foutmodi”- Gedupliceerde of opnieuw afgespeelde batch. Geabsorbeerd door backend-idempotentie; de reporter dedupliceert niet. Vertrouw niet op exactly-once-levering.
- Uitgeputte retries. De batch voor die backend wordt gedropt en gelogd op error-niveau. Een normale retour van
report()offlush()impliceert nooit levering. - Procesafsluiting vóór flush. De buffer is alleen in het geheugen. Een crash, of een afsluiting zonder geregistreerde shutdown-handler, verliest de gebufferde entries.
- Worker-model-mismatch. PHP-FPM-deployments roepen
registerShutdownFlush()één keer aan bij de bootstrap, zodat de rest flusht aan het einde van de request. Langlopende workers (Octane, Symfony worker, queue worker) moeten in plaats daarvan flushen op een periodieke timer; anders accumuleren entries totdat het worker-proces afsluit. $bufferSizeonder1. Schendt het gedocumenteerdepositive-int-contract; het waarneembare resultaat is een flush bij elkerecord()-aanroep.- Gevoelige metadata.
$metadatais vormvrij en kan gevoelige operatiecontext dragen. Opslag, bewaring en toegangscontrole zijn de verantwoordelijkheid van de backend-operator. - Pushgateway-leveringsfout. Een niet-2xx-respons werpt
PrometheusPushgatewayExceptionmet de HTTP-status en de responsbody; een PSR-18-transportfout wordt in hetzelfde exceptietype verpakt. De retry-en-isolatielus van de reporter absorbeert beide. - Health-probe.
PrometheusMeteringBackend::isHealthy()doet een GET tegen<pushgatewayUrl>/-/healthyen retourneerttruealleen bij HTTP 200. Elke transportfout retourneertfalse; de probe gooit nooit. - Vijandige labelwaarden. Backslash-, dubbele-aanhalingsteken- en line-feed-tekens in operation- of tenant-waarden worden bij emissie geëscaped, zodat een labelwaarde geen extra expositieregels kan injecteren of het labelblok kan corrumperen.
- FIPS-modus. De collector en de reporter voeren geen cryptografische bewerkingen uit en hebben geen FIPS-specifiek gedrag. Een backend die in transit ondertekent of versleutelt erft de FIPS-positie van zijn host-crypto-provider.
Conformiteit
Sectie met titel “Conformiteit”Geen externe standaard beheerst het in-process collector-, reporter- of backend-contract; er is geen normatieve specificatie om te citeren, dus deze pagina draagt by design geen RAG-citatie. De Prometheus-backend zendt het Prometheus-tekstexpositieformaat uit en pusht met Content-Type text/plain; version=0.0.4; dat formaat is een ecosysteemconventie in plaats van een ISO- of IETF-standaard, en de claim is gegrond in de productbron. NextPDF doet geen conformiteits- of certificeringsclaim voor dit oppervlak.
Ontwikkelnotities
Sectie met titel “Ontwikkelnotities”- Alle klassen declareren
strict_types=1en zijnfinal;MeterEntryisfinal readonlymet gepromoveerde public properties. Niet-overeenkomende argumenttypen werpen een PHPTypeErrorin de aanroeper. - De moduleklassen dragen een pakket-
@since-annotatie van2.1.0;PrometheusPushgatewayExceptiondraagt@since3.2.0. - De logger van de reporter valt standaard terug op een PSR-3
NullLogger. Injecteer een echte logger in productie, anders laten gedropte batches geen spoor na. - Unit-testen: implementeer een nep-
MeteringBackendInterfaceen construeerMeterEntry-waarden direct. De Prometheus-backend neemt PSR-18/PSR-17-abstracties, dus een mock-HTTP-client oefent het volledige push-pad offline uit. - Aanbevolen grenstests: buffer exact op
$bufferSize, re-entrante flush, flush van lege buffer, één backend die faalt terwijl een tweede slaagt, en logging bij retry-uitputting. - Backend-implementeerders werpen
RuntimeException(of een subklasse) bij een leveringsfout; de reporter absorbeert deze. Respecteer de idempotentie-eis voordat je verder stroomopwaarts retries toevoegt.
Publicatiegrens
Sectie met titel “Publicatiegrens”Deze pagina documenteert alleen extern waarneembaar gedrag en het ondersteunde publieke API-oppervlak. Interne namespace-paden, helperklassen, mechanismetabellen, runbook-bestandsnamen en ticketprefixen vallen buiten de scope.
Zie ook
Sectie met titel “Zie ook”- Metering — NextPDF Enterprise — de capaciteitspagina: workflow, configuratie en uitgewerkte deployment-voorbeelden.
- Billing — Diepe referentie — plan-tiers, overage-semantiek en de alert-ladder.
- SaaS — Diepe referentie — het multi-tenant-orchestratie-oppervlak.
- Licensing — Diepe referentie — de licentie-envelope die Enterprise-capaciteiten activeert.