AI Usage Observer

Automatically deducts credits and calculates profit metrics whenever an AI usage log is created.

Overview

The AIUsageLogObserver listens for the created event on AIUsageLog models. Every time your AI processes a request — whether it's a chat response, embedding, or playground query — this observer kicks in to:

  1. Deduct credits from the tenant's balance
  2. Calculate revenue and profit metrics
  3. Handle failed usage logs gracefully

File: app/Observers/AIUsageLogObserver.php

How It Works

When an AIUsageLog is created, the observer follows this flow:

  1. Check status — If the log is failed, handle it separately (zero out credits, set model)
  2. Validate context — Ensure an agent and tenant_id exist; try to resolve missing tenant context
  3. Route to correct credit pool — Playground types use PlaygroundCredit, all others use Credit
  4. Deduct credits — Uses FIFO ordering with atomic locks to prevent race conditions
  5. Calculate profit — Computes revenue vs. cost in both USD and NGN

Credit Deduction

Standard Credits

For regular AI usage (chat responses, embeddings, safety checks):

  • Credits to deduct = total_tokens / agent.tokens_per_credit
  • Credits are deducted from the tenant's Credit packages in FIFO order (oldest first)
  • When the oldest package is depleted, deduction spans to the next package
  • A weighted average price per credit is calculated across packages

Playground Credits

For playground-related types (playground_chat_response, playground_embedding, playground_embedding_chunks, playground_safety):

  • Same deduction logic as standard credits, but from the PlaygroundCredit pool
  • No overdraft support — can only use credits with positive remaining balance

Atomic Locking

Credit deduction uses Cache::lock() with a 10-second TTL and 5-second wait to prevent race conditions when multiple AI requests complete simultaneously for the same tenant.

Overdraft Tenants

Tenants listed in ai.skip_charge_for_tenants settings can go into negative credit balance. Regular tenants can only use credits with positive remaining amounts.

Profit Metrics

After credit deduction, the observer calculates:

Metric Formula
Input Cost (USD) input_token_count × agent.input_cost / 1,000,000
Output Cost (USD) output_token_count × agent.output_cost / 1,000,000
Revenue (USD) (price_per_credit_ngn / exchange_rate) × (total_tokens / tokens_per_credit)
Profit (USD) revenue_usd - total_cost_usd

Exchange rate comes from settings('ai.usage_exchange_rate') (default: 1500 NGN/USD).

All values are saved to the AIUsageLog record for historical reporting.

Failed Usage Handling

When an AI request fails (status = 'failed'):

  • credits_used and credits_cost are zeroed out
  • model is populated from the agent's base model or metadata
  • An exception is reported (unless metadata.exception_reported is already true)

Tenant Resolution

If tenant_id is missing on the usage log, the observer tries to resolve it from:

  1. The agent's tenant context
  2. The company's tenant_id
  3. The conversation's tenant_id
  4. The user's tenant_id

Auto-Created Credits

When a new tenant is created, TenantObserver automatically assigns 50 free credits (both standard and playground) with a 6-month expiry. These credits have price_per_credit_ngn = 0 since they're complimentary.

See Also

  • Dynamic AI Service — Creates the usage logs that trigger this observer
  • Test file: tests/Feature/Observers/AIUsageLogObserverTest.php

Keywords

AI usage, credit deduction, billing, profit metrics, observer, token tracking, FIFO credits, playground credits, revenue calculation