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