Merge pull request #143 from mesosphere/identity-analytics
Identity analytics -- DCOS-1258
This commit is contained in:
@@ -50,25 +50,63 @@ def wait_and_track(subproc):
|
||||
return exit_code
|
||||
|
||||
|
||||
def _send_segment_event(event, properties):
|
||||
def _segment_track(event, conf, properties):
|
||||
"""
|
||||
Send a segment event
|
||||
Send a segment.io 'track' event
|
||||
|
||||
:param event: name of event
|
||||
:type event: string
|
||||
:param conf: dcos config file
|
||||
:type conf: Toml
|
||||
:param properties: event properties
|
||||
:type properties: dict
|
||||
:rtype: None
|
||||
"""
|
||||
|
||||
data = {'anonymousId': session_id,
|
||||
'event': event,
|
||||
data = {'event': event,
|
||||
'properties': properties}
|
||||
|
||||
if 'core.email' in conf:
|
||||
data['userId'] = conf['core.email']
|
||||
else:
|
||||
data['anonymousId'] = session_id
|
||||
|
||||
_segment_request('track', data)
|
||||
|
||||
|
||||
def segment_identify(conf):
|
||||
"""
|
||||
Send a segment.io 'identify' event
|
||||
|
||||
:param conf: dcos config file
|
||||
:type conf: Toml
|
||||
:rtype: None
|
||||
"""
|
||||
|
||||
if 'core.email' in conf:
|
||||
data = {'userId': conf.get('core.email')}
|
||||
else:
|
||||
data = {'anonymousId': session_id}
|
||||
|
||||
_segment_request('identify', data)
|
||||
|
||||
|
||||
def _segment_request(path, data):
|
||||
"""
|
||||
Send a segment.io HTTP request
|
||||
|
||||
:param path: URL path
|
||||
:type path: str
|
||||
:param data: json POST data
|
||||
:type data: dict
|
||||
:rtype: None
|
||||
"""
|
||||
|
||||
key = SEGMENT_IO_WRITE_KEY_PROD if _is_prod() else \
|
||||
SEGMENT_IO_WRITE_KEY_DEV
|
||||
|
||||
try:
|
||||
requests.post(SEGMENT_URL,
|
||||
requests.post('{}/{}'.format(SEGMENT_URL, path),
|
||||
json=data,
|
||||
auth=HTTPBasicAuth(key, ''),
|
||||
timeout=1)
|
||||
@@ -135,7 +173,7 @@ def _segment_track_cli(pool, conf):
|
||||
"""
|
||||
|
||||
props = _base_properties(conf)
|
||||
pool.submit(_send_segment_event, SEGMENT_IO_CLI_EVENT, props)
|
||||
pool.submit(_segment_track, SEGMENT_IO_CLI_EVENT, conf, props)
|
||||
|
||||
|
||||
def _segment_track_err(pool, conf, err, exit_code):
|
||||
@@ -156,7 +194,7 @@ def _segment_track_err(pool, conf, err, exit_code):
|
||||
props = _base_properties(conf)
|
||||
props['err'] = err
|
||||
props['exit_code'] = exit_code
|
||||
pool.submit(_send_segment_event, SEGMENT_IO_CLI_ERROR_EVENT, props)
|
||||
pool.submit(_segment_track, SEGMENT_IO_CLI_ERROR_EVENT, conf, props)
|
||||
|
||||
|
||||
def _rollbar_track_err(conf, err, exit_code):
|
||||
|
||||
@@ -30,8 +30,9 @@ import docopt
|
||||
import pkg_resources
|
||||
import six
|
||||
import toml
|
||||
from dcos.api import (cmds, config, constants, emitting, errors, jsonitem,
|
||||
options, subcommand, util)
|
||||
from dcos.api import (cmds, config, constants, emitting, errors, http,
|
||||
jsonitem, options, subcommand, util)
|
||||
from dcoscli.analytics import segment_identify
|
||||
|
||||
emitter = emitting.FlatEmitter()
|
||||
|
||||
@@ -46,6 +47,8 @@ def main():
|
||||
__doc__,
|
||||
version='dcos-config version {}'.format(dcoscli.version))
|
||||
|
||||
http.silence_requests_warnings()
|
||||
|
||||
returncode, err = cmds.execute(_cmds(), args)
|
||||
if err is not None:
|
||||
emitter.publish(err)
|
||||
@@ -132,6 +135,11 @@ def _set(name, value):
|
||||
return 1
|
||||
|
||||
toml_config[name] = python_value
|
||||
|
||||
if (name == 'core.reporting' and python_value is True) or \
|
||||
(name == 'core.email'):
|
||||
segment_identify(toml_config)
|
||||
|
||||
_save_config_file(config_path, toml_config)
|
||||
|
||||
return 0
|
||||
|
||||
@@ -4,6 +4,6 @@ SEGMENT_IO_WRITE_KEY_PROD = '51ybGTeFEFU1xo6u10XMDrr6kATFyRyh'
|
||||
SEGMENT_IO_WRITE_KEY_DEV = '39uhSEOoRHMw6cMR6st9tYXDbAL3JSaP'
|
||||
SEGMENT_IO_CLI_EVENT = 'dcos-cli'
|
||||
SEGMENT_IO_CLI_ERROR_EVENT = 'dcos-cli-error'
|
||||
SEGMENT_URL = 'https://api.segment.io/v1/track'
|
||||
SEGMENT_URL = 'https://api.segment.io/v1'
|
||||
|
||||
DCOS_PRODUCTION_ENV = 'DCOS_PRODUCTION'
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
[core]
|
||||
reporting = true
|
||||
email = "test@mail.com"
|
||||
reporting = true
|
||||
|
||||
@@ -60,3 +60,30 @@ def assert_command(cmd,
|
||||
assert returncode_ == returncode
|
||||
assert stdout_ == stdout
|
||||
assert stderr_ == stderr
|
||||
|
||||
|
||||
def mock_called_some_args(mock, *args, **kwargs):
|
||||
"""Convience method for some mock assertions. Returns True if the
|
||||
arguments to one of the calls of `mock` contains `args` and
|
||||
`kwargs`.
|
||||
|
||||
:param mock: the mock to check
|
||||
:type mock: mock.Mock
|
||||
:returns: True if the arguments to one of the calls for `mock`
|
||||
contains `args` and `kwargs`.
|
||||
:rtype: bool
|
||||
"""
|
||||
|
||||
for call in mock.call_args_list:
|
||||
call_args, call_kwargs = call
|
||||
|
||||
if any(arg not in call_args for arg in args):
|
||||
continue
|
||||
|
||||
if any(k not in call_kwargs or call_kwargs[k] != v
|
||||
for k, v in kwargs.items()):
|
||||
continue
|
||||
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
@@ -6,15 +6,18 @@ import requests
|
||||
import rollbar
|
||||
from dcos.api import constants, util
|
||||
from dcoscli.analytics import _base_properties
|
||||
from dcoscli.config.main import main as config_main
|
||||
from dcoscli.constants import (ROLLBAR_SERVER_POST_KEY,
|
||||
SEGMENT_IO_CLI_ERROR_EVENT,
|
||||
SEGMENT_IO_CLI_EVENT, SEGMENT_IO_WRITE_KEY_DEV,
|
||||
SEGMENT_IO_WRITE_KEY_PROD, SEGMENT_URL)
|
||||
from dcoscli.main import main
|
||||
|
||||
from common import mock_called_some_args
|
||||
from mock import patch
|
||||
|
||||
ANON_ID = 0
|
||||
USER_ID = 'test@mail.com'
|
||||
|
||||
|
||||
def _mock(fn):
|
||||
@@ -38,7 +41,6 @@ def test_no_exc():
|
||||
|
||||
'''
|
||||
|
||||
# args
|
||||
args = [util.which('dcos')]
|
||||
env = _env_reporting()
|
||||
|
||||
@@ -46,14 +48,13 @@ def test_no_exc():
|
||||
assert main() == 0
|
||||
|
||||
# segment.io
|
||||
args, kwargs = requests.post.call_args
|
||||
assert args == (SEGMENT_URL,)
|
||||
|
||||
props = _base_properties()
|
||||
assert kwargs['json'] == {'anonymousId': ANON_ID,
|
||||
'event': SEGMENT_IO_CLI_EVENT,
|
||||
'properties': props}
|
||||
assert kwargs['timeout'] == 1
|
||||
data = {'userId': USER_ID,
|
||||
'event': SEGMENT_IO_CLI_EVENT,
|
||||
'properties': _base_properties()}
|
||||
assert mock_called_some_args(requests.post,
|
||||
'{}/track'.format(SEGMENT_URL),
|
||||
json=data,
|
||||
timeout=1)
|
||||
|
||||
# rollbar
|
||||
assert rollbar.report_message.call_count == 0
|
||||
@@ -66,7 +67,6 @@ def test_exc():
|
||||
|
||||
'''
|
||||
|
||||
# args
|
||||
args = [util.which('dcos')]
|
||||
env = _env_reporting()
|
||||
|
||||
@@ -77,15 +77,19 @@ def test_exc():
|
||||
assert main() == 1
|
||||
|
||||
# segment.io
|
||||
_, kwargs = requests.post.call_args_list[1]
|
||||
|
||||
props = _base_properties()
|
||||
props['err'] = 'Traceback'
|
||||
props['exit_code'] = 1
|
||||
assert kwargs['json'] == {'anonymousId': ANON_ID,
|
||||
'event': SEGMENT_IO_CLI_ERROR_EVENT,
|
||||
'properties': props}
|
||||
data = {'userId': USER_ID,
|
||||
'event': SEGMENT_IO_CLI_ERROR_EVENT,
|
||||
'properties': props}
|
||||
|
||||
assert mock_called_some_args(requests.post,
|
||||
'{}/track'.format(SEGMENT_URL),
|
||||
json=data,
|
||||
timeout=1)
|
||||
|
||||
# rollbar
|
||||
props = _base_properties()
|
||||
props['exit_code'] = 1
|
||||
rollbar.report_message.assert_called_with('Traceback', 'error',
|
||||
@@ -150,6 +154,24 @@ def test_production_setting_false():
|
||||
rollbar.init.assert_called_with(ROLLBAR_SERVER_POST_KEY, 'dev')
|
||||
|
||||
|
||||
@_mock
|
||||
def test_config_set():
|
||||
'''Tests that a `dcos config set core.email <email>` makes a
|
||||
segment.io identify call'''
|
||||
|
||||
args = [util.which('dcos'), 'config', 'set', 'core.email', 'test@mail.com']
|
||||
env = _env_reporting()
|
||||
|
||||
with patch('sys.argv', args), patch.dict(os.environ, env):
|
||||
assert config_main() == 0
|
||||
|
||||
# segment.io
|
||||
assert mock_called_some_args(requests.post,
|
||||
'{}/identify'.format(SEGMENT_URL),
|
||||
json={'userId': 'test@mail.com'},
|
||||
timeout=1)
|
||||
|
||||
|
||||
def _env_reporting():
|
||||
path = os.path.join('tests', 'data', 'analytics', 'dcos_reporting.toml')
|
||||
return {constants.DCOS_CONFIG_ENV: path}
|
||||
|
||||
Reference in New Issue
Block a user