Przejdź do głównej zawartości
getnextpdf.com

Enterprise edycja

Metering — szczegółowa referencja

Przestrzeń nazw NextPDF\Enterprise\Metering dostarcza pomiary zużycia na poziomie orchestracji dla widoczności rozliczeń oraz audytu. Powierzchnia publiczna to sześć symboli: MeterCollector, MeterEntry, MeteringReporter, MeteringBackendInterface, PrometheusMeteringBackend oraz PrometheusPushgatewayException. Kolektor buforuje niezmienne wpisy w pamięci i opróżnia je w partiach. Reporter rozsyła każdą partię do jednego lub wielu backendów z ponawianiem i izolacją niepowodzeń na poziomie pojedynczego backendu. Pomiary są best-effort i niefatalne: awaria backendu pomiarów degraduje obserwowalność, nigdy przetwarzanie dokumentów. Ten strumień nie jest autorytatywnym źródłem dla egzekwowania limitów. Przewodnik na poziomie procesu znajduje się na stronie Metering.

Ta możliwość jest dostarczana w NextPDF Enterprise (nextpdf/enterprise) i aktywuje się wraz z kopertą licencyjną poziomu Enterprise. Wdrożenie bez tego uprawnienia nie ładuje klas tej możliwości. Porównaj edycje i uzyskaj licencję.

Pomiary są podstawową możliwością Enterprise, dostępną po zainstalowaniu pakietu Enterprise; nie ma osobnej flagi dla poszczególnych funkcji. NextPDF Core (Apache-2.0) oraz NextPDF Pro nie mają powierzchni kolektora, reportera ani backendu; kontrakt jest dostarczany wyłącznie w nextpdf/enterprise.

SymbolParametryZachowanie domyślneZwracaRzuca lub zawodzi zUwagi
MeterCollector::__constructMeteringReporter $reporter, int $bufferSize = 100Tworzy kolektor z pustym buforem w pamięciNowy MeterCollectorNie rzuca$bufferSize jest udokumentowany jako positive-int
MeterCollector::recordstring $operation, int $count, string $tenantId, string $licenseId, int $pagesProcessed = 0, float $durationMs = 0.0, array $metadata = []Dołącza jeden niezmienny MeterEntry ostemplowany bieżącym czasem; opróżnia automatycznie, gdy bufor osiągnie $bufferSizevoidNie rzuca; automatyczne opróżnienie deleguje do reportera, który nigdy nie rzucaZnacznik czasu jest pobierany w momencie zapisu
MeterCollector::flushPrzekazuje wszystkie zbuforowane wpisy do reportera; pusty bufor to brak operacjivoidNie rzuca; niepowodzenia backendu są pochłaniane przez reporteraBufor jest wymieniany przed przekazaniem; bezpieczny przy ponownym wejściu
MeterCollector::bufferCountZwraca liczbę zbuforowanych wpisówint<0, max>Nie rzucaDiagnostyka i decyzje o przeciwciśnieniu
MeterCollector::registerShutdownFlushRejestruje flush() przez register_shutdown_functionvoidNie rzucaWywołaj raz podczas bootstrapu we wdrożeniach PHP-FPM
MeterEntry::__constructstring $operation, int $count, DateTimeImmutable $timestamp, string $tenantId, string $licenseId, int $pagesProcessed = 0, float $durationMs = 0.0, array $metadata = []Przechowuje dostarczone wartości dosłownieNowy MeterEntryBrak zadeklarowanego @throws; PHP zgłasza TypeError przy niezgodnych typach argumentów pod strict_typesfinal readonly; wszystkie osiem promowanych właściwości jest publicznych
MeteringReporter::__constructlist<MeteringBackendInterface> $backends, int $maxRetries = 2, LoggerInterface $logger = new NullLogger()Waliduje i przechowuje listę backendówNowy MeteringReporterInvalidArgumentException, gdy $backends jest pusta$maxRetries liczy łączną liczbę prób dostarczenia na backend
MeteringReporter::reportlist<MeterEntry> $entriesDostarcza partię do każdego backendu niezależnie, z ponawianiem na poziomie backenduvoidNie rzuca; wyczerpane próby logują na poziomie błędu i porzucają partię tego backenduPusta lista to brak operacji
MeteringBackendInterface::reportlist<MeterEntry> $entriesDostarcza partię do backenduvoidRuntimeException, gdy backend jest nieosiągalnyImplementacje MUSZĄ być idempotentne (deduplikacja według timestamp + operation + tenantId)
MeteringBackendInterface::isHealthySonda osiągalnościboolBrak zadeklarowanego @throwsWyłącznie diagnostyka; reporter nie bramkuje na jej podstawie
MeteringBackendInterface::backendNameDiagnostyczna nazwa backendunon-empty-stringBrak zadeklarowanego @throwsNa przykład "prometheus", "billing-api", "null"
PrometheusMeteringBackend::__constructClientInterface $httpClient, RequestFactoryInterface $requestFactory, StreamFactoryInterface $streamFactory, string $pushgatewayUrl, string $jobName = 'nextpdf_metering'Konfiguruje cel push PushgatewayNowy PrometheusMeteringBackendNie rzucaKlient PSR-18 oraz fabryki PSR-17 są wstrzykiwane
PrometheusMeteringBackend::reportlist<MeterEntry> $entriesAgreguje partię według serii operacja-i-najemca oraz wysyła POST-em tekst ekspozycji do <pushgatewayUrl>/metrics/job/<jobName>voidPrometheusPushgatewayException przy statusie spoza 2xx lub niepowodzeniu transportu PSR-18Pusta lista to brak operacji
PrometheusMeteringBackend::isHealthySonduje punkt końcowy kondycji Pushgateway; true tylko przy HTTP 200boolNie rzuca; każde niepowodzenie zwraca falseSonda GET tylko do odczytu
PrometheusMeteringBackend::backendNameZwraca "prometheus"non-empty-stringNie rzucaStała
PrometheusPushgatewayExceptionSygnalizuje nieudane dostarczenie do PushgatewayJest rzucanym obiektemfinal; rozszerza 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 {}

Publiczne właściwości readonly MeterEntry

WłaściwośćTypZnaczenie
$operationnon-empty-stringTyp operacji, na przykład "parse", "compress", "embed", "rag_query"
$countpositive-intLiczba zużytych jednostek
$timestampDateTimeImmutableKiedy wystąpiła operacja; kolektor stempluje go w momencie zapisu
$tenantIdnon-empty-stringIdentyfikator najemcy
$licenseIdnon-empty-stringIdentyfikator licencji
$pagesProcessedint<0, max>Przetworzone strony PDF; 0 dla operacji innych niż PDF
$durationMsfloatCzas trwania operacji w milisekundach
$metadataarray<string, mixed>Metadane dowolnej postaci specyficzne dla operacji
  • MeterCollector::record() konstruuje jeden niezmienny MeterEntry, stempluje go bieżącym czasem i dołącza do bufora w pamięci. Gdy bufor osiągnie $bufferSize wpisów, kolektor opróżnia automatycznie.
  • flush() jest idempotentne i bezpieczne przy ponownym wejściu. Pusty bufor to brak operacji. Bufor jest wymieniany, zanim partia zostanie przekazana do reportera, dzięki czemu ponowne wejście w opróżnianie nie może spowodować podwójnego wysłania.
  • MeteringReporter odrzuca konstrukcję z pustą listą backendów. Ten InvalidArgumentException jest jedynym wyjątkiem na ścieżce kolektora/reportera.
  • MeteringReporter::report() dostarcza każdą partię do każdego backendu niezależnie. Zawodzący backend nigdy nie powstrzymuje innego backendu od otrzymania tej samej partii.
  • $maxRetries liczy łączną liczbę prób dostarczenia na backend; wartość domyślna 2 oznacza jedną początkową próbę plus jedno ponowienie. Każda nieudana próba loguje ostrzeżenie z nazwą backendu, numerem próby oraz liczbą wpisów.
  • Gdy ostatnia próba dla backendu zawiedzie, reporter dodatkowo loguje na poziomie błędu z liczbą porzuconych wpisów, a następnie idzie dalej. Nigdy nie rzuca z report(), więc wywołujący nie mogą wnioskować o dostarczeniu na podstawie normalnego zwrotu.
  • Backendy MUSZĄ być idempotentne. Kontrakt interfejsu wymaga deduplikacji kluczowanej znacznikiem czasu, operacją oraz identyfikatorem najemcy. Sam reporter nie deduplikuje.
  • PrometheusMeteringBackend::report() agreguje partię w serie na operację i na najemcę oraz wysyła POST-em tekstową ekspozycję Prometheus do <pushgatewayUrl>/metrics/job/<jobName> z Content-Type text/plain; version=0.0.4. Domyślna nazwa zadania to nextpdf_metering.
  • Wysłany ładunek niesie trzy liczniki — nextpdf_operations_total, nextpdf_pages_processed_total oraz nextpdf_operation_duration_ms_total — każdy etykietowany operacją i najemcą.
  • Ten strumień pomiarów jest nieautorytatywny. Egzekwowanie limitów oraz autorytatywne pomiary obliczeń konsumują oddzielną autorytatywną liczbę zużycia wdrożenia, nigdy ten bufor. Luka w pomiarach orchestracji jest luką w obserwowalności, a nie luką w poprawności rozliczeń.
  • Zduplikowana lub odtworzona partia. Pochłaniana przez idempotencję backendu; reporter nie deduplikuje. Nie polegaj na dostarczeniu dokładnie raz.
  • Wyczerpane ponowienia. Partia tego backendu jest porzucana i logowana na poziomie błędu. Normalny zwrot z report() lub flush() nigdy nie oznacza dostarczenia.
  • Zakończenie procesu przed opróżnieniem. Bufor istnieje tylko w pamięci. Awaria lub zakończenie bez zarejestrowanej procedury obsługi zamknięcia traci zbuforowane wpisy.
  • Niedopasowanie modelu pracownika. Wdrożenia PHP-FPM wywołują registerShutdownFlush() raz podczas bootstrapu, aby pozostałość opróżniała się na końcu żądania. Długo działający pracownicy (Octane, pracownik Symfony, pracownik kolejki) muszą zamiast tego opróżniać na cyklicznym czasomierzu; w przeciwnym razie wpisy akumulują się aż do zakończenia procesu pracownika.
  • $bufferSize poniżej 1. Narusza udokumentowany kontrakt positive-int; obserwowalnym skutkiem jest opróżnienie przy każdym wywołaniu record().
  • Wrażliwe metadane. $metadata mają dowolną postać i mogą nieść wrażliwy kontekst operacji. Przechowywanie, retencja oraz kontrola dostępu należą do odpowiedzialności operatora backendu.
  • Niepowodzenie dostarczenia do Pushgateway. Odpowiedź spoza 2xx zgłasza PrometheusPushgatewayException niosący status HTTP oraz treść odpowiedzi; niepowodzenie transportu PSR-18 jest opakowane w ten sam typ wyjątku. Pętla ponawiania i izolacji reportera pochłania oba.
  • Sonda kondycji. PrometheusMeteringBackend::isHealthy() wysyła GET na <pushgatewayUrl>/-/healthy i zwraca true tylko przy HTTP 200. Każdy błąd transportu zwraca false; sonda nigdy nie rzuca.
  • Wrogie wartości etykiet. Znaki ukośnika wstecznego, cudzysłowu podwójnego oraz nowej linii w wartościach operacji lub najemcy są eskejpowane przy emisji, więc wartość etykiety nie może wstrzyknąć dodatkowych linii ekspozycji ani uszkodzić bloku etykiet.
  • Tryb FIPS. Kolektor oraz reporter nie wykonują żadnych operacji kryptograficznych i nie mają zachowania specyficznego dla FIPS. Backend, który podpisuje lub szyfruje w tranzycie, dziedziczy stanowisko FIPS swojego dostawcy kryptografii hosta.

Żaden zewnętrzny standard nie reguluje kontraktu kolektora, reportera ani backendu działającego w procesie; nie ma normatywnej specyfikacji do przywołania, więc ta strona z założenia nie niesie żadnego cytatu RAG. Backend Prometheus emituje tekstowy format ekspozycji Prometheus i wysyła z Content-Type text/plain; version=0.0.4; ten format jest konwencją ekosystemu, a nie standardem ISO ani IETF, a to stwierdzenie jest oparte na źródle produktu. NextPDF nie składa żadnego oświadczenia o zgodności ani certyfikacji dla tej powierzchni.

  • Wszystkie klasy deklarują strict_types=1 i są final; MeterEntry jest final readonly z promowanymi właściwościami publicznymi. Niezgodne typy argumentów zgłaszają PHP TypeError u wywołującego.
  • Klasy modułu niosą adnotację pakietu @since o wartości 2.1.0; PrometheusPushgatewayException niesie @since 3.2.0.
  • Logger reportera domyślnie przyjmuje PSR-3 NullLogger. Wstrzyknij prawdziwy logger w środowisku produkcyjnym, w przeciwnym razie porzucone partie nie pozostawią śladu.
  • Testy jednostkowe: zaimplementuj sztuczny MeteringBackendInterface i konstruuj wartości MeterEntry bezpośrednio. Backend Prometheus przyjmuje abstrakcje PSR-18/PSR-17, więc atrapa klienta HTTP przechodzi pełną ścieżkę push offline.
  • Zalecane testy brzegowe: bufor dokładnie przy $bufferSize, opróżnienie przy ponownym wejściu, opróżnienie pustego bufora, jeden backend zawodzi, gdy drugi się powodzi, oraz logowanie wyczerpania ponowień.
  • Implementatorzy backendów rzucają RuntimeException (lub podklasę) przy niepowodzeniu dostarczenia; reporter to pochłania. Uszanuj wymóg idempotencji przed dodaniem dalszych ponowień w górę strumienia.

Ta strona dokumentuje wyłącznie zewnętrznie obserwowalne zachowanie oraz wspieraną powierzchnię publicznego API. Wewnętrzne ścieżki przestrzeni nazw, klasy pomocnicze, tabele mechanizmów, nazwy plików runbooków oraz prefiksy zgłoszeń są poza zakresem.