Remove Jinja2 template fallback (1249 lines) — /admin/performance now serves Vue SPA exclusively via send_from_directory. Backend: - Add _SLOW_QUERY_WAITING counter with get_slow_query_waiting_count() - Record slow-path latency in read_sql_df_slow/iter via record_query_latency() - Extend metrics_history schema with slow_query_active, slow_query_waiting, worker_rss_bytes columns + ALTER TABLE migration for existing DBs - Add cleanup_archive_logs() with configurable ARCHIVE_LOG_DIR/KEEP_COUNT - Integrate archive cleanup into MetricsHistoryCollector 50-min cycle Frontend: - Add slow_query_active and slow_query_waiting StatCards to connection pool - Add slow_query_active trend line to pool trend chart - Add Worker memory (RSS MB) trend chart with preprocessing - Update modernization gate check path to frontend style.css Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
3.1 KiB
ADDED Requirements
Requirement: Slow query active count in metrics history snapshots
The MetricsHistoryCollector SHALL include slow_query_active in each 30-second snapshot, recording the number of slow queries currently executing via dedicated connections.
Scenario: Snapshot includes slow_query_active
- WHEN the collector writes a snapshot while 3 slow queries are executing
- THEN the
slow_query_activecolumn SHALL contain the value 3
Scenario: No slow queries active
- WHEN the collector writes a snapshot while no slow queries are executing
- THEN the
slow_query_activecolumn SHALL contain the value 0
Requirement: Slow query waiting count tracked and persisted
The system SHALL maintain a thread-safe counter _SLOW_QUERY_WAITING in database.py that tracks the number of threads currently waiting to acquire the slow query semaphore. This counter SHALL be included in get_pool_status() and persisted to metrics history snapshots.
Scenario: Counter increments on semaphore wait
- WHEN a thread enters
read_sql_df_slow()and the semaphore is full - THEN
_SLOW_QUERY_WAITINGSHALL be incremented beforesemaphore.acquire()and decremented after acquire completes (success or timeout)
Scenario: Counter in pool status API
- WHEN
get_pool_status()is called - THEN the returned dict SHALL include
slow_query_waitingwith the current waiting thread count
Scenario: Counter persisted to metrics history
- WHEN the collector writes a snapshot
- THEN the
slow_query_waitingcolumn SHALL reflect the count at snapshot time
Requirement: Slow-path query latency recorded in QueryMetrics
The read_sql_df_slow() and read_sql_df_slow_iter() functions SHALL call record_query_latency() with the elapsed query time, so that P50/P95/P99 metrics reflect all query paths (pool + slow).
Scenario: Slow query latency appears in percentiles
- WHEN a
read_sql_df_slow()call completes in 5.2 seconds - THEN
record_query_latency(5.2)SHALL be called and the latency SHALL appear in subsequentget_percentiles()results
Scenario: Slow iter latency recorded on completion
- WHEN a
read_sql_df_slow_iter()generator completes after yielding all batches in 120 seconds total - THEN
record_query_latency(120.0)SHALL be called in the finally block
Requirement: Slow query metrics displayed in Vue SPA
The admin performance Vue SPA SHALL display slow_query_active and slow_query_waiting as StatCards in the connection pool panel, and include slow_query_active as a trend line in the connection pool trend chart.
Scenario: StatCards display current values
- WHEN the performance-detail API returns
db_pool.status.slow_query_active = 4anddb_pool.status.slow_query_waiting = 2 - THEN the connection pool panel SHALL display StatCards showing "慢查詢執行中: 4" and "慢查詢排隊中: 2"
Scenario: Trend chart includes slow_query_active
- WHEN historical snapshots contain
slow_query_activedata points - THEN the connection pool trend chart SHALL include a "慢查詢執行中" line series