Initial setup of zookeepr and kafka
This commit is contained in:
@@ -1,8 +1,8 @@
|
|||||||
init_config:
|
init_config:
|
||||||
|
|
||||||
instances:
|
instances:
|
||||||
# - host: localhost
|
- host: localhost
|
||||||
# port: 2181
|
port: 2181
|
||||||
# timeout: 3
|
timeout: 3
|
||||||
# dimensions:
|
# dimensions:
|
||||||
# dim1: value1
|
# dim1: value1
|
||||||
|
|||||||
@@ -9,3 +9,7 @@ configuring it to start up on boot.
|
|||||||
which run locally but are checking a remote box.
|
which run locally but are checking a remote box.
|
||||||
- The ability to dynamically add detection plugins could be quite valuable. Also it could aid in the active check config.
|
- The ability to dynamically add detection plugins could be quite valuable. Also it could aid in the active check config.
|
||||||
- With the ability to dynamically add I should also include the ability to dynamically remove.
|
- With the ability to dynamically add I should also include the ability to dynamically remove.
|
||||||
|
- A config file with metadata to assist in automatic configuration could be quite valuable, for example user/pass for
|
||||||
|
logging into mysql.
|
||||||
|
- The current system does not work well in the case of clusters, for example the kafka plugin will end up collecting
|
||||||
|
the same data on each node of a cluster.
|
||||||
@@ -41,12 +41,23 @@ class Plugin(object):
|
|||||||
return self.__class__.__name__
|
return self.__class__.__name__
|
||||||
|
|
||||||
|
|
||||||
|
def find_process_cmdline(search_string):
|
||||||
|
"""Simple function to search running process for one with cmdline containing
|
||||||
|
"""
|
||||||
|
for process in psutil.process_iter():
|
||||||
|
for arg in process.cmdline():
|
||||||
|
if arg.find(search_string) != -1:
|
||||||
|
return process
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def find_process_name(pname):
|
def find_process_name(pname):
|
||||||
"""Simple function to search running process for one with pname.
|
"""Simple function to search running process for one with pname.
|
||||||
"""
|
"""
|
||||||
for process in psutil.process_iter():
|
for process in psutil.process_iter():
|
||||||
if pname == process.name():
|
if pname == process.name():
|
||||||
return process.pid
|
return process
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|||||||
66
monsetup/detection/kafka.py
Normal file
66
monsetup/detection/kafka.py
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
import collections
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from . import Plugin, find_process_cmdline, watch_process
|
||||||
|
from monsetup import agent_config
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class Kafka(Plugin):
|
||||||
|
"""Detect Kafka daemons and sets up configuration to monitor them.
|
||||||
|
This plugin configures the kafka_consumer plugin and does not configure any jmx based checks against kafka.
|
||||||
|
Note this plugin will pull the same information from kafka on each node in the cluster it runs on.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def _detect(self):
|
||||||
|
"""Run detection, set self.available True if the service is detected."""
|
||||||
|
if find_process_cmdline('kafka') is not None:
|
||||||
|
self.available = True
|
||||||
|
|
||||||
|
def build_config(self):
|
||||||
|
"""Build the config as a Plugins object and return.
|
||||||
|
"""
|
||||||
|
config = agent_config.Plugins()
|
||||||
|
# First watch the process
|
||||||
|
config.update(watch_process(['kafka']))
|
||||||
|
log.info("\tWatching the kafka process.")
|
||||||
|
|
||||||
|
if self.dependencies_installed():
|
||||||
|
# todo this naively assumes zookeeper is also available on localhost
|
||||||
|
|
||||||
|
import kazoo
|
||||||
|
from kazoo.client import KazooClient
|
||||||
|
logging.getLogger('kazoo').setLevel(logging.WARN) # kazoo fills up the console without this
|
||||||
|
|
||||||
|
zk = KazooClient(hosts='127.0.0.1:2181', read_only=True)
|
||||||
|
zk.start()
|
||||||
|
topics = {}
|
||||||
|
for topic in zk.get_children('/brokers/topics'):
|
||||||
|
topics[topic] = zk.get_children('/brokers/topics/%s/partitions' % topic)
|
||||||
|
|
||||||
|
consumers = collections.defaultdict(dict) # {'consumer_group_name': { 'topic1': [ 0, 1, 2] # partitions }}
|
||||||
|
for consumer in zk.get_children('/consumers'):
|
||||||
|
try:
|
||||||
|
for topic in zk.get_children('/consumers/%s/offsets' % consumer):
|
||||||
|
if topic in topics:
|
||||||
|
consumers[consumer][topic] = topics[topic]
|
||||||
|
except kazoo.exceptions.NoNodeError:
|
||||||
|
continue
|
||||||
|
|
||||||
|
|
||||||
|
log.info("\tInstalling kafka_consumer plugin.")
|
||||||
|
config['kafka_consumer'] = {'init_config': None,
|
||||||
|
'instances': [{'kafka_connect_str': 'localhost:9092',
|
||||||
|
'zk_connect_str': 'localhost:2181',
|
||||||
|
'consumer_groups': dict(consumers)}]}
|
||||||
|
return config
|
||||||
|
|
||||||
|
def dependencies_installed(self):
|
||||||
|
try:
|
||||||
|
import kafka
|
||||||
|
import kazoo
|
||||||
|
except ImportError:
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
@@ -8,7 +8,10 @@ log = logging.getLogger(__name__)
|
|||||||
|
|
||||||
class MySQL(Plugin):
|
class MySQL(Plugin):
|
||||||
"""Detect MySQL daemons and setup configuration to monitor them.
|
"""Detect MySQL daemons and setup configuration to monitor them.
|
||||||
This plugin needs user/pass infor for mysql setup, this is best placed in /root/.mysql.cnf
|
This plugin needs user/pass infor for mysql setup, this is best placed in /root/.my.cnf in a format such as
|
||||||
|
[client]
|
||||||
|
user = root
|
||||||
|
password = yourpassword
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def _detect(self):
|
def _detect(self):
|
||||||
@@ -24,18 +27,18 @@ class MySQL(Plugin):
|
|||||||
config.update(watch_process(['mysqld']))
|
config.update(watch_process(['mysqld']))
|
||||||
log.info("\tWatching the mysqld process.")
|
log.info("\tWatching the mysqld process.")
|
||||||
|
|
||||||
# Attempt login, requires either an empty root password from localhost or relying on a configured .mysql.cnf
|
# Attempt login, requires either an empty root password from localhost or relying on a configured .my.cnf
|
||||||
if self.dependencies_installed(): # ensures MySQLdb is available
|
if self.dependencies_installed(): # ensures MySQLdb is available
|
||||||
import MySQLdb
|
import MySQLdb
|
||||||
import _mysql_exceptions
|
import _mysql_exceptions
|
||||||
try:
|
try:
|
||||||
MySQLdb.connect(read_default_file='/root/.mysql.cnf')
|
MySQLdb.connect(read_default_file='/root/.my.cnf')
|
||||||
except _mysql_exceptions.MySQLError:
|
except _mysql_exceptions.MySQLError:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
log.info("\tConfiguring MySQL plugin to connect with auth settings from /root/.mysql.cnf")
|
log.info("\tConfiguring MySQL plugin to connect with auth settings from /root/.my.cnf")
|
||||||
config['mysql'] = {'init_config': None, 'instances':
|
config['mysql'] = {'init_config': None, 'instances':
|
||||||
[{'server': 'localhost', 'user': 'root', 'defaults_file': '/root/.mysql.cnf'}]}
|
[{'server': 'localhost', 'user': 'root', 'defaults_file': '/root/.my.cnf'}]}
|
||||||
|
|
||||||
if not 'mysql' in config:
|
if not 'mysql' in config:
|
||||||
try:
|
try:
|
||||||
|
|||||||
36
monsetup/detection/zookeeper.py
Normal file
36
monsetup/detection/zookeeper.py
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
import logging
|
||||||
|
import os
|
||||||
|
import yaml
|
||||||
|
|
||||||
|
from . import Plugin, find_process_cmdline, watch_process
|
||||||
|
from monsetup import agent_config
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class Zookeeper(Plugin):
|
||||||
|
"""Detect Zookeeper daemons and setup configuration to monitor them.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def _detect(self):
|
||||||
|
"""Run detection, set self.available True if the service is detected."""
|
||||||
|
if find_process_cmdline('zookeeper') is not None:
|
||||||
|
self.available = True
|
||||||
|
|
||||||
|
def build_config(self):
|
||||||
|
"""Build the config as a Plugins object and return.
|
||||||
|
"""
|
||||||
|
config = agent_config.Plugins()
|
||||||
|
# First watch the process
|
||||||
|
log.info("\tWatching the zookeeper process.")
|
||||||
|
config.update(watch_process(['zookeeper']))
|
||||||
|
|
||||||
|
log.info("\tEnabling the zookeeper plugin")
|
||||||
|
with open(os.path.join(self.template_dir, 'conf.d/zk.yaml.example'), 'r') as zk_template:
|
||||||
|
zk_config = yaml.load(zk_template.read())
|
||||||
|
config['zk'] = zk_config
|
||||||
|
|
||||||
|
return config
|
||||||
|
|
||||||
|
def dependencies_installed(self):
|
||||||
|
return True # The current plugin just does a simple socket connection to zookeeper and parses the stat command
|
||||||
@@ -12,11 +12,11 @@ import sys
|
|||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
import agent_config
|
import agent_config
|
||||||
from detection import mysql, network, nova
|
from detection import kafka, mysql, network, nova, zookeeper
|
||||||
from service import sysv
|
from service import sysv
|
||||||
|
|
||||||
# List of all detection plugins to run
|
# List of all detection plugins to run
|
||||||
DETECTION_PLUGINS = [mysql.MySQL, network.Network, nova.Nova]
|
DETECTION_PLUGINS = [kafka.Kafka, mysql.MySQL, network.Network, nova.Nova, zookeeper.Zookeeper]
|
||||||
# Map OS to service type
|
# Map OS to service type
|
||||||
OS_SERVICE_MAP = {'linux': sysv.SysV}
|
OS_SERVICE_MAP = {'linux': sysv.SysV}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user