diff --git a/dvc/analytics.py b/dvc/analytics.py deleted file mode 100644 index 6e3dc91..0000000 --- a/dvc/analytics.py +++ /dev/null @@ -1,156 +0,0 @@ -import json -import logging -import os - -from .env import DVC_NO_ANALYTICS - -logger = logging.getLogger(__name__) - - -def collect_and_send_report(args=None, return_code=None): - """ - Collect information from the runtime/environment and the command - being executed into a report and send it over the network. - - To prevent analytics from blocking the execution of the main thread, - sending the report is done in a separate process. - - The inter-process communication happens through a file containing the - report as a JSON, where the _collector_ generates it and the _sender_ - removes it after sending it. - """ - import tempfile - - from dvc.daemon import daemon - - report = {} - - # Include command execution information on the report only when available. - if args and hasattr(args, "func"): - report.update({"cmd_class": args.func.__name__}) - - if return_code is not None: - report.update({"cmd_return_code": return_code}) - - with tempfile.NamedTemporaryFile(delete=False, mode="w") as fobj: - json.dump(report, fobj) - daemon(["analytics", fobj.name]) - - -def is_enabled(): - from dvc.config import Config, to_bool - from dvc.utils import env2bool - - if env2bool("DVC_TEST"): - return False - - enabled = not os.getenv(DVC_NO_ANALYTICS) - if enabled: - enabled = to_bool( - Config.from_cwd(validate=False).get("core", {}).get("analytics", "true") - ) - - logger.debug("Analytics is %sabled.", "en" if enabled else "dis") - - return enabled - - -def send(path): - """ - Side effect: Removes the report after sending it. - - The report is generated and stored in a temporary file, see: - `collect_and_send_report`. Sending happens on another process, - thus, the need of removing such file afterwards. - """ - import requests - - url = "https://analytics.dvc.org" - headers = {"content-type": "application/json"} - - with open(path, encoding="utf-8") as fobj: - report = json.load(fobj) - - report.update(_runtime_info()) - - try: - requests.post(url, json=report, headers=headers, timeout=5) - except requests.exceptions.RequestException: - logger.debug("failed to send analytics report", exc_info=True) - - os.remove(path) - - -def _scm_in_use(): - from dvc.exceptions import NotDvcRepoError - from dvc.repo import Repo - from dvc.scm import NoSCM - - from .scm import SCM, SCMError - - try: - scm = SCM(root_dir=Repo.find_root()) - return type(scm).__name__ - except SCMError: - return NoSCM.__name__ - except NotDvcRepoError: - pass - - -def _runtime_info(): - """ - Gather information from the environment where DVC runs to fill a report. - """ - from iterative_telemetry import _generate_ci_id, find_or_create_user_id - - from dvc import __version__ - from dvc.utils import is_binary - - ci_id = _generate_ci_id() - if ci_id: - group_id, user_id = ci_id - else: - group_id, user_id = None, find_or_create_user_id() - - return { - "dvc_version": __version__, - "is_binary": is_binary(), - "scm_class": _scm_in_use(), - "system_info": _system_info(), - "user_id": user_id, - "group_id": group_id, - } - - -def _system_info(): - import platform - import sys - - import distro - - system = platform.system() - - if system == "Windows": - version = sys.getwindowsversion() # type: ignore[attr-defined] - - return { - "os": "windows", - "windows_version_build": version.build, - "windows_version_major": version.major, - "windows_version_minor": version.minor, - "windows_version_service_pack": version.service_pack, - } - - if system == "Darwin": - return {"os": "mac", "mac_version": platform.mac_ver()[0]} - - if system == "Linux": - return { - "os": "linux", - "linux_distro": distro.id(), - "linux_distro_like": distro.like(), - "linux_distro_version": distro.version(), - } - - # We don't collect data for any other system. - raise NotImplementedError diff --git a/dvc/cli/__init__.py b/dvc/cli/__init__.py index 274b564..b601d84 100644 --- a/dvc/cli/__init__.py +++ b/dvc/cli/__init__.py @@ -236,11 +236,6 @@ def main(argv=None): # noqa: C901, PLR0912, PLR0915 ret = _log_exceptions(exc) or 255 try: - from dvc import analytics - - if analytics.is_enabled(): - analytics.collect_and_send_report(args, ret) - return ret finally: logger.setLevel(outer_log_level) diff --git a/dvc/commands/daemon.py b/dvc/commands/daemon.py index 35d6e90..d5a7b6e 100644 --- a/dvc/commands/daemon.py +++ b/dvc/commands/daemon.py @@ -26,15 +26,6 @@ class CmdDaemonUpdater(CmdDaemonBase): return 0 -class CmdDaemonAnalytics(CmdDaemonBase): - def run(self): - from dvc import analytics - - analytics.send(self.args.target) - - return 0 - - def add_parser(subparsers, parent_parser): DAEMON_HELP = "Service daemon." daemon_parser = subparsers.add_parser( @@ -59,15 +50,3 @@ def add_parser(subparsers, parent_parser): help=DAEMON_UPDATER_HELP, ) daemon_updater_parser.set_defaults(func=CmdDaemonUpdater) - - DAEMON_ANALYTICS_HELP = "Send dvc usage analytics." - daemon_analytics_parser = daemon_subparsers.add_parser( - "analytics", - parents=[parent_parser], - description=DAEMON_ANALYTICS_HELP, - help=DAEMON_ANALYTICS_HELP, - ) - daemon_analytics_parser.add_argument( - "target", help="Analytics file." - ).complete = completion.FILE - daemon_analytics_parser.set_defaults(func=CmdDaemonAnalytics) diff --git a/dvc/commands/init.py b/dvc/commands/init.py index ca44919..05730aa 100644 --- a/dvc/commands/init.py +++ b/dvc/commands/init.py @@ -3,7 +3,6 @@ import logging import colorama -from dvc import analytics from dvc.cli.command import CmdBaseNoRepo from dvc.cli.utils import append_doc_link from dvc.utils import boxify @@ -15,16 +14,6 @@ logger = logging.getLogger(__name__) def _welcome_message(): from dvc.ui import ui - if analytics.is_enabled(): - ui.write( - boxify( - "DVC has enabled anonymous aggregate usage analytics.\n" - "Read the analytics documentation (and how to opt-out) here:\n" - + fmt_link("https://dvc.org/doc/user-guide/analytics"), - border_color="red", - ) - ) - msg = ( "{yellow}What's next?{nc}\n" "{yellow}------------{nc}\n" diff --git a/dvc/config_schema.py b/dvc/config_schema.py index 2e36e90..3d9e402 100644 --- a/dvc/config_schema.py +++ b/dvc/config_schema.py @@ -144,7 +144,6 @@ SCHEMA = { "remote": Lower, "checksum_jobs": All(Coerce(int), Range(1)), Optional("interactive", default=False): Bool, - Optional("analytics", default=True): Bool, Optional("hardlink_lock", default=False): Bool, Optional("no_scm", default=False): Bool, Optional("autostage", default=False): Bool, diff --git a/dvc/env.py b/dvc/env.py index 081ec9d..06c1332 100644 --- a/dvc/env.py +++ b/dvc/env.py @@ -7,7 +7,6 @@ DVC_EXP_GIT_REMOTE = "DVC_EXP_GIT_REMOTE" DVC_EXP_NAME = "DVC_EXP_NAME" DVC_GLOBAL_CONFIG_DIR = "DVC_GLOBAL_CONFIG_DIR" DVC_IGNORE_ISATTY = "DVC_IGNORE_ISATTY" -DVC_NO_ANALYTICS = "DVC_NO_ANALYTICS" DVC_PAGER = "DVC_PAGER" DVC_ROOT = "DVC_ROOT" DVC_SHOW_TRACEBACK = "DVC_SHOW_TRACEBACK"