Testanleitung: eigenes X-Display je Projekt fuer Parallelbetrieb
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:
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
|
||||
namespace PolyTraderSharp.Services
|
||||
{
|
||||
@@ -69,6 +69,21 @@ namespace PolyTraderSharp.Services
|
||||
$"„{TimeZoneInfo.Local.Id}\" verwendet. Empfohlen ist die IANA-Schreibweise, z.B. „{DefaultId}\".");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Jetzt – in der Anzeige-Zeitzone, mit dem dazu passenden Offset.
|
||||
///
|
||||
/// <para>Bewusst <see cref="DateTimeOffset"/> und nicht <see cref="DateTime"/>: Ein
|
||||
/// umgerechneter <c>DateTime</c> trägt seine Zone nicht mit sich, und beim Formatieren mit
|
||||
/// <c>zzz</c> setzt .NET dann den Offset des <i>Systems</i> ein. Genau daran lag der
|
||||
/// Widerspruch, den der Linux-Lauf gezeigt hat: Auf einem UTC-Server meldete die Anwendung
|
||||
/// „Anzeige-Zeitzone: Europe/Berlin" und stempelte in derselben Zeile mit UTC (§8 des
|
||||
/// Befundberichts vom 26.08.2026).</para>
|
||||
/// </summary>
|
||||
public static DateTimeOffset Now => TimeZoneInfo.ConvertTime(DateTimeOffset.UtcNow, Current);
|
||||
|
||||
/// <summary>Der heutige Tag in der Anzeige-Zeitzone – für Logdatei-Tagesgrenzen.</summary>
|
||||
public static DateTime Today => Now.Date;
|
||||
|
||||
/// <summary>Rechnet einen Zeitstempel in die Anzeige-Zeitzone um (UTC-Kennzeichnung wird beachtet).</summary>
|
||||
public static DateTime ToDisplay(DateTime value) =>
|
||||
value.Kind == DateTimeKind.Utc
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
@@ -130,7 +130,13 @@ namespace PolyTraderSharp.Services
|
||||
{
|
||||
if (!File.Exists(_settings.MullvadCliPath))
|
||||
{
|
||||
_logger.Error($"Mullvad CLI not found at: {_settings.MullvadCliPath}");
|
||||
// Nennt gleich den plattformueblichen Pfad mit: Ein aus der Windows-Zeit
|
||||
// uebernommener Wert in server_settings.xml ist auf dem Linux-Server der
|
||||
// haeufigste Grund, und ohne diesen Hinweis sieht man ihm das nicht an
|
||||
// (Befund B-5 des Linux-Sichttests).
|
||||
_logger.Error($"Mullvad CLI nicht gefunden: \"{_settings.MullvadCliPath}\". " +
|
||||
$"Auf diesem System wird ueblicherweise \"{ServerSettings.DefaultMullvadCliPath}\" erwartet " +
|
||||
$"(Einstellung \"Mullvad CLI Path\").");
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user