How the Grok Audit Service Tracks Usage and Client Billing in chenyme/grok2api

The Grok audit service tracks usage by persisting structured audit records with embedded attempt logs in SQLite, then calculates client billing using fixed-point USD ticks based on official pricing tables stored alongside each request.

The chenyme/grok2api repository implements a comprehensive audit system that records every API request and its upstream attempts to enable precise usage tracking and client billing. This Grok audit service architecture separates concerns between persistence, domain logic for pricing, and application services to ensure accurate cost attribution even when pricing models change.

Architecture of the Grok Audit Service

The implementation follows a three-layer architecture centered on the backend/internal/application/audit/service.go file, which exposes a thread-safe API for the HTTP transport layer.

Persistence Layer (SQLite Repository)

The backend/internal/repository/audit.go file manages an embedded SQLite database (audit-service.db). It stores auditdomain.Record objects that contain request identifiers, the client-key ID, model-route ID, HTTP status code, timestamps, input and output token counts, and a serialized list of auditdomain.Attempt objects. This repository handles low-level CRUD operations and query helpers used by the service layer.

Domain Layer (Pricing and Models)

Located in backend/internal/domain/audit/pricing.go and backend/internal/domain/audit/audit.go, the domain layer defines the data structures and business rules. The auditdomain.Record struct holds the primary audit data, while auditdomain.Attempt captures individual upstream HTTP calls including stage names, start and end timestamps, upstream status codes, and truncated response bodies. The domain expresses monetary costs as CostInUSDTicks, where one USD equals 1,000,000 ticks, preventing floating-point rounding errors. The ReconstructOfficialCost function calculates costs by looking up the OfficialPricingSource pricing tables for the specific model version used.

Application Service Layer

The backend/internal/application/audit/service.go file implements the Service struct, which provides the public methods consumed by HTTP handlers. These include Create and CreateDurable for inserting new records, Record for updating existing entries after retries or errors, ListCursor for paginating through audit history, and Summary for aggregating billing statistics. The service coalesces rapid-fire events and ensures thread-safe access to the underlying SQLite store.

How the Grok Audit Service Tracks Usage

Usage tracking follows a lifecycle that captures request metadata, upstream attempts, and final cost calculations.

1. Request Initialization with Create

When the gateway receives a request, it invokes auditService.Create with a minimal auditdomain.Record containing the request ID, client-key ID, model-route ID, an initial HTTP 202 status code, and the creation timestamp. The service persists this row to SQLite and returns the generated database ID, which subsequent operations reference to append data to the same record.

2. Attempt Logging via Record Updates

Each upstream HTTP call—such as credential fetching or model inference—generates an auditdomain.Attempt object. The application layer calls AddAttempt (internally managed by the Record method) to append these attempts to the Record.Attempts slice. Each attempt captures the stage name (e.g., credential or upstream_response), precise start and end timestamps, the upstream HTTP status code, input and output token counts, and a truncated response body for debugging.

3. Token-Based Cost Calculation

After receiving the model response, the service calculates the monetary cost by invoking auditdomain.ReconstructOfficialCost. This function queries the OfficialPricingSource tables for the specific model version and multiplies the input and output token counts by the per-token price. The resulting CostInUSDTicks value is stored on the audit record, ensuring the exact pricing model version is preserved alongside the usage data for historical accuracy.

4. Billing Breakdown Persistence

The audit record stores a PricingModel identifier (e.g., grok-build-0.1) and a PricingVersion timestamp. This versioning allows the service to reconstruct historical billing statements even after official pricing changes. The domain also supports EstimatedCostInUSDTicks for preview modes, allowing clients to see potential costs before finalizing requests.

How Client Billing Is Derived

The billing pipeline operates as a map-reduce query over the SQLite audit records.

Filtering Audit Records

Administrators or client-facing APIs call ListCursor with a ListFilter specifying the client-key ID, date range, and request status. The service translates these parameters into SQL queries against the backend/internal/repository/audit.go layer, returning only the rows belonging to the requested client.

Aggregation and Summarization

The Summary method aggregates the filtered records to produce billing reports. It calculates the total request count, successful request count, total input and output token usage, and the sum of CostInUSDTicks across all matching records. This aggregation happens at the database level for efficiency, utilizing SQLite's SUM and COUNT functions.

Currency Conversion and Display

Costs remain in USDTicks throughout the backend to maintain precision. The frontend or API consumers divide the tick value by 1,000,000 to display decimal USD amounts. This fixed-point approach ensures that financial calculations remain exact and free from floating-point artifacts common in monetary computations.

Code Implementation Examples

Creating an Audit Record

The following pattern from backend/internal/application/audit/service.go demonstrates initializing a request audit:

func (s *Service) Create(ctx context.Context, rec auditdomain.Record) (uint64, error) {
    // Insert minimal record with status 202 (Accepted)
    rec.StatusCode = http.StatusAccepted
    rec.CreatedAt = time.Now().UTC()
    
    id, err := s.repo.Insert(ctx, rec)
    if err != nil {
        return 0, fmt.Errorf("failed to create audit record: %w", err)
    }
    return id, nil
}

Logging an Upstream Attempt

When capturing telemetry from upstream providers, the service appends attempts to the existing record:

func (s *Service) AddAttempt(ctx context.Context, recordID uint64, attempt auditdomain.Attempt) error {
    attempt.StartedAt = time.Now().UTC()
    
    // Capture token usage from model response
    attempt.InputTokens = resp.Usage.InputTokens
    attempt.OutputTokens = resp.Usage.OutputTokens
    attempt.UpstreamStatusCode = &resp.StatusCode
    
    return s.repo.AppendAttempt(ctx, recordID, attempt)
}

Retrieving Client Billing via HTTP

The HTTP handler in backend/internal/transport/http/audit/handler.go exposes billing summaries:

curl -H "Authorization: Bearer <admin-token>" \
     "https://api.example.com/api/admin/v1/request-audits/summary?clientKeyId=42&period=30d"

Response structure:

{
  "requests": 1245,
  "successfulRequests": 1198,
  "totalCostUSDTicks": 5873200,
  "totalInputTokens": 3210000,
  "totalOutputTokens": 1950000
}

Summary

  • The Grok audit service uses a three-tier architecture separating SQLite persistence, domain pricing logic, and application services.
  • Usage tracking relies on auditdomain.Record and auditdomain.Attempt structures stored in audit-service.db, capturing every upstream HTTP call and token count.
  • Cost calculation employs ReconstructOfficialCost and OfficialPricingSource to compute CostInUSDTicks, ensuring financial precision with fixed-point arithmetic.
  • Client billing derives from the Summary and ListCursor methods in backend/internal/application/audit/service.go, which aggregate filtered records by client-key and date range.
  • Versioned pricing allows historical billing reconstruction because each record stores its specific PricingModel and PricingVersion.

Frequently Asked Questions

How does the Grok audit service store usage data?

The service stores usage data in an embedded SQLite database managed by backend/internal/repository/audit.go. Each row represents an auditdomain.Record containing request metadata, client identification, token counts, and a JSON array of auditdomain.Attempt objects that log every upstream interaction.

What is a USDTick and why is it used for billing?

A USDTick is a fixed-point representation of US dollars where 1 USD equals 1,000,000 ticks. The backend/internal/domain/audit/pricing.go file defines costs as CostInUSDTicks to avoid floating-point rounding errors in financial calculations, ensuring that client billing remains mathematically precise.

How does the service handle pricing model changes?

The audit record stores the PricingModel identifier and PricingVersion timestamp alongside the CostInUSDTicks. Because the domain logic in backend/internal/domain/audit/pricing.go preserves the historical pricing version with each record, the system can reconstruct accurate billing statements even after official pricing tables are updated.

Which files contain the core audit logic?

The primary files are backend/internal/application/audit/service.go for the application service, backend/internal/domain/audit/pricing.go for cost calculations, backend/internal/domain/audit/audit.go for data models, and backend/internal/repository/audit.go for SQLite persistence. The HTTP API surface is exposed through backend/internal/transport/http/audit/handler.go.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →