prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  [marathon] 404 when the configured URL has a trailing slash
  The web server powering Marathon apparently doesn't like double slashes, so dd-agent is getting a 404 back when trying to hit the /v2/apps endpoint.
  
  e.g., with this configuration:
  
  ```
  instances:
  - url: "http://10.0.10.1:8080/"
  ```
  
  The agent reports this error:
  
  ```
  instance #0 [ERROR]: Exception('Got 404 when hitting http://10.0.10.1:8080/',)
  ```
  
  This works fine if you leave off the trailing slash. 
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `checks.d/marathon.py`
  Content:
  ```
  1 # project
  2 from checks import AgentCheck
  3 
  4 # 3rd party
  5 import requests
  6 
  7 class Marathon(AgentCheck):
  8 
  9     DEFAULT_TIMEOUT = 5
  10     SERVICE_CHECK_NAME = 'marathon.can_connect'
  11 
  12     APP_METRICS = [
  13         'backoffFactor',
  14         'backoffSeconds',
  15         'cpus',
  16         'dist',
  17         'instances',
  18         'mem',
  19         'taskRateLimit',
  20         'tasksRunning',
  21         'tasksStaged'
  22     ]
  23 
  24     def check(self, instance):
  25         if 'url' not in instance:
  26             raise Exception('Marathon instance missing "url" value.')
  27 
  28         # Load values from the instance config
  29         url = instance['url']
  30         instance_tags = instance.get('tags', [])
  31         default_timeout = self.init_config.get('default_timeout', self.DEFAULT_TIMEOUT)
  32         timeout = float(instance.get('timeout', default_timeout))
  33 
  34         response = self.get_json(url + "/v2/apps", timeout)
  35         if response is not None:
  36             self.gauge('marathon.apps', len(response['apps']), tags=instance_tags)
  37             for app in response['apps']:
  38                 tags = ['app_id:' + app['id'], 'version:' + app['version']] + instance_tags
  39                 for attr in self.APP_METRICS:
  40                     if attr in app:
  41                         self.gauge('marathon.' + attr, app[attr], tags=tags)
  42                 versions_reply = self.get_json(url + "/v2/apps/" + app['id'] + "/versions", timeout)
  43                 if versions_reply is not None:
  44                     self.gauge('marathon.versions', len(versions_reply['versions']), tags=tags)
  45 
  46     def get_json(self, url, timeout):
  47         try:
  48             r = requests.get(url, timeout=timeout)
  49             r.raise_for_status()
  50         except requests.exceptions.Timeout:
  51             # If there's a timeout
  52             self.service_check(self.SERVICE_CHECK_NAME, AgentCheck.CRITICAL,
  53                 message='%s timed out after %s seconds.' % (url, timeout),
  54                 tags = ["url:{}".format(url)])
  55             raise Exception("Timeout when hitting %s" % url)
  56 
  57         except requests.exceptions.HTTPError:
  58             self.service_check(self.SERVICE_CHECK_NAME, AgentCheck.CRITICAL,
  59                 message='%s returned a status of %s' % (url, r.status_code),
  60                 tags = ["url:{}".format(url)])
  61             raise Exception("Got %s when hitting %s" % (r.status_code, url))
  62 
  63         else:
  64             self.service_check(self.SERVICE_CHECK_NAME, AgentCheck.OK,
  65                 tags = ["url:{}".format(url)]
  66             )
  67 
  68         return r.json()
  69
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/checks.d/marathon.py b/checks.d/marathon.py
  --- a/checks.d/marathon.py
  +++ b/checks.d/marathon.py
  @@ -1,3 +1,6 @@
  +# stdlib
  +from urlparse import urljoin
  +
   # project
   from checks import AgentCheck
   
  @@ -31,7 +34,7 @@
           default_timeout = self.init_config.get('default_timeout', self.DEFAULT_TIMEOUT)
           timeout = float(instance.get('timeout', default_timeout))
   
  -        response = self.get_json(url + "/v2/apps", timeout)
  +        response = self.get_json(urljoin(url, "/v2/apps"), timeout)
           if response is not None:
               self.gauge('marathon.apps', len(response['apps']), tags=instance_tags)
               for app in response['apps']:
  @@ -39,7 +42,10 @@
                   for attr in self.APP_METRICS:
                       if attr in app:
                           self.gauge('marathon.' + attr, app[attr], tags=tags)
  -                versions_reply = self.get_json(url + "/v2/apps/" + app['id'] + "/versions", timeout)
  +
  +                query_url = urljoin(url, "/v2/apps/{0}/versions".format(app['id']))
  +                versions_reply = self.get_json(query_url, timeout)
  +
                   if versions_reply is not None:
                       self.gauge('marathon.versions', len(versions_reply['versions']), tags=tags)
  
verification_info: {"golden_diff": "diff --git a/checks.d/marathon.py b/checks.d/marathon.py\n--- a/checks.d/marathon.py\n+++ b/checks.d/marathon.py\n@@ -1,3 +1,6 @@\n+# stdlib\n+from urlparse import urljoin\n+\n # project\n from checks import AgentCheck\n \n@@ -31,7 +34,7 @@\n         default_timeout = self.init_config.get('default_timeout', self.DEFAULT_TIMEOUT)\n         timeout = float(instance.get('timeout', default_timeout))\n \n-        response = self.get_json(url + \"/v2/apps\", timeout)\n+        response = self.get_json(urljoin(url, \"/v2/apps\"), timeout)\n         if response is not None:\n             self.gauge('marathon.apps', len(response['apps']), tags=instance_tags)\n             for app in response['apps']:\n@@ -39,7 +42,10 @@\n                 for attr in self.APP_METRICS:\n                     if attr in app:\n                         self.gauge('marathon.' + attr, app[attr], tags=tags)\n-                versions_reply = self.get_json(url + \"/v2/apps/\" + app['id'] + \"/versions\", timeout)\n+\n+                query_url = urljoin(url, \"/v2/apps/{0}/versions\".format(app['id']))\n+                versions_reply = self.get_json(query_url, timeout)\n+\n                 if versions_reply is not None:\n                     self.gauge('marathon.versions', len(versions_reply['versions']), tags=tags)\n", "issue": "[marathon] 404 when the configured URL has a trailing slash\nThe web server powering Marathon apparently doesn't like double slashes, so dd-agent is getting a 404 back when trying to hit the /v2/apps endpoint.\n\ne.g., with this configuration:\n\n```\ninstances:\n- url: \"http://10.0.10.1:8080/\"\n```\n\nThe agent reports this error:\n\n```\ninstance #0 [ERROR]: Exception('Got 404 when hitting http://10.0.10.1:8080/',)\n```\n\nThis works fine if you leave off the trailing slash. \n\n", "before_files": [{"content": "# project\nfrom checks import AgentCheck\n\n# 3rd party\nimport requests\n\nclass Marathon(AgentCheck):\n\n    DEFAULT_TIMEOUT = 5\n    SERVICE_CHECK_NAME = 'marathon.can_connect'\n\n    APP_METRICS = [\n        'backoffFactor',\n        'backoffSeconds',\n        'cpus',\n        'dist',\n        'instances',\n        'mem',\n        'taskRateLimit',\n        'tasksRunning',\n        'tasksStaged'\n    ]\n\n    def check(self, instance):\n        if 'url' not in instance:\n            raise Exception('Marathon instance missing \"url\" value.')\n\n        # Load values from the instance config\n        url = instance['url']\n        instance_tags = instance.get('tags', [])\n        default_timeout = self.init_config.get('default_timeout', self.DEFAULT_TIMEOUT)\n        timeout = float(instance.get('timeout', default_timeout))\n\n        response = self.get_json(url + \"/v2/apps\", timeout)\n        if response is not None:\n            self.gauge('marathon.apps', len(response['apps']), tags=instance_tags)\n            for app in response['apps']:\n                tags = ['app_id:' + app['id'], 'version:' + app['version']] + instance_tags\n                for attr in self.APP_METRICS:\n                    if attr in app:\n                        self.gauge('marathon.' + attr, app[attr], tags=tags)\n                versions_reply = self.get_json(url + \"/v2/apps/\" + app['id'] + \"/versions\", timeout)\n                if versions_reply is not None:\n                    self.gauge('marathon.versions', len(versions_reply['versions']), tags=tags)\n\n    def get_json(self, url, timeout):\n        try:\n            r = requests.get(url, timeout=timeout)\n            r.raise_for_status()\n        except requests.exceptions.Timeout:\n            # If there's a timeout\n            self.service_check(self.SERVICE_CHECK_NAME, AgentCheck.CRITICAL,\n                message='%s timed out after %s seconds.' % (url, timeout),\n                tags = [\"url:{}\".format(url)])\n            raise Exception(\"Timeout when hitting %s\" % url)\n\n        except requests.exceptions.HTTPError:\n            self.service_check(self.SERVICE_CHECK_NAME, AgentCheck.CRITICAL,\n                message='%s returned a status of %s' % (url, r.status_code),\n                tags = [\"url:{}\".format(url)])\n            raise Exception(\"Got %s when hitting %s\" % (r.status_code, url))\n\n        else:\n            self.service_check(self.SERVICE_CHECK_NAME, AgentCheck.OK,\n                tags = [\"url:{}\".format(url)]\n            )\n\n        return r.json()\n", "path": "checks.d/marathon.py"}], "after_files": [{"content": "# stdlib\nfrom urlparse import urljoin\n\n# project\nfrom checks import AgentCheck\n\n# 3rd party\nimport requests\n\nclass Marathon(AgentCheck):\n\n    DEFAULT_TIMEOUT = 5\n    SERVICE_CHECK_NAME = 'marathon.can_connect'\n\n    APP_METRICS = [\n        'backoffFactor',\n        'backoffSeconds',\n        'cpus',\n        'dist',\n        'instances',\n        'mem',\n        'taskRateLimit',\n        'tasksRunning',\n        'tasksStaged'\n    ]\n\n    def check(self, instance):\n        if 'url' not in instance:\n            raise Exception('Marathon instance missing \"url\" value.')\n\n        # Load values from the instance config\n        url = instance['url']\n        instance_tags = instance.get('tags', [])\n        default_timeout = self.init_config.get('default_timeout', self.DEFAULT_TIMEOUT)\n        timeout = float(instance.get('timeout', default_timeout))\n\n        response = self.get_json(urljoin(url, \"/v2/apps\"), timeout)\n        if response is not None:\n            self.gauge('marathon.apps', len(response['apps']), tags=instance_tags)\n            for app in response['apps']:\n                tags = ['app_id:' + app['id'], 'version:' + app['version']] + instance_tags\n                for attr in self.APP_METRICS:\n                    if attr in app:\n                        self.gauge('marathon.' + attr, app[attr], tags=tags)\n\n                query_url = urljoin(url, \"/v2/apps/{0}/versions\".format(app['id']))\n                versions_reply = self.get_json(query_url, timeout)\n\n                if versions_reply is not None:\n                    self.gauge('marathon.versions', len(versions_reply['versions']), tags=tags)\n\n    def get_json(self, url, timeout):\n        try:\n            r = requests.get(url, timeout=timeout)\n            r.raise_for_status()\n        except requests.exceptions.Timeout:\n            # If there's a timeout\n            self.service_check(self.SERVICE_CHECK_NAME, AgentCheck.CRITICAL,\n                message='%s timed out after %s seconds.' % (url, timeout),\n                tags = [\"url:{}\".format(url)])\n            raise Exception(\"Timeout when hitting %s\" % url)\n\n        except requests.exceptions.HTTPError:\n            self.service_check(self.SERVICE_CHECK_NAME, AgentCheck.CRITICAL,\n                message='%s returned a status of %s' % (url, r.status_code),\n                tags = [\"url:{}\".format(url)])\n            raise Exception(\"Got %s when hitting %s\" % (r.status_code, url))\n\n        else:\n            self.service_check(self.SERVICE_CHECK_NAME, AgentCheck.OK,\n                tags = [\"url:{}\".format(url)]\n            )\n\n        return r.json()\n", "path": "checks.d/marathon.py"}]}