Commit Graph

20 Commits

Author SHA1 Message Date
stellarshenson
9162de622f fix: volume sizes logging and tooltip cleanup
- Add _get_logger() helper for JupyterHub application logger integration
- Module-level logger doesn't inherit JupyterHub handlers, causing
  invisible logs for VolumeSizeRefresher and Volume Sizes operations
- Update all volume-related functions to use _get_logger()
- Add cache validation to prevent empty results overwriting valid cache
- Remove "(>8h/day)" suffix from activity tooltip when score > 100%
2026-01-26 12:57:32 +01:00
stellarshenson
d2a93a08f2 fix: Auth column width and Volumes tooltip
- Increased .col-auth width from 4em to 5em to prevent truncation
- Changed Volumes tooltip to generic "hover for breakdown" since
  volume names are autodiscovered
2026-01-25 12:50:06 +01:00
stellarshenson
845d458d75 feat: add column tooltips and authorization status column
- Added explanatory tooltips to all 9 column headers in Activity Monitor
- Added sortable Auth column showing NativeAuthenticator authorization status
- Green checkmark for authorized users, red X for not authorized
- Backend queries users_info table with graceful fallback
- Updated documentation with new column and API schema
2026-01-25 12:44:11 +01:00
stellarshenson
ad1d37b16f feat: add 24h minimum data requirement for activity score
- Activity tooltip shows "Not enough data (Nh of 24h collected)" until
  sufficient samples collected (144 samples at 10-min intervals)
- Progress bar still renders to show emerging trend, tooltip clarifies
  percentage not yet reliable
- Added activitymon_sample_interval to template_vars for frontend access
- Rewrote docs/activity-tracking-methodology.md as comprehensive
  implementation specification covering data collection, scoring formulas,
  UI components, API endpoints, and design rationale
2026-01-25 12:25:38 +01:00
stellarshenson
05c99624d9 feat: add activity score normalization with TARGET_HOURS
Added JUPYTERHUB_ACTIVITYMON_TARGET_HOURS env var (default 8) to
normalize activity scores based on expected daily work hours.

- Raw score (% of sampled time active) normalized to target
- 8h/day worker with 33% raw score -> 100% normalized
- Progress bar capped at 5 segments (100%)
- Tooltip shows real % with "(>8h/day)" indicator if over 100%

Files: Dockerfile, settings_dictionary.yml, jupyterhub_config.py,
activity.html
2026-01-25 12:17:26 +01:00
stellarshenson
8980e552cf refactor: simplify Activity column header
Removed "(7 days)" suffix from Activity column header in activity.html.
The retention period is a configuration detail, not needed in the UI.
2026-01-25 11:48:49 +01:00
stellarshenson
ea5e8b730a feat: add volume size tooltip with per-volume breakdown
Activity Monitor now shows hover tooltip on volume sizes displaying
individual volume sizes (home, workspace, cache) instead of just total.

Backend changes:
- _fetch_volume_sizes() returns {total, volumes: {suffix: size}}
- ActivityDataHandler passes volume_breakdown to frontend

Frontend changes:
- formatVolumeSize() displays tooltip with sorted volume list
- Dotted underline indicates tooltip availability

Also: removed clean dependency from build targets in Makefile
2026-01-22 22:39:54 +01:00
stellarshenson
a2b7a0249a fix: activity bar colors 1=red, 2-3=yellow, 4-5=green 2026-01-21 16:50: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
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
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
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
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
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