mirror of
https://github.com/HMCL-dev/HMCL.git
synced 2025-09-13 22:07:01 -04:00
Optimization HMCLProcessListener::onLog (#1867)
This commit is contained in:
parent
2e532be34c
commit
e1eb40c129
@ -685,7 +685,7 @@ public final class LauncherHelper {
|
|||||||
* Guarantee that one [JavaProcess], one [HMCLProcessListener].
|
* Guarantee that one [JavaProcess], one [HMCLProcessListener].
|
||||||
* Because every time we launched a game, we generates a new [HMCLProcessListener]
|
* Because every time we launched a game, we generates a new [HMCLProcessListener]
|
||||||
*/
|
*/
|
||||||
class HMCLProcessListener implements ProcessListener {
|
private final class HMCLProcessListener implements ProcessListener {
|
||||||
|
|
||||||
private final HMCLGameRepository repository;
|
private final HMCLGameRepository repository;
|
||||||
private final Version version;
|
private final Version version;
|
||||||
@ -694,9 +694,11 @@ public final class LauncherHelper {
|
|||||||
private boolean lwjgl;
|
private boolean lwjgl;
|
||||||
private LogWindow logWindow;
|
private LogWindow logWindow;
|
||||||
private final boolean detectWindow;
|
private final boolean detectWindow;
|
||||||
private final ArrayDeque<Pair<String, Log4jLevel>> logs;
|
private final ArrayDeque<String> logs;
|
||||||
|
private final ArrayDeque</*Log4jLevel*/Object> levels;
|
||||||
private final CountDownLatch logWindowLatch = new CountDownLatch(1);
|
private final CountDownLatch logWindowLatch = new CountDownLatch(1);
|
||||||
private final CountDownLatch launchingLatch;
|
private final CountDownLatch launchingLatch;
|
||||||
|
private final String forbiddenAccessToken;
|
||||||
|
|
||||||
public HMCLProcessListener(HMCLGameRepository repository, Version version, AuthInfo authInfo, LaunchOptions launchOptions, CountDownLatch launchingLatch, boolean detectWindow) {
|
public HMCLProcessListener(HMCLGameRepository repository, Version version, AuthInfo authInfo, LaunchOptions launchOptions, CountDownLatch launchingLatch, boolean detectWindow) {
|
||||||
this.repository = repository;
|
this.repository = repository;
|
||||||
@ -704,8 +706,11 @@ public final class LauncherHelper {
|
|||||||
this.launchOptions = launchOptions;
|
this.launchOptions = launchOptions;
|
||||||
this.launchingLatch = launchingLatch;
|
this.launchingLatch = launchingLatch;
|
||||||
this.detectWindow = detectWindow;
|
this.detectWindow = detectWindow;
|
||||||
|
this.forbiddenAccessToken = authInfo != null ? authInfo.getAccessToken() : null;
|
||||||
|
|
||||||
this.logs = new ArrayDeque<>(config().getLogLines() + 1);
|
final int numLogs = config().getLogLines() + 1;
|
||||||
|
this.logs = new ArrayDeque<>(numLogs);
|
||||||
|
this.levels = new ArrayDeque<>(numLogs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -764,17 +769,24 @@ public final class LauncherHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void onLog(String log, Log4jLevel level) {
|
public void onLog(String log, boolean isErrorStream) {
|
||||||
String filteredLog = Logging.filterForbiddenToken(log);
|
String filteredLog = forbiddenAccessToken == null ? log : log.replace(forbiddenAccessToken, "<access token>");
|
||||||
|
|
||||||
if (level.lessOrEqual(Log4jLevel.ERROR))
|
if (isErrorStream)
|
||||||
System.err.println(filteredLog);
|
System.err.println(filteredLog);
|
||||||
else
|
else
|
||||||
System.out.println(filteredLog);
|
System.out.println(filteredLog);
|
||||||
|
|
||||||
logs.add(pair(filteredLog, level));
|
Log4jLevel level = isErrorStream ? Log4jLevel.ERROR : (showLogs ? Log4jLevel.guessLevel(filteredLog) : null);
|
||||||
if (logs.size() > config().getLogLines())
|
|
||||||
logs.removeFirst();
|
synchronized (this) {
|
||||||
|
logs.add(filteredLog);
|
||||||
|
levels.add(level != null ? level : Optional.empty()); // Use 'Optional.empty()' as hole
|
||||||
|
if (logs.size() > config().getLogLines()) {
|
||||||
|
logs.removeFirst();
|
||||||
|
levels.removeFirst();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (showLogs) {
|
if (showLogs) {
|
||||||
try {
|
try {
|
||||||
@ -787,7 +799,7 @@ public final class LauncherHelper {
|
|||||||
Platform.runLater(() -> logWindow.logLine(filteredLog, level));
|
Platform.runLater(() -> logWindow.logLine(filteredLog, level));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!lwjgl && (filteredLog.toLowerCase().contains("lwjgl version") || filteredLog.toLowerCase().contains("lwjgl openal") || !detectWindow)) {
|
if (!lwjgl && (!detectWindow || filteredLog.toLowerCase().contains("lwjgl version") || filteredLog.toLowerCase().contains("lwjgl openal"))) {
|
||||||
lwjgl = true;
|
lwjgl = true;
|
||||||
finishLaunch();
|
finishLaunch();
|
||||||
}
|
}
|
||||||
@ -804,8 +816,11 @@ public final class LauncherHelper {
|
|||||||
if (!lwjgl) finishLaunch();
|
if (!lwjgl) finishLaunch();
|
||||||
|
|
||||||
if (exitType != ExitType.NORMAL) {
|
if (exitType != ExitType.NORMAL) {
|
||||||
|
ArrayList<Pair<String, Log4jLevel>> pairs = new ArrayList<>(logs.size());
|
||||||
|
Lang.forEachZipped(logs, levels,
|
||||||
|
(log, l) -> pairs.add(pair(log, l instanceof Log4jLevel ? ((Log4jLevel) l) : Log4jLevel.guessLevel(log))));
|
||||||
repository.markVersionLaunchedAbnormally(version.getId());
|
repository.markVersionLaunchedAbnormally(version.getId());
|
||||||
Platform.runLater(() -> new GameCrashWindow(process, exitType, repository, version, launchOptions, logs).show());
|
Platform.runLater(() -> new GameCrashWindow(process, exitType, repository, version, launchOptions, pairs).show());
|
||||||
}
|
}
|
||||||
|
|
||||||
checkExit();
|
checkExit();
|
||||||
|
@ -42,6 +42,7 @@ import org.jackhuang.hmcl.task.Schedulers;
|
|||||||
import org.jackhuang.hmcl.ui.construct.TwoLineListItem;
|
import org.jackhuang.hmcl.ui.construct.TwoLineListItem;
|
||||||
import org.jackhuang.hmcl.util.Lang;
|
import org.jackhuang.hmcl.util.Lang;
|
||||||
import org.jackhuang.hmcl.util.Log4jLevel;
|
import org.jackhuang.hmcl.util.Log4jLevel;
|
||||||
|
import org.jackhuang.hmcl.util.Logging;
|
||||||
import org.jackhuang.hmcl.util.Pair;
|
import org.jackhuang.hmcl.util.Pair;
|
||||||
import org.jackhuang.hmcl.util.platform.Architecture;
|
import org.jackhuang.hmcl.util.platform.Architecture;
|
||||||
import org.jackhuang.hmcl.util.platform.CommandBuilder;
|
import org.jackhuang.hmcl.util.platform.CommandBuilder;
|
||||||
@ -222,7 +223,7 @@ public class GameCrashWindow extends Stage {
|
|||||||
private void showLogWindow() {
|
private void showLogWindow() {
|
||||||
LogWindow logWindow = new LogWindow();
|
LogWindow logWindow = new LogWindow();
|
||||||
|
|
||||||
logWindow.logLine("Command: " + new CommandBuilder().addAll(managedProcess.getCommands()).toString(), Log4jLevel.INFO);
|
logWindow.logLine(Logging.filterForbiddenToken("Command: " + new CommandBuilder().addAll(managedProcess.getCommands())), Log4jLevel.INFO);
|
||||||
if (managedProcess.getClasspath() != null) logWindow.logLine("ClassPath: " + managedProcess.getClasspath(), Log4jLevel.INFO);
|
if (managedProcess.getClasspath() != null) logWindow.logLine("ClassPath: " + managedProcess.getClasspath(), Log4jLevel.INFO);
|
||||||
for (Map.Entry<String, Log4jLevel> entry : logs)
|
for (Map.Entry<String, Log4jLevel> entry : logs)
|
||||||
logWindow.logLine(entry.getKey(), entry.getValue());
|
logWindow.logLine(entry.getKey(), entry.getValue());
|
||||||
|
@ -37,7 +37,6 @@ import javafx.stage.Stage;
|
|||||||
import org.apache.commons.lang3.mutable.MutableObject;
|
import org.apache.commons.lang3.mutable.MutableObject;
|
||||||
import org.jackhuang.hmcl.game.LauncherHelper;
|
import org.jackhuang.hmcl.game.LauncherHelper;
|
||||||
import org.jackhuang.hmcl.util.Log4jLevel;
|
import org.jackhuang.hmcl.util.Log4jLevel;
|
||||||
import org.jackhuang.hmcl.util.Logging;
|
|
||||||
import org.jackhuang.hmcl.util.platform.OperatingSystem;
|
import org.jackhuang.hmcl.util.platform.OperatingSystem;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -95,8 +94,8 @@ public final class LogWindow extends Stage {
|
|||||||
levelShownMap.values().forEach(property -> property.addListener((a, b, newValue) -> shakeLogs()));
|
levelShownMap.values().forEach(property -> property.addListener((a, b, newValue) -> shakeLogs()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void logLine(String line, Log4jLevel level) {
|
public void logLine(String filteredLine, Log4jLevel level) {
|
||||||
Log log = new Log(Logging.filterForbiddenToken(parseEscapeSequence(line)), level);
|
Log log = new Log(parseEscapeSequence(filteredLine), level);
|
||||||
logs.add(log);
|
logs.add(log);
|
||||||
if (levelShownMap.get(level).get())
|
if (levelShownMap.get(level).get())
|
||||||
impl.listView.getItems().add(log);
|
impl.listView.getItems().add(log);
|
||||||
|
@ -21,7 +21,6 @@ import org.jackhuang.hmcl.auth.AuthInfo;
|
|||||||
import org.jackhuang.hmcl.download.LibraryAnalyzer;
|
import org.jackhuang.hmcl.download.LibraryAnalyzer;
|
||||||
import org.jackhuang.hmcl.game.*;
|
import org.jackhuang.hmcl.game.*;
|
||||||
import org.jackhuang.hmcl.util.Lang;
|
import org.jackhuang.hmcl.util.Lang;
|
||||||
import org.jackhuang.hmcl.util.Log4jLevel;
|
|
||||||
import org.jackhuang.hmcl.util.StringUtils;
|
import org.jackhuang.hmcl.util.StringUtils;
|
||||||
import org.jackhuang.hmcl.util.gson.UUIDTypeAdapter;
|
import org.jackhuang.hmcl.util.gson.UUIDTypeAdapter;
|
||||||
import org.jackhuang.hmcl.util.io.FileUtils;
|
import org.jackhuang.hmcl.util.io.FileUtils;
|
||||||
@ -646,15 +645,15 @@ public class DefaultLauncher extends Launcher {
|
|||||||
throw new ExecutionPolicyLimitException();
|
throw new ExecutionPolicyLimitException();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startMonitors(ManagedProcess managedProcess, ProcessListener processListener, Charset encoding, boolean isDaemon) {
|
private static void startMonitors(ManagedProcess managedProcess, ProcessListener processListener, Charset encoding, boolean isDaemon) {
|
||||||
processListener.setProcess(managedProcess);
|
processListener.setProcess(managedProcess);
|
||||||
Thread stdout = Lang.thread(new StreamPump(managedProcess.getProcess().getInputStream(), it -> {
|
Thread stdout = Lang.thread(new StreamPump(managedProcess.getProcess().getInputStream(), it -> {
|
||||||
processListener.onLog(it, Optional.ofNullable(Log4jLevel.guessLevel(it)).orElse(Log4jLevel.INFO));
|
processListener.onLog(it, false);
|
||||||
managedProcess.addLine(it);
|
managedProcess.addLine(it);
|
||||||
}, encoding), "stdout-pump", isDaemon);
|
}, encoding), "stdout-pump", isDaemon);
|
||||||
managedProcess.addRelatedThread(stdout);
|
managedProcess.addRelatedThread(stdout);
|
||||||
Thread stderr = Lang.thread(new StreamPump(managedProcess.getProcess().getErrorStream(), it -> {
|
Thread stderr = Lang.thread(new StreamPump(managedProcess.getProcess().getErrorStream(), it -> {
|
||||||
processListener.onLog(it, Log4jLevel.ERROR);
|
processListener.onLog(it, true);
|
||||||
managedProcess.addLine(it);
|
managedProcess.addLine(it);
|
||||||
}, encoding), "stderr-pump", isDaemon);
|
}, encoding), "stderr-pump", isDaemon);
|
||||||
managedProcess.addRelatedThread(stderr);
|
managedProcess.addRelatedThread(stderr);
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.jackhuang.hmcl.launch;
|
package org.jackhuang.hmcl.launch;
|
||||||
|
|
||||||
import org.jackhuang.hmcl.util.Log4jLevel;
|
|
||||||
import org.jackhuang.hmcl.util.platform.ManagedProcess;
|
import org.jackhuang.hmcl.util.platform.ManagedProcess;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -40,7 +39,7 @@ public interface ProcessListener {
|
|||||||
*
|
*
|
||||||
* @param log the log
|
* @param log the log
|
||||||
*/
|
*/
|
||||||
void onLog(String log, Log4jLevel level);
|
void onLog(String log, boolean isErrorStream);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the game process stops.
|
* Called when the game process stops.
|
||||||
|
@ -366,6 +366,13 @@ public final class Lang {
|
|||||||
return () -> iterator;
|
return () -> iterator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static <T, U> void forEachZipped(Iterable<T> i1, Iterable<U> i2, BiConsumer<T, U> action) {
|
||||||
|
Iterator<T> it1 = i1.iterator();
|
||||||
|
Iterator<U> it2 = i2.iterator();
|
||||||
|
while (it1.hasNext() && it2.hasNext())
|
||||||
|
action.accept(it1.next(), it2.next());
|
||||||
|
}
|
||||||
|
|
||||||
private static Timer timer;
|
private static Timer timer;
|
||||||
|
|
||||||
public static synchronized Timer getTimer() {
|
public static synchronized Timer getTimer() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user