generated from coulomb/repo-seed
Fix compilation errors across 6 controllers and 29 views: import cleanup, ResponseException pattern for API auth, type fixes, unused import removal. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
49 lines
1.6 KiB
Haskell
49 lines
1.6 KiB
Haskell
module Web.Controller.ApiDashboard where
|
|
|
|
import Web.Types
|
|
import Web.View.ApiDashboard.Show
|
|
import Generated.Types
|
|
import IHP.Prelude
|
|
import IHP.ControllerPrelude
|
|
import Web.Routes ()
|
|
import Database.PostgreSQL.Simple (Only(..))
|
|
|
|
instance Controller ApiDashboardController where
|
|
beforeAction = ensureIsUser
|
|
|
|
action ShowApiDashboardAction = autoRefresh do
|
|
consumers <- query @ApiConsumer
|
|
|> orderByAsc #name
|
|
|> fetch
|
|
stats <- mapM fetchStats consumers
|
|
render ShowView { stats }
|
|
|
|
-- | Aggregate per-consumer stats from api_request_log (last 24 hours).
|
|
fetchStats :: (?modelContext :: ModelContext) => ApiConsumer -> IO ConsumerStats
|
|
fetchStats consumer = do
|
|
rows <- sqlQuery
|
|
"SELECT COUNT(*), \
|
|
\ COUNT(*) FILTER (WHERE status_code >= 400), \
|
|
\ MAX(requested_at) \
|
|
\FROM api_request_log \
|
|
\WHERE api_consumer_id = ? \
|
|
\ AND requested_at >= NOW() - INTERVAL '24 hours'"
|
|
(Only consumer.id)
|
|
case rows of
|
|
[(total, errs, lastTs)] ->
|
|
let errRate = if (total :: Int) == 0
|
|
then 0.0
|
|
else fromIntegral (errs :: Int) / fromIntegral total
|
|
in pure ConsumerStats
|
|
{ consumer
|
|
, requests24h = total
|
|
, errorRate = errRate
|
|
, lastSeen = lastTs
|
|
}
|
|
_ -> pure ConsumerStats
|
|
{ consumer
|
|
, requests24h = 0
|
|
, errorRate = 0.0
|
|
, lastSeen = Nothing
|
|
}
|