diff --git a/Dockerfile b/Dockerfile index 36647f9..0b2bb24 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM gradle:8.14-jdk21 +FROM gradle:9.3-jdk21 WORKDIR /workspace diff --git a/src/main/java/com/prometheus/spigot/PrometheusSpigotPlugin.java b/src/main/java/com/prometheus/spigot/PrometheusSpigotPlugin.java index 55b33b0..7a1cc3d 100644 --- a/src/main/java/com/prometheus/spigot/PrometheusSpigotPlugin.java +++ b/src/main/java/com/prometheus/spigot/PrometheusSpigotPlugin.java @@ -2,11 +2,14 @@ package com.prometheus.spigot; import com.prometheus.spigot.http.MetricsHttpHandler; import com.prometheus.spigot.listeners.BlockBreakListener; +import com.prometheus.spigot.listeners.BlockPlaceListener; import com.prometheus.spigot.listeners.ChatListener; import com.prometheus.spigot.listeners.ChunkListener; import com.prometheus.spigot.listeners.CommandListener; import com.prometheus.spigot.listeners.ConnectionListener; +import com.prometheus.spigot.listeners.CraftListener; import com.prometheus.spigot.listeners.DeathListener; +import com.prometheus.spigot.listeners.EntityKillListener; import com.prometheus.spigot.listeners.MoveListener; import com.prometheus.spigot.listeners.PluginListener; import com.prometheus.spigot.metrics.MetricsRegistry; @@ -71,6 +74,7 @@ public final class PrometheusSpigotPlugin extends JavaPlugin { private void registerListeners() { var pluginManager = getServer().getPluginManager(); pluginManager.registerEvents(new BlockBreakListener(metricsRegistry), this); + pluginManager.registerEvents(new BlockPlaceListener(metricsRegistry), this); pluginManager.registerEvents(new DeathListener(metricsRegistry), this); pluginManager.registerEvents(new ChatListener(metricsRegistry), this); pluginManager.registerEvents(new MoveListener(metricsRegistry, countBlockMovementOnly), this); @@ -78,6 +82,8 @@ public final class PrometheusSpigotPlugin extends JavaPlugin { pluginManager.registerEvents(new CommandListener(metricsRegistry), this); pluginManager.registerEvents(new ChunkListener(metricsRegistry), this); pluginManager.registerEvents(new PluginListener(metricsRegistry), this); + pluginManager.registerEvents(new CraftListener(metricsRegistry), this); + pluginManager.registerEvents(new EntityKillListener(metricsRegistry), this); } private void startHttpServer() { diff --git a/src/main/java/com/prometheus/spigot/listeners/BlockPlaceListener.java b/src/main/java/com/prometheus/spigot/listeners/BlockPlaceListener.java new file mode 100644 index 0000000..b09175f --- /dev/null +++ b/src/main/java/com/prometheus/spigot/listeners/BlockPlaceListener.java @@ -0,0 +1,19 @@ +package com.prometheus.spigot.listeners; + +import com.prometheus.spigot.metrics.MetricsRegistry; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.block.BlockPlaceEvent; + +public final class BlockPlaceListener implements Listener { + private final MetricsRegistry registry; + + public BlockPlaceListener(MetricsRegistry registry) { + this.registry = registry; + } + + @EventHandler + public void onBlockPlace(BlockPlaceEvent event) { + registry.incrementBlocksPlaced(event.getBlockPlaced().getType()); + } +} diff --git a/src/main/java/com/prometheus/spigot/listeners/CraftListener.java b/src/main/java/com/prometheus/spigot/listeners/CraftListener.java new file mode 100644 index 0000000..dfdf80e --- /dev/null +++ b/src/main/java/com/prometheus/spigot/listeners/CraftListener.java @@ -0,0 +1,25 @@ +package com.prometheus.spigot.listeners; + +import com.prometheus.spigot.metrics.MetricsRegistry; +import org.bukkit.Material; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.CraftItemEvent; +import org.bukkit.inventory.ItemStack; + +public final class CraftListener implements Listener { + private final MetricsRegistry registry; + + public CraftListener(MetricsRegistry registry) { + this.registry = registry; + } + + @EventHandler + public void onCraft(CraftItemEvent event) { + ItemStack result = event.getRecipe() != null ? event.getRecipe().getResult() : null; + if (result == null || result.getType() == Material.AIR) { + return; + } + registry.incrementItemsCrafted(result.getType()); + } +} diff --git a/src/main/java/com/prometheus/spigot/listeners/EntityKillListener.java b/src/main/java/com/prometheus/spigot/listeners/EntityKillListener.java new file mode 100644 index 0000000..40797cb --- /dev/null +++ b/src/main/java/com/prometheus/spigot/listeners/EntityKillListener.java @@ -0,0 +1,22 @@ +package com.prometheus.spigot.listeners; + +import com.prometheus.spigot.metrics.MetricsRegistry; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityDeathEvent; + +public final class EntityKillListener implements Listener { + private final MetricsRegistry registry; + + public EntityKillListener(MetricsRegistry registry) { + this.registry = registry; + } + + @EventHandler + public void onEntityDeath(EntityDeathEvent event) { + Player killer = event.getEntity().getKiller(); + String killerLabel = killer != null ? killer.getName() : "null"; + registry.incrementEntityKill(event.getEntity().getType(), killerLabel); + } +} diff --git a/src/main/java/com/prometheus/spigot/metrics/MetricsRegistry.java b/src/main/java/com/prometheus/spigot/metrics/MetricsRegistry.java index 6e78d60..14e1b24 100644 --- a/src/main/java/com/prometheus/spigot/metrics/MetricsRegistry.java +++ b/src/main/java/com/prometheus/spigot/metrics/MetricsRegistry.java @@ -44,11 +44,14 @@ public final class MetricsRegistry { private final LongAdder chunkGenerations = new LongAdder(); private final LongAdder pluginEnables = new LongAdder(); private final LongAdder pluginDisables = new LongAdder(); + private final ConcurrentHashMap blocksPlacedByMaterial = new ConcurrentHashMap<>(); private final ConcurrentHashMap blocksBrokenByMaterial = new ConcurrentHashMap<>(); private final ConcurrentHashMap deathsByCause = new ConcurrentHashMap<>(); private final ConcurrentHashMap loginFailuresByReason = new ConcurrentHashMap<>(); private final ConcurrentHashMap commandsBlocked = new ConcurrentHashMap<>(); private final ConcurrentHashMap commandsExecuted = new ConcurrentHashMap<>(); + private final ConcurrentHashMap itemsCraftedByMaterial = new ConcurrentHashMap<>(); + private final ConcurrentHashMap entityKills = new ConcurrentHashMap<>(); public MetricsRegistry(Server server, boolean enableJvm, boolean enableProcess) { this.server = server; @@ -85,6 +88,10 @@ public final class MetricsRegistry { incrementLabeledCounter(blocksBrokenByMaterial, material.name()); } + public void incrementBlocksPlaced(Material material) { + incrementLabeledCounter(blocksPlacedByMaterial, material.name()); + } + public void incrementPlayerDeath(EntityDamageEvent.DamageCause cause) { incrementLabeledCounter(deathsByCause, cause.name()); } @@ -123,6 +130,16 @@ public final class MetricsRegistry { pluginDisables.increment(); } + public void incrementItemsCrafted(Material material) { + incrementLabeledCounter(itemsCraftedByMaterial, material.name()); + } + + public void incrementEntityKill(EntityType entityType, String killer) { + String normalizedEntity = normalizeLabel(entityType.name()); + String normalizedKiller = normalizeLabel(killer); + entityKills.computeIfAbsent(new LabelPair(normalizedEntity, normalizedKiller), key -> new LongAdder()).increment(); + } + public void refreshEntitySnapshots() { Map entityCounts = new HashMap<>(); Map tileCounts = new HashMap<>(); @@ -168,10 +185,13 @@ public final class MetricsRegistry { appendCounter(builder, "spigot_plugin_disable_total", "Total plugin disable events", pluginDisables.sum()); appendLabeledCounterAdder(builder, "spigot_blocks_broken_total", "Blocks broken by material", "material", blocksBrokenByMaterial); + appendLabeledCounterAdder(builder, "spigot_blocks_placed_total", "Blocks placed by material", "material", blocksPlacedByMaterial); appendLabeledCounterAdder(builder, "spigot_player_deaths_total", "Player deaths by cause", "cause", deathsByCause); appendLabeledCounterAdder(builder, "spigot_player_logins_failed_total", "Failed player logins by reason", "reason", loginFailuresByReason); appendLabeledCounterAdder(builder, "spigot_commands_blocked_total", "Blocked commands by name", "command", commandsBlocked); appendLabeledCounterAdder(builder, "spigot_commands_executed_total", "Commands executed by source", "command", "source", commandsExecuted); + appendLabeledCounterAdder(builder, "spigot_items_crafted_total", "Items crafted by material", "material", itemsCraftedByMaterial); + appendLabeledCounterAdder(builder, "spigot_entities_killed_total", "Entities killed by player", "entity", "killer", entityKills); appendGauge(builder, "spigot_players_online", "Online player count", server.getOnlinePlayers().size()); appendGauge(builder, "spigot_players_max", "Max player slots", server.getMaxPlayers());