Skip to content

Commit

Permalink
✨Add Analytics (#193)
Browse files Browse the repository at this point in the history
* Fix and move no-sentry to default options. Setup framework for analytics

* Fix some things. --toggle-analytics works

* Analytics should be working. Need to figure out which commands matter

* Make use-analytics a choice not a toggle

* Show no-analytics flag feedback so user knows it works

* Analytics appear to be working!

* Reset uid to None

* Compress code a bit

* Remove interactive command analytics. Fix info-project typo

* Move GA config to cli.pros. Fixes --use-analytics
  • Loading branch information
BennyBot authored Feb 2, 2022
1 parent a7a6c80 commit 851efc3
Show file tree
Hide file tree
Showing 14 changed files with 174 additions and 21 deletions.
5 changes: 5 additions & 0 deletions pros/cli/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import click

import pros.conductor as c
from pros.ga.analytics import analytics
from pros.cli.common import default_options, logger, project_option, pros_root, shadow_command
from .upload import upload

Expand All @@ -20,6 +21,7 @@ def make(project: c.Project, build_args):
"""
Build current PROS project or cwd
"""
analytics.send("make")
exit_code = project.compile(build_args)
if exit_code != 0:
logger(__name__).error(f'Failed to make project: Exit Code {exit_code}', extra={'sentry': False})
Expand All @@ -33,6 +35,7 @@ def make(project: c.Project, build_args):
@project_option()
@click.pass_context
def make_upload(ctx, project: c.Project, build_args: List[str], **upload_args):
analytics.send("make-upload")
ctx.invoke(make, project=project, build_args=build_args)
ctx.invoke(upload, project=project, **upload_args)

Expand All @@ -43,6 +46,7 @@ def make_upload(ctx, project: c.Project, build_args: List[str], **upload_args):
@project_option()
@click.pass_context
def make_upload_terminal(ctx, project: c.Project, build_args, **upload_args):
analytics.send("make-upload-terminal")
from .terminal import terminal
ctx.invoke(make, project=project, build_args=build_args)
ctx.invoke(upload, project=project, **upload_args)
Expand All @@ -63,6 +67,7 @@ def build_compile_commands(project: c.Project, suppress_output: bool, compile_co
Build a compile_commands.json compatible with cquery
:return:
"""
analytics.send("build-compile-commands")
exit_code = project.make_scan_build(build_args, cdb_file=compile_commands, suppress_output=suppress_output,
sandbox=sandbox)
if exit_code != 0:
Expand Down
35 changes: 33 additions & 2 deletions pros/cli/common.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import click.core

from pros.common.sentry import add_tag
from pros.ga.analytics import analytics
from pros.common.utils import *
from pros.common.ui import echo
from .click_classes import *


Expand Down Expand Up @@ -113,12 +115,41 @@ def callback(ctx: click.Context, param: click.Parameter, value: str):
decorator.__name__ = f.__name__
return decorator

def no_sentry_option(f: Union[click.Command, Callable]):
"""
disables the sentry y/N prompt when an error/exception occurs
"""
def callback(ctx: click.Context, param: click.Parameter, value: bool):
ctx.ensure_object(dict)
add_tag('no-sentry',value)
if value:
pros.common.sentry.disable_prompt()
decorator = click.option('--no-sentry', expose_value=False, is_flag=True, default=False, is_eager=True,
help="Disable sentry reporting prompt.", callback=callback, cls=PROSOption, hidden=True)(f)
decorator.__name__ = f.__name__
return decorator

def no_analytics(f: Union[click.Command, Callable]):
"""
Don't use analytics for this command
"""
def callback(ctx: click.Context, param: click.Parameter, value: bool):
ctx.ensure_object(dict)
add_tag('no-analytics',value)
if value:
echo("Not sending analytics for this command.\n")
analytics.useAnalytics = False
pass
decorator = click.option('--no-analytics', expose_value=False, is_flag=True, default=False, is_eager=True,
help="Don't send analytics for this command.", callback=callback, cls=PROSOption, hidden=True)(f)
decorator.__name__ = f.__name__
return decorator

def default_options(f: Union[click.Command, Callable]):
"""
combines verbosity, debug, machine output options (most commonly used)
combines verbosity, debug, machine output, no analytics, and no sentry options
"""
decorator = debug_option(verbose_option(logging_option(logfile_option(machine_output_option(f)))))
decorator = debug_option(verbose_option(logging_option(logfile_option(machine_output_option(no_sentry_option(no_analytics(f)))))))
decorator.__name__ = f.__name__
return decorator

Expand Down
12 changes: 9 additions & 3 deletions pros/cli/conductor.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import pros.conductor as c
from pros.cli.common import *
from pros.conductor.templates import ExternalTemplate

from pros.ga.analytics import analytics

@pros_root
def conductor_cli():
Expand Down Expand Up @@ -41,7 +41,7 @@ def fetch(query: c.BaseTemplate):
Visit https://pros.cs.purdue.edu/v5/cli/conductor.html to learn more
"""

analytics.send("fetch-template")
template_file = None
if os.path.exists(query.identifier):
template_file = query.identifier
Expand Down Expand Up @@ -98,6 +98,7 @@ def apply(project: c.Project, query: c.BaseTemplate, **kwargs):
Visit https://pros.cs.purdue.edu/v5/cli/conductor.html to learn more
"""
analytics.send("apply-template")
return c.Conductor().apply_template(project, identifier=query, **kwargs)


Expand All @@ -122,6 +123,7 @@ def install(ctx: click.Context, **kwargs):
Visit https://pros.cs.purdue.edu/v5/cli/conductor.html to learn more
"""
analytics.send("install-template")
return ctx.invoke(apply, install_ok=True, **kwargs)


Expand All @@ -146,6 +148,7 @@ def upgrade(ctx: click.Context, project: c.Project, query: c.BaseTemplate, **kwa
Visit https://pros.cs.purdue.edu/v5/cli/conductor.html to learn more
"""
analytics.send("upgrade-project")
if not query.name:
for template in project.templates.keys():
click.secho(f'Upgrading {template}', color='yellow')
Expand All @@ -170,6 +173,7 @@ def uninstall_template(project: c.Project, query: c.BaseTemplate, remove_user: b
Visit https://pros.cs.purdue.edu/v5/cli/conductor.html to learn more
"""
analytics.send("uninstall-template")
c.Conductor().remove_template(project, query, remove_user=remove_user,
remove_empty_directories=remove_empty_directories)

Expand Down Expand Up @@ -200,6 +204,7 @@ def new_project(ctx: click.Context, path: str, target: str, version: str,
Visit https://pros.cs.purdue.edu/v5/cli/conductor.html to learn more
"""
analytics.send("new-project")
if version.lower() == 'latest' or not version:
version = '>0'
if not force_system and c.Project.find_project(path) is not None:
Expand Down Expand Up @@ -246,6 +251,7 @@ def query_templates(ctx, query: c.BaseTemplate, allow_offline: bool, allow_onlin
Visit https://pros.cs.purdue.edu/v5/cli/conductor.html to learn more
"""
analytics.send("query-templates")
if limit < 0:
limit = 15
templates = c.Conductor().resolve_templates(query, allow_offline=allow_offline, allow_online=allow_online,
Expand Down Expand Up @@ -285,7 +291,7 @@ def info_project(project: c.Project, ls_upgrades):
Visit https://pros.cs.purdue.edu/v5/cli/conductor.html to learn more
"""

analytics.send("info-project")
from pros.conductor.project import ProjectReport
report = ProjectReport(project)
_conductor = c.Conductor()
Expand Down
4 changes: 3 additions & 1 deletion pros/cli/conductor_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import pros.conductor as c
from pros.common.utils import logger
from pros.conductor.templates import ExternalTemplate

from pros.ga.analytics import analytics
from .common import default_options, template_query
from .conductor import conductor

Expand Down Expand Up @@ -55,6 +55,7 @@ def create_template(ctx, path: str, destination: str, do_zip: bool, **kwargs):
pros conduct create-template . libblrs 2.0.1 --system "firmware/*.a" --system "include/*.h"
"""
analytics.send("create-template")
project = c.Project.find_project(path, recurse_times=1)
if project:
project = c.Project(project)
Expand Down Expand Up @@ -151,6 +152,7 @@ def filename_remap(file_path: str) -> str:
@template_query(required=False)
@default_options
def purge_template(query: c.BaseTemplate, force):
analytics.send("purge-template")
if not query:
force = click.confirm('Are you sure you want to remove all cached templates? This action is non-reversable!',
abort=True)
Expand Down
2 changes: 1 addition & 1 deletion pros/cli/interactive.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import click
import pros.conductor as c
from .common import PROSGroup, default_options, project_option, pros_root

from pros.ga.analytics import analytics

@pros_root
def interactive_cli():
Expand Down
29 changes: 25 additions & 4 deletions pros/cli/main.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import logging

# Setup analytics first because it is used by other files

import os.path

import pros.common.sentry
Expand All @@ -11,6 +14,8 @@
from pros.cli.click_classes import *
from pros.cli.common import default_options, root_commands
from pros.common.utils import get_version, logger
from pros.ga.analytics import analytics


root_sources = [
'build',
Expand Down Expand Up @@ -61,16 +66,32 @@ def version(ctx: click.Context, param, value):
ui.echo('pros, version {}'.format(get_version()))
ctx.exit(0)

def use_analytics(ctx: click.Context, param, value):
if value==None:
return
touse = not analytics.useAnalytics
if str(value).lower().startswith("t"):
touse = True
elif str(value).lower().startswith("f"):
touse = False
else:
ui.echo('Invalid argument provided for \'--use-analytics\'. Try \'--use-analytics=False\' or \'--use-analytics=True\'')
ctx.exit(0)
ctx.ensure_object(dict)
analytics.set_use(touse)
ui.echo('Analytics set to : {}'.format(analytics.useAnalytics))
ctx.exit(0)

@click.command('pros',
cls=PROSCommandCollection,
sources=root_commands)
@default_options
@click.option('--version', help='Displays version and exits', is_flag=True, expose_value=False, is_eager=True,
@click.option('--version', help='Displays version and exits.', is_flag=True, expose_value=False, is_eager=True,
callback=version)
@click.option('--no-sentry', help='Disables sentry reporting prompt (Made for VSCode Extension)',is_flag=True,default=False)
def cli(**kwargs):
pros.common.sentry.register(kwargs['no_sentry'])
@click.option('--use-analytics', help='Set analytics usage (True/False).', type=str, expose_value=False,
is_eager=True, default=None, callback=use_analytics)
def cli():
pros.common.sentry.register()

if __name__ == '__main__':
main()
3 changes: 2 additions & 1 deletion pros/cli/misc_commands.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import pros.common.ui as ui
from pros.cli.common import *

from pros.ga.analytics import analytics

@pros_root
def misc_commands_cli():
Expand All @@ -17,6 +17,7 @@ def upgrade(force_check, no_install):
"""
Check for updates to the PROS CLI
"""
analytics.send("upgrade")
from pros.upgrade import UpgradeManager
manager = UpgradeManager()
manifest = manager.get_manifest(force_check)
Expand Down
3 changes: 2 additions & 1 deletion pros/cli/terminal.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from pros.common.utils import logger
from .common import default_options, resolve_v5_port, resolve_cortex_port, pros_root
from pros.serial.ports.v5_wireless_port import V5WirelessPort

from pros.ga.analytics import analytics

@pros_root
def terminal_cli():
Expand Down Expand Up @@ -40,6 +40,7 @@ def terminal(port: str, backend: str, **kwargs):
Note: share backend is not yet implemented.
"""
analytics.send("terminal")
from pros.serial.devices.vex.v5_user_device import V5UserDevice
from pros.serial.terminal import Terminal
is_v5_user_joystick = False
Expand Down
5 changes: 4 additions & 1 deletion pros/cli/upload.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import pros.conductor as c

from .common import *

from pros.ga.analytics import analytics

@pros_root
def upload_cli():
Expand Down Expand Up @@ -47,6 +47,7 @@ def upload(path: Optional[str], project: Optional[c.Project], port: str, **kwarg
[PORT] may be any valid communication port file, such as COM1 or /dev/ttyACM0. If left blank, then a port is
automatically detected based on the target (or as supplied by the PROS project)
"""
analytics.send("upload")
import pros.serial.devices.vex as vex
from pros.serial.ports import DirectPort
if path is None or os.path.isdir(path):
Expand Down Expand Up @@ -138,6 +139,7 @@ def ls_usb(target):
"""
List plugged in VEX Devices
"""
analytics.send("ls-usb")
from pros.serial.devices.vex import find_v5_ports, find_cortex_ports

class PortReport(object):
Expand Down Expand Up @@ -177,6 +179,7 @@ def __str__(self):
@shadow_command(upload)
@click.pass_context
def make_upload_terminal(ctx, **upload_kwargs):
analytics.send("upload-terminal")
from .terminal import terminal
ctx.invoke(upload, **upload_kwargs)
ctx.invoke(terminal, request_banner=False)
3 changes: 2 additions & 1 deletion pros/cli/user_script.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from pros.common import ui
from .common import default_options, pros_root

from pros.ga.analytics import analytics

@pros_root
def user_script_cli():
Expand All @@ -16,6 +16,7 @@ def user_script(script_file):
"""
Run a script file with the PROS CLI package
"""
analytics.send("user-script")
import os.path
import importlib.util
package_name = os.path.splitext(os.path.split(script_file)[0])[0]
Expand Down
Loading

0 comments on commit 851efc3

Please sign in to comment.