Skip to content

Commit 4451a6a

Browse files
committed
Updated env var to disable telemetry
1 parent 5df47de commit 4451a6a

12 files changed

Lines changed: 211 additions & 1 deletion

File tree

‎Cargo.lock‎

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎README.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ OpenShell is built agent-first — your agent is your first collaborator. Before
247247

248248
OpenShell collects anonymous telemetry to help improve the project for developers. This data is not used to track individual user behavior. It helps us understand aggregate usage of sandbox, provider, and policy workflows so we can prioritize product improvements and share usage trends with the community.
249249

250-
Disable telemetry with `OPENSHELL_TELEMETRY_ENABLED=false`. See the [telemetry schema](openshell_telemetry_schema.json) for details.
250+
Disable telemetry by setting `OPENSHELL_TELEMETRY_ENABLED=false` on the gateway deployment. OpenShell propagates this deployment setting into sandbox supervisor environments so sandbox-side telemetry collection is disabled as well. See the [telemetry schema](openshell_telemetry_schema.json) for details.
251251

252252
Telemetry events are limited to anonymous operational categories and counts, such as sandbox lifecycle outcomes, provider profile buckets, policy decision counts, and aggregate network activity denial categories. OpenShell telemetry does not collect sandbox names or IDs, hostnames, file paths, binary paths, prompts, credentials, provider names, model names, or user content.
253253

‎crates/openshell-core/src/sandbox_env.rs‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ pub const LOG_LEVEL: &str = "OPENSHELL_LOG_LEVEL";
2626
/// Shell command to run inside the sandbox.
2727
pub const SANDBOX_COMMAND: &str = "OPENSHELL_SANDBOX_COMMAND";
2828

29+
/// Deployment-controlled telemetry toggle propagated to the sandbox supervisor.
30+
pub const TELEMETRY_ENABLED: &str = "OPENSHELL_TELEMETRY_ENABLED";
31+
2932
/// Path to the CA certificate for mTLS communication with the gateway.
3033
pub const TLS_CA: &str = "OPENSHELL_TLS_CA";
3134

‎crates/openshell-core/src/telemetry.rs‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,18 @@ pub fn enabled() -> bool {
3434
telemetry_enabled_from(std::env::var("OPENSHELL_TELEMETRY_ENABLED").ok().as_deref())
3535
}
3636

37+
pub fn enabled_env_value() -> &'static str {
38+
enabled_env_value_from(std::env::var("OPENSHELL_TELEMETRY_ENABLED").ok().as_deref())
39+
}
40+
41+
fn enabled_env_value_from(value: Option<&str>) -> &'static str {
42+
if telemetry_enabled_from(value) {
43+
"true"
44+
} else {
45+
"false"
46+
}
47+
}
48+
3749
fn telemetry_enabled_from(value: Option<&str>) -> bool {
3850
let value = value.unwrap_or("true");
3951
!matches!(
@@ -405,6 +417,14 @@ mod tests {
405417
assert!(telemetry_enabled_from(Some("yes")));
406418
}
407419

420+
#[test]
421+
fn telemetry_enabled_env_value_is_normalized() {
422+
assert_eq!(enabled_env_value_from(Some("false")), "false");
423+
assert_eq!(enabled_env_value_from(Some("0")), "false");
424+
assert_eq!(enabled_env_value_from(None), "true");
425+
assert_eq!(enabled_env_value_from(Some("yes")), "true");
426+
}
427+
408428
#[test]
409429
fn telemetry_endpoint_empty_disables_publish() {
410430
assert_eq!(telemetry_endpoint_from(Some(" ")), None);

‎crates/openshell-driver-docker/Cargo.toml‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,8 @@ tar = "0.4"
2525
tempfile = "3"
2626
url = { workspace = true }
2727

28+
[dev-dependencies]
29+
temp-env = "0.3"
30+
2831
[lints]
2932
workspace = true

‎crates/openshell-driver-docker/src/lib.rs‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -970,6 +970,10 @@ fn build_environment(sandbox: &DriverSandbox, config: &DockerDriverRuntimeConfig
970970
openshell_core::sandbox_env::SANDBOX_COMMAND.to_string(),
971971
SANDBOX_COMMAND.to_string(),
972972
);
973+
environment.insert(
974+
openshell_core::sandbox_env::TELEMETRY_ENABLED.to_string(),
975+
openshell_core::telemetry::enabled_env_value().to_string(),
976+
);
973977
// The root supervisor executes namespace helpers during bootstrap; keep
974978
// their search path driver-owned even when the template/spec set PATH.
975979
environment.insert("PATH".to_string(), SUPERVISOR_PATH.to_string());

‎crates/openshell-driver-docker/src/tests.rs‎

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@ use openshell_core::proto::compute::v1::{
88
};
99
use std::fs;
1010
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
11+
use std::sync::{LazyLock, Mutex};
1112
use tempfile::TempDir;
1213

1314
const TLS_MOUNT_DIR: &str = "/etc/openshell/tls/client";
15+
static ENV_LOCK: LazyLock<Mutex<()>> = LazyLock::new(|| Mutex::new(()));
1416

1517
fn test_sandbox() -> DriverSandbox {
1618
// Mirrors the gateway-supplied request: the public `Sandbox` API no
@@ -420,6 +422,41 @@ fn build_environment_keeps_path_driver_controlled() {
420422
assert_eq!(path_entries[0], &expected_path);
421423
}
422424

425+
#[test]
426+
fn build_environment_keeps_telemetry_toggle_driver_controlled() {
427+
let _guard = ENV_LOCK.lock().unwrap();
428+
temp_env::with_vars(
429+
[(
430+
openshell_core::sandbox_env::TELEMETRY_ENABLED,
431+
Some("false"),
432+
)],
433+
|| {
434+
let mut sandbox = test_sandbox();
435+
sandbox.spec.as_mut().unwrap().environment.insert(
436+
openshell_core::sandbox_env::TELEMETRY_ENABLED.to_string(),
437+
"true".to_string(),
438+
);
439+
440+
let env = build_environment(&sandbox, &runtime_config());
441+
let telemetry_entries = env
442+
.iter()
443+
.filter(|entry| {
444+
entry.starts_with(&format!(
445+
"{}=",
446+
openshell_core::sandbox_env::TELEMETRY_ENABLED
447+
))
448+
})
449+
.collect::<Vec<_>>();
450+
451+
assert_eq!(telemetry_entries.len(), 1);
452+
assert_eq!(
453+
telemetry_entries[0],
454+
&format!("{}=false", openshell_core::sandbox_env::TELEMETRY_ENABLED)
455+
);
456+
},
457+
);
458+
}
459+
423460
#[test]
424461
fn build_binds_uses_docker_tls_directory() {
425462
let binds = build_binds(&runtime_config());

‎crates/openshell-driver-kubernetes/Cargo.toml‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,8 @@ tracing-subscriber = { workspace = true }
3434
thiserror = { workspace = true }
3535
miette = { workspace = true }
3636

37+
[dev-dependencies]
38+
temp-env = "0.3"
39+
3740
[lints]
3841
workspace = true

‎crates/openshell-driver-kubernetes/src/driver.rs‎

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1424,6 +1424,11 @@ fn apply_required_env(
14241424
openshell_core::sandbox_env::SANDBOX_COMMAND,
14251425
"sleep infinity",
14261426
);
1427+
upsert_env(
1428+
env,
1429+
openshell_core::sandbox_env::TELEMETRY_ENABLED,
1430+
openshell_core::telemetry::enabled_env_value(),
1431+
);
14271432
if !ssh_socket_path.is_empty() {
14281433
upsert_env(
14291434
env,
@@ -1592,6 +1597,9 @@ mod tests {
15921597
};
15931598
use prost_types::{Struct, Value, value::Kind};
15941599

1600+
static ENV_LOCK: std::sync::LazyLock<std::sync::Mutex<()>> =
1601+
std::sync::LazyLock::new(|| std::sync::Mutex::new(()));
1602+
15951603
#[test]
15961604
fn kube_pulling_event_adds_image_progress_metadata() {
15971605
let mut metadata = std::collections::HashMap::new();
@@ -2475,6 +2483,37 @@ mod tests {
24752483
assert!(cr["spec"].get("logLevel").is_none());
24762484
}
24772485

2486+
#[test]
2487+
fn telemetry_toggle_propagates_from_driver_env_to_sandbox_pod() {
2488+
let _guard = ENV_LOCK.lock().unwrap();
2489+
temp_env::with_vars(
2490+
[(
2491+
openshell_core::sandbox_env::TELEMETRY_ENABLED,
2492+
Some("false"),
2493+
)],
2494+
|| {
2495+
let spec = SandboxSpec {
2496+
environment: std::collections::HashMap::from([(
2497+
openshell_core::sandbox_env::TELEMETRY_ENABLED.to_string(),
2498+
"true".to_string(),
2499+
)]),
2500+
..SandboxSpec::default()
2501+
};
2502+
let cr = sandbox_to_k8s_spec(Some(&spec), &SandboxPodParams::default());
2503+
let env = cr["spec"]["podTemplate"]["spec"]["containers"][0]["env"]
2504+
.as_array()
2505+
.unwrap();
2506+
let telemetry_entries = env
2507+
.iter()
2508+
.filter(|entry| entry["name"] == openshell_core::sandbox_env::TELEMETRY_ENABLED)
2509+
.collect::<Vec<_>>();
2510+
2511+
assert_eq!(telemetry_entries.len(), 1);
2512+
assert_eq!(telemetry_entries[0]["value"], serde_json::json!("false"));
2513+
},
2514+
);
2515+
}
2516+
24782517
#[test]
24792518
fn node_selector_from_platform_config() {
24802519
let template = SandboxTemplate {

‎crates/openshell-driver-podman/src/container.rs‎

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,10 @@ fn build_env(
280280
openshell_core::sandbox_env::SANDBOX_COMMAND.into(),
281281
"sleep infinity".into(),
282282
);
283+
env.insert(
284+
openshell_core::sandbox_env::TELEMETRY_ENABLED.into(),
285+
openshell_core::telemetry::enabled_env_value().into(),
286+
);
283287

284288
// 3. TLS client cert paths (when mTLS is enabled). These point to
285289
// the container-side mount paths where the cert files are
@@ -636,6 +640,9 @@ fn parse_memory_to_bytes(quantity: &str) -> Option<u64> {
636640
mod tests {
637641
use super::*;
638642

643+
static ENV_LOCK: std::sync::LazyLock<std::sync::Mutex<()>> =
644+
std::sync::LazyLock::new(|| std::sync::Mutex::new(()));
645+
639646
#[test]
640647
fn parse_cpu_millicore() {
641648
assert_eq!(parse_cpu_to_microseconds("500m"), Some(50_000));
@@ -908,6 +915,41 @@ mod tests {
908915
);
909916
}
910917

918+
#[test]
919+
fn container_spec_telemetry_toggle_comes_from_driver_env() {
920+
use openshell_core::proto::compute::v1::{DriverSandboxSpec, DriverSandboxTemplate};
921+
922+
let _guard = ENV_LOCK.lock().unwrap();
923+
temp_env::with_vars(
924+
[(
925+
openshell_core::sandbox_env::TELEMETRY_ENABLED,
926+
Some("false"),
927+
)],
928+
|| {
929+
let mut sandbox = test_sandbox("test-id", "legit-name");
930+
sandbox.spec = Some(DriverSandboxSpec {
931+
environment: std::collections::HashMap::from([(
932+
openshell_core::sandbox_env::TELEMETRY_ENABLED.to_string(),
933+
"true".to_string(),
934+
)]),
935+
template: Some(DriverSandboxTemplate::default()),
936+
..Default::default()
937+
});
938+
939+
let spec = build_container_spec(&sandbox, &test_config());
940+
let env_map = spec["env"].as_object().expect("env should be an object");
941+
942+
assert_eq!(
943+
env_map
944+
.get(openshell_core::sandbox_env::TELEMETRY_ENABLED)
945+
.and_then(|v| v.as_str()),
946+
Some("false"),
947+
"telemetry toggle must come from the deployment environment"
948+
);
949+
},
950+
);
951+
}
952+
911953
#[test]
912954
fn container_spec_required_labels_cannot_be_overridden() {
913955
use openshell_core::proto::compute::v1::{DriverSandboxSpec, DriverSandboxTemplate};

0 commit comments

Comments
 (0)