@@ -627,19 +627,65 @@ func (r *Repository) LatestAggregatedStats(appID int64) (*ContainerStats, error)
627627 return s , nil
628628}
629629
630- // LatestStatsByApp returns the latest aggregated container stats per app
631- // (summed across all of an app's containers at the most recent collection tick),
632- // keyed by app ID. Apps with no collected stats are absent. Two queries total.
630+ // LatestStatsByApp returns refined per-app resource metrics for the app list view:
631+ // - CPU: 15-minute moving average (AVG of total container CPU per tick)
632+ // - Memory: 1-hour peak usage (MAX of total container RAM per tick)
633+ // - Network / Block IO: Latest snapshot
634+ // Falls back to latest available tick if no data exists within the time window.
633635func (r * Repository ) LatestStatsByApp () (map [int64 ]* ContainerStats , error ) {
634636 rows , err := r .db .Query (`
635- SELECT cs.app_id,
636- SUM(cs.cpu_percent), SUM(cs.mem_usage_bytes), SUM(cs.mem_limit_bytes), SUM(cs.mem_percent),
637- SUM(cs.net_io_rx_bytes), SUM(cs.net_io_tx_bytes), SUM(cs.block_io_read), SUM(cs.block_io_write)
638- FROM container_stats cs
639- JOIN (
640- SELECT app_id, MAX(created_at) AS max_ts FROM container_stats GROUP BY app_id
641- ) m ON m.app_id = cs.app_id AND m.max_ts = cs.created_at
642- GROUP BY cs.app_id
637+ WITH cs_15m AS (
638+ SELECT app_id, AVG(tick_cpu) AS avg_cpu
639+ FROM (
640+ SELECT app_id, created_at, SUM(cpu_percent) AS tick_cpu
641+ FROM container_stats
642+ WHERE created_at >= DATETIME('now', '-15 minutes')
643+ GROUP BY app_id, created_at
644+ )
645+ GROUP BY app_id
646+ ),
647+ cs_60m AS (
648+ SELECT app_id,
649+ MAX(tick_mem_bytes) AS max_mem_bytes,
650+ MAX(tick_mem_limit) AS max_mem_limit,
651+ MAX(tick_mem_pct) AS max_mem_pct
652+ FROM (
653+ SELECT app_id, created_at,
654+ SUM(mem_usage_bytes) AS tick_mem_bytes,
655+ SUM(mem_limit_bytes) AS tick_mem_limit,
656+ SUM(mem_percent) AS tick_mem_pct
657+ FROM container_stats
658+ WHERE created_at >= DATETIME('now', '-1 hour')
659+ GROUP BY app_id, created_at
660+ )
661+ GROUP BY app_id
662+ ),
663+ cs_latest AS (
664+ SELECT cs.app_id,
665+ SUM(cs.cpu_percent) AS fallback_cpu,
666+ SUM(cs.mem_usage_bytes) AS fallback_mem_bytes,
667+ SUM(cs.mem_limit_bytes) AS fallback_mem_limit,
668+ SUM(cs.mem_percent) AS fallback_mem_pct,
669+ SUM(cs.net_io_rx_bytes) AS latest_rx,
670+ SUM(cs.net_io_tx_bytes) AS latest_tx,
671+ SUM(cs.block_io_read) AS latest_blk_r,
672+ SUM(cs.block_io_write) AS latest_blk_w
673+ FROM container_stats cs
674+ JOIN (
675+ SELECT app_id, MAX(created_at) AS max_ts FROM container_stats GROUP BY app_id
676+ ) m ON m.app_id = cs.app_id AND m.max_ts = cs.created_at
677+ GROUP BY cs.app_id
678+ )
679+ SELECT
680+ l.app_id,
681+ COALESCE(c15.avg_cpu, l.fallback_cpu) AS cpu_percent,
682+ COALESCE(c60.max_mem_bytes, l.fallback_mem_bytes) AS mem_usage_bytes,
683+ COALESCE(c60.max_mem_limit, l.fallback_mem_limit) AS mem_limit_bytes,
684+ COALESCE(c60.max_mem_pct, l.fallback_mem_pct) AS mem_percent,
685+ l.latest_rx, l.latest_tx, l.latest_blk_r, l.latest_blk_w
686+ FROM cs_latest l
687+ LEFT JOIN cs_15m c15 ON c15.app_id = l.app_id
688+ LEFT JOIN cs_60m c60 ON c60.app_id = l.app_id
643689 ` )
644690 if err != nil {
645691 return nil , err
0 commit comments