Skip to content

Add minimal, anonymous usage telemetry #283

Description

@sdairs

Add usage telemetry to clickhousectl

Default-on telemetry with first-run notice and easy opt-out, to measure local/offline adoption. Consent model follows Homebrew: nothing is ever sent before the notice has been shown.

Consent & state

  • State lives in telemetry.json in the existing config dir, single key: {"disabled": false}. The file doubles as the first-run marker.
  • First run (file absent): print notice, write file, send nothing, continue as normal.
  • Subsequent runs: disabled: false → send; disabled: true → fully silent.
  • DO_NOT_TRACK env var (donottrack.sh spec) is checked first and overrides everything: no notice, no file write, no send. If later unset and no file exists, the first-run flow applies then.
  • Config dir unwritable → fail open to disabled: no send, no error, no repeated notice. We only send if we successfully recorded that the notice was shown.
  • Notice prints to stderr (stdout stays machine-parseable), regardless of TTY — otherwise agent/non-interactive usage never triggers the notice and is never measured.
  • clickhousectl telemetry disable|enable|status subcommand toggles the file; this is what the notice references.

Notice content

Four things only: what's collected (command + flag names, never values), why, both off switches (clickhousectl telemetry disable, DO_NOT_TRACK=1), docs URL.

Payload

  • Command path (e.g. local start)
  • Flag names only — never flag values, never positional args. Build payload from clap definitions, not env::args(), so leaking values is structurally impossible. Document this.
  • Exit success/failure
  • Agent detection via existing is-ai-agent
  • CI boolean (CI env var) so pipelines can be filtered from adoption numbers
  • chctl version
  • os/arch

No install ID, no device ID, no fingerprinting, etc.

Transport

  • Detached child process: parent exits immediately; child fires one POST with 1–2s timeout, all stdio nulled, dies silently on any failure. Zero latency impact, zero disk writes.
  • Telemetry is forwarded to a clickhouse.com address served via Cloudflare.

Transparency

  • CHCTL_TELEMETRY_DEBUG=1 → print exact payload to stderr, send nothing.
  • Public docs page: what's collected, why, retention, all opt-out methods. Publish before release; announce in changelog.
  • Build-time cargo feature flag to compile telemetry out entirely (for distro packagers).

Acceptance criteria

  • First run sends nothing, shows notice once, creates telemetry.json
  • DO_NOT_TRACK=1 → fully silent, nothing written or sent
  • telemetry disable/enable/status works and persists
  • Payload contains no flag values or positional args (test against clap fixture)
  • Command latency unaffected with endpoint unreachable/blackholed
  • Debug mode prints payload without sending
  • Telemetry compiles out via feature flag

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions