Skip to content

Add machine_id to UserData so it can be used in analytics. #3449

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
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,22 @@
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "lldb",
"request": "launch",
"name": "mirrord-cli",
"program": "${workspaceFolder}/target/debug/mirrord",
"args": [
"exec",
"ls",
],
"env": {
"MIRRORD_TELEMETRY": "true",
"MIRRORD_PROGRESS_MODE": "off",
"RUST_LOG": "mirrord=debug,warn",
},
"cwd": "${workspaceFolder}"
},
{
"type": "lldb",
"request": "launch",
Expand Down
3 changes: 3 additions & 0 deletions Cargo.lock

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

3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,9 @@ pem = "3"
# Used by `cli`, `auth`
home = "0.5"

# Used by `cli`, `analytics`
uuid = { version = "1.17", features = ["v4", "serde"] }

[workspace.lints.rustdoc]
private_intra_doc_links = "allow"

Expand Down
1 change: 1 addition & 0 deletions mirrord/analytics/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ reqwest.workspace = true
tracing.workspace = true
tokio.workspace = true
drain.workspace = true
uuid.workspace = true

[dev-dependencies]
serde_json.workspace = true
Expand Down
37 changes: 27 additions & 10 deletions mirrord/analytics/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ use std::{collections::HashMap, str::FromStr, time::Instant};

use base64::{engine::general_purpose, Engine as _};
use serde::{Deserialize, Serialize};
use tracing::info;
use tracing::{info, Level};
use uuid::Uuid;

const CURRENT_VERSION: &str = env!("CARGO_PKG_VERSION");

Expand All @@ -16,6 +17,7 @@ const CURRENT_VERSION: &str = env!("CARGO_PKG_VERSION");
pub enum AnalyticValue {
Bool(bool),
Number(u32),
Uuid(Uuid),
Nested(Analytics),
}

Expand Down Expand Up @@ -161,6 +163,12 @@ impl From<usize> for AnalyticValue {
}
}

impl From<Uuid> for AnalyticValue {
fn from(id: Uuid) -> Self {
AnalyticValue::Uuid(id)
}
}

impl From<Analytics> for AnalyticValue {
fn from(analytics: Analytics) -> Self {
AnalyticValue::Nested(analytics)
Expand Down Expand Up @@ -198,9 +206,15 @@ pub struct AnalyticsReporter {
}

impl AnalyticsReporter {
pub fn new(enabled: bool, execution_kind: ExecutionKind, watch: drain::Watch) -> Self {
pub fn new(
enabled: bool,
execution_kind: ExecutionKind,
watch: drain::Watch,
machine_id: Uuid,
) -> Self {
let mut analytics = Analytics::default();
analytics.add("execution_kind", execution_kind as u32);
analytics.add("machine_id", machine_id);

AnalyticsReporter {
analytics,
Expand All @@ -213,8 +227,13 @@ impl AnalyticsReporter {
}
}

pub fn only_error(enabled: bool, execution_kind: ExecutionKind, watch: drain::Watch) -> Self {
let mut reporter = AnalyticsReporter::new(enabled, execution_kind, watch);
pub fn only_error(
enabled: bool,
execution_kind: ExecutionKind,
watch: drain::Watch,
machine_id: Uuid,
) -> Self {
let mut reporter = AnalyticsReporter::new(enabled, execution_kind, watch, machine_id);
reporter.error_only_send = true;
reporter
}
Expand Down Expand Up @@ -316,15 +335,13 @@ struct AnalyticsReport {
error: Option<AnalyticsError>,
}

const ANALYTICS_ADDRESS: &str = "https://analytics.metalbear.co/api/v1/event";

/// Actualy send `Analytics` & `AnalyticsOperatorProperties` to analytics.metalbear.co
#[tracing::instrument(level = "trace")]
#[tracing::instrument(level = Level::TRACE)]
async fn send_analytics(report: AnalyticsReport) {
let client = reqwest::Client::new();
let res = client
.post("https://analytics.metalbear.co/api/v1/event")
.json(&report)
.send()
.await;
let res = client.post(ANALYTICS_ADDRESS).json(&report).send().await;
if let Err(e) = res {
info!("Failed to send analytics: {e}");
}
Expand Down
1 change: 1 addition & 0 deletions mirrord/cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ tokio-stream = { workspace = true, features = ["io-util", "net"] }
regex.workspace = true
mid = "3.0.0"
home.workspace = true
uuid.workspace = true

[target.'cfg(target_os = "macos")'.dependencies]
mirrord-sip = { path = "../sip" }
Expand Down
16 changes: 12 additions & 4 deletions mirrord/cli/src/container.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use crate::{
error::{CliResult, ContainerError},
execution::{MirrordExecution, LINUX_INJECTION_ENV_VAR},
logging::pipe_intproxy_sidecar_logs,
user_data::UserData,
util::MIRRORD_CONSOLE_ADDR_ENV,
wsl::adjust_container_config_for_wsl,
};
Expand Down Expand Up @@ -65,13 +66,18 @@ async fn create_config_and_analytics<P: Progress>(
progress: &mut P,
mut cfg_context: ConfigContext,
watch: drain::Watch,
user_data: &UserData,
) -> CliResult<(LayerConfig, AnalyticsReporter)> {
let mut config = LayerConfig::resolve(&mut cfg_context)?;
crate::profile::apply_profile_if_configured(&mut config, progress).await?;

// Initialize only error analytics, extproxy will be the full AnalyticsReporter.
let analytics =
AnalyticsReporter::only_error(config.telemetry, ExecutionKind::Container, watch);
let analytics = AnalyticsReporter::only_error(
config.telemetry,
ExecutionKind::Container,
watch,
user_data.machine_id(),
);

let result = config.verify(&mut cfg_context);
for warning in cfg_context.into_warnings() {
Expand Down Expand Up @@ -165,6 +171,7 @@ pub async fn container_command(
runtime_args: RuntimeArgs,
exec_params: ExecParams,
watch: drain::Watch,
user_data: &UserData,
) -> CliResult<i32> {
let mut progress = ProgressTracker::from_env("mirrord container");

Expand All @@ -180,7 +187,7 @@ pub async fn container_command(

let cfg_context = ConfigContext::default().override_envs(exec_params.as_env_vars());
let (mut config, mut analytics) =
create_config_and_analytics(&mut progress, cfg_context, watch).await?;
create_config_and_analytics(&mut progress, cfg_context, watch, user_data).await?;

adjust_container_config_for_wsl(runtime_args.runtime, &mut config);

Expand Down Expand Up @@ -229,6 +236,7 @@ pub async fn container_ext_command(
config_file: Option<PathBuf>,
target: Option<String>,
watch: drain::Watch,
user_data: &UserData,
) -> CliResult<()> {
let mut progress = ProgressTracker::try_from_env("mirrord preparing to launch")
.unwrap_or_else(|| JsonProgress::new("mirrord preparing to launch").into());
Expand All @@ -237,7 +245,7 @@ pub async fn container_ext_command(
.override_env_opt(LayerConfig::FILE_PATH_ENV, config_file)
.override_env_opt("MIRRORD_IMPERSONATED_TARGET", target);
let (mut config, mut analytics) =
create_config_and_analytics(&mut progress, cfg_context, watch).await?;
create_config_and_analytics(&mut progress, cfg_context, watch, user_data).await?;

let container_runtime = std::env::var("MIRRORD_CONTAINER_USE_RUNTIME")
.ok()
Expand Down
14 changes: 12 additions & 2 deletions mirrord/cli/src/dump.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,31 @@ use super::config::DumpArgs;
use crate::{
connection::{create_and_connect, AgentConnection},
error::{CliError, CliResult},
user_data::UserData,
};

/// Implements the `mirrord dump` command.
///
/// This command starts a mirrord session using the given config file and target arguments,
/// subscribes to mirror traffic from the specified ports, and prints any traffic that comes
/// to the screen with the connection ID.
pub async fn dump_command(args: &DumpArgs, watch: drain::Watch) -> CliResult<()> {
pub async fn dump_command(
args: &DumpArgs,
watch: drain::Watch,
user_data: &UserData,
) -> CliResult<()> {
// Set up configuration similar to exec command
let mut cfg_context = ConfigContext::default().override_envs(args.params.as_env_vars());

let mut config = LayerConfig::resolve(&mut cfg_context)?;

let mut progress = ProgressTracker::from_env("mirrord dump");
let mut analytics = AnalyticsReporter::new(config.telemetry, ExecutionKind::Dump, watch);
let mut analytics = AnalyticsReporter::new(
config.telemetry,
ExecutionKind::Dump,
watch,
user_data.machine_id(),
);

if !args.params.disable_version_check {
super::prompt_outdated_version(&progress).await;
Expand Down
17 changes: 14 additions & 3 deletions mirrord/cli/src/extension.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ use mirrord_analytics::{AnalyticsError, AnalyticsReporter, Reporter};
use mirrord_config::{config::ConfigContext, LayerConfig};
use mirrord_progress::{JsonProgress, Progress, ProgressTracker};

use crate::{config::ExtensionExecArgs, execution::MirrordExecution, CliResult};
use crate::{
config::ExtensionExecArgs, execution::MirrordExecution, user_data::UserData, CliResult,
};

/// Actually facilitate execution after all preparations were complete
async fn mirrord_exec<P>(
Expand Down Expand Up @@ -33,7 +35,11 @@ where
}

/// Facilitate the execution of a process using mirrord by an IDE extension
pub(crate) async fn extension_exec(args: ExtensionExecArgs, watch: drain::Watch) -> CliResult<()> {
pub(crate) async fn extension_exec(
args: ExtensionExecArgs,
watch: drain::Watch,
user_data: &UserData,
) -> CliResult<()> {
let progress = ProgressTracker::try_from_env("mirrord preparing to launch")
.unwrap_or_else(|| JsonProgress::new("mirrord preparing to launch").into());

Expand All @@ -44,7 +50,12 @@ pub(crate) async fn extension_exec(args: ExtensionExecArgs, watch: drain::Watch)
let mut config = LayerConfig::resolve(&mut cfg_context)?;
crate::profile::apply_profile_if_configured(&mut config, &progress).await?;

let mut analytics = AnalyticsReporter::only_error(config.telemetry, Default::default(), watch);
let mut analytics = AnalyticsReporter::only_error(
config.telemetry,
Default::default(),
watch,
user_data.machine_id(),
);

let result = config.verify(&mut cfg_context);
for warning in cfg_context.into_warnings() {
Expand Down
15 changes: 13 additions & 2 deletions mirrord/cli/src/external_proxy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ use crate::{
error::{CliResult, ExternalProxyError},
execution::MIRRORD_EXECUTION_KIND_ENV,
internal_proxy::connect_and_ping,
user_data::UserData,
util::{create_listen_socket, detach_io},
};

Expand All @@ -59,7 +60,12 @@ fn print_addr(listener: &TcpListener) -> io::Result<()> {
}

#[tracing::instrument(level = Level::INFO, skip_all, err)]
pub async fn proxy(config: LayerConfig, listen_port: u16, watch: drain::Watch) -> CliResult<()> {
pub async fn proxy(
config: LayerConfig,
listen_port: u16,
watch: drain::Watch,
user_data: &UserData,
) -> CliResult<()> {
tracing::info!(
?config,
listen_port,
Expand All @@ -81,7 +87,12 @@ pub async fn proxy(config: LayerConfig, listen_port: u16, watch: drain::Watch) -
.and_then(|execution_kind| execution_kind.parse().ok())
.unwrap_or_default();

let mut analytics = AnalyticsReporter::new(config.telemetry, execution_kind, watch);
let mut analytics = AnalyticsReporter::new(
config.telemetry,
execution_kind,
watch,
user_data.machine_id(),
);
(&config).collect_analytics(analytics.get_mut());

// This connection is just to keep the agent alive as long as the client side is running.
Expand Down
16 changes: 14 additions & 2 deletions mirrord/cli/src/internal_proxy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ use crate::{
connection::AGENT_CONNECT_INFO_ENV_KEY,
error::{CliResult, InternalProxyError},
execution::MIRRORD_EXECUTION_KIND_ENV,
user_data::UserData,
util::{create_listen_socket, detach_io},
};

Expand All @@ -51,6 +52,7 @@ pub(crate) async fn proxy(
config: LayerConfig,
listen_port: u16,
watch: drain::Watch,
user_data: &UserData,
) -> CliResult<(), InternalProxyError> {
tracing::info!(
?config,
Expand Down Expand Up @@ -83,9 +85,19 @@ pub(crate) async fn proxy(
let container_mode = crate::util::intproxy_container_mode();

let mut analytics = if container_mode {
AnalyticsReporter::only_error(config.telemetry, execution_kind, watch)
AnalyticsReporter::only_error(
config.telemetry,
execution_kind,
watch,
user_data.machine_id(),
)
} else {
AnalyticsReporter::new(config.telemetry, execution_kind, watch)
AnalyticsReporter::new(
config.telemetry,
execution_kind,
watch,
user_data.machine_id(),
)
};
(&config).collect_analytics(analytics.get_mut());

Expand Down
Loading
Loading