prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <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
  ```
  
  </issue>
  <code>
  [start of elasticapm/instrumentation/packages/redis.py]
  1 #  BSD 3-Clause License
  2 #
  3 #  Copyright (c) 2019, Elasticsearch BV
  4 #  All rights reserved.
  5 #
  6 #  Redistribution and use in source and binary forms, with or without
  7 #  modification, are permitted provided that the following conditions are met:
  8 #
  9 #  * Redistributions of source code must retain the above copyright notice, this
  10 #    list of conditions and the following disclaimer.
  11 #
  12 #  * Redistributions in binary form must reproduce the above copyright notice,
  13 #    this list of conditions and the following disclaimer in the documentation
  14 #    and/or other materials provided with the distribution.
  15 #
  16 #  * Neither the name of the copyright holder nor the names of its
  17 #    contributors may be used to endorse or promote products derived from
  18 #    this software without specific prior written permission.
  19 #
  20 #  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  21 #  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  22 #  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  23 #  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  24 #  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  25 #  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  26 #  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  27 #  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  28 #  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  29 #  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30 
  31 from __future__ import absolute_import
  32 
  33 from elasticapm.instrumentation.packages.base import AbstractInstrumentedModule
  34 from elasticapm.traces import capture_span, execution_context
  35 
  36 
  37 class Redis3CheckMixin(object):
  38     instrument_list_3 = []
  39     instrument_list = []
  40 
  41     def get_instrument_list(self):
  42         try:
  43             from redis import VERSION
  44 
  45             if VERSION[0] >= 3:
  46                 return self.instrument_list_3
  47             return self.instrument_list
  48         except ImportError:
  49             return self.instrument_list
  50 
  51 
  52 class RedisInstrumentation(Redis3CheckMixin, AbstractInstrumentedModule):
  53     name = "redis"
  54 
  55     # no need to instrument StrictRedis in redis-py >= 3.0
  56     instrument_list_3 = [("redis.client", "Redis.execute_command")]
  57     instrument_list = [("redis.client", "Redis.execute_command"), ("redis.client", "StrictRedis.execute_command")]
  58 
  59     def call(self, module, method, wrapped, instance, args, kwargs):
  60         if len(args) > 0:
  61             wrapped_name = str(args[0])
  62         else:
  63             wrapped_name = self.get_wrapped_name(wrapped, instance, method)
  64 
  65         with capture_span(wrapped_name, span_type="db", span_subtype="redis", span_action="query", leaf=True):
  66             return wrapped(*args, **kwargs)
  67 
  68 
  69 class RedisPipelineInstrumentation(Redis3CheckMixin, AbstractInstrumentedModule):
  70     name = "redis"
  71 
  72     # BasePipeline has been renamed to Pipeline in redis-py 3
  73     instrument_list_3 = [("redis.client", "Pipeline.execute")]
  74     instrument_list = [("redis.client", "BasePipeline.execute")]
  75 
  76     def call(self, module, method, wrapped, instance, args, kwargs):
  77         wrapped_name = self.get_wrapped_name(wrapped, instance, method)
  78         with capture_span(wrapped_name, span_type="db", span_subtype="redis", span_action="query", leaf=True):
  79             return wrapped(*args, **kwargs)
  80 
  81 
  82 class RedisConnectionInstrumentation(AbstractInstrumentedModule):
  83     name = "redis"
  84 
  85     instrument_list = (("redis.connection", "Connection.send_packed_command"),)
  86 
  87     def call(self, module, method, wrapped, instance, args, kwargs):
  88         span = execution_context.get_span()
  89         if span and span.subtype == "redis":
  90             port = int(instance.port) if instance.port else None
  91             destination_info = {
  92                 "address": instance.host,
  93                 "port": port,
  94                 "service": {"name": "redis", "resource": "redis", "type": "db"},
  95             }
  96             span.context["destination"] = destination_info
  97         return wrapped(*args, **kwargs)
  98
  [end of elasticapm/instrumentation/packages/redis.py]
  </code>
  
  I need you to solve this issue by generating a single patch file that I can apply directly to this repository using git apply. Please respond with a single patch file in the following format.
  <patch>
  diff --git a/file.py b/file.py
  --- a/file.py
  +++ b/file.py
  @@ -1,27 +1,35 @@
   def euclidean(a, b):
  -    while b:
  -        a, b = b, a % b
  -    return a
  +    if b == 0:
  +        return a
  +    return euclidean(b, a % b)
   
   
   def bresenham(x0, y0, x1, y1):
       points = []
       dx = abs(x1 - x0)
       dy = abs(y1 - y0)
  -    sx = 1 if x0 < x1 else -1
  -    sy = 1 if y0 < y1 else -1
  -    err = dx - dy
  +    x, y = x0, y0
  +    sx = -1 if x0 > x1 else 1
  +    sy = -1 if y0 > y1 else 1
   
  -    while True:
  -        points.append((x0, y0))
  -        if x0 == x1 and y0 == y1:
  -            break
  -        e2 = 2 * err
  -        if e2 > -dy:
  -            err -= dy
  -            x0 += sx
  -        if e2 < dx:
  -            err += dx
  -            y0 += sy
  +    if dx > dy:
  +        err = dx / 2.0
  +        while x != x1:
  +            points.append((x, y))
  +            err -= dy
  +            if err < 0:
  +                y += sy
  +                err += dx
  +            x += sx
  +    else:
  +        err = dy / 2.0
  +        while y != y1:
  +            points.append((x, y))
  +            err -= dx
  +            if err < 0:
  +                x += sx
  +                err += dy
  +            y += sy
  +
  +    points.append((x, y))
       return points
  
  </patch>
golden_diff: 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 @@
       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
  
verification_info: {"golden_diff": "diff --git a/elasticapm/instrumentation/packages/redis.py b/elasticapm/instrumentation/packages/redis.py\n--- a/elasticapm/instrumentation/packages/redis.py\n+++ b/elasticapm/instrumentation/packages/redis.py\n@@ -87,11 +87,16 @@\n     def call(self, module, method, wrapped, instance, args, kwargs):\n         span = execution_context.get_span()\n         if span and span.subtype == \"redis\":\n-            port = int(instance.port) if instance.port else None\n-            destination_info = {\n-                \"address\": instance.host,\n-                \"port\": port,\n-                \"service\": {\"name\": \"redis\", \"resource\": \"redis\", \"type\": \"db\"},\n-            }\n-            span.context[\"destination\"] = destination_info\n+            span.context[\"destination\"] = get_destination_info(instance)\n         return wrapped(*args, **kwargs)\n+\n+\n+def get_destination_info(connection):\n+    destination_info = {\"service\": {\"name\": \"redis\", \"resource\": \"redis\", \"type\": \"db\"}}\n+    if hasattr(connection, \"port\"):\n+        destination_info[\"port\"] = connection.port\n+        destination_info[\"address\"] = connection.host\n+    elif hasattr(connection, \"path\"):\n+        destination_info[\"port\"] = None\n+        destination_info[\"address\"] = \"unix://\" + connection.path\n+    return destination_info\n", "issue": "'UnixDomainSocketConnection' object has no attribute 'port'\nAttributeError: 'UnixDomainSocketConnection' object has no attribute 'port'\r\nelastic-apm==5.5.1\r\n\r\n```\r\n  File \"django_redis/cache.py\", line 32, in _decorator\r\n    return method(self, *args, **kwargs)\r\n  File \"django_redis/cache.py\", line 80, in get\r\n    return self.client.get(key, default=default, version=version,\r\n  File \"django_redis/client/default.py\", line 203, in get\r\n    value = client.get(key)\r\n  File \"redis/client.py\", line 976, in get\r\n    return self.execute_command('GET', name)\r\n  File \"elasticapm/instrumentation/packages/base.py\", line 210, in call_if_sampling\r\n    return self.call(module, method, wrapped, instance, args, kwargs)\r\n  File \"elasticapm/instrumentation/packages/redis.py\", line 66, in call\r\n    return wrapped(*args, **kwargs)\r\n  File \"redis/client.py\", line 667, in execute_command\r\n    connection.send_command(*args)\r\n  File \"redis/connection.py\", line 610, in send_command\r\n    self.send_packed_command(self.pack_command(*args))\r\n  File \"elasticapm/instrumentation/packages/base.py\", line 210, in call_if_sampling\r\n    return self.call(module, method, wrapped, instance, args, kwargs)\r\n  File \"elasticapm/instrumentation/packages/redis.py\", line 90, in call\r\n    port = int(instance.port) if instance.port else None\r\n```\n", "before_files": [{"content": "#  BSD 3-Clause License\n#\n#  Copyright (c) 2019, Elasticsearch BV\n#  All rights reserved.\n#\n#  Redistribution and use in source and binary forms, with or without\n#  modification, are permitted provided that the following conditions are met:\n#\n#  * Redistributions of source code must retain the above copyright notice, this\n#    list of conditions and the following disclaimer.\n#\n#  * Redistributions in binary form must reproduce the above copyright notice,\n#    this list of conditions and the following disclaimer in the documentation\n#    and/or other materials provided with the distribution.\n#\n#  * Neither the name of the copyright holder nor the names of its\n#    contributors may be used to endorse or promote products derived from\n#    this software without specific prior written permission.\n#\n#  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n#  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n#  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n#  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\n#  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n#  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n#  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n#  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\n#  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n#  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nfrom __future__ import absolute_import\n\nfrom elasticapm.instrumentation.packages.base import AbstractInstrumentedModule\nfrom elasticapm.traces import capture_span, execution_context\n\n\nclass Redis3CheckMixin(object):\n    instrument_list_3 = []\n    instrument_list = []\n\n    def get_instrument_list(self):\n        try:\n            from redis import VERSION\n\n            if VERSION[0] >= 3:\n                return self.instrument_list_3\n            return self.instrument_list\n        except ImportError:\n            return self.instrument_list\n\n\nclass RedisInstrumentation(Redis3CheckMixin, AbstractInstrumentedModule):\n    name = \"redis\"\n\n    # no need to instrument StrictRedis in redis-py >= 3.0\n    instrument_list_3 = [(\"redis.client\", \"Redis.execute_command\")]\n    instrument_list = [(\"redis.client\", \"Redis.execute_command\"), (\"redis.client\", \"StrictRedis.execute_command\")]\n\n    def call(self, module, method, wrapped, instance, args, kwargs):\n        if len(args) > 0:\n            wrapped_name = str(args[0])\n        else:\n            wrapped_name = self.get_wrapped_name(wrapped, instance, method)\n\n        with capture_span(wrapped_name, span_type=\"db\", span_subtype=\"redis\", span_action=\"query\", leaf=True):\n            return wrapped(*args, **kwargs)\n\n\nclass RedisPipelineInstrumentation(Redis3CheckMixin, AbstractInstrumentedModule):\n    name = \"redis\"\n\n    # BasePipeline has been renamed to Pipeline in redis-py 3\n    instrument_list_3 = [(\"redis.client\", \"Pipeline.execute\")]\n    instrument_list = [(\"redis.client\", \"BasePipeline.execute\")]\n\n    def call(self, module, method, wrapped, instance, args, kwargs):\n        wrapped_name = self.get_wrapped_name(wrapped, instance, method)\n        with capture_span(wrapped_name, span_type=\"db\", span_subtype=\"redis\", span_action=\"query\", leaf=True):\n            return wrapped(*args, **kwargs)\n\n\nclass RedisConnectionInstrumentation(AbstractInstrumentedModule):\n    name = \"redis\"\n\n    instrument_list = ((\"redis.connection\", \"Connection.send_packed_command\"),)\n\n    def call(self, module, method, wrapped, instance, args, kwargs):\n        span = execution_context.get_span()\n        if span and span.subtype == \"redis\":\n            port = int(instance.port) if instance.port else None\n            destination_info = {\n                \"address\": instance.host,\n                \"port\": port,\n                \"service\": {\"name\": \"redis\", \"resource\": \"redis\", \"type\": \"db\"},\n            }\n            span.context[\"destination\"] = destination_info\n        return wrapped(*args, **kwargs)\n", "path": "elasticapm/instrumentation/packages/redis.py"}]}