forked from StarOpenSource/Engine
Nuke StackTraceParser
This commit is contained in:
parent
f25dd19e98
commit
794f8bb471
7 changed files with 35 additions and 158 deletions
|
@ -19,9 +19,9 @@
|
||||||
|
|
||||||
package de.staropensource.sosengine.base.internal.implementation.placeholder.crashhandler;
|
package de.staropensource.sosengine.base.internal.implementation.placeholder.crashhandler;
|
||||||
|
|
||||||
import de.staropensource.sosengine.base.implementable.Placeholder;
|
|
||||||
import de.staropensource.sosengine.base.exception.UnexpectedThrowableException;
|
import de.staropensource.sosengine.base.exception.UnexpectedThrowableException;
|
||||||
import de.staropensource.sosengine.base.utility.StackTraceParser;
|
import de.staropensource.sosengine.base.implementable.Placeholder;
|
||||||
|
import de.staropensource.sosengine.base.utility.Miscellaneous;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
@ -85,12 +85,10 @@ public final class Stacktrace implements Placeholder {
|
||||||
stacktrace.append("\n");
|
stacktrace.append("\n");
|
||||||
|
|
||||||
// Append stack trace
|
// Append stack trace
|
||||||
StackTraceParser parser = new StackTraceParser(throwable);
|
|
||||||
|
|
||||||
stacktrace
|
stacktrace
|
||||||
.append(parser.getHeader())
|
.append(Miscellaneous.getStackTraceHeader(throwable))
|
||||||
.append("\n")
|
.append("\n")
|
||||||
.append(parser.getStackTrace());
|
.append(Miscellaneous.getStackTraceAsString(throwable, true));
|
||||||
|
|
||||||
// Handle throwables which contain other throwables
|
// Handle throwables which contain other throwables
|
||||||
if (throwable instanceof UnexpectedThrowableException unexpectedThrowableException)
|
if (throwable instanceof UnexpectedThrowableException unexpectedThrowableException)
|
||||||
|
|
|
@ -63,7 +63,7 @@ public final class StacktraceAll implements Placeholder {
|
||||||
.append(thread.isDaemon())
|
.append(thread.isDaemon())
|
||||||
.append(")")
|
.append(")")
|
||||||
.append("\n")
|
.append("\n")
|
||||||
.append(Miscellaneous.stringifyStackTrace(stacktraces.get(thread), false));
|
.append(Miscellaneous.getStackTraceAsString(stacktraces.get(thread), false));
|
||||||
}
|
}
|
||||||
|
|
||||||
return text.replace("%stacktrace_all%", output.toString().replace("<", "\\<"));
|
return text.replace("%stacktrace_all%", output.toString().replace("<", "\\<"));
|
||||||
|
|
|
@ -206,15 +206,25 @@ public final class Miscellaneous {
|
||||||
return Thread.currentThread().threadId() == 1;
|
return Thread.currentThread().threadId() == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the {@code Caused by} message usually found when the JVM prints a throwable.
|
||||||
|
*
|
||||||
|
* @return stack trace header
|
||||||
|
* @since v1-alpha4
|
||||||
|
*/
|
||||||
|
public static @NotNull String getStackTraceHeader(@NotNull Throwable throwable) {
|
||||||
|
return "Caused by: " + throwable.getClass().getName() + (throwable.getMessage() == null ? "" : ": " + throwable.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts an array of {@link StackTraceElement}s into a regular string.
|
* Converts an array of {@link StackTraceElement}s into a regular string.
|
||||||
*
|
*
|
||||||
* @param stacktrace array of {@link StackTraceElement}s to convert
|
* @param stacktrace array of {@link StackTraceElement}s to convert
|
||||||
* @param indent if all lines should be indented with a single {@code \t} character, like in regular stack traces
|
* @param indent if all lines should be indented with a single {@code \t} character, like in regular stack traces
|
||||||
* @return converted stacktrace string
|
* @return converted stacktrace string
|
||||||
* @since v1-alpha2
|
* @since v1-alpha4
|
||||||
*/
|
*/
|
||||||
public static @NotNull String stringifyStackTrace(@NotNull StackTraceElement[] stacktrace, boolean indent) {
|
public static @NotNull String getStackTraceAsString(@NotNull StackTraceElement[] stacktrace, boolean indent) {
|
||||||
StringBuilder output = new StringBuilder();
|
StringBuilder output = new StringBuilder();
|
||||||
|
|
||||||
for (StackTraceElement element : stacktrace) {
|
for (StackTraceElement element : stacktrace) {
|
||||||
|
@ -228,4 +238,16 @@ public final class Miscellaneous {
|
||||||
|
|
||||||
return output.toString();
|
return output.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the stacktrace of a throwable into a regular string.
|
||||||
|
*
|
||||||
|
* @param throwable throwable to derive the stacktrace from
|
||||||
|
* @param indent if all lines should be indented with a single {@code \t} character, like in regular stack traces
|
||||||
|
* @return converted stacktrace string
|
||||||
|
* @since v1-alpha4
|
||||||
|
*/
|
||||||
|
public static @NotNull String getStackTraceAsString(@NotNull Throwable throwable, boolean indent) {
|
||||||
|
return getStackTraceAsString(throwable.getStackTrace(), indent);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,78 +0,0 @@
|
||||||
/*
|
|
||||||
* STAROPENSOURCE ENGINE SOURCE FILE
|
|
||||||
* Copyright (c) 2024 The StarOpenSource Engine Authors
|
|
||||||
* Licensed under the GNU Affero General Public License v3
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as
|
|
||||||
* published by the Free Software Foundation, either version 3 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package de.staropensource.sosengine.base.utility;
|
|
||||||
|
|
||||||
import lombok.AccessLevel;
|
|
||||||
import lombok.Getter;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parses the stacktrace of a {@link Throwable} for use in {@link String}s.
|
|
||||||
*
|
|
||||||
* @see Throwable
|
|
||||||
* @since v1-alpha0
|
|
||||||
*/
|
|
||||||
// TODO deprecate """parser""" and move getHeader() to Miscellaneous class
|
|
||||||
public final class StackTraceParser {
|
|
||||||
/**
|
|
||||||
* Contains the {@link Throwable} to parse.
|
|
||||||
*
|
|
||||||
* @see Throwable
|
|
||||||
* @since v1-alpha0
|
|
||||||
* -- GETTER --
|
|
||||||
* Returns the {@link Throwable} to parse.
|
|
||||||
*
|
|
||||||
* @see Throwable
|
|
||||||
* @since v1-alpha0
|
|
||||||
*/
|
|
||||||
@Getter(AccessLevel.PROTECTED)
|
|
||||||
private final @NotNull Throwable throwable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs this class.
|
|
||||||
*
|
|
||||||
* @param throwable throwable to parse
|
|
||||||
* @since v1-alpha0
|
|
||||||
*/
|
|
||||||
public StackTraceParser(@NotNull Throwable throwable) {
|
|
||||||
this.throwable = throwable;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the stack trace header.
|
|
||||||
* It looks like this: {@code Caused by java.lang.NullPointerThrowable: This application can crash!}
|
|
||||||
*
|
|
||||||
* @return stack trace header
|
|
||||||
* @since v1-alpha0
|
|
||||||
*/
|
|
||||||
public @NotNull String getHeader() {
|
|
||||||
return "Caused by: " + throwable.getClass().getName() + (throwable.getMessage() == null ? "" : ": " + throwable.getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the stack trace.
|
|
||||||
*
|
|
||||||
* @return stack trace
|
|
||||||
* @since v1-alpha0
|
|
||||||
*/
|
|
||||||
public @NotNull String getStackTrace() {
|
|
||||||
return Miscellaneous.stringifyStackTrace(throwable.getStackTrace(), true);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -22,8 +22,8 @@ package de.staropensource.sosengine.base.utility.information;
|
||||||
import de.staropensource.sosengine.base.Engine;
|
import de.staropensource.sosengine.base.Engine;
|
||||||
import de.staropensource.sosengine.base.logging.LoggerInstance;
|
import de.staropensource.sosengine.base.logging.LoggerInstance;
|
||||||
import de.staropensource.sosengine.base.type.VersionType;
|
import de.staropensource.sosengine.base.type.VersionType;
|
||||||
|
import de.staropensource.sosengine.base.utility.Miscellaneous;
|
||||||
import de.staropensource.sosengine.base.utility.PropertiesReader;
|
import de.staropensource.sosengine.base.utility.PropertiesReader;
|
||||||
import de.staropensource.sosengine.base.utility.StackTraceParser;
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
@ -427,9 +427,8 @@ public final class EngineInformation {
|
||||||
calendar.setTime(date);
|
calendar.setTime(date);
|
||||||
gitCommitTime = calendar.toZonedDateTime();
|
gitCommitTime = calendar.toZonedDateTime();
|
||||||
} catch (ParseException exception) {
|
} catch (ParseException exception) {
|
||||||
StackTraceParser parser = new StackTraceParser(exception);
|
|
||||||
System.out.println("Unable to load build information: Can't parse \"" + gitParser.getString("git.commit.time") + "\" using format \"yyyy-MM-dd'T'HH:mmZ\"");
|
System.out.println("Unable to load build information: Can't parse \"" + gitParser.getString("git.commit.time") + "\" using format \"yyyy-MM-dd'T'HH:mmZ\"");
|
||||||
System.out.println(parser.getHeader() + "\n" + parser.getStackTrace());
|
System.out.println(Miscellaneous.getStackTraceHeader(exception) + "\n" + Miscellaneous.getStackTraceAsString(exception, true));
|
||||||
Engine.getInstance().shutdown(69);
|
Engine.getInstance().shutdown(69);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,61 +0,0 @@
|
||||||
/*
|
|
||||||
* STAROPENSOURCE ENGINE SOURCE FILE
|
|
||||||
* Copyright (c) 2024 The StarOpenSource Engine Authors
|
|
||||||
* Licensed under the GNU Affero General Public License v3
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as
|
|
||||||
* published by the Free Software Foundation, either version 3 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package de.staropensource.sosengine.base.srctests.utility;
|
|
||||||
|
|
||||||
import de.staropensource.sosengine.base.srctests.TestBase;
|
|
||||||
import de.staropensource.sosengine.base.utility.StackTraceParser;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.junit.jupiter.api.DisplayName;
|
|
||||||
import org.junit.jupiter.params.ParameterizedTest;
|
|
||||||
import org.junit.jupiter.params.provider.ValueSource;
|
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests the class {@link StackTraceParser}.
|
|
||||||
*/
|
|
||||||
@DisplayName("StackTraceParser")
|
|
||||||
class StackTraceParserTest extends TestBase {
|
|
||||||
/**
|
|
||||||
* Tests the method {@code getHeader}.
|
|
||||||
*/
|
|
||||||
@ParameterizedTest
|
|
||||||
@DisplayName("getHeader")
|
|
||||||
@ValueSource(strings = {
|
|
||||||
"",
|
|
||||||
"This is an example message",
|
|
||||||
"Some description here..."
|
|
||||||
})
|
|
||||||
void testGetHeader(@NotNull String message) {
|
|
||||||
if (checkCondition()) return;
|
|
||||||
getLogger().testCall("testGetHeader", message);
|
|
||||||
|
|
||||||
String output;
|
|
||||||
if (message.isEmpty())
|
|
||||||
output = new StackTraceParser(new NumberFormatException()).getHeader();
|
|
||||||
else
|
|
||||||
output = new StackTraceParser(new NumberFormatException(message)).getHeader();
|
|
||||||
|
|
||||||
String expected = "Caused by: " + NumberFormatException.class.getName();
|
|
||||||
if (!message.isEmpty())
|
|
||||||
expected += ": " + message;
|
|
||||||
assertEquals(expected, output, "Output \"" + output + "\" does not match expected output \"" + expected + "\"");
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -23,7 +23,7 @@ import de.staropensource.sosengine.base.Engine;
|
||||||
import de.staropensource.sosengine.base.annotation.EventListener;
|
import de.staropensource.sosengine.base.annotation.EventListener;
|
||||||
import de.staropensource.sosengine.base.logging.LoggerInstance;
|
import de.staropensource.sosengine.base.logging.LoggerInstance;
|
||||||
import de.staropensource.sosengine.base.type.vector.Vec2i;
|
import de.staropensource.sosengine.base.type.vector.Vec2i;
|
||||||
import de.staropensource.sosengine.base.utility.StackTraceParser;
|
import de.staropensource.sosengine.base.utility.Miscellaneous;
|
||||||
import de.staropensource.sosengine.windowing.WindowingSubsystem;
|
import de.staropensource.sosengine.windowing.WindowingSubsystem;
|
||||||
import de.staropensource.sosengine.windowing.event.InputEvent;
|
import de.staropensource.sosengine.windowing.event.InputEvent;
|
||||||
import de.staropensource.sosengine.windowing.implementable.Window;
|
import de.staropensource.sosengine.windowing.implementable.Window;
|
||||||
|
@ -148,18 +148,15 @@ public final class Main {
|
||||||
StringBuilder message = new StringBuilder();
|
StringBuilder message = new StringBuilder();
|
||||||
message.append("Render loop failed on some windows:\n");
|
message.append("Render loop failed on some windows:\n");
|
||||||
|
|
||||||
for (Window windowFailed : renderLoopFailures.keySet()) {
|
for (Window windowFailed : renderLoopFailures.keySet())
|
||||||
StackTraceParser parser = new StackTraceParser(renderLoopFailures.get(windowFailed));
|
|
||||||
|
|
||||||
message
|
message
|
||||||
.append("-> ")
|
.append("-> ")
|
||||||
.append(window)
|
.append(window)
|
||||||
.append(": ")
|
.append(": ")
|
||||||
.append(parser.getHeader())
|
.append(Miscellaneous.getStackTraceHeader(renderLoopFailures.get(windowFailed)))
|
||||||
.append("\n")
|
.append("\n")
|
||||||
.append(parser.getStackTrace())
|
.append(Miscellaneous.getStackTraceAsString(renderLoopFailures.get(windowFailed), true))
|
||||||
.append("\n");
|
.append("\n");
|
||||||
}
|
|
||||||
|
|
||||||
logger.crash(message.toString());
|
logger.crash(message.toString());
|
||||||
} catch (Exception exception) {
|
} catch (Exception exception) {
|
||||||
|
|
Loading…
Reference in a new issue