Skip to content

Commit

Permalink
[elasticsearch] Remove hostname matching logic
Browse files Browse the repository at this point in the history
The hostname matching is not needed anymore as:
- since PR #1181 we only ask the _local node for stats when `is_external` is set to `false`
- we don't match the hostname at all when `is_external` is `true`

Matching hostnames can also filter out legitimate data when the
local elasticsearch node reports a different hostname.

See also issue #457
  • Loading branch information
olivielpeau committed Jun 5, 2015
1 parent 6ed6edf commit 8cbf5ac
Show file tree
Hide file tree
Showing 2 changed files with 6 additions and 84 deletions.
85 changes: 4 additions & 81 deletions checks.d/elastic.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
# stdlib
from collections import namedtuple, defaultdict
import socket
import subprocess
import time
import urlparse

Expand All @@ -11,7 +9,6 @@
# project
from checks import AgentCheck
from config import _is_affirmative
from utils.platform import Platform
from util import headers


Expand Down Expand Up @@ -359,88 +356,14 @@ def _process_stats_data(self, nodes_url, data, stats_metrics, config):
# On newer version of ES it's "host" not "hostname"
node_hostname = node_data.get(
'hostname', node_data.get('host', None))
should_process = (
is_external or self.should_process_node(
nodes_url, node_name, node_hostname, config))

# Override the metric hostname if we're hitting an external cluster
metric_hostname = node_hostname if is_external else None

if should_process:
for metric in stats_metrics:
desc = stats_metrics[metric]
self._process_metric(
node_data, metric, *desc, tags=config.tags,
hostname=metric_hostname)

def should_process_node(self, nodes_url, node_name, node_hostname, config):
""" The node stats API will return stats for every node so we
want to filter out nodes that we don't care about.
"""
if node_hostname is not None:
# For ES >= 0.19
hostnames = (
self.hostname.decode('utf-8'),
socket.gethostname().decode('utf-8'),
socket.getfqdn().decode('utf-8')
)
if node_hostname.decode('utf-8') in hostnames:
return True
else:
# FIXME 6.x : deprecate this code, it's EOL'd
# ES < 0.19
# Fetch interface address from ifconfig or ip addr and check
# against the primary IP from ES
try:
nodes_url = urlparse.urljoin(config.url, nodes_url)
primary_addr = self._get_primary_addr(
nodes_url, node_name, config)
except NodeNotFound:
# Skip any nodes that aren't found
return False
if self._host_matches_node(primary_addr):
return True

def _get_primary_addr(self, url, node_name, config):
""" Returns a list of primary interface addresses as seen by ES.
Used in ES < 0.19
"""
data = self._get_data(url, config)

if node_name in data['nodes']:
node = data['nodes'][node_name]
if ('network' in node
and 'primary_interface' in node['network']
and 'address' in node['network']['primary_interface']):
return node['network']['primary_interface']['address']

raise NodeNotFound()

def _host_matches_node(self, primary_addrs):
""" For < 0.19, check if the current host matches the IP given in the
cluster nodes check `/_cluster/nodes`. Uses `ip addr` on Linux and
`ifconfig` on Mac
"""
if Platform.is_darwin():
ifaces = subprocess.Popen(['ifconfig'], stdout=subprocess.PIPE)
else:
ifaces = subprocess.Popen(['ip', 'addr'], stdout=subprocess.PIPE)
grepper = subprocess.Popen(
['grep', 'inet'], stdin=ifaces.stdout, stdout=subprocess.PIPE,
stderr=subprocess.PIPE)

ifaces.stdout.close()
out, err = grepper.communicate()

# Capture the list of interface IPs
ips = []
for iface in out.split("\n"):
iface = iface.strip()
if iface:
ips.append(iface.split(' ')[1].split('/')[0])

# Check the interface addresses against the primary address
return primary_addrs in ips
for metric, desc in stats_metrics.iteritems():
self._process_metric(
node_data, metric, *desc, tags=config.tags,
hostname=metric_hostname)

def _process_metric(self, data, metric, xtype, path, xform=None,
tags=None, hostname=None):
Expand Down
5 changes: 2 additions & 3 deletions conf.d/elastic.yaml.example
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,8 @@ instances:
# and password for every instance that requires authentication.
#
# If your cluster is hosted externally (i.e., you're not pointing to localhost)
# you will need to set `is_external` to true otherwise the check will compare
# the local hostname against hostnames of the Elasticsearch nodes and only
# submit metrics if they match.
# you will need to set `is_external` to true otherwise the check will only
# submit metrics of the local node.
#
- url: http://localhost:9200
# username: username
Expand Down

0 comments on commit 8cbf5ac

Please sign in to comment.