Testanleitung: eigenes X-Display je Projekt fuer Parallelbetrieb
CI / Build & Tests (Linux) (push) Canceled after 0s
CI / Plattformneutralität & Hygiene (push) Canceled after 0s

Damit mehrere Agenten gleichzeitig Oberflaechen testen koennen, bekommt jedes
Projekt eine feste Displaynummer (Vorgabe Richard):

  :99 PolyTrader, :98 Predictalytics, :97 ClawdDotNet, :96 IBKRTrader,
  :95 und absteigend fuer kuenftige Projekte.

Zwei Prozesse auf demselben Display sehen die Fenster des jeweils anderen -
Klicks landen im falschen Programm, Aufnahmen zeigen fremde Anwendungen.

Beim Durcharbeiten fielen zwei weitere Kollisionspunkte auf, die zum
Parallelbetrieb dazugehoeren und mit aufgenommen wurden:

- Screenshot- und Logdateien in /tmp brauchen ein Projektpraefix. /tmp/v_1.png
  ueberschreiben sich parallel laufende Projekte gegenseitig.
- "xvfb-run -a" darf NICHT mehr verwendet werden: Das -a sucht sich selbst ein
  freies Display und beginnt dabei bei :99 - ausgerechnet PolyTraders Nummer.
  Stattdessen "xvfb-run -n <nummer>".

Die Warnung ist nicht theoretisch: Auf der VM lag ein verwaister X98-Socket,
entstanden durch genau so einen "xvfb-run -a"-Aufruf beim smoke-ui-Test, als
:99 belegt war. Er blockierte Predictalytics' reservierte Nummer, ohne dass ein
Prozess lief. Entfernt, und die Anleitung erklaert jetzt, wie man verwaiste
Sockets erkennt (ls /tmp/.X11-unix/ gegen pgrep -a Xvfb lesen) und aufraeumt.

Weiter ergaenzt:
- pkill nie ohne Displaynummer - "pkill Xvfb" erschlaegt die Sitzungen aller
  anderen Projekte.
- DISPLAY in jedem Skript setzen, sonst landet man auf :0, dem echten Desktop.
- Die Skriptvorlage hat jetzt einen Kopf mit PROJEKT/DISP/FENSTER; das ist
  alles, was sich je Projekt unterscheidet. Praktisch gegengetestet.
- Aufraeumabschnitt und Belegungsliste um Displays und Verzeichnisse erweitert.

Nebenbei aufgefallen: Das PolyTrader-Publish lag unter ~/pt-test statt
~/polytrader-test und verletzte damit die eigene Verzeichniskonvention.
Umbenannt.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Richard
2026-08-27 20:49:28 +02:00
co-authored by Claude Opus 5
parent 62570cfdd8
commit 9b2294cb4c
33 changed files with 979 additions and 244 deletions
+20 -5
View File
@@ -1,4 +1,4 @@
using System;
using System;
using System.IO;
using System.Threading.Tasks;
using System.Threading.Channels;
@@ -11,7 +11,17 @@ namespace PolyTraderSharp.Services
{
public string Message { get; }
public LogLevel Level { get; }
public DateTime Timestamp { get; }
/// <summary>
/// Zeitpunkt in der Anzeige-Zeitzone der Anwendung, mit passendem Offset.
///
/// <para>Bis zum 27.08.2026 stand hier <c>DateTime.Now</c> – die Zeit des <i>Systems</i>.
/// Auf einem UTC-Server (dem Normalfall) stempelten die Logs damit UTC, während die
/// Oberfläche Ortszeit anzeigte: Wer einen Vorfall von „22:30" suchte, fand ihn unter
/// 20:30 – zwischen Mitternacht und 2 Uhr sogar in der Logdatei des Vortags
/// (§8 des Befundberichts vom 26.08.2026).</para>
/// </summary>
public DateTimeOffset Timestamp { get; }
/// <summary>Korrelations-ID (z. B. SignalId) für die Log-Forensik; leer wenn ohne Kontext.</summary>
public string CorrelationId { get; }
@@ -20,7 +30,7 @@ namespace PolyTraderSharp.Services
{
Message = message;
Level = level;
Timestamp = DateTime.Now;
Timestamp = AppTimeZone.Now;
CorrelationId = correlationId ?? "";
}
}
@@ -105,7 +115,12 @@ namespace PolyTraderSharp.Services
{
try
{
string dateStr = e.Timestamp.ToString("dd-MM-yyyy");
// ISO-Datum wie bei der JSONL-Datei. Bis zum 26.08.2026 stand hier
// "dd-MM-yyyy" - im selben Logs-Ordner lagen damit zwei Namenskonventionen
// nebeneinander: eine Logrotate-Regel brauchte zwei Muster, und im
// Dateimanager sortierten die .log-Dateien nach Tag statt nach Datum
// (Befund B-2 des Linux-Laufs).
string dateStr = e.Timestamp.ToString("yyyy-MM-dd");
string fileName = $"{dateStr}-{e.Level}.log";
string fullPath = Path.Combine(_logsDirectory, fileName);
@@ -167,7 +182,7 @@ namespace PolyTraderSharp.Services
{
lock (_lock)
{
var cutoff = DateTime.Now - maxAge;
var cutoff = DateTimeOffset.UtcNow - maxAge;
return _history.Where(x => x.Timestamp >= cutoff).ToList();
}
}