Exemplo n.º 1
0
def patch():
    """ patch the built-in urllib/httplib/httplib.client methods for tracing"""
    if getattr(httplib, "__datadog_patch", False):
        return
    setattr(httplib, "__datadog_patch", True)

    # Patch the desired methods
    setattr(httplib.HTTPConnection, "__init__",
            wrapt.FunctionWrapper(httplib.HTTPConnection.__init__, _wrap_init))
    setattr(
        httplib.HTTPConnection,
        "getresponse",
        wrapt.FunctionWrapper(httplib.HTTPConnection.getresponse,
                              _wrap_getresponse),
    )
    setattr(
        httplib.HTTPConnection, "request",
        wrapt.FunctionWrapper(httplib.HTTPConnection.request, _wrap_request))
    setattr(
        httplib.HTTPConnection, "putrequest",
        wrapt.FunctionWrapper(httplib.HTTPConnection.putrequest,
                              _wrap_putrequest))
    setattr(
        httplib.HTTPConnection, "putheader",
        wrapt.FunctionWrapper(httplib.HTTPConnection.putheader,
                              _wrap_putheader))
Exemplo n.º 2
0
def instrument_view(django, view):
    """Helper to wrap Django views."""
    # All views should be callable, double check before doing anything
    if not callable(view) or isinstance(view, wrapt.ObjectProxy):
        return view

    # Patch view HTTP methods and lifecycle methods
    http_method_names = getattr(view, "http_method_names",
                                ("get", "delete", "post", "options", "head"))
    lifecycle_methods = ("setup", "dispatch", "http_method_not_allowed")
    for name in list(http_method_names) + list(lifecycle_methods):
        try:
            # View methods can be staticmethods
            func = getattr_static(view, name, None)
            if not func or isinstance(func, wrapt.ObjectProxy):
                continue

            resource = "{0}.{1}".format(func_name(view), name)
            op_name = "django.view.{0}".format(name)

            # Set attribute here rather than using wrapt.wrappers.wrap_function_wrapper
            # since it will not resolve attribute to staticmethods
            wrapper = wrapt.FunctionWrapper(
                func, traced_func(django, name=op_name, resource=resource))
            setattr(view, name, wrapper)
        except Exception:
            log.debug("Failed to instrument Django view %r function %s",
                      view,
                      name,
                      exc_info=True)

    # Patch response methods
    response_cls = getattr(view, "response_class", None)
    if response_cls:
        methods = ("render", )
        for name in methods:
            try:
                func = getattr(response_cls, name, None)
                # Do not wrap if the method does not exist or is already wrapped
                if not func or isinstance(func, wrapt.ObjectProxy):
                    continue

                resource = "{0}.{1}".format(func_name(response_cls), name)
                op_name = "django.response.{0}".format(name)
                wrap(response_cls, name,
                     traced_func(django, name=op_name, resource=resource))
            except Exception:
                log.debug(
                    "Failed to instrument Django response %r function %s",
                    response_cls,
                    name,
                    exc_info=True)

    # Return a wrapped version of this view
    return wrapt.FunctionWrapper(
        view, traced_func(django, "django.view", resource=func_name(view)))
Exemplo n.º 3
0
def _instrument_view(django, view):
    """Helper to wrap Django views."""
    # All views should be callable, double check before doing anything
    if not callable(view):
        return view

    # Patch view HTTP methods and lifecycle methods
    http_method_names = getattr(view, "http_method_names",
                                ("get", "delete", "post", "options", "head"))
    lifecycle_methods = ("setup", "dispatch", "http_method_not_allowed")
    for name in list(http_method_names) + list(lifecycle_methods):
        try:
            func = getattr(view, name, None)
            if not func or isinstance(func, wrapt.ObjectProxy):
                continue

            resource = "{0}.{1}".format(func_name(view), name)
            op_name = "django.view.{0}".format(name)
            trace_utils.wrap(
                view, name, traced_func(django,
                                        name=op_name,
                                        resource=resource))
        except Exception:
            log.debug("Failed to instrument Django view %r function %s",
                      view,
                      name,
                      exc_info=True)

    # Patch response methods
    response_cls = getattr(view, "response_class", None)
    if response_cls:
        methods = ("render", )
        for name in methods:
            try:
                func = getattr(response_cls, name, None)
                # Do not wrap if the method does not exist or is already wrapped
                if not func or isinstance(func, wrapt.ObjectProxy):
                    continue

                resource = "{0}.{1}".format(func_name(response_cls), name)
                op_name = "django.response.{0}".format(name)
                trace_utils.wrap(
                    response_cls, name,
                    traced_func(django, name=op_name, resource=resource))
            except Exception:
                log.debug(
                    "Failed to instrument Django response %r function %s",
                    response_cls,
                    name,
                    exc_info=True)

    # If the view itself is not wrapped, wrap it
    if not isinstance(view, wrapt.ObjectProxy):
        view = wrapt.FunctionWrapper(
            view,
            traced_func(django,
                        "django.view",
                        resource=func_name(view),
                        ignored_excs=[django.http.Http404]))
    return view
Exemplo n.º 4
0
def patch_conn(django, conn):
    def cursor(django, pin, func, instance, args, kwargs):
        alias = getattr(conn, "alias", "default")

        if config.django.database_service_name:
            service = config.django.database_service_name
        else:
            database_prefix = config.django.database_service_name_prefix
            service = "{}{}{}".format(database_prefix, alias, "db")

        vendor = getattr(conn, "vendor", "db")
        prefix = sqlx.normalize_vendor(vendor)
        tags = {
            "django.db.vendor": vendor,
            "django.db.alias": alias,
        }
        pin = Pin(service, tags=tags, tracer=pin.tracer, app=prefix)
        cursor = func(*args, **kwargs)
        traced_cursor_cls = dbapi.TracedCursor
        if (Psycopg2TracedCursor is not None and hasattr(cursor, "cursor")
                and isinstance(cursor.cursor, psycopg_cursor_cls)):
            traced_cursor_cls = Psycopg2TracedCursor
        return traced_cursor_cls(cursor, pin, config.django)

    if not isinstance(conn.cursor, wrapt.ObjectProxy):
        conn.cursor = wrapt.FunctionWrapper(
            conn.cursor,
            trace_utils.with_traced_module(cursor)(django))
Exemplo n.º 5
0
def traced_connect(func, instance, args, kwargs):
    session = func(*args, **kwargs)
    if not isinstance(session.execute, wrapt.FunctionWrapper):
        # FIXME[matt] this should probably be private.
        setattr(
            session, 'execute_async',
            wrapt.FunctionWrapper(session.execute_async, traced_execute_async))
    return session
Exemplo n.º 6
0
 def wrapped_factory(func, instance, args, kwargs):
     # r is the middleware handler function returned from the factory
     r = func(*args, **kwargs)
     if r:
         return wrapt.FunctionWrapper(r, traced_func(django, "django.middleware", resource=mw_path))
     # If r is an empty middleware function (i.e. returns None), don't wrap since NoneType cannot be called
     else:
         return r
Exemplo n.º 7
0
def traced_as_view(django, pin, func, instance, args, kwargs):
    """
    Wrapper for django's View.as_view class method
    """
    try:
        instrument_view(django, instance)
    except Exception:
        log.debug("Failed to instrument Django view %r", instance, exc_info=True)
    view = func(*args, **kwargs)
    return wrapt.FunctionWrapper(view, traced_func(django, "django.view", resource=func_name(view)))
Exemplo n.º 8
0
def traced_execute_async(func, instance, args, kwargs):
    cluster = getattr(instance, 'cluster', None)
    pin = Pin.get_from(cluster)
    if not pin or not pin.enabled():
        return func(*args, **kwargs)

    query = kwargs.get("query") or args[0]

    span = _start_span_and_set_tags(pin, query, instance, cluster)

    try:
        result = func(*args, **kwargs)
        setattr(result, CURRENT_SPAN, span)
        setattr(result, PAGE_NUMBER, 1)
        setattr(
            result, '_set_final_result',
            wrapt.FunctionWrapper(result._set_final_result,
                                  traced_set_final_result))
        setattr(
            result, '_set_final_exception',
            wrapt.FunctionWrapper(result._set_final_exception,
                                  traced_set_final_exception))
        setattr(
            result, 'start_fetching_next_page',
            wrapt.FunctionWrapper(result.start_fetching_next_page,
                                  traced_start_fetching_next_page))
        # Since we cannot be sure that the previous methods were overwritten
        # before the call ended, we add callbacks that will be run
        # synchronously if the call already returned and we remove them right
        # after.
        result.add_callbacks(_close_span_on_success,
                             _close_span_on_error,
                             callback_args=(result, ),
                             errback_args=(result, ))
        result.clear_callbacks()
        return result
    except Exception:
        with span:
            span.set_exc_info(*sys.exc_info())
        raise
Exemplo n.º 9
0
def instrument_dbs(django):
    def set_connection(wrapped, instance, args, kwargs):
        _, conn = args
        try:
            patch_conn(django, conn)
        except Exception:
            log.debug("Error instrumenting database connection %r", conn, exc_info=True)
        return wrapped(*args, **kwargs)

    if not isinstance(django.db.connections.__setitem__, wrapt.ObjectProxy):
        django.db.connections.__setitem__ = wrapt.FunctionWrapper(django.db.connections.__setitem__, set_connection)

    if hasattr(django.db, "connection") and not isinstance(django.db.connection.cursor, wrapt.ObjectProxy):
        patch_conn(django, django.db.connection)
Exemplo n.º 10
0
def instrument_dbs(django):
    def get_connection(wrapped, instance, args, kwargs):
        conn = wrapped(*args, **kwargs)
        try:
            patch_conn(django, conn)
        except Exception:
            log.debug("Error instrumenting database connection %r",
                      conn,
                      exc_info=True)
        return conn

    if not isinstance(django.db.utils.ConnectionHandler.__getitem__,
                      wrapt.ObjectProxy):
        django.db.utils.ConnectionHandler.__getitem__ = wrapt.FunctionWrapper(
            django.db.utils.ConnectionHandler.__getitem__, get_connection)
Exemplo n.º 11
0
def instrument_dbs(django):
    def all_connections(wrapped, instance, args, kwargs):
        conns = wrapped(*args, **kwargs)
        for conn in conns:
            try:
                patch_conn(django, conn)
            except Exception:
                log.debug("Error instrumenting database connection %r", conn, exc_info=True)
        return conns

    if not isinstance(django.db.connections.all, wrapt.ObjectProxy):
        django.db.connections.all = wrapt.FunctionWrapper(django.db.connections.all, all_connections)

    if hasattr(django.db, "connection") and not isinstance(django.db.connection.cursor, wrapt.ObjectProxy):
        patch_conn(django, django.db.connection)
Exemplo n.º 12
0
def patch_conn(django, conn):
    def cursor(django, pin, func, instance, args, kwargs):
        database_prefix = config.django.database_service_name_prefix
        alias = getattr(conn, "alias", "default")
        service = "{}{}{}".format(database_prefix, alias, "db")
        vendor = getattr(conn, "vendor", "db")
        prefix = sqlx.normalize_vendor(vendor)
        tags = {
            "django.db.vendor": vendor,
            "django.db.alias": alias,
        }
        pin = Pin(service, tags=tags, tracer=pin.tracer, app=prefix)
        return dbapi.TracedCursor(func(*args, **kwargs), pin)

    if not isinstance(conn.cursor, wrapt.ObjectProxy):
        conn.cursor = wrapt.FunctionWrapper(conn.cursor, with_traced_module(cursor)(django))
Exemplo n.º 13
0
 def wrapped_factory(func, instance, args, kwargs):
     # r is the middleware handler function returned from the factory
     r = func(*args, **kwargs)
     return wrapt.FunctionWrapper(
         r,
         traced_func(django, "django.middleware", resource=mw_path))
Exemplo n.º 14
0
def patch():
    """ patch will add tracing to the cassandra library. """
    setattr(cassandra.cluster.Cluster, 'connect',
            wrapt.FunctionWrapper(_connect, traced_connect))
    Pin(service=SERVICE, app=SERVICE,
        app_type="db").onto(cassandra.cluster.Cluster)
Exemplo n.º 15
0
 def request(self, conn=None):
     conn = conn or self.get_http_connection(SOCKET)
     with contextlib.closing(conn):
         conn.send = wrapt.FunctionWrapper(conn.send, self.send)
         conn.request("POST", "/status/200", body="key=value")
         conn.getresponse()
Exemplo n.º 16
0
def patch():
    wrapped = wrapt.FunctionWrapper(_connect, traced_connect)

    setattr(sqlite3, 'connect', wrapped)
    setattr(sqlite3.dbapi2, 'connect', wrapped)