diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e06f9d5..3f5c7b6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -67,6 +67,15 @@ jobs: retention-days: 14 # Keep artifacts for 14 days if-no-files-found: error # Fail the workflow if no JARs are found + # Upload BungeeCord JAR as an artifact + - name: Upload BungeeCord JAR Artifact + uses: actions/upload-artifact@v4 + with: + name: serverpulse-bungeecord-jar + path: bungeecord/build/libs/serverpulse-*.jar + retention-days: 14 + if-no-files-found: error # Fail the workflow if no JARs are found + # --- Infrastructure Testing --- # 4. Install jq (needed for parsing InfluxDB health check JSON) diff --git a/api/src/main/java/it/renvins/serverpulse/api/data/AsyncMetricsSnapshot.java b/api/src/main/java/it/renvins/serverpulse/api/data/AsyncMetricsSnapshot.java index 898a8b8..cf91f84 100644 --- a/api/src/main/java/it/renvins/serverpulse/api/data/AsyncMetricsSnapshot.java +++ b/api/src/main/java/it/renvins/serverpulse/api/data/AsyncMetricsSnapshot.java @@ -1,5 +1,6 @@ package it.renvins.serverpulse.api.data; + public class AsyncMetricsSnapshot { private final long usedHeap; @@ -25,30 +26,65 @@ public AsyncMetricsSnapshot(long usedHeap, long commitedHeap, long totalDisk, lo this.avgPing = avgPing; } + /** + * Gets the amount of used heap memory in bytes. + * + * @return the used heap memory + */ public long getUsedHeap() { return usedHeap; } + /** + * Gets the amount of committed heap memory in bytes. + * + * @return the committed heap memory + */ public long getCommitedHeap() { return commitedHeap; } + /** + * Gets the total disk space available in bytes. + * + * @return the total disk space + */ public long getTotalDisk() { return totalDisk; } + /** + * Gets the usable disk space available in bytes. + * + * @return the usable disk space + */ public long getUsableDisk() { return usableDisk; } + /** + * Gets the minimum ping recorded in milliseconds. + * + * @return the minimum ping + */ public long getMinPing() { return minPing; } + /** + * Gets the maximum ping recorded in milliseconds. + * + * @return the maximum ping + */ public long getMaxPing() { return maxPing; } + /** + * Gets the average ping recorded in milliseconds. + * + * @return the average ping + */ public long getAvgPing() { return avgPing; } diff --git a/api/src/main/java/it/renvins/serverpulse/api/data/SyncMetricsSnapshot.java b/api/src/main/java/it/renvins/serverpulse/api/data/SyncMetricsSnapshot.java index 0705dc3..e784ade 100644 --- a/api/src/main/java/it/renvins/serverpulse/api/data/SyncMetricsSnapshot.java +++ b/api/src/main/java/it/renvins/serverpulse/api/data/SyncMetricsSnapshot.java @@ -2,7 +2,6 @@ import java.util.Map; - public class SyncMetricsSnapshot { private final double[] tps; diff --git a/build.gradle.kts b/build.gradle.kts index 4340748..74b24dd 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,5 +1,5 @@ group = "it.renvins" -version = "0.4.2-SNAPSHOT" +version = "0.4.5-SNAPSHOT" repositories { mavenCentral() diff --git a/bukkit/build.gradle.kts b/bukkit/build.gradle.kts index 888d651..919ade5 100644 --- a/bukkit/build.gradle.kts +++ b/bukkit/build.gradle.kts @@ -14,6 +14,7 @@ repositories { name = "papermc" url = uri("https://repo.papermc.io/repository/maven-public/") } + maven { url = uri("https://jitpack.io") } } dependencies { @@ -21,6 +22,7 @@ dependencies { implementation(project(":common")) compileOnly("io.papermc.paper:paper-api:1.21.7-R0.1-SNAPSHOT") + compileOnly("com.github.Carleslc.Simple-YAML:Simple-Yaml:1.8.4") } java { @@ -31,6 +33,9 @@ tasks.withType { archiveBaseName = "serverpulse" archiveClassifier = "bukkit" archiveVersion = "${rootProject.version}" + duplicatesStrategy = DuplicatesStrategy.EXCLUDE + + minimize() } tasks.withType { diff --git a/bukkit/src/main/java/it/renvins/serverpulse/bukkit/ServerPulseBukkitLoader.java b/bukkit/src/main/java/it/renvins/serverpulse/bukkit/ServerPulseBukkitLoader.java index 337c7a6..d8960e5 100644 --- a/bukkit/src/main/java/it/renvins/serverpulse/bukkit/ServerPulseBukkitLoader.java +++ b/bukkit/src/main/java/it/renvins/serverpulse/bukkit/ServerPulseBukkitLoader.java @@ -12,14 +12,10 @@ import it.renvins.serverpulse.bukkit.logger.BukkitLogger; import it.renvins.serverpulse.bukkit.metrics.BukkitTPSRetriever; import it.renvins.serverpulse.common.DatabaseService; -import it.renvins.serverpulse.common.config.DatabaseConfiguration; -import it.renvins.serverpulse.common.config.MetricsConfiguration; +import it.renvins.serverpulse.common.config.GeneralConfiguration; import it.renvins.serverpulse.bukkit.commands.ServerPulseCommand; -import it.renvins.serverpulse.bukkit.config.BukkitConfiguration; import it.renvins.serverpulse.common.logger.PulseLogger; import it.renvins.serverpulse.common.disk.DiskRetriever; -import it.renvins.serverpulse.bukkit.config.BukkitDatabaseConfiguration; -import it.renvins.serverpulse.bukkit.config.BukkitMetricsConfiguration; import it.renvins.serverpulse.bukkit.metrics.BukkitPingRetriever; import it.renvins.serverpulse.bukkit.metrics.PaperTPSRetriever; import it.renvins.serverpulse.bukkit.platform.BukkitPlatform; @@ -35,7 +31,7 @@ public class ServerPulseBukkitLoader implements Service { private final ServerPulseBukkit plugin; public static Logger LOGGER; - private final BukkitConfiguration config; + private final GeneralConfiguration config; private final Platform platform; @@ -51,17 +47,14 @@ public ServerPulseBukkitLoader(ServerPulseBukkit plugin) { this.plugin = plugin; LOGGER = plugin.getLogger(); - this.config = new BukkitConfiguration(plugin, "config.yml"); - PulseLogger logger = new BukkitLogger(LOGGER); + this.config = new GeneralConfiguration(logger, plugin.getDataFolder(), "config.yml"); + this.platform = new BukkitPlatform(plugin); TaskScheduler taskScheduler = new BukkitTaskScheduler(plugin); - DatabaseConfiguration databaseConfiguration = new BukkitDatabaseConfiguration(config); - MetricsConfiguration metricsConfiguration = new BukkitMetricsConfiguration(config); - - this.databaseService = new DatabaseService(logger, platform, databaseConfiguration, taskScheduler); + this.databaseService = new DatabaseService(logger, platform, config, taskScheduler); if (isPaper()) { this.tpsRetriever = new PaperTPSRetriever(); @@ -72,7 +65,7 @@ public ServerPulseBukkitLoader(ServerPulseBukkit plugin) { this.pingRetriever = new BukkitPingRetriever(); MetricsCollector collector = new MetricsCollector(logger, platform, tpsRetriever, diskRetriever, pingRetriever); - LineProtocolFormatter formatter = new LineProtocolFormatter(metricsConfiguration); + LineProtocolFormatter formatter = new LineProtocolFormatter(config); this.metricsService = new MetricsService(logger, collector, formatter, taskScheduler, databaseService); diff --git a/bukkit/src/main/java/it/renvins/serverpulse/bukkit/commands/ReloadCommand.java b/bukkit/src/main/java/it/renvins/serverpulse/bukkit/commands/ReloadCommand.java index 9768a39..4b5487a 100644 --- a/bukkit/src/main/java/it/renvins/serverpulse/bukkit/commands/ReloadCommand.java +++ b/bukkit/src/main/java/it/renvins/serverpulse/bukkit/commands/ReloadCommand.java @@ -1,14 +1,14 @@ package it.renvins.serverpulse.bukkit.commands; +import it.renvins.serverpulse.common.config.GeneralConfiguration; import it.renvins.serverpulse.common.utils.ChatUtils; -import it.renvins.serverpulse.bukkit.config.BukkitConfiguration; import org.bukkit.command.CommandSender; public class ReloadCommand extends GeneralCommand { - private final BukkitConfiguration config; + private final GeneralConfiguration config; - public ReloadCommand(String permission, boolean isPlayerOnly, BukkitConfiguration config) { + public ReloadCommand(String permission, boolean isPlayerOnly, GeneralConfiguration config) { super(permission, isPlayerOnly); this.config = config; } @@ -19,7 +19,7 @@ public void run(CommandSender sender, String[] args) { sender.sendMessage(ChatUtils.format(config.getConfig().getString("messages.reloadConfigUsage"))); return; } - if (!config.reload()) { + if (!config.load()) { sender.sendMessage(ChatUtils.format(config.getConfig().getString("messages.reloadConfigError"))); } else { sender.sendMessage(ChatUtils.format(config.getConfig().getString("messages.reloadConfig"))); diff --git a/bukkit/src/main/java/it/renvins/serverpulse/bukkit/commands/ServerPulseCommand.java b/bukkit/src/main/java/it/renvins/serverpulse/bukkit/commands/ServerPulseCommand.java index 7b261e6..438a5f1 100644 --- a/bukkit/src/main/java/it/renvins/serverpulse/bukkit/commands/ServerPulseCommand.java +++ b/bukkit/src/main/java/it/renvins/serverpulse/bukkit/commands/ServerPulseCommand.java @@ -3,8 +3,8 @@ import java.util.HashMap; import java.util.Map; +import it.renvins.serverpulse.common.config.GeneralConfiguration; import it.renvins.serverpulse.common.utils.ChatUtils; -import it.renvins.serverpulse.bukkit.config.BukkitConfiguration; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; @@ -12,10 +12,10 @@ public class ServerPulseCommand implements CommandExecutor { - private final BukkitConfiguration config; + private final GeneralConfiguration config; private final Map commands = new HashMap<>(); - public ServerPulseCommand(BukkitConfiguration config) { + public ServerPulseCommand(GeneralConfiguration config) { this.config = config; registerCommands(); } diff --git a/bukkit/src/main/java/it/renvins/serverpulse/bukkit/commands/StatusCommand.java b/bukkit/src/main/java/it/renvins/serverpulse/bukkit/commands/StatusCommand.java index 1ac2761..14f8b0f 100644 --- a/bukkit/src/main/java/it/renvins/serverpulse/bukkit/commands/StatusCommand.java +++ b/bukkit/src/main/java/it/renvins/serverpulse/bukkit/commands/StatusCommand.java @@ -1,15 +1,15 @@ package it.renvins.serverpulse.bukkit.commands; import it.renvins.serverpulse.api.ServerPulseProvider; +import it.renvins.serverpulse.common.config.GeneralConfiguration; import it.renvins.serverpulse.common.utils.ChatUtils; -import it.renvins.serverpulse.bukkit.config.BukkitConfiguration; import org.bukkit.command.CommandSender; public class StatusCommand extends GeneralCommand { - private final BukkitConfiguration config; + private final GeneralConfiguration config; - public StatusCommand(String permission, boolean isPlayerOnly, BukkitConfiguration config) { + public StatusCommand(String permission, boolean isPlayerOnly, GeneralConfiguration config) { super(permission, isPlayerOnly); this.config = config; diff --git a/bukkit/src/main/java/it/renvins/serverpulse/bukkit/config/BukkitConfiguration.java b/bukkit/src/main/java/it/renvins/serverpulse/bukkit/config/BukkitConfiguration.java deleted file mode 100644 index 42e6126..0000000 --- a/bukkit/src/main/java/it/renvins/serverpulse/bukkit/config/BukkitConfiguration.java +++ /dev/null @@ -1,52 +0,0 @@ -package it.renvins.serverpulse.bukkit.config; - -import java.io.File; -import java.util.logging.Level; - -import it.renvins.serverpulse.bukkit.ServerPulseBukkitLoader; -import it.renvins.serverpulse.bukkit.ServerPulseBukkit; -import lombok.Getter; -import org.bukkit.configuration.file.YamlConfiguration; - -public class BukkitConfiguration { - - private final ServerPulseBukkit plugin; - private final String name; - - private File file; - @Getter private YamlConfiguration config; - - public BukkitConfiguration(ServerPulseBukkit plugin, String name) { - this.plugin = plugin; - this.name = name; - } - - public void load() { - if (!plugin.getDataFolder().exists()) { - plugin.getDataFolder().mkdir(); - } - file = new File(plugin.getDataFolder(), name); - if (!file.exists()) { - plugin.saveResource(name, false); - } - config = YamlConfiguration.loadConfiguration(file); - } - - public void save() { - try { - config.save(file); - } catch (Exception e) { - ServerPulseBukkitLoader.LOGGER.log(Level.SEVERE, "Could not save " + name + " file", e); - } - } - - public boolean reload() { - if (file == null) { - ServerPulseBukkitLoader.LOGGER.log(Level.SEVERE, "File is null, cannot reload configuration."); - return false; - } - config = YamlConfiguration.loadConfiguration(file); - return true; - } - -} diff --git a/bukkit/src/main/java/it/renvins/serverpulse/bukkit/config/BukkitDatabaseConfiguration.java b/bukkit/src/main/java/it/renvins/serverpulse/bukkit/config/BukkitDatabaseConfiguration.java deleted file mode 100644 index 04d19a2..0000000 --- a/bukkit/src/main/java/it/renvins/serverpulse/bukkit/config/BukkitDatabaseConfiguration.java +++ /dev/null @@ -1,30 +0,0 @@ -package it.renvins.serverpulse.bukkit.config; - -import it.renvins.serverpulse.common.config.DatabaseConfiguration; -import lombok.RequiredArgsConstructor; - -@RequiredArgsConstructor -public class BukkitDatabaseConfiguration implements DatabaseConfiguration { - - private final BukkitConfiguration configuration; - - @Override - public String getHost() { - return configuration.getConfig().getString("metrics.influxdb.url"); - } - - @Override - public String getOrg() { - return configuration.getConfig().getString("metrics.influxdb.org"); - } - - @Override - public String getToken() { - return configuration.getConfig().getString("metrics.influxdb.token"); - } - - @Override - public String getBucket() { - return configuration.getConfig().getString("metrics.influxdb.bucket"); - } -} diff --git a/bukkit/src/main/java/it/renvins/serverpulse/bukkit/config/BukkitMetricsConfiguration.java b/bukkit/src/main/java/it/renvins/serverpulse/bukkit/config/BukkitMetricsConfiguration.java deleted file mode 100644 index cc865a9..0000000 --- a/bukkit/src/main/java/it/renvins/serverpulse/bukkit/config/BukkitMetricsConfiguration.java +++ /dev/null @@ -1,40 +0,0 @@ -package it.renvins.serverpulse.bukkit.config; - -import java.util.HashMap; -import java.util.Map; - -import it.renvins.serverpulse.common.config.MetricsConfiguration; -import lombok.RequiredArgsConstructor; - -@RequiredArgsConstructor -public class BukkitMetricsConfiguration implements MetricsConfiguration { - - private final BukkitConfiguration configuration; - - @Override - public String getServerTag() { - return configuration.getConfig().getString("metrics.tags.server"); - } - - @Override - public String getMeasurementTable() { - return configuration.getConfig().getString("metrics.influxdb.table"); - } - - @Override - public long getMetricsInterval() { - return configuration.getConfig().getLong("metrics.interval"); - } - - @Override - public Map getTags() { - Map tags = configuration.getConfig().getConfigurationSection("metrics.tags").getValues(false); - Map stringTags = new HashMap<>(); - tags.forEach((key, value) -> { - if (value instanceof String && !key.equalsIgnoreCase("server") && !key.equalsIgnoreCase("world")) { - stringTags.put(key, (String) value); - } - }); - return stringTags; - } -} diff --git a/bungeecord/build.gradle.kts b/bungeecord/build.gradle.kts index 3d83669..3af463d 100644 --- a/bungeecord/build.gradle.kts +++ b/bungeecord/build.gradle.kts @@ -18,6 +18,9 @@ repositories { name = "mojang" url = uri("https://libraries.minecraft.net/") } + maven { + url = uri("https://jitpack.io") + } } dependencies { @@ -25,6 +28,7 @@ dependencies { implementation(project(":common")) compileOnly("net.md-5:bungeecord-api:1.21-R0.4-SNAPSHOT") + compileOnly("com.github.Carleslc.Simple-YAML:Simple-Yaml:1.8.4") } java { @@ -35,6 +39,9 @@ tasks.withType { archiveBaseName = "serverpulse" archiveClassifier = "bungeecord" archiveVersion = "${rootProject.version}" + duplicatesStrategy = DuplicatesStrategy.EXCLUDE + + minimize() } tasks.withType { diff --git a/bungeecord/src/main/java/it/renvins/serverpulse/bungeecord/ServerPulseBungeeCordLoader.java b/bungeecord/src/main/java/it/renvins/serverpulse/bungeecord/ServerPulseBungeeCordLoader.java index 1372152..7646e1d 100644 --- a/bungeecord/src/main/java/it/renvins/serverpulse/bungeecord/ServerPulseBungeeCordLoader.java +++ b/bungeecord/src/main/java/it/renvins/serverpulse/bungeecord/ServerPulseBungeeCordLoader.java @@ -8,17 +8,13 @@ import it.renvins.serverpulse.api.service.IMetricsService; import it.renvins.serverpulse.api.service.Service; import it.renvins.serverpulse.bungeecord.commands.ServerPulseCommand; -import it.renvins.serverpulse.bungeecord.config.BungeeCordConfiguration; -import it.renvins.serverpulse.bungeecord.config.BungeeCordDatabaseConfiguration; -import it.renvins.serverpulse.bungeecord.config.BungeeCordMetricsConfiguration; import it.renvins.serverpulse.bungeecord.logger.BungeeCordLogger; import it.renvins.serverpulse.bungeecord.metrics.BungeeCordPingRetriever; import it.renvins.serverpulse.bungeecord.platform.BungeeCordPlatform; import it.renvins.serverpulse.bungeecord.scheduler.BungeeCordTaskScheduler; import it.renvins.serverpulse.common.DatabaseService; import it.renvins.serverpulse.common.MetricsService; -import it.renvins.serverpulse.common.config.DatabaseConfiguration; -import it.renvins.serverpulse.common.config.MetricsConfiguration; +import it.renvins.serverpulse.common.config.GeneralConfiguration; import it.renvins.serverpulse.common.logger.PulseLogger; import it.renvins.serverpulse.common.disk.DiskRetriever; import it.renvins.serverpulse.common.metrics.LineProtocolFormatter; @@ -35,7 +31,7 @@ public class ServerPulseBungeeCordLoader implements Service { private final ServerPulseBungeeCord plugin; public static Logger LOGGER; - private final BungeeCordConfiguration config; + private final GeneralConfiguration config; private final Platform platform; private final IDatabaseService databaseService; @@ -49,16 +45,14 @@ public ServerPulseBungeeCordLoader(ServerPulseBungeeCord plugin) { this.plugin = plugin; LOGGER = plugin.getLogger(); - this.config = new BungeeCordConfiguration(plugin, "config.yml"); + PulseLogger pulseLogger = new BungeeCordLogger(plugin); + + this.config = new GeneralConfiguration(pulseLogger, plugin.getDataFolder(), "config.yml"); this.platform = new BungeeCordPlatform(plugin); - PulseLogger pulseLogger = new BungeeCordLogger(plugin); TaskScheduler scheduler = new BungeeCordTaskScheduler(plugin); - DatabaseConfiguration dbConfig = new BungeeCordDatabaseConfiguration(config); - MetricsConfiguration metricsConfig = new BungeeCordMetricsConfiguration(config); - - this.databaseService = new DatabaseService(pulseLogger, platform, dbConfig, scheduler); + this.databaseService = new DatabaseService(pulseLogger, platform, config, scheduler); this.diskRetriever = new DiskRetriever(plugin.getDataFolder()); this.pingRetriever =new BungeeCordPingRetriever(plugin); @@ -66,7 +60,7 @@ public ServerPulseBungeeCordLoader(ServerPulseBungeeCord plugin) { ITPSRetriever tpsRetriever = new UnsupportedTPSRetriever(); MetricsCollector collector = new MetricsCollector(pulseLogger, platform, tpsRetriever, diskRetriever, pingRetriever); - LineProtocolFormatter formatter = new LineProtocolFormatter(metricsConfig); + LineProtocolFormatter formatter = new LineProtocolFormatter(config); this.metricsService = new MetricsService(pulseLogger, collector, formatter, scheduler, databaseService); diff --git a/bungeecord/src/main/java/it/renvins/serverpulse/bungeecord/commands/ReloadCommand.java b/bungeecord/src/main/java/it/renvins/serverpulse/bungeecord/commands/ReloadCommand.java index c389504..0f1199d 100644 --- a/bungeecord/src/main/java/it/renvins/serverpulse/bungeecord/commands/ReloadCommand.java +++ b/bungeecord/src/main/java/it/renvins/serverpulse/bungeecord/commands/ReloadCommand.java @@ -1,15 +1,15 @@ package it.renvins.serverpulse.bungeecord.commands; +import it.renvins.serverpulse.common.config.GeneralConfiguration; import it.renvins.serverpulse.common.utils.ChatUtils; -import it.renvins.serverpulse.bungeecord.config.BungeeCordConfiguration; import net.md_5.bungee.api.CommandSender; import net.md_5.bungee.api.chat.TextComponent; public class ReloadCommand extends GeneralCommand { - private final BungeeCordConfiguration config; + private final GeneralConfiguration config; - public ReloadCommand(String permission, boolean isPlayerOnly, BungeeCordConfiguration config) { + public ReloadCommand(String permission, boolean isPlayerOnly, GeneralConfiguration config) { super(permission, isPlayerOnly); this.config = config; } @@ -20,7 +20,7 @@ public void run(CommandSender sender, String[] args) { sender.sendMessage(new TextComponent(ChatUtils.format(config.getConfig().getString("messages.reloadConfigUsage")))); return; } - if (!config.reload()) { + if (!config.load()) { sender.sendMessage(new TextComponent(ChatUtils.format(config.getConfig().getString("messages.reloadConfigError")))); } else { sender.sendMessage(new TextComponent(ChatUtils.format(config.getConfig().getString("messages.reloadConfig")))); diff --git a/bungeecord/src/main/java/it/renvins/serverpulse/bungeecord/commands/ServerPulseCommand.java b/bungeecord/src/main/java/it/renvins/serverpulse/bungeecord/commands/ServerPulseCommand.java index 876204e..b555c2b 100644 --- a/bungeecord/src/main/java/it/renvins/serverpulse/bungeecord/commands/ServerPulseCommand.java +++ b/bungeecord/src/main/java/it/renvins/serverpulse/bungeecord/commands/ServerPulseCommand.java @@ -3,8 +3,8 @@ import java.util.HashMap; import java.util.Map; +import it.renvins.serverpulse.common.config.GeneralConfiguration; import it.renvins.serverpulse.common.utils.ChatUtils; -import it.renvins.serverpulse.bungeecord.config.BungeeCordConfiguration; import net.md_5.bungee.api.CommandSender; import net.md_5.bungee.api.chat.TextComponent; import net.md_5.bungee.api.connection.ProxiedPlayer; @@ -12,11 +12,12 @@ public class ServerPulseCommand extends Command { - private final BungeeCordConfiguration config; + private final GeneralConfiguration config; private final Map commands = new HashMap<>(); - public ServerPulseCommand(BungeeCordConfiguration config) { + public ServerPulseCommand(GeneralConfiguration config) { super("serverpulsebungeecord", "serverpulse.use", "sp", "spb"); + this.config = config; registerCommands(); } diff --git a/bungeecord/src/main/java/it/renvins/serverpulse/bungeecord/commands/StatusCommand.java b/bungeecord/src/main/java/it/renvins/serverpulse/bungeecord/commands/StatusCommand.java index 9896b5b..01aa2fd 100644 --- a/bungeecord/src/main/java/it/renvins/serverpulse/bungeecord/commands/StatusCommand.java +++ b/bungeecord/src/main/java/it/renvins/serverpulse/bungeecord/commands/StatusCommand.java @@ -1,16 +1,16 @@ package it.renvins.serverpulse.bungeecord.commands; import it.renvins.serverpulse.api.ServerPulseProvider; +import it.renvins.serverpulse.common.config.GeneralConfiguration; import it.renvins.serverpulse.common.utils.ChatUtils; -import it.renvins.serverpulse.bungeecord.config.BungeeCordConfiguration; import net.md_5.bungee.api.CommandSender; import net.md_5.bungee.api.chat.TextComponent; public class StatusCommand extends GeneralCommand { - private final BungeeCordConfiguration config; + private final GeneralConfiguration config; - public StatusCommand(String permission, boolean isPlayerOnly, BungeeCordConfiguration config) { + public StatusCommand(String permission, boolean isPlayerOnly, GeneralConfiguration config) { super(permission, isPlayerOnly); this.config = config; } diff --git a/bungeecord/src/main/java/it/renvins/serverpulse/bungeecord/config/BungeeCordConfiguration.java b/bungeecord/src/main/java/it/renvins/serverpulse/bungeecord/config/BungeeCordConfiguration.java deleted file mode 100644 index af937aa..0000000 --- a/bungeecord/src/main/java/it/renvins/serverpulse/bungeecord/config/BungeeCordConfiguration.java +++ /dev/null @@ -1,70 +0,0 @@ -package it.renvins.serverpulse.bungeecord.config; - -import it.renvins.serverpulse.bungeecord.ServerPulseBungeeCord; -import lombok.Getter; -import net.md_5.bungee.config.Configuration; -import net.md_5.bungee.config.ConfigurationProvider; -import net.md_5.bungee.config.YamlConfiguration; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.util.logging.Level; - -public class BungeeCordConfiguration { - - private final ServerPulseBungeeCord plugin; - private final String name; - - private File file; - @Getter private Configuration config; - - public BungeeCordConfiguration(ServerPulseBungeeCord plugin, String name) { - this.plugin = plugin; - this.name = name; - } - - public void load() { - if (!plugin.getDataFolder().exists()) { - plugin.getDataFolder().mkdir(); - } - - file = new File(plugin.getDataFolder(), name); - - if (!file.exists()) { - // Copy default config from resources - try (InputStream is = plugin.getResourceAsStream(name)) { - is.transferTo(java.nio.file.Files.newOutputStream(file.toPath())); - plugin.getLogger().info("Created default configuration file: " + name); - } catch (Exception e) { - plugin.getLogger().log(Level.SEVERE, "Failed to copy default config", e); - } - } - try { - config = ConfigurationProvider.getProvider(YamlConfiguration.class).load(file); - } catch (IOException e) { - plugin.getLogger().log(Level.SEVERE, "Failed to load config: " + name, e); - } - } - - public void save() { - if (file == null || config == null) { - return; - } - try { - ConfigurationProvider.getProvider(YamlConfiguration.class).save(config, file); - } catch (IOException e) { - plugin.getLogger().log(Level.SEVERE, "Failed to save config!", e); - } - } - - public boolean reload() { - try { - config = ConfigurationProvider.getProvider(YamlConfiguration.class).load(file); - return true; - } catch (IOException e) { - plugin.getLogger().log(Level.SEVERE, "Failed to reload config: " + name, e); - return false; - } - } -} diff --git a/bungeecord/src/main/java/it/renvins/serverpulse/bungeecord/config/BungeeCordDatabaseConfiguration.java b/bungeecord/src/main/java/it/renvins/serverpulse/bungeecord/config/BungeeCordDatabaseConfiguration.java deleted file mode 100644 index 00a8bd6..0000000 --- a/bungeecord/src/main/java/it/renvins/serverpulse/bungeecord/config/BungeeCordDatabaseConfiguration.java +++ /dev/null @@ -1,30 +0,0 @@ -package it.renvins.serverpulse.bungeecord.config; - -import it.renvins.serverpulse.common.config.DatabaseConfiguration; -import lombok.RequiredArgsConstructor; - -@RequiredArgsConstructor -public class BungeeCordDatabaseConfiguration implements DatabaseConfiguration { - - private final BungeeCordConfiguration configuration; - - @Override - public String getHost() { - return configuration.getConfig().getString("metrics.influxdb.url"); - } - - @Override - public String getOrg() { - return configuration.getConfig().getString("metrics.influxdb.org"); - } - - @Override - public String getToken() { - return configuration.getConfig().getString("metrics.influxdb.token"); - } - - @Override - public String getBucket() { - return configuration.getConfig().getString("metrics.influxdb.bucket"); - } -} diff --git a/bungeecord/src/main/java/it/renvins/serverpulse/bungeecord/config/BungeeCordMetricsConfiguration.java b/bungeecord/src/main/java/it/renvins/serverpulse/bungeecord/config/BungeeCordMetricsConfiguration.java deleted file mode 100644 index d90ab7c..0000000 --- a/bungeecord/src/main/java/it/renvins/serverpulse/bungeecord/config/BungeeCordMetricsConfiguration.java +++ /dev/null @@ -1,44 +0,0 @@ -package it.renvins.serverpulse.bungeecord.config; - -import it.renvins.serverpulse.common.config.MetricsConfiguration; -import lombok.RequiredArgsConstructor; -import net.md_5.bungee.config.Configuration; - -import java.util.HashMap; -import java.util.Map; - -@RequiredArgsConstructor -public class BungeeCordMetricsConfiguration implements MetricsConfiguration { - - private final BungeeCordConfiguration configuration; - - @Override - public String getServerTag() { - return configuration.getConfig().getString("metrics.tags.server"); - } - - @Override - public String getMeasurementTable() { - return configuration.getConfig().getString("metrics.influxdb.table"); - } - - @Override - public long getMetricsInterval() { - return configuration.getConfig().getLong("metrics.interval"); - } - - @Override - public Map getTags() { - Map stringTags = new HashMap<>(); - Configuration tagsSection = configuration.getConfig().getSection("metrics.tags"); - if (tagsSection != null) { - for (String key : tagsSection.getKeys()) { - Object value = tagsSection.get(key); - if (value instanceof String && !key.equalsIgnoreCase("server") && !key.equalsIgnoreCase("world")) { - stringTags.put(key, (String) value); - } - } - } - return stringTags; - } -} diff --git a/common/build.gradle.kts b/common/build.gradle.kts index c2a118a..3aae09a 100644 --- a/common/build.gradle.kts +++ b/common/build.gradle.kts @@ -1,6 +1,8 @@ +import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar + plugins { id("java") - id("java-library") + id("com.gradleup.shadow") version "9.0.0-beta11" id("io.freefair.lombok") version "8.13.1" } group = "it.renvins" @@ -11,8 +13,19 @@ java { repositories { mavenCentral() + maven { + url = uri("https://jitpack.io") + } } dependencies { implementation(project(":api")) + implementation("com.github.Carleslc.Simple-YAML:Simple-Yaml:1.8.4") +} + +tasks.withType() { + archiveBaseName = "serverpulse" + archiveClassifier = "common" + archiveVersion = "${rootProject.version}" + minimize() } \ No newline at end of file diff --git a/common/src/main/java/it/renvins/serverpulse/common/DatabaseService.java b/common/src/main/java/it/renvins/serverpulse/common/DatabaseService.java index 025401a..5dc25fa 100644 --- a/common/src/main/java/it/renvins/serverpulse/common/DatabaseService.java +++ b/common/src/main/java/it/renvins/serverpulse/common/DatabaseService.java @@ -10,6 +10,7 @@ import it.renvins.serverpulse.api.service.IDatabaseService; import it.renvins.serverpulse.common.config.DatabaseConfiguration; +import it.renvins.serverpulse.common.config.GeneralConfiguration; import it.renvins.serverpulse.common.logger.PulseLogger; import it.renvins.serverpulse.common.platform.Platform; import it.renvins.serverpulse.common.scheduler.Task; @@ -38,11 +39,11 @@ public class DatabaseService implements IDatabaseService { private String pingUrl; private String writeUrl; - public DatabaseService(PulseLogger logger, Platform platform, DatabaseConfiguration configuration, TaskScheduler scheduler) { + public DatabaseService(PulseLogger logger, Platform platform, GeneralConfiguration generalConfig, TaskScheduler scheduler) { this.logger = logger; this.platform = platform; - this.configuration = configuration; + this.configuration = new DatabaseConfiguration(generalConfig); this.scheduler = scheduler; this.httpClient = HttpClient.newBuilder() @@ -133,7 +134,7 @@ public boolean ping() { HttpResponse response = httpClient.send(request, HttpResponse.BodyHandlers.discarding()); return response.statusCode() == 204; } catch (Exception e) { - logger.warning("InfluxDB ping failed: " + e.getMessage()); + logger.error("InfluxDB ping failed", e); return false; } } diff --git a/common/src/main/java/it/renvins/serverpulse/common/MetricsService.java b/common/src/main/java/it/renvins/serverpulse/common/MetricsService.java index 896414a..d496522 100644 --- a/common/src/main/java/it/renvins/serverpulse/common/MetricsService.java +++ b/common/src/main/java/it/renvins/serverpulse/common/MetricsService.java @@ -1,24 +1,15 @@ package it.renvins.serverpulse.common; -import java.time.Instant; -import java.util.ArrayList; import java.util.List; -import java.util.Map; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executor; -import it.renvins.serverpulse.api.ServerPulseProvider; import it.renvins.serverpulse.api.data.AsyncMetricsSnapshot; -import it.renvins.serverpulse.api.data.LineProtocolPoint; import it.renvins.serverpulse.api.service.IDatabaseService; -import it.renvins.serverpulse.api.utils.MemoryUtils; import it.renvins.serverpulse.api.data.SyncMetricsSnapshot; -import it.renvins.serverpulse.api.data.WorldData; import it.renvins.serverpulse.api.service.IMetricsService; -import it.renvins.serverpulse.common.config.MetricsConfiguration; import it.renvins.serverpulse.common.logger.PulseLogger; import it.renvins.serverpulse.common.metrics.LineProtocolFormatter; import it.renvins.serverpulse.common.metrics.MetricsCollector; -import it.renvins.serverpulse.common.platform.Platform; import it.renvins.serverpulse.common.scheduler.TaskScheduler; public class MetricsService implements IMetricsService { diff --git a/common/src/main/java/it/renvins/serverpulse/common/config/DatabaseConfiguration.java b/common/src/main/java/it/renvins/serverpulse/common/config/DatabaseConfiguration.java index e7a93de..cc89ff8 100644 --- a/common/src/main/java/it/renvins/serverpulse/common/config/DatabaseConfiguration.java +++ b/common/src/main/java/it/renvins/serverpulse/common/config/DatabaseConfiguration.java @@ -1,9 +1,30 @@ package it.renvins.serverpulse.common.config; -public interface DatabaseConfiguration { +import lombok.RequiredArgsConstructor; + +/** + * Configuration class for InfluxDB database settings. + * This class retrieves the database connection details from the general configuration. + */ +@RequiredArgsConstructor +public class DatabaseConfiguration { + + private final GeneralConfiguration configuration; + + public String getHost() { + return configuration.getConfig().getString("metrics.influxdb.url"); + } + + public String getOrg() { + return configuration.getConfig().getString("metrics.influxdb.org"); + } + + public String getToken() { + return configuration.getConfig().getString("metrics.influxdb.token"); + } + + public String getBucket() { + return configuration.getConfig().getString("metrics.influxdb.bucket"); + } - String getHost(); - String getOrg(); - String getToken(); - String getBucket(); } diff --git a/common/src/main/java/it/renvins/serverpulse/common/config/GeneralConfiguration.java b/common/src/main/java/it/renvins/serverpulse/common/config/GeneralConfiguration.java new file mode 100644 index 0000000..aff1278 --- /dev/null +++ b/common/src/main/java/it/renvins/serverpulse/common/config/GeneralConfiguration.java @@ -0,0 +1,70 @@ +package it.renvins.serverpulse.common.config; + +import it.renvins.serverpulse.common.logger.PulseLogger; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.simpleyaml.configuration.file.YamlFile; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; + +/** + * General configuration class for managing the configuration file. + * This class handles loading the configuration from a YAML file and creating a default configuration if it does not exist. + */ +@RequiredArgsConstructor +public class GeneralConfiguration { + + private final PulseLogger logger; + + private final File dataFolder; + private final String name; + + @Getter private YamlFile config; + + /** + * Loads the configuration file. + * If the file does not exist, it creates a default configuration from the resources. + * + * @return true if the configuration was loaded successfully, false otherwise + */ + public boolean load() { + try { + createDefaultConfigIfNotExists(); + config = new YamlFile(new File(dataFolder, name)); + + config.load(); + logger.info("Successfully loaded configuration file: " + name); + + return true; + } catch (IOException e) { + logger.error("Failed to load configuration file: " + name, e); + return false; + } + } + + /** + * Creates the configuration file from the JAR's resources if it doesn't already exist. + */ + private void createDefaultConfigIfNotExists() { + if (!dataFolder.exists()) { + dataFolder.mkdirs(); + } + + File configFile = new File(dataFolder, name); + if (!configFile.exists()) { + try (InputStream inputStream = getClass().getClassLoader().getResourceAsStream(name)) { + if (inputStream == null) { + logger.error("Failed to load default configuration file: " + name); + return; + } + Files.copy(inputStream, configFile.toPath()); + logger.info("Successfully created default configuration file: " + name); + } catch (IOException e) { + logger.error("Failed to copy default configuration file: " + name, e); + } + } + } +} diff --git a/common/src/main/java/it/renvins/serverpulse/common/config/MetricsConfiguration.java b/common/src/main/java/it/renvins/serverpulse/common/config/MetricsConfiguration.java index e2cf70b..fc8ad43 100644 --- a/common/src/main/java/it/renvins/serverpulse/common/config/MetricsConfiguration.java +++ b/common/src/main/java/it/renvins/serverpulse/common/config/MetricsConfiguration.java @@ -1,12 +1,39 @@ package it.renvins.serverpulse.common.config; +import lombok.RequiredArgsConstructor; + +import java.util.HashMap; import java.util.Map; -public interface MetricsConfiguration { +/** + * Configuration class for metrics settings. + * This class retrieves various metrics-related settings from the general configuration. + */ +@RequiredArgsConstructor +public class MetricsConfiguration { + + private final GeneralConfiguration configuration; + + public String getServerTag() { + return configuration.getConfig().getString("metrics.tags.server"); + } + + public String getMeasurementTable() { + return configuration.getConfig().getString("metrics.influxdb.table"); + } - String getServerTag(); - String getMeasurementTable(); - long getMetricsInterval(); - Map getTags(); + public long getMetricsInterval() { + return configuration.getConfig().getLong("metrics.interval"); + } + public Map getTags() { + Map tags = configuration.getConfig().getConfigurationSection("metrics.tags").getValues(false); + Map stringTags = new HashMap<>(); + tags.forEach((key, value) -> { + if (value instanceof String && !key.equalsIgnoreCase("server") && !key.equalsIgnoreCase("world")) { + stringTags.put(key, (String) value); + } + }); + return stringTags; + } } diff --git a/common/src/main/java/it/renvins/serverpulse/common/logger/PulseLogger.java b/common/src/main/java/it/renvins/serverpulse/common/logger/PulseLogger.java index 9ec297b..6d206c3 100644 --- a/common/src/main/java/it/renvins/serverpulse/common/logger/PulseLogger.java +++ b/common/src/main/java/it/renvins/serverpulse/common/logger/PulseLogger.java @@ -1,5 +1,8 @@ package it.renvins.serverpulse.common.logger; +/* This interface defines a simple logging mechanism for the ServerPulse modules. + * It provides methods for logging informational messages, warnings, and errors. + */ public interface PulseLogger { void info(String message); diff --git a/common/src/main/java/it/renvins/serverpulse/common/metrics/LineProtocolFormatter.java b/common/src/main/java/it/renvins/serverpulse/common/metrics/LineProtocolFormatter.java index f829561..095f8a8 100644 --- a/common/src/main/java/it/renvins/serverpulse/common/metrics/LineProtocolFormatter.java +++ b/common/src/main/java/it/renvins/serverpulse/common/metrics/LineProtocolFormatter.java @@ -4,8 +4,8 @@ import it.renvins.serverpulse.api.data.LineProtocolPoint; import it.renvins.serverpulse.api.data.SyncMetricsSnapshot; import it.renvins.serverpulse.api.data.WorldData; +import it.renvins.serverpulse.common.config.GeneralConfiguration; import it.renvins.serverpulse.common.config.MetricsConfiguration; -import lombok.RequiredArgsConstructor; import java.time.Instant; import java.util.ArrayList; @@ -17,11 +17,14 @@ * Formats raw metric snapshots into InfluxDB Line Protocol strings. * Its single responsibility is to handle the formatting logic. */ -@RequiredArgsConstructor public class LineProtocolFormatter { private final MetricsConfiguration metricsConfig; + public LineProtocolFormatter(GeneralConfiguration generalConfig) { + this.metricsConfig = new MetricsConfiguration(generalConfig); + } + public List format(SyncMetricsSnapshot syncData, AsyncMetricsSnapshot asyncData) { List points = new ArrayList<>(); long timestamp = Instant.now().toEpochMilli() * 1_000_000; @@ -29,9 +32,6 @@ public List format(SyncMetricsSnapshot syncData, AsyncMetricsSnapshot as LineProtocolPoint generalPoint = new LineProtocolPoint(metricsConfig.getMeasurementTable()) .addTag("server", metricsConfig.getServerTag()) // Sync data - .addField("tps_1m", syncData.getTps()[0]) - .addField("tps_5m", syncData.getTps()[1]) - .addField("tps_15m", syncData.getTps()[2]) .addField("players_online", syncData.getPlayerCount()) // Async data .addField("used_memory", asyncData.getUsedHeap()) @@ -43,6 +43,12 @@ public List format(SyncMetricsSnapshot syncData, AsyncMetricsSnapshot as .addField("avg_ping", asyncData.getAvgPing()) .setTimestamp(timestamp); + if (syncData.getTps()[0] != 0.0 && syncData.getTps()[1] != 0.0 && syncData.getTps()[2] != 0.0) { + generalPoint.addField("tps_1m", syncData.getTps()[0]) + .addField("tps_5m", syncData.getTps()[1]) + .addField("tps_15m", syncData.getTps()[2]); + } + addConfigTags(generalPoint); points.add(generalPoint); diff --git a/fabric/build.gradle.kts b/fabric/build.gradle.kts index 8e18ac6..1a501b6 100644 --- a/fabric/build.gradle.kts +++ b/fabric/build.gradle.kts @@ -35,7 +35,7 @@ repositories { dependencies { minecraft("com.mojang:minecraft:1.21.7") mappings("net.fabricmc:yarn:1.21.7+build.2:v2") - modImplementation("net.fabricmc:fabric-loader:0.16.14") + modImplementation("net.fabricmc:fabric-loader:0.16.14") // modImplementation("net.fabricmc.fabric-api:fabric-api:0.128.2+1.21.7") @@ -45,13 +45,12 @@ dependencies { include(project(":api")) include(project(":common")) - // SimpleYAML - implementation("com.github.Carleslc.Simple-YAML:Simple-Yaml:1.8.4") - include("com.github.Carleslc.Simple-YAML:Simple-Yaml:1.8.4") - // Fabric Permissions API modImplementation("me.lucko:fabric-permissions-api:0.3.1") include("me.lucko:fabric-permissions-api:0.3.1") + + compileOnly("com.github.Carleslc.Simple-YAML:Simple-Yaml:1.8.4") + include("com.github.Carleslc.Simple-YAML:Simple-Yaml:1.8.4") } tasks.processResources { @@ -60,7 +59,7 @@ tasks.processResources { filesMatching("fabric.mod.json") { expand(mapOf( "version" to rootProject.version, - "minecraft_version" to "1.21.4", + "minecraft_version" to "1.21.7", "loader_version" to "0.16.10" ) ) diff --git a/fabric/src/main/java/it/renvins/serverpulse/fabric/ServerPulseFabric.java b/fabric/src/main/java/it/renvins/serverpulse/fabric/ServerPulseFabric.java index ca02fd4..504285a 100644 --- a/fabric/src/main/java/it/renvins/serverpulse/fabric/ServerPulseFabric.java +++ b/fabric/src/main/java/it/renvins/serverpulse/fabric/ServerPulseFabric.java @@ -11,6 +11,7 @@ import it.renvins.serverpulse.common.DatabaseService; import it.renvins.serverpulse.common.MetricsService; import it.renvins.serverpulse.common.config.DatabaseConfiguration; +import it.renvins.serverpulse.common.config.GeneralConfiguration; import it.renvins.serverpulse.common.config.MetricsConfiguration; import it.renvins.serverpulse.common.logger.PulseLogger; import it.renvins.serverpulse.common.disk.DiskRetriever; @@ -19,9 +20,6 @@ import it.renvins.serverpulse.common.platform.Platform; import it.renvins.serverpulse.common.scheduler.TaskScheduler; import it.renvins.serverpulse.fabric.command.ServerPulseCommand; -import it.renvins.serverpulse.fabric.config.FabricConfiguration; -import it.renvins.serverpulse.fabric.config.FabricDatabaseConfiguration; -import it.renvins.serverpulse.fabric.config.FabricMetricsConfiguration; import it.renvins.serverpulse.fabric.logger.FabricLogger; import it.renvins.serverpulse.fabric.metrics.FabricPingRetriever; import it.renvins.serverpulse.fabric.metrics.FabricTPSRetriever; @@ -39,7 +37,7 @@ public class ServerPulseFabric implements ModInitializer { public static final String MOD_ID = "serverpulse"; public static final Logger LOGGER = Logger.getLogger(MOD_ID); - private final FabricConfiguration config; + private final GeneralConfiguration config; private final Platform platform; private final TaskScheduler scheduler; @@ -53,24 +51,21 @@ public class ServerPulseFabric implements ModInitializer { private final IMetricsService metricsService; public ServerPulseFabric() { - this.config = new FabricConfiguration(FabricLoader.getInstance().getConfigDir().resolve("serverpulse"), "config.yml"); - PulseLogger logger = new FabricLogger(); + this.config = new GeneralConfiguration(logger, FabricLoader.getInstance().getConfigDir().resolve("serverpulse").toFile(), "config.yml"); + this.platform = new FabricPlatform(this); this.scheduler = new FabricScheduler(); - DatabaseConfiguration dbConfig = new FabricDatabaseConfiguration(config); - MetricsConfiguration metricsConfig = new FabricMetricsConfiguration(config); - - this.databaseService = new DatabaseService(logger, platform, dbConfig, scheduler); + this.databaseService = new DatabaseService(logger, platform, config, scheduler); this.tpsRetriever = new FabricTPSRetriever(); this.diskRetriever = new DiskRetriever(FabricLoader.getInstance().getGameDir().toFile()); this.pingRetriever = new FabricPingRetriever(this); MetricsCollector collector = new MetricsCollector(logger, platform, tpsRetriever, diskRetriever, pingRetriever); - LineProtocolFormatter formatter = new LineProtocolFormatter(metricsConfig); + LineProtocolFormatter formatter = new LineProtocolFormatter(config); this.metricsService = new MetricsService(logger, collector, formatter, scheduler, databaseService); } @@ -81,6 +76,7 @@ public ServerPulseFabric() { public void onInitialize() { ServerLifecycleEvents.SERVER_STARTING.register(this::onServerStarting); ServerLifecycleEvents.SERVER_STOPPING.register(this::onServerStopped); + CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> dispatcher.register(new ServerPulseCommand(config).createCommand())); @@ -93,7 +89,6 @@ private void onServerStarting(MinecraftServer server) { LOGGER.info("Loading configuration..."); config.load(); - databaseService.load(); if (!platform.isEnabled()) { return; diff --git a/fabric/src/main/java/it/renvins/serverpulse/fabric/command/ServerPulseCommand.java b/fabric/src/main/java/it/renvins/serverpulse/fabric/command/ServerPulseCommand.java index 3615345..e2ac019 100644 --- a/fabric/src/main/java/it/renvins/serverpulse/fabric/command/ServerPulseCommand.java +++ b/fabric/src/main/java/it/renvins/serverpulse/fabric/command/ServerPulseCommand.java @@ -4,8 +4,8 @@ import com.mojang.brigadier.builder.LiteralArgumentBuilder; import com.mojang.brigadier.context.CommandContext; import it.renvins.serverpulse.api.ServerPulseProvider; +import it.renvins.serverpulse.common.config.GeneralConfiguration; import it.renvins.serverpulse.common.utils.ChatUtils; -import it.renvins.serverpulse.fabric.config.FabricConfiguration; import lombok.RequiredArgsConstructor; import me.lucko.fabric.api.permissions.v0.Permissions; import net.minecraft.server.command.CommandManager; @@ -15,7 +15,7 @@ @RequiredArgsConstructor public class ServerPulseCommand { - private final FabricConfiguration config; + private final GeneralConfiguration config; public LiteralArgumentBuilder createCommand() { // Create the main command diff --git a/fabric/src/main/java/it/renvins/serverpulse/fabric/config/FabricConfiguration.java b/fabric/src/main/java/it/renvins/serverpulse/fabric/config/FabricConfiguration.java deleted file mode 100644 index c1f9104..0000000 --- a/fabric/src/main/java/it/renvins/serverpulse/fabric/config/FabricConfiguration.java +++ /dev/null @@ -1,64 +0,0 @@ -package it.renvins.serverpulse.fabric.config; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.logging.Level; - -import it.renvins.serverpulse.fabric.ServerPulseFabric; -import lombok.Getter; -import org.simpleyaml.configuration.file.YamlFile; - -public class FabricConfiguration { - - private final String name; - - @Getter private final YamlFile config; - - public FabricConfiguration(Path dataDir, String name) { - this.name = name; - - try { - Files.createDirectories(dataDir); - } catch (IOException e) { - ServerPulseFabric.LOGGER.log(Level.SEVERE,"Failed to create data directory: " + dataDir, e); - } - this.config = new YamlFile(new File(dataDir.toFile(), name)); - } - - public boolean load() { - try { - if (!config.exists()) { - if (copyDefaultsFromResource()) { - ServerPulseFabric.LOGGER.info("Created configuration file: " + name); - } else { - config.createNewFile(); - ServerPulseFabric.LOGGER.info("Configuration file not found, created a new one: " + name); - } - } else { - ServerPulseFabric.LOGGER.info("Loading configuration file: " + name); - } - config.load(); - return true; - } catch (Exception e) { - ServerPulseFabric.LOGGER.log(Level.SEVERE,"Failed to load configuration file: " + name, e); - return false; - } - } - - private boolean copyDefaultsFromResource() { - try (InputStream in = getClass().getClassLoader().getResourceAsStream(name)) { - if (in != null) { - Files.copy(in, config.getConfigurationFile().toPath()); - return true; - } else { - return false; - } - } catch (IOException e) { - ServerPulseFabric.LOGGER.log(Level.SEVERE,"Failed to copy default configuration file: " + name, e); - return false; - } - } -} diff --git a/fabric/src/main/java/it/renvins/serverpulse/fabric/config/FabricDatabaseConfiguration.java b/fabric/src/main/java/it/renvins/serverpulse/fabric/config/FabricDatabaseConfiguration.java deleted file mode 100644 index cdd921c..0000000 --- a/fabric/src/main/java/it/renvins/serverpulse/fabric/config/FabricDatabaseConfiguration.java +++ /dev/null @@ -1,30 +0,0 @@ -package it.renvins.serverpulse.fabric.config; - -import it.renvins.serverpulse.common.config.DatabaseConfiguration; -import lombok.RequiredArgsConstructor; - -@RequiredArgsConstructor -public class FabricDatabaseConfiguration implements DatabaseConfiguration { - - private final FabricConfiguration configuration; - - @Override - public String getHost() { - return configuration.getConfig().getString("metrics.influxdb.url"); - } - - @Override - public String getOrg() { - return configuration.getConfig().getString("metrics.influxdb.org"); - } - - @Override - public String getToken() { - return configuration.getConfig().getString("metrics.influxdb.token"); - } - - @Override - public String getBucket() { - return configuration.getConfig().getString("metrics.influxdb.bucket"); - } -} diff --git a/fabric/src/main/java/it/renvins/serverpulse/fabric/config/FabricMetricsConfiguration.java b/fabric/src/main/java/it/renvins/serverpulse/fabric/config/FabricMetricsConfiguration.java deleted file mode 100644 index da8d2a7..0000000 --- a/fabric/src/main/java/it/renvins/serverpulse/fabric/config/FabricMetricsConfiguration.java +++ /dev/null @@ -1,40 +0,0 @@ -package it.renvins.serverpulse.fabric.config; - -import java.util.HashMap; -import java.util.Map; - -import it.renvins.serverpulse.common.config.MetricsConfiguration; -import lombok.RequiredArgsConstructor; - -@RequiredArgsConstructor -public class FabricMetricsConfiguration implements MetricsConfiguration { - - private final FabricConfiguration configuration; - - @Override - public String getServerTag() { - return configuration.getConfig().getString("metrics.tags.server"); - } - - @Override - public String getMeasurementTable() { - return configuration.getConfig().getString("metrics.influxdb.table"); - } - - @Override - public long getMetricsInterval() { - return configuration.getConfig().getLong("metrics.interval"); - } - - @Override - public Map getTags() { - Map tags = configuration.getConfig().getConfigurationSection("metrics.tags").getValues(false); - Map stringTags = new HashMap<>(); - tags.forEach((key, value) -> { - if (value instanceof String && !key.equalsIgnoreCase("server") && !key.equalsIgnoreCase("world")) { - stringTags.put(key, (String) value); - } - }); - return stringTags; - } -} diff --git a/settings.gradle.kts b/settings.gradle.kts index 62f20bf..ad46e98 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -6,6 +6,8 @@ include("bukkit") include("common") include("velocity") include("fabric") +include("bungeecord") +include("teste2e") pluginManagement { repositories { @@ -16,5 +18,4 @@ pluginManagement { mavenCentral() gradlePluginPortal() } -} -include("bungeecord") \ No newline at end of file +} \ No newline at end of file diff --git a/teste2e/build.gradle.kts b/teste2e/build.gradle.kts new file mode 100644 index 0000000..5a09131 --- /dev/null +++ b/teste2e/build.gradle.kts @@ -0,0 +1,38 @@ +plugins { + id("java") + id("io.freefair.lombok") version "8.13.1" +} + +group = "it.renvins" + +repositories { + mavenCentral() + maven { + name = "opencollabRepositoryMavenReleases" + url = uri("https://repo.opencollab.dev/maven-releases") + } +} + +dependencies { + // === FIX: Import the JUnit 5 Bill of Materials (BOM) === + // This forces all JUnit dependencies to use the same version + testImplementation(platform("org.junit:junit-bom:5.10.2")) + testImplementation(platform("org.testcontainers:testcontainers-bom:1.21.3")) // ADDED THIS LINE + + testImplementation("org.junit.jupiter:junit-jupiter-params") + + // Testcontainers dependencies + testImplementation("org.testcontainers:testcontainers") + testImplementation("org.testcontainers:junit-jupiter") + + testImplementation("org.junit.jupiter:junit-jupiter-api") + testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine") + + // To handle the Minecraft protocol + testImplementation("org.geysermc.mcprotocollib:protocol:1.21.7-1") + +} + +tasks.test { + useJUnitPlatform() +} diff --git a/teste2e/src/test/java/it/renvins/serverpulse/e2e/ServerE2ETest.java b/teste2e/src/test/java/it/renvins/serverpulse/e2e/ServerE2ETest.java new file mode 100644 index 0000000..82ae340 --- /dev/null +++ b/teste2e/src/test/java/it/renvins/serverpulse/e2e/ServerE2ETest.java @@ -0,0 +1,73 @@ +package it.renvins.serverpulse.e2e; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testcontainers.containers.DockerComposeContainer; +import org.testcontainers.containers.output.Slf4jLogConsumer; +import org.testcontainers.containers.wait.strategy.Wait; +import org.testcontainers.junit.jupiter.Testcontainers; + +import java.io.File; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.time.Duration; +import java.util.concurrent.TimeUnit; +import java.util.stream.Stream; + +@Testcontainers +public class ServerE2ETest { + + private static final Logger logger = LoggerFactory.getLogger(ServerE2ETest.class); + private static final Path CONFIG_PATH = Paths.get("src/test/resources/config/ServerPulse/config.yml"); + private static final Path CONFIG_TEMPLATE_PATH = Paths.get("src/test/resources/config/ServerPulse/config.template.yml"); + + private static Stream testConfigStream() { + return Stream.of( + new TestConfig("bungeecord", "bungeecord-server", 25578, ".*Listening on /0.0.0.0:25577.*", "bungeecord"), + new TestConfig("velocity", "velocity-server", 25577, ".*Done \\(.*\\)!.*", "velocity1"), + new TestConfig("bukkit", "bukkit-server", 25565, ".*Done \\(.*\\)! For help, type \"help\".*", "bed1"), + new TestConfig("fabric", "fabric-server", 25566, ".*Done \\(.*\\)! For help, type \"help\".*", "fabric1")); + } + + @ParameterizedTest(name = "E2E Test for {0}") + @MethodSource("testConfigStream") + void testServerMetrics(TestConfig config) throws Exception { + String templateContent = Files.readString(CONFIG_TEMPLATE_PATH); + String actualContent = templateContent.replace("%%SERVER_NAME%%", config.getServerTag()); + Files.writeString(CONFIG_PATH, actualContent); + + try (DockerComposeContainer environment = new DockerComposeContainer<>(new File("src/test/resources/compose/" + config.getModuleName() + ".yml")) + .withExposedService("influxdb", 8086, Wait.forHttp("/ping").forStatusCode(204).withStartupTimeout(Duration.ofMinutes(2))) + .withExposedService("grafana", 3000, Wait.forHttp("/api/health").forStatusCode(200).withStartupTimeout(Duration.ofMinutes(2))) + .withExposedService(config.getServiceName(), config.getPort(), Wait.forLogMessage(config.getLogMessage(), 1).withStartupTimeout(Duration.ofMinutes(5))) + .withLogConsumer(config.getServiceName(), new Slf4jLogConsumer(logger).withPrefix(config.getModuleName().toUpperCase()))) { + + environment.start(); + + System.out.println("Environment for " + config.getModuleName() + " is running. Waiting 30 seconds for the test to complete..."); + + TimeUnit.SECONDS.sleep(30); + + System.out.println("Test for " + config.getModuleName() + " completed, shutting down."); + } finally { + Files.deleteIfExists(CONFIG_PATH); + } + } + + @RequiredArgsConstructor + @Getter + private static class TestConfig { + private final String moduleName; + private final String serviceName; + + private final int port; + + private final String logMessage; + private final String serverTag; + } +} \ No newline at end of file diff --git a/teste2e/src/test/resources/compose/bukkit.yml b/teste2e/src/test/resources/compose/bukkit.yml new file mode 100644 index 0000000..b415eb9 --- /dev/null +++ b/teste2e/src/test/resources/compose/bukkit.yml @@ -0,0 +1,44 @@ +services: + influxdb: + image: influxdb:latest + ports: + - "8086:8086" + environment: + DOCKER_INFLUXDB_INIT_MODE: setup + DOCKER_INFLUXDB_INIT_USERNAME: admin + DOCKER_INFLUXDB_INIT_PASSWORD: absolutely + DOCKER_INFLUXDB_INIT_ORG: ares + DOCKER_INFLUXDB_INIT_BUCKET: metrics_db + DOCKER_INFLUXDB_INIT_ADMIN_TOKEN: jGEss1Q6KpTmkCFqYvN0kjaKcXGmFRDL1xz00Xp8VseY-5uLldtY0_HxujH8aMRkMD3Cb3e7MLipahJSlGs6Ng== + volumes: + - influxdb-test-data:/var/lib/influxdb2 + grafana: + image: grafana/grafana:latest + ports: + - "3000:3000" + volumes: + - ../../../../../infra/grafana/provisioning:/etc/grafana/provisioning + - ../../../../../infra/grafana/dashboards:/var/lib/grafana/dashboards + - grafana-test-data:/var/lib/grafana + depends_on: + - influxdb + environment: + GF_SECURITY_ADMIN_USER: admin + GF_SECURITY_ADMIN_PASSWORD: absolutely + bukkit-server: + image: itzg/minecraft-server + ports: + - "25565:25565" + environment: + EULA: "TRUE" + ONLINE_MODE: "FALSE" + TYPE: "PAPER" + VERSION: "1.21.7" + volumes: + - ../../../../../bukkit/build/libs:/data/plugins + - ../config/ServerPulse:/data/plugins/ServerPulse + - bukkit-server-data:/data +volumes: + influxdb-test-data: + grafana-test-data: + bukkit-server-data: \ No newline at end of file diff --git a/teste2e/src/test/resources/compose/bungeecord.yml b/teste2e/src/test/resources/compose/bungeecord.yml new file mode 100644 index 0000000..adb515b --- /dev/null +++ b/teste2e/src/test/resources/compose/bungeecord.yml @@ -0,0 +1,41 @@ +services: + influxdb: + image: influxdb:latest + ports: + - "8086:8086" + environment: + DOCKER_INFLUXDB_INIT_MODE: setup + DOCKER_INFLUXDB_INIT_USERNAME: admin + DOCKER_INFLUXDB_INIT_PASSWORD: absolutely + DOCKER_INFLUXDB_INIT_ORG: ares + DOCKER_INFLUXDB_INIT_BUCKET: metrics_db + DOCKER_INFLUXDB_INIT_ADMIN_TOKEN: jGEss1Q6KpTmkCFqYvN0kjaKcXGmFRDL1xz00Xp8VseY-5uLldtY0_HxujH8aMRkMD3Cb3e7MLipahJSlGs6Ng== + volumes: + - influxdb-test-data:/var/lib/influxdb2 + grafana: + image: grafana/grafana:latest + ports: + - "3000:3000" + volumes: + - ../../../../../infra/grafana/provisioning:/etc/grafana/provisioning + - ../../../../../infra/grafana/dashboards:/var/lib/grafana/dashboards + - grafana-test-data:/var/lib/grafana + depends_on: + - influxdb + environment: + GF_SECURITY_ADMIN_USER: admin + GF_SECURITY_ADMIN_PASSWORD: absolutely + bungeecord-server: + image: itzg/mc-proxy + ports: + - "25578:25577" + environment: + TYPE: "BUNGEECORD" + volumes: + - ../../../../../bungeecord/build/libs:/plugins + - ../config/ServerPulse:/plugins/ServerPulse + - bungeecord-server-data:/server +volumes: + influxdb-test-data: + grafana-test-data: + bungeecord-server-data: \ No newline at end of file diff --git a/teste2e/src/test/resources/compose/fabric.yml b/teste2e/src/test/resources/compose/fabric.yml new file mode 100644 index 0000000..dd8c3c8 --- /dev/null +++ b/teste2e/src/test/resources/compose/fabric.yml @@ -0,0 +1,45 @@ +services: + influxdb: + image: influxdb:latest + ports: + - "8086:8086" + environment: + DOCKER_INFLUXDB_INIT_MODE: setup + DOCKER_INFLUXDB_INIT_USERNAME: admin + DOCKER_INFLUXDB_INIT_PASSWORD: absolutely + DOCKER_INFLUXDB_INIT_ORG: ares + DOCKER_INFLUXDB_INIT_BUCKET: metrics_db + DOCKER_INFLUXDB_INIT_ADMIN_TOKEN: jGEss1Q6KpTmkCFqYvN0kjaKcXGmFRDL1xz00Xp8VseY-5uLldtY0_HxujH8aMRkMD3Cb3e7MLipahJSlGs6Ng== + volumes: + - influxdb-test-data:/var/lib/influxdb2 + grafana: + image: grafana/grafana:latest + ports: + - "3000:3000" + volumes: + - ../../../../../infra/grafana/provisioning:/etc/grafana/provisioning + - ../../../../../infra/grafana/dashboards:/var/lib/grafana/dashboards + - grafana-test-data:/var/lib/grafana + depends_on: + - influxdb + environment: + GF_SECURITY_ADMIN_USER: admin + GF_SECURITY_ADMIN_PASSWORD: absolutely + fabric-server: + image: itzg/minecraft-server + ports: + - "25566:25565" + environment: + EULA: "TRUE" + TYPE: "FABRIC" + ONLINE_MODE: "FALSE" + VERSION: "1.21.7" + MODS: "https://cdn.modrinth.com/data/P7dR8mSH/versions/JntuF9Ul/fabric-api-0.129.0%2B1.21.7.jar" + volumes: + - ../../../../../fabric/build/libs:/data/mods + - ../config/ServerPulse:/data/config/serverpulse + - fabric-server-data:/data +volumes: + influxdb-test-data: + grafana-test-data: + fabric-server-data: \ No newline at end of file diff --git a/teste2e/src/test/resources/compose/velocity.yml b/teste2e/src/test/resources/compose/velocity.yml new file mode 100644 index 0000000..83092f9 --- /dev/null +++ b/teste2e/src/test/resources/compose/velocity.yml @@ -0,0 +1,41 @@ +services: + influxdb: + image: influxdb:latest + ports: + - "8086:8086" + environment: + DOCKER_INFLUXDB_INIT_MODE: setup + DOCKER_INFLUXDB_INIT_USERNAME: admin + DOCKER_INFLUXDB_INIT_PASSWORD: absolutely + DOCKER_INFLUXDB_INIT_ORG: ares + DOCKER_INFLUXDB_INIT_BUCKET: metrics_db + DOCKER_INFLUXDB_INIT_ADMIN_TOKEN: jGEss1Q6KpTmkCFqYvN0kjaKcXGmFRDL1xz00Xp8VseY-5uLldtY0_HxujH8aMRkMD3Cb3e7MLipahJSlGs6Ng== + volumes: + - influxdb-test-data:/var/lib/influxdb2 + grafana: + image: grafana/grafana:latest + ports: + - "3000:3000" + volumes: + - ../../../../../infra/grafana/provisioning:/etc/grafana/provisioning + - ../../../../../infra/grafana/dashboards:/var/lib/grafana/dashboards + - grafana-test-data:/var/lib/grafana + depends_on: + - influxdb + environment: + GF_SECURITY_ADMIN_USER: admin + GF_SECURITY_ADMIN_PASSWORD: absolutely + velocity-server: + image: itzg/mc-proxy + ports: + - "25577:25577" + environment: + TYPE: "VELOCITY" + volumes: + - ../../../../../velocity/build/libs:/plugins + - ../config/ServerPulse:/plugins/serverpulse + - velocity-server-data:/server +volumes: + influxdb-test-data: + grafana-test-data: + velocity-server-data: \ No newline at end of file diff --git a/teste2e/src/test/resources/config/ServerPulse/config.template.yml b/teste2e/src/test/resources/config/ServerPulse/config.template.yml new file mode 100644 index 0000000..d8089e8 --- /dev/null +++ b/teste2e/src/test/resources/config/ServerPulse/config.template.yml @@ -0,0 +1,21 @@ +metrics: + interval: 5 + influxdb: + url: http://influxdb:8086 # The URL of the InfluxDB API + org: ares # The organization where metrics are stored + bucket: metrics_db # The bucket where metrics are stored + token: jGEss1Q6KpTmkCFqYvN0kjaKcXGmFRDL1xz00Xp8VseY-5uLldtY0_HxujH8aMRkMD3Cb3e7MLipahJSlGs6Ng== # The token to access the InfluxDB API (WRITE AND READ ACCESS) + table: minecraft_stats # The table where metrics are stored + tags: + server: "%%SERVER_NAME%%" +messages: + noPerms: "&7[&bServer&7Pulse] &7You don't have &bpermission &7to use this &bcommand&7." + reloadConfig: "&7[&bServer&7Pulse] &7Configuration &breloaded&7." + reloadConfigError: "&7[&bServer&7Pulse] &7Error &breloading &7configuration..." + noArgs: "&7[&bServer&7Pulse] &7You need to specify a &bcommand&7: &breload&7, &bstatus&7." + playerOnly: "&7[&bServer&7Pulse] &7This command can only be used by &bplayers&7." + noCommand: "&7[&bServer&7Pulse] &7This command is not &bavailable&7." + reloadConfigUsage: "&7[&bServer&7Pulse] &7Usage: &b/serverpulse reload&7." + statusConfigUsage: "&7[&bServer&7Pulse] &7Usage: &b/serverpulse status&7." + statusConnected: "&7[&bServer&7Pulse] &7Connected to &bInfluxDB&7." + statusNotConnected: "&7[&bServer&7Pulse] &7Not connected to &bInfluxDB&7." diff --git a/velocity/build.gradle.kts b/velocity/build.gradle.kts index d46413c..5333861 100644 --- a/velocity/build.gradle.kts +++ b/velocity/build.gradle.kts @@ -20,10 +20,11 @@ repositories { dependencies { implementation(project(":api")) implementation(project(":common")) - implementation("com.github.Carleslc.Simple-YAML:Simple-Yaml:1.8.4") compileOnly("com.velocitypowered:velocity-api:3.4.0-SNAPSHOT") annotationProcessor("com.velocitypowered:velocity-api:3.4.0-SNAPSHOT") + + compileOnly("com.github.Carleslc.Simple-YAML:Simple-Yaml:1.8.4") } java { @@ -34,4 +35,7 @@ tasks.withType { archiveBaseName = "serverpulse" archiveClassifier = "velocity" archiveVersion = "${rootProject.version}" + duplicatesStrategy = DuplicatesStrategy.EXCLUDE + + minimize() } \ No newline at end of file diff --git a/velocity/src/main/java/it/renvins/serverpulse/velocity/ServerPulseVelocity.java b/velocity/src/main/java/it/renvins/serverpulse/velocity/ServerPulseVelocity.java index e36d1d9..b6c25ac 100644 --- a/velocity/src/main/java/it/renvins/serverpulse/velocity/ServerPulseVelocity.java +++ b/velocity/src/main/java/it/renvins/serverpulse/velocity/ServerPulseVelocity.java @@ -18,8 +18,7 @@ import it.renvins.serverpulse.api.service.IMetricsService; import it.renvins.serverpulse.common.DatabaseService; import it.renvins.serverpulse.common.MetricsService; -import it.renvins.serverpulse.common.config.DatabaseConfiguration; -import it.renvins.serverpulse.common.config.MetricsConfiguration; +import it.renvins.serverpulse.common.config.GeneralConfiguration; import it.renvins.serverpulse.common.logger.PulseLogger; import it.renvins.serverpulse.common.disk.DiskRetriever; import it.renvins.serverpulse.common.metrics.LineProtocolFormatter; @@ -28,9 +27,6 @@ import it.renvins.serverpulse.common.platform.Platform; import it.renvins.serverpulse.common.scheduler.TaskScheduler; import it.renvins.serverpulse.velocity.commands.ServerPulseCommand; -import it.renvins.serverpulse.velocity.config.VelocityConfiguration; -import it.renvins.serverpulse.velocity.config.VelocityDatabaseConfiguration; -import it.renvins.serverpulse.velocity.config.VelocityMetricsConfiguration; import it.renvins.serverpulse.velocity.logger.VelocityLogger; import it.renvins.serverpulse.velocity.metrics.VelocityPingRetriever; import it.renvins.serverpulse.velocity.platform.VelocityPlatform; @@ -38,7 +34,7 @@ import lombok.Getter; import org.slf4j.Logger; -@Plugin(id = "serverpulse", name = "ServerPulse", version = "0.4.2-SNAPSHOT", +@Plugin(id = "serverpulse", name = "ServerPulse", version = "0.4.5-SNAPSHOT", description = "Effortless Minecraft performance monitoring with pre-configured Grafana/InfluxDB via Docker.", authors = {"renvins"}) public class ServerPulseVelocity { @@ -48,7 +44,7 @@ public class ServerPulseVelocity { private PulseLogger pulseLogger; - private VelocityConfiguration config; + private GeneralConfiguration config; private IDatabaseService databaseService; @@ -63,25 +59,21 @@ public ServerPulseVelocity(ProxyServer server, Logger logger, @DataDirectory Pat this.logger = logger; this.dataDirectory = dataDirectory; - logger.info("ServerPulse for Fabric initialized - waiting for proxy starting..."); + logger.info("ServerPulse for Velocity initialized - waiting for proxy starting..."); } @Subscribe public void onProxyInitialization(ProxyInitializeEvent event) { this.pulseLogger = new VelocityLogger(logger); - this.config = new VelocityConfiguration(logger, dataDirectory, "config.yml"); + this.config = new GeneralConfiguration(pulseLogger, dataDirectory.toFile(), "config.yml"); logger.info("Loading configuration file..."); config.load(); - DatabaseConfiguration dbConfig = new VelocityDatabaseConfiguration(config); - MetricsConfiguration metricsConfig = new VelocityMetricsConfiguration(config); - - Platform platform = new VelocityPlatform(this); TaskScheduler scheduler = new VelocityTaskScheduler(this); - this.databaseService = new DatabaseService(pulseLogger, platform, dbConfig, scheduler); + this.databaseService = new DatabaseService(pulseLogger, platform, config, scheduler); this.diskRetriever = new DiskRetriever(dataDirectory.toFile()); this.pingRetriever = new VelocityPingRetriever(this); @@ -89,7 +81,7 @@ public void onProxyInitialization(ProxyInitializeEvent event) { ITPSRetriever tpsRetriever = new UnsupportedTPSRetriever(); // Velocity does not provide a TPS retriever MetricsCollector collector = new MetricsCollector(pulseLogger, platform, tpsRetriever, diskRetriever, pingRetriever); - LineProtocolFormatter formatter = new LineProtocolFormatter(metricsConfig); + LineProtocolFormatter formatter = new LineProtocolFormatter(config); this.metricsService = new MetricsService(pulseLogger, collector, formatter, scheduler, databaseService); @@ -97,9 +89,11 @@ public void onProxyInitialization(ProxyInitializeEvent event) { if (server.isShuttingDown()) { return; } - metricsService.load(); + long intervalTicks = config.getConfig().getLong("metrics.interval", 5) * 20L; + scheduler.runTaskTimerAsync(metricsService::collectAndSendMetrics, 0L, intervalTicks); + CommandMeta meta = server.getCommandManager().metaBuilder("serverpulsevelocity") .plugin(this).aliases("spv").build(); server.getCommandManager().register(meta, new ServerPulseCommand(config).createCommand()); diff --git a/velocity/src/main/java/it/renvins/serverpulse/velocity/commands/ServerPulseCommand.java b/velocity/src/main/java/it/renvins/serverpulse/velocity/commands/ServerPulseCommand.java index 2382bdc..78917cc 100644 --- a/velocity/src/main/java/it/renvins/serverpulse/velocity/commands/ServerPulseCommand.java +++ b/velocity/src/main/java/it/renvins/serverpulse/velocity/commands/ServerPulseCommand.java @@ -6,8 +6,8 @@ import com.velocitypowered.api.command.BrigadierCommand; import com.velocitypowered.api.command.CommandSource; import it.renvins.serverpulse.api.ServerPulseProvider; +import it.renvins.serverpulse.common.config.GeneralConfiguration; import it.renvins.serverpulse.common.utils.ChatUtils; -import it.renvins.serverpulse.velocity.config.VelocityConfiguration; import lombok.RequiredArgsConstructor; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; @@ -15,7 +15,7 @@ @RequiredArgsConstructor public class ServerPulseCommand { - private final VelocityConfiguration config; + private final GeneralConfiguration config; public BrigadierCommand createCommand() { // Create the main command diff --git a/velocity/src/main/java/it/renvins/serverpulse/velocity/config/VelocityConfiguration.java b/velocity/src/main/java/it/renvins/serverpulse/velocity/config/VelocityConfiguration.java deleted file mode 100644 index 19b38ad..0000000 --- a/velocity/src/main/java/it/renvins/serverpulse/velocity/config/VelocityConfiguration.java +++ /dev/null @@ -1,65 +0,0 @@ -package it.renvins.serverpulse.velocity.config; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.nio.file.Files; -import java.nio.file.Path; - -import lombok.Getter; -import org.simpleyaml.configuration.file.YamlFile; -import org.slf4j.Logger; - -public class VelocityConfiguration { - - private final Logger logger; - private final String name; - - @Getter private final YamlFile config; - - public VelocityConfiguration(Logger logger, Path dataDir, String name) { - this.logger = logger; - this.name = name; - - try { - Files.createDirectories(dataDir); - } catch (IOException e) { - logger.error("Failed to create data directory: " + dataDir, e); - } - this.config = new YamlFile(new File(dataDir.toFile(), name)); - } - - public boolean load() { - try { - if (!config.exists()) { - if (copyDefaultsFromResource()) { - logger.info("Created configuration file: " + name); - } else { - config.createNewFile(); - logger.info("Configuration file not found, created a new one: " + name); - } - } else { - logger.info("Loading configuration file: " + name); - } - config.load(); - return true; - } catch (Exception e) { - logger.error("Failed to load configuration file: " + name, e); - return false; - } - } - - private boolean copyDefaultsFromResource() { - try (InputStream in = getClass().getClassLoader().getResourceAsStream(name)) { - if (in != null) { - Files.copy(in, config.getConfigurationFile().toPath()); - return true; - } else { - return false; - } - } catch (IOException e) { - logger.error("Failed to copy default configuration file: " + name, e); - return false; - } - } -} \ No newline at end of file diff --git a/velocity/src/main/java/it/renvins/serverpulse/velocity/config/VelocityDatabaseConfiguration.java b/velocity/src/main/java/it/renvins/serverpulse/velocity/config/VelocityDatabaseConfiguration.java deleted file mode 100644 index 81e8908..0000000 --- a/velocity/src/main/java/it/renvins/serverpulse/velocity/config/VelocityDatabaseConfiguration.java +++ /dev/null @@ -1,30 +0,0 @@ -package it.renvins.serverpulse.velocity.config; - -import it.renvins.serverpulse.common.config.DatabaseConfiguration; -import lombok.RequiredArgsConstructor; - -@RequiredArgsConstructor -public class VelocityDatabaseConfiguration implements DatabaseConfiguration { - - private final VelocityConfiguration configuration; - - @Override - public String getHost() { - return configuration.getConfig().getString("metrics.influxdb.url"); - } - - @Override - public String getOrg() { - return configuration.getConfig().getString("metrics.influxdb.org"); - } - - @Override - public String getToken() { - return configuration.getConfig().getString("metrics.influxdb.token"); - } - - @Override - public String getBucket() { - return configuration.getConfig().getString("metrics.influxdb.bucket"); - } -} diff --git a/velocity/src/main/java/it/renvins/serverpulse/velocity/config/VelocityMetricsConfiguration.java b/velocity/src/main/java/it/renvins/serverpulse/velocity/config/VelocityMetricsConfiguration.java deleted file mode 100644 index f1d3735..0000000 --- a/velocity/src/main/java/it/renvins/serverpulse/velocity/config/VelocityMetricsConfiguration.java +++ /dev/null @@ -1,40 +0,0 @@ -package it.renvins.serverpulse.velocity.config; - -import java.util.HashMap; -import java.util.Map; - -import it.renvins.serverpulse.common.config.MetricsConfiguration; -import lombok.RequiredArgsConstructor; - -@RequiredArgsConstructor -public class VelocityMetricsConfiguration implements MetricsConfiguration { - - private final VelocityConfiguration configuration; - - @Override - public String getServerTag() { - return configuration.getConfig().getString("metrics.tags.server"); - } - - @Override - public String getMeasurementTable() { - return configuration.getConfig().getString("metrics.influxdb.table"); - } - - @Override - public long getMetricsInterval() { - return configuration.getConfig().getLong("metrics.interval"); - } - - @Override - public Map getTags() { - Map tags = configuration.getConfig().getConfigurationSection("metrics.tags").getValues(false); - Map stringTags = new HashMap<>(); - tags.forEach((key, value) -> { - if (value instanceof String && !key.equalsIgnoreCase("server") && !key.equalsIgnoreCase("world")) { - stringTags.put(key, (String) value); - } - }); - return stringTags; - } -}