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

Fix: disabling tracking resets invocation ID (#2398) #2400

Merged
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
## dbt next (release TBD)
## dbt 0.17.0 (Release TBD)

### Fixes
- When tracking is disabled due to errors, do not reset the invocation ID ([#2398](https://github.com/fishtown-analytics/dbt/issues/2398), [#2400](https://github.com/fishtown-analytics/dbt/pull/2400))

## dbt 0.17.0b1 (May 5, 2020)

### Breaking changes
- Added a new dbt_project.yml version format. This emits a deprecation warning currently, but support for the existing version will be removed in a future dbt version ([#2300](https://github.com/fishtown-analytics/dbt/issues/2300), [#2312](https://github.com/fishtown-analytics/dbt/pull/2312))
Expand Down
2 changes: 1 addition & 1 deletion core/dbt/config/runtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -522,7 +522,7 @@ def _get_rendered_profile(
# return the poisoned form
profile = UnsetProfile()
# disable anonymous usage statistics
tracking.do_not_track()
tracking.disable_tracking()
return profile

@classmethod
Expand Down
16 changes: 15 additions & 1 deletion core/dbt/tracking.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def handle_failure(num_ok, unsent):
# num_ok will always be 0, unsent will always be 1 entry long, because
# the buffer is length 1, so not much to talk about
logger.warning('Error sending message, disabling tracking')
do_not_track()
disable_tracking()

def _log_request(self, request, payload):
sp_logger.info(f"Sending {request} request to {self.endpoint}...")
Expand Down Expand Up @@ -112,6 +112,12 @@ def initialize(self):
subject.set_user_id(self.id)
tracker.set_subject(subject)

def disable_tracking(self):
self.do_not_track = True
self.id = None
self.cookie_dir = None
tracker.set_subject(None)

def set_cookie(self):
# If the user points dbt to a profile directory which exists AND
# contains a profiles.yml file, then we can set a cookie. If the
Expand Down Expand Up @@ -364,6 +370,14 @@ def flush():
tracker.flush()


def disable_tracking():
global active_user
if active_user is not None:
active_user.disable_tracking()
else:
active_user = User(None)


def do_not_track():
global active_user
active_user = User(None)
Expand Down
72 changes: 72 additions & 0 deletions test/unit/test_tracking.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import dbt.tracking
import datetime
import shutil
import tempfile
import unittest


class TestTracking(unittest.TestCase):
def setUp(self):
dbt.tracking.active_user = None
self.tempdir = tempfile.mkdtemp()

def tearDown(self):
dbt.tracking.active_user = None
shutil.rmtree(self.tempdir)

def test_tracking_initial(self):
assert dbt.tracking.active_user is None
dbt.tracking.initialize_tracking(self.tempdir)
assert isinstance(dbt.tracking.active_user, dbt.tracking.User)

invocation_id = dbt.tracking.active_user.invocation_id
run_started_at = dbt.tracking.active_user.run_started_at

assert dbt.tracking.active_user.do_not_track is False
assert isinstance(dbt.tracking.active_user.id, str)
assert isinstance(invocation_id, str)
assert isinstance(run_started_at, datetime.datetime)

dbt.tracking.disable_tracking()
assert isinstance(dbt.tracking.active_user, dbt.tracking.User)

assert dbt.tracking.active_user.do_not_track is True
assert dbt.tracking.active_user.id is None
assert dbt.tracking.active_user.invocation_id == invocation_id
assert dbt.tracking.active_user.run_started_at == run_started_at

# this should generate a whole new user object -> new invocation_id/run_started_at
dbt.tracking.do_not_track()
assert isinstance(dbt.tracking.active_user, dbt.tracking.User)

assert dbt.tracking.active_user.do_not_track is True
assert dbt.tracking.active_user.id is None
assert isinstance(dbt.tracking.active_user.invocation_id, str)
assert isinstance(dbt.tracking.active_user.run_started_at, datetime.datetime)
assert dbt.tracking.active_user.invocation_id != invocation_id
# if you use `!=`, you might hit a race condition (especially on windows)
assert dbt.tracking.active_user.run_started_at is not run_started_at

def test_tracking_never_ok(self):
assert dbt.tracking.active_user is None

# this should generate a whole new user object -> new invocation_id/run_started_at
dbt.tracking.do_not_track()
assert isinstance(dbt.tracking.active_user, dbt.tracking.User)

assert dbt.tracking.active_user.do_not_track is True
assert dbt.tracking.active_user.id is None
assert isinstance(dbt.tracking.active_user.invocation_id, str)
assert isinstance(dbt.tracking.active_user.run_started_at, datetime.datetime)

def test_disable_never_enabled(self):
assert dbt.tracking.active_user is None

# this should generate a whole new user object -> new invocation_id/run_started_at
dbt.tracking.disable_tracking()
assert isinstance(dbt.tracking.active_user, dbt.tracking.User)

assert dbt.tracking.active_user.do_not_track is True
assert dbt.tracking.active_user.id is None
assert isinstance(dbt.tracking.active_user.invocation_id, str)
assert isinstance(dbt.tracking.active_user.run_started_at, datetime.datetime)