Every section below corresponds to specific code paths in the Rust core. The full list of events and their payloads is below.
Per-install identifier
A random UUIDv4 generated on first launch, stored locally in ~/.config/dimmy/analytics_id (or %APPDATA%\dimmy\analytics_id on Windows). It only exists to de-duplicate "1 user did X 5 times" from "5 users each did X once". Reset it any time from Settings → Privacy → Reset anonymous ID. It is never linked to anything that could identify you.
Per-process session identifier
A fresh UUIDv4 generated on each app launch, not persisted. Lets us answer questions like "how many transcriptions per session?" without tracking open or close events.
Platform context
Attached to every event:
- App version (e.g. 0.6.27).
- Operating system family (windows / macos).
- CPU architecture (x86_64 / aarch64).
Lifecycle events
app.startedWhen the app launches. Includes cold-start time in milliseconds.app.session_endedWhen the app closes. Includes total session duration (seconds) and number of transcriptions in the session.
Transcription events
transcription.completedWhen a transcription succeeds. Path (local whisper.cpp vs cloud provider), provider category (groq / openai / anthropic / gemini / deepgram / openrouter / local: only the tag, never the URL or API key), audio duration in seconds, processing time in milliseconds, word count (the number only, never the words), language ISO code (e.g. en, it), whether filler removal ran (boolean), whether LLM post-processing ran (boolean).transcription.failedProvider category and error category (e.g. 401, timeout).transcription.cancelledAudio duration up to the cancel.
LLM post-processing events
llm.appliedProvider category, style name, tone name, processing time. Never the prompt. Never the output.llm.failedProvider category and error category.
Configuration changes
When you change any of these in Settings, we log that the change happened. For free-text fields we never log the value, just that something changed.
- STT mode toggle (local ↔ cloud)
- Cloud provider switch (categorical: groq → openai, etc.)
- LLM enabled toggle
- LLM style dropdown
- Preprocessing toggle
- Input gain slider value (number)
Not tracked: prompt text, custom LLM prompt, microphone device name, shortcut combo string.
Feature usage
feature.hotkey_triggeredWhen the global hotkey starts a recording. Helps us understand whether people prefer hotkey or button.feature.api_key_setWhen you save an API key, we log the scope (stt / llm) and the provider category. The key itself never leaves your machine.
Performance + stability
perf.startup_msCold-start duration in milliseconds.perf.gpu_statusOn each launch: which GPU backend was compiled (vulkan / cuda / metal / cpu), whether the previous launch crashed during GPU init, whether a sticky known-bad marker is set.error.gpu_crashOnly on the launch immediately after a GPU crash: which backend, which call site (e.g. whisper_load: <path>, with paths scrubbed).
Counters
Atomic increment operators on a small set of cumulative per-user counters. They let us segment active users from users who installed but never tried it, without scanning every event.
- total_transcriptions
- total_transcription_failures
- total_transcriptions_cancelled
- total_llm_uses
- total_llm_failures
- total_sessions
Person properties
Attached to your anonymous-ID record so dashboards can build cohorts and retention curves.
- first_seen_at: timestamp of your first event (set once).
- first_app_version, first_os, first_arch: your install context (set once).
- latest_app_version, latest_seen_at, latest_os, latest_arch: refreshed on every event.
- latest_stt_provider, latest_stt_mode: last STT provider used.
- latest_llm_provider: last LLM provider used.
Crash reports (Sentry)
When the app crashes or hits an error path, we send to Sentry EU:
- Error message, truncated to 4 KB. Secret-shaped substrings are replaced with <redacted>.
- A Rust stack trace (function names, currently mangled in shipping builds, source-mapped in a future release).
- Platform context (OS, arch, app version, environment = production).
- The anonymous ID (so we can de-duplicate the same crash from the same user).
We do not send server name, hostname, username, environment variables (PATH, HOME, USERPROFILE and similar are stripped), IP addresses (Sentry EU drops them at ingest), file paths, microphone device names, transcripts, prompts.
Feedback form
The Settings → Send feedback form goes to Sentry as a tagged message. The text you type is included verbatim. The email field is optional and only included if you explicitly type it. We never auto-fill it from anywhere.