Cleanup config.nodes_of
[check_mk.git] / checks / jolokia.include
blob1bb814b4a39fa12da743f9d981385c088c52ead8
1 #!/usr/bin/python
2 # -*- encoding: utf-8; py-indent-offset: 4 -*-
3 # +------------------------------------------------------------------+
4 # | ____ _ _ __ __ _ __ |
5 # | / ___| |__ ___ ___| | __ | \/ | |/ / |
6 # | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
7 # | | |___| | | | __/ (__| < | | | | . \ |
8 # | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
9 # | |
10 # | Copyright Mathias Kettner 2018 mk@mathias-kettner.de |
11 # +------------------------------------------------------------------+
13 # This file is part of Check_MK.
14 # The official homepage is at http://mathias-kettner.de/check_mk.
16 # check_mk is free software; you can redistribute it and/or modify it
17 # under the terms of the GNU General Public License as published by
18 # the Free Software Foundation in version 2. check_mk is distributed
19 # in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
20 # out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
21 # PARTICULAR PURPOSE. See the GNU General Public License for more de-
22 # tails. You should have received a copy of the GNU General Public
23 # License along with GNU Make; see the file COPYING. If not, write
24 # to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
25 # Boston, MA 02110-1301 USA.
27 # .--Parse---------------------------------------------------------------.
28 # | ____ |
29 # | | _ \ __ _ _ __ ___ ___ |
30 # | | |_) / _` | '__/ __|/ _ \ |
31 # | | __/ (_| | | \__ \ __/ |
32 # | |_| \__,_|_| |___/\___| |
33 # | |
34 # '----------------------------------------------------------------------'
37 def jolokia_basic_split(line, expected_length):
38 # line should consist of $expected_length tokens,
39 # if there are more, we assume the second one
40 # was split up by it's spaces.
41 if len(line) == expected_length:
42 return line
43 if len(line) < expected_length:
44 raise ValueError("Too few values: %r (expected >= %d)" \
45 % (line, expected_length))
46 if expected_length < 2:
47 raise NotImplementedError("use 'join' to create single token")
48 tokens = line[:]
49 while len(tokens) > expected_length:
50 # len(tokens) is at least 3!
51 tokens[1] += " %s" % tokens.pop(2)
52 return tokens
55 def jolokoia_extract_opt(instance_raw):
56 if ',' not in instance_raw:
57 return instance_raw, {}, []
59 instance, raw = instance_raw.split(',', 1)
61 attr = {}
62 pos = []
63 for part in raw.split(','):
64 if ":" in part:
65 part = part.split(":", 1)[1]
66 if "=" in part:
67 key, val = part.split("=")
68 attr[key] = val
69 else:
70 pos.append(part)
72 return instance, attr, pos
75 # .--Parse function------------------------------------------------------.
76 # | ____ __ _ _ |
77 # | | _ \ __ _ _ __ ___ ___ / _|_ _ _ __ ___| |_(_) ___ _ __ |
78 # | | |_) / _` | '__/ __|/ _ \ | |_| | | | '_ \ / __| __| |/ _ \| '_ \ |
79 # | | __/ (_| | | \__ \ __/ | _| |_| | | | | (__| |_| | (_) | | | | |
80 # | |_| \__,_|_| |___/\___| |_| \__,_|_| |_|\___|\__|_|\___/|_| |_| |
81 # | |
82 # '----------------------------------------------------------------------'
85 def jolokia_metrics_parse(info):
86 parsed = {}
87 for line in info:
88 if len(line) > 1 and line[1] == "ERROR":
89 continue
91 try:
92 inst_raw, var, value = jolokia_basic_split(line, 3)
93 except ValueError:
94 continue
96 inst, attributes, positional = jolokoia_extract_opt(inst_raw)
98 parsed.setdefault(inst, {})
100 if 'type' in attributes:
101 bean_name = attributes.pop('name')
102 bean_type = attributes.pop('type')
103 # backwards compatibility
104 bean_type = {"GarbageCollector": "gc", "ThreadPool": "tp"}.get(bean_type, bean_type)
105 # maybe do this for all types?
106 if bean_type == "tp":
107 bean_name = bean_name.replace('"', '')
109 bean = parsed[inst].setdefault(bean_type, {}).setdefault(bean_name, {})
110 bean[var] = value
111 bean.update(attributes)
112 else:
113 if positional:
114 app = positional[0]
115 app_dict = parsed[inst].setdefault('apps', {}).setdefault(app, {})
116 if len(positional) > 1:
117 servlet = positional[1]
118 app_dict.setdefault('servlets', {}).setdefault(servlet, {})
119 app_dict['servlets'][servlet][var] = value
120 else:
121 app_dict[var] = value
122 else:
123 parsed[inst][var] = value
124 return parsed
128 # .--Generic inventory functions-----------------------------------------.
129 # | ____ _ |
130 # | / ___| ___ _ __ ___ _ __(_) ___ |
131 # | | | _ / _ \ '_ \ / _ \ '__| |/ __| |
132 # | | |_| | __/ | | | __/ | | | (__ |
133 # | \____|\___|_| |_|\___|_| |_|\___| |
134 # | |
135 # | _ _ |
136 # | (_)_ ____ _____ _ __ | |_ ___ _ __ _ _ |
137 # | | | '_ \ \ / / _ \ '_ \| __/ _ \| '__| | | | |
138 # | | | | | \ V / __/ | | | || (_) | | | |_| | |
139 # | |_|_| |_|\_/ \___|_| |_|\__\___/|_| \__, | |
140 # | |___/ |
141 # | __ _ _ |
142 # | / _|_ _ _ __ ___| |_(_) ___ _ __ ___ |
143 # | | |_| | | | '_ \ / __| __| |/ _ \| '_ \/ __| |
144 # | | _| |_| | | | | (__| |_| | (_) | | | \__ \ |
145 # | |_| \__,_|_| |_|\___|\__|_|\___/|_| |_|___/ |
146 # | |
147 # '----------------------------------------------------------------------'
150 def inventory_jolokia_metrics(info, what):
151 parsed = jolokia_metrics_parse(info)
153 levels = None
155 if what == 'mem':
156 levels = {}
157 elif what == 'threads':
158 levels = 'jolokia_metrics_threads_default_levels'
160 for instance, data in parsed.items():
161 if data is None:
162 continue # No connection to agent currently
164 if what == 'uptime' and "Uptime" not in data:
165 continue
166 if what == 'mem' and ("HeapMemoryUsage" not in data or "NonHeapMemoryUsage" not in data or
167 "HeapMemoryMax" not in data or "NonHeapMemoryMax" not in data):
168 # don't add memory check if we don't have the necessary data
169 continue
170 yield instance, levels
173 def inventory_jolokia_metrics_apps(info, what):
174 inv = []
175 parsed = jolokia_metrics_parse(info)
177 if what == 'app_sess':
178 levels = 'jolokia_metrics_app_sess_default_levels'
179 needed_key = ["Sessions", "activeSessions"]
180 elif what == 'bea_app_sess':
181 levels = 'jolokia_metrics_app_sess_default_levels'
182 needed_key = ["OpenSessionsCurrentCount"]
183 elif what == 'queue':
184 needed_key = ["QueueLength"]
185 levels = "jolokia_metrics_queue_default_levels"
186 # Only works on BEA
187 elif what == 'bea_requests':
188 needed_key = ["CompletedRequestCount"]
189 levels = None
190 elif what == 'requests':
191 needed_key = ["requestCount"]
192 levels = None
193 elif what == 'threads':
194 needed_key = ["StandbyThreadCount"]
195 levels = None
196 else:
197 needed_key = ["Running", "stateName"]
198 levels = None
200 # this handles information from BEA, they stack one level
201 # higher than the rest.
202 if what == 'bea_app_sess':
203 for inst, vals in parsed.iteritems():
204 if vals is None:
205 continue # no data from agent
207 for app, appstate in vals.get('apps', {}).items():
208 if 'servlets' in appstate:
209 for nk in needed_key:
210 for servlet in appstate['servlets']:
211 if nk in appstate['servlets'][servlet]:
212 inv.append(('%s %s %s' % (inst, app, servlet), levels))
213 continue
214 # This does the same for tomcat
215 for inst, vals in parsed.iteritems():
216 if vals is None:
217 continue # no data from agent
219 for app, appstate in vals.get('apps', {}).items():
220 for nk in needed_key:
221 if nk in appstate:
222 inv.append(('%s %s' % (inst, app), levels))
223 continue
224 return inv