跳轉到

計費指標

MeteringReporter 是 NextPDF SaaS Foundation 的計量核心,負責精細記錄每個租戶的 PDF 操作量,為計費、配額管控與分析提供可靠的資料基礎。


計量維度

核心 PDF 操作

指標名稱 類型 標籤 說明
nextpdf_pdf_generated_total Counter tenant_id, plan, template 生成的 PDF 文件數量
nextpdf_pdf_pages_generated_total Counter tenant_id, plan 生成的總頁數
nextpdf_pdf_bytes_generated_total Counter tenant_id, plan 生成的 PDF 總位元組數
nextpdf_pdf_parsed_total Counter tenant_id, plan 解析的 PDF 文件數量
nextpdf_pdf_pages_parsed_total Counter tenant_id, plan 解析的總頁數

影像操作

指標名稱 類型 標籤 說明
nextpdf_images_compressed_total Counter tenant_id, format 壓縮的影像數量
nextpdf_bytes_saved_total Counter tenant_id 透過壓縮節省的位元組數

簽章操作

指標名稱 類型 標籤 說明
nextpdf_signatures_applied_total Counter tenant_id, level, hsm 簽章次數(含 PAdES 等級)
nextpdf_signatures_validated_total Counter tenant_id, result 驗章次數

RAG / AI 操作(Enterprise)

指標名稱 類型 標籤 說明
nextpdf_rag_documents_indexed_total Counter tenant_id, vector_backend 索引的文件數
nextpdf_rag_chunks_indexed_total Counter tenant_id 索引的 Chunk 數量
nextpdf_rag_tokens_embedded_total Counter tenant_id, model 向量化的 Token 數(計費依據)
nextpdf_rag_searches_total Counter tenant_id 語意搜尋次數

效能指標

指標名稱 類型 標籤 說明
nextpdf_operation_duration_seconds Histogram tenant_id, operation 操作耗時分佈
nextpdf_queue_depth Gauge tenant_id, priority 目前佇列深度
nextpdf_errors_total Counter tenant_id, operation, error_code 操作錯誤數量

PHP 實作

MeteringReporter 基本使用

<?php

declare(strict_types=1);

use NextPDF\Enterprise\Metering\MeteringReporter;
use NextPDF\Enterprise\Metering\Operation;

final class PdfGenerationService
{
    public function __construct(
        private readonly MeteringReporter $metering,
    ) {}

    public function generate(
        string $tenantId,
        string $html,
        string $plan,
    ): GeneratedPdf {
        $startTime = microtime(true);

        $pdf = $this->doGenerate($html);

        // 記錄計量事件
        $this->metering->record(
            operation: Operation::PDF_GENERATE,
            tenantId: $tenantId,
            attributes: [
                'plan' => $plan,
                'pages' => $pdf->getPageCount(),
                'bytes' => $pdf->getSizeBytes(),
                'duration_ms' => (int)((microtime(true) - $startTime) * 1000),
            ]
        );

        return $pdf;
    }
}

批次計量(高吞吐量場景)

use NextPDF\Enterprise\Metering\BatchMeteringReporter;

// 使用批次報告器(緩衝 100 個事件或每 5 秒批次發送)
$metering = new BatchMeteringReporter(
    backend: $prometheusBackend,
    bufferSize: 100,
    flushIntervalSeconds: 5,
);

// 在應用程式關閉時確保緩衝區已清空
register_shutdown_function([$metering, 'flush']);

Prometheus 匯出格式

# HELP nextpdf_pdf_generated_total Total PDFs generated
# TYPE nextpdf_pdf_generated_total counter
nextpdf_pdf_generated_total{tenant_id="tenant-abc123",plan="pro",template="invoice"} 1542
nextpdf_pdf_generated_total{tenant_id="tenant-xyz789",plan="enterprise",template="contract"} 389

# HELP nextpdf_pdf_pages_generated_total Total pages generated
# TYPE nextpdf_pdf_pages_generated_total counter
nextpdf_pdf_pages_generated_total{tenant_id="tenant-abc123",plan="pro"} 12456
nextpdf_pdf_pages_generated_total{tenant_id="tenant-xyz789",plan="enterprise"} 4523

# HELP nextpdf_pdf_bytes_generated_total Total bytes of generated PDFs
# TYPE nextpdf_pdf_bytes_generated_total counter
nextpdf_pdf_bytes_generated_total{tenant_id="tenant-abc123",plan="pro"} 524288000

# HELP nextpdf_rag_tokens_embedded_total Total tokens embedded for RAG
# TYPE nextpdf_rag_tokens_embedded_total counter
nextpdf_rag_tokens_embedded_total{tenant_id="tenant-xyz789",model="nextpdf-embed-v1"} 2048000

# HELP nextpdf_operation_duration_seconds Operation duration
# TYPE nextpdf_operation_duration_seconds histogram
nextpdf_operation_duration_seconds_bucket{tenant_id="tenant-abc123",operation="pdf.generate",le="0.5"} 1200
nextpdf_operation_duration_seconds_bucket{tenant_id="tenant-abc123",operation="pdf.generate",le="1.0"} 1490
nextpdf_operation_duration_seconds_bucket{tenant_id="tenant-abc123",operation="pdf.generate",le="5.0"} 1540
nextpdf_operation_duration_seconds_bucket{tenant_id="tenant-abc123",operation="pdf.generate",le="+Inf"} 1542
nextpdf_operation_duration_seconds_sum{tenant_id="tenant-abc123",operation="pdf.generate"} 892.5
nextpdf_operation_duration_seconds_count{tenant_id="tenant-abc123",operation="pdf.generate"} 1542

計費方案整合

Stripe 整合範例

<?php

declare(strict_types=1);

use NextPDF\Enterprise\Metering\BillingExporter;
use Stripe\StripeClient;

final class StripeUsageReporter
{
    public function __construct(
        private readonly BillingExporter $exporter,
        private readonly StripeClient $stripe,
    ) {}

    public function reportUsage(string $tenantId, DateTimeImmutable $periodEnd): void
    {
        $usage = $this->exporter->getUsage(
            tenantId: $tenantId,
            periodStart: $periodEnd->modify('-1 month'),
            periodEnd: $periodEnd,
        );

        // 報告 PDF 頁數用量
        $this->stripe->subscriptionItems->createUsageRecord(
            $this->getStripeItemId($tenantId, 'pdf_pages'),
            [
                'quantity' => $usage->pdfPagesGenerated,
                'timestamp' => $periodEnd->getTimestamp(),
                'action' => 'set',
            ]
        );

        // 報告 RAG Token 用量
        if ($usage->ragTokensEmbedded > 0) {
            $this->stripe->subscriptionItems->createUsageRecord(
                $this->getStripeItemId($tenantId, 'rag_tokens'),
                [
                    'quantity' => $usage->ragTokensEmbedded,
                    'timestamp' => $periodEnd->getTimestamp(),
                    'action' => 'set',
                ]
            );
        }
    }
}

計費定價維度建議

維度 計費單位 建議計費週期
PDF 生成頁數 每 1,000 頁 月結
PDF 解析頁數 每 1,000 頁 月結
RAG 嵌入 Token 每 1,000 Token 月結
語意搜尋查詢 每 1,000 次查詢 月結
數位簽章 每次簽章 即時
儲存空間 每 GB/月 月結

Grafana 儀表板範本

租戶使用量儀表板

{
  "title": "NextPDF Tenant Usage",
  "panels": [
    {
      "title": "PDF 生成量(每小時)",
      "type": "graph",
      "targets": [
        {
          "expr": "rate(nextpdf_pdf_generated_total{tenant_id=~\"$tenant\"}[1h]) * 3600",
          "legendFormat": "{{ tenant_id }}"
        }
      ]
    },
    {
      "title": "頁數累計(當月)",
      "type": "stat",
      "targets": [
        {
          "expr": "increase(nextpdf_pdf_pages_generated_total{tenant_id=~\"$tenant\"}[30d])"
        }
      ]
    },
    {
      "title": "P95 操作延遲",
      "type": "graph",
      "targets": [
        {
          "expr": "histogram_quantile(0.95, rate(nextpdf_operation_duration_seconds_bucket{tenant_id=~\"$tenant\"}[5m]))"
        }
      ]
    }
  ]
}

配額管控

<?php

declare(strict_types=1);

use NextPDF\Enterprise\Metering\QuotaGuard;
use NextPDF\Enterprise\Metering\QuotaExceededException;

final class QuotaAwarePdfService
{
    public function __construct(
        private readonly QuotaGuard $quotaGuard,
    ) {}

    /**
     * @throws QuotaExceededException
     */
    public function generate(string $tenantId, string $html): GeneratedPdf
    {
        // 先檢查配額,不足則拋出異常(避免產生後才發現超額)
        $this->quotaGuard->checkAndReserve(
            tenantId: $tenantId,
            operation: 'pdf.generate',
            units: 1,
        );

        try {
            return $this->doGenerate($html);
        } catch (\Throwable $e) {
            // 生成失敗時退還預留的配額
            $this->quotaGuard->release($tenantId, 'pdf.generate', 1);
            throw $e;
        }
    }
}

參見

Commercial License

This feature requires a commercial license. Contact our team for pricing and deployment support.

Contact Sales