From 54738d3259da56813bf4cd52aecf3f0a4bf127e7 Mon Sep 17 00:00:00 2001 From: Cyd Date: Fri, 14 Aug 2026 09:19:50 -0500 Subject: [PATCH] The log keeps the whole night Every launch truncated rpl4.log, so a tester who played six races and hit trouble in the second had nothing to send: the evidence was overwritten by the races that came after. Collecting it meant copying the file aside between games, which nobody remembers to do while five other people are waiting to start - and the logs that did arrive were a scatter of rpl4 (2).log through rpl4 (16).log that had to be sorted out afterwards. It appends now. Each run opens with a rule and the wall-clock time it started, because that is what a report is made of - "the third race, about nine" - and nothing else in the log carries the time of day. Play the evening, send one file. It rolls once to rpl4.prev.log past 64 MB rather than growing without limit; only the per-frame diagnostics can manage that in an evening, but a log nobody can open is no more use than one that was overwritten. RP412LOGAPPEND=0 restores the old behaviour. Verified: three launches in a scratch install take the file 1521 -> 3042 -> 4563 bytes with three stamped separators, and RP412LOGAPPEND=0 puts it back to one run of 1368. Co-Authored-By: Claude Opus 5 (1M context) --- RP_L4/RPL4.CPP | 66 ++++++++++++++++++++++++++++++++++++++++++- RP_L4/RPL4ENVIRON.cpp | 12 ++++++++ 2 files changed, 77 insertions(+), 1 deletion(-) diff --git a/RP_L4/RPL4.CPP b/RP_L4/RPL4.CPP index dfe8788..ef57386 100644 --- a/RP_L4/RPL4.CPP +++ b/RP_L4/RPL4.CPP @@ -40,6 +40,8 @@ // end add #include #include +#include // the log is rolled before it is opened +#include // and stamped with the wall clock #include #include #include // the test-build expiry check @@ -146,10 +148,72 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine char filename[50]; strcpy_s(filename, 50, "rpl4.log"); + // + //--------------------------------------------------------------------- + // The log keeps the whole night, not just the last race. + // + // Every launch used to truncate it, so a tester who played six races + // and hit trouble in the second had nothing to send: the evidence was + // overwritten by the races that followed. Collecting it meant copying + // the file aside between games, which nobody remembers to do while + // everyone is waiting to start. + // + // Appending costs a separator, below, so the runs can still be told + // apart. RP412LOGAPPEND=0 restores the old behaviour. + // + // Rolled once when it gets big rather than left to grow: a session + // with the per-frame diagnostics turned on writes fast, and a log + // nobody can open is no more use than one that was overwritten. The + // previous generation is kept beside it. + //--------------------------------------------------------------------- + // + const char *append_setting = getenv("RP412LOGAPPEND"); + bool append_log = !(append_setting != NULL && append_setting[0] == '0'); + + if (append_log) + { + const long kMaximumLogBytes = 64L * 1024L * 1024L; + + std::ifstream probe(filename, std::ios::binary | std::ios::ate); + if (probe.is_open()) + { + std::streamoff grown = probe.tellg(); + probe.close(); + if (grown > kMaximumLogBytes) + { + remove("rpl4.prev.log"); + rename(filename, "rpl4.prev.log"); + } + } + } + std::ofstream logfile; - logfile.open(filename); + logfile.open(filename, append_log ? (std::ios::out | std::ios::app) + : std::ios::out); std::cout.rdbuf(logfile.rdbuf()); + // + // Where one run stops and the next starts. Wall-clock time, because + // that is what a tester reports trouble against ("the third race, + // about nine") and nothing else in the log carries it. + // + if (append_log) + { + time_t now = time(NULL); + struct tm local; + char stamp[32]; + + if (localtime_s(&local, &now) == 0 && + strftime(stamp, sizeof(stamp), "%Y-%m-%d %H:%M:%S", &local) > 0) + { + DEBUG_STREAM << "\n" + << "========================================================\n" + << " run started " << stamp << "\n" + << "========================================================\n" + << std::flush; + } + } + SetUnhandledExceptionFilter(RPL4CrashDumpFilter); // diff --git a/RP_L4/RPL4ENVIRON.cpp b/RP_L4/RPL4ENVIRON.cpp index ba326b9..a930ab1 100644 --- a/RP_L4/RPL4ENVIRON.cpp +++ b/RP_L4/RPL4ENVIRON.cpp @@ -398,6 +398,18 @@ namespace "# of its own inside every call, which is why this is not a loop.\n" "#RP412MESHRETRY=1\n" "\n" +"# 0 = start rpl4.log fresh every launch, as builds before this one did.\n" +"#\n" +"# It now keeps the whole night instead. Each run is separated by a line\n" +"# of equals signs and the wall-clock time it started, so a report of\n" +"# \"the third race, about nine\" can be found in it. Nobody has to\n" +"# remember to copy the file aside between games any more - play the\n" +"# evening, send one log.\n" +"#\n" +"# It rolls itself to rpl4.prev.log once past 64 MB, which only the\n" +"# per-frame diagnostics can manage in an evening.\n" +"#RP412LOGAPPEND=0\n" +"\n" "# How much memory to set aside for a recording, in megabytes. 1 to 512,\n" "# default 100.\n" "#\n"