From dc539e83d137ff72741c92805acd4c340496f3f3 Mon Sep 17 00:00:00 2001 From: Dylan Garvis Date: Tue, 27 Jan 2026 22:34:59 -0500 Subject: [PATCH 1/2] feat: add block place and craft metrics --- .../spigot/PrometheusSpigotPlugin.java | 4 +++ .../spigot/listeners/BlockPlaceListener.java | 19 ++++++++++++++ .../spigot/listeners/CraftListener.java | 25 +++++++++++++++++++ .../spigot/metrics/MetricsRegistry.java | 12 +++++++++ 4 files changed, 60 insertions(+) create mode 100644 src/main/java/com/prometheus/spigot/listeners/BlockPlaceListener.java create mode 100644 src/main/java/com/prometheus/spigot/listeners/CraftListener.java diff --git a/src/main/java/com/prometheus/spigot/PrometheusSpigotPlugin.java b/src/main/java/com/prometheus/spigot/PrometheusSpigotPlugin.java index 55b33b0..6d0cb98 100644 --- a/src/main/java/com/prometheus/spigot/PrometheusSpigotPlugin.java +++ b/src/main/java/com/prometheus/spigot/PrometheusSpigotPlugin.java @@ -2,10 +2,12 @@ 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.MoveListener; import com.prometheus.spigot.listeners.PluginListener; @@ -71,6 +73,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 +81,7 @@ 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); } 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/metrics/MetricsRegistry.java b/src/main/java/com/prometheus/spigot/metrics/MetricsRegistry.java index 6e78d60..693f73b 100644 --- a/src/main/java/com/prometheus/spigot/metrics/MetricsRegistry.java +++ b/src/main/java/com/prometheus/spigot/metrics/MetricsRegistry.java @@ -44,11 +44,13 @@ 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<>(); public MetricsRegistry(Server server, boolean enableJvm, boolean enableProcess) { this.server = server; @@ -85,6 +87,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 +129,10 @@ public final class MetricsRegistry { pluginDisables.increment(); } + public void incrementItemsCrafted(Material material) { + incrementLabeledCounter(itemsCraftedByMaterial, material.name()); + } + public void refreshEntitySnapshots() { Map entityCounts = new HashMap<>(); Map tileCounts = new HashMap<>(); @@ -168,10 +178,12 @@ 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); appendGauge(builder, "spigot_players_online", "Online player count", server.getOnlinePlayers().size()); appendGauge(builder, "spigot_players_max", "Max player slots", server.getMaxPlayers()); From aca7a81ad30da26b6bb12fac2d56fa6ee7c8edfb Mon Sep 17 00:00:00 2001 From: Dylan Garvis Date: Tue, 27 Jan 2026 22:41:32 -0500 Subject: [PATCH 2/2] feat: track entity kills by player --- .../spigot/PrometheusSpigotPlugin.java | 2 ++ .../spigot/listeners/EntityKillListener.java | 22 +++++++++++++++++++ .../spigot/metrics/MetricsRegistry.java | 8 +++++++ 3 files changed, 32 insertions(+) create mode 100644 src/main/java/com/prometheus/spigot/listeners/EntityKillListener.java diff --git a/src/main/java/com/prometheus/spigot/PrometheusSpigotPlugin.java b/src/main/java/com/prometheus/spigot/PrometheusSpigotPlugin.java index 6d0cb98..7a1cc3d 100644 --- a/src/main/java/com/prometheus/spigot/PrometheusSpigotPlugin.java +++ b/src/main/java/com/prometheus/spigot/PrometheusSpigotPlugin.java @@ -9,6 +9,7 @@ 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; @@ -82,6 +83,7 @@ public final class PrometheusSpigotPlugin extends JavaPlugin { 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/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 693f73b..14e1b24 100644 --- a/src/main/java/com/prometheus/spigot/metrics/MetricsRegistry.java +++ b/src/main/java/com/prometheus/spigot/metrics/MetricsRegistry.java @@ -51,6 +51,7 @@ public final class MetricsRegistry { 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; @@ -133,6 +134,12 @@ public final class MetricsRegistry { 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<>(); @@ -184,6 +191,7 @@ public final class MetricsRegistry { 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());