-
Notifications
You must be signed in to change notification settings - Fork 89
feat(clp-package): Add anonymous usage telemetry framework and opt-out consent model #2079
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
Nathan903
wants to merge
31
commits into
y-scope:main
Choose a base branch
from
Nathan903:2024-anonymous-usage-telemetry-framework-for-clp
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 19 commits
Commits
Show all changes
31 commits
Select commit
Hold shift + click to select a range
1f9a3eb
feat: Introduce an anonymous usage telemetry system with a dedicated …
Nathan903 fe9c572
remove server code
Nathan903 8e09801
fix cargo test failure
Nathan903 f52fd36
chore: update Cargo.lock.
Nathan903 ece60a0
refactor: streamline imports in telemetry module; update user docs to…
Nathan903 2d36ab0
chore: update version to 0.2.0-dev.2 in Helm chart
Nathan903 328432d
refactor: rust linter
Nathan903 88a6565
refactor: py linter
Nathan903 2ae4119
Merge branch 'main' into 2024-anonymous-usage-telemetry-framework-for…
Nathan903 03dca64
feat: Implement graceful shutdown for the telemetry background task u…
Nathan903 b17a4ff
Revert "feat: Implement graceful shutdown for the telemetry backgroun…
Nathan903 807bcb6
Reorder router initialization to occur before telemetry setup.
Nathan903 72b77d4
fix: Resolve CLP_VERSION file path using `_clp_home` instead of `logs…
Nathan903 ffa6dda
fix: make `CLP_DISABLE_TELEMETRY` environment variable check case-ins…
Nathan903 5da85cc
fix: replace existing telemetry configuration block or append a new o…
Nathan903 e997a5e
refactor: separate `CLP_HOST_ARCH` export from its assignment.
Nathan903 ca531c5
docs: add GitHub links to telemetry client, consent prompt, and serve…
Nathan903 07d9959
fix: improve telemetry config detection by anchoring grep pattern to …
Nathan903 cfc2f8a
Update Docker Compose project name to use the full instance ID.
Nathan903 2e7cc5a
build: Add `rust-version = "1.85"` to `Cargo.toml` files for api-serv…
Nathan903 2a141fa
refactor: Strip whitespace from read instance IDs and generate 4-char…
Nathan903 0ac9335
fix rust lint
Nathan903 fb32994
feat: Add DO_NOT_TRACK environment variable to telemetry configuration
Nathan903 6e46a65
fix: Handle empty input for telemetry consent prompt
Nathan903 0d1339b
feat: Enhance telemetry consent logic to support configurable logs di…
Nathan903 7c2a4d6
fix: Update instance ID generation to use full UUID instead of trunca…
Nathan903 0404d61
fix: Update instance ID validation to accept full UUIDs and 4-charact…
Nathan903 8351497
Merge branch 'main' into 2024-anonymous-usage-telemetry-framework-for…
Nathan903 bbaafad
chore: Bump chart version to 0.2.0-dev.3
Nathan903 0ba0b26
Merge branch 'main' into 2024-anonymous-usage-telemetry-framework-for…
Nathan903 7d34e8c
Merge branch 'main' into 2024-anonymous-usage-telemetry-framework-for…
junhaoliao File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,4 @@ | ||
| pub mod client; | ||
| mod error; | ||
| pub mod routes; | ||
| pub mod telemetry; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,144 @@ | ||
| use std::{env, time::Duration}; | ||
|
|
||
| use chrono::Utc; | ||
| use clp_rust_utils::clp_config::package::config::Config; | ||
| use serde::Serialize; | ||
|
|
||
| const TELEMETRY_ENDPOINT: &str = "https://telemetry.yscope.io/v1/events"; | ||
| const TELEMETRY_SEND_INTERVAL: Duration = Duration::from_hours(24); // 24 hours | ||
Nathan903 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| const TELEMETRY_HTTP_TIMEOUT: Duration = Duration::from_secs(5); | ||
|
|
||
| /// Schema version for the telemetry payload. | ||
| const SCHEMA_VERSION: u32 = 1; | ||
|
|
||
| #[derive(Debug, Serialize)] | ||
| struct TelemetryEvent { | ||
| schema_version: u32, | ||
| telemetry_id: String, | ||
| timestamp: String, | ||
| event_type: String, | ||
| clp_version: String, | ||
| deployment_method: String, | ||
| os: String, | ||
| os_version: String, | ||
| arch: String, | ||
| storage_engine: String, | ||
| #[serde(skip_serializing_if = "Option::is_none")] | ||
| payload: Option<serde_json::Value>, | ||
| } | ||
|
|
||
| /// Checks whether telemetry is disabled through any of the supported mechanisms. | ||
| fn is_telemetry_disabled(config: &Config) -> bool { | ||
| // Check config file setting | ||
| if config.telemetry.disable { | ||
| return true; | ||
| } | ||
|
|
||
| // Check CLP_DISABLE_TELEMETRY env var | ||
| if let Ok(val) = env::var("CLP_DISABLE_TELEMETRY") | ||
| && (val.eq_ignore_ascii_case("true") || val == "1") | ||
| { | ||
| return true; | ||
| } | ||
|
|
||
| // Check DO_NOT_TRACK env var (https://consoledonottrack.com/) | ||
| if let Ok(val) = env::var("DO_NOT_TRACK") | ||
| && val == "1" | ||
| { | ||
| return true; | ||
| } | ||
|
|
||
| false | ||
| } | ||
|
|
||
| const fn get_storage_engine_str(config: &Config) -> &'static str { | ||
| match config.package.storage_engine { | ||
| clp_rust_utils::clp_config::package::config::StorageEngine::Clp => "clp", | ||
| clp_rust_utils::clp_config::package::config::StorageEngine::ClpS => "clp-s", | ||
| } | ||
| } | ||
|
|
||
| fn build_event(event_type: &str, config: &Config) -> TelemetryEvent { | ||
| let telemetry_id = env::var("CLP_INSTANCE_ID").unwrap_or_else(|_| "unknown".to_owned()); | ||
| let clp_version = env::var("CLP_VERSION").unwrap_or_else(|_| "unknown".to_owned()); | ||
| let deployment_method = | ||
| env::var("CLP_DEPLOYMENT_METHOD").unwrap_or_else(|_| "unknown".to_owned()); | ||
| let os = env::var("CLP_HOST_OS").unwrap_or_else(|_| std::env::consts::OS.to_owned()); | ||
| let os_version = env::var("CLP_HOST_OS_VERSION").unwrap_or_else(|_| "unknown".to_owned()); | ||
| let arch = env::var("CLP_HOST_ARCH").unwrap_or_else(|_| std::env::consts::ARCH.to_owned()); | ||
|
|
||
| TelemetryEvent { | ||
| schema_version: SCHEMA_VERSION, | ||
| telemetry_id, | ||
| timestamp: Utc::now().format("%Y-%m-%dT%H:%M:%SZ").to_string(), | ||
| event_type: event_type.to_owned(), | ||
| clp_version, | ||
| deployment_method, | ||
| os, | ||
| os_version, | ||
| arch, | ||
| storage_engine: get_storage_engine_str(config).to_owned(), | ||
| payload: None, | ||
| } | ||
| } | ||
|
|
||
| async fn send_event(client: &reqwest::Client, event: &TelemetryEvent) { | ||
| let is_debug = | ||
| env::var("CLP_TELEMETRY_DEBUG").is_ok_and(|v| v.eq_ignore_ascii_case("true") || v == "1"); | ||
|
|
||
| if is_debug { | ||
| match serde_json::to_string_pretty(event) { | ||
| Ok(json) => tracing::info!("[telemetry-debug] Would send:\n{json}"), | ||
| Err(e) => tracing::warn!("[telemetry-debug] Failed to serialize event: {e}"), | ||
| } | ||
| return; | ||
| } | ||
|
|
||
| match client.post(TELEMETRY_ENDPOINT).json(event).send().await { | ||
| Ok(resp) => { | ||
| tracing::debug!("Telemetry event sent, status: {}", resp.status()); | ||
| } | ||
| Err(e) => { | ||
| tracing::debug!("Failed to send telemetry event (this is not an error): {e}"); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| /// Runs the telemetry background loop. Sends a `deployment_start` event on startup | ||
| /// and a `heartbeat` event every 24 hours. All failures are silently ignored. | ||
| /// | ||
| /// This function is designed to be spawned as a background tokio task: | ||
| /// ```ignore | ||
| /// tokio::spawn(telemetry::run_telemetry_loop(config)); | ||
| /// ``` | ||
| pub async fn run_telemetry_loop(config: Config) { | ||
| if is_telemetry_disabled(&config) { | ||
| tracing::info!("Anonymous telemetry is disabled."); | ||
| return; | ||
| } | ||
|
|
||
| tracing::info!("Anonymous telemetry is enabled. Set CLP_DISABLE_TELEMETRY=true to disable."); | ||
|
|
||
| let client = match reqwest::Client::builder() | ||
| .timeout(TELEMETRY_HTTP_TIMEOUT) | ||
| .build() | ||
| { | ||
| Ok(c) => c, | ||
| Err(e) => { | ||
| tracing::debug!("Failed to create telemetry HTTP client: {e}"); | ||
| return; | ||
| } | ||
| }; | ||
|
|
||
| // Send deployment_start event | ||
| let start_event = build_event("deployment_start", &config); | ||
| send_event(&client, &start_event).await; | ||
|
|
||
| // Periodic heartbeat | ||
| loop { | ||
| tokio::time::sleep(TELEMETRY_SEND_INTERVAL).await; | ||
|
|
||
| let heartbeat_event = build_event("heartbeat", &config); | ||
| send_event(&client, &heartbeat_event).await; | ||
| } | ||
coderabbitai[bot] marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. im not sure if this change is correct. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.