Skip to content

feat: Anonymous usage telemetry#386

Merged
lwshang merged 17 commits intomainfrom
lwshang/SDK-2558_telemetry_instrument
Feb 24, 2026
Merged

feat: Anonymous usage telemetry#386
lwshang merged 17 commits intomainfrom
lwshang/SDK-2558_telemetry_instrument

Conversation

@lwshang
Copy link
Contributor

@lwshang lwshang commented Feb 24, 2026

Collects command name, arguments, duration, and outcome

  • Enabled by default; opt out with icp settings telemetry false, DO_NOT_TRACK=1, or ICP_TELEMETRY_DISABLED=1
  • Automatically disabled in CI environments (CI env var set)
  • icp settings telemetry to view or change the current setting

lwshang and others added 15 commits February 23, 2026 11:18
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>
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>
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>
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>
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>
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>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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>
- 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>
- 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>
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>
… 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>
- 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>
@lwshang lwshang marked this pull request as ready for review February 24, 2026 03:10
@lwshang lwshang requested a review from a team as a code owner February 24, 2026 03:10
- IP addresses, usernames, or any personally identifiable information
- Project names, file paths, or file contents
- Canister IDs, wallet addresses, or cycle balances
- Free-form argument values (only values from constrained `possible_values` sets are recorded)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could recipe names be considered free-form values? If someone creates their own recipes it could contain some quite descriptive strings

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only "registry" recipes are recorded — recipes specified as local file paths or URLs are excluded. Registry recipes are considered public knowledge, making this field analogous to the "canister type" field in dfx.

lwshang and others added 2 commits February 24, 2026 10:52
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>
@lwshang lwshang merged commit 7166590 into main Feb 24, 2026
88 checks passed
@lwshang lwshang deleted the lwshang/SDK-2558_telemetry_instrument branch February 24, 2026 16:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants