Später · 22 Ausreißer ohne feste Schwellen: Normalwert je Wochenstunde
- kern/ausreisser.py: 168 Fächer je Reihe (CPU, GPU, Speicher, Temperaturen, Netz), erst genau, ab acht Werten gleitend; auffällig ab 4 Streuungen und Mindestabstand, erst mit drei Wochen Erfahrung; Ausreißer gekappt gelernt - services/ausreisser.py: Wächter beider Rollen, gelber Hinweis nach zwei auffälligen Stunden mit Normalwert und Wochenstunde im Satz; erster Lauf lernt aus den aufbewahrten acht Tagen - Monitoring: Zeile mit Lernwoche bzw. was gerade auffällt; GET /api/ausreisser, /api/homelab/ausreisser Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
904598031a
commit
2972cdfeca
+2
-2
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
-1
File diff suppressed because one or more lines are too long
+1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
-1
File diff suppressed because one or more lines are too long
+1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
@@ -1 +1 @@
|
||||
import{i as e,r as t}from"./dist-aE7UmubC.js";import{G as n,K as r}from"./index-CuG_RlEw.js";import{a as i,i as a,n as o,r as s,t as c}from"./sheet-DG7u1mB-.js";var l=t(),u=e();function d(e){let t=(0,l.c)(8),{onSchliessen:d}=e,f;t[0]===d?f=t[1]:(f=e=>!e&&d(),t[0]=d,t[1]=f);let p;t[2]===Symbol.for(`react.memo_cache_sentinel`)?(p=(0,u.jsxs)(a,{className:`p-0`,children:[(0,u.jsx)(i,{asChild:!0,children:(0,u.jsx)(`div`,{children:(0,u.jsx)(n,{})})}),(0,u.jsx)(s,{className:`sr-only`,children:`Bereiche und Seiten`})]}),t[2]=p):p=t[2];let m;t[3]===d?m=t[4]:(m=(0,u.jsxs)(o,{side:`left`,className:`flex flex-col gap-7 border-white/[0.06] bg-[#0a0d14] px-4 pt-5 pb-[calc(1.25rem+env(safe-area-inset-bottom))] data-[side=left]:w-[300px]`,children:[p,(0,u.jsx)(r,{onGewaehlt:d})]}),t[3]=d,t[4]=m);let h;return t[5]!==f||t[6]!==m?(h=(0,u.jsx)(c,{open:!0,onOpenChange:f,children:m}),t[5]=f,t[6]=m,t[7]=h):h=t[7],h}export{d as MenueSchublade};
|
||||
import{i as e,r as t}from"./dist-aE7UmubC.js";import{G as n,K as r}from"./index-Cdq4iteU.js";import{a as i,i as a,n as o,r as s,t as c}from"./sheet-DG7u1mB-.js";var l=t(),u=e();function d(e){let t=(0,l.c)(8),{onSchliessen:d}=e,f;t[0]===d?f=t[1]:(f=e=>!e&&d(),t[0]=d,t[1]=f);let p;t[2]===Symbol.for(`react.memo_cache_sentinel`)?(p=(0,u.jsxs)(a,{className:`p-0`,children:[(0,u.jsx)(i,{asChild:!0,children:(0,u.jsx)(`div`,{children:(0,u.jsx)(n,{})})}),(0,u.jsx)(s,{className:`sr-only`,children:`Bereiche und Seiten`})]}),t[2]=p):p=t[2];let m;t[3]===d?m=t[4]:(m=(0,u.jsxs)(o,{side:`left`,className:`flex flex-col gap-7 border-white/[0.06] bg-[#0a0d14] px-4 pt-5 pb-[calc(1.25rem+env(safe-area-inset-bottom))] data-[side=left]:w-[300px]`,children:[p,(0,u.jsx)(r,{onGewaehlt:d})]}),t[3]=d,t[4]=m);let h;return t[5]!==f||t[6]!==m?(h=(0,u.jsx)(c,{open:!0,onOpenChange:f,children:m}),t[5]=f,t[6]=m,t[7]=h):h=t[7],h}export{d as MenueSchublade};
|
||||
+1
-1
File diff suppressed because one or more lines are too long
-1
File diff suppressed because one or more lines are too long
+1
File diff suppressed because one or more lines are too long
Vendored
+2
-2
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+2
-2
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+4
-4
File diff suppressed because one or more lines are too long
Vendored
+2
-2
@@ -9,11 +9,11 @@
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<link rel="apple-touch-icon" href="/apple-touch-icon.png" />
|
||||
<title>Homelab Orchestrator</title>
|
||||
<script type="module" crossorigin src="/assets/index-CuG_RlEw.js"></script>
|
||||
<script type="module" crossorigin src="/assets/index-Cdq4iteU.js"></script>
|
||||
<link rel="modulepreload" crossorigin href="/assets/dist-aE7UmubC.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/button-BHVKhtQ6.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/dist-CakcBaML.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/abfragen-CDCgpAto.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/abfragen-DNMpmgyt.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/useSelector-DBNxxw17.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/useMatch-DDVpPKJI.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/useRouterState-DJr4hrdj.js">
|
||||
|
||||
@@ -11,7 +11,7 @@ import { stromVerbunden } from "./strom"
|
||||
import type {
|
||||
Ablauf, AktionsErgebnis, Altrest, AufraeumKandidat, BoxMesswerte, EinstellungenStand, Hinweis, HomelabEinstellungen,
|
||||
HomelabLauf, HomelabMesswerte, HomelabSpeicher, HomelabStand, HomelabZertifikate, NeuesGeraet, NeuerStack, NeuWahl, DockerLage, Neuerungen, HomelabWartung, WartungsRegel,
|
||||
LucyAutonomie, LucyStufe, Rueckfragen, Wochenbericht, Platte, HomelabPlatten, Instanz, InstanzMitStand, Job, Modell, Nutzung, PartnerStatus,
|
||||
LucyAutonomie, LucyStufe, Rueckfragen, Wochenbericht, Platte, HomelabPlatten, AusreisserLage, Instanz, InstanzMitStand, Job, Modell, Nutzung, PartnerStatus,
|
||||
ProtokollEintrag, Radar, SammelPlanSchritt, Sammellauf, Sicherung, Start, TelegramTest, UpdateDetails, ZielAktion,
|
||||
ZielStand, Zeitraum,
|
||||
} from "./typen"
|
||||
@@ -512,6 +512,16 @@ export const useNeuerungen = (zid: string, baustein: string, aktiv: boolean) =>
|
||||
retry: false,
|
||||
})
|
||||
|
||||
/** Ausreißer ohne feste Schwellen (seit 26.09.2026): Lernstand und was gerade auffällt, je Bereich. */
|
||||
export const useAusreisser = (bereich: "box" | "homelab", aktiv = true) =>
|
||||
useQuery({
|
||||
queryKey: ["ausreisser", bereich],
|
||||
queryFn: () => api<AusreisserLage>(bereich === "box" ? "/api/ausreisser" : "/api/homelab/ausreisser"),
|
||||
enabled: aktiv,
|
||||
refetchInterval: 600_000,
|
||||
retry: false,
|
||||
})
|
||||
|
||||
/** Plattengesundheit (seit 26.09.2026): die KI-Box selbst und das Homelab (Proxmox-Host, NAS über SNMP). */
|
||||
export const useBoxPlatten = () =>
|
||||
useQuery({ queryKey: ["platten"], queryFn: () => api<{ platten: Platte[] }>("/api/platten"), refetchInterval: 600_000, retry: false })
|
||||
|
||||
@@ -915,3 +915,14 @@ export interface HomelabPlatten {
|
||||
platten: Platte[]
|
||||
nas: { eingerichtet: boolean; ok: boolean; detail: string | null; system: string | null }
|
||||
}
|
||||
|
||||
// --- Ausreißer ohne feste Schwellen (GET /api/ausreisser, /api/homelab/ausreisser; seit 26.09.2026) ---------------
|
||||
|
||||
export interface AusreisserLage {
|
||||
reihen: number
|
||||
wochen: number
|
||||
lernt: boolean
|
||||
min_wochen: number
|
||||
stunde: number | null
|
||||
auffaellig: { quelle: string; name: string; folge: number; wert: number; normal: number; fach: number; titel: string }[]
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import { Geraetesymbol } from "@/components/cockpit/Geraetesymbol"
|
||||
import { Panel } from "@/components/cockpit/Panel"
|
||||
import { Kennzahl } from "@/components/diagramme/Kennzahl"
|
||||
import { Verlauf } from "@/components/diagramme/Verlauf"
|
||||
import { useBoxMesswerte, useHomelabMesswerte, useInstanz, usePartner } from "@/lib/abfragen"
|
||||
import { useAusreisser, useBoxMesswerte, useHomelabMesswerte, useInstanz, usePartner } from "@/lib/abfragen"
|
||||
import { geraetebild } from "@/lib/geraetebild"
|
||||
import { laufzeit, letzterWert, zustandBei } from "@/lib/messung"
|
||||
import { useLetzteMetrik } from "@/lib/strom"
|
||||
@@ -51,6 +51,18 @@ const zeitraumText = (z: Zeitraum) => ZEITRAEUME.find((x) => x.id === z)?.text ?
|
||||
|
||||
// --- KI-Box -------------------------------------------------------------------------------------------
|
||||
|
||||
/** Ausreißer ohne feste Schwellen (seit 26.09.2026): lernt noch — oder was gerade ungewöhnlich ist. */
|
||||
export function AusreisserZeile({ bereich, aktiv = true }: { bereich: "box" | "homelab"; aktiv?: boolean }) {
|
||||
const a = useAusreisser(bereich, aktiv).data
|
||||
if (!a || a.reihen === 0) return null
|
||||
const text = a.lernt
|
||||
? `Ungewöhnliches meldet der Orchestrator, sobald er je Wochenstunde ${a.min_wochen} Wochen Erfahrung hat — er lernt gerade (Woche ${a.wochen} von ${a.min_wochen}).`
|
||||
: a.auffaellig.length
|
||||
? `Gerade ungewöhnlich: ${a.auffaellig.map((x) => x.titel).join("; ")}.`
|
||||
: "Nichts Ungewöhnliches — verglichen mit den üblichen Werten dieser Wochenstunde."
|
||||
return <p className={cn("m-0 text-sm", !a.lernt && a.auffaellig.length ? "text-bernstein" : "text-text-3")}>{text}</p>
|
||||
}
|
||||
|
||||
export function BoxMonitoringSeite() {
|
||||
const [zeitraum, setZeitraum] = useState<Zeitraum>("1h")
|
||||
const mess = useBoxMesswerte(zeitraum)
|
||||
@@ -65,6 +77,7 @@ export function BoxMonitoringSeite() {
|
||||
<ZeitraumWahl wert={zeitraum} onWahl={setZeitraum} farbe="box" />
|
||||
<span className="text-sm text-text-3">Zahlen live, Verläufe im Minutentakt</span>
|
||||
</div>
|
||||
<AusreisserZeile bereich="box" />
|
||||
<div className="grid grid-cols-2 gap-2.5 sm:grid-cols-3 xl:grid-cols-6">
|
||||
<Kennzahl label="CPU" wert={wert(live?.cpu, "cpu")} einheit="prozent" max={100} zustand={zustandBei(wert(live?.cpu, "cpu"), 85, 95)} zeitraumText={zeitraumText(zeitraum)} />
|
||||
<Kennzahl label="Speicher" wert={wert(live?.ram, "ram")} einheit="prozent" max={100} zustand={zustandBei(wert(live?.ram, "ram"), 85, 95)} zeitraumText={zeitraumText(zeitraum)} />
|
||||
@@ -140,6 +153,7 @@ export function HomelabMonitoringSeite() {
|
||||
<ZeitraumWahl wert={zeitraum} onWahl={setZeitraum} farbe="homelab" />
|
||||
<span className="text-sm text-text-3">Werte im Minutentakt vom Proxmox-Host</span>
|
||||
</div>
|
||||
<AusreisserZeile bereich="homelab" aktiv={aktiv} />
|
||||
{host && (
|
||||
<Panel titel="Proxmox-Host" rechts={<span className="ziffern text-sm text-text-3">läuft {laufzeit(h.uptime_s)}{h.load1 != null ? ` · Last ${h.load1.toFixed(2).replace(".", ",")}` : ""}</span>}>
|
||||
<div className="grid grid-cols-2 gap-2.5 sm:grid-cols-4">
|
||||
|
||||
Reference in New Issue
Block a user