Repository: elastic/apm-agent-python

Issue:
'UnixDomainSocketConnection' object has no attribute 'port'
AttributeError: 'UnixDomainSocketConnection' object has no attribute 'port'
elastic-apm==5.5.1

```
  File "django_redis/cache.py", line 32, in _decorator
    return method(self, *args, **kwargs)
  File "django_redis/cache.py", line 80, in get
    return self.client.get(key, default=default, version=version,
  File "django_redis/client/default.py", line 203, in get
    value = client.get(key)
  File "redis/client.py", line 976, in get
    return self.execute_command('GET', name)
  File "elasticapm/instrumentation/packages/base.py", line 210, in call_if_sampling
    return self.call(module, method, wrapped, instance, args, kwargs)
  File "elasticapm/instrumentation/packages/redis.py", line 66, in call
    return wrapped(*args, **kwargs)
  File "redis/client.py", line 667, in execute_command
    connection.send_command(*args)
  File "redis/connection.py", line 610, in send_command
    self.send_packed_command(self.pack_command(*args))
  File "elasticapm/instrumentation/packages/base.py", line 210, in call_if_sampling
    return self.call(module, method, wrapped, instance, args, kwargs)
  File "elasticapm/instrumentation/packages/redis.py", line 90, in call
    port = int(instance.port) if instance.port else None
```


Discussion:
@kvspb thanks for raising this! I'll get a fix released ASAP. In the mean time, you can downgrade to 5.4.3.

Resolving patch:
diff --git a/elasticapm/instrumentation/packages/redis.py b/elasticapm/instrumentation/packages/redis.py
--- a/elasticapm/instrumentation/packages/redis.py
+++ b/elasticapm/instrumentation/packages/redis.py
@@ -87,11 +87,16 @@ class RedisConnectionInstrumentation(AbstractInstrumentedModule):
     def call(self, module, method, wrapped, instance, args, kwargs):
         span = execution_context.get_span()
         if span and span.subtype == "redis":
-            port = int(instance.port) if instance.port else None
-            destination_info = {
-                "address": instance.host,
-                "port": port,
-                "service": {"name": "redis", "resource": "redis", "type": "db"},
-            }
-            span.context["destination"] = destination_info
+            span.context["destination"] = get_destination_info(instance)
         return wrapped(*args, **kwargs)
+
+
+def get_destination_info(connection):
+    destination_info = {"service": {"name": "redis", "resource": "redis", "type": "db"}}
+    if hasattr(connection, "port"):
+        destination_info["port"] = connection.port
+        destination_info["address"] = connection.host
+    elif hasattr(connection, "path"):
+        destination_info["port"] = None
+        destination_info["address"] = "unix://" + connection.path
+    return destination_info


Test patch:
diff --git a/tests/instrumentation/redis_tests.py b/tests/instrumentation/redis_tests.py
--- a/tests/instrumentation/redis_tests.py
+++ b/tests/instrumentation/redis_tests.py
@@ -30,15 +30,16 @@
 
 import pytest  # isort:skip
 
-pytest.importorskip("redis")  # isort:skip
+redis = pytest.importorskip("redis")  # isort:skip
 
 import os
 from functools import partial
 
-import redis
+from redis import UnixDomainSocketConnection
 from redis.client import StrictRedis
 
 from elasticapm.conf.constants import TRANSACTION
+from elasticapm.instrumentation.packages.redis import get_destination_info
 from elasticapm.traces import capture_span
 
 pytestmark = [pytest.mark.redis]
@@ -155,3 +156,10 @@ def test_redis_client(instrument, elasticapm_client, redis_conn):
     assert spans[2]["type"] == "test"
 
     assert len(spans) == 3
+
+
+def test_unix_domain_socket_connection_destination_info():
+    conn = UnixDomainSocketConnection("/some/path")
+    destination_info = get_destination_info(conn)
+    assert destination_info["port"] is None
+    assert destination_info["address"] == "unix:///some/path"