Skip to content
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

chore(Turborepo): refactor telemetry to use turbopath #7567

Merged
merged 5 commits into from Mar 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion crates/turborepo-lib/src/commands/telemetry.rs
Expand Up @@ -38,7 +38,7 @@ pub fn configure(
base: &mut CommandBase,
telemetry: CommandEventBuilder,
) {
let config = TelemetryConfig::new();
let config = TelemetryConfig::with_default_config_path();
let mut config = match config {
Ok(config) => config,
Err(e) => {
Expand Down
1 change: 1 addition & 0 deletions crates/turborepo-telemetry/Cargo.toml
Expand Up @@ -30,6 +30,7 @@ sha2 = "0.10.8"
thiserror = { workspace = true }
tokio = { workspace = true, features = ["full", "time"] }
tracing = { workspace = true }
turbopath = { workspace = true }
turborepo-api-client = { workspace = true }
turborepo-dirs = { path = "../turborepo-dirs" }
turborepo-ui = { workspace = true }
Expand Down
77 changes: 41 additions & 36 deletions crates/turborepo-telemetry/src/config.rs
@@ -1,4 +1,4 @@
use std::{env, fs, path::Path};
use std::env;

use chrono::{DateTime, Utc};
pub use config::{Config, ConfigError, File, FileFormat};
Expand All @@ -7,6 +7,7 @@ use serde::{Deserialize, Serialize};
use serde_json;
use sha2::{Digest, Sha256};
use tracing::{debug, error};
use turbopath::{AbsoluteSystemPath, AbsoluteSystemPathBuf};
use turborepo_dirs::config_dir;
use turborepo_ui::{color, BOLD, GREY, UI, UNDERLINE};
use uuid::Uuid;
Expand Down Expand Up @@ -48,20 +49,24 @@ impl Default for TelemetryConfigContents {

#[derive(Debug)]
pub struct TelemetryConfig {
config_path: String,
config_path: AbsoluteSystemPathBuf,
config: TelemetryConfigContents,
}

impl TelemetryConfig {
pub fn new() -> Result<TelemetryConfig, ConfigError> {
let file_path = &get_config_path()?;
debug!("Telemetry config path: {}", file_path);
if !Path::new(file_path).try_exists().unwrap_or(false) {
write_new_config()?;
pub fn with_default_config_path() -> Result<TelemetryConfig, ConfigError> {
let config_path = get_config_path()?;
TelemetryConfig::new(config_path)
}

pub fn new(config_path: AbsoluteSystemPathBuf) -> Result<TelemetryConfig, ConfigError> {
debug!("Telemetry config path: {}", config_path);
if !config_path.exists() {
write_new_config(&config_path)?;
}

let mut settings = Config::builder();
settings = settings.add_source(File::new(file_path, FileFormat::Json));
settings = settings.add_source(File::new(config_path.as_str(), FileFormat::Json));
let settings = settings.build();

// If this is a FileParse error, we assume something corrupted the file or
Expand All @@ -71,16 +76,18 @@ impl TelemetryConfig {
let config = match settings {
Ok(settings) => settings.try_deserialize::<TelemetryConfigContents>()?,
Err(ConfigError::FileParse { .. }) => {
fs::remove_file(file_path).map_err(|e| ConfigError::Message(e.to_string()))?;
write_new_config()?;
config_path
.remove_file()
.map_err(|e| ConfigError::Message(e.to_string()))?;
write_new_config(&config_path)?;
return Err(settings.unwrap_err());
}
// Propagate other errors
Err(err) => return Err(err),
};

let config = TelemetryConfig {
config_path: file_path.to_string(),
config_path,
config,
};

Expand All @@ -90,13 +97,14 @@ impl TelemetryConfig {
fn write(&self) -> Result<(), ConfigError> {
let serialized = serde_json::to_string_pretty(&self.config)
.map_err(|e| ConfigError::Message(e.to_string()))?;
fs::write(&self.config_path, serialized)
self.config_path
.create_with_contents(serialized)
.map_err(|e| ConfigError::Message(e.to_string()))?;
Ok(())
}

pub fn one_way_hash(input: &str) -> String {
match TelemetryConfig::new() {
match TelemetryConfig::with_default_config_path() {
Ok(config) => config.one_way_hash_with_config_salt(input),
Err(_) => TelemetryConfig::one_way_hash_with_tmp_salt(input),
}
Expand Down Expand Up @@ -219,44 +227,41 @@ impl TelemetryConfig {
}
}

fn get_config_path() -> Result<String, ConfigError> {
fn get_config_path() -> Result<AbsoluteSystemPathBuf, ConfigError> {
if cfg!(test) {
let tmp_dir = env::temp_dir();
let config_path = tmp_dir.join("test-telemetry.json");
Ok(config_path.to_str().unwrap().to_string())
let tmp_dir = AbsoluteSystemPathBuf::try_from(env::temp_dir()).unwrap();
let config_path = tmp_dir.join_component("test-telemetry.json");
Ok(config_path)
} else {
let config_dir = config_dir().ok_or(ConfigError::Message(
"Unable to find telemetry config directory".to_string(),
))?;
let abs_config_dir =
AbsoluteSystemPathBuf::try_from(config_dir.as_path()).map_err(|e| {
ConfigError::Message(format!(
"Invalid config directory {}: {}",
config_dir.display(),
e
))
})?;
// stored as a sibling to the turbo global config
let config_path = config_dir.join("turborepo").join("telemetry.json");
Ok(config_path.to_str().unwrap().to_string())
Ok(abs_config_dir.join_components(&["turborepo", "telemetry.json"]))
}
}

fn write_new_config() -> Result<(), ConfigError> {
let file_path = get_config_path()?;
fn write_new_config(file_path: &AbsoluteSystemPath) -> Result<(), ConfigError> {
let serialized = serde_json::to_string_pretty(&TelemetryConfigContents::default())
.map_err(|e| ConfigError::Message(e.to_string()))?;

// Extract the directory path from the file path
let dir_path = Path::new(&file_path).parent().ok_or_else(|| {
ConfigError::Message("Failed to extract directory path from file path".to_string())
})?;

// Create the directory if it doesn't exist
if !dir_path.try_exists().unwrap_or(false) {
fs::create_dir_all(dir_path).map_err(|e| {
ConfigError::Message(format!(
"Failed to create directory {}: {}",
dir_path.display(),
e
))
})?;
}
file_path
.ensure_dir()
.map_err(|_| ConfigError::Message("Failed to create directory".to_string()))?;

// Write the file
fs::write(&file_path, serialized).map_err(|e| ConfigError::Message(e.to_string()))?;
file_path
.create_with_contents(serialized)
.map_err(|e| ConfigError::Message(e.to_string()))?;
Ok(())
}

Expand Down
2 changes: 1 addition & 1 deletion crates/turborepo-telemetry/src/lib.rs
Expand Up @@ -81,7 +81,7 @@ fn init(
) -> Result<(TelemetryHandle, TelemetrySender), Box<dyn std::error::Error>> {
let (tx, rx) = mpsc::unbounded_channel();
let (cancel_tx, cancel_rx) = oneshot::channel();
let mut config = TelemetryConfig::new()?;
let mut config = TelemetryConfig::with_default_config_path()?;
config.show_alert(ui);

let session_id = Uuid::new_v4();
Expand Down