Remove Sentry

- Remove automatic error reporting and server-identifying attachments.
- Remove Sentry dependencies, release tooling, settings, and test commands.
- Keep failures operator-visible through local stack traces and logging.
This commit is contained in:
Brian Neumann-Fopiano
2026-08-28 16:29:33 -04:00
parent 1a561da2cd
commit 1ca943ab51
44 changed files with 31 additions and 533 deletions
-1
View File
@@ -21,7 +21,6 @@ dependencies {
testImplementation('org.mockito:mockito-core:5.23.0')
testImplementation(libs.paper.api)
testImplementation(libs.bstats)
testImplementation(libs.sentry)
testImplementation(project(':core'))
testImplementation(volmLibCoordinate) {
transitive = false
@@ -423,7 +423,6 @@ public class Iris extends VolmitPlugin implements Listener, ReloadAware {
return;
}
Bindings.capture(e);
boolean debug = false;
if (instance != null) {
try {
@@ -455,6 +454,8 @@ public class Iris extends VolmitPlugin implements Listener, ReloadAware {
Iris.debug("Exception Logged: " + e.getClass().getSimpleName() + ": " + C.RESET + "" + C.LIGHT_PURPLE + e.getMessage());
}
e.printStackTrace(System.err);
}
public static void reportError(String context, Throwable e) {
@@ -473,7 +474,6 @@ public class Iris extends VolmitPlugin implements Listener, ReloadAware {
}
reportError(error);
error.printStackTrace(System.err);
}
public static void dump() {
@@ -606,7 +606,6 @@ public class Iris extends VolmitPlugin implements Listener, ReloadAware {
SimdSupport.install();
services = new KMap<>();
BukkitPlatform.hostHud(new HudActionBar(this), new HudBossBarLane());
Bindings.setupSentry();
// Explicit, ordered service list: the previous reflective jar scan gave hash-ordered
// enable/disable and paid a full-jar class sweep at boot. Infrastructure first,
// engine/world services next, commands last.
@@ -34,7 +34,6 @@ import art.arcane.iris.engine.IrisEngineMantle;
import art.arcane.iris.engine.framework.Engine;
import art.arcane.iris.engine.object.IrisDimension;
import art.arcane.iris.engine.platform.PlatformChunkGenerator;
import art.arcane.iris.util.project.context.IrisContext;
import art.arcane.iris.util.project.matter.IrisMatterContext;
import art.arcane.iris.util.common.director.DirectorExecutor;
import art.arcane.volmlib.util.director.DirectorOrigin;
@@ -79,19 +78,6 @@ public class CommandDeveloper implements DirectorExecutor {
.engineStatus(sender());
}
@Director(description = "Send a test exception to sentry", descriptionKey = "iris.director.commanddeveloper.director.send_test_exception_sentry")
public void Sentry() {
Engine engine = engine();
Exception testException = new Exception("This is a test");
if (engine == null) {
Iris.reportError(testException);
return;
}
try (IrisContext.Scope scope = IrisContext.open(engine, engine.getGenerationSessionId(), null)) {
Iris.reportError(testException);
}
}
@Director(description = "Hash generated block output of a fixed area for determinism/identity testing", descriptionKey = "iris.director.commanddeveloper.director.hash_generated_block_output_fixed_area_determinism_identity_testing", origin = DirectorOrigin.BOTH)
public void genhash(
@Param(description = "The world to hash", descriptionKey = "iris.director.commanddeveloper.param.world_hash", contextual = true, contextualOverride = true)
+1 -3
View File
@@ -162,8 +162,7 @@ dependencies {
libs.lru,
libs.caffeine,
libs.dom4j,
libs.jaxen,
libs.sentry
libs.jaxen
]
shared.each { Object notation ->
add('bundle', notation)
@@ -271,7 +270,6 @@ tasks.named('shadowJar', ShadowJar).configure {
exclude('art/arcane/iris/platform/bukkit/**')
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
relocate('org.objectweb.asm', 'art.arcane.iris.shadow.asm')
relocate('io.sentry', 'art.arcane.iris.shadow.sentry')
// Split-package guard. A co-installed mod that ships any of these at their original coordinates
// puts two copies of the same package on one module layer, which the loaders reject at boot
// (Terra ships paralithic; caffeine and dom4j are common in mod dependency trees). First-party
+1 -3
View File
@@ -161,8 +161,7 @@ dependencies {
libs.lru,
libs.caffeine,
libs.dom4j,
libs.jaxen,
libs.sentry
libs.jaxen
]
shared.each { Object notation ->
add('bundle', notation)
@@ -263,7 +262,6 @@ tasks.named('shadowJar', ShadowJar).configure {
exclude('art/arcane/iris/platform/bukkit/**')
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
relocate('org.objectweb.asm', 'art.arcane.iris.shadow.asm')
relocate('io.sentry', 'art.arcane.iris.shadow.sentry')
// Split-package guard. A co-installed mod that ships any of these at their original coordinates
// puts two copies of the same package on one module layer, which the loaders reject at boot
// (Terra ships paralithic; caffeine and dom4j are common in mod dependency trees). First-party
@@ -113,7 +113,6 @@ public final class ModdedEngineBootstrap {
bindWorldGenerators(server);
services().enableAll();
ModdedProtocolHandler.start(server);
ModdedSentry.start(loader());
}
private static void bindWorldGenerators(MinecraftServer server) {
@@ -194,7 +193,6 @@ public final class ModdedEngineBootstrap {
MultiBurst.burst.close();
MultiBurst.ioBurst.close();
});
failure = runStopStage(failure, "sentry", ModdedSentry::flush);
failure = runStopStage(failure, "startup state", ModdedStartup::reset);
failure = runStopStage(failure, "server state", () -> {
currentServer = null;
@@ -47,7 +47,6 @@ public final class ModdedPlatform implements IrisPlatform {
private static final ConcurrentHashMap<String, ErrorThrottle> ERROR_THROTTLES = new ConcurrentHashMap<>();
private static volatile Consumer<Throwable> ERROR_SINK = null;
private static volatile Consumer<Throwable> CAPTURE_SINK = null;
private final ModdedLoader loader;
private final ModdedRegistries registries;
@@ -67,10 +66,6 @@ public final class ModdedPlatform implements IrisPlatform {
ERROR_SINK = sink;
}
public static void captureSink(Consumer<Throwable> sink) {
CAPTURE_SINK = sink;
}
public MinecraftServer server() {
return ModdedEngineBootstrap.currentServer();
}
@@ -230,9 +225,8 @@ public final class ModdedPlatform implements IrisPlatform {
}
/**
* Throttled per exception signature. A single broken pack rule can fail on every generated chunk, and this
* feeds Sentry, so each distinct signature reports its first few occurrences and then only a periodic
* suppressed-count summary.
* Throttled per exception signature. A single broken pack rule can fail on every generated chunk, so each
* distinct signature reports its first few occurrences and then only a periodic suppressed-count summary.
*/
@Override
public void reportError(Throwable error) {
@@ -261,14 +255,6 @@ public final class ModdedPlatform implements IrisPlatform {
return;
}
ModdedIrisLog.error(message, error);
Consumer<Throwable> capture = CAPTURE_SINK;
if (capture != null) {
try {
capture.accept(error);
} catch (Throwable captureFailure) {
ModdedIrisLog.error("Iris error-reporting sink failed", captureFailure);
}
}
}
static void resetErrorThrottles() {
@@ -1,81 +0,0 @@
/*
* Iris is a World Generator for Minecraft Servers
* Copyright (c) 2026 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package art.arcane.iris.modded;
import art.arcane.iris.BuildConstants;
import art.arcane.iris.core.IrisSettings;
import art.arcane.iris.spi.IrisLogging;
import art.arcane.volmlib.util.json.JSONException;
import com.google.gson.JsonSyntaxException;
import io.sentry.Sentry;
import java.util.concurrent.atomic.AtomicBoolean;
public final class ModdedSentry {
private static final String DSN = "http://4cdbb9ac953306529947f4ca1e8e6b26@sentry.volmit.com:8080/2";
private static final long FLUSH_TIMEOUT_MS = 2000L;
private static final AtomicBoolean STARTED = new AtomicBoolean(false);
private ModdedSentry() {
}
public static void start(ModdedLoader loader) {
IrisSettings.IrisSettingsSentry settings = IrisSettings.get().getSentry();
if (settings.disableAutoReporting || Sentry.isEnabled() || Boolean.getBoolean("iris.suppressReporting")) {
return;
}
if (!STARTED.compareAndSet(false, true)) {
return;
}
IrisLogging.info("Enabling Sentry for anonymous error reporting. You can disable this in the settings.");
Sentry.init(options -> {
options.setDsn(DSN);
if (settings.debug) {
options.setDebug(true);
}
options.setAttachServerName(false);
options.setEnableUncaughtExceptionHandler(false);
options.setRelease(loader.modVersion());
options.setEnvironment(BuildConstants.ENVIRONMENT);
options.setBeforeSend((event, hint) -> suppress(event.getThrowable()) ? null : event);
});
Sentry.configureScope(scope -> {
scope.setTag("server", loader.platformName());
scope.setTag("server.mc", loader.minecraftVersion());
scope.setTag("iris.loader", loader.platformName());
scope.setTag("iris.commit", BuildConstants.COMMIT);
});
ModdedPlatform.captureSink(Sentry::captureException);
}
public static void flush() {
if (Sentry.isEnabled()) {
Sentry.flush(FLUSH_TIMEOUT_MS);
Sentry.close();
}
ModdedPlatform.captureSink(null);
STARTED.set(false);
}
private static boolean suppress(Throwable error) {
return (error instanceof IllegalStateException state && "zip file closed".equals(state.getMessage()))
|| error instanceof JSONException
|| error instanceof JsonSyntaxException;
}
}
@@ -87,7 +87,7 @@ final class ModdedCommandHelp {
Entry.group("datapack", ModdedHelpMessages.GROUP_DATAPACK_WORLD_DATAPACK_INSTALL_AND_STATUS_HELPERS, "datapacks", "dp"),
Entry.group("structure", ModdedHelpMessages.GROUP_STRUCTURE_IRIS_STRUCTURE_INDEX_INFO_AND_PLACEMENT_TOOLS, "struct", "str"),
Entry.command("goldenhash", "[radius] [threads] [capture|verify]", ModdedHelpMessages.COMMAND_GOLDENHASH_GENERATE_DETERMINISTIC_BLOCK_HASHES_FOR_PARITY_TESTING, "gold"),
Entry.group("developer", ModdedHelpMessages.GROUP_DEVELOPER_DEVELOPER_DIAGNOSTICS_SENTRY_TEST_NETWORK_INTERFACES_REGION_FILE_SCAN, "dev")
Entry.group("developer", ModdedHelpMessages.GROUP_DEVELOPER_DEVELOPER_DIAGNOSTICS_NETWORK_INTERFACES_REGION_FILE_SCAN, "dev")
));
SECTIONS.put("what", List.of(
Entry.command("here", "", ModdedHelpMessages.COMMAND_WHAT_HERE_INSPECT_CURRENT_IRIS_CONTEXT),
@@ -197,7 +197,6 @@ final class ModdedCommandHelp {
SECTIONS.put("struct", SECTIONS.get("structure"));
SECTIONS.put("str", SECTIONS.get("structure"));
SECTIONS.put("developer", List.of(
Entry.command("sentry", "", ModdedHelpMessages.COMMAND_SENTRY_SEND_A_TEST_EXCEPTION_TO_THE_IRIS_ERROR_REPORTER),
Entry.command("network", "", ModdedHelpMessages.COMMAND_NETWORK_LIST_NETWORK_INTERFACES_AND_THEIR_ADDRESSES, "ip")
));
SECTIONS.put("dev", SECTIONS.get("developer"));
@@ -19,7 +19,6 @@
package art.arcane.iris.modded.command;
import art.arcane.iris.modded.ModdedIrisLog;
import art.arcane.iris.spi.IrisPlatforms;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.context.CommandContext;
import net.minecraft.commands.CommandSourceStack;
@@ -44,20 +43,12 @@ final class ModdedDeveloperCommands {
static LiteralArgumentBuilder<CommandSourceStack> tree(String name) {
return Commands.literal(name).requires(GATE)
.executes((CommandContext<CommandSourceStack> context) -> ModdedCommandHelp.send(context.getSource(), "developer"))
.then(Commands.literal("sentry")
.executes((CommandContext<CommandSourceStack> context) -> sentry(context.getSource())))
.then(Commands.literal("network")
.executes((CommandContext<CommandSourceStack> context) -> network(context.getSource())))
.then(Commands.literal("ip")
.executes((CommandContext<CommandSourceStack> context) -> network(context.getSource())));
}
private static int sentry(CommandSourceStack source) {
IrisPlatforms.get().reportError(new Exception("This is an Iris Sentry test exception"));
ModdedCommandFeedback.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_DEVELOPER_COMMANDS_DISPATCHED_TEST_EXCEPTION_IRIS_ERROR_REPORTER_SENTRY_IF_ENABLED));
return 1;
}
private static int network(CommandSourceStack source) {
try {
Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
+1 -3
View File
@@ -131,8 +131,7 @@ dependencies {
libs.lru,
libs.caffeine,
libs.dom4j,
libs.jaxen,
libs.sentry
libs.jaxen
]
shared.each { Object notation ->
add('bundle', notation)
@@ -239,7 +238,6 @@ tasks.named('shadowJar', ShadowJar).configure {
exclude('art/arcane/iris/platform/bukkit/**')
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
relocate('org.objectweb.asm', 'art.arcane.iris.shadow.asm')
relocate('io.sentry', 'art.arcane.iris.shadow.sentry')
// Split-package guard. A co-installed mod that ships any of these at their original coordinates
// puts two copies of the same package on one module layer, which the loaders reject at boot
// (Terra ships paralithic; caffeine and dom4j are common in mod dependency trees). First-party