瀏覽代碼

Expose queue stats via status endpoint

tags/v0.9.0
Jan Svabenik 1 月之前
父節點
當前提交
fb21dec0ed
共有 4 個檔案被更改,包括 51 行新增2 行删除
  1. +10
    -2
      docs/API.md
  2. +2
    -0
      docs/pro-runtime-hardening-workboard.md
  3. +3
    -0
      internal/control/control.go
  4. +36
    -0
      internal/control/control_test.go

+ 10
- 2
docs/API.md 查看文件

@@ -19,7 +19,7 @@ Health check.

### `GET /status`

Current transmitter status (read-only snapshot).
Current transmitter status (read-only snapshot). Runtime indicator, alert, and queue stats from the running TX controller are mirrored here for quick health checks.

**Response:**
```json
@@ -31,7 +31,15 @@ Current transmitter status (read-only snapshot).
"rdsEnabled": true,
"preEmphasisTauUS": 50,
"limiterEnabled": true,
"fmModulationEnabled": true
"fmModulationEnabled": true,
"runtimeIndicator": "normal",
"runtimeAlert": "",
"queue": {
"capacity": 3,
"depth": 1,
"fillLevel": 0.33,
"health": "low"
}
}
```



+ 2
- 0
docs/pro-runtime-hardening-workboard.md 查看文件

@@ -250,6 +250,7 @@ Generator/Upsampler und Hardwarewriter werden als getrennte Stufen mit kleinem,
| 2026-04-05 | Queue-Health-Indikator | `QueueStats.Health` gibt `critical`/`low`/`normal` zurück und `txBridge` leitet `EngineStats.Queue` ins `/runtime`-JSON. |
| 2026-04-05 | Runtime-Indikator | `EngineStats.RuntimeIndicator` kombiniert `queue.health` + `lateBuffers`, `/runtime` zeigt `engine.runtimeIndicator`. |
| 2026-04-05 | /status runtime indicator | `/status` reuses `txBridge.TXStats()` and now reports `runtimeIndicator` alongside the config snapshot for quick ops. |
| 2026-04-05 | /status queue stats | `/status` spiegelt das `queue`-Objekt aus `txBridge.TXStats()` für schnelle Queue-Checks, API-Doku und `TestStatusReportsQueueStats` fangen den neuen Key ab. |

## WS-01 Verifikation
| Datum | Fokus | Ergebnis |
@@ -259,6 +260,7 @@ Generator/Upsampler und Hardwarewriter werden als getrennte Stufen mit kleinem,
| 2026-04-05 | Runtime-Indikator | OK `go test ./...` deckt `runtimeIndicator` sowie `/runtime`-Exposition von `engine.runtimeIndicator`. |
| 2026-04-05 | Runtime API queue health | ✅ `/runtime` liefert jetzt `engine.queue.health` dank `txBridge.TXStats`. |
| 2026-04-05 | /status runtime indicator | ✅ `/status` gibt jetzt `runtimeIndicator` aus (`control_test` deckt den neuen Key). |
| 2026-04-05 | /status queue stats | ✅ `TestStatusReportsQueueStats` plus `docs/API.md` zeigen, dass `queue` korrekt durchgereicht wird. |

---



+ 3
- 0
internal/control/control.go 查看文件

@@ -140,6 +140,9 @@ func (s *Server) handleStatus(w http.ResponseWriter, _ *http.Request) {
if alert, ok := stats["runtimeAlert"]; ok {
status["runtimeAlert"] = alert
}
if queue, ok := stats["queue"]; ok {
status["queue"] = queue
}
}
}



+ 36
- 0
internal/control/control_test.go 查看文件

@@ -9,6 +9,7 @@ import (
"testing"

cfgpkg "github.com/jan/fm-rds-tx/internal/config"
"github.com/jan/fm-rds-tx/internal/output"
)

func TestHealthz(t *testing.T) {
@@ -55,6 +56,41 @@ func TestStatusReportsRuntimeIndicator(t *testing.T) {
}
}

func TestStatusReportsQueueStats(t *testing.T) {
cfg := cfgpkg.Default()
queueStats := output.QueueStats{
Capacity: cfg.Runtime.FrameQueueCapacity,
Depth: 1,
FillLevel: 0.25,
Health: output.QueueHealthLow,
}
srv := NewServer(cfg)
srv.SetTXController(&fakeTXController{stats: map[string]any{"queue": queueStats}})
rec := httptest.NewRecorder()
srv.Handler().ServeHTTP(rec, httptest.NewRequest(http.MethodGet, "/status", nil))
if rec.Code != 200 {
t.Fatalf("status: %d", rec.Code)
}
var body map[string]any
if err := json.Unmarshal(rec.Body.Bytes(), &body); err != nil {
t.Fatalf("unmarshal queue stats: %v", err)
}
queueRaw, ok := body["queue"]
if !ok {
t.Fatalf("missing queue in status")
}
queueMap, ok := queueRaw.(map[string]any)
if !ok {
t.Fatalf("queue stats type mismatch: %T", queueRaw)
}
if queueMap["capacity"] != float64(queueStats.Capacity) {
t.Fatalf("queue capacity mismatch: want %v got %v", queueStats.Capacity, queueMap["capacity"])
}
if queueMap["health"] != string(queueStats.Health) {
t.Fatalf("queue health mismatch: want %s got %v", queueStats.Health, queueMap["health"])
}
}

func TestDryRunEndpoint(t *testing.T) {
srv := NewServer(cfgpkg.Default())
rec := httptest.NewRecorder()


Loading…
取消
儲存