Skip to content

Commit 0ba3905

Browse files
MarkoVcodeclaude
andcommitted
Implement adaptive throttling phases 2-4 with quality monitoring
Phase 2: Transport-specific limits - Add USB TMC, Serial, and TCP/IP specific queue depth and interval limits - USB TMC: Conservative limits (5 queue depth, 1-2s intervals) - Serial: Standard limits (10 queue depth, 0.5-1s intervals) - TCP/IP: Higher buffering (15 queue depth, 0.5-1s intervals) - Extract and pass transport_type through connection chain Phase 3: Enhanced quality scoring - Implement weighted recent history (2.0x for most recent 25%) - Add quality trend detection using linear regression - Quality tiers: excellent/good/fair/poor/critical - Handle startup case with has_sufficient_data() check - Override quality to critical for dead devices Phase 4: Monitoring & metrics - Extend DeviceMetrics with throttling metrics - Add /metrics and /metrics/{device_id} API endpoints - Record throttle events, backoff multiplier, quality scores - Create comprehensive ADAPTIVE_THROTTLING.md documentation Bug fixes: - Fix empty dict reference bug in unified_scheduler (device_connections) - Add missing time import in api.py - Circuit breaker only blocks "dead" devices, not "unknown" - Add recovery attempt logic (retry every 30s) - Reduce circuit breaker log spam (200 skips vs 20) - Fix frozen quality scores for dead devices - Improve startup quality score handling 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 6f25c74 commit 0ba3905

12 files changed

Lines changed: 1338 additions & 79 deletions

File tree

benchmesh-serial-service/ADAPTIVE_THROTTLING.md

Lines changed: 449 additions & 0 deletions
Large diffs are not rendered by default.

benchmesh-serial-service/config.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
version: 1
22
devices:
3+
- id: eol-1
4+
name: OWON OEL
5+
driver: owon_oel
6+
port: /dev/ttyOEL1515
7+
baud: 115200
8+
serial: 8N1
9+
model: OEL1515
310
- id: dmm-1
411
name: OWON XDM
512
driver: owon_xdm

benchmesh-serial-service/src/benchmesh_service/api.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import os
22
import sys
33
import json
4+
import time
45
import asyncio
56
import subprocess
67
import hashlib
@@ -310,6 +311,50 @@ def list_drivers():
310311

311312
return drivers
312313

314+
@app.get("/metrics", summary="Get performance and throttling metrics for all devices", response_model=dict)
315+
def get_all_metrics():
316+
"""
317+
Phase 4: Get performance and adaptive throttling metrics for all devices.
318+
319+
Returns metrics including:
320+
- Serial port utilization %
321+
- QPS (queries per second)
322+
- API latency percentiles (P95, P99)
323+
- Average queue depth
324+
- Throttle events and skip rate
325+
- Backoff multipliers
326+
- Connection quality scores, tiers, and trends
327+
- Transport types
328+
"""
329+
global _manager
330+
if not _manager or not _manager.metrics_collector:
331+
return {"error": "Metrics collector not available"}
332+
333+
summary = _manager.metrics_collector.get_utilization_summary()
334+
return {
335+
"summary": summary,
336+
"timestamp": time.time()
337+
}
338+
339+
@app.get("/metrics/{device_id}", summary="Get performance and throttling metrics for a specific device", response_model=dict)
340+
def get_device_metrics(device_id: str):
341+
"""
342+
Phase 4: Get performance and adaptive throttling metrics for a specific device.
343+
344+
Returns detailed metrics for the specified device including utilization,
345+
latency, queue depth, throttling events, backoff state, and quality metrics.
346+
"""
347+
global _manager
348+
if not _manager or not _manager.metrics_collector:
349+
return {"error": "Metrics collector not available"}
350+
351+
metrics = _manager.metrics_collector.get_device_metrics(device_id)
352+
if not metrics:
353+
return {"error": f"No metrics available for device {device_id}"}
354+
355+
metrics["timestamp"] = time.time()
356+
return metrics
357+
313358
@app.get("/drivers/{driver_id}", summary="List models for a specific driver", response_model=list)
314359
def list_driver_models(driver_id: str):
315360
"""

0 commit comments

Comments
 (0)