PERF: Migrate AI usage report to use AiApiRequestStat for better perf (#31)

Changes the AiUsage report to query AiApiRequestStat instead of
AiApiAuditLog for significantly improved query performance.
This commit is contained in:
Rafael dos Santos Silva 2025-11-26 12:24:07 -03:00 committed by GitHub
parent bdbac80063
commit f4560c2292
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -2,21 +2,22 @@
# AI usage statistics from discourse-ai plugin # AI usage statistics from discourse-ai plugin
# Shows total usage, favorite features, token consumption, etc. # Shows total usage, favorite features, token consumption, etc.
# Uses AiApiRequestStat for efficient aggregation queries
module DiscourseRewind module DiscourseRewind
module Action module Action
class AiUsage < BaseReport class AiUsage < BaseReport
def call def call
return if !enabled? return if !enabled?
base_query = AiApiAuditLog.where(user_id: user.id).where(created_at: date) base_query = AiApiRequestStat.where(user_id: user.id).where(bucket_date: date)
# Get aggregated stats in a single query # Get aggregated stats in a single query
stats = stats =
base_query.select( base_query.select(
"COUNT(*) as total_requests", "COALESCE(SUM(usage_count), 0) as total_requests",
"COALESCE(SUM(request_tokens), 0) as total_request_tokens", "COALESCE(SUM(request_tokens), 0) as total_request_tokens",
"COALESCE(SUM(response_tokens), 0) as total_response_tokens", "COALESCE(SUM(response_tokens), 0) as total_response_tokens",
"COUNT(CASE WHEN response_tokens > 0 THEN 1 END) as successful_requests", "COALESCE(SUM(CASE WHEN response_tokens > 0 THEN usage_count ELSE 0 END), 0) as successful_requests",
).take ).take
return if stats.total_requests == 0 return if stats.total_requests == 0
@ -35,9 +36,9 @@ module DiscourseRewind
feature_usage = feature_usage =
base_query base_query
.group(:feature_name) .group(:feature_name)
.order("COUNT(*) DESC") .order("SUM(usage_count) DESC")
.limit(5) .limit(5)
.pluck(:feature_name, Arel.sql("COUNT(*)")) .pluck(:feature_name, Arel.sql("SUM(usage_count)"))
.to_h .to_h
# Most used AI model (top 5) # Most used AI model (top 5)
@ -45,9 +46,9 @@ module DiscourseRewind
base_query base_query
.where.not(language_model: nil) .where.not(language_model: nil)
.group(:language_model) .group(:language_model)
.order("COUNT(*) DESC") .order("SUM(usage_count) DESC")
.limit(5) .limit(5)
.pluck(:language_model, Arel.sql("COUNT(*)")) .pluck(:language_model, Arel.sql("SUM(usage_count)"))
.to_h .to_h
{ {
@ -65,7 +66,7 @@ module DiscourseRewind
end end
def enabled? def enabled?
defined?(AiApiAuditLog) && SiteSetting.discourse_ai_enabled defined?(AiApiRequestStat) && SiteSetting.discourse_ai_enabled
end end
end end
end end