Skip to content

Releases: gzimbric/TickScope

TickScope v1.5.0

Choose a tag to compare

@gzimbric gzimbric released this 05 Sep 19:35

Changes

  • Collection health is now visible even when scrapes succeed. New freshness timestamps,
    enabled-stage gauges, and failure counters distinguish a working HTTP endpoint from a
    stalled collector. /tickscope status also reports collection age and failures.
  • Eight ready-to-use Prometheus alerts cover unreachable exporters, stale collections and
    world scans, sustained low Paper and Folia TPS, high regional MSPT, heap pressure, and
    incomplete Folia player sampling. The bundle includes tested hold durations and excludes
    disabled collection stages and unsupported readings.
  • Folia sampling no longer builds a queue behind a lagging player. Only one task per
    player can remain outstanding. An unfinished batch publishes its available readings when
    the next collection cycle starts, with completed and expected player counts showing the
    coverage. Expired callbacks cannot overwrite the published results.
  • Folia sample data and its generation are now published atomically, fixing a race where an
    older callback could overwrite a newer reading after passing the generation check.
  • World exclusions and an entity-type allowlist let operators narrow collection scope.
    exclude-worlds skips named worlds before scanning; entity-types.allowlist limits the
    per-type series while preserving full entity totals for included worlds.
  • The Grafana dashboard now includes server names in legends, collection age, collection
    failures, and Folia player coverage. An additional per-server overview repeats a row for
    each selected backend.
  • Malformed YAML and missing configuration files now reject a reload instead of silently
    applying defaults, including an empty authentication token. Oversized port values are
    rejected before integer conversion can turn them into a different valid port.
  • Reloading or disabling TickScope now closes active and queued HTTP connections, including
    clients that never read the response. Shutdown no longer leaves those sockets waiting
    after their deadline watchdog has stopped.
  • Disabling world metrics or narrowing filters removes the corresponding cached series
    immediately. Still-enabled cached readings survive a reload until the next scan.
  • Scheduled collection exceptions retain the last snapshot, increment failure counters,
    and retry on the next cycle. Health readings remain available independently of snapshot
    publication.

Upgrading: existing configuration files continue to work; the new filters default to
including every world and entity type. Add the optional settings manually to use them, and
re-import the dashboard to see the new panels. Collection-health timestamps and failure
counters reset on configuration reload. Folia ping and regional summaries can now represent
partial batches, so consult the coverage metrics alongside them. The default alert thresholds
assume the standard collection intervals; adjust them if you sample less often. Alertmanager
must be configured separately to deliver notifications. Setup instructions and metric semantics
are in the monitoring guide.

Full changelog: v1.4.0...v1.5.0

TickScope v1.4.0

Choose a tag to compare

@gzimbric gzimbric released this 13 Aug 00:16

Changes

  • The metrics endpoint can no longer be silenced by a stalled client. A connection that sent
    a partial request previously held the only HTTP worker indefinitely, and every scrape timed out
    until that client disconnected — with no token required, since parsing stalls before
    authentication. The endpoint now runs on its own socket with per-connection deadlines and
    recovers on its own. Still no runtime dependencies.
  • Authorization: bearer <token> is now accepted alongside Bearer, as the HTTP specification
    requires. A scrape configured with a lowercase scheme used to fail like a mistyped token.
  • Per-world entity and tile-entity totals moved to the slower scan interval
    (entity-types.interval-ticks). Counting tile entities walks every loaded chunk, and before
    Minecraft 26 counting entities walked every entity, so neither belonged on the 5-second
    collection cycle. mc_world_chunks and mc_world_players are unchanged and still sampled
    every collection.
  • These three series are now omitted on Folia rather than read from the global region, which does
    not own the world data they walk.
  • Readings the platform cannot supply are omitted instead of reported as zero. CPU load on a JVM
    that does not expose it no longer looks like an idle server, and player ping is published only
    when a player was actually measured.
  • On Folia, a batch of per-player samples that finishes late is now used rather than thrown
    away. With several regions lagging at staggered times no batch ever finished before the
    next began, so ping and regional figures could stay frozen at the last success.
  • Deaths cancelled by another plugin are no longer counted.
  • A configuration value of the wrong type is now rejected with the setting named. port: "9200"
    previously bound the default port and per-world: "false" silently stayed enabled.
  • /tickscope reload reports what actually happened, including when a rollback failed, and two
    simultaneous reloads on Folia can no longer leave an endpoint running that nothing can close.
  • The entity-type series survive a reload instead of disappearing until the next scan, and
    /tickscope status prints a valid URL for an IPv6 bind address.
  • The bundled Grafana dashboard gained a Folia regions row; its tick panels were blank on Folia,
    which is the one platform where those metrics do not exist.
  • Release jars are now reproducible, so a download can be checked against its published checksum
    by rebuilding the tag.

Upgrading: two panels can look empty after this release. mc_player_ping_avg_ms and
mc_player_ping_max_ms are absent while nobody is online, and the CPU ratios are absent on a JVM
that cannot report them, instead of both reading zero. That is the documented "missing series"
behaviour rather than a removal — add or vector(0) where a panel needs a visible zero, exactly
as the entity-type series already require. Per-world entity and tile-entity totals now refresh
every entity-types.interval-ticks (600 ticks) rather than every collection, so those graphs are
coarser; they are absent entirely on Folia.

Full changelog: v1.3.0...v1.4.0

TickScope v1.3.0

Choose a tag to compare

@gzimbric gzimbric released this 12 Aug 01:02

Changes

  • Folia and Canvas support. TickScope now runs on Folia-compatible servers and exports
    mc_folia_region_tps, sampled at the locations of online players.
  • Regional MSPT (mc_folia_region_mspt_ms) is exported where the server API exposes
    per-region tick times, which today means Canvas. Pure Folia reports regional TPS only.
  • Server-wide mc_mspt_ms and mc_tps are intentionally absent on Folia, which has no
    truthful global equivalent, rather than being reported as a misleading single number.
  • Entity-by-type metrics are disabled on Folia, where a world-wide entity walk has no
    safe scheduler to run on.
  • Release jars now ship a .sha256 file alongside them so downloads can be verified.

Still one jar for Paper and Purpur 1.18.2 through 26.2, still no runtime dependencies.

Full changelog: v1.2.2...v1.3.0

TickScope v1.2.2

Choose a tag to compare

@gzimbric gzimbric released this 09 Aug 04:14

Changes

  • Login counting moved to the async pre-login event, which the modern login pipeline is
    guaranteed to fire.
  • Added the Grafana dashboard and a security policy; long-form documentation moved to the wiki.

Full changelog: v1.2.1...v1.2.2

TickScope v1.2.1

Choose a tag to compare

@gzimbric gzimbric released this 09 Aug 02:05

What changed

  • Made /tickscope reload failure-safe while preserving process-lifetime event counters.
  • Fixed listener and HTTP executor leaks across reloads.
  • Changed fresh installs to bind to loopback by default and added endpoint validation.
  • Added build/runtime information and separate entity-scan timing metrics.
  • Added correct GET, HEAD, 404, and 405 endpoint behavior.
  • Added automated tests and CI coverage on Java 17, 21, and 25.
  • Corrected documentation for supported versions, command aliases, authentication, and Docker configuration.

One dependency-free jar supports Paper 1.18.2 through 26.2 on Java 17 or newer.

TickScope 1.2.0

Choose a tag to compare

@gzimbric gzimbric released this 08 Aug 04:12

Wider version support

One jar now covers Paper 1.18.2 through 26.2. Nothing in the exporter needed a modern API — the
only blocker was a single call in the status command. The build targets Java 17, which is Minecraft
1.18's own runtime requirement, so there is no version-specific code, no multi-module build, and no
meaningful change in size.

Verified against real 1.18.2, 1.19.4, 1.20.6, 1.21.4 and 26.2 servers: identical metric families,
identical label values, no startup warnings.

Optional bearer auth on the endpoint

The metrics endpoint has always been open, on the assumption it sits on loopback or behind a
firewall. That is not available to everyone, so auth-token in config.yml now requires
Authorization: Bearer <token> on every scrape.

It is empty by default, so nothing changes for an existing install. The comparison is
constant-time, and a refused scrape gets an empty body rather than anything describing the server.

This is not confidentiality — the endpoint is plain HTTP and the token crosses the wire in the clear.
Put a TLS-terminating reverse proxy in front if the scrape path leaves a network you control.

Fixed

Entity type labels are now the Minecraft registry name rather than the Bukkit enum name. Bukkit
realigned the enum with the registry in 1.20.5, so on older servers 18 of 114 entity types were
labelled differently — including dropped_item, which is item everywhere now. No effect on
26.2
, where the two already agree, so existing dashboards and history are untouched.

Upgrading

Drop the new jar in and restart. No configuration changes required.

TickScope 1.1.0

Choose a tag to compare

@gzimbric gzimbric released this 07 Aug 04:26

First public release.

A Prometheus exporter for Minecraft Paper servers in a 28 KB jar with zero runtime dependencies — no Spring, no Micrometer, nothing shaded. Drop it in plugins/, scrape http://127.0.0.1:9101/metrics, graph it in Grafana.

Highlights

  • Exact tick percentilesmc_mspt_ms at avg/min/max/p50/p95/p99, computed from Paper's raw per-tick nanosecond array rather than estimated from buckets. TPS caps at 20 and hides everything below it; MSPT does not.
  • Per-world counts — entities, tile entities, chunks and players, from Paper's O(1) counters.
  • Entities by typemc_world_entities_by_type{world,type}, for finding what is actually piling up.
  • JVM and process — heap and non-heap memory, threads, GC cycles and time per collector, process and system CPU.
  • Player event counters — login, join, quit, chat, death. Counters rather than gauges, so nothing is missed between scrapes.
  • Its own overhead, reported as mc_collection_duration_seconds — typically 2–3 ms.

Scrapes never touch the server thread: collection runs on a scheduler task and publishes an immutable snapshot that the HTTP handler serialises.

Requirements

Paper 26.2+, Java 25+. Purpur works. Plain Spigot and Bukkit do not, and Folia is not supported.

Docker

Set bind-address: "0.0.0.0" and restrict on the publish side with ports: ["127.0.0.1:9101:9101"]. Binding to loopback inside the container makes the port unreachable even with a correct -p mapping.

Full documentation in the README · also on Modrinth.