Enterprise edición
Medición — Referencia detallada
De un vistazo
Sección titulada «De un vistazo»El espacio de nombres NextPDF\Enterprise\Metering incorpora medición de uso a nivel de orquestación para visibilidad de facturación y auditoría. La superficie pública consta de seis símbolos: MeterCollector, MeterEntry, MeteringReporter, MeteringBackendInterface, PrometheusMeteringBackend y PrometheusPushgatewayException. El colector almacena entradas inmutables en memoria y las vacía por lotes. El reportador difunde cada lote hacia uno o varios backends con reintento y aislamiento de fallos por backend. La medición es de mejor esfuerzo y no fatal: una interrupción de un backend de medición degrada la observabilidad, nunca el procesamiento de documentos. Este flujo no es la fuente autoritativa para la aplicación de cuotas. Para la guía a nivel de flujo de trabajo, véase Medición.
Disponibilidad y licencias
Sección titulada «Disponibilidad y licencias»Esta capacidad se incorpora en NextPDF Enterprise (nextpdf/enterprise) y se activa con un sobre de licencia de nivel Enterprise. Un despliegue sin esa titularidad no carga las clases de la capacidad. Comparar ediciones y obtener una licencia.
La medición es una capacidad base de Enterprise, disponible una vez instalado el paquete Enterprise; no existe un indicador separado por característica. NextPDF Core (Apache-2.0) y NextPDF Pro no tienen colector, reportador ni superficie de backend; el contrato se incorpora únicamente en nextpdf/enterprise.
Superficie de la API pública
Sección titulada «Superficie de la API pública»| Símbolo | Parámetros | Comportamiento por defecto | Devuelve | Lanza o falla con | Notas |
|---|---|---|---|---|---|
MeterCollector::__construct | MeteringReporter $reporter, int $bufferSize = 100 | Crea un colector con un búfer en memoria vacío | Nuevo MeterCollector | No lanza | $bufferSize está documentado como positive-int |
MeterCollector::record | string $operation, int $count, string $tenantId, string $licenseId, int $pagesProcessed = 0, float $durationMs = 0.0, array $metadata = [] | Añade una MeterEntry inmutable marcada con la hora actual; se vacía automáticamente cuando el búfer alcanza $bufferSize | void | No lanza; un vaciado automático delega en el reportador, que nunca lanza | La marca temporal se toma en el momento del registro |
MeterCollector::flush | — | Entrega todas las entradas almacenadas al reportador; un búfer vacío es una operación nula | void | No lanza; los fallos de backend son absorbidos por el reportador | El búfer se intercambia antes de la entrega; seguro ante reentrada |
MeterCollector::bufferCount | — | Devuelve el número de entradas almacenadas | int<0, max> | No lanza | Diagnóstico y decisiones de contrapresión |
MeterCollector::registerShutdownFlush | — | Registra flush() mediante register_shutdown_function | void | No lanza | Llamar una vez en el arranque en despliegues PHP-FPM |
MeterEntry::__construct | string $operation, int $count, DateTimeImmutable $timestamp, string $tenantId, string $licenseId, int $pagesProcessed = 0, float $durationMs = 0.0, array $metadata = [] | Almacena los valores suministrados tal cual | Nuevo MeterEntry | Sin @throws declarado; PHP lanza TypeError ante tipos de argumento no coincidentes bajo strict_types | final readonly; las ocho propiedades promovidas son públicas |
MeteringReporter::__construct | list<MeteringBackendInterface> $backends, int $maxRetries = 2, LoggerInterface $logger = new NullLogger() | Valida y almacena la lista de backends | Nuevo MeteringReporter | InvalidArgumentException cuando $backends está vacía | $maxRetries cuenta el total de intentos de entrega por backend |
MeteringReporter::report | list<MeterEntry> $entries | Entrega el lote a cada backend de forma independiente, con reintento por backend | void | No lanza; los intentos agotados registran a nivel de error y descartan el lote de ese backend | Una lista vacía es una operación nula |
MeteringBackendInterface::report | list<MeterEntry> $entries | Entrega un lote al backend | void | RuntimeException cuando el backend es inalcanzable | Las implementaciones DEBEN ser idempotentes (deduplicar por timestamp + operation + tenantId) |
MeteringBackendInterface::isHealthy | — | Sonda de alcanzabilidad | bool | Sin @throws declarado | Solo diagnóstico; el reportador no lo usa como control de acceso |
MeteringBackendInterface::backendName | — | Nombre de backend para diagnóstico | non-empty-string | Sin @throws declarado | Por ejemplo "prometheus", "billing-api", "null" |
PrometheusMeteringBackend::__construct | ClientInterface $httpClient, RequestFactoryInterface $requestFactory, StreamFactoryInterface $streamFactory, string $pushgatewayUrl, string $jobName = 'nextpdf_metering' | Configura un destino de push de Pushgateway | Nuevo PrometheusMeteringBackend | No lanza | Se inyectan el cliente PSR-18 y las factorías PSR-17 |
PrometheusMeteringBackend::report | list<MeterEntry> $entries | Agrega el lote por serie de operación-y-tenant y hace POST del texto de exposición a <pushgatewayUrl>/metrics/job/<jobName> | void | PrometheusPushgatewayException ante un estado distinto de 2xx o un fallo de transporte PSR-18 | Una lista vacía es una operación nula |
PrometheusMeteringBackend::isHealthy | — | Sondea el endpoint de salud de Pushgateway; true solo con HTTP 200 | bool | No lanza; cualquier fallo devuelve false | Sonda GET de solo lectura |
PrometheusMeteringBackend::backendName | — | Devuelve "prometheus" | non-empty-string | No lanza | Constante |
PrometheusPushgatewayException | — | Señala una entrega de Pushgateway fallida | — | Es el lanzable | final; extiende 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 {}Propiedades públicas de solo lectura de MeterEntry
| Propiedad | Tipo | Significado |
|---|---|---|
$operation | non-empty-string | Tipo de operación, por ejemplo "parse", "compress", "embed", "rag_query" |
$count | positive-int | Número de unidades consumidas |
$timestamp | DateTimeImmutable | Cuándo ocurrió la operación; el colector la marca en el momento del registro |
$tenantId | non-empty-string | Identificador del tenant |
$licenseId | non-empty-string | Identificador de licencia |
$pagesProcessed | int<0, max> | Páginas PDF procesadas; 0 para operaciones que no son PDF |
$durationMs | float | Duración de la operación en milisegundos |
$metadata | array<string, mixed> | Metadatos de formato libre específicos de la operación |
Contrato de comportamiento
Sección titulada «Contrato de comportamiento»MeterCollector::record()construye unaMeterEntryinmutable, la marca con la hora actual y la añade al búfer en memoria. Cuando el búfer alcanza$bufferSizeentradas, el colector se vacía automáticamente.flush()es idempotente y seguro ante reentrada. Un búfer vacío es una operación nula. El búfer se intercambia antes de entregar el lote al reportador, de modo que un vaciado reentrante no puede duplicar el envío.MeteringReporterrechaza la construcción con una lista de backends vacía. EsaInvalidArgumentExceptiones la única excepción en la ruta colector/reportador.MeteringReporter::report()entrega cada lote a cada backend de forma independiente. Un backend que falla nunca impide que otro backend reciba el mismo lote.$maxRetriescuenta el total de intentos de entrega por backend; el valor por defecto de2significa un intento inicial más un reintento. Cada intento fallido registra una advertencia con el nombre del backend, el número de intento y el recuento de entradas.- Cuando el intento final para un backend falla, el reportador registra además a nivel de error con el recuento de entradas descartadas, y luego continúa. Nunca lanza desde
report(), por lo que quienes lo invocan no deben inferir la entrega a partir de un retorno normal. - Los backends DEBEN ser idempotentes. El contrato de la interfaz exige deduplicación basada en timestamp, operation y el identificador del tenant. El reportador en sí no deduplica.
PrometheusMeteringBackend::report()agrega el lote en series por operación y por tenant y hace POST de exposición de texto Prometheus a<pushgatewayUrl>/metrics/job/<jobName>con Content-Typetext/plain; version=0.0.4. El nombre de trabajo por defecto esnextpdf_metering.- La carga útil enviada lleva tres contadores —
nextpdf_operations_total,nextpdf_pages_processed_totalynextpdf_operation_duration_ms_total— cada uno etiquetado por operación y tenant. - Este flujo de medición no es autoritativo. La aplicación de cuotas y la medición autoritativa de cómputo consumen la cifra de uso autoritativa separada del despliegue, nunca este búfer. Una brecha en la medición de orquestación es una brecha de observabilidad, no una brecha de exactitud de facturación.
Casos límite y modos de fallo
Sección titulada «Casos límite y modos de fallo»- Lote duplicado o reproducido. Absorbido por la idempotencia del backend; el reportador no deduplica. No confíe en una entrega exactamente-una-vez.
- Reintentos agotados. El lote de ese backend se descarta y se registra a nivel de error. Un retorno normal de
report()oflush()nunca implica entrega. - Salida del proceso antes del vaciado. El búfer está únicamente en memoria. Un fallo, o una salida sin un manejador de apagado registrado, pierde las entradas almacenadas.
- Desajuste del modelo de workers. Los despliegues PHP-FPM llaman a
registerShutdownFlush()una vez en el arranque para que el resto se vacíe al final de la petición. Los workers de larga duración (Octane, worker de Symfony, worker de cola) deben vaciar mediante un temporizador periódico en su lugar; de lo contrario, las entradas se acumulan hasta que el proceso worker sale. $bufferSizepor debajo de1. Viola el contrato documentadopositive-int; el resultado observable es un vaciado en cada llamada arecord().- Metadatos sensibles.
$metadataes de formato libre y puede llevar contexto de operación sensible. El almacenamiento, la retención y el control de acceso son responsabilidad del operador del backend. - Fallo de entrega de Pushgateway. Una respuesta distinta de 2xx lanza
PrometheusPushgatewayExceptionque lleva el estado HTTP y el cuerpo de la respuesta; un fallo de transporte PSR-18 se envuelve en el mismo tipo de excepción. El bucle de reintento y aislamiento del reportador absorbe ambos. - Sonda de salud.
PrometheusMeteringBackend::isHealthy()emite un GET contra<pushgatewayUrl>/-/healthyy devuelvetruesolo con HTTP 200. Cualquier error de transporte devuelvefalse; la sonda nunca lanza. - Valores de etiqueta hostiles. Los caracteres de barra invertida, comilla doble y salto de línea en los valores de operación o tenant se escapan en la emisión, de modo que un valor de etiqueta no puede inyectar líneas de exposición adicionales ni corromper el bloque de etiquetas.
- Modo FIPS. El colector y el reportador no realizan operaciones criptográficas y no tienen comportamiento específico de FIPS. Un backend que firma o cifra en tránsito hereda la postura FIPS del proveedor de cifrado de su host.
Conformidad
Sección titulada «Conformidad»Ningún estándar externo rige el contrato del colector, el reportador ni el backend en proceso; no hay una especificación normativa que citar, por lo que esta página no lleva ninguna cita RAG por diseño. El backend de Prometheus emite el formato de exposición de texto de Prometheus y envía con Content-Type text/plain; version=0.0.4; ese formato es una convención del ecosistema en lugar de un estándar ISO o IETF, y la afirmación se fundamenta en la fuente del producto. NextPDF no formula ninguna declaración de conformidad ni de certificación para esta superficie.
Notas de desarrollo
Sección titulada «Notas de desarrollo»- Todas las clases declaran
strict_types=1y sonfinal;MeterEntryesfinal readonlycon propiedades públicas promovidas. Los tipos de argumento no coincidentes lanzan unTypeErrorde PHP en quien invoca. - Las clases del módulo llevan una anotación de paquete
@sincede2.1.0;PrometheusPushgatewayExceptionlleva@since3.2.0. - El logger del reportador tiene por defecto un
NullLoggerde PSR-3. Inyecte un logger real en producción, o los lotes descartados no dejarán rastro. - Pruebas unitarias: implemente un
MeteringBackendInterfacefalso y construya valoresMeterEntrydirectamente. El backend de Prometheus toma abstracciones PSR-18/PSR-17, por lo que un cliente HTTP simulado ejercita la ruta completa de push sin conexión. - Pruebas de límite recomendadas: búfer exactamente en
$bufferSize, vaciado reentrante, vaciado con búfer vacío, un backend que falla mientras un segundo tiene éxito, y registro de agotamiento de reintentos. - Quienes implementen backends lanzan
RuntimeException(o una subclase) ante un fallo de entrega; el reportador la absorbe. Respete el requisito de idempotencia antes de añadir más reintentos aguas arriba.
Límite de publicación
Sección titulada «Límite de publicación»Esta página documenta únicamente el comportamiento observable externamente y la superficie de la API pública soportada. Las rutas de espacios de nombres internos, las clases auxiliares, las tablas de mecanismos, los nombres de archivo de runbooks y los prefijos de tickets están fuera de alcance.
Véase también
Sección titulada «Véase también»- Medición — NextPDF Enterprise — la página de la capacidad: flujo de trabajo, configuración y ejemplos de despliegue trabajados.
- Facturación — Referencia detallada — niveles de plan, semántica de excedentes y la escalera de alertas.
- SaaS — Referencia detallada — la superficie de orquestación multitenant.
- Licencias — Referencia detallada — el sobre de licencia que activa las capacidades de Enterprise.