We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
0.50 bug sanic APM
Thanks for taking the time for reporting an issue!

Before reporting an issue on dd-trace-py, please be sure to provide all
necessary information.

If you're hitting a bug, make sure that you're using the latest version of this
library.

### Which version of dd-trace-py are you using?
0.50.0

### Which version of pip are you using?
19.0.3

### Which version of the libraries are you using?
Package             Version
------------------- ---------
aiofiles            0.7.0
aiohttp             3.6.2
aiomysql            0.0.20
astroid             2.3.3
async-timeout       3.0.1
attrs               19.3.0
certifi             2019.9.11
cffi                1.13.2
chardet             3.0.4
Click               7.0
cryptography        2.8
ddtrace             0.50.0
Deprecated          1.2.11
elasticsearch       7.5.1
elasticsearch-async 6.2.0
h11                 0.8.1
h2                  3.1.1
hpack               3.0.0
hstspreload         2020.1.7
httpcore            0.3.0
httptools           0.0.13
httpx               0.9.3
hyperframe          5.2.0
idna                2.8
isort               4.3.21
lazy-object-proxy   1.4.3
mccabe              0.6.1
motor               2.4.0
multidict           5.1.0
packaging           21.0
peewee              3.13.1
pip                 19.0.3
protobuf            3.17.3
pycparser           2.19
PyJWT               1.7.1
pymongo             3.11.4
PyMySQL             0.9.2
pyparsing           2.4.7
pytz                2019.3
PyYAML              5.3
requests            2.22.0
requests-async      0.5.0
rfc3986             1.3.2
sanic               21.3.4
sanic-motor         0.5.0
sanic-routing       0.6.2
sanic-scheduler     1.0.7
setuptools          40.8.0
six                 1.14.0
sniffio             1.1.0
stringcase          1.2.0
tenacity            8.0.1
typed-ast           1.4.1
ujson               1.35
urllib3             1.25.6
uvloop              0.13.0
websockets          8.1
wrapt               1.11.2
yarl                1.4.2

### How can we reproduce your problem?
#### Description
It's not working patch when apply APM on Sanic
If path variable type is int on sanic route

Case code
```
@app.route('/<gam_id:int>/slot/count', methods=['GET'])
async def slot_count(request, gam_id):
    try:
        pass
    except Exception as e:
        abort(500, e)
    return json(response(200, 'Complete Successfully', {}))

```

Error
```
[2021-07-13 19:50:48 +0000] [13] [ERROR] Exception occurred while handling uri: 'http://xxxxxxxxx.xxx/25/slot/count'
NoneType: None

```

### What is the result that you get?
my production env is not working on Sanic


### What is the result that you expected?
I wanna use datadog APM on my production SANIC

I made already pull request
- https://github.com/DataDog/dd-trace-py/pull/2662


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `ddtrace/contrib/sanic/patch.py`
Content:
```
1 import asyncio
2 
3 import sanic
4 
5 import ddtrace
6 from ddtrace import config
7 from ddtrace.constants import ANALYTICS_SAMPLE_RATE_KEY
8 from ddtrace.ext import SpanTypes
9 from ddtrace.pin import Pin
10 from ddtrace.utils.wrappers import unwrap as _u
11 from ddtrace.vendor import wrapt
12 from ddtrace.vendor.wrapt import wrap_function_wrapper as _w
13 
14 from .. import trace_utils
15 from ...internal.logger import get_logger
16 
17 
18 log = get_logger(__name__)
19 
20 config._add("sanic", dict(_default_service="sanic", distributed_tracing=True))
21 
22 SANIC_PRE_21 = None
23 
24 
25 def update_span(span, response):
26     if isinstance(response, sanic.response.BaseHTTPResponse):
27         status_code = response.status
28         response_headers = response.headers
29     else:
30         # invalid response causes ServerError exception which must be handled
31         status_code = 500
32         response_headers = None
33     trace_utils.set_http_meta(span, config.sanic, status_code=status_code, response_headers=response_headers)
34 
35 
36 def _wrap_response_callback(span, callback):
37     # Only for sanic 20 and older
38     # Wrap response callbacks (either sync or async function) to set HTTP
39     # response span tags
40 
41     @wrapt.function_wrapper
42     def wrap_sync(wrapped, instance, args, kwargs):
43         r = wrapped(*args, **kwargs)
44         response = args[0]
45         update_span(span, response)
46         return r
47 
48     @wrapt.function_wrapper
49     async def wrap_async(wrapped, instance, args, kwargs):
50         r = await wrapped(*args, **kwargs)
51         response = args[0]
52         update_span(span, response)
53         return r
54 
55     if asyncio.iscoroutinefunction(callback):
56         return wrap_async(callback)
57 
58     return wrap_sync(callback)
59 
60 
61 async def patch_request_respond(wrapped, instance, args, kwargs):
62     # Only for sanic 21 and newer
63     # Wrap the framework response to set HTTP response span tags
64     response = await wrapped(*args, **kwargs)
65     pin = Pin._find(instance.ctx)
66     if pin is not None and pin.enabled():
67         span = pin.tracer.current_span()
68         if span is not None:
69             update_span(span, response)
70     return response
71 
72 
73 def _get_path(request):
74     """Get path and replace path parameter values with names if route exists."""
75     path = request.path
76     try:
77         match_info = request.match_info
78     except sanic.exceptions.SanicException:
79         return path
80     for key, value in match_info.items():
81         path = path.replace(value, f"<{key}>")
82     return path
83 
84 
85 async def patch_run_request_middleware(wrapped, instance, args, kwargs):
86     # Set span resource from the framework request
87     request = args[0]
88     pin = Pin._find(request.ctx)
89     if pin is not None and pin.enabled():
90         span = pin.tracer.current_span()
91         if span is not None:
92             span.resource = "{} {}".format(request.method, _get_path(request))
93     return await wrapped(*args, **kwargs)
94 
95 
96 def patch():
97     """Patch the instrumented methods."""
98     global SANIC_PRE_21
99 
100     if getattr(sanic, "__datadog_patch", False):
101         return
102     setattr(sanic, "__datadog_patch", True)
103 
104     SANIC_PRE_21 = sanic.__version__[:2] < "21"
105 
106     _w("sanic", "Sanic.handle_request", patch_handle_request)
107     if not SANIC_PRE_21:
108         _w("sanic", "Sanic._run_request_middleware", patch_run_request_middleware)
109         _w(sanic.request, "Request.respond", patch_request_respond)
110 
111 
112 def unpatch():
113     """Unpatch the instrumented methods."""
114     _u(sanic.Sanic, "handle_request")
115     if not SANIC_PRE_21:
116         _u(sanic.Sanic, "_run_request_middleware")
117         _u(sanic.request.Request, "respond")
118     if not getattr(sanic, "__datadog_patch", False):
119         return
120     setattr(sanic, "__datadog_patch", False)
121 
122 
123 async def patch_handle_request(wrapped, instance, args, kwargs):
124     """Wrapper for Sanic.handle_request"""
125 
126     def unwrap(request, write_callback=None, stream_callback=None, **kwargs):
127         return request, write_callback, stream_callback, kwargs
128 
129     request, write_callback, stream_callback, new_kwargs = unwrap(*args, **kwargs)
130 
131     if request.scheme not in ("http", "https"):
132         return await wrapped(*args, **kwargs)
133 
134     pin = Pin()
135     if SANIC_PRE_21:
136         # Set span resource from the framework request
137         resource = "{} {}".format(request.method, _get_path(request))
138     else:
139         # The path is not available anymore in 21.x. Get it from
140         # the _run_request_middleware instrumented method.
141         resource = None
142         pin.onto(request.ctx)
143 
144     headers = request.headers.copy()
145 
146     trace_utils.activate_distributed_headers(ddtrace.tracer, int_config=config.sanic, request_headers=headers)
147 
148     with pin.tracer.trace(
149         "sanic.request",
150         service=trace_utils.int_service(None, config.sanic),
151         resource=resource,
152         span_type=SpanTypes.WEB,
153     ) as span:
154         sample_rate = config.sanic.get_analytics_sample_rate(use_global_config=True)
155         if sample_rate is not None:
156             span.set_tag(ANALYTICS_SAMPLE_RATE_KEY, sample_rate)
157 
158         method = request.method
159         url = "{scheme}://{host}{path}".format(scheme=request.scheme, host=request.host, path=request.path)
160         query_string = request.query_string
161         if isinstance(query_string, bytes):
162             query_string = query_string.decode()
163         trace_utils.set_http_meta(
164             span, config.sanic, method=method, url=url, query=query_string, request_headers=headers
165         )
166 
167         if write_callback is not None:
168             new_kwargs["write_callback"] = _wrap_response_callback(span, write_callback)
169         if stream_callback is not None:
170             new_kwargs["stream_callback"] = _wrap_response_callback(span, stream_callback)
171 
172         return await wrapped(request, **new_kwargs)
173
```
--- 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/ddtrace/contrib/sanic/patch.py b/ddtrace/contrib/sanic/patch.py
--- a/ddtrace/contrib/sanic/patch.py
+++ b/ddtrace/contrib/sanic/patch.py
@@ -78,6 +78,11 @@
     except sanic.exceptions.SanicException:
         return path
     for key, value in match_info.items():
+        try:
+            value = str(value)
+        except Exception:
+            # Best effort
+            continue
         path = path.replace(value, f"<{key}>")
     return path

{"golden_diff": "diff --git a/ddtrace/contrib/sanic/patch.py b/ddtrace/contrib/sanic/patch.py\n--- a/ddtrace/contrib/sanic/patch.py\n+++ b/ddtrace/contrib/sanic/patch.py\n@@ -78,6 +78,11 @@\n     except sanic.exceptions.SanicException:\n         return path\n     for key, value in match_info.items():\n+        try:\n+            value = str(value)\n+        except Exception:\n+            # Best effort\n+            continue\n         path = path.replace(value, f\"<{key}>\")\n     return path\n", "issue": "0.50 bug sanic APM\nThanks for taking the time for reporting an issue!\r\n\r\nBefore reporting an issue on dd-trace-py, please be sure to provide all\r\nnecessary information.\r\n\r\nIf you're hitting a bug, make sure that you're using the latest version of this\r\nlibrary.\r\n\r\n### Which version of dd-trace-py are you using?\r\n0.50.0\r\n\r\n### Which version of pip are you using?\r\n19.0.3\r\n\r\n### Which version of the libraries are you using?\r\nPackage             Version\r\n------------------- ---------\r\naiofiles            0.7.0\r\naiohttp             3.6.2\r\naiomysql            0.0.20\r\nastroid             2.3.3\r\nasync-timeout       3.0.1\r\nattrs               19.3.0\r\ncertifi             2019.9.11\r\ncffi                1.13.2\r\nchardet             3.0.4\r\nClick               7.0\r\ncryptography        2.8\r\nddtrace             0.50.0\r\nDeprecated          1.2.11\r\nelasticsearch       7.5.1\r\nelasticsearch-async 6.2.0\r\nh11                 0.8.1\r\nh2                  3.1.1\r\nhpack               3.0.0\r\nhstspreload         2020.1.7\r\nhttpcore            0.3.0\r\nhttptools           0.0.13\r\nhttpx               0.9.3\r\nhyperframe          5.2.0\r\nidna                2.8\r\nisort               4.3.21\r\nlazy-object-proxy   1.4.3\r\nmccabe              0.6.1\r\nmotor               2.4.0\r\nmultidict           5.1.0\r\npackaging           21.0\r\npeewee              3.13.1\r\npip                 19.0.3\r\nprotobuf            3.17.3\r\npycparser           2.19\r\nPyJWT               1.7.1\r\npymongo             3.11.4\r\nPyMySQL             0.9.2\r\npyparsing           2.4.7\r\npytz                2019.3\r\nPyYAML              5.3\r\nrequests            2.22.0\r\nrequests-async      0.5.0\r\nrfc3986             1.3.2\r\nsanic               21.3.4\r\nsanic-motor         0.5.0\r\nsanic-routing       0.6.2\r\nsanic-scheduler     1.0.7\r\nsetuptools          40.8.0\r\nsix                 1.14.0\r\nsniffio             1.1.0\r\nstringcase          1.2.0\r\ntenacity            8.0.1\r\ntyped-ast           1.4.1\r\nujson               1.35\r\nurllib3             1.25.6\r\nuvloop              0.13.0\r\nwebsockets          8.1\r\nwrapt               1.11.2\r\nyarl                1.4.2\r\n\r\n### How can we reproduce your problem?\r\n#### Description\r\nIt's not working patch when apply APM on Sanic\r\nIf path variable type is int on sanic route\r\n\r\nCase code\r\n```\r\n@app.route('/<gam_id:int>/slot/count', methods=['GET'])\r\nasync def slot_count(request, gam_id):\r\n    try:\r\n        pass\r\n    except Exception as e:\r\n        abort(500, e)\r\n    return json(response(200, 'Complete Successfully', {}))\r\n\r\n```\r\n\r\nError\r\n```\r\n[2021-07-13 19:50:48 +0000] [13] [ERROR] Exception occurred while handling uri: 'http://xxxxxxxxx.xxx/25/slot/count'\r\nNoneType: None\r\n\r\n```\r\n\r\n### What is the result that you get?\r\nmy production env is not working on Sanic\r\n\r\n\r\n### What is the result that you expected?\r\nI wanna use datadog APM on my production SANIC\r\n\r\nI made already pull request\r\n- https://github.com/DataDog/dd-trace-py/pull/2662\r\n\n", "before_files": [{"content": "import asyncio\n\nimport sanic\n\nimport ddtrace\nfrom ddtrace import config\nfrom ddtrace.constants import ANALYTICS_SAMPLE_RATE_KEY\nfrom ddtrace.ext import SpanTypes\nfrom ddtrace.pin import Pin\nfrom ddtrace.utils.wrappers import unwrap as _u\nfrom ddtrace.vendor import wrapt\nfrom ddtrace.vendor.wrapt import wrap_function_wrapper as _w\n\nfrom .. import trace_utils\nfrom ...internal.logger import get_logger\n\n\nlog = get_logger(__name__)\n\nconfig._add(\"sanic\", dict(_default_service=\"sanic\", distributed_tracing=True))\n\nSANIC_PRE_21 = None\n\n\ndef update_span(span, response):\n    if isinstance(response, sanic.response.BaseHTTPResponse):\n        status_code = response.status\n        response_headers = response.headers\n    else:\n        # invalid response causes ServerError exception which must be handled\n        status_code = 500\n        response_headers = None\n    trace_utils.set_http_meta(span, config.sanic, status_code=status_code, response_headers=response_headers)\n\n\ndef _wrap_response_callback(span, callback):\n    # Only for sanic 20 and older\n    # Wrap response callbacks (either sync or async function) to set HTTP\n    # response span tags\n\n    @wrapt.function_wrapper\n    def wrap_sync(wrapped, instance, args, kwargs):\n        r = wrapped(*args, **kwargs)\n        response = args[0]\n        update_span(span, response)\n        return r\n\n    @wrapt.function_wrapper\n    async def wrap_async(wrapped, instance, args, kwargs):\n        r = await wrapped(*args, **kwargs)\n        response = args[0]\n        update_span(span, response)\n        return r\n\n    if asyncio.iscoroutinefunction(callback):\n        return wrap_async(callback)\n\n    return wrap_sync(callback)\n\n\nasync def patch_request_respond(wrapped, instance, args, kwargs):\n    # Only for sanic 21 and newer\n    # Wrap the framework response to set HTTP response span tags\n    response = await wrapped(*args, **kwargs)\n    pin = Pin._find(instance.ctx)\n    if pin is not None and pin.enabled():\n        span = pin.tracer.current_span()\n        if span is not None:\n            update_span(span, response)\n    return response\n\n\ndef _get_path(request):\n    \"\"\"Get path and replace path parameter values with names if route exists.\"\"\"\n    path = request.path\n    try:\n        match_info = request.match_info\n    except sanic.exceptions.SanicException:\n        return path\n    for key, value in match_info.items():\n        path = path.replace(value, f\"<{key}>\")\n    return path\n\n\nasync def patch_run_request_middleware(wrapped, instance, args, kwargs):\n    # Set span resource from the framework request\n    request = args[0]\n    pin = Pin._find(request.ctx)\n    if pin is not None and pin.enabled():\n        span = pin.tracer.current_span()\n        if span is not None:\n            span.resource = \"{} {}\".format(request.method, _get_path(request))\n    return await wrapped(*args, **kwargs)\n\n\ndef patch():\n    \"\"\"Patch the instrumented methods.\"\"\"\n    global SANIC_PRE_21\n\n    if getattr(sanic, \"__datadog_patch\", False):\n        return\n    setattr(sanic, \"__datadog_patch\", True)\n\n    SANIC_PRE_21 = sanic.__version__[:2] < \"21\"\n\n    _w(\"sanic\", \"Sanic.handle_request\", patch_handle_request)\n    if not SANIC_PRE_21:\n        _w(\"sanic\", \"Sanic._run_request_middleware\", patch_run_request_middleware)\n        _w(sanic.request, \"Request.respond\", patch_request_respond)\n\n\ndef unpatch():\n    \"\"\"Unpatch the instrumented methods.\"\"\"\n    _u(sanic.Sanic, \"handle_request\")\n    if not SANIC_PRE_21:\n        _u(sanic.Sanic, \"_run_request_middleware\")\n        _u(sanic.request.Request, \"respond\")\n    if not getattr(sanic, \"__datadog_patch\", False):\n        return\n    setattr(sanic, \"__datadog_patch\", False)\n\n\nasync def patch_handle_request(wrapped, instance, args, kwargs):\n    \"\"\"Wrapper for Sanic.handle_request\"\"\"\n\n    def unwrap(request, write_callback=None, stream_callback=None, **kwargs):\n        return request, write_callback, stream_callback, kwargs\n\n    request, write_callback, stream_callback, new_kwargs = unwrap(*args, **kwargs)\n\n    if request.scheme not in (\"http\", \"https\"):\n        return await wrapped(*args, **kwargs)\n\n    pin = Pin()\n    if SANIC_PRE_21:\n        # Set span resource from the framework request\n        resource = \"{} {}\".format(request.method, _get_path(request))\n    else:\n        # The path is not available anymore in 21.x. Get it from\n        # the _run_request_middleware instrumented method.\n        resource = None\n        pin.onto(request.ctx)\n\n    headers = request.headers.copy()\n\n    trace_utils.activate_distributed_headers(ddtrace.tracer, int_config=config.sanic, request_headers=headers)\n\n    with pin.tracer.trace(\n        \"sanic.request\",\n        service=trace_utils.int_service(None, config.sanic),\n        resource=resource,\n        span_type=SpanTypes.WEB,\n    ) as span:\n        sample_rate = config.sanic.get_analytics_sample_rate(use_global_config=True)\n        if sample_rate is not None:\n            span.set_tag(ANALYTICS_SAMPLE_RATE_KEY, sample_rate)\n\n        method = request.method\n        url = \"{scheme}://{host}{path}\".format(scheme=request.scheme, host=request.host, path=request.path)\n        query_string = request.query_string\n        if isinstance(query_string, bytes):\n            query_string = query_string.decode()\n        trace_utils.set_http_meta(\n            span, config.sanic, method=method, url=url, query=query_string, request_headers=headers\n        )\n\n        if write_callback is not None:\n            new_kwargs[\"write_callback\"] = _wrap_response_callback(span, write_callback)\n        if stream_callback is not None:\n            new_kwargs[\"stream_callback\"] = _wrap_response_callback(span, stream_callback)\n\n        return await wrapped(request, **new_kwargs)\n", "path": "ddtrace/contrib/sanic/patch.py"}], "after_files": [{"content": "import asyncio\n\nimport sanic\n\nimport ddtrace\nfrom ddtrace import config\nfrom ddtrace.constants import ANALYTICS_SAMPLE_RATE_KEY\nfrom ddtrace.ext import SpanTypes\nfrom ddtrace.pin import Pin\nfrom ddtrace.utils.wrappers import unwrap as _u\nfrom ddtrace.vendor import wrapt\nfrom ddtrace.vendor.wrapt import wrap_function_wrapper as _w\n\nfrom .. import trace_utils\nfrom ...internal.logger import get_logger\n\n\nlog = get_logger(__name__)\n\nconfig._add(\"sanic\", dict(_default_service=\"sanic\", distributed_tracing=True))\n\nSANIC_PRE_21 = None\n\n\ndef update_span(span, response):\n    if isinstance(response, sanic.response.BaseHTTPResponse):\n        status_code = response.status\n        response_headers = response.headers\n    else:\n        # invalid response causes ServerError exception which must be handled\n        status_code = 500\n        response_headers = None\n    trace_utils.set_http_meta(span, config.sanic, status_code=status_code, response_headers=response_headers)\n\n\ndef _wrap_response_callback(span, callback):\n    # Only for sanic 20 and older\n    # Wrap response callbacks (either sync or async function) to set HTTP\n    # response span tags\n\n    @wrapt.function_wrapper\n    def wrap_sync(wrapped, instance, args, kwargs):\n        r = wrapped(*args, **kwargs)\n        response = args[0]\n        update_span(span, response)\n        return r\n\n    @wrapt.function_wrapper\n    async def wrap_async(wrapped, instance, args, kwargs):\n        r = await wrapped(*args, **kwargs)\n        response = args[0]\n        update_span(span, response)\n        return r\n\n    if asyncio.iscoroutinefunction(callback):\n        return wrap_async(callback)\n\n    return wrap_sync(callback)\n\n\nasync def patch_request_respond(wrapped, instance, args, kwargs):\n    # Only for sanic 21 and newer\n    # Wrap the framework response to set HTTP response span tags\n    response = await wrapped(*args, **kwargs)\n    pin = Pin._find(instance.ctx)\n    if pin is not None and pin.enabled():\n        span = pin.tracer.current_span()\n        if span is not None:\n            update_span(span, response)\n    return response\n\n\ndef _get_path(request):\n    \"\"\"Get path and replace path parameter values with names if route exists.\"\"\"\n    path = request.path\n    try:\n        match_info = request.match_info\n    except sanic.exceptions.SanicException:\n        return path\n    for key, value in match_info.items():\n        try:\n            value = str(value)\n        except Exception:\n            # Best effort\n            continue\n        path = path.replace(value, f\"<{key}>\")\n    return path\n\n\nasync def patch_run_request_middleware(wrapped, instance, args, kwargs):\n    # Set span resource from the framework request\n    request = args[0]\n    pin = Pin._find(request.ctx)\n    if pin is not None and pin.enabled():\n        span = pin.tracer.current_span()\n        if span is not None:\n            span.resource = \"{} {}\".format(request.method, _get_path(request))\n    return await wrapped(*args, **kwargs)\n\n\ndef patch():\n    \"\"\"Patch the instrumented methods.\"\"\"\n    global SANIC_PRE_21\n\n    if getattr(sanic, \"__datadog_patch\", False):\n        return\n    setattr(sanic, \"__datadog_patch\", True)\n\n    SANIC_PRE_21 = sanic.__version__[:2] < \"21\"\n\n    _w(\"sanic\", \"Sanic.handle_request\", patch_handle_request)\n    if not SANIC_PRE_21:\n        _w(\"sanic\", \"Sanic._run_request_middleware\", patch_run_request_middleware)\n        _w(sanic.request, \"Request.respond\", patch_request_respond)\n\n\ndef unpatch():\n    \"\"\"Unpatch the instrumented methods.\"\"\"\n    _u(sanic.Sanic, \"handle_request\")\n    if not SANIC_PRE_21:\n        _u(sanic.Sanic, \"_run_request_middleware\")\n        _u(sanic.request.Request, \"respond\")\n    if not getattr(sanic, \"__datadog_patch\", False):\n        return\n    setattr(sanic, \"__datadog_patch\", False)\n\n\nasync def patch_handle_request(wrapped, instance, args, kwargs):\n    \"\"\"Wrapper for Sanic.handle_request\"\"\"\n\n    def unwrap(request, write_callback=None, stream_callback=None, **kwargs):\n        return request, write_callback, stream_callback, kwargs\n\n    request, write_callback, stream_callback, new_kwargs = unwrap(*args, **kwargs)\n\n    if request.scheme not in (\"http\", \"https\"):\n        return await wrapped(*args, **kwargs)\n\n    pin = Pin()\n    if SANIC_PRE_21:\n        # Set span resource from the framework request\n        resource = \"{} {}\".format(request.method, _get_path(request))\n    else:\n        # The path is not available anymore in 21.x. Get it from\n        # the _run_request_middleware instrumented method.\n        resource = None\n        pin.onto(request.ctx)\n\n    headers = request.headers.copy()\n\n    trace_utils.activate_distributed_headers(ddtrace.tracer, int_config=config.sanic, request_headers=headers)\n\n    with pin.tracer.trace(\n        \"sanic.request\",\n        service=trace_utils.int_service(None, config.sanic),\n        resource=resource,\n        span_type=SpanTypes.WEB,\n    ) as span:\n        sample_rate = config.sanic.get_analytics_sample_rate(use_global_config=True)\n        if sample_rate is not None:\n            span.set_tag(ANALYTICS_SAMPLE_RATE_KEY, sample_rate)\n\n        method = request.method\n        url = \"{scheme}://{host}{path}\".format(scheme=request.scheme, host=request.host, path=request.path)\n        query_string = request.query_string\n        if isinstance(query_string, bytes):\n            query_string = query_string.decode()\n        trace_utils.set_http_meta(\n            span, config.sanic, method=method, url=url, query=query_string, request_headers=headers\n        )\n\n        if write_callback is not None:\n            new_kwargs[\"write_callback\"] = _wrap_response_callback(span, write_callback)\n        if stream_callback is not None:\n            new_kwargs[\"stream_callback\"] = _wrap_response_callback(span, stream_callback)\n\n        return await wrapped(request, **new_kwargs)\n", "path": "ddtrace/contrib/sanic/patch.py"}]}