prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  Track user agent for metrics
  **Describe the feature you'd like and what it will do**
  In HS v2.5.4, we don't track user_agent in our metrics. This makes it difficult to tell when requests to HS are occurring via direct UI interactions, or via other tools like hsclient.
  
  
  **Why is this feature important?**
  We need more insight into how HS' ecosystem of tools are being used. This information should drive our continued development on existing tools and our consideration of additions for future use.
  
  **Is your feature request related to a problem? Please describe.**
  It is difficult to make decisions without information.
  
  
  </issue>
  <code>
  [start of hs_tracking/utils.py]
  1 import robot_detection
  2 from ipware.ip import get_ip
  3 from hs_tools_resource.models import RequestUrlBase, RequestUrlBaseAggregation, RequestUrlBaseFile
  4 from urllib.parse import urlparse
  5 
  6 
  7 def get_client_ip(request):
  8     return get_ip(request)
  9 
  10 
  11 def get_user_type(session):
  12     try:
  13         user = session.visitor.user
  14         usertype = user.userprofile.user_type
  15     except AttributeError:
  16         usertype = None
  17     return usertype
  18 
  19 
  20 def get_user_email_domain(session):
  21     try:
  22         user = session.visitor.user
  23         emaildomain = user.email.split('@')[-1]
  24     except AttributeError:
  25         emaildomain = None
  26     return emaildomain
  27 
  28 
  29 def get_user_email_tld(session, emaildomain=None):
  30     try:
  31         if not emaildomain:
  32             emaildomain = get_user_email_domain(session)
  33         if emaildomain:
  34             shortdomain = '.'.join(emaildomain.split('.')[1:])
  35             return shortdomain
  36     except AttributeError:
  37         return None
  38 
  39 
  40 def is_human(user_agent):
  41     if robot_detection.is_robot(user_agent):
  42         return False
  43     return True
  44 
  45 
  46 def get_std_log_fields(request, session=None):
  47     """ returns a standard set of metadata that to each receiver function.
  48     This ensures that all activities are reporting a consistent set of metrics
  49     """
  50     user_type = None
  51     user_email_tld = None
  52     full_domain = None
  53     if session is not None:
  54         user_type = get_user_type(session)
  55         full_domain = get_user_email_domain(session)
  56         user_email_tld = get_user_email_tld(session, full_domain)
  57 
  58     return {
  59         'user_ip': get_client_ip(request),
  60         'user_type': user_type,
  61         'user_email_domain': user_email_tld,
  62         'user_email_domain_full': full_domain
  63     }
  64 
  65 
  66 def authentic_redirect_url(url):
  67     """ Validates a url scheme and netloc is in an existing web app
  68     :param url: String of a url
  69     :return: Boolean, True if the url exists in a web app
  70     """
  71     if not url:
  72         return False
  73     u = urlparse(url)
  74     url_base = "{}://{}".format(u.scheme, u.netloc)
  75     return RequestUrlBase.objects.filter(value__startswith=url_base).exists() \
  76         or RequestUrlBaseAggregation.objects.filter(value__startswith=url_base).exists() \
  77         or RequestUrlBaseFile.objects.filter(value__startswith=url_base).exists()
  78
  [end of hs_tracking/utils.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/hs_tracking/utils.py b/hs_tracking/utils.py
  --- a/hs_tracking/utils.py
  +++ b/hs_tracking/utils.py
  @@ -47,6 +47,12 @@
       """ returns a standard set of metadata that to each receiver function.
       This ensures that all activities are reporting a consistent set of metrics
       """
  +    try:
  +        user_agent = request.META['HTTP_USER_AGENT']
  +        human = is_human(user_agent)
  +    except KeyError:
  +        user_agent = None
  +        human = None
       user_type = None
       user_email_tld = None
       full_domain = None
  @@ -59,7 +65,9 @@
           'user_ip': get_client_ip(request),
           'user_type': user_type,
           'user_email_domain': user_email_tld,
  -        'user_email_domain_full': full_domain
  +        'user_email_domain_full': full_domain,
  +        'is_human': human,
  +        'user_agent': user_agent
       }
  
verification_info: {"golden_diff": "diff --git a/hs_tracking/utils.py b/hs_tracking/utils.py\n--- a/hs_tracking/utils.py\n+++ b/hs_tracking/utils.py\n@@ -47,6 +47,12 @@\n     \"\"\" returns a standard set of metadata that to each receiver function.\n     This ensures that all activities are reporting a consistent set of metrics\n     \"\"\"\n+    try:\n+        user_agent = request.META['HTTP_USER_AGENT']\n+        human = is_human(user_agent)\n+    except KeyError:\n+        user_agent = None\n+        human = None\n     user_type = None\n     user_email_tld = None\n     full_domain = None\n@@ -59,7 +65,9 @@\n         'user_ip': get_client_ip(request),\n         'user_type': user_type,\n         'user_email_domain': user_email_tld,\n-        'user_email_domain_full': full_domain\n+        'user_email_domain_full': full_domain,\n+        'is_human': human,\n+        'user_agent': user_agent\n     }\n", "issue": "Track user agent for metrics\n**Describe the feature you'd like and what it will do**\r\nIn HS v2.5.4, we don't track user_agent in our metrics. This makes it difficult to tell when requests to HS are occurring via direct UI interactions, or via other tools like hsclient.\r\n\r\n\r\n**Why is this feature important?**\r\nWe need more insight into how HS' ecosystem of tools are being used. This information should drive our continued development on existing tools and our consideration of additions for future use.\r\n\r\n**Is your feature request related to a problem? Please describe.**\r\nIt is difficult to make decisions without information.\r\n\n", "before_files": [{"content": "import robot_detection\nfrom ipware.ip import get_ip\nfrom hs_tools_resource.models import RequestUrlBase, RequestUrlBaseAggregation, RequestUrlBaseFile\nfrom urllib.parse import urlparse\n\n\ndef get_client_ip(request):\n    return get_ip(request)\n\n\ndef get_user_type(session):\n    try:\n        user = session.visitor.user\n        usertype = user.userprofile.user_type\n    except AttributeError:\n        usertype = None\n    return usertype\n\n\ndef get_user_email_domain(session):\n    try:\n        user = session.visitor.user\n        emaildomain = user.email.split('@')[-1]\n    except AttributeError:\n        emaildomain = None\n    return emaildomain\n\n\ndef get_user_email_tld(session, emaildomain=None):\n    try:\n        if not emaildomain:\n            emaildomain = get_user_email_domain(session)\n        if emaildomain:\n            shortdomain = '.'.join(emaildomain.split('.')[1:])\n            return shortdomain\n    except AttributeError:\n        return None\n\n\ndef is_human(user_agent):\n    if robot_detection.is_robot(user_agent):\n        return False\n    return True\n\n\ndef get_std_log_fields(request, session=None):\n    \"\"\" returns a standard set of metadata that to each receiver function.\n    This ensures that all activities are reporting a consistent set of metrics\n    \"\"\"\n    user_type = None\n    user_email_tld = None\n    full_domain = None\n    if session is not None:\n        user_type = get_user_type(session)\n        full_domain = get_user_email_domain(session)\n        user_email_tld = get_user_email_tld(session, full_domain)\n\n    return {\n        'user_ip': get_client_ip(request),\n        'user_type': user_type,\n        'user_email_domain': user_email_tld,\n        'user_email_domain_full': full_domain\n    }\n\n\ndef authentic_redirect_url(url):\n    \"\"\" Validates a url scheme and netloc is in an existing web app\n    :param url: String of a url\n    :return: Boolean, True if the url exists in a web app\n    \"\"\"\n    if not url:\n        return False\n    u = urlparse(url)\n    url_base = \"{}://{}\".format(u.scheme, u.netloc)\n    return RequestUrlBase.objects.filter(value__startswith=url_base).exists() \\\n        or RequestUrlBaseAggregation.objects.filter(value__startswith=url_base).exists() \\\n        or RequestUrlBaseFile.objects.filter(value__startswith=url_base).exists()\n", "path": "hs_tracking/utils.py"}]}