Ejemplo n.º 1
0
def report_success(trial):  # pragma: no cover
    """
    Reports a trial success... essentially a noop but useful for mocking in tests
    """
    logger.info(f"Flowserver trial message flow for run {str(trial.run.uuid)} succeeded")

    analytics.gauge("temba.flowserver_trial.campaign_pass")
Ejemplo n.º 2
0
    def test_gauge(self, mock_get_backends):
        good = MagicMock()
        mock_get_backends.return_value = [BadBackend(), good]

        analytics.gauge("foo_level", 123)

        good.gauge.assert_called_once_with("foo_level", 123)
Ejemplo n.º 3
0
def report_success(trial):  # pragma: no cover
    """
    Reports a trial success... essentially a noop but useful for mocking in tests
    """
    logger.info(f"Trial resume for run {str(trial.run.uuid)} in flow '{trial.run.flow.name}' succeeded")

    analytics.gauge("temba.flowserver_trial.resume_pass")
Ejemplo n.º 4
0
def mage_handle_new_contact(org, contact):
    """
    Contacts created Mage are only saved to the database. Here we take care of the other stuff
    """
    # possible to have dynamic groups based on name
    contact.handle_update(attrs=('name',))

    analytics.gauge('temba.contact_created')
Ejemplo n.º 5
0
def handle_new_contact(org, contact):
    """
    Contacts created by mage or courier are only saved to the database. Here we take care of the other stuff
    """
    # possible to have dynamic groups based on name
    contact.handle_update(attrs=("name", ), is_new=True)

    analytics.gauge("temba.contact_created")
Ejemplo n.º 6
0
def mage_handle_new_contact(org, contact):
    """
    Contacts created Mage are only saved to the database. Here we take care of the other stuff
    """
    # possible to have dynamic groups based on name
    contact.handle_update(attrs=('name',))

    analytics.gauge('temba.contact_created')
Ejemplo n.º 7
0
def handle_new_contact(org, contact):
    """
    Contacts created by courier are only saved to the database. Here we take care of the other stuff
    """
    # possible to have dynamic groups based on name
    contact.handle_update(fields=("name",), is_new=True, urns=[str(u) for u in contact.get_urns()])

    analytics.gauge("temba.contact_created")
Ejemplo n.º 8
0
def handle_new_contact(org, contact):
    """
    Contacts created by courier are only saved to the database. Here we take care of the other stuff
    """
    # possible to have dynamic groups based on name
    contact.handle_update(fields=("name", ),
                          is_new=True,
                          urns=[str(u) for u in contact.get_urns()])

    analytics.gauge("temba.contact_created")
Ejemplo n.º 9
0
def mage_handle_new_message(org, msg):
    """
    Messages created Mage are only saved to the database. Here we take care of the other stuff
    """
    # Mage no longer assigns topups
    if not msg.topup_id:
        msg.topup_id = org.decrement_credit()
        msg.save(update_fields=('topup_id',))

    analytics.gauge('temba.msg_incoming_%s' % msg.channel.channel_type.lower())
Ejemplo n.º 10
0
def mage_handle_new_message(org, msg):
    """
    Messages created Mage are only saved to the database. Here we take care of the other stuff
    """
    # Mage no longer assigns topups
    if not msg.topup_id:
        (msg.topup_id, amount) = org.decrement_credit()
        msg.save(update_fields=('topup_id',))

    # set the preferred channel for this contact
    msg.contact.set_preferred_channel(msg.channel)

    analytics.gauge('temba.msg_incoming_%s' % msg.channel.channel_type.lower())
Ejemplo n.º 11
0
def mage_handle_new_message(org, msg):
    """
    Messages created Mage are only saved to the database. Here we take care of the other stuff
    """
    # Mage no longer assigns topups
    if not msg.topup_id:
        (msg.topup_id, amount) = org.decrement_credit()
        msg.save(update_fields=('topup_id',))

    # set the preferred channel for this contact
    msg.contact.set_preferred_channel(msg.channel)

    analytics.gauge('temba.msg_incoming_%s' % msg.channel.channel_type.lower())
Ejemplo n.º 12
0
def report_failure(trial):  # pragma: no cover
    """
    Reports a trial failure to sentry
    """
    logger.error(
        "trial message flow in flowserver produced different output",
        extra={
            "org": trial.flow.org.name,
            "flow": {"uuid": str(trial.flow.uuid), "name": trial.flow.name},
            "run_id": trial.run.id,
            "differences": trial.differences,
        },
    )

    analytics.gauge("temba.flowserver_trial.campaign_fail")
Ejemplo n.º 13
0
def handle_new_message(org, msg):
    """
    Messages created by courier are only saved to the database. Here we take care of the other stuff
    """
    if not msg.topup_id:
        (msg.topup_id, amount) = org.decrement_credit()
        msg.save(update_fields=("topup_id", ))

    # set the preferred channel for this contact
    msg.contact.set_preferred_channel(msg.channel)

    # if this contact is stopped, unstop them
    if msg.contact.is_stopped:
        msg.contact.unstop(msg.channel.created_by)

    analytics.gauge("temba.msg_incoming_%s" % msg.channel.channel_type.lower())
Ejemplo n.º 14
0
def handle_new_message(org, msg):
    """
    Messages created by courier are only saved to the database. Here we take care of the other stuff
    """
    if not msg.topup_id:
        (msg.topup_id, amount) = org.decrement_credit()
        msg.save(update_fields=("topup_id",))

    # set the preferred channel for this contact
    msg.contact.set_preferred_channel(msg.channel)

    # if this contact is stopped, unstop them
    if msg.contact.is_stopped:
        msg.contact.unstop(msg.channel.created_by)

    analytics.gauge("temba.msg_incoming_%s" % msg.channel.channel_type.lower())
Ejemplo n.º 15
0
def report_failure(trial):  # pragma: no cover
    """
    Reports a trial failure to sentry
    """
    logger.error(
        f"Trial resume (simple={'yes' if trial.is_simple else 'no'}) in flowserver produced different output",
        extra={
            "org": trial.run.org.name,
            "flow": {"uuid": str(trial.run.flow.uuid), "name": trial.run.flow.name},
            "run_id": trial.run.id,
            "differences": trial.differences,
        },
    )

    if trial.is_simple:
        analytics.gauge("temba.flowserver_trial.resume_simple_fail")
    else:
        analytics.gauge("temba.flowserver_trial.resume_fail")
Ejemplo n.º 16
0
    def _maybe_scale(self, req=None):
        if self.should_run():
            self.collect_stats()

            analytics.gauge('temba.celery_active_workers_%s' % (self.bound_queues,), self.processes)

            logging_msg = '_maybe_scale => CUR: (%s) CON: (%s,%s), Qty: %s, CPU: %s, Mem: %s, Db: %s' % (
                self.processes, self.min_concurrency, self.max_concurrency, self.qty,
                self.max_cpu_bound_workers, self.max_memory_bound_workers, self.max_db_bound_workers
            )
            LOG.info(logging_msg)
            self._debug(logging_msg)

            max_target_procs = min(
                self.qty, self.max_concurrency, self.max_cpu_bound_workers, self.max_memory_bound_workers,
                self.max_db_bound_workers
            )
            if max_target_procs > self.processes:
                n = min((max_target_procs - self.processes), settings.AUTOSCALE_MAX_WORKER_INC_BY)
                self._debug('SCALE_UP => %s + %s = %s' % (self.processes, n, self.processes + n))
                self.scale_up(n)

                analytics.gauge('temba.celery_worker_scale_up_%s' % (self.bound_queues,), n)
                return True

            min_target_procs = max(self.min_concurrency, max_target_procs)
            if min_target_procs < self.processes:
                n = min((self.processes - min_target_procs), settings.AUTOSCALE_MAX_WORKER_DEC_BY)
                self._debug('SCALE_DOWN => %s - %s = %s' % (self.processes, n, self.processes - n))
                self.scale_down(n)

                analytics.gauge('temba.celery_worker_scale_down_%s' % (self.bound_queues,), n)
                return True
Ejemplo n.º 17
0
def collect_message_metrics_task():
    """
    Collects message metrics and sends them to our analytics.
    """
    from .models import INCOMING, OUTGOING, PENDING, QUEUED, ERRORED, INITIALIZING
    from temba.utils import analytics

    r = get_redis_connection()

    # only do this if we aren't already running
    key = 'collect_message_metrics'
    if not r.get(key):
        with r.lock(key, timeout=900):
            # current # of queued messages (excluding Android)
            count = Msg.current_messages.filter(direction=OUTGOING, status=QUEUED).exclude(channel=None).\
                exclude(topup=None).exclude(channel__channel_type='A').exclude(next_attempt__gte=timezone.now()).count()
            analytics.gauge('temba.current_outgoing_queued', count)

            # current # of initializing messages (excluding Android)
            count = Msg.current_messages.filter(direction=OUTGOING, status=INITIALIZING).exclude(channel=None).exclude(topup=None).exclude(channel__channel_type='A').count()
            analytics.gauge('temba.current_outgoing_initializing', count)

            # current # of pending messages (excluding Android)
            count = Msg.current_messages.filter(direction=OUTGOING, status=PENDING).exclude(channel=None).exclude(topup=None).exclude(channel__channel_type='A').count()
            analytics.gauge('temba.current_outgoing_pending', count)

            # current # of errored messages (excluding Android)
            count = Msg.current_messages.filter(direction=OUTGOING, status=ERRORED).exclude(channel=None).exclude(topup=None).exclude(channel__channel_type='A').count()
            analytics.gauge('temba.current_outgoing_errored', count)

            # current # of android outgoing messages waiting to be sent
            count = Msg.current_messages.filter(direction=OUTGOING, status__in=[PENDING, QUEUED], channel__channel_type='A').exclude(channel=None).exclude(topup=None).count()
            analytics.gauge('temba.current_outgoing_android', count)

            # current # of pending incoming messages that haven't yet been handled
            count = Msg.current_messages.filter(direction=INCOMING, status=PENDING).exclude(channel=None).count()
            analytics.gauge('temba.current_incoming_pending', count)

            # stuff into redis when we last run, we do this as a canary as to whether our tasks are falling behind or not running
            cache.set('last_cron', timezone.now())
Ejemplo n.º 18
0
def collect_message_metrics_task():  # pragma: needs cover
    """
    Collects message metrics and sends them to our analytics.
    """
    from .models import INCOMING, OUTGOING, PENDING, QUEUED, ERRORED, INITIALIZING
    from temba.utils import analytics

    # current # of queued messages (excluding Android)
    count = (
        Msg.objects.filter(direction=OUTGOING, status=QUEUED)
        .exclude(channel=None)
        .exclude(topup=None)
        .exclude(channel__channel_type="A")
        .exclude(next_attempt__gte=timezone.now())
        .count()
    )
    analytics.gauge("temba.current_outgoing_queued", count)

    # current # of initializing messages (excluding Android)
    count = (
        Msg.objects.filter(direction=OUTGOING, status=INITIALIZING)
        .exclude(channel=None)
        .exclude(topup=None)
        .exclude(channel__channel_type="A")
        .count()
    )
    analytics.gauge("temba.current_outgoing_initializing", count)

    # current # of pending messages (excluding Android)
    count = (
        Msg.objects.filter(direction=OUTGOING, status=PENDING)
        .exclude(channel=None)
        .exclude(topup=None)
        .exclude(channel__channel_type="A")
        .count()
    )
    analytics.gauge("temba.current_outgoing_pending", count)

    # current # of errored messages (excluding Android)
    count = (
        Msg.objects.filter(direction=OUTGOING, status=ERRORED)
        .exclude(channel=None)
        .exclude(topup=None)
        .exclude(channel__channel_type="A")
        .count()
    )
    analytics.gauge("temba.current_outgoing_errored", count)

    # current # of android outgoing messages waiting to be sent
    count = (
        Msg.objects.filter(direction=OUTGOING, status__in=[PENDING, QUEUED], channel__channel_type="A")
        .exclude(channel=None)
        .exclude(topup=None)
        .count()
    )
    analytics.gauge("temba.current_outgoing_android", count)

    # current # of pending incoming messages that haven't yet been handled
    count = Msg.objects.filter(direction=INCOMING, status=PENDING).exclude(channel=None).count()
    analytics.gauge("temba.current_incoming_pending", count)

    # stuff into redis when we last run, we do this as a canary as to whether our tasks are falling behind or not running
    cache.set("last_cron", timezone.now())
Ejemplo n.º 19
0
def collect_message_metrics_task():  # pragma: needs cover
    """
    Collects message metrics and sends them to our analytics.
    """
    from .models import INCOMING, OUTGOING, PENDING, QUEUED, ERRORED, INITIALIZING
    from temba.utils import analytics

    # current # of queued messages (excluding Android)
    count = Msg.objects.filter(direction=OUTGOING, status=QUEUED).exclude(channel=None).\
        exclude(topup=None).exclude(channel__channel_type='A').exclude(next_attempt__gte=timezone.now()).count()
    analytics.gauge('temba.current_outgoing_queued', count)

    # current # of initializing messages (excluding Android)
    count = Msg.objects.filter(
        direction=OUTGOING, status=INITIALIZING).exclude(channel=None).exclude(
            topup=None).exclude(channel__channel_type='A').count()
    analytics.gauge('temba.current_outgoing_initializing', count)

    # current # of pending messages (excluding Android)
    count = Msg.objects.filter(
        direction=OUTGOING, status=PENDING).exclude(channel=None).exclude(
            topup=None).exclude(channel__channel_type='A').count()
    analytics.gauge('temba.current_outgoing_pending', count)

    # current # of errored messages (excluding Android)
    count = Msg.objects.filter(
        direction=OUTGOING, status=ERRORED).exclude(channel=None).exclude(
            topup=None).exclude(channel__channel_type='A').count()
    analytics.gauge('temba.current_outgoing_errored', count)

    # current # of android outgoing messages waiting to be sent
    count = Msg.objects.filter(direction=OUTGOING,
                               status__in=[PENDING, QUEUED],
                               channel__channel_type='A').exclude(
                                   channel=None).exclude(topup=None).count()
    analytics.gauge('temba.current_outgoing_android', count)

    # current # of pending incoming messages that haven't yet been handled
    count = Msg.objects.filter(direction=INCOMING,
                               status=PENDING).exclude(channel=None).count()
    analytics.gauge('temba.current_incoming_pending', count)

    # stuff into redis when we last run, we do this as a canary as to whether our tasks are falling behind or not running
    cache.set('last_cron', timezone.now())
Ejemplo n.º 20
0
def collect_message_metrics_task():  # pragma: needs cover
    """
    Collects message metrics and sends them to our analytics.
    """

    # current # of queued messages (excluding Android)
    count = (Msg.objects.filter(
        direction=Msg.DIRECTION_OUT, status=Msg.STATUS_QUEUED).exclude(
            channel=None).exclude(channel__channel_type="A").exclude(
                next_attempt__gte=timezone.now()).count())
    analytics.gauge("temba.current_outgoing_queued", count)

    # current # of initializing messages (excluding Android)
    count = (Msg.objects.filter(
        direction=Msg.DIRECTION_OUT, status=Msg.STATUS_INITIALIZING).exclude(
            channel=None).exclude(channel__channel_type="A").count())
    analytics.gauge("temba.current_outgoing_initializing", count)

    # current # of pending messages (excluding Android)
    count = (Msg.objects.filter(
        direction=Msg.DIRECTION_OUT, status=Msg.STATUS_PENDING).exclude(
            channel=None).exclude(channel__channel_type="A").count())
    analytics.gauge("temba.current_outgoing_pending", count)

    # current # of errored messages (excluding Android)
    count = (Msg.objects.filter(
        direction=Msg.DIRECTION_OUT, status=Msg.STATUS_ERRORED).exclude(
            channel=None).exclude(channel__channel_type="A").count())
    analytics.gauge("temba.current_outgoing_errored", count)

    # current # of android outgoing messages waiting to be sent
    count = (Msg.objects.filter(
        direction=Msg.DIRECTION_OUT,
        status__in=[Msg.STATUS_PENDING, Msg.STATUS_QUEUED],
        channel__channel_type="A").exclude(channel=None).count())
    analytics.gauge("temba.current_outgoing_android", count)

    # current # of pending incoming messages older than a minute that haven't yet been handled
    minute_ago = timezone.now() - timedelta(minutes=1)
    count = (Msg.objects.filter(
        direction=Msg.DIRECTION_IN,
        status=Msg.STATUS_PENDING,
        created_on__lte=minute_ago).exclude(channel=None).count())
    analytics.gauge("temba.current_incoming_pending", count)

    # stuff into redis when we last run, we do this as a canary as to whether our tasks are falling behind or not running
    cache.set("last_cron", timezone.now())