Skip to content

Commit 20d2fe9

Browse files
authored
Add a persisted telemetry setting to mapbox config
mapbox config set telemetry off stops the run's telemetry event in every shell, beside MAPBOX_CLI_NO_TELEMETRY for one. The setting is read again at exit, so the run that turns it off does not report itself.
1 parent 18a5f2c commit 20d2fe9

7 files changed

Lines changed: 61 additions & 11 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,10 @@ that may never merge. They are not releases and are not listed here.
260260
code; it does find a `~/.mapbox/history` directory it didn't before, and
261261
`mapbox config list` now reports a second key, `history`.
262262

263+
- `mapbox config set telemetry off` turns the telemetry event off for good,
264+
in every shell, the way `MAPBOX_CLI_NO_TELEMETRY=1` does for one. The run
265+
that turns it off records nothing either. `mapbox config list` now also
266+
reports `telemetry`.
263267
- Each run sends one `cli.command` telemetry event to Mapbox, from a
264268
background process the command doesn't wait for, with your own token
265269
(`--token`, `MAPBOX_ACCESS_TOKEN` or your login) or, when you have none,

‎README.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ it, and dropped if it can't be delivered. It is sent with your own token
295295
(`--token`, `MAPBOX_ACCESS_TOKEN` or your login) when you have one, and with
296296
a token built into the CLI otherwise. A build from source has no built-in
297297
token, so with no token of your own the event is dropped.
298-
`MAPBOX_CLI_NO_TELEMETRY=1` turns it off.
298+
`MAPBOX_CLI_NO_TELEMETRY=1` or `mapbox config set telemetry off` turns it off.
299299

300300
### Diagnostics and settings
301301

‎docs/commands.md‎

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4129,6 +4129,7 @@ was set in, and stays in every future shell instead.
41294129
| `update-check` | `on` | The update notice; mirrors `MAPBOX_NO_UPDATE_CHECK` (see [Update notices](../README.md#update-notices)) |
41304130
| `history` | `on` | [Command history](../README.md#command-history), read by `mapbox history`; `MAPBOX_HISTORY=0` or `=1` overrides it for a session |
41314131
| `log` | `off` | [Diagnostic logs](../README.md#diagnostic-logs), shown by `mapbox history show`; `MAPBOX_LOG=1` or `=0` overrides it for a session. Needs `history` on: `config set log on` with history off fails with `history_required` |
4132+
| `telemetry` | `on` | The run's telemetry event; mirrors `MAPBOX_CLI_NO_TELEMETRY` (see [Privacy](../README.md#privacy)) |
41324133

41334134
### `mapbox config get`
41344135

@@ -4140,7 +4141,7 @@ than failing, the same forgiving read the update-check cache itself uses.
41404141

41414142
| Parameter | Effect |
41424143
| --- | --- |
4143-
| `<key>` | Which setting to read: `update-check`, `history` or `log`. |
4144+
| `<key>` | Which setting to read: `update-check`, `history`, `log` or `telemetry`. |
41444145

41454146
#### Examples
41464147

@@ -4179,7 +4180,7 @@ without an environment variable.
41794180

41804181
| Parameter | Effect |
41814182
| --- | --- |
4182-
| `<key>` | Which setting to change: `update-check`, `history` or `log`. |
4183+
| `<key>` | Which setting to change: `update-check`, `history`, `log` or `telemetry`. |
41834184
| `<value>` | `on` or `off`. |
41844185

41854186
#### Examples
@@ -4238,6 +4239,7 @@ mapbox config list
42384239
update-check on
42394240
history on
42404241
log off
4242+
telemetry on
42414243
```
42424244

42434245
</td><td>
@@ -4255,6 +4257,10 @@ log off
42554257
{
42564258
"key": "log",
42574259
"value": false
4260+
},
4261+
{
4262+
"key": "telemetry",
4263+
"value": true
42584264
}
42594265
]
42604266
```
@@ -4273,7 +4279,7 @@ default, a key explicitly set to the old default value does not.
42734279

42744280
| Parameter | Effect |
42754281
| --- | --- |
4276-
| `<key>` | Which setting to clear: `update-check`, `history` or `log`. |
4282+
| `<key>` | Which setting to clear: `update-check`, `history`, `log` or `telemetry`. |
42774283

42784284
#### Examples
42794285

‎src/config.rs‎

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ const CONFIG_FILE: &str = "config.json";
3333
const UPDATE_CHECK_KEY: &str = "update-check";
3434
const HISTORY_KEY: &str = "history";
3535
const LOG_KEY: &str = "log";
36-
const KEYS: &[&str] = &[UPDATE_CHECK_KEY, HISTORY_KEY, LOG_KEY];
36+
const TELEMETRY_KEY: &str = "telemetry";
37+
const KEYS: &[&str] = &[UPDATE_CHECK_KEY, HISTORY_KEY, LOG_KEY, TELEMETRY_KEY];
3738

3839
const ON: &str = "on";
3940
const OFF: &str = "off";
@@ -50,6 +51,8 @@ struct Config {
5051
history: Option<bool>,
5152
#[serde(default, skip_serializing_if = "Option::is_none")]
5253
log: Option<bool>,
54+
#[serde(default, skip_serializing_if = "Option::is_none")]
55+
telemetry: Option<bool>,
5356
}
5457

5558
fn config_path() -> Option<PathBuf> {
@@ -102,6 +105,12 @@ pub fn log_enabled() -> bool {
102105
read_config().log.unwrap_or(false)
103106
}
104107

108+
/// Whether the run's telemetry event may be recorded, per the persisted
109+
/// setting. [`crate::telemetry_event`] checks it alongside `MAPBOX_CLI_NO_TELEMETRY`.
110+
pub fn telemetry_enabled() -> bool {
111+
read_config().telemetry.unwrap_or(true)
112+
}
113+
105114
fn on_off(enabled: bool) -> &'static str {
106115
if enabled {
107116
ON
@@ -118,6 +127,7 @@ fn resolve(config: &Config, key: &str) -> bool {
118127
UPDATE_CHECK_KEY => update_check_setting(config),
119128
HISTORY_KEY => config.history.unwrap_or(true),
120129
LOG_KEY => config.log.unwrap_or(false),
130+
TELEMETRY_KEY => config.telemetry.unwrap_or(true),
121131
_ => unreachable!("clap's value_parser restricts `key` to {KEYS:?}"),
122132
}
123133
}
@@ -132,6 +142,7 @@ fn clear(config: &mut Config, key: &str) {
132142
UPDATE_CHECK_KEY => config.update_check = None,
133143
HISTORY_KEY => config.history = None,
134144
LOG_KEY => config.log = None,
145+
TELEMETRY_KEY => config.telemetry = None,
135146
_ => unreachable!("clap's value_parser restricts `key` to {KEYS:?}"),
136147
}
137148
}
@@ -214,6 +225,7 @@ pub fn set(matches: &ArgMatches, mode: Mode) -> Result<()> {
214225
UPDATE_CHECK_KEY => config.update_check = Some(enabled),
215226
HISTORY_KEY => config.history = Some(enabled),
216227
LOG_KEY => config.log = Some(enabled),
228+
TELEMETRY_KEY => config.telemetry = Some(enabled),
217229
_ => unreachable!("clap's value_parser restricts `key` to {KEYS:?}"),
218230
}
219231
write_config(&config)?;

‎src/telemetry_event.rs‎

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@
1818
//!
1919
//! Best-effort throughout: nothing here can change a command's output, its
2020
//! exit code, or how long it takes to return. With telemetry off
21-
//! (`MAPBOX_CLI_NO_TELEMETRY`), nothing is built or written.
21+
//! (`MAPBOX_CLI_NO_TELEMETRY`, or `mapbox config set telemetry off`),
22+
//! nothing is built or written.
2223
2324
use std::io::IsTerminal;
2425
use std::path::Path;
@@ -332,7 +333,12 @@ fn with_workflow(f: impl FnOnce(&mut Option<Workflow>)) {
332333
/// of them — a fresh `userId` each time. Skipped for the same reason
333334
/// `run_history` skips it (aws/aws-cli#10031).
334335
pub(crate) fn deliver(record: &Record) {
335-
if !telemetry::telemetry_allowed() || std::env::var_os("SUDO_USER").is_some() {
336+
// The config setting is read at the end of the run: the run that turns
337+
// telemetry off is one that should not report itself.
338+
if !telemetry::telemetry_allowed()
339+
|| !crate::config::telemetry_enabled()
340+
|| std::env::var_os("SUDO_USER").is_some()
341+
{
336342
return;
337343
}
338344
let event = build(record);

‎tests/config.rs‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ fn list_reports_every_setting_including_an_unset_one() {
138138
assert!(empty.status.success());
139139
assert_eq!(
140140
stdout(&empty),
141-
r#"[{"key":"update-check","value":true},{"key":"history","value":true},{"key":"log","value":false}]"#
141+
r#"[{"key":"update-check","value":true},{"key":"history","value":true},{"key":"log","value":false},{"key":"telemetry","value":true}]"#
142142
);
143143

144144
let set = command(&home)
@@ -154,7 +154,7 @@ fn list_reports_every_setting_including_an_unset_one() {
154154
assert!(after.status.success());
155155
assert_eq!(
156156
stdout(&after),
157-
r#"[{"key":"update-check","value":false},{"key":"history","value":true},{"key":"log","value":false}]"#
157+
r#"[{"key":"update-check","value":false},{"key":"history","value":true},{"key":"log","value":false},{"key":"telemetry","value":true}]"#
158158
);
159159

160160
let text = command(&home)
@@ -164,7 +164,7 @@ fn list_reports_every_setting_including_an_unset_one() {
164164
assert!(text.status.success());
165165
assert_eq!(
166166
stdout(&text),
167-
"update-check off\nhistory on\nlog off"
167+
"update-check off\nhistory on\nlog off\ntelemetry on"
168168
);
169169
}
170170

‎tests/telemetry_events.rs‎

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ fn help_version_and_usage_errors_record_their_invocation() {
201201
}
202202

203203
#[test]
204-
fn the_opt_out_records_nothing() {
204+
fn either_opt_out_records_nothing() {
205205
let home = scratch("opt-out-env");
206206
let out = command(&home)
207207
.env("MAPBOX_CLI_NO_TELEMETRY", "1")
@@ -213,6 +213,28 @@ fn the_opt_out_records_nothing() {
213213
!config_dir(&home).join(".telemetry").exists(),
214214
"MAPBOX_CLI_NO_TELEMETRY=1 still wrote telemetry"
215215
);
216+
217+
// With a token and somewhere to send, so that nothing arriving is the
218+
// setting's doing.
219+
let home = scratch("opt-out-config");
220+
let (received, url) = events_server(true);
221+
let with_a_token = |args: &[&str]| {
222+
command(&home)
223+
.env("MAPBOX_INTERNAL_TELEMETRY_URL", &url)
224+
.env("MAPBOX_CLI_TOKEN", "pk.cli")
225+
.args(args)
226+
.output()
227+
.expect("run mapbox")
228+
};
229+
assert!(with_a_token(&["config", "set", "telemetry", "off"])
230+
.status
231+
.success());
232+
// That run sends nothing either: the setting it wrote is read at exit.
233+
let _ = with_a_token(&["config", "list"]);
234+
assert!(
235+
received.recv_timeout(Duration::from_secs(3)).is_err(),
236+
"`telemetry off` still sent an event"
237+
);
216238
}
217239

218240
#[test]

0 commit comments

Comments
 (0)