Write DiscordSRV log messages to a file for debugging

This commit is contained in:
Vankka 2022-01-24 18:55:36 +02:00
parent 9f7a453132
commit 67e25a765a
No known key found for this signature in database
GPG Key ID: 6E50CB7A29B96AD0
33 changed files with 321 additions and 140 deletions

View File

@ -47,17 +47,12 @@ public class DiscordSRVBukkitBootstrap extends BukkitBootstrap {
@Override @Override
public void onEnable() { public void onEnable() {
// Wait until dependencies ready, then initialize DiscordSRV dependencies.loadAndEnable(() -> this.discordSRV = new BukkitDiscordSRV(this, logger));
dependencies.join(); getPlugin().getServer().getScheduler().runTaskLater(getPlugin(), () -> discordSRV.invokeServerStarted(), 1L);
this.discordSRV = new BukkitDiscordSRV(this, logger);
dependencies.runWhenComplete(() -> discordSRV.invokeEnable());
getPlugin().getServer().getScheduler().runTaskLater(getPlugin(),
() -> dependencies.runWhenComplete(() -> discordSRV.invokeServerStarted()), 1L);
} }
@Override @Override
public void onDisable() { public void onDisable() {
dependencies.runWhenComplete(() -> discordSRV.invokeDisable()); dependencies.disable(discordSRV);
} }
} }

View File

@ -20,6 +20,7 @@ package com.discordsrv.bukkit.console;
import com.discordsrv.bukkit.BukkitDiscordSRV; import com.discordsrv.bukkit.BukkitDiscordSRV;
import com.discordsrv.common.console.Console; import com.discordsrv.common.console.Console;
import com.discordsrv.common.logging.NamedLogger;
import com.discordsrv.common.logging.backend.LoggingBackend; import com.discordsrv.common.logging.backend.LoggingBackend;
import com.discordsrv.common.logging.backend.impl.JavaLoggerImpl; import com.discordsrv.common.logging.backend.impl.JavaLoggerImpl;
import com.discordsrv.common.logging.backend.impl.Log4JLoggerImpl; import com.discordsrv.common.logging.backend.impl.Log4JLoggerImpl;
@ -43,7 +44,7 @@ public class BukkitConsole implements Console {
} catch (ClassNotFoundException ignored) { } catch (ClassNotFoundException ignored) {
// Log4j with Filter has been in the vanilla server since Minecraft 1.7, // Log4j with Filter has been in the vanilla server since Minecraft 1.7,
// this is mostly for Bukkit servers that don't use the vanilla server software // this is mostly for Bukkit servers that don't use the vanilla server software
discordSRV.logger().debug("Not using Log4j for advanced console features"); new NamedLogger(discordSRV, "CONSOLE").debug("Not using Log4j for advanced console features");
logging = JavaLoggerImpl.getRoot(); logging = JavaLoggerImpl.getRoot();
} }
this.loggingBackend = logging; this.loggingBackend = logging;

View File

@ -25,8 +25,8 @@ import com.discordsrv.common.config.main.MainConfig;
import com.discordsrv.common.config.manager.ConnectionConfigManager; import com.discordsrv.common.config.manager.ConnectionConfigManager;
import com.discordsrv.common.config.manager.MainConfigManager; import com.discordsrv.common.config.manager.MainConfigManager;
import com.discordsrv.common.logging.Logger; import com.discordsrv.common.logging.Logger;
import com.discordsrv.proxy.ProxyDiscordSRV;
import com.discordsrv.common.scheduler.StandardScheduler; import com.discordsrv.common.scheduler.StandardScheduler;
import com.discordsrv.proxy.ProxyDiscordSRV;
import net.kyori.adventure.platform.bungeecord.BungeeAudiences; import net.kyori.adventure.platform.bungeecord.BungeeAudiences;
import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.plugin.Plugin; import net.md_5.bungee.api.plugin.Plugin;

View File

@ -47,15 +47,11 @@ public class DiscordSRVBungeeBootstrap extends BungeeBootstrap {
@Override @Override
public void onEnable() { public void onEnable() {
// Wait until dependencies ready, then initialize DiscordSRV dependencies.loadAndEnable(() -> this.discordSRV = new BungeeDiscordSRV(this, logger));
dependencies.join();
this.discordSRV = new BungeeDiscordSRV(this, logger);
dependencies.runWhenComplete(discordSRV::invokeEnable);
} }
@Override @Override
public void onDisable() { public void onDisable() {
dependencies.runWhenComplete(discordSRV::invokeDisable); dependencies.disable(discordSRV);
} }
} }

View File

@ -27,6 +27,7 @@ import com.discordsrv.api.event.events.message.receive.game.ServerSwitchMessageR
import com.discordsrv.common.DiscordSRV; import com.discordsrv.common.DiscordSRV;
import com.discordsrv.common.config.main.channels.base.BaseChannelConfig; import com.discordsrv.common.config.main.channels.base.BaseChannelConfig;
import com.discordsrv.common.function.OrDefault; import com.discordsrv.common.function.OrDefault;
import com.discordsrv.common.logging.NamedLogger;
import com.discordsrv.common.messageforwarding.game.AbstractGameMessageModule; import com.discordsrv.common.messageforwarding.game.AbstractGameMessageModule;
import com.discordsrv.proxy.config.channels.ServerSwitchMessageConfig; import com.discordsrv.proxy.config.channels.ServerSwitchMessageConfig;
import com.discordsrv.proxy.config.channels.base.ProxyBaseChannelConfig; import com.discordsrv.proxy.config.channels.base.ProxyBaseChannelConfig;
@ -34,7 +35,7 @@ import com.discordsrv.proxy.config.channels.base.ProxyBaseChannelConfig;
public class ServerSwitchMessageModule extends AbstractGameMessageModule<ServerSwitchMessageConfig> { public class ServerSwitchMessageModule extends AbstractGameMessageModule<ServerSwitchMessageConfig> {
public ServerSwitchMessageModule(DiscordSRV discordSRV) { public ServerSwitchMessageModule(DiscordSRV discordSRV) {
super(discordSRV); super(discordSRV, new NamedLogger(discordSRV, "SERVER_SWITCH"));
} }
@Subscribe(priority = EventPriority.LAST) @Subscribe(priority = EventPriority.LAST)

View File

@ -26,15 +26,16 @@ import com.discordsrv.api.event.events.message.forward.game.DeathMessageForwarde
import com.discordsrv.api.event.events.message.receive.game.DeathMessageReceiveEvent; import com.discordsrv.api.event.events.message.receive.game.DeathMessageReceiveEvent;
import com.discordsrv.common.DiscordSRV; import com.discordsrv.common.DiscordSRV;
import com.discordsrv.common.config.main.channels.base.BaseChannelConfig; import com.discordsrv.common.config.main.channels.base.BaseChannelConfig;
import com.discordsrv.common.server.config.channels.DeathMessageConfig;
import com.discordsrv.common.function.OrDefault; import com.discordsrv.common.function.OrDefault;
import com.discordsrv.common.logging.NamedLogger;
import com.discordsrv.common.messageforwarding.game.AbstractGameMessageModule; import com.discordsrv.common.messageforwarding.game.AbstractGameMessageModule;
import com.discordsrv.common.server.config.channels.DeathMessageConfig;
import com.discordsrv.common.server.config.channels.base.ServerBaseChannelConfig; import com.discordsrv.common.server.config.channels.base.ServerBaseChannelConfig;
public class DeathMessageModule extends AbstractGameMessageModule<DeathMessageConfig> { public class DeathMessageModule extends AbstractGameMessageModule<DeathMessageConfig> {
public DeathMessageModule(DiscordSRV discordSRV) { public DeathMessageModule(DiscordSRV discordSRV) {
super(discordSRV); super(discordSRV, new NamedLogger(discordSRV, "DEATH"));
} }
@Subscribe(priority = EventPriority.LAST) @Subscribe(priority = EventPriority.LAST)

View File

@ -23,6 +23,7 @@ import com.discordsrv.api.event.bus.EventBus;
import com.discordsrv.api.event.events.lifecycle.DiscordSRVReloadEvent; import com.discordsrv.api.event.events.lifecycle.DiscordSRVReloadEvent;
import com.discordsrv.api.event.events.lifecycle.DiscordSRVShuttingDownEvent; import com.discordsrv.api.event.events.lifecycle.DiscordSRVShuttingDownEvent;
import com.discordsrv.api.linking.LinkingBackend; import com.discordsrv.api.linking.LinkingBackend;
import com.discordsrv.api.module.type.Module;
import com.discordsrv.common.api.util.ApiInstanceUtil; import com.discordsrv.common.api.util.ApiInstanceUtil;
import com.discordsrv.common.channel.ChannelConfigHelper; import com.discordsrv.common.channel.ChannelConfigHelper;
import com.discordsrv.common.channel.ChannelUpdaterModule; import com.discordsrv.common.channel.ChannelUpdaterModule;
@ -42,7 +43,6 @@ import com.discordsrv.common.function.CheckedFunction;
import com.discordsrv.common.function.CheckedRunnable; import com.discordsrv.common.function.CheckedRunnable;
import com.discordsrv.common.groupsync.GroupSyncModule; import com.discordsrv.common.groupsync.GroupSyncModule;
import com.discordsrv.common.integration.LuckPermsIntegration; import com.discordsrv.common.integration.LuckPermsIntegration;
import com.discordsrv.common.logging.Logger;
import com.discordsrv.common.logging.adapter.DependencyLoggerAdapter; import com.discordsrv.common.logging.adapter.DependencyLoggerAdapter;
import com.discordsrv.common.logging.impl.DependencyLoggingHandler; import com.discordsrv.common.logging.impl.DependencyLoggingHandler;
import com.discordsrv.common.logging.impl.DiscordSRVLogger; import com.discordsrv.common.logging.impl.DiscordSRVLogger;
@ -52,7 +52,6 @@ import com.discordsrv.common.messageforwarding.game.JoinMessageModule;
import com.discordsrv.common.messageforwarding.game.LeaveMessageModule; import com.discordsrv.common.messageforwarding.game.LeaveMessageModule;
import com.discordsrv.common.module.ModuleManager; import com.discordsrv.common.module.ModuleManager;
import com.discordsrv.common.module.type.AbstractModule; import com.discordsrv.common.module.type.AbstractModule;
import com.discordsrv.api.module.type.Module;
import com.discordsrv.common.placeholder.ComponentResultStringifier; import com.discordsrv.common.placeholder.ComponentResultStringifier;
import com.discordsrv.common.placeholder.PlaceholderServiceImpl; import com.discordsrv.common.placeholder.PlaceholderServiceImpl;
import com.discordsrv.common.placeholder.context.GlobalTextHandlingContext; import com.discordsrv.common.placeholder.context.GlobalTextHandlingContext;
@ -85,8 +84,8 @@ public abstract class AbstractDiscordSRV<C extends MainConfig, CC extends Connec
private DiscordConnectionDetails discordConnectionDetails; private DiscordConnectionDetails discordConnectionDetails;
// DiscordSRV // DiscordSRV
private final DiscordSRVLogger logger; private DiscordSRVLogger logger;
private final ModuleManager moduleManager; private ModuleManager moduleManager;
private ChannelConfigHelper channelConfig; private ChannelConfigHelper channelConfig;
private DiscordConnectionManager discordConnectionManager; private DiscordConnectionManager discordConnectionManager;
@ -95,11 +94,14 @@ public abstract class AbstractDiscordSRV<C extends MainConfig, CC extends Connec
public AbstractDiscordSRV() { public AbstractDiscordSRV() {
ApiInstanceUtil.setInstance(this); ApiInstanceUtil.setInstance(this);
this.logger = new DiscordSRVLogger(this);
this.moduleManager = new ModuleManager(this);
} }
/**
* Method that should be called at the end of implementors constructors.
*/
protected final void load() { protected final void load() {
this.logger = new DiscordSRVLogger(this);
this.moduleManager = new ModuleManager(this);
this.eventBus = new EventBusImpl(this); this.eventBus = new EventBusImpl(this);
this.placeholderService = new PlaceholderServiceImpl(this); this.placeholderService = new PlaceholderServiceImpl(this);
this.componentFactory = new ComponentFactory(this); this.componentFactory = new ComponentFactory(this);
@ -153,7 +155,7 @@ public abstract class AbstractDiscordSRV<C extends MainConfig, CC extends Connec
// DiscordSRV // DiscordSRV
@Override @Override
public Logger logger() { public DiscordSRVLogger logger() {
return logger; return logger;
} }
@ -184,6 +186,8 @@ public abstract class AbstractDiscordSRV<C extends MainConfig, CC extends Connec
return configManager().config(); return configManager().config();
} }
// Module
@Override @Override
public <T extends Module> T getModule(Class<T> moduleType) { public <T extends Module> T getModule(Class<T> moduleType) {
return moduleManager.getModule(moduleType); return moduleManager.getModule(moduleType);
@ -212,6 +216,8 @@ public abstract class AbstractDiscordSRV<C extends MainConfig, CC extends Connec
return Locale.getDefault(); return Locale.getDefault();
} }
// Status
@Override @Override
public void setStatus(Status status) { public void setStatus(Status status) {
synchronized (this.status) { synchronized (this.status) {
@ -239,6 +245,8 @@ public abstract class AbstractDiscordSRV<C extends MainConfig, CC extends Connec
} }
} }
// Lifecycle
protected CompletableFuture<Void> invokeLifecycle(CheckedRunnable runnable, String message, boolean enable) { protected CompletableFuture<Void> invokeLifecycle(CheckedRunnable runnable, String message, boolean enable) {
return invoke(() -> { return invoke(() -> {
try { try {

View File

@ -28,6 +28,7 @@ import com.discordsrv.common.config.manager.MainConfigManager;
import com.discordsrv.common.console.Console; import com.discordsrv.common.console.Console;
import com.discordsrv.common.discord.api.DiscordAPIImpl; import com.discordsrv.common.discord.api.DiscordAPIImpl;
import com.discordsrv.common.discord.connection.DiscordConnectionManager; import com.discordsrv.common.discord.connection.DiscordConnectionManager;
import com.discordsrv.common.logging.impl.DiscordSRVLogger;
import com.discordsrv.common.module.type.AbstractModule; import com.discordsrv.common.module.type.AbstractModule;
import com.discordsrv.api.module.type.Module; import com.discordsrv.api.module.type.Module;
import com.discordsrv.common.placeholder.PlaceholderServiceImpl; import com.discordsrv.common.placeholder.PlaceholderServiceImpl;
@ -71,7 +72,7 @@ public interface DiscordSRV extends DiscordSRVApi {
DiscordAPIImpl discordAPI(); DiscordAPIImpl discordAPI();
// Logger // Logger
Logger logger(); DiscordSRVLogger logger();
// Config // Config
ConnectionConfigManager<? extends ConnectionConfig> connectionConfigManager(); ConnectionConfigManager<? extends ConnectionConfig> connectionConfigManager();

View File

@ -20,6 +20,7 @@ package com.discordsrv.common.channel;
import com.discordsrv.common.DiscordSRV; import com.discordsrv.common.DiscordSRV;
import com.discordsrv.common.config.main.ChannelUpdaterConfig; import com.discordsrv.common.config.main.ChannelUpdaterConfig;
import com.discordsrv.common.logging.NamedLogger;
import com.discordsrv.common.module.type.AbstractModule; import com.discordsrv.common.module.type.AbstractModule;
import net.dv8tion.jda.api.JDA; import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.entities.GuildChannel; import net.dv8tion.jda.api.entities.GuildChannel;
@ -39,7 +40,7 @@ public class ChannelUpdaterModule extends AbstractModule<DiscordSRV> {
private boolean firstReload = true; private boolean firstReload = true;
public ChannelUpdaterModule(DiscordSRV discordSRV) { public ChannelUpdaterModule(DiscordSRV discordSRV) {
super(discordSRV); super(discordSRV, new NamedLogger(discordSRV, "CHANNEL_UPDATER"));
} }
@Override @Override
@ -100,7 +101,7 @@ public class ChannelUpdaterModule extends AbstractModule<DiscordSRV> {
} }
if (!anythingChanged) { if (!anythingChanged) {
discordSRV.logger().debug("Skipping updating channel " + channel + ": nothing changed"); logger().debug("Skipping updating channel " + channel + ": nothing changed");
continue; continue;
} }

View File

@ -35,11 +35,11 @@ public class GlobalChannelLookupModule extends AbstractModule<DiscordSRV> {
@Subscribe(priority = EventPriority.LATE) @Subscribe(priority = EventPriority.LATE)
public void onGameChannelLookup(GameChannelLookupEvent event) { public void onGameChannelLookup(GameChannelLookupEvent event) {
if (event.getChannelName().equalsIgnoreCase("global")) {
if (checkProcessor(event)) { if (checkProcessor(event)) {
return; return;
} }
if (event.getChannelName().equalsIgnoreCase("global")) {
event.process(defaultGlobalChannel); event.process(defaultGlobalChannel);
} }
} }

View File

@ -18,6 +18,7 @@
package com.discordsrv.common.dependency; package com.discordsrv.common.dependency;
import com.discordsrv.common.DiscordSRV;
import com.discordsrv.common.logging.Logger; import com.discordsrv.common.logging.Logger;
import com.discordsrv.common.scheduler.threadfactory.CountingForkJoinWorkerThreadFactory; import com.discordsrv.common.scheduler.threadfactory.CountingForkJoinWorkerThreadFactory;
import dev.vankka.dependencydownload.classpath.ClasspathAppender; import dev.vankka.dependencydownload.classpath.ClasspathAppender;
@ -28,15 +29,14 @@ import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.*;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.function.Supplier;
import java.util.concurrent.ForkJoinPool;
public class InitialDependencyLoader { public class InitialDependencyLoader {
private final Logger logger;
private final ForkJoinPool taskPool; private final ForkJoinPool taskPool;
private final CompletableFuture<?> completableFuture; private final CompletableFuture<?> completableFuture;
private final List<Runnable> tasks = new CopyOnWriteArrayList<>();
public InitialDependencyLoader( public InitialDependencyLoader(
Logger logger, Logger logger,
@ -44,6 +44,7 @@ public class InitialDependencyLoader {
String[] dependencyResources, String[] dependencyResources,
ClasspathAppender classpathAppender ClasspathAppender classpathAppender
) throws IOException { ) throws IOException {
this.logger = logger;
this.taskPool = new ForkJoinPool( this.taskPool = new ForkJoinPool(
Runtime.getRuntime().availableProcessors(), Runtime.getRuntime().availableProcessors(),
new CountingForkJoinWorkerThreadFactory("DiscordSRV Initialization #%s"), new CountingForkJoinWorkerThreadFactory("DiscordSRV Initialization #%s"),
@ -63,40 +64,51 @@ public class InitialDependencyLoader {
); );
this.completableFuture = dependencyLoader.process(classpathAppender); this.completableFuture = dependencyLoader.process(classpathAppender);
completableFuture.whenComplete((v, t) -> { completableFuture.whenComplete((v, t) -> taskPool.shutdown());
if (t != null) {
logger.error("Error loading dependencies", t);
return;
} }
for (Runnable task : tasks) { public void loadAndEnable(Supplier<DiscordSRV> discordSRVSupplier) {
load();
enable(discordSRVSupplier);
}
public void load() {
try { try {
task.run(); completableFuture.get();
} catch (Throwable throwable) { } catch (ExecutionException | InterruptedException e) {
logger.error("Callback failed", throwable); logger.error("Failed to download dependencies", e);
} }
} }
taskPool.shutdown(); public void enable(Supplier<DiscordSRV> discordSRVSupplier) {
}); if (!completableFuture.isDone()) {
return;
}
discordSRVSupplier.get().invokeEnable();
} }
/** public void reload(DiscordSRV discordSRV) {
* Joins the dependency download. if (discordSRV == null) {
*/ return;
public void join() { }
completableFuture.join(); discordSRV.invokeReload();
} }
/** public void disable(DiscordSRV discordSRV) {
* This will run on the current thread if dependencies are already downloaded, otherwise will be added to a list. if (!completableFuture.isDone()) {
*/ completableFuture.cancel(true);
public void runWhenComplete(Runnable runnable) {
if (completableFuture.isDone()) {
runnable.run();
return; return;
} }
tasks.add(runnable); if (discordSRV == null) {
return;
} }
try {
discordSRV.invokeDisable().get(15, TimeUnit.SECONDS);
} catch (InterruptedException | TimeoutException e) {
logger.warning("Timed out/interrupted shutting down DiscordSRV");
} catch (ExecutionException ignored) {}
}
} }

View File

@ -27,14 +27,16 @@ import com.discordsrv.api.event.events.placeholder.PlaceholderLookupEvent;
import com.discordsrv.api.placeholder.PlaceholderLookupResult; import com.discordsrv.api.placeholder.PlaceholderLookupResult;
import com.discordsrv.common.DiscordSRV; import com.discordsrv.common.DiscordSRV;
import com.discordsrv.common.config.connection.ConnectionConfig; import com.discordsrv.common.config.connection.ConnectionConfig;
import com.discordsrv.common.discord.api.entity.DiscordUserImpl;
import com.discordsrv.common.discord.api.entity.channel.DiscordDMChannelImpl; import com.discordsrv.common.discord.api.entity.channel.DiscordDMChannelImpl;
import com.discordsrv.common.discord.api.entity.channel.DiscordTextChannelImpl; import com.discordsrv.common.discord.api.entity.channel.DiscordTextChannelImpl;
import com.discordsrv.common.discord.api.entity.guild.DiscordGuildImpl; import com.discordsrv.common.discord.api.entity.guild.DiscordGuildImpl;
import com.discordsrv.common.discord.api.entity.guild.DiscordGuildMemberImpl; import com.discordsrv.common.discord.api.entity.guild.DiscordGuildMemberImpl;
import com.discordsrv.common.discord.api.entity.guild.DiscordRoleImpl; import com.discordsrv.common.discord.api.entity.guild.DiscordRoleImpl;
import com.discordsrv.common.discord.api.entity.message.ReceivedDiscordMessageImpl; import com.discordsrv.common.discord.api.entity.message.ReceivedDiscordMessageImpl;
import com.discordsrv.common.discord.api.entity.DiscordUserImpl;
import com.discordsrv.common.discord.connection.DiscordConnectionManager; import com.discordsrv.common.discord.connection.DiscordConnectionManager;
import com.discordsrv.common.logging.Logger;
import com.discordsrv.common.logging.NamedLogger;
import com.discordsrv.common.scheduler.Scheduler; import com.discordsrv.common.scheduler.Scheduler;
import com.discordsrv.common.scheduler.threadfactory.CountingThreadFactory; import com.discordsrv.common.scheduler.threadfactory.CountingThreadFactory;
import com.discordsrv.common.time.util.Timeout; import com.discordsrv.common.time.util.Timeout;
@ -102,7 +104,7 @@ public class JDAConnectionManager implements DiscordConnectionManager {
); );
// Set default failure handling // Set default failure handling
RestAction.setDefaultFailure(new DefaultFailureCallback()); RestAction.setDefaultFailure(new DefaultFailureCallback(new NamedLogger(discordSRV, "DISCORD_REQUESTS")));
// Disable all mentions by default for safety // Disable all mentions by default for safety
AllowedMentions.setDefaultMentions(Collections.emptyList()); AllowedMentions.setDefaultMentions(Collections.emptyList());
@ -437,6 +439,12 @@ public class JDAConnectionManager implements DiscordConnectionManager {
private class DefaultFailureCallback implements Consumer<Throwable> { private class DefaultFailureCallback implements Consumer<Throwable> {
private final Logger logger;
protected DefaultFailureCallback(Logger logger) {
this.logger = logger;
}
@Override @Override
public void accept(Throwable t) { public void accept(Throwable t) {
if ((t instanceof InterruptedIOException || t instanceof InterruptedException) if ((t instanceof InterruptedIOException || t instanceof InterruptedException)
@ -448,13 +456,13 @@ public class JDAConnectionManager implements DiscordConnectionManager {
boolean cancelled; boolean cancelled;
if ((cancelled = t instanceof CancellationException) || t instanceof TimeoutException) { if ((cancelled = t instanceof CancellationException) || t instanceof TimeoutException) {
// Cancelling/timing out requests is always intentional // Cancelling/timing out requests is always intentional
discordSRV.logger().debug("A request " + (cancelled ? "was cancelled" : "timed out"), t.getCause()); logger.debug("A request " + (cancelled ? "was cancelled" : "timed out"), t.getCause());
} else if (t instanceof RateLimitedException) { } else if (t instanceof RateLimitedException) {
// Log route & retry after on warn & context on debug // Log route & retry after on warn & context on debug
RateLimitedException exception = ((RateLimitedException) t); RateLimitedException exception = ((RateLimitedException) t);
discordSRV.logger().warning("A request on route " + exception.getRateLimitedRoute() discordSRV.logger().warning("A request on route " + exception.getRateLimitedRoute()
+ " was rate-limited for " + exception.getRetryAfter() + "ms"); + " was rate-limited for " + exception.getRetryAfter() + "ms");
discordSRV.logger().debug(exception.getCause()); logger.debug(exception.getCause());
} else if (t instanceof ErrorResponseException) { } else if (t instanceof ErrorResponseException) {
ErrorResponseException exception = (ErrorResponseException) t; ErrorResponseException exception = (ErrorResponseException) t;
if (exception.getErrorCode() == Response.ERROR_CODE) { if (exception.getErrorCode() == Response.ERROR_CODE) {
@ -464,7 +472,7 @@ public class JDAConnectionManager implements DiscordConnectionManager {
// Run the cause through this method again // Run the cause through this method again
accept(cause); accept(cause);
} else { } else {
discordSRV.logger().error("Failed to complete request for a unknown reason", exception); logger.error("Failed to complete request for a unknown reason", exception);
} }
return; return;
} }
@ -504,17 +512,17 @@ public class JDAConnectionManager implements DiscordConnectionManager {
discordSRV.logger().error("+--------------------------------------------------------------->"); discordSRV.logger().error("+--------------------------------------------------------------->");
} else { } else {
// Log as debug as to not spam out the server console/log // Log as debug as to not spam out the server console/log
discordSRV.logger().debug("Failed to complete a request, Discord returned a server error (HTTP 500)"); logger.debug("Failed to complete a request, Discord returned a server error (HTTP 500)");
} }
// Log context to find what made the request // Log context to find what made the request
discordSRV.logger().debug(exception.getCause()); logger.debug(exception.getCause());
return; return;
} }
default: break; default: break;
} }
discordSRV.logger().error("Failed to complete a request: " + response.getMeaning()); logger.error("Failed to complete a request: " + response.getMeaning());
discordSRV.logger().debug(exception); logger.debug(exception);
} }
} }
} }

View File

@ -18,14 +18,18 @@
package com.discordsrv.common.event.bus; package com.discordsrv.common.event.bus;
import com.discordsrv.api.event.bus.EventBus;
import com.discordsrv.api.event.bus.EventListener; import com.discordsrv.api.event.bus.EventListener;
import com.discordsrv.api.event.bus.*; import com.discordsrv.api.event.bus.EventPriority;
import com.discordsrv.api.event.bus.Subscribe;
import com.discordsrv.api.event.bus.internal.EventStateHolder; import com.discordsrv.api.event.bus.internal.EventStateHolder;
import com.discordsrv.api.event.events.Cancellable; import com.discordsrv.api.event.events.Cancellable;
import com.discordsrv.api.event.events.Event; import com.discordsrv.api.event.events.Event;
import com.discordsrv.api.event.events.Processable; import com.discordsrv.api.event.events.Processable;
import com.discordsrv.common.DiscordSRV; import com.discordsrv.common.DiscordSRV;
import com.discordsrv.common.exception.InvalidListenerMethodException; import com.discordsrv.common.exception.InvalidListenerMethodException;
import com.discordsrv.common.logging.Logger;
import com.discordsrv.common.logging.NamedLogger;
import net.dv8tion.jda.api.events.GenericEvent; import net.dv8tion.jda.api.events.GenericEvent;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -35,7 +39,7 @@ import java.lang.reflect.Method;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.util.*; import java.util.*;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet; import java.util.concurrent.CopyOnWriteArrayList;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -48,11 +52,13 @@ public class EventBusImpl implements EventBus {
Pair.of(event -> event instanceof Processable && ((Processable) event).isProcessed(), EventStateHolder.PROCESSED) Pair.of(event -> event instanceof Processable && ((Processable) event).isProcessed(), EventStateHolder.PROCESSED)
); );
private final Map<Object, Set<EventListenerImpl>> listeners = new ConcurrentHashMap<>(); private final Map<Object, List<EventListenerImpl>> listeners = new ConcurrentHashMap<>();
private final DiscordSRV discordSRV; private final DiscordSRV discordSRV;
private final Logger logger;
public EventBusImpl(DiscordSRV discordSRV) { public EventBusImpl(DiscordSRV discordSRV) {
this.discordSRV = discordSRV; this.discordSRV = discordSRV;
this.logger = new NamedLogger(discordSRV, "EVENT_BUS");
} }
@Override @Override
@ -64,8 +70,8 @@ public class EventBusImpl implements EventBus {
Class<?> listenerClass = eventListener.getClass(); Class<?> listenerClass = eventListener.getClass();
List<Throwable> suppressedMethods = new ArrayList<>(); List<Throwable> suppressedMethods = new ArrayList<>();
Set<EventListenerImpl> methods = new HashSet<>(); List<EventListenerImpl> methods = new ArrayList<>();
EnumMap<EventPriority, Set<EventListenerImpl>> methodsByPriority = new EnumMap<>(EventPriority.class); EnumMap<EventPriority, List<EventListenerImpl>> methodsByPriority = new EnumMap<>(EventPriority.class);
Class<?> currentClass = listenerClass; Class<?> currentClass = listenerClass;
do { do {
@ -82,12 +88,12 @@ public class EventBusImpl implements EventBus {
} }
listeners.put(eventListener, methods); listeners.put(eventListener, methods);
discordSRV.logger().debug("Listener " + eventListener.getClass().getName() + " subscribed"); logger.debug("Listener " + eventListener.getClass().getName() + " subscribed");
} }
private void checkMethod(Class<?> listenerClass, Method method, private void checkMethod(Class<?> listenerClass, Method method,
List<Throwable> suppressedMethods, Set<EventListenerImpl> methods, List<Throwable> suppressedMethods, List<EventListenerImpl> methods,
EnumMap<EventPriority, Set<EventListenerImpl>> methodsByPriority) { EnumMap<EventPriority, List<EventListenerImpl>> methodsByPriority) {
Subscribe annotation = method.getAnnotation(Subscribe.class); Subscribe annotation = method.getAnnotation(Subscribe.class);
if (annotation == null) { if (annotation == null) {
return; return;
@ -137,7 +143,7 @@ public class EventBusImpl implements EventBus {
EventListenerImpl listener = new EventListenerImpl(listenerClass, annotation, firstParameter, method); EventListenerImpl listener = new EventListenerImpl(listenerClass, annotation, firstParameter, method);
methods.add(listener); methods.add(listener);
methodsByPriority.computeIfAbsent(eventPriority, key -> new CopyOnWriteArraySet<>()) methodsByPriority.computeIfAbsent(eventPriority, key -> new CopyOnWriteArrayList<>())
.add(listener); .add(listener);
} }
@ -149,7 +155,7 @@ public class EventBusImpl implements EventBus {
@Override @Override
public void unsubscribe(@NotNull Object eventListener) { public void unsubscribe(@NotNull Object eventListener) {
listeners.remove(eventListener); listeners.remove(eventListener);
discordSRV.logger().debug("Listener " + eventListener.getClass().getName() + " unsubscribed"); logger.debug("Listener " + eventListener.getClass().getName() + " unsubscribed");
} }
@Override @Override
@ -176,7 +182,7 @@ public class EventBusImpl implements EventBus {
Class<?> eventClass = event.getClass(); Class<?> eventClass = event.getClass();
for (EventPriority priority : EventPriority.values()) { for (EventPriority priority : EventPriority.values()) {
for (Map.Entry<Object, Set<EventListenerImpl>> entry : listeners.entrySet()) { for (Map.Entry<Object, List<EventListenerImpl>> entry : listeners.entrySet()) {
Object listener = entry.getKey(); Object listener = entry.getKey();
for (EventListenerImpl eventListener : entry.getValue()) { for (EventListenerImpl eventListener : entry.getValue()) {
if (eventListener.isIgnoringCancelled() && event instanceof Cancellable && ((Cancellable) event).isCancelled()) { if (eventListener.isIgnoringCancelled() && event instanceof Cancellable && ((Cancellable) event).isCancelled()) {
@ -198,7 +204,7 @@ public class EventBusImpl implements EventBus {
discordSRV.logger().error("Failed to pass " + event.getClass().getSimpleName() + " to " + eventListener, e.getCause()); discordSRV.logger().error("Failed to pass " + event.getClass().getSimpleName() + " to " + eventListener, e.getCause());
} }
long timeTaken = System.currentTimeMillis() - startTime; long timeTaken = System.currentTimeMillis() - startTime;
discordSRV.logger().trace(eventListener + " took " + timeTaken + "ms to execute"); logger.trace(eventListener + " took " + timeTaken + "ms to execute");
for (int index = 0; index < STATES.size(); index++) { for (int index = 0; index < STATES.size(); index++) {
Pair<Function<Object, Boolean>, ThreadLocal<EventListener>> state = STATES.get(index); Pair<Function<Object, Boolean>, ThreadLocal<EventListener>> state = STATES.get(index);

View File

@ -22,12 +22,13 @@ import com.discordsrv.api.event.bus.EventListener;
import com.discordsrv.api.event.events.Cancellable; import com.discordsrv.api.event.events.Cancellable;
import com.discordsrv.api.event.events.Processable; import com.discordsrv.api.event.events.Processable;
import com.discordsrv.common.DiscordSRV; import com.discordsrv.common.DiscordSRV;
import com.discordsrv.common.logging.Logger;
public final class EventUtil { public final class EventUtil {
private EventUtil() {} private EventUtil() {}
public static boolean checkProcessor(DiscordSRV discordSRV,Processable event) { public static boolean checkProcessor(DiscordSRV discordSRV, Processable event, Logger logger) {
if (!event.isProcessed()) { if (!event.isProcessed()) {
return false; return false;
} }
@ -36,12 +37,12 @@ public final class EventUtil {
.map(EventListener::className) .map(EventListener::className)
.orElse("Unknown"); .orElse("Unknown");
if (!whoProcessed.startsWith("com.discordsrv")) { if (!whoProcessed.startsWith("com.discordsrv")) {
discordSRV.logger().debug(event + " was handled by non-DiscordSRV handler: " + whoProcessed); logger.debug(event + " was handled by non-DiscordSRV handler: " + whoProcessed);
} }
return true; return true;
} }
public static boolean checkCancellation(DiscordSRV discordSRV, Cancellable event) { public static boolean checkCancellation(DiscordSRV discordSRV, Cancellable event, Logger logger) {
if (!event.isCancelled()) { if (!event.isCancelled()) {
return false; return false;
} }
@ -49,7 +50,7 @@ public final class EventUtil {
String whoCancelled = event.whoCancelled() String whoCancelled = event.whoCancelled()
.map(EventListener::className) .map(EventListener::className)
.orElse("Unknown"); .orElse("Unknown");
discordSRV.logger().debug(event + " was cancelled by " + whoCancelled); logger.debug(event + " was cancelled by " + whoCancelled);
return true; return true;
} }
} }

View File

@ -30,6 +30,7 @@ import com.discordsrv.common.groupsync.enums.GroupSyncCause;
import com.discordsrv.common.groupsync.enums.GroupSyncDirection; import com.discordsrv.common.groupsync.enums.GroupSyncDirection;
import com.discordsrv.common.groupsync.enums.GroupSyncResult; import com.discordsrv.common.groupsync.enums.GroupSyncResult;
import com.discordsrv.common.groupsync.enums.GroupSyncSide; import com.discordsrv.common.groupsync.enums.GroupSyncSide;
import com.discordsrv.common.logging.NamedLogger;
import com.discordsrv.common.module.type.AbstractModule; import com.discordsrv.common.module.type.AbstractModule;
import com.discordsrv.common.module.type.PermissionDataProvider; import com.discordsrv.common.module.type.PermissionDataProvider;
import com.discordsrv.common.player.IPlayer; import com.discordsrv.common.player.IPlayer;
@ -53,7 +54,7 @@ public class GroupSyncModule extends AbstractModule<DiscordSRV> {
private final Cache<UUID, Map<String, Boolean>> expectedMinecraftChanges; private final Cache<UUID, Map<String, Boolean>> expectedMinecraftChanges;
public GroupSyncModule(DiscordSRV discordSRV) { public GroupSyncModule(DiscordSRV discordSRV) {
super(discordSRV); super(discordSRV, new NamedLogger(discordSRV, "GROUP_SYNC"));
this.expectedDiscordChanges = discordSRV.caffeineBuilder() this.expectedDiscordChanges = discordSRV.caffeineBuilder()
.expireAfterWrite(30, TimeUnit.SECONDS) .expireAfterWrite(30, TimeUnit.SECONDS)
.build(); .build();
@ -124,7 +125,7 @@ public class GroupSyncModule extends AbstractModule<DiscordSRV> {
for (Map.Entry<GroupSyncConfig.PairConfig, CompletableFuture<GroupSyncResult>> entry : pairs.entrySet()) { for (Map.Entry<GroupSyncConfig.PairConfig, CompletableFuture<GroupSyncResult>> entry : pairs.entrySet()) {
summary.add(entry.getKey(), entry.getValue().join()); summary.add(entry.getKey(), entry.getValue().join());
} }
discordSRV.logger().debug(summary.toString()); logger().debug(summary.toString());
}); });
} }
@ -224,9 +225,9 @@ public class GroupSyncModule extends AbstractModule<DiscordSRV> {
continue; continue;
} }
resyncPair(pair, uuid, userId) resyncPair(pair, uuid, userId).whenComplete((result, t) -> logger().debug(
.whenComplete((result, t) -> discordSRV.logger().debug( new SynchronizationSummary(uuid, cause, pair, result).toString()
new SynchronizationSummary(uuid, cause, pair, result).toString())); ));
} }
} }

View File

@ -24,7 +24,7 @@ import org.jetbrains.annotations.Nullable;
public interface Logger { public interface Logger {
default void info(String message) { default void info(String message) {
log(LogLevel.INFO, message, null); log(null, LogLevel.INFO, message, null);
} }
default void warning(String message) { default void warning(String message) {
@ -34,7 +34,7 @@ public interface Logger {
warning(null, throwable); warning(null, throwable);
} }
default void warning(String message, Throwable throwable) { default void warning(String message, Throwable throwable) {
log(LogLevel.WARNING, message, throwable); log(null, LogLevel.WARNING, message, throwable);
} }
default void error(String message) { default void error(String message) {
@ -44,7 +44,7 @@ public interface Logger {
error(null, throwable); error(null, throwable);
} }
default void error(String message, Throwable throwable) { default void error(String message, Throwable throwable) {
log(LogLevel.ERROR, message, throwable); log(null, LogLevel.ERROR, message, throwable);
} }
default void debug(String message) { default void debug(String message) {
@ -54,7 +54,7 @@ public interface Logger {
debug(null, throwable); debug(null, throwable);
} }
default void debug(String message, Throwable throwable) { default void debug(String message, Throwable throwable) {
log(LogLevel.DEBUG, message, throwable); log(null, LogLevel.DEBUG, message, throwable);
} }
default void trace(String message) { default void trace(String message) {
@ -64,9 +64,9 @@ public interface Logger {
trace(null, throwable); trace(null, throwable);
} }
default void trace(String message, Throwable throwable) { default void trace(String message, Throwable throwable) {
log(LogLevel.TRACE, message, throwable); log(null, LogLevel.TRACE, message, throwable);
} }
void log(@NotNull LogLevel logLevel, @Nullable String message, @Nullable Throwable throwable); void log(@Nullable String loggerName, @NotNull LogLevel logLevel, @Nullable String message, @Nullable Throwable throwable);
} }

View File

@ -0,0 +1,39 @@
/*
* This file is part of DiscordSRV, licensed under the GPLv3 License
* Copyright (c) 2016-2022 Austin "Scarsz" Shapiro, Henri "Vankka" Schubin and DiscordSRV contributors
*
* 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 com.discordsrv.common.logging;
import com.discordsrv.common.DiscordSRV;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class NamedLogger implements Logger {
private final DiscordSRV discordSRV;
private final String name;
public NamedLogger(DiscordSRV discordSRV, String name) {
this.discordSRV = discordSRV;
this.name = name;
}
@Override
public void log(@Nullable String loggerName, @NotNull LogLevel logLevel, @Nullable String message, @Nullable Throwable throwable) {
discordSRV.logger().log(name, logLevel, message, throwable);
}
}

View File

@ -59,7 +59,7 @@ public class JavaLoggerImpl implements Logger, LoggingBackend {
} }
@Override @Override
public void log(@NotNull LogLevel level, @Nullable String message, @Nullable Throwable throwable) { public void log(@Nullable String loggerName, @NotNull LogLevel level, @Nullable String message, @Nullable Throwable throwable) {
Level logLevel = LEVELS.getKey(level); Level logLevel = LEVELS.getKey(level);
if (logLevel != null) { if (logLevel != null) {
logger.log(logLevel, message, throwable); logger.log(logLevel, message, throwable);

View File

@ -64,7 +64,7 @@ public class Log4JLoggerImpl implements Logger, LoggingBackend {
} }
@Override @Override
public void log(@NotNull LogLevel level, @Nullable String message, @Nullable Throwable throwable) { public void log(@Nullable String loggerName, @NotNull LogLevel level, @Nullable String message, @Nullable Throwable throwable) {
Level logLevel = LEVELS.getKey(level); Level logLevel = LEVELS.getKey(level);
logger.log(logLevel, message, throwable); logger.log(logLevel, message, throwable);
} }

View File

@ -32,7 +32,7 @@ public class SLF4JLoggerImpl implements Logger {
} }
@Override @Override
public void log(@NotNull LogLevel level, @Nullable String message, @Nullable Throwable throwable) { public void log(@Nullable String loggerName, @NotNull LogLevel level, @Nullable String message, @Nullable Throwable throwable) {
if (!(level instanceof LogLevel.StandardLogLevel)) { if (!(level instanceof LogLevel.StandardLogLevel)) {
return; return;
} }

View File

@ -84,6 +84,6 @@ public class DependencyLoggingHandler implements LogAppender {
} }
} }
discordSRV.logger().log(logLevel, "[" + name + "]" + (message != null ? " " + message : ""), throwable); discordSRV.logger().log(null, logLevel, "[" + name + "]" + (message != null ? " " + message : ""), throwable);
} }
} }

View File

@ -23,24 +23,77 @@ import com.discordsrv.common.logging.LogLevel;
import com.discordsrv.common.logging.Logger; import com.discordsrv.common.logging.Logger;
import net.dv8tion.jda.api.Permission; import net.dv8tion.jda.api.Permission;
import net.dv8tion.jda.api.exceptions.InsufficientPermissionException; import net.dv8tion.jda.api.exceptions.InsufficientPermissionException;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
public class DiscordSRVLogger implements Logger { public class DiscordSRVLogger implements Logger {
private static final DateFormat DATE_TIME_FORMATTER = new SimpleDateFormat("EEE HH:mm:ss z");
private static final String LOG_LINE_FORMAT = "[%s] [%s] %s";
private static final String LOG_FILE_NAME_FORMAT = "%s-%s.log";
private final DiscordSRV discordSRV; private final DiscordSRV discordSRV;
private final Path logsDirectory;
private final List<Path> debugLogs;
public DiscordSRVLogger(DiscordSRV discordSRV) { public DiscordSRVLogger(DiscordSRV discordSRV) {
this.discordSRV = discordSRV; this.discordSRV = discordSRV;
this.logsDirectory = discordSRV.dataDirectory().resolve("logs");
if (!Files.exists(logsDirectory)) {
try {
Files.createDirectory(logsDirectory);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
this.debugLogs = rotateLog("debug", 3);
}
public List<Path> getDebugLogs() {
return debugLogs;
}
@SuppressWarnings("SameParameterValue")
private List<Path> rotateLog(String label, int amount) {
try {
List<Path> logs = new ArrayList<>(amount);
for (int i = amount; i > 0; i--) {
Path log = logsDirectory.resolve(String.format(LOG_FILE_NAME_FORMAT, label, i));
logs.add(log);
if (!Files.exists(log)) {
continue;
}
if (i == amount) {
Files.delete(log);
continue;
}
Path to = logsDirectory.resolve(String.format(LOG_FILE_NAME_FORMAT, label, i + 1));
Files.move(log, to);
}
return logs;
} catch (IOException e) {
e.printStackTrace();
return null;
}
} }
@Override @Override
public void log(@NotNull LogLevel logLevel, @Nullable String message, @Nullable Throwable throwable) { public void log(@Nullable String loggerName, @NotNull LogLevel logLevel, @Nullable String message, @Nullable Throwable throwable) {
if (logLevel == LogLevel.DEBUG || logLevel == LogLevel.TRACE || logLevel instanceof LogLevel.CustomLogLevel) {
// TODO: handle debug/trace
return;
}
if (throwable instanceof InsufficientPermissionException) { if (throwable instanceof InsufficientPermissionException) {
Permission permission = ((InsufficientPermissionException) throwable).getPermission(); Permission permission = ((InsufficientPermissionException) throwable).getPermission();
String msg = "The bot is missing the \"" + permission.getName() + "\" permission"; String msg = "The bot is missing the \"" + permission.getName() + "\" permission";
@ -49,11 +102,55 @@ public class DiscordSRVLogger implements Logger {
} else { } else {
message += ": " + msg; message += ": " + msg;
} }
discordSRV.platformLogger().log(logLevel, message, null); doLog(loggerName, logLevel, message, null);
discordSRV.logger().debug(throwable); doLog(loggerName, LogLevel.DEBUG, null, throwable);
return; return;
} }
discordSRV.platformLogger().log(logLevel, message, throwable); doLog(loggerName, logLevel, message, throwable);
}
private void doLog(String loggerName, LogLevel logLevel, String message, Throwable throwable) {
if (logLevel != LogLevel.DEBUG && logLevel != LogLevel.TRACE) {
discordSRV.platformLogger().log(null, logLevel, message, throwable);
}
// TODO: handle trace
Path debugLog = debugLogs.isEmpty() ? null : debugLogs.get(0);
if (debugLog == null || logLevel == LogLevel.TRACE) {
return;
}
long time = System.currentTimeMillis();
discordSRV.scheduler().runFork(() -> writeToFile(loggerName, debugLog, time, logLevel, message, throwable));
}
private void writeToFile(String loggerName, Path path, long time, LogLevel logLevel, String message, Throwable throwable) {
try {
Path parent = path.getParent();
if (!Files.exists(parent)) {
Files.createDirectories(parent);
}
if (!Files.exists(path)) {
Files.createFile(path);
}
if (message == null) {
message = "";
}
if (loggerName != null) {
message = "[" + loggerName + "] " + message;
}
String timestamp = DATE_TIME_FORMATTER.format(time);
String line = String.format(LOG_LINE_FORMAT, timestamp, logLevel.name(), message) + "\n";
if (throwable != null) {
line += ExceptionUtils.getStackTrace(throwable) + "\n";
}
Files.write(path, line.getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND);
} catch (Throwable e) {
// Prevent infinite loop
discordSRV.platformLogger().error("Failed to write to debug log", e);
}
} }
} }

View File

@ -36,6 +36,7 @@ import com.discordsrv.common.config.main.DiscordIgnores;
import com.discordsrv.common.config.main.channels.DiscordToMinecraftChatConfig; import com.discordsrv.common.config.main.channels.DiscordToMinecraftChatConfig;
import com.discordsrv.common.config.main.channels.base.BaseChannelConfig; import com.discordsrv.common.config.main.channels.base.BaseChannelConfig;
import com.discordsrv.common.function.OrDefault; import com.discordsrv.common.function.OrDefault;
import com.discordsrv.common.logging.NamedLogger;
import com.discordsrv.common.module.type.AbstractModule; import com.discordsrv.common.module.type.AbstractModule;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
@ -44,7 +45,7 @@ import java.util.Map;
public class DiscordChatMessageModule extends AbstractModule<DiscordSRV> { public class DiscordChatMessageModule extends AbstractModule<DiscordSRV> {
public DiscordChatMessageModule(DiscordSRV discordSRV) { public DiscordChatMessageModule(DiscordSRV discordSRV) {
super(discordSRV); super(discordSRV, new NamedLogger(discordSRV, "DISCORD_TO_MINECRAFT"));
} }
@Subscribe @Subscribe

View File

@ -38,6 +38,7 @@ import com.discordsrv.common.config.main.channels.base.BaseChannelConfig;
import com.discordsrv.common.config.main.channels.base.IChannelConfig; import com.discordsrv.common.config.main.channels.base.IChannelConfig;
import com.discordsrv.common.function.OrDefault; import com.discordsrv.common.function.OrDefault;
import com.discordsrv.common.future.util.CompletableFutureUtil; import com.discordsrv.common.future.util.CompletableFutureUtil;
import com.discordsrv.common.logging.NamedLogger;
import com.discordsrv.common.module.type.AbstractModule; import com.discordsrv.common.module.type.AbstractModule;
import com.github.benmanes.caffeine.cache.Cache; import com.github.benmanes.caffeine.cache.Cache;
@ -50,7 +51,7 @@ public class DiscordMessageMirroringModule extends AbstractModule<DiscordSRV> {
private final Cache<MessageReference, Set<MessageReference>> mapping; private final Cache<MessageReference, Set<MessageReference>> mapping;
public DiscordMessageMirroringModule(DiscordSRV discordSRV) { public DiscordMessageMirroringModule(DiscordSRV discordSRV) {
super(discordSRV); super(discordSRV, new NamedLogger(discordSRV, "DISCORD_MIRRORING"));
this.mapping = discordSRV.caffeineBuilder() this.mapping = discordSRV.caffeineBuilder()
.expireAfterWrite(30, TimeUnit.MINUTES) .expireAfterWrite(30, TimeUnit.MINUTES)
.expireAfterAccess(10, TimeUnit.MINUTES) .expireAfterAccess(10, TimeUnit.MINUTES)

View File

@ -35,6 +35,7 @@ import com.discordsrv.common.config.main.channels.base.BaseChannelConfig;
import com.discordsrv.common.config.main.channels.base.IChannelConfig; import com.discordsrv.common.config.main.channels.base.IChannelConfig;
import com.discordsrv.common.discord.api.entity.message.ReceivedDiscordMessageClusterImpl; import com.discordsrv.common.discord.api.entity.message.ReceivedDiscordMessageClusterImpl;
import com.discordsrv.common.function.OrDefault; import com.discordsrv.common.function.OrDefault;
import com.discordsrv.common.logging.Logger;
import com.discordsrv.common.module.type.AbstractModule; import com.discordsrv.common.module.type.AbstractModule;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -47,8 +48,8 @@ import java.util.concurrent.CopyOnWriteArrayList;
public abstract class AbstractGameMessageModule<T> extends AbstractModule<DiscordSRV> { public abstract class AbstractGameMessageModule<T> extends AbstractModule<DiscordSRV> {
public AbstractGameMessageModule(DiscordSRV discordSRV) { public AbstractGameMessageModule(DiscordSRV discordSRV, Logger logger) {
super(discordSRV); super(discordSRV, logger);
} }
public abstract OrDefault<T> mapConfig(OrDefault<BaseChannelConfig> channelConfig); public abstract OrDefault<T> mapConfig(OrDefault<BaseChannelConfig> channelConfig);

View File

@ -28,11 +28,12 @@ import com.discordsrv.common.DiscordSRV;
import com.discordsrv.common.config.main.channels.JoinMessageConfig; import com.discordsrv.common.config.main.channels.JoinMessageConfig;
import com.discordsrv.common.config.main.channels.base.BaseChannelConfig; import com.discordsrv.common.config.main.channels.base.BaseChannelConfig;
import com.discordsrv.common.function.OrDefault; import com.discordsrv.common.function.OrDefault;
import com.discordsrv.common.logging.NamedLogger;
public class JoinMessageModule extends AbstractGameMessageModule<JoinMessageConfig> { public class JoinMessageModule extends AbstractGameMessageModule<JoinMessageConfig> {
public JoinMessageModule(DiscordSRV discordSRV) { public JoinMessageModule(DiscordSRV discordSRV) {
super(discordSRV); super(discordSRV, new NamedLogger(discordSRV, "JOIN_MESSAGES"));
} }
@Override @Override

View File

@ -28,11 +28,12 @@ import com.discordsrv.common.DiscordSRV;
import com.discordsrv.common.config.main.channels.LeaveMessageConfig; import com.discordsrv.common.config.main.channels.LeaveMessageConfig;
import com.discordsrv.common.config.main.channels.base.BaseChannelConfig; import com.discordsrv.common.config.main.channels.base.BaseChannelConfig;
import com.discordsrv.common.function.OrDefault; import com.discordsrv.common.function.OrDefault;
import com.discordsrv.common.logging.NamedLogger;
public class LeaveMessageModule extends AbstractGameMessageModule<LeaveMessageConfig> { public class LeaveMessageModule extends AbstractGameMessageModule<LeaveMessageConfig> {
public LeaveMessageModule(DiscordSRV discordSRV) { public LeaveMessageModule(DiscordSRV discordSRV) {
super(discordSRV); super(discordSRV, new NamedLogger(discordSRV, "LEAVE_MESSAGES"));
} }
@Override @Override

View File

@ -37,6 +37,7 @@ import com.discordsrv.common.DiscordSRV;
import com.discordsrv.common.config.main.channels.MinecraftToDiscordChatConfig; import com.discordsrv.common.config.main.channels.MinecraftToDiscordChatConfig;
import com.discordsrv.common.config.main.channels.base.BaseChannelConfig; import com.discordsrv.common.config.main.channels.base.BaseChannelConfig;
import com.discordsrv.common.function.OrDefault; import com.discordsrv.common.function.OrDefault;
import com.discordsrv.common.logging.NamedLogger;
import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.GuildChannel; import net.dv8tion.jda.api.entities.GuildChannel;
import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Member;
@ -65,7 +66,7 @@ public class MinecraftToDiscordChatModule extends AbstractGameMessageModule<Mine
private final Map<Long, Map<Long, CachedMention>> channelMentions = new ConcurrentHashMap<>(); private final Map<Long, Map<Long, CachedMention>> channelMentions = new ConcurrentHashMap<>();
public MinecraftToDiscordChatModule(DiscordSRV discordSRV) { public MinecraftToDiscordChatModule(DiscordSRV discordSRV) {
super(discordSRV); super(discordSRV, new NamedLogger(discordSRV, "MINECRAFT_TO_DISCORD"));
} }
@Override @Override

View File

@ -23,14 +23,25 @@ import com.discordsrv.api.event.events.Processable;
import com.discordsrv.api.module.type.Module; import com.discordsrv.api.module.type.Module;
import com.discordsrv.common.DiscordSRV; import com.discordsrv.common.DiscordSRV;
import com.discordsrv.common.event.util.EventUtil; import com.discordsrv.common.event.util.EventUtil;
import com.discordsrv.common.logging.Logger;
public abstract class AbstractModule<DT extends DiscordSRV> implements Module { public abstract class AbstractModule<DT extends DiscordSRV> implements Module {
protected final DT discordSRV; protected final DT discordSRV;
private final Logger logger;
private boolean hasBeenEnabled = false; private boolean hasBeenEnabled = false;
public AbstractModule(DT discordSRV) { public AbstractModule(DT discordSRV) {
this(discordSRV, discordSRV.logger());
}
public AbstractModule(DT discordSRV, Logger logger) {
this.discordSRV = discordSRV; this.discordSRV = discordSRV;
this.logger = logger;
}
public final Logger logger() {
return logger;
} }
public final void enableModule() { public final void enableModule() {
@ -49,10 +60,10 @@ public abstract class AbstractModule<DT extends DiscordSRV> implements Module {
// Utility // Utility
protected final boolean checkProcessor(Processable event) { protected final boolean checkProcessor(Processable event) {
return EventUtil.checkProcessor(discordSRV, event); return EventUtil.checkProcessor(discordSRV, event, logger());
} }
protected final boolean checkCancellation(Cancellable event) { protected final boolean checkCancellation(Cancellable event) {
return EventUtil.checkCancellation(discordSRV, event); return EventUtil.checkCancellation(discordSRV, event, logger());
} }
} }

View File

@ -31,6 +31,7 @@ import com.discordsrv.common.scheduler.StandardScheduler;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths;
public class MockDiscordSRV extends AbstractDiscordSRV<MainConfig, ConnectionConfig> { public class MockDiscordSRV extends AbstractDiscordSRV<MainConfig, ConnectionConfig> {
@ -50,7 +51,7 @@ public class MockDiscordSRV extends AbstractDiscordSRV<MainConfig, ConnectionCon
@Override @Override
public Path dataDirectory() { public Path dataDirectory() {
return null; return Paths.get("");
} }
@Override @Override

View File

@ -61,25 +61,24 @@ public class DiscordSRVSpongeBootstrap extends AbstractBootstrap implements ISpo
@Override @Override
public void onConstruct() { public void onConstruct() {
// Wait until dependencies ready, then initialize DiscordSRV dependencies.load();
dependencies.join();
} }
@Override @Override
public void onStarted() { public void onStarted() {
this.discordSRV = new SpongeDiscordSRV(logger, pluginContainer, game, classLoader, dataDirectory); dependencies.enable(() -> this.discordSRV = new SpongeDiscordSRV(logger, pluginContainer, game, classLoader, dataDirectory));
if (discordSRV != null) {
dependencies.runWhenComplete(discordSRV::invokeEnable); discordSRV.invokeServerStarted();
dependencies.runWhenComplete(discordSRV::invokeServerStarted); }
} }
@Override @Override
public void onRefresh() { public void onRefresh() {
dependencies.runWhenComplete(discordSRV::invokeReload); dependencies.reload(discordSRV);
} }
@Override @Override
public void onStopping() { public void onStopping() {
dependencies.runWhenComplete(discordSRV::invokeDisable); dependencies.disable(discordSRV);
} }
} }

View File

@ -68,21 +68,17 @@ public class DiscordSRVVelocityBootstrap {
@Subscribe @Subscribe
public void onProxyInitialize(ProxyInitializeEvent event) { public void onProxyInitialize(ProxyInitializeEvent event) {
// Wait until dependencies ready, then initialize DiscordSRV dependencies.loadAndEnable(() -> this.discordSRV = new VelocityDiscordSRV(this, logger, proxyServer, pluginContainer, dataDirectory));
dependencies.join();
this.discordSRV = new VelocityDiscordSRV(this, logger, proxyServer, pluginContainer, dataDirectory);
dependencies.runWhenComplete(discordSRV::invokeEnable);
} }
@Subscribe @Subscribe
public void onProxyReload(ProxyReloadEvent event) { public void onProxyReload(ProxyReloadEvent event) {
dependencies.runWhenComplete(discordSRV::invokeReload); dependencies.reload(discordSRV);
} }
@Subscribe @Subscribe
public void onProxyShutdown(ProxyShutdownEvent event) { public void onProxyShutdown(ProxyShutdownEvent event) {
dependencies.runWhenComplete(discordSRV::invokeDisable); dependencies.disable(discordSRV);
} }
} }

View File

@ -23,8 +23,8 @@ import com.discordsrv.common.config.main.MainConfig;
import com.discordsrv.common.config.manager.ConnectionConfigManager; import com.discordsrv.common.config.manager.ConnectionConfigManager;
import com.discordsrv.common.config.manager.MainConfigManager; import com.discordsrv.common.config.manager.MainConfigManager;
import com.discordsrv.common.logging.Logger; import com.discordsrv.common.logging.Logger;
import com.discordsrv.proxy.ProxyDiscordSRV;
import com.discordsrv.common.scheduler.StandardScheduler; import com.discordsrv.common.scheduler.StandardScheduler;
import com.discordsrv.proxy.ProxyDiscordSRV;
import com.discordsrv.velocity.console.VelocityConsole; import com.discordsrv.velocity.console.VelocityConsole;
import com.discordsrv.velocity.player.VelocityPlayerProvider; import com.discordsrv.velocity.player.VelocityPlayerProvider;
import com.velocitypowered.api.plugin.PluginContainer; import com.velocitypowered.api.plugin.PluginContainer;