prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Jinja2: Handle non-string template names as span resources
  Jinja2 template names may not be strings, but need to be serialized as strings prior to being set as a span resource. Problem areas can be found in `ddtrace/contrib/jinja2/patch.py` on lines 63, 81 and 97 where the value from Jinja2 is trusted to be a string, but may not be.
  
  https://github.com/DataDog/dd-trace-py/blob/fb8dfa2f33fff37d21df9728d8386c0260df9744/ddtrace/contrib/jinja2/patch.py#L51-L100
  
  
  Here is an example of the exception we are seeing when `span.finish` is called:
  
  ```
    File "/opt/venv/lib/python3.8/site-packages/ddtrace/span.py", line 237, in finish
      cb(self)
    File "/opt/venv/lib/python3.8/site-packages/ddtrace/tracer.py", line 712, in _on_span_finish
      p.on_span_finish(span)
    File "/opt/venv/lib/python3.8/site-packages/ddtrace/internal/processor/trace.py", line 208, in on_span_finish
      self._writer.write(spans)
    File "/opt/venv/lib/python3.8/site-packages/ddtrace/internal/writer.py", line 518, in write
      self._encoder.put(spans)
    File "ddtrace/internal/_encoding.pyx", line 456, in ddtrace.internal._encoding.MsgpackEncoderBase.put
    File "ddtrace/internal/_encoding.pyx", line 460, in ddtrace.internal._encoding.MsgpackEncoderBase.put
    File "ddtrace/internal/_encoding.pyx", line 483, in ddtrace.internal._encoding.MsgpackEncoderBase.put
    File "ddtrace/internal/_encoding.pyx", line 464, in ddtrace.internal._encoding.MsgpackEncoderBase.put
    File "ddtrace/internal/_encoding.pyx", line 451, in ddtrace.internal._encoding.MsgpackEncoderBase._pack_trace
    File "ddtrace/internal/_encoding.pyx", line 600, in ddtrace.internal._encoding.MsgpackEncoderV03.pack_span
    File "ddtrace/internal/_encoding.pyx", line 142, in ddtrace.internal._encoding.pack_text
  TypeError: Unhandled text type: <class 'int'>
  ```
  
  Relevant pip dependencies:
  datadogpy == 0.44.0
  dd-trace-py == 1.2.3
  jinja2 == 3.0.3
  
  
  --- 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/jinja2/patch.py`
  Content:
  ```
  1 import os
  2 
  3 import jinja2
  4 
  5 from ddtrace import config
  6 from ddtrace.vendor.wrapt import wrap_function_wrapper as _w
  7 
  8 from ...constants import SPAN_MEASURED_KEY
  9 from ...ext import SpanTypes
  10 from ...internal.utils import ArgumentError
  11 from ...internal.utils import get_argument_value
  12 from ...pin import Pin
  13 from ..trace_utils import unwrap as _u
  14 from .constants import DEFAULT_TEMPLATE_NAME
  15 
  16 
  17 # default settings
  18 config._add(
  19     "jinja2",
  20     {
  21         "service_name": os.getenv("DD_JINJA2_SERVICE_NAME"),
  22     },
  23 )
  24 
  25 
  26 def patch():
  27     if getattr(jinja2, "__datadog_patch", False):
  28         # already patched
  29         return
  30     setattr(jinja2, "__datadog_patch", True)
  31     Pin(
  32         service=config.jinja2["service_name"],
  33         _config=config.jinja2,
  34     ).onto(jinja2.environment.Environment)
  35     _w(jinja2, "environment.Template.render", _wrap_render)
  36     _w(jinja2, "environment.Template.generate", _wrap_render)
  37     _w(jinja2, "environment.Environment.compile", _wrap_compile)
  38     _w(jinja2, "environment.Environment._load_template", _wrap_load_template)
  39 
  40 
  41 def unpatch():
  42     if not getattr(jinja2, "__datadog_patch", False):
  43         return
  44     setattr(jinja2, "__datadog_patch", False)
  45     _u(jinja2.Template, "render")
  46     _u(jinja2.Template, "generate")
  47     _u(jinja2.Environment, "compile")
  48     _u(jinja2.Environment, "_load_template")
  49 
  50 
  51 def _wrap_render(wrapped, instance, args, kwargs):
  52     """Wrap `Template.render()` or `Template.generate()`"""
  53     pin = Pin.get_from(instance.environment)
  54     if not pin or not pin.enabled():
  55         return wrapped(*args, **kwargs)
  56 
  57     template_name = instance.name or DEFAULT_TEMPLATE_NAME
  58     with pin.tracer.trace("jinja2.render", pin.service, span_type=SpanTypes.TEMPLATE) as span:
  59         span.set_tag(SPAN_MEASURED_KEY)
  60         try:
  61             return wrapped(*args, **kwargs)
  62         finally:
  63             span.resource = template_name
  64             span.set_tag("jinja2.template_name", template_name)
  65 
  66 
  67 def _wrap_compile(wrapped, instance, args, kwargs):
  68     pin = Pin.get_from(instance)
  69     if not pin or not pin.enabled():
  70         return wrapped(*args, **kwargs)
  71 
  72     try:
  73         template_name = get_argument_value(args, kwargs, 1, "name")
  74     except ArgumentError:
  75         template_name = DEFAULT_TEMPLATE_NAME
  76 
  77     with pin.tracer.trace("jinja2.compile", pin.service, span_type=SpanTypes.TEMPLATE) as span:
  78         try:
  79             return wrapped(*args, **kwargs)
  80         finally:
  81             span.resource = template_name
  82             span.set_tag("jinja2.template_name", template_name)
  83 
  84 
  85 def _wrap_load_template(wrapped, instance, args, kwargs):
  86     pin = Pin.get_from(instance)
  87     if not pin or not pin.enabled():
  88         return wrapped(*args, **kwargs)
  89 
  90     template_name = get_argument_value(args, kwargs, 0, "name")
  91     with pin.tracer.trace("jinja2.load", pin.service, span_type=SpanTypes.TEMPLATE) as span:
  92         template = None
  93         try:
  94             template = wrapped(*args, **kwargs)
  95             return template
  96         finally:
  97             span.resource = template_name
  98             span.set_tag("jinja2.template_name", template_name)
  99             if template:
  100                 span.set_tag("jinja2.template_path", template.filename)
  101
  ```
  --- 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()
  
  ```
  
golden_diff: diff --git a/ddtrace/contrib/jinja2/patch.py b/ddtrace/contrib/jinja2/patch.py
  --- a/ddtrace/contrib/jinja2/patch.py
  +++ b/ddtrace/contrib/jinja2/patch.py
  @@ -7,6 +7,7 @@
   
   from ...constants import SPAN_MEASURED_KEY
   from ...ext import SpanTypes
  +from ...internal.compat import stringify
   from ...internal.utils import ArgumentError
   from ...internal.utils import get_argument_value
   from ...pin import Pin
  @@ -54,7 +55,7 @@
       if not pin or not pin.enabled():
           return wrapped(*args, **kwargs)
   
  -    template_name = instance.name or DEFAULT_TEMPLATE_NAME
  +    template_name = stringify(instance.name or DEFAULT_TEMPLATE_NAME)
       with pin.tracer.trace("jinja2.render", pin.service, span_type=SpanTypes.TEMPLATE) as span:
           span.set_tag(SPAN_MEASURED_KEY)
           try:
  
verification_info: {"golden_diff": "diff --git a/ddtrace/contrib/jinja2/patch.py b/ddtrace/contrib/jinja2/patch.py\n--- a/ddtrace/contrib/jinja2/patch.py\n+++ b/ddtrace/contrib/jinja2/patch.py\n@@ -7,6 +7,7 @@\n \n from ...constants import SPAN_MEASURED_KEY\n from ...ext import SpanTypes\n+from ...internal.compat import stringify\n from ...internal.utils import ArgumentError\n from ...internal.utils import get_argument_value\n from ...pin import Pin\n@@ -54,7 +55,7 @@\n     if not pin or not pin.enabled():\n         return wrapped(*args, **kwargs)\n \n-    template_name = instance.name or DEFAULT_TEMPLATE_NAME\n+    template_name = stringify(instance.name or DEFAULT_TEMPLATE_NAME)\n     with pin.tracer.trace(\"jinja2.render\", pin.service, span_type=SpanTypes.TEMPLATE) as span:\n         span.set_tag(SPAN_MEASURED_KEY)\n         try:\n", "issue": "Jinja2: Handle non-string template names as span resources\nJinja2 template names may not be strings, but need to be serialized as strings prior to being set as a span resource. Problem areas can be found in `ddtrace/contrib/jinja2/patch.py` on lines 63, 81 and 97 where the value from Jinja2 is trusted to be a string, but may not be.\r\n\r\nhttps://github.com/DataDog/dd-trace-py/blob/fb8dfa2f33fff37d21df9728d8386c0260df9744/ddtrace/contrib/jinja2/patch.py#L51-L100\r\n\r\n\r\nHere is an example of the exception we are seeing when `span.finish` is called:\r\n\r\n```\r\n  File \"/opt/venv/lib/python3.8/site-packages/ddtrace/span.py\", line 237, in finish\r\n    cb(self)\r\n  File \"/opt/venv/lib/python3.8/site-packages/ddtrace/tracer.py\", line 712, in _on_span_finish\r\n    p.on_span_finish(span)\r\n  File \"/opt/venv/lib/python3.8/site-packages/ddtrace/internal/processor/trace.py\", line 208, in on_span_finish\r\n    self._writer.write(spans)\r\n  File \"/opt/venv/lib/python3.8/site-packages/ddtrace/internal/writer.py\", line 518, in write\r\n    self._encoder.put(spans)\r\n  File \"ddtrace/internal/_encoding.pyx\", line 456, in ddtrace.internal._encoding.MsgpackEncoderBase.put\r\n  File \"ddtrace/internal/_encoding.pyx\", line 460, in ddtrace.internal._encoding.MsgpackEncoderBase.put\r\n  File \"ddtrace/internal/_encoding.pyx\", line 483, in ddtrace.internal._encoding.MsgpackEncoderBase.put\r\n  File \"ddtrace/internal/_encoding.pyx\", line 464, in ddtrace.internal._encoding.MsgpackEncoderBase.put\r\n  File \"ddtrace/internal/_encoding.pyx\", line 451, in ddtrace.internal._encoding.MsgpackEncoderBase._pack_trace\r\n  File \"ddtrace/internal/_encoding.pyx\", line 600, in ddtrace.internal._encoding.MsgpackEncoderV03.pack_span\r\n  File \"ddtrace/internal/_encoding.pyx\", line 142, in ddtrace.internal._encoding.pack_text\r\nTypeError: Unhandled text type: <class 'int'>\r\n```\r\n\r\nRelevant pip dependencies:\r\ndatadogpy == 0.44.0\r\ndd-trace-py == 1.2.3\r\njinja2 == 3.0.3\r\n\n", "before_files": [{"content": "import os\n\nimport jinja2\n\nfrom ddtrace import config\nfrom ddtrace.vendor.wrapt import wrap_function_wrapper as _w\n\nfrom ...constants import SPAN_MEASURED_KEY\nfrom ...ext import SpanTypes\nfrom ...internal.utils import ArgumentError\nfrom ...internal.utils import get_argument_value\nfrom ...pin import Pin\nfrom ..trace_utils import unwrap as _u\nfrom .constants import DEFAULT_TEMPLATE_NAME\n\n\n# default settings\nconfig._add(\n    \"jinja2\",\n    {\n        \"service_name\": os.getenv(\"DD_JINJA2_SERVICE_NAME\"),\n    },\n)\n\n\ndef patch():\n    if getattr(jinja2, \"__datadog_patch\", False):\n        # already patched\n        return\n    setattr(jinja2, \"__datadog_patch\", True)\n    Pin(\n        service=config.jinja2[\"service_name\"],\n        _config=config.jinja2,\n    ).onto(jinja2.environment.Environment)\n    _w(jinja2, \"environment.Template.render\", _wrap_render)\n    _w(jinja2, \"environment.Template.generate\", _wrap_render)\n    _w(jinja2, \"environment.Environment.compile\", _wrap_compile)\n    _w(jinja2, \"environment.Environment._load_template\", _wrap_load_template)\n\n\ndef unpatch():\n    if not getattr(jinja2, \"__datadog_patch\", False):\n        return\n    setattr(jinja2, \"__datadog_patch\", False)\n    _u(jinja2.Template, \"render\")\n    _u(jinja2.Template, \"generate\")\n    _u(jinja2.Environment, \"compile\")\n    _u(jinja2.Environment, \"_load_template\")\n\n\ndef _wrap_render(wrapped, instance, args, kwargs):\n    \"\"\"Wrap `Template.render()` or `Template.generate()`\"\"\"\n    pin = Pin.get_from(instance.environment)\n    if not pin or not pin.enabled():\n        return wrapped(*args, **kwargs)\n\n    template_name = instance.name or DEFAULT_TEMPLATE_NAME\n    with pin.tracer.trace(\"jinja2.render\", pin.service, span_type=SpanTypes.TEMPLATE) as span:\n        span.set_tag(SPAN_MEASURED_KEY)\n        try:\n            return wrapped(*args, **kwargs)\n        finally:\n            span.resource = template_name\n            span.set_tag(\"jinja2.template_name\", template_name)\n\n\ndef _wrap_compile(wrapped, instance, args, kwargs):\n    pin = Pin.get_from(instance)\n    if not pin or not pin.enabled():\n        return wrapped(*args, **kwargs)\n\n    try:\n        template_name = get_argument_value(args, kwargs, 1, \"name\")\n    except ArgumentError:\n        template_name = DEFAULT_TEMPLATE_NAME\n\n    with pin.tracer.trace(\"jinja2.compile\", pin.service, span_type=SpanTypes.TEMPLATE) as span:\n        try:\n            return wrapped(*args, **kwargs)\n        finally:\n            span.resource = template_name\n            span.set_tag(\"jinja2.template_name\", template_name)\n\n\ndef _wrap_load_template(wrapped, instance, args, kwargs):\n    pin = Pin.get_from(instance)\n    if not pin or not pin.enabled():\n        return wrapped(*args, **kwargs)\n\n    template_name = get_argument_value(args, kwargs, 0, \"name\")\n    with pin.tracer.trace(\"jinja2.load\", pin.service, span_type=SpanTypes.TEMPLATE) as span:\n        template = None\n        try:\n            template = wrapped(*args, **kwargs)\n            return template\n        finally:\n            span.resource = template_name\n            span.set_tag(\"jinja2.template_name\", template_name)\n            if template:\n                span.set_tag(\"jinja2.template_path\", template.filename)\n", "path": "ddtrace/contrib/jinja2/patch.py"}], "after_files": [{"content": "import os\n\nimport jinja2\n\nfrom ddtrace import config\nfrom ddtrace.vendor.wrapt import wrap_function_wrapper as _w\n\nfrom ...constants import SPAN_MEASURED_KEY\nfrom ...ext import SpanTypes\nfrom ...internal.compat import stringify\nfrom ...internal.utils import ArgumentError\nfrom ...internal.utils import get_argument_value\nfrom ...pin import Pin\nfrom ..trace_utils import unwrap as _u\nfrom .constants import DEFAULT_TEMPLATE_NAME\n\n\n# default settings\nconfig._add(\n    \"jinja2\",\n    {\n        \"service_name\": os.getenv(\"DD_JINJA2_SERVICE_NAME\"),\n    },\n)\n\n\ndef patch():\n    if getattr(jinja2, \"__datadog_patch\", False):\n        # already patched\n        return\n    setattr(jinja2, \"__datadog_patch\", True)\n    Pin(\n        service=config.jinja2[\"service_name\"],\n        _config=config.jinja2,\n    ).onto(jinja2.environment.Environment)\n    _w(jinja2, \"environment.Template.render\", _wrap_render)\n    _w(jinja2, \"environment.Template.generate\", _wrap_render)\n    _w(jinja2, \"environment.Environment.compile\", _wrap_compile)\n    _w(jinja2, \"environment.Environment._load_template\", _wrap_load_template)\n\n\ndef unpatch():\n    if not getattr(jinja2, \"__datadog_patch\", False):\n        return\n    setattr(jinja2, \"__datadog_patch\", False)\n    _u(jinja2.Template, \"render\")\n    _u(jinja2.Template, \"generate\")\n    _u(jinja2.Environment, \"compile\")\n    _u(jinja2.Environment, \"_load_template\")\n\n\ndef _wrap_render(wrapped, instance, args, kwargs):\n    \"\"\"Wrap `Template.render()` or `Template.generate()`\"\"\"\n    pin = Pin.get_from(instance.environment)\n    if not pin or not pin.enabled():\n        return wrapped(*args, **kwargs)\n\n    template_name = stringify(instance.name or DEFAULT_TEMPLATE_NAME)\n    with pin.tracer.trace(\"jinja2.render\", pin.service, span_type=SpanTypes.TEMPLATE) as span:\n        span.set_tag(SPAN_MEASURED_KEY)\n        try:\n            return wrapped(*args, **kwargs)\n        finally:\n            span.resource = template_name\n            span.set_tag(\"jinja2.template_name\", template_name)\n\n\ndef _wrap_compile(wrapped, instance, args, kwargs):\n    pin = Pin.get_from(instance)\n    if not pin or not pin.enabled():\n        return wrapped(*args, **kwargs)\n\n    try:\n        template_name = get_argument_value(args, kwargs, 1, \"name\")\n    except ArgumentError:\n        template_name = DEFAULT_TEMPLATE_NAME\n\n    with pin.tracer.trace(\"jinja2.compile\", pin.service, span_type=SpanTypes.TEMPLATE) as span:\n        try:\n            return wrapped(*args, **kwargs)\n        finally:\n            span.resource = template_name\n            span.set_tag(\"jinja2.template_name\", template_name)\n\n\ndef _wrap_load_template(wrapped, instance, args, kwargs):\n    pin = Pin.get_from(instance)\n    if not pin or not pin.enabled():\n        return wrapped(*args, **kwargs)\n\n    template_name = get_argument_value(args, kwargs, 0, \"name\")\n    with pin.tracer.trace(\"jinja2.load\", pin.service, span_type=SpanTypes.TEMPLATE) as span:\n        template = None\n        try:\n            template = wrapped(*args, **kwargs)\n            return template\n        finally:\n            span.resource = template_name\n            span.set_tag(\"jinja2.template_name\", template_name)\n            if template:\n                span.set_tag(\"jinja2.template_path\", template.filename)\n", "path": "ddtrace/contrib/jinja2/patch.py"}]}