We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Instrument non-index Elasticsearch client methods
There are many methods on the `elasticsearch-py` client class that we aren't instrumenting, for example `ping()`, because they don't operate on an index.

We should capture all these calls too - I'm sure many applications have such calls that would be good to show on traces.

https://github.com/elastic/elasticsearch-py/blob/master/elasticsearch/client/__init__.py

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `src/scout_apm/instruments/elasticsearch.py`
Content:
```
1 # coding=utf-8
2 from __future__ import absolute_import, division, print_function, unicode_literals
3 
4 import logging
5 
6 import wrapt
7 
8 from scout_apm.core.tracked_request import TrackedRequest
9 
10 try:
11     from elasticsearch import Elasticsearch, Transport
12 except ImportError:  # pragma: no cover
13     Elasticsearch = None
14     Transport = None
15 
16 logger = logging.getLogger(__name__)
17 
18 
19 def ensure_installed():
20     logger.info("Ensuring elasticsearch instrumentation is installed.")
21 
22     if Elasticsearch is None:
23         logger.info("Unable to import elasticsearch.Elasticsearch")
24     else:
25         ensure_client_instrumented()
26         ensure_transport_instrumented()
27 
28 
29 CLIENT_METHODS = [
30     "bulk",
31     "count",
32     "create",
33     "delete",
34     "delete_by_query",
35     "exists",
36     "exists_source",
37     "explain",
38     "field_caps",
39     "get",
40     "get_source",
41     "index",
42     "mget",
43     "msearch",
44     "msearch_template",
45     "mtermvectors",
46     "reindex",
47     "reindex_rethrottle",
48     "search",
49     "search_shards",
50     "search_template",
51     "termvectors",
52     "update",
53     "update_by_query",
54 ]
55 
56 
57 have_patched_client = False
58 
59 
60 def ensure_client_instrumented():
61     global have_patched_client
62 
63     if not have_patched_client:
64         for name in CLIENT_METHODS:
65             try:
66                 setattr(
67                     Elasticsearch,
68                     name,
69                     wrap_client_method(getattr(Elasticsearch, name)),
70                 )
71             except Exception as exc:
72                 logger.warning(
73                     "Unable to instrument elasticsearch.Elasticsearch.%s: %r",
74                     name,
75                     exc,
76                     exc_info=exc,
77                 )
78 
79         have_patched_client = True
80 
81 
82 @wrapt.decorator
83 def wrap_client_method(wrapped, instance, args, kwargs):
84     def _get_index(index, *args, **kwargs):
85         return index
86 
87     try:
88         index = _get_index(*args, **kwargs)
89     except TypeError:
90         index = "Unknown"
91     else:
92         if not index:
93             index = "Unknown"
94         if isinstance(index, (list, tuple)):
95             index = ",".join(index)
96     index = index.title()
97     camel_name = "".join(c.title() for c in wrapped.__name__.split("_"))
98     operation = "Elasticsearch/{}/{}".format(index, camel_name)
99     tracked_request = TrackedRequest.instance()
100     tracked_request.start_span(operation=operation, ignore_children=True)
101 
102     try:
103         return wrapped(*args, **kwargs)
104     finally:
105         tracked_request.stop_span()
106 
107 
108 have_patched_transport = False
109 
110 
111 def ensure_transport_instrumented():
112     global have_patched_transport
113 
114     if not have_patched_transport:
115         try:
116             Transport.perform_request = wrapped_perform_request(
117                 Transport.perform_request
118             )
119         except Exception as exc:
120             logger.warning(
121                 "Unable to instrument elasticsearch.Transport.perform_request: %r",
122                 exc,
123                 exc_info=exc,
124             )
125 
126     have_patched_transport = True
127 
128 
129 def _sanitize_name(name):
130     try:
131         op = name.split("/")[-1]
132         op = op[1:]  # chop leading '_' from op
133         known_names = (
134             "bench",
135             "bulk",
136             "count",
137             "exists",
138             "explain",
139             "field_stats",
140             "health",
141             "mget",
142             "mlt",
143             "mpercolate",
144             "msearch",
145             "mtermvectors",
146             "percolate",
147             "query",
148             "scroll",
149             "search_shards",
150             "source",
151             "suggest",
152             "template",
153             "termvectors",
154             "update",
155             "search",
156         )
157         if op in known_names:
158             return op.title()
159         return "Unknown"
160     except Exception:
161         return "Unknown"
162 
163 
164 @wrapt.decorator
165 def wrapped_perform_request(wrapped, instance, args, kwargs):
166     try:
167         op = _sanitize_name(args[1])
168     except IndexError:
169         op = "Unknown"
170 
171     tracked_request = TrackedRequest.instance()
172     tracked_request.start_span(
173         operation="Elasticsearch/{}".format(op), ignore_children=True
174     )
175 
176     try:
177         return wrapped(*args, **kwargs)
178     finally:
179         tracked_request.stop_span()
180
```
--- 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/src/scout_apm/instruments/elasticsearch.py b/src/scout_apm/instruments/elasticsearch.py
--- a/src/scout_apm/instruments/elasticsearch.py
+++ b/src/scout_apm/instruments/elasticsearch.py
@@ -2,6 +2,7 @@
 from __future__ import absolute_import, division, print_function, unicode_literals
 
 import logging
+from collections import namedtuple
 
 import wrapt
 
@@ -26,31 +27,46 @@
         ensure_transport_instrumented()
 
 
+ClientMethod = namedtuple("ClientMethod", ["name", "takes_index_argument"])
+
 CLIENT_METHODS = [
-    "bulk",
-    "count",
-    "create",
-    "delete",
-    "delete_by_query",
-    "exists",
-    "exists_source",
-    "explain",
-    "field_caps",
-    "get",
-    "get_source",
-    "index",
-    "mget",
-    "msearch",
-    "msearch_template",
-    "mtermvectors",
-    "reindex",
-    "reindex_rethrottle",
-    "search",
-    "search_shards",
-    "search_template",
-    "termvectors",
-    "update",
-    "update_by_query",
+    ClientMethod("bulk", True),
+    ClientMethod("clear_scroll", False),
+    ClientMethod("count", True),
+    ClientMethod("create", True),
+    ClientMethod("delete", True),
+    ClientMethod("delete_by_query", True),
+    ClientMethod("delete_by_query_rethrottle", False),
+    ClientMethod("delete_script", False),
+    ClientMethod("exists", True),
+    ClientMethod("exists_source", True),
+    ClientMethod("explain", True),
+    ClientMethod("field_caps", True),
+    ClientMethod("get", True),
+    ClientMethod("get_script", False),
+    ClientMethod("get_source", True),
+    ClientMethod("index", True),
+    ClientMethod("info", False),
+    ClientMethod("mget", True),
+    ClientMethod("msearch", True),
+    ClientMethod("msearch_template", True),
+    ClientMethod("mtermvectors", True),
+    ClientMethod("ping", False),
+    ClientMethod("put_script", False),
+    ClientMethod("rank_eval", True),
+    ClientMethod("reindex", False),
+    ClientMethod("reindex_rethrottle", False),
+    ClientMethod("render_search_template", False),
+    ClientMethod("scripts_painless_context", False),
+    ClientMethod("scripts_painless_execute", False),
+    ClientMethod("scroll", False),
+    ClientMethod("search", True),
+    ClientMethod("search_shards", True),
+    ClientMethod("search_template", True),
+    ClientMethod("termvectors", True),
+    ClientMethod("update", True),
+    ClientMethod("update_by_query", True),
+    ClientMethod("update_by_query_rethrottle", False),
 ]
 
 
@@ -61,13 +77,14 @@
     global have_patched_client
 
     if not have_patched_client:
-        for name in CLIENT_METHODS:
+        for name, takes_index_argument in CLIENT_METHODS:
             try:
-                setattr(
-                    Elasticsearch,
-                    name,
-                    wrap_client_method(getattr(Elasticsearch, name)),
-                )
+                method = getattr(Elasticsearch, name)
+                if takes_index_argument:
+                    wrapped = wrap_client_index_method(method)
+                else:
+                    wrapped = wrap_client_method(method)
+                setattr(Elasticsearch, name, wrapped)
             except Exception as exc:
                 logger.warning(
                     "Unable to instrument elasticsearch.Elasticsearch.%s: %r",
@@ -80,7 +97,7 @@
 
 
 @wrapt.decorator
-def wrap_client_method(wrapped, instance, args, kwargs):
+def wrap_client_index_method(wrapped, instance, args, kwargs):
     def _get_index(index, *args, **kwargs):
         return index
 
@@ -105,6 +122,19 @@
         tracked_request.stop_span()
 
 
+@wrapt.decorator
+def wrap_client_method(wrapped, instance, args, kwargs):
+    camel_name = "".join(c.title() for c in wrapped.__name__.split("_"))
+    operation = "Elasticsearch/{}".format(camel_name)
+    tracked_request = TrackedRequest.instance()
+    tracked_request.start_span(operation=operation, ignore_children=True)
+
+    try:
+        return wrapped(*args, **kwargs)
+    finally:
+        tracked_request.stop_span()
+
+
 have_patched_transport = False

{"golden_diff": "diff --git a/src/scout_apm/instruments/elasticsearch.py b/src/scout_apm/instruments/elasticsearch.py\n--- a/src/scout_apm/instruments/elasticsearch.py\n+++ b/src/scout_apm/instruments/elasticsearch.py\n@@ -2,6 +2,7 @@\n from __future__ import absolute_import, division, print_function, unicode_literals\n \n import logging\n+from collections import namedtuple\n \n import wrapt\n \n@@ -26,31 +27,46 @@\n         ensure_transport_instrumented()\n \n \n+ClientMethod = namedtuple(\"ClientMethod\", [\"name\", \"takes_index_argument\"])\n+\n CLIENT_METHODS = [\n-    \"bulk\",\n-    \"count\",\n-    \"create\",\n-    \"delete\",\n-    \"delete_by_query\",\n-    \"exists\",\n-    \"exists_source\",\n-    \"explain\",\n-    \"field_caps\",\n-    \"get\",\n-    \"get_source\",\n-    \"index\",\n-    \"mget\",\n-    \"msearch\",\n-    \"msearch_template\",\n-    \"mtermvectors\",\n-    \"reindex\",\n-    \"reindex_rethrottle\",\n-    \"search\",\n-    \"search_shards\",\n-    \"search_template\",\n-    \"termvectors\",\n-    \"update\",\n-    \"update_by_query\",\n+    ClientMethod(\"bulk\", True),\n+    ClientMethod(\"clear_scroll\", False),\n+    ClientMethod(\"count\", True),\n+    ClientMethod(\"create\", True),\n+    ClientMethod(\"delete\", True),\n+    ClientMethod(\"delete_by_query\", True),\n+    ClientMethod(\"delete_by_query_rethrottle\", False),\n+    ClientMethod(\"delete_script\", False),\n+    ClientMethod(\"exists\", True),\n+    ClientMethod(\"exists_source\", True),\n+    ClientMethod(\"explain\", True),\n+    ClientMethod(\"field_caps\", True),\n+    ClientMethod(\"get\", True),\n+    ClientMethod(\"get_script\", False),\n+    ClientMethod(\"get_source\", True),\n+    ClientMethod(\"index\", True),\n+    ClientMethod(\"info\", False),\n+    ClientMethod(\"mget\", True),\n+    ClientMethod(\"msearch\", True),\n+    ClientMethod(\"msearch_template\", True),\n+    ClientMethod(\"mtermvectors\", True),\n+    ClientMethod(\"ping\", False),\n+    ClientMethod(\"put_script\", False),\n+    ClientMethod(\"rank_eval\", True),\n+    ClientMethod(\"reindex\", False),\n+    ClientMethod(\"reindex_rethrottle\", False),\n+    ClientMethod(\"render_search_template\", False),\n+    ClientMethod(\"scripts_painless_context\", False),\n+    ClientMethod(\"scripts_painless_execute\", False),\n+    ClientMethod(\"scroll\", False),\n+    ClientMethod(\"search\", True),\n+    ClientMethod(\"search_shards\", True),\n+    ClientMethod(\"search_template\", True),\n+    ClientMethod(\"termvectors\", True),\n+    ClientMethod(\"update\", True),\n+    ClientMethod(\"update_by_query\", True),\n+    ClientMethod(\"update_by_query_rethrottle\", False),\n ]\n \n \n@@ -61,13 +77,14 @@\n     global have_patched_client\n \n     if not have_patched_client:\n-        for name in CLIENT_METHODS:\n+        for name, takes_index_argument in CLIENT_METHODS:\n             try:\n-                setattr(\n-                    Elasticsearch,\n-                    name,\n-                    wrap_client_method(getattr(Elasticsearch, name)),\n-                )\n+                method = getattr(Elasticsearch, name)\n+                if takes_index_argument:\n+                    wrapped = wrap_client_index_method(method)\n+                else:\n+                    wrapped = wrap_client_method(method)\n+                setattr(Elasticsearch, name, wrapped)\n             except Exception as exc:\n                 logger.warning(\n                     \"Unable to instrument elasticsearch.Elasticsearch.%s: %r\",\n@@ -80,7 +97,7 @@\n \n \n @wrapt.decorator\n-def wrap_client_method(wrapped, instance, args, kwargs):\n+def wrap_client_index_method(wrapped, instance, args, kwargs):\n     def _get_index(index, *args, **kwargs):\n         return index\n \n@@ -105,6 +122,19 @@\n         tracked_request.stop_span()\n \n \n+@wrapt.decorator\n+def wrap_client_method(wrapped, instance, args, kwargs):\n+    camel_name = \"\".join(c.title() for c in wrapped.__name__.split(\"_\"))\n+    operation = \"Elasticsearch/{}\".format(camel_name)\n+    tracked_request = TrackedRequest.instance()\n+    tracked_request.start_span(operation=operation, ignore_children=True)\n+\n+    try:\n+        return wrapped(*args, **kwargs)\n+    finally:\n+        tracked_request.stop_span()\n+\n+\n have_patched_transport = False\n", "issue": "Instrument non-index Elasticsearch client methods\nThere are many methods on the `elasticsearch-py` client class that we aren't instrumenting, for example `ping()`, because they don't operate on an index.\r\n\r\nWe should capture all these calls too - I'm sure many applications have such calls that would be good to show on traces.\r\n\r\nhttps://github.com/elastic/elasticsearch-py/blob/master/elasticsearch/client/__init__.py\n", "before_files": [{"content": "# coding=utf-8\nfrom __future__ import absolute_import, division, print_function, unicode_literals\n\nimport logging\n\nimport wrapt\n\nfrom scout_apm.core.tracked_request import TrackedRequest\n\ntry:\n    from elasticsearch import Elasticsearch, Transport\nexcept ImportError:  # pragma: no cover\n    Elasticsearch = None\n    Transport = None\n\nlogger = logging.getLogger(__name__)\n\n\ndef ensure_installed():\n    logger.info(\"Ensuring elasticsearch instrumentation is installed.\")\n\n    if Elasticsearch is None:\n        logger.info(\"Unable to import elasticsearch.Elasticsearch\")\n    else:\n        ensure_client_instrumented()\n        ensure_transport_instrumented()\n\n\nCLIENT_METHODS = [\n    \"bulk\",\n    \"count\",\n    \"create\",\n    \"delete\",\n    \"delete_by_query\",\n    \"exists\",\n    \"exists_source\",\n    \"explain\",\n    \"field_caps\",\n    \"get\",\n    \"get_source\",\n    \"index\",\n    \"mget\",\n    \"msearch\",\n    \"msearch_template\",\n    \"mtermvectors\",\n    \"reindex\",\n    \"reindex_rethrottle\",\n    \"search\",\n    \"search_shards\",\n    \"search_template\",\n    \"termvectors\",\n    \"update\",\n    \"update_by_query\",\n]\n\n\nhave_patched_client = False\n\n\ndef ensure_client_instrumented():\n    global have_patched_client\n\n    if not have_patched_client:\n        for name in CLIENT_METHODS:\n            try:\n                setattr(\n                    Elasticsearch,\n                    name,\n                    wrap_client_method(getattr(Elasticsearch, name)),\n                )\n            except Exception as exc:\n                logger.warning(\n                    \"Unable to instrument elasticsearch.Elasticsearch.%s: %r\",\n                    name,\n                    exc,\n                    exc_info=exc,\n                )\n\n        have_patched_client = True\n\n\n@wrapt.decorator\ndef wrap_client_method(wrapped, instance, args, kwargs):\n    def _get_index(index, *args, **kwargs):\n        return index\n\n    try:\n        index = _get_index(*args, **kwargs)\n    except TypeError:\n        index = \"Unknown\"\n    else:\n        if not index:\n            index = \"Unknown\"\n        if isinstance(index, (list, tuple)):\n            index = \",\".join(index)\n    index = index.title()\n    camel_name = \"\".join(c.title() for c in wrapped.__name__.split(\"_\"))\n    operation = \"Elasticsearch/{}/{}\".format(index, camel_name)\n    tracked_request = TrackedRequest.instance()\n    tracked_request.start_span(operation=operation, ignore_children=True)\n\n    try:\n        return wrapped(*args, **kwargs)\n    finally:\n        tracked_request.stop_span()\n\n\nhave_patched_transport = False\n\n\ndef ensure_transport_instrumented():\n    global have_patched_transport\n\n    if not have_patched_transport:\n        try:\n            Transport.perform_request = wrapped_perform_request(\n                Transport.perform_request\n            )\n        except Exception as exc:\n            logger.warning(\n                \"Unable to instrument elasticsearch.Transport.perform_request: %r\",\n                exc,\n                exc_info=exc,\n            )\n\n    have_patched_transport = True\n\n\ndef _sanitize_name(name):\n    try:\n        op = name.split(\"/\")[-1]\n        op = op[1:]  # chop leading '_' from op\n        known_names = (\n            \"bench\",\n            \"bulk\",\n            \"count\",\n            \"exists\",\n            \"explain\",\n            \"field_stats\",\n            \"health\",\n            \"mget\",\n            \"mlt\",\n            \"mpercolate\",\n            \"msearch\",\n            \"mtermvectors\",\n            \"percolate\",\n            \"query\",\n            \"scroll\",\n            \"search_shards\",\n            \"source\",\n            \"suggest\",\n            \"template\",\n            \"termvectors\",\n            \"update\",\n            \"search\",\n        )\n        if op in known_names:\n            return op.title()\n        return \"Unknown\"\n    except Exception:\n        return \"Unknown\"\n\n\n@wrapt.decorator\ndef wrapped_perform_request(wrapped, instance, args, kwargs):\n    try:\n        op = _sanitize_name(args[1])\n    except IndexError:\n        op = \"Unknown\"\n\n    tracked_request = TrackedRequest.instance()\n    tracked_request.start_span(\n        operation=\"Elasticsearch/{}\".format(op), ignore_children=True\n    )\n\n    try:\n        return wrapped(*args, **kwargs)\n    finally:\n        tracked_request.stop_span()\n", "path": "src/scout_apm/instruments/elasticsearch.py"}], "after_files": [{"content": "# coding=utf-8\nfrom __future__ import absolute_import, division, print_function, unicode_literals\n\nimport logging\nfrom collections import namedtuple\n\nimport wrapt\n\nfrom scout_apm.core.tracked_request import TrackedRequest\n\ntry:\n    from elasticsearch import Elasticsearch, Transport\nexcept ImportError:  # pragma: no cover\n    Elasticsearch = None\n    Transport = None\n\nlogger = logging.getLogger(__name__)\n\n\ndef ensure_installed():\n    logger.info(\"Ensuring elasticsearch instrumentation is installed.\")\n\n    if Elasticsearch is None:\n        logger.info(\"Unable to import elasticsearch.Elasticsearch\")\n    else:\n        ensure_client_instrumented()\n        ensure_transport_instrumented()\n\n\nClientMethod = namedtuple(\"ClientMethod\", [\"name\", \"takes_index_argument\"])\n\nCLIENT_METHODS = [\n    ClientMethod(\"bulk\", True),\n    ClientMethod(\"clear_scroll\", False),\n    ClientMethod(\"count\", True),\n    ClientMethod(\"create\", True),\n    ClientMethod(\"delete\", True),\n    ClientMethod(\"delete_by_query\", True),\n    ClientMethod(\"delete_by_query_rethrottle\", False),\n    ClientMethod(\"delete_script\", False),\n    ClientMethod(\"exists\", True),\n    ClientMethod(\"exists_source\", True),\n    ClientMethod(\"explain\", True),\n    ClientMethod(\"field_caps\", True),\n    ClientMethod(\"get\", True),\n    ClientMethod(\"get_script\", False),\n    ClientMethod(\"get_source\", True),\n    ClientMethod(\"index\", True),\n    ClientMethod(\"info\", False),\n    ClientMethod(\"mget\", True),\n    ClientMethod(\"msearch\", True),\n    ClientMethod(\"msearch_template\", True),\n    ClientMethod(\"mtermvectors\", True),\n    ClientMethod(\"ping\", False),\n    ClientMethod(\"put_script\", False),\n    ClientMethod(\"rank_eval\", True),\n    ClientMethod(\"reindex\", False),\n    ClientMethod(\"reindex_rethrottle\", False),\n    ClientMethod(\"render_search_template\", False),\n    ClientMethod(\"scripts_painless_context\", False),\n    ClientMethod(\"scripts_painless_execute\", False),\n    ClientMethod(\"scroll\", False),\n    ClientMethod(\"search\", True),\n    ClientMethod(\"search_shards\", True),\n    ClientMethod(\"search_template\", True),\n    ClientMethod(\"termvectors\", True),\n    ClientMethod(\"update\", True),\n    ClientMethod(\"update_by_query\", True),\n    ClientMethod(\"update_by_query_rethrottle\", False),\n]\n\n\nhave_patched_client = False\n\n\ndef ensure_client_instrumented():\n    global have_patched_client\n\n    if not have_patched_client:\n        for name, takes_index_argument in CLIENT_METHODS:\n            try:\n                method = getattr(Elasticsearch, name)\n                if takes_index_argument:\n                    wrapped = wrap_client_index_method(method)\n                else:\n                    wrapped = wrap_client_method(method)\n                setattr(Elasticsearch, name, wrapped)\n            except Exception as exc:\n                logger.warning(\n                    \"Unable to instrument elasticsearch.Elasticsearch.%s: %r\",\n                    name,\n                    exc,\n                    exc_info=exc,\n                )\n\n        have_patched_client = True\n\n\n@wrapt.decorator\ndef wrap_client_index_method(wrapped, instance, args, kwargs):\n    def _get_index(index, *args, **kwargs):\n        return index\n\n    try:\n        index = _get_index(*args, **kwargs)\n    except TypeError:\n        index = \"Unknown\"\n    else:\n        if not index:\n            index = \"Unknown\"\n        if isinstance(index, (list, tuple)):\n            index = \",\".join(index)\n    index = index.title()\n    camel_name = \"\".join(c.title() for c in wrapped.__name__.split(\"_\"))\n    operation = \"Elasticsearch/{}/{}\".format(index, camel_name)\n    tracked_request = TrackedRequest.instance()\n    tracked_request.start_span(operation=operation, ignore_children=True)\n\n    try:\n        return wrapped(*args, **kwargs)\n    finally:\n        tracked_request.stop_span()\n\n\n@wrapt.decorator\ndef wrap_client_method(wrapped, instance, args, kwargs):\n    camel_name = \"\".join(c.title() for c in wrapped.__name__.split(\"_\"))\n    operation = \"Elasticsearch/{}\".format(camel_name)\n    tracked_request = TrackedRequest.instance()\n    tracked_request.start_span(operation=operation, ignore_children=True)\n\n    try:\n        return wrapped(*args, **kwargs)\n    finally:\n        tracked_request.stop_span()\n\n\nhave_patched_transport = False\n\n\ndef ensure_transport_instrumented():\n    global have_patched_transport\n\n    if not have_patched_transport:\n        try:\n            Transport.perform_request = wrapped_perform_request(\n                Transport.perform_request\n            )\n        except Exception as exc:\n            logger.warning(\n                \"Unable to instrument elasticsearch.Transport.perform_request: %r\",\n                exc,\n                exc_info=exc,\n            )\n\n    have_patched_transport = True\n\n\ndef _sanitize_name(name):\n    try:\n        op = name.split(\"/\")[-1]\n        op = op[1:]  # chop leading '_' from op\n        known_names = (\n            \"bench\",\n            \"bulk\",\n            \"count\",\n            \"exists\",\n            \"explain\",\n            \"field_stats\",\n            \"health\",\n            \"mget\",\n            \"mlt\",\n            \"mpercolate\",\n            \"msearch\",\n            \"mtermvectors\",\n            \"percolate\",\n            \"query\",\n            \"scroll\",\n            \"search_shards\",\n            \"source\",\n            \"suggest\",\n            \"template\",\n            \"termvectors\",\n            \"update\",\n            \"search\",\n        )\n        if op in known_names:\n            return op.title()\n        return \"Unknown\"\n    except Exception:\n        return \"Unknown\"\n\n\n@wrapt.decorator\ndef wrapped_perform_request(wrapped, instance, args, kwargs):\n    try:\n        op = _sanitize_name(args[1])\n    except IndexError:\n        op = \"Unknown\"\n\n    tracked_request = TrackedRequest.instance()\n    tracked_request.start_span(\n        operation=\"Elasticsearch/{}\".format(op), ignore_children=True\n    )\n\n    try:\n        return wrapped(*args, **kwargs)\n    finally:\n        tracked_request.stop_span()\n", "path": "src/scout_apm/instruments/elasticsearch.py"}]}