Metrics and telemetry

Metrics are opt-in for developers: nothing is included unless the consumer adds keystone-metrics. A chart is declared once and can be sent to bStats, bwmp telemetry or a custom MetricsSink.

<dependency>
    <groupId>dev.bwmp</groupId>
    <artifactId>keystone-metrics</artifactId>
</dependency>
KeystoneMetrics metrics = KeystoneMetrics.builder(keystone)
    .bstats(28123)
    .telemetry("https://plugins.metrics.bwmp.dev", "example")
    .chart(Chart.singleLine("items", registry::size))
    .chart(Chart.simplePie("storage", settings::storageType))
    .start();

metrics.chart(Chart.singleLine("addons", addons::size));

Charts may be added after start(), which is useful when another plugin registers an extension after your plugin has enabled.

Chart types

simplePieCallable<String>

One labelled value.

advancedPieCallable<Map<String, Integer>>

Several labelled counts.

drilldownPienested labelled counts

Two levels of grouping.

singleLineCallable<Integer>

One numeric value over time.

multiLineCallable<Map<String, Integer>>

Several numeric series.

simpleBarCallable<Map<String, Integer>>

One count per bar.

advancedBarCallable<Map<String, int[]>>

Several values per bar.

Keystone adds its version, the probe-detected server brand and Folia status automatically.

Server-owner controls

The first telemetry-enabled consumer creates plugins/Keystone/telemetry.yml:

enabled: true
server-id: "random UUID generated on first run"

Setting enabled: false disables Keystone telemetry for every consumer on that server. Disabling bStats in plugins/bStats/config.yml also disables Keystone telemetry, so one global refusal covers both systems. Deleting server-id causes a new random id to be created on the next clean setup; the id is not derived from the host.

The telemetry header documents the payload: plugin and version, server software and Minecraft version, Java/OS/architecture, core and player counts, online mode, and declared charts. It does not send addresses, player names, player UUIDs or world data.

Relocation requirement

bStats checks that it has been relocated and refuses to start otherwise. keystone-parent includes the org.bstats. relocation automatically. If you override the entire relocation list for the Paper-only Adventure build, copy the bStats relocation into the replacement list.

Custom sinks

Implement MetricsSink, register it through .sink(yourSink), and accept each Chart in add. Close network clients or executors from the sink's close() method. KeystoneMetrics itself is registered with the Keystone handle and closes its sinks during shutdown.

Chart callables should return current aggregate values quickly and must not perform a database or network round trip. Telemetry samples charts on the server thread and submits the network request asynchronously; a sink failure is logged and isolated rather than stopping the consumer plugin. Verify server-owner opt-out with the generated telemetry settings before adding custom charts.