From 43e0bdfafdb5a7b7931186aa154e093b9a001a58 Mon Sep 17 00:00:00 2001 From: Mike Crocker Date: Mon, 14 Apr 2014 10:46:12 -0700 Subject: [PATCH 1/3] Avilable plugins as of 4-14-2014 did not work with solr1.4. My plugin gathers same metrics as Pete Shima's plugins. Differences are I used nokogiri and CSS selectors to parse the XML. Allowing users to dynamically locate metrics and stats I feel work quite well in my plugin. --- plugins/solr/solr-v1.4graphite.rb | 91 +++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 plugins/solr/solr-v1.4graphite.rb diff --git a/plugins/solr/solr-v1.4graphite.rb b/plugins/solr/solr-v1.4graphite.rb new file mode 100644 index 000000000..3f9ec6a3d --- /dev/null +++ b/plugins/solr/solr-v1.4graphite.rb @@ -0,0 +1,91 @@ +#!/usr/bin/env ruby +# +# Grab various metrics from apache-solr stats page +# +require 'rubygems' if RUBY_VERSION < '1.9.0' +require 'sensu-plugin/metric/cli' +require 'socket' +require 'nokogiri' +require 'open-uri' + +class SolrGraphite < Sensu::Plugin::Metric::CLI::Graphite + option :host, + :short => "-h HOST", + :long => "--host HOST", + :description => "Solr host to connect to", + :default => "#{Socket.gethostname}" + + option :port, + :short => "-p PORT", + :long => "--port PORT", + :description => "Solr port to connect", + :proc => proc {|p| p.to_i}, + :required => true + + option :scheme, + :short => "-s SCHEME", + :long => "--scheme", + :default => "#{Socket.gethostname}" + + def lookingfor (needle, haystack) + haystack.each_with_index do |element, index| + if element.css('name').text.strip == needle; then return index else next end + end + end + + def outputstats (section, queryindex, statpage, metrics, label) + metrics.each do |value| + stat = statpage.css("#{section} entry")[queryindex].css("stats stat[name=#{value}]").text.strip + output [config[:scheme], label, value].join("."), stat, Time.now.to_i + end + end + + def run + + #Capture initial stats page XML data. + doc = Nokogiri::XML(open("http://#{config[:host]}:#{config[:port]}/solr/admin/stats.jsp")) + + #Go through each core and get the appropriate data + doc.css('CORE entry').each do |coreinfo| + output [config[:scheme], 'CORE', coreinfo.css('name').text.strip, 'numDocs'].join("."), coreinfo.css("stats stat[name='numDocs']").text.strip, Time.now.to_i + output [config[:scheme], 'CORE', coreinfo.css('name').text.strip, 'maxDoc'].join("."), coreinfo.css("stats stat[name='maxDoc']").text.strip, Time.now.to_i + output [config[:scheme], 'CORE', coreinfo.css('name').text.strip, 'warmupTime'].join("."), coreinfo.css("stats stat[name='warmupTime']").text.strip, Time.now.to_i + end + + #Location of particular metric on our XML stat page + indStandard = lookingfor('standard', doc.css('QUERYHANDLER entry')) + indUpdate = lookingfor('/update', doc.css('QUERYHANDLER entry')) + indUpdateHand = lookingfor('updateHandler', doc.css('UPDATEHANDLER entry')) + indCache = lookingfor('queryResultCache', doc.css('CACHE entry')) + indDocCache = lookingfor('documentCache', doc.css('CACHE entry')) + indFilCache = lookingfor('filterCache', doc.css('CACHE entry')) + + # All the metrics we're looking for + statcache = Array['numDocs', 'maxDoc', 'warmupTime'] + statqueryhand = Array['requests', 'errors', 'timeouts', 'avgTimePerRequest', 'avgRequestsPerSecond'] + statupdatehand = Array['commits', 'autocommits', 'optimizes', 'rollbacks', 'docsPending', 'adds', 'errors', 'cumulative_adds', \ + 'cumulative_errors'] + statcache = Array['lookups', 'hits', 'hitratio', 'inserts', 'size', 'warmupTime', 'cumulative_lookups', 'cumulative_hits', \ + 'cumulative_hitratio', 'cumulative_inserts'] + + name = doc.css('QUERYHANDLER entry')[indStandard].css('name').text.strip + outputstats('QUERYHANDLER', indStandard, doc, statqueryhand, name) + + name = doc.css('QUERYHANDLER entry')[indUpdate].css('name').text.strip + outputstats('QUERYHANDLER', indUpdate, doc, statqueryhand, name) + + name = doc.css('UPDATEHANDLER entry')[indUpdateHand].css('name').text.strip + outputstats('UPDATEHANDLER', indUpdateHand, doc, statupdatehand, name) + + name = doc.css('CACHE entry')[indCache].css('name').text.strip + outputstats('CACHE', indCache, doc, statcache, name) + + name = doc.css('CACHE entry')[indDocCache].css('name').text.strip + outputstats('CACHE', indDocCache, doc, statcache, name) + + name = doc.css('CACHE entry')[indFilCache].css('name').text.strip + outputstats('CACHE', indFilCache, doc, statcache, name) + + ok + end +end \ No newline at end of file From 7799b3eb7fb0700fbc9817f8565cb5522695415a Mon Sep 17 00:00:00 2001 From: Mike Crocker Date: Thu, 24 Apr 2014 09:41:24 -0700 Subject: [PATCH 2/3] fixed format issues per Travis ci instruction --- plugins/solr/solr-v1.4graphite.rb | 156 +++++++++++++++--------------- 1 file changed, 80 insertions(+), 76 deletions(-) diff --git a/plugins/solr/solr-v1.4graphite.rb b/plugins/solr/solr-v1.4graphite.rb index 3f9ec6a3d..87ef23ec9 100644 --- a/plugins/solr/solr-v1.4graphite.rb +++ b/plugins/solr/solr-v1.4graphite.rb @@ -1,5 +1,5 @@ #!/usr/bin/env ruby -# +# Created by Mike Crocker # Grab various metrics from apache-solr stats page # require 'rubygems' if RUBY_VERSION < '1.9.0' @@ -10,82 +10,86 @@ class SolrGraphite < Sensu::Plugin::Metric::CLI::Graphite option :host, - :short => "-h HOST", - :long => "--host HOST", - :description => "Solr host to connect to", - :default => "#{Socket.gethostname}" + :short => "-h HOST", + :long => "--host HOST", + :description => "Solr host to connect to", + :default => "#{Socket.gethostname}" option :port, - :short => "-p PORT", - :long => "--port PORT", - :description => "Solr port to connect", - :proc => proc {|p| p.to_i}, - :required => true + :short => "-p PORT", + :long => "--port PORT", + :description => "Solr port to connect", + :proc => proc {|p| p.to_i}, + :required => true option :scheme, - :short => "-s SCHEME", - :long => "--scheme", - :default => "#{Socket.gethostname}" - - def lookingfor (needle, haystack) - haystack.each_with_index do |element, index| - if element.css('name').text.strip == needle; then return index else next end - end - end - - def outputstats (section, queryindex, statpage, metrics, label) - metrics.each do |value| - stat = statpage.css("#{section} entry")[queryindex].css("stats stat[name=#{value}]").text.strip - output [config[:scheme], label, value].join("."), stat, Time.now.to_i - end - end - - def run - - #Capture initial stats page XML data. - doc = Nokogiri::XML(open("http://#{config[:host]}:#{config[:port]}/solr/admin/stats.jsp")) - - #Go through each core and get the appropriate data - doc.css('CORE entry').each do |coreinfo| - output [config[:scheme], 'CORE', coreinfo.css('name').text.strip, 'numDocs'].join("."), coreinfo.css("stats stat[name='numDocs']").text.strip, Time.now.to_i - output [config[:scheme], 'CORE', coreinfo.css('name').text.strip, 'maxDoc'].join("."), coreinfo.css("stats stat[name='maxDoc']").text.strip, Time.now.to_i - output [config[:scheme], 'CORE', coreinfo.css('name').text.strip, 'warmupTime'].join("."), coreinfo.css("stats stat[name='warmupTime']").text.strip, Time.now.to_i - end - - #Location of particular metric on our XML stat page - indStandard = lookingfor('standard', doc.css('QUERYHANDLER entry')) - indUpdate = lookingfor('/update', doc.css('QUERYHANDLER entry')) - indUpdateHand = lookingfor('updateHandler', doc.css('UPDATEHANDLER entry')) - indCache = lookingfor('queryResultCache', doc.css('CACHE entry')) - indDocCache = lookingfor('documentCache', doc.css('CACHE entry')) - indFilCache = lookingfor('filterCache', doc.css('CACHE entry')) - - # All the metrics we're looking for - statcache = Array['numDocs', 'maxDoc', 'warmupTime'] - statqueryhand = Array['requests', 'errors', 'timeouts', 'avgTimePerRequest', 'avgRequestsPerSecond'] - statupdatehand = Array['commits', 'autocommits', 'optimizes', 'rollbacks', 'docsPending', 'adds', 'errors', 'cumulative_adds', \ - 'cumulative_errors'] - statcache = Array['lookups', 'hits', 'hitratio', 'inserts', 'size', 'warmupTime', 'cumulative_lookups', 'cumulative_hits', \ - 'cumulative_hitratio', 'cumulative_inserts'] - - name = doc.css('QUERYHANDLER entry')[indStandard].css('name').text.strip - outputstats('QUERYHANDLER', indStandard, doc, statqueryhand, name) - - name = doc.css('QUERYHANDLER entry')[indUpdate].css('name').text.strip - outputstats('QUERYHANDLER', indUpdate, doc, statqueryhand, name) - - name = doc.css('UPDATEHANDLER entry')[indUpdateHand].css('name').text.strip - outputstats('UPDATEHANDLER', indUpdateHand, doc, statupdatehand, name) - - name = doc.css('CACHE entry')[indCache].css('name').text.strip - outputstats('CACHE', indCache, doc, statcache, name) - - name = doc.css('CACHE entry')[indDocCache].css('name').text.strip - outputstats('CACHE', indDocCache, doc, statcache, name) - - name = doc.css('CACHE entry')[indFilCache].css('name').text.strip - outputstats('CACHE', indFilCache, doc, statcache, name) - - ok - end -end \ No newline at end of file + :short => "-s SCHEME", + :long => "--scheme", + :default => "#{Socket.gethostname}" + + def lookingfor (needle, haystack) + haystack.each_with_index do |element, index| + if element.css('name').text.strip == needle + return index + else + next + end + end + end + + def outputstats (section, queryindex, statpage, metrics, label) + metrics.each do |value| + stat = statpage.css("#{section} entry")[queryindex].css("stats stat[name=#{value}]").text.strip + output [config[:scheme], label, value].join("."), stat, Time.now.to_i + end + end + + def run + + # Capture initial stats page XML data. Sol4 1.4 takes a while to load stats page, the timeout accomidates that. + doc = Nokogiri::XML(open("http://#{config[:host]}:#{config[:port]}/solr/admin/stats.jsp", :read_timeout => 300)) + + # Go through each core and get the appropriate data + doc.css('CORE entry').each do |coreinfo| + output [config[:scheme], 'CORE', coreinfo.css('name').text.strip, 'numDocs'].join("."), coreinfo.css("stats stat[name='numDocs']").text.strip, Time.now.to_i + output [config[:scheme], 'CORE', coreinfo.css('name').text.strip, 'maxDoc'].join("."), coreinfo.css("stats stat[name='maxDoc']").text.strip, Time.now.to_i + output [config[:scheme], 'CORE', coreinfo.css('name').text.strip, 'warmupTime'].join("."), coreinfo.css("stats stat[name='warmupTime']").text.strip, \ + Time.now.to_i + end + + # Location of particular metric on our XML stat page + indStandard = lookingfor('standard', doc.css('QUERYHANDLER entry')) + indUpdate = lookingfor('/update', doc.css('QUERYHANDLER entry')) + indUpdateHand = lookingfor('updateHandler', doc.css('UPDATEHANDLER entry')) + indCache = lookingfor('queryResultCache', doc.css('CACHE entry')) + indDocCache = lookingfor('documentCache', doc.css('CACHE entry')) + indFilCache = lookingfor('filterCache', doc.css('CACHE entry')) + + # All the metrics we're looking for + statqueryhand = Array['requests', 'errors', 'timeouts', 'avgTimePerRequest', 'avgRequestsPerSecond'] + statupdatehand = Array['commits', 'autocommits', 'optimizes', 'rollbacks', 'docsPending', 'adds', 'errors', 'cumulative_adds', \ + 'cumulative_errors'] + statcache = Array['lookups', 'hits', 'hitratio', 'inserts', 'size', 'warmupTime', 'cumulative_lookups', 'cumulative_hits', \ + 'cumulative_hitratio', 'cumulative_inserts'] + + name = doc.css('QUERYHANDLER entry')[indStandard].css('name').text.strip + outputstats('QUERYHANDLER', indStandard, doc, statqueryhand, name) + + name = doc.css('QUERYHANDLER entry')[indUpdate].css('name').text.strip + outputstats('QUERYHANDLER', indUpdate, doc, statqueryhand, name) + + name = doc.css('UPDATEHANDLER entry')[indUpdateHand].css('name').text.strip + outputstats('UPDATEHANDLER', indUpdateHand, doc, statupdatehand, name) + + name = doc.css('CACHE entry')[indCache].css('name').text.strip + outputstats('CACHE', indCache, doc, statcache, name) + + name = doc.css('CACHE entry')[indDocCache].css('name').text.strip + outputstats('CACHE', indDocCache, doc, statcache, name) + + name = doc.css('CACHE entry')[indFilCache].css('name').text.strip + outputstats('CACHE', indFilCache, doc, statcache, name) + + ok + end +end From 80d9d75ecf401078153ce6217254345a8464c812 Mon Sep 17 00:00:00 2001 From: Mike Crocker Date: Thu, 24 Apr 2014 10:55:36 -0700 Subject: [PATCH 3/3] Reduced length of line for readability --- plugins/solr/solr-v1.4graphite.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/plugins/solr/solr-v1.4graphite.rb b/plugins/solr/solr-v1.4graphite.rb index 87ef23ec9..b9a0f76d7 100644 --- a/plugins/solr/solr-v1.4graphite.rb +++ b/plugins/solr/solr-v1.4graphite.rb @@ -51,7 +51,8 @@ def run # Go through each core and get the appropriate data doc.css('CORE entry').each do |coreinfo| - output [config[:scheme], 'CORE', coreinfo.css('name').text.strip, 'numDocs'].join("."), coreinfo.css("stats stat[name='numDocs']").text.strip, Time.now.to_i + output [config[:scheme], 'CORE', coreinfo.css('name').text.strip, 'numDocs'].join("."), coreinfo.css("stats stat[name='numDocs']").text.strip, \ + Time.now.to_i output [config[:scheme], 'CORE', coreinfo.css('name').text.strip, 'maxDoc'].join("."), coreinfo.css("stats stat[name='maxDoc']").text.strip, Time.now.to_i output [config[:scheme], 'CORE', coreinfo.css('name').text.strip, 'warmupTime'].join("."), coreinfo.css("stats stat[name='warmupTime']").text.strip, \ Time.now.to_i @@ -90,6 +91,6 @@ def run name = doc.css('CACHE entry')[indFilCache].css('name').text.strip outputstats('CACHE', indFilCache, doc, statcache, name) - ok + ok end end