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.Recordandauditdomain.Attemptstructures stored inaudit-service.db, capturing every upstream HTTP call and token count. - Cost calculation employs
ReconstructOfficialCostandOfficialPricingSourceto computeCostInUSDTicks, ensuring financial precision with fixed-point arithmetic. - Client billing derives from the
SummaryandListCursormethods inbackend/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
PricingModelandPricingVersion.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →