Skip to content

Commit

Permalink
Add a service check for Couchbase.
Browse files Browse the repository at this point in the history
- With a test that should work without Couchbase running (testing
  failure)
- Also cleaned up some pre-omnibus code checking the Python version.
  • Loading branch information
conorbranagan committed Nov 14, 2014
1 parent a9a26b2 commit 7b16648
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 19 deletions.
37 changes: 23 additions & 14 deletions checks.d/couchbase.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class Couchbase(AgentCheck):
"""Extracts stats from Couchbase via its REST API
http://docs.couchbase.com/couchbase-manual-2.0/#using-the-rest-api
"""
SERVICE_CHECK_NAME = 'couchbase.can_connect'

def _create_metrics(self, data, tags=None):
storage_totals = data['stats']['storageTotals']
Expand Down Expand Up @@ -45,18 +46,14 @@ def _create_metrics(self, data, tags=None):


def _get_stats(self, url, instance):
"Hit a given URL and return the parsed json"
""" Hit a given URL and return the parsed json. """
self.log.debug('Fetching Couchbase stats at url: %s' % url)
req = urllib2.Request(url, None, headers(self.agentConfig))
if 'user' in instance and 'password' in instance:
add_basic_auth(req, instance['user'], instance['password'])

if instance['is_recent_python']:
timeout = instance.get('timeout' , DEFAULT_TIMEOUT)
request = urllib2.urlopen(req,timeout=timeout)
else:
request = urllib2.urlopen(req)

timeout = float(instance.get('timeout', DEFAULT_TIMEOUT))
request = urllib2.urlopen(req, timeout=timeout)
response = request.read()
return json.loads(response)

Expand All @@ -72,7 +69,6 @@ def check(self, instance):
else:
tags = list(set(tags))
tags.append('instance:%s' % server)
instance['is_recent_python'] = sys.version_info >= (2,6,0)
data = self.get_data(server, instance)
self._create_metrics(data, tags=list(set(tags)))

Expand All @@ -85,12 +81,25 @@ def get_data(self, server, instance):

# build couchbase stats entry point
url = '%s%s' % (server, COUCHBASE_STATS_PATH)
overall_stats = self._get_stats(url, instance)

# No overall stats? bail out now
if overall_stats is None:
raise Exception("No data returned from couchbase endpoint: %s" % url)

# Fetch initial stats and capture a service check based on response.
service_check_tags = {'instance:%s' % server}
try:
overall_stats = self._get_stats(url, instance)
# No overall stats? bail out now
if overall_stats is None:
raise Exception("No data returned from couchbase endpoint: %s" % url)
except urllib2.URLError as e:
self.service_check(self.SERVICE_CHECK_NAME, AgentCheck.CRITICAL,
tags=service_check_tags, message=e.reason)
raise
except Exception as e:
self.service_check(self.SERVICE_CHECK_NAME, AgentCheck.CRITICAL,
tags=service_check_tags, message=str(e))
raise
else:
self.service_check(self.SERVICE_CHECK_NAME, AgentCheck.OK)

couchbase['stats'] = overall_stats

nodes = overall_stats['nodes']
Expand Down Expand Up @@ -130,7 +139,7 @@ def camel_case_to_joined_lower(self, variable):

# remove duplicate _
converted_variable = re.sub('_+', '_', converted_variable)

# handle special case of starting/ending underscores
converted_variable = re.sub('^_|_$', '', converted_variable)

Expand Down
23 changes: 18 additions & 5 deletions tests/test_couchbase.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import unittest
from tests.common import load_check
from checks import AgentCheck

from nose.plugins.attrib import attr
from nose.plugins.skip import SkipTest

@attr('couchbase')
class CouchbaseTestCase(unittest.TestCase):

def setUp(self):
Expand All @@ -11,6 +14,7 @@ def setUp(self):
'server': 'http://localhost:8091',
'user': 'Administrator',
'password': 'password',
'timeout': 0.1
}]
}
self.agentConfig = {
Expand All @@ -19,7 +23,6 @@ def setUp(self):
}
self.check = load_check('couchbase', self.config, self.agentConfig)

@attr('couchbase')
def test_camel_case_to_joined_lower(self):
test_pairs = {
'camelCase' : 'camel_case',
Expand All @@ -36,17 +39,16 @@ def test_camel_case_to_joined_lower(self):

for test_input, expected_output in test_pairs.items():
test_output = self.check.camel_case_to_joined_lower(test_input)
self.assertEqual(test_output, expected_output,
self.assertEqual(test_output, expected_output,
'Input was %s, expected output was %s, actual output was %s' % (test_input, expected_output, test_output))

@attr('couchbase')
def test_metrics_casing(self):
raise SkipTest("Skipped for now as it's hard to configure couchbase on travis")
self.check.check(self.config['instances'][0])

metrics = self.check.get_metrics()

camel_cased_metrics = [u'couchbase.hdd.used_by_data',
camel_cased_metrics = [u'couchbase.hdd.used_by_data',
u'couchbase.ram.used_by_data',
u'couchbase.ram.quota_total',
u'couchbase.ram.quota_used',
Expand All @@ -55,7 +57,6 @@ def test_metrics_casing(self):
found_metrics = [k[0] for k in metrics if k[0] in camel_cased_metrics]
self.assertEqual(found_metrics.sort(), camel_cased_metrics.sort())

@attr('couchbase')
def test_metrics(self):
raise SkipTest("Skipped for now as it's hard to configure couchbase on travis")
self.check.check(self.config['instances'][0])
Expand All @@ -68,3 +69,15 @@ def test_metrics(self):

self.assertTrue(len([k for k in metrics if -1 != k[0].find('by_node')]) > 1, 'Unable to fund any per node metrics')
self.assertTrue(len([k for k in metrics if -1 != k[0].find('by_bucket')]) > 1, 'Unable to fund any per node metrics')

def test_service_check(self):
try:
self.check.check(self.config['instances'][0])
except Exception:
service_checks = self.check.get_service_checks()
self.assertEqual(len(service_checks), 1)
service_check = service_checks[0]
self.assertEqual(service_check['check'], self.check.SERVICE_CHECK_NAME)
self.assertEqual(service_check['status'], AgentCheck.CRITICAL)
else:
raise Exception('Couchbase check should have failed')

0 comments on commit 7b16648

Please sign in to comment.