From 8a32b28b543abb0eae550e0f28fefe6ec1cc06d0 Mon Sep 17 00:00:00 2001 From: "Mr. Outis" Date: Mon, 2 Dec 2019 22:54:16 -0600 Subject: [PATCH] analytics: collect and send on daemon --- dvc/analytics.py | 13 +++++-------- dvc/command/daemon.py | 14 ++++++++++---- dvc/main.py | 12 +++--------- tests/func/test_analytics.py | 8 +------- tests/unit/test_analytics.py | 8 ++------ 5 files changed, 21 insertions(+), 34 deletions(-) diff --git a/dvc/analytics.py b/dvc/analytics.py index 7939ba5c3..6ea473571 100644 --- a/dvc/analytics.py +++ b/dvc/analytics.py @@ -14,18 +14,18 @@ from dvc.lock import Lock, LockError from dvc.repo import Repo from dvc.scm import SCM from dvc.utils import env2bool, is_binary, makedirs -from dvc.utils.compat import str, FileNotFoundError, fspath_py35 +from dvc.utils.compat import str, FileNotFoundError logger = logging.getLogger(__name__) -def collect(args=None, return_code=None): +def collect(cmd_class=None, return_code=None): """ Query the system to fill a report. """ return { - "cmd_class": args.func.__name__ if hasattr(args, "func") else None, + "cmd_class": cmd_class, "cmd_return_code": return_code, "dvc_version": __version__, "is_binary": is_binary(), @@ -50,12 +50,9 @@ def is_enabled(): return enabled -def send(path): +def send(report): url = "https://analytics.dvc.org" - headers = {"content-type": "application/json"} - - with open(fspath_py35(path)) as fobj: - requests.post(url, data=fobj, headers=headers, timeout=5) + requests.post(url, json=report, timeout=5) def scm_in_use(): diff --git a/dvc/command/daemon.py b/dvc/command/daemon.py index 3f5f545a1..6bcb15f54 100644 --- a/dvc/command/daemon.py +++ b/dvc/command/daemon.py @@ -25,10 +25,11 @@ class CmdDaemonUpdater(CmdDaemonBase): class CmdDaemonAnalytics(CmdDaemonBase): def run(self): + """Collect and send analytics""" from dvc import analytics - analytics.send(self.args.target) - os.remove(self.args.target) + report = analytics.collect(self.args.cmd_class, self.args.ret) + analytics.send(report) return 0 @@ -57,12 +58,17 @@ def add_parser(subparsers, parent_parser): ) daemon_updater_parser.set_defaults(func=CmdDaemonUpdater) - DAEMON_ANALYTICS_HELP = "Send dvc usage analytics." + DAEMON_ANALYTICS_HELP = "Collect and 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.") + daemon_analytics_parser.add_argument( + "cmd_class", help="Class called through main" + ) + daemon_analytics_parser.add_argument( + "ret", help="Return code from running such class" + ) daemon_analytics_parser.set_defaults(func=CmdDaemonAnalytics) diff --git a/dvc/main.py b/dvc/main.py index 2b74fe6e9..c88661714 100644 --- a/dvc/main.py +++ b/dvc/main.py @@ -1,9 +1,7 @@ """Main entry point for dvc CLI.""" from __future__ import unicode_literals -import json import logging -import tempfile from dvc import analytics from dvc.cli import parse_args @@ -85,12 +83,8 @@ def main(argv=None): logger.info(FOOTER) if analytics.is_enabled(): - report = analytics.collect(args, ret) - - # Use a temporary file to pass the report between the current and - # detached process. - with tempfile.NamedTemporaryFile(delete=False, mode="w") as fobj: - json.dump(report, fobj) - daemon(["analytics", fobj.name]) + # Include the command class and return code on the analytics report + cmd_class = args.func.__name__ if hasattr(args, "func") else None + daemon(["analytics", cmd_class, ret]) return ret diff --git a/tests/func/test_analytics.py b/tests/func/test_analytics.py index 97a71d6d0..31d62d56c 100644 --- a/tests/func/test_analytics.py +++ b/tests/func/test_analytics.py @@ -1,15 +1,9 @@ import mock -import json from dvc.main import main -from dvc.utils.compat import fspath @mock.patch("dvc.analytics.send") def test_daemon_analytics(mock_send, tmp_path): - report = {"name": "dummy report"} - fname = tmp_path / "report" - fname.write_text(str(json.dumps(report))) - - assert 0 == main(["daemon", "analytics", fspath(fname)]) + assert 0 == main(["daemon", "analytics", None, 0]) assert mock_send.called diff --git a/tests/unit/test_analytics.py b/tests/unit/test_analytics.py index 7a864bfa3..c56898721 100644 --- a/tests/unit/test_analytics.py +++ b/tests/unit/test_analytics.py @@ -1,4 +1,3 @@ -import json import pytest import mock @@ -40,12 +39,9 @@ def test_collect(tmp_global_config): def test_send(mock_post, tmp_path): url = "https://analytics.dvc.org" report = {"name": "dummy report"} - fname = tmp_path / "report" - fname.write_text(str(json.dumps(report))) - analytics.send(fname) - assert mock_post.called - assert mock_post.call_args.args[0] == url + analytics.send(report) + mock_post.assert_called_with(url, json=report, timeout=5) @pytest.mark.parametrize(