diff --git a/src/main/java/com/gmail/artemis/the/gr8/playerstats/Main.java b/src/main/java/com/gmail/artemis/the/gr8/playerstats/Main.java
index 94e38b9..6d3034a 100644
--- a/src/main/java/com/gmail/artemis/the/gr8/playerstats/Main.java
+++ b/src/main/java/com/gmail/artemis/the/gr8/playerstats/Main.java
@@ -68,8 +68,4 @@ public class Main extends JavaPlugin {
}
this.getLogger().info("Disabled PlayerStats!");
}
-
- public void logTimeTaken(String className, String methodName, long previousTime) {
- getLogger().info(className + ", " + methodName + ": " + (System.currentTimeMillis() - previousTime) + "ms");
- }
}
diff --git a/src/main/java/com/gmail/artemis/the/gr8/playerstats/ThreadManager.java b/src/main/java/com/gmail/artemis/the/gr8/playerstats/ThreadManager.java
index 9e11a93..412ea9e 100644
--- a/src/main/java/com/gmail/artemis/the/gr8/playerstats/ThreadManager.java
+++ b/src/main/java/com/gmail/artemis/the/gr8/playerstats/ThreadManager.java
@@ -5,13 +5,16 @@ import com.gmail.artemis.the.gr8.playerstats.reload.ReloadThread;
import com.gmail.artemis.the.gr8.playerstats.statistic.StatRequest;
import com.gmail.artemis.the.gr8.playerstats.statistic.StatThread;
import com.gmail.artemis.the.gr8.playerstats.msg.MessageFactory;
+import com.gmail.artemis.the.gr8.playerstats.utils.MyLogger;
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
import org.bukkit.command.CommandSender;
public class ThreadManager {
- private static final int threshold = 10;
+ private final int threshold = 10;
+ private int statThreadID;
+ private int reloadThreadID;
private final Main plugin;
private final BukkitAudiences adventure;
@@ -28,16 +31,27 @@ public class ThreadManager {
messageFactory = m;
plugin = p;
- startReloadThread(null, true);
+ statThreadID = 0;
+ reloadThreadID = 0;
+ startReloadThread(null);
}
- public void startReloadThread(CommandSender sender, boolean firstTimeLoading) {
- reloadThread = new ReloadThread(adventure, config, messageFactory, plugin, threshold, firstTimeLoading, statThread, sender);
- reloadThread.start();
+ public void startReloadThread(CommandSender sender) {
+ if (reloadThread == null || !reloadThread.isAlive()) {
+ reloadThreadID += 1;
+
+ reloadThread = new ReloadThread(adventure, config, messageFactory, plugin, threshold, reloadThreadID, statThread, sender);
+ reloadThread.start();
+ }
+ else {
+ MyLogger.threadAlreadyRunning(reloadThread.getName());
+ }
}
public void startStatThread(StatRequest request) {
- statThread = new StatThread(adventure, config, messageFactory, plugin, threshold, request, reloadThread);
+ statThreadID += 1;
+
+ statThread = new StatThread(adventure, config, messageFactory, plugin, statThreadID, threshold, request, reloadThread);
statThread.start();
}
diff --git a/src/main/java/com/gmail/artemis/the/gr8/playerstats/commands/ReloadCommand.java b/src/main/java/com/gmail/artemis/the/gr8/playerstats/commands/ReloadCommand.java
index 95d12e3..ea19f77 100644
--- a/src/main/java/com/gmail/artemis/the/gr8/playerstats/commands/ReloadCommand.java
+++ b/src/main/java/com/gmail/artemis/the/gr8/playerstats/commands/ReloadCommand.java
@@ -17,7 +17,7 @@ public class ReloadCommand implements CommandExecutor {
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) {
- threadManager.startReloadThread(sender, false);
+ threadManager.startReloadThread(sender);
return true;
}
}
diff --git a/src/main/java/com/gmail/artemis/the/gr8/playerstats/commands/StatCommand.java b/src/main/java/com/gmail/artemis/the/gr8/playerstats/commands/StatCommand.java
index 9f9d170..9f15e07 100644
--- a/src/main/java/com/gmail/artemis/the/gr8/playerstats/commands/StatCommand.java
+++ b/src/main/java/com/gmail/artemis/the/gr8/playerstats/commands/StatCommand.java
@@ -169,7 +169,7 @@ public class StatCommand implements CommandExecutor {
request.setPlayerName(sender.getName());
request.setSelection(Query.PLAYER);
}
- else if (OfflinePlayerHandler.isOfflinePlayerName(arg) && request.getPlayerName() == null) {
+ else if (OfflinePlayerHandler.isRelevantPlayer(arg) && request.getPlayerName() == null) {
request.setPlayerName(arg);
request.setSelection(Query.PLAYER);
}
diff --git a/src/main/java/com/gmail/artemis/the/gr8/playerstats/config/ConfigHandler.java b/src/main/java/com/gmail/artemis/the/gr8/playerstats/config/ConfigHandler.java
index 47f9603..780cc64 100644
--- a/src/main/java/com/gmail/artemis/the/gr8/playerstats/config/ConfigHandler.java
+++ b/src/main/java/com/gmail/artemis/the/gr8/playerstats/config/ConfigHandler.java
@@ -2,6 +2,7 @@ package com.gmail.artemis.the.gr8.playerstats.config;
import com.gmail.artemis.the.gr8.playerstats.Main;
import com.gmail.artemis.the.gr8.playerstats.enums.Query;
+import com.gmail.artemis.the.gr8.playerstats.utils.MyLogger;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
@@ -24,15 +25,27 @@ public class ConfigHandler {
configVersion = 3.1;
checkConfigVersion();
+ MyLogger.setDebugLevel(debugLevel());
}
- /** Reloads the config from file, or creates a new file with default values if there is none. */
+ /** Returns the desired debugging level.
+
1 = low (only show unexpected errors)
+ 2 = medium (show all encountered exceptions, log main tasks and show time taken)
+ 3 = high (log all tasks and time taken)
+ Default: 1
*/
+ public int debugLevel() {
+ return config.getInt("debug-level", 1);
+ }
+
+ /** Reloads the config from file, or creates a new file with default values if there is none.
+ Also reads the value for debug-level and passes it on to MyLogger. */
public boolean reloadConfig() {
try {
if (!configFile.exists()) {
saveDefaultConfig();
}
config = YamlConfiguration.loadConfiguration(configFile);
+ MyLogger.setDebugLevel(debugLevel());
return true;
}
catch (Exception e) {
diff --git a/src/main/java/com/gmail/artemis/the/gr8/playerstats/enums/DebugLevel.java b/src/main/java/com/gmail/artemis/the/gr8/playerstats/enums/DebugLevel.java
new file mode 100644
index 0000000..3969097
--- /dev/null
+++ b/src/main/java/com/gmail/artemis/the/gr8/playerstats/enums/DebugLevel.java
@@ -0,0 +1,5 @@
+package com.gmail.artemis.the.gr8.playerstats.enums;
+
+public enum DebugLevel {
+ LOW, MEDIUM, HIGH
+}
diff --git a/src/main/java/com/gmail/artemis/the/gr8/playerstats/listeners/JoinListener.java b/src/main/java/com/gmail/artemis/the/gr8/playerstats/listeners/JoinListener.java
index 1dd19bc..e6dfd6b 100644
--- a/src/main/java/com/gmail/artemis/the/gr8/playerstats/listeners/JoinListener.java
+++ b/src/main/java/com/gmail/artemis/the/gr8/playerstats/listeners/JoinListener.java
@@ -16,7 +16,7 @@ public class JoinListener implements Listener {
@EventHandler
public void onPlayerJoin(PlayerJoinEvent joinEvent) {
if (!joinEvent.getPlayer().hasPlayedBefore()) {
- threadManager.startReloadThread(null, false);
+ threadManager.startReloadThread(null);
}
}
}
diff --git a/src/main/java/com/gmail/artemis/the/gr8/playerstats/reload/ReloadAction.java b/src/main/java/com/gmail/artemis/the/gr8/playerstats/reload/ReloadAction.java
index 1088fa5..8b3af9b 100644
--- a/src/main/java/com/gmail/artemis/the/gr8/playerstats/reload/ReloadAction.java
+++ b/src/main/java/com/gmail/artemis/the/gr8/playerstats/reload/ReloadAction.java
@@ -1,5 +1,6 @@
package com.gmail.artemis.the.gr8.playerstats.reload;
+import com.gmail.artemis.the.gr8.playerstats.utils.MyLogger;
import com.gmail.artemis.the.gr8.playerstats.utils.UnixTimeHandler;
import org.bukkit.OfflinePlayer;
@@ -15,40 +16,33 @@ public class ReloadAction extends RecursiveAction {
private final int start;
private final int end;
- private final boolean whitelistOnly;
- private final boolean excludeBanned;
private final int lastPlayedLimit;
private final ConcurrentHashMap offlinePlayerUUIDs;
/** Fills a ConcurrentHashMap with PlayerNames and UUIDs for all OfflinePlayers that should be included in statistic calculations.
* @param threshold the maximum length of OfflinePlayers to process in one task
* @param players array of all OfflinePlayers (straight from Bukkit)
- * @param whitelistOnly whether to limit players based on the whitelist
- * @param excludeBanned whether to exclude banned players
* @param lastPlayedLimit whether to set a limit based on last-played-date
* @param offlinePlayerUUIDs the ConcurrentHashMap to put resulting playerNames and UUIDs on
*/
public ReloadAction(int threshold, OfflinePlayer[] players,
- boolean whitelistOnly, boolean excludeBanned, int lastPlayedLimit,
- ConcurrentHashMap offlinePlayerUUIDs) {
+ int lastPlayedLimit, ConcurrentHashMap offlinePlayerUUIDs) {
- this(threshold, players, 0, players.length,
- whitelistOnly, excludeBanned, lastPlayedLimit, offlinePlayerUUIDs);
+ this(threshold, players, 0, players.length, lastPlayedLimit, offlinePlayerUUIDs);
}
protected ReloadAction(int threshold, OfflinePlayer[] players, int start, int end,
- boolean whitelistOnly, boolean excludeBanned, int lastPlayedLimit,
- ConcurrentHashMap offlinePlayerUUIDs) {
+ int lastPlayedLimit, ConcurrentHashMap offlinePlayerUUIDs) {
this.threshold = threshold;
this.players = players;
this.start = start;
this.end = end;
- this.whitelistOnly = whitelistOnly;
- this.excludeBanned = excludeBanned;
this.lastPlayedLimit = lastPlayedLimit;
this.offlinePlayerUUIDs = offlinePlayerUUIDs;
+
+ MyLogger.subActionCreated(Thread.currentThread().getName());
}
@Override
@@ -60,9 +54,9 @@ public class ReloadAction extends RecursiveAction {
else {
final int split = length / 2;
final ReloadAction subTask1 = new ReloadAction(threshold, players, start, (start + split),
- whitelistOnly, excludeBanned, lastPlayedLimit, offlinePlayerUUIDs);
+ lastPlayedLimit, offlinePlayerUUIDs);
final ReloadAction subTask2 = new ReloadAction(threshold, players, (start + split), end,
- whitelistOnly, excludeBanned, lastPlayedLimit, offlinePlayerUUIDs);
+ lastPlayedLimit, offlinePlayerUUIDs);
//queue and compute all subtasks in the right order
invokeAll(subTask1, subTask2);
@@ -72,11 +66,11 @@ public class ReloadAction extends RecursiveAction {
private void process() {
for (int i = start; i < end; i++) {
OfflinePlayer player = players[i];
- if (player.getName() != null &&
- (!whitelistOnly || player.isWhitelisted()) &&
- (!excludeBanned || !player.isBanned()) &&
+ String playerName = player.getName();
+ MyLogger.actionRunning(Thread.currentThread().getName(), playerName, 1);
+ if (playerName != null &&
(lastPlayedLimit == 0 || UnixTimeHandler.hasPlayedSince(lastPlayedLimit, player.getLastPlayed()))) {
- offlinePlayerUUIDs.put(player.getName(), player.getUniqueId());
+ offlinePlayerUUIDs.put(playerName, player.getUniqueId());
}
}
}
diff --git a/src/main/java/com/gmail/artemis/the/gr8/playerstats/reload/ReloadThread.java b/src/main/java/com/gmail/artemis/the/gr8/playerstats/reload/ReloadThread.java
index aa707e6..b8d4a54 100644
--- a/src/main/java/com/gmail/artemis/the/gr8/playerstats/reload/ReloadThread.java
+++ b/src/main/java/com/gmail/artemis/the/gr8/playerstats/reload/ReloadThread.java
@@ -5,6 +5,7 @@ import com.gmail.artemis.the.gr8.playerstats.ThreadManager;
import com.gmail.artemis.the.gr8.playerstats.config.ConfigHandler;
import com.gmail.artemis.the.gr8.playerstats.statistic.StatThread;
import com.gmail.artemis.the.gr8.playerstats.msg.MessageFactory;
+import com.gmail.artemis.the.gr8.playerstats.utils.MyLogger;
import com.gmail.artemis.the.gr8.playerstats.utils.OfflinePlayerHandler;
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
import org.bukkit.Bukkit;
@@ -13,7 +14,9 @@ import org.bukkit.command.CommandSender;
import org.bukkit.command.ConsoleCommandSender;
import org.jetbrains.annotations.Nullable;
+import java.util.Arrays;
import java.util.ConcurrentModificationException;
+import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ForkJoinPool;
@@ -21,6 +24,7 @@ import java.util.concurrent.ForkJoinPool;
public class ReloadThread extends Thread {
private final int threshold;
+ private final int reloadThreadID;
private final BukkitAudiences adventure;
private static ConfigHandler config;
@@ -29,10 +33,11 @@ public class ReloadThread extends Thread {
private final StatThread statThread;
private final CommandSender sender;
- private final boolean firstTimeLoading;
- public ReloadThread(BukkitAudiences a, ConfigHandler c, MessageFactory m, Main p, int threshold, boolean firstTime, @Nullable StatThread s, @Nullable CommandSender se) {
+ public ReloadThread(BukkitAudiences a, ConfigHandler c, MessageFactory m, Main p, int threshold, int ID, @Nullable StatThread s, @Nullable CommandSender se) {
this.threshold = threshold;
+ reloadThreadID = ID;
+
adventure = a;
config = c;
messageFactory = m;
@@ -40,18 +45,21 @@ public class ReloadThread extends Thread {
statThread = s;
sender = se;
- firstTimeLoading = firstTime;
+
+ this.setName("ReloadThread-" + reloadThreadID);
+ MyLogger.threadCreated(this.getName());
}
@Override
public void run() {
long time = System.currentTimeMillis();
+ MyLogger.threadStart(this.getName());
- //if reload is triggered by /statreload...
- if (!firstTimeLoading) {
+ //if reload is triggered by /statreload (aka this thread does not have ID number 1)...
+ if (reloadThreadID != 1) {
if (statThread != null && statThread.isAlive()) {
try {
- plugin.getLogger().info("Waiting for statThread to finish up...");
+ MyLogger.waitingForOtherThread(this.getName(), statThread.getName());
statThread.join();
} catch (InterruptedException e) {
plugin.getLogger().warning(e.toString());
@@ -62,7 +70,7 @@ public class ReloadThread extends Thread {
if (config.reloadConfig()) {
try {
- OfflinePlayerHandler.updateOfflinePlayerList(getPlayerMap(false));
+ OfflinePlayerHandler.updateOfflinePlayerList(getPlayerMap());
}
catch (ConcurrentModificationException e) {
plugin.getLogger().warning("The request could not be fully executed due to a ConcurrentModificationException");
@@ -71,7 +79,7 @@ public class ReloadThread extends Thread {
}
}
- plugin.logTimeTaken("ReloadThread", ("loaded " + OfflinePlayerHandler.getOfflinePlayerCount() + " offline players"), time);
+ MyLogger.logTimeTakenDefault("ReloadThread", ("loaded " + OfflinePlayerHandler.getOfflinePlayerCount() + " offline players"), time);
if (sender != null) {
adventure.sender(sender).sendMessage(messageFactory.reloadedConfig(sender instanceof ConsoleCommandSender));
}
@@ -79,26 +87,36 @@ public class ReloadThread extends Thread {
}
//during first start-up...
else {
- OfflinePlayerHandler.updateOfflinePlayerList(getPlayerMap(true));
- plugin.logTimeTaken("ReloadThread", ("loaded " + OfflinePlayerHandler.getOfflinePlayerCount() + " offline players"), time);
+ OfflinePlayerHandler.updateOfflinePlayerList(getPlayerMap());
+ MyLogger.logTimeTakenDefault("ReloadThread", ("loaded " + OfflinePlayerHandler.getOfflinePlayerCount() + " offline players"), time);
ThreadManager.recordCalcTime(System.currentTimeMillis() - time);
}
}
- private ConcurrentHashMap getPlayerMap(boolean firstTimeLoading) {
- OfflinePlayer[] offlinePlayers = Bukkit.getOfflinePlayers();
-
- int size;
- if (firstTimeLoading) {
- size = offlinePlayers.length;
+ private ConcurrentHashMap getPlayerMap() {
+ long time = System.currentTimeMillis();
+ OfflinePlayer[] offlinePlayers;
+ if (config.whitelistOnly()) {
+ offlinePlayers = Bukkit.getWhitelistedPlayers().toArray(OfflinePlayer[]::new);
+ MyLogger.logTimeTaken("ReloadThread", "getting white-list-only list", time);
+ }
+ else if (config.excludeBanned()) {
+ Set bannedPlayers = Bukkit.getBannedPlayers();
+ offlinePlayers = Arrays.stream(Bukkit.getOfflinePlayers())
+ .parallel()
+ .filter(offlinePlayer -> !bannedPlayers.contains(offlinePlayer)).toArray(OfflinePlayer[]::new);
+ MyLogger.logTimeTaken("ReloadThread", "getting excluding-banned-players list", time);
}
else {
- size = OfflinePlayerHandler.getOfflinePlayerCount() != 0 ? OfflinePlayerHandler.getOfflinePlayerCount() : 16;
+ offlinePlayers = Bukkit.getOfflinePlayers();
+ MyLogger.logTimeTaken("ReloadThread", "getting regular player list", time);
}
+ int size = offlinePlayers != null ? offlinePlayers.length : 16;
ConcurrentHashMap playerMap = new ConcurrentHashMap<>(size);
- ReloadAction task = new ReloadAction(threshold, offlinePlayers, config.whitelistOnly(), config.excludeBanned(), config.lastPlayedLimit(), playerMap);
+ ReloadAction task = new ReloadAction(threshold, offlinePlayers, config.lastPlayedLimit(), playerMap);
+ MyLogger.actionCreated((offlinePlayers != null) ? offlinePlayers.length : 0);
ForkJoinPool commonPool = ForkJoinPool.commonPool();
try {
@@ -106,6 +124,8 @@ public class ReloadThread extends Thread {
} catch (ConcurrentModificationException e) {
throw new ConcurrentModificationException(e.toString());
}
+
+ MyLogger.actionFinished(1);
return playerMap;
}
diff --git a/src/main/java/com/gmail/artemis/the/gr8/playerstats/statistic/StatThread.java b/src/main/java/com/gmail/artemis/the/gr8/playerstats/statistic/StatThread.java
index c135eb5..9dfa703 100644
--- a/src/main/java/com/gmail/artemis/the/gr8/playerstats/statistic/StatThread.java
+++ b/src/main/java/com/gmail/artemis/the/gr8/playerstats/statistic/StatThread.java
@@ -5,6 +5,7 @@ import com.gmail.artemis.the.gr8.playerstats.enums.Query;
import com.gmail.artemis.the.gr8.playerstats.reload.ReloadThread;
import com.gmail.artemis.the.gr8.playerstats.ThreadManager;
import com.gmail.artemis.the.gr8.playerstats.config.ConfigHandler;
+import com.gmail.artemis.the.gr8.playerstats.utils.MyLogger;
import com.gmail.artemis.the.gr8.playerstats.utils.OfflinePlayerHandler;
import com.gmail.artemis.the.gr8.playerstats.msg.MessageFactory;
import com.google.common.collect.ImmutableList;
@@ -23,6 +24,7 @@ import java.util.stream.Collectors;
public class StatThread extends Thread {
private final int threshold;
+
private final StatRequest request;
private final ReloadThread reloadThread;
@@ -32,8 +34,9 @@ public class StatThread extends Thread {
private final Main plugin;
//constructor (called on thread creation)
- public StatThread(BukkitAudiences a, ConfigHandler c, MessageFactory m, Main p, int threshold, StatRequest s, @Nullable ReloadThread r) {
+ public StatThread(BukkitAudiences a, ConfigHandler c, MessageFactory m, Main p, int ID, int threshold, StatRequest s, @Nullable ReloadThread r) {
this.threshold = threshold;
+
request = s;
reloadThread = r;
@@ -41,11 +44,16 @@ public class StatThread extends Thread {
config = c;
messageFactory = m;
plugin = p;
+
+ this.setName("StatThread-" + ID);
+ MyLogger.threadCreated(this.getName());
}
//what the thread will do once started
@Override
public void run() throws IllegalStateException, NullPointerException {
+ MyLogger.threadStart(this.getName());
+
if (messageFactory == null || plugin == null) {
throw new IllegalStateException("Not all classes off the plugin are running!");
}
@@ -54,8 +62,10 @@ public class StatThread extends Thread {
}
if (reloadThread != null && reloadThread.isAlive()) {
try {
- plugin.getLogger().info("Waiting for reloadThread to finish up...");
- adventure.sender(request.getCommandSender()).sendMessage(messageFactory.stillReloading(request.getCommandSender() instanceof ConsoleCommandSender));
+ MyLogger.waitingForOtherThread(this.getName(), reloadThread.getName());
+ adventure.sender(request.getCommandSender())
+ .sendMessage(messageFactory
+ .stillReloading(request.getCommandSender() instanceof ConsoleCommandSender));
reloadThread.join();
} catch (InterruptedException e) {
plugin.getLogger().warning(e.toString());
@@ -128,10 +138,11 @@ public class StatThread extends Thread {
int size = OfflinePlayerHandler.getOfflinePlayerCount() != 0 ? (int) (OfflinePlayerHandler.getOfflinePlayerCount() * 1.05) : 16;
ConcurrentHashMap playerStats = new ConcurrentHashMap<>(size);
ImmutableList playerNames = ImmutableList.copyOf(OfflinePlayerHandler.getOfflinePlayerNames());
- TopStatAction task = new TopStatAction(threshold, playerNames,
- request, playerStats);
+ TopStatAction task = new TopStatAction(threshold, playerNames, request, playerStats);
+ MyLogger.actionCreated(playerNames.size());
ForkJoinPool commonPool = ForkJoinPool.commonPool();
+
try {
commonPool.invoke(task);
} catch (ConcurrentModificationException e) {
@@ -140,8 +151,9 @@ public class StatThread extends Thread {
throw new ConcurrentModificationException(e.toString());
}
+ MyLogger.actionFinished(2);
ThreadManager.recordCalcTime(System.currentTimeMillis() - time);
- plugin.logTimeTaken("StatThread", "calculated all stats", time);
+ MyLogger.logTimeTakenDefault("StatThread", "calculated all stats", time);
return playerStats;
}
diff --git a/src/main/java/com/gmail/artemis/the/gr8/playerstats/statistic/TopStatAction.java b/src/main/java/com/gmail/artemis/the/gr8/playerstats/statistic/TopStatAction.java
index 839c6a4..e80cc95 100644
--- a/src/main/java/com/gmail/artemis/the/gr8/playerstats/statistic/TopStatAction.java
+++ b/src/main/java/com/gmail/artemis/the/gr8/playerstats/statistic/TopStatAction.java
@@ -1,5 +1,6 @@
package com.gmail.artemis.the.gr8.playerstats.statistic;
+import com.gmail.artemis.the.gr8.playerstats.utils.MyLogger;
import com.gmail.artemis.the.gr8.playerstats.utils.OfflinePlayerHandler;
import com.google.common.collect.ImmutableList;
import org.bukkit.OfflinePlayer;
@@ -31,6 +32,8 @@ public class TopStatAction extends RecursiveAction {
this.request = statRequest;
this.playerStats = playerStats;
+
+ MyLogger.subActionCreated(Thread.currentThread().getName());
}
@Override
@@ -53,6 +56,7 @@ public class TopStatAction extends RecursiveAction {
if (iterator.hasNext()) {
do {
String playerName = iterator.next();
+ MyLogger.actionRunning(Thread.currentThread().getName(), playerName, 2);
OfflinePlayer player = OfflinePlayerHandler.getOfflinePlayer(playerName);
if (player != null) {
int statistic = 0;
diff --git a/src/main/java/com/gmail/artemis/the/gr8/playerstats/utils/MyLogger.java b/src/main/java/com/gmail/artemis/the/gr8/playerstats/utils/MyLogger.java
new file mode 100644
index 0000000..9ac4de5
--- /dev/null
+++ b/src/main/java/com/gmail/artemis/the/gr8/playerstats/utils/MyLogger.java
@@ -0,0 +1,166 @@
+package com.gmail.artemis.the.gr8.playerstats.utils;
+
+import com.gmail.artemis.the.gr8.playerstats.enums.DebugLevel;
+import org.bukkit.Bukkit;
+import org.bukkit.plugin.Plugin;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.logging.Logger;
+
+public class MyLogger {
+
+ private static final Logger logger;
+ private static DebugLevel debugLevel;
+
+ private static final String[] processedPlayers;
+ private static final AtomicInteger playersIndex;
+ private static ConcurrentHashMap threadNames;
+
+ static{
+ Plugin plugin = Bukkit.getPluginManager().getPlugin("PlayerStats");
+
+ logger = plugin != null ? plugin.getLogger() : Bukkit.getLogger();
+ debugLevel = DebugLevel.LOW;
+
+ processedPlayers = new String[10];
+ playersIndex = new AtomicInteger(0);
+ threadNames = new ConcurrentHashMap<>();
+ }
+
+ private MyLogger() {
+ }
+
+ /** Accesses the playersIndex to up it by 1 and return its previous value. */
+ private static int nextPlayersIndex() {
+ return playersIndex.getAndIncrement();
+ }
+
+ /** Returns true if the playersIndex is 10, or any subsequent increment of 10. */
+ private static boolean incrementOfTen() {
+ return (playersIndex.get() == 10 || (playersIndex.get() > 10 && playersIndex.get() % 10 == 0));
+ }
+
+ /** Sets the desired debugging level.
+ 1 = low (only show unexpected errors)
+ 2 = medium (show all encountered exceptions, log main tasks and show time taken)
+ 3 = high (log all tasks and time taken)
+ Default: 1
*/
+ public static void setDebugLevel(int level) {
+ if (level == 2) {
+ debugLevel = DebugLevel.MEDIUM;
+ }
+ else if (level == 3) {
+ debugLevel = DebugLevel.HIGH;
+ }
+ else {
+ debugLevel = DebugLevel.LOW;
+ }
+ }
+
+ /** Output to console that the given thread has been created (but not started yet).*/
+ public static void threadCreated(String threadName) {
+ if (debugLevel != DebugLevel.LOW) {
+ logger.info(threadName + " created!");
+ }
+ }
+
+ /** Output to console that the given thread has been started. */
+ public static void threadStart(String threadName) {
+ if (debugLevel == DebugLevel.MEDIUM || debugLevel == DebugLevel.HIGH) {
+ logger.info(threadName + " started!");
+ }
+ }
+
+ /** Output to console that another reloadThread is already running. */
+ public static void threadAlreadyRunning(String threadName) {
+ logger.info("Another reloadThread is already running! (" + threadName + ")");
+ }
+
+ /** Output to console that the executingThread is waiting for otherThread to finish up. */
+ public static void waitingForOtherThread(String executingThread, String otherThread) {
+ logger.info(executingThread + ": Waiting for " + otherThread + " to finish up...");
+ }
+
+ /** If DebugLevel is MEDIUM or HIGH, output to console that an action has started.
+ @param taskLength Length of the action (in terms of units-to-process)*/
+ public static void actionCreated(int taskLength) {
+ if (debugLevel != DebugLevel.LOW) {
+ threadNames = new ConcurrentHashMap<>();
+ playersIndex.set(0);
+ logger.info("Initial Action created for " + taskLength + " Players. Start Index is " + playersIndex.get() + ". Processing...");
+ }
+ }
+
+ /** Internally save the name of the executing thread for later logging of this action.
+ The list of names is reset upon the start of every new action.
+ @param threadName Name of the executing thread*/
+ public static void subActionCreated(String threadName) {
+ if (debugLevel == DebugLevel.HIGH) {
+ if (!threadNames.containsKey(threadName)) {
+ threadNames.put(threadName, threadNames.size());
+ }
+ }
+ }
+
+ /** Internally save the name of the executing thread and processed player for logging,
+ and for the ReloadThread, if DebugLevel is HIGH, output the last 10 processed players once
+ there have been 10 names saved in MyLogger. This method is synchronized.
+ @param threadName Name of the executing thread
+ @param playerName Name of the player that was processed in this action
+ @param thread 1 for ReloadThread, 2 for StatThread */
+ public static synchronized void actionRunning(String threadName, String playerName, int thread) {
+ if (debugLevel != DebugLevel.LOW) {
+ if (!threadNames.containsKey(threadName)) {
+ threadNames.put(threadName, threadNames.size());
+ }
+ if (thread == 1 && debugLevel == DebugLevel.HIGH) {
+ if (incrementOfTen()) {
+ logger.info(Arrays.asList(processedPlayers).toString());
+ }
+ processedPlayers[nextPlayersIndex() % 10] = playerName;
+ }
+ else if (debugLevel == DebugLevel.MEDIUM) {
+ nextPlayersIndex();
+ }
+ }
+ }
+
+ /** Output to console that an action has finished.
+ For the ReloadThread, if DebugLevel is HIGH, output the left-over processed players.
+ For both threads, if DebugLevel is MEDIUM or HIGH, output the names of the threads that were used.
+ @param thread 1 for ReloadThread, 2 for StatThread */
+ public static void actionFinished(int thread) {
+ if (thread == 1 && debugLevel == DebugLevel.HIGH) {
+ ArrayList leftOvers = new ArrayList<>(Arrays.asList(processedPlayers).subList(playersIndex.intValue() % 10, 10));
+ logger.info(leftOvers.toString());
+ }
+ if (debugLevel != DebugLevel.LOW) {
+ logger.info("Finished Recursive Action! In total " +
+ threadNames.size() + " Threads were used to process " +
+ playersIndex.get() + " Players: " +
+ Collections.list(threadNames.keys()));
+ }
+ }
+
+ /** Output to console how long a certain task has taken if DebugLevel is MEDIUM or HIGH.
+ @param className Name of the class executing the task
+ @param methodName Name or description of the task
+ @param startTime Timestamp marking the beginning of the task */
+ public static void logTimeTaken(String className, String methodName, long startTime) {
+ if (debugLevel != DebugLevel.LOW) {
+ logger.info(className + " " + methodName + ": " + (System.currentTimeMillis() - startTime) + "ms");
+ }
+ }
+
+ /** Output to console how long a certain task has taken (regardless of DebugLevel).
+ @param className Name of the class executing the task
+ @param methodName Name or description of the task
+ @param startTime Timestamp marking the beginning of the task */
+ public static void logTimeTakenDefault(String className, String methodName, long startTime) {
+ logger.info(className + " " + methodName + ":" + (System.currentTimeMillis() - startTime) + "ms");
+ }
+}
diff --git a/src/main/java/com/gmail/artemis/the/gr8/playerstats/utils/OfflinePlayerHandler.java b/src/main/java/com/gmail/artemis/the/gr8/playerstats/utils/OfflinePlayerHandler.java
index 09a7748..168dc93 100644
--- a/src/main/java/com/gmail/artemis/the/gr8/playerstats/utils/OfflinePlayerHandler.java
+++ b/src/main/java/com/gmail/artemis/the/gr8/playerstats/utils/OfflinePlayerHandler.java
@@ -12,18 +12,23 @@ public class OfflinePlayerHandler {
private static ConcurrentHashMap offlinePlayerUUIDs;
private static ArrayList playerNames;
+ static{
+ offlinePlayerUUIDs = new ConcurrentHashMap<>();
+ playerNames = new ArrayList<>();
+ }
+
private OfflinePlayerHandler() {
}
/** Checks if a given playerName is on the private HashMap of players that should be included in statistic calculations
@param playerName String, case-sensitive */
- public static boolean isOfflinePlayerName(String playerName) {
+ public static boolean isRelevantPlayer(String playerName) {
return offlinePlayerUUIDs.containsKey(playerName);
}
/** Returns the number of OfflinePlayers that are included in statistic calculations */
public static int getOfflinePlayerCount() {
- return offlinePlayerUUIDs != null ? offlinePlayerUUIDs.size() : 0;
+ return offlinePlayerUUIDs.size();
}
/** Get an ArrayList of names from all OfflinePlayers that should be included in statistic calculations */
diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml
index 4a4724d..6c88a0b 100644
--- a/src/main/resources/config.yml
+++ b/src/main/resources/config.yml
@@ -8,6 +8,12 @@ config-version: 3.1
# # General # #
# # ------------------------------- # #
+# How much output in console you'll get while PlayerStats is processing
+# 1 = low (only show unexpected errors)
+# 2 = medium (show all encountered exceptions, log main tasks and show time taken)
+# 3 = high (log all tasks and time taken)
+debug-level: 1
+
# Filtering options to control which players should be included in statistic calculations
include-whitelist-only: false
exclude-banned-players: false