1
0
forked from wrenn/wrenn
Files
wrenn-releases/internal/db/metrics.sql.go
pptx704 fee66bda50 Add live stats page with metrics sampling and route split
- New sandbox_metrics_snapshots table sampled every 10s (60-day retention)
- Background MetricsSampler goroutine wired into control plane startup
- GET /v1/sandboxes/stats?range=5m|1h|6h|24h|30d endpoint with adaptive
  polling intervals; reserved CPU/RAM uses ceil(paused/2) formula
- StatsPanel component: 4 stat cards + 2 Chart.js line charts (straight
  lines, integer y-axis for running count, dual-axis for CPU/RAM)
- Range filter persisted in URL query param; polls update data silently
  (no blink — loading state only shown on initial mount)
- Split /dashboard/capsules into /list and /stats sub-routes with shared
  layout; capsuleRunningCount store syncs badge across routes
- CreateCapsuleDialog extracted as reusable component
2026-03-25 14:41:05 +06:00

142 lines
4.3 KiB
Go

// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.30.0
// source: metrics.sql
package db
import (
"context"
"github.com/jackc/pgx/v5/pgtype"
)
const getCurrentMetrics = `-- name: GetCurrentMetrics :one
SELECT running_count, vcpus_reserved, memory_mb_reserved, sampled_at
FROM sandbox_metrics_snapshots
WHERE team_id = $1
ORDER BY sampled_at DESC
LIMIT 1
`
type GetCurrentMetricsRow struct {
RunningCount int32 `json:"running_count"`
VcpusReserved int32 `json:"vcpus_reserved"`
MemoryMbReserved int32 `json:"memory_mb_reserved"`
SampledAt pgtype.Timestamptz `json:"sampled_at"`
}
func (q *Queries) GetCurrentMetrics(ctx context.Context, teamID string) (GetCurrentMetricsRow, error) {
row := q.db.QueryRow(ctx, getCurrentMetrics, teamID)
var i GetCurrentMetricsRow
err := row.Scan(
&i.RunningCount,
&i.VcpusReserved,
&i.MemoryMbReserved,
&i.SampledAt,
)
return i, err
}
const getPeakMetrics = `-- name: GetPeakMetrics :one
SELECT
COALESCE(MAX(running_count), 0)::INTEGER AS peak_running_count,
COALESCE(MAX(vcpus_reserved), 0)::INTEGER AS peak_vcpus,
COALESCE(MAX(memory_mb_reserved), 0)::INTEGER AS peak_memory_mb
FROM sandbox_metrics_snapshots
WHERE team_id = $1
AND sampled_at > NOW() - INTERVAL '30 days'
`
type GetPeakMetricsRow struct {
PeakRunningCount int32 `json:"peak_running_count"`
PeakVcpus int32 `json:"peak_vcpus"`
PeakMemoryMb int32 `json:"peak_memory_mb"`
}
func (q *Queries) GetPeakMetrics(ctx context.Context, teamID string) (GetPeakMetricsRow, error) {
row := q.db.QueryRow(ctx, getPeakMetrics, teamID)
var i GetPeakMetricsRow
err := row.Scan(&i.PeakRunningCount, &i.PeakVcpus, &i.PeakMemoryMb)
return i, err
}
const insertMetricsSnapshot = `-- name: InsertMetricsSnapshot :exec
INSERT INTO sandbox_metrics_snapshots (team_id, running_count, vcpus_reserved, memory_mb_reserved)
VALUES ($1, $2, $3, $4)
`
type InsertMetricsSnapshotParams struct {
TeamID string `json:"team_id"`
RunningCount int32 `json:"running_count"`
VcpusReserved int32 `json:"vcpus_reserved"`
MemoryMbReserved int32 `json:"memory_mb_reserved"`
}
func (q *Queries) InsertMetricsSnapshot(ctx context.Context, arg InsertMetricsSnapshotParams) error {
_, err := q.db.Exec(ctx, insertMetricsSnapshot,
arg.TeamID,
arg.RunningCount,
arg.VcpusReserved,
arg.MemoryMbReserved,
)
return err
}
const pruneOldMetrics = `-- name: PruneOldMetrics :exec
DELETE FROM sandbox_metrics_snapshots
WHERE sampled_at < NOW() - INTERVAL '60 days'
`
func (q *Queries) PruneOldMetrics(ctx context.Context) error {
_, err := q.db.Exec(ctx, pruneOldMetrics)
return err
}
const sampleSandboxMetrics = `-- name: SampleSandboxMetrics :many
SELECT
team_id,
(COUNT(*) FILTER (WHERE status IN ('running', 'starting')))::INTEGER AS running_count,
(COALESCE(SUM(vcpus) FILTER (WHERE status IN ('running', 'starting')), 0)
+ CEIL(COALESCE(SUM(vcpus) FILTER (WHERE status = 'paused'), 0)::NUMERIC / 2))::INTEGER AS vcpus_reserved,
(COALESCE(SUM(memory_mb) FILTER (WHERE status IN ('running', 'starting')), 0)
+ CEIL(COALESCE(SUM(memory_mb) FILTER (WHERE status = 'paused'), 0)::NUMERIC / 2))::INTEGER AS memory_mb_reserved
FROM sandboxes
WHERE status IN ('running', 'starting', 'paused')
GROUP BY team_id
`
type SampleSandboxMetricsRow struct {
TeamID string `json:"team_id"`
RunningCount int32 `json:"running_count"`
VcpusReserved int32 `json:"vcpus_reserved"`
MemoryMbReserved int32 `json:"memory_mb_reserved"`
}
// Aggregates per-team resource usage from the live sandboxes table.
// paused sandboxes count at 50% (ceil) for capacity reservation.
func (q *Queries) SampleSandboxMetrics(ctx context.Context) ([]SampleSandboxMetricsRow, error) {
rows, err := q.db.Query(ctx, sampleSandboxMetrics)
if err != nil {
return nil, err
}
defer rows.Close()
var items []SampleSandboxMetricsRow
for rows.Next() {
var i SampleSandboxMetricsRow
if err := rows.Scan(
&i.TeamID,
&i.RunningCount,
&i.VcpusReserved,
&i.MemoryMbReserved,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}