@cryptotaxi247 / netdata-1 / commits / a5b3dcec4

initial revision of python plugin for monit (https://mmonit.com/monit/)

Evgeniy Kostenko committed Aug 2, 2018 at 07:01 UTC a5b3dcec48aa85f74e727318e7021e9512fb6330
1 file changed +148
python.d/monit.chart.py new
+148
@@ -0,0 +1,148 @@
1 +# -*- coding: utf-8 -*-
2 +# Description: monit netdata python.d module
3 +# Author: Evgeniy K. (n0guest)
4 +# SPDX-License-Identifier: GPL-3.0+
5 +
6 +import xml.etree.ElementTree as ET
7 +import pdb
8 +
9 +from bases.FrameworkServices.UrlService import UrlService
10 +
11 +# default module values (can be overridden per job in `config`)
12 +# update_every = 2
13 +priority = 60000
14 +retries = 60
15 +
16 +MONIT_SERVICE_NAMES = [ 'Filesystem', 'Directory', 'File', 'Process', 'Host', 'System', 'Fifo', 'Program', 'Net' ]
17 +DEFAULT_SERVICES_IDS = [ 0, 1, 2, 3, 4, 6, 7, 8 ]
18 +
19 +# charts order (can be overridden if you want less charts, or different order)
20 +ORDER = [ 'filesystem', 'directory', 'file', 'process', 'process_uptime', 'process_threads', 'process_children', 'host', 'host_latency', 'system', 'fifo', 'program', 'net' ]
21 +CHARTS = {
22 + # id: {
23 + # 'options': [name, title, units, family, context, charttype],
24 + # 'lines': [
25 + # [unique_dimension_name, name, algorithm, multiplier, divisor]
26 + # ]}
27 + 'filesystem': {
28 + 'options': ['filesystems', 'Filesystems', 'filesystems', 'filesystem', 'monit.filesystems', 'line'],
29 + 'lines': []
30 + },
31 + 'directory': {
32 + 'options': ['directories', 'Directories', 'directories', 'filesystem', 'monit.directories', 'line'],
33 + 'lines': []
34 + },
35 + 'file': {
36 + 'options': ['files', 'Files', 'files', 'filesystem', 'monit.files', 'line'],
37 + 'lines': []
38 + },
39 + 'fifo': {
40 + 'options': ['fifos', 'Pipes (fifo)', 'pipes', 'filesystem', 'monit.fifos', 'line'],
41 + 'lines': []
42 + },
43 + 'program': {
44 + 'options': ['programs', 'Programs statuses', 'programs', 'applications', 'monit.programs', 'line'],
45 + 'lines': []
46 + },
47 + 'process': {
48 + 'options': ['processes', 'Processes statuses', 'processes', 'applications', 'monit.services', 'line'],
49 + 'lines': []
50 + },
51 + 'process_uptime': {
52 + 'options': ['processes uptime', 'Processes uptime', 'seconds', 'applications', 'monit.process_uptime', 'line', 'hidden'],
53 + 'lines': []
54 + },
55 + 'process_threads': {
56 + 'options': ['processes threads', 'Processes threads', 'threads', 'applications', 'monit.process_threads', 'line'],
57 + 'lines': []
58 + },
59 + 'process_children': {
60 + 'options': ['processes childrens', 'Child processes', 'childrens', 'applications', 'monit.process_childrens', 'line'],
61 + 'lines': []
62 + },
63 + 'host': {
64 + 'options': ['hosts', 'Hosts', 'hosts', 'network', 'monit.hosts', 'line'],
65 + 'lines': []
66 + },
67 + 'host_latency': {
68 + 'options': ['hosts latency', 'Hosts latency', 'milliseconds/s', 'network', 'monit.hosts', 'line'],
69 + 'lines': []
70 + },
71 + 'net': {
72 + 'options': ['interfaces', 'Network interfaces and addresses', 'interfaces', 'network', 'monit.networks', 'line'],
73 + 'lines': []
74 + },
75 +}
76 +
77 +class Service(UrlService):
78 + def __init__(self, configuration=None, name=None):
79 + UrlService.__init__(self, configuration=configuration, name=name)
80 + self.url = self.configuration.get('url', "http://127.0.0.1:2812/_status?format=xml&level=full")
81 + self.order = ORDER
82 + self.definitions = CHARTS
83 +
84 + def check(self):
85 + self._manager = self._build_manager()
86 + raw_data = self._get_raw_data()
87 + if raw_data:
88 + try:
89 + xml = ET.fromstring(raw_data)
90 + except ET.ParseError:
91 + self.debug('%s is not a vaild XML page. Please add "_status?format=xml&level=full" to monit URL.' % self.url)
92 + return None
93 + return True
94 + return None
95 +
96 + def _get_data(self):
97 + data = None
98 + raw_data = self._get_raw_data()
99 + if raw_data:
100 + try:
101 + xml = ET.fromstring(raw_data)
102 + except ET.ParseError:
103 + self.debug('%s is not a vaild XML page. Please add "_status?format=xml&level=full" to monit URL.' % self.url)
104 + return None
105 + data = {}
106 +
107 + for svc_id in DEFAULT_SERVICES_IDS:
108 + if svc_id not in DEFAULT_SERVICES_IDS:
109 + continue
110 +
111 + svc_category = MONIT_SERVICE_NAMES[svc_id].lower()
112 + if svc_category == 'system':
113 + self.debug("Skipping service from 'System' category, because it's useless in graphs")
114 + continue
115 +
116 + xpath_query = "./service[@type='%d']" % (svc_id)
117 + self.debug("Searching for %s as %s" % (svc_category, xpath_query))
118 + for svc in xml.findall(xpath_query):
119 + svc_name = svc.find('name').text
120 + svc_status = svc.find('status').text
121 + svc_monitor = svc.find('monitor').text
122 + self.debug('=> found %s with type=%s, status=%s, monitoring=%s' % (svc_name, svc_id, svc_status, svc_monitor))
123 +
124 + dimension_key = svc_category + '_' + svc_name
125 + if dimension_key not in self.charts[svc_category]:
126 + self.charts[svc_category].add_dimension([dimension_key, svc_name, 'absolute'])
127 + data[dimension_key] = 1 if svc_status == "0" and svc_monitor == "1" else 0
128 +
129 + if svc_category == 'process':
130 + for node in ('uptime', 'threads', 'children'):
131 + node_value = svc.find(node)
132 + if node_value != None:
133 + if node == 'uptime' and int(node_value.text) < 0:
134 + self.debug('Skipping bugged metrics with negative uptime')
135 + continue
136 + dimension_key = 'process_%s_%s' % (node, svc_name)
137 + if dimension_key not in self.charts['process_' + node]:
138 + self.charts['process_' + node].add_dimension([dimension_key, svc_name, 'absolute'])
139 + data[dimension_key] = int(node_value.text)
140 +
141 + if svc_category == 'host':
142 + node_value = svc.find('./icmp/responsetime')
143 + if node_value != None:
144 + dimension_key = 'host_latency_%s' % (svc_name)
145 + if dimension_key not in self.charts['host_latency']:
146 + self.charts['host_latency'].add_dimension([dimension_key, svc_name, 'absolute', 1000, 1000000])
147 + data[dimension_key] = float(node_value.text) * 1000000
148 + return data or None