コード例 #1
0
    def test_request_retry(self):
        # we should retry on general errors
        consumer = Consumer(None, 'testsecret')
        self._test_request_retry(consumer, Exception('generic exception'), 2)

        # we should retry on server errors
        consumer = Consumer(None, 'testsecret')
        self._test_request_retry(
            consumer, APIError(500, 'code', 'Internal Server Error'), 2)

        # we should retry on HTTP 429 errors
        consumer = Consumer(None, 'testsecret')
        self._test_request_retry(consumer,
                                 APIError(429, 'code', 'Too Many Requests'), 2)

        # we should NOT retry on other client errors
        consumer = Consumer(None, 'testsecret')
        api_error = APIError(400, 'code', 'Client Errors')
        try:
            self._test_request_retry(consumer, api_error, 1)
        except APIError:
            pass
        else:
            self.fail('request() should not retry on client errors')

        # test for number of exceptions raise > retries value
        consumer = Consumer(None, 'testsecret', retries=3)
        self._test_request_retry(
            consumer, APIError(500, 'code', 'Internal Server Error'), 3)
コード例 #2
0
    def __init__(self, write_key=None, host=None, debug=False, max_queue_size=10000,
                 send=True, on_error=None, upload_size=100, upload_interval=0.5,
                 gzip=False, max_retries=10):
        require('write_key', write_key, string_types)

        self.queue = queue.Queue(max_queue_size)
        self.consumer = Consumer(self.queue, write_key, host=host, on_error=on_error,
                                 upload_size=upload_size, upload_interval=upload_interval,
                                 gzip=gzip, retries=max_retries)
        self.write_key = write_key
        self.on_error = on_error
        self.debug = debug
        self.send = send

        if debug:
            self.log.setLevel(logging.DEBUG)

        # if we've disabled sending, just don't start the consumer
        if send:
            # On program exit, allow the consumer thread to exit cleanly.
            # This prevents exceptions and a messy shutdown when the interpreter is
            # destroyed before the daemon thread finishes execution. However, it
            # is *not* the same as flushing the queue! To guarantee all messages
            # have been delivered, you'll still need to call flush().
            atexit.register(self.join)
            self.consumer.start()
コード例 #3
0
class Client(_Client):
    def __init__(self,
                 write_key=None,
                 debug=False,
                 max_queue_size=10000,
                 send=True,
                 on_error=None):
        # We need a different queue type to have a client that works properly across separate processes.
        # This client is meant to be shared and used within celery environment (although it should work otherwise).
        # This will hopefully fix: https://github.com/segmentio/analytics-python/issues/51 although it is uncertain
        # what exactly is causing it.
        require('write_key', write_key, str)

        self.queue = JoinableQueue(max_queue_size)
        self.consumer = Consumer(self.queue, write_key, on_error=on_error)
        self.write_key = write_key
        self.on_error = on_error
        self.debug = debug
        self.send = send

        if debug:
            self.log.setLevel(logging.DEBUG)

        # if we've disabled sending, just don't start the consumer
        if send:
            self.consumer.start()
コード例 #4
0
    def test_max_batch_size(self):
        q = Queue()
        consumer = Consumer(q,
                            'testsecret',
                            upload_size=100000,
                            upload_interval=3)
        track = {'type': 'track', 'event': 'python event', 'userId': 'userId'}
        msg_size = len(json.dumps(track).encode())
        # number of messages in a maximum-size batch
        n_msgs = int(475000 / msg_size)

        def mock_post_fn(_, data, **kwargs):
            res = mock.Mock()
            res.status_code = 200
            self.assertTrue(
                len(data.encode()) < 500000,
                'batch size (%d) exceeds 500KB limit' % len(data.encode()))
            return res

        with mock.patch('analytics.request._session.post',
                        side_effect=mock_post_fn) as mock_post:
            consumer.start()
            for _ in range(0, n_msgs + 2):
                q.put(track)
            q.join()
            self.assertEqual(mock_post.call_count, 2)
コード例 #5
0
 def test_upload(self):
     q = Queue()
     consumer = Consumer(q, 'testsecret')
     track = {'type': 'track', 'event': 'python event', 'userId': 'userId'}
     q.put(track)
     success = consumer.upload()
     self.assertTrue(success)
コード例 #6
0
 def test_dropping_oversize_msg(self):
     q = Queue()
     consumer = Consumer(q, '')
     oversize_msg = {'m': 'x' * MAX_MSG_SIZE}
     q.put(oversize_msg)
     next = consumer.next()
     self.assertEqual(next, [])
     self.assertTrue(q.empty())
コード例 #7
0
 def test_next_limit(self):
     q = Queue()
     flush_at = 50
     consumer = Consumer(q, '', flush_at)
     for i in range(10000):
         q.put(i)
     next = consumer.next()
     self.assertEqual(next, list(range(flush_at)))
コード例 #8
0
 def test_dropping_oversize_msg(self):
     q = Queue()
     consumer = Consumer(q, '')
     oversize_msg = {'m': 'x' * MAX_MSG_SIZE}
     q.put(oversize_msg)
     next = consumer.next()
     self.assertEqual(next, [])
     self.assertTrue(q.empty())
コード例 #9
0
 def test_request(self):
     consumer = Consumer(None, 'testsecret')
     track = {
         'type': 'track',
         'event': 'python event',
         'userId': 'userId'
     }
     consumer.request([track])
コード例 #10
0
 def test_next_limit(self):
     q = Queue()
     upload_size = 50
     consumer = Consumer(q, '', upload_size)
     for i in range(10000):
         q.put(i)
     next = consumer.next()
     self.assertEqual(next, list(range(upload_size)))
コード例 #11
0
 def test_request(cls):
     consumer = Consumer(None, 'testsecret')
     track = {
         'type': 'track',
         'event': 'python event',
         'userId': 'userId'
     }
     consumer.request([track])
コード例 #12
0
 def test_next_limit(self):
     q = Queue()
     upload_size = 50
     consumer = Consumer(q, '', upload_size)
     for i in range(10000):
         q.put(i)
     next = consumer.next()
     self.assertEqual(next, list(range(upload_size)))
コード例 #13
0
ファイル: client.py プロジェクト: russellp17/analytics-python
    def __init__(self,
                 write_key=None,
                 host=None,
                 debug=False,
                 max_queue_size=10000,
                 send=True,
                 on_error=None,
                 flush_at=100,
                 flush_interval=0.5,
                 gzip=False,
                 max_retries=3,
                 sync_mode=False,
                 timeout=15,
                 thread=1):
        require('write_key', write_key, string_types)

        self.queue = queue.Queue(max_queue_size)
        self.write_key = write_key
        self.on_error = on_error
        self.debug = debug
        self.send = send
        self.sync_mode = sync_mode
        self.host = host
        self.gzip = gzip
        self.timeout = timeout

        if debug:
            self.log.setLevel(logging.DEBUG)

        if sync_mode:
            self.consumers = None
        else:
            # On program exit, allow the consumer thread to exit cleanly.
            # This prevents exceptions and a messy shutdown when the
            # interpreter is destroyed before the daemon thread finishes
            # execution. However, it is *not* the same as flushing the queue!
            # To guarantee all messages have been delivered, you'll still need
            # to call flush().
            if send:
                atexit.register(self.join)
            for n in range(thread):
                self.consumers = []
                consumer = Consumer(
                    self.queue,
                    write_key,
                    host=host,
                    on_error=on_error,
                    flush_at=flush_at,
                    flush_interval=flush_interval,
                    gzip=gzip,
                    retries=max_retries,
                    timeout=timeout,
                )
                self.consumers.append(consumer)

                # if we've disabled sending, just don't start the consumer
                if send:
                    consumer.start()
コード例 #14
0
 def test_upload(self):
     q = Queue()
     consumer  = Consumer(q, 'testsecret')
     track = {
         'type': 'track',
         'event': 'python event',
         'userId': 'userId'
     }
     q.put(track)
     success = consumer.upload()
     self.assertTrue(success)
コード例 #15
0
ファイル: client.py プロジェクト: devs1991/test_edx_docmode
    def __init__(self, write_key=None, debug=False, max_queue_size=10000,
                 send=True, on_error=None):
        require('write_key', write_key, string_types)

        self.queue = queue.Queue(max_queue_size)
        self.consumer = Consumer(self.queue, write_key, on_error=on_error)
        self.write_key = write_key
        self.on_error = on_error
        self.debug = debug
        self.send = send

        if debug:
            self.log.setLevel(logging.DEBUG)

        # if we've disabled sending, just don't start the consumer
        if send:
            self.consumer.start()
コード例 #16
0
 def test_upload_interval(self):
     # Put _n_ items in the queue, pausing a little bit more than _upload_interval_
     # after each one. The consumer should upload _n_ times.
     q = Queue()
     upload_interval = 0.3
     consumer = Consumer(q, 'testsecret', upload_size=10, upload_interval=upload_interval)
     with mock.patch('analytics.consumer.post') as mock_post:
         consumer.start()
         for i in range(0, 3):
             track = {
                 'type': 'track',
                 'event': 'python event %d' % i,
                 'userId': 'userId'
             }
             q.put(track)
             time.sleep(upload_interval * 1.1)
         self.assertEqual(mock_post.call_count, 3)
コード例 #17
0
 def test_multiple_uploads_per_interval(self):
     # Put _upload_size*2_ items in the queue at once, then pause for _upload_interval_.
     # The consumer should upload 2 times.
     q = Queue()
     upload_interval = 0.5
     upload_size = 10
     consumer = Consumer(q, 'testsecret', upload_size=upload_size, upload_interval=upload_interval)
     with mock.patch('analytics.consumer.post') as mock_post:
         consumer.start()
         for i in range(0, upload_size * 2):
             track = {
                 'type': 'track',
                 'event': 'python event %d' % i,
                 'userId': 'userId'
             }
             q.put(track)
         time.sleep(upload_interval * 1.1)
         self.assertEqual(mock_post.call_count, 2)
コード例 #18
0
 def test_flush_interval(self):
     # Put _n_ items in the queue, pausing a little bit more than
     # _flush_interval_ after each one.
     # The consumer should upload _n_ times.
     q = Queue()
     flush_interval = 0.3
     consumer = Consumer(q, 'testsecret', flush_at=10,
                         flush_interval=flush_interval)
     with mock.patch('analytics.consumer.post') as mock_post:
         consumer.start()
         for i in range(0, 3):
             track = {
                 'type': 'track',
                 'event': 'python event %d' % i,
                 'userId': 'userId'
             }
             q.put(track)
             time.sleep(flush_interval * 1.1)
         self.assertEqual(mock_post.call_count, 3)
コード例 #19
0
 def test_multiple_uploads_per_interval(self):
     # Put _flush_at*2_ items in the queue at once, then pause for
     # _flush_interval_. The consumer should upload 2 times.
     q = Queue()
     flush_interval = 0.5
     flush_at = 10
     consumer = Consumer(q, 'testsecret', flush_at=flush_at,
                         flush_interval=flush_interval)
     with mock.patch('analytics.consumer.post') as mock_post:
         consumer.start()
         for i in range(0, flush_at * 2):
             track = {
                 'type': 'track',
                 'event': 'python event %d' % i,
                 'userId': 'userId'
             }
             q.put(track)
         time.sleep(flush_interval * 1.1)
         self.assertEqual(mock_post.call_count, 2)
コード例 #20
0
    def _test_request_retry(self, expected_exception, exception_count):
        def mock_post(*args, **kwargs):
            mock_post.call_count += 1
            if mock_post.call_count <= exception_count:
                raise expected_exception

        mock_post.call_count = 0

        with mock.patch('analytics.consumer.post',
                        mock.Mock(side_effect=mock_post)):
            consumer = Consumer(None, 'testsecret')
            track = {
                'type': 'track',
                'event': 'python event',
                'userId': 'userId'
            }
            # request() should succeed if the number of exceptions raised is less
            # than the retries paramater.
            if exception_count <= consumer.retries:
                consumer.request([track])
            else:
                # if exceptions are raised more times than the retries parameter,
                # we expect the exception to be returned to the caller.
                try:
                    consumer.request([track])
                except type(expected_exception) as exc:
                    self.assertEqual(exc, expected_exception)
                else:
                    self.fail(
                        "request() should raise an exception if still failing after %d retries"
                        % consumer.retries)
コード例 #21
0
    def test_max_batch_size(self):
        q = Queue()
        consumer = Consumer(q, 'testsecret', upload_size=100000, upload_interval=3)
        track = {
            'type': 'track',
            'event': 'python event',
            'userId': 'userId'
        }
        msg_size = len(json.dumps(track).encode())
        n_msgs = int(475000 / msg_size)  # number of messages in a maximum-size batch

        def mock_post_fn(_, data, **kwargs):
            res = mock.Mock()
            res.status_code = 200
            self.assertTrue(len(data.encode()) < 500000, 'batch size (%d) exceeds 500KB limit' % len(data.encode()))
            return res

        with mock.patch('analytics.request._session.post', side_effect=mock_post_fn) as mock_post:
            consumer.start()
            for _ in range(0, n_msgs + 2):
                q.put(track)
            q.join()
            self.assertEquals(mock_post.call_count, 2)
コード例 #22
0
    def __init__(self, write_key=None, debug=False, max_queue_size=10000,
                 send=True, on_error=None):
        require('write_key', write_key, string_types)

        self.queue = queue.Queue(max_queue_size)
        self.consumer = Consumer(self.queue, write_key, on_error=on_error)
        self.write_key = write_key
        self.on_error = on_error
        self.debug = debug
        self.send = send

        if debug:
            self.log.setLevel('debug')

        self.consumer.start()
コード例 #23
0
ファイル: client.py プロジェクト: EricSchles/analytics-python
    def __init__(self, write_key=None, debug=False, max_queue_size=10000,
                 send=True, on_error=None):
        require('write_key', write_key, string_types)

        self.queue = queue.Queue(max_queue_size)
        self.consumer = Consumer(self.queue, write_key, on_error=on_error)
        self.write_key = write_key
        self.on_error = on_error
        self.debug = debug
        self.send = send

        if debug:
            self.log.setLevel('DEBUG')

        # if we've disabled sending, just don't start the consumer
        if send:
            self.consumer.start()
コード例 #24
0
    def __init__(self, write_key=None, debug=False, max_queue_size=10000,
                 send=True, on_error=None):
        require('write_key', write_key, string_types)

        self.queue = queue.Queue(max_queue_size)
        self.consumer = Consumer(self.queue, write_key, on_error=on_error)
        self.write_key = write_key
        self.on_error = on_error
        self.debug = debug
        self.send = send

        if debug:
            self.log.setLevel(logging.DEBUG)

        # if we've disabled sending, just don't start the consumer
        if send:
            # On program exit, allow the consumer thread to exit cleanly.
            # This prevents exceptions and a messy shutdown when the interpreter is
            # destroyed before the daemon thread finishes execution. However, it
            # is *not* the same as flushing the queue! To guarantee all messages
            # have been delivered, you'll still need to call flush().
            atexit.register(self.join)
            self.consumer.start()
コード例 #25
0
class Client(object):
    """Create a new Segment client."""
    log = logging.getLogger('segment')

    def __init__(self, write_key=None, host=None, debug=False, max_queue_size=10000,
                 send=True, on_error=None, upload_size=100, upload_interval=0.5,
                 gzip=False, max_retries=10):
        require('write_key', write_key, string_types)

        self.queue = queue.Queue(max_queue_size)
        self.consumer = Consumer(self.queue, write_key, host=host, on_error=on_error,
                                 upload_size=upload_size, upload_interval=upload_interval,
                                 gzip=gzip, retries=max_retries)
        self.write_key = write_key
        self.on_error = on_error
        self.debug = debug
        self.send = send

        if debug:
            self.log.setLevel(logging.DEBUG)

        # if we've disabled sending, just don't start the consumer
        if send:
            # On program exit, allow the consumer thread to exit cleanly.
            # This prevents exceptions and a messy shutdown when the interpreter is
            # destroyed before the daemon thread finishes execution. However, it
            # is *not* the same as flushing the queue! To guarantee all messages
            # have been delivered, you'll still need to call flush().
            atexit.register(self.join)
            self.consumer.start()

    def identify(self, user_id=None, traits=None, context=None, timestamp=None,
                 anonymous_id=None, integrations=None, message_id=None):
        traits = traits or {}
        context = context or {}
        integrations = integrations or {}
        require('user_id or anonymous_id', user_id or anonymous_id, ID_TYPES)
        require('traits', traits, dict)

        msg = {
            'integrations': integrations,
            'anonymousId': anonymous_id,
            'timestamp': timestamp,
            'context': context,
            'type': 'identify',
            'userId': user_id,
            'traits': traits,
            'messageId': message_id,
        }

        return self._enqueue(msg)

    def track(self, user_id=None, event=None, properties=None, context=None,
              timestamp=None, anonymous_id=None, integrations=None, message_id=None):
        properties = properties or {}
        context = context or {}
        integrations = integrations or {}
        require('user_id or anonymous_id', user_id or anonymous_id, ID_TYPES)
        require('properties', properties, dict)
        require('event', event, string_types)

        msg = {
            'integrations': integrations,
            'anonymousId': anonymous_id,
            'properties': properties,
            'timestamp': timestamp,
            'context': context,
            'userId': user_id,
            'type': 'track',
            'event': event,
            'messageId': message_id,
        }

        return self._enqueue(msg)

    def alias(self, previous_id=None, user_id=None, context=None,
              timestamp=None, integrations=None, message_id=None):
        context = context or {}
        integrations = integrations or {}
        require('previous_id', previous_id, ID_TYPES)
        require('user_id', user_id, ID_TYPES)

        msg = {
            'integrations': integrations,
            'previousId': previous_id,
            'timestamp': timestamp,
            'context': context,
            'userId': user_id,
            'type': 'alias',
            'messageId': message_id,
        }

        return self._enqueue(msg)

    def group(self, user_id=None, group_id=None, traits=None, context=None,
              timestamp=None, anonymous_id=None, integrations=None, message_id=None):
        traits = traits or {}
        context = context or {}
        integrations = integrations or {}
        require('user_id or anonymous_id', user_id or anonymous_id, ID_TYPES)
        require('group_id', group_id, ID_TYPES)
        require('traits', traits, dict)

        msg = {
            'integrations': integrations,
            'anonymousId': anonymous_id,
            'timestamp': timestamp,
            'groupId': group_id,
            'context': context,
            'userId': user_id,
            'traits': traits,
            'type': 'group',
            'messageId': message_id,
        }

        return self._enqueue(msg)

    def page(self, user_id=None, category=None, name=None, properties=None,
             context=None, timestamp=None, anonymous_id=None,
             integrations=None, message_id=None):
        properties = properties or {}
        context = context or {}
        integrations = integrations or {}
        require('user_id or anonymous_id', user_id or anonymous_id, ID_TYPES)
        require('properties', properties, dict)

        if name:
            require('name', name, string_types)
        if category:
            require('category', category, string_types)

        msg = {
            'integrations': integrations,
            'anonymousId': anonymous_id,
            'properties': properties,
            'timestamp': timestamp,
            'category': category,
            'context': context,
            'userId': user_id,
            'type': 'page',
            'name': name,
            'messageId': message_id,
        }

        return self._enqueue(msg)

    def screen(self, user_id=None, category=None, name=None, properties=None,
               context=None, timestamp=None, anonymous_id=None,
               integrations=None, message_id=None):
        properties = properties or {}
        context = context or {}
        integrations = integrations or {}
        require('user_id or anonymous_id', user_id or anonymous_id, ID_TYPES)
        require('properties', properties, dict)

        if name:
            require('name', name, string_types)
        if category:
            require('category', category, string_types)

        msg = {
            'integrations': integrations,
            'anonymousId': anonymous_id,
            'properties': properties,
            'timestamp': timestamp,
            'category': category,
            'context': context,
            'userId': user_id,
            'type': 'screen',
            'name': name,
            'messageId': message_id,
        }

        return self._enqueue(msg)

    def _enqueue(self, msg):
        """Push a new `msg` onto the queue, return `(success, msg)`"""
        timestamp = msg['timestamp']
        if timestamp is None:
            timestamp = datetime.utcnow().replace(tzinfo=tzutc())
        message_id = msg.get('messageId')
        if message_id is None:
            message_id = uuid4()

        require('integrations', msg['integrations'], dict)
        require('type', msg['type'], string_types)
        require('timestamp', timestamp, datetime)
        require('context', msg['context'], dict)

        # add common
        timestamp = guess_timezone(timestamp)
        msg['timestamp'] = timestamp.isoformat()
        msg['messageId'] = stringify_id(message_id)
        msg['context']['library'] = {
            'name': 'analytics-python',
            'version': VERSION
        }

        msg['userId'] = stringify_id(msg.get('userId', None))
        msg['anonymousId'] = stringify_id(msg.get('anonymousId', None))

        msg = clean(msg)
        self.log.debug('queueing: %s', msg)

        # if send is False, return msg as if it was successfully queued
        if not self.send:
            return True, msg

        try:
            self.queue.put(msg, block=False)
            self.log.debug('enqueued %s.', msg['type'])
            return True, msg
        except queue.Full:
            self.log.warn('analytics-python queue is full')
            return False, msg

    def flush(self):
        """Forces a flush from the internal queue to the server"""
        queue = self.queue
        size = queue.qsize()
        queue.join()
        # Note that this message may not be precise, because of threading.
        self.log.debug('successfully flushed about %s items.', size)

    def join(self):
        """Ends the consumer thread once the queue is empty. Blocks execution until finished"""
        self.consumer.pause()
        try:
            self.consumer.join()
        except RuntimeError:
            # consumer thread has not started
            pass

    def shutdown(self):
        """Flush all messages and cleanly shutdown the client"""
        self.flush()
        self.join()
コード例 #26
0
ファイル: client.py プロジェクト: EricSchles/analytics-python
class Client(object):
    """Create a new Segment client."""
    log = logging.getLogger('segment')

    def __init__(self, write_key=None, debug=False, max_queue_size=10000,
                 send=True, on_error=None):
        require('write_key', write_key, string_types)

        self.queue = queue.Queue(max_queue_size)
        self.consumer = Consumer(self.queue, write_key, on_error=on_error)
        self.write_key = write_key
        self.on_error = on_error
        self.debug = debug
        self.send = send

        if debug:
            self.log.setLevel('DEBUG')

        # if we've disabled sending, just don't start the consumer
        if send:
            self.consumer.start()

    def identify(self, user_id=None, traits={}, context={}, timestamp=None,
                 anonymous_id=None, integrations={}):
        require('user_id or anonymous_id', user_id or anonymous_id, ID_TYPES)
        require('traits', traits, dict)

        msg = {
            'integrations': integrations,
            'anonymousId': anonymous_id,
            'timestamp': timestamp,
            'context': context,
            'type': 'identify',
            'userId': user_id,
            'traits': traits
        }

        return self._enqueue(msg)

    def track(self, user_id=None, event=None, properties={}, context={},
              timestamp=None, anonymous_id=None, integrations={}):

        require('user_id or anonymous_id', user_id or anonymous_id, ID_TYPES)
        require('properties', properties, dict)
        require('event', event, string_types)

        msg = {
            'integrations': integrations,
            'anonymousId': anonymous_id,
            'properties': properties,
            'timestamp': timestamp,
            'context': context,
            'userId': user_id,
            'type': 'track',
            'event': event
        }

        return self._enqueue(msg)

    def alias(self, previous_id=None, user_id=None, context={}, timestamp=None,
              integrations={}):
        require('previous_id', previous_id, ID_TYPES)
        require('user_id', user_id, ID_TYPES)

        msg = {
            'integrations': integrations,
            'previousId': previous_id,
            'timestamp': timestamp,
            'context': context,
            'userId': user_id,
            'type': 'alias'
        }

        return self._enqueue(msg)

    def group(self, user_id=None, group_id=None, traits={}, context={},
              timestamp=None, anonymous_id=None, integrations={}):
        require('user_id or anonymous_id', user_id or anonymous_id, ID_TYPES)
        require('group_id', group_id, ID_TYPES)
        require('traits', traits, dict)

        msg = {
            'integrations': integrations,
            'anonymousId': anonymous_id,
            'timestamp': timestamp,
            'groupId': group_id,
            'context': context,
            'userId': user_id,
            'traits': traits,
            'type': 'group'
        }

        return self._enqueue(msg)

    def page(self, user_id=None, category=None, name=None, properties={},
             context={}, timestamp=None, anonymous_id=None, integrations={}):
        require('user_id or anonymous_id', user_id or anonymous_id, ID_TYPES)
        require('properties', properties, dict)

        if name:
            require('name', name, string_types)
        if category:
            require('category', category, string_types)

        msg = {
            'integrations': integrations,
            'anonymousId': anonymous_id,
            'properties': properties,
            'timestamp': timestamp,
            'category': category,
            'context': context,
            'userId': user_id,
            'type': 'page',
            'name': name,
        }

        return self._enqueue(msg)

    def screen(self, user_id=None, category=None, name=None, properties={},
               context={}, timestamp=None, anonymous_id=None, integrations={}):
        require('user_id or anonymous_id', user_id or anonymous_id, ID_TYPES)
        require('properties', properties, dict)

        if name:
            require('name', name, string_types)
        if category:
            require('category', category, string_types)

        msg = {
            'integrations': integrations,
            'anonymousId': anonymous_id,
            'properties': properties,
            'timestamp': timestamp,
            'category': category,
            'context': context,
            'userId': user_id,
            'type': 'screen',
            'name': name,
        }

        return self._enqueue(msg)

    def _enqueue(self, msg):
        """Push a new `msg` onto the queue, return `(success, msg)`"""
        timestamp = msg['timestamp']
        if timestamp is None:
            timestamp = datetime.utcnow().replace(tzinfo=tzutc())

        require('integrations', msg['integrations'], dict)
        require('type', msg['type'], string_types)
        require('timestamp', timestamp, datetime)
        require('context', msg['context'], dict)

        # add common
        timestamp = guess_timezone(timestamp)
        msg['timestamp'] = timestamp.isoformat()
        msg['messageId'] = str(uuid4())
        msg['context']['library'] = {
            'name': 'analytics-python',
            'version': VERSION
        }

        clean(msg)

        if self.queue.full():
            self.log.warn('analytics-python queue is full')
            return False, msg

        self.queue.put(msg)
        self.log.debug('enqueued ' + msg['type'] + '.')
        return True, msg

    def flush(self):
        """Forces a flush from the internal queue to the server"""
        queue = self.queue
        size = queue.qsize()
        queue.join()
        self.log.debug('successfully flushed {0} items.'.format(size))
コード例 #27
0
 def test_next(self):
     q = Queue()
     consumer = Consumer(q, '')
     q.put(1)
     next = consumer.next()
     self.assertEqual(next, [1])
コード例 #28
0
class Client(object):
    """Create a new Segment client."""
    log = logging.getLogger('segment')

    def __init__(self, write_key=None, debug=False, max_queue_size=10000,
                 send=True, on_error=None):
        require('write_key', write_key, string_types)

        self.queue = queue.Queue(max_queue_size)
        self.consumer = Consumer(self.queue, write_key, on_error=on_error)
        self.write_key = write_key
        self.on_error = on_error
        self.debug = debug
        self.send = send

        if debug:
            self.log.setLevel(logging.DEBUG)

        # if we've disabled sending, just don't start the consumer
        if send:
            # On program exit, allow the consumer thread to exit cleanly.
            # This prevents exceptions and a messy shutdown when the interpreter is
            # destroyed before the daemon thread finishes execution. However, it
            # is *not* the same as flushing the queue! To guarantee all messages
            # have been delivered, you'll still need to call flush().
            atexit.register(self.join)
            self.consumer.start()

    def identify(self, user_id=None, traits=None, context=None, timestamp=None,
                 anonymous_id=None, integrations=None):
        traits = traits or {}
        context = context or {}
        integrations = integrations or {}
        require('user_id or anonymous_id', user_id or anonymous_id, ID_TYPES)
        require('traits', traits, dict)

        msg = {
            'integrations': integrations,
            'anonymousId': anonymous_id,
            'timestamp': timestamp,
            'context': context,
            'type': 'identify',
            'userId': user_id,
            'traits': traits
        }

        return self._enqueue(msg)

    def track(self, user_id=None, event=None, properties=None, context=None,
              timestamp=None, anonymous_id=None, integrations=None):
        properties = properties or {}
        context = context or {}
        integrations = integrations or {}
        require('user_id or anonymous_id', user_id or anonymous_id, ID_TYPES)
        require('properties', properties, dict)
        require('event', event, string_types)

        msg = {
            'integrations': integrations,
            'anonymousId': anonymous_id,
            'properties': properties,
            'timestamp': timestamp,
            'context': context,
            'userId': user_id,
            'type': 'track',
            'event': event
        }

        return self._enqueue(msg)

    def alias(self, previous_id=None, user_id=None, context=None,
              timestamp=None, integrations=None):
        context = context or {}
        integrations = integrations or {}
        require('previous_id', previous_id, ID_TYPES)
        require('user_id', user_id, ID_TYPES)

        msg = {
            'integrations': integrations,
            'previousId': previous_id,
            'timestamp': timestamp,
            'context': context,
            'userId': user_id,
            'type': 'alias'
        }

        return self._enqueue(msg)

    def group(self, user_id=None, group_id=None, traits=None, context=None,
              timestamp=None, anonymous_id=None, integrations=None):
        traits = traits or {}
        context = context or {}
        integrations = integrations or {}
        require('user_id or anonymous_id', user_id or anonymous_id, ID_TYPES)
        require('group_id', group_id, ID_TYPES)
        require('traits', traits, dict)

        msg = {
            'integrations': integrations,
            'anonymousId': anonymous_id,
            'timestamp': timestamp,
            'groupId': group_id,
            'context': context,
            'userId': user_id,
            'traits': traits,
            'type': 'group'
        }

        return self._enqueue(msg)

    def page(self, user_id=None, category=None, name=None, properties=None,
             context=None, timestamp=None, anonymous_id=None,
             integrations=None):
        properties = properties or {}
        context = context or {}
        integrations = integrations or {}
        require('user_id or anonymous_id', user_id or anonymous_id, ID_TYPES)
        require('properties', properties, dict)

        if name:
            require('name', name, string_types)
        if category:
            require('category', category, string_types)

        msg = {
            'integrations': integrations,
            'anonymousId': anonymous_id,
            'properties': properties,
            'timestamp': timestamp,
            'category': category,
            'context': context,
            'userId': user_id,
            'type': 'page',
            'name': name,
        }

        return self._enqueue(msg)

    def screen(self, user_id=None, category=None, name=None, properties=None,
               context=None, timestamp=None, anonymous_id=None,
               integrations=None):
        properties = properties or {}
        context = context or {}
        integrations = integrations or {}
        require('user_id or anonymous_id', user_id or anonymous_id, ID_TYPES)
        require('properties', properties, dict)

        if name:
            require('name', name, string_types)
        if category:
            require('category', category, string_types)

        msg = {
            'integrations': integrations,
            'anonymousId': anonymous_id,
            'properties': properties,
            'timestamp': timestamp,
            'category': category,
            'context': context,
            'userId': user_id,
            'type': 'screen',
            'name': name,
        }

        return self._enqueue(msg)

    def _enqueue(self, msg):
        """Push a new `msg` onto the queue, return `(success, msg)`"""
        timestamp = msg['timestamp']
        if timestamp is None:
            timestamp = datetime.utcnow().replace(tzinfo=tzutc())

        require('integrations', msg['integrations'], dict)
        require('type', msg['type'], string_types)
        require('timestamp', timestamp, datetime)
        require('context', msg['context'], dict)

        # add common
        timestamp = guess_timezone(timestamp)
        msg['timestamp'] = timestamp.isoformat()
        msg['messageId'] = str(uuid4())
        msg['context']['library'] = {
            'name': 'analytics-python',
            'version': VERSION
        }

        msg = clean(msg)
        self.log.debug('queueing: %s', msg)

        # if send is False, return msg as if it was successfully queued
        if not self.send:
            return True, msg

        try:
            self.queue.put(msg, block=False)
            self.log.debug('enqueued %s.', msg['type'])
            return True, msg
        except queue.Full:
            self.log.warn('analytics-python queue is full')
            return False, msg

    def flush(self):
        """Forces a flush from the internal queue to the server"""
        queue = self.queue
        size = queue.qsize()
        queue.join()
        # Note that this message may not be precise, because of threading.
        self.log.debug('successfully flushed about %s items.', size)

    def join(self):
        """Ends the consumer thread once the queue is empty. Blocks execution until finished"""
        self.consumer.pause()
        try:
            self.consumer.join()
        except RuntimeError:
            # consumer thread has not started
            pass
コード例 #29
0
 def test_pause(self):
     consumer = Consumer(None, 'testsecret')
     consumer.pause()
     self.assertFalse(consumer.running)
コード例 #30
0
ファイル: client.py プロジェクト: devs1991/test_edx_docmode
class Client(object):
    """Create a new Segment client."""
    log = logging.getLogger('segment')

    def __init__(self, write_key=None, debug=False, max_queue_size=10000,
                 send=True, on_error=None):
        require('write_key', write_key, string_types)

        self.queue = queue.Queue(max_queue_size)
        self.consumer = Consumer(self.queue, write_key, on_error=on_error)
        self.write_key = write_key
        self.on_error = on_error
        self.debug = debug
        self.send = send

        if debug:
            self.log.setLevel(logging.DEBUG)

        # if we've disabled sending, just don't start the consumer
        if send:
            self.consumer.start()

    def identify(self, user_id=None, traits={}, context={}, timestamp=None,
                 anonymous_id=None, integrations={}):
        require('user_id or anonymous_id', user_id or anonymous_id, ID_TYPES)
        require('traits', traits, dict)

        msg = {
            'integrations': integrations,
            'anonymousId': anonymous_id,
            'timestamp': timestamp,
            'context': context,
            'type': 'identify',
            'userId': user_id,
            'traits': traits
        }

        return self._enqueue(msg)

    def track(self, user_id=None, event=None, properties={}, context={},
              timestamp=None, anonymous_id=None, integrations={}):

        require('user_id or anonymous_id', user_id or anonymous_id, ID_TYPES)
        require('properties', properties, dict)
        require('event', event, string_types)

        msg = {
            'integrations': integrations,
            'anonymousId': anonymous_id,
            'properties': properties,
            'timestamp': timestamp,
            'context': context,
            'userId': user_id,
            'type': 'track',
            'event': event
        }

        return self._enqueue(msg)

    def alias(self, previous_id=None, user_id=None, context={}, timestamp=None,
              integrations={}):
        require('previous_id', previous_id, ID_TYPES)
        require('user_id', user_id, ID_TYPES)

        msg = {
            'integrations': integrations,
            'previousId': previous_id,
            'timestamp': timestamp,
            'context': context,
            'userId': user_id,
            'type': 'alias'
        }

        return self._enqueue(msg)

    def group(self, user_id=None, group_id=None, traits={}, context={},
              timestamp=None, anonymous_id=None, integrations={}):
        require('user_id or anonymous_id', user_id or anonymous_id, ID_TYPES)
        require('group_id', group_id, ID_TYPES)
        require('traits', traits, dict)

        msg = {
            'integrations': integrations,
            'anonymousId': anonymous_id,
            'timestamp': timestamp,
            'groupId': group_id,
            'context': context,
            'userId': user_id,
            'traits': traits,
            'type': 'group'
        }

        return self._enqueue(msg)

    def page(self, user_id=None, category=None, name=None, properties={},
             context={}, timestamp=None, anonymous_id=None, integrations={}):
        require('user_id or anonymous_id', user_id or anonymous_id, ID_TYPES)
        require('properties', properties, dict)

        if name:
            require('name', name, string_types)
        if category:
            require('category', category, string_types)

        msg = {
            'integrations': integrations,
            'anonymousId': anonymous_id,
            'properties': properties,
            'timestamp': timestamp,
            'category': category,
            'context': context,
            'userId': user_id,
            'type': 'page',
            'name': name,
        }

        return self._enqueue(msg)

    def screen(self, user_id=None, category=None, name=None, properties={},
               context={}, timestamp=None, anonymous_id=None, integrations={}):
        require('user_id or anonymous_id', user_id or anonymous_id, ID_TYPES)
        require('properties', properties, dict)

        if name:
            require('name', name, string_types)
        if category:
            require('category', category, string_types)

        msg = {
            'integrations': integrations,
            'anonymousId': anonymous_id,
            'properties': properties,
            'timestamp': timestamp,
            'category': category,
            'context': context,
            'userId': user_id,
            'type': 'screen',
            'name': name,
        }

        return self._enqueue(msg)

    def _enqueue(self, msg):
        """Push a new `msg` onto the queue, return `(success, msg)`"""
        timestamp = msg['timestamp']
        if timestamp is None:
            timestamp = datetime.utcnow().replace(tzinfo=tzutc())

        require('integrations', msg['integrations'], dict)
        require('type', msg['type'], string_types)
        require('timestamp', timestamp, datetime)
        require('context', msg['context'], dict)

        # add common
        timestamp = guess_timezone(timestamp)
        msg['timestamp'] = timestamp.isoformat()
        msg['messageId'] = str(uuid4())
        msg['context']['library'] = {
            'name': 'analytics-python',
            'version': VERSION
        }

        msg = clean(msg)
        self.log.debug('queueing: %s', msg)

        if self.queue.full():
            self.log.warn('analytics-python queue is full')
            return False, msg

        self.queue.put(msg)
        self.log.debug('enqueued ' + msg['type'] + '.')
        return True, msg

    def flush(self):
        """Forces a flush from the internal queue to the server"""
        queue = self.queue
        size = queue.qsize()
        queue.join()
        self.log.debug('successfully flushed {0} items.'.format(size))

    def join(self):
        """Ends the consumer thread once the queue is empty. Blocks execution until finished"""
        self.consumer.pause()
        self.consumer.join()
コード例 #31
0
 def test_proxies(cls):
     consumer = Consumer(None, 'testsecret', proxies='203.243.63.16:80')
     track = {'type': 'track', 'event': 'python event', 'userId': 'userId'}
     consumer.request([track])
コード例 #32
0
 def test_next(self):
     q = Queue()
     consumer = Consumer(q, '')
     q.put(1)
     next = consumer.next()
     self.assertEqual(next, [1])
コード例 #33
0
 def test_pause(self):
     consumer = Consumer(None, 'testsecret')
     consumer.pause()
     self.assertFalse(consumer.running)