Bisher kam man an die Ausgabe von solarManager.py, dem Runner und den uebrigen Dauerprozessen nur per SSH heran. Die neue Seite unter "Protokolle" zeigt sie: links die fuenf Dateien mit Groesse und Alter - eine, die seit Tagen nicht gewachsen ist, faellt so auf, ohne dass man sie oeffnet -, rechts die Zeilen mit Volltextsuche, Level-Filter und optionalem Nachladen. Nicht in die Datenbank geschrieben, obwohl das naheliegt: ein Log muss genau dann noch funktionieren, wenn die Datenbank es nicht tut. Ein Handler, der nach MySQL schreibt, verschluckt ausgerechnet die Meldung "Datenbank nicht erreichbar" - also die, wegen der man nachsieht. Was strukturiert ausgewertet werden soll, steht ohnehin in automation_log. Gelesen wird rueckwaerts in Bloecken: 5000 Zeilen aus der 329 MB grossen Datei der Wallbox kosten 46 ms, weil nur das Ende angefasst wird. Sucht man ins Leere, bricht der Server nach 4 MB ab und sagt es auch. Die beiden Prozesse formatieren unterschiedlich - der eine stellt das Level voran, der andere den Zeitstempel -, deshalb wird beides gesucht statt an fester Stelle erwartet. Zeilen ohne eigenes Level erben das der Zeile darueber, sonst filterte "nur Fehler" die Tracebacks weg, die den Fehler erklaeren. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
60 lines
1.6 KiB
PHP
60 lines
1.6 KiB
PHP
<?php
|
|
/**
|
|
* Endpunkt der Logseite.
|
|
*
|
|
* GET ?action=list Zustand aller bekannten Dateien
|
|
* GET ?action=read&datei=runner&... Zeilen einer Datei
|
|
*
|
|
* Parameter von read:
|
|
* datei Schluessel aus logDateien()
|
|
* anzahl wieviele Zeilen (1 bis 5000)
|
|
* suche Text, der vorkommen muss
|
|
* level Mindestlevel: INFO, WARNING, ERROR
|
|
*
|
|
* Ein reiner Verteiler - gelesen wird in restricted/logdateien.php.
|
|
*/
|
|
|
|
require_once("../helper.php");
|
|
require_once("../restricted/logdateien.php");
|
|
|
|
if (!checkLogin()) {
|
|
http_response_code(403);
|
|
exit;
|
|
}
|
|
|
|
function jsonAntwort($data, $code = 200)
|
|
{
|
|
http_response_code($code);
|
|
header("Content-Type: application/json; charset=utf-8");
|
|
echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
|
|
exit;
|
|
}
|
|
|
|
$action = $_GET["action"] ?? "list";
|
|
|
|
try {
|
|
switch ($action) {
|
|
case "list":
|
|
$liste = [];
|
|
foreach (array_keys(logDateien()) as $key) {
|
|
$liste[] = logZustand($key);
|
|
}
|
|
jsonAntwort(["dateien" => $liste]);
|
|
|
|
case "read":
|
|
jsonAntwort(logLesen(
|
|
$_GET["datei"] ?? "",
|
|
$_GET["anzahl"] ?? 300,
|
|
trim((string) ($_GET["suche"] ?? "")),
|
|
strtoupper(trim((string) ($_GET["level"] ?? "")))
|
|
));
|
|
|
|
default:
|
|
jsonAntwort(["error" => "Unbekannte Aktion."], 400);
|
|
}
|
|
} catch (InvalidArgumentException $e) {
|
|
jsonAntwort(["error" => $e->getMessage()], 400);
|
|
} catch (Throwable $e) {
|
|
jsonAntwort(["error" => $e->getMessage()], 500);
|
|
}
|