Salta ai contenuti
getnextpdf.com

Enterprise edizione

Metering — Riferimento approfondito

Il namespace NextPDF\Enterprise\Metering fornisce un metering dell’utilizzo a livello di orchestrazione per la visibilità di fatturazione e l’audit. La superficie pubblica è composta da sei simboli: MeterCollector, MeterEntry, MeteringReporter, MeteringBackendInterface, PrometheusMeteringBackend e PrometheusPushgatewayException. Il collector mette in buffer in memoria voci immutabili e le sottopone a flush in batch. Il reporter distribuisce (fan-out) ciascun batch verso uno o più backend con retry per backend e isolamento dei guasti. Il metering è best-effort e non fatale: un’interruzione di un backend di metering degrada l’osservabilità, mai l’elaborazione dei documenti. Questo stream non è la sorgente autorevole per l’applicazione delle quote. Per la guida a livello di workflow, vedere Metering.

Questa capability è inclusa in NextPDF Enterprise (nextpdf/enterprise) e si attiva con un envelope di licenza di tier Enterprise. Una distribuzione priva di tale entitlement non carica le classi della capability. Confronta le edizioni e ottieni una licenza.

Il metering è una capability di base di Enterprise, disponibile una volta installato il pacchetto Enterprise; non esiste alcun flag separato per funzionalità. NextPDF Core (Apache-2.0) e NextPDF Pro non dispongono di alcuna superficie di collector, reporter o backend; il contratto è incluso esclusivamente in nextpdf/enterprise.

SimboloParametriComportamento predefinitoRestituisceSolleva o fallisce conNote
MeterCollector::__constructMeteringReporter $reporter, int $bufferSize = 100Crea un collector con un buffer in memoria vuotoNuovo MeterCollectorNon solleva eccezioni$bufferSize è documentato come positive-int
MeterCollector::recordstring $operation, int $count, string $tenantId, string $licenseId, int $pagesProcessed = 0, float $durationMs = 0.0, array $metadata = []Aggiunge una MeterEntry immutabile marcata con l’ora corrente; esegue un flush automatico quando il buffer raggiunge $bufferSizevoidNon solleva eccezioni; un flush automatico delega al reporter, che non solleva mai eccezioniIl timestamp viene rilevato al momento della registrazione
MeterCollector::flushConsegna al reporter tutte le voci in buffer; un buffer vuoto è un no-opvoidNon solleva eccezioni; i guasti dei backend vengono assorbiti dal reporterIl buffer viene scambiato (swap out) prima della consegna; sicuro in caso di rientranza
MeterCollector::bufferCountRestituisce il numero di voci in bufferint<0, max>Non solleva eccezioniDiagnostica e decisioni di back-pressure
MeterCollector::registerShutdownFlushRegistra flush() tramite register_shutdown_functionvoidNon solleva eccezioniDa chiamare una sola volta al bootstrap nelle distribuzioni PHP-FPM
MeterEntry::__constructstring $operation, int $count, DateTimeImmutable $timestamp, string $tenantId, string $licenseId, int $pagesProcessed = 0, float $durationMs = 0.0, array $metadata = []Memorizza i valori forniti così come sonoNuovo MeterEntryNessun @throws dichiarato; PHP solleva TypeError in caso di tipi di argomento non corrispondenti sotto strict_typesfinal readonly; tutte e otto le proprietà promosse sono pubbliche
MeteringReporter::__constructlist<MeteringBackendInterface> $backends, int $maxRetries = 2, LoggerInterface $logger = new NullLogger()Valida e memorizza l’elenco dei backendNuovo MeteringReporterInvalidArgumentException quando $backends è vuoto$maxRetries conta il totale dei tentativi di consegna per backend
MeteringReporter::reportlist<MeterEntry> $entriesConsegna il batch a ogni backend in modo indipendente, con retry per backendvoidNon solleva eccezioni; i tentativi esauriti vengono registrati a livello error e il batch di quel backend viene scartatoUn elenco vuoto è un no-op
MeteringBackendInterface::reportlist<MeterEntry> $entriesConsegna un batch al backendvoidRuntimeException quando il backend è irraggiungibileLe implementazioni DEVONO essere idempotenti (deduplicazione per timestamp + operation + tenantId)
MeteringBackendInterface::isHealthySonda di raggiungibilitàboolNessun @throws dichiaratoSolo per diagnostica; il reporter non vi applica alcun gate
MeteringBackendInterface::backendNameNome del backend per la diagnosticanon-empty-stringNessun @throws dichiaratoPer esempio "prometheus", "billing-api", "null"
PrometheusMeteringBackend::__constructClientInterface $httpClient, RequestFactoryInterface $requestFactory, StreamFactoryInterface $streamFactory, string $pushgatewayUrl, string $jobName = 'nextpdf_metering'Configura un target push PushgatewayNuovo PrometheusMeteringBackendNon solleva eccezioniIl client PSR-18 e le factory PSR-17 vengono iniettati
PrometheusMeteringBackend::reportlist<MeterEntry> $entriesAggrega il batch per serie operazione-e-tenant ed esegue un POST del testo di esposizione verso <pushgatewayUrl>/metrics/job/<jobName>voidPrometheusPushgatewayException in caso di status non-2xx o di guasto di trasporto PSR-18Un elenco vuoto è un no-op
PrometheusMeteringBackend::isHealthySonda l’endpoint di health del Pushgateway; true solo con HTTP 200boolNon solleva eccezioni; qualsiasi guasto restituisce falseSonda GET in sola lettura
PrometheusMeteringBackend::backendNameRestituisce "prometheus"non-empty-stringNon solleva eccezioniCostante
PrometheusPushgatewayExceptionSegnala una consegna Pushgateway fallitaÈ il throwablefinal; estende 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(): void
public 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): void
public 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 {}

Proprietà pubbliche readonly di MeterEntry

ProprietàTipoSignificato
$operationnon-empty-stringTipo di operazione, per esempio "parse", "compress", "embed", "rag_query"
$countpositive-intNumero di unità consumate
$timestampDateTimeImmutableQuando è avvenuta l’operazione; il collector la marca al momento della registrazione
$tenantIdnon-empty-stringIdentificatore del tenant
$licenseIdnon-empty-stringIdentificatore della licenza
$pagesProcessedint<0, max>Pagine PDF elaborate; 0 per operazioni non-PDF
$durationMsfloatDurata dell’operazione in millisecondi
$metadataarray<string, mixed>Metadati specifici dell’operazione in formato libero
  • MeterCollector::record() costruisce una MeterEntry immutabile, la marca con l’ora corrente e la aggiunge al buffer in memoria. Quando il buffer raggiunge $bufferSize voci, il collector esegue un flush automatico.
  • flush() è idempotente e sicuro in caso di rientranza. Un buffer vuoto è un no-op. Il buffer viene scambiato (swap out) prima che il batch sia consegnato al reporter, così che un flush rientrante non possa causare un doppio invio.
  • MeteringReporter rifiuta la costruzione con un elenco di backend vuoto. Quella InvalidArgumentException è l’unica eccezione sul percorso collector/reporter.
  • MeteringReporter::report() consegna ciascun batch a ogni backend in modo indipendente. Un backend in errore non impedisce mai a un altro backend di ricevere lo stesso batch.
  • $maxRetries conta il totale dei tentativi di consegna per backend; il valore predefinito 2 significa un tentativo iniziale più un retry. Ogni tentativo fallito registra un warning con il nome del backend, il numero del tentativo e il conteggio delle voci.
  • Quando l’ultimo tentativo per un backend fallisce, il reporter registra inoltre a livello error con il conteggio delle voci scartate, poi prosegue. Non solleva mai eccezioni da report(), quindi i chiamanti non devono dedurre la consegna da un ritorno normale.
  • I backend DEVONO essere idempotenti. Il contratto dell’interfaccia richiede una deduplicazione basata su timestamp, operazione e identificatore del tenant. Il reporter stesso non deduplica.
  • PrometheusMeteringBackend::report() aggrega il batch in serie per operazione e per tenant ed esegue un POST dell’esposizione testuale Prometheus verso <pushgatewayUrl>/metrics/job/<jobName> con Content-Type text/plain; version=0.0.4. Il nome del job predefinito è nextpdf_metering.
  • Il payload inviato trasporta tre counter — nextpdf_operations_total, nextpdf_pages_processed_total e nextpdf_operation_duration_ms_total — ciascuno etichettato per operazione e tenant.
  • Questo stream di metering non è autorevole. L’applicazione delle quote e il metering autorevole del compute consumano la cifra di utilizzo autorevole separata della distribuzione, mai questo buffer. Una lacuna nel metering di orchestrazione è una lacuna di osservabilità, non una lacuna di correttezza della fatturazione.
  • Batch duplicato o riprodotto (replayed). Assorbito dall’idempotenza del backend; il reporter non deduplica. Non fare affidamento su una consegna exactly-once.
  • Retry esauriti. Il batch di quel backend viene scartato e registrato a livello error. Un ritorno normale da report() o flush() non implica mai la consegna.
  • Uscita del processo prima del flush. Il buffer è solo in memoria. Un crash, o un’uscita senza uno shutdown handler registrato, perde le voci in buffer.
  • Disallineamento del modello di worker. Le distribuzioni PHP-FPM chiamano registerShutdownFlush() una sola volta al bootstrap, così che il resto venga sottoposto a flush alla fine della richiesta. I worker a lunga esecuzione (Octane, worker Symfony, queue worker) devono invece eseguire il flush su un timer periodico; altrimenti le voci si accumulano finché il processo worker non termina.
  • $bufferSize inferiore a 1. Viola il contratto documentato positive-int; il risultato osservabile è un flush a ogni chiamata record().
  • Metadati sensibili. $metadata è in formato libero e può trasportare contesto operativo sensibile. Storage, conservazione e controllo degli accessi sono responsabilità dell’operatore del backend.
  • Guasto di consegna Pushgateway. Una risposta non-2xx solleva PrometheusPushgatewayException che trasporta lo status HTTP e il corpo della risposta; un guasto di trasporto PSR-18 viene incapsulato nello stesso tipo di eccezione. Il ciclo di retry e isolamento del reporter assorbe entrambi.
  • Sonda di health. PrometheusMeteringBackend::isHealthy() esegue una GET verso <pushgatewayUrl>/-/healthy e restituisce true solo con HTTP 200. Qualsiasi errore di trasporto restituisce false; la sonda non solleva mai eccezioni.
  • Valori di label ostili. I caratteri backslash, doppio apice e line-feed nei valori di operazione o tenant vengono sottoposti a escape al momento dell’emissione, così che un valore di label non possa iniettare righe di esposizione aggiuntive né corrompere il blocco delle label.
  • Modalità FIPS. Il collector e il reporter non eseguono alcuna operazione crittografica e non hanno alcun comportamento specifico per FIPS. Un backend che firma o cifra in transito eredita la postura FIPS del provider crittografico del proprio host.

Nessuno standard esterno governa il contratto in-process del collector, del reporter o del backend; non esiste alcuna specifica normativa da citare, quindi questa pagina non riporta alcuna citazione RAG, per progettazione. Il backend Prometheus emette il formato di esposizione testuale Prometheus ed esegue il push con Content-Type text/plain; version=0.0.4; tale formato è una convenzione dell’ecosistema piuttosto che uno standard ISO o IETF, e l’affermazione è fondata sul codice sorgente del prodotto. NextPDF non avanza alcuna dichiarazione di conformità o certificazione per questa superficie.

  • Tutte le classi dichiarano strict_types=1 e sono final; MeterEntry è final readonly con proprietà pubbliche promosse. Tipi di argomento non corrispondenti sollevano un TypeError PHP nel chiamante.
  • Le classi del modulo riportano un’annotazione di pacchetto @since pari a 2.1.0; PrometheusPushgatewayException riporta @since 3.2.0.
  • Il logger del reporter è per impostazione predefinita un NullLogger PSR-3. Iniettare un logger reale in produzione, altrimenti i batch scartati non lasciano alcuna traccia.
  • Test unitari: implementare un fake di MeteringBackendInterface e costruire direttamente i valori MeterEntry. Il backend Prometheus accetta astrazioni PSR-18/PSR-17, quindi un client HTTP mock esercita l’intero percorso di push offline.
  • Test di confine consigliati: buffer esattamente a $bufferSize, flush rientrante, flush con buffer vuoto, un backend che fallisce mentre un secondo ha successo, e logging di esaurimento dei retry.
  • Chi implementa un backend solleva RuntimeException (o una sottoclasse) in caso di guasto di consegna; il reporter la assorbe. Rispettare il requisito di idempotenza prima di aggiungere ulteriori retry a monte.

Questa pagina documenta esclusivamente il comportamento osservabile dall’esterno e la superficie dell’API pubblica supportata. I percorsi di namespace interni, le classi helper, le tabelle dei meccanismi, i nomi di file dei runbook e i prefissi dei ticket sono fuori ambito.