-
Notifications
You must be signed in to change notification settings - Fork 0
/
check_alfresco_solr.py
executable file
·230 lines (208 loc) · 10.8 KB
/
check_alfresco_solr.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# check_alfresco_solr.py
#
# Copyright 2018 Alexandre Chapellon <[email protected]>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301, USA.
#
#
import argparse
import nagiosplugin
import urllib3
import xml.etree.ElementTree
from sys import argv
class alfSolrRes(nagiosplugin.Resource):
"""Deal with Solr statistics values gathered from the status and
summary reports generated by Alfresco's Solr server. Only valid for
Solr 4 and above (shipped in Alfresco 5.x and above)"""
def __init__(self, args):
self.solrClientCertFile = args.sslcert
self.solrClientKeyFile = args.sslkey
self.solrHost = args.host
self.solrPort = args.port
self.solrScheme = args.scheme
self.solrAdminUrl = args.admin
self.solrCore = args.core
self.monitor = args.monitor
self.item = args.item
self.relaxed = args.relaxed
self.statusData = self.solrReq('status')
self.summaryData = self.solrReq('summary')
self.monitorDict = {}
self.metrics = []
def probe(self):
try:
self.monitorDict.update(self.analyzeData(self.solrCore, [self.statusData, self.summaryData]))
except ValueError as valueErr:
nagiosplugin.Result(nagiosplugin.Unknown, hint='something went wrong gathering data from Solr')
return
if self.monitor in 'index' 'fts':
monitorData = self.monitorDict[self.solrCore][self.monitor]
else:
monitorData = self.monitorDict[self.solrCore][self.monitor][self.item]
if self.monitor == 'handlers':
for key, value in monitorData.items():
if key in 'errors' 'timeouts' 'requests':
uom = 'c'
if key == 'errors':
context = 'nonZeroCrit' if not self.relaxed else 'noCtx'
elif key == 'timeouts':
context = 'nonZeroWarn' if not self.relaxed else 'noCtx'
else:
context = 'noCtx'
self.metrics.append(nagiosplugin.Metric(key, float(value), uom=uom, context=context))
elif key in '75thPcRequestTime' '99thPcRequestTime' 'avgTimePerRequest':
uom='ms'
if key == 'avgTimePerRequest':
context = context=self.monitor + ':' + self.item
self.metrics.insert(0, nagiosplugin.Metric(key, float(value), uom=uom, context=context))
else:
context = 'noCtx'
self.metrics.append(nagiosplugin.Metric(key, float(value), uom=uom, context=context))
elif self.monitor == 'caches':
for key, value in monitorData.items():
if key == 'hitratio':
uom = '%'
context = context=self.monitor + ':' + self.item
value = float(value) * 100
self.metrics.insert(0, nagiosplugin.Metric(key, float(value), uom=uom, context=context))
else:
uom = 'c'
context = 'noCtx'
self.metrics.append(nagiosplugin.Metric(key, float(value), uom=uom, context=context))
elif self.monitor in 'index' 'fts':
for key, value in monitorData.items():
uom = 'b' if key == 'indexSize' else 'c'
if key == self.item:
self.metrics.insert(0, nagiosplugin.Metric(key, float(value), uom=uom, context=self.monitor + ':' + self.item))
else:
self.metrics.append(nagiosplugin.Metric(key, float(value), uom=uom, context='noCtx'))
for metric in self.metrics:
yield metric
def solrConnect(self):
if self.solrScheme == 'https':
urllib3.disable_warnings()
conn = urllib3.connectionpool.HTTPSConnectionPool(self.solrHost, port=self.solrPort, cert_file=self.solrClientCertFile, key_file=self.solrClientKeyFile, cert_reqs='CERT_NONE')
else:
conn = urllib3.connectionpool.HTTPConnectionPool(self.solrHost, port=self.solrPort)
return conn
def solrReq (self, action):
monConnection = self.solrConnect()
try:
if action == 'FIX':
monResponse = monConnection.request('GET', self.solrAdminUrl + '?action=FIX', timeout=600)
else:
monResponse = monConnection.request('GET', self.solrAdminUrl + '?action=' + action)
except urllib3.exceptions.MaxRetryError as e:
return None
return monResponse.data
def analyzeData (self, core, data):
solrDataDict = {}
solrDataDict[core] = { 'index': {},
'handlers': {
'/alfresco': {},
'/cmis': {},
'/afts': {}
},
'caches': {
'/alfrescoPathCache': {},
'/queryResultCache': {},
'/alfrescoAuthorityCache': {},
'/filterCache': {}
},
'fts': {}
}
xpathStatusQString = 'lst[@name="status"]/lst[@name="' + core + '"]/lst[@name="index"]/'
xpathStatisticsQString = 'lst[@name="Summary"]/lst[@name="' + core + '"]/'
try:
statusTree = xml.etree.ElementTree.fromstring(data[0])
statisticsTree = xml.etree.ElementTree.fromstring(data[1])
solrDataDict[core]['index']['numDocs'] = statusTree.find(xpathStatusQString + 'int[@name="numDocs"]').text
solrDataDict[core]['index']['segmentCount'] = statusTree.find(xpathStatusQString + 'int[@name="segmentCount"]').text
solrDataDict[core]['index']['indexSize'] = statusTree.find(xpathStatusQString + 'long[@name="sizeInBytes"]').text
for key in 'Alfresco Acls in Index','Alfresco Nodes in Index','Alfresco Transactions in Index',\
'Alfresco Acl Transactions in Index','Alfresco States in Index','Alfresco Unindexed Nodes',\
'Alfresco Error Nodes in Index':
solrDataDict[core]['index'][key] = statisticsTree.find(xpathStatisticsQString + 'long[@name="' + key + '"]').text
for handler in '/alfresco','/cmis','/afts':
for key in 'requests','errors','timeouts':
solrDataDict[core]['handlers'][handler][key] = statisticsTree.find(xpathStatisticsQString + '/lst[@name="' + handler + '"]/long[@name="' + key + '"]').text
for key in 'avgTimePerRequest','75thPcRequestTime','99thPcRequestTime':
solrDataDict[core]['handlers'][handler][key] = statisticsTree.find(xpathStatisticsQString + '/lst[@name="' + handler + '"]/double[@name="' + key + '"]').text
for cache in '/alfrescoPathCache','/alfrescoAuthorityCache','/queryResultCache','/filterCache':
solrDataDict[core]['caches'][cache]['hits'] = statisticsTree.find(xpathStatisticsQString + 'lst[@name="' + cache + '"]/long[@name="hits"]').text
solrDataDict[core]['caches'][cache]['misses'] = statisticsTree.find(xpathStatisticsQString + 'lst[@name="' + cache + '"]/long[@name="inserts"]').text
solrDataDict[core]['caches'][cache]['evictions'] = statisticsTree.find(xpathStatisticsQString + 'lst[@name="' + cache + '"]/long[@name="evictions"]').text
solrDataDict[core]['caches'][cache]['hitratio'] = statisticsTree.find(xpathStatisticsQString + 'lst[@name="' + cache + '"]/float[@name="cumulative_hitratio"]').text
solrDataDict[core]['caches'][cache]['size'] = statisticsTree.find(xpathStatisticsQString + 'lst[@name="' + cache + '"]/' + ('long' if cache == '/filterCache' else 'int') + '[@name="size"]').text
for fts in 'Clean','Dirty','New':
solrDataDict[core]['fts'][fts] = statisticsTree.find(xpathStatisticsQString + 'lst[@name="FTS"]/long[@name="Node count with FTSStatus ' + fts + '"]').text
# ~ for child in statisticsTree.findall(xpathStatisticsQString + 'lst[@name="FTS"]/*'):
# ~ print child.tag
# ~ print child.attrib
# ~ print child.text
except Exception as e:
return str(e)
return solrDataDict
def main():
parser = argparse.ArgumentParser(description='''Monitor different parts of Solr. The following can be monitored:
- index: A group of item regarding index status. warning (-w) and critical (-c) command line parameters are
applied to the item specified with --item
Available items: Alfresco Acls in Index,
Alfresco Nodes in Index, Alfresco Transactions in Index,
Alfresco Acl Transactions in Index,
Alfresco States in Index, Alfresco Unindexed Nodes,
Alfresco Error Nodes in Index, numDocs, segmentCount,indexSize
- fts: warning (-w) and critical (-c) command line parameters are
applied to the item specified with --item
Available items: New, Clean, Dirty
- handlers: Will return CRITICAL if the handler report any error,
WARNING in case of timeouts. warning (-w) and critical (-c)
command line parameters are applied to the average request
time for that handler.
Available items: /alfresco, /afts, /cmis
- caches: warning (-w) and critical (-c) command line parameters
apply to the hitratio of the cache.
Available items: /alfrescoPathCache, /alfrescoAuthorityCache,
/queryResultCache, /filterCache
''', formatter_class=argparse.RawTextHelpFormatter)
parser.add_argument('--host', default='localhost', help='hostname or IP address of the Solr service')
parser.add_argument('--port', default='8983', help='port number of the Solr service')
parser.add_argument('--scheme', default='http', help='protocol scheme of the Solr service')
parser.add_argument('--sslcert', help='file containing the SSL client certificate if any', required='--sslkey' in argv)
parser.add_argument('--sslkey', help='file containing the client private key if any', required='--sslcert' in argv)
parser.add_argument('--admin', help='Cores admin URL of the Solr service')
parser.add_argument('--fix', action='store_true', help='Attempt a FIX action if error nodes are detected')
parser.add_argument('core', help='Specify the name of the Solr core')
parser.add_argument('--monitor', choices=['fts','index','handlers','caches'], \
help='Specify what Solr part (group of items) we want to monitor', required = '--fix' not in argv)
parser.add_argument('-w', dest='warning', help='Warning threshold for Nagios style monitoring')
parser.add_argument('-c', dest='critical', help='Critical threshold for Nagios style monitoring')
parser.add_argument('--item', help='Name of item to monitor (see above for details)', required = '--monitor' in argv)
parser.add_argument('--relaxed', action='store_true', help='do not trigger alerts on error in handlers neither warning on handelrs\' timeouts')
args = parser.parse_args()
if args.monitor:
check = nagiosplugin.Check(alfSolrRes(args), \
nagiosplugin.ScalarContext(args.monitor + ':' + args.item, args.warning, args.critical), \
nagiosplugin.ScalarContext('noCtx', None, None), \
nagiosplugin.ScalarContext('nonZeroWarn', ':0', None), \
nagiosplugin.ScalarContext('nonZeroCrit', None, ':0')
)
check.main()
if __name__ == '__main__':
main()