mirror of
https://github.com/open-telemetry/opentelemetry-python-contrib.git
synced 2025-07-28 12:43:39 +08:00
Sanitize DB_STATEMENT by default for elasticsearch (#1758)
This commit is contained in:
@ -20,6 +20,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
- Fix elasticsearch db.statement attribute to be sanitized by default
|
||||||
|
([#1758](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1758))
|
||||||
- Fix `AttributeError` when AWS Lambda handler receives a list event
|
- Fix `AttributeError` when AWS Lambda handler receives a list event
|
||||||
([#1738](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1738))
|
([#1738](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1738))
|
||||||
- Fix `None does not implement middleware` error when there are no middlewares registered
|
- Fix `None does not implement middleware` error when there are no middlewares registered
|
||||||
|
@ -44,7 +44,6 @@ environment variable or by passing the prefix as an argument to the instrumentor
|
|||||||
|
|
||||||
The instrument() method accepts the following keyword args:
|
The instrument() method accepts the following keyword args:
|
||||||
tracer_provider (TracerProvider) - an optional tracer provider
|
tracer_provider (TracerProvider) - an optional tracer provider
|
||||||
sanitize_query (bool) - an optional query sanitization flag
|
|
||||||
request_hook (Callable) - a function with extra user-defined logic to be performed before performing the request
|
request_hook (Callable) - a function with extra user-defined logic to be performed before performing the request
|
||||||
this function signature is:
|
this function signature is:
|
||||||
def request_hook(span: Span, method: str, url: str, kwargs)
|
def request_hook(span: Span, method: str, url: str, kwargs)
|
||||||
@ -138,13 +137,11 @@ class ElasticsearchInstrumentor(BaseInstrumentor):
|
|||||||
tracer = get_tracer(__name__, __version__, tracer_provider)
|
tracer = get_tracer(__name__, __version__, tracer_provider)
|
||||||
request_hook = kwargs.get("request_hook")
|
request_hook = kwargs.get("request_hook")
|
||||||
response_hook = kwargs.get("response_hook")
|
response_hook = kwargs.get("response_hook")
|
||||||
sanitize_query = kwargs.get("sanitize_query", False)
|
|
||||||
_wrap(
|
_wrap(
|
||||||
elasticsearch,
|
elasticsearch,
|
||||||
"Transport.perform_request",
|
"Transport.perform_request",
|
||||||
_wrap_perform_request(
|
_wrap_perform_request(
|
||||||
tracer,
|
tracer,
|
||||||
sanitize_query,
|
|
||||||
self._span_name_prefix,
|
self._span_name_prefix,
|
||||||
request_hook,
|
request_hook,
|
||||||
response_hook,
|
response_hook,
|
||||||
@ -163,7 +160,6 @@ _regex_search_url = re.compile(r"/([^/]+)/_search[/]?")
|
|||||||
|
|
||||||
def _wrap_perform_request(
|
def _wrap_perform_request(
|
||||||
tracer,
|
tracer,
|
||||||
sanitize_query,
|
|
||||||
span_name_prefix,
|
span_name_prefix,
|
||||||
request_hook=None,
|
request_hook=None,
|
||||||
response_hook=None,
|
response_hook=None,
|
||||||
@ -225,10 +221,9 @@ def _wrap_perform_request(
|
|||||||
if method:
|
if method:
|
||||||
attributes["elasticsearch.method"] = method
|
attributes["elasticsearch.method"] = method
|
||||||
if body:
|
if body:
|
||||||
statement = str(body)
|
attributes[SpanAttributes.DB_STATEMENT] = sanitize_body(
|
||||||
if sanitize_query:
|
body
|
||||||
statement = sanitize_body(body)
|
)
|
||||||
attributes[SpanAttributes.DB_STATEMENT] = statement
|
|
||||||
if params:
|
if params:
|
||||||
attributes["elasticsearch.params"] = str(params)
|
attributes["elasticsearch.params"] = str(params)
|
||||||
if doc_id:
|
if doc_id:
|
||||||
|
@ -29,7 +29,8 @@ def _flatten_dict(d, parent_key=""):
|
|||||||
items = []
|
items = []
|
||||||
for k, v in d.items():
|
for k, v in d.items():
|
||||||
new_key = parent_key + "." + k if parent_key else k
|
new_key = parent_key + "." + k if parent_key else k
|
||||||
if isinstance(v, dict):
|
# recursive call _flatten_dict for a non-empty dict value
|
||||||
|
if isinstance(v, dict) and v:
|
||||||
items.extend(_flatten_dict(v, new_key).items())
|
items.extend(_flatten_dict(v, new_key).items())
|
||||||
else:
|
else:
|
||||||
items.append((new_key, v))
|
items.append((new_key, v))
|
||||||
|
@ -58,9 +58,7 @@ class TestElasticsearchIntegration(TestBase):
|
|||||||
"elasticsearch.url": "/test-index/_search",
|
"elasticsearch.url": "/test-index/_search",
|
||||||
"elasticsearch.method": helpers.dsl_search_method,
|
"elasticsearch.method": helpers.dsl_search_method,
|
||||||
"elasticsearch.target": "test-index",
|
"elasticsearch.target": "test-index",
|
||||||
SpanAttributes.DB_STATEMENT: str(
|
SpanAttributes.DB_STATEMENT: str({"query": {"bool": {"filter": "?"}}}),
|
||||||
{"query": {"bool": {"filter": [{"term": {"author": "testing"}}]}}}
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
create_attributes = {
|
create_attributes = {
|
||||||
@ -264,18 +262,6 @@ class TestElasticsearchIntegration(TestBase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def test_dsl_search_sanitized(self, request_mock):
|
def test_dsl_search_sanitized(self, request_mock):
|
||||||
# Reset instrumentation to use sanitized query (default)
|
|
||||||
ElasticsearchInstrumentor().uninstrument()
|
|
||||||
ElasticsearchInstrumentor().instrument(sanitize_query=True)
|
|
||||||
|
|
||||||
# update expected attributes to match sanitized query
|
|
||||||
sanitized_search_attributes = self.search_attributes.copy()
|
|
||||||
sanitized_search_attributes.update(
|
|
||||||
{
|
|
||||||
SpanAttributes.DB_STATEMENT: "{'query': {'bool': {'filter': '?'}}}"
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
request_mock.return_value = (1, {}, '{"hits": {"hits": []}}')
|
request_mock.return_value = (1, {}, '{"hits": {"hits": []}}')
|
||||||
client = Elasticsearch()
|
client = Elasticsearch()
|
||||||
search = Search(using=client, index="test-index").filter(
|
search = Search(using=client, index="test-index").filter(
|
||||||
@ -289,7 +275,7 @@ class TestElasticsearchIntegration(TestBase):
|
|||||||
self.assertIsNotNone(span.end_time)
|
self.assertIsNotNone(span.end_time)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
span.attributes,
|
span.attributes,
|
||||||
sanitized_search_attributes,
|
self.search_attributes,
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_dsl_create(self, request_mock):
|
def test_dsl_create(self, request_mock):
|
||||||
@ -320,9 +306,6 @@ class TestElasticsearchIntegration(TestBase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def test_dsl_create_sanitized(self, request_mock):
|
def test_dsl_create_sanitized(self, request_mock):
|
||||||
# Reset instrumentation to explicitly use sanitized query
|
|
||||||
ElasticsearchInstrumentor().uninstrument()
|
|
||||||
ElasticsearchInstrumentor().instrument(sanitize_query=True)
|
|
||||||
request_mock.return_value = (1, {}, {})
|
request_mock.return_value = (1, {}, {})
|
||||||
client = Elasticsearch()
|
client = Elasticsearch()
|
||||||
Article.init(using=client)
|
Article.init(using=client)
|
||||||
|
Reference in New Issue
Block a user