diff --git a/app/src/remote_server/mod.rs b/app/src/remote_server/mod.rs index 2e40f60b..184d9885 100644 --- a/app/src/remote_server/mod.rs +++ b/app/src/remote_server/mod.rs @@ -58,9 +58,16 @@ pub(super) fn run_daemon_app( .spawn(warp_logging::rotate_log_files()) .detach(); + use crate::server::telemetry::context_provider::NoopTelemetryContextProvider; use repo_metadata::repositories::DetectedRepositories; use repo_metadata::watcher::DirectoryWatcher; use repo_metadata::RepoMetadataModel; + + // Register a no-op telemetry context so that `send_telemetry_from_ctx!` + // calls (e.g. from RepoMetadataModel on ExceededMaxFileLimit) don't + // panic due to a missing TelemetryContextModel singleton. + ctx.add_singleton_model(NoopTelemetryContextProvider::new_context_provider); + // Order matters: DetectedRepositories must be registered before // RepoMetadataModel because LocalRepoMetadataModel::new() // subscribes to DetectedRepositories::handle(ctx). diff --git a/app/src/server/telemetry/context_provider.rs b/app/src/server/telemetry/context_provider.rs index e14da9a5..306d1826 100644 --- a/app/src/server/telemetry/context_provider.rs +++ b/app/src/server/telemetry/context_provider.rs @@ -24,3 +24,29 @@ impl TelemetryContextProvider for AppTelemetryContextProvider { auth_state.anonymous_id() } } + +/// A no-op telemetry context provider for headless contexts (e.g. the remote +/// server daemon) that run without authentication. Telemetry events that +/// require a user/anonymous ID will silently produce empty identifiers, +/// preventing panics from an unregistered `TelemetryContextModel` singleton. +#[cfg_attr(target_family = "wasm", allow(dead_code))] +pub struct NoopTelemetryContextProvider; + +impl NoopTelemetryContextProvider { + #[cfg_attr(target_family = "wasm", allow(dead_code))] + pub fn new_context_provider( + _ctx: &mut ModelContext, + ) -> TelemetryContextModel { + Box::new(Self) + } +} + +impl TelemetryContextProvider for NoopTelemetryContextProvider { + fn user_id(&self, _ctx: &AppContext) -> Option { + None + } + + fn anonymous_id(&self, _ctx: &AppContext) -> String { + String::new() + } +}