콘텐츠로 이동
getnextpdf.com

Enterprise 에디션

미터링 — 심층 참조

NextPDF\Enterprise\Metering 네임스페이스는 청구 가시성과 감사를 위한 오케스트레이션 수준 사용량 미터링을 제공합니다. 공개 표면은 여섯 개의 심볼입니다: MeterCollector, MeterEntry, MeteringReporter, MeteringBackendInterface, PrometheusMeteringBackend, PrometheusPushgatewayException. 컬렉터는 불변 항목을 메모리에 버퍼링하고 배치 단위로 플러시합니다. 리포터는 각 배치를 백엔드별 재시도와 실패 격리를 갖추어 하나 이상의 백엔드로 팬아웃합니다. 미터링은 최선 노력이며 비치명적입니다. 미터링 백엔드 장애는 관측성을 저하시킬 뿐 결코 문서 처리를 저하시키지 않습니다. 이 스트림은 할당량 시행의 권위적 출처가 아닙니다. 워크플로 수준 가이드는 미터링을 참조하십시오.

이 기능은 NextPDF Enterprise(nextpdf/enterprise)에 포함되며 Enterprise 등급 라이선스 엔벨로프로 활성화됩니다. 해당 권한이 없는 배포는 이 기능의 클래스를 로드하지 않습니다. 에디션 비교 및 라이선스 받기.

미터링은 기본 Enterprise 기능으로, Enterprise 패키지가 설치되면 사용할 수 있습니다. 별도의 기능별 플래그가 없습니다. NextPDF Core(Apache-2.0)와 NextPDF Pro에는 컬렉터, 리포터, 백엔드 표면이 없습니다. 이 계약은 nextpdf/enterprise에만 포함됩니다.

심볼매개변수기본 동작반환던지거나 실패하는 경우참고
MeterCollector::__constructMeteringReporter $reporter, int $bufferSize = 100빈 인메모리 버퍼를 가진 컬렉터를 생성합니다MeterCollector던지지 않음$bufferSize는 문서상 positive-int입니다
MeterCollector::recordstring $operation, int $count, string $tenantId, string $licenseId, int $pagesProcessed = 0, float $durationMs = 0.0, array $metadata = []현재 시간이 찍힌 불변 MeterEntry 하나를 추가합니다. 버퍼가 $bufferSize에 도달하면 자동 플러시합니다void던지지 않음. 자동 플러시는 리포터에 위임되며, 리포터는 결코 던지지 않습니다타임스탬프는 기록 시점에 취득됩니다
MeterCollector::flush버퍼링된 모든 항목을 리포터에 전달합니다. 빈 버퍼는 무연산입니다void던지지 않음. 백엔드 장애는 리포터가 흡수합니다전달 전에 버퍼가 교체됩니다. 재진입 안전
MeterCollector::bufferCount버퍼링된 항목 수를 반환합니다int<0, max>던지지 않음진단 및 배압(back-pressure) 결정용
MeterCollector::registerShutdownFlushregister_shutdown_function을 통해 flush()를 등록합니다void던지지 않음PHP-FPM 배포에서 부트스트랩 시 한 번 호출하십시오
MeterEntry::__constructstring $operation, int $count, DateTimeImmutable $timestamp, string $tenantId, string $licenseId, int $pagesProcessed = 0, float $durationMs = 0.0, array $metadata = []제공된 값을 그대로 저장합니다MeterEntry선언된 @throws 없음. strict_types 하에서 인수 타입이 불일치하면 PHP가 TypeError를 발생시킵니다final readonly. 승격된 여덟 개 프로퍼티는 모두 public입니다
MeteringReporter::__constructlist<MeteringBackendInterface> $backends, int $maxRetries = 2, LoggerInterface $logger = new NullLogger()백엔드 목록을 검증하고 저장합니다MeteringReporter$backends가 비어 있으면 InvalidArgumentException$maxRetries는 백엔드별 총 전달 시도 횟수를 셉니다
MeteringReporter::reportlist<MeterEntry> $entries배치를 백엔드별 재시도와 함께 모든 백엔드에 독립적으로 전달합니다void던지지 않음. 소진된 시도는 오류 수준으로 기록되고 그 백엔드의 배치를 드롭합니다빈 목록은 무연산입니다
MeteringBackendInterface::reportlist<MeterEntry> $entries배치를 백엔드에 전달합니다void백엔드에 도달할 수 없으면 RuntimeException구현은 반드시 멱등이어야 합니다(timestamp + operation + tenantId로 중복 제거)
MeteringBackendInterface::isHealthy도달 가능성 프로브bool선언된 @throws 없음진단 전용. 리포터는 이에 게이트하지 않습니다
MeteringBackendInterface::backendName진단용 백엔드 이름non-empty-string선언된 @throws 없음예: "prometheus", "billing-api", "null"
PrometheusMeteringBackend::__constructClientInterface $httpClient, RequestFactoryInterface $requestFactory, StreamFactoryInterface $streamFactory, string $pushgatewayUrl, string $jobName = 'nextpdf_metering'Pushgateway 푸시 대상을 구성합니다PrometheusMeteringBackend던지지 않음PSR-18 클라이언트와 PSR-17 팩토리가 주입됩니다
PrometheusMeteringBackend::reportlist<MeterEntry> $entries배치를 연산 및 테넌트 시리즈별로 집계하고 노출 텍스트를 <pushgatewayUrl>/metrics/job/<jobName>에 POST합니다void2xx가 아닌 상태 또는 PSR-18 전송 실패 시 PrometheusPushgatewayException빈 목록은 무연산입니다
PrometheusMeteringBackend::isHealthyPushgateway 상태 엔드포인트를 프로브합니다. HTTP 200에서만 truebool던지지 않음. 어떤 실패든 false를 반환합니다읽기 전용 GET 프로브
PrometheusMeteringBackend::backendName"prometheus"를 반환합니다non-empty-string던지지 않음상수
PrometheusPushgatewayException실패한 Pushgateway 전달을 알립니다던져지는 대상입니다final. 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 {}

MeterEntry public readonly 프로퍼티

프로퍼티타입의미
$operationnon-empty-string연산 유형, 예: "parse", "compress", "embed", "rag_query"
$countpositive-int소비된 단위 수
$timestampDateTimeImmutable연산이 발생한 시점. 컬렉터가 기록 시점에 찍습니다
$tenantIdnon-empty-string테넌트 식별자
$licenseIdnon-empty-string라이선스 식별자
$pagesProcessedint<0, max>처리된 PDF 페이지 수. PDF가 아닌 연산은 0
$durationMsfloat밀리초 단위 연산 지속 시간
$metadataarray<string, mixed>자유 형식의 연산별 메타데이터
  • MeterCollector::record()는 불변 MeterEntry 하나를 생성하고 현재 시간을 찍어 인메모리 버퍼에 추가합니다. 버퍼가 $bufferSize 항목에 도달하면 컬렉터가 자동 플러시합니다.
  • flush()는 멱등이며 재진입 안전합니다. 빈 버퍼는 무연산입니다. 배치가 리포터에 전달되기 전에 버퍼가 교체되므로, 재진입 플러시가 이중 전송할 수 없습니다.
  • MeteringReporter는 빈 백엔드 목록으로의 생성을 거부합니다. 그 InvalidArgumentException은 컬렉터/리포터 경로의 유일한 예외입니다.
  • MeteringReporter::report()는 각 배치를 모든 백엔드에 독립적으로 전달합니다. 실패하는 백엔드가 다른 백엔드의 동일 배치 수신을 결코 막지 않습니다.
  • $maxRetries는 백엔드별 총 전달 시도 횟수를 셉니다. 기본값 2는 최초 시도 한 번에 재시도 한 번을 의미합니다. 모든 실패한 시도는 백엔드 이름, 시도 번호, 항목 수와 함께 경고를 기록합니다.
  • 백엔드에 대한 마지막 시도가 실패하면, 리포터는 드롭된 항목 수와 함께 오류 수준으로 추가 기록한 뒤 다음으로 넘어갑니다. report()에서 결코 던지지 않으므로, 호출자는 정상 반환으로부터 전달을 추론해서는 안 됩니다.
  • 백엔드는 반드시 멱등이어야 합니다. 인터페이스 계약은 타임스탬프, 연산, 테넌트 식별자를 키로 하는 중복 제거를 요구합니다. 리포터 자체는 중복 제거하지 않습니다.
  • PrometheusMeteringBackend::report()는 배치를 연산별, 테넌트별 시리즈로 집계하고 Prometheus 텍스트 노출을 Content-Type text/plain; version=0.0.4<pushgatewayUrl>/metrics/job/<jobName>에 POST합니다. 기본 잡 이름은 nextpdf_metering입니다.
  • 푸시된 페이로드는 세 개의 카운터 — nextpdf_operations_total, nextpdf_pages_processed_total, nextpdf_operation_duration_ms_total — 를 담으며, 각각 연산과 테넌트로 레이블됩니다.
  • 이 미터링 스트림은 비권위적입니다. 할당량 시행과 권위적 컴퓨트 미터링은 이 버퍼가 아니라 배포의 별도 권위적 사용량 수치를 소비합니다. 오케스트레이션 미터링의 누락은 관측성 누락이지 청구 정확성 누락이 아닙니다.
  • 중복되거나 재생된 배치. 백엔드 멱등성에 의해 흡수됩니다. 리포터는 중복 제거하지 않습니다. 정확히 한 번 전달에 의존하지 마십시오.
  • 소진된 재시도. 그 백엔드의 배치는 드롭되고 오류 수준으로 기록됩니다. report() 또는 flush()의 정상 반환은 결코 전달을 의미하지 않습니다.
  • 플러시 전 프로세스 종료. 버퍼는 메모리 전용입니다. 크래시, 또는 등록된 셧다운 핸들러 없는 종료는 버퍼링된 항목을 잃습니다.
  • 워커 모델 불일치. PHP-FPM 배포는 부트스트랩에서 registerShutdownFlush()를 한 번 호출하여 나머지가 요청 종료 시 플러시되도록 합니다. 장시간 실행 워커(Octane, Symfony 워커, 큐 워커)는 대신 주기적 타이머로 플러시해야 합니다. 그렇지 않으면 워커 프로세스가 종료될 때까지 항목이 누적됩니다.
  • 1 미만의 $bufferSize. 문서화된 positive-int 계약을 위반합니다. 관찰 가능한 결과는 매 record() 호출마다 플러시가 발생하는 것입니다.
  • 민감한 메타데이터. $metadata는 자유 형식이며 민감한 연산 컨텍스트를 담을 수 있습니다. 저장, 보존, 접근 제어는 백엔드 운영자의 책임입니다.
  • Pushgateway 전달 실패. 2xx가 아닌 응답은 HTTP 상태와 응답 본문을 담은 PrometheusPushgatewayException을 발생시킵니다. PSR-18 전송 실패는 동일한 예외 유형으로 래핑됩니다. 리포터의 재시도-격리 루프가 둘 다 흡수합니다.
  • 상태 프로브. PrometheusMeteringBackend::isHealthy()<pushgatewayUrl>/-/healthy에 대해 GET을 발행하고 HTTP 200에서만 true를 반환합니다. 어떤 전송 오류든 false를 반환하며, 프로브는 결코 던지지 않습니다.
  • 적대적 레이블 값. 연산 또는 테넌트 값 내의 백슬래시, 큰따옴표, 줄바꿈 문자는 방출 시 이스케이프되므로, 레이블 값이 추가 노출 라인을 주입하거나 레이블 블록을 손상시킬 수 없습니다.
  • FIPS 모드. 컬렉터와 리포터는 어떠한 암호화 연산도 수행하지 않으며 FIPS별 동작이 없습니다. 전송 중 서명하거나 암호화하는 백엔드는 그 호스트 암호 제공자의 FIPS 태세를 상속합니다.

어떤 외부 표준도 인프로세스 컬렉터, 리포터, 백엔드 계약을 관장하지 않습니다. 인용할 규범 사양이 없으므로 이 페이지는 설계상 RAG 인용을 담지 않습니다. Prometheus 백엔드는 Prometheus 텍스트 노출 형식을 방출하고 Content-Type text/plain; version=0.0.4로 푸시합니다. 그 형식은 ISO나 IETF 표준이 아니라 생태계 관례이며, 이 주장은 제품 소스에 근거합니다. NextPDF는 이 표면에 대해 어떠한 적합성 또는 인증 주장도 하지 않습니다.

  • 모든 클래스는 strict_types=1을 선언하며 final입니다. MeterEntry는 승격된 public 프로퍼티를 가진 final readonly입니다. 인수 타입이 불일치하면 호출자에서 PHP TypeError가 발생합니다.
  • 모듈 클래스는 패키지 @since 주석 2.1.0을 담습니다. PrometheusPushgatewayException@since 3.2.0을 담습니다.
  • 리포터의 로거는 기본적으로 PSR-3 NullLogger입니다. 프로덕션에서는 실제 로거를 주입하십시오. 그렇지 않으면 드롭된 배치가 흔적을 남기지 않습니다.
  • 단위 테스트: 가짜 MeteringBackendInterface를 구현하고 MeterEntry 값을 직접 생성하십시오. Prometheus 백엔드는 PSR-18/PSR-17 추상화를 취하므로, 모의 HTTP 클라이언트가 오프라인에서 전체 푸시 경로를 수행합니다.
  • 권장 경계 테스트: $bufferSize에서 정확히 버퍼, 재진입 플러시, 빈 버퍼 플러시, 한 백엔드가 실패하는 동안 두 번째가 성공, 그리고 재시도 소진 로깅.
  • 백엔드 구현자는 전달 실패 시 RuntimeException(또는 서브클래스)을 던지고, 리포터가 이를 흡수합니다. 상류에 추가 재시도를 더하기 전에 멱등성 요구사항을 준수하십시오.

이 페이지는 외부에서 관찰 가능한 동작과 지원되는 공개 API 표면만을 문서화합니다. 내부 네임스페이스 경로, 헬퍼 클래스, 메커니즘 표, 런북 파일명, 티켓 접두사는 범위 밖입니다.