A SimHub plugin + browser dashboard for structured iRacing replay review. Instead of manually scrubbing a replay to find incidents, Sim Steward gives you an incident queue, one-click frame seeks, a driver-scoped view, and automated scan walks — all observable via Grafana Loki.
| Area | Shipped |
|---|---|
| Replay controls | Jump start/end, speed pills (0.25×–16×), play/pause, prev/next incident |
| Incident leaderboard | All incidents from plugin, filter by severity (1×/2×/4×/Mine), click to seek |
| Incident meta strip | Click any incident → replay seeks to frame + detail panel expands (car/driver/sev/cause) |
| This driver's incidents | Left-column panel filtered by selected car — for reviewing any opponent, not just yourself |
| Scan walk | Auto-seek every incident frame for one driver or the whole session; results in Captured tab |
| Captured incidents | Visited incidents list with group-by-driver accordion |
| Driver standings | Position/car/driver/incident count, collapsible |
| Telemetry strip | Throttle, brake, steering wheel (real data from plugin) |
| Selected Incident Panel | Camera group dropdown (cameraGroups from plugin), ▶ Capture (capture_incident: pre-roll, optional camera, 1× speed), prev/next within filtered list |
| Observability | Structured logs → Grafana Loki (SIMSTEWARD_LOKI_URL); optional OTLP metrics → local OpenTelemetry Collector → Prometheus (OTEL_EXPORTER_OTLP_ENDPOINT, docs/observability-local.md); capture_incident includes correlation fields on action_result; re-capture confirms before sending (Loki is append-only) |
| Replay incident index (iRacing replay) | WebSocket actions replay_incident_index_build (start / cancel), replay_incident_index_seek (JSON sessionTimeMs, optional sessionNum), replay_incident_index_record (on / off — 60Hz NDJSON under %LocalAppData%\SimSteward\replay-incident-index\record-samples\). IRSDKSharper 60Hz poll, 16× fast-forward, detection → JSON index on disk (...\{subSessionId}.json, TR-020 v1). Dashboard: http://<host>:8888/Web/sim-steward-dash/replay-incident-index.html (summary, sortable table, build/record, seeks); main dash links to it. Spec: docs/IRACING-REPLAY-INCIDENT-INDEX-REQUIREMENTS.md. |
North-star / gaps still open: true plugin-side YAML scan (session walk still uses the leaderboard frame list), scrub bar seek (PoC / toast only), plugin-owned suggestedCamera, dual-view capture, OBS integration. See docs/PRODUCT-FLOW.md and docs/DATA-ROUTING-OBSERVABILITY.md for what belongs in Loki vs a future metrics path.
iRacing (shared memory)
│
▼
SimSteward.Plugin (C# / .NET 4.8 / SimHub)
│ IRSDKSharper reads iRacing SDK
│ Fleck WebSocket server → port 19847
│ PluginLogger → plugin-structured.jsonl
│
├──→ Browser dashboard (HTML/JS)
│ src/SimSteward.Dashboard/index.html
│ src/SimSteward.Dashboard/replay-incident-index.html (replay incident index / M6)
│ served by SimHub HTTP → Web/sim-steward-dash/
│
└──→ Grafana Loki (optional)
plugin → HTTPS POST to SIMSTEWARD_LOKI_URL (single endpoint)
└──→ OTLP metrics (optional)
plugin → localhost:4317 → OpenTelemetry Collector → Prometheus (:9090)
local Docker stack: observability/local/
src/
SimSteward.Plugin/ C# SimHub plugin (.NET 4.8)
SimSteward.Dashboard/ Browser dashboard (index.html, replay-incident-index.html; no build step)
SimSteward.Plugin.Tests/ xUnit unit tests
docs/ Documentation (start with docs/README.md)
PRODUCT-FLOW.md Vision, feature maturity, what's missing
USER-FLOWS.md Step-by-step user journeys + flow diagrams
USER-FEATURES-PM.md PM-style feature descriptions
GRAFANA-LOGGING.md Loki labels, events, LogQL
IRACING-REPLAY-INCIDENT-INDEX-REQUIREMENTS.md SDK fast-forward incident index (milestones, TR IDs)
DATA-ROUTING-OBSERVABILITY.md Events vs high-rate telemetry (Loki vs OTel/metrics)
TROUBLESHOOTING.md Runtime issues, deploy, logs
observability/local/ Local Grafana + Loki + Prometheus + OTel Collector Docker stack
tests/ PowerShell integration tests
scripts/ obs-bridge, Loki helpers, deploy utilities
deploy.ps1 Build + deploy to local SimHub
- SimHub installed
- iRacing
- .NET Framework 4.8 SDK
- Place
SimHub.Plugins.dllandGameReaderCommon.dllinlib/SimHub/(or set$env:SIMHUB_PATH)
.\deploy.ps1Builds the plugin, runs dotnet test, runs PowerShell integration tests, then copies DLLs to the SimHub plugins folder. Requires 0 build errors and all tests passing.
With SimHub running and the plugin loaded, open (SimHub default HTTP port is 8888):
http://localhost:8888/Web/sim-steward-dash/index.html
Replay incident index (build status, TR-019 table, Record mode, seek-to-row): docs/IRACING-REPLAY-INCIDENT-INDEX-REQUIREMENTS.md
http://localhost:8888/Web/sim-steward-dash/replay-incident-index.html
Both pages connect to the plugin WebSocket on port 19847 (window.location.hostname, so LAN clients use the same host). Optional: ?token= / ?wsToken= when SIMSTEWARD_WS_TOKEN is set.
.\scripts\run-simhub-local-observability.ps1Starts Grafana + Loki via Docker. See docs/observability-local.md.
| Doc | Read when |
|---|---|
| docs/README.md | Start here — tiered index of all docs |
| docs/PRODUCT-FLOW.md | Understanding the vision, feature maturity, open PM issues |
| docs/USER-FLOWS.md | How each feature actually works as a user (flow diagrams) |
| docs/GRAFANA-LOGGING.md | Structured logging, Loki labels, LogQL queries |
| docs/IRACING-REPLAY-INCIDENT-INDEX-REQUIREMENTS.md | Replay incident index build (SDK-only), JSON output, validation, milestone status |
| docs/DATA-ROUTING-OBSERVABILITY.md | What ships to Loki vs metrics at scale |
| docs/TROUBLESHOOTING.md | Runtime issues, WebSocket, deploy failures |