Skip to content

feat: KV-store player-stats snapshots (Spigot + Forge) - #27

Open
shiftySenpai wants to merge 23 commits into
splunk:developfrom
shiftySenpai:pr3-kvstore-player-stats
Open

feat: KV-store player-stats snapshots (Spigot + Forge)#27
shiftySenpai wants to merge 23 commits into
splunk:developfrom
shiftySenpai:pr3-kvstore-player-stats

Conversation

@shiftySenpai

Copy link
Copy Markdown

Summary

Split out of #23 (KV-store slice). Stacked on #24 (build/deps) and #25 (extended logging) — this branch includes both, so the diff below will look large until those merge, after which GitHub will automatically shrink it to just this PR's commits.

  • Adds PlayerStatsScraper + KvStoreConnection (Spigot): periodically snapshots per-player stats/advancements into a Splunk KV-store collection (minecraft_player_stats), shipped in a new SplunkCraft app. HEC can only write to an index, not a KV store, hence the separate direct-REST connector.
  • Ports the extended-logging categories (Combat/Item/Progression/Server/Performance) and the KV-store scraper to Forge 1.20.1, which previously only had the original block/death/player loggers — Forge's event-bus API shares nothing with Bukkit beyond the platform-agnostic shared-mc core, so this is a full parallel implementation, not a refactor. Two Forge API gaps are documented inline rather than approximated (no per-orb XP-change event, no enchant-item event); hunger/weather-change are polled each tick since Forge has no direct event for either.

These two commits are combined in one PR because the Forge commit adds the module from scratch in a single atomic change spanning both feature areas — splitting it further would leave an intermediate state that doesn't build.

Test plan

  • mvn clean package for Spigot/shared-mc (not verified in this environment — no local Maven install; please build-check before merging)
  • forge-1.20.1-47.4.20 Gradle build (not verified in this environment)
  • Verified live against a real Forge 1.20.1 server + real player session: Combat/Item/Progression/Server/Performance events landing in the Splunk HEC index; KV-store upserts confirmed via direct REST GET and | inputlookup minecraft_player_stats — carried over from Extend Minecraft event logging, add KV-store player stats, modernize deps #23's test plan

Part of the #23 split.

Extract buildHecEnvelope() helper in SingleSplunkConnection using gson
(already a shared-mc dependency) instead of the unmaintained json-simple
1.1 library. Wire format is unchanged: {"event": <message>}. Adds unit
tests covering basic wrapping and quote escaping, and removes the
json-simple dependency from shared-mc/pom.xml and the parent pom's
dependencyManagement.
…'d deps

Adds per-platform MC-version Maven profiles (spigot: 1.21.1 default plus
1.20.1/1.20.4/1.20.6), a shade-plugin build producing
logtosplunk-<mc.version>-<loader>-<loader.version>.jar per module, and marks
server-provided deps (log4j, spigot-api) as provided scope so they aren't
shaded into the plugin jar. Pins kotlin-stdlib to 2.0.21 to clear
CVE-2026-53914 pulled in transitively via splunk-library-javalogging ->
okhttp3 -> kotlin-stdlib:1.6.20. Tunes the OWASP dependency-check plugin to
skip provided-scope CVEs (server operator's responsibility) and not fail on
Sonatype OSS Index 401s (paid-only), while still enforcing the CVSS 7.0 gate.
…ments writeup

Adds repo-convention javadoc to all new/modified classes from the extended-logging
feature (combat/item/progression/server/performance/session-detail), explaining the
non-obvious bits: throttle rationale, ENABLE_* toggle gating, Paper-only API gaps
(TPS/MSPT/protocol-version), and why combat kills don't duplicate DeathEventLogger.
Adds a PR description and a comprehensive enhancements writeup for review.
… player snapshots

Periodically reads <world>/stats/<uuid>.json + <world>/advancements/<uuid>.json
and upserts one flattened document per player into a Splunk KV-store
collection, keyed by UUID for idempotent overwrite. This is current-state
snapshot data, not a time series, so it deliberately does not go through
HEC -- HEC can only write to an index, never a KV store. KvStoreConnection
talks to the splunkd management REST endpoint (port 8089, HTTPS, bearer
token auth) instead, a different port and credential than HEC.

Runs async via ScheduledMetricLogger#startAsync so the file I/O + HTTP
never stalls a server tick. New splunk.craft.enable.playerstats /
splunk.craft.kvstore.* config keys, all opt-in and documented inline in
the splunk.properties template.

The SplunkCraft app ships the minecraft_player_stats collection and its
transforms.conf lookup definition, so the data is queryable via
`| inputlookup minecraft_player_stats`.
Forge/NeoForge/Fabric only ever had the original block/death/player
loggers -- the Combat/Item/Progression/Server/Performance categories and
the KV-store PlayerStatsScraper (added on the spigot/paper side across
prior commits) were never ported, since Forge's event-bus API shares
nothing with Bukkit beyond the platform-agnostic shared-mc core.

Ports all five categories plus PlayerStatsScraper/KvStoreConnection to
forge-1.20.1-47.4.20, gated by the same splunk.craft.enable.* toggles as
spigot. Two Forge API gaps, documented inline rather than approximated:
- no per-orb XP-change event (only PlayerXpEvent.LevelChange exists), so
  exp_change is omitted;
- no enchant-item event, so enchant is omitted.
Hunger and weather-change also have no direct Forge event, so both are
polled each tick and reported only on actual change (same pattern already
used for move-sampling in the existing Forge PlayerEventLogger).

Verified against a live Forge 1.20.1 server with a real player session:
Combat (damage/heal/hunger)/Item (pickup)/Progression (craft)/Server
(start/weather)/Performance events all landed in the Splunk HEC index,
and the KV-store scraper's upserts were confirmed via a direct REST GET
against the minecraft_player_stats collection.

NeoForge and Fabric still have the original gap; not addressed here.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant