diff --git a/base/src/main/java/de/staropensource/sosengine/base/Engine.java b/base/src/main/java/de/staropensource/sosengine/base/Engine.java index 61d741af..8da30c9f 100644 --- a/base/src/main/java/de/staropensource/sosengine/base/Engine.java +++ b/base/src/main/java/de/staropensource/sosengine/base/Engine.java @@ -225,6 +225,7 @@ public final class Engine implements SubsystemMainClass { CrashHandler.getCrashContent().put("Java Virtual Machine", crashContentJvm); CrashHandler.getCrashContent().put("Operating system", crashContentOS); CrashHandler.getCrashContent().put("Stacktrace", "\n%stacktrace%"); + CrashHandler.getCrashContent().put("Stacktrace for all threads", "\n%stacktrace_all%"); } /** diff --git a/base/src/main/java/de/staropensource/sosengine/base/internal/placeholders/crashhandler/StacktraceAll.java b/base/src/main/java/de/staropensource/sosengine/base/internal/placeholders/crashhandler/StacktraceAll.java new file mode 100644 index 00000000..f7455068 --- /dev/null +++ b/base/src/main/java/de/staropensource/sosengine/base/internal/placeholders/crashhandler/StacktraceAll.java @@ -0,0 +1,72 @@ +/* + * STAROPENSOURCE ENGINE SOURCE FILE + * Copyright (c) 2024 The StarOpenSource Engine Contributors + * 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 . + */ + +package de.staropensource.sosengine.base.internal.placeholders.crashhandler; + +import de.staropensource.sosengine.base.classes.Placeholder; +import de.staropensource.sosengine.base.utility.Miscellaneous; +import org.jetbrains.annotations.NotNull; + +import java.util.Map; + +/** + * Implements the {@code stacktrace_all} placeholder. + * + * @see Placeholder + * @since v1-alpha0 + */ +@SuppressWarnings({ "unused" }) +public final class StacktraceAll implements Placeholder { + /** + * Constructs this class. + * + * @since v1-alpha2 + */ + public StacktraceAll() {} + + /** {@inheritDoc} */ + @NotNull + @Override + public String replace(@NotNull String text) { + StringBuilder output = new StringBuilder(); + Map stacktraces = Thread.getAllStackTraces(); + + for (Thread thread : stacktraces.keySet()) { + if (!output.isEmpty()) + output.append("\n\n"); + output + .append(thread.getName()) + .append(" (id=") + .append(thread.threadId()) + .append(" priority=") + .append(thread.getPriority()) + .append(" group=") + .append(thread.getThreadGroup().getName()) + .append(" state=") + .append(thread.getState().name()) + .append(" daemon=") + .append(thread.isDaemon()) + .append(")") + .append("\n") + .append(Miscellaneous.stringifyStackTrace(stacktraces.get(thread), false)); + } + + return text.replace("%stacktrace_all%", output.toString()); + } +} diff --git a/base/src/main/java/de/staropensource/sosengine/base/logging/CrashHandler.java b/base/src/main/java/de/staropensource/sosengine/base/logging/CrashHandler.java index 0fb2f858..1670c419 100644 --- a/base/src/main/java/de/staropensource/sosengine/base/logging/CrashHandler.java +++ b/base/src/main/java/de/staropensource/sosengine/base/logging/CrashHandler.java @@ -136,8 +136,9 @@ public final class CrashHandler { temporaryPlaceholders.add(new IssuerInfo(logIssuer)); temporaryPlaceholders.add(new IssuerPackage(logIssuer)); temporaryPlaceholders.add(new IssuerPath(logIssuer)); - // etc + // stacktrace* temporaryPlaceholders.add(new Stacktrace(throwable)); + temporaryPlaceholders.add(new StacktraceAll()); // Replace placeholders base = PlaceholderEngine.getInstance().process(base, temporaryPlaceholders); diff --git a/base/src/main/java/de/staropensource/sosengine/base/utility/Miscellaneous.java b/base/src/main/java/de/staropensource/sosengine/base/utility/Miscellaneous.java index 2b5ca047..bb4a5e44 100644 --- a/base/src/main/java/de/staropensource/sosengine/base/utility/Miscellaneous.java +++ b/base/src/main/java/de/staropensource/sosengine/base/utility/Miscellaneous.java @@ -217,4 +217,28 @@ public final class Miscellaneous { public static boolean onMainThread() { return Thread.currentThread().threadId() == 1; } + + /** + * Converts an array of {@link StackTraceElement}s into a regular string. + * + * @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 + * @return converted stacktrace string + * @since v1-alpha2 + */ + @NotNull + public static String stringifyStackTrace(@NotNull StackTraceElement[] stacktrace, boolean indent) { + StringBuilder output = new StringBuilder(); + + for (StackTraceElement element : stacktrace) { + if (!output.isEmpty()) + output.append("\n"); + if (indent) + output.append("\t"); + + output.append("at ").append(element); + } + + return output.toString(); + } } diff --git a/base/src/main/java/de/staropensource/sosengine/base/utility/parser/StackTraceParser.java b/base/src/main/java/de/staropensource/sosengine/base/utility/parser/StackTraceParser.java index 4bac3770..4822edb1 100644 --- a/base/src/main/java/de/staropensource/sosengine/base/utility/parser/StackTraceParser.java +++ b/base/src/main/java/de/staropensource/sosengine/base/utility/parser/StackTraceParser.java @@ -19,6 +19,7 @@ package de.staropensource.sosengine.base.utility.parser; +import de.staropensource.sosengine.base.utility.Miscellaneous; import lombok.AccessLevel; import lombok.Getter; import org.jetbrains.annotations.NotNull; @@ -79,13 +80,6 @@ public final class StackTraceParser { */ @NotNull public String getStackTrace() { - StringBuilder output = new StringBuilder(); - - for (StackTraceElement element : throwable.getStackTrace()) { - if (!output.isEmpty()) output.append("\n"); - output.append("\tat ").append(element.toString()); - } - - return output.toString(); + return Miscellaneous.stringifyStackTrace(throwable.getStackTrace(), true); } }