feat(query): include session totals and stable framework names

This commit is contained in:
William Valentin
2026-05-20 17:35:56 -07:00
parent db73eca6fd
commit 78376bdd83
5 changed files with 82 additions and 3 deletions
+1 -1
View File
@@ -33,7 +33,7 @@ func (d *DB) GetSessionWithRuns(ctx context.Context, sessionID string) (*Session
session_id,
MIN(ts) as started_at,
MAX(CASE WHEN type = 'session.end' THEN ts END) as ended_at,
MAX(source_framework) as framework,
COALESCE((ARRAY_AGG(source_framework ORDER BY CASE WHEN type = 'session.start' THEN 0 ELSE 1 END, ts) FILTER (WHERE source_framework IS NOT NULL))[1], 'unknown') as framework,
MAX(payload->'event'->'source'->>'host') as host
FROM events
WHERE session_id = $1
+57 -1
View File
@@ -89,7 +89,7 @@ func (d *DB) ListSessions(ctx context.Context, f SessionsFilter) ([]SessionRow,
session_id,
MIN(ts) as started_at,
MAX(CASE WHEN type = 'session.end' THEN ts END) as ended_at,
MAX(source_framework) as framework,
COALESCE((ARRAY_AGG(source_framework ORDER BY CASE WHEN type = 'session.start' THEN 0 ELSE 1 END, ts) FILTER (WHERE source_framework IS NOT NULL))[1], 'unknown') as framework,
MAX(client_id) as client_id,
MAX(payload->'event'->'source'->>'host') as host,
COUNT(DISTINCT run_id) as run_count
@@ -136,3 +136,59 @@ func (d *DB) ListSessions(ctx context.Context, f SessionsFilter) ([]SessionRow,
return out, nextCursor, rows.Err()
}
// CountSessions returns the total number of sessions matching the filter (without limit or cursor).
func (d *DB) CountSessions(ctx context.Context, f SessionsFilter) (int, error) {
var innerConditions []string
var outerConditions []string
var args []any
argN := 1
if f.From == nil {
t := time.Now().Add(-24 * time.Hour)
f.From = &t
}
innerConditions = append(innerConditions, fmt.Sprintf("ts >= $%d", argN))
args = append(args, *f.From)
argN++
if f.To != nil {
innerConditions = append(innerConditions, fmt.Sprintf("ts <= $%d", argN))
args = append(args, *f.To)
argN++
}
if f.Framework != "" {
innerConditions = append(innerConditions, fmt.Sprintf("source_framework = $%d", argN))
args = append(args, f.Framework)
argN++
}
if f.Host != "" {
outerConditions = append(outerConditions, fmt.Sprintf("host = $%d", argN))
args = append(args, f.Host)
argN++
}
innerWhere := strings.Join(innerConditions, " AND ")
outerWhere := ""
if len(outerConditions) > 0 {
outerWhere = "WHERE " + strings.Join(outerConditions, " AND ")
}
query := fmt.Sprintf(`
WITH session_groups AS (
SELECT
session_id,
MAX(payload->'event'->'source'->>'host') as host
FROM events
WHERE session_id IS NOT NULL AND %s
GROUP BY session_id
)
SELECT COUNT(*) FROM session_groups %s
`, innerWhere, outerWhere)
var count int
err := d.sql.QueryRowContext(ctx, query, args...).Scan(&count)
return count, err
}
+1 -1
View File
@@ -51,7 +51,7 @@ func (d *DB) GetSummary(ctx context.Context) (*Summary, error) {
WITH session_groups AS (
SELECT
session_id,
COALESCE(MAX(source_framework), 'unknown') AS framework,
COALESCE((ARRAY_AGG(source_framework ORDER BY CASE WHEN type = 'session.start' THEN 0 ELSE 1 END, ts) FILTER (WHERE source_framework IS NOT NULL))[1], 'unknown') AS framework,
MAX(ts) AS last_event_at,
BOOL_OR(type = 'session.start') AS has_start,
BOOL_OR(type = 'session.end') AS has_end