Exemplo n.º 1
0
        def wrapper(wrapped, instance, args, kwargs):
            transaction = current_transaction()

            if transaction is None:
                return wrapped(*args, **kwargs)

            before = (transaction.name, transaction.group)

            with FunctionTrace(name=name):
                try:
                    return wrapped(*args, **kwargs)

                finally:
                    # We want to name the transaction after this
                    # middleware but only if the transaction wasn't
                    # named from within the middleware itself explicity.

                    after = (transaction.name, transaction.group)
                    if before == after:
                        transaction.set_transaction_name(name, priority=2)
Exemplo n.º 2
0
def _nr_wrapper_django_template_base_InclusionNode_render_(
        wrapped, instance, args, kwargs):

    transaction = current_transaction()

    if transaction is None:
        return wrapped(*args, **kwargs)

    if wrapped.__self__ is None:
        return wrapped(*args, **kwargs)

    file_name = getattr(wrapped.__self__, '_nr_file_name', None)

    if file_name is None:
        return wrapped(*args, **kwargs)

    name = wrapped.__self__._nr_file_name

    with FunctionTrace(transaction, name, 'Template/Include'):
        return wrapped(*args, **kwargs)
Exemplo n.º 3
0
def _nr_wrapper_WSGIContainer___call__body_(wrapped, instance, args, kwargs):
    # This variant of the WSGIContainer.__call__() wrapper is used when
    # being used with HTTPServer directly and it is believed that we are
    # being called for a HTTP request where there is request content.
    # This would also be used where FallbackHandler was being used.
    # There should already be a transaction associated with the Tornado
    # request object and also a current active transaction.

    def _params(request, *args, **kwargs):
        return request

    request = _params(*args, **kwargs)

    transaction = retrieve_current_transaction()

    transaction.set_transaction_name(request.uri, 'Uri', priority=1)

    with FunctionTrace(transaction, name='Request/Process',
            group='Python/Tornado'):
        return wrapped(*args, **kwargs)
                    def _generator(generator):
                        try:
                            value = None
                            exc = None

                            while True:
                                transaction = current_transaction()

                                params = {}

                                params['filename'] = \
                                        generator.gi_frame.f_code.co_filename
                                params['lineno'] = \
                                        generator.gi_frame.f_lineno

                                with FunctionTrace(transaction, name,
                                        params=params):
                                    try:
                                        if exc is not None:
                                            yielded = generator.throw(*exc)
                                            exc = None
                                        else:
                                            yielded = generator.send(value)

                                    except (Return, StopIteration):
                                        raise

                                    except Exception:
                                        if transaction:
                                            transaction.record_exception(
                                                    *sys.exc_info())
                                        raise

                                try:
                                    value = yield yielded

                                except Exception:
                                    exc = sys.exc_info()

                        finally:
                            generator.close()
Exemplo n.º 5
0
    def wrapper(wrapped, instance, args, kwargs):
        transaction = current_transaction()

        if transaction is None:
            return wrapped(*args, **kwargs)

        transaction.set_transaction_name(name, priority=priority)

        with FunctionTrace(name=name):
            try:
                return wrapped(*args, **kwargs)

            except:  # Catch all
                exc_info = sys.exc_info()
                try:
                    # Store exc_info on the request to check response code
                    # prior to reporting
                    args[0]._nr_exc_info = exc_info
                except:
                    record_exception(*exc_info)
                raise
def _nr_wrapper_django_inclusion_tag_wrapper_(wrapped, instance, args, kwargs):

    transaction = current_transaction()

    if transaction is None:
        return wrapped(*args, **kwargs)

    name = hasattr(wrapped, '__name__') and wrapped.__name__

    if name is None:
        return wrapped(*args, **kwargs)

    qualname = callable_name(wrapped)

    tags = django_settings.instrumentation.templates.inclusion_tag

    if '*' not in tags and name not in tags and qualname not in tags:
        return wrapped(*args, **kwargs)

    with FunctionTrace(transaction, name, group='Template/Tag'):
        return wrapped(*args, **kwargs)
Exemplo n.º 7
0
def _nr_wrapper_GZipMiddleware_process_response_(wrapped, instance, args,
                                                 kwargs):

    transaction = current_transaction()

    if transaction is None:
        return wrapped(*args, **kwargs)

    def _bind_params(request, response, *args, **kwargs):
        return request, response

    request, response = _bind_params(*args, **kwargs)

    if should_add_browser_timing(response, transaction):
        with FunctionTrace(name=callable_name(browser_timing_insertion)):
            response_with_browser = browser_timing_insertion(
                response, transaction)

        return wrapped(request, response_with_browser)

    return wrapped(request, response)
def view_handler_wrapper(wrapped, instance, args, kwargs):
    transaction = current_transaction()

    if not transaction:
        return wrapped(*args, **kwargs)

    try:
        view_callable = wrapped.__original_view__ or wrapped
    except AttributeError:
        view_callable = wrapped

    name = callable_name(view_callable)

    transaction.set_transaction_name(name)

    with FunctionTrace(name) as trace:
        try:
            return wrapped(*args, **kwargs)

        except:  # Catch all
            trace.record_exception(ignore_errors=should_ignore)
            raise
    def wrapper(wrapped, instance, args, kwargs):
        transaction = current_transaction()

        if callable(name):
            if instance and inspect.ismethod(wrapped):
                _name = name(instance, *args, **kwargs)
            else:
                _name = name(*args, **kwargs)

        elif name is None:
            _name = callable_name(wrapped)

        else:
            _name = name

        # Helper for obtaining the appropriate application object. If
        # has an activate() method assume it is a valid application
        # object. Don't check by type so se can easily mock it for
        # testing if need be.

        def _application():
            if hasattr(application, 'activate'):
                return application
            return application_instance(application)

        # Check to see if we are being called within the context of an
        # existing transaction. If we are, then we will record the call
        # as a function trace node instead. This situation can occur
        # when a function wrapped with Celery task decorator is called
        # explicitly in the context of an existing transaction.

        if transaction:
            with FunctionTrace(transaction, callable_name(wrapped)):
                return wrapped(*args, **kwargs)

        # Otherwise treat it as top level background task.

        with BackgroundTask(_application(), _name, 'Celery'):
            return wrapped(*args, **kwargs)
Exemplo n.º 10
0
    def wrapped_callback(*args, **kwargs):
        transaction = current_transaction()

        if transaction is None:
            return callback(*args, **kwargs)

        if not kwargs:
            method, properties = args[1:3]
            start_time = getattr(wrapped_callback, '_nr_start_time', None)

            _add_consume_rabbitmq_trace(transaction,
                                        method=method,
                                        properties=properties,
                                        nr_start_time=start_time,
                                        queue_name=queue)
        else:
            m = transaction._transaction_metrics.get(KWARGS_ERROR, 0)
            transaction._transaction_metrics[KWARGS_ERROR] = m + 1

        name = callable_name(callback)
        with FunctionTrace(transaction=transaction, name=name):
            return callback(*args, **kwargs)
def _nr_wrapper_APIView_dispatch_(wrapped, instance, args, kwargs):
    transaction = current_transaction()

    if transaction is None:
        return wrapped(*args, **kwargs)

    def _args(request, *args, **kwargs):
        return request

    view = instance
    request = _args(*args, **kwargs)
    request_method = request.method.lower()

    if request_method in view.http_method_names:
        handler = getattr(view, request_method, view.http_method_not_allowed)
    else:
        handler = view.http_method_not_allowed

    view_func = getattr(view, '_nr_view_func', None)
    view_func_callable_name = getattr(view, '_nr_view_func_callable_name',
            None)
    if view_func_callable_name:
        if handler == view.http_method_not_allowed:
            name = '%s.%s' % (view_func_callable_name,
                    'http_method_not_allowed')
        else:
            name = '%s.%s' % (view_func_callable_name, request_method)
    else:
        name = callable_name(handler)

    transaction.set_transaction_name(name)

    # catch exceptions handled by view.handle_exception
    view.handle_exception = _nr_wrapper_APIView_handle_exception_(
            view.handle_exception, request)

    with FunctionTrace(name=name, source=view_func or handler):
        return wrapped(*args, **kwargs)
Exemplo n.º 12
0
def _nr_wrapper_handler_(wrapped, instance, args, kwargs):
    transaction = current_transaction()

    if transaction is None:
        return wrapped(*args, **kwargs)

    name = callable_name(wrapped)
    view_class = getattr(wrapped, 'view_class', None)
    view = view_class or wrapped
    if view_class:
        try:
            method = args[0].method.lower()
            name = callable_name(view_class) + '.' + method
            view = getattr(view_class, method)
        except:
            pass
    
    transaction.set_transaction_name(name, priority=3)
    import sanic
    transaction.add_framework_info(name='Sanic', version=sanic.__version__)

    with FunctionTrace(name=name, source=view):
        return wrapped(*args, **kwargs)
Exemplo n.º 13
0
    def wrapper(wrapped, instance, args, kwargs):
        transaction = current_transaction()

        if transaction is None:
            return wrapped(*args, **kwargs)

        transaction.name_transaction(name, priority=priority)

        with FunctionTrace(transaction, name=name):
            try:
                return wrapped(*args, **kwargs)

            except:  # Catch all
                # Python 2.5 doesn't allow *args before keywords.
                # See http://bugs.python.org/issue3473.
                exc_info = sys.exc_info()
                transaction.record_exception(exc_info[0], exc_info[1],
                        exc_info[2], ignore_errors=['django.http:Http404',
                        'django.http.response:Http404'])
                raise

            finally:
                exc_info = None
Exemplo n.º 14
0
def _nr_wrapper_gen_coroutine_function_(wrapped, instance, args, kwargs):
    # This wrapper is applied outside of any instance of the gen.engine
    # and gen.coroutine decorators. We record the call as a function
    # trace, flagging it as a special coroutine instance. This also
    # works on conjunction with the wrapper on the Runner class, which
    # applies a wrapper to the generator when passed to the generator.
    # When this wrapped function is called, if the result of the
    # function that gen.engine or gen.coroutine calls is a generator,
    # the Runner is created and run. If running it, it will always call
    # into the generator at least once. On that first time the wrapper
    # for the generator will see the active transaction and can keep a
    # reference to it to allow the transaction to be reinstated across
    # calls of the generator to yield an item.

    transaction = retrieve_current_transaction()

    if transaction is None:
        return wrapped(*args, **kwargs)

    name = callable_name(wrapped)

    with FunctionTrace(transaction, '%s (coroutine)' % name):
        return wrapped(*args, **kwargs)
Exemplo n.º 15
0
def _nr_wrapper_RequestHandler_on_connection_close(wrapped, instance, args,
                                                   kwargs):

    # The RequestHandler.on_connection_close() method is called when the
    # client closes the connection prematurely before the request had
    # been completed. The callback itself wasn't registered at a point
    # where there was any request tracking so there shouldn't be any
    # active transaction when this is called. We track the call of the
    # wrapped method and then finalize the whole transaction.

    transaction = retrieve_current_transaction()

    if transaction:
        return wrapped(*args, **kwargs)

    handler = instance
    request = handler.request

    transaction = resume_request_monitoring(request)

    if transaction is None:
        return wrapped(*args, **kwargs)

    name = callable_name(wrapped)

    try:
        with FunctionTrace(transaction, name):
            result = wrapped(*args, **kwargs)

    except:  # Catch all
        finalize_request_monitoring(request, *sys.exc_info())
        raise

    else:
        finalize_request_monitoring(request)

        return result
    def execute_wrapper(wrapped, instance, args, kwargs):
        assert instance is not None

        handler = instance
        request = handler.request

        # Check to see if we are being called within the context of any
        # sort of transaction. If we are, then we don't bother doing
        # anything and just call the wrapped function. This should not
        # really ever occur but check anyway.

        transaction = current_transaction()

        if transaction is None:
            return wrapped(*args, **kwargs)

        if request.method not in handler.SUPPORTED_METHODS:
            return wrapped(*args, **kwargs)

        name = callable_name(getattr(handler, request.method.lower()))
        transaction.set_transaction_name(name)

        with FunctionTrace(transaction, name=name):
            return wrapped(*args, **kwargs)
Exemplo n.º 17
0
def test_sentinel_exited_complete_root_exception():
    """
    This test forces a transaction to exit while it still has an active trace
    this causes an exception to be raised in TraceCache complete_root(). It
    verifies that the sentinel.exited property is set to true if an exception
    is raised in complete_root(), and that the exception is caught.
    """

    txn = None
    sentinel = None
    txn = BackgroundTask(application_instance(), "Parent")
    txn.__enter__()
    sentinel = txn.root_span
    trace = FunctionTrace("trace")
    trace.__enter__()
    txn.__exit__(None, None, None)
    assert sentinel.exited
    # Make sure to exit properly so cleanup is performed
    trace.__exit__(None, None, None)
    txn.__exit__(None, None, None)
 async def __call__(self, scope, receive, send):
     await send({"type": "http.response.start", "status": 200, "headers": []})
     with FunctionTrace(name=callable_name(self.route)):
         await self.route(None)
Exemplo n.º 19
0
    def __call__(self, frame, event, arg):

        if event not in [
                'call', 'c_call', 'return', 'c_return', 'exception',
                'c_exception'
        ]:
            return

        parent = current_trace()

        if not parent:
            return

        # Not sure if setprofile() is reliable in the face of
        # coroutine systems based on greenlets so don't run
        # if we detect may be using greenlets.

        if (hasattr(sys, '_current_frames')
                and parent.thread_id not in sys._current_frames()):
            return

        co = frame.f_code
        func_name = co.co_name
        func_line_no = frame.f_lineno
        func_filename = co.co_filename

        def _callable_name():
            # A stack frame doesn't provide any information about the
            # original callable object. We thus need to try and
            # deduce what it is by searching through the stack
            # frame globals. This will still not work in many
            # cases, including lambdas, generator expressions,
            # and decorated attributes such as properties of
            # classes.

            try:
                if func_name in frame.f_globals:
                    if frame.f_globals[func_name].func_code is co:
                        return callable_name(frame.f_globals[func_name])

            except Exception:
                pass

            for name, obj in six.iteritems(frame.f_globals):
                try:
                    if obj.__dict__[func_name].func_code is co:
                        return callable_name(obj.__dict__[func_name])

                except Exception:
                    pass

        if event in ['call', 'c_call']:
            # Skip the outermost as we catch that with the root
            # function traces for the profile trace.

            if len(self.function_traces) == 0:
                self.function_traces.append(None)
                return

            if self.current_depth >= self.maximum_depth:
                self.function_traces.append(None)
                return

            if func_filename.startswith(AGENT_PACKAGE_DIRECTORY):
                self.function_traces.append(None)
                return

            if event == 'call':
                name = _callable_name()
                if not name:
                    name = '%s:%s#%s' % (func_filename, func_name,
                                         func_line_no)
            else:
                name = callable_name(arg)
                if not name:
                    name = '%s:@%s#%s' % (func_filename, func_name,
                                          func_line_no)

            function_trace = FunctionTrace(name=name, parent=parent)
            function_trace.__enter__()

            self.function_traces.append(function_trace)
            self.current_depth += 1

        elif event in ['return', 'c_return', 'c_exception']:
            if not self.function_traces:
                return

            try:
                function_trace = self.function_traces.pop()

            except IndexError:
                pass

            else:
                if function_trace:
                    function_trace.__exit__(None, None, None)
                    self.current_depth -= 1
Exemplo n.º 20
0
    def wrapper(wrapped, instance, args, kwargs):
        parent = current_trace()

        if parent is None:
            return wrapped(*args, **kwargs)

        if callable(name):
            if instance is not None:
                _name = name(instance, *args, **kwargs)
            else:
                _name = name(*args, **kwargs)

        elif name is None:
            _name = callable_name(wrapped)

        else:
            _name = name

        if callable(group):
            if instance is not None:
                _group = group(instance, *args, **kwargs)
            else:
                _group = group(*args, **kwargs)

        else:
            _group = group

        if callable(label):
            if instance is not None:
                _label = label(instance, *args, **kwargs)
            else:
                _label = label(*args, **kwargs)

        else:
            _label = label

        if callable(params):
            if instance is not None:
                _params = params(instance, *args, **kwargs)
            else:
                _params = params(*args, **kwargs)

        else:
            _params = params

        with FunctionTrace(_name, _group, _label, _params, parent=parent):
            if not hasattr(sys, 'getprofile'):
                return wrapped(*args, **kwargs)

            profiler = sys.getprofile()

            if profiler:
                return wrapped(*args, **kwargs)

            sys.setprofile(ProfileTrace(depth))

            try:
                return wrapped(*args, **kwargs)

            finally:
                sys.setprofile(None)
Exemplo n.º 21
0
 def _test():
     with FunctionTrace("trace", params={"secret": "super secret"}):
         pass
Exemplo n.º 22
0
    def __call__(self, frame, event, arg):

        if event not in ['call', 'c_call', 'return', 'c_return',
                'exception', 'c_exception']:
            return

        transaction = current_transaction()

        if not transaction:
            return

        # Not sure if setprofile() is reliable in the face of
        # coroutine systems based on greenlets so don't run
        # if we detect may be using greenlets.

        if (hasattr(sys, '_current_frames') and not
                transaction.thread_id in sys._current_frames()):
            return

        co = frame.f_code
        func_name = co.co_name
        func_line_no = frame.f_lineno
        func_filename = co.co_filename

        def _callable_name():
            # This is pretty ugly and inefficient, but a stack
            # frame doesn't provide any information about the
            # original callable object. We thus need to try and
            # deduce what it is by searching through the stack
            # frame globals. This will still not work in many
            # cases, including lambdas, generator expressions,
            # and decoratored attributes such as properties of
            # classes.

            try:
                if func_name in frame.f_globals:
                    if frame.f_globals[func_name].func_code is co:
                        return callable_name(frame.f_globals[func_name])

            except Exception:
                pass

            for name, obj in six.iteritems(frame.f_globals):
                try:
                    if obj.__dict__[func_name].func_code is co:
                        return callable_name(obj.__dict__[func_name])

                except Exception:
                    pass

        if event in ['call', 'c_call']:
            # Skip the outermost as we catch that with the root
            # function traces for the profile trace.

            if len(self.function_traces) == 0:
                self.function_traces.append(None)
                return

            if self.current_depth >= self.maximum_depth:
                self.function_traces.append(None)
                return

            if func_filename.startswith(AGENT_PACKAGE_DIRECTORY):
                self.function_traces.append(None)
                return

            if event == 'call':
                name = _callable_name()
                if not name:
                    name = '%s:%s#%s' % (func_filename, func_name,
                            func_line_no)
            else:
                name = callable_name(arg)
                if not name:
                    name = '%s:@%s#%s' % (func_filename, func_name,
                            func_line_no)

            function_trace = FunctionTrace(transaction, name=name)
            function_trace.__enter__()

            self.function_traces.append(function_trace)
            self.current_depth += 1

        elif event in ['return', 'c_return', 'c_exception']:
            if not self.function_traces:
                return

            try:
                function_trace = self.function_traces.pop()

            except IndexError:
                pass

            else:
                if function_trace:
                    function_trace.__exit__(None, None, None)
                    self.current_depth -= 1
Exemplo n.º 23
0
    def _test():
        transaction = current_transaction()
        transaction._sampled = True

        with FunctionTrace('span_generator'):
            pass
Exemplo n.º 24
0
        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)
Exemplo n.º 25
0
    def wrapper(wrapped, instance, args, kwargs):
        transaction = current_transaction()

        if transaction is None:
            return wrapped(*args, **kwargs)

        if callable(name):
            if instance is not None:
                _name = name(instance, *args, **kwargs)
            else:
                _name = name(*args, **kwargs)

        elif name is None:
            _name = callable_name(wrapped)

        else:
            _name = name

        if callable(group):
            if instance is not None:
                _group = group(instance, *args, **kwargs)
            else:
                _group = group(*args, **kwargs)

        else:
            _group = group

        if callable(label):
            if instance is not None:
                _label = label(instance, *args, **kwargs)
            else:
                _label = label(*args, **kwargs)

        else:
            _label = label

        if callable(params):
            if instance is not None:
                _params = params(instance, *args, **kwargs)
            else:
                _params = params(*args, **kwargs)

        else:
            _params = params

        def _generator(generator):
            _gname = '%s (generator)' % _name

            try:
                value = None
                exc = None

                while True:
                    transaction = current_transaction()

                    params = {}

                    frame = generator.gi_frame

                    params['filename'] = frame.f_code.co_filename
                    params['lineno'] = frame.f_lineno

                    with FunctionTrace(transaction,
                                       _gname,
                                       _group,
                                       params=params):
                        try:
                            if exc is not None:
                                yielded = generator.throw(*exc)
                                exc = None
                            else:
                                yielded = generator.send(value)

                        except StopIteration:
                            raise

                        except Exception:
                            raise

                    try:
                        value = yield yielded

                    except Exception:
                        exc = sys.exc_info()

            finally:
                generator.close()

        with FunctionTrace(transaction, _name, _group, _label, _params):
            try:
                result = wrapped(*args, **kwargs)

            except:  # Catch all
                raise

            else:
                if isinstance(result, types.GeneratorType):
                    return _generator(result)

                else:
                    return result
Exemplo n.º 26
0
class _WSGIApplicationIterable(object):

    def __init__(self, transaction, generator):
        self.transaction = transaction
        self.generator = generator
        self.response_trace = None
        self.closed = False

    def __iter__(self):
        self.start_trace()

        try:
            for item in self.generator:
                try:
                    self.transaction._calls_yield += 1
                    self.transaction._bytes_sent += len(item)
                except Exception:
                    pass

                yield item

        except GeneratorExit:
            raise

        except:  # Catch all
            self.transaction.record_exception(*sys.exc_info())
            raise

        finally:
            self.close()

    def start_trace(self):
        if not self.transaction._sent_start:
            self.transaction._sent_start = time.time()

        if not self.response_trace:
            self.response_trace = FunctionTrace(
                    name='Response', group='Python/WSGI')
            self.response_trace.__enter__()

    def close(self):
        if self.closed:
            return

        if self.response_trace:
            self.response_trace.__exit__(None, None, None)
            self.response_trace = None

        try:
            with FunctionTrace(
                    name='Finalize', group='Python/WSGI'):

                if isinstance(self.generator, _WSGIApplicationMiddleware):
                    self.generator.close()

                elif hasattr(self.generator, 'close'):
                    name = callable_name(self.generator.close)
                    with FunctionTrace(name):
                        self.generator.close()

        except:  # Catch all
            self.transaction.__exit__(*sys.exc_info())
            raise

        else:
            self.transaction.__exit__(None, None, None)
            self.transaction._sent_end = time.time()

        finally:
            self.closed = True
Exemplo n.º 27
0
 def _test():
     with FunctionTrace("_test", source=obj):
         pass
Exemplo n.º 28
0
def test_get_linking_metadata_api_inside_transaction():
    with FunctionTrace("test_linking_metadata") as trace:
        metadata = trace.get_linking_metadata()
        validate_metadata(metadata, EXPECTED_KEYS_TXN)
    metadata = trace.get_linking_metadata()
    validate_metadata(metadata, EXPECTED_KEYS_TRACE_ENDED)
Exemplo n.º 29
0
    def wrapper(wrapped, instance, args, kwargs):
        transaction = current_transaction(active_only=False)

        if callable(name):
            # Start Hotfix v2.2.1.
            # if instance and inspect.ismethod(wrapped):
            #     _name = name(instance, *args, **kwargs)
            # else:
            #     _name = name(*args, **kwargs)

            if instance is not None:
                _name = name(instance, *args, **kwargs)
            else:
                _name = name(*args, **kwargs)
            # End Hotfix v2.2.1.

        elif name is None:
            _name = callable_name(wrapped)

        else:
            _name = name

        # Helper for obtaining the appropriate application object. If
        # has an activate() method assume it is a valid application
        # object. Don't check by type so se can easily mock it for
        # testing if need be.

        def _application():
            if hasattr(application, 'activate'):
                return application
            return application_instance(application)

        # A Celery Task can be called either outside of a transaction, or
        # within the context of an existing transaction. There are 3
        # possibilities we need to handle:
        #
        #   1. In an inactive transaction
        #
        #      If the end_of_transaction() or ignore_transaction() API calls
        #      have been invoked, this task may be called in the context
        #      of an inactive transaction. In this case, don't wrap the task
        #      in any way. Just run the original function.
        #
        #   2. In an active transaction
        #
        #      Run the original function inside a FunctionTrace.
        #
        #   3. Outside of a transaction
        #
        #      This is the typical case for a celery Task. Since it's not
        #      running inside of an existing transaction, we want to create
        #      a new background transaction for it.

        if transaction and (transaction.ignore_transaction
                            or transaction.stopped):
            return wrapped(*args, **kwargs)

        elif transaction:
            with FunctionTrace(callable_name(wrapped)):
                return wrapped(*args, **kwargs)

        else:
            with BackgroundTask(_application(), _name, 'Celery'):
                return wrapped(*args, **kwargs)
Exemplo n.º 30
0
    def _nr_wsgi_application_wrapper_(wrapped, instance, args, kwargs):
        # Check to see if any transaction is present, even an inactive
        # one which has been marked to be ignored or which has been
        # stopped already.

        transaction = current_transaction(active_only=False)

        if transaction:
            # If there is any active transaction we will return without
            # applying a new WSGI application wrapper context. In the
            # case of a transaction which is being ignored or which has
            # been stopped, we do that without doing anything further.

            if transaction.ignore_transaction or transaction.stopped:
                return wrapped(*args, **kwargs)

            # For any other transaction, we record the details of any
            # framework against the transaction for later reporting as
            # supportability metrics.

            if framework:
                transaction.add_framework_info(
                        name=framework[0], version=framework[1])

            # Also override the web transaction name to be the name of
            # the wrapped callable if not explicitly named, and we want
            # the default name to be that of the WSGI component for the
            # framework. This will override the use of a raw URL which
            # can result in metric grouping issues where a framework is
            # not instrumented or is leaking URLs.

            settings = transaction._settings

            if name is None and settings:
                if framework is not None:
                    naming_scheme = settings.transaction_name.naming_scheme
                    if naming_scheme in (None, 'framework'):
                        transaction.set_transaction_name(
                                callable_name(wrapped), priority=1)

            elif name:
                transaction.set_transaction_name(name, group, priority=1)

            return wrapped(*args, **kwargs)

        # Otherwise treat it as top level transaction. We have to though
        # look first to see whether the application name has been
        # overridden through the WSGI environ dictionary.

        def _args(environ, start_response, *args, **kwargs):
            return environ, start_response

        environ, start_response = _args(*args, **kwargs)

        target_application = application

        if 'newrelic.app_name' in environ:
            app_name = environ['newrelic.app_name']

            if ';' in app_name:
                app_names = [n.strip() for n in app_name.split(';')]
                app_name = app_names[0]
                target_application = application_instance(app_name)
                for altname in app_names[1:]:
                    target_application.link_to_application(altname)
            else:
                target_application = application_instance(app_name)
        else:
            # If application has an activate() method we assume it is an
            # actual application. Do this rather than check type so that
            # can easily mock it for testing.

            # FIXME Should this allow for multiple apps if a string.

            if not hasattr(application, 'activate'):
                target_application = application_instance(application)

        # Now start recording the actual web transaction.
        transaction = WSGIWebTransaction(target_application, environ)
        transaction.__enter__()

        # Record details of framework against the transaction for later
        # reporting as supportability metrics.

        if framework:
            transaction.add_framework_info(
                    name=framework[0], version=framework[1])

        # Override the initial web transaction name to be the supplied
        # name, or the name of the wrapped callable if wanting to use
        # the callable as the default. This will override the use of a
        # raw URL which can result in metric grouping issues where a
        # framework is not instrumented or is leaking URLs.
        #
        # Note that at present if default for naming scheme is still
        # None and we aren't specifically wrapping a designated
        # framework, then we still allow old URL based naming to
        # override. When we switch to always forcing a name we need to
        # check for naming scheme being None here.

        settings = transaction._settings

        if name is None and settings:
            naming_scheme = settings.transaction_name.naming_scheme

            if framework is not None:
                if naming_scheme in (None, 'framework'):
                    transaction.set_transaction_name(
                            callable_name(wrapped), priority=1)

            elif naming_scheme in ('component', 'framework'):
                transaction.set_transaction_name(
                        callable_name(wrapped), priority=1)

        elif name:
            transaction.set_transaction_name(name, group, priority=1)

        def _start_response(status, response_headers, *args):

            additional_headers = transaction.process_response(
                    status, response_headers, *args)

            _write = start_response(status,
                    response_headers + additional_headers, *args)

            def write(data):
                if not transaction._sent_start:
                    transaction._sent_start = time.time()
                result = _write(data)
                transaction._calls_write += 1
                try:
                    transaction._bytes_sent += len(data)
                except Exception:
                    pass
                transaction._sent_end = time.time()
                return result

            return write

        try:
            # Should always exist, but check as test harnesses may not
            # have it.

            if 'wsgi.input' in environ:
                environ['wsgi.input'] = _WSGIInputWrapper(transaction,
                        environ['wsgi.input'])

            with FunctionTrace(
                    name='Application', group='Python/WSGI'):
                with FunctionTrace(name=callable_name(wrapped)):
                    if (settings and settings.browser_monitoring.enabled and
                            not transaction.autorum_disabled):
                        result = _WSGIApplicationMiddleware(wrapped,
                                environ, _start_response, transaction)
                    else:
                        result = wrapped(environ, _start_response)

        except:  # Catch all
            transaction.__exit__(*sys.exc_info())
            raise

        return _WSGIApplicationIterable(transaction, result)
 def _make_request():
     with FunctionTrace(name="parent", terminal=True):
         response = yield client.fetch("http://localhost:%s" % port)
     return response