mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2025-07-01 15:36:45 +00:00
implement opt-out auto reporting with sentry (#1201)
This commit is contained in:
parent
52f87befa2
commit
329e136a66
10
build.gradle
10
build.gradle
@ -33,6 +33,7 @@ plugins {
|
|||||||
id "io.github.goooler.shadow" version "8.1.7"
|
id "io.github.goooler.shadow" version "8.1.7"
|
||||||
id "de.undercouch.download" version "5.0.1"
|
id "de.undercouch.download" version "5.0.1"
|
||||||
id "xyz.jpenilla.run-paper" version "2.3.1"
|
id "xyz.jpenilla.run-paper" version "2.3.1"
|
||||||
|
id "io.sentry.jvm.gradle" version "5.7.0"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -132,6 +133,7 @@ configurations.configureEach {
|
|||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
apply plugin: 'java'
|
apply plugin: 'java'
|
||||||
|
apply plugin: 'io.sentry.jvm.gradle'
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
@ -203,6 +205,14 @@ allprojects {
|
|||||||
archiveClassifier.set('javadoc')
|
archiveClassifier.set('javadoc')
|
||||||
from javadoc.destinationDir
|
from javadoc.destinationDir
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sentry {
|
||||||
|
includeSourceContext = true
|
||||||
|
|
||||||
|
org = "volmit-software"
|
||||||
|
projectName = "iris"
|
||||||
|
authToken = property("sentry.auth.token")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (JavaVersion.current().toString() != "21") {
|
if (JavaVersion.current().toString() != "21") {
|
||||||
|
@ -32,7 +32,6 @@ import com.volmit.iris.core.nms.v1X.NMSBinding1X;
|
|||||||
import com.volmit.iris.core.pregenerator.LazyPregenerator;
|
import com.volmit.iris.core.pregenerator.LazyPregenerator;
|
||||||
import com.volmit.iris.core.service.StudioSVC;
|
import com.volmit.iris.core.service.StudioSVC;
|
||||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||||
import com.volmit.iris.core.tools.IrisWorldCreator;
|
|
||||||
import com.volmit.iris.engine.EnginePanic;
|
import com.volmit.iris.engine.EnginePanic;
|
||||||
import com.volmit.iris.engine.object.IrisCompat;
|
import com.volmit.iris.engine.object.IrisCompat;
|
||||||
import com.volmit.iris.engine.object.IrisContextInjector;
|
import com.volmit.iris.engine.object.IrisContextInjector;
|
||||||
@ -64,7 +63,10 @@ import com.volmit.iris.util.reflect.ShadeFix;
|
|||||||
import com.volmit.iris.util.scheduling.J;
|
import com.volmit.iris.util.scheduling.J;
|
||||||
import com.volmit.iris.util.scheduling.Queue;
|
import com.volmit.iris.util.scheduling.Queue;
|
||||||
import com.volmit.iris.util.scheduling.ShurikenQueue;
|
import com.volmit.iris.util.scheduling.ShurikenQueue;
|
||||||
|
import com.volmit.iris.util.sentry.Attachments;
|
||||||
|
import com.volmit.iris.util.sentry.IrisLogger;
|
||||||
import io.papermc.lib.PaperLib;
|
import io.papermc.lib.PaperLib;
|
||||||
|
import io.sentry.Sentry;
|
||||||
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
|
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
|
||||||
import net.kyori.adventure.text.serializer.ComponentSerializer;
|
import net.kyori.adventure.text.serializer.ComponentSerializer;
|
||||||
import org.bstats.bukkit.Metrics;
|
import org.bstats.bukkit.Metrics;
|
||||||
@ -392,6 +394,7 @@ public class Iris extends VolmitPlugin implements Listener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void reportError(Throwable e) {
|
public static void reportError(Throwable e) {
|
||||||
|
Sentry.captureException(e);
|
||||||
if (IrisSettings.get().getGeneral().isDebug()) {
|
if (IrisSettings.get().getGeneral().isDebug()) {
|
||||||
String n = e.getClass().getCanonicalName() + "-" + e.getStackTrace()[0].getClassName() + "-" + e.getStackTrace()[0].getLineNumber();
|
String n = e.getClass().getCanonicalName() + "-" + e.getStackTrace()[0].getClassName() + "-" + e.getStackTrace()[0].getLineNumber();
|
||||||
|
|
||||||
@ -456,6 +459,7 @@ public class Iris extends VolmitPlugin implements Listener {
|
|||||||
instance = this;
|
instance = this;
|
||||||
services = new KMap<>();
|
services = new KMap<>();
|
||||||
setupAudience();
|
setupAudience();
|
||||||
|
setupSentry();
|
||||||
initialize("com.volmit.iris.core.service").forEach((i) -> services.put((Class<? extends IrisService>) i.getClass(), (IrisService) i));
|
initialize("com.volmit.iris.core.service").forEach((i) -> services.put((Class<? extends IrisService>) i.getClass(), (IrisService) i));
|
||||||
INMS.get();
|
INMS.get();
|
||||||
IO.delete(new File("iris"));
|
IO.delete(new File("iris"));
|
||||||
@ -486,6 +490,12 @@ public class Iris extends VolmitPlugin implements Listener {
|
|||||||
checkForBukkitWorlds();
|
checkForBukkitWorlds();
|
||||||
IrisToolbelt.retainMantleDataForSlice(String.class.getCanonicalName());
|
IrisToolbelt.retainMantleDataForSlice(String.class.getCanonicalName());
|
||||||
IrisToolbelt.retainMantleDataForSlice(BlockData.class.getCanonicalName());
|
IrisToolbelt.retainMantleDataForSlice(BlockData.class.getCanonicalName());
|
||||||
|
|
||||||
|
try {
|
||||||
|
throw new Exception("This is a test exception");
|
||||||
|
} catch (Exception e) {
|
||||||
|
reportError(e);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -527,6 +537,7 @@ public class Iris extends VolmitPlugin implements Listener {
|
|||||||
}
|
}
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
Sentry.captureException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -544,7 +555,7 @@ public class Iris extends VolmitPlugin implements Listener {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
} catch (IrisException e) {
|
} catch (IrisException e) {
|
||||||
e.printStackTrace();
|
Sentry.captureException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -940,4 +951,29 @@ public class Iris extends VolmitPlugin implements Listener {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void setupSentry() {
|
||||||
|
var settings = IrisSettings.get().getSentry();
|
||||||
|
if (settings.disableAutoReporting || Sentry.isEnabled()) return;
|
||||||
|
Sentry.init(options -> {
|
||||||
|
options.setDsn("https://9e190553a1aea18f1cab566cbc894d3f@o4509451052646400.ingest.de.sentry.io/4509451115036752");
|
||||||
|
if (settings.debug) {
|
||||||
|
options.setLogger(new IrisLogger());
|
||||||
|
options.setDebug(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
options.setBeforeSend((event, hint) -> {
|
||||||
|
event.setTag("iris.safeguard", IrisSafeguard.mode());
|
||||||
|
event.setTag("iris.nms", INMS.get().getClass().getCanonicalName());
|
||||||
|
return event;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
Sentry.configureScope(scope -> {
|
||||||
|
scope.addAttachment(Attachments.PLUGINS);
|
||||||
|
scope.setTag("server", Bukkit.getVersion());
|
||||||
|
scope.setTag("server.type", Bukkit.getName());
|
||||||
|
scope.setTag("server.api", Bukkit.getBukkitVersion());
|
||||||
|
});
|
||||||
|
Runtime.getRuntime().addShutdownHook(new Thread(Sentry::close));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,6 +46,7 @@ public class IrisSettings {
|
|||||||
private IrisSettingsPerformance performance = new IrisSettingsPerformance();
|
private IrisSettingsPerformance performance = new IrisSettingsPerformance();
|
||||||
private IrisSettingsUpdater updater = new IrisSettingsUpdater();
|
private IrisSettingsUpdater updater = new IrisSettingsUpdater();
|
||||||
private IrisSettingsPregen pregen = new IrisSettingsPregen();
|
private IrisSettingsPregen pregen = new IrisSettingsPregen();
|
||||||
|
private IrisSettingsSentry sentry = new IrisSettingsSentry();
|
||||||
|
|
||||||
public static int getThreadCount(int c) {
|
public static int getThreadCount(int c) {
|
||||||
return switch (c) {
|
return switch (c) {
|
||||||
@ -222,6 +223,12 @@ public class IrisSettings {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class IrisSettingsSentry {
|
||||||
|
public boolean disableAutoReporting = false;
|
||||||
|
public boolean debug = false;
|
||||||
|
}
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public static class IrisSettingsGUI {
|
public static class IrisSettingsGUI {
|
||||||
public boolean useServerLaunchedGuis = true;
|
public boolean useServerLaunchedGuis = true;
|
||||||
|
@ -47,6 +47,7 @@ public class WorldEditLink {
|
|||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
Iris.error("Could not get selection");
|
Iris.error("Could not get selection");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
Iris.reportError(e);
|
||||||
active.reset();
|
active.reset();
|
||||||
active.aquire(() -> false);
|
active.aquire(() -> false);
|
||||||
}
|
}
|
||||||
|
@ -300,6 +300,7 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
|||||||
|
|
||||||
return r;
|
return r;
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
|
Iris.reportError(e);
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
Iris.error("Failed to create loader! " + registrant.getCanonicalName());
|
Iris.error("Failed to create loader! " + registrant.getCanonicalName());
|
||||||
}
|
}
|
||||||
|
@ -109,6 +109,7 @@ public class ChunkUpdater {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
Iris.reportError(e);
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}, 0, 3, TimeUnit.SECONDS);
|
}, 0, 3, TimeUnit.SECONDS);
|
||||||
@ -314,6 +315,7 @@ public class ChunkUpdater {
|
|||||||
world.save();
|
world.save();
|
||||||
}).get();
|
}).get();
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
|
Iris.reportError(e);
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -71,6 +71,7 @@ class PregenCacheImpl implements PregenCache {
|
|||||||
return new Plate(key, in);
|
return new Plate(key, in);
|
||||||
} catch (IOException e){
|
} catch (IOException e){
|
||||||
Iris.error("Failed to read pregen cache " + file);
|
Iris.error("Failed to read pregen cache " + file);
|
||||||
|
Iris.reportError(e);
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
return new Plate(key);
|
return new Plate(key);
|
||||||
}
|
}
|
||||||
@ -87,6 +88,7 @@ class PregenCacheImpl implements PregenCache {
|
|||||||
IO.write(file, out -> new DataOutputStream(new LZ4BlockOutputStream(out)), plate::write);
|
IO.write(file, out -> new DataOutputStream(new LZ4BlockOutputStream(out)), plate::write);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Iris.error("Failed to write pregen cache " + file);
|
Iris.error("Failed to write pregen cache " + file);
|
||||||
|
Iris.reportError(e);
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -157,7 +157,10 @@ public class AsyncPregenMethod implements PregeneratorMethod {
|
|||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
Iris.warn("Failed to increase worker threads, if you are on paper or a fork of it please increase it manually to " + adjusted);
|
Iris.warn("Failed to increase worker threads, if you are on paper or a fork of it please increase it manually to " + adjusted);
|
||||||
Iris.warn("For more information see https://docs.papermc.io/paper/reference/global-configuration#chunk_system_worker_threads");
|
Iris.warn("For more information see https://docs.papermc.io/paper/reference/global-configuration#chunk_system_worker_threads");
|
||||||
if (e instanceof InvocationTargetException) e.printStackTrace();
|
if (e instanceof InvocationTargetException) {
|
||||||
|
Iris.reportError(e);
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
});
|
});
|
||||||
@ -173,6 +176,7 @@ public class AsyncPregenMethod implements PregeneratorMethod {
|
|||||||
method.invoke(pool, i);
|
method.invoke(pool, i);
|
||||||
return 0;
|
return 0;
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
|
Iris.reportError(e);
|
||||||
Iris.error("Failed to reset worker threads");
|
Iris.error("Failed to reset worker threads");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
@ -201,6 +205,7 @@ public class AsyncPregenMethod implements PregeneratorMethod {
|
|||||||
}).get();
|
}).get();
|
||||||
} catch (InterruptedException ignored) {
|
} catch (InterruptedException ignored) {
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
|
Iris.reportError(e);
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
} finally {
|
} finally {
|
||||||
semaphore.release();
|
semaphore.release();
|
||||||
@ -219,6 +224,7 @@ public class AsyncPregenMethod implements PregeneratorMethod {
|
|||||||
public void generate(int x, int z, PregenListener listener) {
|
public void generate(int x, int z, PregenListener listener) {
|
||||||
PaperLib.getChunkAtAsync(world, x, z, true, urgent)
|
PaperLib.getChunkAtAsync(world, x, z, true, urgent)
|
||||||
.exceptionally(e -> {
|
.exceptionally(e -> {
|
||||||
|
Iris.reportError(e);
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
return null;
|
return null;
|
||||||
})
|
})
|
||||||
|
@ -20,5 +20,15 @@ public class IrisSafeguard {
|
|||||||
Iris.instance.splash();
|
Iris.instance.splash();
|
||||||
UtilsSFG.splash();
|
UtilsSFG.splash();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String mode() {
|
||||||
|
if (unstablemode) {
|
||||||
|
return "unstable";
|
||||||
|
} else if (warningmode) {
|
||||||
|
return "warning";
|
||||||
|
} else {
|
||||||
|
return "stable";
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,7 +36,6 @@ public abstract class Looper extends Thread {
|
|||||||
//noinspection BusyWait
|
//noinspection BusyWait
|
||||||
Thread.sleep(m);
|
Thread.sleep(m);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
Iris.reportError(e);
|
|
||||||
break;
|
break;
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
Iris.reportError(e);
|
Iris.reportError(e);
|
||||||
|
@ -0,0 +1,41 @@
|
|||||||
|
package com.volmit.iris.util.sentry;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.GsonBuilder;
|
||||||
|
import com.volmit.iris.util.collection.KMap;
|
||||||
|
import io.sentry.Attachment;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
|
||||||
|
public class Attachments {
|
||||||
|
private static final Gson GSON = new GsonBuilder().disableHtmlEscaping().create();
|
||||||
|
public static final Attachment PLUGINS = jsonProvider(Attachments::plugins, "plugins.json");
|
||||||
|
|
||||||
|
public static Attachment json(Object object, String name) {
|
||||||
|
return new Attachment(GSON.toJson(object).getBytes(StandardCharsets.UTF_8), name, "application/json", "event.attachment", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Attachment jsonProvider(Callable<Object> object, String name) {
|
||||||
|
return new Attachment(() -> GSON.toJson(object.call()).getBytes(StandardCharsets.UTF_8), name, "application/json", "event.attachment", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static KMap<String, Object> plugins() {
|
||||||
|
KMap<String, String> enabled = new KMap<>();
|
||||||
|
KMap<String, String> disabled = new KMap<>();
|
||||||
|
|
||||||
|
var pm = Bukkit.getPluginManager();
|
||||||
|
for (var plugin : pm.getPlugins()) {
|
||||||
|
if (plugin.isEnabled()) {
|
||||||
|
enabled.put(plugin.getName(), plugin.getDescription().getVersion());
|
||||||
|
} else {
|
||||||
|
disabled.put(plugin.getName(), plugin.getDescription().getVersion());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new KMap<String, Object>()
|
||||||
|
.qput("enabled", enabled)
|
||||||
|
.qput("disabled", disabled);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,47 @@
|
|||||||
|
package com.volmit.iris.util.sentry;
|
||||||
|
|
||||||
|
import com.volmit.iris.Iris;
|
||||||
|
import io.sentry.ILogger;
|
||||||
|
import io.sentry.SentryLevel;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.io.StringWriter;
|
||||||
|
|
||||||
|
public class IrisLogger implements ILogger {
|
||||||
|
@Override
|
||||||
|
public void log(@NotNull SentryLevel level, @NotNull String message, @Nullable Object... args) {
|
||||||
|
Iris.msg(String.format("%s: %s", level, String.format(message, args)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void log(@NotNull SentryLevel level, @NotNull String message, @Nullable Throwable throwable) {
|
||||||
|
if (throwable == null) {
|
||||||
|
log(level, message);
|
||||||
|
} else {
|
||||||
|
Iris.msg(String.format("%s: %s\n%s", level, String.format(message, throwable), captureStackTrace(throwable)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void log(@NotNull SentryLevel level, @Nullable Throwable throwable, @NotNull String message, @Nullable Object... args) {
|
||||||
|
if (throwable == null) {
|
||||||
|
log(level, message, args);
|
||||||
|
} else {
|
||||||
|
Iris.msg(String.format("%s: %s\n%s", level, String.format(message, throwable), captureStackTrace(throwable)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEnabled(@Nullable SentryLevel level) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private @NotNull String captureStackTrace(@NotNull Throwable throwable) {
|
||||||
|
StringWriter stringWriter = new StringWriter();
|
||||||
|
PrintWriter printWriter = new PrintWriter(stringWriter);
|
||||||
|
throwable.printStackTrace(printWriter);
|
||||||
|
return stringWriter.toString();
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user