Skip to content

Commit 39b5452

Browse files
adding response_hook to elastic instrumentation
1 parent fc8a02b commit 39b5452

File tree

3 files changed

+71
-10
lines changed

3 files changed

+71
-10
lines changed

Diff for: CHANGELOG.md

+3
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99
- `opentelemetry-sdk-extension-aws` Release AWS Python SDK Extension as 1.0.0
1010
([#667](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/667))
1111

12+
### Added
13+
- `opentelemetry-instrumentation-elasticsearch` Added `response_hook` callback
14+
1215
### Changed
1316
- `opentelemetry-instrumentation-botocore` Unpatch botocore Endpoint.prepare_request on uninstrument
1417
([#664](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/664))

Diff for: instrumentation/opentelemetry-instrumentation-elasticsearch/src/opentelemetry/instrumentation/elasticsearch/__init__.py

+15-9
Original file line numberDiff line numberDiff line change
@@ -97,17 +97,20 @@ def _instrument(self, **kwargs):
9797
"""
9898
tracer_provider = kwargs.get("tracer_provider")
9999
tracer = get_tracer(__name__, __version__, tracer_provider)
100+
response_hook = kwargs.get("response_hook", _default_response_hook)
100101
_wrap(
101102
elasticsearch,
102103
"Transport.perform_request",
103-
_wrap_perform_request(tracer, self._span_name_prefix),
104+
_wrap_perform_request(
105+
tracer, self._span_name_prefix, response_hook
106+
),
104107
)
105108

106109
def _uninstrument(self, **kwargs):
107110
unwrap(elasticsearch.Transport, "perform_request")
108111

109112

110-
def _wrap_perform_request(tracer, span_name_prefix):
113+
def _wrap_perform_request(tracer, span_name_prefix, response_hook):
111114
# pylint: disable=R0912
112115
def wrapper(wrapped, _, args, kwargs):
113116
method = url = None
@@ -143,13 +146,16 @@ def wrapper(wrapped, _, args, kwargs):
143146
span.set_attribute(key, value)
144147

145148
rv = wrapped(*args, **kwargs)
146-
if isinstance(rv, dict) and span.is_recording():
147-
for member in _ATTRIBUTES_FROM_RESULT:
148-
if member in rv:
149-
span.set_attribute(
150-
"elasticsearch.{0}".format(member),
151-
str(rv[member]),
152-
)
149+
response_hook(span, rv)
153150
return rv
154151

155152
return wrapper
153+
154+
155+
def _default_response_hook(span, response):
156+
if isinstance(response, dict) and span.is_recording():
157+
for member in _ATTRIBUTES_FROM_RESULT:
158+
if member in response:
159+
span.set_attribute(
160+
"elasticsearch.{0}".format(member), str(response[member]),
161+
)

Diff for: instrumentation/opentelemetry-instrumentation-elasticsearch/tests/test_elasticsearch.py

+53-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
14-
14+
import json
1515
import os
1616
import threading
1717
from ast import literal_eval
@@ -316,3 +316,55 @@ def test_dsl_index(self, request_mock):
316316
"title": "About searching",
317317
},
318318
)
319+
320+
def test_response_hook(self, request_mock):
321+
response_attribute_name = "db.query_result"
322+
323+
def response_hook(span, response):
324+
if span and span.is_recording():
325+
span.set_attribute(
326+
response_attribute_name, json.dumps(response)
327+
)
328+
329+
ElasticsearchInstrumentor().uninstrument()
330+
ElasticsearchInstrumentor().instrument(response_hook=response_hook)
331+
332+
response_payload = {
333+
"took": 9,
334+
"timed_out": False,
335+
"_shards": {
336+
"total": 1,
337+
"successful": 1,
338+
"skipped": 0,
339+
"failed": 0,
340+
},
341+
"hits": {
342+
"total": {"value": 1, "relation": "eq"},
343+
"max_score": 0.18232156,
344+
"hits": [
345+
{
346+
"_index": "test-index",
347+
"_type": "tweet",
348+
"_id": "1",
349+
"_score": 0.18232156,
350+
"_source": {"name": "tester"},
351+
}
352+
],
353+
},
354+
}
355+
356+
request_mock.return_value = (
357+
1,
358+
{},
359+
json.dumps(response_payload),
360+
)
361+
es = Elasticsearch()
362+
es.get(index="test-index", doc_type="tweet", id=1)
363+
364+
spans = self.get_finished_spans()
365+
366+
self.assertEqual(1, len(spans))
367+
self.assertEqual(
368+
json.dumps(response_payload),
369+
spans[0].attributes[response_attribute_name],
370+
)

0 commit comments

Comments
 (0)