fix: count only live dashboard sessions
This commit is contained in:
@@ -160,7 +160,14 @@ function renderSummaryCards() {
|
|||||||
const fws = Object.keys(s.by_framework || {});
|
const fws = Object.keys(s.by_framework || {});
|
||||||
if (fws.length > 0) {
|
if (fws.length > 0) {
|
||||||
const sub = document.getElementById('dash-active-sub');
|
const sub = document.getElementById('dash-active-sub');
|
||||||
if (sub) sub.textContent = fws.map(f => `${f} ${(s.by_framework[f].runs || 0)}`).join(' · ');
|
if (sub) {
|
||||||
|
const activeByFramework = fws
|
||||||
|
.map(f => [f, s.by_framework[f].active_sessions || 0])
|
||||||
|
.filter(([, count]) => count > 0);
|
||||||
|
sub.textContent = activeByFramework.length > 0
|
||||||
|
? activeByFramework.map(([f, count]) => `${f} ${count}`).join(' · ')
|
||||||
|
: 'no live sessions';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const errEl = document.getElementById('dash-errors');
|
const errEl = document.getElementById('dash-errors');
|
||||||
|
|||||||
@@ -6,9 +6,10 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type FrameworkStats struct {
|
type FrameworkStats struct {
|
||||||
Runs int `json:"runs"`
|
ActiveSessions int `json:"active_sessions"`
|
||||||
Tools int `json:"tools"`
|
Runs int `json:"runs"`
|
||||||
Errors int `json:"errors"`
|
Tools int `json:"tools"`
|
||||||
|
Errors int `json:"errors"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Summary struct {
|
type Summary struct {
|
||||||
@@ -44,23 +45,47 @@ func (d *DB) GetSummary(ctx context.Context) (*Summary, error) {
|
|||||||
now := time.Now()
|
now := time.Now()
|
||||||
midnight := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())
|
midnight := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())
|
||||||
|
|
||||||
// Active sessions: sessions with a session.start but no session.end (last 7 days)
|
// Active sessions are open sessions with recent activity. Some hook sources can
|
||||||
|
// miss session.end, so "started but never ended" alone overstates live work.
|
||||||
activeQ := `
|
activeQ := `
|
||||||
SELECT COUNT(DISTINCT e.session_id)
|
WITH session_groups AS (
|
||||||
FROM events e
|
SELECT
|
||||||
WHERE e.type = 'session.start'
|
session_id,
|
||||||
AND e.session_id IS NOT NULL
|
COALESCE(MAX(source_framework), 'unknown') AS framework,
|
||||||
AND e.ts >= $1
|
MAX(ts) AS last_event_at,
|
||||||
AND NOT EXISTS (
|
BOOL_OR(type = 'session.start') AS has_start,
|
||||||
SELECT 1
|
BOOL_OR(type = 'session.end') AS has_end
|
||||||
FROM events e2
|
FROM events
|
||||||
WHERE e2.type = 'session.end'
|
WHERE session_id IS NOT NULL
|
||||||
AND e2.session_id = e.session_id
|
GROUP BY session_id
|
||||||
)
|
)
|
||||||
|
SELECT framework, COUNT(*)
|
||||||
|
FROM session_groups
|
||||||
|
WHERE has_start
|
||||||
|
AND NOT has_end
|
||||||
|
AND last_event_at >= $1
|
||||||
|
GROUP BY framework
|
||||||
`
|
`
|
||||||
|
activeRows, err := d.sql.QueryContext(ctx, activeQ, now.Add(-15*time.Minute))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer activeRows.Close()
|
||||||
|
|
||||||
|
byFramework := make(map[string]FrameworkStats)
|
||||||
var activeSessions int
|
var activeSessions int
|
||||||
activeSessionsSince := time.Now().Add(-7 * 24 * time.Hour)
|
for activeRows.Next() {
|
||||||
if err := d.sql.QueryRowContext(ctx, activeQ, activeSessionsSince).Scan(&activeSessions); err != nil {
|
var fw string
|
||||||
|
var count int
|
||||||
|
if err := activeRows.Scan(&fw, &count); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
fs := byFramework[fw]
|
||||||
|
fs.ActiveSessions = count
|
||||||
|
byFramework[fw] = fs
|
||||||
|
activeSessions += count
|
||||||
|
}
|
||||||
|
if err := activeRows.Err(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,7 +108,6 @@ func (d *DB) GetSummary(ctx context.Context) (*Summary, error) {
|
|||||||
}
|
}
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
|
|
||||||
byFramework := make(map[string]FrameworkStats)
|
|
||||||
var totalRuns, totalTools, totalErrors int
|
var totalRuns, totalTools, totalErrors int
|
||||||
|
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
@@ -92,6 +116,9 @@ func (d *DB) GetSummary(ctx context.Context) (*Summary, error) {
|
|||||||
if err := rows.Scan(&fw, &fs.Runs, &fs.Tools, &fs.Errors); err != nil {
|
if err := rows.Scan(&fw, &fs.Runs, &fs.Tools, &fs.Errors); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if existing, ok := byFramework[fw]; ok {
|
||||||
|
fs.ActiveSessions = existing.ActiveSessions
|
||||||
|
}
|
||||||
byFramework[fw] = fs
|
byFramework[fw] = fs
|
||||||
totalRuns += fs.Runs
|
totalRuns += fs.Runs
|
||||||
totalTools += fs.Tools
|
totalTools += fs.Tools
|
||||||
|
|||||||
Reference in New Issue
Block a user