Skip to main content
Daniel McCoy Stephenson

Usage reporting

This page is for anyone who runs one of the programs that report to trace — a Minecraft server owner with a Dans-Plugins plugin installed, someone playing a Preponderous game, someone self-hosting a Stephenson-Software tool. It says what leaves your machine, what does not, who receives it, and how to stop it. Reporting is on by default in every program that reports; the programs people run also print a line at startup saying so and pointing here.

See the figures: trace.danielstephenson.dev shows, with no sign-in, every program that has reported, how many events it has sent and when it was last heard from. Usage on this site shows the last 30 days for each of these projects.

Turn it off: set TRACE_USAGE_REPORTING=off or DO_NOT_TRACK=1 in the environment — every way to turn it off.

What is sent

One small JSON document per event, sent with the program’s key as an Authorization: Bearer header and a User-Agent: trace-client/<version> (<program>) header (trace-client-python/…, trace-client-js/… and trace-client-cpp/… from those clients), and nothing else. The client is one source file with no dependencies, so the whole of what it can send is the json(...) method in TraceClient.java (the same file every Java program vendors; the Python, JavaScript, C# and C++ clients build the same shape). It has four fields:

application
The program’s name — MedievalFactions, roam, gh-backup.
name
The event — almost always startup, or command when a top-level command was run; page-view from a website. A few programs use one or two more (world-loaded, backup-completed).
value
An optional number. Most programs send none, or 1.
tags
A flat map of short strings: version = the program’s version, and for a command event name = the command’s name (/mf, not what came after it). Websites add page = the path viewed, never a query string. Self-hosted services add service=true; automated test servers add ci=true. install = a random per-installation ID (a UUID the client generates and keeps in the program’s own file — plugins/trace/config.yml on a Spigot server — so installations can be counted rather than events; delete it to get a new one, and no ID is made up while reporting is off).

On receipt the server adds a timestamp. That is the whole record: what is stored is exactly those fields plus an id and the time it arrived.

What is never sent

  • Nothing about players: no names, UUIDs, chat, or counts.
  • Nothing about worlds, saves, or game state.
  • Nothing about the server: no address, port, MOTD, player list, or the other plugins installed.
  • Nothing typed after a command. A command event carries the command’s name; its arguments are never read by the client.
  • Nothing about the machine: no hardware, operating system, Java version, locale, or hostname.

The IP address the report arrived from is not stored. The stored record has no column for it, and the endpoint that records a report reads only the JSON body and the program the key resolved to — it never consults the connection’s address or the request headers beyond the Authorization header that carries the key. The service also keeps no HTTP access log of its own. (Like any web server, the reverse proxy in front of the deployment writes ordinary per-request access logs to its container output; none of that reaches trace’s database or the public stats.)

Who receives it, and what it is used for

Reports go to https://trace.danielstephenson.dev, a single-operator service run by the author of these programs (Daniel Stephenson); what it holds is readable by anyone at trace.danielstephenson.dev, while the individual events and the operator’s dashboard need a sign-in. It exists to answer one question: which of these programs are actually in use, and on which versions — so that maintenance effort goes where people are, and a program nobody runs can be retired instead of kept alive. The data is not sold, not shared with anyone, and not used for advertising or profiling; there is no one to share it with. The public stats page shows the same totals the author looks at.

How to turn it off

Every one of these works on its own; the first that applies wins, and the program’s startup line says which.

  1. Environment, for every program at once: set TRACE_USAGE_REPORTING=off (also false, 0, no) or DO_NOT_TRACK=1 (also true, yes; see consoledonottrack.com) in the environment the program starts in. Honoured by every program on client 0.2.0 or newer.
  2. Server-wide, for every plugin on a Spigot server: set enabled: false in plugins/trace/config.yml. The first reporting plugin to start creates that file; every reporting plugin on the server reads it, and none of them ever turns it back on.
  3. Per plugin: set usage-reporting.enabled: false in that plugin’s own config.yml.
  4. Per program, for programs that are not Spigot plugins: each has its own flag — a settings.json key, an environment variable such as USAGE_REPORTING_ENABLED=false, or a command-line switch.

Turning it off is silent and complete: the client becomes a no-op that sends nothing, and the program behaves identically otherwise.

Keys

Each program reports with a key bundled inside it — in the plugin’s config.yml, or in the program’s own configuration. Because these programs ship publicly, the key is public too. It identifies the program (so a report cannot claim to be from a different one) and it can be revoked (so a misbehaving build can be cut off); it does not authenticate anything, grants nothing but the right to say “I ran”, and cannot read any data back.

Retention

Raw events are kept for 12 months, after which only per-program monthly totals are retained. Nothing is ever shared, at any age. The software does this itself: once a day, every raw event older than trace.retention.months (12) is folded into a row per program, event name and UTC month — a count and the newest timestamp, nothing else — and deleted. The exact instant, the value and the tags of an aged event are gone for good. Events from CI servers, hosted services and website page views (the three kinds the public figures leave out) are dropped at that point rather than totalled. The job is trace.retention.enabled (on).

Public stats

trace.danielstephenson.dev (also at /stats) shows, for every program that has reported: its name, how many events it has sent in total, and when it was last heard from. It needs no login, is read straight from the same database, and leaves out only what is not a real installation: events from automated test servers (tagged ci), from services the author hosts himself (tagged service), and website page views (tagged page). The JSON behind it is GET /api/public/summary, in the same shape as the operator’s /api/metrics/summary, recomputed at most once a minute. One difference: the public lastSeen is cut to the hour. The operator’s summary keeps the instant; a reader needs no more than the hour to see whether a program is in use, and an exact time could be matched against one server’s own restart.

GET /api/public/programs/{name} is one program’s figures, for a page about it elsewhere (a dansplugins.com resource page), under the same exclusions:

{
  "application": "MedievalFactions",
  "lastSeen": "2026-10-03T14:00:00Z",
  "window": "P30D",
  "startups30d": 412,
  "activeInstalls30d": 57,
  "versions": [
    {"version": "6.1.0", "installs": 41, "startups": 300},
    {"version": "6.0.0", "installs": 16, "startups": 112}
  ],
  "days": [{"day": "2026-09-04", "startups": 11}, {"day": "2026-09-05", "startups": 0}]
}
  • lastSeen is the newest event of any name, raw or rolled up, to the hour — as in the summary, so it may be older than the window.
  • The window is the last 30 UTC calendar days including today, from midnight; startups30d, versions and days count startup events in it, and days has all 30 days, oldest first, zeroes included.
  • activeInstalls30d is how many distinct install tag values events in the window carried. Clients new enough send a random id per server under that tag; older ones send none, and a window in which no event carried one answers null, not 0. The ids are counted in the database and never served.
  • versions lists at most 10, most startups first. installs is how many installations’ latest startup in the window was that version, so a server that upgraded counts once, under its new build; null when none of that version’s startups carried an install tag. Startups with no version tag are one row with "version": null.

Each program’s answer is recomputed at most once a minute, and only for a name that is a registered program with a live key: an unknown name, a revoked one and one that has never reported anything public all answer the same 404.

The full list

Every program that has reported is listed on trace.danielstephenson.dev. The complete register — every program that reports, the events each sends, and its exact opt-out flag — is kept with trace’s own documentation, which is not public.