<NME> haproxy_monitoring.rb
<BEF> class HaproxyMonitoring < Scout::Plugin

  if RUBY_VERSION < "1.9"
    needs 'fastercsv'
  else
    # typically, avoid require. In this case we can't use needs' deferred loading because we need to alias CSV
    require 'csv'
    FasterCSV=CSV
  end
  needs 'open-uri'

  OPTIONS=<<-EOS
  uri:
    name: URI
    notes: "URI of the haproxy CSV stats url. See the 'CSV Export' link on your haproxy stats page (example stats page: http://demo.1wt.eu/)."
  proxy:
    notes: The name of the proxy to monitor. Proxies are typically listed in the haproxy.cfg file.
  proxy_type:
    notes: "If multiple proxies have the same name, specify which proxy you want to monitor (ex: 'frontend' or 'backend')."
    attributes: advanced
  ssl_verify_none:
    default: false
    notes: "Specify 'true' to ignore SSL verification errors (e.g. when using a self-signed certificate)."
    attributes: advanced
  user:
    notes: If protected under basic authentication provide the user name.
  password:
    notes: If protected under basic authentication provide the password.
    attributes: password
  EOS

  def build_report

    if option(:uri).nil?
      return error('URI to HAProxy Stats Required', "It looks like the URI to the HAProxy stats page (in csv format) hasn't been provided. Please enter this URI in the plugin settings.")
    end
    proxy = option(:proxy)
    if option(:proxy_type)
      proxy_type = option(:proxy_type)
      if option(:proxy_type) =~ /frontend|backend/i
       proxy_type = proxy_type.upcase
      end
    end
    found_proxies = []
    possible_proxies = []
    open_uri_options = {}
    open_uri_options[:http_basic_authentication] = [option(:user),option(:password)]
    open_uri_options[:ssl_verify_mode] = OpenSSL::SSL::VERIFY_NONE if option(:ssl_verify_none).to_s.strip == 'true'
    begin
      FasterCSV.parse(open(option(:uri), open_uri_options), :headers => true) do |row|
        next if proxy_type and proxy_type != row["svname"] # ensure the proxy type (if provided) matches
        possible_proxies << row["# pxname"] # used in error message
        next unless proxy.to_s.strip.downcase == row["# pxname"].downcase # ensure the proxy name matches
        # if multiple proxies have the same name, we don't know which to report on. 
        if found_proxies.include?(row["# pxname"])
      return error('Unable to access stats page', "The plugin encountered an error attempting to access the stats page (in CSV format) at: #{option(:uri)}. The exception: #{$!.message}\n#{$!.backtrace}")
    end
    if proxy.nil?
      error('Proxy name required',"The name of the proxy to monitor must be provided in the plugin settings. The possible proxies to monitor:\n\n#{possible_proxies.map { |p| "* #{p}"}.join('\n')}")
    elsif !proxy_found
      error('Proxy not found',"The proxy '#{proxy}' was not found. The possible proxies to monitor:\n<ul>#{possible_proxies.map { |p| "<li>#{p}</li>"}.join('')}</ul>")
      
        counter(:errors_req,  row['ereq'].to_i,  :per => :minute) if row['ereq']
        counter(:errors_conn, row['econ'].to_i,  :per => :minute) if row['econ']
        counter(:errors_resp, row['eresp'].to_i, :per => :minute) if row['eresp']

        counter(:bytes_in,  row['bin'].to_i,  :per => :second) if row['bin']
        counter(:bytes_out, row['bout'].to_i, :per => :second) if row['bout']

        report(:active_sessions => row['scur'])
        report(:queued_sessions => row['qcur']) if row['qcur']

        report(:active_servers => row['act']) if row['act']
        report(:backup_servers => row['bck']) if row['bck']

        report(:proxy_up=>%w(UP OPEN).find {|s| s == row['status']} ? 1 : 0)
      end # FasterCSV.parse
    rescue OpenURI::HTTPError
      if $!.message == '401 Unauthorized'
        return error("Authentication Failed", "Unable to access the stats page at #{option(:uri)} with the username '#{option(:user)}' and provided password. Please ensure the username, password, and URI are correct.")
      elsif $!.message != '404 Not Found'
        return error("Unable to find the stats page", "The stats page could not be found at: #{option(:uri)}.")
      else
        raise
      end
    rescue FasterCSV::MalformedCSVError
      return error('Unable to access stats page', "The plugin encountered an error attempting to access the stats page (in CSV format) at: #{option(:uri)}. The exception: #{$!.message}\n#{$!.backtrace}")
    end
    if proxy.nil?
      error('Proxy name required',"The name of the proxy to monitor must be provided in the plugin settings. The possible proxies to monitor:\n<ul>#{possible_proxies.map { |p| "<li>#{p}</li>"}.join('')}</ul>")
    elsif found_proxies.empty?
      error('Proxy not found',"The proxy '#{proxy}' #{proxy_type ? "w/proxy type [#{proxy_type}]" : nil} was not found. The possible proxies #{proxy_type ? "for this proxy type" : nil} to monitor:\n<ul>#{possible_proxies.map { |p| "<li>#{p}</li>"}.join('')}</ul>")
    end
  end

end

<MSG> Fixing error message formatting for no proxy

<DFF> @@ -56,7 +56,7 @@ class HaproxyMonitoring < Scout::Plugin
       return error('Unable to access stats page', "The plugin encountered an error attempting to access the stats page (in CSV format) at: #{option(:uri)}. The exception: #{$!.message}\n#{$!.backtrace}")
     end
     if proxy.nil?
-      error('Proxy name required',"The name of the proxy to monitor must be provided in the plugin settings. The possible proxies to monitor:\n\n#{possible_proxies.map { |p| "* #{p}"}.join('\n')}")
+      error('Proxy name required',"The name of the proxy to monitor must be provided in the plugin settings. The possible proxies to monitor:\n<ul>#{possible_proxies.map { |p| "<li>#{p}</li>"}.join('')}</ul>")
     elsif !proxy_found
       error('Proxy not found',"The proxy '#{proxy}' was not found. The possible proxies to monitor:\n<ul>#{possible_proxies.map { |p| "<li>#{p}</li>"}.join('')}</ul>")
       

{'commit': 'diff --git a/haproxy_monitoring/haproxy_monitoring.rb b/haproxy_monitoring/haproxy_monitoring.rb\nindex 61bacfa..d16b2f4 100644\n--- a/haproxy_monitoring/haproxy_monitoring.rb\n+++ b/haproxy_monitoring/haproxy_monitoring.rb\n@@ -56,7 +56,7 @@ class HaproxyMonitoring < Scout::Plugin\n       return error(\'Unable to access stats page\', "The plugin encountered an error attempting to access the stats page (in CSV format) at: #{option(:uri)}. The exception: #{$!.message}\\n#{$!.backtrace}")\n     end\n     if proxy.nil?\n-      error(\'Proxy name required\',"The name of the proxy to monitor must be provided in the plugin settings. The possible proxies to monitor:\\n\\n#{possible_proxies.map { |p| "* #{p}"}.join(\'\\n\')}")\n+      error(\'Proxy name required\',"The name of the proxy to monitor must be provided in the plugin settings. The possible proxies to monitor:\\n<ul>#{possible_proxies.map { |p| "<li>#{p}</li>"}.join(\'\')}</ul>")\n     elsif !proxy_found\n       error(\'Proxy not found\',"The proxy \'#{proxy}\' was not found. The possible proxies to monitor:\\n<ul>#{possible_proxies.map { |p| "<li>#{p}</li>"}.join(\'\')}</ul>")\n       \n', 'commit_subject': 'Fixing error message formatting for no proxy', 'repo_name': 'pingdomserver/scout-plugins', 'committer': {'name': 'Derek Haynes', 'email': 'f912d82aa5db1c3aa87dcfc173e49d40c4424817@gmail.com', 'time_sec': '1317668739', 'tz_offset': '-420', 'date': {'seconds': '1317668739'}}, 'commit_tree': '09bd30caa809c17e5a23285a0c7871b475726a9a', 'commit_message': 'Fixing error message formatting for no proxy\n', 'language_name': 'Python', 'license': 'mit', 'hunks': '@@ -56,7 +56,7 @@ class HaproxyMonitoring < Scout::Plugin\n       return error(\'Unable to access stats page\', "The plugin encountered an error attempting to access the stats page (in CSV format) at: #{option(:uri)}. The exception: #{$!.message}\\n#{$!.backtrace}")\n     end\n     if proxy.nil?\n-      error(\'Proxy name required\',"The name of the proxy to monitor must be provided in the plugin settings. The possible proxies to monitor:\\n\\n#{possible_proxies.map { |p| "* #{p}"}.join(\'\\n\')}")\n+      error(\'Proxy name required\',"The name of the proxy to monitor must be provided in the plugin settings. The possible proxies to monitor:\\n<ul>#{possible_proxies.map { |p| "<li>#{p}</li>"}.join(\'\')}</ul>")\n     elsif !proxy_found\n       error(\'Proxy not found\',"The proxy \'#{proxy}\' was not found. The possible proxies to monitor:\\n<ul>#{possible_proxies.map { |p| "<li>#{p}</li>"}.join(\'\')}</ul>")\n       \n', 'addition_count': 1, 'deletion_count': 1, 'src_file': 'a/haproxy_monitoring/haproxy_monitoring.rb', 'tgt_file': 'b/haproxy_monitoring/haproxy_monitoring.rb', 'file_extension': '.rb', 'before_file': 'class HaproxyMonitoring < Scout::Plugin\n\n  if RUBY_VERSION < "1.9"\n    needs \'fastercsv\'\n  else\n    # typically, avoid require. In this case we can\'t use needs\' deferred loading because we need to alias CSV\n    require \'csv\'\n    FasterCSV=CSV\n  end\n  needs \'open-uri\'\n\n  OPTIONS=<<-EOS\n  uri:\n    name: URI\n    notes: "URI of the haproxy CSV stats url. See the \'CSV Export\' link on your haproxy stats page (example stats page: http://demo.1wt.eu/)."\n  proxy:\n    notes: The name of the proxy to monitor. Proxies are typically listed in the haproxy.cfg file.\n  proxy_type:\n    notes: "If multiple proxies have the same name, specify which proxy you want to monitor (ex: \'frontend\' or \'backend\')."\n    attributes: advanced\n  ssl_verify_none:\n    default: false\n    notes: "Specify \'true\' to ignore SSL verification errors (e.g. when using a self-signed certificate)."\n    attributes: advanced\n  user:\n    notes: If protected under basic authentication provide the user name.\n  password:\n    notes: If protected under basic authentication provide the password.\n    attributes: password\n  EOS\n\n  def build_report\n\n    if option(:uri).nil?\n      return error(\'URI to HAProxy Stats Required\', "It looks like the URI to the HAProxy stats page (in csv format) hasn\'t been provided. Please enter this URI in the plugin settings.")\n    end\n    proxy = option(:proxy)\n    if option(:proxy_type)\n      proxy_type = option(:proxy_type)\n      if option(:proxy_type) =~ /frontend|backend/i\n       proxy_type = proxy_type.upcase\n      end\n    end\n    found_proxies = []\n    possible_proxies = []\n    open_uri_options = {}\n    open_uri_options[:http_basic_authentication] = [option(:user),option(:password)]\n    open_uri_options[:ssl_verify_mode] = OpenSSL::SSL::VERIFY_NONE if option(:ssl_verify_none).to_s.strip == \'true\'\n    begin\n      FasterCSV.parse(open(option(:uri), open_uri_options), :headers => true) do |row|\n        next if proxy_type and proxy_type != row["svname"] # ensure the proxy type (if provided) matches\n        possible_proxies << row["# pxname"] # used in error message\n        next unless proxy.to_s.strip.downcase == row["# pxname"].downcase # ensure the proxy name matches\n        # if multiple proxies have the same name, we don\'t know which to report on. \n        if found_proxies.include?(row["# pxname"])\n      return error(\'Unable to access stats page\', "The plugin encountered an error attempting to access the stats page (in CSV format) at: #{option(:uri)}. The exception: #{$!.message}\\n#{$!.backtrace}")\n    end\n    if proxy.nil?\n      error(\'Proxy name required\',"The name of the proxy to monitor must be provided in the plugin settings. The possible proxies to monitor:\\n\\n#{possible_proxies.map { |p| "* #{p}"}.join(\'\\n\')}")\n    elsif !proxy_found\n      error(\'Proxy not found\',"The proxy \'#{proxy}\' was not found. The possible proxies to monitor:\\n<ul>#{possible_proxies.map { |p| "<li>#{p}</li>"}.join(\'\')}</ul>")\n      \n        counter(:errors_req,  row[\'ereq\'].to_i,  :per => :minute) if row[\'ereq\']\n        counter(:errors_conn, row[\'econ\'].to_i,  :per => :minute) if row[\'econ\']\n        counter(:errors_resp, row[\'eresp\'].to_i, :per => :minute) if row[\'eresp\']\n\n        counter(:bytes_in,  row[\'bin\'].to_i,  :per => :second) if row[\'bin\']\n        counter(:bytes_out, row[\'bout\'].to_i, :per => :second) if row[\'bout\']\n\n        report(:active_sessions => row[\'scur\'])\n        report(:queued_sessions => row[\'qcur\']) if row[\'qcur\']\n\n        report(:active_servers => row[\'act\']) if row[\'act\']\n        report(:backup_servers => row[\'bck\']) if row[\'bck\']\n\n        report(:proxy_up=>%w(UP OPEN).find {|s| s == row[\'status\']} ? 1 : 0)\n      end # FasterCSV.parse\n    rescue OpenURI::HTTPError\n      if $!.message == \'401 Unauthorized\'\n        return error("Authentication Failed", "Unable to access the stats page at #{option(:uri)} with the username \'#{option(:user)}\' and provided password. Please ensure the username, password, and URI are correct.")\n      elsif $!.message != \'404 Not Found\'\n        return error("Unable to find the stats page", "The stats page could not be found at: #{option(:uri)}.")\n      else\n        raise\n      end\n    rescue FasterCSV::MalformedCSVError\n      return error(\'Unable to access stats page\', "The plugin encountered an error attempting to access the stats page (in CSV format) at: #{option(:uri)}. The exception: #{$!.message}\\n#{$!.backtrace}")\n    end\n    if proxy.nil?\n      error(\'Proxy name required\',"The name of the proxy to monitor must be provided in the plugin settings. The possible proxies to monitor:\\n<ul>#{possible_proxies.map { |p| "<li>#{p}</li>"}.join(\'\')}</ul>")\n    elsif found_proxies.empty?\n      error(\'Proxy not found\',"The proxy \'#{proxy}\' #{proxy_type ? "w/proxy type [#{proxy_type}]" : nil} was not found. The possible proxies #{proxy_type ? "for this proxy type" : nil} to monitor:\\n<ul>#{possible_proxies.map { |p| "<li>#{p}</li>"}.join(\'\')}</ul>")\n    end\n  end\n\nend\n', 'message': 'Fixing error message formatting for no proxy\n', 'author_name': 'Derek Haynes', 'lang': 'rb'}