示例#1
0
def _wrap_Channel_consume_callback(module, obj, bind_params,
                                   callback_referrer):
    @function_wrapper
    def _nr_wrapper_Channel_consume_(wrapped, instance, args, kwargs):
        callback, queue = bind_params(*args, **kwargs)
        name = callable_name(callback)

        @functools.wraps(callback)
        def wrapped_callback(*args, **kwargs):
            transaction = current_transaction(active_only=False)

            if transaction and (transaction.ignore_transaction
                                or transaction.stopped):
                return callback(*args, **kwargs)
            elif transaction:
                with FunctionTrace(transaction=transaction, name=name):
                    return callback(*args, **kwargs)
            else:
                if hasattr(instance, '_nr_disable_txn_tracing'):
                    return callback(*args, **kwargs)
                # Keyword arguments are unknown since this is a user
                # defined callback
                exchange = 'Unknown'
                routing_key = None
                headers = None
                reply_to = None
                correlation_id = None
                unknown_kwargs = False
                if not kwargs:
                    method, properties = args[1:3]
                    exchange = method.exchange or 'Default'
                    routing_key = getattr(method, 'routing_key', None)
                    if properties is not None:
                        headers = getattr(properties, 'headers', None)
                        reply_to = getattr(properties, 'reply_to', None)
                        correlation_id = getattr(properties, 'correlation_id',
                                                 None)
                else:
                    unknown_kwargs = True

                # If headers are available, attempt to process CAT
                cat_id, cat_transaction = None, None
                if headers:
                    cat_id = headers.pop(MessageTrace.cat_id_key, None)
                    cat_transaction = headers.pop(
                        MessageTrace.cat_transaction_key, None)

                with MessageTransaction(application=application_instance(),
                                        library='RabbitMQ',
                                        destination_type='Exchange',
                                        destination_name=exchange,
                                        routing_key=routing_key,
                                        headers=headers,
                                        queue_name=queue,
                                        reply_to=reply_to,
                                        correlation_id=correlation_id) as mt:

                    # Improve transaction naming
                    _new_txn_name = 'RabbitMQ/Exchange/%s/%s' % (exchange,
                                                                 name)
                    mt.set_transaction_name(_new_txn_name, group='Message')

                    # Record that something went horribly wrong
                    if unknown_kwargs:
                        m = mt._transaction_metrics.get(KWARGS_ERROR, 0)
                        mt._transaction_metrics[KWARGS_ERROR] = m + 1

                    # Process CAT headers
                    mt._process_incoming_cat_headers(cat_id, cat_transaction)

                    return callback(*args, **kwargs)

        if len(args) > 0:
            args = list(args)
            args[0] = wrapped_callback
        else:
            kwargs[callback_referrer] = wrapped_callback

        return wrapped(*args, **kwargs)

    # Normally, wrap_object(module, object, ...) would be used here.
    # Since we need to attach the _nr_basic_consume attribute to the class, we
    # use resolve_path to retrieve the class object (parent), apply the
    # patch (as wrap_object would) and attach the _nr_basic_consume attribute
    # after patching the method.
    (parent, attribute, original) = resolve_path(module, obj)
    apply_patch(parent, attribute, _nr_wrapper_Channel_consume_(original))
    parent._nr_basic_consume = True
def _wrap_Channel_consume_callback(module, obj, wrap_consume):
    @function_wrapper
    def _nr_wrapper_Channel_consume_(wrapped, channel, args, kwargs):
        @function_wrapper
        def callback_wrapper(wrapped, instance, args, kwargs):
            name = callable_name(wrapped)

            transaction = current_transaction(active_only=False)

            if transaction and (transaction.ignore_transaction
                                or transaction.stopped):
                return wrapped(*args, **kwargs)
            elif transaction:
                return FunctionTraceWrapper(wrapped, name=name)(*args,
                                                                **kwargs)
            else:
                if hasattr(channel, '_nr_disable_txn_tracing'):
                    return wrapped(*args, **kwargs)

                # Keyword arguments are unknown since this is a user
                # defined callback
                exchange = 'Unknown'
                routing_key = None
                headers = None
                reply_to = None
                correlation_id = None
                unknown_kwargs = False
                if not kwargs:
                    method, properties = args[1:3]
                    exchange = method.exchange or 'Default'
                    routing_key = getattr(method, 'routing_key', None)
                    if properties is not None:
                        headers = getattr(properties, 'headers', None)
                        reply_to = getattr(properties, 'reply_to', None)
                        correlation_id = getattr(properties, 'correlation_id',
                                                 None)
                else:
                    unknown_kwargs = True

                with MessageTransaction(application=application_instance(),
                                        library='RabbitMQ',
                                        destination_type='Exchange',
                                        destination_name=exchange,
                                        routing_key=routing_key,
                                        headers=headers,
                                        queue_name=queue,
                                        reply_to=reply_to,
                                        correlation_id=correlation_id,
                                        source=wrapped) as mt:

                    # Improve transaction naming
                    _new_txn_name = 'RabbitMQ/Exchange/%s/%s' % (exchange,
                                                                 name)
                    mt.set_transaction_name(_new_txn_name, group='Message')

                    # Record that something went horribly wrong
                    if unknown_kwargs:
                        m = mt._transaction_metrics.get(KWARGS_ERROR, 0)
                        mt._transaction_metrics[KWARGS_ERROR] = m + 1

                    return wrapped(*args, **kwargs)

        queue, args, kwargs = wrap_consume(callback_wrapper, *args, **kwargs)
        return wrapped(*args, **kwargs)

    # Normally, wrap_object(module, object, ...) would be used here.
    # Since we need to attach the _nr_basic_consume attribute to the class, we
    # use resolve_path to retrieve the class object (parent), apply the
    # patch (as wrap_object would) and attach the _nr_basic_consume attribute
    # after patching the method.
    (parent, attribute, original) = resolve_path(module, obj)
    apply_patch(parent, attribute, _nr_wrapper_Channel_consume_(original))
    parent._nr_basic_consume = True