root / plugins / solr / solrmulticore @ 8589c6df
Historique | Voir | Annoter | Télécharger (5,87 ko)
| 1 |
#!/usr/bin/python |
|---|---|
| 2 |
# |
| 3 |
# Copyright (C) Rodolphe Franceschi |
| 4 |
# |
| 5 |
# This program is free software; you can redistribute it and/or |
| 6 |
# modify it under the terms of the GNU General Public License |
| 7 |
# as published by the Free Software Foundation; either version 2 |
| 8 |
# of the License, or (at your option) any later version. |
| 9 |
# |
| 10 |
# This program is distributed in the hope that it will be useful, |
| 11 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 12 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 13 |
# GNU General Public License for more details. |
| 14 |
# |
| 15 |
# You should have received a copy of the GNU General Public License |
| 16 |
# along with this program; if not, write to the Free Software |
| 17 |
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
| 18 |
# |
| 19 |
# |
| 20 |
# This plugin monitors a SOLR server configured for multicore by automatically |
| 21 |
# getting core names from SOLR default page. |
| 22 |
# |
| 23 |
# Tested on SOLR 1.4.0 |
| 24 |
# |
| 25 |
# Parameters: |
| 26 |
# config (required) |
| 27 |
# autoconf (optional - used by munin-config) |
| 28 |
# |
| 29 |
# For the full list of options, refer to PLUGINOPTIONSLIST variable |
| 30 |
# |
| 31 |
# Example of symlink creation on Debian Lenny |
| 32 |
# ln -s /usr/share/munin/plugins/solrmulticore_ /etc/munin/plugins/solrmulticore_avgRequestsPerSecond |
| 33 |
# |
| 34 |
# Magic markers (Used by munin-config and some installation scripts. |
| 35 |
# Optional): |
| 36 |
#%# family=auto |
| 37 |
#%# capabilities=autoconf |
| 38 |
|
| 39 |
import sys, os |
| 40 |
import urllib2 |
| 41 |
import HTMLParser, urllib |
| 42 |
|
| 43 |
try: |
| 44 |
from xml.etree import cElementTree as ET |
| 45 |
except ImportError: |
| 46 |
try: |
| 47 |
import cElementTree as ET |
| 48 |
except ImportError: |
| 49 |
sys.exit(1) |
| 50 |
|
| 51 |
|
| 52 |
## GLOBALS |
| 53 |
SOLR_PORT = 8983 |
| 54 |
SOLR_HOST = "localhost" |
| 55 |
PLUGINOPTIONSLIST = {
|
| 56 |
"avgRequestsPerSecond" : { 'xmlpath': '/solr-info/QUERYHANDLER/entry', 'xmlparententryname': 'org.apache.solr.handler.StandardRequestHandler', 'label': 'Average requests per second' },
|
| 57 |
"avgTimePerRequest" : { 'xmlpath': '/solr-info/QUERYHANDLER/entry', 'xmlparententryname': 'org.apache.solr.handler.StandardRequestHandler', 'label': 'Average time per request' },
|
| 58 |
"errors" : { 'xmlpath': '/solr-info/QUERYHANDLER/entry', 'xmlparententryname': 'org.apache.solr.handler.StandardRequestHandler', 'label': 'Number of errors' },
|
| 59 |
"timeouts" : { 'xmlpath': '/solr-info/QUERYHANDLER/entry', 'xmlparententryname': 'org.apache.solr.handler.StandardRequestHandler', 'label': 'Number of timeouts' },
|
| 60 |
"requests" : { 'xmlpath': '/solr-info/QUERYHANDLER/entry', 'xmlparententryname': 'org.apache.solr.handler.StandardRequestHandler', 'label': 'Total number of requests' },
|
| 61 |
"numDocs" : { 'xmlpath': '/solr-info/CORE/entry', 'xmlparententryname': 'searcher', 'label': 'Number of documents' },
|
| 62 |
# "" : { 'xmlpath': '/solr-info/QUERYHANDLER/entry', 'xmlparententryname': 'org.apache.solr.handler.StandardRequestHandler' },
|
| 63 |
} |
| 64 |
|
| 65 |
# Automatic extraction of core names from SOLR default page if empty array |
| 66 |
SOLR_CORES = [] |
| 67 |
# If you do not want automatic gathering, feel free to put your array manually |
| 68 |
#SOLR_CORES = [ "core0", "core1" ] |
| 69 |
|
| 70 |
|
| 71 |
## FUNCTIONS |
| 72 |
def getSolrCoreNameList(): |
| 73 |
url = "http://%s:%s/solr/" % (SOLR_HOST, SOLR_PORT) |
| 74 |
class linkParser(HTMLParser.HTMLParser): |
| 75 |
def __init__(self): |
| 76 |
HTMLParser.HTMLParser.__init__(self) |
| 77 |
self.links = [] |
| 78 |
def handle_starttag(self, tag, attrs): |
| 79 |
if tag=='a': |
| 80 |
self.links.append(dict(attrs)['href']) |
| 81 |
|
| 82 |
htmlSource = urllib.urlopen(url).read(200000) |
| 83 |
p = linkParser() |
| 84 |
p.feed(htmlSource) |
| 85 |
|
| 86 |
# Remove link to . (First one !) |
| 87 |
p.links.pop(0) |
| 88 |
|
| 89 |
dealcores = [ ] |
| 90 |
|
| 91 |
for link in p.links: |
| 92 |
dealcores.append ( link.split("/")[0] )
|
| 93 |
|
| 94 |
return dealcores |
| 95 |
|
| 96 |
|
| 97 |
|
| 98 |
def parseArgs(): |
| 99 |
"Parses the name of the file " |
| 100 |
parts = sys.argv[0].split("_")
|
| 101 |
|
| 102 |
params = { }
|
| 103 |
params['valueName'] = parts[1] |
| 104 |
|
| 105 |
# Automatic / Manual Mode for core names |
| 106 |
if (len(SOLR_CORES) == 0): |
| 107 |
params['cores'] = getSolrCoreNameList() |
| 108 |
else: |
| 109 |
params['cores'] = SOLR_CORES |
| 110 |
|
| 111 |
params['cores'].sort() |
| 112 |
|
| 113 |
return params |
| 114 |
|
| 115 |
# For multicore / Solr 1.3, URL is like that |
| 116 |
def fetchUrl(core, xmlPath): |
| 117 |
URL="http://%s:%d/solr/%s/admin/stats.jsp" |
| 118 |
|
| 119 |
URLFULL = URL % (SOLR_HOST, SOLR_PORT, core) |
| 120 |
response = urllib2.urlopen(URLFULL) |
| 121 |
return parseXmlResponse(response, xmlPath) |
| 122 |
|
| 123 |
def parseXmlResponse(response, xmlPath): |
| 124 |
root = ET.parse(response) |
| 125 |
queues = root.findall(xmlPath) |
| 126 |
return queues |
| 127 |
|
| 128 |
#def fetchFile(): |
| 129 |
# f = open("/tmp/stats.jsp.html")
|
| 130 |
# return parseXmlResponse(f) |
| 131 |
|
| 132 |
def getEntry(entries, entryName): |
| 133 |
for entry in entries: |
| 134 |
name = entry.findtext("name").strip()
|
| 135 |
if (name != entryName): |
| 136 |
continue |
| 137 |
return entry.find("stats")
|
| 138 |
|
| 139 |
def getValue(entry, valueName): |
| 140 |
for stat in entry: |
| 141 |
if stat.get('name') == valueName:
|
| 142 |
return stat.text |
| 143 |
#print "Could not find %s for entry" % valueName |
| 144 |
return 0 |
| 145 |
|
| 146 |
|
| 147 |
|
| 148 |
|
| 149 |
## MAIN |
| 150 |
if len(sys.argv) > 1: |
| 151 |
if sys.argv[1]== "autoconf": |
| 152 |
# check connection |
| 153 |
sys.exit(0) |
| 154 |
elif sys.argv[1] == "config": |
| 155 |
params = parseArgs() |
| 156 |
|
| 157 |
# Extracting Generic graph datas |
| 158 |
print 'graph_title %s' % ( PLUGINOPTIONSLIST[params['valueName']]['label'] ) |
| 159 |
print "graph_args --base 1000"; |
| 160 |
print 'graph_vlabel Size %s' % params['valueName'] |
| 161 |
print 'graph_category search' |
| 162 |
print 'graph_info Info for cores: %s' % ( ",".join(params['cores']) ) |
| 163 |
|
| 164 |
# Iterations for core datas |
| 165 |
for core in params['cores']: |
| 166 |
#print core, params['valueName'] |
| 167 |
print "%s.label %s" % (core, core) |
| 168 |
print "%s.type GAUGE" % (core) |
| 169 |
print "%s.min 0" % (core) |
| 170 |
sys.exit(0) |
| 171 |
|
| 172 |
|
| 173 |
params = parseArgs() |
| 174 |
for core in params['cores']: |
| 175 |
#print core, params['valueName'] |
| 176 |
queues = fetchUrl(core, PLUGINOPTIONSLIST[params['valueName']]['xmlpath']) |
| 177 |
searcher = getEntry(queues, PLUGINOPTIONSLIST[params['valueName']]['xmlparententryname']) |
| 178 |
value = getValue(searcher, params['valueName']).strip() |
| 179 |
print "%s.value %s" % (core, value) |
| 180 |
|
| 181 |
sys.exit(0) |
