From 399c04dec40c4030cbe5720f57246de40040bb65 Mon Sep 17 00:00:00 2001 From: SquidXTV Date: Sun, 16 Jul 2023 00:18:33 +0200 Subject: [PATCH 1/6] Added sourceCodeBaseUrl entry in config --- application/config.json.template | 5 +++-- .../java/org/togetherjava/tjbot/config/Config.java | 14 +++++++++++++- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/application/config.json.template b/application/config.json.template index 84ac087cb0..df769b5ce3 100644 --- a/application/config.json.template +++ b/application/config.json.template @@ -87,6 +87,7 @@ "wsh" ], "logInfoChannelWebhook": "", - "logErrorChannelWebhook": "" - "openaiApiKey": "" + "logErrorChannelWebhook": "", + "openaiApiKey": "", + "sourceCodeBaseUrl": "" } diff --git a/application/src/main/java/org/togetherjava/tjbot/config/Config.java b/application/src/main/java/org/togetherjava/tjbot/config/Config.java index e5933ca262..4afebc7e06 100644 --- a/application/src/main/java/org/togetherjava/tjbot/config/Config.java +++ b/application/src/main/java/org/togetherjava/tjbot/config/Config.java @@ -37,6 +37,7 @@ public final class Config { private final String logInfoChannelWebhook; private final String logErrorChannelWebhook; private final String openaiApiKey; + private final String sourceCodeBaseUrl; @SuppressWarnings("ConstructorWithTooManyParameters") @JsonCreator(mode = JsonCreator.Mode.PROPERTIES) @@ -72,7 +73,8 @@ private Config(@JsonProperty(value = "token", required = true) String token, required = true) String logInfoChannelWebhook, @JsonProperty(value = "logErrorChannelWebhook", required = true) String logErrorChannelWebhook, - @JsonProperty(value = "openaiApiKey", required = true) String openaiApiKey) { + @JsonProperty(value = "openaiApiKey", required = true) String openaiApiKey, + @JsonProperty(value = "sourceCodeBaseUrl", required = true) String sourceCodeBaseUrl) { this.token = Objects.requireNonNull(token); this.gistApiKey = Objects.requireNonNull(gistApiKey); this.databasePath = Objects.requireNonNull(databasePath); @@ -96,6 +98,7 @@ private Config(@JsonProperty(value = "token", required = true) String token, this.logInfoChannelWebhook = Objects.requireNonNull(logInfoChannelWebhook); this.logErrorChannelWebhook = Objects.requireNonNull(logErrorChannelWebhook); this.openaiApiKey = Objects.requireNonNull(openaiApiKey); + this.sourceCodeBaseUrl = Objects.requireNonNull(sourceCodeBaseUrl); } /** @@ -316,4 +319,13 @@ public String getLogErrorChannelWebhook() { public String getOpenaiApiKey() { return openaiApiKey; } + + /** + * The Base URL of the Source code to link tj-bot originated logs to the GitHub file. + * + * @return the base url of the source code + */ + public String getSourceCodeBaseUrl() { + return sourceCodeBaseUrl; + } } From df223dc0137a6ea76a389d97273b968383c1ad42 Mon Sep 17 00:00:00 2001 From: SquidXTV Date: Sun, 16 Jul 2023 00:21:03 +0200 Subject: [PATCH 2/6] Added linkable title functionality --- .../logging/discord/DiscordLogAppender.java | 15 ++++++++--- .../logging/discord/DiscordLogForwarder.java | 25 +++++++++++++++---- .../tjbot/logging/discord/DiscordLogging.java | 7 +++--- 3 files changed, 36 insertions(+), 11 deletions(-) diff --git a/application/src/main/java/org/togetherjava/tjbot/logging/discord/DiscordLogAppender.java b/application/src/main/java/org/togetherjava/tjbot/logging/discord/DiscordLogAppender.java index c826e5066e..563387391b 100644 --- a/application/src/main/java/org/togetherjava/tjbot/logging/discord/DiscordLogAppender.java +++ b/application/src/main/java/org/togetherjava/tjbot/logging/discord/DiscordLogAppender.java @@ -19,10 +19,10 @@ final class DiscordLogAppender extends AbstractAppender { private final DiscordLogForwarder logForwarder; private DiscordLogAppender(String name, Filter filter, StringLayout layout, - boolean ignoreExceptions, URI webhook) { + boolean ignoreExceptions, URI webhook, String sourceCodeBaseUrl) { super(name, filter, layout, ignoreExceptions, NO_PROPERTIES); - logForwarder = new DiscordLogForwarder(webhook); + logForwarder = new DiscordLogForwarder(webhook, sourceCodeBaseUrl); } @Override @@ -43,11 +43,20 @@ static final class DiscordLogAppenderBuilder @Required private URI webhook; + @Required + private String sourceCodeBaseUrl; + + public DiscordLogAppenderBuilder setWebhook(URI webhook) { this.webhook = webhook; return asBuilder(); } + public DiscordLogAppenderBuilder setSourceCodeBaseUrl(String sourceCodeBaseUrl) { + this.sourceCodeBaseUrl = sourceCodeBaseUrl; + return asBuilder(); + } + @Override public DiscordLogAppender build() { Layout layout = getOrCreateLayout(); @@ -58,7 +67,7 @@ public DiscordLogAppender build() { String name = Objects.requireNonNull(getName()); return new DiscordLogAppender(name, getFilter(), (StringLayout) layout, - isIgnoreExceptions(), webhook); + isIgnoreExceptions(), webhook, sourceCodeBaseUrl); } } } 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 ece1a49a5a..69da7c2162 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 @@ -13,6 +13,8 @@ import org.togetherjava.tjbot.features.utils.MessageUtils; import org.togetherjava.tjbot.logging.LogMarkers; +import javax.annotation.Nullable; + import java.io.PrintWriter; import java.io.StringWriter; import java.net.URI; @@ -70,6 +72,7 @@ final class DiscordLogForwarder { 0xDFDF00, Level.ERROR, 0xBF2200, Level.FATAL, 0xFF8484); private final WebhookClient webhookClient; + private final String sourceCodeBaseUrl; /** * Internal buffer of logs that still have to be forwarded to Discord. Actions are synchronized * using {@link #pendingLogsLock} to ensure thread safety. @@ -77,8 +80,10 @@ final class DiscordLogForwarder { private final Queue pendingLogs = new PriorityQueue<>(); private final Object pendingLogsLock = new Object(); - DiscordLogForwarder(URI webhook) { + + DiscordLogForwarder(URI webhook, String sourceCodeBaseUrl) { webhookClient = WebhookClient.withUrl(webhook.toString()); + this.sourceCodeBaseUrl = sourceCodeBaseUrl; SERVICE.scheduleWithFixedDelay(this::processPendingLogs, 5, 5, TimeUnit.SECONDS); } @@ -110,7 +115,7 @@ void forwardLogEvent(LogEvent event) { """); } - LogMessage log = LogMessage.ofEvent(event); + LogMessage log = LogMessage.ofEvent(event, sourceCodeBaseUrl); synchronized (pendingLogsLock) { pendingLogs.add(log); @@ -160,7 +165,9 @@ private List validateBatch(List logBatch) { private record LogMessage(WebhookEmbed embed, Instant timestamp) implements Comparable { - private static LogMessage ofEvent(LogEvent event) { + private static final String BASE_PACKAGE = "org.togetherjava.tjbot."; + + private static LogMessage ofEvent(LogEvent event, String sourceCodeBaseUrl) { String authorName = event.getLoggerName(); String title = event.getLevel().name(); int colorDecimal = Objects.requireNonNull(LEVEL_TO_AMBIENT_COLOR.get(event.getLevel())); @@ -169,13 +176,13 @@ private static LogMessage ofEvent(LogEvent event) { Instant timestamp = Instant.ofEpochMilli(event.getInstant().getEpochMillisecond()); WebhookEmbed embed = new WebhookEmbedBuilder() - .setAuthor(new WebhookEmbed.EmbedAuthor(authorName, null, null)) + .setAuthor(new WebhookEmbed.EmbedAuthor(authorName, null, + linkToSource(event.getSource().getClassName(), sourceCodeBaseUrl))) .setTitle(new WebhookEmbed.EmbedTitle(title, null)) .setDescription(description) .setColor(colorDecimal) .setTimestamp(timestamp) .build(); - return new LogMessage(embed, timestamp); } @@ -193,6 +200,14 @@ private static String describeLogEvent(LogEvent event) { return logMessage + "\n" + exceptionWriter.toString().replace("\t", "> "); } + private static @Nullable String linkToSource(String source, String sourceCodeBaseUrl) { + if (!source.startsWith(BASE_PACKAGE)) { + return null; + } + + return sourceCodeBaseUrl + source.replace('.', '/') + ".java"; + } + private LogMessage shortened() { String shortDescription = MessageUtils.abbreviate( Objects.requireNonNull(embed.getDescription()), MAX_EMBED_DESCRIPTION_SHORT); diff --git a/application/src/main/java/org/togetherjava/tjbot/logging/discord/DiscordLogging.java b/application/src/main/java/org/togetherjava/tjbot/logging/discord/DiscordLogging.java index da53282cf7..99d2de7970 100644 --- a/application/src/main/java/org/togetherjava/tjbot/logging/discord/DiscordLogging.java +++ b/application/src/main/java/org/togetherjava/tjbot/logging/discord/DiscordLogging.java @@ -47,11 +47,11 @@ public static void startDiscordLogging(Config botConfig) { private static void addAppenders(Configuration logConfig, Config botConfig) { parseWebhookUri(botConfig.getLogInfoChannelWebhook()) .ifPresent(webhookUri -> addDiscordLogAppender("DiscordInfo", createInfoRangeFilter(), - webhookUri, logConfig)); + webhookUri, botConfig.getSourceCodeBaseUrl(), logConfig)); parseWebhookUri(botConfig.getLogErrorChannelWebhook()) .ifPresent(webhookUri -> addDiscordLogAppender("DiscordError", createErrorRangeFilter(), - webhookUri, logConfig)); + webhookUri, botConfig.getSourceCodeBaseUrl(), logConfig)); } private static Optional parseWebhookUri(String webhookUri) { @@ -71,7 +71,7 @@ private static Optional parseWebhookUri(String webhookUri) { // to the config. @SuppressWarnings("squid:S4792") private static void addDiscordLogAppender(String name, Filter filter, URI webhookUri, - Configuration logConfig) { + String sourceCodeBaseUrl, Configuration logConfig) { // NOTE The whole setup is done programmatically in order to allow the webhooks // to be read from the config file Filter[] filters = {filter, createDenyMarkerFilter(LogMarkers.NO_DISCORD.getName()), @@ -80,6 +80,7 @@ private static void addDiscordLogAppender(String name, Filter filter, URI webhoo Appender appender = DiscordLogAppender.newBuilder() .setName(name) .setWebhook(webhookUri) + .setSourceCodeBaseUrl(sourceCodeBaseUrl) .setFilter(CompositeFilter.createFilters(filters)) .build(); From 2d91f8c3ff8287cc196286210cdc958e68b42602 Mon Sep 17 00:00:00 2001 From: SquidXTV Date: Sun, 16 Jul 2023 13:24:00 +0200 Subject: [PATCH 3/6] Requested changes --- .../tjbot/logging/discord/DiscordLogAppender.java | 1 - .../tjbot/logging/discord/DiscordLogForwarder.java | 5 ++--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/application/src/main/java/org/togetherjava/tjbot/logging/discord/DiscordLogAppender.java b/application/src/main/java/org/togetherjava/tjbot/logging/discord/DiscordLogAppender.java index 563387391b..fbf6e97a83 100644 --- a/application/src/main/java/org/togetherjava/tjbot/logging/discord/DiscordLogAppender.java +++ b/application/src/main/java/org/togetherjava/tjbot/logging/discord/DiscordLogAppender.java @@ -46,7 +46,6 @@ static final class DiscordLogAppenderBuilder @Required private String sourceCodeBaseUrl; - public DiscordLogAppenderBuilder setWebhook(URI webhook) { this.webhook = webhook; return asBuilder(); 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 69da7c2162..a9c0900da1 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 @@ -80,7 +80,6 @@ final class DiscordLogForwarder { private final Queue pendingLogs = new PriorityQueue<>(); private final Object pendingLogsLock = new Object(); - DiscordLogForwarder(URI webhook, String sourceCodeBaseUrl) { webhookClient = WebhookClient.withUrl(webhook.toString()); this.sourceCodeBaseUrl = sourceCodeBaseUrl; @@ -169,6 +168,7 @@ private record LogMessage(WebhookEmbed embed, private static LogMessage ofEvent(LogEvent event, String sourceCodeBaseUrl) { String authorName = event.getLoggerName(); + String authorUrl = linkToSource(event.getSource().getClassName(), sourceCodeBaseUrl); String title = event.getLevel().name(); int colorDecimal = Objects.requireNonNull(LEVEL_TO_AMBIENT_COLOR.get(event.getLevel())); String description = @@ -176,8 +176,7 @@ private static LogMessage ofEvent(LogEvent event, String sourceCodeBaseUrl) { Instant timestamp = Instant.ofEpochMilli(event.getInstant().getEpochMillisecond()); WebhookEmbed embed = new WebhookEmbedBuilder() - .setAuthor(new WebhookEmbed.EmbedAuthor(authorName, null, - linkToSource(event.getSource().getClassName(), sourceCodeBaseUrl))) + .setAuthor(new WebhookEmbed.EmbedAuthor(authorName, null, authorUrl)) .setTitle(new WebhookEmbed.EmbedTitle(title, null)) .setDescription(description) .setColor(colorDecimal) From 19851e2eccce4cf7be9835c3243829e122190a03 Mon Sep 17 00:00:00 2001 From: SquidXTV Date: Sun, 16 Jul 2023 13:27:12 +0200 Subject: [PATCH 4/6] Requested changes --- application/config.json.template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/config.json.template b/application/config.json.template index df769b5ce3..367eafaca6 100644 --- a/application/config.json.template +++ b/application/config.json.template @@ -89,5 +89,5 @@ "logInfoChannelWebhook": "", "logErrorChannelWebhook": "", "openaiApiKey": "", - "sourceCodeBaseUrl": "" + "sourceCodeBaseUrl": "" } From b51b75a523d5b7f6409edd68f450cf6fbb0f6cf4 Mon Sep 17 00:00:00 2001 From: SquidXTV Date: Mon, 17 Jul 2023 11:30:04 +0200 Subject: [PATCH 5/6] Requested changes --- application/config.json.template | 2 +- .../org/togetherjava/tjbot/config/Config.java | 6 ++++-- .../logging/discord/DiscordLogForwarder.java | 16 ++++++++++------ 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/application/config.json.template b/application/config.json.template index 367eafaca6..3f9262c32b 100644 --- a/application/config.json.template +++ b/application/config.json.template @@ -89,5 +89,5 @@ "logInfoChannelWebhook": "", "logErrorChannelWebhook": "", "openaiApiKey": "", - "sourceCodeBaseUrl": "" + "sourceCodeBaseUrl": "//blob/master/application/src/main/java/>" } diff --git a/application/src/main/java/org/togetherjava/tjbot/config/Config.java b/application/src/main/java/org/togetherjava/tjbot/config/Config.java index 4afebc7e06..f314b129b3 100644 --- a/application/src/main/java/org/togetherjava/tjbot/config/Config.java +++ b/application/src/main/java/org/togetherjava/tjbot/config/Config.java @@ -321,9 +321,11 @@ public String getOpenaiApiKey() { } /** - * The Base URL of the Source code to link tj-bot originated logs to the GitHub file. + * The base URL of the source code of this bot. E.g. + * {@code getSourceCodeBaseUrl() + "/org/togetherjava/tjbot/config/Config.java"} would point to + * this file. * - * @return the base url of the source code + * @return the base url of the source code of this bot */ public String getSourceCodeBaseUrl() { return sourceCodeBaseUrl; 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 a9c0900da1..7d4bfac474 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 @@ -13,8 +13,6 @@ import org.togetherjava.tjbot.features.utils.MessageUtils; import org.togetherjava.tjbot.logging.LogMarkers; -import javax.annotation.Nullable; - import java.io.PrintWriter; import java.io.StringWriter; import java.net.URI; @@ -168,7 +166,8 @@ private record LogMessage(WebhookEmbed embed, private static LogMessage ofEvent(LogEvent event, String sourceCodeBaseUrl) { String authorName = event.getLoggerName(); - String authorUrl = linkToSource(event.getSource().getClassName(), sourceCodeBaseUrl); + String authorUrl = + linkToSource(event.getSource().getClassName(), sourceCodeBaseUrl).orElse(null); String title = event.getLevel().name(); int colorDecimal = Objects.requireNonNull(LEVEL_TO_AMBIENT_COLOR.get(event.getLevel())); String description = @@ -199,12 +198,17 @@ private static String describeLogEvent(LogEvent event) { return logMessage + "\n" + exceptionWriter.toString().replace("\t", "> "); } - private static @Nullable String linkToSource(String source, String sourceCodeBaseUrl) { + private static Optional linkToSource(String source, String sourceCodeBaseUrl) { if (!source.startsWith(BASE_PACKAGE)) { - return null; + return Optional.empty(); + } + + if (!sourceCodeBaseUrl.endsWith("/")) { + sourceCodeBaseUrl += "/"; } - return sourceCodeBaseUrl + source.replace('.', '/') + ".java"; + String link = sourceCodeBaseUrl + source.replace('.', '/') + ".java"; + return Optional.of(link); } private LogMessage shortened() { From 5e67bc2f5061c9ce8e055cba3ee4f98c6b46b1c7 Mon Sep 17 00:00:00 2001 From: SquidXTV Date: Mon, 17 Jul 2023 14:13:26 +0200 Subject: [PATCH 6/6] Requested changes --- .../logging/discord/DiscordLogForwarder.java | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) 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 7d4bfac474..b86a6eec16 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 @@ -7,6 +7,7 @@ import org.apache.logging.log4j.Level; import org.apache.logging.log4j.core.LogEvent; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -80,7 +81,12 @@ final class DiscordLogForwarder { DiscordLogForwarder(URI webhook, String sourceCodeBaseUrl) { webhookClient = WebhookClient.withUrl(webhook.toString()); - this.sourceCodeBaseUrl = sourceCodeBaseUrl; + + if (!sourceCodeBaseUrl.endsWith("/")) { + this.sourceCodeBaseUrl = sourceCodeBaseUrl + "/"; + } else { + this.sourceCodeBaseUrl = sourceCodeBaseUrl; + } SERVICE.scheduleWithFixedDelay(this::processPendingLogs, 5, 5, TimeUnit.SECONDS); } @@ -166,8 +172,7 @@ private record LogMessage(WebhookEmbed embed, private static LogMessage ofEvent(LogEvent event, String sourceCodeBaseUrl) { String authorName = event.getLoggerName(); - String authorUrl = - linkToSource(event.getSource().getClassName(), sourceCodeBaseUrl).orElse(null); + String authorUrl = linkToSource(event.getSource(), sourceCodeBaseUrl).orElse(null); String title = event.getLevel().name(); int colorDecimal = Objects.requireNonNull(LEVEL_TO_AMBIENT_COLOR.get(event.getLevel())); String description = @@ -198,16 +203,18 @@ private static String describeLogEvent(LogEvent event) { return logMessage + "\n" + exceptionWriter.toString().replace("\t", "> "); } - private static Optional linkToSource(String source, String sourceCodeBaseUrl) { - if (!source.startsWith(BASE_PACKAGE)) { + private static Optional linkToSource(@Nullable StackTraceElement sourceElement, + String sourceCodeBaseUrl) { + if (sourceElement == null) { return Optional.empty(); } - if (!sourceCodeBaseUrl.endsWith("/")) { - sourceCodeBaseUrl += "/"; + String source = sourceElement.getClassName(); + if (!source.startsWith(BASE_PACKAGE)) { + return Optional.empty(); } - String link = sourceCodeBaseUrl + source.replace('.', '/') + ".java"; + String link = "%s%s.java".formatted(sourceCodeBaseUrl, source.replace('.', '/')); return Optional.of(link); }