diff --git a/application/src/main/java/org/togetherjava/tjbot/logging/discord/DiscordLogForwarder.java b/application/src/main/java/org/togetherjava/tjbot/logging/discord/DiscordLogForwarder.java
index 92b087d073..76f9186444 100644
--- a/application/src/main/java/org/togetherjava/tjbot/logging/discord/DiscordLogForwarder.java
+++ b/application/src/main/java/org/togetherjava/tjbot/logging/discord/DiscordLogForwarder.java
@@ -35,14 +35,32 @@ final class DiscordLogForwarder {
private static final Logger logger = LoggerFactory.getLogger(DiscordLogForwarder.class);
private static final int MAX_PENDING_LOGS = 10_000;
- private static final int MAX_BATCH_SIZE = WebhookMessage.MAX_EMBEDS;
+ private static final int MAX_PENDING_LOGS_WARNING_THRESHOLD = 8_000;
+
private static final ScheduledExecutorService SERVICE =
Executors.newSingleThreadScheduledExecutor();
+
+ private static final int MAX_BATCH_SIZE = WebhookMessage.MAX_EMBEDS;
+ /**
+ * The max total length of all descriptions contained in a batch of embeds sent to Discord.
+ */
+ private static final int MAX_BATCH_DESCRIPTION_TOTAL = 6_000;
/**
- * Has to be small enough for fitting all {@value MAX_BATCH_SIZE} embeds contained in a batch
- * into the total character length of ~6000.
+ * Has to be small enough for fitting most {@value MAX_BATCH_SIZE} embeds contained in a batch
+ * into the total character length of {@value MAX_BATCH_DESCRIPTION_TOTAL}.
+ *
+ * This limit is preferred to {@link #MAX_EMBED_DESCRIPTION_SHORT}, as usually only a few
+ * messages are too large and need to be limited.
*/
private static final int MAX_EMBED_DESCRIPTION = 1_000;
+ /**
+ * Small enough for fitting all {@value MAX_BATCH_SIZE} embeds contained in a batch into the
+ * total character length of {@value MAX_BATCH_DESCRIPTION_TOTAL}.
+ *
+ * Used when {@link #MAX_EMBED_DESCRIPTION} lead to exceeding the limit.
+ */
+ private static final int MAX_EMBED_DESCRIPTION_SHORT = 400;
+
private static final Map LEVEL_TO_AMBIENT_COLOR =
Map.of(Level.TRACE, 0x00B362, Level.DEBUG, 0x00A5CE, Level.INFO, 0xAC59FF, Level.WARN,
0xDFDF00, Level.ERROR, 0xBF2200, Level.FATAL, 0xFF8484);
@@ -80,6 +98,13 @@ void forwardLogEvent(LogEvent event) {
Logs are forwarded to Discord slower than they pile up. Discarding the latest log...""");
return;
}
+ if (pendingLogs.size() >= MAX_PENDING_LOGS_WARNING_THRESHOLD) {
+ logger.warn("""
+ Nearing the max amount of logs that can be buffered. \
+ Logs are forwarded to Discord slower than they pile up. \
+ Look into the issue, logs will soon be discarded otherwise...
+ """);
+ }
LogMessage log = LogMessage.ofEvent(event);
@@ -95,6 +120,7 @@ private void processPendingLogs() {
if (logsToProcess.isEmpty()) {
return;
}
+ logsToProcess = validateBatch(logsToProcess);
List logBatch = logsToProcess.stream().map(LogMessage::embed).toList();
@@ -112,6 +138,21 @@ private List pollLogsToProcessBatch() {
}
}
+ private List validateBatch(List logBatch) {
+ int totalDescriptionLength = logBatch.stream()
+ .map(LogMessage::embed)
+ .map(WebhookEmbed::getDescription)
+ .mapToInt(description -> description == null ? 0 : description.length())
+ .sum();
+
+ if (totalDescriptionLength >= MAX_BATCH_DESCRIPTION_TOTAL) {
+ // Shorten logs further to go below limit
+ return logBatch.stream().map(LogMessage::shortened).toList();
+ }
+
+ return new ArrayList<>(logBatch);
+ }
+
private record LogMessage(WebhookEmbed embed,
Instant timestamp) implements Comparable {
@@ -146,6 +187,15 @@ private static String abbreviate(String text, int maxLength) {
return text.substring(0, maxLength - 3) + "...";
}
+ private LogMessage shortened() {
+ String shortDescription =
+ abbreviate(embed.getDescription(), MAX_EMBED_DESCRIPTION_SHORT);
+ WebhookEmbed shortEmbed =
+ new WebhookEmbedBuilder(embed).setDescription(shortDescription).build();
+
+ return new LogMessage(shortEmbed, timestamp);
+ }
+
@Override
public int compareTo(@NotNull LogMessage o) {
return timestamp.compareTo(o.timestamp);