1
0
Fork 0
mirror of https://github.com/betaflight/betaflight-configurator.git synced 2025-07-26 01:35:28 +03:00

Suggestions per Coderabbit

This commit is contained in:
Mark Haslinghuis 2025-06-12 19:09:37 +02:00
parent 07ca99ad0d
commit 12d3ddfcaa
8 changed files with 258 additions and 184 deletions

View file

@ -132,7 +132,8 @@ function startProcess() {
console.log(`Libraries: jQuery - ${$.fn.jquery}, three.js - ${THREE.REVISION}`); console.log(`Libraries: jQuery - ${$.fn.jquery}, three.js - ${THREE.REVISION}`);
// Check if this is the first visit // Check if this is the first visit
if (getConfig("firstRun").firstRun === undefined) { const firstRunCfg = getConfig("firstRun") ?? {};
if (firstRunCfg.firstRun === undefined) {
setConfig({ firstRun: true }); setConfig({ firstRun: true });
import("./tabs/static_tab.js").then(({ staticTab }) => { import("./tabs/static_tab.js").then(({ staticTab }) => {
staticTab.initialize("options", () => { staticTab.initialize("options", () => {

View file

@ -51,11 +51,14 @@ const MSP = {
message_buffer: null, message_buffer: null,
message_buffer_uint8_view: null, message_buffer_uint8_view: null,
message_checksum: 0, message_checksum: 0,
crcError: false,
callbacks: [], callbacks: [],
packet_error: 0, packet_error: 0,
unsupported: 0, unsupported: 0,
TIMEOUT: 1000,
last_received_timestamp: null, last_received_timestamp: null,
listeners: [], listeners: [],
@ -65,8 +68,6 @@ const MSP = {
cli_output: [], cli_output: [],
cli_callback: null, cli_callback: null,
TIMEOUT: 1000,
read(readInfo) { read(readInfo) {
if (CONFIGURATOR.virtualMode) { if (CONFIGURATOR.virtualMode) {
return; return;
@ -377,7 +378,6 @@ const MSP = {
return false; return false;
} }
// Create unique key combining code and data
const requestExists = this.callbacks.some((instance) => instance.code === code); const requestExists = this.callbacks.some((instance) => instance.code === code);
const bufferOut = code <= 254 ? this.encode_message_v1(code, data) : this.encode_message_v2(code, data); const bufferOut = code <= 254 ? this.encode_message_v1(code, data) : this.encode_message_v2(code, data);
@ -390,7 +390,6 @@ const MSP = {
start: performance.now(), start: performance.now(),
}; };
// Track only the first outstanding request for a given key
if (!requestExists) { if (!requestExists) {
obj.timer = setTimeout(() => { obj.timer = setTimeout(() => {
console.warn( console.warn(
@ -404,9 +403,7 @@ const MSP = {
// We should probably give up connection if the request takes too long ? // We should probably give up connection if the request takes too long ?
if (executionTime > 5000) { if (executionTime > 5000) {
console.warn( console.warn(
`MSP: data request took too long: ${code} ID: ${serial.connectionId} TAB: ${GUI.active_tab} TIMEOUT: ${ `MSP: data request took too long: ${code} ID: ${serial.connectionId} TAB: ${GUI.active_tab} EXECUTION TIME: ${executionTime}ms`,
this.timeout
} EXECUTION TIME: ${executionTime}ms`,
); );
} }

View file

@ -48,62 +48,82 @@ import('./src/js/msp_debug_tools.js');
**Start monitoring:** **Start monitoring:**
```javascript ```javascript
MSPTestRunner.startQuickMonitor(); MSPDebug.startMonitoring();
``` ```
**Show visual dashboard:** **Show visual dashboard:**
```javascript ```javascript
MSPTestRunner.showDashboard(); MSPDebug.show();
// Or press Ctrl+Shift+M // Or press Ctrl+Shift+M
``` ```
**Quick health check:** **Quick test of alert system:**
```javascript ```javascript
MSPTestRunner.quickHealthCheck(); MSPDebug.testAlerts();
``` ```
**Run stress tests:** **Run stress tests:**
```javascript ```javascript
// Run specific test // Run specific test
MSPTestRunner.runTest('queue-flooding'); MSPDebug.runTests();
// Run full test suite // Run complete stress test suite with detailed console output
MSPTestRunner.runFullSuite(); MSPDebug.runFullSuite();
// Run individual test by name
MSPDebug.runTest('queue-flooding');
// Quick health check
MSPDebug.quickHealthCheck();
// Run stress scenario
MSPDebug.stressScenario('high-frequency');
``` ```
## Available Commands ## Available Commands
The MSP Debug Tools provide two APIs:
- **MSPDebug**: Modern, simplified API (recommended)
- **MSPTestRunner**: Legacy API with additional methods
Both APIs provide the same core functionality. Use `MSPDebug` for new code.
### Monitoring Commands ### Monitoring Commands
| Command | Description | | Command | Description |
|---------|-------------| |---------|-------------|
| `MSPTestRunner.startQuickMonitor()` | Start monitoring with console output | | `MSPDebug.startMonitoring()` | Start monitoring with console output |
| `MSPTestRunner.stopMonitor()` | Stop monitoring | | `MSPDebug.stopMonitoring()` | Stop monitoring |
| `MSPTestRunner.getStatus()` | Get current MSP status | | `MSPDebug.getStatus()` | Get current MSP status |
| `MSPTestRunner.analyzeQueue()` | Analyze current queue contents | | `MSPDebug.monitor.getStatus()` | Get current MSP status (alternative) |
| `MSPDebug.analyze()` | Analyze current queue contents |
### Testing Commands ### Testing Commands
| Command | Description | | Command | Description |
|---------|-------------| |---------|-------------|
| `MSPTestRunner.runTest('test-name')` | Run specific stress test | | `MSPDebug.runTests()` | Run stress test suite |
| `MSPTestRunner.runFullSuite()` | Run complete test suite | | `MSPDebug.runFullSuite()` | Run complete stress test suite with detailed output |
| `MSPTestRunner.quickHealthCheck()` | Quick health validation | | `MSPDebug.runTest('test-name')` | Run a specific test by name |
| `MSPDebug.quickHealthCheck()` | Run a quick MSP health check |
| `MSPDebug.stressScenario('scenario')` | Run specific stress test scenario |
| `MSPDebug.testAlerts()` | Test alert system |
| `MSPDebug.triggerTestAlerts()` | Manually trigger alerts |
### Stress Scenarios ### Alert Testing
| Command | Description | | Command | Description |
|---------|-------------| |---------|-------------|
| `MSPTestRunner.stressScenario('high-frequency')` | High frequency request test | | `MSPDebug.setTestThresholds()` | Lower thresholds for easier testing |
| `MSPTestRunner.stressScenario('queue-overflow')` | Queue overflow handling test | | `MSPDebug.setNormalThresholds()` | Restore normal thresholds |
| `MSPTestRunner.stressScenario('mixed-load')` | Mixed request types test | | `MSPDebug.testAlerts()` | Complete alert system test |
### Visual Tools ### Visual Tools
| Command | Description | | Command | Description |
|---------|-------------| |---------|-------------|
| `MSPTestRunner.showDashboard()` | Show visual debug dashboard | | `MSPDebug.show()` | Show visual debug dashboard |
| `MSPTestRunner.generateReport()` | Generate and download report | | `MSPDebug.report()` | Generate and download report |
## Dashboard Interactions ## Dashboard Interactions
@ -139,15 +159,27 @@ The visual dashboard includes smart interaction handling to ensure a smooth user
## Available Tests ## Available Tests
1. **Queue Flooding** - Tests queue limits with many simultaneous requests ### Individual Test Names (for `runTest`)
2. **Rapid Fire Requests** - Tests high-frequency request handling
3. **Duplicate Request Handling** - Validates duplicate request management 1. **queue-flooding** - Tests queue limits with many simultaneous requests
4. **Timeout Recovery** - Tests timeout and retry mechanisms 2. **rapid-fire** - Tests high-frequency request handling
5. **Memory Leak Detection** - Checks for proper cleanup of completed requests 3. **duplicates** - Validates duplicate request management
6. **Concurrent Mixed Requests** - Tests various request types simultaneously 4. **timeout-recovery** - Tests timeout and retry mechanisms
7. **Queue Overflow Handling** - Tests behavior when queue reaches capacity 5. **memory-leaks** - Checks for proper cleanup of completed requests
8. **Connection Disruption** - Simulates connection issues 6. **concurrent-mixed** - Tests various request types simultaneously
9. **Performance Under Load** - Tests sustained load performance 7. **queue-overflow** - Tests behavior when queue reaches capacity
8. **connection-disruption** - Simulates connection issues
9. **performance-load** - Tests sustained load performance
### Stress Scenarios (for `stressScenario`)
- **high-frequency** - High-frequency requests every 10ms for 5 seconds
- **queue-overflow** - Floods queue beyond capacity
- **mixed-load** - Various request types and sizes
### Full Test Suite
The `runFullSuite()` command runs all individual tests in sequence with detailed console output and generates a comprehensive report.
## Monitoring Metrics ## Monitoring Metrics
@ -190,37 +222,50 @@ The visual dashboard provides:
### Development Testing ### Development Testing
```javascript ```javascript
// Start monitoring during development // Start monitoring during development
MSPTestRunner.startQuickMonitor(); MSPDebug.startMonitoring();
// Run quick health check after changes // Quick health check
MSPTestRunner.quickHealthCheck(); MSPDebug.quickHealthCheck();
// Test specific functionality // Test the alert system
MSPTestRunner.runTest('timeout-recovery'); MSPDebug.testAlerts();
// Show visual dashboard
MSPDebug.show();
``` ```
### Performance Analysis ### Performance Analysis
```javascript ```javascript
// Show dashboard for visual monitoring // Show dashboard for visual monitoring
MSPTestRunner.showDashboard(); MSPDebug.show();
// Run performance stress test // Run complete stress tests with detailed output
MSPTestRunner.stressScenario('high-frequency'); MSPDebug.runFullSuite();
// Test specific scenarios
MSPDebug.stressScenario('high-frequency');
// Generate detailed report // Generate detailed report
MSPTestRunner.generateReport(); MSPDebug.report();
``` ```
### Issue Debugging ### Issue Debugging
```javascript ```javascript
// Get current status
MSPDebug.getStatus();
// Analyze current queue state // Analyze current queue state
MSPTestRunner.analyzeQueue(); MSPDebug.analyze();
// Check for memory leaks // Test specific problematic scenario
MSPTestRunner.runTest('memory-leaks'); MSPDebug.runTest('memory-leaks');
// Run full diagnostic // Check for alerts with low thresholds
MSPTestRunner.runFullSuite(); MSPDebug.setTestThresholds();
MSPDebug.triggerTestAlerts();
// Generate diagnostic report
MSPDebug.report();
``` ```
## Integration with Existing Code ## Integration with Existing Code
@ -232,6 +277,41 @@ The debug tools are designed to be non-intrusive:
- No performance impact when not actively monitoring - No performance impact when not actively monitoring
- Original MSP behavior is preserved - Original MSP behavior is preserved
### Auto-loading
The debug tools auto-load when `msp_debug_tools.js` is imported. They detect the presence of the global MSP object and initialize automatically.
### Keyboard Shortcuts
- `Ctrl+Shift+M`: Toggle debug dashboard
## Implementation Status
### ✅ Current Features
#### Alert System
- Enhanced debug logging with reduced console noise
- Test infrastructure: `triggerTestAlerts()`, `setTestThresholds()`, `setNormalThresholds()`
- Visual alert display in dashboard
- Smart threshold management for testing
#### Interactive Dashboard
- Smart update pausing during user interactions
- Clickable test results with detailed information
- Enhanced interaction handling for all UI elements
- Visual feedback with updates pause indicator
#### Complete API
- Dual API support: `MSPDebug` (modern) and `MSPTestRunner` (legacy)
- All documented commands implemented and verified
- Comprehensive testing methods (9 test types + 3 stress scenarios)
- Real-time monitoring with alert detection
### ✅ Verified Working
- Alert system triggers correctly when thresholds exceeded
- Dashboard displays alerts visually without update interference
- Test results provide comprehensive detailed information
- All API commands function as documented
- Auto-loading works in development environment
## File Structure ## File Structure
``` ```

View file

@ -70,6 +70,9 @@ export class MSPDebugDashboard {
<!-- Alerts Section --> <!-- Alerts Section -->
<div class="alerts-section"> <div class="alerts-section">
<h4>🚨 Alerts</h4> <h4>🚨 Alerts</h4>
<div class="alerts-header">
<button id="clear-alerts" style="float: right; padding: 2px 6px; font-size: 10px; background: #666; color: white; border: none; border-radius: 2px; cursor: pointer;">Clear Alerts</button>
</div>
<div id="alerts-container" class="alerts-container"> <div id="alerts-container" class="alerts-container">
<div class="no-alerts">No active alerts</div> <div class="no-alerts">No active alerts</div>
</div> </div>
@ -88,7 +91,7 @@ export class MSPDebugDashboard {
<!-- Live Chart --> <!-- Live Chart -->
<div class="chart-section"> <div class="chart-section">
<h4>📈 Live Metrics</h4> <h4>📈 Live Metrics</h4>
<canvas id="msp-metrics-chart" width="400" height="200"></canvas> <canvas id="msp-metrics-chart"></canvas>
</div> </div>
<!-- Request Details --> <!-- Request Details -->
@ -304,6 +307,11 @@ export class MSPDebugDashboard {
border-bottom: none; border-bottom: none;
} }
.queue-item-empty {
opacity: 0.3;
font-style: italic;
}
.test-results { .test-results {
background: #2a2a2a; background: #2a2a2a;
padding: 10px; padding: 10px;
@ -344,6 +352,7 @@ export class MSPDebugDashboard {
height: 150px; height: 150px;
background: #2a2a2a; background: #2a2a2a;
border-radius: 3px; border-radius: 3px;
display: block;
} }
.test-result-item { .test-result-item {
@ -421,6 +430,8 @@ export class MSPDebugDashboard {
this.runStressTest(); this.runStressTest();
} else if (e.target.id === "msp-clear-metrics") { } else if (e.target.id === "msp-clear-metrics") {
this.clearMetrics(); this.clearMetrics();
} else if (e.target.id === "clear-alerts") {
this.clearAlerts();
} else if (e.target.id === "msp-close-dashboard") { } else if (e.target.id === "msp-close-dashboard") {
this.hide(); this.hide();
} else if (e.target.id === "analyze-queue") { } else if (e.target.id === "analyze-queue") {
@ -444,6 +455,14 @@ export class MSPDebugDashboard {
this.toggle(); this.toggle();
} }
}); });
// Handle window resize to redraw canvas with correct dimensions
window.addEventListener("resize", () => {
if (this.isVisible) {
// Delay redraw to ensure layout is updated
setTimeout(() => this.drawChart(), 100);
}
});
} }
/** /**
@ -606,6 +625,13 @@ export class MSPDebugDashboard {
this.updateDisplay(); this.updateDisplay();
} }
/**
* Clear alerts only
*/
clearAlerts() {
mspQueueMonitor.clearAlerts();
}
/** /**
* Update display with current status * Update display with current status
*/ */
@ -752,23 +778,37 @@ export class MSPDebugDashboard {
const container = document.getElementById("queue-contents"); const container = document.getElementById("queue-contents");
if (!container) return; if (!container) return;
if (!queueContents || queueContents.length === 0) { // Always show exactly 5 slots to prevent layout shifts
container.innerHTML = '<div style="text-align: center; color: #888; padding: 20px;">Queue is empty</div>'; const maxSlots = 5;
return; const items = queueContents || [];
const slotsHtml = [];
// Add actual queue items
for (let i = 0; i < maxSlots; i++) {
if (i < items.length) {
const item = items[i];
slotsHtml.push(`
<div class="queue-item">
<span>Code: ${item.code}</span>
<span>Age: ${Math.round(item.age)}ms</span>
<span>Attempts: ${item.attempts}</span>
<span style="color: ${item.hasTimer ? "#00ff00" : "#ff4444"}">${item.hasTimer ? "✓" : "✗"}</span>
</div>
`);
} else {
// Add empty slot placeholder
slotsHtml.push(`
<div class="queue-item queue-item-empty">
<span style="color: #555;"></span>
<span style="color: #555;"></span>
<span style="color: #555;"></span>
<span style="color: #555;"></span>
</div>
`);
}
} }
container.innerHTML = queueContents container.innerHTML = slotsHtml.join("");
.map(
(item) => `
<div class="queue-item">
<span>Code: ${item.code}</span>
<span>Age: ${Math.round(item.age)}ms</span>
<span>Attempts: ${item.attempts}</span>
<span style="color: ${item.hasTimer ? "#00ff00" : "#ff4444"}">${item.hasTimer ? "✓" : "✗"}</span>
</div>
`,
)
.join("");
} }
/** /**
@ -805,8 +845,28 @@ export class MSPDebugDashboard {
if (!canvas) return; if (!canvas) return;
const ctx = canvas.getContext("2d"); const ctx = canvas.getContext("2d");
const width = canvas.width;
const height = canvas.height; // Get the display size (CSS pixels)
const rect = canvas.getBoundingClientRect();
const displayWidth = rect.width;
const displayHeight = rect.height;
// Get the device pixel ratio, falling back to 1
const devicePixelRatio = window.devicePixelRatio || 1;
// Set the internal canvas size to actual pixels for Hi-DPI displays
canvas.width = displayWidth * devicePixelRatio;
canvas.height = displayHeight * devicePixelRatio;
// Scale the canvas back down using CSS
canvas.style.width = `${displayWidth }px`;
canvas.style.height = `${displayHeight }px`;
// Scale the drawing context so everything draws at the correct size
ctx.scale(devicePixelRatio, devicePixelRatio);
const width = displayWidth;
const height = displayHeight;
// Clear canvas // Clear canvas
ctx.fillStyle = "#2a2a2a"; ctx.fillStyle = "#2a2a2a";
@ -834,7 +894,7 @@ export class MSPDebugDashboard {
ctx.stroke(); ctx.stroke();
// Draw labels // Draw labels with proper font scaling
ctx.fillStyle = "#ffffff"; ctx.fillStyle = "#ffffff";
ctx.font = "10px monospace"; ctx.font = "10px monospace";
ctx.fillText("Queue Size", 5, 15); ctx.fillText("Queue Size", 5, 15);
@ -1010,10 +1070,17 @@ window.MSPDebug = {
startMonitoring: () => mspQueueMonitor.startMonitoring(), startMonitoring: () => mspQueueMonitor.startMonitoring(),
stopMonitoring: () => mspQueueMonitor.stopMonitoring(), stopMonitoring: () => mspQueueMonitor.stopMonitoring(),
runTests: () => mspStressTest.runStressTestSuite(), runTests: () => mspStressTest.runStressTestSuite(),
runFullSuite: () => mspStressTest.runStressTestSuite(),
analyze: () => mspQueueMonitor.analyzeQueue(), analyze: () => mspQueueMonitor.analyzeQueue(),
report: () => mspQueueMonitor.generateReport(), report: () => mspQueueMonitor.generateReport(),
showTestDetails: (index) => mspDebugDashboard.showTestDetails(index), showTestDetails: (index) => mspDebugDashboard.showTestDetails(index),
// Individual test methods
runTest: (testName) => mspStressTest.runSpecificTest(testName),
quickHealthCheck: () => window.MSPTestRunner.quickHealthCheck(),
stressScenario: (scenario) => window.MSPTestRunner.stressScenario(scenario),
getStatus: () => mspQueueMonitor.getStatus(),
// Alert testing methods // Alert testing methods
triggerTestAlerts: () => mspQueueMonitor.triggerTestAlerts(), triggerTestAlerts: () => mspQueueMonitor.triggerTestAlerts(),
setTestThresholds: () => mspQueueMonitor.setTestThresholds(), setTestThresholds: () => mspQueueMonitor.setTestThresholds(),

View file

@ -29,7 +29,7 @@ export class MSPQueueMonitor {
}; };
this.thresholds = { this.thresholds = {
maxQueueSize: 40, // Alert when queue > 80% of MAX_QUEUE_SIZE maxQueueSize: Math.floor((this.msp.MAX_QUEUE_SIZE || 50) * 0.8), // Alert when queue > 80% of MAX_QUEUE_SIZE
maxAvgResponseTime: 2000, // Alert when avg response > 2s maxAvgResponseTime: 2000, // Alert when avg response > 2s
maxTimeoutRate: 0.1, // Alert when timeout rate > 10% maxTimeoutRate: 0.1, // Alert when timeout rate > 10%
memoryLeakThreshold: 100, // Alert when callbacks grow beyond expected memoryLeakThreshold: 100, // Alert when callbacks grow beyond expected
@ -83,7 +83,7 @@ export class MSPQueueMonitor {
this.metrics.requestsByCode.set(code, count + 1); this.metrics.requestsByCode.set(code, count + 1);
// Check for queue size peaks // Check for queue size peaks
const currentQueueSize = this.msp.callbacks.length; const currentQueueSize = this.msp.callbacks?.length ?? 0;
if (currentQueueSize > this.metrics.queuePeakSize) { if (currentQueueSize > this.metrics.queuePeakSize) {
this.metrics.queuePeakSize = currentQueueSize; this.metrics.queuePeakSize = currentQueueSize;
} }
@ -339,7 +339,7 @@ export class MSPQueueMonitor {
} }
/** /**
* Reset metrics * Reset metrics only (keep alerts intact)
*/ */
resetMetrics() { resetMetrics() {
this.metrics = { this.metrics = {
@ -356,12 +356,30 @@ export class MSPQueueMonitor {
errorsByType: new Map(), errorsByType: new Map(),
}; };
// Note: Alerts are NOT reset here - they should only be cleared when conditions are no longer true
// or when explicitly requested via clearAlerts() method
}
/**
* Clear alerts (separate from metrics)
*/
clearAlerts() {
console.log("🔄 Clearing all alerts...");
this.alerts = { this.alerts = {
queueFull: false, queueFull: false,
highTimeout: false, highTimeout: false,
slowResponses: false, slowResponses: false,
memoryLeak: false, memoryLeak: false,
}; };
this._notifyListeners();
}
/**
* Reset both metrics and alerts (complete reset)
*/
resetAll() {
this.resetMetrics();
this.clearAlerts();
} }
/** /**
@ -516,7 +534,7 @@ export class MSPQueueMonitor {
setNormalThresholds() { setNormalThresholds() {
console.log("🔧 Resetting to normal thresholds..."); console.log("🔧 Resetting to normal thresholds...");
this.thresholds = { this.thresholds = {
maxQueueSize: 40, // Alert when queue > 80% of MAX_QUEUE_SIZE maxQueueSize: Math.floor((this.msp.MAX_QUEUE_SIZE || 50) * 0.8), // Alert when queue > 80% of MAX_QUEUE_SIZE
maxAvgResponseTime: 2000, // Alert when avg response > 2s maxAvgResponseTime: 2000, // Alert when avg response > 2s
maxTimeoutRate: 0.1, // Alert when timeout rate > 10% maxTimeoutRate: 0.1, // Alert when timeout rate > 10%
memoryLeakThreshold: 100, // Alert when callbacks grow beyond expected memoryLeakThreshold: 100, // Alert when callbacks grow beyond expected

View file

@ -60,7 +60,7 @@ export class MSPStressTest {
try { try {
console.log(`\n📋 Running: ${testDef.name}`); console.log(`\n📋 Running: ${testDef.name}`);
this.currentTest = testDef.name; this.currentTest = testDef.name;
this.monitor.resetMetrics(); this.monitor.resetAll(); // Reset both metrics and alerts for clean test start
const startTime = performance.now(); const startTime = performance.now();
const result = await testDef.test(); const result = await testDef.test();
@ -547,7 +547,7 @@ export class MSPStressTest {
console.log(`🧪 Running specific test: ${testName}`); console.log(`🧪 Running specific test: ${testName}`);
this.monitor.startMonitoring(100); this.monitor.startMonitoring(100);
this.monitor.resetMetrics(); this.monitor.resetAll(); // Reset both metrics and alerts for clean test start
try { try {
const result = await testMethod(); const result = await testMethod();

View file

@ -20,13 +20,22 @@ import { mspStressTest } from "./msp_stress_test.js";
import { mspDebugDashboard } from "./msp_debug_dashboard.js"; import { mspDebugDashboard } from "./msp_debug_dashboard.js";
export const MSPTestRunner = { export const MSPTestRunner = {
// Store the listener function so it can be removed later
_quickMonitorListener: null,
/** /**
* Start quick monitoring with console output * Start quick monitoring with console output
*/ */
startQuickMonitor() { startQuickMonitor() {
console.log("🚀 Starting MSP Quick Monitor..."); console.log("🚀 Starting MSP Quick Monitor...");
mspQueueMonitor.addListener((status) => { // Remove any existing listener first
if (this._quickMonitorListener) {
mspQueueMonitor.removeListener(this._quickMonitorListener);
}
// Define the listener function so it can be referenced for removal
this._quickMonitorListener = (status) => {
if (status.alerts && Object.values(status.alerts).some((alert) => alert)) { if (status.alerts && Object.values(status.alerts).some((alert) => alert)) {
console.warn("🚨 MSP Alert:", status.alerts); console.warn("🚨 MSP Alert:", status.alerts);
} }
@ -37,8 +46,9 @@ export const MSPTestRunner = {
`📊 MSP Status: Queue=${status.currentQueueSize}/${status.maxQueueSize}, Requests=${status.metrics.totalRequests}, AvgTime=${Math.round(status.metrics.avgResponseTime)}ms`, `📊 MSP Status: Queue=${status.currentQueueSize}/${status.maxQueueSize}, Requests=${status.metrics.totalRequests}, AvgTime=${Math.round(status.metrics.avgResponseTime)}ms`,
); );
} }
}); };
mspQueueMonitor.addListener(this._quickMonitorListener);
mspQueueMonitor.startMonitoring(1000); mspQueueMonitor.startMonitoring(1000);
console.log("✅ Quick monitor started. Use MSPTestRunner.stopMonitor() to stop."); console.log("✅ Quick monitor started. Use MSPTestRunner.stopMonitor() to stop.");
@ -54,6 +64,13 @@ export const MSPTestRunner = {
*/ */
stopMonitor() { stopMonitor() {
mspQueueMonitor.stopMonitoring(); mspQueueMonitor.stopMonitoring();
// Remove the listener to prevent duplicate logs
if (this._quickMonitorListener) {
mspQueueMonitor.removeListener(this._quickMonitorListener);
this._quickMonitorListener = null;
}
console.log("⏹️ MSP Monitor stopped"); console.log("⏹️ MSP Monitor stopped");
}, },

View file

@ -1,106 +0,0 @@
/**
* Alert System Test Script
* Run this in the browser console to test the MSP debug alert system
*/
console.log("🧪 Starting MSP Alert System Test...");
// Test function to check alert system
async function testAlertSystem() {
console.log("1. Checking if MSPDebug is available...");
if (typeof window.MSPDebug === "undefined") {
console.error("❌ MSPDebug not found! Debug tools may not be loaded.");
return;
}
console.log("✅ MSPDebug is available");
console.log("2. Checking dashboard...");
const dashboard = window.MSPDebug.dashboard;
if (!dashboard) {
console.error("❌ Dashboard not found!");
return;
}
console.log("✅ Dashboard is available");
console.log("3. Checking monitor...");
const monitor = window.MSPDebug.monitor;
if (!monitor) {
console.error("❌ Monitor not found!");
return;
}
console.log("✅ Monitor is available");
console.log("4. Showing dashboard...");
dashboard.show();
console.log("5. Starting monitoring...");
monitor.startMonitoring(500);
console.log("6. Checking alert container exists...");
const alertContainer = document.getElementById("alerts-container");
if (!alertContainer) {
console.error("❌ Alert container not found in DOM!");
return;
}
console.log("✅ Alert container found:", alertContainer);
console.log("7. Getting current status...");
const status = monitor.getStatus();
console.log("Current status:", status);
console.log("Current alerts:", status.alerts);
console.log("8. Testing alert display directly...");
dashboard.updateAlerts({
queueFull: true,
highTimeout: false,
slowResponses: true,
memoryLeak: false,
});
console.log("9. Checking alert container content after manual update...");
console.log("Alert container HTML:", alertContainer.innerHTML);
console.log("10. Triggering test alerts...");
const testAlerts = monitor.triggerTestAlerts();
console.log("Test alerts triggered:", testAlerts);
console.log("11. Waiting 2 seconds and checking again...");
setTimeout(() => {
const newStatus = monitor.getStatus();
console.log("Status after test alerts:", newStatus);
console.log("Alerts after test:", newStatus.alerts);
console.log("Alert container HTML after test:", alertContainer.innerHTML);
// Test the complete update flow
console.log("12. Testing complete update flow...");
dashboard.updateDisplay(newStatus);
console.log("Alert container HTML after updateDisplay:", alertContainer.innerHTML);
console.log("🏁 Alert system test complete!");
}, 2000);
}
// Run the test
testAlertSystem();
// Also provide manual test functions
window.testAlertSystem = testAlertSystem;
window.checkAlerts = () => {
const container = document.getElementById("alerts-container");
console.log("Alert container:", container);
console.log("Alert container HTML:", container?.innerHTML);
const status = window.MSPDebug?.monitor?.getStatus();
console.log("Current alerts:", status?.alerts);
};
window.manualTestAlert = () => {
console.log("Testing alert display manually...");
const dashboard = window.MSPDebug.dashboard;
dashboard.updateAlerts({
queueFull: true,
highTimeout: true,
slowResponses: false,
memoryLeak: true,
});
console.log("Manual test alerts set");
};