Repository: open-telemetry/opentelemetry-python-contrib

Issue:
elasticsearch span_name not correctly

**Steps to reproduce**
Describe exactly how to reproduce the error. Include a code sample if applicable.

**What is the expected behavior?**
Our index is created on a rolling basis
Therefore, we will use a specific time to query the index when querying, and when the plugin generates span_name, it will bring the unified index, so that span_name cannot be described as an operation. As follows
```
Elasticsearch/bkfta_action_20220228_read,bkfta_action_20220301_read,bkfta_action_20220302_read,bkfta_action_20220303_read,bkfta_action_20220304_read,bkfta_action_20220305_read,bkfta_action_20220306_read,bkfta_action_20220307_read/_search
```
**What is the actual behavior?**
span_name shuld be
```
Elasticsearch/{index_name}/_search
```

**Additional context**
Add any other context about the problem here.



Discussion:

Resolving patch:
diff --git a/instrumentation/opentelemetry-instrumentation-elasticsearch/src/opentelemetry/instrumentation/elasticsearch/__init__.py b/instrumentation/opentelemetry-instrumentation-elasticsearch/src/opentelemetry/instrumentation/elasticsearch/__init__.py
--- a/instrumentation/opentelemetry-instrumentation-elasticsearch/src/opentelemetry/instrumentation/elasticsearch/__init__.py
+++ b/instrumentation/opentelemetry-instrumentation-elasticsearch/src/opentelemetry/instrumentation/elasticsearch/__init__.py
@@ -150,11 +150,14 @@ def _uninstrument(self, **kwargs):
 
 _regex_doc_url = re.compile(r"/_doc/([^/]+)")
 
+# search api https://www.elastic.co/guide/en/elasticsearch/reference/current/search-search.html
+_regex_search_url = re.compile(r"/([^/]+)/_search[/]?")
+
 
 def _wrap_perform_request(
     tracer, span_name_prefix, request_hook=None, response_hook=None
 ):
-    # pylint: disable=R0912
+    # pylint: disable=R0912,R0914
     def wrapper(wrapped, _, args, kwargs):
         method = url = None
         try:
@@ -167,7 +170,10 @@ def wrapper(wrapped, _, args, kwargs):
             )
 
         op_name = span_name_prefix + (url or method or _DEFAULT_OP_NAME)
+
         doc_id = None
+        search_target = None
+
         if url:
             # TODO: This regex-based solution avoids creating an unbounded number of span names, but should be replaced by instrumenting individual Elasticsearch methods instead of Transport.perform_request()
             # A limitation of the regex is that only the '_doc' mapping type is supported. Mapping types are deprecated since Elasticsearch 7
@@ -184,6 +190,11 @@ def wrapper(wrapped, _, args, kwargs):
                 )
                 # Put the document ID in attributes
                 doc_id = match.group(1)
+            match = _regex_search_url.search(url)
+            if match is not None:
+                op_name = span_name_prefix + "/<target>/_search"
+                search_target = match.group(1)
+
         params = kwargs.get("params", {})
         body = kwargs.get("body", None)
 
@@ -209,6 +220,8 @@ def wrapper(wrapped, _, args, kwargs):
                     attributes["elasticsearch.params"] = str(params)
                 if doc_id:
                     attributes["elasticsearch.id"] = doc_id
+                if search_target:
+                    attributes["elasticsearch.target"] = search_target
                 for key, value in attributes.items():
                     span.set_attribute(key, value)
 


Test patch:
diff --git a/instrumentation/opentelemetry-instrumentation-elasticsearch/tests/test_elasticsearch.py b/instrumentation/opentelemetry-instrumentation-elasticsearch/tests/test_elasticsearch.py
--- a/instrumentation/opentelemetry-instrumentation-elasticsearch/tests/test_elasticsearch.py
+++ b/instrumentation/opentelemetry-instrumentation-elasticsearch/tests/test_elasticsearch.py
@@ -237,7 +237,7 @@ def test_dsl_search(self, request_mock):
         spans = self.get_finished_spans()
         span = spans[0]
         self.assertEqual(1, len(spans))
-        self.assertEqual(span.name, "Elasticsearch/test-index/_search")
+        self.assertEqual(span.name, "Elasticsearch/<target>/_search")
         self.assertIsNotNone(span.end_time)
         self.assertEqual(
             span.attributes,
@@ -245,6 +245,7 @@ def test_dsl_search(self, request_mock):
                 SpanAttributes.DB_SYSTEM: "elasticsearch",
                 "elasticsearch.url": "/test-index/_search",
                 "elasticsearch.method": helpers.dsl_search_method,
+                "elasticsearch.target": "test-index",
                 SpanAttributes.DB_STATEMENT: str(
                     {
                         "query": {