Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HAProxy: gauge missing statuses with zero #940

Merged
merged 8 commits into from
May 19, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 24 additions & 15 deletions checks.d/haproxy.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import urlparse
import urllib2
import socket

from checks import AgentCheck
from util import json, headers
from util import headers

import time

Expand All @@ -19,6 +17,9 @@ class Services(object):
BACKEND = 'BACKEND'
FRONTEND = 'FRONTEND'
ALL = (BACKEND, FRONTEND)
ALL_STATUSES = (
'up', 'open', 'no_check', 'down', 'maint', 'nolb'
)

class HAProxy(AgentCheck):
def __init__(self, name, init_config, agentConfig):
Expand Down Expand Up @@ -119,16 +120,17 @@ def _process_data(

self._update_data_dict(data_dict, back_or_front)

self._update_hosts_statuses_if_needed(
collect_status_metrics, collect_status_metrics_by_host,
data_dict, hosts_statuses
)

if self._should_process(data_dict, collect_aggregates_only):
# update status
self._update_hosts_statuses_if_needed(
collect_status_metrics, collect_status_metrics_by_host,
data_dict, hosts_statuses
)
# Send the list of data to the metric and event callbacks
self._process_metrics(data_dict, url)
if process_events:
self._process_event(data_dict, url)
if process_events:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is that intentional ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, I thought that we don't want to have events on aggregates if we use the detail otherwise, and vice versa

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this way:

  • use aggregates -> metrics and events for the aggregates
  • don't use aggregates -> metrics and events detailed, without the noise of the aggregates

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great

self._process_event(data_dict, url)

if collect_status_metrics:
self._process_status_metric(hosts_statuses, collect_status_metrics_by_host)
Expand Down Expand Up @@ -182,7 +184,7 @@ def _should_process(self, data_dict, collect_aggregates_only):
if self._is_aggregate(data_dict):
return True
return False
elif data_dict['svname'] is Services.BACKEND:
elif data_dict['svname'] == Services.BACKEND:
return False
return True

Expand All @@ -195,12 +197,12 @@ def _process_status_metric(self, hosts_statuses, collect_status_metrics_by_host)
service, status = host_status
status = status.lower()

tags = ['status:%s' % status, 'service:%s' % service]
tags = ['service:%s' % service]
if collect_status_metrics_by_host:
tags.append('backend:%s' % hostname)
self.gauge("haproxy.count_per_status", count, tags=tags)
self._gauge_all_statuses("haproxy.count_per_status", count, status, tags=tags)

if 'up' in status:
if 'up' in status or 'open' in status:
agg_statuses[service]['available'] += count
if 'down' in status or 'maint' in status or 'nolb' in status:
agg_statuses[service]['unavailable'] += count
Expand All @@ -210,6 +212,13 @@ def _process_status_metric(self, hosts_statuses, collect_status_metrics_by_host)
tags = ['status:%s' % status, 'service:%s' % service]
self.gauge("haproxy.count_per_status", count, tags=tags)

def _gauge_all_statuses(self, metric_name, count, status, tags):
self.gauge(metric_name, count, tags + ['status:%s' % status])
for state in Services.ALL_STATUSES:
if state != status:
self.gauge(metric_name, 0, tags + ['status:%s' % state])


def _process_metrics(self, data, url):
"""
Data is a dictionary related to one host
Expand Down Expand Up @@ -263,13 +272,13 @@ def _process_event(self, data, url):
def _create_event(self, status, hostname, lastchg, service_name):
if status == "DOWN":
alert_type = "error"
title = "HAProxy %s front-end reported %s %s" % (service_name, hostname, status)
title = "%s reported %s %s" % (service_name, hostname, status)
else:
if status == "UP":
alert_type = "success"
else:
alert_type = "info"
title = "HAProxy %s front-end reported %s back and %s" % (service_name, hostname, status)
title = "%s reported %s back and %s" % (service_name, hostname, status)

return {
'timestamp': int(time.time() - lastchg),
Expand Down
6 changes: 3 additions & 3 deletions emitter.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ def get_http_library(proxy_settings, use_forwarder):
else:
# Python version < 2.6.3
import urllib2proxy as urllib2
return urllib2
return urllib2

def post_headers(agentConfig, payload):
return {
Expand Down Expand Up @@ -75,13 +75,13 @@ def get_opener(log, proxy_settings, use_forwarder, urllib2):
log.debug("Not using proxy settings")
else:
proxy_url = '%s:%s' % (proxy_settings['host'], proxy_settings['port'])

if proxy_settings.get('user') is not None:
proxy_auth = proxy_settings['user']
if proxy_settings.get('password') is not None:
proxy_auth = '%s:%s' % (proxy_auth, proxy_settings['password'])
proxy_url = '%s@%s' % (proxy_auth, proxy_url)

proxy = {'https': proxy_url}
log.debug("Using proxy settings %s" % proxy)

Expand Down
4 changes: 2 additions & 2 deletions tests/test_haproxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ def testCheck(self):
self.assertTrue(len(metrics) > 0)

self.assertEquals(len([t for t in metrics
if t[0] == "haproxy.backend.bytes.in_rate"]), 4, metrics)
if t[0] == "haproxy.backend.bytes.in_rate"]), 3, metrics)
self.assertEquals(len([t for t in metrics
if t[0] == "haproxy.frontend.session.current"]), 1, metrics)

Expand Down Expand Up @@ -151,7 +151,7 @@ def testOpenConfig(self):
self.assertTrue(len(metrics) > 0)

self.assertEquals(len([t for t in metrics
if t[0] == "haproxy.backend.bytes.in_rate"]), 4, metrics)
if t[0] == "haproxy.backend.bytes.in_rate"]), 3, metrics)
self.assertEquals(len([t for t in metrics
if t[0] == "haproxy.frontend.session.current"]), 1, metrics)

Expand Down