v1.0.16.14 — rotatsionny log: latest.log + .log.gz arkhiv (Minecraft-style), no limit, legacy launcher.log removal

This commit is contained in:
SashegDev
2026-08-18 22:32:14 +00:00
parent cdc81e4e8d
commit fdd4e24e3c
4 changed files with 103 additions and 8 deletions
@@ -54,6 +54,7 @@ public class Bootstrap {
logDir = baseDir.resolve("logs");
Files.createDirectories(logDir);
javafxPath = baseDir.resolve("lib").resolve("javafx");
rotateLogs();
log("=== ZernMC Launcher ===");
@@ -371,11 +372,50 @@ public class Bootstrap {
return javaBin;
}
private static void rotateLogs() {
// Minecraft-style: archive previous latest.log as .log.gz, keep unlimited.
try {
Path latest = logDir.resolve("latest.log");
if (Files.exists(latest) && Files.size(latest) > 0) {
String ts = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd_HH-mm-ss"));
int n = 1;
Path archive;
do {
archive = logDir.resolve(ts + (n == 1 ? "" : "-" + n) + ".log.gz");
n++;
} while (Files.exists(archive));
gzip(archive, latest);
Files.deleteIfExists(latest);
}
} catch (Exception e) {
System.out.println("[Bootstrap] rotate error: " + e.getMessage());
}
// Migrate old unlimited log.
try {
Files.deleteIfExists(logDir.resolve("launcher.log"));
} catch (Exception ignored) {
}
}
private static void gzip(Path archive, Path source) {
try (java.io.InputStream in = Files.newInputStream(source);
java.io.OutputStream out = Files.newOutputStream(archive);
java.util.zip.GZIPOutputStream gz = new java.util.zip.GZIPOutputStream(out)) {
byte[] buf = new byte[65536];
int n;
while ((n = in.read(buf)) > 0) {
gz.write(buf, 0, n);
}
} catch (Exception e) {
System.out.println("[Bootstrap] gzip error: " + e.getMessage());
}
}
private static void log(String msg) {
String entry = "[" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("HH:mm:ss")) + "] " + msg;
System.out.println(entry);
try {
Files.writeString(logDir.resolve("launcher.log"), entry + "\n",
Files.writeString(logDir.resolve("latest.log"), entry + "\n",
StandardOpenOption.CREATE, StandardOpenOption.APPEND);
} catch (Exception ignored) {}
if (ui != null) ui.setStatus(msg);
@@ -881,7 +921,7 @@ public class Bootstrap {
// Exit
info.put("exit_code", exitCode);
info.put("stderr", stderr != null ? stderr : "");
info.put("launcher_log", readFileSafe(logDir.resolve("launcher.log"), 200));
info.put("launcher_log", readFileSafe(logDir.resolve("latest.log"), 200));
// System
Map<String, Object> system = new HashMap<>();
@@ -211,7 +211,7 @@ public class Bootstrap {
String entry = "[" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("HH:mm:ss")) + "] " + msg;
System.out.println(entry);
try {
Files.writeString(logDir.resolve("launcher.log"), entry + "\n",
Files.writeString(logDir.resolve("latest.log"), entry + "\n",
StandardOpenOption.CREATE, StandardOpenOption.APPEND);
} catch (Exception ignored) {}
}
@@ -53,11 +53,10 @@ public class LauncherLogger {
try {
Path logsDir = Paths.get("").toAbsolutePath().resolve("logs");
Files.createDirectories(logsDir);
logFile = logsDir.resolve("launcher.log");
rotateLogs(logsDir);
logFile = logsDir.resolve("latest.log");
Files.writeString(logFile,
"=== Launcher Log " + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) + " ===\n",
StandardOpenOption.CREATE, StandardOpenOption.APPEND);
Files.writeString(logFile, sessionHeader(), StandardOpenOption.CREATE);
System.out.println("[LauncherLogger] initialized, log: " + logFile.toAbsolutePath());
} catch (Exception e) {
@@ -66,6 +65,62 @@ public class LauncherLogger {
}
}
private static String sessionHeader() {
String ts = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
String os = System.getProperty("os.name") + " " + System.getProperty("os.version")
+ " " + System.getProperty("os.arch");
String java = System.getProperty("java.version") + " (" + System.getProperty("java.vendor") + ")";
String mem = (Runtime.getRuntime().maxMemory() / (1024 * 1024)) + " MB";
return "== ZernMC Launcher =======================================================\n"
+ "== Started: " + ts + "\n"
+ "== OS: " + os + "\n"
+ "== Java: " + java + "\n"
+ "== Max memory: " + mem + "\n"
+ "====================================================================\n";
}
/**
* Minecraft-style rotation: compress the previous latest.log into a dated
* .log.gz archive (unlimited history), then remove the legacy launcher.log.
*/
private static void rotateLogs(Path logsDir) {
// Legacy one-instance log from older builds: delete it, it is replaced by latest.log.
try {
Files.deleteIfExists(logsDir.resolve("launcher.log"));
} catch (Exception ignored) {
}
Path latest = logsDir.resolve("latest.log");
try {
if (Files.exists(latest) && Files.size(latest) > 0) {
String ts = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd_HH-mm-ss"));
int n = 1;
Path archive;
do {
archive = logsDir.resolve(ts + (n == 1 ? "" : "-" + n) + ".log.gz");
n++;
} while (Files.exists(archive));
gzip(logsDir, archive, latest);
Files.deleteIfExists(latest);
}
} catch (Exception e) {
System.err.println("[LauncherLogger] rotate error: " + e.getMessage());
}
}
private static void gzip(Path logsDir, Path archive, Path source) {
try (var in = Files.newInputStream(source);
var gz = new java.util.zip.GZIPOutputStream(Files.newOutputStream(archive))) {
byte[] buf = new byte[65536];
int n;
while ((n = in.read(buf)) > 0) {
gz.write(buf, 0, n);
}
} catch (Exception e) {
System.err.println("[LauncherLogger] gzip error: " + e.getMessage());
}
}
public static Path getLogFile() {
return logFile;
}
+1 -1
View File
@@ -20,7 +20,7 @@
<properties>
<revision>1.0.16</revision>
<hotfix>13</hotfix>
<hotfix>14</hotfix>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>