AI Monitor
Monitor AI API usage and costs across OpenAI, Anthropic, Gemini & Perplexity. Features include API key management, automatic cost calculation, per-user spending limits, and multi-tenancy support.
Author:
Israr Minhas
Documentation
- Features
- Requirements
- Installation
- Register the Plugin
- Helper Functions
- Using the Services
- Usage Examples
- User Spending Limits
- Multi-Tenancy Support
- Dashboard Widgets
- License
A Filament 4 plugin for monitoring AI API usage, costs, and managing API keys across multiple providers (OpenAI, Anthropic, Gemini, Perplexity).
#Features
- Track AI API requests with token counts and automatic cost calculation
- Manage API keys for multiple providers with priority-based rotation
- Configure model-specific pricing with fallback support
- Dashboard with usage analytics and cost trends
- Per-user spending tracking and limits
- Multi-tenancy support (works with
tenant()helper)
#Requirements
- PHP 8.2+
- Laravel 11+
- Filament 4.0+
#Installation
composer require israrminhas/filament-aimonitor
Publish and run migrations:
php artisan vendor:publish --tag="ai-monitor-migrations"
php artisan migrate
Publish config (optional):
php artisan vendor:publish --tag="ai-monitor-config"
#Register the Plugin
Add the plugin to your Filament panel in app/Providers/Filament/AdminPanelProvider.php:
use Filament\AiMonitor\AiMonitorPlugin;
public function panel(Panel $panel): Panel
{
return $panel
->plugins([
AiMonitorPlugin::make(),
]);
}
#Helper Functions
The package provides three global helper functions:
#ai_log() - Log AI Requests
// Log any AI request
ai_log([
'provider' => 'openai',
'model' => 'gpt-4o',
'request_type' => 'chat',
'prompt_tokens' => 150,
'completion_tokens' => 50,
'status' => 'success',
'user_id' => auth()->id(),
]);
Cost is automatically calculated from your pricing configuration. The total_tokens and occurred_at are auto-filled if not provided.
#ai_key() - Get API Key
// Get the highest priority active API key for a provider
$apiKey = ai_key('openai');
$apiKey = ai_key('anthropic');
$apiKey = ai_key('gemini');
#ai_cost() - Calculate Cost
// Calculate cost for tokens without logging
$cost = ai_cost('openai', 'gpt-4o', 1000, 500);
// Returns cost in USD based on your pricing config
#Using the Services
#AiUsageLogger
use Filament\AiMonitor\Services\AiUsageLogger;
$logger = app(AiUsageLogger::class);
// Generic log
$logger->log([
'provider' => 'openai',
'model' => 'gpt-4o',
'prompt_tokens' => 100,
'completion_tokens' => 50,
'status' => 'success',
'user_id' => auth()->id(),
'meta' => ['conversation_id' => 123],
]);
// Provider-specific shortcuts
$logger->logOpenAi([...]);
$logger->logAnthropic([...]);
$logger->logGemini([...]);
$logger->logPerplexity([...]);
#AiKeyManager
use Filament\AiMonitor\Services\AiKeyManager;
$keyManager = app(AiKeyManager::class);
// Get single key (highest priority)
$key = $keyManager->getKey('openai');
// Get all active keys for a provider
$keys = $keyManager->getAllKeys('openai');
// Check if provider has any active keys
if ($keyManager->hasProvider('anthropic')) {
// ...
}
#AiPricingService
use Filament\AiMonitor\Services\AiPricingService;
$pricing = app(AiPricingService::class);
// Get pricing for a model
$rates = $pricing->getPricing('openai', 'gpt-4o');
// Returns: ['input_per_1k' => 0.005, 'output_per_1k' => 0.015]
// Check if pricing exists
if ($pricing->hasPricing('anthropic', 'claude-3-opus')) {
// ...
}
// Calculate cost
$cost = $pricing->calculateCost('openai', 'gpt-4o', 1000, 500);
// Get all configured providers
$providers = $pricing->getProviders();
// Get models for a provider
$models = $pricing->getModelsForProvider('openai');
#AiUsageLimitService
use Filament\AiMonitor\Services\AiUsageLimitService;
$limitService = app(AiUsageLimitService::class);
// Get user's monthly spend
$spent = $limitService->getUserMonthlySpend($userId);
// Get full limit status
$status = $limitService->getUserLimitStatus($user);
// Returns:
// [
// 'limit' => 100.00,
// 'spent' => 45.50,
// 'remaining' => 54.50,
// 'percent_used' => 45.5,
// 'state' => 'ok', // 'ok', 'warning', 'over', 'no-limit'
// ]
#Usage Examples
#OpenAI Integration
use OpenAI\Laravel\Facades\OpenAI;
$response = OpenAI::chat()->create([
'model' => 'gpt-4o',
'messages' => [
['role' => 'user', 'content' => 'Hello!'],
],
]);
// Log the request
ai_log([
'provider' => 'openai',
'model' => $response->model,
'request_type' => 'chat',
'prompt_tokens' => $response->usage->promptTokens,
'completion_tokens' => $response->usage->completionTokens,
'status' => 'success',
'user_id' => auth()->id(),
]);
#Anthropic Integration
$response = Http::withHeaders([
'x-api-key' => ai_key('anthropic'),
'anthropic-version' => '2023-06-01',
])->post('https://api.anthropic.com/v1/messages', [
'model' => 'claude-3-5-sonnet-20241022',
'max_tokens' => 1024,
'messages' => [['role' => 'user', 'content' => 'Hello!']],
]);
$data = $response->json();
ai_log([
'provider' => 'anthropic',
'model' => $data['model'],
'request_type' => 'chat',
'prompt_tokens' => $data['usage']['input_tokens'],
'completion_tokens' => $data['usage']['output_tokens'],
'status' => $response->successful() ? 'success' : 'failed',
'user_id' => auth()->id(),
]);
#With Error Handling
try {
$response = OpenAI::chat()->create([...]);
ai_log([
'provider' => 'openai',
'model' => 'gpt-4o',
'prompt_tokens' => $response->usage->promptTokens,
'completion_tokens' => $response->usage->completionTokens,
'status' => 'success',
'user_id' => auth()->id(),
]);
} catch (\Exception $e) {
ai_log([
'provider' => 'openai',
'model' => 'gpt-4o',
'prompt_tokens' => 0,
'completion_tokens' => 0,
'status' => 'failed',
'user_id' => auth()->id(),
'meta' => ['error' => $e->getMessage()],
]);
}
#User Spending Limits
#Add Columns to Users Table
php artisan make:migration add_ai_limits_to_users_table
Schema::table('users', function (Blueprint $table) {
$table->decimal('ai_monthly_limit_usd', 10, 4)->nullable();
$table->integer('ai_alert_threshold_percent')->default(80);
});
#Check Limits Before AI Calls
use Filament\AiMonitor\Services\AiUsageLimitService;
$limitService = app(AiUsageLimitService::class);
$status = $limitService->getUserLimitStatus(auth()->user());
if ($status['state'] === 'over') {
throw new \Exception('Monthly AI spending limit reached.');
}
if ($status['state'] === 'warning') {
// Notify user they're approaching limit
}
#Multi-Tenancy Support
The package automatically scopes data to the current tenant when tenant() helper is available (e.g., with Filament multi-tenancy or Stancl/Tenancy).
#Configuration
// config/ai-monitor.php
return [
'tenant_support' => true, // Enable/disable tenant scoping
];
#How It Works
- All models use the
IsTenantScopedtrait - When
tenant()returns a tenant,tenant_idis automatically set on create - Queries are automatically scoped to the current tenant
#Dashboard Widgets
The plugin includes these dashboard widgets:
| Widget | Description |
|---|---|
| Stats Overview | Total requests, tokens, cost, success rate |
| Cost & Request Trends | 30-day line chart |
| Cost by Provider | Doughnut chart breakdown |
| Top Models by Cost | Table of most expensive models |
| Usage by User | Table of user spending |
| Recent Requests | Latest API calls with details |
#License
MIT License. See LICENSE for details.
The author
Israr Minhas is a full-stack web developer with experience in Laravel, Filament, Livewire, Vue, and modern PHP development. He has worked on SaaS platforms, dashboards, and multi-tenant systems, focusing on building reliable and easy-to-use web applications. He enjoys learning new technologies and creating practical solutions that simplify work for users and teams.
Featured Plugins
A selection of plugins curated by the Filament team
Custom Dashboards
Let your users build and share their own dashboards with a drag-and-drop interface. Define your data sources in PHP and let them do the rest.
Filament
Custom Fields
Eliminate custom field migrations forever. Let your users create and manage form fields directly in Filament admin panels with 20+ built-in field types, validation, and zero database changes.
Relaticle
Advanced Tables (formerly Filter Sets)
Supercharge your tables with powerful features like user-customizable views, quick filters, multi-column sorting, advanced table searching, convenient view management, and more. Compatible with Resource Panel Tables, Relation Managers, Table Widgets, and Table Builder!
Kenneth Sese