Repository: open-telemetry/opentelemetry-python

Issue:
Make boto and botocore instrumentations share code
The boto and botocore instrumentations share some code. Once #689 and #665 are merged in master make one depend on the other so that the code is not duplicated.


Discussion:

Resolving patch:
diff --git a/ext/opentelemetry-ext-boto/src/opentelemetry/ext/boto/__init__.py b/ext/opentelemetry-ext-boto/src/opentelemetry/ext/boto/__init__.py
--- a/ext/opentelemetry-ext-boto/src/opentelemetry/ext/boto/__init__.py
+++ b/ext/opentelemetry-ext-boto/src/opentelemetry/ext/boto/__init__.py
@@ -48,9 +48,10 @@
 from inspect import currentframe
 
 from boto.connection import AWSAuthConnection, AWSQueryConnection
-from wrapt import ObjectProxy, wrap_function_wrapper
+from wrapt import wrap_function_wrapper
 
 from opentelemetry.ext.boto.version import __version__
+from opentelemetry.ext.botocore import add_span_arg_tags, unwrap
 from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
 from opentelemetry.sdk.trace import Resource
 from opentelemetry.trace import SpanKind, get_tracer
@@ -197,55 +198,3 @@ def _patched_auth_request(self, original_func, instance, args, kwargs):
             args,
             kwargs,
         )
-
-
-def truncate_arg_value(value, max_len=1024):
-    """Truncate values which are bytes and greater than ``max_len``.
-    Useful for parameters like "Body" in ``put_object`` operations.
-    """
-    if isinstance(value, bytes) and len(value) > max_len:
-        return b"..."
-
-    return value
-
-
-def add_span_arg_tags(span, endpoint_name, args, args_names, args_traced):
-    if endpoint_name not in ["kms", "sts"]:
-        tags = dict(
-            (name, value)
-            for (name, value) in zip(args_names, args)
-            if name in args_traced
-        )
-        tags = flatten_dict(tags)
-        for key, value in {
-            k: truncate_arg_value(v)
-            for k, v in tags.items()
-            if k not in {"s3": ["params.Body"]}.get(endpoint_name, [])
-        }.items():
-            span.set_attribute(key, value)
-
-
-def flatten_dict(dict_, sep=".", prefix=""):
-    """
-    Returns a normalized dict of depth 1 with keys in order of embedding
-    """
-    # adapted from https://stackoverflow.com/a/19647596
-    return (
-        {
-            prefix + sep + k if prefix else k: v
-            for kk, vv in dict_.items()
-            for k, v in flatten_dict(vv, sep, kk).items()
-        }
-        if isinstance(dict_, dict)
-        else {prefix: dict_}
-    )
-
-
-def unwrap(obj, attr):
-    function = getattr(obj, attr, None)
-    if (
-        function
-        and isinstance(function, ObjectProxy)
-        and hasattr(function, "__wrapped__")
-    ):
-        setattr(obj, attr, function.__wrapped__)
diff --git a/ext/opentelemetry-ext-botocore/src/opentelemetry/ext/botocore/__init__.py b/ext/opentelemetry-ext-botocore/src/opentelemetry/ext/botocore/__init__.py
--- a/ext/opentelemetry-ext-botocore/src/opentelemetry/ext/botocore/__init__.py
+++ b/ext/opentelemetry-ext-botocore/src/opentelemetry/ext/botocore/__init__.py
@@ -160,6 +160,21 @@ def truncate_arg_value(value, max_len=1024):
 
         return value
 
+    def flatten_dict(dict_, sep=".", prefix=""):
+        """
+        Returns a normalized dict of depth 1 with keys in order of embedding
+        """
+        # adapted from https://stackoverflow.com/a/19647596
+        return (
+            {
+                prefix + sep + k if prefix else k: v
+                for kk, vv in dict_.items()
+                for k, v in flatten_dict(vv, sep, kk).items()
+            }
+            if isinstance(dict_, dict)
+            else {prefix: dict_}
+        )
+
     if endpoint_name not in {"kms", "sts"}:
         tags = dict(
             (name, value)
@@ -175,22 +190,6 @@ def truncate_arg_value(value, max_len=1024):
             span.set_attribute(key, value)
 
 
-def flatten_dict(dict_, sep=".", prefix=""):
-    """
-    Returns a normalized dict of depth 1 with keys in order of embedding
-    """
-    # adapted from https://stackoverflow.com/a/19647596
-    return (
-        {
-            prefix + sep + k if prefix else k: v
-            for kk, vv in dict_.items()
-            for k, v in flatten_dict(vv, sep, kk).items()
-        }
-        if isinstance(dict_, dict)
-        else {prefix: dict_}
-    )
-
-
 def deep_getattr(obj, attr_string, default=None):
     """
     Returns the attribute of ``obj`` at the dotted path given by


Test patch: