Repository: open-telemetry/opentelemetry-python-contrib

Issue:
[Redis] Add support for sanitisation from environment variable
The Redis instrumentation now supports sanitisation. I'd like to use this via auto instrumentation so an environment variable must be configured.

When running auto instrumentation with environment variable `OTEL_PYTHON_INSTRUMENTATION_SANITIZE_REDIS` set to `true`, I expect sanitisation to be enabled.

A more interesting change could be to support kwargs being passed to instrumentations from environment variables.


Discussion:

Resolving patch:
diff --git a/instrumentation/opentelemetry-instrumentation-redis/src/opentelemetry/instrumentation/redis/__init__.py b/instrumentation/opentelemetry-instrumentation-redis/src/opentelemetry/instrumentation/redis/__init__.py
--- a/instrumentation/opentelemetry-instrumentation-redis/src/opentelemetry/instrumentation/redis/__init__.py
+++ b/instrumentation/opentelemetry-instrumentation-redis/src/opentelemetry/instrumentation/redis/__init__.py
@@ -88,10 +88,27 @@ def response_hook(span, instance, response):
     client = redis.StrictRedis(host="localhost", port=6379)
     client.get("my-key")
 
+Configuration
+-------------
+
+Query sanitization
+******************
+To enable query sanitization with an environment variable, set
+``OTEL_PYTHON_INSTRUMENTATION_SANITIZE_REDIS`` to "true".
+
+For example,
+
+::
+
+    export OTEL_PYTHON_INSTRUMENTATION_SANITIZE_REDIS="true"
+
+will result in traced queries like "SET ? ?".
+
 API
 ---
 """
 import typing
+from os import environ
 from typing import Any, Collection
 
 import redis
@@ -99,6 +116,9 @@ def response_hook(span, instance, response):
 
 from opentelemetry import trace
 from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
+from opentelemetry.instrumentation.redis.environment_variables import (
+    OTEL_PYTHON_INSTRUMENTATION_SANITIZE_REDIS,
+)
 from opentelemetry.instrumentation.redis.package import _instruments
 from opentelemetry.instrumentation.redis.util import (
     _extract_conn_attributes,
@@ -287,7 +307,15 @@ def _instrument(self, **kwargs):
             tracer,
             request_hook=kwargs.get("request_hook"),
             response_hook=kwargs.get("response_hook"),
-            sanitize_query=kwargs.get("sanitize_query", False),
+            sanitize_query=kwargs.get(
+                "sanitize_query",
+                environ.get(
+                    OTEL_PYTHON_INSTRUMENTATION_SANITIZE_REDIS, "false"
+                )
+                .lower()
+                .strip()
+                == "true",
+            ),
         )
 
     def _uninstrument(self, **kwargs):
diff --git a/instrumentation/opentelemetry-instrumentation-redis/src/opentelemetry/instrumentation/redis/environment_variables.py b/instrumentation/opentelemetry-instrumentation-redis/src/opentelemetry/instrumentation/redis/environment_variables.py
new file mode 100644
--- /dev/null
+++ b/instrumentation/opentelemetry-instrumentation-redis/src/opentelemetry/instrumentation/redis/environment_variables.py
@@ -0,0 +1,17 @@
+# Copyright The OpenTelemetry Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+OTEL_PYTHON_INSTRUMENTATION_SANITIZE_REDIS = (
+    "OTEL_PYTHON_INSTRUMENTATION_SANITIZE_REDIS"
+)


Test patch:
diff --git a/instrumentation/opentelemetry-instrumentation-redis/tests/test_redis.py b/instrumentation/opentelemetry-instrumentation-redis/tests/test_redis.py
--- a/instrumentation/opentelemetry-instrumentation-redis/tests/test_redis.py
+++ b/instrumentation/opentelemetry-instrumentation-redis/tests/test_redis.py
@@ -168,6 +168,32 @@ def test_query_sanitizer_enabled(self):
         span = spans[0]
         self.assertEqual(span.attributes.get("db.statement"), "SET ? ?")
 
+    def test_query_sanitizer_enabled_env(self):
+        redis_client = redis.Redis()
+        connection = redis.connection.Connection()
+        redis_client.connection = connection
+
+        RedisInstrumentor().uninstrument()
+
+        env_patch = mock.patch.dict(
+            "os.environ",
+            {"OTEL_PYTHON_INSTRUMENTATION_SANITIZE_REDIS": "true"},
+        )
+        env_patch.start()
+        RedisInstrumentor().instrument(
+            tracer_provider=self.tracer_provider,
+        )
+
+        with mock.patch.object(redis_client, "connection"):
+            redis_client.set("key", "value")
+
+        spans = self.memory_exporter.get_finished_spans()
+        self.assertEqual(len(spans), 1)
+
+        span = spans[0]
+        self.assertEqual(span.attributes.get("db.statement"), "SET ? ?")
+        env_patch.stop()
+
     def test_query_sanitizer_disabled(self):
         redis_client = redis.Redis()
         connection = redis.connection.Connection()