From 027c1a867fbe700262b931578e0634442976447f Mon Sep 17 00:00:00 2001 From: Stekeblad Date: Mon, 23 Dec 2019 11:54:00 +0100 Subject: [PATCH] Created logic for limiting the number of identical error messages that appears in popups. From now there should be a cooldown of 15 seconds between exception dialogs opening for identical stacktraces. The cooldown may need to be tweeked later but I think this is better than before. --- .../videouploader/utils/AlertUtils.java | 21 +++++--- .../exceptionHistory/ExceptionHistory.java | 52 +++++++++++++++++++ .../ExceptionHistoryPost.java | 31 +++++++++++ 3 files changed, 96 insertions(+), 8 deletions(-) create mode 100644 src/main/java/io/github/stekeblad/videouploader/utils/exceptionHistory/ExceptionHistory.java create mode 100644 src/main/java/io/github/stekeblad/videouploader/utils/exceptionHistory/ExceptionHistoryPost.java diff --git a/src/main/java/io/github/stekeblad/videouploader/utils/AlertUtils.java b/src/main/java/io/github/stekeblad/videouploader/utils/AlertUtils.java index c3df1b7..ab078d3 100644 --- a/src/main/java/io/github/stekeblad/videouploader/utils/AlertUtils.java +++ b/src/main/java/io/github/stekeblad/videouploader/utils/AlertUtils.java @@ -1,5 +1,6 @@ package io.github.stekeblad.videouploader.utils; +import io.github.stekeblad.videouploader.utils.exceptionHistory.ExceptionHistory; import javafx.application.Platform; import javafx.geometry.HPos; import javafx.geometry.Insets; @@ -24,6 +25,8 @@ */ public class AlertUtils { + private static ExceptionHistory exceptionHistory = new ExceptionHistory(); + /** * Creates an Alert, sets Modality, Header, Content and adjusts the minHeight * @param header Custom window title @@ -163,14 +166,16 @@ public static void simpleClose_longContent(String header, String content) { */ public static void exceptionDialog(String header, String content, Throwable exception) { String stackTrace = getStacktrace(exception); - String fullContent = content + - "\nHere is the error details:" + - "\n-----------------------------------------" + - "\n" + exception.getMessage() + - "\n-----------------------------------------" + - "\n" + stackTrace; - GridPane pane = makeLongMsgPane(fullContent, false); - paneToWindow(pane, header); + if (!exceptionHistory.isInHistory(stackTrace)) { + String fullContent = content + + "\nHere is the error details:" + + "\n-----------------------------------------" + + "\n" + exception.getMessage() + + "\n-----------------------------------------" + + "\n" + stackTrace; + GridPane pane = makeLongMsgPane(fullContent, false); + paneToWindow(pane, header); + } } /** diff --git a/src/main/java/io/github/stekeblad/videouploader/utils/exceptionHistory/ExceptionHistory.java b/src/main/java/io/github/stekeblad/videouploader/utils/exceptionHistory/ExceptionHistory.java new file mode 100644 index 0000000..159f3c2 --- /dev/null +++ b/src/main/java/io/github/stekeblad/videouploader/utils/exceptionHistory/ExceptionHistory.java @@ -0,0 +1,52 @@ +package io.github.stekeblad.videouploader.utils.exceptionHistory; + +import java.time.Duration; +import java.util.ArrayList; + +/** + * The ExceptionHistory holds a list of {@link io.github.stekeblad.videouploader.utils.exceptionHistory.ExceptionHistoryPost} + * with exceptions that recently have been seen. The purpose is to prevent multiple error dialogs from displaying the + * same error message in rapid succession. This can be archived by calling the {@link #isInHistory(String)} method and + * checking the return value before showing an exception dialog. If true is returned then an exception with the same + * stacktrace was seen less than 15 seconds ago and you may want to skip showing an error message. + */ +public class ExceptionHistory { + private ArrayList exceptionHistoryPosts; + + public ExceptionHistory() { + exceptionHistoryPosts = new ArrayList<>(); + } + + /** + * Checks if an exception with the same stacktrace as {@code stacktrace} has been seen within the last 15 seconds + * and if so returns true, if there is no record of an identical stacktrace then the stacktrace is recorded and + * false is returned. If unsure how to get the stacktrace as a string, please look at {@code getStacktrace(Throwable)} + * in the class {@link io.github.stekeblad.videouploader.utils.AlertUtils} + * + * @param stacktrace the stacktrace to compare to previously seen stacktraces + * @return true if an identical stacktrace has been seen in the last 15 seconds, false otherwise. + */ + public boolean isInHistory(String stacktrace) { + for (int i = 0; i < exceptionHistoryPosts.size(); /* no increment */) { + ExceptionHistoryPost post = exceptionHistoryPosts.get(i); + // Test the age of the history post. + // If it was more than a minute ago since its first appeared its to old and should be removed. + // in this case we do not want to increment i because we remove one element and everything after it is shifted + // one step towards the beginning on the list. + if (post.getTimeSinceAdded().compareTo(Duration.ofSeconds(15)) > 0) + exceptionHistoryPosts.remove(i); + + // Check if it exists a stacktrace in the exceptionHistoryPosts with the same stacktrace as the provided one. + // If there is a match this exception happened recently, return true. + else if (post.getStacktrace().equals(stacktrace)) + return true; + + // Else progress to the next post + else + i++; + } + // The stacktrace is new, add it to the history + exceptionHistoryPosts.add(new ExceptionHistoryPost(stacktrace)); + return false; + } +} diff --git a/src/main/java/io/github/stekeblad/videouploader/utils/exceptionHistory/ExceptionHistoryPost.java b/src/main/java/io/github/stekeblad/videouploader/utils/exceptionHistory/ExceptionHistoryPost.java new file mode 100644 index 0000000..1ebdd4c --- /dev/null +++ b/src/main/java/io/github/stekeblad/videouploader/utils/exceptionHistory/ExceptionHistoryPost.java @@ -0,0 +1,31 @@ +package io.github.stekeblad.videouploader.utils.exceptionHistory; + +import java.time.Duration; +import java.time.Instant; + +/** + * ExceptionHistoryPost represents one exception that has happened and contains its stacktrace and the + * {@link java.time.Instant} the post was created. ExceptionHistoryPost is used by + * {@link io.github.stekeblad.videouploader.utils.exceptionHistory.ExceptionHistory} to track exceptions that recently + * been caught and prevent multiple error dialogs from displaying the same error message in rapid succession. + */ +class ExceptionHistoryPost { + private String Stacktrace; + private Instant TimeAdded; + + ExceptionHistoryPost(String stacktrace) { + Stacktrace = stacktrace; + TimeAdded = Instant.now(); + } + + String getStacktrace() { + return Stacktrace; + } + + /** + * @return the time between the current instant and the instant the ExceptionHistoryPost was created + */ + Duration getTimeSinceAdded() { + return Duration.between(TimeAdded, Instant.now()); + } +}