inferwatch-mcp
inferwatch
Echtzeit- und Verlaufsmetriken für lokal betriebene LLMs — Ollama und vLLM — mit einem Browser-Dashboard, einem Einstellungsbildschirm und einem MCP-Server, damit ein Agent dieselben Daten abfragen kann.
Ein Python-Prozess, eine SQLite-Datei. Kein Docker, kein Node, kein Prometheus, keine externen Dienste. Es sitzt nie im Request-Pfad und kann die Inferenz daher weder verlangsamen noch unterbrechen.
┌── Ollama ──────────────┐ ┌── vLLM ────────────────┐
│ journald / file / │ │ GET /metrics │
│ docker logs │ │ (native Prometheus) │
└──────────┬─────────────┘ └──────────┬─────────────┘
│ per-request rows │ pre-aggregated
▼ ▼
┌──────────────── SQLite (WAL) ────────────────┐
│ requests · rollups · vllm_samples/hist │
└───────┬──────────────────────────┬───────────┘
▼ ▼
dashboard :7070 MCP server (stdio)Die beiden Engines sind nicht symmetrisch, und das Tool tut nicht so, als wären sie es
Das ist die zentrale Design-Tatsache, daher lohnt es sich, sie klar auszusprechen.
Ollama | vLLM | |
Quelle | sein Log |
|
Zeilen pro Request | ja | nein — es existieren keine, die gesammelt werden könnten |
TTFT / Latenz | exakt, pro Request | nur Histogramme |
Tokens | pro Request | kumulative Zähler |
Fehler | HTTP-Status pro Request |
|
Client-Adresse | ja | nein |
Perzentile | exakt innerhalb der Aufbewahrungsfrist | Bucket-Obergrenzen; Mittelwerte sind exakt |
Einzigartige Extras | Prompt-Cache-Wiederverwendung, Draft-Akzeptanz, Kaltstartzeit | KV-Cache-Belegung, Preemptions, Batch-Belegung, Wartezeit nach Grund |
Beide Tabs zeigen GPU-Auslastung, VRAM, Temperatur und Stromverbrauch, da diese von nvidia-smi gemessen werden und nicht von einer der beiden Engines. Temperatur und Stromverbrauch erhalten separate Diagramme statt sich eine Achse zu teilen, und jedes wird so aggregiert, wie es seine Einheit verlangt: Die Auslastung wird über die Karten gemittelt, VRAM und Watt werden summiert, die Temperatur meldet die heißeste Karte. Die Temperatur ist die einzige Reihe, die nicht bei null beginnt — ein Bereich von 33–68 °C, der bei 0 startet, würde den Großteil des Diagramms verschwenden.
Daher gibt es separate Dashboard-Tabs, separate Tabellen und separate MCP-Tools. Es wird nicht versucht, Zeilen pro Request für vLLM durch Differenzbildung der Zähler zu rekonstruieren: Man kann nicht wiederherstellen, welcher TTFT zu welchem Request gehörte, und eine Fälschung würde erfundene Zeilen neben echte setzen.
Ollama: Woher die Zahlen kommen
Ollama bietet keinen /metrics-Endpunkt (verifiziert — die Route ist nicht in der Binärdatei). Mit OLLAMA_DEBUG=1 gibt das eingebettete llama.cpp pro Request einen Timing-Block aus, der mit der Zugriffszeile und der Scheduler-Zeile kombiniert wird:
slot print_timing: id 0 | task 6763 | prompt eval time = 1254.52 ms / 55 tokens
slot print_timing: id 0 | task 6763 | eval time = 14591.31 ms / 416 tokens
[GIN] ... | 200 | 16.862061865s | 192.0.2.10 | POST "/v1/chat/completions"
time=... msg="context for request finished" runner.name=.../llama3.2:3bDas ergibt TTFT, Prefill/Decode-Aufteilung, Token-Anzahl, Decode-Rate, Status, Client, Endpunkt und Modell — für jeden Request, von jedem Client, ohne den Request-Pfad zu berühren. Aus der Kombination ergeben sich zwei Zahlen, die keine der beiden Quellen allein hat:
Warteschlangenwartezeit = Wandlatenz − Runner-Zeit: Zeit, die mit Warten statt mit Generieren verbracht wurde. Ein Proxy kann diese nicht trennen.
Prompt-Cache-Wiederverwendung = volle Prompt-Länge − tatsächlich ausgewertete Tokens.
OLLAMA_DEBUG=1 ist erforderlich. Ohne sie druckt llama.cpp keine Timing-Zeilen: Request-Raten, Status und GPU-Metriken funktionieren weiterhin, aber TTFT und Token-Anzahl bleiben leer. Das Dashboard zeigt dies in einem Banner an, statt Nullen anzuzeigen.
# /etc/systemd/system/ollama.service.d/override.conf
[Service]
Environment="OLLAMA_DEBUG=1"vLLM: Woher die Zahlen kommen
Der native Prometheus-Endpunkt von vLLM wird alle collection.scrape_interval_s (Standard 10s) abgerufen. Kumulative Zähler werden differenziert; Histogramm-Buckets werden pro Bucket differenziert; beide werden pro Minute aggregiert geschrieben, denn das Speichern jedes Scrapes würde Millionen von Zeilen pro Monat erzeugen, in Auflösungen, die kein Diagramm nutzt.
Drei Details, die man kennen sollte:
Die eigenen Bucket-Grenzen von vLLM werden mit den Zählwerten gespeichert. Seine Grenzen schreiten 1ms/20ms/250ms/2.5s/40s/640s fort; die von Ollama 25ms/200ms/1.5s/15s/60s. Keine ist eine Verfeinerung der anderen, daher würde das Umsortieren der einen in die andere eine Interpolation zwischen den Grenzen erfordern — das Erfinden von Zahlen. Perzentile werden gegen die eigenen Grenzen jeder Quelle berechnet und als Bucket-Obergrenzen gemeldet.
_sumund_countsind exakt, daher ist der Mittelwert exakt. Da die Buckets von vLLM im Sekundenbereich grob sind, führen Dashboard und MCP-Tools mit dem Mittelwert und kennzeichnen Perzentile als „höchstens".Neustarts werden erkannt über
process_start_time_seconds(und durch einen Zähler, der rückwärts läuft). Das Intervall, das einen Neustart umspannt, wird verworfen, statt als falsches Delta ausgegeben zu werden.
Die Inter-Token-Latenz wurde über vLLM-Versionen hinweg als time_per_output_token_seconds, inter_token_latency_seconds und request_time_per_output_token_seconds geschrieben. Alle werden gesammelt und diejenige mit Daten wird verwendet, sodass dies mit alten und neuen Servern ohne Konfiguration funktioniert.
Related MCP server: System Monitor MCP Server
Installation
Erfordert Python 3.10 oder neuer — nicht wegen dieses Codes (der 3.9-sauber ist), sondern weil fastapi, uvicorn, starlette und mcp alle dies erfordern.
pip install git+https://github.com/floatsmyboat/inferwatch # or:
git clone https://github.com/floatsmyboat/inferwatch && cd inferwatch
python3 -m venv --upgrade-deps .venv && .venv/bin/pip install -e ".[dev]"Die Installation gibt Ihnen zwei Befehle:
Befehl | Was es ist |
| der Collector, das Dashboard und die API ( |
| der MCP-Server, über stdio |
Noch nicht auf PyPI; installieren Sie vorerst aus Git.
Backfill aus einem Journal, das Sie bereits haben, dann schauen Sie sich die Datenbank an:
inferwatch ingest --since 2d # or: python -m inferwatch.main ingest
inferwatch statsFühren Sie es aus:
inferwatch serve # http://127.0.0.1:7070Als Dienst — die Unit wird aus systemd/inferwatch.service.in für den aktuellen Benutzer, den Checkout-Pfad und den Interpreter gerendert, sodass nichts fest verdrahtet ist:
./scripts/install-systemd.sh # system service (uses sudo)
sudo systemctl enable --now inferwatch
./scripts/install-systemd.sh --user # or per-user, no sudo
systemctl --user enable --now inferwatchÜberschreiben Sie mit HOST=0.0.0.0 PORT=7070 DATADIR=... ./scripts/install-systemd.sh.
Im Netzwerk verfügbar machen
Es gibt keine Authentifizierung. Das Dashboard ist schreibgeschützt (nur GET) und speichert keinen Prompt- oder Antworttext — nur Zählwerte, Zeitmessungen, Modellnamen und Client-Adressen. Beschränken Sie es in der Firewall:
sudo ufw allow from 192.168.1.0/24 to any port 7070 proto tcp comment "inferwatch"Konfigurieren, was überwacht wird
Alles ist über den Tab Einstellungen im Dashboard oder über die CLI bearbeitbar:
python -m inferwatch.main sources # list
python -m inferwatch.main sources add --kind vllm --name qwen \
--set url=http://127.0.0.1:8000
python -m inferwatch.main sources add --kind ollama --name box \
--set reader=file --set path=~/.ollama/logs/server.log
python -m inferwatch.main sources disable qwenOllama-Log-Reader. Nicht jeder betreibt Ollama unter systemd:
Reader | für | Zeitstempel-Genauigkeit |
|
| Mikrosekunde, von journald |
|
| abgeleitet; siehe unten |
| Ollama in einem Container | pro Zeile, von |
Der file-Reader folgt wie tail -F, übersteht Rotation (Inode-Änderung) und Kürzung und speichert einen Offset, sodass ein Neustart nicht erneut abspielt. Ollamas Go-Zeilen tragen time=, aber die slot-Zeilen von llama.cpp — diejenigen mit den Token-Anzahlen — tragen keinen Zeitstempel, daher wird der zuletzt gesehene weitergetragen. Die Reihenfolge, von der die Joins abhängen, gilt immer; die absolute Präzision ist geringer als bei journald, und eine [GIN]-Zeile mit Sekundenauflösung wird nach vorne geklemmt, sodass die Zeit nie rückwärts zu laufen scheint.
Einstellungs-Priorität
spec default < database (Settings tab) < environment < command lineEin Schlüssel, der über die Umgebung oder ein Flag bereitgestellt wird, wird im Tab Einstellungen schreibgeschützt mit seiner Herkunft angezeigt, weil dem Prozess gesagt wurde, ihn zu verwenden, und ein Browser dies nicht stillschweigend überschreiben darf. Das Speichern ist Alles-oder-nichts, sodass ein Tippfehler in einem Feld keine halb angewendete Konfiguration hinterlassen kann. Änderungen an Quellen, Intervallen und Aufbewahrung gelten ohne Neustart; server.host und server.port sind als neustartpflichtig markiert, und die API sagt dies nach dem Speichern.
Konfigurationsreferenz
Jede unten stehende Einstellung ist im Tab Einstellungen bearbeitbar, als Umgebungsvariable setzbar, und einige sind mit einem Flag fixierbar. Die Tabellen werden aus dem Code generiert (scripts/gen-config-docs.py), sodass sie nicht von dem abweichen können, was das Programm tatsächlich akzeptiert.
Generiert von scripts/gen-config-docs.py — nicht von Hand bearbeiten.
Sammlung
Einstellung | Standard | Akzeptiert | Umgebungsvariable | Hinweise |
|
| 1–300 |
| Wie oft nvidia-smi und der eigene Status-Endpunkt der Engine abgetastet werden. |
|
| 1–300 |
| Wie oft der /metrics-Endpunkt jeder vLLM-Instanz gelesen wird. vLLM-Zähler sind kumulativ, daher setzt dies die Auflösung jeder daraus abgeleiteten Rate und jedes Histogramms. |
|
|
|
| Neustart erforderlich — Wie weit zurück beim ersten Lauf gelesen wird, bevor ein Resume-Zustand existiert. Akzeptiert 7d / 6h oder eine journalctl-Form wie '-2 days'. |
|
| 10–3600 |
| Wie oft die 1-Minuten- und 1-Stunden-Aggregate neu berechnet werden. |
Aufbewahrung
Einstellung | Standard | Akzeptiert | Umgebungsvariable | Hinweise |
|
| 0.5–3650 |
| Details pro Request, die älter als dies sind, werden gelöscht. Rollups werden unbegrenzt aufbewahrt, sodass Langzeitdiagramme überleben. |
|
| 0.5–3650 |
| GPU-Stichproben, Engine-Stichproben und das Ereignisprotokoll werden auf dies gekürzt. |
Dashboard
Einstellung | Standard | Akzeptiert | Umgebungsvariable | Hinweise |
|
|
|
| Bereich, der beim Öffnen des Dashboards ausgewählt ist. |
|
| — |
| HEAD- und Status-Polling in die Request-Raten einbeziehen. Standardmäßig deaktiviert, da dies bei einer gepollten Instanz 90 %+ der Treffer ausmachen kann. |
|
| 2–600 |
| Wie oft das geöffnete Dashboard neu lädt. Der Live-Request-Feed wird separat gepusht und ist davon nicht betroffen. |
Server
Einstellung | Standard | Akzeptiert | Umgebungsvariable | Hinweise |
|
| — |
| Neustart erforderlich — 0.0.0.0 macht das Dashboard im Netzwerk verfügbar. Es gibt keine Authentifizierung, daher im Firewall einschränken. |
|
| 1–65535 |
| Neustart erforderlich — Port, auf dem Dashboard und API lauschen. |
Quellfelder
Diese mit --set key=value bei sources add oder im Tab „Einstellungen“ setzen.
Ollama (--kind ollama)
Feld | Standard | Erforderlich wenn | Hinweise |
|
| — | Woher ollamas Log gelesen wird. Pro-Request-Metriken stammen aus llama.cpps Debug-Zeilen, daher ist eine dieser Optionen erforderlich. Eine von |
|
|
| |
| — |
| Wird wie tail -F verfolgt, Rotation und Kürzung werden also behandelt. |
|
|
| |
|
| — | Wird verwendet, um /api/ps für residente Modelle abzufragen. |
| — | — | Optional. Löst Blob-Digests bei Ladeereignissen in Modellnamen auf. Standard: $OLLAMA_MODELS oder ~/.ollama/models. |
vLLM (--kind vllm)
Feld | Standard | Erforderlich wenn | Hinweise |
|
| — | Die OpenAI-kompatible Server-Root. /metrics wird von hier gelesen. |
| — | — | Wenn gesetzt, wird das Journal zusätzlich auf HTTP-Statuscodes, Client-Adressen und Engine-Fehler gelesen, die /metrics nicht preisgibt. |
| — | — | Wird als Bearer-Token gesendet, falls der Server eines verlangt. |
Befehlszeilen-Flags
Flag | Zweck | Legt die Einstellung fest |
| — | — |
| systemd-Unit für die geseedete Ollama-Quelle / für den Ingest | — |
| — | — |
| ollama-Modelle-Verzeichnis (löst Blob-Digests in Modellnamen auf) | — |
| Ingest: diese Logdatei statt des Journals lesen | — |
| Log-Backfill-Fenster, z. B. '-2 days' |
|
| Aufbewahrung roher Requests; Rollups werden dauerhaft behalten |
|
| — |
|
| — |
|
| — |
|
| — |
|
| — | — |
Flags, die eine Einstellung festlegen, haben Vorrang vor Umgebung und Einstellungen-Tab; der Tab zeigt diese Schlüssel schreibgeschützt mit ihrer Herkunft.
Umfang: eine Ollama-Quelle, viele vLLM-Quellen
vLLM-Zeilen sind durchgehend nach Quelle verschlüsselt, sodass beliebig viele vLLM-Instanzen nebeneinander überwacht werden können. Die Ollama-Tabellen (requests, events, ps_samples) sind nicht nach Quelle partitioniert, sodass genau eine Ollama-Quelle gleichzeitig läuft; das Aktivieren einer zweiten protokolliert eine Warnung und ignoriert sie, statt zwei Instanzen stillschweigend in einen Zahlensatz zu mischen. Diese Tabellen zu partitionieren ist eine Schemaänderung, die bewusst vorgenommen werden sollte.
Dashboard
http://127.0.0.1:7070 — drei Tabs: Ollama, vLLM, Einstellungen.
Welche GPUs zu welcher Engine gehören
Ein Host betreibt oft mehr als eine Engine, daher würde das Plotten jeder Karte im Bereich einer Instanz implizieren, dass sie alle nutzt. Die GPUs jeder vLLM-Instanz werden durch Verfolgen von Prozessen ermittelt — der Port, den sie bedient → die lauschende PID → ihre Nachkommen → geschnitten mit nvidia-smis Compute-Prozessen → die Karten, die diese halten. Die Karten der Instanz tragen die Serienfarbe und ihre VRAM-Kachel zählt nur diese; die anderen Karten des Hosts bleiben grau sichtbar, beschriftet mit „andere Engine“.
Für die Zuordnung sind ss, eine lokale Instanz und nvidia-smi-Prozesssichtbarkeit erforderlich (in Containern oft nicht vorhanden). Fehlt eine davon, sagt das der Bereich und zeigt jede Karte ohne Hervorhebung, statt zu raten.
Eine Filterzeile begrenzt alles darunter. Jedes Diagramm hat einen Tabellen-Umschalter, der dieselben Serien als Zahlen zeigt, sodass kein Wert nur durch Hovern erreichbar ist. Ein Live-SSE-Feed speist den Request-Ticker und die aktuelle Rate.
URL-Parameter: ?tab=vllm, ?window=6h, ?model=llama3.2:3b, ?source=name, ?nostream=1 (deaktiviert den Live-Feed — nützlich für Kiosk-Displays und Screenshot-Tools, die sonst ewig auf einen offenen Stream warten).
API
Endpoint | Gibt zurück |
| alles, was der Ollama-Tab braucht, ein Zeitschnitt |
| dasselbe für eine vLLM-Instanz |
| Ollama-Aufschlüsselungen |
| vLLM-Aufschlüsselungen |
| Rohzeilen und Zeitverläufe |
| Einstellungen |
| überwachte Engines |
| Dashboard-Standardwerte, Collector-Zustand |
| SSE-Live-Feed |
/api/sources/probe prüft eine Definition bevor sie gespeichert wird, sodass ein Tippfehler dort auftaucht statt als Stille in den Diagrammen.
MCP-Server
./scripts/install-mcp.sh # writes .mcp.json for this checkout (gitignored)oder claude mcp add inferwatch -- /path/to/.venv/bin/python -m inferwatch.mcp_server.
Öffnet dieselbe SQLite-Datei schreibgeschützt (mode=ro plus PRAGMA query_only) und antwortet über dieselbe Abfrageebene wie das Dashboard, sodass eine gemeldete Zahl immer mit der Zahl auf dem Bildschirm übereinstimmt.
Tool | Zweck |
| Ollama-Kennzahlen und -Serien |
| Aufschlüsselung pro Modell; was resident ist |
| Ollama-Details pro Request |
| Kaltladungen, Verdrängungen, Kürzungen, Warnungen |
| vLLM-Metriken, Erreichbarkeit, GPU-Zuordnung |
| pro Gerät Auslastung/VRAM/Temperatur/Leistung |
| was überwacht wird und wie es konfiguriert ist |
| funktioniert die Erfassung, ist Debug-Logging aktiv |
| schreibgeschützte SELECT-Notluke, mit Einheiten |
Aufbewahrung
Rohzeilen pro Request (Ollama): 7 Tage (
retention.raw_days).GPU-Samples, Ereignisse, vLLM-Zeilen: 30 Tage (
retention.sample_days).rollup_1mundrollup_1h: unbegrenzt aufbewahrt.
Rollups speichern Histogramme mit festen Buckets von TTFT und Latenz, keine vorberechneten Perzentile. Histogramme addieren sich, sodass ein Perzentil über einen beliebigen Bereich durch Summieren der Buckets und Fortschreiten zum Zielrang berechnet wird. Perzentile von Perzentilen wären bedeutungslos; das ist es nicht.
Anfragen innerhalb des Rohdatenfensters liefern exakte Perzentile; darüber hinaus stammen sie aus
Histogrammen und werden als obere Grenze des enthaltenden Buckets gemeldet.
Jede Antwort enthält exact: true|false.
Neustarts und Reboots
Der Wiederaufnahmezustand ist pro Quelle — ein journald-Cursor, eine Datei-Inode+Offset oder ein Docker-Zeitstempel — und wird bei SIGTERM geleert. Zwei Dinge machen das sicher statt nur wahrscheinlich:
Schreibvorgänge sind idempotent. Jede Anfrage- und Ereigniszeile trägt einen dedupe_key
unter einem UNIQUE-Index, und Einfügungen erfolgen mit INSERT OR IGNORE. Das erneute Lesen von Zeilen,
die bereits gespeichert wurden, ist ein No-op, sodass ingest wiederholt ausgeführt werden kann und eine
Wiederaufnahme sicher überlappen kann.
Ein Cursor, der nicht verwendet werden kann, wird nicht vertraut. Wenn das Journal, auf das ein Cursor zeigt, rotiert wurde, positioniert journalctl stillschweigend neu, indem es den im Cursor eingebetteten Zeitstempel verwendet, und setzt korrekt fort. Aber ein Cursor, der in der Zukunft gestempelt ist (Clock-Skew, eine wiederhergestellte Datenbank), lässt journalctl auf Einträge warten, die nicht eintreffen werden, was die Sammlung stillschweigend zum Stillstand bringt; ein solcher Cursor wird beim Start abgelehnt. Ein Follow-Versuch, der zweimal hintereinander nichts liefert, bewirkt dasselbe.
systemctl stop ist in deutlich unter einer Sekunde abgeschlossen. systemd zeichnet
ExecMainStatus=15 zusammen mit Result=success auf: uvicorn löst das Signal nach dem Herunterfahren
bewusst erneut aus, sodass das Beenden durch SIGTERM erwartet wird, kein Absturz.
Ehrliche Einschränkungen
Zuordnung unter Parallelität (Ollama). Die Task-ID in den Timing-Zeilen von llama.cpp
und der Status der Zugriffszeile erscheinen nie zusammen, daher werden sie nach
Ankunftsreihenfolge verknüpft. Bei einer laufenden Anfrage ist das exakt. Wenn zwei abschließen, bevor
eine der Zugriffszeilen gedruckt wird, unterscheidet nichts im Log sie — diese Zeilen werden als
attribution='ambiguous' gespeichert statt geraten. Werte: exact,
ambiguous, none (fehlgeschlagen, bevor der Runner erreicht wurde — es wird auch kein Modell
geraten), orphan (Timings ohne Zugriffszeile). Ein 2-Tage-Backfill auf dem
Entwicklungs-Host ergab 174 exact, 9 ambiguous, 4 orphan, mit
OLLAMA_NUM_PARALLEL=1 in Kraft; erwarten Sie einen höheren ambiguous-Anteil, je mehr
Anfragen gleichzeitig laufen.
vLLMs Token- und Anfragezähler sind nicht pro Anfrage ausgerichtet.
generation_tokens_total erhöht sich, während Tokens streamen; request_success_total
erhöht sich nur, wenn eine Anfrage abgeschlossen ist. Über ein kurzes Fenster beschreiben sie daher
überlappende, aber unterschiedliche Mengen von Anfragen, und das Dividieren des einen durch das
andere ergibt nicht Tokens pro Anfrage. Die API kennzeichnet dies mit
counters_aligned: false, und das Dashboard sagt dies auf dem vLLM-Tab.
Kein Pro-Anfrage-Anything für vLLM. Oben abgedeckt. Wenn Sie Pro-Anfrage-Details von vLLM benötigen, ist dessen Request-Level-Logging die einzige Quelle, und es protokolliert Prompt-Text — den dieses Tool bewusst nie speichert.
Logs sind die Zufuhr, nicht das Archiv. Ein Journal kann je nach
journald.conf nur ein oder zwei Tage halten; die SQLite-Datei ist der Historiker. Wenn Logs
schneller rotieren, als inferwatch läuft, ist diese Lücke nicht wiederherstellbar.
Zwei byteidentische Ereignisse in derselben Mikrosekunde kollabieren zu einem. Der Dedupe-Key für Ereignisse wird aus ihren Werten gebildet, sodass eine identische Warnung, die zweimal innerhalb einer Mikrosekunde protokolliert wird, eine Zeile behält. Ein bewusster Tausch für garantierte Idempotenz — das Verwerfen einer wiederholten Warnung schlägt das Duplizieren von Verlauf.
Health-Check-Traffic wird getrennt, nicht gezählt. HEAD / und GET /api/ps
machten 96 % der Anfragen auf dem Entwicklungs-Host aus. Sie werden mit
class='health' gespeichert und von Inferenzraten ausgeschlossen, es sei denn,
dashboard.include_health ist aktiviert; requests_all enthält sie immer.
Hängt von Logformaten und Metriknamen ab. Ollamas Timing-Zeilen sind Debug-
Ausgabe, kein Vertrag, und vLLM benennt Metriken zwischen Releases um.
tests/test_parse.py enthält wörtliche Fixture-Zeilen und tests/test_vllm.py einen
echten /metrics-Auszug; wenn ein Upgrade das Parsen bricht, schlagen diese Tests fehl und zeigen,
was sich geändert hat.
Tests
python -m unittest discover -s tests -t .CI führt dies auf Python 3.10 bis 3.14 aus, plus einen Packaging-Job, der das
Wheel baut, prüft, dass das Dashboard-HTML darin enthalten ist, und es in eine saubere
Umgebung aus einem leeren Verzeichnis installiert, sodass der Quellbaum einen
Packaging-Fehler nicht maskieren kann. Kein Netzwerk, keine GPU und keine Engine ist erforderlich. Parser-Fixtures sind wörtliche echte Logzeilen und ein
echter /metrics-Auszug. Die Abdeckung umfasst den Join des Korrelators und
seine ambiguous/orphan/failed-Fälle, Histogramm-Perzentile und Rollup-Idempotenz,
die Schema-Migration, signal-sichere Commits, Cursor-Validierung, Dateirotation und
-truncation, Zeitstempel-Monotonie, Counter-Reset-Erkennung sowie Konfigurations-
Präzedenz und Sperrung. Die Konfigurationsreferenz in dieser Datei wird aus der Spezifikation
generiert, und ein Test schlägt fehl, wenn sie abweicht. Das JavaScript des Dashboards wird
mit einem reinen Python-Parser syntaxgeprüft und seine Formatierer in einer echten
JS-Engine ausgeführt (beides optional — kein Node nötig).
.venv/bin/python scripts/gen-config-docs.py --check # docs match the code?Layout
inferwatch/parse.py ollama log line parsers (pure, fixture-tested)
inferwatch/readers.py journald / file / docker log readers
inferwatch/collect.py correlator, GPU + model pollers, maintainer
inferwatch/vllm.py Prometheus scraper, delta and reset handling
inferwatch/gpuproc.py maps GPUs to the process tree holding them
inferwatch/vllm_metrics.py vLLM query layer
inferwatch/metrics.py ollama query layer (shared by API and MCP)
inferwatch/store.py SQLite schema, rollups, histograms, retention
inferwatch/config.py typed settings spec, precedence, source validation
inferwatch/supervisor.py builds and rebuilds collectors from the sources table
inferwatch/api.py FastAPI endpoints + SSE
inferwatch/web/index.html dashboard (single file, no CDN, no build step)
inferwatch/mcp_server.py MCP server (read-only)
inferwatch/main.py serve / ingest / stats / sourcesMitwirken
Issues und Pull Requests sind willkommen. Zwei Dinge machen eine Änderung leicht annehmbar:
python -m unittest discover -s tests -t .besteht.Wenn Sie
inferwatch/config.pyangefasst haben, führen Siepython scripts/gen-config-docs.pyaus, damit die Konfigurationsreferenz der README mit dem Code übereinstimmt — ein Test erzwingt das.
Parser-Änderungen sollten mit einer Fixture-Zeile kommen, die wörtlich aus echter Engine- Ausgabe kopiert ist, so wie es die bestehenden Tests tun. Logformate und Metriknamen sind keine Verträge, und eine echte Fixture macht einen zukünftigen Bruch offensichtlich.
Lizenz
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- FlicenseAqualityDmaintenanceEnables AI agents to query Prometheus metrics and Loki logs for intelligent alert investigation and troubleshooting. Provides service discovery, metric querying, log searching, and correlation tools to help identify root causes of issues.9
- FlicenseNot gradedqualityDmaintenanceGives AI agents real-time access to system metrics, process management, and container orchestration.
- AlicenseNot gradedqualityDmaintenanceProvides AI assistants with direct access to Red Hat OpenShift AI observability data, enabling querying of Prometheus metrics, Alertmanager alerts, Loki logs, Grafana dashboards, and Kubernetes cluster state to troubleshoot vLLM inference workloads.4MIT
- FlicenseNot gradedqualityBmaintenanceEnables AI assistants to monitor real-time CPU, RAM, and disk usage on the local machine.
Related MCP Connectors
Provide real-time data querying and visualization by integrating Tako with your agents. Generate o…
Gateway between LLM agents and world data through eight tools and a bundled endpoint catalog.
See, price, and control every tool call your AI agents make: policy checks, cost, and audit tools.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/floatsmyboat/inferwatch'
If you have feedback or need assistance with the MCP directory API, please join our Discord server