feat(admin): Add user engagement insights - #317
Conversation
Token totals now include every user-facing AI path. Administration reports therefore reflect the full user cost.
Administrators can page and search users, inspect engagement, and see token consumption.
Code Review SummaryThis PR successfully introduces comprehensive user engagement and AI usage tracking for the admin console. It bridges the gap between agent usage and routing usage, providing a complete picture of LLM costs per user. 🚀 Key Improvements
💡 Minor Suggestions
|
| use Whilesmart\Engagement\Support\Period; | ||
|
|
||
| class AgentUsageMetricProvider implements MetricProvider | ||
| { |
There was a problem hiding this comment.
Fetching all records for a period into a collection to calculate a sum is inefficient. Use the database's sum() method directly and pass the period to sub-methods to allow for optimized database-level queries.
| { | |
| public function metrics(Period $period): array | |
| { | |
| $baseQuery = TokenUsage::query() | |
| ->whereBetween('created_at', [$period->start, $period->end]); | |
| return [ | |
| Metric::sum('ai_tokens_used', 'AI tokens used', (float) $baseQuery->sum('total_tokens'), 'tokens'), | |
| Metric::series('ai_tokens_series', 'AI tokens over time', $this->series($baseQuery->clone()->get(['created_at', 'total_tokens']), $period), 'tokens'), | |
| Metric::ranking('ai_tokens_by_user', 'AI tokens by user', $this->ranking($period)), | |
| ]; | |
| } |
| ->all(); | ||
| } | ||
|
|
||
| private function ranking(iterable $usage): array |
There was a problem hiding this comment.
Computing the user ranking in PHP by grouping all records is inefficient. This should be performed at the database level to significantly reduce memory usage and improve performance, especially when only the top 8 users are required.
| private function ranking(iterable $usage): array | |
| private function ranking(Period $period): array | |
| { | |
| $userType = (new User())->getMorphClass(); | |
| $totals = TokenUsage::query() | |
| ->where('owner_type', $userType) | |
| ->whereBetween('created_at', [$period->start, $period->end]) | |
| ->groupBy('owner_id') | |
| ->selectRaw('owner_id, sum(total_tokens) as total') | |
| ->orderByDesc('total') | |
| ->take(8) | |
| ->pluck('total', 'owner_id'); | |
| $users = User::query()->whereIn('id', $totals->keys())->get()->keyBy('id'); |
|
Coverage Report |
Provides the admin console with searchable, paginated user engagement and AI usage data. Token totals now cover both routing and agent work, while activity comes from existing Sanctum and transaction records without a user schema change.