Commit Graph

270 Commits

Author SHA1 Message Date
stellarshenson
a2b7a0249a fix: activity bar colors 1=red, 2-3=yellow, 4-5=green 2026-01-21 16:50:36 +01:00
stellarshenson
e94680178c updated version 3.7.14_cuda-13.0.2_jh-5.4.2 2026-01-21 15:53:20 +01:00
stellarshenson
887a3569fb fix: pass db and find_user to activity sampler instead of app
The sampler was expecting an app object with db and users attributes,
but handler settings don't provide that. Changed to pass handler's
self.db and self.find_user directly to the sampler.

Also added flush=True to print statements for immediate log output.
2026-01-21 15:01:13 +01:00
stellarshenson
b8ab1f6614 fix: lazy start activity sampler on first Activity page access
post_init_hook is not a valid JupyterHub config option - sampler never
started. Changed to lazy initialization: ActivityDataHandler starts
the sampler when admin first visits the Activity page.
2026-01-21 14:56:41 +01:00
stellarshenson
24c51a959c feat: background activity sampler with Tornado PeriodicCallback
Add ActivitySampler singleton class that automatically samples activity
for ALL users (active, idle, offline) at configurable interval using
Tornado's PeriodicCallback for non-blocking execution.

- Uses JUPYTERHUB_ACTIVITYMON_ACTIVITY_UPDATE_INTERVAL (default 600s)
- Starts via post_init_hook after JupyterHub initialization
- Runs first sample immediately on startup
- Logs tick statistics after each sample cycle
- Fixes: missing parenthesis and stray code from previous edit
2026-01-21 14:38:17 +01:00
stellarshenson
7f9fb3f871 feat: activity sampling for all users including offline
- Added record_samples_for_all_users() to sample ALL users
- Offline users marked inactive (activity bars decay over time)
- New API: POST /hub/api/activity/sample (admin, for cron jobs)
- Returns counts: total, active, inactive, offline
2026-01-21 13:40:23 +01:00
stellarshenson
2c561490b3 perf: background caching for volume sizes
- Volume sizes now cached and refreshed hourly in background
- Activity page loads instantly (no longer waits for docker df)
- Added JUPYTERHUB_ACTIVITYMON_VOLUMES_UPDATE_INTERVAL (default 3600s)
- First load shows empty volumes until background refresh completes
2026-01-21 08:56:36 +01:00
stellarshenson
48da028968 feat: add Volumes column to activity monitor
- Backend: get_all_user_volumes_sizes() fetches Docker volume sizes
- Frontend: sortable Volumes column with human-friendly display (GB/MB)
- Badge now shows "N users (x active, y idle, z offline)"
- CSS: .col-volumes class (8em width)
2026-01-21 08:45:27 +01:00
stellarshenson
a118bb6d7f fix: remove CPU/Memory color coding in activity monitor
Threshold-based coloring (green/yellow/red) doesn't work for
multi-core systems where CPU usage can exceed 100% (e.g., 6400%
on 64-core machines). Now displays plain text values.
2026-01-21 08:37:29 +01:00
stellarshenson
b80f10a36c updated with new version 2026-01-20 21:41:30 +01:00
stellarshenson
3ab2106c37 style: adjust activity table column widths for better proportions
- CPU: 7.5em, Memory: 9em, Time Left: 12em
- Last Active: 13.5em, Activity: 20em
- User column takes remaining space
- table-layout: fixed with 100% width
3.7.10_cuda-13.0.2_jh-5.4.2
2026-01-20 21:35:24 +01:00
stellarshenson
d691390549 feat: show all users in activity monitor and refactor table styles
- Activity Monitor now shows all users with historical activity, not just active servers
- Badge changed from "X active servers" to "X users (Y active)" format
- Status column now sortable (green > amber > red priority)
- Default sort changed to status descending with secondary sort by username
- Moved inline table styles to CSS classes using em units
- Added .activity-table, .settings-table, .notifications-table classes
- Simplified Activity page subtitle
2026-01-20 21:26:24 +01:00
stellarshenson
21501e0a2d feat: add JUPYTERHUB_ACTIVITYMON_SAMPLING_INTERVAL env var
- Add sampling interval config (default 600s / 10min)
- Separate from RESOURCES_UPDATE_INTERVAL (10s for UI refresh)
- Sampling interval controls how often activity samples are recorded
- Added to Dockerfile, settings_dictionary.yml, and ActivityMonitor class
2026-01-20 20:40:33 +01:00
stellarshenson
9262e30fe8 refactor: separate resource refresh from activity sampling
- Remove "Measured X ago" timer display (adds no value)
- Change auto-refresh interval from 30s to 10s for real-time monitoring
- Add JUPYTERHUB_ACTIVITYMON_RESOURCES_UPDATE_INTERVAL env var (default 10s)
- Resource refresh updates status, CPU, memory, timers only
- Activity sampling is separate (controlled by background process)
- Remove formatTimeAgo function and related timestamp tracking
2026-01-20 20:39:10 +01:00
stellarshenson
094be29d6d feat: add column sorting and improved last active display
- Add clickable column sorting for User, CPU, Memory, Time Left, Last Active
- Sorting cycles: descending -> ascending -> none (default)
- Sort icons show current direction
- Last Active now shows full words ("8 minutes ago", "4 months ago")
- Proper singular/plural handling for time units
2026-01-20 20:33:23 +01:00
stellarshenson
221ab54162 docs: update journal with activity monitor improvements 3.7.9_cuda-13.0.2_jh-5.4.2 2026-01-20 19:35:05 +01:00
stellarshenson
c1cabde01c fix: hide 'Measured' text when time empty, simplify settings text
- Only show "Measured X ago" when timeAgo has value
- Remove compose.yml/compose_override.yml mention from Settings page
2026-01-20 19:34:08 +01:00
stellarshenson
04ef42ce41 refactor: remove sample interval, simplify activity sampling
- Remove JUPYTERHUB_ACTIVITYMON_SAMPLE_INTERVAL env var entirely
- Remove on-demand sampling from activity page view
- Simplify record_sample() to always insert (caller controls frequency)
- Fix formatTimeAgo to show nothing when time ≤0s
- Update Dockerfile, settings_dictionary.yml, custom_handlers.py
2026-01-20 19:29:26 +01:00
stellarshenson
ff32729bd6 docs: update journal with activity monitor improvements 2026-01-20 19:06:38 +01:00
stellarshenson
064c553808 feat: dynamic refresh timer and simplified last active display
- "Measured X ago" now updates every second (shows 5s ago, 3min ago, etc.)
- Last Active column left-aligned and shows rounded times (5min, 2h, 3d)
- Removed redundant minutes/hours from time display
2026-01-20 19:06:17 +01:00
stellarshenson
4b2fc084bf fix: use separate SQLite database for activity monitor
- ActivityMonitor now uses /data/activity_samples.sqlite instead of
  JupyterHub's main database to avoid SQLite locking conflicts
- Fixes "database is locked" errors that prevented login when both
  JupyterHub and ActivityMonitor wrote simultaneously
- Added "Last Active" column to activity table showing relative time
2026-01-20 19:04:39 +01:00
stellarshenson
66de0e7c5c fix: activity bar UI redesign and sample cleanup enforcement
- Redesign activity bar as thin continuous bar (80x8px) with subtle dividers
- Fix inconsistent timestamp text ("Last updated" vs "Measured")
- Fix sample cleanup to always run on record_sample(), not just on inserts
- Ensures samples older than RETENTION_DAYS are properly pruned
2026-01-20 18:53:03 +01:00
stellarshenson
d793f5a68d updated 3.7.3_cuda-13.0.2_jh-5.4.2 2026-01-20 17:49:45 +01:00
stellarshenson
60eb59a854 docs: clarify sample update vs insert behavior in docstring 2026-01-20 17:21:31 +01:00
stellarshenson
aecd6821c7 fix: update last sample on refresh instead of inserting new one 2026-01-20 17:21:15 +01:00
stellarshenson
5f0aa860be docs: update journal with refresh spinner and relative time 2026-01-20 17:16:27 +01:00
stellarshenson
a0dee35bd6 fix: add spinner to refresh button and show relative time 2026-01-20 17:16:00 +01:00
stellarshenson
5e563af39b feat: add Activity Monitor admin page with 3-state status and reset functionality
- Add ActivitySample SQLAlchemy model for database persistence
- Add ActivityMonitor singleton with scoring, reset, lifecycle methods
- Add JUPYTERHUB_ACTIVITYMON_INACTIVE_AFTER env var (default 60 min)
- Update defaults: SAMPLE_INTERVAL=600s, RETENTION_DAYS=7
- Fix score calculation to use measured samples only (not theoretical max)
- Add 3-state status: green (active), yellow (inactive), red (offline)
- Add recently_active field in API response
- Add Reset button with confirmation dialog
- Fix green color (explicit #28a745 instead of text-success)
- Add ThreadPoolExecutor for non-blocking Docker stats
- Remove old background sampler code (on-demand sampling now)
- Bump version to 3.7.0
2026-01-20 17:08:23 +01:00
stellarshenson
8a4be041ac docs: update journal with spawner.orm_spawner.last_activity fix CHECKPOINT_BEFORE_ACTIVITY_TAB_3.6.24 FIX_SPAWNER_ACTIVITY_TRACKING_3.6.24 3.6.28_cuda-13.0.2_jh-5.4.2 3.6.24_cuda-13.0.2_jh-5.4.2 2026-01-20 10:08:35 +01:00
stellarshenson
30f3000ab7 chore: bump version to 3.6.24 2026-01-20 10:08:03 +01:00
stellarshenson
d2ff63b2e1 fix: use spawner.orm_spawner.last_activity (Server object has no last_activity) 2026-01-20 10:05:53 +01:00
stellarshenson
44f8ce0318 docs: update journal with server.last_activity fix and checkpoint command 2026-01-20 10:02:35 +01:00
stellarshenson
5d24f17900 fix: use server.last_activity instead of user.last_activity for idle tracking
- user.last_activity updates on Hub page access (causes timer reset on refresh)
- server.last_activity only updates on actual JupyterLab activity
- Matches what jupyterhub-idle-culler uses for culling decisions
2026-01-20 10:01:52 +01:00
stellarshenson
4b4f254dfb docs: clarify checkpoint tag format - shortened version as suffix 2026-01-20 09:47:42 +01:00
stellarshenson
f0f1ddc0ee docs: rename short_version to version_suffix in checkpoint command 2026-01-20 09:47:16 +01:00
stellarshenson
8fa6fa0dd9 feat: add /checkpoint command for creating milestone tags 2026-01-20 09:46:54 +01:00
stellarshenson
a5fd82b3ea updated version CHECKPOINT_BEFORE_ACTIVITY_TRACKER_3.6.22 2026-01-19 08:06:52 +01:00
stellarshenson
b440a7fe07 fix: show max extension error as disappearing warning alert, remove duplicate static text 3.6.22_cuda-13.0.2_jh-5.4.2 2026-01-18 21:58:25 +01:00
stellarshenson
d492232802 updated version 2026-01-18 21:48:00 +01:00
stellarshenson
439472999d fix: show max hours in extension limit warning message 3.6.21_cuda-13.0.2_jh-5.4.2 2026-01-18 21:45:24 +01:00
stellarshenson
7c9d78d4a5 updated version 3.6.20_cuda-13.0.2_jh-5.4.2 2026-01-18 21:24:32 +01:00
stellarshenson
af9c415d4b docs: update journal with extend button behavior 2026-01-18 21:23:20 +01:00
stellarshenson
3264c26d6b fix: keep extend button enabled when max reached (backend handles rejection) 2026-01-18 21:22:44 +01:00
stellarshenson
6762a5739a fix: truncate excess extension hours instead of rejecting request
- Truncate requested hours to max available instead of returning error
- Add 'truncated' flag in API response with detailed message
- UI shows warning alert (yellow) when truncated, success (green) otherwise
- Warning displays 4 seconds vs 2 seconds for normal success
- Fixed extend button re-enable after successful extension
2026-01-18 21:18:47 +01:00
stellarshenson
42180502e7 fix: extension now ADDS hours (cumulative), added detailed logging 2026-01-18 21:11:34 +01:00
stellarshenson
63efb1a264 fix: simplify session extension - reset activity and SET hours (not add) 2026-01-18 21:04:24 +01:00
stellarshenson
61807cac1f fix: session extension now adds hours instead of resetting timer 2026-01-18 21:03:09 +01:00
stellarshenson
de3863ef5e fix: use offset-naive datetime for last_activity to match JupyterHub internal format 2026-01-18 21:01:28 +01:00
stellarshenson
1d5fb93c49 feat: improve session extension UI with numeric input and idle note 2026-01-18 20:56:58 +01:00
stellarshenson
e0ceed8004 feat: add idle culler session extension and harmonize env settings
Session Extension Feature:
- Add JUPYTERHUB_IDLE_CULLER_MAX_EXTENSION env var (default 24h)
- Add SessionInfoHandler and ExtendSessionHandler API endpoints
- Add Session Status card to home page with countdown timer
- Extension tracking in spawner state (resets on server restart)
- Color-coded warnings (yellow <1h, red <30min)

Environment Settings Harmonization:
- Add all ENV defaults to Dockerfile
- Add idle culler settings to compose.yml
- Standardize logo as JUPYTERHUB_LOGO_URI with file:// prefix
- Update NVIDIA_IMAGE to nvidia/cuda:13.0.2-base-ubuntu24.04
2026-01-18 20:28:33 +01:00