We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
httpx instrumentation: IndexError: tuple index out of range
**Describe the bug**
In some cases `httpx` passes `request` param to its `httpx.Client.send()` as keyword argument rather than positional one, like e.g. when using `httpx.Client.stream()` in a context manager, which is unacceptable by `elastic-apm`.
**Please note same happens when using `httpx.AsyncClient.stream()` instead of sync `httpx.Client.stream()`**.

**Current workaround**
Disable `httpx` instrumenting (set environment variable `SKIP_INSTRUMENT_HTTPX="true"`) prior `elasticapm.instrument()` is called.

**To Reproduce**
```python3
import elasticapm
import httpx


def main():
    elasticapm.instrument()

    client = httpx.Client()
    elastic_apm_client = elasticapm.Client()

    elastic_apm_client.begin_transaction("httpx-context-manager-client-streaming")
    try:
        with client.stream("GET", url="https://example.com") as response:
            assert response
    finally:
        client.close()
        elastic_apm_client.end_transaction("httpx-context-manager-client-streaming")


if __name__ == "__main__":
    main()
```

**Expected result**
No exception is raised.

**Actual result**
```python3
Traceback (most recent call last):
  File "<...>/test.py", line 21, in <module>
    main()
  File "<...>/test.py", line 13, in main
    with client.stream("GET", url="https://example.com") as response:
  File "<...>/venv/lib/python3.8/site-packages/httpx/_client.py", line 1799, in __enter__
    self.response = self.client.send(
  File "<...>/venv/lib/python3.8/site-packages/elasticapm/instrumentation/packages/base.py", line 210, in call_if_sampling
    return self.call(module, method, wrapped, instance, args, kwargs)
  File "<...>/venv/lib/python3.8/site-packages/elasticapm/instrumentation/packages/httpx.py", line 42, in call
    request = kwargs.get("request", args[0])
IndexError: tuple index out of range
```

<br/>
<details>
<summary><b>See similar results for <code>httpx.AsyncClient.stream()</code></b></summary>

**To Reproduce**
```python3
import asyncio

import elasticapm
import httpx


async def main():
    elasticapm.instrument()

    client = httpx.AsyncClient()
    elastic_apm_client = elasticapm.Client()

    elastic_apm_client.begin_transaction("httpx-async-context-manager-client-streaming")
    try:
        async with client.stream("GET", url="https://example.com") as response:
            assert response
    finally:
        await client.aclose()
        elastic_apm_client.end_transaction(
            "httpx-async-context-manager-client-streaming",
        )


if __name__ == "__main__":
    asyncio.run(main())
```

**Actual result**
```python3
Traceback (most recent call last):
  File "<...>/test.py", line 23, in <module>
    asyncio.run(main())
  File "/usr/local/lib/python3.8/asyncio/runners.py", line 44, in run
    return loop.run_until_complete(main)
  File "/usr/local/lib/python3.8/asyncio/base_events.py", line 616, in run_until_complete
    return future.result()
  File "<...>/test.py", line 15, in main
    async with client.stream("GET", url="https://example.com") as response:
  File "<...>/venv/lib/python3.8/site-packages/httpx/_client.py", line 1821, in __aenter__
    self.response = await self.client.send(
  File "<...>/venv/lib/python3.8/site-packages/elasticapm/instrumentation/packages/asyncio/httpx.py", line 42, in call
    request = kwargs.get("request", args[0])
IndexError: tuple index out of range
```
</details>
<br/>

**Environment**
- OS: Ubuntu 18.04.5 LTS
- Python version: 3.8.9
- Framework and version: `httpx==0.17.1` (also reproducible with current latest `httpx==0.19.0`)
- APM Server version: --
- Agent version: `elasticapm==6.4.0`


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `elasticapm/instrumentation/packages/asyncio/httpx.py`
Content:
```
1 #  BSD 3-Clause License
2 #
3 #  Copyright (c) 2019, Elasticsearch BV
4 #  All rights reserved.
5 #
6 #  Redistribution and use in source and binary forms, with or without
7 #  modification, are permitted provided that the following conditions are met:
8 #
9 #  * Redistributions of source code must retain the above copyright notice, this
10 #    list of conditions and the following disclaimer.
11 #
12 #  * Redistributions in binary form must reproduce the above copyright notice,
13 #    this list of conditions and the following disclaimer in the documentation
14 #    and/or other materials provided with the distribution.
15 #
16 #  * Neither the name of the copyright holder nor the names of its
17 #    contributors may be used to endorse or promote products derived from
18 #    this software without specific prior written permission.
19 #
20 #  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 #  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 #  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 #  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24 #  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 #  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 #  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 #  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 #  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 #  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 from elasticapm.contrib.asyncio.traces import async_capture_span
32 from elasticapm.instrumentation.packages.asyncio.base import AsyncAbstractInstrumentedModule
33 from elasticapm.utils import get_host_from_url, sanitize_url, url_to_destination
34 
35 
36 class HttpxAsyncClientInstrumentation(AsyncAbstractInstrumentedModule):
37     name = "httpx"
38 
39     instrument_list = [("httpx", "AsyncClient.send")]
40 
41     async def call(self, module, method, wrapped, instance, args, kwargs):
42         request = kwargs.get("request", args[0])
43 
44         request_method = request.method.upper()
45         url = str(request.url)
46         name = "{request_method} {host}".format(request_method=request_method, host=get_host_from_url(url))
47         url = sanitize_url(url)
48         destination = url_to_destination(url)
49 
50         async with async_capture_span(
51             name,
52             span_type="external",
53             span_subtype="http",
54             extra={"http": {"url": url}, "destination": destination},
55             leaf=True,
56         ) as span:
57             response = await wrapped(*args, **kwargs)
58             if response is not None:
59                 if span.context:
60                     span.context["http"]["status_code"] = response.status_code
61                 span.set_success() if response.status_code < 400 else span.set_failure()
62             return response
63
```

Path: `elasticapm/instrumentation/packages/httpx.py`
Content:
```
1 #  BSD 3-Clause License
2 #
3 #  Copyright (c) 2019, Elasticsearch BV
4 #  All rights reserved.
5 #
6 #  Redistribution and use in source and binary forms, with or without
7 #  modification, are permitted provided that the following conditions are met:
8 #
9 #  * Redistributions of source code must retain the above copyright notice, this
10 #    list of conditions and the following disclaimer.
11 #
12 #  * Redistributions in binary form must reproduce the above copyright notice,
13 #    this list of conditions and the following disclaimer in the documentation
14 #    and/or other materials provided with the distribution.
15 #
16 #  * Neither the name of the copyright holder nor the names of its
17 #    contributors may be used to endorse or promote products derived from
18 #    this software without specific prior written permission.
19 #
20 #  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 #  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 #  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 #  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24 #  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 #  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 #  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 #  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 #  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 #  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 from elasticapm.instrumentation.packages.base import AbstractInstrumentedModule
32 from elasticapm.traces import capture_span
33 from elasticapm.utils import get_host_from_url, sanitize_url, url_to_destination
34 
35 
36 class HttpxClientInstrumentation(AbstractInstrumentedModule):
37     name = "httpx"
38 
39     instrument_list = [("httpx", "Client.send")]
40 
41     def call(self, module, method, wrapped, instance, args, kwargs):
42         request = kwargs.get("request", args[0])
43 
44         request_method = request.method.upper()
45         url = str(request.url)
46         name = "{request_method} {host}".format(request_method=request_method, host=get_host_from_url(url))
47         url = sanitize_url(url)
48         destination = url_to_destination(url)
49 
50         with capture_span(
51             name,
52             span_type="external",
53             span_subtype="http",
54             extra={"http": {"url": url}, "destination": destination},
55             leaf=True,
56         ) as span:
57             response = wrapped(*args, **kwargs)
58             if response is not None:
59                 if span.context:
60                     span.context["http"]["status_code"] = response.status_code
61                 span.set_success() if response.status_code < 400 else span.set_failure()
62             return response
63
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/elasticapm/instrumentation/packages/asyncio/httpx.py b/elasticapm/instrumentation/packages/asyncio/httpx.py
--- a/elasticapm/instrumentation/packages/asyncio/httpx.py
+++ b/elasticapm/instrumentation/packages/asyncio/httpx.py
@@ -39,7 +39,7 @@
     instrument_list = [("httpx", "AsyncClient.send")]
 
     async def call(self, module, method, wrapped, instance, args, kwargs):
-        request = kwargs.get("request", args[0])
+        request = kwargs.get("request") or args[0]
 
         request_method = request.method.upper()
         url = str(request.url)
diff --git a/elasticapm/instrumentation/packages/httpx.py b/elasticapm/instrumentation/packages/httpx.py
--- a/elasticapm/instrumentation/packages/httpx.py
+++ b/elasticapm/instrumentation/packages/httpx.py
@@ -39,7 +39,7 @@
     instrument_list = [("httpx", "Client.send")]
 
     def call(self, module, method, wrapped, instance, args, kwargs):
-        request = kwargs.get("request", args[0])
+        request = kwargs.get("request") or args[0]
 
         request_method = request.method.upper()
         url = str(request.url)

{"golden_diff": "diff --git a/elasticapm/instrumentation/packages/asyncio/httpx.py b/elasticapm/instrumentation/packages/asyncio/httpx.py\n--- a/elasticapm/instrumentation/packages/asyncio/httpx.py\n+++ b/elasticapm/instrumentation/packages/asyncio/httpx.py\n@@ -39,7 +39,7 @@\n     instrument_list = [(\"httpx\", \"AsyncClient.send\")]\n \n     async def call(self, module, method, wrapped, instance, args, kwargs):\n-        request = kwargs.get(\"request\", args[0])\n+        request = kwargs.get(\"request\") or args[0]\n \n         request_method = request.method.upper()\n         url = str(request.url)\ndiff --git a/elasticapm/instrumentation/packages/httpx.py b/elasticapm/instrumentation/packages/httpx.py\n--- a/elasticapm/instrumentation/packages/httpx.py\n+++ b/elasticapm/instrumentation/packages/httpx.py\n@@ -39,7 +39,7 @@\n     instrument_list = [(\"httpx\", \"Client.send\")]\n \n     def call(self, module, method, wrapped, instance, args, kwargs):\n-        request = kwargs.get(\"request\", args[0])\n+        request = kwargs.get(\"request\") or args[0]\n \n         request_method = request.method.upper()\n         url = str(request.url)\n", "issue": "httpx instrumentation: IndexError: tuple index out of range\n**Describe the bug**\r\nIn some cases `httpx` passes `request` param to its `httpx.Client.send()` as keyword argument rather than positional one, like e.g. when using `httpx.Client.stream()` in a context manager, which is unacceptable by `elastic-apm`.\r\n**Please note same happens when using `httpx.AsyncClient.stream()` instead of sync `httpx.Client.stream()`**.\r\n\r\n**Current workaround**\r\nDisable `httpx` instrumenting (set environment variable `SKIP_INSTRUMENT_HTTPX=\"true\"`) prior `elasticapm.instrument()` is called.\r\n\r\n**To Reproduce**\r\n```python3\r\nimport elasticapm\r\nimport httpx\r\n\r\n\r\ndef main():\r\n    elasticapm.instrument()\r\n\r\n    client = httpx.Client()\r\n    elastic_apm_client = elasticapm.Client()\r\n\r\n    elastic_apm_client.begin_transaction(\"httpx-context-manager-client-streaming\")\r\n    try:\r\n        with client.stream(\"GET\", url=\"https://example.com\") as response:\r\n            assert response\r\n    finally:\r\n        client.close()\r\n        elastic_apm_client.end_transaction(\"httpx-context-manager-client-streaming\")\r\n\r\n\r\nif __name__ == \"__main__\":\r\n    main()\r\n```\r\n\r\n**Expected result**\r\nNo exception is raised.\r\n\r\n**Actual result**\r\n```python3\r\nTraceback (most recent call last):\r\n  File \"<...>/test.py\", line 21, in <module>\r\n    main()\r\n  File \"<...>/test.py\", line 13, in main\r\n    with client.stream(\"GET\", url=\"https://example.com\") as response:\r\n  File \"<...>/venv/lib/python3.8/site-packages/httpx/_client.py\", line 1799, in __enter__\r\n    self.response = self.client.send(\r\n  File \"<...>/venv/lib/python3.8/site-packages/elasticapm/instrumentation/packages/base.py\", line 210, in call_if_sampling\r\n    return self.call(module, method, wrapped, instance, args, kwargs)\r\n  File \"<...>/venv/lib/python3.8/site-packages/elasticapm/instrumentation/packages/httpx.py\", line 42, in call\r\n    request = kwargs.get(\"request\", args[0])\r\nIndexError: tuple index out of range\r\n```\r\n\r\n<br/>\r\n<details>\r\n<summary><b>See similar results for <code>httpx.AsyncClient.stream()</code></b></summary>\r\n\r\n**To Reproduce**\r\n```python3\r\nimport asyncio\r\n\r\nimport elasticapm\r\nimport httpx\r\n\r\n\r\nasync def main():\r\n    elasticapm.instrument()\r\n\r\n    client = httpx.AsyncClient()\r\n    elastic_apm_client = elasticapm.Client()\r\n\r\n    elastic_apm_client.begin_transaction(\"httpx-async-context-manager-client-streaming\")\r\n    try:\r\n        async with client.stream(\"GET\", url=\"https://example.com\") as response:\r\n            assert response\r\n    finally:\r\n        await client.aclose()\r\n        elastic_apm_client.end_transaction(\r\n            \"httpx-async-context-manager-client-streaming\",\r\n        )\r\n\r\n\r\nif __name__ == \"__main__\":\r\n    asyncio.run(main())\r\n```\r\n\r\n**Actual result**\r\n```python3\r\nTraceback (most recent call last):\r\n  File \"<...>/test.py\", line 23, in <module>\r\n    asyncio.run(main())\r\n  File \"/usr/local/lib/python3.8/asyncio/runners.py\", line 44, in run\r\n    return loop.run_until_complete(main)\r\n  File \"/usr/local/lib/python3.8/asyncio/base_events.py\", line 616, in run_until_complete\r\n    return future.result()\r\n  File \"<...>/test.py\", line 15, in main\r\n    async with client.stream(\"GET\", url=\"https://example.com\") as response:\r\n  File \"<...>/venv/lib/python3.8/site-packages/httpx/_client.py\", line 1821, in __aenter__\r\n    self.response = await self.client.send(\r\n  File \"<...>/venv/lib/python3.8/site-packages/elasticapm/instrumentation/packages/asyncio/httpx.py\", line 42, in call\r\n    request = kwargs.get(\"request\", args[0])\r\nIndexError: tuple index out of range\r\n```\r\n</details>\r\n<br/>\r\n\r\n**Environment**\r\n- OS: Ubuntu 18.04.5 LTS\r\n- Python version: 3.8.9\r\n- Framework and version: `httpx==0.17.1` (also reproducible with current latest `httpx==0.19.0`)\r\n- APM Server version: --\r\n- Agent version: `elasticapm==6.4.0`\r\n\n", "before_files": [{"content": "#  BSD 3-Clause License\n#\n#  Copyright (c) 2019, Elasticsearch BV\n#  All rights reserved.\n#\n#  Redistribution and use in source and binary forms, with or without\n#  modification, are permitted provided that the following conditions are met:\n#\n#  * Redistributions of source code must retain the above copyright notice, this\n#    list of conditions and the following disclaimer.\n#\n#  * Redistributions in binary form must reproduce the above copyright notice,\n#    this list of conditions and the following disclaimer in the documentation\n#    and/or other materials provided with the distribution.\n#\n#  * Neither the name of the copyright holder nor the names of its\n#    contributors may be used to endorse or promote products derived from\n#    this software without specific prior written permission.\n#\n#  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n#  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n#  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n#  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\n#  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n#  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n#  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n#  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\n#  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n#  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nfrom elasticapm.contrib.asyncio.traces import async_capture_span\nfrom elasticapm.instrumentation.packages.asyncio.base import AsyncAbstractInstrumentedModule\nfrom elasticapm.utils import get_host_from_url, sanitize_url, url_to_destination\n\n\nclass HttpxAsyncClientInstrumentation(AsyncAbstractInstrumentedModule):\n    name = \"httpx\"\n\n    instrument_list = [(\"httpx\", \"AsyncClient.send\")]\n\n    async def call(self, module, method, wrapped, instance, args, kwargs):\n        request = kwargs.get(\"request\", args[0])\n\n        request_method = request.method.upper()\n        url = str(request.url)\n        name = \"{request_method} {host}\".format(request_method=request_method, host=get_host_from_url(url))\n        url = sanitize_url(url)\n        destination = url_to_destination(url)\n\n        async with async_capture_span(\n            name,\n            span_type=\"external\",\n            span_subtype=\"http\",\n            extra={\"http\": {\"url\": url}, \"destination\": destination},\n            leaf=True,\n        ) as span:\n            response = await wrapped(*args, **kwargs)\n            if response is not None:\n                if span.context:\n                    span.context[\"http\"][\"status_code\"] = response.status_code\n                span.set_success() if response.status_code < 400 else span.set_failure()\n            return response\n", "path": "elasticapm/instrumentation/packages/asyncio/httpx.py"}, {"content": "#  BSD 3-Clause License\n#\n#  Copyright (c) 2019, Elasticsearch BV\n#  All rights reserved.\n#\n#  Redistribution and use in source and binary forms, with or without\n#  modification, are permitted provided that the following conditions are met:\n#\n#  * Redistributions of source code must retain the above copyright notice, this\n#    list of conditions and the following disclaimer.\n#\n#  * Redistributions in binary form must reproduce the above copyright notice,\n#    this list of conditions and the following disclaimer in the documentation\n#    and/or other materials provided with the distribution.\n#\n#  * Neither the name of the copyright holder nor the names of its\n#    contributors may be used to endorse or promote products derived from\n#    this software without specific prior written permission.\n#\n#  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n#  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n#  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n#  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\n#  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n#  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n#  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n#  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\n#  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n#  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nfrom elasticapm.instrumentation.packages.base import AbstractInstrumentedModule\nfrom elasticapm.traces import capture_span\nfrom elasticapm.utils import get_host_from_url, sanitize_url, url_to_destination\n\n\nclass HttpxClientInstrumentation(AbstractInstrumentedModule):\n    name = \"httpx\"\n\n    instrument_list = [(\"httpx\", \"Client.send\")]\n\n    def call(self, module, method, wrapped, instance, args, kwargs):\n        request = kwargs.get(\"request\", args[0])\n\n        request_method = request.method.upper()\n        url = str(request.url)\n        name = \"{request_method} {host}\".format(request_method=request_method, host=get_host_from_url(url))\n        url = sanitize_url(url)\n        destination = url_to_destination(url)\n\n        with capture_span(\n            name,\n            span_type=\"external\",\n            span_subtype=\"http\",\n            extra={\"http\": {\"url\": url}, \"destination\": destination},\n            leaf=True,\n        ) as span:\n            response = wrapped(*args, **kwargs)\n            if response is not None:\n                if span.context:\n                    span.context[\"http\"][\"status_code\"] = response.status_code\n                span.set_success() if response.status_code < 400 else span.set_failure()\n            return response\n", "path": "elasticapm/instrumentation/packages/httpx.py"}], "after_files": [{"content": "#  BSD 3-Clause License\n#\n#  Copyright (c) 2019, Elasticsearch BV\n#  All rights reserved.\n#\n#  Redistribution and use in source and binary forms, with or without\n#  modification, are permitted provided that the following conditions are met:\n#\n#  * Redistributions of source code must retain the above copyright notice, this\n#    list of conditions and the following disclaimer.\n#\n#  * Redistributions in binary form must reproduce the above copyright notice,\n#    this list of conditions and the following disclaimer in the documentation\n#    and/or other materials provided with the distribution.\n#\n#  * Neither the name of the copyright holder nor the names of its\n#    contributors may be used to endorse or promote products derived from\n#    this software without specific prior written permission.\n#\n#  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n#  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n#  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n#  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\n#  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n#  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n#  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n#  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\n#  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n#  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nfrom elasticapm.contrib.asyncio.traces import async_capture_span\nfrom elasticapm.instrumentation.packages.asyncio.base import AsyncAbstractInstrumentedModule\nfrom elasticapm.utils import get_host_from_url, sanitize_url, url_to_destination\n\n\nclass HttpxAsyncClientInstrumentation(AsyncAbstractInstrumentedModule):\n    name = \"httpx\"\n\n    instrument_list = [(\"httpx\", \"AsyncClient.send\")]\n\n    async def call(self, module, method, wrapped, instance, args, kwargs):\n        request = kwargs.get(\"request\") or args[0]\n\n        request_method = request.method.upper()\n        url = str(request.url)\n        name = \"{request_method} {host}\".format(request_method=request_method, host=get_host_from_url(url))\n        url = sanitize_url(url)\n        destination = url_to_destination(url)\n\n        async with async_capture_span(\n            name,\n            span_type=\"external\",\n            span_subtype=\"http\",\n            extra={\"http\": {\"url\": url}, \"destination\": destination},\n            leaf=True,\n        ) as span:\n            response = await wrapped(*args, **kwargs)\n            if response is not None:\n                if span.context:\n                    span.context[\"http\"][\"status_code\"] = response.status_code\n                span.set_success() if response.status_code < 400 else span.set_failure()\n            return response\n", "path": "elasticapm/instrumentation/packages/asyncio/httpx.py"}, {"content": "#  BSD 3-Clause License\n#\n#  Copyright (c) 2019, Elasticsearch BV\n#  All rights reserved.\n#\n#  Redistribution and use in source and binary forms, with or without\n#  modification, are permitted provided that the following conditions are met:\n#\n#  * Redistributions of source code must retain the above copyright notice, this\n#    list of conditions and the following disclaimer.\n#\n#  * Redistributions in binary form must reproduce the above copyright notice,\n#    this list of conditions and the following disclaimer in the documentation\n#    and/or other materials provided with the distribution.\n#\n#  * Neither the name of the copyright holder nor the names of its\n#    contributors may be used to endorse or promote products derived from\n#    this software without specific prior written permission.\n#\n#  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n#  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n#  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n#  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\n#  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n#  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n#  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n#  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\n#  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n#  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nfrom elasticapm.instrumentation.packages.base import AbstractInstrumentedModule\nfrom elasticapm.traces import capture_span\nfrom elasticapm.utils import get_host_from_url, sanitize_url, url_to_destination\n\n\nclass HttpxClientInstrumentation(AbstractInstrumentedModule):\n    name = \"httpx\"\n\n    instrument_list = [(\"httpx\", \"Client.send\")]\n\n    def call(self, module, method, wrapped, instance, args, kwargs):\n        request = kwargs.get(\"request\") or args[0]\n\n        request_method = request.method.upper()\n        url = str(request.url)\n        name = \"{request_method} {host}\".format(request_method=request_method, host=get_host_from_url(url))\n        url = sanitize_url(url)\n        destination = url_to_destination(url)\n\n        with capture_span(\n            name,\n            span_type=\"external\",\n            span_subtype=\"http\",\n            extra={\"http\": {\"url\": url}, \"destination\": destination},\n            leaf=True,\n        ) as span:\n            response = wrapped(*args, **kwargs)\n            if response is not None:\n                if span.context:\n                    span.context[\"http\"][\"status_code\"] = response.status_code\n                span.set_success() if response.status_code < 400 else span.set_failure()\n            return response\n", "path": "elasticapm/instrumentation/packages/httpx.py"}]}