fix(observability): fix top performers data loss, dead guards, display bugs, and response time unit conversion#3794
Conversation
86c42bd to
ddf6b1a
Compare
07be570 to
342b76c
Compare
342b76c to
45faa1d
Compare
45faa1d to
8d2339b
Compare
|
Hi @mxwlantian, Can you please help me review this PR? It includes changes for #3580 |
|
Thanks @shoummu1 — good catch on the data loss and unit conversion issues. Small, targeted fix. Please add the DCO |
439dd19 to
548164b
Compare
548164b to
b879f83
Compare
Maintainer review notesRebased onto current Rebase conflict resolution
Changes made during reviewBug fix — CSV export zero-value handling: Dead code removal — Trailing whitespace fix in Test fixes:
Verification
|
…bugs Signed-off-by: Shoumi <shoumimukherjee@gmail.com>
…ards Signed-off-by: Shoumi <shoumimukherjee@gmail.com>
…e ms conversion Signed-off-by: Shoumi <shoumimukherjee@gmail.com>
…bug, add differential tests - Remove unreachable avgResponseTime/lastExecutionTime branches from createPerformanceCard (its metrics list only has memory/CPU/disk/network keys) - Fix CSV export treating avg_response_time=0 as N/A by using != null instead of truthiness check, consistent with table rendering - Fix trailing whitespace in updateTableRows - Update modularized test assertion for ×1000 conversion (150 → 150000) - Add JS tests for createMetricsCard: seconds→ms conversion, ISO datetime formatting, null handling, zero-value preservation - Add Python test verifying build_top_performers preserves 0.0 values Closes #3793, Closes #3580 Signed-off-by: Mihai Criveti <crivetimihai@gmail.com>
b879f83 to
4b137ec
Compare
…y bugs, and response time unit conversion (#3794) * fix metrics top performers panel data loss, dead guards, and display bugs Signed-off-by: Shoumi <shoumimukherjee@gmail.com> * convert avg_response_time seconds to ms in admin.js KPI and metrics cards Signed-off-by: Shoumi <shoumimukherjee@gmail.com> * update vitest assertions and prettier formatting for avg_response_time ms conversion Signed-off-by: Shoumi <shoumimukherjee@gmail.com> * fix: remove dead code from createPerformanceCard, fix CSV zero-value bug, add differential tests - Remove unreachable avgResponseTime/lastExecutionTime branches from createPerformanceCard (its metrics list only has memory/CPU/disk/network keys) - Fix CSV export treating avg_response_time=0 as N/A by using != null instead of truthiness check, consistent with table rendering - Fix trailing whitespace in updateTableRows - Update modularized test assertion for ×1000 conversion (150 → 150000) - Add JS tests for createMetricsCard: seconds→ms conversion, ISO datetime formatting, null handling, zero-value preservation - Add Python test verifying build_top_performers preserves 0.0 values Closes #3793, Closes #3580 Signed-off-by: Mihai Criveti <crivetimihai@gmail.com> --------- Signed-off-by: Shoumi <shoumimukherjee@gmail.com> Signed-off-by: Mihai Criveti <crivetimihai@gmail.com> Co-authored-by: Mihai Criveti <crivetimihai@gmail.com>
…y bugs, and response time unit conversion (#3794) * fix metrics top performers panel data loss, dead guards, and display bugs Signed-off-by: Shoumi <shoumimukherjee@gmail.com> * convert avg_response_time seconds to ms in admin.js KPI and metrics cards Signed-off-by: Shoumi <shoumimukherjee@gmail.com> * update vitest assertions and prettier formatting for avg_response_time ms conversion Signed-off-by: Shoumi <shoumimukherjee@gmail.com> * fix: remove dead code from createPerformanceCard, fix CSV zero-value bug, add differential tests - Remove unreachable avgResponseTime/lastExecutionTime branches from createPerformanceCard (its metrics list only has memory/CPU/disk/network keys) - Fix CSV export treating avg_response_time=0 as N/A by using != null instead of truthiness check, consistent with table rendering - Fix trailing whitespace in updateTableRows - Update modularized test assertion for ×1000 conversion (150 → 150000) - Add JS tests for createMetricsCard: seconds→ms conversion, ISO datetime formatting, null handling, zero-value preservation - Add Python test verifying build_top_performers preserves 0.0 values Closes #3793, Closes #3580 Signed-off-by: Mihai Criveti <crivetimihai@gmail.com> --------- Signed-off-by: Shoumi <shoumimukherjee@gmail.com> Signed-off-by: Mihai Criveti <crivetimihai@gmail.com> Co-authored-by: Mihai Criveti <crivetimihai@gmail.com>
Bug-fix PR
📌 Summary
Fixes five silent display/logic bugs in the Top Performers metrics panel (#3793) and resolves the response time unit inconsistency (seconds displayed as milliseconds) across all three monitoring panels in the Admin UI (#3580): Top Performers, KPI cards, and individual entity metrics cards.
🔗 Related Issues
Closes: #3793
Closes: #3580
🔁 Reproduction Steps
See #3793 for full steps. Minimal:
2026-03-13T06:00:00.000000) displayed0.0%with red badge instead ofN/A1.194) instead of milliseconds (1194ms)🐞 Root Cause
Six bugs across three files:
metrics_common.pybuild_top_performers()used falsy checks (if result.success_rate,if result.avg_response_time) which coerced genuine0.0toNone, losing the distinction between "no data" and actual zerometrics_top_performers_partial.html!= 'N/A'guard —avgResponseTimeisOptional[float], never the string'N/A'; branch was unreachablemetrics_top_performers_partial.html!= 'Never'guard —lastExecutionisNoneor an ISO string, never the string'Never'; branch was unreachablemetrics_top_performers_partial.html{{ last_exec }}rendered the raw ISO-8601 datetime verbatim instead of a human-readable formatmetrics_top_performers_partial.htmlitem.get('successRate', 0) or 0collapsedNone(no executions) into0, making un-executed tools display0.0%with a red error badgemetrics_top_performers_partial.html,admin.jsavg_response_time(stored in seconds) was rendered without×1000conversion across Top Performers template, KPI cards, entity metrics cards, paginated table rows, and CSV export💡 Fix Description
mcpgateway/utils/metrics_common.pyis not Noneguards so0.0values are preserved:mcpgateway/templates/metrics_top_performers_partial.html!= 'N/A'guard;Nonecheck is sufficient×1000conversion foravgResponseTime(seconds → ms)item.get('successRate', 0) or 0with a properNone-aware check; rendersN/A(no badge) for un-executed tools!= 'Never'guard{{ last_exec }}with{{ last_exec[:16] | replace('T', ' ') }}→ e.g.2026-03-13 06:00mcpgateway/static/admin.jsextractKPIData: multiplied weighted averageavgResponseTimeby×1000before returning to KPI displaycreateTopPerformersTable/updateTableRows:||→??(preserves0.0) +×1000conversion applied consistently to both initial render and paginated updatesexportMetricsToCSV: same??+×1000fix so downloaded CSV values match the UIcreateMetricsCard: added explicitavgResponseTimebranch (×1000,.toFixed(1) ms) andlastExecutionTimebranch (ISO slice →YYYY-MM-DD HH:mm)🧪 Verification
make lintmake testmake coverageManual checks performed:
1194ms✅2026-03-13 06:00✅100.0%badge for executed tool ✅N/A(no badge) for un-executed entities ✅1194.1 ms✅2026-03-13 06:00✅📐 MCP Compliance (if relevant)
✅ Checklist
make black isort pre-commit)