Commit 7166590
feat: Anonymous usage telemetry (#386)
* docs: add telemetry design document
Describes what data is collected, opt-out mechanisms, storage,
batched transmission strategy, and implementation details for a
simple per-command telemetry system.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: implement telemetry collection and submission
Replace the placeholder tracing-based telemetry layer with a full
implementation that records anonymous usage data (command, flags,
duration, outcome) to a local events.jsonl file and periodically
ships batches to an ingestion endpoint via a detached background
process. Add `icp settings telemetry` command and `telemetry_enabled`
user setting for opt-out control.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: detach telemetry send process from parent process group
Use process_group(0) on Unix and CREATE_NO_WINDOW on Windows so the
background send process survives if the parent CLI process is killed
or the terminal is closed.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: adopt clap-based argument sanitization for telemetry
Replace raw flag-name collection with structured argument extraction
using clap's ArgMatches introspection. Each argument now records its
name, source (command-line vs environment variable), and value — but
only when the value comes from a constrained possible_values set.
Free-form values (paths, principals, etc.) are always null to prevent
leaking sensitive data.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add batch ID and sequence numbers to telemetry payloads
Generate a batch UUID when rotating events.jsonl and embed it in the
batch filename (batch-<timestamp>-<uuid>.jsonl). At send time, inject
the batch UUID and a per-record sequence number into each JSON line.
This enables server-side deduplication on retried sends and preserves
event ordering within a batch.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: move telemetry setup logic from main.rs into telemetry.rs
Move setup_telemetry() and command_telemetry_name() into the telemetry
module so main.rs only has a single-line call to telemetry::setup().
Narrow visibility of is_disabled_by_env, show_notice_if_needed, and
collect_arguments to private since they are now internal to the module.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: remove timestamp from telemetry records
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: collect identity storage type in telemetry records
Introduce a TelemetryData bag in Context that subsystems can write to
during command execution. The identity loader now records the storage
type (pem/keyring/hsm/anonymous) when loading an identity, and the
telemetry session reads it at finish time to include in the record.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: collect managed network info in telemetry records
- Add `NetworkType` (managed/connected) to `TelemetryData`; set it in
`Context::get_environment` and `Context::get_network` so any command
that resolves a network contributes the value automatically.
- Add `autocontainerize` setting value to `TelemetrySession`; captured
once in `telemetry::setup` alongside the existing telemetry-enabled
check, avoiding a second settings load.
- Both fields are omitted from the JSON record when absent
(`skip_serializing_if = "Option::is_none"`).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat: collect canister count and registry recipes in telemetry records
- Add `CanisterSource` field to `Canister` to track whether it was
defined with explicit build/sync steps or via a recipe reference
- Record `num_canisters` and `recipes` (registry recipe names) as flat
fields on `TelemetryRecord` instead of a nested `CanistersTelemetry`
object, making the data easier to query in the telemetry table
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* refactor: derive telemetry command name from clap subcommand traversal
Replace the exhaustive `command_name()` match with automatic command
name derivation by collecting subcommand names while walking ArgMatches,
eliminating boilerplate that had to be updated for every new command.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: rename os to platform with WSL detection, reorder telemetry record fields
Rename the `os` field to `platform` and detect WSL via the
WSL_DISTRO_NAME env var so it reports "wsl" instead of "linux".
Reorder TelemetryRecord fields into logical groups and update
telemetry.md to match the current struct (add new fields, remove
timestamp, fix recipes example).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: add telemetry integration tests and settings telemetry tests
- Change TELEMETRY_ENDPOINT to https://telemetry.invalid/v1/events
(.invalid TLD per RFC 2606, never resolves, sends fail silently)
- Add ICP_TELEMETRY_ENDPOINT env var override for integration testing
- Add telemetry_tests.rs covering the full control-flow pipeline:
opt-out env vars (DO_NOT_TRACK, ICP_TELEMETRY_DISABLED, CI),
record append, first-run notice, time/size send triggers,
no-rotation guard, batch delivery, stale/excess batch cleanup,
and machine-id persistence across invocations
- Add settings telemetry tests to settings_tests.rs mirroring the
existing autocontainerize test set (default, set-false, set-true,
persists)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix
* apply review suggestions
* feat(telemetry): record UTC date per event for timeseries analysis
Add a `date` field (YYYY-MM-DD, UTC) to TelemetryRecord so events can be
analyzed as a timeseries. The ClickHouse schema should use the Date type
(2 bytes) rather than DateTime. Test verifies the field is present and
matches today's UTC date.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>1 parent 481f484 commit 7166590
File tree
18 files changed
+1708
-134
lines changed- crates
- icp-cli
- src
- commands
- tests
- icp/src
- context
- identity
- manifest
- docs
- reference
18 files changed
+1708
-134
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
18 | 18 | | |
19 | 19 | | |
20 | 20 | | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
21 | 25 | | |
22 | 26 | | |
23 | 27 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
67 | 67 | | |
68 | 68 | | |
69 | 69 | | |
| 70 | + | |
70 | 71 | | |
71 | 72 | | |
72 | 73 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
18 | 18 | | |
19 | 19 | | |
20 | 20 | | |
| 21 | + | |
| 22 | + | |
21 | 23 | | |
22 | 24 | | |
23 | 25 | | |
| |||
26 | 28 | | |
27 | 29 | | |
28 | 30 | | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
29 | 37 | | |
30 | 38 | | |
31 | 39 | | |
| 40 | + | |
32 | 41 | | |
33 | 42 | | |
34 | 43 | | |
| |||
65 | 74 | | |
66 | 75 | | |
67 | 76 | | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
0 commit comments