-
-
Notifications
You must be signed in to change notification settings - Fork 26
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
492 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,243 @@ | ||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 | ||
From: adabugra <57899270+adabugra@users.noreply.github.com> | ||
Date: Mon, 6 Jan 2025 19:24:06 +0300 | ||
Subject: [PATCH] Pufferfish: Sentry | ||
|
||
|
||
diff --git a/build.gradle.kts b/build.gradle.kts | ||
index 1aa76451f9129b578d6887b1239966eb67f5ee1b..2ddad10cf12dd07fd227ddda13336fdd61cd0197 100644 | ||
--- a/build.gradle.kts | ||
+++ b/build.gradle.kts | ||
@@ -66,6 +66,7 @@ dependencies { | ||
apiAndDocs("net.kyori:adventure-text-logger-slf4j") | ||
api("org.apache.logging.log4j:log4j-api:$log4jVersion") | ||
api("org.slf4j:slf4j-api:$slf4jVersion") | ||
+ api("io.sentry:sentry:8.0.0-rc.2") // Pufferfish | ||
|
||
implementation("org.ow2.asm:asm:9.7.1") | ||
implementation("org.ow2.asm:asm-commons:9.7.1") | ||
diff --git a/src/main/java/gg/pufferfish/pufferfish/sentry/SentryContext.java b/src/main/java/gg/pufferfish/pufferfish/sentry/SentryContext.java | ||
new file mode 100644 | ||
index 0000000000000000000000000000000000000000..c7772aac00f6db664f7a5673bc2585fa025e6aad | ||
--- /dev/null | ||
+++ b/src/main/java/gg/pufferfish/pufferfish/sentry/SentryContext.java | ||
@@ -0,0 +1,165 @@ | ||
+package gg.pufferfish.pufferfish.sentry; | ||
+ | ||
+import com.google.gson.Gson; | ||
+ | ||
+import java.lang.reflect.Field; | ||
+import java.lang.reflect.Modifier; | ||
+import java.util.Map; | ||
+import java.util.TreeMap; | ||
+ | ||
+import org.apache.logging.log4j.ThreadContext; | ||
+import org.bukkit.command.Command; | ||
+import org.bukkit.command.CommandSender; | ||
+import org.bukkit.entity.Player; | ||
+import org.bukkit.event.Event; | ||
+import org.bukkit.event.player.PlayerEvent; | ||
+import org.bukkit.plugin.Plugin; | ||
+import org.bukkit.plugin.RegisteredListener; | ||
+import org.jetbrains.annotations.Nullable; | ||
+ | ||
+public class SentryContext { | ||
+ | ||
+ private static final Gson GSON = new Gson(); | ||
+ | ||
+ public static void setPluginContext(@Nullable Plugin plugin) { | ||
+ if (plugin != null) { | ||
+ ThreadContext.put("pufferfishsentry_pluginname", plugin.getName()); | ||
+ ThreadContext.put("pufferfishsentry_pluginversion", plugin.getPluginMeta().getVersion()); | ||
+ } | ||
+ } | ||
+ | ||
+ public static void removePluginContext() { | ||
+ ThreadContext.remove("pufferfishsentry_pluginname"); | ||
+ ThreadContext.remove("pufferfishsentry_pluginversion"); | ||
+ } | ||
+ | ||
+ public static void setSenderContext(@Nullable CommandSender sender) { | ||
+ if (sender != null) { | ||
+ ThreadContext.put("pufferfishsentry_playername", sender.getName()); | ||
+ if (sender instanceof Player player) { | ||
+ ThreadContext.put("pufferfishsentry_playerid", player.getUniqueId().toString()); | ||
+ } | ||
+ } | ||
+ } | ||
+ | ||
+ public static void removeSenderContext() { | ||
+ ThreadContext.remove("pufferfishsentry_playername"); | ||
+ ThreadContext.remove("pufferfishsentry_playerid"); | ||
+ } | ||
+ | ||
+ public static void setEventContext(Event event, RegisteredListener registration) { | ||
+ setPluginContext(registration.getPlugin()); | ||
+ | ||
+ try { | ||
+ // Find the player that was involved with this event | ||
+ Player player = null; | ||
+ if (event instanceof PlayerEvent) { | ||
+ player = ((PlayerEvent) event).getPlayer(); | ||
+ } else { | ||
+ Class<? extends Event> eventClass = event.getClass(); | ||
+ | ||
+ Field playerField = null; | ||
+ | ||
+ for (Field field : eventClass.getDeclaredFields()) { | ||
+ if (field.getType().equals(Player.class)) { | ||
+ playerField = field; | ||
+ break; | ||
+ } | ||
+ } | ||
+ | ||
+ if (playerField != null) { | ||
+ playerField.setAccessible(true); | ||
+ player = (Player) playerField.get(event); | ||
+ } | ||
+ } | ||
+ | ||
+ if (player != null) { | ||
+ setSenderContext(player); | ||
+ } | ||
+ } catch (Exception ignored) { | ||
+ } // We can't really safely log exceptions. | ||
+ | ||
+ ThreadContext.put("pufferfishsentry_eventdata", GSON.toJson(serializeFields(event))); | ||
+ } | ||
+ | ||
+ public static void removeEventContext() { | ||
+ removePluginContext(); | ||
+ removeSenderContext(); | ||
+ ThreadContext.remove("pufferfishsentry_eventdata"); | ||
+ } | ||
+ | ||
+ private static Map<String, String> serializeFields(Object object) { | ||
+ Map<String, String> fields = new TreeMap<>(); | ||
+ fields.put("_class", object.getClass().getName()); | ||
+ for (Field declaredField : object.getClass().getDeclaredFields()) { | ||
+ try { | ||
+ if (Modifier.isStatic(declaredField.getModifiers())) { | ||
+ continue; | ||
+ } | ||
+ | ||
+ String fieldName = declaredField.getName(); | ||
+ if (fieldName.equals("handlers")) { | ||
+ continue; | ||
+ } | ||
+ declaredField.setAccessible(true); | ||
+ Object value = declaredField.get(object); | ||
+ if (value != null) { | ||
+ fields.put(fieldName, value.toString()); | ||
+ } else { | ||
+ fields.put(fieldName, "<null>"); | ||
+ } | ||
+ } catch (Exception ignored) { | ||
+ } // We can't really safely log exceptions. | ||
+ } | ||
+ return fields; | ||
+ } | ||
+ | ||
+ public static class State { | ||
+ | ||
+ private Plugin plugin; | ||
+ private Command command; | ||
+ private String commandLine; | ||
+ private Event event; | ||
+ private RegisteredListener registeredListener; | ||
+ | ||
+ public Plugin getPlugin() { | ||
+ return plugin; | ||
+ } | ||
+ | ||
+ public void setPlugin(Plugin plugin) { | ||
+ this.plugin = plugin; | ||
+ } | ||
+ | ||
+ public Command getCommand() { | ||
+ return command; | ||
+ } | ||
+ | ||
+ public void setCommand(Command command) { | ||
+ this.command = command; | ||
+ } | ||
+ | ||
+ public String getCommandLine() { | ||
+ return commandLine; | ||
+ } | ||
+ | ||
+ public void setCommandLine(String commandLine) { | ||
+ this.commandLine = commandLine; | ||
+ } | ||
+ | ||
+ public Event getEvent() { | ||
+ return event; | ||
+ } | ||
+ | ||
+ public void setEvent(Event event) { | ||
+ this.event = event; | ||
+ } | ||
+ | ||
+ public RegisteredListener getRegisteredListener() { | ||
+ return registeredListener; | ||
+ } | ||
+ | ||
+ public void setRegisteredListener(RegisteredListener registeredListener) { | ||
+ this.registeredListener = registeredListener; | ||
+ } | ||
+ } | ||
+} | ||
diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java | ||
index ab36e3aaff57e2f27b5aed06b4bdfe277f86a35e..96da9f1082ab134d197b3a6069f2fcdf38585efe 100644 | ||
--- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java | ||
+++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java | ||
@@ -597,7 +597,9 @@ public final class SimplePluginManager implements PluginManager { | ||
|
||
// Paper start | ||
private void handlePluginException(String msg, Throwable ex, Plugin plugin) { | ||
+ gg.pufferfish.pufferfish.sentry.SentryContext.setPluginContext(plugin); // Pufferfish | ||
server.getLogger().log(Level.SEVERE, msg, ex); | ||
+ gg.pufferfish.pufferfish.sentry.SentryContext.removePluginContext(); // Pufferfish | ||
callEvent(new com.destroystokyo.paper.event.server.ServerExceptionEvent(new com.destroystokyo.paper.exception.ServerPluginEnableDisableException(msg, ex, plugin))); | ||
} | ||
// Paper end | ||
@@ -667,9 +669,11 @@ public final class SimplePluginManager implements PluginManager { | ||
)); | ||
} | ||
} catch (Throwable ex) { | ||
+ gg.pufferfish.pufferfish.sentry.SentryContext.setEventContext(event, registration); // Pufferfish | ||
// Paper start - error reporting | ||
String msg = "Could not pass event " + event.getEventName() + " to " + registration.getPlugin().getDescription().getFullName(); | ||
server.getLogger().log(Level.SEVERE, msg, ex); | ||
+ gg.pufferfish.pufferfish.sentry.SentryContext.removeEventContext(); // Pufferfish | ||
if (!(event instanceof com.destroystokyo.paper.event.server.ServerExceptionEvent)) { // We don't want to cause an endless event loop | ||
callEvent(new com.destroystokyo.paper.event.server.ServerExceptionEvent(new com.destroystokyo.paper.exception.ServerEventException(msg, ex, registration.getPlugin(), registration.getListener(), event))); | ||
} | ||
diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java | ||
index b412aaf08901d169ac9fc89b36f9d6ccb95c53d3..45a9ca8969f635d20cc44c062fda85bbccd8f8ff 100644 | ||
--- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java | ||
+++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java | ||
@@ -336,7 +336,13 @@ public final class JavaPluginLoader implements PluginLoader { | ||
try { | ||
jPlugin.setEnabled(true); | ||
} catch (Throwable ex) { | ||
+ gg.pufferfish.pufferfish.sentry.SentryContext.setPluginContext(plugin); // Pufferfish | ||
server.getLogger().log(Level.SEVERE, "Error occurred while enabling " + plugin.getDescription().getFullName() + " (Is it up to date?)", ex); | ||
+ gg.pufferfish.pufferfish.sentry.SentryContext.removePluginContext(); // Pufferfish | ||
+ // Paper start - Disable plugins that fail to load | ||
+ this.server.getPluginManager().disablePlugin(jPlugin); | ||
+ return; | ||
+ // Paper end | ||
} | ||
|
||
// Perhaps abort here, rather than continue going, but as it stands, | ||
@@ -361,7 +367,9 @@ public final class JavaPluginLoader implements PluginLoader { | ||
try { | ||
jPlugin.setEnabled(false); | ||
} catch (Throwable ex) { | ||
+ gg.pufferfish.pufferfish.sentry.SentryContext.setPluginContext(plugin); // Pufferfish | ||
server.getLogger().log(Level.SEVERE, "Error occurred while disabling " + plugin.getDescription().getFullName() + " (Is it up to date?)", ex); | ||
+ gg.pufferfish.pufferfish.sentry.SentryContext.removePluginContext(); // Pufferfish | ||
} | ||
|
||
if (cloader instanceof PluginClassLoader) { |
Oops, something went wrong.