Example #1
0
    def call(self, module, method, wrapped, instance, args, kwargs):
        signature = "psycopg2.connect"

        host = kwargs.get("host")
        if host:
            signature += " " + compat.text_type(host)

            port = kwargs.get("port")
            if port:
                port = str(port)
                if int(port) != default_ports.get("postgresql"):
                    host += ":" + port
            signature += " " + compat.text_type(host)
        else:
            # Parse connection string and extract host/port
            pass
        destination_info = {
            "address": kwargs.get("host", "localhost"),
            "port": int(kwargs.get("port", default_ports.get("postgresql"))),
            "service": {"name": "postgresql", "resource": "postgresql", "type": "db"},
        }
        with capture_span(
            signature,
            span_type="db",
            span_subtype="postgresql",
            span_action="connect",
            extra={"destination": destination_info},
        ):
            return PGConnectionProxy(wrapped(*args, **kwargs), destination_info=destination_info)
async def test_aiomysql_select(instrument, aiomysql_connection,
                               elasticapm_client):
    try:
        elasticapm_client.begin_transaction("web.django")

        async with aiomysql_connection.cursor() as cursor:
            query = "SELECT * FROM test WHERE `name` LIKE 't%' ORDER BY id"
            await cursor.execute(query)
            assert await cursor.fetchall() == ((2, "two"), (3, "three"))

        elasticapm_client.end_transaction(None, "test-transaction")
    finally:
        transactions = elasticapm_client.events[TRANSACTION]
        spans = elasticapm_client.spans_for_transaction(transactions[0])
        span = spans[0]
        assert span["name"] == "SELECT FROM test"
        assert span["type"] == "db"
        assert span["subtype"] == "mysql"
        assert span["action"] == "query"
        assert "db" in span["context"]
        assert span["context"]["db"]["type"] == "sql"
        assert span["context"]["db"]["statement"] == query
        assert span["context"]["destination"] == {
            "address": os.environ.get("MYSQL_HOST", "localhost"),
            "port": default_ports.get("mysql"),
            "service": {
                "name": "mysql",
                "resource": "mysql",
                "type": "db"
            },
        }
Example #3
0
 def call(self, module, method, wrapped, instance, args, kwargs):
     destination_info = {
         "address": kwargs.get("host", "localhost"),
         "port": int(kwargs.get("port", default_ports.get("mysql"))),
     }
     return MySQLConnectionProxy(wrapped(*args, **kwargs),
                                 destination_info=destination_info)
Example #4
0
def get_host_from_url(url):
    parsed_url = urlparse.urlparse(url)
    host = parsed_url.hostname or " "

    if parsed_url.port and default_ports.get(parsed_url.scheme) != parsed_url.port:
        host += ":" + str(parsed_url.port)

    return host
Example #5
0
    def call(self, module, method, wrapped, instance, args, kwargs):
        if "method" in kwargs:
            method = kwargs["method"]
        else:
            method = args[0]

        headers = None
        if "headers" in kwargs:
            headers = kwargs["headers"]
            if headers is None:
                headers = {}
                kwargs["headers"] = headers

        host = instance.host

        if instance.port != default_ports.get(instance.scheme):
            host += ":" + str(instance.port)

        if "url" in kwargs:
            url = kwargs["url"]
        else:
            url = args[1]

        signature = method.upper() + " " + host

        url = "%s://%s%s" % (instance.scheme, host, url)
        destination = url_to_destination(url)

        transaction = execution_context.get_transaction()

        with capture_span(
                signature,
                span_type="external",
                span_subtype="http",
                extra={
                    "http": {
                        "url": url
                    },
                    "destination": destination
                },
                leaf=True,
        ) as span:
            # if urllib3 has been called in a leaf span, this span might be a DroppedSpan.
            leaf_span = span
            while isinstance(leaf_span, DroppedSpan):
                leaf_span = leaf_span.parent

            if headers is not None:
                # It's possible that there are only dropped spans, e.g. if we started dropping spans.
                # In this case, the transaction.id is used
                parent_id = leaf_span.id if leaf_span else transaction.id
                trace_parent = transaction.trace_parent.copy_from(
                    span_id=parent_id,
                    trace_options=TracingOptions(recorded=True))
                self._set_disttracing_headers(headers, trace_parent,
                                              transaction)
            return wrapped(*args, **kwargs)
Example #6
0
    def call(self, module, method, wrapped, instance, args, kwargs):
        if "method" in kwargs:
            method = kwargs["method"]
        else:
            method = args[0]

        host = instance.host

        if instance.port != default_ports.get(instance.scheme):
            host += ":" + str(instance.port)

        if "url" in kwargs:
            url = kwargs["url"]
        else:
            url = args[1]

        signature = method.upper() + " " + host

        url = "%s://%s%s" % (instance.scheme, host, url)
        destination = url_to_destination(url)

        transaction = execution_context.get_transaction()

        with capture_span(
                signature,
                span_type="external",
                span_subtype="http",
                extra={
                    "http": {
                        "url": url
                    },
                    "destination": destination
                },
                leaf=True,
        ) as span:
            # if urllib3 has been called in a leaf span, this span might be a DroppedSpan.
            leaf_span = span
            while isinstance(leaf_span, DroppedSpan):
                leaf_span = leaf_span.parent

            parent_id = leaf_span.id if leaf_span else transaction.id
            trace_parent = transaction.trace_parent.copy_from(
                span_id=parent_id, trace_options=TracingOptions(recorded=True))
            args, kwargs = update_headers(args, kwargs, instance, transaction,
                                          trace_parent)
            response = wrapped(*args, **kwargs)
            if response:
                if span.context:
                    span.context["http"]["status_code"] = response.status
                span.set_success(
                ) if response.status < 400 else span.set_failure()
            return response
Example #7
0
def get_host_port(args, kwargs):
    host = args[0] if args else kwargs.get("server")
    port = None
    if not host:
        host = kwargs.get("host", "localhost")
        for sep in (",", ":"):
            if sep in host:
                host, port = host.rsplit(sep, 1)
                port = int(port)
                break
    if not port:
        port = int(kwargs.get("port", default_ports.get("mssql")))
    return host, port
Example #8
0
    def call(self, module, method, wrapped, instance, args, kwargs):
        if "method" in kwargs:
            method = kwargs["method"]
        else:
            method = args[0]

        headers = None
        if "headers" in kwargs:
            headers = kwargs["headers"]
            if headers is None:
                headers = {}
                kwargs["headers"] = headers

        host = instance.host

        if instance.port != default_ports.get(instance.scheme):
            host += ":" + str(instance.port)

        if "url" in kwargs:
            url = kwargs["url"]
        else:
            url = args[1]

        signature = method.upper() + " " + host

        # TODO: reconstruct URL more faithfully, e.g. include port
        url = instance.scheme + "://" + host + url
        transaction = execution_context.get_transaction()

        with capture_span(signature,
                          span_type="external",
                          span_subtype="http",
                          extra={"http": {
                              "url": url
                          }},
                          leaf=True) as span:
            # if urllib3 has been called in a leaf span, this span might be a DroppedSpan.
            leaf_span = span
            while isinstance(leaf_span, DroppedSpan):
                leaf_span = leaf_span.parent

            if headers is not None:
                # It's possible that there are only dropped spans, e.g. if we started dropping spans.
                # In this case, the transaction.id is used
                parent_id = leaf_span.id if leaf_span else transaction.id
                trace_parent = transaction.trace_parent.copy_from(
                    span_id=parent_id,
                    trace_options=TracingOptions(recorded=True))
                headers[constants.
                        TRACEPARENT_HEADER_NAME] = trace_parent.to_string()
            return wrapped(*args, **kwargs)
Example #9
0
 def call(self, module, method, wrapped, instance, args, kwargs):
     destination_info = {
         "address":
         args[0] if len(args) else kwargs.get("host", "localhost"),
         "port":
         args[4] if len(args) > 4 else int(
             kwargs.get("port", default_ports.get("mysql"))),
         "service": {
             "name": "mysql",
             "resource": "mysql",
             "type": "db"
         },
     }
     return MySQLConnectionProxy(wrapped(*args, **kwargs),
                                 destination_info=destination_info)
Example #10
0
def get_destination_info(host: Optional[str], port: Union[None, str,
                                                          int]) -> tuple:
    if host:
        if "," in host:  # multiple hosts defined, take first
            host = host.split(",")[0]
    else:
        host = "localhost"
    if port:
        port = str(port)
        if "," in port:  # multiple ports defined, take first
            port = port.split(",")[0]
        port = int(port)
    else:
        port = default_ports.get("postgresql")
    return host, port
Example #11
0
    def call(self, module, method, wrapped, instance, args, kwargs):
        signature = "psycopg2.connect"

        host = kwargs.get('host')
        if host:
            signature += " " + str(host)

            port = kwargs.get('port')
            if port:
                port = str(port)
                if int(port) != default_ports.get("postgresql"):
                    signature += ":" + port
        else:
            # Parse connection string and extract host/port
            pass

        with capture_span(signature, "db.postgreql.connect"):
            return PGConnectionProxy(wrapped(*args, **kwargs))
Example #12
0
    def call(self, module, method, wrapped, instance, args, kwargs):
        url, method, headers = utils.get_request_data(args, kwargs)
        scheme, host, port, target = url
        if port != default_ports.get(scheme):
            host += ":" + str(port)

        signature = "%s %s" % (method.upper(), host)

        url = "%s://%s%s" % (scheme, host, target)

        transaction = execution_context.get_transaction()

        with capture_span(
                signature,
                span_type="external",
                span_subtype="http",
                extra={"http": {
                    "url": url
                }},
                leaf=True,
        ) as span:
            # if httpcore has been called in a leaf span, this span might be a DroppedSpan.
            leaf_span = span
            while isinstance(leaf_span, DroppedSpan):
                leaf_span = leaf_span.parent

            if headers is not None:
                # It's possible that there are only dropped spans, e.g. if we started dropping spans.
                # In this case, the transaction.id is used
                parent_id = leaf_span.id if leaf_span else transaction.id
                trace_parent = transaction.trace_parent.copy_from(
                    span_id=parent_id,
                    trace_options=TracingOptions(recorded=True))
                utils.set_disttracing_headers(headers, trace_parent,
                                              transaction)
                if leaf_span:
                    leaf_span.dist_tracing_propagated = True
            response = wrapped(*args, **kwargs)
            status_code = utils.get_status(response)
            if status_code:
                if span.context:
                    span.context["http"]["status_code"] = status_code
                span.set_success() if status_code < 400 else span.set_failure()
            return response
Example #13
0
def request_host(request):
    """Return request-host, as defined by RFC 2965.

    Variation from RFC: returned value is lowercased, for convenient
    comparison.

    """
    url = request.get_full_url()
    parse_result = compat.urlparse.urlparse(url)
    scheme, host, port = parse_result.scheme, parse_result.hostname, parse_result.port
    try:
        port = int(port)
    except (ValueError, TypeError):
        pass
    if host == "":
        host = request.get_header("Host", "")

    if port and port != default_ports.get(scheme):
        host = "%s:%s" % (host, port)
    return host
Example #14
0
    def call(self, module, method, wrapped, instance, args, kwargs):
        if 'method' in kwargs:
            method = kwargs['method']
        else:
            method = args[0]

        host = instance.host

        if instance.port != default_ports.get(instance.scheme):
            host += ":" + str(instance.port)

        if 'url' in kwargs:
            url = kwargs['url']
        else:
            url = args[1]

        signature = method.upper() + " " + host

        url = instance.scheme + "://" + host + url

        with trace(signature, "ext.http.urllib3", {'url': url}, leaf=True):
            return wrapped(*args, **kwargs)
Example #15
0
 async def call(self, module, method, wrapped, instance, args, kwargs):
     query = args[0] if len(args) else kwargs["query"]
     name = extract_signature(query)
     context = {"db": {"type": "sql", "statement": query}}
     action = "query"
     destination_info = {
         "address": kwargs.get("host", "localhost"),
         "port": int(kwargs.get("port", default_ports.get("postgresql"))),
         "service": {
             "name": "postgres",
             "resource": "postgres",
             "type": "db"
         },
     }
     context["destination"] = destination_info
     async with async_capture_span(name,
                                   leaf=True,
                                   span_type="db",
                                   span_subtype="postgres",
                                   span_action=action,
                                   extra=context):
         return await wrapped(*args, **kwargs)
Example #16
0
 async def call(self, module, method, wrapped, instance, args, kwargs):
     query = self.get_query(method, args)
     name = extract_signature(query)
     sql_string = shorten(query, string_length=10000)
     context = {"db": {"type": "sql", "statement": sql_string}}
     action = "query"
     destination_info = {
         "address": kwargs.get("host", "localhost"),
         "port": int(kwargs.get("port", default_ports.get("postgresql"))),
         "service": {
             "name": "",
             "resource": "postgresql",
             "type": ""
         },
     }
     context["destination"] = destination_info
     async with async_capture_span(name,
                                   leaf=True,
                                   span_type="db",
                                   span_subtype="postgresql",
                                   span_action=action,
                                   extra=context):
         return await wrapped(*args, **kwargs)
Example #17
0
    def call(self, module, method, wrapped, instance, args, kwargs):
        if "method" in kwargs:
            method = kwargs["method"]
        else:
            method = args[0]

        host = instance.host

        if instance.port != default_ports.get(instance.scheme):
            host += ":" + str(instance.port)

        if "url" in kwargs:
            url = kwargs["url"]
        else:
            url = args[1]

        signature = method.upper() + " " + host

        url = instance.scheme + "://" + host + url

        with capture_span(signature,
                          "ext.http.urllib3", {"url": url},
                          leaf=True):
            return wrapped(*args, **kwargs)
Example #18
0
    def call(self, module, method, wrapped, instance, args, kwargs):
        if "method" in kwargs:
            method = kwargs["method"].decode("utf-8")
        else:
            method = args[0].decode("utf-8")

        # URL is a tuple of (scheme, host, port, path), we want path
        if "url" in kwargs:
            url = kwargs["url"][3].decode("utf-8")
        else:
            url = args[1][3].decode("utf-8")

        headers = None
        if "headers" in kwargs:
            headers = kwargs["headers"]
            if headers is None:
                headers = []
                kwargs["headers"] = headers

        scheme, host, port = instance.origin
        scheme = scheme.decode("utf-8")
        host = host.decode("utf-8")

        if port != default_ports.get(scheme):
            host += ":" + str(port)

        signature = "%s %s" % (method.upper(), host)

        url = "%s://%s%s" % (scheme, host, url)
        destination = url_to_destination(url)

        transaction = execution_context.get_transaction()

        with capture_span(
                signature,
                span_type="external",
                span_subtype="http",
                extra={
                    "http": {
                        "url": url
                    },
                    "destination": destination
                },
                leaf=True,
        ) as span:
            # if httpcore has been called in a leaf span, this span might be a DroppedSpan.
            leaf_span = span
            while isinstance(leaf_span, DroppedSpan):
                leaf_span = leaf_span.parent

            if headers is not None:
                # It's possible that there are only dropped spans, e.g. if we started dropping spans.
                # In this case, the transaction.id is used
                parent_id = leaf_span.id if leaf_span else transaction.id
                trace_parent = transaction.trace_parent.copy_from(
                    span_id=parent_id,
                    trace_options=TracingOptions(recorded=True))
                self._set_disttracing_headers(headers, trace_parent,
                                              transaction)
            response = wrapped(*args, **kwargs)
            if len(response) > 4:
                # httpcore < 0.11.0
                # response = (http_version, status_code, reason_phrase, headers, stream)
                status_code = response[1]
            else:
                # httpcore >= 0.11.0
                # response = (status_code, headers, stream, ext)
                status_code = response[0]
            if status_code:
                if span.context:
                    span.context["http"]["status_code"] = status_code
                span.set_success() if status_code < 400 else span.set_failure()
            return response