Enterprise edição
Metering — Referência Profunda
Visão geral
Seção intitulada “Visão geral”O namespace NextPDF\Enterprise\Metering distribui medição de uso no nível de orquestração para visibilidade de cobrança e auditoria. A superfície pública é de seis símbolos: MeterCollector, MeterEntry, MeteringReporter, MeteringBackendInterface, PrometheusMeteringBackend e PrometheusPushgatewayException. O coletor faz buffer de entradas imutáveis na memória e as descarrega em lotes. O reporter distribui cada lote para um ou mais backends com retentativa por backend e isolamento de falhas. A medição é de melhor esforço e não fatal: uma indisponibilidade de backend de medição degrada a observabilidade, nunca o processamento de documentos. Este fluxo não é a fonte autoritativa para a imposição de cota. Para o guia no nível de fluxo de trabalho, consulte Metering.
Disponibilidade e licenciamento
Seção intitulada “Disponibilidade e licenciamento”Este recurso é distribuído no NextPDF Enterprise (nextpdf/enterprise) e é ativado com um envelope de licença de nível Enterprise. Uma implantação sem essa habilitação não carrega as classes do recurso. Compare edições e obtenha uma licença.
A medição é um recurso base do Enterprise, disponível assim que o pacote Enterprise é instalado; não há um sinalizador separado por recurso. NextPDF Core (Apache-2.0) e NextPDF Pro não têm superfície de coletor, reporter ou backend; o contrato é distribuído apenas em nextpdf/enterprise.
Superfície da API pública
Seção intitulada “Superfície da API pública”| Símbolo | Parâmetros | Comportamento padrão | Retorna | Lança ou falha com | Notas |
|---|---|---|---|---|---|
MeterCollector::__construct | MeteringReporter $reporter, int $bufferSize = 100 | Cria um coletor com um buffer em memória vazio | Novo MeterCollector | Não lança exceção | $bufferSize é documentado como positive-int |
MeterCollector::record | string $operation, int $count, string $tenantId, string $licenseId, int $pagesProcessed = 0, float $durationMs = 0.0, array $metadata = [] | Anexa um MeterEntry imutável carimbado com a hora atual; faz flush automático quando o buffer atinge $bufferSize | void | Não lança exceção; um flush automático delega ao reporter, que nunca lança exceção | O timestamp é obtido no momento do registro |
MeterCollector::flush | — | Entrega todas as entradas em buffer ao reporter; um buffer vazio é um no-op | void | Não lança exceção; falhas de backend são absorvidas pelo reporter | O buffer é trocado antes da entrega; seguro para reentrância |
MeterCollector::bufferCount | — | Retorna o número de entradas em buffer | int<0, max> | Não lança exceção | Diagnósticos e decisões de contrapressão (back-pressure) |
MeterCollector::registerShutdownFlush | — | Registra flush() por meio de register_shutdown_function | void | Não lança exceção | Chame uma vez no bootstrap em implantações PHP-FPM |
MeterEntry::__construct | string $operation, int $count, DateTimeImmutable $timestamp, string $tenantId, string $licenseId, int $pagesProcessed = 0, float $durationMs = 0.0, array $metadata = [] | Armazena os valores fornecidos literalmente | Novo MeterEntry | Sem @throws declarado; o PHP levanta TypeError em tipos de argumento incompatíveis sob strict_types | final readonly; todas as oito propriedades promovidas são públicas |
MeteringReporter::__construct | list<MeteringBackendInterface> $backends, int $maxRetries = 2, LoggerInterface $logger = new NullLogger() | Valida e armazena a lista de backends | Novo MeteringReporter | InvalidArgumentException quando $backends está vazio | $maxRetries conta o total de tentativas de entrega por backend |
MeteringReporter::report | list<MeterEntry> $entries | Entrega o lote a cada backend de forma independente, com retentativa por backend | void | Não lança exceção; tentativas esgotadas são registradas em nível de erro e o lote daquele backend é descartado | Uma lista vazia é um no-op |
MeteringBackendInterface::report | list<MeterEntry> $entries | Entrega um lote ao backend | void | RuntimeException quando o backend está inacessível | As implementações DEVEM ser idempotentes (dedupe por timestamp + operation + tenantId) |
MeteringBackendInterface::isHealthy | — | Sonda de acessibilidade | bool | Sem @throws declarado | Apenas diagnósticos; o reporter não depende dela |
MeteringBackendInterface::backendName | — | Nome de backend para diagnóstico | non-empty-string | Sem @throws declarado | Por exemplo "prometheus", "billing-api", "null" |
PrometheusMeteringBackend::__construct | ClientInterface $httpClient, RequestFactoryInterface $requestFactory, StreamFactoryInterface $streamFactory, string $pushgatewayUrl, string $jobName = 'nextpdf_metering' | Configura um alvo de push do Pushgateway | Novo PrometheusMeteringBackend | Não lança exceção | O cliente PSR-18 e as factories PSR-17 são injetados |
PrometheusMeteringBackend::report | list<MeterEntry> $entries | Agrega o lote por série de operação-e-tenant e faz POST do texto de exposição para <pushgatewayUrl>/metrics/job/<jobName> | void | PrometheusPushgatewayException em um status não-2xx ou uma falha de transporte PSR-18 | Uma lista vazia é um no-op |
PrometheusMeteringBackend::isHealthy | — | Sonda o endpoint de saúde do Pushgateway; true apenas em HTTP 200 | bool | Não lança exceção; qualquer falha retorna false | Sonda GET somente leitura |
PrometheusMeteringBackend::backendName | — | Retorna "prometheus" | non-empty-string | Não lança exceção | Constante |
PrometheusPushgatewayException | — | Sinaliza uma entrega do Pushgateway com falha | — | É o throwable | final; 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(): 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 {}Propriedades públicas readonly de MeterEntry
| Propriedade | Tipo | Significado |
|---|---|---|
$operation | non-empty-string | Tipo de operação, por exemplo "parse", "compress", "embed", "rag_query" |
$count | positive-int | Número de unidades consumidas |
$timestamp | DateTimeImmutable | Quando a operação ocorreu; o coletor a carimba no momento do registro |
$tenantId | non-empty-string | Identificador do tenant |
$licenseId | non-empty-string | Identificador da licença |
$pagesProcessed | int<0, max> | Páginas PDF processadas; 0 para operações não-PDF |
$durationMs | float | Duração da operação em milissegundos |
$metadata | array<string, mixed> | Metadados específicos da operação, de formato livre |
Contrato de comportamento
Seção intitulada “Contrato de comportamento”MeterCollector::record()constrói umMeterEntryimutável, carimba-o com a hora atual e o anexa ao buffer em memória. Quando o buffer atinge$bufferSizeentradas, o coletor faz flush automático.flush()é idempotente e seguro para reentrância. Um buffer vazio é um no-op. O buffer é trocado antes que o lote seja entregue ao reporter, de modo que um flush reentrante não possa enviar em duplicidade.MeteringReporterrejeita a construção com uma lista de backends vazia. EssaInvalidArgumentExceptioné a única exceção no caminho do coletor/reporter.MeteringReporter::report()entrega cada lote a todos os backends de forma independente. Um backend com falha nunca impede que outro backend receba o mesmo lote.$maxRetriesconta o total de tentativas de entrega por backend; o padrão de2significa uma tentativa inicial mais uma retentativa. Cada tentativa com falha registra um aviso com o nome do backend, o número da tentativa e a contagem de entradas.- Quando a tentativa final de um backend falha, o reporter adicionalmente registra em nível de erro com a contagem de entradas descartadas e então segue adiante. Ele nunca lança exceção a partir de
report(), então os chamadores não devem inferir a entrega a partir de um retorno normal. - Os backends DEVEM ser idempotentes. O contrato da interface exige deduplicação com chave em timestamp, operação e identificador do tenant. O próprio reporter não deduplica.
PrometheusMeteringBackend::report()agrega o lote em séries por operação e por tenant e faz POST da exposição de texto do Prometheus para<pushgatewayUrl>/metrics/job/<jobName>com Content-Typetext/plain; version=0.0.4. O nome de job padrão énextpdf_metering.- O payload enviado carrega três counters —
nextpdf_operations_total,nextpdf_pages_processed_totalenextpdf_operation_duration_ms_total— cada um rotulado por operação e tenant. - Este fluxo de medição não é autoritativo. A imposição de cota e a medição autoritativa de computação consomem o número de uso autoritativo separado da implantação, nunca este buffer. Uma lacuna na medição de orquestração é uma lacuna de observabilidade, não uma lacuna de correção de cobrança.
Casos extremos e modos de falha
Seção intitulada “Casos extremos e modos de falha”- Lote duplicado ou reenviado. Absorvido pela idempotência do backend; o reporter não deduplica. Não confie em entrega exatamente-uma-vez.
- Retentativas esgotadas. O lote daquele backend é descartado e registrado em nível de erro. Um retorno normal de
report()ouflush()nunca implica entrega. - Encerramento do processo antes do flush. O buffer é apenas em memória. Um crash, ou um encerramento sem um handler de shutdown registrado, perde as entradas em buffer.
- Incompatibilidade de modelo de worker. Implantações PHP-FPM chamam
registerShutdownFlush()uma vez no bootstrap para que o restante seja descarregado no fim da requisição. Workers de longa duração (Octane, worker do Symfony, worker de fila) devem, em vez disso, fazer flush em um temporizador periódico; caso contrário, as entradas se acumulam até o processo do worker encerrar. $bufferSizeabaixo de1. Viola o contrato documentadopositive-int; o resultado observável é um flush a cada chamada derecord().- Metadados sensíveis.
$metadatatem formato livre e pode carregar contexto operacional sensível. Armazenamento, retenção e controle de acesso são responsabilidade do operador do backend. - Falha de entrega do Pushgateway. Uma resposta não-2xx levanta
PrometheusPushgatewayExceptioncarregando o status HTTP e o corpo da resposta; uma falha de transporte PSR-18 é encapsulada no mesmo tipo de exceção. O laço de retentativa e isolamento do reporter absorve ambos. - Sonda de saúde.
PrometheusMeteringBackend::isHealthy()emite um GET contra<pushgatewayUrl>/-/healthye retornatrueapenas em HTTP 200. Qualquer erro de transporte retornafalse; a sonda nunca lança exceção. - Valores de rótulo hostis. Caracteres de barra invertida, aspas duplas e quebra de linha em valores de operação ou tenant são escapados na emissão, de modo que um valor de rótulo não possa injetar linhas de exposição adicionais nem corromper o bloco de rótulos.
- Modo FIPS. O coletor e o reporter não realizam nenhuma operação criptográfica e não têm comportamento específico de FIPS. Um backend que assina ou criptografa em trânsito herda a postura FIPS do provedor de criptografia do seu host.
Conformidade
Seção intitulada “Conformidade”Nenhum padrão externo rege o contrato em processo do coletor, do reporter ou do backend; não há especificação normativa a citar, então esta página não carrega nenhuma citação RAG, por design. O backend Prometheus emite o formato de exposição de texto do Prometheus e faz push com Content-Type text/plain; version=0.0.4; esse formato é uma convenção do ecossistema, e não um padrão ISO ou IETF, e a afirmação está fundamentada no código-fonte do produto. A NextPDF não faz nenhuma afirmação de conformidade ou certificação para esta superfície.
Notas de desenvolvimento
Seção intitulada “Notas de desenvolvimento”- Todas as classes declaram
strict_types=1e sãofinal;MeterEntryéfinal readonlycom propriedades públicas promovidas. Tipos de argumento incompatíveis levantam umTypeErrordo PHP no chamador. - As classes do módulo carregam uma anotação de pacote
@sincede2.1.0;PrometheusPushgatewayExceptioncarrega@since3.2.0. - O logger do reporter usa por padrão um
NullLoggerPSR-3. Injete um logger real em produção, ou os lotes descartados não deixam rastro. - Teste unitário: implemente um fake
MeteringBackendInterfacee construa valoresMeterEntrydiretamente. O backend Prometheus recebe abstrações PSR-18/PSR-17, então um cliente HTTP mock exercita todo o caminho de push offline. - Testes de limite recomendados: buffer exatamente em
$bufferSize, flush reentrante, flush de buffer vazio, um backend falhando enquanto um segundo tem sucesso e registro de esgotamento de retentativas. - Os implementadores de backend lançam
RuntimeException(ou uma subclasse) em falha de entrega; o reporter a absorve. Respeite o requisito de idempotência antes de adicionar mais retentativas upstream.
Limite de publicação
Seção intitulada “Limite de publicação”Esta página documenta apenas o comportamento observável externamente e a superfície de API pública suportada. Caminhos de namespace internos, classes auxiliares, tabelas de mecanismo, nomes de arquivo de runbook e prefixos de tíquete estão fora do escopo.
Veja também
Seção intitulada “Veja também”- Metering — NextPDF Enterprise — a página do recurso: fluxo de trabalho, configuração e exemplos práticos de implantação.
- Billing — Referência Profunda — níveis de plano, semântica de excedente e a escala de alertas.
- SaaS — Referência aprofundada — a superfície de orquestração multi-tenant.
- Licensing — Referência Profunda — o envelope de licença que ativa os recursos do Enterprise.