import functools import json import logging from requests import auth from requests_futures import sessions from lbrynet.conf import settings from lbrynet.analytics import utils log = logging.getLogger(__name__) def log_response(fn): def _log(future): if future.cancelled(): log.warning('Request was unexpectedly cancelled') elif future.exception(): exc, traceback = future.exception_info() log.warning('Failed to send an analytics event', exc_info=(type(exc), exc, traceback)) else: response = future.result() log.debug('Response (%s): %s', response.status_code, response.content) @functools.wraps(fn) def wrapper(*args, **kwargs): future = fn(*args, **kwargs) future.add_done_callback(_log) return future return wrapper class Api(object): def __init__(self, session, url, write_key): self.session = session self.url = url self.write_key = write_key @property def auth(self): return auth.HTTPBasicAuth(self.write_key, '') @log_response def batch(self, events): """Send multiple events in one request. Each event needs to have its type specified. """ data = json.dumps({ 'batch': events, 'sentAt': utils.now(), }) log.debug('sending %s events', len(events)) log.debug('Data: %s', data) return self.session.post(self.url + '/batch', json=data, auth=self.auth) @log_response def track(self, event): """Send a single tracking event""" log.debug('Sending track event: %s', event) return self.session.post(self.url + '/track', json=event, auth=self.auth) @classmethod def new_instance(cls, session=None): """Initialize an instance using values from the configuration""" if not session: session = sessions.FuturesSession() return cls( session, settings.ANALYTICS_ENDPOINT, utils.deobfuscate(settings.ANALYTICS_TOKEN) )