prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  AsyncPG Instrumentation Span Names are too long when using query string
  **Is your feature request related to a problem?**
  Not a problem per se however, the `asyncpg` instrumentation uses sets span names as the query string which results in some very messing looking trace names in jaeger, datadog, etc and outright doesn't work with promscale due to long queries exhaust the available bytes for btree indexes.
  
  **Describe the solution you'd like**
  - The ability to change the name of the span with a hook or something similar. The `httpx` instrumentation provides hooks that receive the span and the name can be updated there.
  - Just use a shorter or truncated version of the query as the name.
  
  Which alternative solutions or features have you considered?
  Not using the `asyncpg` instrumentation and manually instrumenting specific queries.
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `instrumentation/opentelemetry-instrumentation-asyncpg/src/opentelemetry/instrumentation/asyncpg/__init__.py`
  Content:
  ```
  1 # Copyright The OpenTelemetry Authors
  2 #
  3 # Licensed under the Apache License, Version 2.0 (the "License");
  4 # you may not use this file except in compliance with the License.
  5 # You may obtain a copy of the License at
  6 #
  7 #     http://www.apache.org/licenses/LICENSE-2.0
  8 #
  9 # Unless required by applicable law or agreed to in writing, software
  10 # distributed under the License is distributed on an "AS IS" BASIS,
  11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12 # See the License for the specific language governing permissions and
  13 # limitations under the License.
  14 
  15 """
  16 This library allows tracing PostgreSQL queries made by the
  17 `asyncpg <https://magicstack.github.io/asyncpg/current/>`_ library.
  18 
  19 Usage
  20 -----
  21 
  22 .. code-block:: python
  23 
  24     import asyncpg
  25     from opentelemetry.instrumentation.asyncpg import AsyncPGInstrumentor
  26 
  27     # You can optionally pass a custom TracerProvider to AsyncPGInstrumentor.instrument()
  28     AsyncPGInstrumentor().instrument()
  29     conn = await asyncpg.connect(user='user', password='password',
  30                                  database='database', host='127.0.0.1')
  31     values = await conn.fetch('''SELECT 42;''')
  32 
  33 API
  34 ---
  35 """
  36 
  37 from typing import Collection
  38 
  39 import asyncpg
  40 import wrapt
  41 
  42 from opentelemetry import trace
  43 from opentelemetry.instrumentation.asyncpg.package import _instruments
  44 from opentelemetry.instrumentation.asyncpg.version import __version__
  45 from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
  46 from opentelemetry.instrumentation.utils import unwrap
  47 from opentelemetry.semconv.trace import (
  48     DbSystemValues,
  49     NetTransportValues,
  50     SpanAttributes,
  51 )
  52 from opentelemetry.trace import SpanKind
  53 from opentelemetry.trace.status import Status, StatusCode
  54 
  55 
  56 def _hydrate_span_from_args(connection, query, parameters) -> dict:
  57     """Get network and database attributes from connection."""
  58     span_attributes = {
  59         SpanAttributes.DB_SYSTEM: DbSystemValues.POSTGRESQL.value
  60     }
  61 
  62     # connection contains _params attribute which is a namedtuple ConnectionParameters.
  63     # https://github.com/MagicStack/asyncpg/blob/master/asyncpg/connection.py#L68
  64 
  65     params = getattr(connection, "_params", None)
  66     dbname = getattr(params, "database", None)
  67     if dbname:
  68         span_attributes[SpanAttributes.DB_NAME] = dbname
  69     user = getattr(params, "user", None)
  70     if user:
  71         span_attributes[SpanAttributes.DB_USER] = user
  72 
  73     # connection contains _addr attribute which is either a host/port tuple, or unix socket string
  74     # https://magicstack.github.io/asyncpg/current/_modules/asyncpg/connection.html
  75     addr = getattr(connection, "_addr", None)
  76     if isinstance(addr, tuple):
  77         span_attributes[SpanAttributes.NET_PEER_NAME] = addr[0]
  78         span_attributes[SpanAttributes.NET_PEER_PORT] = addr[1]
  79         span_attributes[
  80             SpanAttributes.NET_TRANSPORT
  81         ] = NetTransportValues.IP_TCP.value
  82     elif isinstance(addr, str):
  83         span_attributes[SpanAttributes.NET_PEER_NAME] = addr
  84         span_attributes[
  85             SpanAttributes.NET_TRANSPORT
  86         ] = NetTransportValues.UNIX.value
  87 
  88     if query is not None:
  89         span_attributes[SpanAttributes.DB_STATEMENT] = query
  90 
  91     if parameters is not None and len(parameters) > 0:
  92         span_attributes["db.statement.parameters"] = str(parameters)
  93 
  94     return span_attributes
  95 
  96 
  97 class AsyncPGInstrumentor(BaseInstrumentor):
  98     def __init__(self, capture_parameters=False):
  99         super().__init__()
  100         self.capture_parameters = capture_parameters
  101         self._tracer = None
  102 
  103     def instrumentation_dependencies(self) -> Collection[str]:
  104         return _instruments
  105 
  106     def _instrument(self, **kwargs):
  107         tracer_provider = kwargs.get("tracer_provider")
  108         self._tracer = trace.get_tracer(__name__, __version__, tracer_provider)
  109 
  110         for method in [
  111             "Connection.execute",
  112             "Connection.executemany",
  113             "Connection.fetch",
  114             "Connection.fetchval",
  115             "Connection.fetchrow",
  116         ]:
  117             wrapt.wrap_function_wrapper(
  118                 "asyncpg.connection", method, self._do_execute
  119             )
  120 
  121     def _uninstrument(self, **__):
  122         for method in [
  123             "execute",
  124             "executemany",
  125             "fetch",
  126             "fetchval",
  127             "fetchrow",
  128         ]:
  129             unwrap(asyncpg.Connection, method)
  130 
  131     async def _do_execute(self, func, instance, args, kwargs):
  132 
  133         exception = None
  134         params = getattr(instance, "_params", {})
  135         name = args[0] if args[0] else params.get("database", "postgresql")
  136 
  137         with self._tracer.start_as_current_span(
  138             name, kind=SpanKind.CLIENT
  139         ) as span:
  140             if span.is_recording():
  141                 span_attributes = _hydrate_span_from_args(
  142                     instance,
  143                     args[0],
  144                     args[1:] if self.capture_parameters else None,
  145                 )
  146                 for attribute, value in span_attributes.items():
  147                     span.set_attribute(attribute, value)
  148 
  149             try:
  150                 result = await func(*args, **kwargs)
  151             except Exception as exc:  # pylint: disable=W0703
  152                 exception = exc
  153                 raise
  154             finally:
  155                 if span.is_recording() and exception is not None:
  156                     span.set_status(Status(StatusCode.ERROR))
  157 
  158         return result
  159
  ```
  --- 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/instrumentation/opentelemetry-instrumentation-asyncpg/src/opentelemetry/instrumentation/asyncpg/__init__.py b/instrumentation/opentelemetry-instrumentation-asyncpg/src/opentelemetry/instrumentation/asyncpg/__init__.py
  --- a/instrumentation/opentelemetry-instrumentation-asyncpg/src/opentelemetry/instrumentation/asyncpg/__init__.py
  +++ b/instrumentation/opentelemetry-instrumentation-asyncpg/src/opentelemetry/instrumentation/asyncpg/__init__.py
  @@ -134,6 +134,11 @@
           params = getattr(instance, "_params", {})
           name = args[0] if args[0] else params.get("database", "postgresql")
   
  +        try:
  +            name = name.split()[0]
  +        except IndexError:
  +            name = ""
  +
           with self._tracer.start_as_current_span(
               name, kind=SpanKind.CLIENT
           ) as span:
  
verification_info: {"golden_diff": "diff --git a/instrumentation/opentelemetry-instrumentation-asyncpg/src/opentelemetry/instrumentation/asyncpg/__init__.py b/instrumentation/opentelemetry-instrumentation-asyncpg/src/opentelemetry/instrumentation/asyncpg/__init__.py\n--- a/instrumentation/opentelemetry-instrumentation-asyncpg/src/opentelemetry/instrumentation/asyncpg/__init__.py\n+++ b/instrumentation/opentelemetry-instrumentation-asyncpg/src/opentelemetry/instrumentation/asyncpg/__init__.py\n@@ -134,6 +134,11 @@\n         params = getattr(instance, \"_params\", {})\n         name = args[0] if args[0] else params.get(\"database\", \"postgresql\")\n \n+        try:\n+            name = name.split()[0]\n+        except IndexError:\n+            name = \"\"\n+\n         with self._tracer.start_as_current_span(\n             name, kind=SpanKind.CLIENT\n         ) as span:\n", "issue": "AsyncPG Instrumentation Span Names are too long when using query string\n**Is your feature request related to a problem?**\r\nNot a problem per se however, the `asyncpg` instrumentation uses sets span names as the query string which results in some very messing looking trace names in jaeger, datadog, etc and outright doesn't work with promscale due to long queries exhaust the available bytes for btree indexes.\r\n\r\n**Describe the solution you'd like**\r\n- The ability to change the name of the span with a hook or something similar. The `httpx` instrumentation provides hooks that receive the span and the name can be updated there.\r\n- Just use a shorter or truncated version of the query as the name.\r\n\r\nWhich alternative solutions or features have you considered?\r\nNot using the `asyncpg` instrumentation and manually instrumenting specific queries.\r\n\n", "before_files": [{"content": "# Copyright The OpenTelemetry Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n\"\"\"\nThis library allows tracing PostgreSQL queries made by the\n`asyncpg <https://magicstack.github.io/asyncpg/current/>`_ library.\n\nUsage\n-----\n\n.. code-block:: python\n\n    import asyncpg\n    from opentelemetry.instrumentation.asyncpg import AsyncPGInstrumentor\n\n    # You can optionally pass a custom TracerProvider to AsyncPGInstrumentor.instrument()\n    AsyncPGInstrumentor().instrument()\n    conn = await asyncpg.connect(user='user', password='password',\n                                 database='database', host='127.0.0.1')\n    values = await conn.fetch('''SELECT 42;''')\n\nAPI\n---\n\"\"\"\n\nfrom typing import Collection\n\nimport asyncpg\nimport wrapt\n\nfrom opentelemetry import trace\nfrom opentelemetry.instrumentation.asyncpg.package import _instruments\nfrom opentelemetry.instrumentation.asyncpg.version import __version__\nfrom opentelemetry.instrumentation.instrumentor import BaseInstrumentor\nfrom opentelemetry.instrumentation.utils import unwrap\nfrom opentelemetry.semconv.trace import (\n    DbSystemValues,\n    NetTransportValues,\n    SpanAttributes,\n)\nfrom opentelemetry.trace import SpanKind\nfrom opentelemetry.trace.status import Status, StatusCode\n\n\ndef _hydrate_span_from_args(connection, query, parameters) -> dict:\n    \"\"\"Get network and database attributes from connection.\"\"\"\n    span_attributes = {\n        SpanAttributes.DB_SYSTEM: DbSystemValues.POSTGRESQL.value\n    }\n\n    # connection contains _params attribute which is a namedtuple ConnectionParameters.\n    # https://github.com/MagicStack/asyncpg/blob/master/asyncpg/connection.py#L68\n\n    params = getattr(connection, \"_params\", None)\n    dbname = getattr(params, \"database\", None)\n    if dbname:\n        span_attributes[SpanAttributes.DB_NAME] = dbname\n    user = getattr(params, \"user\", None)\n    if user:\n        span_attributes[SpanAttributes.DB_USER] = user\n\n    # connection contains _addr attribute which is either a host/port tuple, or unix socket string\n    # https://magicstack.github.io/asyncpg/current/_modules/asyncpg/connection.html\n    addr = getattr(connection, \"_addr\", None)\n    if isinstance(addr, tuple):\n        span_attributes[SpanAttributes.NET_PEER_NAME] = addr[0]\n        span_attributes[SpanAttributes.NET_PEER_PORT] = addr[1]\n        span_attributes[\n            SpanAttributes.NET_TRANSPORT\n        ] = NetTransportValues.IP_TCP.value\n    elif isinstance(addr, str):\n        span_attributes[SpanAttributes.NET_PEER_NAME] = addr\n        span_attributes[\n            SpanAttributes.NET_TRANSPORT\n        ] = NetTransportValues.UNIX.value\n\n    if query is not None:\n        span_attributes[SpanAttributes.DB_STATEMENT] = query\n\n    if parameters is not None and len(parameters) > 0:\n        span_attributes[\"db.statement.parameters\"] = str(parameters)\n\n    return span_attributes\n\n\nclass AsyncPGInstrumentor(BaseInstrumentor):\n    def __init__(self, capture_parameters=False):\n        super().__init__()\n        self.capture_parameters = capture_parameters\n        self._tracer = None\n\n    def instrumentation_dependencies(self) -> Collection[str]:\n        return _instruments\n\n    def _instrument(self, **kwargs):\n        tracer_provider = kwargs.get(\"tracer_provider\")\n        self._tracer = trace.get_tracer(__name__, __version__, tracer_provider)\n\n        for method in [\n            \"Connection.execute\",\n            \"Connection.executemany\",\n            \"Connection.fetch\",\n            \"Connection.fetchval\",\n            \"Connection.fetchrow\",\n        ]:\n            wrapt.wrap_function_wrapper(\n                \"asyncpg.connection\", method, self._do_execute\n            )\n\n    def _uninstrument(self, **__):\n        for method in [\n            \"execute\",\n            \"executemany\",\n            \"fetch\",\n            \"fetchval\",\n            \"fetchrow\",\n        ]:\n            unwrap(asyncpg.Connection, method)\n\n    async def _do_execute(self, func, instance, args, kwargs):\n\n        exception = None\n        params = getattr(instance, \"_params\", {})\n        name = args[0] if args[0] else params.get(\"database\", \"postgresql\")\n\n        with self._tracer.start_as_current_span(\n            name, kind=SpanKind.CLIENT\n        ) as span:\n            if span.is_recording():\n                span_attributes = _hydrate_span_from_args(\n                    instance,\n                    args[0],\n                    args[1:] if self.capture_parameters else None,\n                )\n                for attribute, value in span_attributes.items():\n                    span.set_attribute(attribute, value)\n\n            try:\n                result = await func(*args, **kwargs)\n            except Exception as exc:  # pylint: disable=W0703\n                exception = exc\n                raise\n            finally:\n                if span.is_recording() and exception is not None:\n                    span.set_status(Status(StatusCode.ERROR))\n\n        return result\n", "path": "instrumentation/opentelemetry-instrumentation-asyncpg/src/opentelemetry/instrumentation/asyncpg/__init__.py"}], "after_files": [{"content": "# Copyright The OpenTelemetry Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n\"\"\"\nThis library allows tracing PostgreSQL queries made by the\n`asyncpg <https://magicstack.github.io/asyncpg/current/>`_ library.\n\nUsage\n-----\n\n.. code-block:: python\n\n    import asyncpg\n    from opentelemetry.instrumentation.asyncpg import AsyncPGInstrumentor\n\n    # You can optionally pass a custom TracerProvider to AsyncPGInstrumentor.instrument()\n    AsyncPGInstrumentor().instrument()\n    conn = await asyncpg.connect(user='user', password='password',\n                                 database='database', host='127.0.0.1')\n    values = await conn.fetch('''SELECT 42;''')\n\nAPI\n---\n\"\"\"\n\nfrom typing import Collection\n\nimport asyncpg\nimport wrapt\n\nfrom opentelemetry import trace\nfrom opentelemetry.instrumentation.asyncpg.package import _instruments\nfrom opentelemetry.instrumentation.asyncpg.version import __version__\nfrom opentelemetry.instrumentation.instrumentor import BaseInstrumentor\nfrom opentelemetry.instrumentation.utils import unwrap\nfrom opentelemetry.semconv.trace import (\n    DbSystemValues,\n    NetTransportValues,\n    SpanAttributes,\n)\nfrom opentelemetry.trace import SpanKind\nfrom opentelemetry.trace.status import Status, StatusCode\n\n\ndef _hydrate_span_from_args(connection, query, parameters) -> dict:\n    \"\"\"Get network and database attributes from connection.\"\"\"\n    span_attributes = {\n        SpanAttributes.DB_SYSTEM: DbSystemValues.POSTGRESQL.value\n    }\n\n    # connection contains _params attribute which is a namedtuple ConnectionParameters.\n    # https://github.com/MagicStack/asyncpg/blob/master/asyncpg/connection.py#L68\n\n    params = getattr(connection, \"_params\", None)\n    dbname = getattr(params, \"database\", None)\n    if dbname:\n        span_attributes[SpanAttributes.DB_NAME] = dbname\n    user = getattr(params, \"user\", None)\n    if user:\n        span_attributes[SpanAttributes.DB_USER] = user\n\n    # connection contains _addr attribute which is either a host/port tuple, or unix socket string\n    # https://magicstack.github.io/asyncpg/current/_modules/asyncpg/connection.html\n    addr = getattr(connection, \"_addr\", None)\n    if isinstance(addr, tuple):\n        span_attributes[SpanAttributes.NET_PEER_NAME] = addr[0]\n        span_attributes[SpanAttributes.NET_PEER_PORT] = addr[1]\n        span_attributes[\n            SpanAttributes.NET_TRANSPORT\n        ] = NetTransportValues.IP_TCP.value\n    elif isinstance(addr, str):\n        span_attributes[SpanAttributes.NET_PEER_NAME] = addr\n        span_attributes[\n            SpanAttributes.NET_TRANSPORT\n        ] = NetTransportValues.UNIX.value\n\n    if query is not None:\n        span_attributes[SpanAttributes.DB_STATEMENT] = query\n\n    if parameters is not None and len(parameters) > 0:\n        span_attributes[\"db.statement.parameters\"] = str(parameters)\n\n    return span_attributes\n\n\nclass AsyncPGInstrumentor(BaseInstrumentor):\n    def __init__(self, capture_parameters=False):\n        super().__init__()\n        self.capture_parameters = capture_parameters\n        self._tracer = None\n\n    def instrumentation_dependencies(self) -> Collection[str]:\n        return _instruments\n\n    def _instrument(self, **kwargs):\n        tracer_provider = kwargs.get(\"tracer_provider\")\n        self._tracer = trace.get_tracer(__name__, __version__, tracer_provider)\n\n        for method in [\n            \"Connection.execute\",\n            \"Connection.executemany\",\n            \"Connection.fetch\",\n            \"Connection.fetchval\",\n            \"Connection.fetchrow\",\n        ]:\n            wrapt.wrap_function_wrapper(\n                \"asyncpg.connection\", method, self._do_execute\n            )\n\n    def _uninstrument(self, **__):\n        for method in [\n            \"execute\",\n            \"executemany\",\n            \"fetch\",\n            \"fetchval\",\n            \"fetchrow\",\n        ]:\n            unwrap(asyncpg.Connection, method)\n\n    async def _do_execute(self, func, instance, args, kwargs):\n\n        exception = None\n        params = getattr(instance, \"_params\", {})\n        name = args[0] if args[0] else params.get(\"database\", \"postgresql\")\n\n        try:\n            name = name.split()[0]\n        except IndexError:\n            name = \"\"\n\n        with self._tracer.start_as_current_span(\n            name, kind=SpanKind.CLIENT\n        ) as span:\n            if span.is_recording():\n                span_attributes = _hydrate_span_from_args(\n                    instance,\n                    args[0],\n                    args[1:] if self.capture_parameters else None,\n                )\n                for attribute, value in span_attributes.items():\n                    span.set_attribute(attribute, value)\n\n            try:\n                result = await func(*args, **kwargs)\n            except Exception as exc:  # pylint: disable=W0703\n                exception = exc\n                raise\n            finally:\n                if span.is_recording() and exception is not None:\n                    span.set_status(Status(StatusCode.ERROR))\n\n        return result\n", "path": "instrumentation/opentelemetry-instrumentation-asyncpg/src/opentelemetry/instrumentation/asyncpg/__init__.py"}]}