prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Couchbase service check do not send tags on OK status
  Missing a `tags=service_check_tags` on line:
  https://github.com/DataDog/dd-agent/blob/master/checks.d/couchbase.py#L104
  
  Pretty small fix.
  
  
  --- 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/couchbase.py`
  Content:
  ```
  1 # stdlib
  2 import re
  3 
  4 # 3rd party
  5 import requests
  6 
  7 # project
  8 from checks import AgentCheck
  9 from util import headers
  10 
  11 # Constants
  12 COUCHBASE_STATS_PATH = '/pools/default'
  13 DEFAULT_TIMEOUT = 10
  14 
  15 
  16 class Couchbase(AgentCheck):
  17     """Extracts stats from Couchbase via its REST API
  18     http://docs.couchbase.com/couchbase-manual-2.0/#using-the-rest-api
  19     """
  20     SERVICE_CHECK_NAME = 'couchbase.can_connect'
  21 
  22     def _create_metrics(self, data, tags=None):
  23         storage_totals = data['stats']['storageTotals']
  24         for key, storage_type in storage_totals.items():
  25             for metric_name, val in storage_type.items():
  26                 if val is not None:
  27                     metric_name = '.'.join(['couchbase', key, self.camel_case_to_joined_lower(metric_name)])
  28                     self.gauge(metric_name, val, tags=tags)
  29 
  30         for bucket_name, bucket_stats in data['buckets'].items():
  31             for metric_name, val in bucket_stats.items():
  32                 if val is not None:
  33                     metric_name = '.'.join(['couchbase', 'by_bucket', self.camel_case_to_joined_lower(metric_name)])
  34                     metric_tags = list(tags)
  35                     metric_tags.append('bucket:%s' % bucket_name)
  36                     self.gauge(metric_name, val[0], tags=metric_tags, device_name=bucket_name)
  37 
  38         for node_name, node_stats in data['nodes'].items():
  39             for metric_name, val in node_stats['interestingStats'].items():
  40                 if val is not None:
  41                     metric_name = '.'.join(['couchbase', 'by_node', self.camel_case_to_joined_lower(metric_name)])
  42                     metric_tags = list(tags)
  43                     metric_tags.append('node:%s' % node_name)
  44                     self.gauge(metric_name, val, tags=metric_tags, device_name=node_name)
  45 
  46 
  47     def _get_stats(self, url, instance):
  48         """ Hit a given URL and return the parsed json. """
  49         self.log.debug('Fetching Couchbase stats at url: %s' % url)
  50 
  51         timeout = float(instance.get('timeout', DEFAULT_TIMEOUT))
  52 
  53         auth = None
  54         if 'user' in instance and 'password' in instance:
  55             auth = (instance['user'], instance['password'])
  56 
  57         r = requests.get(url, auth=auth, headers=headers(self.agentConfig),
  58             timeout=timeout)
  59         r.raise_for_status()
  60         return r.json()
  61 
  62     def check(self, instance):
  63         server = instance.get('server', None)
  64         if server is None:
  65             raise Exception("The server must be specified")
  66         tags = instance.get('tags', [])
  67         # Clean up tags in case there was a None entry in the instance
  68         # e.g. if the yaml contains tags: but no actual tags
  69         if tags is None:
  70             tags = []
  71         else:
  72             tags = list(set(tags))
  73         tags.append('instance:%s' % server)
  74         data = self.get_data(server, instance)
  75         self._create_metrics(data, tags=list(set(tags)))
  76 
  77     def get_data(self, server, instance):
  78         # The dictionary to be returned.
  79         couchbase = {
  80             'stats': None,
  81             'buckets': {},
  82             'nodes': {}
  83         }
  84 
  85         # build couchbase stats entry point
  86         url = '%s%s' % (server, COUCHBASE_STATS_PATH)
  87 
  88         # Fetch initial stats and capture a service check based on response.
  89         service_check_tags = ['instance:%s' % server]
  90         try:
  91             overall_stats = self._get_stats(url, instance)
  92             # No overall stats? bail out now
  93             if overall_stats is None:
  94                 raise Exception("No data returned from couchbase endpoint: %s" % url)
  95         except requests.exceptions.HTTPError as e:
  96             self.service_check(self.SERVICE_CHECK_NAME, AgentCheck.CRITICAL,
  97                 tags=service_check_tags, message=str(e.message))
  98             raise
  99         except Exception as e:
  100             self.service_check(self.SERVICE_CHECK_NAME, AgentCheck.CRITICAL,
  101                 tags=service_check_tags, message=str(e))
  102             raise
  103         else:
  104             self.service_check(self.SERVICE_CHECK_NAME, AgentCheck.OK)
  105 
  106         couchbase['stats'] = overall_stats
  107 
  108         nodes = overall_stats['nodes']
  109 
  110         # Next, get all the nodes
  111         if nodes is not None:
  112             for node in nodes:
  113                 couchbase['nodes'][node['hostname']] = node
  114 
  115         # Next, get all buckets .
  116         endpoint = overall_stats['buckets']['uri']
  117 
  118         url = '%s%s' % (server, endpoint)
  119         buckets = self._get_stats(url, instance)
  120 
  121         if buckets is not None:
  122             for bucket in buckets:
  123                 bucket_name = bucket['name']
  124 
  125                 # Fetch URI for the stats bucket
  126                 endpoint = bucket['stats']['uri']
  127                 url = '%s%s' % (server, endpoint)
  128 
  129                 try:
  130                     bucket_stats = self._get_stats(url, instance)
  131                 except requests.exceptions.HTTPError:
  132                     url_backup = '%s/pools/nodes/buckets/%s/stats' % (server, bucket_name)
  133                     bucket_stats = self._get_stats(url_backup, instance)
  134 
  135                 bucket_samples = bucket_stats['op']['samples']
  136                 if bucket_samples is not None:
  137                     couchbase['buckets'][bucket['name']] = bucket_samples
  138 
  139         return couchbase
  140 
  141     # Takes a camelCased variable and returns a joined_lower equivalent.
  142     # Returns input if non-camelCase variable is detected.
  143     def camel_case_to_joined_lower(self, variable):
  144         # replace non-word with _
  145         converted_variable = re.sub('\W+', '_', variable)
  146 
  147         # insert _ in front of capital letters and lowercase the string
  148         converted_variable = re.sub('([A-Z])', '_\g<1>', converted_variable).lower()
  149 
  150         # remove duplicate _
  151         converted_variable = re.sub('_+', '_', converted_variable)
  152 
  153         # handle special case of starting/ending underscores
  154         converted_variable = re.sub('^_|_$', '', converted_variable)
  155 
  156         return converted_variable
  157
  ```
  --- 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/couchbase.py b/checks.d/couchbase.py
  --- a/checks.d/couchbase.py
  +++ b/checks.d/couchbase.py
  @@ -101,7 +101,8 @@
                   tags=service_check_tags, message=str(e))
               raise
           else:
  -            self.service_check(self.SERVICE_CHECK_NAME, AgentCheck.OK)
  +            self.service_check(self.SERVICE_CHECK_NAME, AgentCheck.OK,
  +                tags=service_check_tags)
   
           couchbase['stats'] = overall_stats
  
verification_info: {"golden_diff": "diff --git a/checks.d/couchbase.py b/checks.d/couchbase.py\n--- a/checks.d/couchbase.py\n+++ b/checks.d/couchbase.py\n@@ -101,7 +101,8 @@\n                 tags=service_check_tags, message=str(e))\n             raise\n         else:\n-            self.service_check(self.SERVICE_CHECK_NAME, AgentCheck.OK)\n+            self.service_check(self.SERVICE_CHECK_NAME, AgentCheck.OK,\n+                tags=service_check_tags)\n \n         couchbase['stats'] = overall_stats\n", "issue": "Couchbase service check do not send tags on OK status\nMissing a `tags=service_check_tags` on line:\nhttps://github.com/DataDog/dd-agent/blob/master/checks.d/couchbase.py#L104\n\nPretty small fix.\n\n", "before_files": [{"content": "# stdlib\nimport re\n\n# 3rd party\nimport requests\n\n# project\nfrom checks import AgentCheck\nfrom util import headers\n\n# Constants\nCOUCHBASE_STATS_PATH = '/pools/default'\nDEFAULT_TIMEOUT = 10\n\n\nclass Couchbase(AgentCheck):\n    \"\"\"Extracts stats from Couchbase via its REST API\n    http://docs.couchbase.com/couchbase-manual-2.0/#using-the-rest-api\n    \"\"\"\n    SERVICE_CHECK_NAME = 'couchbase.can_connect'\n\n    def _create_metrics(self, data, tags=None):\n        storage_totals = data['stats']['storageTotals']\n        for key, storage_type in storage_totals.items():\n            for metric_name, val in storage_type.items():\n                if val is not None:\n                    metric_name = '.'.join(['couchbase', key, self.camel_case_to_joined_lower(metric_name)])\n                    self.gauge(metric_name, val, tags=tags)\n\n        for bucket_name, bucket_stats in data['buckets'].items():\n            for metric_name, val in bucket_stats.items():\n                if val is not None:\n                    metric_name = '.'.join(['couchbase', 'by_bucket', self.camel_case_to_joined_lower(metric_name)])\n                    metric_tags = list(tags)\n                    metric_tags.append('bucket:%s' % bucket_name)\n                    self.gauge(metric_name, val[0], tags=metric_tags, device_name=bucket_name)\n\n        for node_name, node_stats in data['nodes'].items():\n            for metric_name, val in node_stats['interestingStats'].items():\n                if val is not None:\n                    metric_name = '.'.join(['couchbase', 'by_node', self.camel_case_to_joined_lower(metric_name)])\n                    metric_tags = list(tags)\n                    metric_tags.append('node:%s' % node_name)\n                    self.gauge(metric_name, val, tags=metric_tags, device_name=node_name)\n\n\n    def _get_stats(self, url, instance):\n        \"\"\" Hit a given URL and return the parsed json. \"\"\"\n        self.log.debug('Fetching Couchbase stats at url: %s' % url)\n\n        timeout = float(instance.get('timeout', DEFAULT_TIMEOUT))\n\n        auth = None\n        if 'user' in instance and 'password' in instance:\n            auth = (instance['user'], instance['password'])\n\n        r = requests.get(url, auth=auth, headers=headers(self.agentConfig),\n            timeout=timeout)\n        r.raise_for_status()\n        return r.json()\n\n    def check(self, instance):\n        server = instance.get('server', None)\n        if server is None:\n            raise Exception(\"The server must be specified\")\n        tags = instance.get('tags', [])\n        # Clean up tags in case there was a None entry in the instance\n        # e.g. if the yaml contains tags: but no actual tags\n        if tags is None:\n            tags = []\n        else:\n            tags = list(set(tags))\n        tags.append('instance:%s' % server)\n        data = self.get_data(server, instance)\n        self._create_metrics(data, tags=list(set(tags)))\n\n    def get_data(self, server, instance):\n        # The dictionary to be returned.\n        couchbase = {\n            'stats': None,\n            'buckets': {},\n            'nodes': {}\n        }\n\n        # build couchbase stats entry point\n        url = '%s%s' % (server, COUCHBASE_STATS_PATH)\n\n        # Fetch initial stats and capture a service check based on response.\n        service_check_tags = ['instance:%s' % server]\n        try:\n            overall_stats = self._get_stats(url, instance)\n            # No overall stats? bail out now\n            if overall_stats is None:\n                raise Exception(\"No data returned from couchbase endpoint: %s\" % url)\n        except requests.exceptions.HTTPError as e:\n            self.service_check(self.SERVICE_CHECK_NAME, AgentCheck.CRITICAL,\n                tags=service_check_tags, message=str(e.message))\n            raise\n        except Exception as e:\n            self.service_check(self.SERVICE_CHECK_NAME, AgentCheck.CRITICAL,\n                tags=service_check_tags, message=str(e))\n            raise\n        else:\n            self.service_check(self.SERVICE_CHECK_NAME, AgentCheck.OK)\n\n        couchbase['stats'] = overall_stats\n\n        nodes = overall_stats['nodes']\n\n        # Next, get all the nodes\n        if nodes is not None:\n            for node in nodes:\n                couchbase['nodes'][node['hostname']] = node\n\n        # Next, get all buckets .\n        endpoint = overall_stats['buckets']['uri']\n\n        url = '%s%s' % (server, endpoint)\n        buckets = self._get_stats(url, instance)\n\n        if buckets is not None:\n            for bucket in buckets:\n                bucket_name = bucket['name']\n\n                # Fetch URI for the stats bucket\n                endpoint = bucket['stats']['uri']\n                url = '%s%s' % (server, endpoint)\n\n                try:\n                    bucket_stats = self._get_stats(url, instance)\n                except requests.exceptions.HTTPError:\n                    url_backup = '%s/pools/nodes/buckets/%s/stats' % (server, bucket_name)\n                    bucket_stats = self._get_stats(url_backup, instance)\n\n                bucket_samples = bucket_stats['op']['samples']\n                if bucket_samples is not None:\n                    couchbase['buckets'][bucket['name']] = bucket_samples\n\n        return couchbase\n\n    # Takes a camelCased variable and returns a joined_lower equivalent.\n    # Returns input if non-camelCase variable is detected.\n    def camel_case_to_joined_lower(self, variable):\n        # replace non-word with _\n        converted_variable = re.sub('\\W+', '_', variable)\n\n        # insert _ in front of capital letters and lowercase the string\n        converted_variable = re.sub('([A-Z])', '_\\g<1>', converted_variable).lower()\n\n        # remove duplicate _\n        converted_variable = re.sub('_+', '_', converted_variable)\n\n        # handle special case of starting/ending underscores\n        converted_variable = re.sub('^_|_$', '', converted_variable)\n\n        return converted_variable\n", "path": "checks.d/couchbase.py"}], "after_files": [{"content": "# stdlib\nimport re\n\n# 3rd party\nimport requests\n\n# project\nfrom checks import AgentCheck\nfrom util import headers\n\n# Constants\nCOUCHBASE_STATS_PATH = '/pools/default'\nDEFAULT_TIMEOUT = 10\n\n\nclass Couchbase(AgentCheck):\n    \"\"\"Extracts stats from Couchbase via its REST API\n    http://docs.couchbase.com/couchbase-manual-2.0/#using-the-rest-api\n    \"\"\"\n    SERVICE_CHECK_NAME = 'couchbase.can_connect'\n\n    def _create_metrics(self, data, tags=None):\n        storage_totals = data['stats']['storageTotals']\n        for key, storage_type in storage_totals.items():\n            for metric_name, val in storage_type.items():\n                if val is not None:\n                    metric_name = '.'.join(['couchbase', key, self.camel_case_to_joined_lower(metric_name)])\n                    self.gauge(metric_name, val, tags=tags)\n\n        for bucket_name, bucket_stats in data['buckets'].items():\n            for metric_name, val in bucket_stats.items():\n                if val is not None:\n                    metric_name = '.'.join(['couchbase', 'by_bucket', self.camel_case_to_joined_lower(metric_name)])\n                    metric_tags = list(tags)\n                    metric_tags.append('bucket:%s' % bucket_name)\n                    self.gauge(metric_name, val[0], tags=metric_tags, device_name=bucket_name)\n\n        for node_name, node_stats in data['nodes'].items():\n            for metric_name, val in node_stats['interestingStats'].items():\n                if val is not None:\n                    metric_name = '.'.join(['couchbase', 'by_node', self.camel_case_to_joined_lower(metric_name)])\n                    metric_tags = list(tags)\n                    metric_tags.append('node:%s' % node_name)\n                    self.gauge(metric_name, val, tags=metric_tags, device_name=node_name)\n\n\n    def _get_stats(self, url, instance):\n        \"\"\" Hit a given URL and return the parsed json. \"\"\"\n        self.log.debug('Fetching Couchbase stats at url: %s' % url)\n\n        timeout = float(instance.get('timeout', DEFAULT_TIMEOUT))\n\n        auth = None\n        if 'user' in instance and 'password' in instance:\n            auth = (instance['user'], instance['password'])\n\n        r = requests.get(url, auth=auth, headers=headers(self.agentConfig),\n            timeout=timeout)\n        r.raise_for_status()\n        return r.json()\n\n    def check(self, instance):\n        server = instance.get('server', None)\n        if server is None:\n            raise Exception(\"The server must be specified\")\n        tags = instance.get('tags', [])\n        # Clean up tags in case there was a None entry in the instance\n        # e.g. if the yaml contains tags: but no actual tags\n        if tags is None:\n            tags = []\n        else:\n            tags = list(set(tags))\n        tags.append('instance:%s' % server)\n        data = self.get_data(server, instance)\n        self._create_metrics(data, tags=list(set(tags)))\n\n    def get_data(self, server, instance):\n        # The dictionary to be returned.\n        couchbase = {\n            'stats': None,\n            'buckets': {},\n            'nodes': {}\n        }\n\n        # build couchbase stats entry point\n        url = '%s%s' % (server, COUCHBASE_STATS_PATH)\n\n        # Fetch initial stats and capture a service check based on response.\n        service_check_tags = ['instance:%s' % server]\n        try:\n            overall_stats = self._get_stats(url, instance)\n            # No overall stats? bail out now\n            if overall_stats is None:\n                raise Exception(\"No data returned from couchbase endpoint: %s\" % url)\n        except requests.exceptions.HTTPError as e:\n            self.service_check(self.SERVICE_CHECK_NAME, AgentCheck.CRITICAL,\n                tags=service_check_tags, message=str(e.message))\n            raise\n        except Exception as e:\n            self.service_check(self.SERVICE_CHECK_NAME, AgentCheck.CRITICAL,\n                tags=service_check_tags, message=str(e))\n            raise\n        else:\n            self.service_check(self.SERVICE_CHECK_NAME, AgentCheck.OK,\n                tags=service_check_tags)\n\n        couchbase['stats'] = overall_stats\n\n        nodes = overall_stats['nodes']\n\n        # Next, get all the nodes\n        if nodes is not None:\n            for node in nodes:\n                couchbase['nodes'][node['hostname']] = node\n\n        # Next, get all buckets .\n        endpoint = overall_stats['buckets']['uri']\n\n        url = '%s%s' % (server, endpoint)\n        buckets = self._get_stats(url, instance)\n\n        if buckets is not None:\n            for bucket in buckets:\n                bucket_name = bucket['name']\n\n                # Fetch URI for the stats bucket\n                endpoint = bucket['stats']['uri']\n                url = '%s%s' % (server, endpoint)\n\n                try:\n                    bucket_stats = self._get_stats(url, instance)\n                except requests.exceptions.HTTPError:\n                    url_backup = '%s/pools/nodes/buckets/%s/stats' % (server, bucket_name)\n                    bucket_stats = self._get_stats(url_backup, instance)\n\n                bucket_samples = bucket_stats['op']['samples']\n                if bucket_samples is not None:\n                    couchbase['buckets'][bucket['name']] = bucket_samples\n\n        return couchbase\n\n    # Takes a camelCased variable and returns a joined_lower equivalent.\n    # Returns input if non-camelCase variable is detected.\n    def camel_case_to_joined_lower(self, variable):\n        # replace non-word with _\n        converted_variable = re.sub('\\W+', '_', variable)\n\n        # insert _ in front of capital letters and lowercase the string\n        converted_variable = re.sub('([A-Z])', '_\\g<1>', converted_variable).lower()\n\n        # remove duplicate _\n        converted_variable = re.sub('_+', '_', converted_variable)\n\n        # handle special case of starting/ending underscores\n        converted_variable = re.sub('^_|_$', '', converted_variable)\n\n        return converted_variable\n", "path": "checks.d/couchbase.py"}]}